--- linux-2.6.37.orig/dropped.txt +++ linux-2.6.37/dropped.txt @@ -0,0 +1,62 @@ +UBUNTU: ubuntu: AUFS -- aufs2 standalone patch for linux-2.6.34 +UBUNTU: SAUCE: AppArmor: -- mainline 2010-06-23 +UBUNTU: SAUCE: AppArmor 2.4 compatibility patch +UBUNTU: [Upstream] Input: evdev - convert to dynamic event buffer +UBUNTU: [Upstream] Input: evdev - use driver hint to compute size of event buffer +UBUNTU: [Upstream] Add support for the ATIF ACPI method to the radeon driver +perf probe: Support tracing an entry of array +perf probe: Support static and global variables +UBUNTU: SAUCE: AppArmor: -- sync to AppArmor mainline 2010-07-27 +UBUNTU: SAUCE: AppArmor: -- sync to AppArmor mainline 2010-07-29 +UBUNTU: SAUCE: AppArmor 2.4 compatibility patch +Input: introduce MT event slots +x86 platform driver: intelligent power sharing driver +UBUNTU: SAUCE: Bring in staging/lirc from 2.6.36 +UBUNTU: SAUCE: Update ir-core to linuxtv/other which should be merged for 2.6.36. +UBUNTU: SAUCE: Bring in streamzap support from linuxtv/other +(pre-stable) ALSA: HDA: Add Sony VAIO quirk for ALC269 +(pre-stable) ALSA: HDA: Fix front mic on Dell Precision M6500 +input: mt: Initialize slots to unused (rev2) +mt: Add support for the Bamboo Touch trackpad +x86, cpu: Package Level Thermal Control, Power Limit Notification definitions +x86, hwmon: Package Level Thermal/Power: pkgtemp hwmon driver +hwmon: Package Level Thermal/Power: thermal throttling handler +drm/i915: fix VGA plane disable for Ironlake+ +e1000e: initial support for 82579 LOMs +(pre-stable) ALSA: hda - Add a new hp-laptop model for Conexant 5066, tested on HP G60 +agp/intel: Support the extended physical addressing bits on Sandybridge. +drm/i915,intel_agp: Add support for Sandybridge D0 +Revert input: mt: Add support for the Bamboo Touch trackpad +UBUNTU: SAUCE: Input: wacom - parse the Bamboo device family +UBUNTU: SAUCE: Input: wacom - collect device quirks into single function +UBUNTU: SAUCE: Input: wacom - add support for the Bamboo Touch trackpad +UBUNTU: SAUCE: Input: wacom - add a quirk for low resolution Bamboo devices +(pre-stable) drm/i915: don't enable self-refresh on Ironlake +PM / Runtime: Make runtime_status attribute not debug-only (v. 2) +UBUNTU: SAUCE: ALSA: HDA: Enable internal mic on Dell E6410 and Dell E6510 +UBUNTU: SAUCE: AppArmor: allow newer tools to load policy on older kernels +UBUNTU: SAUCE: Adding vdd_sdi regulator supply to OMAP3EVM +Revert UBUNTU: SAUCE: AppArmor: allow newer tools to load policy on older kernels +UBUNTU: SAUCE: AppArmor: allow newer tools to load policy on older kernels +UBUNTU: SAUCE: ir-core: Fix null dereferences in the protocols sysfs interface +ALSA: HDA: Enable internal speaker on Dell M101z +UBUNTU: SAUCE: drm -- stop early access to drm devices +UBUNTU: SAUCE: libata: Add ALPM power state accounting to the AHCI driver +UBUNTU: SAUCE: Added quirk to recognize GE0301 3G modem as an interface. +hid: 3m: Convert to MT slots +HID: magicmouse: don't allow hidinput to initialize the device +HID: magicmouse: simplify touch data bit manipulation +HID: magicmouse: simplify touch down logic +HID: magicmouse: enable Magic Trackpad support +UBUNTU: SAUCE: hid: ntrig: remove sysfs nodes +UBUNTU: SAUCE: hid: ntrig: Setup input filtering manually +UBUNTU: SAUCE: hid: ntrig: New ghost-filtering event logic +UBUNTU: SAUCE: hid: ntrig: identify firmware version (wiggled) +UBUNTU: (pre-stable): input: Support Clickpad devices in ClickZone mode +UBUNTU: SAUCE: KMS: cache the EDID information of the LVDS +UBUNTU: SAUCE: fbcon -- fix race between open and removal of framebuffers +UBUNTU: SAUCE: fbcon -- fix OOPs triggered by race prevention fixes +UBUNTU: SAUCE: x86: implement cs-limit nx-emulation for ia32 +UBUNTU: SAUCE: x86: more tightly confine cs-limit nx-emulation to ia32 only +UBUNTU: SAUCE: [um] Don't use nx_enabled under UML +UBUNTU: SAUCE: x86: brk away from exec rand area --- linux-2.6.37.orig/Makefile +++ linux-2.6.37/Makefile @@ -341,13 +341,22 @@ AFLAGS_KERNEL = CFLAGS_GCOV = -fprofile-arcs -ftest-coverage +# Prefer linux-backports-modules +ifneq ($(KBUILD_SRC),) +ifneq ($(shell if test -e $(KBUILD_OUTPUT)/ubuntu-build; then echo yes; fi),yes) +UBUNTUINCLUDE := -I/usr/src/linux-headers-lbm-$(KERNELRELEASE) +endif +endif # Use LINUXINCLUDE when you must reference the include/ directory. # Needed to be compatible with the O= option -LINUXINCLUDE := -I$(srctree)/arch/$(hdr-arch)/include -Iinclude \ +LINUXINCLUDE := $(UBUNTUINCLUDE) -I$(srctree)/arch/$(hdr-arch)/include -Iinclude \ $(if $(KBUILD_SRC), -I$(srctree)/include) \ -include include/generated/autoconf.h +# UBUNTU: Include our third party driver stuff too +LINUXINCLUDE += -Iubuntu/include $(if $(KBUILD_SRC),-I$(srctree)/ubuntu/include) + KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ @@ -486,7 +495,7 @@ # Objects we will link into vmlinux / subdirs we need to visit init-y := init/ -drivers-y := drivers/ sound/ firmware/ +drivers-y := drivers/ sound/ firmware/ ubuntu/ net-y := net/ libs-y := lib/ core-y := usr/ @@ -1029,6 +1038,7 @@ $(error Headers not exportable for the $(SRCARCH) architecture)) $(Q)$(MAKE) $(hdr-inst)=include $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst) + $(Q)$(MAKE) $(hdr-inst)=ubuntu/include dst=include oldheaders= PHONY += headers_check_all headers_check_all: headers_install_all @@ -1038,6 +1048,7 @@ headers_check: headers_install $(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1 $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst) HDRCHECK=1 + $(Q)$(MAKE) $(hdr-inst)=ubuntu/include dst=include oldheaders= HDRCHECK=1 # --------------------------------------------------------------------------- # Modules --- linux-2.6.37.orig/arch/arm/Kconfig +++ linux-2.6.37/arch/arm/Kconfig @@ -1850,6 +1850,8 @@ source "drivers/Kconfig" +source "ubuntu/Kconfig" + source "fs/Kconfig" source "arch/arm/Kconfig.debug" --- linux-2.6.37.orig/arch/arm/mach-omap2/board-4430sdp.c +++ linux-2.6.37/arch/arm/mach-omap2/board-4430sdp.c @@ -199,10 +199,18 @@ .id = -1, }; +static struct platform_device sdp4430_nop_usb_device = { + .name = "nop_usb_xceiv", + .id = -1, + .resource = NULL, + .num_resources = 0, +}; + static struct platform_device *sdp4430_devices[] __initdata = { &sdp4430_lcd_device, &sdp4430_gpio_keys_device, &sdp4430_leds_gpio, + &sdp4430_nop_usb_device, }; static struct omap_lcd_config sdp4430_lcd_config __initdata = { @@ -514,8 +522,6 @@ platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices)); omap_serial_init(); omap4_twl6030_hsmmc_init(mmc); - /* OMAP4 SDP uses internal transceiver so register nop transceiver */ - usb_nop_xceiv_register(); /* FIXME: allow multi-omap to boot until musb is updated for omap4 */ if (!cpu_is_omap44xx()) usb_musb_init(&musb_board_data); --- linux-2.6.37.orig/arch/arm/mach-omap2/board-omap3beagle.c +++ linux-2.6.37/arch/arm/mach-omap2/board-omap3beagle.c @@ -233,13 +233,20 @@ static struct regulator_consumer_supply beagle_vdac_supply = REGULATOR_SUPPLY("vdda_dac", "omapdss"); -static struct regulator_consumer_supply beagle_vdvi_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply beagle_vdds_supplies[] = { + REGULATOR_SUPPLY("vdds_dsi", "omapdss"), + REGULATOR_SUPPLY("vdds_sdi", "omapdss"), +}; static void __init beagle_display_init(void) { int r; + if (cpu_is_omap3630()) + beagle_dvi_device.reset_gpio = 129; + else + beagle_dvi_device.reset_gpio = 170; + r = gpio_request(beagle_dvi_device.reset_gpio, "DVI reset"); if (r < 0) { printk(KERN_ERR "Unable to get DVI reset GPIO\n"); @@ -294,12 +301,22 @@ * power switch and overcurrent detect */ - gpio_request(gpio + 1, "EHCI_nOC"); - gpio_direction_input(gpio + 1); - - /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */ - gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); - gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); + if (cpu_is_omap3630()) { + gpio_request(gpio + 1, "nDVI_PWR_EN"); + gpio_direction_output(gpio + 1, 0); + + /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */ + gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); + gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1); + } + else { + gpio_request(gpio + 1, "EHCI_nOC"); + gpio_direction_input(gpio + 1); + + /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */ + gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR"); + gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0); + } /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */ gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1; @@ -365,7 +382,6 @@ /* VPLL2 for digital video outputs */ static struct regulator_init_data beagle_vpll2 = { .constraints = { - .name = "VDVI", .min_uV = 1800000, .max_uV = 1800000, .valid_modes_mask = REGULATOR_MODE_NORMAL @@ -373,8 +389,8 @@ .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &beagle_vdvi_supply, + .num_consumer_supplies = ARRAY_SIZE(beagle_vdds_supplies), + .consumer_supplies = beagle_vdds_supplies, }; static struct twl4030_usb_data beagle_usb_data = { @@ -567,11 +583,6 @@ ARRAY_SIZE(omap3_beagle_devices)); omap_serial_init(); - omap_mux_init_gpio(170, OMAP_PIN_INPUT); - gpio_request(170, "DVI_nPD"); - /* REVISIT leave DVI powered down until it's needed ... */ - gpio_direction_output(170, true); - usb_musb_init(&musb_board_data); usb_ehci_init(&ehci_pdata); omap3beagle_flash_init(); --- linux-2.6.37.orig/arch/arm/mach-omap2/board-omap3evm.c +++ linux-2.6.37/arch/arm/mach-omap2/board-omap3evm.c @@ -515,8 +515,10 @@ }; /* VPLL2 for digital video outputs */ -static struct regulator_consumer_supply omap3_evm_vpll2_supply = - REGULATOR_SUPPLY("vdds_dsi", "omapdss"); +static struct regulator_consumer_supply omap3_evm_vdds_supplies[] = { + REGULATOR_SUPPLY("vdds_sdi", "omapdss"), + REGULATOR_SUPPLY("vdds_dsi", "omapdss"), +}; static struct regulator_init_data omap3_evm_vpll2 = { .constraints = { @@ -528,8 +530,8 @@ .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, }, - .num_consumer_supplies = 1, - .consumer_supplies = &omap3_evm_vpll2_supply, + .num_consumer_supplies = ARRAY_SIZE(omap3_evm_vdds_supplies), + .consumer_supplies = omap3_evm_vdds_supplies, }; static struct twl4030_platform_data omap3evm_twldata = { @@ -616,6 +618,13 @@ }, }; +static struct platform_device omap3_evm_nop_usb_device = { + .name = "nop_usb_xceiv", + .id = -1, + .resource = NULL, + .num_resources = 0, +}; + static struct omap_board_config_kernel omap3_evm_config[] __initdata = { }; @@ -630,6 +639,7 @@ static struct platform_device *omap3_evm_devices[] __initdata = { &omap3_evm_dss_device, + &omap3_evm_nop_usb_device, }; static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = { @@ -678,9 +688,6 @@ omap_serial_init(); - /* OMAP3EVM uses ISP1504 phy and so register nop transceiver */ - usb_nop_xceiv_register(); - if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) { /* enable EHCI VBUS using GPIO22 */ omap_mux_init_gpio(22, OMAP_PIN_INPUT_PULLUP); --- linux-2.6.37.orig/arch/arm/mach-versatile/Kconfig +++ linux-2.6.37/arch/arm/mach-versatile/Kconfig @@ -3,14 +3,14 @@ config ARCH_VERSATILE_PB bool "Support Versatile/PB platform" - select CPU_ARM926T + select CPU_V7 default y help Include support for the ARM(R) Versatile/PB platform. config MACH_VERSATILE_AB bool "Support Versatile/AB platform" - select CPU_ARM926T + select CPU_V7 help Include support for the ARM(R) Versatile/AP platform. --- linux-2.6.37.orig/arch/arm/plat-omap/include/plat/cpu.h +++ linux-2.6.37/arch/arm/plat-omap/include/plat/cpu.h @@ -394,6 +394,62 @@ #define OMAP4430_REV_ES2_0 0x44301044 /* + * Silicon revisions + */ +#define OMAP_ES_1_0 0x00 +#define OMAP_ES_2_0 0x10 +#define OMAP_ES_2_1 0x20 +#define OMAP_ES_3_0 0x30 +#define OMAP_ES_3_1 0x40 + +#define OMAP_REV_MASK 0x0000ff00 +#define OMAP_REV_BITS ((omap_rev() & OMAP_REV_MASK) >> 8) + +#define OMAP_REV_IS(revid) \ +static inline u8 omap_rev_is_ ##revid (void) \ +{ \ + return (OMAP_REV_BITS == OMAP_ES_ ##revid) ? 1 : 0; \ +} + +#define OMAP_REV_LT(revid) \ +static inline u8 omap_rev_lt_ ##revid (void) \ +{ \ + return (OMAP_REV_BITS < OMAP_ES_ ##revid) ? 1 : 0; \ +} + +#define OMAP_REV_LE(revid) \ +static inline u8 omap_rev_le_ ##revid (void) \ +{ \ + return (OMAP_REV_BITS <= OMAP_ES_ ##revid) ? 1 : 0; \ +} + +#define OMAP_REV_GT(revid) \ +static inline u8 omap_rev_gt_ ##revid (void) \ +{ \ + return (OMAP_REV_BITS > OMAP_ES_ ##revid) ? 1 : 0; \ +} + +#define OMAP_REV_GE(revid) \ +static inline u8 omap_rev_ge_ ##revid (void) \ +{ \ + return (OMAP_REV_BITS >= OMAP_ES_ ##revid) ? 1 : 0; \ +} + +#define OMAP_REV_FUNCTIONS(revid) \ + OMAP_REV_IS(revid) \ + OMAP_REV_LT(revid) \ + OMAP_REV_LE(revid) \ + OMAP_REV_GT(revid) \ + OMAP_REV_GE(revid) + +OMAP_REV_FUNCTIONS(1_0) +OMAP_REV_FUNCTIONS(2_0) +OMAP_REV_FUNCTIONS(2_1) +OMAP_REV_FUNCTIONS(3_0) +OMAP_REV_FUNCTIONS(3_1) + +/* + * omap_chip bits * * CHIP_IS_OMAP{2420,2430,3430} indicate that a particular structure is --- linux-2.6.37.orig/arch/powerpc/Kconfig +++ linux-2.6.37/arch/powerpc/Kconfig @@ -968,6 +968,8 @@ source "drivers/Kconfig" +source "ubuntu/Kconfig" + source "fs/Kconfig" source "arch/powerpc/sysdev/qe_lib/Kconfig" --- linux-2.6.37.orig/arch/x86/Kconfig +++ linux-2.6.37/arch/x86/Kconfig @@ -366,6 +366,12 @@ # Following is an alphabetically sorted list of 32 bit extended platforms # Please maintain the alphabetic order if and when there are additions +config X86_LPIA + bool "LPIA-compatible" + depends on X86_32 && X86_PC + help + Choose this option if your computer is an LPIA platform. + config X86_ELAN bool "AMD Elan" depends on X86_32 @@ -829,6 +835,14 @@ Additional support for intel specific MCE features such as the thermal monitor. +config X86_MCE_XEON75XX + tristate "Intel Xeon 7500 series corrected memory error driver" + depends on X86_MCE_INTEL && PCI + ---help--- + Add support for a Intel Xeon 7500 series specific memory error driver. + This allows to report the DIMM and physical address on a corrected + memory error machine check event. + config X86_MCE_AMD def_bool y prompt "AMD MCE features" @@ -2113,6 +2127,8 @@ source "drivers/Kconfig" +source "ubuntu/Kconfig" + source "drivers/firmware/Kconfig" source "fs/Kconfig" --- linux-2.6.37.orig/arch/x86/Kconfig.debug +++ linux-2.6.37/arch/x86/Kconfig.debug @@ -117,6 +117,17 @@ feature as well as for the change_page_attr() infrastructure. If in doubt, say "N" +config DEBUG_SET_MODULE_RONX + bool "Set loadable kernel module data as NX and text as RO" + depends on MODULES + ---help--- + This option helps catch unintended modifications to loadable + kernel module's text and read-only data. It also prevents execution + of module data. Such protection may interfere with run-time code + patching and dynamic kernel tracing - and they might also protect + against certain classes of kernel exploits. + If in doubt, say "N". + config DEBUG_NX_TEST tristate "Testcase for the NX non-executable stack feature" depends on DEBUG_KERNEL && m --- linux-2.6.37.orig/arch/x86/boot/compressed/head_64.S +++ linux-2.6.37/arch/x86/boot/compressed/head_64.S @@ -182,7 +182,7 @@ hlt jmp 1b -#include "../../kernel/verify_cpu_64.S" +#include "../../kernel/verify_cpu.S" /* * Be careful here startup_64 needs to be at a predictable --- linux-2.6.37.orig/arch/x86/include/asm/desc.h +++ linux-2.6.37/arch/x86/include/asm/desc.h @@ -5,6 +5,7 @@ #include #include #include +#include static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *info) @@ -93,6 +94,9 @@ #define load_TLS(t, cpu) native_load_tls(t, cpu) #define set_ldt native_set_ldt +#ifdef CONFIG_X86_32 +#define load_user_cs_desc native_load_user_cs_desc +#endif /*CONFIG_X86_32*/ #define write_ldt_entry(dt, entry, desc) \ native_write_ldt_entry(dt, entry, desc) @@ -392,4 +396,25 @@ _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS); } +#ifdef CONFIG_X86_32 +static inline void set_user_cs(struct desc_struct *desc, unsigned long limit) +{ + limit = (limit - 1) / PAGE_SIZE; + desc->a = limit & 0xffff; + desc->b = (limit & 0xf0000) | 0x00c0fb00; +} + +static inline void native_load_user_cs_desc(int cpu, struct mm_struct *mm) +{ + get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS] = (mm)->context.user_cs; +} + +#define arch_add_exec_range arch_add_exec_range +#define arch_remove_exec_range arch_remove_exec_range +#define arch_flush_exec_range arch_flush_exec_range +extern void arch_add_exec_range(struct mm_struct *mm, unsigned long limit); +extern void arch_remove_exec_range(struct mm_struct *mm, unsigned long limit); +extern void arch_flush_exec_range(struct mm_struct *mm); +#endif /* CONFIG_X86_32 */ + #endif /* _ASM_X86_DESC_H */ --- linux-2.6.37.orig/arch/x86/include/asm/dma-mapping.h +++ linux-2.6.37/arch/x86/include/asm/dma-mapping.h @@ -144,8 +144,6 @@ { struct dma_map_ops *ops = get_dma_ops(dev); - WARN_ON(irqs_disabled()); /* for portability */ - if (dma_release_from_coherent(dev, get_order(size), vaddr)) return; --- linux-2.6.37.orig/arch/x86/include/asm/jump_label.h +++ linux-2.6.37/arch/x86/include/asm/jump_label.h @@ -14,7 +14,7 @@ do { \ asm goto("1:" \ JUMP_LABEL_INITIAL_NOP \ - ".pushsection __jump_table, \"a\" \n\t"\ + ".pushsection __jump_table, \"aw\" \n\t"\ _ASM_PTR "1b, %l[" #label "], %c0 \n\t" \ ".popsection \n\t" \ : : "i" (key) : : label); \ --- linux-2.6.37.orig/arch/x86/include/asm/mce.h +++ linux-2.6.37/arch/x86/include/asm/mce.h @@ -71,6 +71,8 @@ __u32 socketid; /* CPU socket ID */ __u32 apicid; /* CPU initial apic ID */ __u64 mcgcap; /* MCGCAP MSR: machine check capabilities of CPU */ + __u64 aux0; /* model specific */ + __u64 aux1; /* model specific */ }; /* --- linux-2.6.37.orig/arch/x86/include/asm/mmu.h +++ linux-2.6.37/arch/x86/include/asm/mmu.h @@ -7,12 +7,19 @@ /* * The x86 doesn't have a mmu context, but * we put the segment information here. + * + * exec_limit is used to track the range PROT_EXEC + * mappings span. */ typedef struct { void *ldt; int size; struct mutex lock; void *vdso; +#ifdef CONFIG_X86_32 + struct desc_struct user_cs; + unsigned long exec_limit; +#endif } mm_context_t; #ifdef CONFIG_SMP --- linux-2.6.37.orig/arch/x86/include/asm/paravirt.h +++ linux-2.6.37/arch/x86/include/asm/paravirt.h @@ -289,6 +289,12 @@ { PVOP_VCALL2(pv_cpu_ops.set_ldt, addr, entries); } +#ifdef CONFIG_X86_32 +static inline void load_user_cs_desc(unsigned int cpu, struct mm_struct *mm) +{ + PVOP_VCALL2(pv_cpu_ops.load_user_cs_desc, cpu, mm); +} +#endif /*CONFIG_X86_32*/ static inline void store_gdt(struct desc_ptr *dtr) { PVOP_VCALL1(pv_cpu_ops.store_gdt, dtr); --- linux-2.6.37.orig/arch/x86/include/asm/paravirt_types.h +++ linux-2.6.37/arch/x86/include/asm/paravirt_types.h @@ -118,6 +118,9 @@ void (*store_gdt)(struct desc_ptr *); void (*store_idt)(struct desc_ptr *); void (*set_ldt)(const void *desc, unsigned entries); +#ifdef CONFIG_X86_32 + void (*load_user_cs_desc)(int cpu, struct mm_struct *mm); +#endif unsigned long (*store_tr)(void); void (*load_tls)(struct thread_struct *t, unsigned int cpu); #ifdef CONFIG_X86_64 --- linux-2.6.37.orig/arch/x86/include/asm/pci.h +++ linux-2.6.37/arch/x86/include/asm/pci.h @@ -65,6 +65,7 @@ #define PCIBIOS_MIN_CARDBUS_IO 0x4000 +extern int pcibios_enabled; void pcibios_config_init(void); struct pci_bus *pcibios_scan_root(int bus); --- linux-2.6.37.orig/arch/x86/kernel/e820.c +++ linux-2.6.37/arch/x86/kernel/e820.c @@ -72,7 +72,7 @@ * Note: this function only works correct if the e820 table is sorted and * not-overlapping, which is the case */ -int __init e820_all_mapped(u64 start, u64 end, unsigned type) +int e820_all_mapped(u64 start, u64 end, unsigned type) { int i; @@ -99,6 +99,7 @@ } return 0; } +EXPORT_SYMBOL_GPL(e820_all_mapped); /* * Add a memory region to the kernel e820 map. --- linux-2.6.37.orig/arch/x86/kernel/ftrace.c +++ linux-2.6.37/arch/x86/kernel/ftrace.c @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -49,6 +50,7 @@ int ftrace_arch_code_modify_prepare(void) { set_kernel_text_rw(); + set_all_modules_text_rw(); modifying_code = 1; return 0; } @@ -56,6 +58,7 @@ int ftrace_arch_code_modify_post_process(void) { modifying_code = 0; + set_all_modules_text_ro(); set_kernel_text_ro(); return 0; } --- linux-2.6.37.orig/arch/x86/kernel/head_32.S +++ linux-2.6.37/arch/x86/kernel/head_32.S @@ -316,6 +316,10 @@ subl $0x80000001, %eax cmpl $(0x8000ffff-0x80000001), %eax ja 6f + + /* Clear bogus XD_DISABLE bits */ + call verify_cpu + mov $0x80000001, %eax cpuid /* Execute Disable bit supported? */ @@ -611,6 +615,8 @@ #endif iret +#include "verify_cpu.S" + __REFDATA .align 4 ENTRY(initial_code) --- linux-2.6.37.orig/arch/x86/kernel/paravirt.c +++ linux-2.6.37/arch/x86/kernel/paravirt.c @@ -345,6 +345,9 @@ .read_tscp = native_read_tscp, .load_tr_desc = native_load_tr_desc, .set_ldt = native_set_ldt, +#ifdef CONFIG_X86_32 + .load_user_cs_desc = native_load_user_cs_desc, +#endif /*CONFIG_X86_32*/ .load_gdt = native_load_gdt, .load_idt = native_load_idt, .store_gdt = native_store_gdt, --- linux-2.6.37.orig/arch/x86/kernel/process.c +++ linux-2.6.37/arch/x86/kernel/process.c @@ -669,6 +669,16 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) { unsigned long range_end = mm->brk + 0x02000000; - return randomize_range(mm->brk, range_end, 0) ? : mm->brk; + unsigned long bump = 0; +#ifdef CONFIG_X86_32 + /* in the case of NX emulation, shove the brk segment way out of the + way of the exec randomization area, since it can collide with + future allocations if not. */ + if ( (mm->get_unmapped_exec_area == arch_get_unmapped_exec_area) && + (mm->brk < 0x08000000) ) { + bump = (TASK_SIZE/6); + } +#endif + return bump + (randomize_range(mm->brk, range_end, 0) ? : mm->brk); } --- linux-2.6.37.orig/arch/x86/kernel/process_32.c +++ linux-2.6.37/arch/x86/kernel/process_32.c @@ -247,7 +247,10 @@ void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) { + int cpu; + set_user_gs(regs, 0); + regs->fs = 0; set_fs(USER_DS); regs->ds = __USER_DS; @@ -256,6 +259,11 @@ regs->cs = __USER_CS; regs->ip = new_ip; regs->sp = new_sp; + + cpu = get_cpu(); + load_user_cs_desc(cpu, current->mm); + put_cpu(); + /* * Free the old FP and other extended state */ @@ -315,6 +323,9 @@ if (preload_fpu) prefetch(next->fpu.state); + if (next_p->mm) + load_user_cs_desc(cpu, next_p->mm); + /* * Reload esp0. */ @@ -408,3 +419,40 @@ return 0; } +static void modify_cs(struct mm_struct *mm, unsigned long limit) +{ + mm->context.exec_limit = limit; + set_user_cs(&mm->context.user_cs, limit); + if (mm == current->mm) { + int cpu; + + cpu = get_cpu(); + load_user_cs_desc(cpu, mm); + put_cpu(); + } +} + +void arch_add_exec_range(struct mm_struct *mm, unsigned long limit) +{ + if (limit > mm->context.exec_limit) + modify_cs(mm, limit); +} + +void arch_remove_exec_range(struct mm_struct *mm, unsigned long old_end) +{ + struct vm_area_struct *vma; + unsigned long limit = PAGE_SIZE; + + if (old_end == mm->context.exec_limit) { + for (vma = mm->mmap; vma; vma = vma->vm_next) + if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit)) + limit = vma->vm_end; + modify_cs(mm, limit); + } +} + +void arch_flush_exec_range(struct mm_struct *mm) +{ + mm->context.exec_limit = 0; + set_user_cs(&mm->context.user_cs, 0); +} --- linux-2.6.37.orig/arch/x86/kernel/trampoline_64.S +++ linux-2.6.37/arch/x86/kernel/trampoline_64.S @@ -127,7 +127,7 @@ no_longmode: hlt jmp no_longmode -#include "verify_cpu_64.S" +#include "verify_cpu.S" # Careful these need to be in the same 64K segment as the above; tidt: --- linux-2.6.37.orig/arch/x86/kernel/traps.c +++ linux-2.6.37/arch/x86/kernel/traps.c @@ -109,6 +109,78 @@ dec_preempt_count(); } +#ifdef CONFIG_X86_32 +static inline int +__compare_user_cs_desc(const struct desc_struct *desc1, + const struct desc_struct *desc2) +{ + return ((desc1->limit0 != desc2->limit0) || + (desc1->limit != desc2->limit) || + (desc1->base0 != desc2->base0) || + (desc1->base1 != desc2->base1) || + (desc1->base2 != desc2->base2)); +} + +/* + * lazy-check for CS validity on exec-shield binaries: + * + * the original non-exec stack patch was written by + * Solar Designer . Thanks! + */ +static int +check_lazy_exec_limit(int cpu, struct pt_regs *regs, long error_code) +{ + struct desc_struct *desc1, *desc2; + struct vm_area_struct *vma; + unsigned long limit; + + if (current->mm == NULL) + return 0; + + limit = -1UL; + if (current->mm->context.exec_limit != -1UL) { + limit = PAGE_SIZE; + spin_lock(¤t->mm->page_table_lock); + for (vma = current->mm->mmap; vma; vma = vma->vm_next) + if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit)) + limit = vma->vm_end; + vma = get_gate_vma(current); + if (vma && (vma->vm_flags & VM_EXEC) && (vma->vm_end > limit)) + limit = vma->vm_end; + spin_unlock(¤t->mm->page_table_lock); + if (limit >= TASK_SIZE) + limit = -1UL; + current->mm->context.exec_limit = limit; + } + set_user_cs(¤t->mm->context.user_cs, limit); + + desc1 = ¤t->mm->context.user_cs; + desc2 = get_cpu_gdt_table(cpu) + GDT_ENTRY_DEFAULT_USER_CS; + + if (__compare_user_cs_desc(desc1, desc2)) { + /* + * The CS was not in sync - reload it and retry the + * instruction. If the instruction still faults then + * we won't hit this branch next time around. + */ + if (print_fatal_signals >= 2) { + printk(KERN_ERR "#GPF fixup (%ld[seg:%lx]) at %08lx, CPU#%d.\n", + error_code, error_code/8, regs->ip, + smp_processor_id()); + printk(KERN_ERR "exec_limit: %08lx, user_cs: %08x/%08x, CPU_cs: %08x/%08x.\n", + current->mm->context.exec_limit, + desc1->a, desc1->b, desc2->a, desc2->b); + } + + load_user_cs_desc(cpu, current->mm); + + return 1; + } + + return 0; +} +#endif + static void __kprobes do_trap(int trapnr, int signr, char *str, struct pt_regs *regs, long error_code, siginfo_t *info) @@ -265,6 +337,29 @@ if (!user_mode(regs)) goto gp_in_kernel; +#ifdef CONFIG_X86_32 +{ + int cpu; + int ok; + + cpu = get_cpu(); + ok = check_lazy_exec_limit(cpu, regs, error_code); + put_cpu(); + + if (ok) + return; + + if (print_fatal_signals) { + printk(KERN_ERR "#GPF(%ld[seg:%lx]) at %08lx, CPU#%d.\n", + error_code, error_code/8, regs->ip, smp_processor_id()); + printk(KERN_ERR "exec_limit: %08lx, user_cs: %08x/%08x.\n", + current->mm->context.exec_limit, + current->mm->context.user_cs.a, + current->mm->context.user_cs.b); + } +} +#endif /*CONFIG_X86_32*/ + tsk->thread.error_code = error_code; tsk->thread.trap_no = 13; @@ -798,19 +893,37 @@ } #ifdef CONFIG_X86_32 +/* + * The fixup code for errors in iret jumps to here (iret_exc). It loses + * the original trap number and erorr code. The bogus trap 32 and error + * code 0 are what the vanilla kernel delivers via: + * DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0, 1) + * + * NOTE: Because of the final "1" in the macro we need to enable interrupts. + * + * In case of a general protection fault in the iret instruction, we + * need to check for a lazy CS update for exec-shield. + */ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) { - siginfo_t info; + int ok; + int cpu; + local_irq_enable(); - info.si_signo = SIGILL; - info.si_errno = 0; - info.si_code = ILL_BADSTK; - info.si_addr = NULL; - if (notify_die(DIE_TRAP, "iret exception", - regs, error_code, 32, SIGILL) == NOTIFY_STOP) - return; - do_trap(32, SIGILL, "iret exception", regs, error_code, &info); + cpu = get_cpu(); + ok = check_lazy_exec_limit(cpu, regs, error_code); + put_cpu(); + + if (!ok && notify_die(DIE_TRAP, "iret exception", regs, + error_code, 32, SIGSEGV) != NOTIFY_STOP) { + siginfo_t info; + info.si_signo = SIGSEGV; + info.si_errno = 0; + info.si_code = ILL_BADSTK; + info.si_addr = 0; + do_trap(32, SIGSEGV, "iret exception", regs, error_code, &info); + } } #endif --- linux-2.6.37.orig/arch/x86/kernel/verify_cpu.S +++ linux-2.6.37/arch/x86/kernel/verify_cpu.S @@ -0,0 +1,139 @@ +/* + * + * verify_cpu.S - Code for cpu long mode and SSE verification. This + * code has been borrowed from boot/setup.S and was introduced by + * Andi Kleen. + * + * Copyright (c) 2007 Andi Kleen (ak@suse.de) + * Copyright (c) 2007 Eric Biederman (ebiederm@xmission.com) + * Copyright (c) 2007 Vivek Goyal (vgoyal@in.ibm.com) + * Copyright (c) 2010 Kees Cook (kees.cook@canonical.com) + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + * + * This is a common code for verification whether CPU supports + * long mode and SSE or not. It is not called directly instead this + * file is included at various places and compiled in that context. + * This file is expected to run in 32bit code. Currently: + * + * arch/x86_64/boot/compressed/head_64.S: Boot cpu verification + * arch/x86_64/kernel/trampoline_64.S: secondary processor verfication + * arch/x86_64/kernel/head_32.S: processor startup + * + * verify_cpu, returns the status of longmode and SSE in register %eax. + * 0: Success 1: Failure + * + * On Intel, the XD_DISABLE flag will be cleared as a side-effect. + * + * The caller needs to check for the error code and take the action + * appropriately. Either display a message or halt. + */ + +#include +#include + +verify_cpu: + pushfl # Save caller passed flags + pushl $0 # Kill any dangerous flags + popfl + + pushfl # standard way to check for cpuid + popl %eax + movl %eax,%ebx + xorl $0x200000,%eax + pushl %eax + popfl + pushfl + popl %eax + cmpl %eax,%ebx + jz verify_cpu_no_longmode # cpu has no cpuid + + movl $0x0,%eax # See if cpuid 1 is implemented + cpuid + cmpl $0x1,%eax + jb verify_cpu_no_longmode # no cpuid 1 + + xor %di,%di + cmpl $0x68747541,%ebx # AuthenticAMD + jnz verify_cpu_noamd + cmpl $0x69746e65,%edx + jnz verify_cpu_noamd + cmpl $0x444d4163,%ecx + jnz verify_cpu_noamd + mov $1,%di # cpu is from AMD + jmp verify_cpu_check + +verify_cpu_noamd: + cmpl $0x756e6547,%ebx # GenuineIntel? + jnz verify_cpu_check + cmpl $0x49656e69,%edx + jnz verify_cpu_check + cmpl $0x6c65746e,%ecx + jnz verify_cpu_check + + # only call IA32_MISC_ENABLE when: + # family > 6 || (family == 6 && model >= 0xd) + movl $0x1, %eax # check CPU family and model + cpuid + movl %eax, %ecx + + andl $0x0ff00f00, %eax # mask family and extended family + shrl $8, %eax + cmpl $6, %eax + ja verify_cpu_clear_xd # family > 6, ok + jb verify_cpu_check # family < 6, skip + + andl $0x000f00f0, %ecx # mask model and extended model + shrl $4, %ecx + cmpl $0xd, %ecx + jb verify_cpu_check # family == 6, model < 0xd, skip + +verify_cpu_clear_xd: + movl $MSR_IA32_MISC_ENABLE, %ecx + rdmsr + btrl $2, %edx # clear MSR_IA32_MISC_ENABLE_XD_DISABLE + jnc verify_cpu_check # only write MSR if bit was changed + wrmsr + +verify_cpu_check: + movl $0x1,%eax # Does the cpu have what it takes + cpuid + andl $REQUIRED_MASK0,%edx + xorl $REQUIRED_MASK0,%edx + jnz verify_cpu_no_longmode + + movl $0x80000000,%eax # See if extended cpuid is implemented + cpuid + cmpl $0x80000001,%eax + jb verify_cpu_no_longmode # no extended cpuid + + movl $0x80000001,%eax # Does the cpu have what it takes + cpuid + andl $REQUIRED_MASK1,%edx + xorl $REQUIRED_MASK1,%edx + jnz verify_cpu_no_longmode + +verify_cpu_sse_test: + movl $1,%eax + cpuid + andl $SSE_MASK,%edx + cmpl $SSE_MASK,%edx + je verify_cpu_sse_ok + test %di,%di + jz verify_cpu_no_longmode # only try to force SSE on AMD + movl $MSR_K7_HWCR,%ecx + rdmsr + btr $15,%eax # enable SSE + wrmsr + xor %di,%di # don't loop + jmp verify_cpu_sse_test # try again + +verify_cpu_no_longmode: + popfl # Restore caller passed flags + movl $1,%eax + ret +verify_cpu_sse_ok: + popfl # Restore caller passed flags + xorl %eax, %eax + ret --- linux-2.6.37.orig/arch/x86/kernel/vmlinux.lds.S +++ linux-2.6.37/arch/x86/kernel/vmlinux.lds.S @@ -69,7 +69,7 @@ PHDRS { text PT_LOAD FLAGS(5); /* R_E */ - data PT_LOAD FLAGS(7); /* RWE */ + data PT_LOAD FLAGS(6); /* RW_ */ #ifdef CONFIG_X86_64 user PT_LOAD FLAGS(5); /* R_E */ #ifdef CONFIG_SMP @@ -116,6 +116,10 @@ EXCEPTION_TABLE(16) :text = 0x9090 +#if defined(CONFIG_DEBUG_RODATA) + /* .text should occupy whole number of pages */ + . = ALIGN(PAGE_SIZE); +#endif X64_ALIGN_DEBUG_RODATA_BEGIN RO_DATA(PAGE_SIZE) X64_ALIGN_DEBUG_RODATA_END @@ -335,7 +339,7 @@ __bss_start = .; *(.bss..page_aligned) *(.bss) - . = ALIGN(4); + . = ALIGN(PAGE_SIZE); __bss_stop = .; } --- linux-2.6.37.orig/arch/x86/kernel/cpu/common.c +++ linux-2.6.37/arch/x86/kernel/cpu/common.c @@ -825,6 +825,22 @@ /* Filter out anything that depends on CPUID levels we don't have */ filter_cpuid_features(c, true); +#ifdef CONFIG_X86_32 + /* + * emulation of NX with segment limits unfortunately means + * we have to disable the fast system calls, due to the way that + * sysexit clears the segment limits on return. + * If we have either disabled exec-shield on the boot command line, + * or we have NX, then we don't need to do this. + */ + if (!disable_nx) { +#ifdef CONFIG_X86_PAE + if (!test_cpu_cap(c, X86_FEATURE_NX)) +#endif + clear_cpu_cap(c, X86_FEATURE_SEP); + } +#endif + /* If the model name is still unset, do table lookup. */ if (!c->x86_model_id[0]) { const char *p; --- linux-2.6.37.orig/arch/x86/kernel/cpu/mcheck/Makefile +++ linux-2.6.37/arch/x86/kernel/cpu/mcheck/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_X86_ANCIENT_MCE) += winchip.o p5.o obj-$(CONFIG_X86_MCE_INTEL) += mce_intel.o +obj-$(CONFIG_X86_MCE_XEON75XX) += mce-xeon75xx.o obj-$(CONFIG_X86_MCE_AMD) += mce_amd.o obj-$(CONFIG_X86_MCE_THRESHOLD) += threshold.o obj-$(CONFIG_X86_MCE_INJECT) += mce-inject.o --- linux-2.6.37.orig/arch/x86/kernel/cpu/mcheck/mce-internal.h +++ linux-2.6.37/arch/x86/kernel/cpu/mcheck/mce-internal.h @@ -28,6 +28,8 @@ extern struct mce_bank *mce_banks; +extern void (*mce_cpu_specific_poll)(struct mce *); + #ifdef CONFIG_ACPI_APEI int apei_write_mce(struct mce *m); ssize_t apei_read_mce(struct mce *m, u64 *record_id); --- linux-2.6.37.orig/arch/x86/kernel/cpu/mcheck/mce-xeon75xx.c +++ linux-2.6.37/arch/x86/kernel/cpu/mcheck/mce-xeon75xx.c @@ -0,0 +1,427 @@ +/* + * Xeon 7500 series specific machine check support code. + * Copyright 2009, 2010 Intel Corporation + * Author: Andi Kleen + * + * 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; version 2 + * of the License. + * + * Implement Xeon 7500 series specific code to retrieve the physical address + * and DIMM information for corrected memory errors. + * + * Interface: mce->aux0/aux1 is mapped to a struct pfa_dimm with pad + * redefined to DIMM valid bits. Consumers check CPUID and bank and + * then interpret aux0/aux1 + */ + +/* #define DEBUG 1 */ /* disable for production */ +#define pr_fmt(x) "MCE: " x + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mce-internal.h" + +#define PFA_SIG "$PFA" +#define PFA_SIG_LEN 4 + +/* DIMM description */ +struct aux_pfa_dimm { + u8 fbd_channel_id; + u8 ddr_channel_id; + u8 ddr_dimm_id; + u8 ddr_rank_id; + u8 ddr_dimm_bank_id; + u8 ddr_dimm_row_id; + u8 ddr_dimm_column_id; + u8 valid; +} __attribute__((packed)); + +struct pfa_dimm { + u8 fbd_channel_id; + u8 ddr_channel_id; + u8 ddr_dimm_id; + u8 ddr_rank_id; + u8 ddr_dimm_bank_id; + u32 ddr_dimm_row_id; + u32 ddr_dimm_column_id; +} __attribute__((packed)); + +/* Memory translation table in memory. */ +struct pfa_table { + u8 sig[PFA_SIG_LEN]; /* Signature: '$PFA' */ + u16 len; /* total length */ + u16 revision; /* 0x11 */ + u8 checksum; /* 8bit sum to zero */ + u8 db_value; /* mailbox port command value */ + u8 db_port; /* mailbox port */ + /* end of header; end of checksum */ + u8 command; /* input command */ + u32 valid; /* valid input/output bits */ + u16 status; /* output status */ + u8 socket_id; /* input socket id*/ + u8 bank_id; /* input MCE bank id */ + u32 pad1; + u64 mbox_address; + u64 physical_addr; /* physical address */ + struct pfa_dimm dimm[2]; + /* + * topology information follows: not used for now. + */ +} __attribute__((packed)); + +/* DIMM valid bits in valid: DIMM0: 8..12; DIMM1 16..20 */ +#define DIMM_VALID_BITS(val, num) (((val) >> (4 + (num) * 8)) & DIMM_VALID_ALL) +#define DIMM_SET_VALID(val, num) ((val) << (4 + (num) * 8)) + +enum { + MCE_BANK_MBOX0 = 8, + MCE_BANK_MBOX1 = 9, + + PFA_REVISION = 0x11, /* v1.1 */ + + /* Status bits for valid field */ + PFA_VALID_MA = (1 << 0), + PFA_VALID_SOCKETID = (1 << 1), + PFA_VALID_BANKID = (1 << 2), + PFA_VALID_PA = (1 << 3), + + /* DIMM valid bits in valid */ + /* use with DIMM_VALID_BITS/DIMM_SET_VALID for pfa->valid */ + DIMM_VALID_FBD_CHAN = (1 << 0), + DIMM_VALID_DDR_CHAN = (1 << 1), + DIMM_VALID_DDR_DIMM = (1 << 2), + DIMM_VALID_DDR_RANK = (1 << 3), + DIMM_VALID_DIMM_BANK = (1 << 4), + DIMM_VALID_DIMM_ROW = (1 << 5), + DIMM_VALID_DIMM_COLUMN = (1 << 6), + DIMM_VALID_ALL = 0x7f, + + PFA_DIMM_VALID_MASK = DIMM_SET_VALID(DIMM_VALID_ALL, 0) + | DIMM_SET_VALID(DIMM_VALID_ALL, 1), + + /* Values for status field */ + PFA_STATUS_SUCCESS = 0, + PFA_STATUS_SOCKET_INVALID = (1 << 1), + PFA_STATUS_MBOX_INVALID = (1 << 2), + PFA_STATUS_MA_INVALID = (1 << 3), + PFA_STATUS_PA_INVALID = (1 << 4), + + /* Values for command field */ + PFA_CMD_GET_MEM_CORR_ERR_PA = 0, + PFA_CMD_PA_TO_DIMM_ADDR = 1, + PFA_CMD_DIMM_TO_PA = 2, + PFA_CMD_GET_TOPOLOGY = 3, + + /* PCI device IDs and the base register */ + ICH_PFA_CFG = 0x8c, /* SCRATCH4 */ + PCI_DEVICE_ID_BXB_ICH_LEGACY0 = 0x3422, +}; + +static struct pfa_table *pfa_table __read_mostly; +static int memerr_max_conv_rate __read_mostly = 100; +static int memerr_min_interval __read_mostly = 500; +static int pfa_lost; /* for diagnosis */ + +enum { + RATE_LIMIT_PERIOD = USEC_PER_SEC, /* in us; period of rate limit */ +}; + +module_param(memerr_max_conv_rate, int, 0644); +MODULE_PARM_DESC(memerr_max_conv_rate, + "Maximum number of memory error conversions each second; 0 to disable"); +module_param(memerr_min_interval, int, 0644); +MODULE_PARM_DESC(memerr_min_interval, + "Minimum time delta between two memory conversions; in us; default 500"); + +static int notest; +static int nocsum; +module_param(notest, int, 0); +module_param(nocsum, int, 0); + +static u64 encode_dimm(struct pfa_dimm *d, u8 valid) +{ + union { + struct aux_pfa_dimm d; + u64 v; + } p; + + BUILD_BUG_ON(sizeof(struct aux_pfa_dimm) != sizeof(u64)); + p.d.fbd_channel_id = d->fbd_channel_id; + p.d.ddr_channel_id = d->ddr_channel_id; + p.d.ddr_dimm_id = d->ddr_dimm_id; + p.d.ddr_rank_id = d->ddr_rank_id; + p.d.ddr_dimm_bank_id = d->ddr_dimm_bank_id; + p.d.ddr_dimm_row_id = d->ddr_dimm_row_id; + if (p.d.ddr_dimm_row_id != d->ddr_dimm_row_id) /* truncated? */ + valid &= ~DIMM_VALID_DIMM_ROW; + p.d.ddr_dimm_column_id = d->ddr_dimm_column_id; + if (p.d.ddr_dimm_column_id != d->ddr_dimm_column_id) + valid &= ~DIMM_VALID_DIMM_COLUMN; + p.d.valid = valid; + pr_debug("PFA fbd_ch %u ddr_ch %u dimm %u rank %u bank %u valid %x\n", + d->fbd_channel_id, + d->ddr_channel_id, + d->ddr_dimm_id, + d->ddr_rank_id, + d->ddr_dimm_bank_id, + valid); + return p.v; +} + +static u8 csum(u8 *table, u16 len) +{ + u8 sum = 0; + int i; + for (i = 0; i < len; i++) + sum += *table++; + return sum; +} + +/* + * Execute a command through the mailbox interface. + */ +static int +pfa_command(unsigned bank, unsigned socketid, unsigned command, unsigned valid) +{ + pfa_table->bank_id = bank; + pfa_table->socket_id = socketid; + pfa_table->valid = valid | PFA_VALID_SOCKETID; + pfa_table->command = command; + + outb(pfa_table->db_value, pfa_table->db_port); + + mb(); /* Reread fields after they got changed */ + + if (pfa_table->status != PFA_STATUS_SUCCESS) { + pr_debug("Memory PFA command %d failed: socket:%d bank:%d status:%x\n", + command, socketid, bank, pfa_table->status); + return -pfa_table->status; + } + return 0; +} + +/* + * Retrieve physical address and DIMMs. + */ +static int translate_memory_error(struct mce *m) +{ + struct pfa_table *pfa = pfa_table; + u64 status; + int ret; + u32 valid; + int cpu = smp_processor_id(); + + /* Make sure our structures match the specification */ + BUILD_BUG_ON(offsetof(struct pfa_table, physical_addr) != 0x20); + BUILD_BUG_ON(offsetof(struct pfa_table, status) != 0x10); + BUILD_BUG_ON(offsetof(struct pfa_table, physical_addr) != 0x20); + BUILD_BUG_ON(offsetof(struct pfa_table, dimm[1].ddr_dimm_column_id) != + 0x3e); + + /* Ask for PA/DIMMs of last error */ + if (pfa_command(m->bank, m->socketid, + PFA_CMD_GET_MEM_CORR_ERR_PA, PFA_VALID_BANKID) < 0) + return -1; + + /* + * Recheck machine check bank. If the overflow bit was set + * there was a race. Don't use the information in this case. + */ + rdmsrl(MSR_IA32_MCx_STATUS(m->bank), status); + if (status & MCI_STATUS_OVER) { + pr_debug("%d: overflow race on bank %d\n", cpu, m->bank); + return -1; + } + + ret = -1; + valid = pfa->valid; + if (valid & PFA_VALID_PA) { + m->status |= MCI_STATUS_ADDRV; + m->addr = pfa_table->physical_addr; + pr_debug("%d: got physical address %llx valid %x\n", + cpu, m->addr, valid); + ret = 0; + } + + /* When DIMM information was supplied pass it out */ + if (valid & PFA_DIMM_VALID_MASK) { + m->aux0 = encode_dimm(&pfa->dimm[0], DIMM_VALID_BITS(valid, 0)); + m->aux1 = encode_dimm(&pfa->dimm[1], DIMM_VALID_BITS(valid, 1)); + ret = 0; + } + + return ret; +} + +/* + * Xeon 75xx specific mce poll method to retrieve the physical address + * and DIMM information. + */ +static void xeon75xx_mce_poll(struct mce *m) +{ + static DEFINE_SPINLOCK(convert_lock); /* Protect table and static */ + static unsigned long cperm; + static ktime_t last, last_int; + unsigned long flags; + ktime_t now; + s64 delta; + + /* Memory error? */ + if (m->bank != MCE_BANK_MBOX0 && m->bank != MCE_BANK_MBOX1) + return; + if (m->status & MCI_STATUS_OVER) + return; + if (memerr_max_conv_rate == 0) + return; + + spin_lock_irqsave(&convert_lock, flags); + /* + * Rate limit conversions. The conversion takes some time, + * but it's not good to use all the CPU time during a error + * flood. + * Enforce maximum number per second and minimum interval. + * The ktime call should use TSC on this machine and be fast. + */ + now = ktime_get(); + delta = ktime_us_delta(now, last); + if (delta >= RATE_LIMIT_PERIOD) { + cperm = 0; + last = now; + } + if (ktime_us_delta(now, last_int) >= memerr_min_interval && + ++cperm <= memerr_max_conv_rate) { + if (translate_memory_error(m) < 0) { + /* On error stop converting for the next second */ + cperm = memerr_max_conv_rate; + pr_debug("PFA translation failed\n"); + } + } else + pfa_lost++; + last_int = now; + spin_unlock_irqrestore(&convert_lock, flags); +} + +static struct pci_device_id bxb_mce_pciids[] = { + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_BXB_ICH_LEGACY0) }, + {} +}; + +static int __init xeon75xx_mce_init(void) +{ + u32 addr = 0; + struct pci_dev *dev; + + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || + boot_cpu_data.x86 != 6 || + boot_cpu_data.x86_model != 0x2e) + return -ENODEV; + + /* + * Get table address from register in IOH. + * This just looks up the device, because we don't want to "own" it. + */ + dev = NULL; + while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, dev)) + != NULL) { + if (!pci_match_id(bxb_mce_pciids, dev)) + continue; + pci_read_config_dword(dev, ICH_PFA_CFG, &addr); + if (addr) + break; + } + pci_dev_put(dev); + if (!addr) + return -ENODEV; + + if (!e820_all_mapped(addr, addr + PAGE_SIZE, E820_RESERVED)) { + pr_info("PFA table at %x not e820 reserved\n", addr); + return -ENODEV; + } + + pfa_table = (__force struct pfa_table *)ioremap_cache(addr, PAGE_SIZE); + if (!pfa_table) { + pr_err("Cannot map PFA table at %x\n", addr); + return -EIO; + } + + if (memcmp(&pfa_table->sig, PFA_SIG, PFA_SIG_LEN) || + pfa_table->len < sizeof(struct pfa_table) || + /* assume newer versions are compatible */ + pfa_table->revision < PFA_REVISION) { + pr_info("PFA table at %x invalid\n", addr); + goto error_unmap; + } + + if (!nocsum && csum((u8 *)pfa_table, + offsetof(struct pfa_table, command))) { + pr_info("PFA table at %x length %u has invalid checksum\n", + addr, pfa_table->len); + goto error_unmap; + } + + /* Not strictly needed today */ + if (pfa_table->len > PAGE_SIZE) { + unsigned len = roundup(pfa_table->len, PAGE_SIZE); + iounmap(pfa_table); + pfa_table = (__force void *)ioremap_cache(addr, len); + if (!pfa_table) { + pr_err("Cannot remap %u bytes PFA table at %x\n", + len, addr); + return -EIO; + } + } + + if (!notest) { + int status = pfa_command(0, 0, PFA_CMD_GET_TOPOLOGY, 0); + if (status < 0) { + pr_err("Test of PFA table failed: %x\n", -status); + goto error_unmap; + } + } + + pr_info("Found Xeon75xx PFA memory error translation table at %x\n", + addr); + mb(); + mce_cpu_specific_poll = xeon75xx_mce_poll; + return 0; + +error_unmap: + iounmap(pfa_table); + return -ENODEV; +} + +MODULE_DEVICE_TABLE(pci, bxb_mce_pciids); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Andi Kleen"); +MODULE_DESCRIPTION("Intel Xeon 75xx specific DIMM error reporting"); + +#ifdef CONFIG_MODULE +static void __exit xeon75xx_mce_exit(void) +{ + mce_cpu_specific_poll = NULL; + wmb(); + /* Wait for all machine checks to finish before really unloading */ + synchronize_rcu(); + iounmap(pfa_table); +} + +module_init(xeon75xx_mce_init); +module_exit(xeon75xx_mce_exit); +#else +/* When built-in run as soon as the PCI subsystem is up */ +fs_initcall(xeon75xx_mce_init); +#endif --- linux-2.6.37.orig/arch/x86/kernel/cpu/mcheck/mce.c +++ linux-2.6.37/arch/x86/kernel/cpu/mcheck/mce.c @@ -118,6 +118,9 @@ .priority = -1, }; +void (*mce_cpu_specific_poll)(struct mce *); +EXPORT_SYMBOL_GPL(mce_cpu_specific_poll); + /* MCA banks polled by the period polling timer for corrected events */ DEFINE_PER_CPU(mce_banks_t, mce_poll_banks) = { [0 ... BITS_TO_LONGS(MAX_NR_BANKS)-1] = ~0UL @@ -379,6 +382,11 @@ wrmsrl(msr, v); } +static int under_injection(void) +{ + return __get_cpu_var(injectm).finished; +} + /* * Simple lockless ring to communicate PFNs from the exception handler with the * process context work function. This is vastly simplified because there's @@ -582,6 +590,10 @@ if (!(flags & MCP_TIMESTAMP)) m.tsc = 0; + + if (mce_cpu_specific_poll && !under_injection() && !mce_dont_log_ce) + mce_cpu_specific_poll(&m); + /* * Don't get the IP here because it's unlikely to * have anything to do with the actual error location. --- linux-2.6.37.orig/arch/x86/mm/init.c +++ linux-2.6.37/arch/x86/mm/init.c @@ -364,8 +364,9 @@ /* * We just marked the kernel text read only above, now that * we are going to free part of that, we need to make that - * writeable first. + * writeable and non-executable first. */ + set_memory_nx(begin, (end - begin) >> PAGE_SHIFT); set_memory_rw(begin, (end - begin) >> PAGE_SHIFT); printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10); --- linux-2.6.37.orig/arch/x86/mm/init_32.c +++ linux-2.6.37/arch/x86/mm/init_32.c @@ -226,7 +226,7 @@ static inline int is_kernel_text(unsigned long addr) { - if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end) + if (addr >= (unsigned long)_text && addr <= (unsigned long)__init_end) return 1; return 0; } @@ -912,6 +912,23 @@ set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); } +static void mark_nxdata_nx(void) +{ + /* + * When this called, init has already been executed and released, + * so everything past _etext sould be NX. + */ + unsigned long start = PFN_ALIGN(_etext); + /* + * This comes from is_kernel_text upper limit. Also HPAGE where used: + */ + unsigned long size = (((unsigned long)__init_end + HPAGE_SIZE) & HPAGE_MASK) - start; + + if (__supported_pte_mask & _PAGE_NX) + printk(KERN_INFO "NX-protecting the kernel data: %luk\n", size >> 10); + set_pages_nx(virt_to_page(start), size >> PAGE_SHIFT); +} + void mark_rodata_ro(void) { unsigned long start = PFN_ALIGN(_text); @@ -946,6 +963,7 @@ printk(KERN_INFO "Testing CPA: write protecting again\n"); set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT); #endif + mark_nxdata_nx(); } #endif --- linux-2.6.37.orig/arch/x86/mm/mmap.c +++ linux-2.6.37/arch/x86/mm/mmap.c @@ -131,6 +131,12 @@ } else { mm->mmap_base = mmap_base(); mm->get_unmapped_area = arch_get_unmapped_area_topdown; +#ifdef CONFIG_X86_32 + if (!(current->personality & READ_IMPLIES_EXEC) + && !(__supported_pte_mask & _PAGE_NX) + && mmap_is_ia32()) + mm->get_unmapped_exec_area = arch_get_unmapped_exec_area; +#endif mm->unmap_area = arch_unmap_area_topdown; } } --- linux-2.6.37.orig/arch/x86/mm/pageattr.c +++ linux-2.6.37/arch/x86/mm/pageattr.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -255,13 +256,16 @@ unsigned long pfn) { pgprot_t forbidden = __pgprot(0); + pgprot_t required = __pgprot(0); /* * The BIOS area between 640k and 1Mb needs to be executable for * PCI BIOS based config access (CONFIG_PCI_GOBIOS) support. */ - if (within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT)) +#ifdef CONFIG_PCI_BIOS + if (pcibios_enabled && within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT)) pgprot_val(forbidden) |= _PAGE_NX; +#endif /* * The kernel text needs to be executable for obvious reasons @@ -278,6 +282,12 @@ if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT, __pa((unsigned long)__end_rodata) >> PAGE_SHIFT)) pgprot_val(forbidden) |= _PAGE_RW; + /* + * .data and .bss should always be writable. + */ + if (within(address, (unsigned long)_sdata, (unsigned long)_edata) || + within(address, (unsigned long)__bss_start, (unsigned long)__bss_stop)) + pgprot_val(required) |= _PAGE_RW; #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) /* @@ -317,6 +327,7 @@ #endif prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden)); + prot = __pgprot(pgprot_val(prot) | pgprot_val(required)); return prot; } @@ -393,7 +404,7 @@ { unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn; pte_t new_pte, old_pte, *tmp; - pgprot_t old_prot, new_prot; + pgprot_t old_prot, new_prot, req_prot; int i, do_split = 1; unsigned int level; @@ -438,10 +449,10 @@ * We are safe now. Check whether the new pgprot is the same: */ old_pte = *kpte; - old_prot = new_prot = pte_pgprot(old_pte); + old_prot = new_prot = req_prot = pte_pgprot(old_pte); - pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr); - pgprot_val(new_prot) |= pgprot_val(cpa->mask_set); + pgprot_val(req_prot) &= ~pgprot_val(cpa->mask_clr); + pgprot_val(req_prot) |= pgprot_val(cpa->mask_set); /* * old_pte points to the large page base address. So we need @@ -450,17 +461,17 @@ pfn = pte_pfn(old_pte) + ((address & (psize - 1)) >> PAGE_SHIFT); cpa->pfn = pfn; - new_prot = static_protections(new_prot, address, pfn); + new_prot = static_protections(req_prot, address, pfn); /* * We need to check the full range, whether * static_protection() requires a different pgprot for one of * the pages in the range we try to preserve: */ - addr = address + PAGE_SIZE; - pfn++; - for (i = 1; i < cpa->numpages; i++, addr += PAGE_SIZE, pfn++) { - pgprot_t chk_prot = static_protections(new_prot, addr, pfn); + addr = address & pmask; + pfn = pte_pfn(old_pte); + for (i = 0; i < (psize >> PAGE_SHIFT); i++, addr += PAGE_SIZE, pfn++) { + pgprot_t chk_prot = static_protections(req_prot, addr, pfn); if (pgprot_val(chk_prot) != pgprot_val(new_prot)) goto out_unlock; @@ -483,7 +494,7 @@ * that we limited the number of possible pages already to * the number of pages in the large page. */ - if (address == (nextpage_addr - psize) && cpa->numpages == numpages) { + if (address == (address & pmask) && cpa->numpages == (psize >> PAGE_SHIFT)) { /* * The address is aligned and the number of pages * covers the full page. --- linux-2.6.37.orig/arch/x86/mm/setup_nx.c +++ linux-2.6.37/arch/x86/mm/setup_nx.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,7 +6,7 @@ #include #include -static int disable_nx __cpuinitdata; +int disable_nx __cpuinitdata; /* * noexec = on|off @@ -40,8 +41,18 @@ void __init x86_report_nx(void) { if (!cpu_has_nx) { +#ifdef CONFIG_X86_32 + if (!disable_nx) + printk(KERN_INFO "NX (Execute Disable) protection: " + "approximated by x86 segment limits\n"); + else + printk(KERN_INFO "NX (Execute Disable) protection: " + "approximation disabled by kernel command " + "line option\n"); +#else printk(KERN_NOTICE "Notice: NX (Execute Disable) protection " - "missing in CPU or disabled in BIOS!\n"); + "missing in CPU!\n"); +#endif } else { #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) if (disable_nx) { --- linux-2.6.37.orig/arch/x86/mm/tlb.c +++ linux-2.6.37/arch/x86/mm/tlb.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -134,6 +135,12 @@ union smp_flush_state *f; cpu = smp_processor_id(); + +#ifdef CONFIG_X86_32 + if (current->active_mm) + load_user_cs_desc(cpu, current->active_mm); +#endif + /* * orig_rax contains the negated interrupt vector. * Use that to determine where the sender put the data. --- linux-2.6.37.orig/arch/x86/pci/pcbios.c +++ linux-2.6.37/arch/x86/pci/pcbios.c @@ -9,6 +9,7 @@ #include #include #include +#include /* BIOS32 signature: "_32_" */ #define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) @@ -25,6 +26,27 @@ #define PCIBIOS_HW_TYPE1_SPEC 0x10 #define PCIBIOS_HW_TYPE2_SPEC 0x20 +int pcibios_enabled; + +/* According to the BIOS specification at: + * http://members.datafast.net.au/dft0802/specs/bios21.pdf, we could + * restrict the x zone to some pages and make it ro. But this may be + * broken on some bios, complex to handle with static_protections. + * We could make the 0xe0000-0x100000 range rox, but this can break + * some ISA mapping. + * + * So we let's an rw and x hole when pcibios is used. This shouldn't + * happen for modern system with mmconfig, and if you don't want it + * you could disable pcibios... + */ +static inline void set_bios_x(void) +{ + pcibios_enabled = 1; + set_memory_x(PAGE_OFFSET + BIOS_BEGIN, (BIOS_END - BIOS_BEGIN) >> PAGE_SHIFT); + if (__supported_pte_mask & _PAGE_NX) + printk(KERN_INFO "PCI : PCI BIOS aera is rw and x. Use pci=nobios if you want it NX.\n"); +} + /* * This is the standard structure used to identify the entry point * to the BIOS32 Service Directory, as documented in @@ -332,6 +354,7 @@ DBG("PCI: BIOS32 Service Directory entry at 0x%lx\n", bios32_entry); bios32_indirect.address = bios32_entry + PAGE_OFFSET; + set_bios_x(); if (check_pcibios()) return &pci_bios_access; } --- linux-2.6.37.orig/arch/x86/vdso/vdso32-setup.c +++ linux-2.6.37/arch/x86/vdso/vdso32-setup.c @@ -331,7 +331,7 @@ if (compat) addr = VDSO_HIGH_BASE; else { - addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); + addr = get_unmapped_area_prot(NULL, 0, PAGE_SIZE, 0, 0, 1); if (IS_ERR_VALUE(addr)) { ret = addr; goto up_fail; --- linux-2.6.37.orig/arch/x86/xen/enlighten.c +++ linux-2.6.37/arch/x86/xen/enlighten.c @@ -358,6 +358,24 @@ xen_mc_issue(PARAVIRT_LAZY_CPU); } +#ifdef CONFIG_X86_32 +static void xen_load_user_cs_desc(int cpu, struct mm_struct *mm) +{ + void *gdt; + xmaddr_t mgdt; + u64 descriptor; + struct desc_struct user_cs; + + gdt = &get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS]; + mgdt = virt_to_machine(gdt); + + user_cs = mm->context.user_cs; + descriptor = (u64) user_cs.a | ((u64) user_cs.b) << 32; + + HYPERVISOR_update_descriptor(mgdt.maddr, descriptor); +} +#endif /*CONFIG_X86_32*/ + static void xen_load_gdt(const struct desc_ptr *dtr) { unsigned long va = dtr->address; @@ -798,6 +816,7 @@ { cr4 &= ~X86_CR4_PGE; cr4 &= ~X86_CR4_PSE; + cr4 &= ~X86_CR4_OSXSAVE; native_write_cr4(cr4); } @@ -982,6 +1001,9 @@ .load_tr_desc = paravirt_nop, .set_ldt = xen_set_ldt, +#ifdef CONFIG_X86_32 + .load_user_cs_desc = xen_load_user_cs_desc, +#endif /*CONFIG_X86_32*/ .load_gdt = xen_load_gdt, .load_idt = xen_load_idt, .load_tls = xen_load_tls, --- linux-2.6.37.orig/Documentation/Yama.txt +++ linux-2.6.37/Documentation/Yama.txt @@ -0,0 +1,91 @@ +Yama is a Linux Security Module that collects a number of security +protections that are not handled by the core kernel itself. To select +it at boot time, specify "security=yama" (though this will disable any +other LSM). + +Yama is controlled through sysctl in /proc/sys/kernel/yama: + +- protected_sticky_symlinks +- protected_nonaccess_hardlinks +- ptrace_scope + +============================================================== + +protected_sticky_symlinks: + +A long-standing class of security issues is the symlink-based +time-of-check-time-of-use race, most commonly seen in world-writable +directories like /tmp. The common method of exploitation of this flaw +is to cross privilege boundaries when following a given symlink (i.e. a +root process follows a symlink belonging to another user). For a likely +incomplete list of hundreds of examples across the years, please see: +http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=/tmp + +When set to "0", symlink following behavior is unrestricted. + +When set to "1" symlinks are permitted to be followed only when outside +a sticky world-writable directory, or when the uid of the symlink and +follower match, or when the directory owner matches the symlink's owner. + +This protection is based on the restrictions in Openwall and grsecurity. + +============================================================== + +protected_nonaccess_hardlinks: + +Hardlinks can be abused in a similar fashion to symlinks in sticky +world-writable directories, but their weakness is not limited to +just that scenario. For example, if /etc and /home are on the same +partition, a regular user can create a hardlink to /etc/shadow in their +home directory. While it retains the original owner and permissions, +it is possible for privileged programs that are otherwise symlink-safe +to mistakenly access the file through its hardlink. Additionally, a very +minor untraceable quota-bypassing local denial of service is possible by +an attacker exhausting disk space by filling a world-writable directory +with hardlinks. + +When set to "0", hardlink creation behavior is unrestricted. + +When set to "1", hardlinks cannot be created to files that a given user +would be unable to read and write originally, or are otherwise sensitive. + +This protection is based on the restrictions in Openwall and grsecurity. + +============================================================== + +ptrace_scope: + +As Linux grows in popularity, it will become a larger target for +malware. One particularly troubling weakness of the Linux process +interfaces is that a single user is able to examine the memory and +running state of any of their processes. For example, if one application +(e.g. Pidgin) was compromised, it would be possible for an attacker to +attach to other running processes (e.g. Firefox, SSH sessions, GPG agent, +etc) to extract additional credentials and continue to expand the scope +of their attack without resorting to user-assisted phishing. + +This is not a theoretical problem. SSH session hijacking +(http://www.storm.net.nz/projects/7) and arbitrary code injection +(http://c-skills.blogspot.com/2007/05/injectso.html) attacks already +exist and remain possible if PTRACE is allowed to operate as before. +PTRACE is not commonly used by non-developers and non-admins, so system +builders should be allowed the option to disable this debugging system. + +For a solution, some applications use prctl(PR_SET_DUMPABLE, ...) to +specifically disallow such PTRACE attachment (e.g. ssh-agent), but many +do not. A more general solution is to only allow PTRACE directly from a +parent to a child process (i.e. direct "gdb EXE" and "strace EXE" still +work), or with CAP_SYS_PTRACE (i.e. "gdb --pid=PID", and "strace -p PID" +still work as root). + +0 - classic PTRACE permissions: a process can PTRACE any other process + running under the same uid, as long as it is dumpable (i.e. did not + transition uids, start privileged, or have prctl(PR_SET_DUMPABLE...) + called). + +1 - child-only PTRACE: a process can PTRACE only its descendants when + the above classic criteria is also met. + +This protection is based on the restrictions in grsecurity. + +============================================================== --- linux-2.6.37.orig/Documentation/kernel-parameters.txt +++ linux-2.6.37/Documentation/kernel-parameters.txt @@ -1622,6 +1622,8 @@ noapic [SMP,APIC] Tells the kernel to not make use of any IOAPICs that may be present in the system. + noautogroup Disable scheduler automatic task group creation. + nobats [PPC] Do not use BATs for mapping kernel lowmem on "Classic" PPC cores. --- linux-2.6.37.orig/drivers/acpi/battery.c +++ linux-2.6.37/drivers/acpi/battery.c @@ -925,6 +925,18 @@ power_supply_changed(&battery->bat); } +static LIST_HEAD(acpi_battery_domain); + +static void acpi_battery_update_async(struct acpi_device *device, async_cookie_t cookie) +{ + struct acpi_battery *battery = acpi_driver_data(device); + + acpi_battery_update(battery); + printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", + ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), + device->status.battery_present ? "present" : "absent"); +} + static int acpi_battery_add(struct acpi_device *device) { int result = 0; @@ -943,14 +955,14 @@ if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle, "_BIX", &handle))) set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags); - acpi_battery_update(battery); + /* Mark the battery for update at first access. */ + battery->update_time = 0; #ifdef CONFIG_ACPI_PROCFS_POWER result = acpi_battery_add_fs(device); #endif if (!result) { - printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", - ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), - device->status.battery_present ? "present" : "absent"); + async_schedule_domain(acpi_battery_update_async, device, &acpi_battery_domain); + } else { #ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_remove_fs(device); @@ -966,6 +978,10 @@ if (!device || !acpi_driver_data(device)) return -EINVAL; + + /* Ensure all async updates are complete before freeing the battery. */ + async_synchronize_full_domain(&acpi_battery_domain); + battery = acpi_driver_data(device); #ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_remove_fs(device); @@ -1001,27 +1017,21 @@ }, }; -static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie) +static int __init acpi_battery_init(void) { if (acpi_disabled) return; #ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_dir = acpi_lock_battery_dir(); if (!acpi_battery_dir) - return; + return -1; #endif if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { #ifdef CONFIG_ACPI_PROCFS_POWER acpi_unlock_battery_dir(acpi_battery_dir); #endif - return; + return -1; } - return; -} - -static int __init acpi_battery_init(void) -{ - async_schedule(acpi_battery_init_async, NULL); return 0; } --- linux-2.6.37.orig/drivers/acpi/video.c +++ linux-2.6.37/drivers/acpi/video.c @@ -1488,7 +1488,7 @@ static int acpi_video_bus_start_devices(struct acpi_video_bus *video) { - return acpi_video_bus_DOS(video, 0, 0); + return acpi_video_bus_DOS(video, 0, 1); } static int acpi_video_bus_stop_devices(struct acpi_video_bus *video) --- linux-2.6.37.orig/drivers/ata/ahci.c +++ linux-2.6.37/drivers/ata/ahci.c @@ -380,6 +380,8 @@ { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ { PCI_DEVICE(0x1b4b, 0x9123), .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ + { PCI_DEVICE(0x1b4b, 0x91a3), + .driver_data = board_ahci_yes_fbs }, /* Promise */ { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ --- linux-2.6.37.orig/drivers/base/Kconfig +++ linux-2.6.37/drivers/base/Kconfig @@ -168,4 +168,12 @@ bool default n +config SR_REPORT_TIME_LIMIT + int "Default low threshold" + depends on PM + default 100 + help + Print suspend/resume information for driver/device for time greater + then default msec, ie 100 msec. + endmenu --- linux-2.6.37.orig/drivers/base/power/main.c +++ linux-2.6.37/drivers/base/power/main.c @@ -408,6 +408,24 @@ kobject_name(&dev->kobj), pm_verb(state.event), info, error); } +static void device_show_time(struct device *dev, ktime_t starttime, pm_message_t state, char *info) +{ + ktime_t calltime; + s64 usecs64; + int usecs; + + calltime = ktime_get(); + usecs64 = ktime_to_ns(ktime_sub(calltime, starttime)); + do_div(usecs64, NSEC_PER_USEC); + usecs = usecs64; + if (usecs == 0) + usecs = 1; + if ((usecs / USEC_PER_MSEC) > CONFIG_SR_REPORT_TIME_LIMIT) + pr_info("PM: %s%s%s of drv:%s dev:%s complete after %ld.%03ld msecs\n", info ?: "", info ? " " : "", pm_verb(state.event), + dev_driver_string(dev), dev_name(dev), usecs / USEC_PER_MSEC, + usecs % USEC_PER_MSEC); +} + static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info) { ktime_t calltime; @@ -438,6 +456,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) { int error = 0; + ktime_t starttime = ktime_get(); TRACE_DEVICE(dev); TRACE_RESUME(0); @@ -447,6 +466,7 @@ error = pm_noirq_op(dev, dev->bus->pm, state); if (error) goto End; + device_show_time(dev, starttime, state, "early"); } if (dev->type && dev->type->pm) { @@ -537,6 +557,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) { int error = 0; + ktime_t starttime = ktime_get(); TRACE_DEVICE(dev); TRACE_RESUME(0); @@ -576,6 +597,7 @@ error = legacy_resume(dev, dev->class->resume); } } + device_show_time(dev, starttime, state, NULL); End: device_unlock(dev); complete_all(&dev->power.completion); @@ -769,6 +791,7 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) { int error = 0; + ktime_t starttime = ktime_get(); if (dev->class && dev->class->pm) { pm_dev_dbg(dev, state, "LATE class "); @@ -787,6 +810,7 @@ if (dev->bus && dev->bus->pm) { pm_dev_dbg(dev, state, "LATE "); error = pm_noirq_op(dev, dev->bus->pm, state); + device_show_time(dev, starttime, state, "late"); } End: @@ -869,6 +893,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) { int error = 0; + ktime_t starttime = ktime_get(); dpm_wait_for_children(dev, async); device_lock(dev); @@ -910,6 +935,7 @@ if (!error) dev->power.status = DPM_OFF; + device_show_time(dev, starttime, state, NULL); End: device_unlock(dev); complete_all(&dev->power.completion); --- linux-2.6.37.orig/drivers/block/nbd.c +++ linux-2.6.37/drivers/block/nbd.c @@ -59,7 +59,7 @@ static unsigned int nbds_max = 16; static struct nbd_device *nbd_dev; -static int max_part; +static int max_part = 15; /* * Use just one lock (or at most 1 per NIC). Two arguments for this: --- linux-2.6.37.orig/drivers/block/xen-blkfront.c +++ linux-2.6.37/drivers/block/xen-blkfront.c @@ -72,7 +72,8 @@ static DEFINE_MUTEX(blkfront_mutex); static const struct block_device_operations xlvbd_block_fops; -#define BLK_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE) +#define BLK_MAX_RING_AREA_SIZE (BLKIF_MAX_NUM_RING_PAGES * PAGE_SIZE) +#define BLK_MAX_RING_SIZE __CONST_RING_SIZE(blkif, BLK_MAX_RING_AREA_SIZE) /* * We have one of these per vbd, whether ide, scsi or 'other'. They @@ -87,14 +88,15 @@ int vdevice; blkif_vdev_t handle; enum blkif_state connected; - int ring_ref; + int num_ring_pages; + int ring_ref[BLKIF_MAX_NUM_RING_PAGES]; struct blkif_front_ring ring; struct scatterlist sg[BLKIF_MAX_SEGMENTS_PER_REQUEST]; unsigned int evtchn, irq; struct request_queue *rq; struct work_struct work; struct gnttab_free_callback callback; - struct blk_shadow shadow[BLK_RING_SIZE]; + struct blk_shadow shadow[BLK_MAX_RING_SIZE]; unsigned long shadow_free; unsigned int feature_flush; int is_ready; @@ -126,7 +128,8 @@ static int get_id_from_freelist(struct blkfront_info *info) { unsigned long free = info->shadow_free; - BUG_ON(free >= BLK_RING_SIZE); + int ring_size = __RING_SIZE((struct blkif_sring *)0, info->num_ring_pages * PAGE_SIZE); + BUG_ON(free >= ring_size); info->shadow_free = info->shadow[free].req.id; info->shadow[free].req.id = 0x0fffffee; /* debug */ return free; @@ -584,6 +587,8 @@ static void blkif_free(struct blkfront_info *info, int suspend) { + int i; + /* Prevent new requests being issued until we fix things up. */ spin_lock_irq(&blkif_io_lock); info->connected = suspend ? @@ -599,10 +604,17 @@ flush_scheduled_work(); /* Free resources associated with old device channel. */ - if (info->ring_ref != GRANT_INVALID_REF) { - gnttab_end_foreign_access(info->ring_ref, 0, - (unsigned long)info->ring.sring); - info->ring_ref = GRANT_INVALID_REF; + for (i = 0; i < info->num_ring_pages; i++) { + /* Free resources associated with old device channel. */ + if (info->ring_ref[i] != GRANT_INVALID_REF) { + gnttab_end_foreign_access(info->ring_ref[i], 0, 0L); + info->ring_ref[i] = GRANT_INVALID_REF; + } + } + if (info->ring.sring) { + int ring_area_size = info->num_ring_pages * PAGE_SIZE; + free_pages((unsigned long)info->ring.sring, + get_order(ring_area_size)); info->ring.sring = NULL; } if (info->irq) @@ -705,27 +717,32 @@ struct blkfront_info *info) { struct blkif_sring *sring; - int err; + int i, order, err; + int ring_area_size = info->num_ring_pages * PAGE_SIZE; - info->ring_ref = GRANT_INVALID_REF; + for (i = 0; i < info->num_ring_pages; i++) { + info->ring_ref[i] = GRANT_INVALID_REF; + } - sring = (struct blkif_sring *)__get_free_page(GFP_NOIO | __GFP_HIGH); + order = get_order(ring_area_size); + sring = (struct blkif_sring *)__get_free_pages(GFP_KERNEL, order); if (!sring) { xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); return -ENOMEM; } SHARED_RING_INIT(sring); - FRONT_RING_INIT(&info->ring, sring, PAGE_SIZE); + FRONT_RING_INIT(&info->ring, sring, ring_area_size); - sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST); - - err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring)); - if (err < 0) { - free_page((unsigned long)sring); - info->ring.sring = NULL; - goto fail; + for (i = 0; i < info->num_ring_pages; i++) { + unsigned long addr = (unsigned long)info->ring.sring + i * PAGE_SIZE; + err = xenbus_grant_ring(dev, virt_to_mfn(addr)); + if (err < 0) { + free_pages((unsigned long)sring, order); + info->ring.sring = NULL; + goto fail; + } + info->ring_ref[i] = err; } - info->ring_ref = err; err = xenbus_alloc_evtchn(dev, &info->evtchn); if (err) @@ -754,7 +771,13 @@ { const char *message = NULL; struct xenbus_transaction xbt; - int err; + int err, i; + + BUILD_BUG_ON(BLKIF_MAX_NUM_RING_PAGES != 1 && + BLKIF_MAX_NUM_RING_PAGES != 2 && + BLKIF_MAX_NUM_RING_PAGES != 4 && + BLKIF_MAX_NUM_RING_PAGES != 8 && + BLKIF_MAX_NUM_RING_PAGES != 16); /* Create shared ring, alloc event channel. */ err = setup_blkring(dev, info); @@ -768,11 +791,30 @@ goto destroy_blkring; } - err = xenbus_printf(xbt, dev->nodename, - "ring-ref", "%u", info->ring_ref); - if (err) { - message = "writing ring-ref"; - goto abort_transaction; + if (info->num_ring_pages == 1) { + err = xenbus_printf(xbt, dev->nodename, + "ring-ref", "%u", info->ring_ref[0]); + if (err) { + message = "writing ring-ref"; + goto abort_transaction; + } + } else { + err = xenbus_printf(xbt, dev->nodename, "num-ring-pages", "%u", + info->num_ring_pages); + if (err) { + message = "writing num-ring-pages"; + goto abort_transaction; + } + for (i = 0; i < info->num_ring_pages; i++) { + char buf[16]; + snprintf(buf, sizeof(buf), "ring-ref%d", i); + err = xenbus_printf(xbt, dev->nodename, buf, "%u", + info->ring_ref[i]); + if (err) { + message = "writing ring-refs"; + goto abort_transaction; + } + } } err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", info->evtchn); @@ -820,6 +862,7 @@ { int err, vdevice, i; struct blkfront_info *info; + int ring_size, max_ring_pages; /* FIXME: Use dynamic device id if this is not set. */ err = xenbus_scanf(XBT_NIL, dev->nodename, @@ -833,6 +876,10 @@ return err; } } + err = xenbus_scanf(XBT_NIL, dev->otherend, + "max-ring-pages", "%u", &max_ring_pages); + if (err != 1) + max_ring_pages = 1; if (xen_hvm_domain()) { char *type; @@ -875,9 +922,13 @@ info->connected = BLKIF_STATE_DISCONNECTED; INIT_WORK(&info->work, blkif_restart_queue); - for (i = 0; i < BLK_RING_SIZE; i++) + info->num_ring_pages = min(max_ring_pages, BLKIF_MAX_NUM_RING_PAGES); + + ring_size = __RING_SIZE((struct blkif_sring *)0, + info->num_ring_pages * PAGE_SIZE); + for (i = 0; i < ring_size; i++) info->shadow[i].req.id = i+1; - info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; + info->shadow[ring_size-1].req.id = 0x0fffffff; /* Front end dir is a number, which is used as the id. */ info->handle = simple_strtoul(strrchr(dev->nodename, '/')+1, NULL, 0); @@ -890,6 +941,9 @@ return err; } + printk(KERN_INFO "blkfront %s num-ring-pages %d nr_ents %d.\n", + dev->nodename, info->num_ring_pages, ring_size); + return 0; } @@ -900,6 +954,7 @@ struct blkif_request *req; struct blk_shadow *copy; int j; + int ring_size = __RING_SIZE((struct blkif_sring *)0, info->num_ring_pages * PAGE_SIZE); /* Stage 1: Make a safe copy of the shadow state. */ copy = kmalloc(sizeof(info->shadow), @@ -910,13 +965,13 @@ /* Stage 2: Set up free list. */ memset(&info->shadow, 0, sizeof(info->shadow)); - for (i = 0; i < BLK_RING_SIZE; i++) + for (i = 0; i < ring_size; i++) info->shadow[i].req.id = i+1; info->shadow_free = info->ring.req_prod_pvt; - info->shadow[BLK_RING_SIZE-1].req.id = 0x0fffffff; + info->shadow[ring_size-1].req.id = 0x0fffffff; /* Stage 3: Find pending requests and requeue them. */ - for (i = 0; i < BLK_RING_SIZE; i++) { + for (i = 0; i < ring_size; i++) { /* Not in use? */ if (!copy[i].request) continue; @@ -1318,3 +1373,4 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(XENVBD_MAJOR); MODULE_ALIAS("xen:vbd"); MODULE_ALIAS("xenblk"); + --- linux-2.6.37.orig/drivers/cdrom/cdrom.c +++ linux-2.6.37/drivers/cdrom/cdrom.c @@ -292,7 +292,7 @@ /* default compatibility mode */ static int autoclose=1; static int autoeject; -static int lockdoor = 1; +static int lockdoor = 0; /* will we ever get to use this... sigh. */ static int check_media_type; /* automatically restart mrw format */ --- linux-2.6.37.orig/drivers/char/agp/agp.h +++ linux-2.6.37/drivers/char/agp/agp.h @@ -120,7 +120,6 @@ void (*agp_destroy_page)(struct page *, int flags); void (*agp_destroy_pages)(struct agp_memory *); int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); - void (*chipset_flush)(struct agp_bridge_data *); }; struct agp_bridge_data { --- linux-2.6.37.orig/drivers/char/agp/compat_ioctl.c +++ linux-2.6.37/drivers/char/agp/compat_ioctl.c @@ -276,7 +276,6 @@ break; case AGPIOC_CHIPSET_FLUSH32: - ret_val = agpioc_chipset_flush_wrap(curr_priv); break; } --- linux-2.6.37.orig/drivers/char/agp/compat_ioctl.h +++ linux-2.6.37/drivers/char/agp/compat_ioctl.h @@ -102,6 +102,5 @@ struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type); struct agp_memory *agp_find_mem_by_key(int key); struct agp_client *agp_find_client_by_pid(pid_t id); -int agpioc_chipset_flush_wrap(struct agp_file_private *priv); #endif /* _AGP_COMPAT_H */ --- linux-2.6.37.orig/drivers/char/agp/frontend.c +++ linux-2.6.37/drivers/char/agp/frontend.c @@ -957,13 +957,6 @@ return agp_unbind_memory(memory); } -int agpioc_chipset_flush_wrap(struct agp_file_private *priv) -{ - DBG(""); - agp_flush_chipset(agp_bridge); - return 0; -} - static long agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -1039,7 +1032,6 @@ break; case AGPIOC_CHIPSET_FLUSH: - ret_val = agpioc_chipset_flush_wrap(curr_priv); break; } --- linux-2.6.37.orig/drivers/char/agp/generic.c +++ linux-2.6.37/drivers/char/agp/generic.c @@ -81,13 +81,6 @@ return -1; } -void agp_flush_chipset(struct agp_bridge_data *bridge) -{ - if (bridge->driver->chipset_flush) - bridge->driver->chipset_flush(bridge); -} -EXPORT_SYMBOL(agp_flush_chipset); - /* * Use kmalloc if possible for the page list. Otherwise fall back to * vmalloc. This speeds things up and also saves memory for small AGP @@ -487,26 +480,6 @@ } EXPORT_SYMBOL(agp_unbind_memory); -/** - * agp_rebind_emmory - Rewrite the entire GATT, useful on resume - */ -int agp_rebind_memory(void) -{ - struct agp_memory *curr; - int ret_val = 0; - - spin_lock(&agp_bridge->mapped_lock); - list_for_each_entry(curr, &agp_bridge->mapped_list, mapped_list) { - ret_val = curr->bridge->driver->insert_memory(curr, - curr->pg_start, - curr->type); - if (ret_val != 0) - break; - } - spin_unlock(&agp_bridge->mapped_lock); - return ret_val; -} -EXPORT_SYMBOL(agp_rebind_memory); /* End - Routines for handling swapping of agp_memory into the GATT */ --- linux-2.6.37.orig/drivers/char/agp/intel-agp.c +++ linux-2.6.37/drivers/char/agp/intel-agp.c @@ -828,14 +828,9 @@ static int agp_intel_resume(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - int ret_val; bridge->driver->configure(); - ret_val = agp_rebind_memory(); - if (ret_val != 0) - return ret_val; - return 0; } #endif --- linux-2.6.37.orig/drivers/char/agp/intel-agp.h +++ linux-2.6.37/drivers/char/agp/intel-agp.h @@ -75,6 +75,8 @@ #define I810_GMS_DISABLE 0x00000000 #define I810_PGETBL_CTL 0x2020 #define I810_PGETBL_ENABLED 0x00000001 +/* Note: PGETBL_CTL2 has a different offset on G33. */ +#define I965_PGETBL_CTL2 0x20c4 #define I965_PGETBL_SIZE_MASK 0x0000000e #define I965_PGETBL_SIZE_512KB (0 << 1) #define I965_PGETBL_SIZE_256KB (1 << 1) @@ -82,9 +84,17 @@ #define I965_PGETBL_SIZE_1MB (3 << 1) #define I965_PGETBL_SIZE_2MB (4 << 1) #define I965_PGETBL_SIZE_1_5MB (5 << 1) -#define G33_PGETBL_SIZE_MASK (3 << 8) -#define G33_PGETBL_SIZE_1M (1 << 8) -#define G33_PGETBL_SIZE_2M (2 << 8) +#define G33_GMCH_SIZE_MASK (3 << 8) +#define G33_GMCH_SIZE_1M (1 << 8) +#define G33_GMCH_SIZE_2M (2 << 8) +#define G4x_GMCH_SIZE_MASK (0xf << 8) +#define G4x_GMCH_SIZE_1M (0x1 << 8) +#define G4x_GMCH_SIZE_2M (0x3 << 8) +#define G4x_GMCH_SIZE_VT_1M (0x9 << 8) +#define G4x_GMCH_SIZE_VT_1_5M (0xa << 8) +#define G4x_GMCH_SIZE_VT_2M (0xc << 8) + +#define GFX_FLSH_CNTL 0x2170 /* 915+ */ #define I810_DRAM_CTL 0x3000 #define I810_DRAM_ROW_0 0x00000001 @@ -120,6 +130,7 @@ #define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4) #define I915_IFPADDR 0x60 +#define I830_HIC 0x70 /* Intel 965G registers */ #define I965_MSAC 0x62 --- linux-2.6.37.orig/drivers/char/agp/intel-gtt.c +++ linux-2.6.37/drivers/char/agp/intel-gtt.c @@ -21,10 +21,11 @@ #include #include #include +#include +#include #include #include "agp.h" #include "intel-agp.h" -#include #include /* @@ -39,40 +40,14 @@ #define USE_PCI_DMA_API 0 #endif -/* Max amount of stolen space, anything above will be returned to Linux */ -int intel_max_stolen = 32 * 1024 * 1024; - -static const struct aper_size_info_fixed intel_i810_sizes[] = -{ - {64, 16384, 4}, - /* The 32M mode still requires a 64k gatt */ - {32, 8192, 4} -}; - -#define AGP_DCACHE_MEMORY 1 -#define AGP_PHYS_MEMORY 2 -#define INTEL_AGP_CACHED_MEMORY 3 - -static struct gatt_mask intel_i810_masks[] = -{ - {.mask = I810_PTE_VALID, .type = 0}, - {.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY}, - {.mask = I810_PTE_VALID, .type = 0}, - {.mask = I810_PTE_VALID | I830_PTE_SYSTEM_CACHED, - .type = INTEL_AGP_CACHED_MEMORY} -}; - -#define INTEL_AGP_UNCACHED_MEMORY 0 -#define INTEL_AGP_CACHED_MEMORY_LLC 1 -#define INTEL_AGP_CACHED_MEMORY_LLC_GFDT 2 -#define INTEL_AGP_CACHED_MEMORY_LLC_MLC 3 -#define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT 4 +#define I830_CACHE_COHERENY_CHECKER 1 struct intel_gtt_driver { unsigned int gen : 8; unsigned int is_g33 : 1; unsigned int is_pineview : 1; unsigned int is_ironlake : 1; + unsigned int has_pgtbl_enable : 1; unsigned int dma_mask_size : 8; /* Chipset specific GTT setup */ int (*setup)(void); @@ -95,14 +70,21 @@ u8 __iomem *registers; phys_addr_t gtt_bus_addr; phys_addr_t gma_bus_addr; - phys_addr_t pte_bus_addr; + u32 PGETBL_save; u32 __iomem *gtt; /* I915G */ int num_dcache_entries; union { void __iomem *i9xx_flush_page; void *i8xx_flush_page; }; + char *i81x_gtt_table; struct page *i8xx_page; +#if I830_CACHE_COHERENY_CHECKER + void *i8xx_cpu_check_page; + void __iomem *i8xx_gtt_check_page; + unsigned int i8xx_cache_flush_num; + struct page *i8xx_cc_page; +#endif struct resource ifp_resource; int resource_valid; struct page *scratch_page; @@ -113,42 +95,31 @@ #define IS_G33 intel_private.driver->is_g33 #define IS_PINEVIEW intel_private.driver->is_pineview #define IS_IRONLAKE intel_private.driver->is_ironlake +#define HAS_PGTBL_EN intel_private.driver->has_pgtbl_enable -static void intel_agp_free_sglist(struct agp_memory *mem) -{ - struct sg_table st; - - st.sgl = mem->sg_list; - st.orig_nents = st.nents = mem->page_count; - - sg_free_table(&st); - - mem->sg_list = NULL; - mem->num_sg = 0; -} - -static int intel_agp_map_memory(struct agp_memory *mem) +int intel_gtt_map_memory(struct page **pages, unsigned int num_entries, + struct scatterlist **sg_list, int *num_sg) { struct sg_table st; struct scatterlist *sg; int i; - if (mem->sg_list) + if (*sg_list) return 0; /* already mapped (for e.g. resume */ - DBG("try mapping %lu pages\n", (unsigned long)mem->page_count); + DBG("try mapping %lu pages\n", (unsigned long)num_entries); - if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL)) + if (sg_alloc_table(&st, num_entries, GFP_KERNEL)) goto err; - mem->sg_list = sg = st.sgl; + *sg_list = sg = st.sgl; - for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg)) - sg_set_page(sg, mem->pages[i], PAGE_SIZE, 0); + for (i = 0 ; i < num_entries; i++, sg = sg_next(sg)) + sg_set_page(sg, pages[i], PAGE_SIZE, 0); - mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list, - mem->page_count, PCI_DMA_BIDIRECTIONAL); - if (unlikely(!mem->num_sg)) + *num_sg = pci_map_sg(intel_private.pcidev, *sg_list, + num_entries, PCI_DMA_BIDIRECTIONAL); + if (unlikely(!*num_sg)) goto err; return 0; @@ -157,90 +128,22 @@ sg_free_table(&st); return -ENOMEM; } +EXPORT_SYMBOL(intel_gtt_map_memory); -static void intel_agp_unmap_memory(struct agp_memory *mem) +void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg) { + struct sg_table st; DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); - pci_unmap_sg(intel_private.pcidev, mem->sg_list, - mem->page_count, PCI_DMA_BIDIRECTIONAL); - intel_agp_free_sglist(mem); -} + pci_unmap_sg(intel_private.pcidev, sg_list, + num_sg, PCI_DMA_BIDIRECTIONAL); -static int intel_i810_fetch_size(void) -{ - u32 smram_miscc; - struct aper_size_info_fixed *values; - - pci_read_config_dword(intel_private.bridge_dev, - I810_SMRAM_MISCC, &smram_miscc); - values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); + st.sgl = sg_list; + st.orig_nents = st.nents = num_sg; - if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { - dev_warn(&intel_private.bridge_dev->dev, "i810 is disabled\n"); - return 0; - } - if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { - agp_bridge->current_size = (void *) (values + 1); - agp_bridge->aperture_size_idx = 1; - return values[1].size; - } else { - agp_bridge->current_size = (void *) (values); - agp_bridge->aperture_size_idx = 0; - return values[0].size; - } - - return 0; -} - -static int intel_i810_configure(void) -{ - struct aper_size_info_fixed *current_size; - u32 temp; - int i; - - current_size = A_SIZE_FIX(agp_bridge->current_size); - - if (!intel_private.registers) { - pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp); - temp &= 0xfff80000; - - intel_private.registers = ioremap(temp, 128 * 4096); - if (!intel_private.registers) { - dev_err(&intel_private.pcidev->dev, - "can't remap memory\n"); - return -ENOMEM; - } - } - - if ((readl(intel_private.registers+I810_DRAM_CTL) - & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { - /* This will need to be dynamically assigned */ - dev_info(&intel_private.pcidev->dev, - "detected 4MB dedicated video ram\n"); - intel_private.num_dcache_entries = 1024; - } - pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); - agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); - writel(agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL); - readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ - - if (agp_bridge->driver->needs_scratch_page) { - for (i = 0; i < current_size->num_entries; i++) { - writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); - } - readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI posting. */ - } - global_cache_flush(); - return 0; -} - -static void intel_i810_cleanup(void) -{ - writel(0, intel_private.registers+I810_PGETBL_CTL); - readl(intel_private.registers); /* PCI Posting. */ - iounmap(intel_private.registers); + sg_free_table(&st); } +EXPORT_SYMBOL(intel_gtt_unmap_memory); static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode) { @@ -277,80 +180,64 @@ atomic_dec(&agp_bridge->current_memory_agp); } -static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, - int type) +#define I810_GTT_ORDER 4 +static int i810_setup(void) { - int i, j, num_entries; - void *temp; - int ret = -EINVAL; - int mask_type; - - if (mem->page_count == 0) - goto out; - - temp = agp_bridge->current_size; - num_entries = A_SIZE_FIX(temp)->num_entries; + u32 reg_addr; + char *gtt_table; - if ((pg_start + mem->page_count) > num_entries) - goto out_err; + /* i81x does not preallocate the gtt. It's always 64kb in size. */ + gtt_table = alloc_gatt_pages(I810_GTT_ORDER); + if (gtt_table == NULL) + return -ENOMEM; + intel_private.i81x_gtt_table = gtt_table; + pci_read_config_dword(intel_private.pcidev, I810_MMADDR, ®_addr); + reg_addr &= 0xfff80000; - for (j = pg_start; j < (pg_start + mem->page_count); j++) { - if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j))) { - ret = -EBUSY; - goto out_err; - } - } + intel_private.registers = ioremap(reg_addr, KB(64)); + if (!intel_private.registers) + return -ENOMEM; - if (type != mem->type) - goto out_err; + writel(virt_to_phys(gtt_table) | I810_PGETBL_ENABLED, + intel_private.registers+I810_PGETBL_CTL); - mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type); + intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE; - switch (mask_type) { - case AGP_DCACHE_MEMORY: - if (!mem->is_flushed) - global_cache_flush(); - for (i = pg_start; i < (pg_start + mem->page_count); i++) { - writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, - intel_private.registers+I810_PTE_BASE+(i*4)); - } - readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); - break; - case AGP_PHYS_MEMORY: - case AGP_NORMAL_MEMORY: - if (!mem->is_flushed) - global_cache_flush(); - for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - writel(agp_bridge->driver->mask_memory(agp_bridge, - page_to_phys(mem->pages[i]), mask_type), - intel_private.registers+I810_PTE_BASE+(j*4)); - } - readl(intel_private.registers+I810_PTE_BASE+((j-1)*4)); - break; - default: - goto out_err; + if ((readl(intel_private.registers+I810_DRAM_CTL) + & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { + dev_info(&intel_private.pcidev->dev, + "detected 4MB dedicated video ram\n"); + intel_private.num_dcache_entries = 1024; } -out: - ret = 0; -out_err: - mem->is_flushed = true; - return ret; + return 0; } -static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, - int type) +static void i810_cleanup(void) +{ + writel(0, intel_private.registers+I810_PGETBL_CTL); + free_gatt_pages(intel_private.i81x_gtt_table, I810_GTT_ORDER); +} + +static int i810_insert_dcache_entries(struct agp_memory *mem, off_t pg_start, + int type) { int i; - if (mem->page_count == 0) - return 0; + if ((pg_start + mem->page_count) + > intel_private.num_dcache_entries) + return -EINVAL; + + if (!mem->is_flushed) + global_cache_flush(); - for (i = pg_start; i < (mem->page_count + pg_start); i++) { - writel(agp_bridge->scratch_page, intel_private.registers+I810_PTE_BASE+(i*4)); + for (i = pg_start; i < (pg_start + mem->page_count); i++) { + dma_addr_t addr = i << PAGE_SHIFT; + intel_private.driver->write_entry(addr, + i, type); } - readl(intel_private.registers+I810_PTE_BASE+((i-1)*4)); + readl(intel_private.gtt+i-1); return 0; } @@ -397,29 +284,6 @@ return new; } -static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) -{ - struct agp_memory *new; - - if (type == AGP_DCACHE_MEMORY) { - if (pg_count != intel_private.num_dcache_entries) - return NULL; - - new = agp_create_memory(1); - if (new == NULL) - return NULL; - - new->type = AGP_DCACHE_MEMORY; - new->page_count = pg_count; - new->num_scratch_pages = 0; - agp_free_page_array(new); - return new; - } - if (type == AGP_PHYS_MEMORY) - return alloc_agpphysmem_i8xx(pg_count, type); - return NULL; -} - static void intel_i810_free_by_type(struct agp_memory *curr) { agp_free_key(curr->key); @@ -437,13 +301,6 @@ kfree(curr); } -static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge, - dma_addr_t addr, int type) -{ - /* Type checking must be done elsewhere */ - return addr | bridge->driver->masks[type].mask; -} - static int intel_gtt_setup_scratch_page(void) { struct page *page; @@ -455,7 +312,7 @@ get_page(page); set_pages_uc(page, 1); - if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) { + if (intel_private.base.needs_dmar) { dma_addr = pci_map_page(intel_private.pcidev, page, 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) @@ -470,34 +327,45 @@ return 0; } -static const struct aper_size_info_fixed const intel_fake_agp_sizes[] = { +static void i810_write_entry(dma_addr_t addr, unsigned int entry, + unsigned int flags) +{ + u32 pte_flags = I810_PTE_VALID; + + switch (flags) { + case AGP_DCACHE_MEMORY: + pte_flags |= I810_PTE_LOCAL; + break; + case AGP_USER_CACHED_MEMORY: + pte_flags |= I830_PTE_SYSTEM_CACHED; + break; + } + + writel(addr | pte_flags, intel_private.gtt + entry); +} + +static const struct aper_size_info_fixed intel_fake_agp_sizes[] = { + {32, 8192, 3}, + {64, 16384, 4}, {128, 32768, 5}, - /* The 64M mode still requires a 128k gatt */ - {64, 16384, 5}, {256, 65536, 6}, {512, 131072, 7}, }; -static unsigned int intel_gtt_stolen_entries(void) +static unsigned int intel_gtt_stolen_size(void) { u16 gmch_ctrl; u8 rdct; int local = 0; static const int ddt[4] = { 0, 16, 32, 64 }; - unsigned int overhead_entries, stolen_entries; unsigned int stolen_size = 0; + if (INTEL_GTT_GEN == 1) + return 0; /* no stolen mem on i81x */ + pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl); - if (INTEL_GTT_GEN > 4 || IS_PINEVIEW) - overhead_entries = 0; - else - overhead_entries = intel_private.base.gtt_mappable_entries - / 1024; - - overhead_entries += 1; /* BIOS popup */ - if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB || intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { switch (gmch_ctrl & I830_GMCH_GMS_MASK) { @@ -623,12 +491,7 @@ } } - if (!local && stolen_size > intel_max_stolen) { - dev_info(&intel_private.bridge_dev->dev, - "detected %dK stolen memory, trimming to %dK\n", - stolen_size / KB(1), intel_max_stolen / KB(1)); - stolen_size = intel_max_stolen; - } else if (stolen_size > 0) { + if (stolen_size > 0) { dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n", stolen_size / KB(1), local ? "local" : "stolen"); } else { @@ -637,46 +500,88 @@ stolen_size = 0; } - stolen_entries = stolen_size/KB(4) - overhead_entries; + return stolen_size; +} - return stolen_entries; +static void i965_adjust_pgetbl_size(unsigned int size_flag) +{ + u32 pgetbl_ctl, pgetbl_ctl2; + + /* ensure that ppgtt is disabled */ + pgetbl_ctl2 = readl(intel_private.registers+I965_PGETBL_CTL2); + pgetbl_ctl2 &= ~I810_PGETBL_ENABLED; + writel(pgetbl_ctl2, intel_private.registers+I965_PGETBL_CTL2); + + /* write the new ggtt size */ + pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); + pgetbl_ctl &= ~I965_PGETBL_SIZE_MASK; + pgetbl_ctl |= size_flag; + writel(pgetbl_ctl, intel_private.registers+I810_PGETBL_CTL); } -static unsigned int intel_gtt_total_entries(void) +static unsigned int i965_gtt_total_entries(void) { int size; + u32 pgetbl_ctl; + u16 gmch_ctl; - if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) { - u32 pgetbl_ctl; - pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); + pci_read_config_word(intel_private.bridge_dev, + I830_GMCH_CTRL, &gmch_ctl); - switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { - case I965_PGETBL_SIZE_128KB: - size = KB(128); + if (INTEL_GTT_GEN == 5) { + switch (gmch_ctl & G4x_GMCH_SIZE_MASK) { + case G4x_GMCH_SIZE_1M: + case G4x_GMCH_SIZE_VT_1M: + i965_adjust_pgetbl_size(I965_PGETBL_SIZE_1MB); + break; + case G4x_GMCH_SIZE_VT_1_5M: + i965_adjust_pgetbl_size(I965_PGETBL_SIZE_1_5MB); + break; + case G4x_GMCH_SIZE_2M: + case G4x_GMCH_SIZE_VT_2M: + i965_adjust_pgetbl_size(I965_PGETBL_SIZE_2MB); break; - case I965_PGETBL_SIZE_256KB: - size = KB(256); - break; - case I965_PGETBL_SIZE_512KB: - size = KB(512); - break; - case I965_PGETBL_SIZE_1MB: - size = KB(1024); - break; - case I965_PGETBL_SIZE_2MB: - size = KB(2048); - break; - case I965_PGETBL_SIZE_1_5MB: - size = KB(1024 + 512); - break; - default: - dev_info(&intel_private.pcidev->dev, - "unknown page table size, assuming 512KB\n"); - size = KB(512); } + } - return size/4; - } else if (INTEL_GTT_GEN == 6) { + pgetbl_ctl = readl(intel_private.registers+I810_PGETBL_CTL); + + switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { + case I965_PGETBL_SIZE_128KB: + size = KB(128); + break; + case I965_PGETBL_SIZE_256KB: + size = KB(256); + break; + case I965_PGETBL_SIZE_512KB: + size = KB(512); + break; + /* GTT pagetable sizes bigger than 512KB are not possible on G33! */ + case I965_PGETBL_SIZE_1MB: + size = KB(1024); + break; + case I965_PGETBL_SIZE_2MB: + size = KB(2048); + break; + case I965_PGETBL_SIZE_1_5MB: + size = KB(1024 + 512); + break; + default: + dev_info(&intel_private.pcidev->dev, + "unknown page table size, assuming 512KB\n"); + size = KB(512); + } + + return size/4; +} + +static unsigned int intel_gtt_total_entries(void) +{ + int size; + + if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) + return i965_gtt_total_entries(); + else if (INTEL_GTT_GEN == 6) { u16 snb_gmch_ctl; pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); @@ -706,7 +611,18 @@ { unsigned int aperture_size; - if (INTEL_GTT_GEN == 2) { + if (INTEL_GTT_GEN == 1) { + u32 smram_miscc; + + pci_read_config_dword(intel_private.bridge_dev, + I810_SMRAM_MISCC, &smram_miscc); + + if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) + == I810_GFX_MEM_WIN_32M) + aperture_size = MB(32); + else + aperture_size = MB(64); + } else if (INTEL_GTT_GEN == 2) { u16 gmch_ctrl; pci_read_config_word(intel_private.bridge_dev, @@ -739,7 +655,7 @@ iounmap(intel_private.gtt); iounmap(intel_private.registers); - + intel_gtt_teardown_scratch_page(); } @@ -755,6 +671,14 @@ intel_private.base.gtt_mappable_entries = intel_gtt_mappable_entries(); intel_private.base.gtt_total_entries = intel_gtt_total_entries(); + /* save the PGETBL reg for resume */ + intel_private.PGETBL_save = + readl(intel_private.registers+I810_PGETBL_CTL) + & ~I810_PGETBL_ENABLED; + /* we only ever restore the register when enabling the PGTBL... */ + if (HAS_PGTBL_EN) + intel_private.PGETBL_save |= I810_PGETBL_ENABLED; + dev_info(&intel_private.bridge_dev->dev, "detected gtt size: %dK total, %dK mappable\n", intel_private.base.gtt_total_entries * 4, @@ -772,14 +696,7 @@ global_cache_flush(); /* FIXME: ? */ - /* we have to call this as early as possible after the MMIO base address is known */ - intel_private.base.gtt_stolen_entries = intel_gtt_stolen_entries(); - if (intel_private.base.gtt_stolen_entries == 0) { - intel_private.driver->cleanup(); - iounmap(intel_private.registers); - iounmap(intel_private.gtt); - return -ENOMEM; - } + intel_private.base.stolen_size = intel_gtt_stolen_size(); ret = intel_gtt_setup_scratch_page(); if (ret != 0) { @@ -787,6 +704,8 @@ return ret; } + intel_private.base.needs_dmar = USE_PCI_DMA_API && INTEL_GTT_GEN > 2; + return 0; } @@ -810,6 +729,141 @@ return 0; } +static void i830_write_entry(dma_addr_t addr, unsigned int entry, + unsigned int flags) +{ + u32 pte_flags = I810_PTE_VALID; + + if (flags == AGP_USER_CACHED_MEMORY) + pte_flags |= I830_PTE_SYSTEM_CACHED; + + writel(addr | pte_flags, intel_private.gtt + entry); +} + +#if I830_CACHE_COHERENY_CHECKER +static void intel_i830_cc_setup(void) +{ + /* steal one page of the gtt to check coherency */ + intel_private.base.gtt_total_entries--; + intel_private.base.gtt_mappable_entries--; + + intel_private.i8xx_cc_page = + alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32); + if (!intel_private.i8xx_cc_page) + return; + + intel_private.i8xx_cpu_check_page = + kmap(intel_private.i8xx_cc_page); + if(!intel_private.i8xx_cpu_check_page) + return; + + intel_private.i8xx_gtt_check_page = + ioremap_wc(intel_private.gma_bus_addr + + intel_private.base.gtt_total_entries*4096, + 4096); + if (!intel_private.i8xx_gtt_check_page) + return; + + i830_write_entry(page_to_phys(intel_private.i8xx_cc_page), + intel_private.base.gtt_total_entries, 0); + readl(intel_private.gtt+intel_private.base.gtt_total_entries); + + intel_private.i8xx_cache_flush_num = 0; + + dev_info(&intel_private.bridge_dev->dev, + "i830 cache coherency checker enabled\n"); +} + +static void intel_i830_cc_cleanup(void) +{ + if (intel_private.i8xx_gtt_check_page) + iounmap(intel_private.i8xx_gtt_check_page); + intel_private.i8xx_gtt_check_page = NULL; + + if(intel_private.i8xx_cpu_check_page) + kunmap(intel_private.i8xx_cc_page); + intel_private.i8xx_cpu_check_page = NULL; + + if (intel_private.i8xx_cc_page) + __free_page(intel_private.i8xx_cc_page); + intel_private.i8xx_cc_page = NULL; +} + +DEFINE_RATELIMIT_STATE(i8xx_chipset_flush_ratelimit_cpu, 60*HZ, 1); +DEFINE_RATELIMIT_STATE(i8xx_chipset_flush_ratelimit_gtt, 60*HZ, 1); + +static void intel_i830_cc_before_flush(void) +{ + unsigned int offset1 + = (intel_private.i8xx_cache_flush_num * sizeof(int)) % 4096; + unsigned int offset2 + = (intel_private.i8xx_cache_flush_num * sizeof(int) + + 2048) % 4096; + unsigned int *p_cpu_write = intel_private.i8xx_cpu_check_page + offset2; + + /* write check values */ + *p_cpu_write = intel_private.i8xx_cache_flush_num; + mb(); + if (cpu_has_clflush) { + clflush(p_cpu_write); + } else + wbinvd_on_all_cpus(); + writel(intel_private.i8xx_cache_flush_num, + intel_private.i8xx_gtt_check_page + offset1); + mb(); +} + +static void intel_i830_cc_after_flush(void) +{ + unsigned int offset1 + = (intel_private.i8xx_cache_flush_num * sizeof(int)) % 4096; + unsigned int offset2 + = (intel_private.i8xx_cache_flush_num * sizeof(int) + + 2048) % 4096; + unsigned int *p_cpu_read = intel_private.i8xx_cpu_check_page + offset1; + unsigned int gtt_read, cpu_read; + + if (!intel_private.i8xx_gtt_check_page) + return; + + mb(); + gtt_read = readl(intel_private.i8xx_gtt_check_page + offset2); + cpu_read = *p_cpu_read; + + WARN(cpu_read != intel_private.i8xx_cache_flush_num + && __ratelimit(&i8xx_chipset_flush_ratelimit_cpu), + "i8xx chipset flush failed, expected: %u, cpu_read: %u\n", + intel_private.i8xx_cache_flush_num, cpu_read); + WARN(gtt_read != intel_private.i8xx_cache_flush_num + && __ratelimit(&i8xx_chipset_flush_ratelimit_gtt), + "i8xx chipset flush failed, expected: %u, gtt_read: %u\n", + intel_private.i8xx_cache_flush_num, gtt_read); + + clflush(p_cpu_read); + mb(); + + intel_private.i8xx_cache_flush_num++; + if (intel_private.i8xx_cache_flush_num % 256 == 0) + printk("cache flush num %u\n", intel_private.i8xx_cache_flush_num); +} +#else /* I830_CACHE_COHERENY_CHECKER */ +static void intel_i830_cc_setup(void) +{ +} + +static void intel_i830_cc_cleanup(void) +{ +} + +static void intel_i830_cc_before_flush(void) +{ +} + +static void intel_i830_cc_after_flush(void) +{ +} +#endif + static void i830_cleanup(void) { if (intel_private.i8xx_flush_page) { @@ -819,6 +873,8 @@ __free_page(intel_private.i8xx_page); intel_private.i8xx_page = NULL; + + intel_i830_cc_cleanup(); } static void intel_i830_setup_flush(void) @@ -848,39 +904,39 @@ */ static void i830_chipset_flush(void) { - unsigned int *pg = intel_private.i8xx_flush_page; + unsigned long timeout = jiffies + msecs_to_jiffies(1000); - memset(pg, 0, 1024); + intel_i830_cc_before_flush(); - if (cpu_has_clflush) - clflush_cache_range(pg, 1024); - else if (wbinvd_on_all_cpus() != 0) - printk(KERN_ERR "Timed out waiting for cache flush.\n"); -} + /* Forcibly evict everything from the CPU write buffers. + * clflush appears to be insufficient. + */ + wbinvd_on_all_cpus(); -static void i830_write_entry(dma_addr_t addr, unsigned int entry, - unsigned int flags) -{ - u32 pte_flags = I810_PTE_VALID; - - switch (flags) { - case AGP_DCACHE_MEMORY: - pte_flags |= I810_PTE_LOCAL; - break; - case AGP_USER_CACHED_MEMORY: - pte_flags |= I830_PTE_SYSTEM_CACHED; - break; + /* Now we've only seen documents for this magic bit on 855GM, + * we hope it exists for the other gen2 chipsets... + * + * Also works as advertised on my 845G. + */ + writel(readl(intel_private.registers+I830_HIC) | (1<<31), + intel_private.registers+I830_HIC); + + while (readl(intel_private.registers+I830_HIC) & (1<<31)) { + if (time_after(jiffies, timeout)) + break; + + udelay(50); } - writel(addr | pte_flags, intel_private.gtt + entry); + intel_i830_cc_after_flush(); } -static void intel_enable_gtt(void) +static bool intel_enable_gtt(void) { u32 gma_addr; - u16 gmch_ctrl; + u8 __iomem *reg; - if (INTEL_GTT_GEN == 2) + if (INTEL_GTT_GEN <= 2) pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &gma_addr); else @@ -889,13 +945,47 @@ intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); - pci_read_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, &gmch_ctrl); - gmch_ctrl |= I830_GMCH_ENABLED; - pci_write_config_word(intel_private.bridge_dev, I830_GMCH_CTRL, gmch_ctrl); + if (INTEL_GTT_GEN >= 6) + return true; - writel(intel_private.pte_bus_addr|I810_PGETBL_ENABLED, - intel_private.registers+I810_PGETBL_CTL); - readl(intel_private.registers+I810_PGETBL_CTL); /* PCI Posting. */ + if (INTEL_GTT_GEN == 2) { + u16 gmch_ctrl; + + pci_read_config_word(intel_private.bridge_dev, + I830_GMCH_CTRL, &gmch_ctrl); + gmch_ctrl |= I830_GMCH_ENABLED; + pci_write_config_word(intel_private.bridge_dev, + I830_GMCH_CTRL, gmch_ctrl); + + pci_read_config_word(intel_private.bridge_dev, + I830_GMCH_CTRL, &gmch_ctrl); + if ((gmch_ctrl & I830_GMCH_ENABLED) == 0) { + dev_err(&intel_private.pcidev->dev, + "failed to enable the GTT: GMCH_CTRL=%x\n", + gmch_ctrl); + return false; + } + } + + /* On the resume path we may be adjusting the PGTBL value, so + * be paranoid and flush all chipset write buffers... + */ + if (INTEL_GTT_GEN >= 3) + writel(0, intel_private.registers+GFX_FLSH_CNTL); + + reg = intel_private.registers+I810_PGETBL_CTL; + writel(intel_private.PGETBL_save, reg); + if (HAS_PGTBL_EN && (readl(reg) & I810_PGETBL_ENABLED) == 0) { + dev_err(&intel_private.pcidev->dev, + "failed to enable the GTT: PGETBL=%x [expected %x]\n", + readl(reg), intel_private.PGETBL_save); + return false; + } + + if (INTEL_GTT_GEN >= 3) + writel(0, intel_private.registers+GFX_FLSH_CNTL); + + return true; } static int i830_setup(void) @@ -910,8 +1000,6 @@ return -ENOMEM; intel_private.gtt_bus_addr = reg_addr + I810_PTE_BASE; - intel_private.pte_bus_addr = - readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; intel_i830_setup_flush(); @@ -936,12 +1024,15 @@ { int i; - intel_enable_gtt(); + if (!intel_enable_gtt()) + return -EIO; + + if (INTEL_GTT_GEN == 2) + intel_i830_cc_setup(); agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; - for (i = intel_private.base.gtt_stolen_entries; - i < intel_private.base.gtt_total_entries; i++) { + for (i = 0; i < intel_private.base.gtt_total_entries; i++) { intel_private.driver->write_entry(intel_private.scratch_page_dma, i, 0); } @@ -965,10 +1056,10 @@ return false; } -static void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, - unsigned int sg_len, - unsigned int pg_start, - unsigned int flags) +void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, + unsigned int sg_len, + unsigned int pg_start, + unsigned int flags) { struct scatterlist *sg; unsigned int len, m; @@ -989,27 +1080,34 @@ } readl(intel_private.gtt+j-1); } +EXPORT_SYMBOL(intel_gtt_insert_sg_entries); + +void intel_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries, + struct page **pages, unsigned int flags) +{ + int i, j; + + for (i = 0, j = first_entry; i < num_entries; i++, j++) { + dma_addr_t addr = page_to_phys(pages[i]); + intel_private.driver->write_entry(addr, + j, flags); + } + readl(intel_private.gtt+j-1); +} +EXPORT_SYMBOL(intel_gtt_insert_pages); static int intel_fake_agp_insert_entries(struct agp_memory *mem, off_t pg_start, int type) { - int i, j; int ret = -EINVAL; + if (INTEL_GTT_GEN == 1 && type == AGP_DCACHE_MEMORY) + return i810_insert_dcache_entries(mem, pg_start, type); + if (mem->page_count == 0) goto out; - if (pg_start < intel_private.base.gtt_stolen_entries) { - dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, - "pg_start == 0x%.8lx, gtt_stolen_entries == 0x%.8x\n", - pg_start, intel_private.base.gtt_stolen_entries); - - dev_info(&intel_private.pcidev->dev, - "trying to insert into local/stolen memory\n"); - goto out_err; - } - - if ((pg_start + mem->page_count) > intel_private.base.gtt_total_entries) + if (pg_start + mem->page_count > intel_private.base.gtt_total_entries) goto out_err; if (type != mem->type) @@ -1021,21 +1119,17 @@ if (!mem->is_flushed) global_cache_flush(); - if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) { - ret = intel_agp_map_memory(mem); + if (intel_private.base.needs_dmar) { + ret = intel_gtt_map_memory(mem->pages, mem->page_count, + &mem->sg_list, &mem->num_sg); if (ret != 0) return ret; intel_gtt_insert_sg_entries(mem->sg_list, mem->num_sg, pg_start, type); - } else { - for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - dma_addr_t addr = page_to_phys(mem->pages[i]); - intel_private.driver->write_entry(addr, - j, type); - } - readl(intel_private.gtt+j-1); - } + } else + intel_gtt_insert_pages(pg_start, mem->page_count, mem->pages, + type); out: ret = 0; @@ -1044,40 +1138,54 @@ return ret; } +void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries) +{ + unsigned int i; + + for (i = first_entry; i < (first_entry + num_entries); i++) { + intel_private.driver->write_entry(intel_private.scratch_page_dma, + i, 0); + } + readl(intel_private.gtt+i-1); +} +EXPORT_SYMBOL(intel_gtt_clear_range); + static int intel_fake_agp_remove_entries(struct agp_memory *mem, off_t pg_start, int type) { - int i; - if (mem->page_count == 0) return 0; - if (pg_start < intel_private.base.gtt_stolen_entries) { - dev_info(&intel_private.pcidev->dev, - "trying to disable local/stolen memory\n"); - return -EINVAL; + if (intel_private.base.needs_dmar) { + intel_gtt_unmap_memory(mem->sg_list, mem->num_sg); + mem->sg_list = NULL; + mem->num_sg = 0; } - if (USE_PCI_DMA_API && INTEL_GTT_GEN > 2) - intel_agp_unmap_memory(mem); - - for (i = pg_start; i < (mem->page_count + pg_start); i++) { - intel_private.driver->write_entry(intel_private.scratch_page_dma, - i, 0); - } - readl(intel_private.gtt+i-1); + intel_gtt_clear_range(pg_start, mem->page_count); return 0; } -static void intel_fake_agp_chipset_flush(struct agp_bridge_data *bridge) -{ - intel_private.driver->chipset_flush(); -} - static struct agp_memory *intel_fake_agp_alloc_by_type(size_t pg_count, int type) { + struct agp_memory *new; + + if (type == AGP_DCACHE_MEMORY && INTEL_GTT_GEN == 1) { + if (pg_count != intel_private.num_dcache_entries) + return NULL; + + new = agp_create_memory(1); + if (new == NULL) + return NULL; + + new->type = AGP_DCACHE_MEMORY; + new->page_count = pg_count; + new->num_scratch_pages = 0; + agp_free_page_array(new); + return new; + } if (type == AGP_PHYS_MEMORY) return alloc_agpphysmem_i8xx(pg_count, type); /* always return NULL for other allocation types for now */ @@ -1274,40 +1382,11 @@ intel_private.gtt_bus_addr = reg_addr + gtt_offset; } - intel_private.pte_bus_addr = - readl(intel_private.registers+I810_PGETBL_CTL) & 0xfffff000; - intel_i9xx_setup_flush(); return 0; } -static const struct agp_bridge_driver intel_810_driver = { - .owner = THIS_MODULE, - .aperture_sizes = intel_i810_sizes, - .size_type = FIXED_APER_SIZE, - .num_aperture_sizes = 2, - .needs_scratch_page = true, - .configure = intel_i810_configure, - .fetch_size = intel_i810_fetch_size, - .cleanup = intel_i810_cleanup, - .mask_memory = intel_i810_mask_memory, - .masks = intel_i810_masks, - .agp_enable = intel_fake_agp_enable, - .cache_flush = global_cache_flush, - .create_gatt_table = agp_generic_create_gatt_table, - .free_gatt_table = agp_generic_free_gatt_table, - .insert_memory = intel_i810_insert_entries, - .remove_memory = intel_i810_remove_entries, - .alloc_by_type = intel_i810_alloc_by_type, - .free_by_type = intel_i810_free_by_type, - .agp_alloc_page = agp_generic_alloc_page, - .agp_alloc_pages = agp_generic_alloc_pages, - .agp_destroy_page = agp_generic_destroy_page, - .agp_destroy_pages = agp_generic_destroy_pages, - .agp_type_to_mask_type = agp_generic_type_to_mask_type, -}; - static const struct agp_bridge_driver intel_fake_agp_driver = { .owner = THIS_MODULE, .size_type = FIXED_APER_SIZE, @@ -1328,15 +1407,20 @@ .agp_alloc_pages = agp_generic_alloc_pages, .agp_destroy_page = agp_generic_destroy_page, .agp_destroy_pages = agp_generic_destroy_pages, - .chipset_flush = intel_fake_agp_chipset_flush, }; static const struct intel_gtt_driver i81x_gtt_driver = { .gen = 1, + .has_pgtbl_enable = 1, .dma_mask_size = 32, + .setup = i810_setup, + .cleanup = i810_cleanup, + .check_flags = i830_check_flags, + .write_entry = i810_write_entry, }; static const struct intel_gtt_driver i8xx_gtt_driver = { .gen = 2, + .has_pgtbl_enable = 1, .setup = i830_setup, .cleanup = i830_cleanup, .write_entry = i830_write_entry, @@ -1346,10 +1430,11 @@ }; static const struct intel_gtt_driver i915_gtt_driver = { .gen = 3, + .has_pgtbl_enable = 1, .setup = i9xx_setup, .cleanup = i9xx_cleanup, /* i945 is the last gpu to need phys mem (for overlay and cursors). */ - .write_entry = i830_write_entry, + .write_entry = i830_write_entry, .dma_mask_size = 32, .check_flags = i830_check_flags, .chipset_flush = i9xx_chipset_flush, @@ -1376,6 +1461,7 @@ }; static const struct intel_gtt_driver i965_gtt_driver = { .gen = 4, + .has_pgtbl_enable = 1, .setup = i9xx_setup, .cleanup = i9xx_cleanup, .write_entry = i965_write_entry, @@ -1419,93 +1505,92 @@ static const struct intel_gtt_driver_description { unsigned int gmch_chip_id; char *name; - const struct agp_bridge_driver *gmch_driver; const struct intel_gtt_driver *gtt_driver; } intel_gtt_chipsets[] = { - { PCI_DEVICE_ID_INTEL_82810_IG1, "i810", &intel_810_driver, + { PCI_DEVICE_ID_INTEL_82810_IG1, "i810", &i81x_gtt_driver}, - { PCI_DEVICE_ID_INTEL_82810_IG3, "i810", &intel_810_driver, + { PCI_DEVICE_ID_INTEL_82810_IG3, "i810", &i81x_gtt_driver}, - { PCI_DEVICE_ID_INTEL_82810E_IG, "i810", &intel_810_driver, + { PCI_DEVICE_ID_INTEL_82810E_IG, "i810", &i81x_gtt_driver}, - { PCI_DEVICE_ID_INTEL_82815_CGC, "i815", &intel_810_driver, + { PCI_DEVICE_ID_INTEL_82815_CGC, "i815", &i81x_gtt_driver}, { PCI_DEVICE_ID_INTEL_82830_CGC, "830M", - &intel_fake_agp_driver, &i8xx_gtt_driver}, + &i8xx_gtt_driver}, { PCI_DEVICE_ID_INTEL_82845G_IG, "830M", - &intel_fake_agp_driver, &i8xx_gtt_driver}, + &i8xx_gtt_driver}, { PCI_DEVICE_ID_INTEL_82854_IG, "854", - &intel_fake_agp_driver, &i8xx_gtt_driver}, + &i8xx_gtt_driver}, { PCI_DEVICE_ID_INTEL_82855GM_IG, "855GM", - &intel_fake_agp_driver, &i8xx_gtt_driver}, + &i8xx_gtt_driver}, { PCI_DEVICE_ID_INTEL_82865_IG, "865", - &intel_fake_agp_driver, &i8xx_gtt_driver}, + &i8xx_gtt_driver}, { PCI_DEVICE_ID_INTEL_E7221_IG, "E7221 (i915)", - &intel_fake_agp_driver, &i915_gtt_driver }, + &i915_gtt_driver }, { PCI_DEVICE_ID_INTEL_82915G_IG, "915G", - &intel_fake_agp_driver, &i915_gtt_driver }, + &i915_gtt_driver }, { PCI_DEVICE_ID_INTEL_82915GM_IG, "915GM", - &intel_fake_agp_driver, &i915_gtt_driver }, + &i915_gtt_driver }, { PCI_DEVICE_ID_INTEL_82945G_IG, "945G", - &intel_fake_agp_driver, &i915_gtt_driver }, + &i915_gtt_driver }, { PCI_DEVICE_ID_INTEL_82945GM_IG, "945GM", - &intel_fake_agp_driver, &i915_gtt_driver }, + &i915_gtt_driver }, { PCI_DEVICE_ID_INTEL_82945GME_IG, "945GME", - &intel_fake_agp_driver, &i915_gtt_driver }, + &i915_gtt_driver }, { PCI_DEVICE_ID_INTEL_82946GZ_IG, "946GZ", - &intel_fake_agp_driver, &i965_gtt_driver }, + &i965_gtt_driver }, { PCI_DEVICE_ID_INTEL_82G35_IG, "G35", - &intel_fake_agp_driver, &i965_gtt_driver }, + &i965_gtt_driver }, { PCI_DEVICE_ID_INTEL_82965Q_IG, "965Q", - &intel_fake_agp_driver, &i965_gtt_driver }, + &i965_gtt_driver }, { PCI_DEVICE_ID_INTEL_82965G_IG, "965G", - &intel_fake_agp_driver, &i965_gtt_driver }, + &i965_gtt_driver }, { PCI_DEVICE_ID_INTEL_82965GM_IG, "965GM", - &intel_fake_agp_driver, &i965_gtt_driver }, + &i965_gtt_driver }, { PCI_DEVICE_ID_INTEL_82965GME_IG, "965GME/GLE", - &intel_fake_agp_driver, &i965_gtt_driver }, + &i965_gtt_driver }, { PCI_DEVICE_ID_INTEL_G33_IG, "G33", - &intel_fake_agp_driver, &g33_gtt_driver }, + &g33_gtt_driver }, { PCI_DEVICE_ID_INTEL_Q35_IG, "Q35", - &intel_fake_agp_driver, &g33_gtt_driver }, + &g33_gtt_driver }, { PCI_DEVICE_ID_INTEL_Q33_IG, "Q33", - &intel_fake_agp_driver, &g33_gtt_driver }, + &g33_gtt_driver }, { PCI_DEVICE_ID_INTEL_PINEVIEW_M_IG, "GMA3150", - &intel_fake_agp_driver, &pineview_gtt_driver }, + &pineview_gtt_driver }, { PCI_DEVICE_ID_INTEL_PINEVIEW_IG, "GMA3150", - &intel_fake_agp_driver, &pineview_gtt_driver }, + &pineview_gtt_driver }, { PCI_DEVICE_ID_INTEL_GM45_IG, "GM45", - &intel_fake_agp_driver, &g4x_gtt_driver }, + &g4x_gtt_driver }, { PCI_DEVICE_ID_INTEL_EAGLELAKE_IG, "Eaglelake", - &intel_fake_agp_driver, &g4x_gtt_driver }, + &g4x_gtt_driver }, { PCI_DEVICE_ID_INTEL_Q45_IG, "Q45/Q43", - &intel_fake_agp_driver, &g4x_gtt_driver }, + &g4x_gtt_driver }, { PCI_DEVICE_ID_INTEL_G45_IG, "G45/G43", - &intel_fake_agp_driver, &g4x_gtt_driver }, + &g4x_gtt_driver }, { PCI_DEVICE_ID_INTEL_B43_IG, "B43", - &intel_fake_agp_driver, &g4x_gtt_driver }, + &g4x_gtt_driver }, { PCI_DEVICE_ID_INTEL_B43_1_IG, "B43", - &intel_fake_agp_driver, &g4x_gtt_driver }, + &g4x_gtt_driver }, { PCI_DEVICE_ID_INTEL_G41_IG, "G41", - &intel_fake_agp_driver, &g4x_gtt_driver }, + &g4x_gtt_driver }, { PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG, - "HD Graphics", &intel_fake_agp_driver, &ironlake_gtt_driver }, + "HD Graphics", &ironlake_gtt_driver }, { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, - "HD Graphics", &intel_fake_agp_driver, &ironlake_gtt_driver }, + "HD Graphics", &ironlake_gtt_driver }, { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, - "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, + "Sandybridge", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, - "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, + "Sandybridge", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, - "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, + "Sandybridge", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, - "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, + "Sandybridge", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, - "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, + "Sandybridge", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, - "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, + "Sandybridge", &sandybridge_gtt_driver }, { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, - "Sandybridge", &intel_fake_agp_driver, &sandybridge_gtt_driver }, + "Sandybridge", &sandybridge_gtt_driver }, { 0, NULL, NULL } }; @@ -1530,21 +1615,20 @@ struct agp_bridge_data *bridge) { int i, mask; - bridge->driver = NULL; + intel_private.driver = NULL; for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { - bridge->driver = - intel_gtt_chipsets[i].gmch_driver; - intel_private.driver = + intel_private.driver = intel_gtt_chipsets[i].gtt_driver; break; } } - if (!bridge->driver) + if (!intel_private.driver) return 0; + bridge->driver = &intel_fake_agp_driver; bridge->dev_private_data = &intel_private; bridge->dev = pdev; @@ -1560,8 +1644,8 @@ pci_set_consistent_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)); - if (bridge->driver == &intel_810_driver) - return 1; + /*if (bridge->driver == &intel_810_driver) + return 1;*/ if (intel_gtt_init() != 0) return 0; @@ -1570,12 +1654,19 @@ } EXPORT_SYMBOL(intel_gmch_probe); -struct intel_gtt *intel_gtt_get(void) +const struct intel_gtt *intel_gtt_get(void) { return &intel_private.base; } EXPORT_SYMBOL(intel_gtt_get); +void intel_gtt_chipset_flush(void) +{ + if (intel_private.driver->chipset_flush) + intel_private.driver->chipset_flush(); +} +EXPORT_SYMBOL(intel_gtt_chipset_flush); + void intel_gmch_remove(struct pci_dev *pdev) { if (intel_private.pcidev) --- linux-2.6.37.orig/drivers/gpu/drm/drm_fops.c +++ linux-2.6.37/drivers/gpu/drm/drm_fops.c @@ -128,7 +128,8 @@ minor = idr_find(&drm_minors_idr, minor_id); if (!minor) return -ENODEV; - + if (IS_ERR(minor)) + return PTR_ERR(minor); if (!(dev = minor->dev)) return -ENODEV; @@ -176,7 +177,10 @@ minor = idr_find(&drm_minors_idr, minor_id); if (!minor) goto out; - + if (IS_ERR(minor)) { + err = PTR_ERR(minor); + goto out; + } if (!(dev = minor->dev)) goto out; --- linux-2.6.37.orig/drivers/gpu/drm/drm_pci.c +++ linux-2.6.37/drivers/gpu/drm/drm_pci.c @@ -197,6 +197,10 @@ list_add_tail(&dev->driver_item, &driver->device_list); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + idr_replace(&drm_minors_idr, dev->control, dev->control->index); + idr_replace(&drm_minors_idr, dev->primary, dev->primary->index); + DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", driver->name, driver->major, driver->minor, driver->patchlevel, driver->date, pci_name(pdev), dev->primary->index); --- linux-2.6.37.orig/drivers/gpu/drm/drm_platform.c +++ linux-2.6.37/drivers/gpu/drm/drm_platform.c @@ -89,6 +89,10 @@ list_add_tail(&dev->driver_item, &driver->device_list); + if (drm_core_check_feature(dev, DRIVER_MODESET)) + idr_replace(&drm_minors_idr, dev->control, dev->control->index); + idr_replace(&drm_minors_idr, dev->primary, dev->primary->index); + mutex_unlock(&drm_global_mutex); DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", --- linux-2.6.37.orig/drivers/gpu/drm/drm_agpsupport.c +++ linux-2.6.37/drivers/gpu/drm/drm_agpsupport.c @@ -466,10 +466,4 @@ } EXPORT_SYMBOL(drm_agp_bind_pages); -void drm_agp_chipset_flush(struct drm_device *dev) -{ - agp_flush_chipset(dev->agp->bridge); -} -EXPORT_SYMBOL(drm_agp_chipset_flush); - #endif /* __OS_HAS_AGP */ --- linux-2.6.37.orig/drivers/gpu/drm/drm_crtc_helper.c +++ linux-2.6.37/drivers/gpu/drm/drm_crtc_helper.c @@ -336,7 +336,7 @@ struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; - struct drm_display_mode *adjusted_mode, saved_mode; + struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; struct drm_encoder_helper_funcs *encoder_funcs; int saved_x, saved_y; @@ -350,6 +350,7 @@ if (!crtc->enabled) return true; + saved_hwmode = crtc->hwmode; saved_mode = crtc->mode; saved_x = crtc->x; saved_y = crtc->y; @@ -427,11 +428,21 @@ } + /* Store real post-adjustment hardware mode. */ + crtc->hwmode = *adjusted_mode; + + /* Calculate and store various constants which + * are later needed by vblank and swap-completion + * timestamping. They are derived from true hwmode. + */ + drm_calc_timestamping_constants(crtc); + /* XXX free adjustedmode */ drm_mode_destroy(dev, adjusted_mode); /* FIXME: add subpixel order */ done: if (!ret) { + crtc->hwmode = saved_hwmode; crtc->mode = saved_mode; crtc->x = saved_x; crtc->y = saved_y; --- linux-2.6.37.orig/drivers/gpu/drm/drm_irq.c +++ linux-2.6.37/drivers/gpu/drm/drm_irq.c @@ -40,6 +40,22 @@ #include #include + +/* Access macro for slots in vblank timestamp ringbuffer. */ +#define vblanktimestamp(dev, crtc, count) ( \ + (dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \ + ((count) % DRM_VBLANKTIME_RBSIZE)]) + +/* Retry timestamp calculation up to 3 times to satisfy + * drm_timestamp_precision before giving up. + */ +#define DRM_TIMESTAMP_MAXRETRIES 3 + +/* Threshold in nanoseconds for detection of redundant + * vblank irq in drm_handle_vblank(). 1 msec should be ok. + */ +#define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 + /** * Get interrupt from bus id. * @@ -77,6 +93,87 @@ return 0; } +/* + * Clear vblank timestamp buffer for a crtc. + */ +static void clear_vblank_timestamps(struct drm_device *dev, int crtc) +{ + memset(&dev->_vblank_time[crtc * DRM_VBLANKTIME_RBSIZE], 0, + DRM_VBLANKTIME_RBSIZE * sizeof(struct timeval)); +} + +/* + * Disable vblank irq's on crtc, make sure that last vblank count + * of hardware and corresponding consistent software vblank counter + * are preserved, even if there are any spurious vblank irq's after + * disable. + */ +static void vblank_disable_and_save(struct drm_device *dev, int crtc) +{ + unsigned long irqflags; + u32 vblcount; + s64 diff_ns; + int vblrc; + struct timeval tvblank; + + /* Prevent vblank irq processing while disabling vblank irqs, + * so no updates of timestamps or count can happen after we've + * disabled. Needed to prevent races in case of delayed irq's. + * Disable preemption, so vblank_time_lock is held as short as + * possible, even under a kernel with PREEMPT_RT patches. + */ + preempt_disable(); + spin_lock_irqsave(&dev->vblank_time_lock, irqflags); + + dev->driver->disable_vblank(dev, crtc); + dev->vblank_enabled[crtc] = 0; + + /* No further vblank irq's will be processed after + * this point. Get current hardware vblank count and + * vblank timestamp, repeat until they are consistent. + * + * FIXME: There is still a race condition here and in + * drm_update_vblank_count() which can cause off-by-one + * reinitialization of software vblank counter. If gpu + * vblank counter doesn't increment exactly at the leading + * edge of a vblank interval, then we can lose 1 count if + * we happen to execute between start of vblank and the + * delayed gpu counter increment. + */ + do { + dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); + vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); + } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc)); + + /* Compute time difference to stored timestamp of last vblank + * as updated by last invocation of drm_handle_vblank() in vblank irq. + */ + vblcount = atomic_read(&dev->_vblank_count[crtc]); + diff_ns = timeval_to_ns(&tvblank) - + timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); + + /* If there is at least 1 msec difference between the last stored + * timestamp and tvblank, then we are currently executing our + * disable inside a new vblank interval, the tvblank timestamp + * corresponds to this new vblank interval and the irq handler + * for this vblank didn't run yet and won't run due to our disable. + * Therefore we need to do the job of drm_handle_vblank() and + * increment the vblank counter by one to account for this vblank. + * + * Skip this step if there isn't any high precision timestamp + * available. In that case we can't account for this and just + * hope for the best. + */ + if ((vblrc > 0) && (abs(diff_ns) > 1000000)) + atomic_inc(&dev->_vblank_count[crtc]); + + /* Invalidate all timestamps while vblank irq's are off. */ + clear_vblank_timestamps(dev, crtc); + + spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); + preempt_enable(); +} + static void vblank_disable_fn(unsigned long arg) { struct drm_device *dev = (struct drm_device *)arg; @@ -91,10 +188,7 @@ if (atomic_read(&dev->vblank_refcount[i]) == 0 && dev->vblank_enabled[i]) { DRM_DEBUG("disabling vblank on crtc %d\n", i); - dev->last_vblank[i] = - dev->driver->get_vblank_counter(dev, i); - dev->driver->disable_vblank(dev, i); - dev->vblank_enabled[i] = 0; + vblank_disable_and_save(dev, i); } spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } @@ -117,6 +211,7 @@ kfree(dev->last_vblank); kfree(dev->last_vblank_wait); kfree(dev->vblank_inmodeset); + kfree(dev->_vblank_time); dev->num_crtcs = 0; } @@ -129,6 +224,8 @@ setup_timer(&dev->vblank_disable_timer, vblank_disable_fn, (unsigned long)dev); spin_lock_init(&dev->vbl_lock); + spin_lock_init(&dev->vblank_time_lock); + dev->num_crtcs = num_crtcs; dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs, @@ -161,6 +258,19 @@ if (!dev->vblank_inmodeset) goto err; + dev->_vblank_time = kcalloc(num_crtcs * DRM_VBLANKTIME_RBSIZE, + sizeof(struct timeval), GFP_KERNEL); + if (!dev->_vblank_time) + goto err; + + DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n"); + + /* Driver specific high-precision vblank timestamping supported? */ + if (dev->driver->get_vblank_timestamp) + DRM_INFO("Driver supports precise vblank timestamp query.\n"); + else + DRM_INFO("No driver support for vblank timestamp query.\n"); + /* Zero per-crtc vblank stuff */ for (i = 0; i < num_crtcs; i++) { init_waitqueue_head(&dev->vbl_queue[i]); @@ -279,7 +389,7 @@ * * Calls the driver's \c drm_driver_irq_uninstall() function, and stops the irq. */ -int drm_irq_uninstall(struct drm_device * dev) +int drm_irq_uninstall(struct drm_device *dev) { unsigned long irqflags; int irq_enabled, i; @@ -335,7 +445,9 @@ { struct drm_control *ctl = data; - /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */ + /* if we haven't irq we fallback for compatibility reasons - + * this used to be a separate function in drm_dma.h + */ switch (ctl->func) { @@ -360,6 +472,287 @@ } /** + * drm_calc_timestamping_constants - Calculate and + * store various constants which are later needed by + * vblank and swap-completion timestamping, e.g, by + * drm_calc_vbltimestamp_from_scanoutpos(). + * They are derived from crtc's true scanout timing, + * so they take things like panel scaling or other + * adjustments into account. + * + * @crtc drm_crtc whose timestamp constants should be updated. + * + */ +void drm_calc_timestamping_constants(struct drm_crtc *crtc) +{ + s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; + u64 dotclock; + + /* Dot clock in Hz: */ + dotclock = (u64) crtc->hwmode.clock * 1000; + + /* Valid dotclock? */ + if (dotclock > 0) { + /* Convert scanline length in pixels and video dot clock to + * line duration, frame duration and pixel duration in + * nanoseconds: + */ + pixeldur_ns = (s64) div64_u64(1000000000, dotclock); + linedur_ns = (s64) div64_u64(((u64) crtc->hwmode.crtc_htotal * + 1000000000), dotclock); + framedur_ns = (s64) crtc->hwmode.crtc_vtotal * linedur_ns; + } else + DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n", + crtc->base.id); + + crtc->pixeldur_ns = pixeldur_ns; + crtc->linedur_ns = linedur_ns; + crtc->framedur_ns = framedur_ns; + + DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n", + crtc->base.id, crtc->hwmode.crtc_htotal, + crtc->hwmode.crtc_vtotal, crtc->hwmode.crtc_vdisplay); + DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n", + crtc->base.id, (int) dotclock/1000, (int) framedur_ns, + (int) linedur_ns, (int) pixeldur_ns); +} +EXPORT_SYMBOL(drm_calc_timestamping_constants); + +/** + * drm_calc_vbltimestamp_from_scanoutpos - helper routine for kms + * drivers. Implements calculation of exact vblank timestamps from + * given drm_display_mode timings and current video scanout position + * of a crtc. This can be called from within get_vblank_timestamp() + * implementation of a kms driver to implement the actual timestamping. + * + * Should return timestamps conforming to the OML_sync_control OpenML + * extension specification. The timestamp corresponds to the end of + * the vblank interval, aka start of scanout of topmost-leftmost display + * pixel in the following video frame. + * + * Requires support for optional dev->driver->get_scanout_position() + * in kms driver, plus a bit of setup code to provide a drm_display_mode + * that corresponds to the true scanout timing. + * + * The current implementation only handles standard video modes. It + * returns as no operation if a doublescan or interlaced video mode is + * active. Higher level code is expected to handle this. + * + * @dev: DRM device. + * @crtc: Which crtc's vblank timestamp to retrieve. + * @max_error: Desired maximum allowable error in timestamps (nanosecs). + * On return contains true maximum error of timestamp. + * @vblank_time: Pointer to struct timeval which should receive the timestamp. + * @flags: Flags to pass to driver: + * 0 = Default. + * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. + * @refcrtc: drm_crtc* of crtc which defines scanout timing. + * + * Returns negative value on error, failure or if not supported in current + * video mode: + * + * -EINVAL - Invalid crtc. + * -EAGAIN - Temporary unavailable, e.g., called before initial modeset. + * -ENOTSUPP - Function not supported in current display mode. + * -EIO - Failed, e.g., due to failed scanout position query. + * + * Returns or'ed positive status flags on success: + * + * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping. + * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval. + * + */ +int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags, + struct drm_crtc *refcrtc) +{ + struct timeval stime, raw_time; + struct drm_display_mode *mode; + int vbl_status, vtotal, vdisplay; + int vpos, hpos, i; + s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; + bool invbl; + + if (crtc < 0 || crtc >= dev->num_crtcs) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return -EINVAL; + } + + /* Scanout position query not supported? Should not happen. */ + if (!dev->driver->get_scanout_position) { + DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); + return -EIO; + } + + mode = &refcrtc->hwmode; + vtotal = mode->crtc_vtotal; + vdisplay = mode->crtc_vdisplay; + + /* Durations of frames, lines, pixels in nanoseconds. */ + framedur_ns = refcrtc->framedur_ns; + linedur_ns = refcrtc->linedur_ns; + pixeldur_ns = refcrtc->pixeldur_ns; + + /* If mode timing undefined, just return as no-op: + * Happens during initial modesetting of a crtc. + */ + if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) { + DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc); + return -EAGAIN; + } + + /* Don't know yet how to handle interlaced or + * double scan modes. Just no-op for now. + */ + if (mode->flags & (DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_DBLSCAN)) { + DRM_DEBUG("crtc %d: Noop due to unsupported mode.\n", crtc); + return -ENOTSUPP; + } + + /* Get current scanout position with system timestamp. + * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times + * if single query takes longer than max_error nanoseconds. + * + * This guarantees a tight bound on maximum error if + * code gets preempted or delayed for some reason. + */ + for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) { + /* Disable preemption to make it very likely to + * succeed in the first iteration even on PREEMPT_RT kernel. + */ + preempt_disable(); + + /* Get system timestamp before query. */ + do_gettimeofday(&stime); + + /* Get vertical and horizontal scanout pos. vpos, hpos. */ + vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, &hpos); + + /* Get system timestamp after query. */ + do_gettimeofday(&raw_time); + + preempt_enable(); + + /* Return as no-op if scanout query unsupported or failed. */ + if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { + DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n", + crtc, vbl_status); + return -EIO; + } + + duration_ns = timeval_to_ns(&raw_time) - timeval_to_ns(&stime); + + /* Accept result with < max_error nsecs timing uncertainty. */ + if (duration_ns <= (s64) *max_error) + break; + } + + /* Noisy system timing? */ + if (i == DRM_TIMESTAMP_MAXRETRIES) { + DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n", + crtc, (int) duration_ns/1000, *max_error/1000, i); + } + + /* Return upper bound of timestamp precision error. */ + *max_error = (int) duration_ns; + + /* Check if in vblank area: + * vpos is >=0 in video scanout area, but negative + * within vblank area, counting down the number of lines until + * start of scanout. + */ + invbl = vbl_status & DRM_SCANOUTPOS_INVBL; + + /* Convert scanout position into elapsed time at raw_time query + * since start of scanout at first display scanline. delta_ns + * can be negative if start of scanout hasn't happened yet. + */ + delta_ns = (s64) vpos * linedur_ns + (s64) hpos * pixeldur_ns; + + /* Is vpos outside nominal vblank area, but less than + * 1/100 of a frame height away from start of vblank? + * If so, assume this isn't a massively delayed vblank + * interrupt, but a vblank interrupt that fired a few + * microseconds before true start of vblank. Compensate + * by adding a full frame duration to the final timestamp. + * Happens, e.g., on ATI R500, R600. + * + * We only do this if DRM_CALLED_FROM_VBLIRQ. + */ + if ((flags & DRM_CALLED_FROM_VBLIRQ) && !invbl && + ((vdisplay - vpos) < vtotal / 100)) { + delta_ns = delta_ns - framedur_ns; + + /* Signal this correction as "applied". */ + vbl_status |= 0x8; + } + + /* Subtract time delta from raw timestamp to get final + * vblank_time timestamp for end of vblank. + */ + *vblank_time = ns_to_timeval(timeval_to_ns(&raw_time) - delta_ns); + + DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %d.%d -> %d.%d [e %d us, %d rep]\n", + crtc, (int) vbl_status, hpos, vpos, raw_time.tv_sec, + raw_time.tv_usec, vblank_time->tv_sec, vblank_time->tv_usec, + (int) duration_ns/1000, i); + + vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD; + if (invbl) + vbl_status |= DRM_VBLANKTIME_INVBL; + + return vbl_status; +} +EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); + +/** + * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent + * vblank interval. + * + * @dev: DRM device + * @crtc: which crtc's vblank timestamp to retrieve + * @tvblank: Pointer to target struct timeval which should receive the timestamp + * @flags: Flags to pass to driver: + * 0 = Default. + * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. + * + * Fetches the system timestamp corresponding to the time of the most recent + * vblank interval on specified crtc. May call into kms-driver to + * compute the timestamp with a high-precision GPU specific method. + * + * Returns zero if timestamp originates from uncorrected do_gettimeofday() + * call, i.e., it isn't very precisely locked to the true vblank. + * + * Returns non-zero if timestamp is considered to be very precise. + */ +u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, + struct timeval *tvblank, unsigned flags) +{ + int ret = 0; + + /* Define requested maximum error on timestamps (nanoseconds). */ + int max_error = (int) drm_timestamp_precision * 1000; + + /* Query driver if possible and precision timestamping enabled. */ + if (dev->driver->get_vblank_timestamp && (max_error > 0)) { + ret = dev->driver->get_vblank_timestamp(dev, crtc, &max_error, + tvblank, flags); + if (ret > 0) + return (u32) ret; + } + + /* GPU high precision timestamp query unsupported or failed. + * Return gettimeofday timestamp as best estimate. + */ + do_gettimeofday(tvblank); + + return 0; +} +EXPORT_SYMBOL(drm_get_last_vbltimestamp); + +/** * drm_vblank_count - retrieve "cooked" vblank counter value * @dev: DRM device * @crtc: which counter to retrieve @@ -375,6 +768,40 @@ EXPORT_SYMBOL(drm_vblank_count); /** + * drm_vblank_count_and_time - retrieve "cooked" vblank counter value + * and the system timestamp corresponding to that vblank counter value. + * + * @dev: DRM device + * @crtc: which counter to retrieve + * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. + * + * Fetches the "cooked" vblank count value that represents the number of + * vblank events since the system was booted, including lost events due to + * modesetting activity. Returns corresponding system timestamp of the time + * of the vblank interval that corresponds to the current value vblank counter + * value. + */ +u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, + struct timeval *vblanktime) +{ + u32 cur_vblank; + + /* Read timestamp from slot of _vblank_time ringbuffer + * that corresponds to current vblank count. Retry if + * count has incremented during readout. This works like + * a seqlock. + */ + do { + cur_vblank = atomic_read(&dev->_vblank_count[crtc]); + *vblanktime = vblanktimestamp(dev, crtc, cur_vblank); + smp_rmb(); + } while (cur_vblank != atomic_read(&dev->_vblank_count[crtc])); + + return cur_vblank; +} +EXPORT_SYMBOL(drm_vblank_count_and_time); + +/** * drm_update_vblank_count - update the master vblank counter * @dev: DRM device * @crtc: counter to update @@ -392,7 +819,8 @@ */ static void drm_update_vblank_count(struct drm_device *dev, int crtc) { - u32 cur_vblank, diff; + u32 cur_vblank, diff, tslot, rc; + struct timeval t_vblank; /* * Interrupts were disabled prior to this call, so deal with counter @@ -400,8 +828,18 @@ * NOTE! It's possible we lost a full dev->max_vblank_count events * here if the register is small or we had vblank interrupts off for * a long time. + * + * We repeat the hardware vblank counter & timestamp query until + * we get consistent results. This to prevent races between gpu + * updating its hardware counter while we are retrieving the + * corresponding vblank timestamp. */ - cur_vblank = dev->driver->get_vblank_counter(dev, crtc); + do { + cur_vblank = dev->driver->get_vblank_counter(dev, crtc); + rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0); + } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc)); + + /* Deal with counter wrap */ diff = cur_vblank - dev->last_vblank[crtc]; if (cur_vblank < dev->last_vblank[crtc]) { diff += dev->max_vblank_count; @@ -413,6 +851,16 @@ DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", crtc, diff); + /* Reinitialize corresponding vblank timestamp if high-precision query + * available. Skip this step if query unsupported or failed. Will + * reinitialize delayed at next vblank interrupt in that case. + */ + if (rc) { + tslot = atomic_read(&dev->_vblank_count[crtc]) + diff; + vblanktimestamp(dev, crtc, tslot) = t_vblank; + smp_wmb(); + } + atomic_add(diff, &dev->_vblank_count[crtc]); } @@ -429,15 +877,27 @@ */ int drm_vblank_get(struct drm_device *dev, int crtc) { - unsigned long irqflags; + unsigned long irqflags, irqflags2; int ret = 0; spin_lock_irqsave(&dev->vbl_lock, irqflags); /* Going from 0->1 means we have to enable interrupts again */ if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { + /* Disable preemption while holding vblank_time_lock. Do + * it explicitely to guard against PREEMPT_RT kernel. + */ + preempt_disable(); + spin_lock_irqsave(&dev->vblank_time_lock, irqflags2); if (!dev->vblank_enabled[crtc]) { + /* Enable vblank irqs under vblank_time_lock protection. + * All vblank count & timestamp updates are held off + * until we are done reinitializing master counter and + * timestamps. Filtercode in drm_handle_vblank() will + * prevent double-accounting of same vblank interval. + */ ret = dev->driver->enable_vblank(dev, crtc); - DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret); + DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", + crtc, ret); if (ret) atomic_dec(&dev->vblank_refcount[crtc]); else { @@ -445,6 +905,8 @@ drm_update_vblank_count(dev, crtc); } } + spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2); + preempt_enable(); } else { if (!dev->vblank_enabled[crtc]) { atomic_dec(&dev->vblank_refcount[crtc]); @@ -463,15 +925,17 @@ * @crtc: which counter to give up * * Release ownership of a given vblank counter, turning off interrupts - * if possible. + * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. */ void drm_vblank_put(struct drm_device *dev, int crtc) { - BUG_ON (atomic_read (&dev->vblank_refcount[crtc]) == 0); + BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0); /* Last user schedules interrupt disable */ - if (atomic_dec_and_test(&dev->vblank_refcount[crtc])) - mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ); + if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) && + (drm_vblank_offdelay > 0)) + mod_timer(&dev->vblank_disable_timer, + jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000)); } EXPORT_SYMBOL(drm_vblank_put); @@ -480,10 +944,8 @@ unsigned long irqflags; spin_lock_irqsave(&dev->vbl_lock, irqflags); - dev->driver->disable_vblank(dev, crtc); + vblank_disable_and_save(dev, crtc); DRM_WAKEUP(&dev->vbl_queue[crtc]); - dev->vblank_enabled[crtc] = 0; - dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } EXPORT_SYMBOL(drm_vblank_off); @@ -602,7 +1064,6 @@ e->base.file_priv = file_priv; e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; - do_gettimeofday(&now); spin_lock_irqsave(&dev->event_lock, flags); if (file_priv->event_space < sizeof e->event) { @@ -611,7 +1072,8 @@ } file_priv->event_space -= sizeof e->event; - seq = drm_vblank_count(dev, pipe); + seq = drm_vblank_count_and_time(dev, pipe, &now); + if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && (seq - vblwait->request.sequence) <= (1 << 23)) { vblwait->request.sequence = seq + 1; @@ -727,11 +1189,10 @@ if (ret != -EINTR) { struct timeval now; - do_gettimeofday(&now); - + vblwait->reply.sequence = drm_vblank_count_and_time(dev, crtc, &now); vblwait->reply.tval_sec = now.tv_sec; vblwait->reply.tval_usec = now.tv_usec; - vblwait->reply.sequence = drm_vblank_count(dev, crtc); + DRM_DEBUG("returning %d to client\n", vblwait->reply.sequence); } else { @@ -750,8 +1211,7 @@ unsigned long flags; unsigned int seq; - do_gettimeofday(&now); - seq = drm_vblank_count(dev, crtc); + seq = drm_vblank_count_and_time(dev, crtc, &now); spin_lock_irqsave(&dev->event_lock, flags); @@ -789,11 +1249,64 @@ */ void drm_handle_vblank(struct drm_device *dev, int crtc) { + u32 vblcount; + s64 diff_ns; + struct timeval tvblank; + unsigned long irqflags; + if (!dev->num_crtcs) return; - atomic_inc(&dev->_vblank_count[crtc]); + /* Need timestamp lock to prevent concurrent execution with + * vblank enable/disable, as this would cause inconsistent + * or corrupted timestamps and vblank counts. + */ + spin_lock_irqsave(&dev->vblank_time_lock, irqflags); + + /* Vblank irq handling disabled. Nothing to do. */ + if (!dev->vblank_enabled[crtc]) { + spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); + return; + } + + /* Fetch corresponding timestamp for this vblank interval from + * driver and store it in proper slot of timestamp ringbuffer. + */ + + /* Get current timestamp and count. */ + vblcount = atomic_read(&dev->_vblank_count[crtc]); + drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); + + /* Compute time difference to timestamp of last vblank */ + diff_ns = timeval_to_ns(&tvblank) - + timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); + + /* Update vblank timestamp and count if at least + * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds + * difference between last stored timestamp and current + * timestamp. A smaller difference means basically + * identical timestamps. Happens if this vblank has + * been already processed and this is a redundant call, + * e.g., due to spurious vblank interrupts. We need to + * ignore those for accounting. + */ + if (abs(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) { + /* Store new timestamp in ringbuffer. */ + vblanktimestamp(dev, crtc, vblcount + 1) = tvblank; + smp_wmb(); + + /* Increment cooked vblank count. This also atomically commits + * the timestamp computed above. + */ + atomic_inc(&dev->_vblank_count[crtc]); + } else { + DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", + crtc, (int) diff_ns); + } + DRM_WAKEUP(&dev->vbl_queue[crtc]); drm_handle_vblank_events(dev, crtc); + + spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); } EXPORT_SYMBOL(drm_handle_vblank); --- linux-2.6.37.orig/drivers/gpu/drm/drm_mm.c +++ linux-2.6.37/drivers/gpu/drm/drm_mm.c @@ -392,10 +392,36 @@ mm->scanned_blocks = 0; mm->scan_hit_start = 0; mm->scan_hit_size = 0; + mm->scan_check_range = 0; } EXPORT_SYMBOL(drm_mm_init_scan); /** + * Initializa lru scanning. + * + * This simply sets up the scanning routines with the parameters for the desired + * hole. This version is for range-restricted scans. + * + * Warning: As long as the scan list is non-empty, no other operations than + * adding/removing nodes to/from the scan list are allowed. + */ +void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size, + unsigned alignment, + unsigned long start, + unsigned long end) +{ + mm->scan_alignment = alignment; + mm->scan_size = size; + mm->scanned_blocks = 0; + mm->scan_hit_start = 0; + mm->scan_hit_size = 0; + mm->scan_start = start; + mm->scan_end = end; + mm->scan_check_range = 1; +} +EXPORT_SYMBOL(drm_mm_init_scan_with_range); + +/** * Add a node to the scan list that might be freed to make space for the desired * hole. * @@ -406,6 +432,8 @@ struct drm_mm *mm = node->mm; struct list_head *prev_free, *next_free; struct drm_mm_node *prev_node, *next_node; + unsigned long adj_start; + unsigned long adj_end; mm->scanned_blocks++; @@ -452,7 +480,17 @@ node->free_stack.prev = prev_free; node->free_stack.next = next_free; - if (check_free_hole(node->start, node->start + node->size, + if (mm->scan_check_range) { + adj_start = node->start < mm->scan_start ? + mm->scan_start : node->start; + adj_end = node->start + node->size > mm->scan_end ? + mm->scan_end : node->start + node->size; + } else { + adj_start = node->start; + adj_end = node->start + node->size; + } + + if (check_free_hole(adj_start , adj_end, mm->scan_size, mm->scan_alignment)) { mm->scan_hit_start = node->start; mm->scan_hit_size = node->size; --- linux-2.6.37.orig/drivers/gpu/drm/drm_stub.c +++ linux-2.6.37/drivers/gpu/drm/drm_stub.c @@ -40,12 +40,22 @@ unsigned int drm_debug = 0; /* 1 to enable debug output */ EXPORT_SYMBOL(drm_debug); +unsigned int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ +EXPORT_SYMBOL(drm_vblank_offdelay); + +unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ +EXPORT_SYMBOL(drm_timestamp_precision); + MODULE_AUTHOR(CORE_AUTHOR); MODULE_DESCRIPTION(CORE_DESC); MODULE_LICENSE("GPL and additional rights"); MODULE_PARM_DESC(debug, "Enable debug output"); +MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs]"); +MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); module_param_named(debug, drm_debug, int, 0600); +module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); +module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); struct idr drm_minors_idr; @@ -336,7 +346,7 @@ new_minor->index = minor_id; INIT_LIST_HEAD(&new_minor->master_list); - idr_replace(&drm_minors_idr, new_minor, minor_id); + idr_replace(&drm_minors_idr, ERR_PTR(-EAGAIN), minor_id); if (type == DRM_MINOR_LEGACY) { ret = drm_proc_init(new_minor, minor_id, drm_proc_root); --- linux-2.6.37.orig/drivers/gpu/drm/i915/Makefile +++ linux-2.6.37/drivers/gpu/drm/i915/Makefile @@ -9,6 +9,8 @@ i915_gem.o \ i915_gem_debug.o \ i915_gem_evict.o \ + i915_gem_execbuffer.o \ + i915_gem_gtt.o \ i915_gem_tiling.o \ i915_trace_points.o \ intel_display.o \ --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_debugfs.c +++ linux-2.6.37/drivers/gpu/drm/i915/i915_debugfs.c @@ -32,6 +32,7 @@ #include "drmP.h" #include "drm.h" #include "intel_drv.h" +#include "intel_ringbuffer.h" #include "i915_drm.h" #include "i915_drv.h" @@ -72,7 +73,6 @@ B(is_broadwater); B(is_crestline); B(has_fbc); - B(has_rc6); B(has_pipe_cxsr); B(has_hotplug); B(cursor_needs_physical); @@ -86,19 +86,19 @@ return 0; } -static const char *get_pin_flag(struct drm_i915_gem_object *obj_priv) +static const char *get_pin_flag(struct drm_i915_gem_object *obj) { - if (obj_priv->user_pin_count > 0) + if (obj->user_pin_count > 0) return "P"; - else if (obj_priv->pin_count > 0) + else if (obj->pin_count > 0) return "p"; else return " "; } -static const char *get_tiling_flag(struct drm_i915_gem_object *obj_priv) +static const char *get_tiling_flag(struct drm_i915_gem_object *obj) { - switch (obj_priv->tiling_mode) { + switch (obj->tiling_mode) { default: case I915_TILING_NONE: return " "; case I915_TILING_X: return "X"; @@ -109,7 +109,7 @@ static void describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) { - seq_printf(m, "%p: %s%s %8zd %08x %08x %d%s%s", + seq_printf(m, "%p: %s%s %8zd %04x %04x %d %d%s%s", &obj->base, get_pin_flag(obj), get_tiling_flag(obj), @@ -117,6 +117,7 @@ obj->base.read_domains, obj->base.write_domain, obj->last_rendering_seqno, + obj->last_fenced_seqno, obj->dirty ? " dirty" : "", obj->madv == I915_MADV_DONTNEED ? " purgeable" : ""); if (obj->base.name) @@ -124,7 +125,17 @@ if (obj->fence_reg != I915_FENCE_REG_NONE) seq_printf(m, " (fence: %d)", obj->fence_reg); if (obj->gtt_space != NULL) - seq_printf(m, " (gtt_offset: %08x)", obj->gtt_offset); + seq_printf(m, " (gtt offset: %08x, size: %08x)", + obj->gtt_offset, (unsigned int)obj->gtt_space->size); + if (obj->pin_mappable || obj->fault_mappable) { + char s[3], *t = s; + if (obj->pin_mappable) + *t++ = 'p'; + if (obj->fault_mappable) + *t++ = 'f'; + *t = '\0'; + seq_printf(m, " (%s mappable)", s); + } if (obj->ring != NULL) seq_printf(m, " (%s)", obj->ring->name); } @@ -136,7 +147,7 @@ struct list_head *head; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; size_t total_obj_size, total_gtt_size; int count, ret; @@ -171,12 +182,12 @@ } total_obj_size = total_gtt_size = count = 0; - list_for_each_entry(obj_priv, head, mm_list) { + list_for_each_entry(obj, head, mm_list) { seq_printf(m, " "); - describe_obj(m, obj_priv); + describe_obj(m, obj); seq_printf(m, "\n"); - total_obj_size += obj_priv->base.size; - total_gtt_size += obj_priv->gtt_space->size; + total_obj_size += obj->base.size; + total_gtt_size += obj->gtt_space->size; count++; } mutex_unlock(&dev->struct_mutex); @@ -186,24 +197,79 @@ return 0; } +#define count_objects(list, member) do { \ + list_for_each_entry(obj, list, member) { \ + size += obj->gtt_space->size; \ + ++count; \ + if (obj->map_and_fenceable) { \ + mappable_size += obj->gtt_space->size; \ + ++mappable_count; \ + } \ + } \ +} while(0) + static int i915_gem_object_info(struct seq_file *m, void* data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; + u32 count, mappable_count; + size_t size, mappable_size; + struct drm_i915_gem_object *obj; int ret; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; - seq_printf(m, "%u objects\n", dev_priv->mm.object_count); - seq_printf(m, "%zu object bytes\n", dev_priv->mm.object_memory); - seq_printf(m, "%u pinned\n", dev_priv->mm.pin_count); - seq_printf(m, "%zu pin bytes\n", dev_priv->mm.pin_memory); - seq_printf(m, "%u objects in gtt\n", dev_priv->mm.gtt_count); - seq_printf(m, "%zu gtt bytes\n", dev_priv->mm.gtt_memory); - seq_printf(m, "%zu gtt total\n", dev_priv->mm.gtt_total); + seq_printf(m, "%u objects, %zu bytes\n", + dev_priv->mm.object_count, + dev_priv->mm.object_memory); + + size = count = mappable_size = mappable_count = 0; + count_objects(&dev_priv->mm.gtt_list, gtt_list); + seq_printf(m, "%u [%u] objects, %zu [%zu] bytes in gtt\n", + count, mappable_count, size, mappable_size); + + size = count = mappable_size = mappable_count = 0; + count_objects(&dev_priv->mm.active_list, mm_list); + count_objects(&dev_priv->mm.flushing_list, mm_list); + seq_printf(m, " %u [%u] active objects, %zu [%zu] bytes\n", + count, mappable_count, size, mappable_size); + + size = count = mappable_size = mappable_count = 0; + count_objects(&dev_priv->mm.pinned_list, mm_list); + seq_printf(m, " %u [%u] pinned objects, %zu [%zu] bytes\n", + count, mappable_count, size, mappable_size); + + size = count = mappable_size = mappable_count = 0; + count_objects(&dev_priv->mm.inactive_list, mm_list); + seq_printf(m, " %u [%u] inactive objects, %zu [%zu] bytes\n", + count, mappable_count, size, mappable_size); + + size = count = mappable_size = mappable_count = 0; + count_objects(&dev_priv->mm.deferred_free_list, mm_list); + seq_printf(m, " %u [%u] freed objects, %zu [%zu] bytes\n", + count, mappable_count, size, mappable_size); + + size = count = mappable_size = mappable_count = 0; + list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) { + if (obj->fault_mappable) { + size += obj->gtt_space->size; + ++count; + } + if (obj->pin_mappable) { + mappable_size += obj->gtt_space->size; + ++mappable_count; + } + } + seq_printf(m, "%u pinned mappable objects, %zu bytes\n", + mappable_count, mappable_size); + seq_printf(m, "%u fault mappable objects, %zu bytes\n", + count, size); + + seq_printf(m, "%zu [%zu] gtt total\n", + dev_priv->mm.gtt_total, dev_priv->mm.mappable_gtt_total); mutex_unlock(&dev->struct_mutex); @@ -243,14 +309,14 @@ seq_printf(m, "%d prepares\n", work->pending); if (work->old_fb_obj) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(work->old_fb_obj); - if(obj_priv) - seq_printf(m, "Old framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset ); + struct drm_i915_gem_object *obj = work->old_fb_obj; + if (obj) + seq_printf(m, "Old framebuffer gtt_offset 0x%08x\n", obj->gtt_offset); } if (work->pending_flip_obj) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(work->pending_flip_obj); - if(obj_priv) - seq_printf(m, "New framebuffer gtt_offset 0x%08x\n", obj_priv->gtt_offset ); + struct drm_i915_gem_object *obj = work->pending_flip_obj; + if (obj) + seq_printf(m, "New framebuffer gtt_offset 0x%08x\n", obj->gtt_offset); } } spin_unlock_irqrestore(&dev->event_lock, flags); @@ -265,44 +331,80 @@ struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_request *gem_request; - int ret; + int ret, count; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; - seq_printf(m, "Request:\n"); - list_for_each_entry(gem_request, &dev_priv->render_ring.request_list, - list) { - seq_printf(m, " %d @ %d\n", - gem_request->seqno, - (int) (jiffies - gem_request->emitted_jiffies)); + count = 0; + if (!list_empty(&dev_priv->ring[RCS].request_list)) { + seq_printf(m, "Render requests:\n"); + list_for_each_entry(gem_request, + &dev_priv->ring[RCS].request_list, + list) { + seq_printf(m, " %d @ %d\n", + gem_request->seqno, + (int) (jiffies - gem_request->emitted_jiffies)); + } + count++; + } + if (!list_empty(&dev_priv->ring[VCS].request_list)) { + seq_printf(m, "BSD requests:\n"); + list_for_each_entry(gem_request, + &dev_priv->ring[VCS].request_list, + list) { + seq_printf(m, " %d @ %d\n", + gem_request->seqno, + (int) (jiffies - gem_request->emitted_jiffies)); + } + count++; + } + if (!list_empty(&dev_priv->ring[BCS].request_list)) { + seq_printf(m, "BLT requests:\n"); + list_for_each_entry(gem_request, + &dev_priv->ring[BCS].request_list, + list) { + seq_printf(m, " %d @ %d\n", + gem_request->seqno, + (int) (jiffies - gem_request->emitted_jiffies)); + } + count++; } mutex_unlock(&dev->struct_mutex); + if (count == 0) + seq_printf(m, "No requests\n"); + return 0; } +static void i915_ring_seqno_info(struct seq_file *m, + struct intel_ring_buffer *ring) +{ + if (ring->get_seqno) { + seq_printf(m, "Current sequence (%s): %d\n", + ring->name, ring->get_seqno(ring)); + seq_printf(m, "Waiter sequence (%s): %d\n", + ring->name, ring->waiting_seqno); + seq_printf(m, "IRQ sequence (%s): %d\n", + ring->name, ring->irq_seqno); + } +} + static int i915_gem_seqno_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; - int ret; + int ret, i; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; - if (dev_priv->render_ring.status_page.page_addr != NULL) { - seq_printf(m, "Current sequence: %d\n", - dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring)); - } else { - seq_printf(m, "Current sequence: hws uninitialized\n"); - } - seq_printf(m, "Waiter sequence: %d\n", - dev_priv->mm.waiting_gem_seqno); - seq_printf(m, "IRQ sequence: %d\n", dev_priv->mm.irq_gem_seqno); + for (i = 0; i < I915_NUM_RINGS; i++) + i915_ring_seqno_info(m, &dev_priv->ring[i]); mutex_unlock(&dev->struct_mutex); @@ -315,7 +417,7 @@ struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; - int ret; + int ret, i; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) @@ -354,16 +456,14 @@ } seq_printf(m, "Interrupts received: %d\n", atomic_read(&dev_priv->irq_received)); - if (dev_priv->render_ring.status_page.page_addr != NULL) { - seq_printf(m, "Current sequence: %d\n", - dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring)); - } else { - seq_printf(m, "Current sequence: hws uninitialized\n"); + for (i = 0; i < I915_NUM_RINGS; i++) { + if (IS_GEN6(dev)) { + seq_printf(m, "Graphics Interrupt mask (%s): %08x\n", + dev_priv->ring[i].name, + I915_READ_IMR(&dev_priv->ring[i])); + } + i915_ring_seqno_info(m, &dev_priv->ring[i]); } - seq_printf(m, "Waiter sequence: %d\n", - dev_priv->mm.waiting_gem_seqno); - seq_printf(m, "IRQ sequence: %d\n", - dev_priv->mm.irq_gem_seqno); mutex_unlock(&dev->struct_mutex); return 0; @@ -383,29 +483,17 @@ seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start); seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs); for (i = 0; i < dev_priv->num_fence_regs; i++) { - struct drm_gem_object *obj = dev_priv->fence_regs[i].obj; - - if (obj == NULL) { - seq_printf(m, "Fenced object[%2d] = unused\n", i); - } else { - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj = dev_priv->fence_regs[i].obj; - obj_priv = to_intel_bo(obj); - seq_printf(m, "Fenced object[%2d] = %p: %s " - "%08x %08zx %08x %s %08x %08x %d", - i, obj, get_pin_flag(obj_priv), - obj_priv->gtt_offset, - obj->size, obj_priv->stride, - get_tiling_flag(obj_priv), - obj->read_domains, obj->write_domain, - obj_priv->last_rendering_seqno); - if (obj->name) - seq_printf(m, " (name: %d)", obj->name); - seq_printf(m, "\n"); - } + seq_printf(m, "Fenced object[%2d] = ", i); + if (obj == NULL) + seq_printf(m, "unused"); + else + describe_obj(m, obj); + seq_printf(m, "\n"); } - mutex_unlock(&dev->struct_mutex); + mutex_unlock(&dev->struct_mutex); return 0; } @@ -414,10 +502,12 @@ struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; - int i; + struct intel_ring_buffer *ring; volatile u32 *hws; + int i; - hws = (volatile u32 *)dev_priv->render_ring.status_page.page_addr; + ring = &dev_priv->ring[(uintptr_t)node->info_ent->data]; + hws = (volatile u32 *)ring->status_page.page_addr; if (hws == NULL) return 0; @@ -431,14 +521,14 @@ static void i915_dump_object(struct seq_file *m, struct io_mapping *mapping, - struct drm_i915_gem_object *obj_priv) + struct drm_i915_gem_object *obj) { int page, page_count, i; - page_count = obj_priv->base.size / PAGE_SIZE; + page_count = obj->base.size / PAGE_SIZE; for (page = 0; page < page_count; page++) { u32 *mem = io_mapping_map_wc(mapping, - obj_priv->gtt_offset + page * PAGE_SIZE); + obj->gtt_offset + page * PAGE_SIZE); for (i = 0; i < PAGE_SIZE; i += 4) seq_printf(m, "%08x : %08x\n", i, mem[i / 4]); io_mapping_unmap(mem); @@ -450,25 +540,21 @@ struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int ret; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) { - obj = &obj_priv->base; - if (obj->read_domains & I915_GEM_DOMAIN_COMMAND) { - seq_printf(m, "--- gtt_offset = 0x%08x\n", - obj_priv->gtt_offset); - i915_dump_object(m, dev_priv->mm.gtt_mapping, obj_priv); + list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) { + if (obj->base.read_domains & I915_GEM_DOMAIN_COMMAND) { + seq_printf(m, "--- gtt_offset = 0x%08x\n", obj->gtt_offset); + i915_dump_object(m, dev_priv->mm.gtt_mapping, obj); } } mutex_unlock(&dev->struct_mutex); - return 0; } @@ -477,19 +563,21 @@ struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring; int ret; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; - if (!dev_priv->render_ring.gem_object) { + ring = &dev_priv->ring[(uintptr_t)node->info_ent->data]; + if (!ring->obj) { seq_printf(m, "No ringbuffer setup\n"); } else { - u8 *virt = dev_priv->render_ring.virtual_start; + u8 *virt = ring->virtual_start; uint32_t off; - for (off = 0; off < dev_priv->render_ring.size; off += 4) { + for (off = 0; off < ring->size; off += 4) { uint32_t *ptr = (uint32_t *)(virt + off); seq_printf(m, "%08x : %08x\n", off, *ptr); } @@ -504,19 +592,38 @@ struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; - unsigned int head, tail; + struct intel_ring_buffer *ring; - head = I915_READ(PRB0_HEAD) & HEAD_ADDR; - tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; + ring = &dev_priv->ring[(uintptr_t)node->info_ent->data]; + if (ring->size == 0) + return 0; - seq_printf(m, "RingHead : %08x\n", head); - seq_printf(m, "RingTail : %08x\n", tail); - seq_printf(m, "RingSize : %08lx\n", dev_priv->render_ring.size); - seq_printf(m, "Acthd : %08x\n", I915_READ(INTEL_INFO(dev)->gen >= 4 ? ACTHD_I965 : ACTHD)); + seq_printf(m, "Ring %s:\n", ring->name); + seq_printf(m, " Head : %08x\n", I915_READ_HEAD(ring) & HEAD_ADDR); + seq_printf(m, " Tail : %08x\n", I915_READ_TAIL(ring) & TAIL_ADDR); + seq_printf(m, " Size : %08x\n", ring->size); + seq_printf(m, " Active : %08x\n", intel_ring_get_active_head(ring)); + seq_printf(m, " NOPID : %08x\n", I915_READ_NOPID(ring)); + if (IS_GEN6(dev)) { + seq_printf(m, " Sync 0 : %08x\n", I915_READ_SYNC_0(ring)); + seq_printf(m, " Sync 1 : %08x\n", I915_READ_SYNC_1(ring)); + } + seq_printf(m, " Control : %08x\n", I915_READ_CTL(ring)); + seq_printf(m, " Start : %08x\n", I915_READ_START(ring)); return 0; } +static const char *ring_str(int ring) +{ + switch (ring) { + case RING_RENDER: return " render"; + case RING_BSD: return " bsd"; + case RING_BLT: return " blt"; + default: return ""; + } +} + static const char *pin_flag(int pinned) { if (pinned > 0) @@ -547,6 +654,36 @@ return purgeable ? " purgeable" : ""; } +static void print_error_buffers(struct seq_file *m, + const char *name, + struct drm_i915_error_buffer *err, + int count) +{ + seq_printf(m, "%s [%d]:\n", name, count); + + while (count--) { + seq_printf(m, " %08x %8zd %04x %04x %08x%s%s%s%s%s", + err->gtt_offset, + err->size, + err->read_domains, + err->write_domain, + err->seqno, + pin_flag(err->pinned), + tiling_flag(err->tiling), + dirty_flag(err->dirty), + purgeable_flag(err->purgeable), + ring_str(err->ring)); + + if (err->name) + seq_printf(m, " (name: %d)", err->name); + if (err->fence_reg != I915_FENCE_REG_NONE) + seq_printf(m, " (fence: %d)", err->fence_reg); + + seq_printf(m, "\n"); + err++; + } +} + static int i915_error_state(struct seq_file *m, void *unused) { struct drm_info_node *node = (struct drm_info_node *) m->private; @@ -568,41 +705,46 @@ error->time.tv_usec); seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device); seq_printf(m, "EIR: 0x%08x\n", error->eir); - seq_printf(m, " PGTBL_ER: 0x%08x\n", error->pgtbl_er); - seq_printf(m, " INSTPM: 0x%08x\n", error->instpm); + seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); + if (INTEL_INFO(dev)->gen >= 6) { + seq_printf(m, "ERROR: 0x%08x\n", error->error); + seq_printf(m, "Blitter command stream:\n"); + seq_printf(m, " ACTHD: 0x%08x\n", error->bcs_acthd); + seq_printf(m, " IPEIR: 0x%08x\n", error->bcs_ipeir); + seq_printf(m, " IPEHR: 0x%08x\n", error->bcs_ipehr); + seq_printf(m, " INSTDONE: 0x%08x\n", error->bcs_instdone); + seq_printf(m, " seqno: 0x%08x\n", error->bcs_seqno); + seq_printf(m, "Video (BSD) command stream:\n"); + seq_printf(m, " ACTHD: 0x%08x\n", error->vcs_acthd); + seq_printf(m, " IPEIR: 0x%08x\n", error->vcs_ipeir); + seq_printf(m, " IPEHR: 0x%08x\n", error->vcs_ipehr); + seq_printf(m, " INSTDONE: 0x%08x\n", error->vcs_instdone); + seq_printf(m, " seqno: 0x%08x\n", error->vcs_seqno); + } + seq_printf(m, "Render command stream:\n"); + seq_printf(m, " ACTHD: 0x%08x\n", error->acthd); seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir); seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr); seq_printf(m, " INSTDONE: 0x%08x\n", error->instdone); - seq_printf(m, " ACTHD: 0x%08x\n", error->acthd); if (INTEL_INFO(dev)->gen >= 4) { - seq_printf(m, " INSTPS: 0x%08x\n", error->instps); seq_printf(m, " INSTDONE1: 0x%08x\n", error->instdone1); + seq_printf(m, " INSTPS: 0x%08x\n", error->instps); } - seq_printf(m, "seqno: 0x%08x\n", error->seqno); - - if (error->active_bo_count) { - seq_printf(m, "Buffers [%d]:\n", error->active_bo_count); + seq_printf(m, " INSTPM: 0x%08x\n", error->instpm); + seq_printf(m, " seqno: 0x%08x\n", error->seqno); - for (i = 0; i < error->active_bo_count; i++) { - seq_printf(m, " %08x %8zd %08x %08x %08x%s%s%s%s", - error->active_bo[i].gtt_offset, - error->active_bo[i].size, - error->active_bo[i].read_domains, - error->active_bo[i].write_domain, - error->active_bo[i].seqno, - pin_flag(error->active_bo[i].pinned), - tiling_flag(error->active_bo[i].tiling), - dirty_flag(error->active_bo[i].dirty), - purgeable_flag(error->active_bo[i].purgeable)); - - if (error->active_bo[i].name) - seq_printf(m, " (name: %d)", error->active_bo[i].name); - if (error->active_bo[i].fence_reg != I915_FENCE_REG_NONE) - seq_printf(m, " (fence: %d)", error->active_bo[i].fence_reg); + for (i = 0; i < 16; i++) + seq_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); - seq_printf(m, "\n"); - } - } + if (error->active_bo) + print_error_buffers(m, "Active", + error->active_bo, + error->active_bo_count); + + if (error->pinned_bo) + print_error_buffers(m, "Pinned", + error->pinned_bo, + error->pinned_bo_count); for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++) { if (error->batchbuffer[i]) { @@ -635,6 +777,9 @@ if (error->overlay) intel_overlay_print_error_state(m, error->overlay); + if (error->display) + intel_display_print_error_state(m, dev, error->display); + out: spin_unlock_irqrestore(&dev_priv->error_lock, flags); @@ -658,15 +803,51 @@ struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; drm_i915_private_t *dev_priv = dev->dev_private; - u16 rgvswctl = I915_READ16(MEMSWCTL); - u16 rgvstat = I915_READ16(MEMSTAT_ILK); - seq_printf(m, "Requested P-state: %d\n", (rgvswctl >> 8) & 0xf); - seq_printf(m, "Requested VID: %d\n", rgvswctl & 0x3f); - seq_printf(m, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK) >> - MEMSTAT_VID_SHIFT); - seq_printf(m, "Current P-state: %d\n", - (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT); + if (IS_GEN5(dev)) { + u16 rgvswctl = I915_READ16(MEMSWCTL); + u16 rgvstat = I915_READ16(MEMSTAT_ILK); + + seq_printf(m, "Requested P-state: %d\n", (rgvswctl >> 8) & 0xf); + seq_printf(m, "Requested VID: %d\n", rgvswctl & 0x3f); + seq_printf(m, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK) >> + MEMSTAT_VID_SHIFT); + seq_printf(m, "Current P-state: %d\n", + (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT); + } else if (IS_GEN6(dev)) { + u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); + u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS); + u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); + int max_freq; + + /* RPSTAT1 is in the GT power well */ + __gen6_force_wake_get(dev_priv); + + seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); + seq_printf(m, "RPSTAT1: 0x%08x\n", I915_READ(GEN6_RPSTAT1)); + seq_printf(m, "Render p-state ratio: %d\n", + (gt_perf_status & 0xff00) >> 8); + seq_printf(m, "Render p-state VID: %d\n", + gt_perf_status & 0xff); + seq_printf(m, "Render p-state limit: %d\n", + rp_state_limits & 0xff); + + max_freq = (rp_state_cap & 0xff0000) >> 16; + seq_printf(m, "Lowest (RPN) frequency: %dMHz\n", + max_freq * 100); + + max_freq = (rp_state_cap & 0xff00) >> 8; + seq_printf(m, "Nominal (RP1) frequency: %dMHz\n", + max_freq * 100); + + max_freq = rp_state_cap & 0xff; + seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", + max_freq * 100); + + __gen6_force_wake_put(dev_priv); + } else { + seq_printf(m, "no P-state info available\n"); + } return 0; } @@ -794,7 +975,7 @@ drm_i915_private_t *dev_priv = dev->dev_private; bool sr_enabled = false; - if (IS_GEN5(dev)) + if (HAS_PCH_SPLIT(dev)) sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN; else if (IS_CRESTLINE(dev) || IS_I945G(dev) || IS_I945GM(dev)) sr_enabled = I915_READ(FW_BLC_SELF) & FW_BLC_SELF_EN; @@ -886,7 +1067,7 @@ fb->base.height, fb->base.depth, fb->base.bits_per_pixel); - describe_obj(m, to_intel_bo(fb->obj)); + describe_obj(m, fb->obj); seq_printf(m, "\n"); list_for_each_entry(fb, &dev->mode_config.fb_list, base.head) { @@ -898,7 +1079,7 @@ fb->base.height, fb->base.depth, fb->base.bits_per_pixel); - describe_obj(m, to_intel_bo(fb->obj)); + describe_obj(m, fb->obj); seq_printf(m, "\n"); } @@ -943,7 +1124,6 @@ loff_t *ppos) { struct drm_device *dev = filp->private_data; - drm_i915_private_t *dev_priv = dev->dev_private; char buf[20]; int val = 1; @@ -959,12 +1139,7 @@ } DRM_INFO("Manually setting wedged to %d\n", val); - - atomic_set(&dev_priv->mm.wedged, val); - if (val) { - wake_up_all(&dev_priv->irq_queue); - queue_work(dev_priv->wq, &dev_priv->error_work); - } + i915_handle_error(dev, val); return cnt; } @@ -1028,9 +1203,15 @@ {"i915_gem_seqno", i915_gem_seqno_info, 0}, {"i915_gem_fence_regs", i915_gem_fence_regs_info, 0}, {"i915_gem_interrupt", i915_interrupt_info, 0}, - {"i915_gem_hws", i915_hws_info, 0}, - {"i915_ringbuffer_data", i915_ringbuffer_data, 0}, - {"i915_ringbuffer_info", i915_ringbuffer_info, 0}, + {"i915_gem_hws", i915_hws_info, 0, (void *)RCS}, + {"i915_gem_hws_blt", i915_hws_info, 0, (void *)BCS}, + {"i915_gem_hws_bsd", i915_hws_info, 0, (void *)VCS}, + {"i915_ringbuffer_data", i915_ringbuffer_data, 0, (void *)RCS}, + {"i915_ringbuffer_info", i915_ringbuffer_info, 0, (void *)RCS}, + {"i915_bsd_ringbuffer_data", i915_ringbuffer_data, 0, (void *)VCS}, + {"i915_bsd_ringbuffer_info", i915_ringbuffer_info, 0, (void *)VCS}, + {"i915_blt_ringbuffer_data", i915_ringbuffer_data, 0, (void *)BCS}, + {"i915_blt_ringbuffer_info", i915_ringbuffer_info, 0, (void *)BCS}, {"i915_batchbuffers", i915_batchbuffer_info, 0}, {"i915_error_state", i915_error_state, 0}, {"i915_rstdby_delays", i915_rstdby_delays, 0}, --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_dma.c +++ linux-2.6.37/drivers/gpu/drm/i915/i915_dma.c @@ -50,6 +50,8 @@ static int i915_init_phys_hws(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring = LP_RING(dev_priv); + /* Program Hardware Status Page */ dev_priv->status_page_dmah = drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE); @@ -58,11 +60,10 @@ DRM_ERROR("Can not allocate hardware status page\n"); return -ENOMEM; } - dev_priv->render_ring.status_page.page_addr - = dev_priv->status_page_dmah->vaddr; + ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; - memset(dev_priv->render_ring.status_page.page_addr, 0, PAGE_SIZE); + memset(ring->status_page.page_addr, 0, PAGE_SIZE); if (INTEL_INFO(dev)->gen >= 4) dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) & @@ -80,13 +81,15 @@ static void i915_free_hws(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring = LP_RING(dev_priv); + if (dev_priv->status_page_dmah) { drm_pci_free(dev, dev_priv->status_page_dmah); dev_priv->status_page_dmah = NULL; } - if (dev_priv->render_ring.status_page.gfx_addr) { - dev_priv->render_ring.status_page.gfx_addr = 0; + if (ring->status_page.gfx_addr) { + ring->status_page.gfx_addr = 0; drm_core_ioremapfree(&dev_priv->hws_map, dev); } @@ -98,7 +101,7 @@ { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv; - struct intel_ring_buffer *ring = &dev_priv->render_ring; + struct intel_ring_buffer *ring = LP_RING(dev_priv); /* * We should never lose context on the ring with modesetting @@ -107,8 +110,8 @@ if (drm_core_check_feature(dev, DRIVER_MODESET)) return; - ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; - ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; + ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; + ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; ring->space = ring->head - (ring->tail + 8); if (ring->space < 0) ring->space += ring->size; @@ -124,6 +127,8 @@ static int i915_dma_cleanup(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; + int i; + /* Make sure interrupts are disabled here because the uninstall ioctl * may not have been called from userspace and after dev_private * is freed, it's too late. @@ -132,9 +137,8 @@ drm_irq_uninstall(dev); mutex_lock(&dev->struct_mutex); - intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); - intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); - intel_cleanup_ring_buffer(dev, &dev_priv->blt_ring); + for (i = 0; i < I915_NUM_RINGS; i++) + intel_cleanup_ring_buffer(&dev_priv->ring[i]); mutex_unlock(&dev->struct_mutex); /* Clear the HWS virtual address at teardown */ @@ -148,6 +152,7 @@ { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; + struct intel_ring_buffer *ring = LP_RING(dev_priv); master_priv->sarea = drm_getsarea(dev); if (master_priv->sarea) { @@ -158,24 +163,24 @@ } if (init->ring_size != 0) { - if (dev_priv->render_ring.gem_object != NULL) { + if (ring->obj != NULL) { i915_dma_cleanup(dev); DRM_ERROR("Client tried to initialize ringbuffer in " "GEM mode\n"); return -EINVAL; } - dev_priv->render_ring.size = init->ring_size; + ring->size = init->ring_size; - dev_priv->render_ring.map.offset = init->ring_start; - dev_priv->render_ring.map.size = init->ring_size; - dev_priv->render_ring.map.type = 0; - dev_priv->render_ring.map.flags = 0; - dev_priv->render_ring.map.mtrr = 0; + ring->map.offset = init->ring_start; + ring->map.size = init->ring_size; + ring->map.type = 0; + ring->map.flags = 0; + ring->map.mtrr = 0; - drm_core_ioremap_wc(&dev_priv->render_ring.map, dev); + drm_core_ioremap_wc(&ring->map, dev); - if (dev_priv->render_ring.map.handle == NULL) { + if (ring->map.handle == NULL) { i915_dma_cleanup(dev); DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); @@ -183,7 +188,7 @@ } } - dev_priv->render_ring.virtual_start = dev_priv->render_ring.map.handle; + ring->virtual_start = ring->map.handle; dev_priv->cpp = init->cpp; dev_priv->back_offset = init->back_offset; @@ -202,12 +207,10 @@ static int i915_dma_resume(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + struct intel_ring_buffer *ring = LP_RING(dev_priv); - struct intel_ring_buffer *ring; DRM_DEBUG_DRIVER("%s\n", __func__); - ring = &dev_priv->render_ring; - if (ring->map.handle == NULL) { DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); @@ -222,7 +225,7 @@ DRM_DEBUG_DRIVER("hw status page @ %p\n", ring->status_page.page_addr); if (ring->status_page.gfx_addr != 0) - intel_ring_setup_status_page(dev, ring); + intel_ring_setup_status_page(ring); else I915_WRITE(HWS_PGA, dev_priv->dma_status_page); @@ -264,7 +267,7 @@ * instruction detected will be given a size of zero, which is a * signal to abort the rest of the buffer. */ -static int do_validate_cmd(int cmd) +static int validate_cmd(int cmd) { switch (((cmd >> 29) & 0x7)) { case 0x0: @@ -322,40 +325,27 @@ return 0; } -static int validate_cmd(int cmd) -{ - int ret = do_validate_cmd(cmd); - -/* printk("validate_cmd( %x ): %d\n", cmd, ret); */ - - return ret; -} - static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords) { drm_i915_private_t *dev_priv = dev->dev_private; - int i; + int i, ret; - if ((dwords+1) * sizeof(int) >= dev_priv->render_ring.size - 8) + if ((dwords+1) * sizeof(int) >= LP_RING(dev_priv)->size - 8) return -EINVAL; - BEGIN_LP_RING((dwords+1)&~1); - for (i = 0; i < dwords;) { - int cmd, sz; - - cmd = buffer[i]; - - if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) + int sz = validate_cmd(buffer[i]); + if (sz == 0 || i + sz > dwords) return -EINVAL; - - OUT_RING(cmd); - - while (++i, --sz) { - OUT_RING(buffer[i]); - } + i += sz; } + ret = BEGIN_LP_RING((dwords+1)&~1); + if (ret) + return ret; + + for (i = 0; i < dwords; i++) + OUT_RING(buffer[i]); if (dwords & 1) OUT_RING(0); @@ -366,34 +356,41 @@ int i915_emit_box(struct drm_device *dev, - struct drm_clip_rect *boxes, - int i, int DR1, int DR4) + struct drm_clip_rect *box, + int DR1, int DR4) { - struct drm_clip_rect box = boxes[i]; + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; - if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { + if (box->y2 <= box->y1 || box->x2 <= box->x1 || + box->y2 <= 0 || box->x2 <= 0) { DRM_ERROR("Bad box %d,%d..%d,%d\n", - box.x1, box.y1, box.x2, box.y2); + box->x1, box->y1, box->x2, box->y2); return -EINVAL; } if (INTEL_INFO(dev)->gen >= 4) { - BEGIN_LP_RING(4); + ret = BEGIN_LP_RING(4); + if (ret) + return ret; + OUT_RING(GFX_OP_DRAWRECT_INFO_I965); - OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); - OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); + OUT_RING((box->x1 & 0xffff) | (box->y1 << 16)); + OUT_RING(((box->x2 - 1) & 0xffff) | ((box->y2 - 1) << 16)); OUT_RING(DR4); - ADVANCE_LP_RING(); } else { - BEGIN_LP_RING(6); + ret = BEGIN_LP_RING(6); + if (ret) + return ret; + OUT_RING(GFX_OP_DRAWRECT_INFO); OUT_RING(DR1); - OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); - OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); + OUT_RING((box->x1 & 0xffff) | (box->y1 << 16)); + OUT_RING(((box->x2 - 1) & 0xffff) | ((box->y2 - 1) << 16)); OUT_RING(DR4); OUT_RING(0); - ADVANCE_LP_RING(); } + ADVANCE_LP_RING(); return 0; } @@ -413,12 +410,13 @@ if (master_priv->sarea_priv) master_priv->sarea_priv->last_enqueue = dev_priv->counter; - BEGIN_LP_RING(4); - OUT_RING(MI_STORE_DWORD_INDEX); - OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - OUT_RING(dev_priv->counter); - OUT_RING(0); - ADVANCE_LP_RING(); + if (BEGIN_LP_RING(4) == 0) { + OUT_RING(MI_STORE_DWORD_INDEX); + OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); + OUT_RING(dev_priv->counter); + OUT_RING(0); + ADVANCE_LP_RING(); + } } static int i915_dispatch_cmdbuffer(struct drm_device * dev, @@ -440,7 +438,7 @@ for (i = 0; i < count; i++) { if (i < nbox) { - ret = i915_emit_box(dev, cliprects, i, + ret = i915_emit_box(dev, &cliprects[i], cmd->DR1, cmd->DR4); if (ret) return ret; @@ -459,8 +457,9 @@ drm_i915_batchbuffer_t * batch, struct drm_clip_rect *cliprects) { + struct drm_i915_private *dev_priv = dev->dev_private; int nbox = batch->num_cliprects; - int i = 0, count; + int i, count, ret; if ((batch->start | batch->used) & 0x7) { DRM_ERROR("alignment"); @@ -470,17 +469,19 @@ i915_kernel_lost_context(dev); count = nbox ? nbox : 1; - for (i = 0; i < count; i++) { if (i < nbox) { - int ret = i915_emit_box(dev, cliprects, i, - batch->DR1, batch->DR4); + ret = i915_emit_box(dev, &cliprects[i], + batch->DR1, batch->DR4); if (ret) return ret; } if (!IS_I830(dev) && !IS_845G(dev)) { - BEGIN_LP_RING(2); + ret = BEGIN_LP_RING(2); + if (ret) + return ret; + if (INTEL_INFO(dev)->gen >= 4) { OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); OUT_RING(batch->start); @@ -488,26 +489,29 @@ OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); OUT_RING(batch->start | MI_BATCH_NON_SECURE); } - ADVANCE_LP_RING(); } else { - BEGIN_LP_RING(4); + ret = BEGIN_LP_RING(4); + if (ret) + return ret; + OUT_RING(MI_BATCH_BUFFER); OUT_RING(batch->start | MI_BATCH_NON_SECURE); OUT_RING(batch->start + batch->used - 4); OUT_RING(0); - ADVANCE_LP_RING(); } + ADVANCE_LP_RING(); } if (IS_G4X(dev) || IS_GEN5(dev)) { - BEGIN_LP_RING(2); - OUT_RING(MI_FLUSH | MI_NO_WRITE_FLUSH | MI_INVALIDATE_ISP); - OUT_RING(MI_NOOP); - ADVANCE_LP_RING(); + if (BEGIN_LP_RING(2) == 0) { + OUT_RING(MI_FLUSH | MI_NO_WRITE_FLUSH | MI_INVALIDATE_ISP); + OUT_RING(MI_NOOP); + ADVANCE_LP_RING(); + } } - i915_emit_breadcrumb(dev); + i915_emit_breadcrumb(dev); return 0; } @@ -516,6 +520,7 @@ drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; + int ret; if (!master_priv->sarea_priv) return -EINVAL; @@ -527,12 +532,13 @@ i915_kernel_lost_context(dev); - BEGIN_LP_RING(2); + ret = BEGIN_LP_RING(10); + if (ret) + return ret; + OUT_RING(MI_FLUSH | MI_READ_FLUSH); OUT_RING(0); - ADVANCE_LP_RING(); - BEGIN_LP_RING(6); OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP); OUT_RING(0); if (dev_priv->current_page == 0) { @@ -543,33 +549,32 @@ dev_priv->current_page = 0; } OUT_RING(0); - ADVANCE_LP_RING(); - BEGIN_LP_RING(2); OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); OUT_RING(0); + ADVANCE_LP_RING(); master_priv->sarea_priv->last_enqueue = dev_priv->counter++; - BEGIN_LP_RING(4); - OUT_RING(MI_STORE_DWORD_INDEX); - OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - OUT_RING(dev_priv->counter); - OUT_RING(0); - ADVANCE_LP_RING(); + if (BEGIN_LP_RING(4) == 0) { + OUT_RING(MI_STORE_DWORD_INDEX); + OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); + OUT_RING(dev_priv->counter); + OUT_RING(0); + ADVANCE_LP_RING(); + } master_priv->sarea_priv->pf_current_page = dev_priv->current_page; return 0; } -static int i915_quiescent(struct drm_device * dev) +static int i915_quiescent(struct drm_device *dev) { - drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring = LP_RING(dev->dev_private); i915_kernel_lost_context(dev); - return intel_wait_ring_buffer(dev, &dev_priv->render_ring, - dev_priv->render_ring.size - 8); + return intel_wait_ring_buffer(ring, ring->size - 8); } static int i915_flush_ioctl(struct drm_device *dev, void *data, @@ -768,9 +773,15 @@ case I915_PARAM_HAS_BLT: value = HAS_BLT(dev); break; + case I915_PARAM_HAS_RELAXED_FENCING: + value = 1; + break; case I915_PARAM_HAS_COHERENT_RINGS: value = 1; break; + case I915_PARAM_HAS_EXEC_CONSTANTS: + value = INTEL_INFO(dev)->gen >= 4; + break; default: DRM_DEBUG_DRIVER("Unknown parameter %d\n", param->param); @@ -826,7 +837,7 @@ { drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_hws_addr_t *hws = data; - struct intel_ring_buffer *ring = &dev_priv->render_ring; + struct intel_ring_buffer *ring = LP_RING(dev_priv); if (!I915_NEED_GFX_HWS(dev)) return -EINVAL; @@ -1005,73 +1016,47 @@ #define PTE_VALID (1 << 0) /** - * i915_gtt_to_phys - take a GTT address and turn it into a physical one + * i915_stolen_to_phys - take an offset into stolen memory and turn it into + * a physical one * @dev: drm device - * @gtt_addr: address to translate + * @offset: address to translate * - * Some chip functions require allocations from stolen space but need the - * physical address of the memory in question. We use this routine - * to get a physical address suitable for register programming from a given - * GTT address. + * Some chip functions require allocations from stolen space and need the + * physical address of the memory in question. */ -static unsigned long i915_gtt_to_phys(struct drm_device *dev, - unsigned long gtt_addr) +static unsigned long i915_stolen_to_phys(struct drm_device *dev, u32 offset) { - unsigned long *gtt; - unsigned long entry, phys; - int gtt_bar = IS_GEN2(dev) ? 1 : 0; - int gtt_offset, gtt_size; + struct drm_i915_private *dev_priv = dev->dev_private; + struct pci_dev *pdev = dev_priv->bridge_dev; + u32 base; - if (INTEL_INFO(dev)->gen >= 4) { - if (IS_G4X(dev) || INTEL_INFO(dev)->gen > 4) { - gtt_offset = 2*1024*1024; - gtt_size = 2*1024*1024; - } else { - gtt_offset = 512*1024; - gtt_size = 512*1024; - } +#if 0 + /* On the machines I have tested the Graphics Base of Stolen Memory + * is unreliable, so compute the base by subtracting the stolen memory + * from the Top of Low Usable DRAM which is where the BIOS places + * the graphics stolen memory. + */ + if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) { + /* top 32bits are reserved = 0 */ + pci_read_config_dword(pdev, 0xA4, &base); } else { - gtt_bar = 3; - gtt_offset = 0; - gtt_size = pci_resource_len(dev->pdev, gtt_bar); - } - - gtt = ioremap_wc(pci_resource_start(dev->pdev, gtt_bar) + gtt_offset, - gtt_size); - if (!gtt) { - DRM_ERROR("ioremap of GTT failed\n"); - return 0; - } - - entry = *(volatile u32 *)(gtt + (gtt_addr / 1024)); - - DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry); - - /* Mask out these reserved bits on this hardware. */ - if (INTEL_INFO(dev)->gen < 4 && !IS_G33(dev)) - entry &= ~PTE_ADDRESS_MASK_HIGH; - - /* If it's not a mapping type we know, then bail. */ - if ((entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_UNCACHED && - (entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_CACHED) { - iounmap(gtt); - return 0; + /* XXX presume 8xx is the same as i915 */ + pci_bus_read_config_dword(pdev->bus, 2, 0x5C, &base); } - - if (!(entry & PTE_VALID)) { - DRM_ERROR("bad GTT entry in stolen space\n"); - iounmap(gtt); - return 0; +#else + if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) { + u16 val; + pci_read_config_word(pdev, 0xb0, &val); + base = val >> 4 << 20; + } else { + u8 val; + pci_read_config_byte(pdev, 0x9c, &val); + base = val >> 3 << 27; } + base -= dev_priv->mm.gtt->stolen_size; +#endif - iounmap(gtt); - - phys =(entry & PTE_ADDRESS_MASK) | - ((uint64_t)(entry & PTE_ADDRESS_MASK_HIGH) << (32 - 4)); - - DRM_DEBUG_DRIVER("GTT addr: 0x%08lx, phys addr: 0x%08lx\n", gtt_addr, phys); - - return phys; + return base + offset; } static void i915_warn_stolen(struct drm_device *dev) @@ -1087,54 +1072,35 @@ unsigned long cfb_base; unsigned long ll_base = 0; - /* Leave 1M for line length buffer & misc. */ - compressed_fb = drm_mm_search_free(&dev_priv->mm.vram, size, 4096, 0); - if (!compressed_fb) { - dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; - i915_warn_stolen(dev); - return; - } - - compressed_fb = drm_mm_get_block(compressed_fb, size, 4096); - if (!compressed_fb) { - i915_warn_stolen(dev); - dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; - return; - } - - cfb_base = i915_gtt_to_phys(dev, compressed_fb->start); - if (!cfb_base) { - DRM_ERROR("failed to get stolen phys addr, disabling FBC\n"); - drm_mm_put_block(compressed_fb); - } - - if (!(IS_GM45(dev) || IS_IRONLAKE_M(dev))) { - compressed_llb = drm_mm_search_free(&dev_priv->mm.vram, 4096, - 4096, 0); - if (!compressed_llb) { - i915_warn_stolen(dev); - return; - } - - compressed_llb = drm_mm_get_block(compressed_llb, 4096, 4096); - if (!compressed_llb) { - i915_warn_stolen(dev); - return; - } - - ll_base = i915_gtt_to_phys(dev, compressed_llb->start); - if (!ll_base) { - DRM_ERROR("failed to get stolen phys addr, disabling FBC\n"); - drm_mm_put_block(compressed_fb); - drm_mm_put_block(compressed_llb); - } + compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0); + if (compressed_fb) + compressed_fb = drm_mm_get_block(compressed_fb, size, 4096); + if (!compressed_fb) + goto err; + + cfb_base = i915_stolen_to_phys(dev, compressed_fb->start); + if (!cfb_base) + goto err_fb; + + if (!(IS_GM45(dev) || HAS_PCH_SPLIT(dev))) { + compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen, + 4096, 4096, 0); + if (compressed_llb) + compressed_llb = drm_mm_get_block(compressed_llb, + 4096, 4096); + if (!compressed_llb) + goto err_fb; + + ll_base = i915_stolen_to_phys(dev, compressed_llb->start); + if (!ll_base) + goto err_llb; } dev_priv->cfb_size = size; intel_disable_fbc(dev); dev_priv->compressed_fb = compressed_fb; - if (IS_IRONLAKE_M(dev)) + if (HAS_PCH_SPLIT(dev)) I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start); else if (IS_GM45(dev)) { I915_WRITE(DPFC_CB_BASE, compressed_fb->start); @@ -1144,8 +1110,17 @@ dev_priv->compressed_llb = compressed_llb; } - DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base, - ll_base, size >> 20); + DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", + cfb_base, ll_base, size >> 20); + return; + +err_llb: + drm_mm_put_block(compressed_llb); +err_fb: + drm_mm_put_block(compressed_fb); +err: + dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; + i915_warn_stolen(dev); } static void i915_cleanup_compression(struct drm_device *dev) @@ -1196,17 +1171,20 @@ return can_switch; } -static int i915_load_modeset_init(struct drm_device *dev, - unsigned long prealloc_size, - unsigned long agp_size) +static int i915_load_modeset_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long prealloc_size, gtt_size, mappable_size; int ret = 0; - /* Basic memrange allocator for stolen space (aka mm.vram) */ - drm_mm_init(&dev_priv->mm.vram, 0, prealloc_size); + prealloc_size = dev_priv->mm.gtt->stolen_size; + gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT; + mappable_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; - /* Let GEM Manage from end of prealloc space to end of aperture. + /* Basic memrange allocator for stolen space */ + drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size); + + /* Let GEM Manage all of the aperture. * * However, leave one page at the end still bound to the scratch page. * There are a number of places where the hardware apparently @@ -1215,7 +1193,7 @@ * at the last page of the aperture. One page should be enough to * keep any prefetching inside of the aperture. */ - i915_gem_do_init(dev, prealloc_size, agp_size - 4096); + i915_gem_do_init(dev, 0, mappable_size, gtt_size - PAGE_SIZE); mutex_lock(&dev->struct_mutex); ret = i915_gem_init_ringbuffer(dev); @@ -1227,16 +1205,17 @@ if (I915_HAS_FBC(dev) && i915_powersave) { int cfb_size; - /* Try to get an 8M buffer... */ - if (prealloc_size > (9*1024*1024)) - cfb_size = 8*1024*1024; + /* Leave 1M for line length buffer & misc. */ + + /* Try to get a 32M buffer... */ + if (prealloc_size > (36*1024*1024)) + cfb_size = 32*1024*1024; else /* fall back to 7/8 of the stolen space */ cfb_size = prealloc_size * 7 / 8; i915_setup_compression(dev, cfb_size); } - /* Allow hardware batchbuffers unless told otherwise. - */ + /* Allow hardware batchbuffers unless told otherwise. */ dev_priv->allow_batchbuffer = 1; ret = intel_parse_bios(dev); @@ -1426,152 +1405,12 @@ } } -struct v_table { - u8 vid; - unsigned long vd; /* in .1 mil */ - unsigned long vm; /* in .1 mil */ - u8 pvid; -}; - -static struct v_table v_table[] = { - { 0, 16125, 15000, 0x7f, }, - { 1, 16000, 14875, 0x7e, }, - { 2, 15875, 14750, 0x7d, }, - { 3, 15750, 14625, 0x7c, }, - { 4, 15625, 14500, 0x7b, }, - { 5, 15500, 14375, 0x7a, }, - { 6, 15375, 14250, 0x79, }, - { 7, 15250, 14125, 0x78, }, - { 8, 15125, 14000, 0x77, }, - { 9, 15000, 13875, 0x76, }, - { 10, 14875, 13750, 0x75, }, - { 11, 14750, 13625, 0x74, }, - { 12, 14625, 13500, 0x73, }, - { 13, 14500, 13375, 0x72, }, - { 14, 14375, 13250, 0x71, }, - { 15, 14250, 13125, 0x70, }, - { 16, 14125, 13000, 0x6f, }, - { 17, 14000, 12875, 0x6e, }, - { 18, 13875, 12750, 0x6d, }, - { 19, 13750, 12625, 0x6c, }, - { 20, 13625, 12500, 0x6b, }, - { 21, 13500, 12375, 0x6a, }, - { 22, 13375, 12250, 0x69, }, - { 23, 13250, 12125, 0x68, }, - { 24, 13125, 12000, 0x67, }, - { 25, 13000, 11875, 0x66, }, - { 26, 12875, 11750, 0x65, }, - { 27, 12750, 11625, 0x64, }, - { 28, 12625, 11500, 0x63, }, - { 29, 12500, 11375, 0x62, }, - { 30, 12375, 11250, 0x61, }, - { 31, 12250, 11125, 0x60, }, - { 32, 12125, 11000, 0x5f, }, - { 33, 12000, 10875, 0x5e, }, - { 34, 11875, 10750, 0x5d, }, - { 35, 11750, 10625, 0x5c, }, - { 36, 11625, 10500, 0x5b, }, - { 37, 11500, 10375, 0x5a, }, - { 38, 11375, 10250, 0x59, }, - { 39, 11250, 10125, 0x58, }, - { 40, 11125, 10000, 0x57, }, - { 41, 11000, 9875, 0x56, }, - { 42, 10875, 9750, 0x55, }, - { 43, 10750, 9625, 0x54, }, - { 44, 10625, 9500, 0x53, }, - { 45, 10500, 9375, 0x52, }, - { 46, 10375, 9250, 0x51, }, - { 47, 10250, 9125, 0x50, }, - { 48, 10125, 9000, 0x4f, }, - { 49, 10000, 8875, 0x4e, }, - { 50, 9875, 8750, 0x4d, }, - { 51, 9750, 8625, 0x4c, }, - { 52, 9625, 8500, 0x4b, }, - { 53, 9500, 8375, 0x4a, }, - { 54, 9375, 8250, 0x49, }, - { 55, 9250, 8125, 0x48, }, - { 56, 9125, 8000, 0x47, }, - { 57, 9000, 7875, 0x46, }, - { 58, 8875, 7750, 0x45, }, - { 59, 8750, 7625, 0x44, }, - { 60, 8625, 7500, 0x43, }, - { 61, 8500, 7375, 0x42, }, - { 62, 8375, 7250, 0x41, }, - { 63, 8250, 7125, 0x40, }, - { 64, 8125, 7000, 0x3f, }, - { 65, 8000, 6875, 0x3e, }, - { 66, 7875, 6750, 0x3d, }, - { 67, 7750, 6625, 0x3c, }, - { 68, 7625, 6500, 0x3b, }, - { 69, 7500, 6375, 0x3a, }, - { 70, 7375, 6250, 0x39, }, - { 71, 7250, 6125, 0x38, }, - { 72, 7125, 6000, 0x37, }, - { 73, 7000, 5875, 0x36, }, - { 74, 6875, 5750, 0x35, }, - { 75, 6750, 5625, 0x34, }, - { 76, 6625, 5500, 0x33, }, - { 77, 6500, 5375, 0x32, }, - { 78, 6375, 5250, 0x31, }, - { 79, 6250, 5125, 0x30, }, - { 80, 6125, 5000, 0x2f, }, - { 81, 6000, 4875, 0x2e, }, - { 82, 5875, 4750, 0x2d, }, - { 83, 5750, 4625, 0x2c, }, - { 84, 5625, 4500, 0x2b, }, - { 85, 5500, 4375, 0x2a, }, - { 86, 5375, 4250, 0x29, }, - { 87, 5250, 4125, 0x28, }, - { 88, 5125, 4000, 0x27, }, - { 89, 5000, 3875, 0x26, }, - { 90, 4875, 3750, 0x25, }, - { 91, 4750, 3625, 0x24, }, - { 92, 4625, 3500, 0x23, }, - { 93, 4500, 3375, 0x22, }, - { 94, 4375, 3250, 0x21, }, - { 95, 4250, 3125, 0x20, }, - { 96, 4125, 3000, 0x1f, }, - { 97, 4125, 3000, 0x1e, }, - { 98, 4125, 3000, 0x1d, }, - { 99, 4125, 3000, 0x1c, }, - { 100, 4125, 3000, 0x1b, }, - { 101, 4125, 3000, 0x1a, }, - { 102, 4125, 3000, 0x19, }, - { 103, 4125, 3000, 0x18, }, - { 104, 4125, 3000, 0x17, }, - { 105, 4125, 3000, 0x16, }, - { 106, 4125, 3000, 0x15, }, - { 107, 4125, 3000, 0x14, }, - { 108, 4125, 3000, 0x13, }, - { 109, 4125, 3000, 0x12, }, - { 110, 4125, 3000, 0x11, }, - { 111, 4125, 3000, 0x10, }, - { 112, 4125, 3000, 0x0f, }, - { 113, 4125, 3000, 0x0e, }, - { 114, 4125, 3000, 0x0d, }, - { 115, 4125, 3000, 0x0c, }, - { 116, 4125, 3000, 0x0b, }, - { 117, 4125, 3000, 0x0a, }, - { 118, 4125, 3000, 0x09, }, - { 119, 4125, 3000, 0x08, }, - { 120, 1125, 0, 0x07, }, - { 121, 1000, 0, 0x06, }, - { 122, 875, 0, 0x05, }, - { 123, 750, 0, 0x04, }, - { 124, 625, 0, 0x03, }, - { 125, 500, 0, 0x02, }, - { 126, 375, 0, 0x01, }, - { 127, 0, 0, 0x00, }, -}; - -struct cparams { - int i; - int t; - int m; - int c; -}; - -static struct cparams cparams[] = { +static const struct cparams { + u16 i; + u16 t; + u16 m; + u16 c; +} cparams[] = { { 1, 1333, 301, 28664 }, { 1, 1066, 294, 24460 }, { 1, 800, 294, 25192 }, @@ -1637,21 +1476,145 @@ return ((m * x) / 127) - b; } -static unsigned long pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid) +static u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid) { - unsigned long val = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(v_table); i++) { - if (v_table[i].pvid == pxvid) { - if (IS_MOBILE(dev_priv->dev)) - val = v_table[i].vm; - else - val = v_table[i].vd; - } - } - - return val; + static const struct v_table { + u16 vd; /* in .1 mil */ + u16 vm; /* in .1 mil */ + } v_table[] = { + { 0, 0, }, + { 375, 0, }, + { 500, 0, }, + { 625, 0, }, + { 750, 0, }, + { 875, 0, }, + { 1000, 0, }, + { 1125, 0, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4125, 3000, }, + { 4250, 3125, }, + { 4375, 3250, }, + { 4500, 3375, }, + { 4625, 3500, }, + { 4750, 3625, }, + { 4875, 3750, }, + { 5000, 3875, }, + { 5125, 4000, }, + { 5250, 4125, }, + { 5375, 4250, }, + { 5500, 4375, }, + { 5625, 4500, }, + { 5750, 4625, }, + { 5875, 4750, }, + { 6000, 4875, }, + { 6125, 5000, }, + { 6250, 5125, }, + { 6375, 5250, }, + { 6500, 5375, }, + { 6625, 5500, }, + { 6750, 5625, }, + { 6875, 5750, }, + { 7000, 5875, }, + { 7125, 6000, }, + { 7250, 6125, }, + { 7375, 6250, }, + { 7500, 6375, }, + { 7625, 6500, }, + { 7750, 6625, }, + { 7875, 6750, }, + { 8000, 6875, }, + { 8125, 7000, }, + { 8250, 7125, }, + { 8375, 7250, }, + { 8500, 7375, }, + { 8625, 7500, }, + { 8750, 7625, }, + { 8875, 7750, }, + { 9000, 7875, }, + { 9125, 8000, }, + { 9250, 8125, }, + { 9375, 8250, }, + { 9500, 8375, }, + { 9625, 8500, }, + { 9750, 8625, }, + { 9875, 8750, }, + { 10000, 8875, }, + { 10125, 9000, }, + { 10250, 9125, }, + { 10375, 9250, }, + { 10500, 9375, }, + { 10625, 9500, }, + { 10750, 9625, }, + { 10875, 9750, }, + { 11000, 9875, }, + { 11125, 10000, }, + { 11250, 10125, }, + { 11375, 10250, }, + { 11500, 10375, }, + { 11625, 10500, }, + { 11750, 10625, }, + { 11875, 10750, }, + { 12000, 10875, }, + { 12125, 11000, }, + { 12250, 11125, }, + { 12375, 11250, }, + { 12500, 11375, }, + { 12625, 11500, }, + { 12750, 11625, }, + { 12875, 11750, }, + { 13000, 11875, }, + { 13125, 12000, }, + { 13250, 12125, }, + { 13375, 12250, }, + { 13500, 12375, }, + { 13625, 12500, }, + { 13750, 12625, }, + { 13875, 12750, }, + { 14000, 12875, }, + { 14125, 13000, }, + { 14250, 13125, }, + { 14375, 13250, }, + { 14500, 13375, }, + { 14625, 13500, }, + { 14750, 13625, }, + { 14875, 13750, }, + { 15000, 13875, }, + { 15125, 14000, }, + { 15250, 14125, }, + { 15375, 14250, }, + { 15500, 14375, }, + { 15625, 14500, }, + { 15750, 14625, }, + { 15875, 14750, }, + { 16000, 14875, }, + { 16125, 15000, }, + }; + if (dev_priv->info->is_mobile) + return v_table[pxvid].vm; + else + return v_table[pxvid].vd; } void i915_update_gfx_val(struct drm_i915_private *dev_priv) @@ -1905,9 +1868,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) { struct drm_i915_private *dev_priv; - resource_size_t base, size; int ret = 0, mmio_bar; - uint32_t agp_size, prealloc_size; + uint32_t agp_size; + /* i915 has 4 more counters */ dev->counters += 4; dev->types[6] = _DRM_STAT_IRQ; @@ -1923,11 +1886,6 @@ dev_priv->dev = dev; dev_priv->info = (struct intel_device_info *) flags; - /* Add register map (needed for suspend/resume) */ - mmio_bar = IS_GEN2(dev) ? 1 : 0; - base = pci_resource_start(dev->pdev, mmio_bar); - size = pci_resource_len(dev->pdev, mmio_bar); - if (i915_get_bridge_dev(dev)) { ret = -EIO; goto free_priv; @@ -1937,16 +1895,25 @@ if (IS_GEN2(dev)) dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30)); - dev_priv->regs = ioremap(base, size); + mmio_bar = IS_GEN2(dev) ? 1 : 0; + dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, 0); if (!dev_priv->regs) { DRM_ERROR("failed to map registers\n"); ret = -EIO; goto put_bridge; } + dev_priv->mm.gtt = intel_gtt_get(); + if (!dev_priv->mm.gtt) { + DRM_ERROR("Failed to initialize GTT\n"); + ret = -ENODEV; + goto out_iomapfree; + } + + agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; + dev_priv->mm.gtt_mapping = - io_mapping_create_wc(dev->agp->base, - dev->agp->agp_info.aper_size * 1024*1024); + io_mapping_create_wc(dev->agp->base, agp_size); if (dev_priv->mm.gtt_mapping == NULL) { ret = -EIO; goto out_rmmap; @@ -1958,24 +1925,13 @@ * MTRR if present. Even if a UC MTRR isn't present. */ dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base, - dev->agp->agp_info.aper_size * - 1024 * 1024, + agp_size, MTRR_TYPE_WRCOMB, 1); if (dev_priv->mm.gtt_mtrr < 0) { DRM_INFO("MTRR allocation failed. Graphics " "performance may suffer.\n"); } - dev_priv->mm.gtt = intel_gtt_get(); - if (!dev_priv->mm.gtt) { - DRM_ERROR("Failed to initialize GTT\n"); - ret = -ENODEV; - goto out_iomapfree; - } - - prealloc_size = dev_priv->mm.gtt->gtt_stolen_entries << PAGE_SHIFT; - agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; - /* The i915 workqueue is primarily used for batched retirement of * requests (and thus managing bo) once the task has been completed * by the GPU. i915_gem_retire_requests() is called directly when we @@ -1983,7 +1939,7 @@ * bo. * * It is also used for periodic low-priority events, such as - * idle-timers and hangcheck. + * idle-timers and recording error state. * * All tasks on the workqueue are expected to acquire the dev mutex * so there is no point in running more than one instance of the @@ -2001,22 +1957,6 @@ /* enable GEM by default */ dev_priv->has_gem = 1; - if (prealloc_size > agp_size * 3 / 4) { - DRM_ERROR("Detected broken video BIOS with %d/%dkB of video " - "memory stolen.\n", - prealloc_size / 1024, agp_size / 1024); - DRM_ERROR("Disabling GEM. (try reducing stolen memory or " - "updating the BIOS to fix).\n"); - dev_priv->has_gem = 0; - } - - if (dev_priv->has_gem == 0 && - drm_core_check_feature(dev, DRIVER_MODESET)) { - DRM_ERROR("kernel modesetting requires GEM, disabling driver.\n"); - ret = -ENODEV; - goto out_iomapfree; - } - dev->driver->get_vblank_counter = i915_get_vblank_counter; dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev)) { @@ -2037,8 +1977,8 @@ /* Init HWS */ if (!I915_NEED_GFX_HWS(dev)) { ret = i915_init_phys_hws(dev); - if (ret != 0) - goto out_workqueue_free; + if (ret) + goto out_gem_unload; } if (IS_PINEVIEW(dev)) @@ -2060,16 +2000,13 @@ if (!IS_I945G(dev) && !IS_I945GM(dev)) pci_enable_msi(dev->pdev); - spin_lock_init(&dev_priv->user_irq_lock); + spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->error_lock); dev_priv->trace_irq_seqno = 0; ret = drm_vblank_init(dev, I915_NUM_PIPE); - - if (ret) { - (void) i915_driver_unload(dev); - return ret; - } + if (ret) + goto out_gem_unload; /* Start out suspended */ dev_priv->mm.suspended = 1; @@ -2077,10 +2014,10 @@ intel_detect_pch(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) { - ret = i915_load_modeset_init(dev, prealloc_size, agp_size); + ret = i915_load_modeset_init(dev); if (ret < 0) { DRM_ERROR("failed to init modeset\n"); - goto out_workqueue_free; + goto out_gem_unload; } } @@ -2100,12 +2037,17 @@ return 0; -out_workqueue_free: +out_gem_unload: + if (dev->pdev->msi_enabled) + pci_disable_msi(dev->pdev); + + intel_teardown_gmbus(dev); + intel_teardown_mchbar(dev); destroy_workqueue(dev_priv->wq); out_iomapfree: io_mapping_free(dev_priv->mm.gtt_mapping); out_rmmap: - iounmap(dev_priv->regs); + pci_iounmap(dev->pdev, dev_priv->regs); put_bridge: pci_dev_put(dev_priv->bridge_dev); free_priv: @@ -2122,6 +2064,9 @@ i915_mch_dev = NULL; spin_unlock(&mchdev_lock); + if (dev_priv->mm.inactive_shrinker.shrink) + unregister_shrinker(&dev_priv->mm.inactive_shrinker); + mutex_lock(&dev->struct_mutex); ret = i915_gpu_idle(dev); if (ret) @@ -2179,7 +2124,7 @@ mutex_unlock(&dev->struct_mutex); if (I915_HAS_FBC(dev) && i915_powersave) i915_cleanup_compression(dev); - drm_mm_takedown(&dev_priv->mm.vram); + drm_mm_takedown(&dev_priv->mm.stolen); intel_cleanup_overlay(dev); @@ -2188,7 +2133,7 @@ } if (dev_priv->regs != NULL) - iounmap(dev_priv->regs); + pci_iounmap(dev->pdev, dev_priv->regs); intel_teardown_gmbus(dev); intel_teardown_mchbar(dev); --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_drv.c +++ linux-2.6.37/drivers/gpu/drm/i915/i915_drv.c @@ -49,6 +49,9 @@ unsigned int i915_lvds_downclock = 0; module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); +bool i915_try_reset = true; +module_param_named(reset, i915_try_reset, bool, 0600); + static struct drm_driver driver; extern int intel_agp_enabled; @@ -111,7 +114,7 @@ static const struct intel_device_info intel_i965gm_info = { .gen = 4, .is_crestline = 1, - .is_mobile = 1, .has_fbc = 1, .has_rc6 = 1, .has_hotplug = 1, + .is_mobile = 1, .has_fbc = 1, .has_hotplug = 1, .has_overlay = 1, .supports_tv = 1, }; @@ -130,7 +133,7 @@ static const struct intel_device_info intel_gm45_info = { .gen = 4, .is_g4x = 1, - .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1, + .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, .supports_tv = 1, .has_bsd_ring = 1, @@ -150,7 +153,7 @@ static const struct intel_device_info intel_ironlake_m_info = { .gen = 5, .is_mobile = 1, - .need_gfx_hws = 1, .has_rc6 = 1, .has_hotplug = 1, + .need_gfx_hws = 1, .has_hotplug = 1, .has_fbc = 0, /* disabled due to buggy hardware */ .has_bsd_ring = 1, }; @@ -165,6 +168,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { .gen = 6, .is_mobile = 1, .need_gfx_hws = 1, .has_hotplug = 1, + .has_fbc = 1, .has_bsd_ring = 1, .has_blt_ring = 1, }; @@ -244,6 +248,28 @@ } } +void __gen6_force_wake_get(struct drm_i915_private *dev_priv) +{ + int count; + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1)) + udelay(10); + + I915_WRITE_NOTRACE(FORCEWAKE, 1); + POSTING_READ(FORCEWAKE); + + count = 0; + while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK) & 1) == 0) + udelay(10); +} + +void __gen6_force_wake_put(struct drm_i915_private *dev_priv) +{ + I915_WRITE_NOTRACE(FORCEWAKE, 0); + POSTING_READ(FORCEWAKE); +} + static int i915_drm_freeze(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -304,6 +330,12 @@ struct drm_i915_private *dev_priv = dev->dev_private; int error = 0; + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + mutex_lock(&dev->struct_mutex); + i915_gem_restore_gtt_mappings(dev); + mutex_unlock(&dev->struct_mutex); + } + i915_restore_state(dev); intel_opregion_setup(dev); @@ -405,6 +437,14 @@ return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500); } +static int gen6_do_reset(struct drm_device *dev, u8 flags) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + I915_WRITE(GEN6_GDRST, GEN6_GRDOM_FULL); + return wait_for((I915_READ(GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500); +} + /** * i965_reset - reset chip after a hang * @dev: drm device to reset @@ -431,7 +471,11 @@ bool need_display = true; int ret; - mutex_lock(&dev->struct_mutex); + if (!i915_try_reset) + return 0; + + if (!mutex_trylock(&dev->struct_mutex)) + return -EBUSY; i915_gem_reset(dev); @@ -439,6 +483,9 @@ if (get_seconds() - dev_priv->last_gpu_reset < 5) { DRM_ERROR("GPU hanging too fast, declaring wedged!\n"); } else switch (INTEL_INFO(dev)->gen) { + case 6: + ret = gen6_do_reset(dev, flags); + break; case 5: ret = ironlake_do_reset(dev, flags); break; @@ -472,9 +519,14 @@ */ if (drm_core_check_feature(dev, DRIVER_MODESET) || !dev_priv->mm.suspended) { - struct intel_ring_buffer *ring = &dev_priv->render_ring; dev_priv->mm.suspended = 0; - ring->init(dev, ring); + + dev_priv->ring[RCS].init(&dev_priv->ring[RCS]); + if (HAS_BSD(dev)) + dev_priv->ring[VCS].init(&dev_priv->ring[VCS]); + if (HAS_BLT(dev)) + dev_priv->ring[BCS].init(&dev_priv->ring[BCS]); + mutex_unlock(&dev->struct_mutex); drm_irq_uninstall(dev); drm_irq_install(dev); @@ -606,6 +658,8 @@ .device_is_agp = i915_driver_device_is_agp, .enable_vblank = i915_enable_vblank, .disable_vblank = i915_disable_vblank, + .get_vblank_timestamp = i915_get_vblank_timestamp, + .get_scanout_position = i915_get_crtc_scanoutpos, .irq_preinstall = i915_driver_irq_preinstall, .irq_postinstall = i915_driver_irq_postinstall, .irq_uninstall = i915_driver_irq_uninstall, @@ -661,8 +715,6 @@ driver.num_ioctls = i915_max_ioctl; - i915_gem_shrinker_init(); - /* * If CONFIG_DRM_I915_KMS is set, default to KMS unless * explicitly disabled with the module pararmeter. @@ -684,17 +736,11 @@ driver.driver_features &= ~DRIVER_MODESET; #endif - if (!(driver.driver_features & DRIVER_MODESET)) { - driver.suspend = i915_suspend; - driver.resume = i915_resume; - } - return drm_init(&driver); } static void __exit i915_exit(void) { - i915_gem_shrinker_exit(); drm_exit(&driver); } --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_drv.h +++ linux-2.6.37/drivers/gpu/drm/i915/i915_drv.h @@ -89,7 +89,7 @@ int id; struct page **page_list; drm_dma_handle_t *handle; - struct drm_gem_object *cur_obj; + struct drm_i915_gem_object *cur_obj; }; struct mem_block { @@ -124,9 +124,9 @@ #define I915_FENCE_REG_NONE -1 struct drm_i915_fence_reg { - struct drm_gem_object *obj; struct list_head lru_list; - bool gpu; + struct drm_i915_gem_object *obj; + uint32_t setup_seqno; }; struct sdvo_device_mapping { @@ -139,6 +139,8 @@ u8 ddc_pin; }; +struct intel_display_error_state; + struct drm_i915_error_state { u32 eir; u32 pgtbl_er; @@ -148,11 +150,23 @@ u32 ipehr; u32 instdone; u32 acthd; + u32 error; /* gen6+ */ + u32 bcs_acthd; /* gen6+ blt engine */ + u32 bcs_ipehr; + u32 bcs_ipeir; + u32 bcs_instdone; + u32 bcs_seqno; + u32 vcs_acthd; /* gen6+ bsd engine */ + u32 vcs_ipehr; + u32 vcs_ipeir; + u32 vcs_instdone; + u32 vcs_seqno; u32 instpm; u32 instps; u32 instdone1; u32 seqno; u64 bbaddr; + u64 fence[16]; struct timeval time; struct drm_i915_error_object { int page_count; @@ -171,9 +185,11 @@ u32 tiling:2; u32 dirty:1; u32 purgeable:1; - } *active_bo; - u32 active_bo_count; + u32 ring:4; + } *active_bo, *pinned_bo; + u32 active_bo_count, pinned_bo_count; struct intel_overlay_error_state *overlay; + struct intel_display_error_state *display; }; struct drm_i915_display_funcs { @@ -207,7 +223,6 @@ u8 is_broadwater : 1; u8 is_crestline : 1; u8 has_fbc : 1; - u8 has_rc6 : 1; u8 has_pipe_cxsr : 1; u8 has_hotplug : 1; u8 cursor_needs_physical : 1; @@ -243,6 +258,7 @@ const struct intel_device_info *info; int has_gem; + int relative_constants_mode; void __iomem *regs; @@ -253,20 +269,15 @@ } *gmbus; struct pci_dev *bridge_dev; - struct intel_ring_buffer render_ring; - struct intel_ring_buffer bsd_ring; - struct intel_ring_buffer blt_ring; + struct intel_ring_buffer ring[I915_NUM_RINGS]; uint32_t next_seqno; drm_dma_handle_t *status_page_dmah; - void *seqno_page; dma_addr_t dma_status_page; uint32_t counter; - unsigned int seqno_gfx_addr; drm_local_map_t hws_map; - struct drm_gem_object *seqno_obj; - struct drm_gem_object *pwrctx; - struct drm_gem_object *renderctx; + struct drm_i915_gem_object *pwrctx; + struct drm_i915_gem_object *renderctx; struct resource mch_res; @@ -275,25 +286,17 @@ int front_offset; int current_page; int page_flipping; -#define I915_DEBUG_READ (1<<0) -#define I915_DEBUG_WRITE (1<<1) - unsigned long debug_flags; - wait_queue_head_t irq_queue; atomic_t irq_received; - /** Protects user_irq_refcount and irq_mask_reg */ - spinlock_t user_irq_lock; u32 trace_irq_seqno; + + /* protects the irq masks */ + spinlock_t irq_lock; /** Cached value of IMR to avoid reads in updating the bitfield */ - u32 irq_mask_reg; u32 pipestat[2]; - /** splitted irq regs for graphics and display engine on Ironlake, - irq_mask_reg is still used for display irq. */ - u32 gt_irq_mask_reg; - u32 gt_irq_enable_reg; - u32 de_irq_enable_reg; - u32 pch_irq_mask_reg; - u32 pch_irq_enable_reg; + u32 irq_mask; + u32 gt_irq_mask; + u32 pch_irq_mask; u32 hotplug_supported_mask; struct work_struct hotplug_work; @@ -306,7 +309,7 @@ int num_pipe; /* For hangcheck timer */ -#define DRM_I915_HANGCHECK_PERIOD 250 /* in ms */ +#define DRM_I915_HANGCHECK_PERIOD 1500 /* in ms */ struct timer_list hangcheck_timer; int hangcheck_count; uint32_t last_acthd; @@ -530,23 +533,21 @@ struct { /** Bridge to intel-gtt-ko */ - struct intel_gtt *gtt; + const struct intel_gtt *gtt; /** Memory allocator for GTT stolen memory */ - struct drm_mm vram; + struct drm_mm stolen; /** Memory allocator for GTT */ struct drm_mm gtt_space; + /** List of all objects in gtt_space. Used to restore gtt + * mappings on resume */ + struct list_head gtt_list; + /** End of mappable part of GTT */ + unsigned long gtt_mappable_end; struct io_mapping *gtt_mapping; int gtt_mtrr; - /** - * Membership on list of all loaded devices, used to evict - * inactive buffers under memory pressure. - * - * Modifications should only be done whilst holding the - * shrink_list_lock spinlock. - */ - struct list_head shrink_list; + struct shrinker inactive_shrinker; /** * List of objects currently involved in rendering. @@ -609,16 +610,6 @@ struct delayed_work retire_work; /** - * Waiting sequence number, if any - */ - uint32_t waiting_gem_seqno; - - /** - * Last seq seen at irq time - */ - uint32_t irq_gem_seqno; - - /** * Flag if the X Server, and thus DRM, is not currently in * control of the device. * @@ -645,16 +636,11 @@ /* storage for physical objects */ struct drm_i915_gem_phys_object *phys_objs[I915_MAX_PHYS_OBJECT]; - uint32_t flush_rings; - /* accounting, useful for userland debugging */ - size_t object_memory; - size_t pin_memory; - size_t gtt_memory; size_t gtt_total; + size_t mappable_gtt_total; + size_t object_memory; u32 object_count; - u32 pin_count; - u32 gtt_count; } mm; struct sdvo_device_mapping sdvo_mappings[2]; /* indicate whether the LVDS_BORDER should be enabled or not */ @@ -688,14 +674,14 @@ u8 fmax; u8 fstart; - u64 last_count1; - unsigned long last_time1; - u64 last_count2; - struct timespec last_time2; - unsigned long gfx_power; - int c_m; - int r_t; - u8 corr; + u64 last_count1; + unsigned long last_time1; + u64 last_count2; + struct timespec last_time2; + unsigned long gfx_power; + int c_m; + int r_t; + u8 corr; spinlock_t *mchdev_lock; enum no_fbc_reason no_fbc_reason; @@ -709,20 +695,20 @@ struct intel_fbdev *fbdev; } drm_i915_private_t; -/** driver private structure attached to each drm_gem_object */ struct drm_i915_gem_object { struct drm_gem_object base; /** Current space allocated to this object in the GTT, if any. */ struct drm_mm_node *gtt_space; + struct list_head gtt_list; /** This object's place on the active/flushing/inactive lists */ struct list_head ring_list; struct list_head mm_list; /** This object's place on GPU write list */ struct list_head gpu_write_list; - /** This object's place on eviction list */ - struct list_head evict_list; + /** This object's place in the batchbuffer or on the eviction list */ + struct list_head exec_list; /** * This is set if the object is on the active or flushing lists @@ -738,6 +724,12 @@ unsigned int dirty : 1; /** + * This is set if the object has been written to since the last + * GPU flush. + */ + unsigned int pending_gpu_write : 1; + + /** * Fence register bits (if any) for this object. Will be set * as needed when mapped into the GTT. * Protected by dev->struct_mutex. @@ -747,29 +739,15 @@ signed int fence_reg : 5; /** - * Used for checking the object doesn't appear more than once - * in an execbuffer object list. - */ - unsigned int in_execbuffer : 1; - - /** * Advice: are the backing pages purgeable? */ unsigned int madv : 2; /** - * Refcount for the pages array. With the current locking scheme, there - * are at most two concurrent users: Binding a bo to the gtt and - * pwrite/pread using physical addresses. So two bits for a maximum - * of two users are enough. - */ - unsigned int pages_refcount : 2; -#define DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT 0x3 - - /** * Current tiling mode for the object. */ unsigned int tiling_mode : 2; + unsigned int tiling_changed : 1; /** How many users have pinned this object in GTT space. The following * users can each hold at most one reference: pwrite/pread, pin_ioctl @@ -783,28 +761,54 @@ unsigned int pin_count : 4; #define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf - /** AGP memory structure for our GTT binding. */ - DRM_AGP_MEM *agp_mem; + /** + * Is the object at the current location in the gtt mappable and + * fenceable? Used to avoid costly recalculations. + */ + unsigned int map_and_fenceable : 1; + + /** + * Whether the current gtt mapping needs to be mappable (and isn't just + * mappable by accident). Track pin and fault separate for a more + * accurate mappable working set. + */ + unsigned int fault_mappable : 1; + unsigned int pin_mappable : 1; + + /* + * Is the GPU currently using a fence to access this buffer, + */ + unsigned int pending_fenced_gpu_access:1; + unsigned int fenced_gpu_access:1; struct page **pages; /** - * Current offset of the object in GTT space. - * - * This is the same as gtt_space->start + * DMAR support */ - uint32_t gtt_offset; + struct scatterlist *sg_list; + int num_sg; - /* Which ring is refering to is this object */ - struct intel_ring_buffer *ring; + /** + * Used for performing relocations during execbuffer insertion. + */ + struct hlist_node exec_node; + unsigned long exec_handle; /** - * Fake offset for use by mmap(2) + * Current offset of the object in GTT space. + * + * This is the same as gtt_space->start */ - uint64_t mmap_offset; + uint32_t gtt_offset; /** Breadcrumb of last rendering to the buffer. */ uint32_t last_rendering_seqno; + struct intel_ring_buffer *ring; + + /** Breadcrumb of last fenced GPU access to the buffer. */ + uint32_t last_fenced_seqno; + struct intel_ring_buffer *last_fenced_ring; /** Current tiling stride for the object, if it's tiled. */ uint32_t stride; @@ -880,6 +884,68 @@ CHIP_I965 = 0x08, }; +#define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info) + +#define IS_I830(dev) ((dev)->pci_device == 0x3577) +#define IS_845G(dev) ((dev)->pci_device == 0x2562) +#define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x) +#define IS_I865G(dev) ((dev)->pci_device == 0x2572) +#define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g) +#define IS_I915GM(dev) ((dev)->pci_device == 0x2592) +#define IS_I945G(dev) ((dev)->pci_device == 0x2772) +#define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) +#define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater) +#define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) +#define IS_GM45(dev) ((dev)->pci_device == 0x2A42) +#define IS_G4X(dev) (INTEL_INFO(dev)->is_g4x) +#define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001) +#define IS_PINEVIEW_M(dev) ((dev)->pci_device == 0xa011) +#define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview) +#define IS_G33(dev) (INTEL_INFO(dev)->is_g33) +#define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042) +#define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) +#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) + +#define IS_GEN2(dev) (INTEL_INFO(dev)->gen == 2) +#define IS_GEN3(dev) (INTEL_INFO(dev)->gen == 3) +#define IS_GEN4(dev) (INTEL_INFO(dev)->gen == 4) +#define IS_GEN5(dev) (INTEL_INFO(dev)->gen == 5) +#define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6) + +#define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring) +#define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring) +#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) + +#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) +#define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) + +/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte + * rows, which changed the alignment requirements and fence programming. + */ +#define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \ + IS_I915GM(dev))) +#define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) +#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_GEN5(dev)) +#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_GEN5(dev)) +#define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev)) +#define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv) +#define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) +/* dsparb controlled by hw only */ +#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) + +#define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2) +#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) +#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) + +#define HAS_PCH_SPLIT(dev) (IS_GEN5(dev) || IS_GEN6(dev)) +#define HAS_PIPE_CONTROL(dev) (IS_GEN5(dev) || IS_GEN6(dev)) + +#define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) +#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) +#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) + +#include "i915_trace.h" + extern struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc; @@ -907,8 +973,8 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); extern int i915_emit_box(struct drm_device *dev, - struct drm_clip_rect *boxes, - int i, int DR1, int DR4); + struct drm_clip_rect *box, + int DR1, int DR4); extern int i915_reset(struct drm_device *dev, u8 flags); extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv); extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv); @@ -918,6 +984,7 @@ /* i915_irq.c */ void i915_hangcheck_elapsed(unsigned long data); +void i915_handle_error(struct drm_device *dev, bool wedged); extern int i915_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int i915_irq_wait(struct drm_device *dev, void *data, @@ -939,12 +1006,6 @@ extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc); extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask); -extern void i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask); -extern void ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv, - u32 mask); -extern void ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, - u32 mask); void i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); @@ -953,6 +1014,13 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); void intel_enable_asle (struct drm_device *dev); +int i915_get_vblank_timestamp(struct drm_device *dev, int crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags); + +int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, + int *vpos, int *hpos); #ifdef CONFIG_DEBUG_FS extern void i915_destroy_error_state(struct drm_device *dev); @@ -1017,15 +1085,28 @@ struct drm_file *file_priv); void i915_gem_load(struct drm_device *dev); int i915_gem_init_object(struct drm_gem_object *obj); -struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev, - size_t size); +void i915_gem_flush_ring(struct drm_device *dev, + struct intel_ring_buffer *ring, + uint32_t invalidate_domains, + uint32_t flush_domains); +struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, + size_t size); void i915_gem_free_object(struct drm_gem_object *obj); -int i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment); -void i915_gem_object_unpin(struct drm_gem_object *obj); -int i915_gem_object_unbind(struct drm_gem_object *obj); -void i915_gem_release_mmap(struct drm_gem_object *obj); +int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj, + uint32_t alignment, + bool map_and_fenceable); +void i915_gem_object_unpin(struct drm_i915_gem_object *obj); +int __must_check i915_gem_object_unbind(struct drm_i915_gem_object *obj); +void i915_gem_release_mmap(struct drm_i915_gem_object *obj); void i915_gem_lastclose(struct drm_device *dev); +int __must_check i915_mutex_lock_interruptible(struct drm_device *dev); +int __must_check i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, + bool interruptible); +void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *ring, + u32 seqno); + /** * Returns true if seq1 is later than seq2. */ @@ -1035,73 +1116,88 @@ return (int32_t)(seq1 - seq2) >= 0; } -int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, - bool interruptible); -int i915_gem_object_put_fence_reg(struct drm_gem_object *obj, - bool interruptible); +static inline u32 +i915_gem_next_request_seqno(struct drm_device *dev, + struct intel_ring_buffer *ring) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + return ring->outstanding_lazy_request = dev_priv->next_seqno; +} + +int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined, + bool interruptible); +int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj); + void i915_gem_retire_requests(struct drm_device *dev); void i915_gem_reset(struct drm_device *dev); -void i915_gem_clflush_object(struct drm_gem_object *obj); -int i915_gem_object_set_domain(struct drm_gem_object *obj, - uint32_t read_domains, - uint32_t write_domain); -int i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj, - bool interruptible); -int i915_gem_init_ringbuffer(struct drm_device *dev); +void i915_gem_clflush_object(struct drm_i915_gem_object *obj); +int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj, + uint32_t read_domains, + uint32_t write_domain); +int __must_check i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj, + bool interruptible); +int __must_check i915_gem_init_ringbuffer(struct drm_device *dev); void i915_gem_cleanup_ringbuffer(struct drm_device *dev); -int i915_gem_do_init(struct drm_device *dev, unsigned long start, - unsigned long end); -int i915_gpu_idle(struct drm_device *dev); -int i915_gem_idle(struct drm_device *dev); -uint32_t i915_add_request(struct drm_device *dev, - struct drm_file *file_priv, - struct drm_i915_gem_request *request, - struct intel_ring_buffer *ring); -int i915_do_wait_request(struct drm_device *dev, - uint32_t seqno, - bool interruptible, - struct intel_ring_buffer *ring); +void i915_gem_do_init(struct drm_device *dev, + unsigned long start, + unsigned long mappable_end, + unsigned long end); +int __must_check i915_gpu_idle(struct drm_device *dev); +int __must_check i915_gem_idle(struct drm_device *dev); +int __must_check i915_add_request(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_i915_gem_request *request, + struct intel_ring_buffer *ring); +int __must_check i915_do_wait_request(struct drm_device *dev, + uint32_t seqno, + bool interruptible, + struct intel_ring_buffer *ring); int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); -int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, - int write); -int i915_gem_object_set_to_display_plane(struct drm_gem_object *obj, - bool pipelined); +int __must_check +i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, + bool write); +int __must_check +i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined); int i915_gem_attach_phys_object(struct drm_device *dev, - struct drm_gem_object *obj, + struct drm_i915_gem_object *obj, int id, int align); void i915_gem_detach_phys_object(struct drm_device *dev, - struct drm_gem_object *obj); + struct drm_i915_gem_object *obj); void i915_gem_free_all_phys_object(struct drm_device *dev); -void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv); +void i915_gem_release(struct drm_device *dev, struct drm_file *file); -void i915_gem_shrinker_init(void); -void i915_gem_shrinker_exit(void); +/* i915_gem_gtt.c */ +void i915_gem_restore_gtt_mappings(struct drm_device *dev); +int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj); +void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj); /* i915_gem_evict.c */ -int i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignment); -int i915_gem_evict_everything(struct drm_device *dev); -int i915_gem_evict_inactive(struct drm_device *dev); +int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size, + unsigned alignment, bool mappable); +int __must_check i915_gem_evict_everything(struct drm_device *dev, + bool purgeable_only); +int __must_check i915_gem_evict_inactive(struct drm_device *dev, + bool purgeable_only); /* i915_gem_tiling.c */ void i915_gem_detect_bit_6_swizzle(struct drm_device *dev); -void i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj); -void i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj); -bool i915_tiling_ok(struct drm_device *dev, int stride, int size, - int tiling_mode); -bool i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, - int tiling_mode); +void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj); +void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj); /* i915_gem_debug.c */ -void i915_gem_dump_object(struct drm_gem_object *obj, int len, +void i915_gem_dump_object(struct drm_i915_gem_object *obj, int len, const char *where, uint32_t mark); #if WATCH_LISTS int i915_verify_lists(struct drm_device *dev); #else #define i915_verify_lists(dev) 0 #endif -void i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle); -void i915_gem_dump_object(struct drm_gem_object *obj, int len, +void i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, + int handle); +void i915_gem_dump_object(struct drm_i915_gem_object *obj, int len, const char *where, uint32_t mark); /* i915_debugfs.c */ @@ -1163,6 +1259,7 @@ extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval); extern bool intel_fbc_enabled(struct drm_device *dev); extern bool ironlake_set_drps(struct drm_device *dev, u8 val); +extern void gen6_set_rps(struct drm_device *dev, u8 val); extern void intel_detect_pch (struct drm_device *dev); extern int intel_trans_dp_port_sel (struct drm_crtc *crtc); @@ -1170,79 +1267,120 @@ #ifdef CONFIG_DEBUG_FS extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); extern void intel_overlay_print_error_state(struct seq_file *m, struct intel_overlay_error_state *error); + +extern struct intel_display_error_state *intel_display_capture_error_state(struct drm_device *dev); +extern void intel_display_print_error_state(struct seq_file *m, + struct drm_device *dev, + struct intel_display_error_state *error); #endif +#define LP_RING(d) (&((struct drm_i915_private *)(d))->ring[RCS]) + +#define BEGIN_LP_RING(n) \ + intel_ring_begin(LP_RING(dev_priv), (n)) + +#define OUT_RING(x) \ + intel_ring_emit(LP_RING(dev_priv), x) + +#define ADVANCE_LP_RING() \ + intel_ring_advance(LP_RING(dev_priv)) + /** * Lock test for when it's just for synchronization of ring access. * * In that case, we don't need to do it when GEM is initialized as nobody else * has access to the ring. */ -#define RING_LOCK_TEST_WITH_RETURN(dev, file_priv) do { \ - if (((drm_i915_private_t *)dev->dev_private)->render_ring.gem_object \ - == NULL) \ - LOCK_TEST_WITH_RETURN(dev, file_priv); \ +#define RING_LOCK_TEST_WITH_RETURN(dev, file) do { \ + if (LP_RING(dev->dev_private)->obj == NULL) \ + LOCK_TEST_WITH_RETURN(dev, file); \ } while (0) -static inline u32 i915_read(struct drm_i915_private *dev_priv, u32 reg) + +#define __i915_read(x, y) \ +static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ + u##x val = read##y(dev_priv->regs + reg); \ + trace_i915_reg_rw('R', reg, val, sizeof(val)); \ + return val; \ +} +__i915_read(8, b) +__i915_read(16, w) +__i915_read(32, l) +__i915_read(64, q) +#undef __i915_read + +#define __i915_write(x, y) \ +static inline void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ + trace_i915_reg_rw('W', reg, val, sizeof(val)); \ + write##y(val, dev_priv->regs + reg); \ +} +__i915_write(8, b) +__i915_write(16, w) +__i915_write(32, l) +__i915_write(64, q) +#undef __i915_write + +#define I915_READ8(reg) i915_read8(dev_priv, (reg)) +#define I915_WRITE8(reg, val) i915_write8(dev_priv, (reg), (val)) + +#define I915_READ16(reg) i915_read16(dev_priv, (reg)) +#define I915_WRITE16(reg, val) i915_write16(dev_priv, (reg), (val)) +#define I915_READ16_NOTRACE(reg) readw(dev_priv->regs + (reg)) +#define I915_WRITE16_NOTRACE(reg, val) writew(val, dev_priv->regs + (reg)) + +#define I915_READ(reg) i915_read32(dev_priv, (reg)) +#define I915_WRITE(reg, val) i915_write32(dev_priv, (reg), (val)) +#define I915_READ_NOTRACE(reg) readl(dev_priv->regs + (reg)) +#define I915_WRITE_NOTRACE(reg, val) writel(val, dev_priv->regs + (reg)) + +#define I915_WRITE64(reg, val) i915_write64(dev_priv, (reg), (val)) +#define I915_READ64(reg) i915_read64(dev_priv, (reg)) + +#define POSTING_READ(reg) (void)I915_READ_NOTRACE(reg) +#define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg) + + +/* On SNB platform, before reading ring registers forcewake bit + * must be set to prevent GT core from power down and stale values being + * returned. + */ +void __gen6_force_wake_get(struct drm_i915_private *dev_priv); +void __gen6_force_wake_put (struct drm_i915_private *dev_priv); +static inline u32 i915_safe_read(struct drm_i915_private *dev_priv, u32 reg) { u32 val; - val = readl(dev_priv->regs + reg); - if (dev_priv->debug_flags & I915_DEBUG_READ) - printk(KERN_ERR "read 0x%08x from 0x%08x\n", val, reg); + if (dev_priv->info->gen >= 6) { + __gen6_force_wake_get(dev_priv); + val = I915_READ(reg); + __gen6_force_wake_put(dev_priv); + } else + val = I915_READ(reg); + return val; } -static inline void i915_write(struct drm_i915_private *dev_priv, u32 reg, - u32 val) +static inline void +i915_write(struct drm_i915_private *dev_priv, u32 reg, u64 val, int len) { - writel(val, dev_priv->regs + reg); - if (dev_priv->debug_flags & I915_DEBUG_WRITE) - printk(KERN_ERR "wrote 0x%08x to 0x%08x\n", val, reg); + /* Trace down the write operation before the real write */ + trace_i915_reg_rw('W', reg, val, len); + switch (len) { + case 8: + writeq(val, dev_priv->regs + reg); + break; + case 4: + writel(val, dev_priv->regs + reg); + break; + case 2: + writew(val, dev_priv->regs + reg); + break; + case 1: + writeb(val, dev_priv->regs + reg); + break; + } } -#define I915_READ(reg) i915_read(dev_priv, (reg)) -#define I915_WRITE(reg, val) i915_write(dev_priv, (reg), (val)) -#define I915_READ16(reg) readw(dev_priv->regs + (reg)) -#define I915_WRITE16(reg, val) writel(val, dev_priv->regs + (reg)) -#define I915_READ8(reg) readb(dev_priv->regs + (reg)) -#define I915_WRITE8(reg, val) writeb(val, dev_priv->regs + (reg)) -#define I915_WRITE64(reg, val) writeq(val, dev_priv->regs + (reg)) -#define I915_READ64(reg) readq(dev_priv->regs + (reg)) -#define POSTING_READ(reg) (void)I915_READ(reg) -#define POSTING_READ16(reg) (void)I915_READ16(reg) - -#define I915_DEBUG_ENABLE_IO() (dev_priv->debug_flags |= I915_DEBUG_READ | \ - I915_DEBUG_WRITE) -#define I915_DEBUG_DISABLE_IO() (dev_priv->debug_flags &= ~(I915_DEBUG_READ | \ - I915_DEBUG_WRITE)) - -#define I915_VERBOSE 0 - -#define BEGIN_LP_RING(n) do { \ - drm_i915_private_t *dev_priv__ = dev->dev_private; \ - if (I915_VERBOSE) \ - DRM_DEBUG(" BEGIN_LP_RING %x\n", (int)(n)); \ - intel_ring_begin(dev, &dev_priv__->render_ring, (n)); \ -} while (0) - - -#define OUT_RING(x) do { \ - drm_i915_private_t *dev_priv__ = dev->dev_private; \ - if (I915_VERBOSE) \ - DRM_DEBUG(" OUT_RING %x\n", (int)(x)); \ - intel_ring_emit(dev, &dev_priv__->render_ring, x); \ -} while (0) - -#define ADVANCE_LP_RING() do { \ - drm_i915_private_t *dev_priv__ = dev->dev_private; \ - if (I915_VERBOSE) \ - DRM_DEBUG("ADVANCE_LP_RING %x\n", \ - dev_priv__->render_ring.tail); \ - intel_ring_advance(dev, &dev_priv__->render_ring); \ -} while(0) - /** * Reads a dword out of the status page, which is written to from the command * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or @@ -1259,72 +1397,9 @@ * The area from dword 0x20 to 0x3ff is available for driver usage. */ #define READ_HWSP(dev_priv, reg) (((volatile u32 *)\ - (dev_priv->render_ring.status_page.page_addr))[reg]) + (LP_RING(dev_priv)->status_page.page_addr))[reg]) #define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX) #define I915_GEM_HWS_INDEX 0x20 #define I915_BREADCRUMB_INDEX 0x21 -#define INTEL_INFO(dev) (((struct drm_i915_private *) (dev)->dev_private)->info) - -#define IS_I830(dev) ((dev)->pci_device == 0x3577) -#define IS_845G(dev) ((dev)->pci_device == 0x2562) -#define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x) -#define IS_I865G(dev) ((dev)->pci_device == 0x2572) -#define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g) -#define IS_I915GM(dev) ((dev)->pci_device == 0x2592) -#define IS_I945G(dev) ((dev)->pci_device == 0x2772) -#define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) -#define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater) -#define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) -#define IS_GM45(dev) ((dev)->pci_device == 0x2A42) -#define IS_G4X(dev) (INTEL_INFO(dev)->is_g4x) -#define IS_PINEVIEW_G(dev) ((dev)->pci_device == 0xa001) -#define IS_PINEVIEW_M(dev) ((dev)->pci_device == 0xa011) -#define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview) -#define IS_G33(dev) (INTEL_INFO(dev)->is_g33) -#define IS_IRONLAKE_D(dev) ((dev)->pci_device == 0x0042) -#define IS_IRONLAKE_M(dev) ((dev)->pci_device == 0x0046) -#define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) - -#define IS_GEN2(dev) (INTEL_INFO(dev)->gen == 2) -#define IS_GEN3(dev) (INTEL_INFO(dev)->gen == 3) -#define IS_GEN4(dev) (INTEL_INFO(dev)->gen == 4) -#define IS_GEN5(dev) (INTEL_INFO(dev)->gen == 5) -#define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6) - -#define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring) -#define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring) -#define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) - -#define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) -#define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) - -/* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte - * rows, which changed the alignment requirements and fence programming. - */ -#define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \ - IS_I915GM(dev))) -#define SUPPORTS_DIGITAL_OUTPUTS(dev) (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) -#define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_GEN5(dev)) -#define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_GEN5(dev)) -#define SUPPORTS_EDP(dev) (IS_IRONLAKE_M(dev)) -#define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv) -#define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) -/* dsparb controlled by hw only */ -#define DSPARB_HWCONTROL(dev) (IS_G4X(dev) || IS_IRONLAKE(dev)) - -#define HAS_FW_BLC(dev) (INTEL_INFO(dev)->gen > 2) -#define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) -#define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) -#define I915_HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) - -#define HAS_PCH_SPLIT(dev) (IS_GEN5(dev) || IS_GEN6(dev)) -#define HAS_PIPE_CONTROL(dev) (IS_GEN5(dev) || IS_GEN6(dev)) - -#define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) -#define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) -#define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) - -#define PRIMARY_RINGBUFFER_SIZE (128*1024) - #endif --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_gem.c +++ linux-2.6.37/drivers/gpu/drm/i915/i915_gem.c @@ -34,38 +34,31 @@ #include #include #include -#include -static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); - -static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); -static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); -static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); -static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, - int write); -static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, +static void i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj); +static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj); +static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj); +static int i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, + bool write); +static int i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj, uint64_t offset, uint64_t size); -static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj); -static int i915_gem_object_wait_rendering(struct drm_gem_object *obj, - bool interruptible); -static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, - unsigned alignment); -static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); -static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, +static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_i915_gem_object *obj); +static int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, + unsigned alignment, + bool map_and_fenceable); +static void i915_gem_clear_fence_reg(struct drm_device *dev, + struct drm_i915_fence_reg *reg); +static int i915_gem_phys_pwrite(struct drm_device *dev, + struct drm_i915_gem_object *obj, struct drm_i915_gem_pwrite *args, - struct drm_file *file_priv); -static void i915_gem_free_object_tail(struct drm_gem_object *obj); - -static int -i915_gem_object_get_pages(struct drm_gem_object *obj, - gfp_t gfpmask); + struct drm_file *file); +static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj); -static void -i915_gem_object_put_pages(struct drm_gem_object *obj); +static int i915_gem_inactive_shrink(struct shrinker *shrinker, + int nr_to_scan, + gfp_t gfp_mask); -static LIST_HEAD(shrink_list); -static DEFINE_SPINLOCK(shrink_list_lock); /* some bookkeeping */ static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv, @@ -82,34 +75,6 @@ dev_priv->mm.object_memory -= size; } -static void i915_gem_info_add_gtt(struct drm_i915_private *dev_priv, - size_t size) -{ - dev_priv->mm.gtt_count++; - dev_priv->mm.gtt_memory += size; -} - -static void i915_gem_info_remove_gtt(struct drm_i915_private *dev_priv, - size_t size) -{ - dev_priv->mm.gtt_count--; - dev_priv->mm.gtt_memory -= size; -} - -static void i915_gem_info_add_pin(struct drm_i915_private *dev_priv, - size_t size) -{ - dev_priv->mm.pin_count++; - dev_priv->mm.pin_memory += size; -} - -static void i915_gem_info_remove_pin(struct drm_i915_private *dev_priv, - size_t size) -{ - dev_priv->mm.pin_count--; - dev_priv->mm.pin_memory -= size; -} - int i915_gem_check_is_wedged(struct drm_device *dev) { @@ -140,7 +105,7 @@ return -EIO; } -static int i915_mutex_lock_interruptible(struct drm_device *dev) +int i915_mutex_lock_interruptible(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; int ret; @@ -163,75 +128,76 @@ } static inline bool -i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv) +i915_gem_object_is_inactive(struct drm_i915_gem_object *obj) { - return obj_priv->gtt_space && - !obj_priv->active && - obj_priv->pin_count == 0; + return obj->gtt_space && !obj->active && obj->pin_count == 0; } -int i915_gem_do_init(struct drm_device *dev, - unsigned long start, - unsigned long end) +void i915_gem_do_init(struct drm_device *dev, + unsigned long start, + unsigned long mappable_end, + unsigned long end) { drm_i915_private_t *dev_priv = dev->dev_private; - if (start >= end || - (start & (PAGE_SIZE - 1)) != 0 || - (end & (PAGE_SIZE - 1)) != 0) { - return -EINVAL; - } - drm_mm_init(&dev_priv->mm.gtt_space, start, end - start); dev_priv->mm.gtt_total = end - start; - - return 0; + dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start; + dev_priv->mm.gtt_mappable_end = mappable_end; } int i915_gem_init_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { struct drm_i915_gem_init *args = data; - int ret; + + if (args->gtt_start >= args->gtt_end || + (args->gtt_end | args->gtt_start) & (PAGE_SIZE - 1)) + return -EINVAL; mutex_lock(&dev->struct_mutex); - ret = i915_gem_do_init(dev, args->gtt_start, args->gtt_end); + i915_gem_do_init(dev, args->gtt_start, args->gtt_end, args->gtt_end); mutex_unlock(&dev->struct_mutex); - return ret; + return 0; } int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_get_aperture *args = data; + struct drm_i915_gem_object *obj; + size_t pinned; if (!(dev->driver->driver_features & DRIVER_GEM)) return -ENODEV; + pinned = 0; mutex_lock(&dev->struct_mutex); - args->aper_size = dev_priv->mm.gtt_total; - args->aper_available_size = args->aper_size - dev_priv->mm.pin_memory; + list_for_each_entry(obj, &dev_priv->mm.pinned_list, mm_list) + pinned += obj->gtt_space->size; mutex_unlock(&dev->struct_mutex); + args->aper_size = dev_priv->mm.gtt_total; + args->aper_available_size = args->aper_size -pinned; + return 0; } - /** * Creates a new mm object and returns a handle to it. */ int i915_gem_create_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { struct drm_i915_gem_create *args = data; - struct drm_gem_object *obj; + struct drm_i915_gem_object *obj; int ret; u32 handle; @@ -242,45 +208,28 @@ if (obj == NULL) return -ENOMEM; - ret = drm_gem_handle_create(file_priv, obj, &handle); + ret = drm_gem_handle_create(file, &obj->base, &handle); if (ret) { - drm_gem_object_release(obj); - i915_gem_info_remove_obj(dev->dev_private, obj->size); + drm_gem_object_release(&obj->base); + i915_gem_info_remove_obj(dev->dev_private, obj->base.size); kfree(obj); return ret; } /* drop reference from allocate - handle holds it now */ - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); trace_i915_gem_object_create(obj); args->handle = handle; return 0; } -static inline int -fast_shmem_read(struct page **pages, - loff_t page_base, int page_offset, - char __user *data, - int length) -{ - char *vaddr; - int ret; - - vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]); - ret = __copy_to_user_inatomic(data, vaddr + page_offset, length); - kunmap_atomic(vaddr); - - return ret; -} - -static int i915_gem_object_needs_bit17_swizzle(struct drm_gem_object *obj) +static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj) { - drm_i915_private_t *dev_priv = obj->dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + drm_i915_private_t *dev_priv = obj->base.dev->dev_private; return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 && - obj_priv->tiling_mode != I915_TILING_NONE; + obj->tiling_mode != I915_TILING_NONE; } static inline void @@ -356,38 +305,51 @@ * fault, it fails so we can fall back to i915_gem_shmem_pwrite_slow(). */ static int -i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj, +i915_gem_shmem_pread_fast(struct drm_device *dev, + struct drm_i915_gem_object *obj, struct drm_i915_gem_pread *args, - struct drm_file *file_priv) + struct drm_file *file) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; ssize_t remain; - loff_t offset, page_base; + loff_t offset; char __user *user_data; int page_offset, page_length; user_data = (char __user *) (uintptr_t) args->data_ptr; remain = args->size; - obj_priv = to_intel_bo(obj); offset = args->offset; while (remain > 0) { + struct page *page; + char *vaddr; + int ret; + /* Operation in this page * - * page_base = page offset within aperture * page_offset = offset within page * page_length = bytes to copy for this page */ - page_base = (offset & ~(PAGE_SIZE-1)); page_offset = offset & (PAGE_SIZE-1); page_length = remain; if ((page_offset + remain) > PAGE_SIZE) page_length = PAGE_SIZE - page_offset; - if (fast_shmem_read(obj_priv->pages, - page_base, page_offset, - user_data, page_length)) + page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, + GFP_HIGHUSER | __GFP_RECLAIMABLE); + if (IS_ERR(page)) + return PTR_ERR(page); + + vaddr = kmap_atomic(page); + ret = __copy_to_user_inatomic(user_data, + vaddr + page_offset, + page_length); + kunmap_atomic(vaddr); + + mark_page_accessed(page); + page_cache_release(page); + if (ret) return -EFAULT; remain -= page_length; @@ -398,30 +360,6 @@ return 0; } -static int -i915_gem_object_get_pages_or_evict(struct drm_gem_object *obj) -{ - int ret; - - ret = i915_gem_object_get_pages(obj, __GFP_NORETRY | __GFP_NOWARN); - - /* If we've insufficient memory to map in the pages, attempt - * to make some space by throwing out some old buffers. - */ - if (ret == -ENOMEM) { - struct drm_device *dev = obj->dev; - - ret = i915_gem_evict_something(dev, obj->size, - i915_gem_get_gtt_alignment(obj)); - if (ret) - return ret; - - ret = i915_gem_object_get_pages(obj, 0); - } - - return ret; -} - /** * This is the fallback shmem pread path, which allocates temporary storage * in kernel space to copy_to_user into outside of the struct_mutex, so we @@ -429,18 +367,19 @@ * and not take page faults. */ static int -i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj, +i915_gem_shmem_pread_slow(struct drm_device *dev, + struct drm_i915_gem_object *obj, struct drm_i915_gem_pread *args, - struct drm_file *file_priv) + struct drm_file *file) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; struct mm_struct *mm = current->mm; struct page **user_pages; ssize_t remain; loff_t offset, pinned_pages, i; loff_t first_data_page, last_data_page, num_pages; - int shmem_page_index, shmem_page_offset; - int data_page_index, data_page_offset; + int shmem_page_offset; + int data_page_index, data_page_offset; int page_length; int ret; uint64_t data_ptr = args->data_ptr; @@ -479,19 +418,18 @@ do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); - obj_priv = to_intel_bo(obj); offset = args->offset; while (remain > 0) { + struct page *page; + /* Operation in this page * - * shmem_page_index = page number within shmem file * shmem_page_offset = offset within page in shmem file * data_page_index = page number in get_user_pages return * data_page_offset = offset with data_page_index page. * page_length = bytes to copy for this page */ - shmem_page_index = offset / PAGE_SIZE; shmem_page_offset = offset & ~PAGE_MASK; data_page_index = data_ptr / PAGE_SIZE - first_data_page; data_page_offset = data_ptr & ~PAGE_MASK; @@ -502,8 +440,13 @@ if ((data_page_offset + page_length) > PAGE_SIZE) page_length = PAGE_SIZE - data_page_offset; + page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, + GFP_HIGHUSER | __GFP_RECLAIMABLE); + if (IS_ERR(page)) + return PTR_ERR(page); + if (do_bit17_swizzling) { - slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index], + slow_shmem_bit17_copy(page, shmem_page_offset, user_pages[data_page_index], data_page_offset, @@ -512,11 +455,14 @@ } else { slow_shmem_copy(user_pages[data_page_index], data_page_offset, - obj_priv->pages[shmem_page_index], + page, shmem_page_offset, page_length); } + mark_page_accessed(page); + page_cache_release(page); + remain -= page_length; data_ptr += page_length; offset += page_length; @@ -525,6 +471,7 @@ out: for (i = 0; i < pinned_pages; i++) { SetPageDirty(user_pages[i]); + mark_page_accessed(user_pages[i]); page_cache_release(user_pages[i]); } drm_free_large(user_pages); @@ -539,11 +486,10 @@ */ int i915_gem_pread_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { struct drm_i915_gem_pread *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int ret = 0; if (args->size == 0) @@ -563,39 +509,33 @@ if (ret) return ret; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (obj == NULL) { ret = -ENOENT; goto unlock; } - obj_priv = to_intel_bo(obj); /* Bounds check source. */ - if (args->offset > obj->size || args->size > obj->size - args->offset) { + if (args->offset > obj->base.size || + args->size > obj->base.size - args->offset) { ret = -EINVAL; goto out; } - ret = i915_gem_object_get_pages_or_evict(obj); - if (ret) - goto out; - ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset, args->size); if (ret) - goto out_put; + goto out; ret = -EFAULT; if (!i915_gem_object_needs_bit17_swizzle(obj)) - ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv); + ret = i915_gem_shmem_pread_fast(dev, obj, args, file); if (ret == -EFAULT) - ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv); + ret = i915_gem_shmem_pread_slow(dev, obj, args, file); -out_put: - i915_gem_object_put_pages(obj); out: - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); unlock: mutex_unlock(&dev->struct_mutex); return ret; @@ -645,32 +585,16 @@ io_mapping_unmap(dst_vaddr); } -static inline int -fast_shmem_write(struct page **pages, - loff_t page_base, int page_offset, - char __user *data, - int length) -{ - char *vaddr; - int ret; - - vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]); - ret = __copy_from_user_inatomic(vaddr + page_offset, data, length); - kunmap_atomic(vaddr); - - return ret; -} - /** * This is the fast pwrite path, where we copy the data directly from the * user into the GTT, uncached. */ static int -i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, +i915_gem_gtt_pwrite_fast(struct drm_device *dev, + struct drm_i915_gem_object *obj, struct drm_i915_gem_pwrite *args, - struct drm_file *file_priv) + struct drm_file *file) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); drm_i915_private_t *dev_priv = dev->dev_private; ssize_t remain; loff_t offset, page_base; @@ -680,8 +604,7 @@ user_data = (char __user *) (uintptr_t) args->data_ptr; remain = args->size; - obj_priv = to_intel_bo(obj); - offset = obj_priv->gtt_offset + args->offset; + offset = obj->gtt_offset + args->offset; while (remain > 0) { /* Operation in this page @@ -721,11 +644,11 @@ * than using i915_gem_gtt_pwrite_fast on a G45 (32-bit). */ static int -i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, +i915_gem_gtt_pwrite_slow(struct drm_device *dev, + struct drm_i915_gem_object *obj, struct drm_i915_gem_pwrite *args, - struct drm_file *file_priv) + struct drm_file *file) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); drm_i915_private_t *dev_priv = dev->dev_private; ssize_t remain; loff_t gtt_page_base, offset; @@ -762,12 +685,15 @@ goto out_unpin_pages; } - ret = i915_gem_object_set_to_gtt_domain(obj, 1); + ret = i915_gem_object_set_to_gtt_domain(obj, true); + if (ret) + goto out_unpin_pages; + + ret = i915_gem_object_put_fence(obj); if (ret) goto out_unpin_pages; - obj_priv = to_intel_bo(obj); - offset = obj_priv->gtt_offset + args->offset; + offset = obj->gtt_offset + args->offset; while (remain > 0) { /* Operation in this page @@ -813,39 +739,58 @@ * copy_from_user into the kmapped pages backing the object. */ static int -i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, +i915_gem_shmem_pwrite_fast(struct drm_device *dev, + struct drm_i915_gem_object *obj, struct drm_i915_gem_pwrite *args, - struct drm_file *file_priv) + struct drm_file *file) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; ssize_t remain; - loff_t offset, page_base; + loff_t offset; char __user *user_data; int page_offset, page_length; user_data = (char __user *) (uintptr_t) args->data_ptr; remain = args->size; - obj_priv = to_intel_bo(obj); offset = args->offset; - obj_priv->dirty = 1; + obj->dirty = 1; while (remain > 0) { + struct page *page; + char *vaddr; + int ret; + /* Operation in this page * - * page_base = page offset within aperture * page_offset = offset within page * page_length = bytes to copy for this page */ - page_base = (offset & ~(PAGE_SIZE-1)); page_offset = offset & (PAGE_SIZE-1); page_length = remain; if ((page_offset + remain) > PAGE_SIZE) page_length = PAGE_SIZE - page_offset; - if (fast_shmem_write(obj_priv->pages, - page_base, page_offset, - user_data, page_length)) + page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, + GFP_HIGHUSER | __GFP_RECLAIMABLE); + if (IS_ERR(page)) + return PTR_ERR(page); + + vaddr = kmap_atomic(page, KM_USER0); + ret = __copy_from_user_inatomic(vaddr + page_offset, + user_data, + page_length); + kunmap_atomic(vaddr, KM_USER0); + + set_page_dirty(page); + mark_page_accessed(page); + page_cache_release(page); + + /* If we get a fault while copying data, then (presumably) our + * source page isn't available. Return the error and we'll + * retry in the slow path. + */ + if (ret) return -EFAULT; remain -= page_length; @@ -864,17 +809,18 @@ * struct_mutex is held. */ static int -i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, +i915_gem_shmem_pwrite_slow(struct drm_device *dev, + struct drm_i915_gem_object *obj, struct drm_i915_gem_pwrite *args, - struct drm_file *file_priv) + struct drm_file *file) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; struct mm_struct *mm = current->mm; struct page **user_pages; ssize_t remain; loff_t offset, pinned_pages, i; loff_t first_data_page, last_data_page, num_pages; - int shmem_page_index, shmem_page_offset; + int shmem_page_offset; int data_page_index, data_page_offset; int page_length; int ret; @@ -912,20 +858,19 @@ do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); - obj_priv = to_intel_bo(obj); offset = args->offset; - obj_priv->dirty = 1; + obj->dirty = 1; while (remain > 0) { + struct page *page; + /* Operation in this page * - * shmem_page_index = page number within shmem file * shmem_page_offset = offset within page in shmem file * data_page_index = page number in get_user_pages return * data_page_offset = offset with data_page_index page. * page_length = bytes to copy for this page */ - shmem_page_index = offset / PAGE_SIZE; shmem_page_offset = offset & ~PAGE_MASK; data_page_index = data_ptr / PAGE_SIZE - first_data_page; data_page_offset = data_ptr & ~PAGE_MASK; @@ -936,21 +881,32 @@ if ((data_page_offset + page_length) > PAGE_SIZE) page_length = PAGE_SIZE - data_page_offset; + page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, + GFP_HIGHUSER | __GFP_RECLAIMABLE); + if (IS_ERR(page)) { + ret = PTR_ERR(page); + goto out; + } + if (do_bit17_swizzling) { - slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index], + slow_shmem_bit17_copy(page, shmem_page_offset, user_pages[data_page_index], data_page_offset, page_length, 0); } else { - slow_shmem_copy(obj_priv->pages[shmem_page_index], + slow_shmem_copy(page, shmem_page_offset, user_pages[data_page_index], data_page_offset, page_length); } + set_page_dirty(page); + mark_page_accessed(page); + page_cache_release(page); + remain -= page_length; data_ptr += page_length; offset += page_length; @@ -974,8 +930,7 @@ struct drm_file *file) { struct drm_i915_gem_pwrite *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int ret; if (args->size == 0) @@ -995,15 +950,15 @@ if (ret) return ret; - obj = drm_gem_object_lookup(dev, file, args->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (obj == NULL) { ret = -ENOENT; goto unlock; } - obj_priv = to_intel_bo(obj); /* Bounds check destination. */ - if (args->offset > obj->size || args->size > obj->size - args->offset) { + if (args->offset > obj->base.size || + args->size > obj->base.size - args->offset) { ret = -EINVAL; goto out; } @@ -1014,16 +969,19 @@ * pread/pwrite currently are reading and writing from the CPU * perspective, requiring manual detiling by the client. */ - if (obj_priv->phys_obj) + if (obj->phys_obj) ret = i915_gem_phys_pwrite(dev, obj, args, file); - else if (obj_priv->tiling_mode == I915_TILING_NONE && - obj_priv->gtt_space && - obj->write_domain != I915_GEM_DOMAIN_CPU) { - ret = i915_gem_object_pin(obj, 0); + else if (obj->gtt_space && + obj->base.write_domain != I915_GEM_DOMAIN_CPU) { + ret = i915_gem_object_pin(obj, 0, true); if (ret) goto out; - ret = i915_gem_object_set_to_gtt_domain(obj, 1); + ret = i915_gem_object_set_to_gtt_domain(obj, true); + if (ret) + goto out_unpin; + + ret = i915_gem_object_put_fence(obj); if (ret) goto out_unpin; @@ -1034,26 +992,19 @@ out_unpin: i915_gem_object_unpin(obj); } else { - ret = i915_gem_object_get_pages_or_evict(obj); - if (ret) - goto out; - ret = i915_gem_object_set_to_cpu_domain(obj, 1); if (ret) - goto out_put; + goto out; ret = -EFAULT; if (!i915_gem_object_needs_bit17_swizzle(obj)) ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file); if (ret == -EFAULT) ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file); - -out_put: - i915_gem_object_put_pages(obj); } out: - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); unlock: mutex_unlock(&dev->struct_mutex); return ret; @@ -1065,12 +1016,10 @@ */ int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_set_domain *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; uint32_t read_domains = args->read_domains; uint32_t write_domain = args->write_domain; int ret; @@ -1095,28 +1044,15 @@ if (ret) return ret; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (obj == NULL) { ret = -ENOENT; goto unlock; } - obj_priv = to_intel_bo(obj); - - intel_mark_busy(dev, obj); if (read_domains & I915_GEM_DOMAIN_GTT) { ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); - /* Update the LRU on the fence for the CPU access that's - * about to occur. - */ - if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { - struct drm_i915_fence_reg *reg = - &dev_priv->fence_regs[obj_priv->fence_reg]; - list_move_tail(®->lru_list, - &dev_priv->mm.fence_list); - } - /* Silently promote "you're not bound, there was nothing to do" * to success, since the client was just asking us to * make sure everything was done. @@ -1127,11 +1063,7 @@ ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0); } - /* Maintain LRU order of "inactive" objects */ - if (ret == 0 && i915_gem_object_is_inactive(obj_priv)) - list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); - - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); unlock: mutex_unlock(&dev->struct_mutex); return ret; @@ -1142,10 +1074,10 @@ */ int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { struct drm_i915_gem_sw_finish *args = data; - struct drm_gem_object *obj; + struct drm_i915_gem_object *obj; int ret = 0; if (!(dev->driver->driver_features & DRIVER_GEM)) @@ -1155,17 +1087,17 @@ if (ret) return ret; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (obj == NULL) { ret = -ENOENT; goto unlock; } /* Pinned buffers may be scanout, so flush the cache */ - if (to_intel_bo(obj)->pin_count) + if (obj->pin_count) i915_gem_object_flush_cpu_write_domain(obj); - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); unlock: mutex_unlock(&dev->struct_mutex); return ret; @@ -1180,8 +1112,9 @@ */ int i915_gem_mmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_mmap *args = data; struct drm_gem_object *obj; loff_t offset; @@ -1190,10 +1123,15 @@ if (!(dev->driver->driver_features & DRIVER_GEM)) return -ENODEV; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = drm_gem_object_lookup(dev, file, args->handle); if (obj == NULL) return -ENOENT; + if (obj->size > dev_priv->mm.gtt_mappable_end) { + drm_gem_object_unreference_unlocked(obj); + return -E2BIG; + } + offset = args->offset; down_write(¤t->mm->mmap_sem); @@ -1228,10 +1166,9 @@ */ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { - struct drm_gem_object *obj = vma->vm_private_data; - struct drm_device *dev = obj->dev; + struct drm_i915_gem_object *obj = to_intel_bo(vma->vm_private_data); + struct drm_device *dev = obj->base.dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); pgoff_t page_offset; unsigned long pfn; int ret = 0; @@ -1243,27 +1180,35 @@ /* Now bind it into the GTT if needed */ mutex_lock(&dev->struct_mutex); - if (!obj_priv->gtt_space) { - ret = i915_gem_object_bind_to_gtt(obj, 0); - if (ret) - goto unlock; - ret = i915_gem_object_set_to_gtt_domain(obj, write); + if (!obj->map_and_fenceable) { + ret = i915_gem_object_unbind(obj); if (ret) goto unlock; } - - /* Need a new fence register? */ - if (obj_priv->tiling_mode != I915_TILING_NONE) { - ret = i915_gem_object_get_fence_reg(obj, true); + if (!obj->gtt_space) { + ret = i915_gem_object_bind_to_gtt(obj, 0, true); if (ret) goto unlock; } - if (i915_gem_object_is_inactive(obj_priv)) - list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); + ret = i915_gem_object_set_to_gtt_domain(obj, write); + if (ret) + goto unlock; + + if (obj->tiling_mode == I915_TILING_NONE) + ret = i915_gem_object_put_fence(obj); + else + ret = i915_gem_object_get_fence(obj, NULL, true); + if (ret) + goto unlock; + + if (i915_gem_object_is_inactive(obj)) + list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list); + + obj->fault_mappable = true; - pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + + pfn = ((dev->agp->base + obj->gtt_offset) >> PAGE_SHIFT) + page_offset; /* Finally, remap it using the new GTT offset */ @@ -1272,11 +1217,12 @@ mutex_unlock(&dev->struct_mutex); switch (ret) { + case -EAGAIN: + set_need_resched(); case 0: case -ERESTARTSYS: return VM_FAULT_NOPAGE; case -ENOMEM: - case -EAGAIN: return VM_FAULT_OOM; default: return VM_FAULT_SIGBUS; @@ -1295,37 +1241,39 @@ * This routine allocates and attaches a fake offset for @obj. */ static int -i915_gem_create_mmap_offset(struct drm_gem_object *obj) +i915_gem_create_mmap_offset(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; struct drm_gem_mm *mm = dev->mm_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); struct drm_map_list *list; struct drm_local_map *map; int ret = 0; /* Set the object up for mmap'ing */ - list = &obj->map_list; + list = &obj->base.map_list; list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); if (!list->map) return -ENOMEM; map = list->map; map->type = _DRM_GEM; - map->size = obj->size; + map->size = obj->base.size; map->handle = obj; /* Get a DRM GEM mmap offset allocated... */ list->file_offset_node = drm_mm_search_free(&mm->offset_manager, - obj->size / PAGE_SIZE, 0, 0); + obj->base.size / PAGE_SIZE, + 0, 0); if (!list->file_offset_node) { - DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); + DRM_ERROR("failed to allocate offset for bo %d\n", + obj->base.name); ret = -ENOSPC; goto out_free_list; } list->file_offset_node = drm_mm_get_block(list->file_offset_node, - obj->size / PAGE_SIZE, 0); + obj->base.size / PAGE_SIZE, + 0); if (!list->file_offset_node) { ret = -ENOMEM; goto out_free_list; @@ -1338,16 +1286,13 @@ goto out_free_mm; } - /* By now we should be all set, any drm_mmap request on the offset - * below will get to our mmap & fault handler */ - obj_priv->mmap_offset = ((uint64_t) list->hash.key) << PAGE_SHIFT; - return 0; out_free_mm: drm_mm_put_block(list->file_offset_node); out_free_list: kfree(list->map); + list->map = NULL; return ret; } @@ -1367,38 +1312,51 @@ * fixup by i915_gem_fault(). */ void -i915_gem_release_mmap(struct drm_gem_object *obj) +i915_gem_release_mmap(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + if (!obj->fault_mappable) + return; + + unmap_mapping_range(obj->base.dev->dev_mapping, + (loff_t)obj->base.map_list.hash.key<base.size, 1); - if (dev->dev_mapping) - unmap_mapping_range(dev->dev_mapping, - obj_priv->mmap_offset, obj->size, 1); + obj->fault_mappable = false; } static void -i915_gem_free_mmap_offset(struct drm_gem_object *obj) +i915_gem_free_mmap_offset(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + struct drm_device *dev = obj->base.dev; struct drm_gem_mm *mm = dev->mm_private; - struct drm_map_list *list; + struct drm_map_list *list = &obj->base.map_list; - list = &obj->map_list; drm_ht_remove_item(&mm->offset_hash, &list->hash); + drm_mm_put_block(list->file_offset_node); + kfree(list->map); + list->map = NULL; +} - if (list->file_offset_node) { - drm_mm_put_block(list->file_offset_node); - list->file_offset_node = NULL; - } +static uint32_t +i915_gem_get_gtt_size(struct drm_i915_gem_object *obj) +{ + struct drm_device *dev = obj->base.dev; + uint32_t size; - if (list->map) { - kfree(list->map); - list->map = NULL; - } + if (INTEL_INFO(dev)->gen >= 4 || + obj->tiling_mode == I915_TILING_NONE) + return obj->base.size; + + /* Previous chips need a power-of-two fence region when tiling */ + if (INTEL_INFO(dev)->gen == 3) + size = 1024*1024; + else + size = 512*1024; + + while (size < obj->base.size) + size <<= 1; - obj_priv->mmap_offset = 0; + return size; } /** @@ -1406,42 +1364,68 @@ * @obj: object to check * * Return the required GTT alignment for an object, taking into account - * potential fence register mapping if needed. + * potential fence register mapping. */ static uint32_t -i915_gem_get_gtt_alignment(struct drm_gem_object *obj) +i915_gem_get_gtt_alignment(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int start, i; + struct drm_device *dev = obj->base.dev; /* * Minimum alignment is 4k (GTT page size), but might be greater * if a fence register is needed for the object. */ - if (INTEL_INFO(dev)->gen >= 4 || obj_priv->tiling_mode == I915_TILING_NONE) + if (INTEL_INFO(dev)->gen >= 4 || + obj->tiling_mode == I915_TILING_NONE) return 4096; /* * Previous chips need to be aligned to the size of the smallest * fence register that can contain the object. */ - if (INTEL_INFO(dev)->gen == 3) - start = 1024*1024; - else - start = 512*1024; + return i915_gem_get_gtt_size(obj); +} + +/** + * i915_gem_get_unfenced_gtt_alignment - return required GTT alignment for an + * unfenced object + * @obj: object to check + * + * Return the required GTT alignment for an object, only taking into account + * unfenced tiled surface requirements. + */ +static uint32_t +i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj) +{ + struct drm_device *dev = obj->base.dev; + int tile_height; + + /* + * Minimum alignment is 4k (GTT page size) for sane hw. + */ + if (INTEL_INFO(dev)->gen >= 4 || IS_G33(dev) || + obj->tiling_mode == I915_TILING_NONE) + return 4096; - for (i = start; i < obj->size; i <<= 1) - ; + /* + * Older chips need unfenced tiled buffers to be aligned to the left + * edge of an even tile row (where tile rows are counted as if the bo is + * placed in a fenced gtt region). + */ + if (IS_GEN2(dev) || + (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) + tile_height = 32; + else + tile_height = 8; - return i; + return tile_height * obj->stride * 2; } /** * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing * @dev: DRM device * @data: GTT mapping ioctl data - * @file_priv: GEM object info + * @file: GEM object info * * Simply returns the fake offset to userspace so it can mmap it. * The mmap call will end up in drm_gem_mmap(), which will set things @@ -1454,11 +1438,11 @@ */ int i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_mmap_gtt *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int ret; if (!(dev->driver->driver_features & DRIVER_GEM)) @@ -1468,130 +1452,196 @@ if (ret) return ret; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (obj == NULL) { ret = -ENOENT; goto unlock; } - obj_priv = to_intel_bo(obj); - if (obj_priv->madv != I915_MADV_WILLNEED) { + if (obj->base.size > dev_priv->mm.gtt_mappable_end) { + ret = -E2BIG; + goto unlock; + } + + if (obj->madv != I915_MADV_WILLNEED) { DRM_ERROR("Attempting to mmap a purgeable buffer\n"); ret = -EINVAL; goto out; } - if (!obj_priv->mmap_offset) { + if (!obj->base.map_list.map) { ret = i915_gem_create_mmap_offset(obj); if (ret) goto out; } - args->offset = obj_priv->mmap_offset; - - /* - * Pull it into the GTT so that we have a page list (makes the - * initial fault faster and any subsequent flushing possible). - */ - if (!obj_priv->agp_mem) { - ret = i915_gem_object_bind_to_gtt(obj, 0); - if (ret) - goto out; - } + args->offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT; out: - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); unlock: mutex_unlock(&dev->struct_mutex); return ret; } +static int +i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj, + gfp_t gfpmask) +{ + int page_count, i; + struct address_space *mapping; + struct inode *inode; + struct page *page; + + /* Get the list of pages out of our struct file. They'll be pinned + * at this point until we release them. + */ + page_count = obj->base.size / PAGE_SIZE; + BUG_ON(obj->pages != NULL); + obj->pages = drm_malloc_ab(page_count, sizeof(struct page *)); + if (obj->pages == NULL) + return -ENOMEM; + + inode = obj->base.filp->f_path.dentry->d_inode; + mapping = inode->i_mapping; + for (i = 0; i < page_count; i++) { + page = read_cache_page_gfp(mapping, i, + GFP_HIGHUSER | + __GFP_COLD | + __GFP_RECLAIMABLE | + gfpmask); + if (IS_ERR(page)) + goto err_pages; + + obj->pages[i] = page; + } + + if (obj->tiling_mode != I915_TILING_NONE) + i915_gem_object_do_bit_17_swizzle(obj); + + return 0; + +err_pages: + while (i--) + page_cache_release(obj->pages[i]); + + drm_free_large(obj->pages); + obj->pages = NULL; + return PTR_ERR(page); +} + static void -i915_gem_object_put_pages(struct drm_gem_object *obj) +i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int page_count = obj->size / PAGE_SIZE; + int page_count = obj->base.size / PAGE_SIZE; int i; - BUG_ON(obj_priv->pages_refcount == 0); - BUG_ON(obj_priv->madv == __I915_MADV_PURGED); - - if (--obj_priv->pages_refcount != 0) - return; + BUG_ON(obj->madv == __I915_MADV_PURGED); - if (obj_priv->tiling_mode != I915_TILING_NONE) + if (obj->tiling_mode != I915_TILING_NONE) i915_gem_object_save_bit_17_swizzle(obj); - if (obj_priv->madv == I915_MADV_DONTNEED) - obj_priv->dirty = 0; + if (obj->madv == I915_MADV_DONTNEED) + obj->dirty = 0; for (i = 0; i < page_count; i++) { - if (obj_priv->dirty) - set_page_dirty(obj_priv->pages[i]); + if (obj->dirty) + set_page_dirty(obj->pages[i]); - if (obj_priv->madv == I915_MADV_WILLNEED) - mark_page_accessed(obj_priv->pages[i]); + if (obj->madv == I915_MADV_WILLNEED) + mark_page_accessed(obj->pages[i]); - page_cache_release(obj_priv->pages[i]); + page_cache_release(obj->pages[i]); } - obj_priv->dirty = 0; - - drm_free_large(obj_priv->pages); - obj_priv->pages = NULL; -} - -static uint32_t -i915_gem_next_request_seqno(struct drm_device *dev, - struct intel_ring_buffer *ring) -{ - drm_i915_private_t *dev_priv = dev->dev_private; + obj->dirty = 0; - ring->outstanding_lazy_request = true; - return dev_priv->next_seqno; + drm_free_large(obj->pages); + obj->pages = NULL; } -static void -i915_gem_object_move_to_active(struct drm_gem_object *obj, - struct intel_ring_buffer *ring) +void +i915_gem_object_move_to_active(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *ring, + u32 seqno) { - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - uint32_t seqno = i915_gem_next_request_seqno(dev, ring); BUG_ON(ring == NULL); - obj_priv->ring = ring; + obj->ring = ring; /* Add a reference if we're newly entering the active list. */ - if (!obj_priv->active) { - drm_gem_object_reference(obj); - obj_priv->active = 1; + if (!obj->active) { + drm_gem_object_reference(&obj->base); + obj->active = 1; } /* Move from whatever list we were on to the tail of execution. */ - list_move_tail(&obj_priv->mm_list, &dev_priv->mm.active_list); - list_move_tail(&obj_priv->ring_list, &ring->active_list); - obj_priv->last_rendering_seqno = seqno; -} + list_move_tail(&obj->mm_list, &dev_priv->mm.active_list); + list_move_tail(&obj->ring_list, &ring->active_list); + + obj->last_rendering_seqno = seqno; + if (obj->fenced_gpu_access) { + struct drm_i915_fence_reg *reg; + + BUG_ON(obj->fence_reg == I915_FENCE_REG_NONE); + + obj->last_fenced_seqno = seqno; + obj->last_fenced_ring = ring; + + reg = &dev_priv->fence_regs[obj->fence_reg]; + list_move_tail(®->lru_list, &dev_priv->mm.fence_list); + } +} static void -i915_gem_object_move_to_flushing(struct drm_gem_object *obj) +i915_gem_object_move_off_active(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; + list_del_init(&obj->ring_list); + obj->last_rendering_seqno = 0; +} + +static void +i915_gem_object_move_to_flushing(struct drm_i915_gem_object *obj) +{ + struct drm_device *dev = obj->base.dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - BUG_ON(!obj_priv->active); - list_move_tail(&obj_priv->mm_list, &dev_priv->mm.flushing_list); - list_del_init(&obj_priv->ring_list); - obj_priv->last_rendering_seqno = 0; + BUG_ON(!obj->active); + list_move_tail(&obj->mm_list, &dev_priv->mm.flushing_list); + + i915_gem_object_move_off_active(obj); +} + +static void +i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj) +{ + struct drm_device *dev = obj->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (obj->pin_count != 0) + list_move_tail(&obj->mm_list, &dev_priv->mm.pinned_list); + else + list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list); + + BUG_ON(!list_empty(&obj->gpu_write_list)); + BUG_ON(!obj->active); + obj->ring = NULL; + + i915_gem_object_move_off_active(obj); + obj->fenced_gpu_access = false; + + obj->active = 0; + obj->pending_gpu_write = false; + drm_gem_object_unreference(&obj->base); + + WARN_ON(i915_verify_lists(dev)); } /* Immediately discard the backing storage */ static void -i915_gem_object_truncate(struct drm_gem_object *obj) +i915_gem_object_truncate(struct drm_i915_gem_object *obj) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); struct inode *inode; /* Our goal here is to return as much of the memory as @@ -1600,42 +1650,18 @@ * backing pages, *now*. Here we mirror the actions taken * when by shmem_delete_inode() to release the backing store. */ - inode = obj->filp->f_path.dentry->d_inode; + inode = obj->base.filp->f_path.dentry->d_inode; truncate_inode_pages(inode->i_mapping, 0); if (inode->i_op->truncate_range) inode->i_op->truncate_range(inode, 0, (loff_t)-1); - obj_priv->madv = __I915_MADV_PURGED; + obj->madv = __I915_MADV_PURGED; } static inline int -i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv) -{ - return obj_priv->madv == I915_MADV_DONTNEED; -} - -static void -i915_gem_object_move_to_inactive(struct drm_gem_object *obj) +i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - - if (obj_priv->pin_count != 0) - list_move_tail(&obj_priv->mm_list, &dev_priv->mm.pinned_list); - else - list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); - list_del_init(&obj_priv->ring_list); - - BUG_ON(!list_empty(&obj_priv->gpu_write_list)); - - obj_priv->last_rendering_seqno = 0; - obj_priv->ring = NULL; - if (obj_priv->active) { - obj_priv->active = 0; - drm_gem_object_unreference(obj); - } - WARN_ON(i915_verify_lists(dev)); + return obj->madv == I915_MADV_DONTNEED; } static void @@ -1643,37 +1669,27 @@ uint32_t flush_domains, struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv, *next; + struct drm_i915_gem_object *obj, *next; - list_for_each_entry_safe(obj_priv, next, + list_for_each_entry_safe(obj, next, &ring->gpu_write_list, gpu_write_list) { - struct drm_gem_object *obj = &obj_priv->base; - - if (obj->write_domain & flush_domains) { - uint32_t old_write_domain = obj->write_domain; + if (obj->base.write_domain & flush_domains) { + uint32_t old_write_domain = obj->base.write_domain; - obj->write_domain = 0; - list_del_init(&obj_priv->gpu_write_list); - i915_gem_object_move_to_active(obj, ring); - - /* update the fence lru list */ - if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { - struct drm_i915_fence_reg *reg = - &dev_priv->fence_regs[obj_priv->fence_reg]; - list_move_tail(®->lru_list, - &dev_priv->mm.fence_list); - } + obj->base.write_domain = 0; + list_del_init(&obj->gpu_write_list); + i915_gem_object_move_to_active(obj, ring, + i915_gem_next_request_seqno(dev, ring)); trace_i915_gem_object_change_domain(obj, - obj->read_domains, + obj->base.read_domains, old_write_domain); } } } -uint32_t +int i915_add_request(struct drm_device *dev, struct drm_file *file, struct drm_i915_gem_request *request, @@ -1683,17 +1699,17 @@ struct drm_i915_file_private *file_priv = NULL; uint32_t seqno; int was_empty; + int ret; + + BUG_ON(request == NULL); if (file != NULL) file_priv = file->driver_priv; - if (request == NULL) { - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) - return 0; - } + ret = ring->add_request(ring, &seqno); + if (ret) + return ret; - seqno = ring->add_request(dev, ring, 0); ring->outstanding_lazy_request = false; request->seqno = seqno; @@ -1717,26 +1733,7 @@ queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); } - return seqno; -} - -/** - * Command execution barrier - * - * Ensures that all commands in the ring are finished - * before signalling the CPU - */ -static void -i915_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring) -{ - uint32_t flush_domains = 0; - - /* The sampler always gets flushed on i965 (sigh) */ - if (INTEL_INFO(dev)->gen >= 4) - flush_domains |= I915_GEM_DOMAIN_SAMPLER; - - ring->flush(dev, ring, - I915_GEM_DOMAIN_COMMAND, flush_domains); + return 0; } static inline void @@ -1769,62 +1766,76 @@ } while (!list_empty(&ring->active_list)) { - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; + + obj = list_first_entry(&ring->active_list, + struct drm_i915_gem_object, + ring_list); + + obj->base.write_domain = 0; + list_del_init(&obj->gpu_write_list); + i915_gem_object_move_to_inactive(obj); + } +} + +static void i915_gem_reset_fences(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int i; + + for (i = 0; i < 16; i++) { + struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; + struct drm_i915_gem_object *obj = reg->obj; + + if (!obj) + continue; + + if (obj->tiling_mode) + i915_gem_release_mmap(obj); - obj_priv = list_first_entry(&ring->active_list, - struct drm_i915_gem_object, - ring_list); - - obj_priv->base.write_domain = 0; - list_del_init(&obj_priv->gpu_write_list); - i915_gem_object_move_to_inactive(&obj_priv->base); + reg->obj->fence_reg = I915_FENCE_REG_NONE; + reg->obj->fenced_gpu_access = false; + reg->obj->last_fenced_seqno = 0; + reg->obj->last_fenced_ring = NULL; + i915_gem_clear_fence_reg(dev, reg); } } void i915_gem_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int i; - i915_gem_reset_ring_lists(dev_priv, &dev_priv->render_ring); - i915_gem_reset_ring_lists(dev_priv, &dev_priv->bsd_ring); - i915_gem_reset_ring_lists(dev_priv, &dev_priv->blt_ring); + for (i = 0; i < I915_NUM_RINGS; i++) + i915_gem_reset_ring_lists(dev_priv, &dev_priv->ring[i]); /* Remove anything from the flushing lists. The GPU cache is likely * to be lost on reset along with the data, so simply move the * lost bo to the inactive list. */ while (!list_empty(&dev_priv->mm.flushing_list)) { - obj_priv = list_first_entry(&dev_priv->mm.flushing_list, - struct drm_i915_gem_object, - mm_list); - - obj_priv->base.write_domain = 0; - list_del_init(&obj_priv->gpu_write_list); - i915_gem_object_move_to_inactive(&obj_priv->base); + obj= list_first_entry(&dev_priv->mm.flushing_list, + struct drm_i915_gem_object, + mm_list); + + obj->base.write_domain = 0; + list_del_init(&obj->gpu_write_list); + i915_gem_object_move_to_inactive(obj); } /* Move everything out of the GPU domains to ensure we do any * necessary invalidation upon reuse. */ - list_for_each_entry(obj_priv, + list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) { - obj_priv->base.read_domains &= ~I915_GEM_GPU_DOMAINS; + obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS; } /* The fence registers are invalidated so clear them out */ - for (i = 0; i < 16; i++) { - struct drm_i915_fence_reg *reg; - - reg = &dev_priv->fence_regs[i]; - if (!reg->obj) - continue; - - i915_gem_clear_fence_reg(reg->obj); - } + i915_gem_reset_fences(dev); } /** @@ -1836,6 +1847,7 @@ { drm_i915_private_t *dev_priv = dev->dev_private; uint32_t seqno; + int i; if (!ring->status_page.page_addr || list_empty(&ring->request_list)) @@ -1843,7 +1855,12 @@ WARN_ON(i915_verify_lists(dev)); - seqno = ring->get_seqno(dev, ring); + seqno = ring->get_seqno(ring); + + for (i = 0; i < I915_NUM_RINGS; i++) + if (seqno >= ring->sync_seqno[i]) + ring->sync_seqno[i] = 0; + while (!list_empty(&ring->request_list)) { struct drm_i915_gem_request *request; @@ -1865,18 +1882,16 @@ * by the ringbuffer to the flushing/inactive lists as appropriate. */ while (!list_empty(&ring->active_list)) { - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; - obj_priv = list_first_entry(&ring->active_list, - struct drm_i915_gem_object, - ring_list); + obj= list_first_entry(&ring->active_list, + struct drm_i915_gem_object, + ring_list); - if (!i915_seqno_passed(seqno, obj_priv->last_rendering_seqno)) + if (!i915_seqno_passed(seqno, obj->last_rendering_seqno)) break; - obj = &obj_priv->base; - if (obj->write_domain != 0) + if (obj->base.write_domain != 0) i915_gem_object_move_to_flushing(obj); else i915_gem_object_move_to_inactive(obj); @@ -1884,7 +1899,7 @@ if (unlikely (dev_priv->trace_irq_seqno && i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) { - ring->user_irq_put(dev, ring); + ring->irq_put(ring); dev_priv->trace_irq_seqno = 0; } @@ -1895,24 +1910,24 @@ i915_gem_retire_requests(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + int i; if (!list_empty(&dev_priv->mm.deferred_free_list)) { - struct drm_i915_gem_object *obj_priv, *tmp; + struct drm_i915_gem_object *obj, *next; /* We must be careful that during unbind() we do not * accidentally infinitely recurse into retire requests. * Currently: * retire -> free -> unbind -> wait -> retire_ring */ - list_for_each_entry_safe(obj_priv, tmp, + list_for_each_entry_safe(obj, next, &dev_priv->mm.deferred_free_list, mm_list) - i915_gem_free_object_tail(&obj_priv->base); + i915_gem_free_object_tail(obj); } - i915_gem_retire_requests_ring(dev, &dev_priv->render_ring); - i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring); - i915_gem_retire_requests_ring(dev, &dev_priv->blt_ring); + for (i = 0; i < I915_NUM_RINGS; i++) + i915_gem_retire_requests_ring(dev, &dev_priv->ring[i]); } static void @@ -1934,9 +1949,9 @@ i915_gem_retire_requests(dev); if (!dev_priv->mm.suspended && - (!list_empty(&dev_priv->render_ring.request_list) || - !list_empty(&dev_priv->bsd_ring.request_list) || - !list_empty(&dev_priv->blt_ring.request_list))) + (!list_empty(&dev_priv->ring[RCS].request_list) || + !list_empty(&dev_priv->ring[VCS].request_list) || + !list_empty(&dev_priv->ring[BCS].request_list))) queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); mutex_unlock(&dev->struct_mutex); } @@ -1954,14 +1969,23 @@ if (atomic_read(&dev_priv->mm.wedged)) return -EAGAIN; - if (ring->outstanding_lazy_request) { - seqno = i915_add_request(dev, NULL, NULL, ring); - if (seqno == 0) + if (seqno == ring->outstanding_lazy_request) { + struct drm_i915_gem_request *request; + + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) return -ENOMEM; + + ret = i915_add_request(dev, NULL, request, ring); + if (ret) { + kfree(request); + return ret; + } + + seqno = request->seqno; } - BUG_ON(seqno == dev_priv->next_seqno); - if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) { + if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) { if (HAS_PCH_SPLIT(dev)) ier = I915_READ(DEIER) | I915_READ(GTIER); else @@ -1975,21 +1999,23 @@ trace_i915_gem_request_wait_begin(dev, seqno); - ring->waiting_gem_seqno = seqno; - ring->user_irq_get(dev, ring); - if (interruptible) - ret = wait_event_interruptible(ring->irq_queue, - i915_seqno_passed( - ring->get_seqno(dev, ring), seqno) - || atomic_read(&dev_priv->mm.wedged)); - else - wait_event(ring->irq_queue, - i915_seqno_passed( - ring->get_seqno(dev, ring), seqno) - || atomic_read(&dev_priv->mm.wedged)); - - ring->user_irq_put(dev, ring); - ring->waiting_gem_seqno = 0; + ring->waiting_seqno = seqno; + if (ring->irq_get(ring)) { + if (interruptible) + ret = wait_event_interruptible(ring->irq_queue, + i915_seqno_passed(ring->get_seqno(ring), seqno) + || atomic_read(&dev_priv->mm.wedged)); + else + wait_event(ring->irq_queue, + i915_seqno_passed(ring->get_seqno(ring), seqno) + || atomic_read(&dev_priv->mm.wedged)); + + ring->irq_put(ring); + } else if (wait_for(i915_seqno_passed(ring->get_seqno(ring), + seqno) || + atomic_read(&dev_priv->mm.wedged), 3000)) + ret = -EBUSY; + ring->waiting_seqno = 0; trace_i915_gem_request_wait_end(dev, seqno); } @@ -1998,7 +2024,7 @@ if (ret && ret != -ERESTARTSYS) DRM_ERROR("%s returns %d (awaiting %d at %d, next %d)\n", - __func__, ret, seqno, ring->get_seqno(dev, ring), + __func__, ret, seqno, ring->get_seqno(ring), dev_priv->next_seqno); /* Directly dispatch request retiring. While we have the work queue @@ -2023,70 +2049,30 @@ return i915_do_wait_request(dev, seqno, 1, ring); } -static void -i915_gem_flush_ring(struct drm_device *dev, - struct drm_file *file_priv, - struct intel_ring_buffer *ring, - uint32_t invalidate_domains, - uint32_t flush_domains) -{ - ring->flush(dev, ring, invalidate_domains, flush_domains); - i915_gem_process_flushing_list(dev, flush_domains, ring); -} - -static void -i915_gem_flush(struct drm_device *dev, - struct drm_file *file_priv, - uint32_t invalidate_domains, - uint32_t flush_domains, - uint32_t flush_rings) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - - if (flush_domains & I915_GEM_DOMAIN_CPU) - drm_agp_chipset_flush(dev); - - if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { - if (flush_rings & RING_RENDER) - i915_gem_flush_ring(dev, file_priv, - &dev_priv->render_ring, - invalidate_domains, flush_domains); - if (flush_rings & RING_BSD) - i915_gem_flush_ring(dev, file_priv, - &dev_priv->bsd_ring, - invalidate_domains, flush_domains); - if (flush_rings & RING_BLT) - i915_gem_flush_ring(dev, file_priv, - &dev_priv->blt_ring, - invalidate_domains, flush_domains); - } -} - /** * Ensures that all rendering to the object has completed and the object is * safe to unbind from the GTT or access from the CPU. */ -static int -i915_gem_object_wait_rendering(struct drm_gem_object *obj, +int +i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj, bool interruptible) { - struct drm_device *dev = obj->dev; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + struct drm_device *dev = obj->base.dev; int ret; /* This function only exists to support waiting for existing rendering, * not for emitting required flushes. */ - BUG_ON((obj->write_domain & I915_GEM_GPU_DOMAINS) != 0); + BUG_ON((obj->base.write_domain & I915_GEM_GPU_DOMAINS) != 0); /* If there is rendering queued on the buffer being evicted, wait for * it. */ - if (obj_priv->active) { + if (obj->active) { ret = i915_do_wait_request(dev, - obj_priv->last_rendering_seqno, + obj->last_rendering_seqno, interruptible, - obj_priv->ring); + obj->ring); if (ret) return ret; } @@ -2098,17 +2084,14 @@ * Unbinds an object from the GTT aperture. */ int -i915_gem_object_unbind(struct drm_gem_object *obj) +i915_gem_object_unbind(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); int ret = 0; - if (obj_priv->gtt_space == NULL) + if (obj->gtt_space == NULL) return 0; - if (obj_priv->pin_count != 0) { + if (obj->pin_count != 0) { DRM_ERROR("Attempting to unbind pinned buffer\n"); return -EINVAL; } @@ -2131,27 +2114,27 @@ */ if (ret) { i915_gem_clflush_object(obj); - obj->read_domains = obj->write_domain = I915_GEM_DOMAIN_CPU; + obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU; } /* release the fence reg _after_ flushing */ - if (obj_priv->fence_reg != I915_FENCE_REG_NONE) - i915_gem_clear_fence_reg(obj); - - drm_unbind_agp(obj_priv->agp_mem); - drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE); - - i915_gem_object_put_pages(obj); - BUG_ON(obj_priv->pages_refcount); + ret = i915_gem_object_put_fence(obj); + if (ret == -ERESTARTSYS) + return ret; - i915_gem_info_remove_gtt(dev_priv, obj->size); - list_del_init(&obj_priv->mm_list); + i915_gem_gtt_unbind_object(obj); + i915_gem_object_put_pages_gtt(obj); - drm_mm_put_block(obj_priv->gtt_space); - obj_priv->gtt_space = NULL; - obj_priv->gtt_offset = 0; + list_del_init(&obj->gtt_list); + list_del_init(&obj->mm_list); + /* Avoid an unnecessary call to unbind on rebind. */ + obj->map_and_fenceable = true; + + drm_mm_put_block(obj->gtt_space); + obj->gtt_space = NULL; + obj->gtt_offset = 0; - if (i915_gem_object_is_purgeable(obj_priv)) + if (i915_gem_object_is_purgeable(obj)) i915_gem_object_truncate(obj); trace_i915_gem_object_unbind(obj); @@ -2159,14 +2142,25 @@ return ret; } +void +i915_gem_flush_ring(struct drm_device *dev, + struct intel_ring_buffer *ring, + uint32_t invalidate_domains, + uint32_t flush_domains) +{ + if (ring->flush(ring, invalidate_domains, flush_domains) == 0) + i915_gem_process_flushing_list(dev, flush_domains, ring); +} + static int i915_ring_idle(struct drm_device *dev, struct intel_ring_buffer *ring) { if (list_empty(&ring->gpu_write_list) && list_empty(&ring->active_list)) return 0; - i915_gem_flush_ring(dev, NULL, ring, - I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); + if (!list_empty(&ring->gpu_write_list)) + i915_gem_flush_ring(dev, ring, + I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); return i915_wait_request(dev, i915_gem_next_request_seqno(dev, ring), ring); @@ -2177,7 +2171,7 @@ { drm_i915_private_t *dev_priv = dev->dev_private; bool lists_empty; - int ret; + int ret, i; lists_empty = (list_empty(&dev_priv->mm.flushing_list) && list_empty(&dev_priv->mm.active_list)); @@ -2185,335 +2179,442 @@ return 0; /* Flush everything onto the inactive list. */ - ret = i915_ring_idle(dev, &dev_priv->render_ring); - if (ret) - return ret; - - ret = i915_ring_idle(dev, &dev_priv->bsd_ring); - if (ret) - return ret; - - ret = i915_ring_idle(dev, &dev_priv->blt_ring); - if (ret) - return ret; - - return 0; -} - -static int -i915_gem_object_get_pages(struct drm_gem_object *obj, - gfp_t gfpmask) -{ - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int page_count, i; - struct address_space *mapping; - struct inode *inode; - struct page *page; - - BUG_ON(obj_priv->pages_refcount - == DRM_I915_GEM_OBJECT_MAX_PAGES_REFCOUNT); - - if (obj_priv->pages_refcount++ != 0) - return 0; - - /* Get the list of pages out of our struct file. They'll be pinned - * at this point until we release them. - */ - page_count = obj->size / PAGE_SIZE; - BUG_ON(obj_priv->pages != NULL); - obj_priv->pages = drm_calloc_large(page_count, sizeof(struct page *)); - if (obj_priv->pages == NULL) { - obj_priv->pages_refcount--; - return -ENOMEM; - } - - inode = obj->filp->f_path.dentry->d_inode; - mapping = inode->i_mapping; - for (i = 0; i < page_count; i++) { - page = read_cache_page_gfp(mapping, i, - GFP_HIGHUSER | - __GFP_COLD | - __GFP_RECLAIMABLE | - gfpmask); - if (IS_ERR(page)) - goto err_pages; - - obj_priv->pages[i] = page; + for (i = 0; i < I915_NUM_RINGS; i++) { + ret = i915_ring_idle(dev, &dev_priv->ring[i]); + if (ret) + return ret; } - if (obj_priv->tiling_mode != I915_TILING_NONE) - i915_gem_object_do_bit_17_swizzle(obj); - return 0; - -err_pages: - while (i--) - page_cache_release(obj_priv->pages[i]); - - drm_free_large(obj_priv->pages); - obj_priv->pages = NULL; - obj_priv->pages_refcount--; - return PTR_ERR(page); } -static void sandybridge_write_fence_reg(struct drm_i915_fence_reg *reg) +static int sandybridge_write_fence_reg(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined) { - struct drm_gem_object *obj = reg->obj; - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int regnum = obj_priv->fence_reg; + u32 size = obj->gtt_space->size; + int regnum = obj->fence_reg; uint64_t val; - val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) & - 0xfffff000) << 32; - val |= obj_priv->gtt_offset & 0xfffff000; - val |= (uint64_t)((obj_priv->stride / 128) - 1) << + val = (uint64_t)((obj->gtt_offset + size - 4096) & + 0xfffff000) << 32; + val |= obj->gtt_offset & 0xfffff000; + val |= (uint64_t)((obj->stride / 128) - 1) << SANDYBRIDGE_FENCE_PITCH_SHIFT; - if (obj_priv->tiling_mode == I915_TILING_Y) + if (obj->tiling_mode == I915_TILING_Y) val |= 1 << I965_FENCE_TILING_Y_SHIFT; val |= I965_FENCE_REG_VALID; - I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (regnum * 8), val); + if (pipelined) { + int ret = intel_ring_begin(pipelined, 6); + if (ret) + return ret; + + intel_ring_emit(pipelined, MI_NOOP); + intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(2)); + intel_ring_emit(pipelined, FENCE_REG_SANDYBRIDGE_0 + regnum*8); + intel_ring_emit(pipelined, (u32)val); + intel_ring_emit(pipelined, FENCE_REG_SANDYBRIDGE_0 + regnum*8 + 4); + intel_ring_emit(pipelined, (u32)(val >> 32)); + intel_ring_advance(pipelined); + } else + I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + regnum * 8, val); + + return 0; } -static void i965_write_fence_reg(struct drm_i915_fence_reg *reg) +static int i965_write_fence_reg(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined) { - struct drm_gem_object *obj = reg->obj; - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int regnum = obj_priv->fence_reg; + u32 size = obj->gtt_space->size; + int regnum = obj->fence_reg; uint64_t val; - val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) & + val = (uint64_t)((obj->gtt_offset + size - 4096) & 0xfffff000) << 32; - val |= obj_priv->gtt_offset & 0xfffff000; - val |= ((obj_priv->stride / 128) - 1) << I965_FENCE_PITCH_SHIFT; - if (obj_priv->tiling_mode == I915_TILING_Y) + val |= obj->gtt_offset & 0xfffff000; + val |= ((obj->stride / 128) - 1) << I965_FENCE_PITCH_SHIFT; + if (obj->tiling_mode == I915_TILING_Y) val |= 1 << I965_FENCE_TILING_Y_SHIFT; val |= I965_FENCE_REG_VALID; - I915_WRITE64(FENCE_REG_965_0 + (regnum * 8), val); + if (pipelined) { + int ret = intel_ring_begin(pipelined, 6); + if (ret) + return ret; + + intel_ring_emit(pipelined, MI_NOOP); + intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(2)); + intel_ring_emit(pipelined, FENCE_REG_965_0 + regnum*8); + intel_ring_emit(pipelined, (u32)val); + intel_ring_emit(pipelined, FENCE_REG_965_0 + regnum*8 + 4); + intel_ring_emit(pipelined, (u32)(val >> 32)); + intel_ring_advance(pipelined); + } else + I915_WRITE64(FENCE_REG_965_0 + regnum * 8, val); + + return 0; } -static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) +static int i915_write_fence_reg(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined) { - struct drm_gem_object *obj = reg->obj; - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int regnum = obj_priv->fence_reg; + u32 size = obj->gtt_space->size; + u32 fence_reg, val, pitch_val; int tile_width; - uint32_t fence_reg, val; - uint32_t pitch_val; - if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || - (obj_priv->gtt_offset & (obj->size - 1))) { - WARN(1, "%s: object 0x%08x not 1M or size (0x%zx) aligned\n", - __func__, obj_priv->gtt_offset, obj->size); - return; - } + if (WARN((obj->gtt_offset & ~I915_FENCE_START_MASK) || + (size & -size) != size || + (obj->gtt_offset & (size - 1)), + "object 0x%08x [fenceable? %d] not 1M or pot-size (0x%08x) aligned\n", + obj->gtt_offset, obj->map_and_fenceable, size)) + return -EINVAL; - if (obj_priv->tiling_mode == I915_TILING_Y && - HAS_128_BYTE_Y_TILING(dev)) + if (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)) tile_width = 128; else tile_width = 512; /* Note: pitch better be a power of two tile widths */ - pitch_val = obj_priv->stride / tile_width; + pitch_val = obj->stride / tile_width; pitch_val = ffs(pitch_val) - 1; - if (obj_priv->tiling_mode == I915_TILING_Y && - HAS_128_BYTE_Y_TILING(dev)) - WARN_ON(pitch_val > I830_FENCE_MAX_PITCH_VAL); - else - WARN_ON(pitch_val > I915_FENCE_MAX_PITCH_VAL); - - val = obj_priv->gtt_offset; - if (obj_priv->tiling_mode == I915_TILING_Y) + val = obj->gtt_offset; + if (obj->tiling_mode == I915_TILING_Y) val |= 1 << I830_FENCE_TILING_Y_SHIFT; - val |= I915_FENCE_SIZE_BITS(obj->size); + val |= I915_FENCE_SIZE_BITS(size); val |= pitch_val << I830_FENCE_PITCH_SHIFT; val |= I830_FENCE_REG_VALID; - if (regnum < 8) - fence_reg = FENCE_REG_830_0 + (regnum * 4); + fence_reg = obj->fence_reg; + if (fence_reg < 8) + fence_reg = FENCE_REG_830_0 + fence_reg * 4; else - fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4); - I915_WRITE(fence_reg, val); + fence_reg = FENCE_REG_945_8 + (fence_reg - 8) * 4; + + if (pipelined) { + int ret = intel_ring_begin(pipelined, 4); + if (ret) + return ret; + + intel_ring_emit(pipelined, MI_NOOP); + intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit(pipelined, fence_reg); + intel_ring_emit(pipelined, val); + intel_ring_advance(pipelined); + } else + I915_WRITE(fence_reg, val); + + return 0; } -static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) +static int i830_write_fence_reg(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined) { - struct drm_gem_object *obj = reg->obj; - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int regnum = obj_priv->fence_reg; + u32 size = obj->gtt_space->size; + int regnum = obj->fence_reg; uint32_t val; uint32_t pitch_val; - uint32_t fence_size_bits; - if ((obj_priv->gtt_offset & ~I830_FENCE_START_MASK) || - (obj_priv->gtt_offset & (obj->size - 1))) { - WARN(1, "%s: object 0x%08x not 512K or size aligned\n", - __func__, obj_priv->gtt_offset); - return; - } + if (WARN((obj->gtt_offset & ~I830_FENCE_START_MASK) || + (size & -size) != size || + (obj->gtt_offset & (size - 1)), + "object 0x%08x not 512K or pot-size 0x%08x aligned\n", + obj->gtt_offset, size)) + return -EINVAL; - pitch_val = obj_priv->stride / 128; + pitch_val = obj->stride / 128; pitch_val = ffs(pitch_val) - 1; - WARN_ON(pitch_val > I830_FENCE_MAX_PITCH_VAL); - val = obj_priv->gtt_offset; - if (obj_priv->tiling_mode == I915_TILING_Y) + val = obj->gtt_offset; + if (obj->tiling_mode == I915_TILING_Y) val |= 1 << I830_FENCE_TILING_Y_SHIFT; - fence_size_bits = I830_FENCE_SIZE_BITS(obj->size); - WARN_ON(fence_size_bits & ~0x00000f00); - val |= fence_size_bits; + val |= I830_FENCE_SIZE_BITS(size); val |= pitch_val << I830_FENCE_PITCH_SHIFT; val |= I830_FENCE_REG_VALID; - I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); + if (pipelined) { + int ret = intel_ring_begin(pipelined, 4); + if (ret) + return ret; + + intel_ring_emit(pipelined, MI_NOOP); + intel_ring_emit(pipelined, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit(pipelined, FENCE_REG_830_0 + regnum*4); + intel_ring_emit(pipelined, val); + intel_ring_advance(pipelined); + } else + I915_WRITE(FENCE_REG_830_0 + regnum * 4, val); + + return 0; } -static int i915_find_fence_reg(struct drm_device *dev, - bool interruptible) +static bool ring_passed_seqno(struct intel_ring_buffer *ring, u32 seqno) { - struct drm_i915_fence_reg *reg = NULL; - struct drm_i915_gem_object *obj_priv = NULL; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_gem_object *obj = NULL; - int i, avail, ret; - - /* First try to find a free reg */ - avail = 0; - for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { - reg = &dev_priv->fence_regs[i]; - if (!reg->obj) - return i; + return i915_seqno_passed(ring->get_seqno(ring), seqno); +} - obj_priv = to_intel_bo(reg->obj); - if (!obj_priv->pin_count) - avail++; - } +static int +i915_gem_object_flush_fence(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined, + bool interruptible) +{ + int ret; - if (avail == 0) - return -ENOSPC; + if (obj->fenced_gpu_access) { + if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) + i915_gem_flush_ring(obj->base.dev, + obj->last_fenced_ring, + 0, obj->base.write_domain); - /* None available, try to steal one or wait for a user to finish */ - i = I915_FENCE_REG_NONE; - list_for_each_entry(reg, &dev_priv->mm.fence_list, - lru_list) { - obj = reg->obj; - obj_priv = to_intel_bo(obj); + obj->fenced_gpu_access = false; + } - if (obj_priv->pin_count) - continue; + if (obj->last_fenced_seqno && pipelined != obj->last_fenced_ring) { + if (!ring_passed_seqno(obj->last_fenced_ring, + obj->last_fenced_seqno)) { + ret = i915_do_wait_request(obj->base.dev, + obj->last_fenced_seqno, + interruptible, + obj->last_fenced_ring); + if (ret) + return ret; + } - /* found one! */ - i = obj_priv->fence_reg; - break; + obj->last_fenced_seqno = 0; + obj->last_fenced_ring = NULL; } - BUG_ON(i == I915_FENCE_REG_NONE); - - /* We only have a reference on obj from the active list. put_fence_reg - * might drop that one, causing a use-after-free in it. So hold a - * private reference to obj like the other callers of put_fence_reg - * (set_tiling ioctl) do. */ - drm_gem_object_reference(obj); - ret = i915_gem_object_put_fence_reg(obj, interruptible); - drm_gem_object_unreference(obj); - if (ret != 0) - return ret; + if (obj->base.write_domain == I915_GEM_DOMAIN_GTT) + wmb(); - return i; + return 0; } -/** - * i915_gem_object_get_fence_reg - set up a fence reg for an object - * @obj: object to map through a fence reg - * - * When mapping objects through the GTT, userspace wants to be able to write - * to them without having to worry about swizzling if the object is tiled. - * - * This function walks the fence regs looking for a free one for @obj, - * stealing one if it can't find any. - * - * It then sets up the reg based on the object's properties: address, pitch - * and tiling format. - */ int -i915_gem_object_get_fence_reg(struct drm_gem_object *obj, - bool interruptible) +i915_gem_object_put_fence(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - struct drm_i915_fence_reg *reg = NULL; int ret; - /* Just update our place in the LRU if our fence is getting used. */ - if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { - reg = &dev_priv->fence_regs[obj_priv->fence_reg]; - list_move_tail(®->lru_list, &dev_priv->mm.fence_list); - return 0; + if (obj->tiling_mode) + i915_gem_release_mmap(obj); + + ret = i915_gem_object_flush_fence(obj, NULL, true); + if (ret) + return ret; + + if (obj->fence_reg != I915_FENCE_REG_NONE) { + struct drm_i915_private *dev_priv = obj->base.dev->dev_private; + i915_gem_clear_fence_reg(obj->base.dev, + &dev_priv->fence_regs[obj->fence_reg]); + + obj->fence_reg = I915_FENCE_REG_NONE; } - switch (obj_priv->tiling_mode) { - case I915_TILING_NONE: - WARN(1, "allocating a fence for non-tiled object?\n"); - break; - case I915_TILING_X: - if (!obj_priv->stride) - return -EINVAL; - WARN((obj_priv->stride & (512 - 1)), - "object 0x%08x is X tiled but has non-512B pitch\n", - obj_priv->gtt_offset); - break; - case I915_TILING_Y: - if (!obj_priv->stride) - return -EINVAL; - WARN((obj_priv->stride & (128 - 1)), - "object 0x%08x is Y tiled but has non-128B pitch\n", - obj_priv->gtt_offset); - break; + return 0; +} + +static struct drm_i915_fence_reg * +i915_find_fence_reg(struct drm_device *dev, + struct intel_ring_buffer *pipelined) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_fence_reg *reg, *first, *avail; + int i; + + /* First try to find a free reg */ + avail = NULL; + for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { + reg = &dev_priv->fence_regs[i]; + if (!reg->obj) + return reg; + + if (!reg->obj->pin_count) + avail = reg; + } + + if (avail == NULL) + return NULL; + + /* None available, try to steal one or wait for a user to finish */ + avail = first = NULL; + list_for_each_entry(reg, &dev_priv->mm.fence_list, lru_list) { + if (reg->obj->pin_count) + continue; + + if (first == NULL) + first = reg; + + if (!pipelined || + !reg->obj->last_fenced_ring || + reg->obj->last_fenced_ring == pipelined) { + avail = reg; + break; + } + } + + if (avail == NULL) + avail = first; + + return avail; +} + +/** + * i915_gem_object_get_fence - set up a fence reg for an object + * @obj: object to map through a fence reg + * @pipelined: ring on which to queue the change, or NULL for CPU access + * @interruptible: must we wait uninterruptibly for the register to retire? + * + * When mapping objects through the GTT, userspace wants to be able to write + * to them without having to worry about swizzling if the object is tiled. + * + * This function walks the fence regs looking for a free one for @obj, + * stealing one if it can't find any. + * + * It then sets up the reg based on the object's properties: address, pitch + * and tiling format. + */ +int +i915_gem_object_get_fence(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined, + bool interruptible) +{ + struct drm_device *dev = obj->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_fence_reg *reg; + int ret; + + /* XXX disable pipelining. There are bugs. Shocking. */ + pipelined = NULL; + + /* Just update our place in the LRU if our fence is getting reused. */ + if (obj->fence_reg != I915_FENCE_REG_NONE) { + reg = &dev_priv->fence_regs[obj->fence_reg]; + list_move_tail(®->lru_list, &dev_priv->mm.fence_list); + + if (!obj->fenced_gpu_access && !obj->last_fenced_seqno) + pipelined = NULL; + + if (!pipelined) { + if (reg->setup_seqno) { + if (!ring_passed_seqno(obj->last_fenced_ring, + reg->setup_seqno)) { + ret = i915_do_wait_request(obj->base.dev, + reg->setup_seqno, + interruptible, + obj->last_fenced_ring); + if (ret) + return ret; + } + + reg->setup_seqno = 0; + } + } else if (obj->last_fenced_ring && + obj->last_fenced_ring != pipelined) { + ret = i915_gem_object_flush_fence(obj, + pipelined, + interruptible); + if (ret) + return ret; + } else if (obj->tiling_changed) { + if (obj->fenced_gpu_access) { + if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) + i915_gem_flush_ring(obj->base.dev, obj->ring, + 0, obj->base.write_domain); + + obj->fenced_gpu_access = false; + } + } + + if (!obj->fenced_gpu_access && !obj->last_fenced_seqno) + pipelined = NULL; + BUG_ON(!pipelined && reg->setup_seqno); + + if (obj->tiling_changed) { + if (pipelined) { + reg->setup_seqno = + i915_gem_next_request_seqno(dev, pipelined); + obj->last_fenced_seqno = reg->setup_seqno; + obj->last_fenced_ring = pipelined; + } + goto update; + } + + return 0; } - ret = i915_find_fence_reg(dev, interruptible); - if (ret < 0) + reg = i915_find_fence_reg(dev, pipelined); + if (reg == NULL) + return -ENOSPC; + + ret = i915_gem_object_flush_fence(obj, pipelined, interruptible); + if (ret) return ret; - obj_priv->fence_reg = ret; - reg = &dev_priv->fence_regs[obj_priv->fence_reg]; - list_add_tail(®->lru_list, &dev_priv->mm.fence_list); + if (reg->obj) { + struct drm_i915_gem_object *old = reg->obj; + + drm_gem_object_reference(&old->base); + + if (old->tiling_mode) + i915_gem_release_mmap(old); + + ret = i915_gem_object_flush_fence(old, + pipelined, + interruptible); + if (ret) { + drm_gem_object_unreference(&old->base); + return ret; + } + + if (old->last_fenced_seqno == 0 && obj->last_fenced_seqno == 0) + pipelined = NULL; + + old->fence_reg = I915_FENCE_REG_NONE; + old->last_fenced_ring = pipelined; + old->last_fenced_seqno = + pipelined ? i915_gem_next_request_seqno(dev, pipelined) : 0; + + drm_gem_object_unreference(&old->base); + } else if (obj->last_fenced_seqno == 0) + pipelined = NULL; reg->obj = obj; + list_move_tail(®->lru_list, &dev_priv->mm.fence_list); + obj->fence_reg = reg - dev_priv->fence_regs; + obj->last_fenced_ring = pipelined; + + reg->setup_seqno = + pipelined ? i915_gem_next_request_seqno(dev, pipelined) : 0; + obj->last_fenced_seqno = reg->setup_seqno; +update: + obj->tiling_changed = false; switch (INTEL_INFO(dev)->gen) { case 6: - sandybridge_write_fence_reg(reg); + ret = sandybridge_write_fence_reg(obj, pipelined); break; case 5: case 4: - i965_write_fence_reg(reg); + ret = i965_write_fence_reg(obj, pipelined); break; case 3: - i915_write_fence_reg(reg); + ret = i915_write_fence_reg(obj, pipelined); break; case 2: - i830_write_fence_reg(reg); + ret = i830_write_fence_reg(obj, pipelined); break; } - trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg, - obj_priv->tiling_mode); - - return 0; + return ret; } /** @@ -2521,154 +2622,127 @@ * @obj: object to clear * * Zeroes out the fence register itself and clears out the associated - * data structures in dev_priv and obj_priv. + * data structures in dev_priv and obj. */ static void -i915_gem_clear_fence_reg(struct drm_gem_object *obj) +i915_gem_clear_fence_reg(struct drm_device *dev, + struct drm_i915_fence_reg *reg) { - struct drm_device *dev = obj->dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - struct drm_i915_fence_reg *reg = - &dev_priv->fence_regs[obj_priv->fence_reg]; - uint32_t fence_reg; + uint32_t fence_reg = reg - dev_priv->fence_regs; switch (INTEL_INFO(dev)->gen) { case 6: - I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + - (obj_priv->fence_reg * 8), 0); + I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + fence_reg*8, 0); break; case 5: case 4: - I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); + I915_WRITE64(FENCE_REG_965_0 + fence_reg*8, 0); break; case 3: - if (obj_priv->fence_reg >= 8) - fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - 8) * 4; + if (fence_reg >= 8) + fence_reg = FENCE_REG_945_8 + (fence_reg - 8) * 4; else case 2: - fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; + fence_reg = FENCE_REG_830_0 + fence_reg * 4; I915_WRITE(fence_reg, 0); break; } - reg->obj = NULL; - obj_priv->fence_reg = I915_FENCE_REG_NONE; list_del_init(®->lru_list); -} - -/** - * i915_gem_object_put_fence_reg - waits on outstanding fenced access - * to the buffer to finish, and then resets the fence register. - * @obj: tiled object holding a fence register. - * @bool: whether the wait upon the fence is interruptible - * - * Zeroes out the fence register itself and clears out the associated - * data structures in dev_priv and obj_priv. - */ -int -i915_gem_object_put_fence_reg(struct drm_gem_object *obj, - bool interruptible) -{ - struct drm_device *dev = obj->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - struct drm_i915_fence_reg *reg; - - if (obj_priv->fence_reg == I915_FENCE_REG_NONE) - return 0; - - /* If we've changed tiling, GTT-mappings of the object - * need to re-fault to ensure that the correct fence register - * setup is in place. - */ - i915_gem_release_mmap(obj); - - /* On the i915, GPU access to tiled buffers is via a fence, - * therefore we must wait for any outstanding access to complete - * before clearing the fence. - */ - reg = &dev_priv->fence_regs[obj_priv->fence_reg]; - if (reg->gpu) { - int ret; - - ret = i915_gem_object_flush_gpu_write_domain(obj); - if (ret) - return ret; - - ret = i915_gem_object_wait_rendering(obj, interruptible); - if (ret) - return ret; - - reg->gpu = false; - } - - i915_gem_object_flush_gtt_write_domain(obj); - i915_gem_clear_fence_reg(obj); - - return 0; + reg->obj = NULL; + reg->setup_seqno = 0; } /** * Finds free space in the GTT aperture and binds the object there. */ static int -i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) +i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj, + unsigned alignment, + bool map_and_fenceable) { - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); struct drm_mm_node *free_space; - gfp_t gfpmask = __GFP_NORETRY | __GFP_NOWARN; + gfp_t gfpmask = __GFP_NORETRY | __GFP_NOWARN; + u32 size, fence_size, fence_alignment, unfenced_alignment; + bool mappable, fenceable; int ret; - if (obj_priv->madv != I915_MADV_WILLNEED) { + if (obj->madv != I915_MADV_WILLNEED) { DRM_ERROR("Attempting to bind a purgeable object\n"); return -EINVAL; } + fence_size = i915_gem_get_gtt_size(obj); + fence_alignment = i915_gem_get_gtt_alignment(obj); + unfenced_alignment = i915_gem_get_unfenced_gtt_alignment(obj); + if (alignment == 0) - alignment = i915_gem_get_gtt_alignment(obj); - if (alignment & (i915_gem_get_gtt_alignment(obj) - 1)) { + alignment = map_and_fenceable ? fence_alignment : + unfenced_alignment; + if (map_and_fenceable && alignment & (fence_alignment - 1)) { DRM_ERROR("Invalid object alignment requested %u\n", alignment); return -EINVAL; } + size = map_and_fenceable ? fence_size : obj->base.size; + /* If the object is bigger than the entire aperture, reject it early * before evicting everything in a vain attempt to find space. */ - if (obj->size > dev_priv->mm.gtt_total) { + if (obj->base.size > + (map_and_fenceable ? dev_priv->mm.gtt_mappable_end : dev_priv->mm.gtt_total)) { DRM_ERROR("Attempting to bind an object larger than the aperture\n"); return -E2BIG; } search_free: - free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, - obj->size, alignment, 0); - if (free_space != NULL) - obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size, - alignment); - if (obj_priv->gtt_space == NULL) { + if (map_and_fenceable) + free_space = + drm_mm_search_free_in_range(&dev_priv->mm.gtt_space, + size, alignment, 0, + dev_priv->mm.gtt_mappable_end, + 0); + else + free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, + size, alignment, 0); + + if (free_space != NULL) { + if (map_and_fenceable) + obj->gtt_space = + drm_mm_get_block_range_generic(free_space, + size, alignment, 0, + dev_priv->mm.gtt_mappable_end, + 0); + else + obj->gtt_space = + drm_mm_get_block(free_space, size, alignment); + } + if (obj->gtt_space == NULL) { /* If the gtt is empty and we're still having trouble * fitting our object in, we're out of memory. */ - ret = i915_gem_evict_something(dev, obj->size, alignment); + ret = i915_gem_evict_something(dev, size, alignment, + map_and_fenceable); if (ret) return ret; goto search_free; } - ret = i915_gem_object_get_pages(obj, gfpmask); + ret = i915_gem_object_get_pages_gtt(obj, gfpmask); if (ret) { - drm_mm_put_block(obj_priv->gtt_space); - obj_priv->gtt_space = NULL; + drm_mm_put_block(obj->gtt_space); + obj->gtt_space = NULL; if (ret == -ENOMEM) { /* first try to clear up some space from the GTT */ - ret = i915_gem_evict_something(dev, obj->size, - alignment); + ret = i915_gem_evict_something(dev, size, + alignment, + map_and_fenceable); if (ret) { /* now try to shrink everyone else */ if (gfpmask) { @@ -2685,122 +2759,119 @@ return ret; } - /* Create an AGP memory structure pointing at our pages, and bind it - * into the GTT. - */ - obj_priv->agp_mem = drm_agp_bind_pages(dev, - obj_priv->pages, - obj->size >> PAGE_SHIFT, - obj_priv->gtt_space->start, - obj_priv->agp_type); - if (obj_priv->agp_mem == NULL) { - i915_gem_object_put_pages(obj); - drm_mm_put_block(obj_priv->gtt_space); - obj_priv->gtt_space = NULL; + ret = i915_gem_gtt_bind_object(obj); + if (ret) { + i915_gem_object_put_pages_gtt(obj); + drm_mm_put_block(obj->gtt_space); + obj->gtt_space = NULL; - ret = i915_gem_evict_something(dev, obj->size, alignment); + ret = i915_gem_evict_something(dev, size, + alignment, map_and_fenceable); if (ret) return ret; goto search_free; } - /* keep track of bounds object by adding it to the inactive list */ - list_add_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); - i915_gem_info_add_gtt(dev_priv, obj->size); + list_add_tail(&obj->gtt_list, &dev_priv->mm.gtt_list); + list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list); /* Assert that the object is not currently in any GPU domain. As it * wasn't in the GTT, there shouldn't be any way it could have been in * a GPU cache */ - BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS); - BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); + BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); + BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); + + obj->gtt_offset = obj->gtt_space->start; + + fenceable = + obj->gtt_space->size == fence_size && + (obj->gtt_space->start & (fence_alignment -1)) == 0; - obj_priv->gtt_offset = obj_priv->gtt_space->start; - trace_i915_gem_object_bind(obj, obj_priv->gtt_offset); + mappable = + obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end; + obj->map_and_fenceable = mappable && fenceable; + + trace_i915_gem_object_bind(obj, obj->gtt_offset, map_and_fenceable); return 0; } void -i915_gem_clflush_object(struct drm_gem_object *obj) +i915_gem_clflush_object(struct drm_i915_gem_object *obj) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - /* If we don't have a page list set up, then we're not pinned * to GPU, and we can ignore the cache flush because it'll happen * again at bind time. */ - if (obj_priv->pages == NULL) + if (obj->pages == NULL) return; trace_i915_gem_object_clflush(obj); - drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE); + drm_clflush_pages(obj->pages, obj->base.size / PAGE_SIZE); } /** Flushes any GPU write domain for the object if it's dirty. */ -static int -i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj) +static void +i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; - uint32_t old_write_domain; + struct drm_device *dev = obj->base.dev; - if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) - return 0; + if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0) + return; /* Queue the GPU write cache flushing we need. */ - old_write_domain = obj->write_domain; - i915_gem_flush_ring(dev, NULL, - to_intel_bo(obj)->ring, - 0, obj->write_domain); - BUG_ON(obj->write_domain); - - trace_i915_gem_object_change_domain(obj, - obj->read_domains, - old_write_domain); - - return 0; + i915_gem_flush_ring(dev, obj->ring, 0, obj->base.write_domain); + BUG_ON(obj->base.write_domain); } /** Flushes the GTT write domain for the object if it's dirty. */ static void -i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj) +i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj) { uint32_t old_write_domain; - if (obj->write_domain != I915_GEM_DOMAIN_GTT) + if (obj->base.write_domain != I915_GEM_DOMAIN_GTT) return; - /* No actual flushing is required for the GTT write domain. Writes + /* No actual flushing is required for the GTT write domain. Writes * to it immediately go to main memory as far as we know, so there's * no chipset flush. It also doesn't land in render cache. + * + * However, we do have to enforce the order so that all writes through + * the GTT land before any writes to the device, such as updates to + * the GATT itself. */ - old_write_domain = obj->write_domain; - obj->write_domain = 0; + wmb(); + + i915_gem_release_mmap(obj); + + old_write_domain = obj->base.write_domain; + obj->base.write_domain = 0; trace_i915_gem_object_change_domain(obj, - obj->read_domains, + obj->base.read_domains, old_write_domain); } /** Flushes the CPU write domain for the object if it's dirty. */ static void -i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj) +i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; uint32_t old_write_domain; - if (obj->write_domain != I915_GEM_DOMAIN_CPU) + if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) return; i915_gem_clflush_object(obj); - drm_agp_chipset_flush(dev); - old_write_domain = obj->write_domain; - obj->write_domain = 0; + intel_gtt_chipset_flush(); + old_write_domain = obj->base.write_domain; + obj->base.write_domain = 0; trace_i915_gem_object_change_domain(obj, - obj->read_domains, + obj->base.read_domains, old_write_domain); } @@ -2811,37 +2882,36 @@ * flushes to occur. */ int -i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) +i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); uint32_t old_write_domain, old_read_domains; int ret; /* Not valid to be called on unbound objects. */ - if (obj_priv->gtt_space == NULL) + if (obj->gtt_space == NULL) return -EINVAL; - ret = i915_gem_object_flush_gpu_write_domain(obj); - if (ret != 0) - return ret; - ret = i915_gem_object_wait_rendering(obj, true); - if (ret) - return ret; + i915_gem_object_flush_gpu_write_domain(obj); + if (obj->pending_gpu_write || write) { + ret = i915_gem_object_wait_rendering(obj, true); + if (ret) + return ret; + } i915_gem_object_flush_cpu_write_domain(obj); - old_write_domain = obj->write_domain; - old_read_domains = obj->read_domains; + old_write_domain = obj->base.write_domain; + old_read_domains = obj->base.read_domains; /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); - obj->read_domains |= I915_GEM_DOMAIN_GTT; + BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_GTT) != 0); + obj->base.read_domains |= I915_GEM_DOMAIN_GTT; if (write) { - obj->read_domains = I915_GEM_DOMAIN_GTT; - obj->write_domain = I915_GEM_DOMAIN_GTT; - obj_priv->dirty = 1; + obj->base.read_domains = I915_GEM_DOMAIN_GTT; + obj->base.write_domain = I915_GEM_DOMAIN_GTT; + obj->dirty = 1; } trace_i915_gem_object_change_domain(obj, @@ -2856,23 +2926,20 @@ * wait, as in modesetting process we're not supposed to be interrupted. */ int -i915_gem_object_set_to_display_plane(struct drm_gem_object *obj, - bool pipelined) +i915_gem_object_set_to_display_plane(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); uint32_t old_read_domains; int ret; /* Not valid to be called on unbound objects. */ - if (obj_priv->gtt_space == NULL) + if (obj->gtt_space == NULL) return -EINVAL; - ret = i915_gem_object_flush_gpu_write_domain(obj); - if (ret) - return ret; + i915_gem_object_flush_gpu_write_domain(obj); /* Currently, we are always called from an non-interruptible context. */ - if (!pipelined) { + if (pipelined != obj->ring) { ret = i915_gem_object_wait_rendering(obj, false); if (ret) return ret; @@ -2880,12 +2947,12 @@ i915_gem_object_flush_cpu_write_domain(obj); - old_read_domains = obj->read_domains; - obj->read_domains |= I915_GEM_DOMAIN_GTT; + old_read_domains = obj->base.read_domains; + obj->base.read_domains |= I915_GEM_DOMAIN_GTT; trace_i915_gem_object_change_domain(obj, old_read_domains, - obj->write_domain); + obj->base.write_domain); return 0; } @@ -2898,10 +2965,10 @@ return 0; if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) - i915_gem_flush_ring(obj->base.dev, NULL, obj->ring, + i915_gem_flush_ring(obj->base.dev, obj->ring, 0, obj->base.write_domain); - return i915_gem_object_wait_rendering(&obj->base, interruptible); + return i915_gem_object_wait_rendering(obj, interruptible); } /** @@ -2911,14 +2978,12 @@ * flushes to occur. */ static int -i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) +i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write) { uint32_t old_write_domain, old_read_domains; int ret; - ret = i915_gem_object_flush_gpu_write_domain(obj); - if (ret != 0) - return ret; + i915_gem_object_flush_gpu_write_domain(obj); ret = i915_gem_object_wait_rendering(obj, true); if (ret) return ret; @@ -2930,27 +2995,27 @@ */ i915_gem_object_set_to_full_cpu_read_domain(obj); - old_write_domain = obj->write_domain; - old_read_domains = obj->read_domains; + old_write_domain = obj->base.write_domain; + old_read_domains = obj->base.read_domains; /* Flush the CPU cache if it's still invalid. */ - if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) { + if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0) { i915_gem_clflush_object(obj); - obj->read_domains |= I915_GEM_DOMAIN_CPU; + obj->base.read_domains |= I915_GEM_DOMAIN_CPU; } /* It should now be out of any other write domains, and we can update * the domain values for our changes. */ - BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0); + BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0); /* If we're writing through the CPU, then the GPU read domains will * need to be invalidated at next use. */ if (write) { - obj->read_domains = I915_GEM_DOMAIN_CPU; - obj->write_domain = I915_GEM_DOMAIN_CPU; + obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->base.write_domain = I915_GEM_DOMAIN_CPU; } trace_i915_gem_object_change_domain(obj, @@ -2960,184 +3025,6 @@ return 0; } -/* - * Set the next domain for the specified object. This - * may not actually perform the necessary flushing/invaliding though, - * as that may want to be batched with other set_domain operations - * - * This is (we hope) the only really tricky part of gem. The goal - * is fairly simple -- track which caches hold bits of the object - * and make sure they remain coherent. A few concrete examples may - * help to explain how it works. For shorthand, we use the notation - * (read_domains, write_domain), e.g. (CPU, CPU) to indicate the - * a pair of read and write domain masks. - * - * Case 1: the batch buffer - * - * 1. Allocated - * 2. Written by CPU - * 3. Mapped to GTT - * 4. Read by GPU - * 5. Unmapped from GTT - * 6. Freed - * - * Let's take these a step at a time - * - * 1. Allocated - * Pages allocated from the kernel may still have - * cache contents, so we set them to (CPU, CPU) always. - * 2. Written by CPU (using pwrite) - * The pwrite function calls set_domain (CPU, CPU) and - * this function does nothing (as nothing changes) - * 3. Mapped by GTT - * This function asserts that the object is not - * currently in any GPU-based read or write domains - * 4. Read by GPU - * i915_gem_execbuffer calls set_domain (COMMAND, 0). - * As write_domain is zero, this function adds in the - * current read domains (CPU+COMMAND, 0). - * flush_domains is set to CPU. - * invalidate_domains is set to COMMAND - * clflush is run to get data out of the CPU caches - * then i915_dev_set_domain calls i915_gem_flush to - * emit an MI_FLUSH and drm_agp_chipset_flush - * 5. Unmapped from GTT - * i915_gem_object_unbind calls set_domain (CPU, CPU) - * flush_domains and invalidate_domains end up both zero - * so no flushing/invalidating happens - * 6. Freed - * yay, done - * - * Case 2: The shared render buffer - * - * 1. Allocated - * 2. Mapped to GTT - * 3. Read/written by GPU - * 4. set_domain to (CPU,CPU) - * 5. Read/written by CPU - * 6. Read/written by GPU - * - * 1. Allocated - * Same as last example, (CPU, CPU) - * 2. Mapped to GTT - * Nothing changes (assertions find that it is not in the GPU) - * 3. Read/written by GPU - * execbuffer calls set_domain (RENDER, RENDER) - * flush_domains gets CPU - * invalidate_domains gets GPU - * clflush (obj) - * MI_FLUSH and drm_agp_chipset_flush - * 4. set_domain (CPU, CPU) - * flush_domains gets GPU - * invalidate_domains gets CPU - * wait_rendering (obj) to make sure all drawing is complete. - * This will include an MI_FLUSH to get the data from GPU - * to memory - * clflush (obj) to invalidate the CPU cache - * Another MI_FLUSH in i915_gem_flush (eliminate this somehow?) - * 5. Read/written by CPU - * cache lines are loaded and dirtied - * 6. Read written by GPU - * Same as last GPU access - * - * Case 3: The constant buffer - * - * 1. Allocated - * 2. Written by CPU - * 3. Read by GPU - * 4. Updated (written) by CPU again - * 5. Read by GPU - * - * 1. Allocated - * (CPU, CPU) - * 2. Written by CPU - * (CPU, CPU) - * 3. Read by GPU - * (CPU+RENDER, 0) - * flush_domains = CPU - * invalidate_domains = RENDER - * clflush (obj) - * MI_FLUSH - * drm_agp_chipset_flush - * 4. Updated (written) by CPU again - * (CPU, CPU) - * flush_domains = 0 (no previous write domain) - * invalidate_domains = 0 (no new read domains) - * 5. Read by GPU - * (CPU+RENDER, 0) - * flush_domains = CPU - * invalidate_domains = RENDER - * clflush (obj) - * MI_FLUSH - * drm_agp_chipset_flush - */ -static void -i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, - struct intel_ring_buffer *ring) -{ - struct drm_device *dev = obj->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - uint32_t invalidate_domains = 0; - uint32_t flush_domains = 0; - uint32_t old_read_domains; - - intel_mark_busy(dev, obj); - - /* - * If the object isn't moving to a new write domain, - * let the object stay in multiple read domains - */ - if (obj->pending_write_domain == 0) - obj->pending_read_domains |= obj->read_domains; - else - obj_priv->dirty = 1; - - /* - * Flush the current write domain if - * the new read domains don't match. Invalidate - * any read domains which differ from the old - * write domain - */ - if (obj->write_domain && - (obj->write_domain != obj->pending_read_domains || - obj_priv->ring != ring)) { - flush_domains |= obj->write_domain; - invalidate_domains |= - obj->pending_read_domains & ~obj->write_domain; - } - /* - * Invalidate any read caches which may have - * stale data. That is, any new read domains. - */ - invalidate_domains |= obj->pending_read_domains & ~obj->read_domains; - if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) - i915_gem_clflush_object(obj); - - old_read_domains = obj->read_domains; - - /* The actual obj->write_domain will be updated with - * pending_write_domain after we emit the accumulated flush for all - * of our domain changes in execbuffers (which clears objects' - * write_domains). So if we have a current write domain that we - * aren't changing, set pending_write_domain to that. - */ - if (flush_domains == 0 && obj->pending_write_domain == 0) - obj->pending_write_domain = obj->write_domain; - obj->read_domains = obj->pending_read_domains; - - dev->invalidate_domains |= invalidate_domains; - dev->flush_domains |= flush_domains; - if (flush_domains & I915_GEM_GPU_DOMAINS) - dev_priv->mm.flush_rings |= obj_priv->ring->id; - if (invalidate_domains & I915_GEM_GPU_DOMAINS) - dev_priv->mm.flush_rings |= ring->id; - - trace_i915_gem_object_change_domain(obj, - old_read_domains, - obj->write_domain); -} - /** * Moves the object from a partially CPU read to a full one. * @@ -3145,1148 +3032,261 @@ * and doesn't handle transitioning from !(read_domains & I915_GEM_DOMAIN_CPU). */ static void -i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj) +i915_gem_object_set_to_full_cpu_read_domain(struct drm_i915_gem_object *obj) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - - if (!obj_priv->page_cpu_valid) + if (!obj->page_cpu_valid) return; /* If we're partially in the CPU read domain, finish moving it in. */ - if (obj->read_domains & I915_GEM_DOMAIN_CPU) { + if (obj->base.read_domains & I915_GEM_DOMAIN_CPU) { int i; - for (i = 0; i <= (obj->size - 1) / PAGE_SIZE; i++) { - if (obj_priv->page_cpu_valid[i]) - continue; - drm_clflush_pages(obj_priv->pages + i, 1); - } - } - - /* Free the page_cpu_valid mappings which are now stale, whether - * or not we've got I915_GEM_DOMAIN_CPU. - */ - kfree(obj_priv->page_cpu_valid); - obj_priv->page_cpu_valid = NULL; -} - -/** - * Set the CPU read domain on a range of the object. - * - * The object ends up with I915_GEM_DOMAIN_CPU in its read flags although it's - * not entirely valid. The page_cpu_valid member of the object flags which - * pages have been flushed, and will be respected by - * i915_gem_object_set_to_cpu_domain() if it's called on to get a valid mapping - * of the whole object. - * - * This function returns when the move is complete, including waiting on - * flushes to occur. - */ -static int -i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, - uint64_t offset, uint64_t size) -{ - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - uint32_t old_read_domains; - int i, ret; - - if (offset == 0 && size == obj->size) - return i915_gem_object_set_to_cpu_domain(obj, 0); - - ret = i915_gem_object_flush_gpu_write_domain(obj); - if (ret != 0) - return ret; - ret = i915_gem_object_wait_rendering(obj, true); - if (ret) - return ret; - - i915_gem_object_flush_gtt_write_domain(obj); - - /* If we're already fully in the CPU read domain, we're done. */ - if (obj_priv->page_cpu_valid == NULL && - (obj->read_domains & I915_GEM_DOMAIN_CPU) != 0) - return 0; - - /* Otherwise, create/clear the per-page CPU read domain flag if we're - * newly adding I915_GEM_DOMAIN_CPU - */ - if (obj_priv->page_cpu_valid == NULL) { - obj_priv->page_cpu_valid = kzalloc(obj->size / PAGE_SIZE, - GFP_KERNEL); - if (obj_priv->page_cpu_valid == NULL) - return -ENOMEM; - } else if ((obj->read_domains & I915_GEM_DOMAIN_CPU) == 0) - memset(obj_priv->page_cpu_valid, 0, obj->size / PAGE_SIZE); - - /* Flush the cache on any pages that are still invalid from the CPU's - * perspective. - */ - for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE; - i++) { - if (obj_priv->page_cpu_valid[i]) - continue; - - drm_clflush_pages(obj_priv->pages + i, 1); - - obj_priv->page_cpu_valid[i] = 1; - } - - /* It should now be out of any other write domains, and we can update - * the domain values for our changes. - */ - BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_CPU) != 0); - - old_read_domains = obj->read_domains; - obj->read_domains |= I915_GEM_DOMAIN_CPU; - - trace_i915_gem_object_change_domain(obj, - old_read_domains, - obj->write_domain); - - return 0; -} - -static int -i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, - struct drm_file *file_priv, - struct drm_i915_gem_exec_object2 *entry, - struct drm_i915_gem_relocation_entry *reloc) -{ - struct drm_device *dev = obj->base.dev; - struct drm_gem_object *target_obj; - uint32_t target_offset; - int ret = -EINVAL; - - target_obj = drm_gem_object_lookup(dev, file_priv, - reloc->target_handle); - if (target_obj == NULL) - return -ENOENT; - - target_offset = to_intel_bo(target_obj)->gtt_offset; - -#if WATCH_RELOC - DRM_INFO("%s: obj %p offset %08x target %d " - "read %08x write %08x gtt %08x " - "presumed %08x delta %08x\n", - __func__, - obj, - (int) reloc->offset, - (int) reloc->target_handle, - (int) reloc->read_domains, - (int) reloc->write_domain, - (int) target_offset, - (int) reloc->presumed_offset, - reloc->delta); -#endif - - /* The target buffer should have appeared before us in the - * exec_object list, so it should have a GTT space bound by now. - */ - if (target_offset == 0) { - DRM_ERROR("No GTT space found for object %d\n", - reloc->target_handle); - goto err; - } - - /* Validate that the target is in a valid r/w GPU domain */ - if (reloc->write_domain & (reloc->write_domain - 1)) { - DRM_ERROR("reloc with multiple write domains: " - "obj %p target %d offset %d " - "read %08x write %08x", - obj, reloc->target_handle, - (int) reloc->offset, - reloc->read_domains, - reloc->write_domain); - goto err; - } - if (reloc->write_domain & I915_GEM_DOMAIN_CPU || - reloc->read_domains & I915_GEM_DOMAIN_CPU) { - DRM_ERROR("reloc with read/write CPU domains: " - "obj %p target %d offset %d " - "read %08x write %08x", - obj, reloc->target_handle, - (int) reloc->offset, - reloc->read_domains, - reloc->write_domain); - goto err; - } - if (reloc->write_domain && target_obj->pending_write_domain && - reloc->write_domain != target_obj->pending_write_domain) { - DRM_ERROR("Write domain conflict: " - "obj %p target %d offset %d " - "new %08x old %08x\n", - obj, reloc->target_handle, - (int) reloc->offset, - reloc->write_domain, - target_obj->pending_write_domain); - goto err; - } - - target_obj->pending_read_domains |= reloc->read_domains; - target_obj->pending_write_domain |= reloc->write_domain; - - /* If the relocation already has the right value in it, no - * more work needs to be done. - */ - if (target_offset == reloc->presumed_offset) - goto out; - - /* Check that the relocation address is valid... */ - if (reloc->offset > obj->base.size - 4) { - DRM_ERROR("Relocation beyond object bounds: " - "obj %p target %d offset %d size %d.\n", - obj, reloc->target_handle, - (int) reloc->offset, - (int) obj->base.size); - goto err; - } - if (reloc->offset & 3) { - DRM_ERROR("Relocation not 4-byte aligned: " - "obj %p target %d offset %d.\n", - obj, reloc->target_handle, - (int) reloc->offset); - goto err; - } - - /* and points to somewhere within the target object. */ - if (reloc->delta >= target_obj->size) { - DRM_ERROR("Relocation beyond target object bounds: " - "obj %p target %d delta %d size %d.\n", - obj, reloc->target_handle, - (int) reloc->delta, - (int) target_obj->size); - goto err; - } - - reloc->delta += target_offset; - if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { - uint32_t page_offset = reloc->offset & ~PAGE_MASK; - char *vaddr; - - vaddr = kmap_atomic(obj->pages[reloc->offset >> PAGE_SHIFT]); - *(uint32_t *)(vaddr + page_offset) = reloc->delta; - kunmap_atomic(vaddr); - } else { - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t __iomem *reloc_entry; - void __iomem *reloc_page; - - ret = i915_gem_object_set_to_gtt_domain(&obj->base, 1); - if (ret) - goto err; - - /* Map the page containing the relocation we're going to perform. */ - reloc->offset += obj->gtt_offset; - reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, - reloc->offset & PAGE_MASK); - reloc_entry = (uint32_t __iomem *) - (reloc_page + (reloc->offset & ~PAGE_MASK)); - iowrite32(reloc->delta, reloc_entry); - io_mapping_unmap_atomic(reloc_page); - } - - /* and update the user's relocation entry */ - reloc->presumed_offset = target_offset; - -out: - ret = 0; -err: - drm_gem_object_unreference(target_obj); - return ret; -} - -static int -i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, - struct drm_file *file_priv, - struct drm_i915_gem_exec_object2 *entry) -{ - struct drm_i915_gem_relocation_entry __user *user_relocs; - int i, ret; - - user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; - for (i = 0; i < entry->relocation_count; i++) { - struct drm_i915_gem_relocation_entry reloc; - - if (__copy_from_user_inatomic(&reloc, - user_relocs+i, - sizeof(reloc))) - return -EFAULT; - - ret = i915_gem_execbuffer_relocate_entry(obj, file_priv, entry, &reloc); - if (ret) - return ret; - - if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset, - &reloc.presumed_offset, - sizeof(reloc.presumed_offset))) - return -EFAULT; - } - - return 0; -} - -static int -i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj, - struct drm_file *file_priv, - struct drm_i915_gem_exec_object2 *entry, - struct drm_i915_gem_relocation_entry *relocs) -{ - int i, ret; - - for (i = 0; i < entry->relocation_count; i++) { - ret = i915_gem_execbuffer_relocate_entry(obj, file_priv, entry, &relocs[i]); - if (ret) - return ret; - } - - return 0; -} - -static int -i915_gem_execbuffer_relocate(struct drm_device *dev, - struct drm_file *file, - struct drm_gem_object **object_list, - struct drm_i915_gem_exec_object2 *exec_list, - int count) -{ - int i, ret; - - for (i = 0; i < count; i++) { - struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); - obj->base.pending_read_domains = 0; - obj->base.pending_write_domain = 0; - ret = i915_gem_execbuffer_relocate_object(obj, file, - &exec_list[i]); - if (ret) - return ret; - } - - return 0; -} - -static int -i915_gem_execbuffer_reserve(struct drm_device *dev, - struct drm_file *file, - struct drm_gem_object **object_list, - struct drm_i915_gem_exec_object2 *exec_list, - int count) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int ret, i, retry; - - /* attempt to pin all of the buffers into the GTT */ - for (retry = 0; retry < 2; retry++) { - ret = 0; - for (i = 0; i < count; i++) { - struct drm_i915_gem_exec_object2 *entry = &exec_list[i]; - struct drm_i915_gem_object *obj= to_intel_bo(object_list[i]); - bool need_fence = - entry->flags & EXEC_OBJECT_NEEDS_FENCE && - obj->tiling_mode != I915_TILING_NONE; - - /* Check fence reg constraints and rebind if necessary */ - if (need_fence && - !i915_gem_object_fence_offset_ok(&obj->base, - obj->tiling_mode)) { - ret = i915_gem_object_unbind(&obj->base); - if (ret) - break; - } - - ret = i915_gem_object_pin(&obj->base, entry->alignment); - if (ret) - break; - - /* - * Pre-965 chips need a fence register set up in order - * to properly handle blits to/from tiled surfaces. - */ - if (need_fence) { - ret = i915_gem_object_get_fence_reg(&obj->base, true); - if (ret) { - i915_gem_object_unpin(&obj->base); - break; - } - - dev_priv->fence_regs[obj->fence_reg].gpu = true; - } - - entry->offset = obj->gtt_offset; - } - - while (i--) - i915_gem_object_unpin(object_list[i]); - - if (ret == 0) - break; - - if (ret != -ENOSPC || retry) - return ret; - - ret = i915_gem_evict_everything(dev); - if (ret) - return ret; - } - - return 0; -} - -static int -i915_gem_execbuffer_relocate_slow(struct drm_device *dev, - struct drm_file *file, - struct drm_gem_object **object_list, - struct drm_i915_gem_exec_object2 *exec_list, - int count) -{ - struct drm_i915_gem_relocation_entry *reloc; - int i, total, ret; - - for (i = 0; i < count; i++) { - struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); - obj->in_execbuffer = false; - } - - mutex_unlock(&dev->struct_mutex); - - total = 0; - for (i = 0; i < count; i++) - total += exec_list[i].relocation_count; - - reloc = drm_malloc_ab(total, sizeof(*reloc)); - if (reloc == NULL) { - mutex_lock(&dev->struct_mutex); - return -ENOMEM; - } - - total = 0; - for (i = 0; i < count; i++) { - struct drm_i915_gem_relocation_entry __user *user_relocs; - - user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; - - if (copy_from_user(reloc+total, user_relocs, - exec_list[i].relocation_count * - sizeof(*reloc))) { - ret = -EFAULT; - mutex_lock(&dev->struct_mutex); - goto err; - } - - total += exec_list[i].relocation_count; - } - - ret = i915_mutex_lock_interruptible(dev); - if (ret) { - mutex_lock(&dev->struct_mutex); - goto err; - } - - ret = i915_gem_execbuffer_reserve(dev, file, - object_list, exec_list, - count); - if (ret) - goto err; - - total = 0; - for (i = 0; i < count; i++) { - struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); - obj->base.pending_read_domains = 0; - obj->base.pending_write_domain = 0; - ret = i915_gem_execbuffer_relocate_object_slow(obj, file, - &exec_list[i], - reloc + total); - if (ret) - goto err; - - total += exec_list[i].relocation_count; - } - - /* Leave the user relocations as are, this is the painfully slow path, - * and we want to avoid the complication of dropping the lock whilst - * having buffers reserved in the aperture and so causing spurious - * ENOSPC for random operations. - */ - -err: - drm_free_large(reloc); - return ret; -} - -static int -i915_gem_execbuffer_move_to_gpu(struct drm_device *dev, - struct drm_file *file, - struct intel_ring_buffer *ring, - struct drm_gem_object **objects, - int count) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - int ret, i; - - /* Zero the global flush/invalidate flags. These - * will be modified as new domains are computed - * for each object - */ - dev->invalidate_domains = 0; - dev->flush_domains = 0; - dev_priv->mm.flush_rings = 0; - for (i = 0; i < count; i++) - i915_gem_object_set_to_gpu_domain(objects[i], ring); - - if (dev->invalidate_domains | dev->flush_domains) { -#if WATCH_EXEC - DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", - __func__, - dev->invalidate_domains, - dev->flush_domains); -#endif - i915_gem_flush(dev, file, - dev->invalidate_domains, - dev->flush_domains, - dev_priv->mm.flush_rings); - } - - for (i = 0; i < count; i++) { - struct drm_i915_gem_object *obj = to_intel_bo(objects[i]); - /* XXX replace with semaphores */ - if (obj->ring && ring != obj->ring) { - ret = i915_gem_object_wait_rendering(&obj->base, true); - if (ret) - return ret; - } - } - - return 0; -} - -/* Throttle our rendering by waiting until the ring has completed our requests - * emitted over 20 msec ago. - * - * Note that if we were to use the current jiffies each time around the loop, - * we wouldn't escape the function with any frames outstanding if the time to - * render a frame was over 20ms. - * - * This should get us reasonable parallelism between CPU and GPU but also - * relatively low latency when blocking on a particular request to finish. - */ -static int -i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_file_private *file_priv = file->driver_priv; - unsigned long recent_enough = jiffies - msecs_to_jiffies(20); - struct drm_i915_gem_request *request; - struct intel_ring_buffer *ring = NULL; - u32 seqno = 0; - int ret; - - spin_lock(&file_priv->mm.lock); - list_for_each_entry(request, &file_priv->mm.request_list, client_list) { - if (time_after_eq(request->emitted_jiffies, recent_enough)) - break; - - ring = request->ring; - seqno = request->seqno; - } - spin_unlock(&file_priv->mm.lock); - - if (seqno == 0) - return 0; - - ret = 0; - if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) { - /* And wait for the seqno passing without holding any locks and - * causing extra latency for others. This is safe as the irq - * generation is designed to be run atomically and so is - * lockless. - */ - ring->user_irq_get(dev, ring); - ret = wait_event_interruptible(ring->irq_queue, - i915_seqno_passed(ring->get_seqno(dev, ring), seqno) - || atomic_read(&dev_priv->mm.wedged)); - ring->user_irq_put(dev, ring); - - if (ret == 0 && atomic_read(&dev_priv->mm.wedged)) - ret = -EIO; - } - - if (ret == 0) - queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); - - return ret; -} - -static int -i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec, - uint64_t exec_offset) -{ - uint32_t exec_start, exec_len; - - exec_start = (uint32_t) exec_offset + exec->batch_start_offset; - exec_len = (uint32_t) exec->batch_len; - - if ((exec_start | exec_len) & 0x7) - return -EINVAL; - - if (!exec_start) - return -EINVAL; - - return 0; -} - -static int -validate_exec_list(struct drm_i915_gem_exec_object2 *exec, - int count) -{ - int i; - - for (i = 0; i < count; i++) { - char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; - int length; /* limited by fault_in_pages_readable() */ - - /* First check for malicious input causing overflow */ - if (exec[i].relocation_count > - INT_MAX / sizeof(struct drm_i915_gem_relocation_entry)) - return -EINVAL; - - length = exec[i].relocation_count * - sizeof(struct drm_i915_gem_relocation_entry); - if (!access_ok(VERIFY_READ, ptr, length)) - return -EFAULT; - - /* we may also need to update the presumed offsets */ - if (!access_ok(VERIFY_WRITE, ptr, length)) - return -EFAULT; - - if (fault_in_pages_readable(ptr, length)) - return -EFAULT; - } - - return 0; -} - -static int -i915_gem_do_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file, - struct drm_i915_gem_execbuffer2 *args, - struct drm_i915_gem_exec_object2 *exec_list) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_gem_object **object_list = NULL; - struct drm_gem_object *batch_obj; - struct drm_i915_gem_object *obj_priv; - struct drm_clip_rect *cliprects = NULL; - struct drm_i915_gem_request *request = NULL; - int ret, i, flips; - uint64_t exec_offset; - - struct intel_ring_buffer *ring = NULL; - - ret = i915_gem_check_is_wedged(dev); - if (ret) - return ret; - - ret = validate_exec_list(exec_list, args->buffer_count); - if (ret) - return ret; - -#if WATCH_EXEC - DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", - (int) args->buffers_ptr, args->buffer_count, args->batch_len); -#endif - switch (args->flags & I915_EXEC_RING_MASK) { - case I915_EXEC_DEFAULT: - case I915_EXEC_RENDER: - ring = &dev_priv->render_ring; - break; - case I915_EXEC_BSD: - if (!HAS_BSD(dev)) { - DRM_ERROR("execbuf with invalid ring (BSD)\n"); - return -EINVAL; - } - ring = &dev_priv->bsd_ring; - break; - case I915_EXEC_BLT: - if (!HAS_BLT(dev)) { - DRM_ERROR("execbuf with invalid ring (BLT)\n"); - return -EINVAL; - } - ring = &dev_priv->blt_ring; - break; - default: - DRM_ERROR("execbuf with unknown ring: %d\n", - (int)(args->flags & I915_EXEC_RING_MASK)); - return -EINVAL; - } - - if (args->buffer_count < 1) { - DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); - return -EINVAL; - } - object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count); - if (object_list == NULL) { - DRM_ERROR("Failed to allocate object list for %d buffers\n", - args->buffer_count); - ret = -ENOMEM; - goto pre_mutex_err; - } - - if (args->num_cliprects != 0) { - cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects), - GFP_KERNEL); - if (cliprects == NULL) { - ret = -ENOMEM; - goto pre_mutex_err; - } - - ret = copy_from_user(cliprects, - (struct drm_clip_rect __user *) - (uintptr_t) args->cliprects_ptr, - sizeof(*cliprects) * args->num_cliprects); - if (ret != 0) { - DRM_ERROR("copy %d cliprects failed: %d\n", - args->num_cliprects, ret); - ret = -EFAULT; - goto pre_mutex_err; - } - } - - request = kzalloc(sizeof(*request), GFP_KERNEL); - if (request == NULL) { - ret = -ENOMEM; - goto pre_mutex_err; - } - - ret = i915_mutex_lock_interruptible(dev); - if (ret) - goto pre_mutex_err; - - if (dev_priv->mm.suspended) { - mutex_unlock(&dev->struct_mutex); - ret = -EBUSY; - goto pre_mutex_err; - } - - /* Look up object handles */ - for (i = 0; i < args->buffer_count; i++) { - object_list[i] = drm_gem_object_lookup(dev, file, - exec_list[i].handle); - if (object_list[i] == NULL) { - DRM_ERROR("Invalid object handle %d at index %d\n", - exec_list[i].handle, i); - /* prevent error path from reading uninitialized data */ - args->buffer_count = i + 1; - ret = -ENOENT; - goto err; - } - - obj_priv = to_intel_bo(object_list[i]); - if (obj_priv->in_execbuffer) { - DRM_ERROR("Object %p appears more than once in object list\n", - object_list[i]); - /* prevent error path from reading uninitialized data */ - args->buffer_count = i + 1; - ret = -EINVAL; - goto err; - } - obj_priv->in_execbuffer = true; - } - - /* Move the objects en-masse into the GTT, evicting if necessary. */ - ret = i915_gem_execbuffer_reserve(dev, file, - object_list, exec_list, - args->buffer_count); - if (ret) - goto err; - - /* The objects are in their final locations, apply the relocations. */ - ret = i915_gem_execbuffer_relocate(dev, file, - object_list, exec_list, - args->buffer_count); - if (ret) { - if (ret == -EFAULT) { - ret = i915_gem_execbuffer_relocate_slow(dev, file, - object_list, - exec_list, - args->buffer_count); - BUG_ON(!mutex_is_locked(&dev->struct_mutex)); - } - if (ret) - goto err; - } - - /* Set the pending read domains for the batch buffer to COMMAND */ - batch_obj = object_list[args->buffer_count-1]; - if (batch_obj->pending_write_domain) { - DRM_ERROR("Attempting to use self-modifying batch buffer\n"); - ret = -EINVAL; - goto err; - } - batch_obj->pending_read_domains |= I915_GEM_DOMAIN_COMMAND; - - /* Sanity check the batch buffer */ - exec_offset = to_intel_bo(batch_obj)->gtt_offset; - ret = i915_gem_check_execbuffer(args, exec_offset); - if (ret != 0) { - DRM_ERROR("execbuf with invalid offset/length\n"); - goto err; - } - - ret = i915_gem_execbuffer_move_to_gpu(dev, file, ring, - object_list, args->buffer_count); - if (ret) - goto err; - - for (i = 0; i < args->buffer_count; i++) { - struct drm_gem_object *obj = object_list[i]; - uint32_t old_write_domain = obj->write_domain; - obj->write_domain = obj->pending_write_domain; - trace_i915_gem_object_change_domain(obj, - obj->read_domains, - old_write_domain); - } - -#if WATCH_COHERENCY - for (i = 0; i < args->buffer_count; i++) { - i915_gem_object_check_coherency(object_list[i], - exec_list[i].handle); - } -#endif - -#if WATCH_EXEC - i915_gem_dump_object(batch_obj, - args->batch_len, - __func__, - ~0); -#endif - - /* Check for any pending flips. As we only maintain a flip queue depth - * of 1, we can simply insert a WAIT for the next display flip prior - * to executing the batch and avoid stalling the CPU. - */ - flips = 0; - for (i = 0; i < args->buffer_count; i++) { - if (object_list[i]->write_domain) - flips |= atomic_read(&to_intel_bo(object_list[i])->pending_flip); - } - if (flips) { - int plane, flip_mask; - - for (plane = 0; flips >> plane; plane++) { - if (((flips >> plane) & 1) == 0) - continue; - - if (plane) - flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; - else - flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; - - intel_ring_begin(dev, ring, 2); - intel_ring_emit(dev, ring, - MI_WAIT_FOR_EVENT | flip_mask); - intel_ring_emit(dev, ring, MI_NOOP); - intel_ring_advance(dev, ring); - } - } - - /* Exec the batchbuffer */ - ret = ring->dispatch_gem_execbuffer(dev, ring, args, - cliprects, exec_offset); - if (ret) { - DRM_ERROR("dispatch failed %d\n", ret); - goto err; + for (i = 0; i <= (obj->base.size - 1) / PAGE_SIZE; i++) { + if (obj->page_cpu_valid[i]) + continue; + drm_clflush_pages(obj->pages + i, 1); + } } - /* - * Ensure that the commands in the batch buffer are - * finished before the interrupt fires + /* Free the page_cpu_valid mappings which are now stale, whether + * or not we've got I915_GEM_DOMAIN_CPU. */ - i915_retire_commands(dev, ring); - - for (i = 0; i < args->buffer_count; i++) { - struct drm_gem_object *obj = object_list[i]; + kfree(obj->page_cpu_valid); + obj->page_cpu_valid = NULL; +} - i915_gem_object_move_to_active(obj, ring); - if (obj->write_domain) - list_move_tail(&to_intel_bo(obj)->gpu_write_list, - &ring->gpu_write_list); - } +/** + * Set the CPU read domain on a range of the object. + * + * The object ends up with I915_GEM_DOMAIN_CPU in its read flags although it's + * not entirely valid. The page_cpu_valid member of the object flags which + * pages have been flushed, and will be respected by + * i915_gem_object_set_to_cpu_domain() if it's called on to get a valid mapping + * of the whole object. + * + * This function returns when the move is complete, including waiting on + * flushes to occur. + */ +static int +i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj, + uint64_t offset, uint64_t size) +{ + uint32_t old_read_domains; + int i, ret; - i915_add_request(dev, file, request, ring); - request = NULL; + if (offset == 0 && size == obj->base.size) + return i915_gem_object_set_to_cpu_domain(obj, 0); -err: - for (i = 0; i < args->buffer_count; i++) { - if (object_list[i]) { - obj_priv = to_intel_bo(object_list[i]); - obj_priv->in_execbuffer = false; - } - drm_gem_object_unreference(object_list[i]); - } + i915_gem_object_flush_gpu_write_domain(obj); + ret = i915_gem_object_wait_rendering(obj, true); + if (ret) + return ret; - mutex_unlock(&dev->struct_mutex); + i915_gem_object_flush_gtt_write_domain(obj); -pre_mutex_err: - drm_free_large(object_list); - kfree(cliprects); - kfree(request); + /* If we're already fully in the CPU read domain, we're done. */ + if (obj->page_cpu_valid == NULL && + (obj->base.read_domains & I915_GEM_DOMAIN_CPU) != 0) + return 0; - return ret; -} + /* Otherwise, create/clear the per-page CPU read domain flag if we're + * newly adding I915_GEM_DOMAIN_CPU + */ + if (obj->page_cpu_valid == NULL) { + obj->page_cpu_valid = kzalloc(obj->base.size / PAGE_SIZE, + GFP_KERNEL); + if (obj->page_cpu_valid == NULL) + return -ENOMEM; + } else if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0) + memset(obj->page_cpu_valid, 0, obj->base.size / PAGE_SIZE); -/* - * Legacy execbuffer just creates an exec2 list from the original exec object - * list array and passes it to the real function. - */ -int -i915_gem_execbuffer(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_i915_gem_execbuffer *args = data; - struct drm_i915_gem_execbuffer2 exec2; - struct drm_i915_gem_exec_object *exec_list = NULL; - struct drm_i915_gem_exec_object2 *exec2_list = NULL; - int ret, i; + /* Flush the cache on any pages that are still invalid from the CPU's + * perspective. + */ + for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE; + i++) { + if (obj->page_cpu_valid[i]) + continue; -#if WATCH_EXEC - DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", - (int) args->buffers_ptr, args->buffer_count, args->batch_len); -#endif + drm_clflush_pages(obj->pages + i, 1); - if (args->buffer_count < 1) { - DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); - return -EINVAL; + obj->page_cpu_valid[i] = 1; } - /* Copy in the exec list from userland */ - exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count); - exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); - if (exec_list == NULL || exec2_list == NULL) { - DRM_ERROR("Failed to allocate exec list for %d buffers\n", - args->buffer_count); - drm_free_large(exec_list); - drm_free_large(exec2_list); - return -ENOMEM; - } - ret = copy_from_user(exec_list, - (struct drm_i915_relocation_entry __user *) - (uintptr_t) args->buffers_ptr, - sizeof(*exec_list) * args->buffer_count); - if (ret != 0) { - DRM_ERROR("copy %d exec entries failed %d\n", - args->buffer_count, ret); - drm_free_large(exec_list); - drm_free_large(exec2_list); - return -EFAULT; - } + /* It should now be out of any other write domains, and we can update + * the domain values for our changes. + */ + BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0); - for (i = 0; i < args->buffer_count; i++) { - exec2_list[i].handle = exec_list[i].handle; - exec2_list[i].relocation_count = exec_list[i].relocation_count; - exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr; - exec2_list[i].alignment = exec_list[i].alignment; - exec2_list[i].offset = exec_list[i].offset; - if (INTEL_INFO(dev)->gen < 4) - exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE; - else - exec2_list[i].flags = 0; - } + old_read_domains = obj->base.read_domains; + obj->base.read_domains |= I915_GEM_DOMAIN_CPU; - exec2.buffers_ptr = args->buffers_ptr; - exec2.buffer_count = args->buffer_count; - exec2.batch_start_offset = args->batch_start_offset; - exec2.batch_len = args->batch_len; - exec2.DR1 = args->DR1; - exec2.DR4 = args->DR4; - exec2.num_cliprects = args->num_cliprects; - exec2.cliprects_ptr = args->cliprects_ptr; - exec2.flags = I915_EXEC_RENDER; - - ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list); - if (!ret) { - /* Copy the new buffer offsets back to the user's exec list. */ - for (i = 0; i < args->buffer_count; i++) - exec_list[i].offset = exec2_list[i].offset; - /* ... and back out to userspace */ - ret = copy_to_user((struct drm_i915_relocation_entry __user *) - (uintptr_t) args->buffers_ptr, - exec_list, - sizeof(*exec_list) * args->buffer_count); - if (ret) { - ret = -EFAULT; - DRM_ERROR("failed to copy %d exec entries " - "back to user (%d)\n", - args->buffer_count, ret); - } - } + trace_i915_gem_object_change_domain(obj, + old_read_domains, + obj->base.write_domain); - drm_free_large(exec_list); - drm_free_large(exec2_list); - return ret; + return 0; } -int -i915_gem_execbuffer2(struct drm_device *dev, void *data, - struct drm_file *file_priv) +/* Throttle our rendering by waiting until the ring has completed our requests + * emitted over 20 msec ago. + * + * Note that if we were to use the current jiffies each time around the loop, + * we wouldn't escape the function with any frames outstanding if the time to + * render a frame was over 20ms. + * + * This should get us reasonable parallelism between CPU and GPU but also + * relatively low latency when blocking on a particular request to finish. + */ +static int +i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) { - struct drm_i915_gem_execbuffer2 *args = data; - struct drm_i915_gem_exec_object2 *exec2_list = NULL; + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_file_private *file_priv = file->driver_priv; + unsigned long recent_enough = jiffies - msecs_to_jiffies(20); + struct drm_i915_gem_request *request; + struct intel_ring_buffer *ring = NULL; + u32 seqno = 0; int ret; -#if WATCH_EXEC - DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", - (int) args->buffers_ptr, args->buffer_count, args->batch_len); -#endif + spin_lock(&file_priv->mm.lock); + list_for_each_entry(request, &file_priv->mm.request_list, client_list) { + if (time_after_eq(request->emitted_jiffies, recent_enough)) + break; - if (args->buffer_count < 1) { - DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count); - return -EINVAL; + ring = request->ring; + seqno = request->seqno; } + spin_unlock(&file_priv->mm.lock); - exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); - if (exec2_list == NULL) { - DRM_ERROR("Failed to allocate exec list for %d buffers\n", - args->buffer_count); - return -ENOMEM; - } - ret = copy_from_user(exec2_list, - (struct drm_i915_relocation_entry __user *) - (uintptr_t) args->buffers_ptr, - sizeof(*exec2_list) * args->buffer_count); - if (ret != 0) { - DRM_ERROR("copy %d exec entries failed %d\n", - args->buffer_count, ret); - drm_free_large(exec2_list); - return -EFAULT; - } + if (seqno == 0) + return 0; - ret = i915_gem_do_execbuffer(dev, data, file_priv, args, exec2_list); - if (!ret) { - /* Copy the new buffer offsets back to the user's exec list. */ - ret = copy_to_user((struct drm_i915_relocation_entry __user *) - (uintptr_t) args->buffers_ptr, - exec2_list, - sizeof(*exec2_list) * args->buffer_count); - if (ret) { - ret = -EFAULT; - DRM_ERROR("failed to copy %d exec entries " - "back to user (%d)\n", - args->buffer_count, ret); + ret = 0; + if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) { + /* And wait for the seqno passing without holding any locks and + * causing extra latency for others. This is safe as the irq + * generation is designed to be run atomically and so is + * lockless. + */ + if (ring->irq_get(ring)) { + ret = wait_event_interruptible(ring->irq_queue, + i915_seqno_passed(ring->get_seqno(ring), seqno) + || atomic_read(&dev_priv->mm.wedged)); + ring->irq_put(ring); + + if (ret == 0 && atomic_read(&dev_priv->mm.wedged)) + ret = -EIO; } } - drm_free_large(exec2_list); + if (ret == 0) + queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); + return ret; } int -i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) +i915_gem_object_pin(struct drm_i915_gem_object *obj, + uint32_t alignment, + bool map_and_fenceable) { - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); int ret; - BUG_ON(obj_priv->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); + BUG_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); WARN_ON(i915_verify_lists(dev)); - if (obj_priv->gtt_space != NULL) { - if (alignment == 0) - alignment = i915_gem_get_gtt_alignment(obj); - if (obj_priv->gtt_offset & (alignment - 1)) { - WARN(obj_priv->pin_count, - "bo is already pinned with incorrect alignment: offset=%x, req.alignment=%x\n", - obj_priv->gtt_offset, alignment); + if (obj->gtt_space != NULL) { + if ((alignment && obj->gtt_offset & (alignment - 1)) || + (map_and_fenceable && !obj->map_and_fenceable)) { + WARN(obj->pin_count, + "bo is already pinned with incorrect alignment:" + " offset=%x, req.alignment=%x, req.map_and_fenceable=%d," + " obj->map_and_fenceable=%d\n", + obj->gtt_offset, alignment, + map_and_fenceable, + obj->map_and_fenceable); ret = i915_gem_object_unbind(obj); if (ret) return ret; } } - if (obj_priv->gtt_space == NULL) { - ret = i915_gem_object_bind_to_gtt(obj, alignment); + if (obj->gtt_space == NULL) { + ret = i915_gem_object_bind_to_gtt(obj, alignment, + map_and_fenceable); if (ret) return ret; } - obj_priv->pin_count++; - - /* If the object is not active and not pending a flush, - * remove it from the inactive list - */ - if (obj_priv->pin_count == 1) { - i915_gem_info_add_pin(dev_priv, obj->size); - if (!obj_priv->active) - list_move_tail(&obj_priv->mm_list, + if (obj->pin_count++ == 0) { + if (!obj->active) + list_move_tail(&obj->mm_list, &dev_priv->mm.pinned_list); } + obj->pin_mappable |= map_and_fenceable; WARN_ON(i915_verify_lists(dev)); return 0; } void -i915_gem_object_unpin(struct drm_gem_object *obj) +i915_gem_object_unpin(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); WARN_ON(i915_verify_lists(dev)); - obj_priv->pin_count--; - BUG_ON(obj_priv->pin_count < 0); - BUG_ON(obj_priv->gtt_space == NULL); - - /* If the object is no longer pinned, and is - * neither active nor being flushed, then stick it on - * the inactive list - */ - if (obj_priv->pin_count == 0) { - if (!obj_priv->active) - list_move_tail(&obj_priv->mm_list, + BUG_ON(obj->pin_count == 0); + BUG_ON(obj->gtt_space == NULL); + + if (--obj->pin_count == 0) { + if (!obj->active) + list_move_tail(&obj->mm_list, &dev_priv->mm.inactive_list); - i915_gem_info_remove_pin(dev_priv, obj->size); + obj->pin_mappable = false; } WARN_ON(i915_verify_lists(dev)); } int i915_gem_pin_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { struct drm_i915_gem_pin *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int ret; ret = i915_mutex_lock_interruptible(dev); if (ret) return ret; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (obj == NULL) { ret = -ENOENT; goto unlock; } - obj_priv = to_intel_bo(obj); - if (obj_priv->madv != I915_MADV_WILLNEED) { + if (obj->madv != I915_MADV_WILLNEED) { DRM_ERROR("Attempting to pin a purgeable buffer\n"); ret = -EINVAL; goto out; } - if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { + if (obj->pin_filp != NULL && obj->pin_filp != file) { DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", args->handle); ret = -EINVAL; goto out; } - obj_priv->user_pin_count++; - obj_priv->pin_filp = file_priv; - if (obj_priv->user_pin_count == 1) { - ret = i915_gem_object_pin(obj, args->alignment); + obj->user_pin_count++; + obj->pin_filp = file; + if (obj->user_pin_count == 1) { + ret = i915_gem_object_pin(obj, args->alignment, true); if (ret) goto out; } @@ -4295,9 +3295,9 @@ * as the X server doesn't manage domains yet */ i915_gem_object_flush_cpu_write_domain(obj); - args->offset = obj_priv->gtt_offset; + args->offset = obj->gtt_offset; out: - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); unlock: mutex_unlock(&dev->struct_mutex); return ret; @@ -4305,38 +3305,36 @@ int i915_gem_unpin_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { struct drm_i915_gem_pin *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int ret; ret = i915_mutex_lock_interruptible(dev); if (ret) return ret; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (obj == NULL) { ret = -ENOENT; goto unlock; } - obj_priv = to_intel_bo(obj); - if (obj_priv->pin_filp != file_priv) { + if (obj->pin_filp != file) { DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n", args->handle); ret = -EINVAL; goto out; } - obj_priv->user_pin_count--; - if (obj_priv->user_pin_count == 0) { - obj_priv->pin_filp = NULL; + obj->user_pin_count--; + if (obj->user_pin_count == 0) { + obj->pin_filp = NULL; i915_gem_object_unpin(obj); } out: - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); unlock: mutex_unlock(&dev->struct_mutex); return ret; @@ -4344,48 +3342,50 @@ int i915_gem_busy_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { struct drm_i915_gem_busy *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int ret; ret = i915_mutex_lock_interruptible(dev); if (ret) return ret; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (obj == NULL) { ret = -ENOENT; goto unlock; } - obj_priv = to_intel_bo(obj); /* Count all active objects as busy, even if they are currently not used * by the gpu. Users of this interface expect objects to eventually * become non-busy without any further actions, therefore emit any * necessary flushes here. */ - args->busy = obj_priv->active; + args->busy = obj->active; if (args->busy) { /* Unconditionally flush objects, even when the gpu still uses this * object. Userspace calling this function indicates that it wants to * use this buffer rather sooner than later, so issuing the required * flush earlier is beneficial. */ - if (obj->write_domain & I915_GEM_GPU_DOMAINS) { - i915_gem_flush_ring(dev, file_priv, - obj_priv->ring, - 0, obj->write_domain); - } else if (obj_priv->ring->outstanding_lazy_request) { + if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) { + i915_gem_flush_ring(dev, obj->ring, + 0, obj->base.write_domain); + } else if (obj->ring->outstanding_lazy_request == + obj->last_rendering_seqno) { + struct drm_i915_gem_request *request; + /* This ring is not being cleared by active usage, * so emit a request to do so. */ - u32 seqno = i915_add_request(dev, - NULL, NULL, - obj_priv->ring); - if (seqno == 0) + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (request) + ret = i915_add_request(dev, + NULL, request, + obj->ring); + else ret = -ENOMEM; } @@ -4394,12 +3394,12 @@ * are actually unmasked, and our working set ends up being * larger than required. */ - i915_gem_retire_requests_ring(dev, obj_priv->ring); + i915_gem_retire_requests_ring(dev, obj->ring); - args->busy = obj_priv->active; + args->busy = obj->active; } - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); unlock: mutex_unlock(&dev->struct_mutex); return ret; @@ -4417,8 +3417,7 @@ struct drm_file *file_priv) { struct drm_i915_gem_madvise *args = data; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int ret; switch (args->madv) { @@ -4433,37 +3432,36 @@ if (ret) return ret; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, file_priv, args->handle)); if (obj == NULL) { ret = -ENOENT; goto unlock; } - obj_priv = to_intel_bo(obj); - if (obj_priv->pin_count) { + if (obj->pin_count) { ret = -EINVAL; goto out; } - if (obj_priv->madv != __I915_MADV_PURGED) - obj_priv->madv = args->madv; + if (obj->madv != __I915_MADV_PURGED) + obj->madv = args->madv; /* if the object is no longer bound, discard its backing storage */ - if (i915_gem_object_is_purgeable(obj_priv) && - obj_priv->gtt_space == NULL) + if (i915_gem_object_is_purgeable(obj) && + obj->gtt_space == NULL) i915_gem_object_truncate(obj); - args->retained = obj_priv->madv != __I915_MADV_PURGED; + args->retained = obj->madv != __I915_MADV_PURGED; out: - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); unlock: mutex_unlock(&dev->struct_mutex); return ret; } -struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev, - size_t size) +struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, + size_t size) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; @@ -4486,11 +3484,15 @@ obj->base.driver_private = NULL; obj->fence_reg = I915_FENCE_REG_NONE; INIT_LIST_HEAD(&obj->mm_list); + INIT_LIST_HEAD(&obj->gtt_list); INIT_LIST_HEAD(&obj->ring_list); + INIT_LIST_HEAD(&obj->exec_list); INIT_LIST_HEAD(&obj->gpu_write_list); obj->madv = I915_MADV_WILLNEED; + /* Avoid an unnecessary call to unbind on the first bind. */ + obj->map_and_fenceable = true; - return &obj->base; + return obj; } int i915_gem_init_object(struct drm_gem_object *obj) @@ -4500,42 +3502,41 @@ return 0; } -static void i915_gem_free_object_tail(struct drm_gem_object *obj) +static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); int ret; ret = i915_gem_object_unbind(obj); if (ret == -ERESTARTSYS) { - list_move(&obj_priv->mm_list, + list_move(&obj->mm_list, &dev_priv->mm.deferred_free_list); return; } - if (obj_priv->mmap_offset) + if (obj->base.map_list.map) i915_gem_free_mmap_offset(obj); - drm_gem_object_release(obj); - i915_gem_info_remove_obj(dev_priv, obj->size); + drm_gem_object_release(&obj->base); + i915_gem_info_remove_obj(dev_priv, obj->base.size); - kfree(obj_priv->page_cpu_valid); - kfree(obj_priv->bit_17); - kfree(obj_priv); + kfree(obj->page_cpu_valid); + kfree(obj->bit_17); + kfree(obj); } -void i915_gem_free_object(struct drm_gem_object *obj) +void i915_gem_free_object(struct drm_gem_object *gem_obj) { - struct drm_device *dev = obj->dev; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); + struct drm_device *dev = obj->base.dev; trace_i915_gem_object_destroy(obj); - while (obj_priv->pin_count > 0) + while (obj->pin_count > 0) i915_gem_object_unpin(obj); - if (obj_priv->phys_obj) + if (obj->phys_obj) i915_gem_detach_phys_object(dev, obj); i915_gem_free_object_tail(obj); @@ -4562,13 +3563,15 @@ /* Under UMS, be paranoid and evict. */ if (!drm_core_check_feature(dev, DRIVER_MODESET)) { - ret = i915_gem_evict_inactive(dev); + ret = i915_gem_evict_inactive(dev, false); if (ret) { mutex_unlock(&dev->struct_mutex); return ret; } } + i915_gem_reset_fences(dev); + /* Hack! Don't let anybody do execbuf while we don't control the chip. * We need to replace this with a semaphore, or something. * And not confound mm.suspended! @@ -4587,82 +3590,15 @@ return 0; } -/* - * 965+ support PIPE_CONTROL commands, which provide finer grained control - * over cache flushing. - */ -static int -i915_gem_init_pipe_control(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; - int ret; - - obj = i915_gem_alloc_object(dev, 4096); - if (obj == NULL) { - DRM_ERROR("Failed to allocate seqno page\n"); - ret = -ENOMEM; - goto err; - } - obj_priv = to_intel_bo(obj); - obj_priv->agp_type = AGP_USER_CACHED_MEMORY; - - ret = i915_gem_object_pin(obj, 4096); - if (ret) - goto err_unref; - - dev_priv->seqno_gfx_addr = obj_priv->gtt_offset; - dev_priv->seqno_page = kmap(obj_priv->pages[0]); - if (dev_priv->seqno_page == NULL) - goto err_unpin; - - dev_priv->seqno_obj = obj; - memset(dev_priv->seqno_page, 0, PAGE_SIZE); - - return 0; - -err_unpin: - i915_gem_object_unpin(obj); -err_unref: - drm_gem_object_unreference(obj); -err: - return ret; -} - - -static void -i915_gem_cleanup_pipe_control(struct drm_device *dev) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; - - obj = dev_priv->seqno_obj; - obj_priv = to_intel_bo(obj); - kunmap(obj_priv->pages[0]); - i915_gem_object_unpin(obj); - drm_gem_object_unreference(obj); - dev_priv->seqno_obj = NULL; - - dev_priv->seqno_page = NULL; -} - int i915_gem_init_ringbuffer(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; int ret; - if (HAS_PIPE_CONTROL(dev)) { - ret = i915_gem_init_pipe_control(dev); - if (ret) - return ret; - } - ret = intel_init_render_ring_buffer(dev); if (ret) - goto cleanup_pipe_control; + return ret; if (HAS_BSD(dev)) { ret = intel_init_bsd_ring_buffer(dev); @@ -4681,12 +3617,9 @@ return 0; cleanup_bsd_ring: - intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); + intel_cleanup_ring_buffer(&dev_priv->ring[VCS]); cleanup_render_ring: - intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); -cleanup_pipe_control: - if (HAS_PIPE_CONTROL(dev)) - i915_gem_cleanup_pipe_control(dev); + intel_cleanup_ring_buffer(&dev_priv->ring[RCS]); return ret; } @@ -4694,12 +3627,10 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + int i; - intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); - intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); - intel_cleanup_ring_buffer(dev, &dev_priv->blt_ring); - if (HAS_PIPE_CONTROL(dev)) - i915_gem_cleanup_pipe_control(dev); + for (i = 0; i < I915_NUM_RINGS; i++) + intel_cleanup_ring_buffer(&dev_priv->ring[i]); } int @@ -4707,7 +3638,7 @@ struct drm_file *file_priv) { drm_i915_private_t *dev_priv = dev->dev_private; - int ret; + int ret, i; if (drm_core_check_feature(dev, DRIVER_MODESET)) return 0; @@ -4727,14 +3658,12 @@ } BUG_ON(!list_empty(&dev_priv->mm.active_list)); - BUG_ON(!list_empty(&dev_priv->render_ring.active_list)); - BUG_ON(!list_empty(&dev_priv->bsd_ring.active_list)); - BUG_ON(!list_empty(&dev_priv->blt_ring.active_list)); BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); - BUG_ON(!list_empty(&dev_priv->render_ring.request_list)); - BUG_ON(!list_empty(&dev_priv->bsd_ring.request_list)); - BUG_ON(!list_empty(&dev_priv->blt_ring.request_list)); + for (i = 0; i < I915_NUM_RINGS; i++) { + BUG_ON(!list_empty(&dev_priv->ring[i].active_list)); + BUG_ON(!list_empty(&dev_priv->ring[i].request_list)); + } mutex_unlock(&dev->struct_mutex); ret = drm_irq_install(dev); @@ -4796,17 +3725,14 @@ INIT_LIST_HEAD(&dev_priv->mm.pinned_list); INIT_LIST_HEAD(&dev_priv->mm.fence_list); INIT_LIST_HEAD(&dev_priv->mm.deferred_free_list); - init_ring_lists(&dev_priv->render_ring); - init_ring_lists(&dev_priv->bsd_ring); - init_ring_lists(&dev_priv->blt_ring); + INIT_LIST_HEAD(&dev_priv->mm.gtt_list); + for (i = 0; i < I915_NUM_RINGS; i++) + init_ring_lists(&dev_priv->ring[i]); for (i = 0; i < 16; i++) INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); INIT_DELAYED_WORK(&dev_priv->mm.retire_work, i915_gem_retire_work_handler); init_completion(&dev_priv->error_completion); - spin_lock(&shrink_list_lock); - list_add(&dev_priv->mm.shrink_list, &shrink_list); - spin_unlock(&shrink_list_lock); /* On GEN3 we really need to make sure the ARB C3 LP bit is set */ if (IS_GEN3(dev)) { @@ -4818,6 +3744,8 @@ } } + dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL; + /* Old X drivers will take 0-2 for front, back, depth buffers */ if (!drm_core_check_feature(dev, DRIVER_MODESET)) dev_priv->fence_reg_start = 3; @@ -4849,6 +3777,10 @@ } i915_gem_detect_bit_6_swizzle(dev); init_waitqueue_head(&dev_priv->pending_flip_queue); + + dev_priv->mm.inactive_shrinker.shrink = i915_gem_inactive_shrink; + dev_priv->mm.inactive_shrinker.seeks = DEFAULT_SEEKS; + register_shrinker(&dev_priv->mm.inactive_shrinker); } /* @@ -4918,47 +3850,47 @@ } void i915_gem_detach_phys_object(struct drm_device *dev, - struct drm_gem_object *obj) + struct drm_i915_gem_object *obj) { - struct drm_i915_gem_object *obj_priv; + struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; + char *vaddr; int i; - int ret; int page_count; - obj_priv = to_intel_bo(obj); - if (!obj_priv->phys_obj) + if (!obj->phys_obj) return; + vaddr = obj->phys_obj->handle->vaddr; - ret = i915_gem_object_get_pages(obj, 0); - if (ret) - goto out; - - page_count = obj->size / PAGE_SIZE; - + page_count = obj->base.size / PAGE_SIZE; for (i = 0; i < page_count; i++) { - char *dst = kmap_atomic(obj_priv->pages[i]); - char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); + struct page *page = read_cache_page_gfp(mapping, i, + GFP_HIGHUSER | __GFP_RECLAIMABLE); + if (!IS_ERR(page)) { + char *dst = kmap_atomic(page); + memcpy(dst, vaddr + i*PAGE_SIZE, PAGE_SIZE); + kunmap_atomic(dst); - memcpy(dst, src, PAGE_SIZE); - kunmap_atomic(dst); + drm_clflush_pages(&page, 1); + + set_page_dirty(page); + mark_page_accessed(page); + page_cache_release(page); + } } - drm_clflush_pages(obj_priv->pages, page_count); - drm_agp_chipset_flush(dev); + intel_gtt_chipset_flush(); - i915_gem_object_put_pages(obj); -out: - obj_priv->phys_obj->cur_obj = NULL; - obj_priv->phys_obj = NULL; + obj->phys_obj->cur_obj = NULL; + obj->phys_obj = NULL; } int i915_gem_attach_phys_object(struct drm_device *dev, - struct drm_gem_object *obj, + struct drm_i915_gem_object *obj, int id, int align) { + struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; int ret = 0; int page_count; int i; @@ -4966,10 +3898,8 @@ if (id > I915_MAX_PHYS_OBJECT) return -EINVAL; - obj_priv = to_intel_bo(obj); - - if (obj_priv->phys_obj) { - if (obj_priv->phys_obj->id == id) + if (obj->phys_obj) { + if (obj->phys_obj->id == id) return 0; i915_gem_detach_phys_object(dev, obj); } @@ -4977,51 +3907,50 @@ /* create a new object */ if (!dev_priv->mm.phys_objs[id - 1]) { ret = i915_gem_init_phys_object(dev, id, - obj->size, align); + obj->base.size, align); if (ret) { - DRM_ERROR("failed to init phys object %d size: %zu\n", id, obj->size); - goto out; + DRM_ERROR("failed to init phys object %d size: %zu\n", + id, obj->base.size); + return ret; } } /* bind to the object */ - obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1]; - obj_priv->phys_obj->cur_obj = obj; - - ret = i915_gem_object_get_pages(obj, 0); - if (ret) { - DRM_ERROR("failed to get page list\n"); - goto out; - } + obj->phys_obj = dev_priv->mm.phys_objs[id - 1]; + obj->phys_obj->cur_obj = obj; - page_count = obj->size / PAGE_SIZE; + page_count = obj->base.size / PAGE_SIZE; for (i = 0; i < page_count; i++) { - char *src = kmap_atomic(obj_priv->pages[i]); - char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE); + struct page *page; + char *dst, *src; + + page = read_cache_page_gfp(mapping, i, + GFP_HIGHUSER | __GFP_RECLAIMABLE); + if (IS_ERR(page)) + return PTR_ERR(page); + src = kmap_atomic(page); + dst = obj->phys_obj->handle->vaddr + (i * PAGE_SIZE); memcpy(dst, src, PAGE_SIZE); kunmap_atomic(src); - } - i915_gem_object_put_pages(obj); + mark_page_accessed(page); + page_cache_release(page); + } return 0; -out: - return ret; } static int -i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, +i915_gem_phys_pwrite(struct drm_device *dev, + struct drm_i915_gem_object *obj, struct drm_i915_gem_pwrite *args, struct drm_file *file_priv) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - void *vaddr = obj_priv->phys_obj->handle->vaddr + args->offset; + void *vaddr = obj->phys_obj->handle->vaddr + args->offset; char __user *user_data = (char __user *) (uintptr_t) args->data_ptr; - DRM_DEBUG_DRIVER("vaddr %p, %lld\n", vaddr, args->size); - if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) { unsigned long unwritten; @@ -5036,7 +3965,7 @@ return -EFAULT; } - drm_agp_chipset_flush(dev); + intel_gtt_chipset_flush(); return 0; } @@ -5074,144 +4003,68 @@ } static int -i915_gem_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) -{ - drm_i915_private_t *dev_priv, *next_dev; - struct drm_i915_gem_object *obj_priv, *next_obj; - int cnt = 0; - int would_deadlock = 1; +i915_gem_inactive_shrink(struct shrinker *shrinker, + int nr_to_scan, + gfp_t gfp_mask) +{ + struct drm_i915_private *dev_priv = + container_of(shrinker, + struct drm_i915_private, + mm.inactive_shrinker); + struct drm_device *dev = dev_priv->dev; + struct drm_i915_gem_object *obj, *next; + int cnt; + + if (!mutex_trylock(&dev->struct_mutex)) + return 0; /* "fast-path" to count number of available objects */ if (nr_to_scan == 0) { - spin_lock(&shrink_list_lock); - list_for_each_entry(dev_priv, &shrink_list, mm.shrink_list) { - struct drm_device *dev = dev_priv->dev; - - if (mutex_trylock(&dev->struct_mutex)) { - list_for_each_entry(obj_priv, - &dev_priv->mm.inactive_list, - mm_list) - cnt++; - mutex_unlock(&dev->struct_mutex); - } - } - spin_unlock(&shrink_list_lock); - - return (cnt / 100) * sysctl_vfs_cache_pressure; + cnt = 0; + list_for_each_entry(obj, + &dev_priv->mm.inactive_list, + mm_list) + cnt++; + mutex_unlock(&dev->struct_mutex); + return cnt / 100 * sysctl_vfs_cache_pressure; } - spin_lock(&shrink_list_lock); - rescan: /* first scan for clean buffers */ - list_for_each_entry_safe(dev_priv, next_dev, - &shrink_list, mm.shrink_list) { - struct drm_device *dev = dev_priv->dev; - - if (! mutex_trylock(&dev->struct_mutex)) - continue; - - spin_unlock(&shrink_list_lock); - i915_gem_retire_requests(dev); + i915_gem_retire_requests(dev); - list_for_each_entry_safe(obj_priv, next_obj, - &dev_priv->mm.inactive_list, - mm_list) { - if (i915_gem_object_is_purgeable(obj_priv)) { - i915_gem_object_unbind(&obj_priv->base); - if (--nr_to_scan <= 0) - break; - } + list_for_each_entry_safe(obj, next, + &dev_priv->mm.inactive_list, + mm_list) { + if (i915_gem_object_is_purgeable(obj)) { + if (i915_gem_object_unbind(obj) == 0 && + --nr_to_scan == 0) + break; } - - spin_lock(&shrink_list_lock); - mutex_unlock(&dev->struct_mutex); - - would_deadlock = 0; - - if (nr_to_scan <= 0) - break; } /* second pass, evict/count anything still on the inactive list */ - list_for_each_entry_safe(dev_priv, next_dev, - &shrink_list, mm.shrink_list) { - struct drm_device *dev = dev_priv->dev; - - if (! mutex_trylock(&dev->struct_mutex)) - continue; - - spin_unlock(&shrink_list_lock); - - list_for_each_entry_safe(obj_priv, next_obj, - &dev_priv->mm.inactive_list, - mm_list) { - if (nr_to_scan > 0) { - i915_gem_object_unbind(&obj_priv->base); - nr_to_scan--; - } else - cnt++; - } - - spin_lock(&shrink_list_lock); - mutex_unlock(&dev->struct_mutex); - - would_deadlock = 0; + cnt = 0; + list_for_each_entry_safe(obj, next, + &dev_priv->mm.inactive_list, + mm_list) { + if (nr_to_scan && + i915_gem_object_unbind(obj) == 0) + nr_to_scan--; + else + cnt++; } - if (nr_to_scan) { - int active = 0; - + if (nr_to_scan && i915_gpu_is_active(dev)) { /* * We are desperate for pages, so as a last resort, wait * for the GPU to finish and discard whatever we can. * This has a dramatic impact to reduce the number of * OOM-killer events whilst running the GPU aggressively. */ - list_for_each_entry(dev_priv, &shrink_list, mm.shrink_list) { - struct drm_device *dev = dev_priv->dev; - - if (!mutex_trylock(&dev->struct_mutex)) - continue; - - spin_unlock(&shrink_list_lock); - - if (i915_gpu_is_active(dev)) { - i915_gpu_idle(dev); - active++; - } - - spin_lock(&shrink_list_lock); - mutex_unlock(&dev->struct_mutex); - } - - if (active) + if (i915_gpu_idle(dev) == 0) goto rescan; } - - spin_unlock(&shrink_list_lock); - - if (would_deadlock) - return -1; - else if (cnt > 0) - return (cnt / 100) * sysctl_vfs_cache_pressure; - else - return 0; -} - -static struct shrinker shrinker = { - .shrink = i915_gem_shrink, - .seeks = DEFAULT_SEEKS, -}; - -__init void -i915_gem_shrinker_init(void) -{ - register_shrinker(&shrinker); -} - -__exit void -i915_gem_shrinker_exit(void) -{ - unregister_shrinker(&shrinker); + mutex_unlock(&dev->struct_mutex); + return cnt / 100 * sysctl_vfs_cache_pressure; } --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_gem_debug.c +++ linux-2.6.37/drivers/gpu/drm/i915/i915_gem_debug.c @@ -152,13 +152,12 @@ } void -i915_gem_dump_object(struct drm_gem_object *obj, int len, +i915_gem_dump_object(struct drm_i915_gem_object *obj, int len, const char *where, uint32_t mark) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); int page; - DRM_INFO("%s: object at offset %08x\n", where, obj_priv->gtt_offset); + DRM_INFO("%s: object at offset %08x\n", where, obj->gtt_offset); for (page = 0; page < (len + PAGE_SIZE-1) / PAGE_SIZE; page++) { int page_len, chunk, chunk_len; @@ -170,9 +169,9 @@ chunk_len = page_len - chunk; if (chunk_len > 128) chunk_len = 128; - i915_gem_dump_page(obj_priv->pages[page], + i915_gem_dump_page(obj->pages[page], chunk, chunk + chunk_len, - obj_priv->gtt_offset + + obj->gtt_offset + page * PAGE_SIZE, mark); } @@ -182,21 +181,19 @@ #if WATCH_COHERENCY void -i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) +i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle) { - struct drm_device *dev = obj->dev; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + struct drm_device *dev = obj->base.dev; int page; uint32_t *gtt_mapping; uint32_t *backing_map = NULL; int bad_count = 0; DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %zdkb):\n", - __func__, obj, obj_priv->gtt_offset, handle, + __func__, obj, obj->gtt_offset, handle, obj->size / 1024); - gtt_mapping = ioremap(dev->agp->base + obj_priv->gtt_offset, - obj->size); + gtt_mapping = ioremap(dev->agp->base + obj->gtt_offset, obj->base.size); if (gtt_mapping == NULL) { DRM_ERROR("failed to map GTT space\n"); return; @@ -205,7 +202,7 @@ for (page = 0; page < obj->size / PAGE_SIZE; page++) { int i; - backing_map = kmap_atomic(obj_priv->pages[page], KM_USER0); + backing_map = kmap_atomic(obj->pages[page], KM_USER0); if (backing_map == NULL) { DRM_ERROR("failed to map backing page\n"); @@ -220,7 +217,7 @@ if (cpuval != gttval) { DRM_INFO("incoherent CPU vs GPU at 0x%08x: " "0x%08x vs 0x%08x\n", - (int)(obj_priv->gtt_offset + + (int)(obj->gtt_offset + page * PAGE_SIZE + i * 4), cpuval, gttval); if (bad_count++ >= 8) { --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_gem_evict.c +++ linux-2.6.37/drivers/gpu/drm/i915/i915_gem_evict.c @@ -32,28 +32,36 @@ #include "i915_drm.h" static bool -mark_free(struct drm_i915_gem_object *obj_priv, - struct list_head *unwind) +mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind) { - list_add(&obj_priv->evict_list, unwind); - drm_gem_object_reference(&obj_priv->base); - return drm_mm_scan_add_block(obj_priv->gtt_space); + list_add(&obj->exec_list, unwind); + drm_gem_object_reference(&obj->base); + return drm_mm_scan_add_block(obj->gtt_space); } int -i915_gem_evict_something(struct drm_device *dev, int min_size, unsigned alignment) +i915_gem_evict_something(struct drm_device *dev, int min_size, + unsigned alignment, bool mappable) { drm_i915_private_t *dev_priv = dev->dev_private; struct list_head eviction_list, unwind_list; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int ret = 0; i915_gem_retire_requests(dev); /* Re-check for free space after retiring requests */ - if (drm_mm_search_free(&dev_priv->mm.gtt_space, - min_size, alignment, 0)) - return 0; + if (mappable) { + if (drm_mm_search_free_in_range(&dev_priv->mm.gtt_space, + min_size, alignment, 0, + dev_priv->mm.gtt_mappable_end, + 0)) + return 0; + } else { + if (drm_mm_search_free(&dev_priv->mm.gtt_space, + min_size, alignment, 0)) + return 0; + } /* * The goal is to evict objects and amalgamate space in LRU order. @@ -79,45 +87,50 @@ */ INIT_LIST_HEAD(&unwind_list); - drm_mm_init_scan(&dev_priv->mm.gtt_space, min_size, alignment); + if (mappable) + drm_mm_init_scan_with_range(&dev_priv->mm.gtt_space, min_size, + alignment, 0, + dev_priv->mm.gtt_mappable_end); + else + drm_mm_init_scan(&dev_priv->mm.gtt_space, min_size, alignment); /* First see if there is a large enough contiguous idle region... */ - list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, mm_list) { - if (mark_free(obj_priv, &unwind_list)) + list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) { + if (mark_free(obj, &unwind_list)) goto found; } /* Now merge in the soon-to-be-expired objects... */ - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) { + list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) { /* Does the object require an outstanding flush? */ - if (obj_priv->base.write_domain || obj_priv->pin_count) + if (obj->base.write_domain || obj->pin_count) continue; - if (mark_free(obj_priv, &unwind_list)) + if (mark_free(obj, &unwind_list)) goto found; } /* Finally add anything with a pending flush (in order of retirement) */ - list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, mm_list) { - if (obj_priv->pin_count) + list_for_each_entry(obj, &dev_priv->mm.flushing_list, mm_list) { + if (obj->pin_count) continue; - if (mark_free(obj_priv, &unwind_list)) + if (mark_free(obj, &unwind_list)) goto found; } - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) { - if (! obj_priv->base.write_domain || obj_priv->pin_count) + list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) { + if (! obj->base.write_domain || obj->pin_count) continue; - if (mark_free(obj_priv, &unwind_list)) + if (mark_free(obj, &unwind_list)) goto found; } /* Nothing found, clean up and bail out! */ - list_for_each_entry(obj_priv, &unwind_list, evict_list) { - ret = drm_mm_scan_remove_block(obj_priv->gtt_space); + list_for_each_entry(obj, &unwind_list, exec_list) { + ret = drm_mm_scan_remove_block(obj->gtt_space); BUG_ON(ret); - drm_gem_object_unreference(&obj_priv->base); + drm_gem_object_unreference(&obj->base); } /* We expect the caller to unpin, evict all and try again, or give up. @@ -131,33 +144,33 @@ * temporary list. */ INIT_LIST_HEAD(&eviction_list); while (!list_empty(&unwind_list)) { - obj_priv = list_first_entry(&unwind_list, - struct drm_i915_gem_object, - evict_list); - if (drm_mm_scan_remove_block(obj_priv->gtt_space)) { - list_move(&obj_priv->evict_list, &eviction_list); + obj = list_first_entry(&unwind_list, + struct drm_i915_gem_object, + exec_list); + if (drm_mm_scan_remove_block(obj->gtt_space)) { + list_move(&obj->exec_list, &eviction_list); continue; } - list_del(&obj_priv->evict_list); - drm_gem_object_unreference(&obj_priv->base); + list_del_init(&obj->exec_list); + drm_gem_object_unreference(&obj->base); } /* Unbinding will emit any required flushes */ while (!list_empty(&eviction_list)) { - obj_priv = list_first_entry(&eviction_list, - struct drm_i915_gem_object, - evict_list); + obj = list_first_entry(&eviction_list, + struct drm_i915_gem_object, + exec_list); if (ret == 0) - ret = i915_gem_object_unbind(&obj_priv->base); - list_del(&obj_priv->evict_list); - drm_gem_object_unreference(&obj_priv->base); + ret = i915_gem_object_unbind(obj); + list_del_init(&obj->exec_list); + drm_gem_object_unreference(&obj->base); } return ret; } int -i915_gem_evict_everything(struct drm_device *dev) +i915_gem_evict_everything(struct drm_device *dev, bool purgeable_only) { drm_i915_private_t *dev_priv = dev->dev_private; int ret; @@ -176,36 +189,22 @@ BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); - ret = i915_gem_evict_inactive(dev); - if (ret) - return ret; - - lists_empty = (list_empty(&dev_priv->mm.inactive_list) && - list_empty(&dev_priv->mm.flushing_list) && - list_empty(&dev_priv->mm.active_list)); - BUG_ON(!lists_empty); - - return 0; + return i915_gem_evict_inactive(dev, purgeable_only); } /** Unbinds all inactive objects. */ int -i915_gem_evict_inactive(struct drm_device *dev) +i915_gem_evict_inactive(struct drm_device *dev, bool purgeable_only) { drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj, *next; - while (!list_empty(&dev_priv->mm.inactive_list)) { - struct drm_gem_object *obj; - int ret; - - obj = &list_first_entry(&dev_priv->mm.inactive_list, - struct drm_i915_gem_object, - mm_list)->base; - - ret = i915_gem_object_unbind(obj); - if (ret != 0) { - DRM_ERROR("Error unbinding object: %d\n", ret); - return ret; + list_for_each_entry_safe(obj, next, + &dev_priv->mm.inactive_list, mm_list) { + if (!purgeable_only || obj->madv != I915_MADV_WILLNEED) { + int ret = i915_gem_object_unbind(obj); + if (ret) + return ret; } } --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ linux-2.6.37/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -0,0 +1,1345 @@ +/* + * Copyright © 2008,2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + * Chris Wilson + * + */ + +#include "drmP.h" +#include "drm.h" +#include "i915_drm.h" +#include "i915_drv.h" +#include "i915_trace.h" +#include "intel_drv.h" + +struct change_domains { + uint32_t invalidate_domains; + uint32_t flush_domains; + uint32_t flush_rings; +}; + +/* + * Set the next domain for the specified object. This + * may not actually perform the necessary flushing/invaliding though, + * as that may want to be batched with other set_domain operations + * + * This is (we hope) the only really tricky part of gem. The goal + * is fairly simple -- track which caches hold bits of the object + * and make sure they remain coherent. A few concrete examples may + * help to explain how it works. For shorthand, we use the notation + * (read_domains, write_domain), e.g. (CPU, CPU) to indicate the + * a pair of read and write domain masks. + * + * Case 1: the batch buffer + * + * 1. Allocated + * 2. Written by CPU + * 3. Mapped to GTT + * 4. Read by GPU + * 5. Unmapped from GTT + * 6. Freed + * + * Let's take these a step at a time + * + * 1. Allocated + * Pages allocated from the kernel may still have + * cache contents, so we set them to (CPU, CPU) always. + * 2. Written by CPU (using pwrite) + * The pwrite function calls set_domain (CPU, CPU) and + * this function does nothing (as nothing changes) + * 3. Mapped by GTT + * This function asserts that the object is not + * currently in any GPU-based read or write domains + * 4. Read by GPU + * i915_gem_execbuffer calls set_domain (COMMAND, 0). + * As write_domain is zero, this function adds in the + * current read domains (CPU+COMMAND, 0). + * flush_domains is set to CPU. + * invalidate_domains is set to COMMAND + * clflush is run to get data out of the CPU caches + * then i915_dev_set_domain calls i915_gem_flush to + * emit an MI_FLUSH and drm_agp_chipset_flush + * 5. Unmapped from GTT + * i915_gem_object_unbind calls set_domain (CPU, CPU) + * flush_domains and invalidate_domains end up both zero + * so no flushing/invalidating happens + * 6. Freed + * yay, done + * + * Case 2: The shared render buffer + * + * 1. Allocated + * 2. Mapped to GTT + * 3. Read/written by GPU + * 4. set_domain to (CPU,CPU) + * 5. Read/written by CPU + * 6. Read/written by GPU + * + * 1. Allocated + * Same as last example, (CPU, CPU) + * 2. Mapped to GTT + * Nothing changes (assertions find that it is not in the GPU) + * 3. Read/written by GPU + * execbuffer calls set_domain (RENDER, RENDER) + * flush_domains gets CPU + * invalidate_domains gets GPU + * clflush (obj) + * MI_FLUSH and drm_agp_chipset_flush + * 4. set_domain (CPU, CPU) + * flush_domains gets GPU + * invalidate_domains gets CPU + * wait_rendering (obj) to make sure all drawing is complete. + * This will include an MI_FLUSH to get the data from GPU + * to memory + * clflush (obj) to invalidate the CPU cache + * Another MI_FLUSH in i915_gem_flush (eliminate this somehow?) + * 5. Read/written by CPU + * cache lines are loaded and dirtied + * 6. Read written by GPU + * Same as last GPU access + * + * Case 3: The constant buffer + * + * 1. Allocated + * 2. Written by CPU + * 3. Read by GPU + * 4. Updated (written) by CPU again + * 5. Read by GPU + * + * 1. Allocated + * (CPU, CPU) + * 2. Written by CPU + * (CPU, CPU) + * 3. Read by GPU + * (CPU+RENDER, 0) + * flush_domains = CPU + * invalidate_domains = RENDER + * clflush (obj) + * MI_FLUSH + * drm_agp_chipset_flush + * 4. Updated (written) by CPU again + * (CPU, CPU) + * flush_domains = 0 (no previous write domain) + * invalidate_domains = 0 (no new read domains) + * 5. Read by GPU + * (CPU+RENDER, 0) + * flush_domains = CPU + * invalidate_domains = RENDER + * clflush (obj) + * MI_FLUSH + * drm_agp_chipset_flush + */ +static void +i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *ring, + struct change_domains *cd) +{ + uint32_t invalidate_domains = 0, flush_domains = 0; + + /* + * If the object isn't moving to a new write domain, + * let the object stay in multiple read domains + */ + if (obj->base.pending_write_domain == 0) + obj->base.pending_read_domains |= obj->base.read_domains; + + /* + * Flush the current write domain if + * the new read domains don't match. Invalidate + * any read domains which differ from the old + * write domain + */ + if (obj->base.write_domain && + (((obj->base.write_domain != obj->base.pending_read_domains || + obj->ring != ring)) || + (obj->fenced_gpu_access && !obj->pending_fenced_gpu_access))) { + flush_domains |= obj->base.write_domain; + invalidate_domains |= + obj->base.pending_read_domains & ~obj->base.write_domain; + } + /* + * Invalidate any read caches which may have + * stale data. That is, any new read domains. + */ + invalidate_domains |= obj->base.pending_read_domains & ~obj->base.read_domains; + if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) + i915_gem_clflush_object(obj); + + /* blow away mappings if mapped through GTT */ + if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_GTT) + i915_gem_release_mmap(obj); + + /* The actual obj->write_domain will be updated with + * pending_write_domain after we emit the accumulated flush for all + * of our domain changes in execbuffers (which clears objects' + * write_domains). So if we have a current write domain that we + * aren't changing, set pending_write_domain to that. + */ + if (flush_domains == 0 && obj->base.pending_write_domain == 0) + obj->base.pending_write_domain = obj->base.write_domain; + + cd->invalidate_domains |= invalidate_domains; + cd->flush_domains |= flush_domains; + if (flush_domains & I915_GEM_GPU_DOMAINS) + cd->flush_rings |= obj->ring->id; + if (invalidate_domains & I915_GEM_GPU_DOMAINS) + cd->flush_rings |= ring->id; +} + +struct eb_objects { + int and; + struct hlist_head buckets[0]; +}; + +static struct eb_objects * +eb_create(int size) +{ + struct eb_objects *eb; + int count = PAGE_SIZE / sizeof(struct hlist_head) / 2; + while (count > size) + count >>= 1; + eb = kzalloc(count*sizeof(struct hlist_head) + + sizeof(struct eb_objects), + GFP_KERNEL); + if (eb == NULL) + return eb; + + eb->and = count - 1; + return eb; +} + +static void +eb_reset(struct eb_objects *eb) +{ + memset(eb->buckets, 0, (eb->and+1)*sizeof(struct hlist_head)); +} + +static void +eb_add_object(struct eb_objects *eb, struct drm_i915_gem_object *obj) +{ + hlist_add_head(&obj->exec_node, + &eb->buckets[obj->exec_handle & eb->and]); +} + +static struct drm_i915_gem_object * +eb_get_object(struct eb_objects *eb, unsigned long handle) +{ + struct hlist_head *head; + struct hlist_node *node; + struct drm_i915_gem_object *obj; + + head = &eb->buckets[handle & eb->and]; + hlist_for_each(node, head) { + obj = hlist_entry(node, struct drm_i915_gem_object, exec_node); + if (obj->exec_handle == handle) + return obj; + } + + return NULL; +} + +static void +eb_destroy(struct eb_objects *eb) +{ + kfree(eb); +} + +static int +i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, + struct eb_objects *eb, + struct drm_i915_gem_exec_object2 *entry, + struct drm_i915_gem_relocation_entry *reloc) +{ + struct drm_device *dev = obj->base.dev; + struct drm_gem_object *target_obj; + uint32_t target_offset; + int ret = -EINVAL; + + /* we've already hold a reference to all valid objects */ + target_obj = &eb_get_object(eb, reloc->target_handle)->base; + if (unlikely(target_obj == NULL)) + return -ENOENT; + + target_offset = to_intel_bo(target_obj)->gtt_offset; + +#if WATCH_RELOC + DRM_INFO("%s: obj %p offset %08x target %d " + "read %08x write %08x gtt %08x " + "presumed %08x delta %08x\n", + __func__, + obj, + (int) reloc->offset, + (int) reloc->target_handle, + (int) reloc->read_domains, + (int) reloc->write_domain, + (int) target_offset, + (int) reloc->presumed_offset, + reloc->delta); +#endif + + /* The target buffer should have appeared before us in the + * exec_object list, so it should have a GTT space bound by now. + */ + if (unlikely(target_offset == 0)) { + DRM_ERROR("No GTT space found for object %d\n", + reloc->target_handle); + return ret; + } + + /* Validate that the target is in a valid r/w GPU domain */ + if (unlikely(reloc->write_domain & (reloc->write_domain - 1))) { + DRM_ERROR("reloc with multiple write domains: " + "obj %p target %d offset %d " + "read %08x write %08x", + obj, reloc->target_handle, + (int) reloc->offset, + reloc->read_domains, + reloc->write_domain); + return ret; + } + if (unlikely((reloc->write_domain | reloc->read_domains) & I915_GEM_DOMAIN_CPU)) { + DRM_ERROR("reloc with read/write CPU domains: " + "obj %p target %d offset %d " + "read %08x write %08x", + obj, reloc->target_handle, + (int) reloc->offset, + reloc->read_domains, + reloc->write_domain); + return ret; + } + if (unlikely(reloc->write_domain && target_obj->pending_write_domain && + reloc->write_domain != target_obj->pending_write_domain)) { + DRM_ERROR("Write domain conflict: " + "obj %p target %d offset %d " + "new %08x old %08x\n", + obj, reloc->target_handle, + (int) reloc->offset, + reloc->write_domain, + target_obj->pending_write_domain); + return ret; + } + + target_obj->pending_read_domains |= reloc->read_domains; + target_obj->pending_write_domain |= reloc->write_domain; + + /* If the relocation already has the right value in it, no + * more work needs to be done. + */ + if (target_offset == reloc->presumed_offset) + return 0; + + /* Check that the relocation address is valid... */ + if (unlikely(reloc->offset > obj->base.size - 4)) { + DRM_ERROR("Relocation beyond object bounds: " + "obj %p target %d offset %d size %d.\n", + obj, reloc->target_handle, + (int) reloc->offset, + (int) obj->base.size); + return ret; + } + if (unlikely(reloc->offset & 3)) { + DRM_ERROR("Relocation not 4-byte aligned: " + "obj %p target %d offset %d.\n", + obj, reloc->target_handle, + (int) reloc->offset); + return ret; + } + + /* and points to somewhere within the target object. */ + if (unlikely(reloc->delta >= target_obj->size)) { + DRM_ERROR("Relocation beyond target object bounds: " + "obj %p target %d delta %d size %d.\n", + obj, reloc->target_handle, + (int) reloc->delta, + (int) target_obj->size); + return ret; + } + + reloc->delta += target_offset; + if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { + uint32_t page_offset = reloc->offset & ~PAGE_MASK; + char *vaddr; + + vaddr = kmap_atomic(obj->pages[reloc->offset >> PAGE_SHIFT]); + *(uint32_t *)(vaddr + page_offset) = reloc->delta; + kunmap_atomic(vaddr); + } else { + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t __iomem *reloc_entry; + void __iomem *reloc_page; + + ret = i915_gem_object_set_to_gtt_domain(obj, 1); + if (ret) + return ret; + + /* Map the page containing the relocation we're going to perform. */ + reloc->offset += obj->gtt_offset; + reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, + reloc->offset & PAGE_MASK); + reloc_entry = (uint32_t __iomem *) + (reloc_page + (reloc->offset & ~PAGE_MASK)); + iowrite32(reloc->delta, reloc_entry); + io_mapping_unmap_atomic(reloc_page); + } + + /* and update the user's relocation entry */ + reloc->presumed_offset = target_offset; + + return 0; +} + +static int +i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj, + struct eb_objects *eb, + struct drm_i915_gem_exec_object2 *entry) +{ + struct drm_i915_gem_relocation_entry __user *user_relocs; + int i, ret; + + user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; + for (i = 0; i < entry->relocation_count; i++) { + struct drm_i915_gem_relocation_entry reloc; + + if (__copy_from_user_inatomic(&reloc, + user_relocs+i, + sizeof(reloc))) + return -EFAULT; + + ret = i915_gem_execbuffer_relocate_entry(obj, eb, entry, &reloc); + if (ret) + return ret; + + if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset, + &reloc.presumed_offset, + sizeof(reloc.presumed_offset))) + return -EFAULT; + } + + return 0; +} + +static int +i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj, + struct eb_objects *eb, + struct drm_i915_gem_exec_object2 *entry, + struct drm_i915_gem_relocation_entry *relocs) +{ + int i, ret; + + for (i = 0; i < entry->relocation_count; i++) { + ret = i915_gem_execbuffer_relocate_entry(obj, eb, entry, &relocs[i]); + if (ret) + return ret; + } + + return 0; +} + +static int +i915_gem_execbuffer_relocate(struct drm_device *dev, + struct eb_objects *eb, + struct list_head *objects, + struct drm_i915_gem_exec_object2 *exec) +{ + struct drm_i915_gem_object *obj; + int ret; + + list_for_each_entry(obj, objects, exec_list) { + obj->base.pending_read_domains = 0; + obj->base.pending_write_domain = 0; + ret = i915_gem_execbuffer_relocate_object(obj, eb, exec++); + if (ret) + return ret; + } + + return 0; +} + +static int +i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring, + struct drm_file *file, + struct list_head *objects, + struct drm_i915_gem_exec_object2 *exec) +{ + struct drm_i915_gem_object *obj; + struct drm_i915_gem_exec_object2 *entry; + int ret, retry; + bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4; + + /* Attempt to pin all of the buffers into the GTT. + * This is done in 3 phases: + * + * 1a. Unbind all objects that do not match the GTT constraints for + * the execbuffer (fenceable, mappable, alignment etc). + * 1b. Increment pin count for already bound objects. + * 2. Bind new objects. + * 3. Decrement pin count. + * + * This avoid unnecessary unbinding of later objects in order to makr + * room for the earlier objects *unless* we need to defragment. + */ + retry = 0; + do { + ret = 0; + + /* Unbind any ill-fitting objects or pin. */ + entry = exec; + list_for_each_entry(obj, objects, exec_list) { + bool need_fence, need_mappable; + + if (!obj->gtt_space) { + entry++; + continue; + } + + need_fence = + has_fenced_gpu_access && + entry->flags & EXEC_OBJECT_NEEDS_FENCE && + obj->tiling_mode != I915_TILING_NONE; + need_mappable = + entry->relocation_count ? true : need_fence; + + if ((entry->alignment && obj->gtt_offset & (entry->alignment - 1)) || + (need_mappable && !obj->map_and_fenceable)) + ret = i915_gem_object_unbind(obj); + else + ret = i915_gem_object_pin(obj, + entry->alignment, + need_mappable); + if (ret) + goto err; + + entry++; + } + + /* Bind fresh objects */ + entry = exec; + list_for_each_entry(obj, objects, exec_list) { + bool need_fence; + + need_fence = + has_fenced_gpu_access && + entry->flags & EXEC_OBJECT_NEEDS_FENCE && + obj->tiling_mode != I915_TILING_NONE; + + if (!obj->gtt_space) { + bool need_mappable = + entry->relocation_count ? true : need_fence; + + ret = i915_gem_object_pin(obj, + entry->alignment, + need_mappable); + if (ret) + break; + } + + if (has_fenced_gpu_access) { + if (need_fence) { + ret = i915_gem_object_get_fence(obj, ring, 1); + if (ret) + break; + } else if (entry->flags & EXEC_OBJECT_NEEDS_FENCE && + obj->tiling_mode == I915_TILING_NONE) { + /* XXX pipelined! */ + ret = i915_gem_object_put_fence(obj); + if (ret) + break; + } + obj->pending_fenced_gpu_access = need_fence; + } + + entry->offset = obj->gtt_offset; + entry++; + } + + /* Decrement pin count for bound objects */ + list_for_each_entry(obj, objects, exec_list) { + if (obj->gtt_space) + i915_gem_object_unpin(obj); + } + + if (ret != -ENOSPC || retry > 1) + return ret; + + /* First attempt, just clear anything that is purgeable. + * Second attempt, clear the entire GTT. + */ + ret = i915_gem_evict_everything(ring->dev, retry == 0); + if (ret) + return ret; + + retry++; + } while (1); + +err: + obj = list_entry(obj->exec_list.prev, + struct drm_i915_gem_object, + exec_list); + while (objects != &obj->exec_list) { + if (obj->gtt_space) + i915_gem_object_unpin(obj); + + obj = list_entry(obj->exec_list.prev, + struct drm_i915_gem_object, + exec_list); + } + + return ret; +} + +static int +i915_gem_execbuffer_relocate_slow(struct drm_device *dev, + struct drm_file *file, + struct intel_ring_buffer *ring, + struct list_head *objects, + struct eb_objects *eb, + struct drm_i915_gem_exec_object2 *exec, + int count) +{ + struct drm_i915_gem_relocation_entry *reloc; + struct drm_i915_gem_object *obj; + int i, total, ret; + + /* We may process another execbuffer during the unlock... */ + while (list_empty(objects)) { + obj = list_first_entry(objects, + struct drm_i915_gem_object, + exec_list); + list_del_init(&obj->exec_list); + drm_gem_object_unreference(&obj->base); + } + + mutex_unlock(&dev->struct_mutex); + + total = 0; + for (i = 0; i < count; i++) + total += exec[i].relocation_count; + + reloc = drm_malloc_ab(total, sizeof(*reloc)); + if (reloc == NULL) { + mutex_lock(&dev->struct_mutex); + return -ENOMEM; + } + + total = 0; + for (i = 0; i < count; i++) { + struct drm_i915_gem_relocation_entry __user *user_relocs; + + user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; + + if (copy_from_user(reloc+total, user_relocs, + exec[i].relocation_count * sizeof(*reloc))) { + ret = -EFAULT; + mutex_lock(&dev->struct_mutex); + goto err; + } + + total += exec[i].relocation_count; + } + + ret = i915_mutex_lock_interruptible(dev); + if (ret) { + mutex_lock(&dev->struct_mutex); + goto err; + } + + /* reacquire the objects */ + INIT_LIST_HEAD(objects); + eb_reset(eb); + for (i = 0; i < count; i++) { + struct drm_i915_gem_object *obj; + + obj = to_intel_bo(drm_gem_object_lookup(dev, file, + exec[i].handle)); + if (obj == NULL) { + DRM_ERROR("Invalid object handle %d at index %d\n", + exec[i].handle, i); + ret = -ENOENT; + goto err; + } + + list_add_tail(&obj->exec_list, objects); + obj->exec_handle = exec[i].handle; + eb_add_object(eb, obj); + } + + ret = i915_gem_execbuffer_reserve(ring, file, objects, exec); + if (ret) + goto err; + + total = 0; + list_for_each_entry(obj, objects, exec_list) { + obj->base.pending_read_domains = 0; + obj->base.pending_write_domain = 0; + ret = i915_gem_execbuffer_relocate_object_slow(obj, eb, + exec, + reloc + total); + if (ret) + goto err; + + total += exec->relocation_count; + exec++; + } + + /* Leave the user relocations as are, this is the painfully slow path, + * and we want to avoid the complication of dropping the lock whilst + * having buffers reserved in the aperture and so causing spurious + * ENOSPC for random operations. + */ + +err: + drm_free_large(reloc); + return ret; +} + +static void +i915_gem_execbuffer_flush(struct drm_device *dev, + uint32_t invalidate_domains, + uint32_t flush_domains, + uint32_t flush_rings) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + int i; + + if (flush_domains & I915_GEM_DOMAIN_CPU) + intel_gtt_chipset_flush(); + + if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { + for (i = 0; i < I915_NUM_RINGS; i++) + if (flush_rings & (1 << i)) + i915_gem_flush_ring(dev, &dev_priv->ring[i], + invalidate_domains, + flush_domains); + } +} + +static int +i915_gem_execbuffer_sync_rings(struct drm_i915_gem_object *obj, + struct intel_ring_buffer *to) +{ + struct intel_ring_buffer *from = obj->ring; + u32 seqno; + int ret, idx; + + if (from == NULL || to == from) + return 0; + + if (INTEL_INFO(obj->base.dev)->gen < 6) + return i915_gem_object_wait_rendering(obj, true); + + idx = intel_ring_sync_index(from, to); + + seqno = obj->last_rendering_seqno; + if (seqno <= from->sync_seqno[idx]) + return 0; + + if (seqno == from->outstanding_lazy_request) { + struct drm_i915_gem_request *request; + + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL) + return -ENOMEM; + + ret = i915_add_request(obj->base.dev, NULL, request, from); + if (ret) { + kfree(request); + return ret; + } + + seqno = request->seqno; + } + + from->sync_seqno[idx] = seqno; + return intel_ring_sync(to, from, seqno - 1); +} + +static int +i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring, + struct list_head *objects) +{ + struct drm_i915_gem_object *obj; + struct change_domains cd; + int ret; + + cd.invalidate_domains = 0; + cd.flush_domains = 0; + cd.flush_rings = 0; + list_for_each_entry(obj, objects, exec_list) + i915_gem_object_set_to_gpu_domain(obj, ring, &cd); + + if (cd.invalidate_domains | cd.flush_domains) { +#if WATCH_EXEC + DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", + __func__, + cd.invalidate_domains, + cd.flush_domains); +#endif + i915_gem_execbuffer_flush(ring->dev, + cd.invalidate_domains, + cd.flush_domains, + cd.flush_rings); + } + + list_for_each_entry(obj, objects, exec_list) { + ret = i915_gem_execbuffer_sync_rings(obj, ring); + if (ret) + return ret; + } + + return 0; +} + +static bool +i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) +{ + return ((exec->batch_start_offset | exec->batch_len) & 0x7) == 0; +} + +static int +validate_exec_list(struct drm_i915_gem_exec_object2 *exec, + int count) +{ + int i; + + for (i = 0; i < count; i++) { + char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; + int length; /* limited by fault_in_pages_readable() */ + + /* First check for malicious input causing overflow */ + if (exec[i].relocation_count > + INT_MAX / sizeof(struct drm_i915_gem_relocation_entry)) + return -EINVAL; + + length = exec[i].relocation_count * + sizeof(struct drm_i915_gem_relocation_entry); + if (!access_ok(VERIFY_READ, ptr, length)) + return -EFAULT; + + /* we may also need to update the presumed offsets */ + if (!access_ok(VERIFY_WRITE, ptr, length)) + return -EFAULT; + + if (fault_in_pages_readable(ptr, length)) + return -EFAULT; + } + + return 0; +} + +static int +i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, + struct list_head *objects) +{ + struct drm_i915_gem_object *obj; + int flips; + + /* Check for any pending flips. As we only maintain a flip queue depth + * of 1, we can simply insert a WAIT for the next display flip prior + * to executing the batch and avoid stalling the CPU. + */ + flips = 0; + list_for_each_entry(obj, objects, exec_list) { + if (obj->base.write_domain) + flips |= atomic_read(&obj->pending_flip); + } + if (flips) { + int plane, flip_mask, ret; + + for (plane = 0; flips >> plane; plane++) { + if (((flips >> plane) & 1) == 0) + continue; + + if (plane) + flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; + else + flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; + + ret = intel_ring_begin(ring, 2); + if (ret) + return ret; + + intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask); + intel_ring_emit(ring, MI_NOOP); + intel_ring_advance(ring); + } + } + + return 0; +} + +static void +i915_gem_execbuffer_move_to_active(struct list_head *objects, + struct intel_ring_buffer *ring, + u32 seqno) +{ + struct drm_i915_gem_object *obj; + + list_for_each_entry(obj, objects, exec_list) { + obj->base.read_domains = obj->base.pending_read_domains; + obj->base.write_domain = obj->base.pending_write_domain; + obj->fenced_gpu_access = obj->pending_fenced_gpu_access; + + i915_gem_object_move_to_active(obj, ring, seqno); + if (obj->base.write_domain) { + obj->dirty = 1; + obj->pending_gpu_write = true; + list_move_tail(&obj->gpu_write_list, + &ring->gpu_write_list); + intel_mark_busy(ring->dev, obj); + } + + trace_i915_gem_object_change_domain(obj, + obj->base.read_domains, + obj->base.write_domain); + } +} + +static void +i915_gem_execbuffer_retire_commands(struct drm_device *dev, + struct drm_file *file, + struct intel_ring_buffer *ring) +{ + struct drm_i915_gem_request *request; + u32 invalidate; + + /* + * Ensure that the commands in the batch buffer are + * finished before the interrupt fires. + * + * The sampler always gets flushed on i965 (sigh). + */ + invalidate = I915_GEM_DOMAIN_COMMAND; + if (INTEL_INFO(dev)->gen >= 4) + invalidate |= I915_GEM_DOMAIN_SAMPLER; + if (ring->flush(ring, invalidate, 0)) { + i915_gem_next_request_seqno(dev, ring); + return; + } + + /* Add a breadcrumb for the completion of the batch buffer */ + request = kzalloc(sizeof(*request), GFP_KERNEL); + if (request == NULL || i915_add_request(dev, file, request, ring)) { + i915_gem_next_request_seqno(dev, ring); + kfree(request); + } +} + +static int +i915_gem_do_execbuffer(struct drm_device *dev, void *data, + struct drm_file *file, + struct drm_i915_gem_execbuffer2 *args, + struct drm_i915_gem_exec_object2 *exec) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct list_head objects; + struct eb_objects *eb; + struct drm_i915_gem_object *batch_obj; + struct drm_clip_rect *cliprects = NULL; + struct intel_ring_buffer *ring; + u32 exec_start, exec_len; + u32 seqno; + int ret, mode, i; + + if (!i915_gem_check_execbuffer(args)) { + DRM_ERROR("execbuf with invalid offset/length\n"); + return -EINVAL; + } + + ret = validate_exec_list(exec, args->buffer_count); + if (ret) + return ret; + +#if WATCH_EXEC + DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", + (int) args->buffers_ptr, args->buffer_count, args->batch_len); +#endif + switch (args->flags & I915_EXEC_RING_MASK) { + case I915_EXEC_DEFAULT: + case I915_EXEC_RENDER: + ring = &dev_priv->ring[RCS]; + break; + case I915_EXEC_BSD: + if (!HAS_BSD(dev)) { + DRM_ERROR("execbuf with invalid ring (BSD)\n"); + return -EINVAL; + } + ring = &dev_priv->ring[VCS]; + break; + case I915_EXEC_BLT: + if (!HAS_BLT(dev)) { + DRM_ERROR("execbuf with invalid ring (BLT)\n"); + return -EINVAL; + } + ring = &dev_priv->ring[BCS]; + break; + default: + DRM_ERROR("execbuf with unknown ring: %d\n", + (int)(args->flags & I915_EXEC_RING_MASK)); + return -EINVAL; + } + + mode = args->flags & I915_EXEC_CONSTANTS_MASK; + switch (mode) { + case I915_EXEC_CONSTANTS_REL_GENERAL: + case I915_EXEC_CONSTANTS_ABSOLUTE: + case I915_EXEC_CONSTANTS_REL_SURFACE: + if (ring == &dev_priv->ring[RCS] && + mode != dev_priv->relative_constants_mode) { + if (INTEL_INFO(dev)->gen < 4) + return -EINVAL; + + if (INTEL_INFO(dev)->gen > 5 && + mode == I915_EXEC_CONSTANTS_REL_SURFACE) + return -EINVAL; + + ret = intel_ring_begin(ring, 4); + if (ret) + return ret; + + intel_ring_emit(ring, MI_NOOP); + intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1)); + intel_ring_emit(ring, INSTPM); + intel_ring_emit(ring, + I915_EXEC_CONSTANTS_MASK << 16 | mode); + intel_ring_advance(ring); + + dev_priv->relative_constants_mode = mode; + } + break; + default: + DRM_ERROR("execbuf with unknown constants: %d\n", mode); + return -EINVAL; + } + + if (args->buffer_count < 1) { + DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); + return -EINVAL; + } + + if (args->num_cliprects != 0) { + if (ring != &dev_priv->ring[RCS]) { + DRM_ERROR("clip rectangles are only valid with the render ring\n"); + return -EINVAL; + } + + cliprects = kmalloc(args->num_cliprects * sizeof(*cliprects), + GFP_KERNEL); + if (cliprects == NULL) { + ret = -ENOMEM; + goto pre_mutex_err; + } + + if (copy_from_user(cliprects, + (struct drm_clip_rect __user *)(uintptr_t) + args->cliprects_ptr, + sizeof(*cliprects)*args->num_cliprects)) { + ret = -EFAULT; + goto pre_mutex_err; + } + } + + ret = i915_mutex_lock_interruptible(dev); + if (ret) + goto pre_mutex_err; + + if (dev_priv->mm.suspended) { + mutex_unlock(&dev->struct_mutex); + ret = -EBUSY; + goto pre_mutex_err; + } + + eb = eb_create(args->buffer_count); + if (eb == NULL) { + mutex_unlock(&dev->struct_mutex); + ret = -ENOMEM; + goto pre_mutex_err; + } + + /* Look up object handles */ + INIT_LIST_HEAD(&objects); + for (i = 0; i < args->buffer_count; i++) { + struct drm_i915_gem_object *obj; + + obj = to_intel_bo(drm_gem_object_lookup(dev, file, + exec[i].handle)); + if (obj == NULL) { + DRM_ERROR("Invalid object handle %d at index %d\n", + exec[i].handle, i); + /* prevent error path from reading uninitialized data */ + ret = -ENOENT; + goto err; + } + + if (!list_empty(&obj->exec_list)) { + DRM_ERROR("Object %p [handle %d, index %d] appears more than once in object list\n", + obj, exec[i].handle, i); + ret = -EINVAL; + goto err; + } + + list_add_tail(&obj->exec_list, &objects); + obj->exec_handle = exec[i].handle; + eb_add_object(eb, obj); + } + + /* Move the objects en-masse into the GTT, evicting if necessary. */ + ret = i915_gem_execbuffer_reserve(ring, file, &objects, exec); + if (ret) + goto err; + + /* The objects are in their final locations, apply the relocations. */ + ret = i915_gem_execbuffer_relocate(dev, eb, &objects, exec); + if (ret) { + if (ret == -EFAULT) { + ret = i915_gem_execbuffer_relocate_slow(dev, file, ring, + &objects, eb, + exec, + args->buffer_count); + BUG_ON(!mutex_is_locked(&dev->struct_mutex)); + } + if (ret) + goto err; + } + + /* Set the pending read domains for the batch buffer to COMMAND */ + batch_obj = list_entry(objects.prev, + struct drm_i915_gem_object, + exec_list); + if (batch_obj->base.pending_write_domain) { + DRM_ERROR("Attempting to use self-modifying batch buffer\n"); + ret = -EINVAL; + goto err; + } + batch_obj->base.pending_read_domains |= I915_GEM_DOMAIN_COMMAND; + + ret = i915_gem_execbuffer_move_to_gpu(ring, &objects); + if (ret) + goto err; + + ret = i915_gem_execbuffer_wait_for_flips(ring, &objects); + if (ret) + goto err; + + seqno = i915_gem_next_request_seqno(dev, ring); + for (i = 0; i < I915_NUM_RINGS-1; i++) { + if (seqno < ring->sync_seqno[i]) { + /* The GPU can not handle its semaphore value wrapping, + * so every billion or so execbuffers, we need to stall + * the GPU in order to reset the counters. + */ + ret = i915_gpu_idle(dev); + if (ret) + goto err; + + BUG_ON(ring->sync_seqno[i]); + } + } + + exec_start = batch_obj->gtt_offset + args->batch_start_offset; + exec_len = args->batch_len; + if (cliprects) { + for (i = 0; i < args->num_cliprects; i++) { + ret = i915_emit_box(dev, &cliprects[i], + args->DR1, args->DR4); + if (ret) + goto err; + + ret = ring->dispatch_execbuffer(ring, + exec_start, exec_len); + if (ret) + goto err; + } + } else { + ret = ring->dispatch_execbuffer(ring, exec_start, exec_len); + if (ret) + goto err; + } + + i915_gem_execbuffer_move_to_active(&objects, ring, seqno); + i915_gem_execbuffer_retire_commands(dev, file, ring); + +err: + eb_destroy(eb); + while (!list_empty(&objects)) { + struct drm_i915_gem_object *obj; + + obj = list_first_entry(&objects, + struct drm_i915_gem_object, + exec_list); + list_del_init(&obj->exec_list); + drm_gem_object_unreference(&obj->base); + } + + mutex_unlock(&dev->struct_mutex); + +pre_mutex_err: + kfree(cliprects); + return ret; +} + +/* + * Legacy execbuffer just creates an exec2 list from the original exec object + * list array and passes it to the real function. + */ +int +i915_gem_execbuffer(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_i915_gem_execbuffer *args = data; + struct drm_i915_gem_execbuffer2 exec2; + struct drm_i915_gem_exec_object *exec_list = NULL; + struct drm_i915_gem_exec_object2 *exec2_list = NULL; + int ret, i; + +#if WATCH_EXEC + DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", + (int) args->buffers_ptr, args->buffer_count, args->batch_len); +#endif + + if (args->buffer_count < 1) { + DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); + return -EINVAL; + } + + /* Copy in the exec list from userland */ + exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count); + exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); + if (exec_list == NULL || exec2_list == NULL) { + DRM_ERROR("Failed to allocate exec list for %d buffers\n", + args->buffer_count); + drm_free_large(exec_list); + drm_free_large(exec2_list); + return -ENOMEM; + } + ret = copy_from_user(exec_list, + (struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + sizeof(*exec_list) * args->buffer_count); + if (ret != 0) { + DRM_ERROR("copy %d exec entries failed %d\n", + args->buffer_count, ret); + drm_free_large(exec_list); + drm_free_large(exec2_list); + return -EFAULT; + } + + for (i = 0; i < args->buffer_count; i++) { + exec2_list[i].handle = exec_list[i].handle; + exec2_list[i].relocation_count = exec_list[i].relocation_count; + exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr; + exec2_list[i].alignment = exec_list[i].alignment; + exec2_list[i].offset = exec_list[i].offset; + if (INTEL_INFO(dev)->gen < 4) + exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE; + else + exec2_list[i].flags = 0; + } + + exec2.buffers_ptr = args->buffers_ptr; + exec2.buffer_count = args->buffer_count; + exec2.batch_start_offset = args->batch_start_offset; + exec2.batch_len = args->batch_len; + exec2.DR1 = args->DR1; + exec2.DR4 = args->DR4; + exec2.num_cliprects = args->num_cliprects; + exec2.cliprects_ptr = args->cliprects_ptr; + exec2.flags = I915_EXEC_RENDER; + + ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); + if (!ret) { + /* Copy the new buffer offsets back to the user's exec list. */ + for (i = 0; i < args->buffer_count; i++) + exec_list[i].offset = exec2_list[i].offset; + /* ... and back out to userspace */ + ret = copy_to_user((struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + exec_list, + sizeof(*exec_list) * args->buffer_count); + if (ret) { + ret = -EFAULT; + DRM_ERROR("failed to copy %d exec entries " + "back to user (%d)\n", + args->buffer_count, ret); + } + } + + drm_free_large(exec_list); + drm_free_large(exec2_list); + return ret; +} + +int +i915_gem_execbuffer2(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_i915_gem_execbuffer2 *args = data; + struct drm_i915_gem_exec_object2 *exec2_list = NULL; + int ret; + +#if WATCH_EXEC + DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", + (int) args->buffers_ptr, args->buffer_count, args->batch_len); +#endif + + if (args->buffer_count < 1) { + DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count); + return -EINVAL; + } + + exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); + if (exec2_list == NULL) { + DRM_ERROR("Failed to allocate exec list for %d buffers\n", + args->buffer_count); + return -ENOMEM; + } + ret = copy_from_user(exec2_list, + (struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + sizeof(*exec2_list) * args->buffer_count); + if (ret != 0) { + DRM_ERROR("copy %d exec entries failed %d\n", + args->buffer_count, ret); + drm_free_large(exec2_list); + return -EFAULT; + } + + ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list); + if (!ret) { + /* Copy the new buffer offsets back to the user's exec list. */ + ret = copy_to_user((struct drm_i915_relocation_entry __user *) + (uintptr_t) args->buffers_ptr, + exec2_list, + sizeof(*exec2_list) * args->buffer_count); + if (ret) { + ret = -EFAULT; + DRM_ERROR("failed to copy %d exec entries " + "back to user (%d)\n", + args->buffer_count, ret); + } + } + + drm_free_large(exec2_list); + return ret; +} + --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_gem_gtt.c +++ linux-2.6.37/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -0,0 +1,111 @@ +/* + * Copyright © 2010 Daniel Vetter + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#include "drmP.h" +#include "drm.h" +#include "i915_drm.h" +#include "i915_drv.h" +#include "i915_trace.h" +#include "intel_drv.h" + +void i915_gem_restore_gtt_mappings(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj; + + list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) { + i915_gem_clflush_object(obj); + + if (dev_priv->mm.gtt->needs_dmar) { + BUG_ON(!obj->sg_list); + + intel_gtt_insert_sg_entries(obj->sg_list, + obj->num_sg, + obj->gtt_space->start + >> PAGE_SHIFT, + obj->agp_type); + } else + intel_gtt_insert_pages(obj->gtt_space->start + >> PAGE_SHIFT, + obj->base.size >> PAGE_SHIFT, + obj->pages, + obj->agp_type); + } + + intel_gtt_chipset_flush(); +} + +int i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj) +{ + struct drm_device *dev = obj->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int ret; + + if (dev_priv->mm.gtt->needs_dmar) { + ret = intel_gtt_map_memory(obj->pages, + obj->base.size >> PAGE_SHIFT, + &obj->sg_list, + &obj->num_sg); + if (ret != 0) + return ret; + + intel_gtt_insert_sg_entries(obj->sg_list, + obj->num_sg, + obj->gtt_space->start >> PAGE_SHIFT, + obj->agp_type); + } else + intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT, + obj->base.size >> PAGE_SHIFT, + obj->pages, + obj->agp_type); + + if (IS_I830(dev) || IS_845G(dev)) { + struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; + /* Workaround an erratum on these two chipsets, whereby the + * BLT invalidates the wrong entries following an update to + * the GTT. Ergo, we need to flush any pending writes before + * using this object (by the BLT, but to be safe, we alway + * flush). + */ + if (!list_empty(&ring->gpu_write_list)) + i915_gem_flush_ring(dev, ring, 0, I915_GEM_GPU_DOMAINS); + } + + return 0; +} + +void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) +{ + struct drm_device *dev = obj->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->mm.gtt->needs_dmar) { + intel_gtt_unmap_memory(obj->sg_list, obj->num_sg); + obj->sg_list = NULL; + obj->num_sg = 0; + } + + intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT, + obj->base.size >> PAGE_SHIFT); +} --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_gem_tiling.c +++ linux-2.6.37/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -181,7 +181,7 @@ } /* Check pitch constriants for all chips & tiling formats */ -bool +static bool i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) { int tile_width; @@ -232,32 +232,44 @@ return true; } -bool -i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode) +/* Is the current GTT allocation valid for the change in tiling? */ +static bool +i915_gem_object_fence_ok(struct drm_i915_gem_object *obj, int tiling_mode) { - struct drm_device *dev = obj->dev; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - - if (obj_priv->gtt_space == NULL) - return true; + u32 size; if (tiling_mode == I915_TILING_NONE) return true; - if (INTEL_INFO(dev)->gen >= 4) + if (INTEL_INFO(obj->base.dev)->gen >= 4) return true; - if (obj_priv->gtt_offset & (obj->size - 1)) - return false; - - if (IS_GEN3(dev)) { - if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK) + if (INTEL_INFO(obj->base.dev)->gen == 3) { + if (obj->gtt_offset & ~I915_FENCE_START_MASK) return false; } else { - if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK) + if (obj->gtt_offset & ~I830_FENCE_START_MASK) return false; } + /* + * Previous chips need to be aligned to the size of the smallest + * fence register that can contain the object. + */ + if (INTEL_INFO(obj->base.dev)->gen == 3) + size = 1024*1024; + else + size = 512*1024; + + while (size < obj->base.size) + size <<= 1; + + if (obj->gtt_space->size != size) + return false; + + if (obj->gtt_offset & (size - 1)) + return false; + return true; } @@ -267,30 +279,29 @@ */ int i915_gem_set_tiling(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { struct drm_i915_gem_set_tiling *args = data; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int ret; ret = i915_gem_check_is_wedged(dev); if (ret) return ret; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (obj == NULL) return -ENOENT; - obj_priv = to_intel_bo(obj); - if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) { - drm_gem_object_unreference_unlocked(obj); + if (!i915_tiling_ok(dev, + args->stride, obj->base.size, args->tiling_mode)) { + drm_gem_object_unreference_unlocked(&obj->base); return -EINVAL; } - if (obj_priv->pin_count) { - drm_gem_object_unreference_unlocked(obj); + if (obj->pin_count) { + drm_gem_object_unreference_unlocked(&obj->base); return -EBUSY; } @@ -324,34 +335,28 @@ } mutex_lock(&dev->struct_mutex); - if (args->tiling_mode != obj_priv->tiling_mode || - args->stride != obj_priv->stride) { + if (args->tiling_mode != obj->tiling_mode || + args->stride != obj->stride) { /* We need to rebind the object if its current allocation * no longer meets the alignment restrictions for its new * tiling mode. Otherwise we can just leave it alone, but * need to ensure that any fence register is cleared. */ - if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode)) - ret = i915_gem_object_unbind(obj); - else if (obj_priv->fence_reg != I915_FENCE_REG_NONE) - ret = i915_gem_object_put_fence_reg(obj, true); - else - i915_gem_release_mmap(obj); + i915_gem_release_mmap(obj); - if (ret != 0) { - args->tiling_mode = obj_priv->tiling_mode; - args->stride = obj_priv->stride; - goto err; - } - - obj_priv->tiling_mode = args->tiling_mode; - obj_priv->stride = args->stride; + obj->map_and_fenceable = + obj->gtt_space == NULL || + (obj->gtt_offset + obj->base.size <= dev_priv->mm.gtt_mappable_end && + i915_gem_object_fence_ok(obj, args->tiling_mode)); + + obj->tiling_changed = true; + obj->tiling_mode = args->tiling_mode; + obj->stride = args->stride; } -err: - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); - return ret; + return 0; } /** @@ -359,22 +364,20 @@ */ int i915_gem_get_tiling(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { struct drm_i915_gem_get_tiling *args = data; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; - obj = drm_gem_object_lookup(dev, file_priv, args->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle)); if (obj == NULL) return -ENOENT; - obj_priv = to_intel_bo(obj); mutex_lock(&dev->struct_mutex); - args->tiling_mode = obj_priv->tiling_mode; - switch (obj_priv->tiling_mode) { + args->tiling_mode = obj->tiling_mode; + switch (obj->tiling_mode) { case I915_TILING_X: args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x; break; @@ -394,7 +397,7 @@ if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17) args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10; - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); return 0; @@ -424,46 +427,44 @@ } void -i915_gem_object_do_bit_17_swizzle(struct drm_gem_object *obj) +i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int page_count = obj->size >> PAGE_SHIFT; + int page_count = obj->base.size >> PAGE_SHIFT; int i; if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17) return; - if (obj_priv->bit_17 == NULL) + if (obj->bit_17 == NULL) return; for (i = 0; i < page_count; i++) { - char new_bit_17 = page_to_phys(obj_priv->pages[i]) >> 17; + char new_bit_17 = page_to_phys(obj->pages[i]) >> 17; if ((new_bit_17 & 0x1) != - (test_bit(i, obj_priv->bit_17) != 0)) { - i915_gem_swizzle_page(obj_priv->pages[i]); - set_page_dirty(obj_priv->pages[i]); + (test_bit(i, obj->bit_17) != 0)) { + i915_gem_swizzle_page(obj->pages[i]); + set_page_dirty(obj->pages[i]); } } } void -i915_gem_object_save_bit_17_swizzle(struct drm_gem_object *obj) +i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj) { - struct drm_device *dev = obj->dev; + struct drm_device *dev = obj->base.dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); - int page_count = obj->size >> PAGE_SHIFT; + int page_count = obj->base.size >> PAGE_SHIFT; int i; if (dev_priv->mm.bit_6_swizzle_x != I915_BIT_6_SWIZZLE_9_10_17) return; - if (obj_priv->bit_17 == NULL) { - obj_priv->bit_17 = kmalloc(BITS_TO_LONGS(page_count) * + if (obj->bit_17 == NULL) { + obj->bit_17 = kmalloc(BITS_TO_LONGS(page_count) * sizeof(long), GFP_KERNEL); - if (obj_priv->bit_17 == NULL) { + if (obj->bit_17 == NULL) { DRM_ERROR("Failed to allocate memory for bit 17 " "record\n"); return; @@ -471,9 +472,9 @@ } for (i = 0; i < page_count; i++) { - if (page_to_phys(obj_priv->pages[i]) & (1 << 17)) - __set_bit(i, obj_priv->bit_17); + if (page_to_phys(obj->pages[i]) & (1 << 17)) + __set_bit(i, obj->bit_17); else - __clear_bit(i, obj_priv->bit_17); + __clear_bit(i, obj->bit_17); } } --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_irq.c +++ linux-2.6.37/drivers/gpu/drm/i915/i915_irq.c @@ -64,64 +64,24 @@ #define DRM_I915_VBLANK_PIPE_ALL (DRM_I915_VBLANK_PIPE_A | \ DRM_I915_VBLANK_PIPE_B) -void -ironlake_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) -{ - if ((dev_priv->gt_irq_mask_reg & mask) != 0) { - dev_priv->gt_irq_mask_reg &= ~mask; - I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg); - (void) I915_READ(GTIMR); - } -} - -void -ironlake_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask) -{ - if ((dev_priv->gt_irq_mask_reg & mask) != mask) { - dev_priv->gt_irq_mask_reg |= mask; - I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg); - (void) I915_READ(GTIMR); - } -} - /* For display hotplug interrupt */ static void ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask) { - if ((dev_priv->irq_mask_reg & mask) != 0) { - dev_priv->irq_mask_reg &= ~mask; - I915_WRITE(DEIMR, dev_priv->irq_mask_reg); - (void) I915_READ(DEIMR); + if ((dev_priv->irq_mask & mask) != 0) { + dev_priv->irq_mask &= ~mask; + I915_WRITE(DEIMR, dev_priv->irq_mask); + POSTING_READ(DEIMR); } } static inline void ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask) { - if ((dev_priv->irq_mask_reg & mask) != mask) { - dev_priv->irq_mask_reg |= mask; - I915_WRITE(DEIMR, dev_priv->irq_mask_reg); - (void) I915_READ(DEIMR); - } -} - -void -i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask) -{ - if ((dev_priv->irq_mask_reg & mask) != 0) { - dev_priv->irq_mask_reg &= ~mask; - I915_WRITE(IMR, dev_priv->irq_mask_reg); - (void) I915_READ(IMR); - } -} - -void -i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask) -{ - if ((dev_priv->irq_mask_reg & mask) != mask) { - dev_priv->irq_mask_reg |= mask; - I915_WRITE(IMR, dev_priv->irq_mask_reg); - (void) I915_READ(IMR); + if ((dev_priv->irq_mask & mask) != mask) { + dev_priv->irq_mask |= mask; + I915_WRITE(DEIMR, dev_priv->irq_mask); + POSTING_READ(DEIMR); } } @@ -144,7 +104,7 @@ dev_priv->pipestat[pipe] |= mask; /* Enable the interrupt, clear any pending status */ I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16)); - (void) I915_READ(reg); + POSTING_READ(reg); } } @@ -156,16 +116,19 @@ dev_priv->pipestat[pipe] &= ~mask; I915_WRITE(reg, dev_priv->pipestat[pipe]); - (void) I915_READ(reg); + POSTING_READ(reg); } } /** * intel_enable_asle - enable ASLE interrupt for OpRegion */ -void intel_enable_asle (struct drm_device *dev) +void intel_enable_asle(struct drm_device *dev) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + drm_i915_private_t *dev_priv = dev->dev_private; + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); if (HAS_PCH_SPLIT(dev)) ironlake_enable_display_irq(dev_priv, DE_GSE); @@ -176,6 +139,8 @@ i915_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE); } + + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } /** @@ -243,6 +208,92 @@ return I915_READ(reg); } +int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, + int *vpos, int *hpos) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + u32 vbl = 0, position = 0; + int vbl_start, vbl_end, htotal, vtotal; + bool in_vbl = true; + int ret = 0; + + if (!i915_pipe_enabled(dev, pipe)) { + DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled " + "pipe %d\n", pipe); + return 0; + } + + /* Get vtotal. */ + vtotal = 1 + ((I915_READ(VTOTAL(pipe)) >> 16) & 0x1fff); + + if (INTEL_INFO(dev)->gen >= 4) { + /* No obvious pixelcount register. Only query vertical + * scanout position from Display scan line register. + */ + position = I915_READ(PIPEDSL(pipe)); + + /* Decode into vertical scanout position. Don't have + * horizontal scanout position. + */ + *vpos = position & 0x1fff; + *hpos = 0; + } else { + /* Have access to pixelcount since start of frame. + * We can split this into vertical and horizontal + * scanout position. + */ + position = (I915_READ(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) >> PIPE_PIXEL_SHIFT; + + htotal = 1 + ((I915_READ(HTOTAL(pipe)) >> 16) & 0x1fff); + *vpos = position / htotal; + *hpos = position - (*vpos * htotal); + } + + /* Query vblank area. */ + vbl = I915_READ(VBLANK(pipe)); + + /* Test position against vblank region. */ + vbl_start = vbl & 0x1fff; + vbl_end = (vbl >> 16) & 0x1fff; + + if ((*vpos < vbl_start) || (*vpos > vbl_end)) + in_vbl = false; + + /* Inside "upper part" of vblank area? Apply corrective offset: */ + if (in_vbl && (*vpos >= vbl_start)) + *vpos = *vpos - vtotal; + + /* Readouts valid? */ + if (vbl > 0) + ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE; + + /* In vblank? */ + if (in_vbl) + ret |= DRM_SCANOUTPOS_INVBL; + + return ret; +} + +int i915_get_vblank_timestamp(struct drm_device *dev, int crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags) +{ + struct drm_crtc *drmcrtc; + + if (crtc < 0 || crtc >= dev->num_crtcs) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return -EINVAL; + } + + /* Get drm_crtc to timestamp: */ + drmcrtc = intel_get_crtc_for_pipe(dev, crtc); + + /* Helper routine in DRM core does all the work: */ + return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, + vblank_time, flags, drmcrtc); +} + /* * Handle hotplug events outside the interrupt handler proper. */ @@ -297,20 +348,61 @@ struct intel_ring_buffer *ring) { struct drm_i915_private *dev_priv = dev->dev_private; - u32 seqno = ring->get_seqno(dev, ring); - ring->irq_gem_seqno = seqno; + u32 seqno = ring->get_seqno(ring); + trace_i915_gem_request_complete(dev, seqno); + + ring->irq_seqno = seqno; wake_up_all(&ring->irq_queue); + dev_priv->hangcheck_count = 0; mod_timer(&dev_priv->hangcheck_timer, jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); } +static void gen6_pm_irq_handler(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + u8 new_delay = dev_priv->cur_delay; + u32 pm_iir; + + pm_iir = I915_READ(GEN6_PMIIR); + if (!pm_iir) + return; + + if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { + if (dev_priv->cur_delay != dev_priv->max_delay) + new_delay = dev_priv->cur_delay + 1; + if (new_delay > dev_priv->max_delay) + new_delay = dev_priv->max_delay; + } else if (pm_iir & (GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT)) { + if (dev_priv->cur_delay != dev_priv->min_delay) + new_delay = dev_priv->cur_delay - 1; + if (new_delay < dev_priv->min_delay) { + new_delay = dev_priv->min_delay; + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, + I915_READ(GEN6_RP_INTERRUPT_LIMITS) | + ((new_delay << 16) & 0x3f0000)); + } else { + /* Make sure we continue to get down interrupts + * until we hit the minimum frequency */ + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, + I915_READ(GEN6_RP_INTERRUPT_LIMITS) & ~0x3f0000); + } + + } + + gen6_set_rps(dev, new_delay); + dev_priv->cur_delay = new_delay; + + I915_WRITE(GEN6_PMIIR, pm_iir); +} + static irqreturn_t ironlake_irq_handler(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = IRQ_NONE; - u32 de_iir, gt_iir, de_ier, pch_iir; + u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir; u32 hotplug_mask; struct drm_i915_master_private *master_priv; u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT; @@ -321,13 +413,15 @@ /* disable master interrupt before clearing iir */ de_ier = I915_READ(DEIER); I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); - (void)I915_READ(DEIER); + POSTING_READ(DEIER); de_iir = I915_READ(DEIIR); gt_iir = I915_READ(GTIIR); pch_iir = I915_READ(SDEIIR); + pm_iir = I915_READ(GEN6_PMIIR); - if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) + if (de_iir == 0 && gt_iir == 0 && pch_iir == 0 && + (!IS_GEN6(dev) || pm_iir == 0)) goto done; if (HAS_PCH_CPT(dev)) @@ -344,12 +438,12 @@ READ_BREADCRUMB(dev_priv); } - if (gt_iir & GT_PIPE_NOTIFY) - notify_ring(dev, &dev_priv->render_ring); + if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY)) + notify_ring(dev, &dev_priv->ring[RCS]); if (gt_iir & bsd_usr_interrupt) - notify_ring(dev, &dev_priv->bsd_ring); - if (HAS_BLT(dev) && gt_iir & GT_BLT_USER_INTERRUPT) - notify_ring(dev, &dev_priv->blt_ring); + notify_ring(dev, &dev_priv->ring[VCS]); + if (gt_iir & GT_BLT_USER_INTERRUPT) + notify_ring(dev, &dev_priv->ring[BCS]); if (de_iir & DE_GSE) intel_opregion_gse_intr(dev); @@ -379,6 +473,9 @@ i915_handle_rps_change(dev); } + if (IS_GEN6(dev)) + gen6_pm_irq_handler(dev); + /* should clear PCH hotplug event before clear CPU irq */ I915_WRITE(SDEIIR, pch_iir); I915_WRITE(GTIIR, gt_iir); @@ -386,7 +483,7 @@ done: I915_WRITE(DEIER, de_ier); - (void)I915_READ(DEIER); + POSTING_READ(DEIER); return ret; } @@ -423,28 +520,23 @@ #ifdef CONFIG_DEBUG_FS static struct drm_i915_error_object * i915_error_object_create(struct drm_device *dev, - struct drm_gem_object *src) + struct drm_i915_gem_object *src) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_error_object *dst; - struct drm_i915_gem_object *src_priv; int page, page_count; u32 reloc_offset; - if (src == NULL) - return NULL; - - src_priv = to_intel_bo(src); - if (src_priv->pages == NULL) + if (src == NULL || src->pages == NULL) return NULL; - page_count = src->size / PAGE_SIZE; + page_count = src->base.size / PAGE_SIZE; dst = kmalloc(sizeof(*dst) + page_count * sizeof (u32 *), GFP_ATOMIC); if (dst == NULL) return NULL; - reloc_offset = src_priv->gtt_offset; + reloc_offset = src->gtt_offset; for (page = 0; page < page_count; page++) { unsigned long flags; void __iomem *s; @@ -466,7 +558,7 @@ reloc_offset += PAGE_SIZE; } dst->page_count = page_count; - dst->gtt_offset = src_priv->gtt_offset; + dst->gtt_offset = src->gtt_offset; return dst; @@ -520,36 +612,96 @@ } static u32 -i915_ringbuffer_last_batch(struct drm_device *dev) +i915_ringbuffer_last_batch(struct drm_device *dev, + struct intel_ring_buffer *ring) { struct drm_i915_private *dev_priv = dev->dev_private; u32 head, bbaddr; - u32 *ring; + u32 *val; /* Locate the current position in the ringbuffer and walk back * to find the most recently dispatched batch buffer. */ - bbaddr = 0; - head = I915_READ(PRB0_HEAD) & HEAD_ADDR; - ring = (u32 *)(dev_priv->render_ring.virtual_start + head); + head = I915_READ_HEAD(ring) & HEAD_ADDR; - while (--ring >= (u32 *)dev_priv->render_ring.virtual_start) { - bbaddr = i915_get_bbaddr(dev, ring); + val = (u32 *)(ring->virtual_start + head); + while (--val >= (u32 *)ring->virtual_start) { + bbaddr = i915_get_bbaddr(dev, val); if (bbaddr) - break; + return bbaddr; } - if (bbaddr == 0) { - ring = (u32 *)(dev_priv->render_ring.virtual_start - + dev_priv->render_ring.size); - while (--ring >= (u32 *)dev_priv->render_ring.virtual_start) { - bbaddr = i915_get_bbaddr(dev, ring); - if (bbaddr) - break; - } + val = (u32 *)(ring->virtual_start + ring->size); + while (--val >= (u32 *)ring->virtual_start) { + bbaddr = i915_get_bbaddr(dev, val); + if (bbaddr) + return bbaddr; + } + + return 0; +} + +static u32 capture_bo_list(struct drm_i915_error_buffer *err, + int count, + struct list_head *head) +{ + struct drm_i915_gem_object *obj; + int i = 0; + + list_for_each_entry(obj, head, mm_list) { + err->size = obj->base.size; + err->name = obj->base.name; + err->seqno = obj->last_rendering_seqno; + err->gtt_offset = obj->gtt_offset; + err->read_domains = obj->base.read_domains; + err->write_domain = obj->base.write_domain; + err->fence_reg = obj->fence_reg; + err->pinned = 0; + if (obj->pin_count > 0) + err->pinned = 1; + if (obj->user_pin_count > 0) + err->pinned = -1; + err->tiling = obj->tiling_mode; + err->dirty = obj->dirty; + err->purgeable = obj->madv != I915_MADV_WILLNEED; + err->ring = obj->ring ? obj->ring->id : 0; + + if (++i == count) + break; + + err++; } - return bbaddr; + return i; +} + +static void i915_gem_record_fences(struct drm_device *dev, + struct drm_i915_error_state *error) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int i; + + /* Fences */ + switch (INTEL_INFO(dev)->gen) { + case 6: + for (i = 0; i < 16; i++) + error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); + break; + case 5: + case 4: + for (i = 0; i < 16; i++) + error->fence[i] = I915_READ64(FENCE_REG_965_0 + (i * 8)); + break; + case 3: + if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) + for (i = 0; i < 8; i++) + error->fence[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4)); + case 2: + for (i = 0; i < 8; i++) + error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4)); + break; + + } } /** @@ -564,9 +716,9 @@ static void i915_capture_error_state(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; struct drm_i915_error_state *error; - struct drm_gem_object *batchbuffer[2]; + struct drm_i915_gem_object *batchbuffer[2]; unsigned long flags; u32 bbaddr; int count; @@ -585,20 +737,33 @@ DRM_DEBUG_DRIVER("generating error event\n"); - error->seqno = - dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring); + error->seqno = dev_priv->ring[RCS].get_seqno(&dev_priv->ring[RCS]); error->eir = I915_READ(EIR); error->pgtbl_er = I915_READ(PGTBL_ER); error->pipeastat = I915_READ(PIPEASTAT); error->pipebstat = I915_READ(PIPEBSTAT); error->instpm = I915_READ(INSTPM); - if (INTEL_INFO(dev)->gen < 4) { - error->ipeir = I915_READ(IPEIR); - error->ipehr = I915_READ(IPEHR); - error->instdone = I915_READ(INSTDONE); - error->acthd = I915_READ(ACTHD); - error->bbaddr = 0; - } else { + error->error = 0; + if (INTEL_INFO(dev)->gen >= 6) { + error->error = I915_READ(ERROR_GEN6); + + error->bcs_acthd = I915_READ(BCS_ACTHD); + error->bcs_ipehr = I915_READ(BCS_IPEHR); + error->bcs_ipeir = I915_READ(BCS_IPEIR); + error->bcs_instdone = I915_READ(BCS_INSTDONE); + error->bcs_seqno = 0; + if (dev_priv->ring[BCS].get_seqno) + error->bcs_seqno = dev_priv->ring[BCS].get_seqno(&dev_priv->ring[BCS]); + + error->vcs_acthd = I915_READ(VCS_ACTHD); + error->vcs_ipehr = I915_READ(VCS_IPEHR); + error->vcs_ipeir = I915_READ(VCS_IPEIR); + error->vcs_instdone = I915_READ(VCS_INSTDONE); + error->vcs_seqno = 0; + if (dev_priv->ring[VCS].get_seqno) + error->vcs_seqno = dev_priv->ring[VCS].get_seqno(&dev_priv->ring[VCS]); + } + if (INTEL_INFO(dev)->gen >= 4) { error->ipeir = I915_READ(IPEIR_I965); error->ipehr = I915_READ(IPEHR_I965); error->instdone = I915_READ(INSTDONE_I965); @@ -606,42 +771,45 @@ error->instdone1 = I915_READ(INSTDONE1); error->acthd = I915_READ(ACTHD_I965); error->bbaddr = I915_READ64(BB_ADDR); + } else { + error->ipeir = I915_READ(IPEIR); + error->ipehr = I915_READ(IPEHR); + error->instdone = I915_READ(INSTDONE); + error->acthd = I915_READ(ACTHD); + error->bbaddr = 0; } + i915_gem_record_fences(dev, error); - bbaddr = i915_ringbuffer_last_batch(dev); + bbaddr = i915_ringbuffer_last_batch(dev, &dev_priv->ring[RCS]); /* Grab the current batchbuffer, most likely to have crashed. */ batchbuffer[0] = NULL; batchbuffer[1] = NULL; count = 0; - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) { - struct drm_gem_object *obj = &obj_priv->base; - + list_for_each_entry(obj, &dev_priv->mm.active_list, mm_list) { if (batchbuffer[0] == NULL && - bbaddr >= obj_priv->gtt_offset && - bbaddr < obj_priv->gtt_offset + obj->size) + bbaddr >= obj->gtt_offset && + bbaddr < obj->gtt_offset + obj->base.size) batchbuffer[0] = obj; if (batchbuffer[1] == NULL && - error->acthd >= obj_priv->gtt_offset && - error->acthd < obj_priv->gtt_offset + obj->size) + error->acthd >= obj->gtt_offset && + error->acthd < obj->gtt_offset + obj->base.size) batchbuffer[1] = obj; count++; } /* Scan the other lists for completeness for those bizarre errors. */ if (batchbuffer[0] == NULL || batchbuffer[1] == NULL) { - list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list, mm_list) { - struct drm_gem_object *obj = &obj_priv->base; - + list_for_each_entry(obj, &dev_priv->mm.flushing_list, mm_list) { if (batchbuffer[0] == NULL && - bbaddr >= obj_priv->gtt_offset && - bbaddr < obj_priv->gtt_offset + obj->size) + bbaddr >= obj->gtt_offset && + bbaddr < obj->gtt_offset + obj->base.size) batchbuffer[0] = obj; if (batchbuffer[1] == NULL && - error->acthd >= obj_priv->gtt_offset && - error->acthd < obj_priv->gtt_offset + obj->size) + error->acthd >= obj->gtt_offset && + error->acthd < obj->gtt_offset + obj->base.size) batchbuffer[1] = obj; if (batchbuffer[0] && batchbuffer[1]) @@ -649,17 +817,15 @@ } } if (batchbuffer[0] == NULL || batchbuffer[1] == NULL) { - list_for_each_entry(obj_priv, &dev_priv->mm.inactive_list, mm_list) { - struct drm_gem_object *obj = &obj_priv->base; - + list_for_each_entry(obj, &dev_priv->mm.inactive_list, mm_list) { if (batchbuffer[0] == NULL && - bbaddr >= obj_priv->gtt_offset && - bbaddr < obj_priv->gtt_offset + obj->size) + bbaddr >= obj->gtt_offset && + bbaddr < obj->gtt_offset + obj->base.size) batchbuffer[0] = obj; if (batchbuffer[1] == NULL && - error->acthd >= obj_priv->gtt_offset && - error->acthd < obj_priv->gtt_offset + obj->size) + error->acthd >= obj->gtt_offset && + error->acthd < obj->gtt_offset + obj->base.size) batchbuffer[1] = obj; if (batchbuffer[0] && batchbuffer[1]) @@ -678,46 +844,41 @@ /* Record the ringbuffer */ error->ringbuffer = i915_error_object_create(dev, - dev_priv->render_ring.gem_object); + dev_priv->ring[RCS].obj); - /* Record buffers on the active list. */ + /* Record buffers on the active and pinned lists. */ error->active_bo = NULL; - error->active_bo_count = 0; + error->pinned_bo = NULL; + + error->active_bo_count = count; + list_for_each_entry(obj, &dev_priv->mm.pinned_list, mm_list) + count++; + error->pinned_bo_count = count - error->active_bo_count; - if (count) + if (count) { error->active_bo = kmalloc(sizeof(*error->active_bo)*count, GFP_ATOMIC); - - if (error->active_bo) { - int i = 0; - list_for_each_entry(obj_priv, &dev_priv->mm.active_list, mm_list) { - struct drm_gem_object *obj = &obj_priv->base; - - error->active_bo[i].size = obj->size; - error->active_bo[i].name = obj->name; - error->active_bo[i].seqno = obj_priv->last_rendering_seqno; - error->active_bo[i].gtt_offset = obj_priv->gtt_offset; - error->active_bo[i].read_domains = obj->read_domains; - error->active_bo[i].write_domain = obj->write_domain; - error->active_bo[i].fence_reg = obj_priv->fence_reg; - error->active_bo[i].pinned = 0; - if (obj_priv->pin_count > 0) - error->active_bo[i].pinned = 1; - if (obj_priv->user_pin_count > 0) - error->active_bo[i].pinned = -1; - error->active_bo[i].tiling = obj_priv->tiling_mode; - error->active_bo[i].dirty = obj_priv->dirty; - error->active_bo[i].purgeable = obj_priv->madv != I915_MADV_WILLNEED; - - if (++i == count) - break; - } - error->active_bo_count = i; - } + if (error->active_bo) + error->pinned_bo = + error->active_bo + error->active_bo_count; + } + + if (error->active_bo) + error->active_bo_count = + capture_bo_list(error->active_bo, + error->active_bo_count, + &dev_priv->mm.active_list); + + if (error->pinned_bo) + error->pinned_bo_count = + capture_bo_list(error->pinned_bo, + error->pinned_bo_count, + &dev_priv->mm.pinned_list); do_gettimeofday(&error->time); error->overlay = intel_overlay_capture_error_state(dev); + error->display = intel_display_capture_error_state(dev); spin_lock_irqsave(&dev_priv->error_lock, flags); if (dev_priv->first_error == NULL) { @@ -775,7 +936,7 @@ printk(KERN_ERR " ACTHD: 0x%08x\n", I915_READ(ACTHD_I965)); I915_WRITE(IPEIR_I965, ipeir); - (void)I915_READ(IPEIR_I965); + POSTING_READ(IPEIR_I965); } if (eir & GM45_ERROR_PAGE_TABLE) { u32 pgtbl_err = I915_READ(PGTBL_ER); @@ -783,7 +944,7 @@ printk(KERN_ERR " PGTBL_ER: 0x%08x\n", pgtbl_err); I915_WRITE(PGTBL_ER, pgtbl_err); - (void)I915_READ(PGTBL_ER); + POSTING_READ(PGTBL_ER); } } @@ -794,7 +955,7 @@ printk(KERN_ERR " PGTBL_ER: 0x%08x\n", pgtbl_err); I915_WRITE(PGTBL_ER, pgtbl_err); - (void)I915_READ(PGTBL_ER); + POSTING_READ(PGTBL_ER); } } @@ -825,7 +986,7 @@ printk(KERN_ERR " ACTHD: 0x%08x\n", I915_READ(ACTHD)); I915_WRITE(IPEIR, ipeir); - (void)I915_READ(IPEIR); + POSTING_READ(IPEIR); } else { u32 ipeir = I915_READ(IPEIR_I965); @@ -842,12 +1003,12 @@ printk(KERN_ERR " ACTHD: 0x%08x\n", I915_READ(ACTHD_I965)); I915_WRITE(IPEIR_I965, ipeir); - (void)I915_READ(IPEIR_I965); + POSTING_READ(IPEIR_I965); } } I915_WRITE(EIR, eir); - (void)I915_READ(EIR); + POSTING_READ(EIR); eir = I915_READ(EIR); if (eir) { /* @@ -870,7 +1031,7 @@ * so userspace knows something bad happened (should trigger collection * of a ring dump etc.). */ -static void i915_handle_error(struct drm_device *dev, bool wedged) +void i915_handle_error(struct drm_device *dev, bool wedged) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -884,11 +1045,11 @@ /* * Wakeup waiting processes so they don't hang */ - wake_up_all(&dev_priv->render_ring.irq_queue); + wake_up_all(&dev_priv->ring[RCS].irq_queue); if (HAS_BSD(dev)) - wake_up_all(&dev_priv->bsd_ring.irq_queue); + wake_up_all(&dev_priv->ring[VCS].irq_queue); if (HAS_BLT(dev)) - wake_up_all(&dev_priv->blt_ring.irq_queue); + wake_up_all(&dev_priv->ring[BCS].irq_queue); } queue_work(dev_priv->wq, &dev_priv->error_work); @@ -899,7 +1060,7 @@ drm_i915_private_t *dev_priv = dev->dev_private; struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; struct intel_unpin_work *work; unsigned long flags; bool stall_detected; @@ -918,13 +1079,13 @@ } /* Potential stall - if we see that the flip has happened, assume a missed interrupt */ - obj_priv = to_intel_bo(work->pending_flip_obj); + obj = work->pending_flip_obj; if (INTEL_INFO(dev)->gen >= 4) { int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF; - stall_detected = I915_READ(dspsurf) == obj_priv->gtt_offset; + stall_detected = I915_READ(dspsurf) == obj->gtt_offset; } else { int dspaddr = intel_crtc->plane == 0 ? DSPAADDR : DSPBADDR; - stall_detected = I915_READ(dspaddr) == (obj_priv->gtt_offset + + stall_detected = I915_READ(dspaddr) == (obj->gtt_offset + crtc->y * crtc->fb->pitch + crtc->x * crtc->fb->bits_per_pixel/8); } @@ -970,7 +1131,7 @@ * It doesn't set the bit in iir again, but it still produces * interrupts (for non-MSI). */ - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); pipea_stats = I915_READ(PIPEASTAT); pipeb_stats = I915_READ(PIPEBSTAT); @@ -993,7 +1154,7 @@ I915_WRITE(PIPEBSTAT, pipeb_stats); irq_received = 1; } - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); if (!irq_received) break; @@ -1026,9 +1187,9 @@ } if (iir & I915_USER_INTERRUPT) - notify_ring(dev, &dev_priv->render_ring); - if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT)) - notify_ring(dev, &dev_priv->bsd_ring); + notify_ring(dev, &dev_priv->ring[RCS]); + if (iir & I915_BSD_USER_INTERRUPT) + notify_ring(dev, &dev_priv->ring[VCS]); if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) { intel_prepare_page_flip(dev, 0); @@ -1101,12 +1262,13 @@ if (master_priv->sarea_priv) master_priv->sarea_priv->last_enqueue = dev_priv->counter; - BEGIN_LP_RING(4); - OUT_RING(MI_STORE_DWORD_INDEX); - OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - OUT_RING(dev_priv->counter); - OUT_RING(MI_USER_INTERRUPT); - ADVANCE_LP_RING(); + if (BEGIN_LP_RING(4) == 0) { + OUT_RING(MI_STORE_DWORD_INDEX); + OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); + OUT_RING(dev_priv->counter); + OUT_RING(MI_USER_INTERRUPT); + ADVANCE_LP_RING(); + } return dev_priv->counter; } @@ -1114,12 +1276,11 @@ void i915_trace_irq_get(struct drm_device *dev, u32 seqno) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - struct intel_ring_buffer *render_ring = &dev_priv->render_ring; + struct intel_ring_buffer *ring = LP_RING(dev_priv); - if (dev_priv->trace_irq_seqno == 0) - render_ring->user_irq_get(dev, render_ring); - - dev_priv->trace_irq_seqno = seqno; + if (dev_priv->trace_irq_seqno == 0 && + ring->irq_get(ring)) + dev_priv->trace_irq_seqno = seqno; } static int i915_wait_irq(struct drm_device * dev, int irq_nr) @@ -1127,7 +1288,7 @@ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; int ret = 0; - struct intel_ring_buffer *render_ring = &dev_priv->render_ring; + struct intel_ring_buffer *ring = LP_RING(dev_priv); DRM_DEBUG_DRIVER("irq_nr=%d breadcrumb=%d\n", irq_nr, READ_BREADCRUMB(dev_priv)); @@ -1141,10 +1302,12 @@ if (master_priv->sarea_priv) master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; - render_ring->user_irq_get(dev, render_ring); - DRM_WAIT_ON(ret, dev_priv->render_ring.irq_queue, 3 * DRM_HZ, - READ_BREADCRUMB(dev_priv) >= irq_nr); - render_ring->user_irq_put(dev, render_ring); + ret = -ENODEV; + if (ring->irq_get(ring)) { + DRM_WAIT_ON(ret, ring->irq_queue, 3 * DRM_HZ, + READ_BREADCRUMB(dev_priv) >= irq_nr); + ring->irq_put(ring); + } if (ret == -EBUSY) { DRM_ERROR("EBUSY -- rec: %d emitted: %d\n", @@ -1163,7 +1326,7 @@ drm_i915_irq_emit_t *emit = data; int result; - if (!dev_priv || !dev_priv->render_ring.virtual_start) { + if (!dev_priv || !LP_RING(dev_priv)->virtual_start) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } @@ -1209,9 +1372,9 @@ if (!i915_pipe_enabled(dev, pipe)) return -EINVAL; - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); if (HAS_PCH_SPLIT(dev)) - ironlake_enable_display_irq(dev_priv, (pipe == 0) ? + ironlake_enable_display_irq(dev_priv, (pipe == 0) ? DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); else if (INTEL_INFO(dev)->gen >= 4) i915_enable_pipestat(dev_priv, pipe, @@ -1219,7 +1382,7 @@ else i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; } @@ -1231,15 +1394,15 @@ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); if (HAS_PCH_SPLIT(dev)) - ironlake_disable_display_irq(dev_priv, (pipe == 0) ? + ironlake_disable_display_irq(dev_priv, (pipe == 0) ? DE_PIPEA_VBLANK: DE_PIPEB_VBLANK); else i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE | PIPE_START_VBLANK_INTERRUPT_ENABLE); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } void i915_enable_interrupt (struct drm_device *dev) @@ -1306,12 +1469,50 @@ return -EINVAL; } -static struct drm_i915_gem_request * -i915_get_tail_request(struct drm_device *dev) +static u32 +ring_last_seqno(struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = dev->dev_private; - return list_entry(dev_priv->render_ring.request_list.prev, - struct drm_i915_gem_request, list); + return list_entry(ring->request_list.prev, + struct drm_i915_gem_request, list)->seqno; +} + +static bool i915_hangcheck_ring_idle(struct intel_ring_buffer *ring, bool *err) +{ + if (list_empty(&ring->request_list) || + i915_seqno_passed(ring->get_seqno(ring), ring_last_seqno(ring))) { + /* Issue a wake-up to catch stuck h/w. */ + if (ring->waiting_seqno && waitqueue_active(&ring->irq_queue)) { + DRM_ERROR("Hangcheck timer elapsed... %s idle [waiting on %d, at %d], missed IRQ?\n", + ring->name, + ring->waiting_seqno, + ring->get_seqno(ring)); + wake_up_all(&ring->irq_queue); + *err = true; + } + return true; + } + return false; +} + +static bool kick_ring(struct intel_ring_buffer *ring) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + u32 tmp = I915_READ_CTL(ring); + if (tmp & RING_WAIT) { + DRM_ERROR("Kicking stuck wait on %s\n", + ring->name); + I915_WRITE_CTL(ring, tmp); + return true; + } + if (IS_GEN6(dev) && + (tmp & RING_WAIT_SEMAPHORE)) { + DRM_ERROR("Kicking stuck semaphore on %s\n", + ring->name); + I915_WRITE_CTL(ring, tmp); + return true; + } + return false; } /** @@ -1325,6 +1526,17 @@ struct drm_device *dev = (struct drm_device *)data; drm_i915_private_t *dev_priv = dev->dev_private; uint32_t acthd, instdone, instdone1; + bool err = false; + + /* If all work is done then ACTHD clearly hasn't advanced. */ + if (i915_hangcheck_ring_idle(&dev_priv->ring[RCS], &err) && + i915_hangcheck_ring_idle(&dev_priv->ring[VCS], &err) && + i915_hangcheck_ring_idle(&dev_priv->ring[BCS], &err)) { + dev_priv->hangcheck_count = 0; + if (err) + goto repeat; + return; + } if (INTEL_INFO(dev)->gen < 4) { acthd = I915_READ(ACTHD); @@ -1336,38 +1548,6 @@ instdone1 = I915_READ(INSTDONE1); } - /* If all work is done then ACTHD clearly hasn't advanced. */ - if (list_empty(&dev_priv->render_ring.request_list) || - i915_seqno_passed(dev_priv->render_ring.get_seqno(dev, &dev_priv->render_ring), - i915_get_tail_request(dev)->seqno)) { - bool missed_wakeup = false; - - dev_priv->hangcheck_count = 0; - - /* Issue a wake-up to catch stuck h/w. */ - if (dev_priv->render_ring.waiting_gem_seqno && - waitqueue_active(&dev_priv->render_ring.irq_queue)) { - wake_up_all(&dev_priv->render_ring.irq_queue); - missed_wakeup = true; - } - - if (dev_priv->bsd_ring.waiting_gem_seqno && - waitqueue_active(&dev_priv->bsd_ring.irq_queue)) { - wake_up_all(&dev_priv->bsd_ring.irq_queue); - missed_wakeup = true; - } - - if (dev_priv->blt_ring.waiting_gem_seqno && - waitqueue_active(&dev_priv->blt_ring.irq_queue)) { - wake_up_all(&dev_priv->blt_ring.irq_queue); - missed_wakeup = true; - } - - if (missed_wakeup) - DRM_ERROR("Hangcheck timer elapsed... GPU idle, missed IRQ.\n"); - return; - } - if (dev_priv->last_acthd == acthd && dev_priv->last_instdone == instdone && dev_priv->last_instdone1 == instdone1) { @@ -1380,12 +1560,17 @@ * and break the hang. This should work on * all but the second generation chipsets. */ - u32 tmp = I915_READ(PRB0_CTL); - if (tmp & RING_WAIT) { - I915_WRITE(PRB0_CTL, tmp); - POSTING_READ(PRB0_CTL); - goto out; - } + + if (kick_ring(&dev_priv->ring[RCS])) + goto repeat; + + if (HAS_BSD(dev) && + kick_ring(&dev_priv->ring[VCS])) + goto repeat; + + if (HAS_BLT(dev) && + kick_ring(&dev_priv->ring[BCS])) + goto repeat; } i915_handle_error(dev, true); @@ -1399,7 +1584,7 @@ dev_priv->last_instdone1 = instdone1; } -out: +repeat: /* Reset timer case chip hangs without another request being added */ mod_timer(&dev_priv->hangcheck_timer, jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); @@ -1417,17 +1602,17 @@ I915_WRITE(DEIMR, 0xffffffff); I915_WRITE(DEIER, 0x0); - (void) I915_READ(DEIER); + POSTING_READ(DEIER); /* and GT */ I915_WRITE(GTIMR, 0xffffffff); I915_WRITE(GTIER, 0x0); - (void) I915_READ(GTIER); + POSTING_READ(GTIER); /* south display irq */ I915_WRITE(SDEIMR, 0xffffffff); I915_WRITE(SDEIER, 0x0); - (void) I915_READ(SDEIER); + POSTING_READ(SDEIER); } static int ironlake_irq_postinstall(struct drm_device *dev) @@ -1436,38 +1621,34 @@ /* enable kind of interrupts always enabled */ u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE; - u32 render_mask = GT_PIPE_NOTIFY | GT_BSD_USER_INTERRUPT; + u32 render_irqs; u32 hotplug_mask; - dev_priv->irq_mask_reg = ~display_mask; - dev_priv->de_irq_enable_reg = display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK; + dev_priv->irq_mask = ~display_mask; /* should always can generate irq */ I915_WRITE(DEIIR, I915_READ(DEIIR)); - I915_WRITE(DEIMR, dev_priv->irq_mask_reg); - I915_WRITE(DEIER, dev_priv->de_irq_enable_reg); - (void) I915_READ(DEIER); + I915_WRITE(DEIMR, dev_priv->irq_mask); + I915_WRITE(DEIER, display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK); + POSTING_READ(DEIER); - if (IS_GEN6(dev)) { - render_mask = - GT_PIPE_NOTIFY | - GT_GEN6_BSD_USER_INTERRUPT | - GT_BLT_USER_INTERRUPT; - } - - dev_priv->gt_irq_mask_reg = ~render_mask; - dev_priv->gt_irq_enable_reg = render_mask; + dev_priv->gt_irq_mask = ~0; I915_WRITE(GTIIR, I915_READ(GTIIR)); - I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg); - if (IS_GEN6(dev)) { - I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT); - I915_WRITE(GEN6_BSD_IMR, ~GEN6_BSD_IMR_USER_INTERRUPT); - I915_WRITE(GEN6_BLITTER_IMR, ~GEN6_BLITTER_USER_INTERRUPT); - } + I915_WRITE(GTIMR, dev_priv->gt_irq_mask); - I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); - (void) I915_READ(GTIER); + if (IS_GEN6(dev)) + render_irqs = + GT_USER_INTERRUPT | + GT_GEN6_BSD_USER_INTERRUPT | + GT_BLT_USER_INTERRUPT; + else + render_irqs = + GT_USER_INTERRUPT | + GT_PIPE_NOTIFY | + GT_BSD_USER_INTERRUPT; + I915_WRITE(GTIER, render_irqs); + POSTING_READ(GTIER); if (HAS_PCH_CPT(dev)) { hotplug_mask = SDE_CRT_HOTPLUG_CPT | SDE_PORTB_HOTPLUG_CPT | @@ -1477,13 +1658,12 @@ SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; } - dev_priv->pch_irq_mask_reg = ~hotplug_mask; - dev_priv->pch_irq_enable_reg = hotplug_mask; + dev_priv->pch_irq_mask = ~hotplug_mask; I915_WRITE(SDEIIR, I915_READ(SDEIIR)); - I915_WRITE(SDEIMR, dev_priv->pch_irq_mask_reg); - I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg); - (void) I915_READ(SDEIER); + I915_WRITE(SDEIMR, dev_priv->pch_irq_mask); + I915_WRITE(SDEIER, hotplug_mask); + POSTING_READ(SDEIER); if (IS_IRONLAKE_M(dev)) { /* Clear & enable PCU event interrupts */ @@ -1519,7 +1699,7 @@ I915_WRITE(PIPEBSTAT, 0); I915_WRITE(IMR, 0xffffffff); I915_WRITE(IER, 0x0); - (void) I915_READ(IER); + POSTING_READ(IER); } /* @@ -1532,11 +1712,11 @@ u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; u32 error_mask; - DRM_INIT_WAITQUEUE(&dev_priv->render_ring.irq_queue); + DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue); if (HAS_BSD(dev)) - DRM_INIT_WAITQUEUE(&dev_priv->bsd_ring.irq_queue); + DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue); if (HAS_BLT(dev)) - DRM_INIT_WAITQUEUE(&dev_priv->blt_ring.irq_queue); + DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue); dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; @@ -1544,7 +1724,7 @@ return ironlake_irq_postinstall(dev); /* Unmask the interrupts that we always want on. */ - dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX; + dev_priv->irq_mask = ~I915_INTERRUPT_ENABLE_FIX; dev_priv->pipestat[0] = 0; dev_priv->pipestat[1] = 0; @@ -1553,7 +1733,7 @@ /* Enable in IER... */ enable_mask |= I915_DISPLAY_PORT_INTERRUPT; /* and unmask in IMR */ - dev_priv->irq_mask_reg &= ~I915_DISPLAY_PORT_INTERRUPT; + dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; } /* @@ -1571,9 +1751,9 @@ } I915_WRITE(EMR, error_mask); - I915_WRITE(IMR, dev_priv->irq_mask_reg); + I915_WRITE(IMR, dev_priv->irq_mask); I915_WRITE(IER, enable_mask); - (void) I915_READ(IER); + POSTING_READ(IER); if (I915_HAS_HOTPLUG(dev)) { u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_reg.h +++ linux-2.6.37/drivers/gpu/drm/i915/i915_reg.h @@ -78,6 +78,12 @@ #define GRDOM_RENDER (1<<2) #define GRDOM_MEDIA (3<<2) +#define GEN6_GDRST 0x941c +#define GEN6_GRDOM_FULL (1 << 0) +#define GEN6_GRDOM_RENDER (1 << 1) +#define GEN6_GRDOM_MEDIA (1 << 2) +#define GEN6_GRDOM_BLT (1 << 3) + /* VGA stuff */ #define VGA_ST01_MDA 0x3ba @@ -158,12 +164,23 @@ #define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) #define MI_STORE_DWORD_INDEX_SHIFT 2 -#define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1) +/* Official intel docs are somewhat sloppy concerning MI_LOAD_REGISTER_IMM: + * - Always issue a MI_NOOP _before_ the MI_LOAD_REGISTER_IMM - otherwise hw + * simply ignores the register load under certain conditions. + * - One can actually load arbitrary many arbitrary registers: Simply issue x + * address/value pairs. Don't overdue it, though, x <= 2^4 must hold! + */ +#define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*x-1) #define MI_FLUSH_DW MI_INSTR(0x26, 2) /* for GEN6 */ #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) #define MI_BATCH_NON_SECURE (1) #define MI_BATCH_NON_SECURE_I965 (1<<8) #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) +#define MI_SEMAPHORE_MBOX MI_INSTR(0x16, 1) /* gen6+ */ +#define MI_SEMAPHORE_GLOBAL_GTT (1<<22) +#define MI_SEMAPHORE_UPDATE (1<<21) +#define MI_SEMAPHORE_COMPARE (1<<20) +#define MI_SEMAPHORE_REGISTER (1<<18) /* * 3D instructions used by the kernel */ @@ -256,10 +273,6 @@ * Instruction and interrupt control regs */ #define PGTBL_ER 0x02024 -#define PRB0_TAIL 0x02030 -#define PRB0_HEAD 0x02034 -#define PRB0_START 0x02038 -#define PRB0_CTL 0x0203c #define RENDER_RING_BASE 0x02000 #define BSD_RING_BASE 0x04000 #define GEN6_BSD_RING_BASE 0x12000 @@ -268,9 +281,14 @@ #define RING_HEAD(base) ((base)+0x34) #define RING_START(base) ((base)+0x38) #define RING_CTL(base) ((base)+0x3c) +#define RING_SYNC_0(base) ((base)+0x40) +#define RING_SYNC_1(base) ((base)+0x44) +#define RING_MAX_IDLE(base) ((base)+0x54) #define RING_HWS_PGA(base) ((base)+0x80) #define RING_HWS_PGA_GEN6(base) ((base)+0x2080) #define RING_ACTHD(base) ((base)+0x74) +#define RING_NOPID(base) ((base)+0x94) +#define RING_IMR(base) ((base)+0xa8) #define TAIL_ADDR 0x001FFFF8 #define HEAD_WRAP_COUNT 0xFFE00000 #define HEAD_WRAP_ONE 0x00200000 @@ -285,10 +303,17 @@ #define RING_INVALID 0x00000000 #define RING_WAIT_I8XX (1<<0) /* gen2, PRBx_HEAD */ #define RING_WAIT (1<<11) /* gen3+, PRBx_CTL */ +#define RING_WAIT_SEMAPHORE (1<<10) /* gen6+ */ +#if 0 +#define PRB0_TAIL 0x02030 +#define PRB0_HEAD 0x02034 +#define PRB0_START 0x02038 +#define PRB0_CTL 0x0203c #define PRB1_TAIL 0x02040 /* 915+ only */ #define PRB1_HEAD 0x02044 /* 915+ only */ #define PRB1_START 0x02048 /* 915+ only */ #define PRB1_CTL 0x0204c /* 915+ only */ +#endif #define IPEIR_I965 0x02064 #define IPEHR_I965 0x02068 #define INSTDONE_I965 0x0206c @@ -305,11 +330,42 @@ #define INSTDONE 0x02090 #define NOPID 0x02094 #define HWSTAM 0x02098 +#define VCS_INSTDONE 0x1206C +#define VCS_IPEIR 0x12064 +#define VCS_IPEHR 0x12068 +#define VCS_ACTHD 0x12074 +#define BCS_INSTDONE 0x2206C +#define BCS_IPEIR 0x22064 +#define BCS_IPEHR 0x22068 +#define BCS_ACTHD 0x22074 + +#define ERROR_GEN6 0x040a0 + +/* GM45+ chicken bits -- debug workaround bits that may be required + * for various sorts of correct behavior. The top 16 bits of each are + * the enables for writing to the corresponding low bit. + */ +#define _3D_CHICKEN 0x02084 +#define _3D_CHICKEN2 0x0208c +/* Disables pipelining of read flushes past the SF-WIZ interface. + * Required on all Ironlake steppings according to the B-Spec, but the + * particular danger of not doing so is not specified. + */ +# define _3D_CHICKEN2_WM_READ_PIPELINED (1 << 14) +#define _3D_CHICKEN3 0x02090 #define MI_MODE 0x0209c # define VS_TIMER_DISPATCH (1 << 6) # define MI_FLUSH_ENABLE (1 << 11) +#define GFX_MODE 0x02520 +#define GFX_RUN_LIST_ENABLE (1<<15) +#define GFX_TLB_INVALIDATE_ALWAYS (1<<13) +#define GFX_SURFACE_FAULT_ENABLE (1<<12) +#define GFX_REPLAY_MODE (1<<11) +#define GFX_PSMI_GRANULARITY (1<<10) +#define GFX_PPGTT_ENABLE (1<<9) + #define SCPD0 0x0209c /* 915+ only */ #define IER 0x020a0 #define IIR 0x020a4 @@ -461,7 +517,7 @@ #define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3) #define GEN6_BSD_IMR 0x120a8 -#define GEN6_BSD_IMR_USER_INTERRUPT (1 << 12) +#define GEN6_BSD_USER_INTERRUPT (1 << 12) #define GEN6_BSD_RNCID 0x12198 @@ -541,6 +597,18 @@ #define ILK_DISPLAY_CHICKEN1 0x42000 #define ILK_FBCQ_DIS (1<<22) +#define ILK_PABSTRETCH_DIS (1<<21) + + +/* + * Framebuffer compression for Sandybridge + * + * The following two registers are of type GTTMMADR + */ +#define SNB_DPFC_CTL_SA 0x100100 +#define SNB_CPU_FENCE_ENABLE (1<<29) +#define DPFC_CPU_FENCE_OFFSET 0x100104 + /* * GPIO regs @@ -900,6 +968,8 @@ */ #define MCHBAR_MIRROR_BASE 0x10000 +#define MCHBAR_MIRROR_BASE_SNB 0x140000 + /** 915-945 and GM965 MCH register controlling DRAM channel access */ #define DCC 0x10200 #define DCC_ADDRESSING_MODE_SINGLE_CHANNEL (0 << 0) @@ -1119,6 +1189,10 @@ #define DDRMPLL1 0X12c20 #define PEG_BAND_GAP_DATA 0x14d68 +#define GEN6_GT_PERF_STATUS 0x145948 +#define GEN6_RP_STATE_LIMITS 0x145994 +#define GEN6_RP_STATE_CAP 0x145998 + /* * Logical Context regs */ @@ -1168,7 +1242,6 @@ #define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B) #define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B) #define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B) -#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC) #define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B) /* VGA port control */ @@ -2182,8 +2255,10 @@ #define PIPE_6BPC (2 << 5) #define PIPE_12BPC (3 << 5) +#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC) #define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF) #define PIPEDSL(pipe) _PIPE(pipe, PIPEADSL, PIPEBDSL) +#define PIPEFRAMEPIXEL(pipe) _PIPE(pipe, PIPEAFRAMEPIXEL, PIPEBFRAMEPIXEL) #define DSPARB 0x70030 #define DSPARB_CSTART_MASK (0x7f << 7) @@ -2271,8 +2346,13 @@ /* Memory latency timer register */ #define MLTR_ILK 0x11222 +#define MLTR_WM1_SHIFT 0 +#define MLTR_WM2_SHIFT 8 /* the unit of memory self-refresh latency time is 0.5us */ #define ILK_SRLT_MASK 0x3f +#define ILK_LATENCY(shift) (I915_READ(MLTR_ILK) >> (shift) & ILK_SRLT_MASK) +#define ILK_READ_WM1_LATENCY() ILK_LATENCY(MLTR_WM1_SHIFT) +#define ILK_READ_WM2_LATENCY() ILK_LATENCY(MLTR_WM2_SHIFT) /* define the fifo size on Ironlake */ #define ILK_DISPLAY_FIFO 128 @@ -2291,6 +2371,40 @@ #define ILK_FIFO_LINE_SIZE 64 +/* define the WM info on Sandybridge */ +#define SNB_DISPLAY_FIFO 128 +#define SNB_DISPLAY_MAXWM 0x7f /* bit 16:22 */ +#define SNB_DISPLAY_DFTWM 8 +#define SNB_CURSOR_FIFO 32 +#define SNB_CURSOR_MAXWM 0x1f /* bit 4:0 */ +#define SNB_CURSOR_DFTWM 8 + +#define SNB_DISPLAY_SR_FIFO 512 +#define SNB_DISPLAY_MAX_SRWM 0x1ff /* bit 16:8 */ +#define SNB_DISPLAY_DFT_SRWM 0x3f +#define SNB_CURSOR_SR_FIFO 64 +#define SNB_CURSOR_MAX_SRWM 0x3f /* bit 5:0 */ +#define SNB_CURSOR_DFT_SRWM 8 + +#define SNB_FBC_MAX_SRWM 0xf /* bit 23:20 */ + +#define SNB_FIFO_LINE_SIZE 64 + + +/* the address where we get all kinds of latency value */ +#define SSKPD 0x5d10 +#define SSKPD_WM_MASK 0x3f +#define SSKPD_WM0_SHIFT 0 +#define SSKPD_WM1_SHIFT 8 +#define SSKPD_WM2_SHIFT 16 +#define SSKPD_WM3_SHIFT 24 + +#define SNB_LATENCY(shift) (I915_READ(MCHBAR_MIRROR_BASE_SNB + SSKPD) >> (shift) & SSKPD_WM_MASK) +#define SNB_READ_WM0_LATENCY() SNB_LATENCY(SSKPD_WM0_SHIFT) +#define SNB_READ_WM1_LATENCY() SNB_LATENCY(SSKPD_WM1_SHIFT) +#define SNB_READ_WM2_LATENCY() SNB_LATENCY(SSKPD_WM2_SHIFT) +#define SNB_READ_WM3_LATENCY() SNB_LATENCY(SSKPD_WM3_SHIFT) + /* * The two pipe frame counter registers are not synchronized, so * reading a stable value is somewhat tricky. The following code @@ -2351,6 +2465,10 @@ #define CURBBASE 0x700c4 #define CURBPOS 0x700c8 +#define CURCNTR(pipe) _PIPE(pipe, CURACNTR, CURBCNTR) +#define CURBASE(pipe) _PIPE(pipe, CURABASE, CURBBASE) +#define CURPOS(pipe) _PIPE(pipe, CURAPOS, CURBPOS) + /* Display A control */ #define DSPACNTR 0x70180 #define DISPLAY_PLANE_ENABLE (1<<31) @@ -2589,6 +2707,8 @@ #define GTIER 0x4401c #define ILK_DISPLAY_CHICKEN2 0x42004 +/* Required on all Ironlake and Sandybridge according to the B-Spec. */ +#define ILK_ELPIN_409_SELECT (1 << 25) #define ILK_DPARB_GATE (1<<22) #define ILK_VSDPFD_FULL (1<<21) #define ILK_DISPLAY_CHICKEN_FUSES 0x42014 @@ -2600,6 +2720,8 @@ #define ILK_DESKTOP (1<<23) #define ILK_DSPCLK_GATE 0x42020 #define ILK_DPARB_CLK_GATE (1<<5) +#define ILK_DPFD_CLK_GATE (1<<7) + /* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */ #define ILK_CLK_FBC (1<<7) #define ILK_DPFC_DIS1 (1<<8) @@ -2679,6 +2801,7 @@ #define PCH_DPLL(pipe) _PIPE(pipe, PCH_DPLL_A, PCH_DPLL_B) #define PCH_FPA0 0xc6040 +#define FP_CB_TUNE (0x3<<22) #define PCH_FPA1 0xc6044 #define PCH_FPB0 0xc6048 #define PCH_FPB1 0xc604c @@ -3063,4 +3186,67 @@ #define EDP_LINK_TRAIN_800MV_0DB_SNB_B (0x38<<22) #define EDP_LINK_TRAIN_VOL_EMP_MASK_SNB (0x3f<<22) +#define FORCEWAKE 0xA18C +#define FORCEWAKE_ACK 0x130090 + +#define GEN6_RPNSWREQ 0xA008 +#define GEN6_TURBO_DISABLE (1<<31) +#define GEN6_FREQUENCY(x) ((x)<<25) +#define GEN6_OFFSET(x) ((x)<<19) +#define GEN6_AGGRESSIVE_TURBO (0<<15) +#define GEN6_RC_VIDEO_FREQ 0xA00C +#define GEN6_RC_CONTROL 0xA090 +#define GEN6_RC_CTL_RC6pp_ENABLE (1<<16) +#define GEN6_RC_CTL_RC6p_ENABLE (1<<17) +#define GEN6_RC_CTL_RC6_ENABLE (1<<18) +#define GEN6_RC_CTL_RC1e_ENABLE (1<<20) +#define GEN6_RC_CTL_RC7_ENABLE (1<<22) +#define GEN6_RC_CTL_EI_MODE(x) ((x)<<27) +#define GEN6_RC_CTL_HW_ENABLE (1<<31) +#define GEN6_RP_DOWN_TIMEOUT 0xA010 +#define GEN6_RP_INTERRUPT_LIMITS 0xA014 +#define GEN6_RPSTAT1 0xA01C +#define GEN6_RP_CONTROL 0xA024 +#define GEN6_RP_MEDIA_TURBO (1<<11) +#define GEN6_RP_USE_NORMAL_FREQ (1<<9) +#define GEN6_RP_MEDIA_IS_GFX (1<<8) +#define GEN6_RP_ENABLE (1<<7) +#define GEN6_RP_UP_BUSY_MAX (0x2<<3) +#define GEN6_RP_DOWN_BUSY_MIN (0x2<<0) +#define GEN6_RP_UP_THRESHOLD 0xA02C +#define GEN6_RP_DOWN_THRESHOLD 0xA030 +#define GEN6_RP_UP_EI 0xA068 +#define GEN6_RP_DOWN_EI 0xA06C +#define GEN6_RP_IDLE_HYSTERSIS 0xA070 +#define GEN6_RC_STATE 0xA094 +#define GEN6_RC1_WAKE_RATE_LIMIT 0xA098 +#define GEN6_RC6_WAKE_RATE_LIMIT 0xA09C +#define GEN6_RC6pp_WAKE_RATE_LIMIT 0xA0A0 +#define GEN6_RC_EVALUATION_INTERVAL 0xA0A8 +#define GEN6_RC_IDLE_HYSTERSIS 0xA0AC +#define GEN6_RC_SLEEP 0xA0B0 +#define GEN6_RC1e_THRESHOLD 0xA0B4 +#define GEN6_RC6_THRESHOLD 0xA0B8 +#define GEN6_RC6p_THRESHOLD 0xA0BC +#define GEN6_RC6pp_THRESHOLD 0xA0C0 +#define GEN6_PMINTRMSK 0xA168 + +#define GEN6_PMISR 0x44020 +#define GEN6_PMIMR 0x44024 +#define GEN6_PMIIR 0x44028 +#define GEN6_PMIER 0x4402C +#define GEN6_PM_MBOX_EVENT (1<<25) +#define GEN6_PM_THERMAL_EVENT (1<<24) +#define GEN6_PM_RP_DOWN_TIMEOUT (1<<6) +#define GEN6_PM_RP_UP_THRESHOLD (1<<5) +#define GEN6_PM_RP_DOWN_THRESHOLD (1<<4) +#define GEN6_PM_RP_UP_EI_EXPIRED (1<<2) +#define GEN6_PM_RP_DOWN_EI_EXPIRED (1<<1) + +#define GEN6_PCODE_MAILBOX 0x138124 +#define GEN6_PCODE_READY (1<<31) +#define GEN6_READ_OC_PARAMS 0xc +#define GEN6_PCODE_WRITE_MIN_FREQ_TABLE 0x9 +#define GEN6_PCODE_DATA 0x138128 + #endif /* _I915_REG_H_ */ --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_suspend.c +++ linux-2.6.37/drivers/gpu/drm/i915/i915_suspend.c @@ -235,6 +235,7 @@ static void i915_save_modeset_reg(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + int i; if (drm_core_check_feature(dev, DRIVER_MODESET)) return; @@ -367,6 +368,28 @@ } i915_save_palette(dev, PIPE_B); dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT); + + /* Fences */ + switch (INTEL_INFO(dev)->gen) { + case 6: + for (i = 0; i < 16; i++) + dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); + break; + case 5: + case 4: + for (i = 0; i < 16; i++) + dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8)); + break; + case 3: + if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) + for (i = 0; i < 8; i++) + dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4)); + case 2: + for (i = 0; i < 8; i++) + dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4)); + break; + } + return; } @@ -375,10 +398,33 @@ struct drm_i915_private *dev_priv = dev->dev_private; int dpll_a_reg, fpa0_reg, fpa1_reg; int dpll_b_reg, fpb0_reg, fpb1_reg; + int i; if (drm_core_check_feature(dev, DRIVER_MODESET)) return; + /* Fences */ + switch (INTEL_INFO(dev)->gen) { + case 6: + for (i = 0; i < 16; i++) + I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]); + break; + case 5: + case 4: + for (i = 0; i < 16; i++) + I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]); + break; + case 3: + case 2: + if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) + for (i = 0; i < 8; i++) + I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); + for (i = 0; i < 8; i++) + I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]); + break; + } + + if (HAS_PCH_SPLIT(dev)) { dpll_a_reg = PCH_DPLL_A; dpll_b_reg = PCH_DPLL_B; @@ -771,8 +817,14 @@ dev_priv->saveIMR = I915_READ(IMR); } - if (HAS_PCH_SPLIT(dev)) + if (IS_IRONLAKE_M(dev)) ironlake_disable_drps(dev); + if (IS_GEN6(dev)) + gen6_disable_rps(dev); + + /* XXX disabling the clock gating breaks suspend on gm45 + intel_disable_clock_gating(dev); + */ /* Cache mode state */ dev_priv->saveCACHE_MODE_0 = I915_READ(CACHE_MODE_0); @@ -788,28 +840,6 @@ for (i = 0; i < 3; i++) dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2)); - /* Fences */ - switch (INTEL_INFO(dev)->gen) { - case 6: - for (i = 0; i < 16; i++) - dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8)); - break; - case 5: - case 4: - for (i = 0; i < 16; i++) - dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 + (i * 8)); - break; - case 3: - if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) - for (i = 0; i < 8; i++) - dev_priv->saveFENCE[i+8] = I915_READ(FENCE_REG_945_8 + (i * 4)); - case 2: - for (i = 0; i < 8; i++) - dev_priv->saveFENCE[i] = I915_READ(FENCE_REG_830_0 + (i * 4)); - break; - - } - return 0; } @@ -823,27 +853,6 @@ /* Hardware status page */ I915_WRITE(HWS_PGA, dev_priv->saveHWS); - /* Fences */ - switch (INTEL_INFO(dev)->gen) { - case 6: - for (i = 0; i < 16; i++) - I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]); - break; - case 5: - case 4: - for (i = 0; i < 16; i++) - I915_WRITE64(FENCE_REG_965_0 + (i * 8), dev_priv->saveFENCE[i]); - break; - case 3: - case 2: - if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) - for (i = 0; i < 8; i++) - I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); - for (i = 0; i < 8; i++) - I915_WRITE(FENCE_REG_830_0 + (i * 4), dev_priv->saveFENCE[i]); - break; - } - i915_restore_display(dev); /* Interrupt state */ @@ -860,13 +869,16 @@ } /* Clock gating state */ - intel_init_clock_gating(dev); + intel_enable_clock_gating(dev); - if (HAS_PCH_SPLIT(dev)) { + if (IS_IRONLAKE_M(dev)) { ironlake_enable_drps(dev); intel_init_emon(dev); } + if (IS_GEN6(dev)) + gen6_enable_rps(dev_priv); + /* Cache mode state */ I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); --- linux-2.6.37.orig/drivers/gpu/drm/i915/i915_trace.h +++ linux-2.6.37/drivers/gpu/drm/i915/i915_trace.h @@ -6,6 +6,7 @@ #include #include +#include "i915_drv.h" #undef TRACE_SYSTEM #define TRACE_SYSTEM i915 @@ -16,18 +17,18 @@ TRACE_EVENT(i915_gem_object_create, - TP_PROTO(struct drm_gem_object *obj), + TP_PROTO(struct drm_i915_gem_object *obj), TP_ARGS(obj), TP_STRUCT__entry( - __field(struct drm_gem_object *, obj) + __field(struct drm_i915_gem_object *, obj) __field(u32, size) ), TP_fast_assign( __entry->obj = obj; - __entry->size = obj->size; + __entry->size = obj->base.size; ), TP_printk("obj=%p, size=%u", __entry->obj, __entry->size) @@ -35,40 +36,43 @@ TRACE_EVENT(i915_gem_object_bind, - TP_PROTO(struct drm_gem_object *obj, u32 gtt_offset), + TP_PROTO(struct drm_i915_gem_object *obj, u32 gtt_offset, bool mappable), - TP_ARGS(obj, gtt_offset), + TP_ARGS(obj, gtt_offset, mappable), TP_STRUCT__entry( - __field(struct drm_gem_object *, obj) + __field(struct drm_i915_gem_object *, obj) __field(u32, gtt_offset) + __field(bool, mappable) ), TP_fast_assign( __entry->obj = obj; __entry->gtt_offset = gtt_offset; + __entry->mappable = mappable; ), - TP_printk("obj=%p, gtt_offset=%08x", - __entry->obj, __entry->gtt_offset) + TP_printk("obj=%p, gtt_offset=%08x%s", + __entry->obj, __entry->gtt_offset, + __entry->mappable ? ", mappable" : "") ); TRACE_EVENT(i915_gem_object_change_domain, - TP_PROTO(struct drm_gem_object *obj, uint32_t old_read_domains, uint32_t old_write_domain), + TP_PROTO(struct drm_i915_gem_object *obj, uint32_t old_read_domains, uint32_t old_write_domain), TP_ARGS(obj, old_read_domains, old_write_domain), TP_STRUCT__entry( - __field(struct drm_gem_object *, obj) + __field(struct drm_i915_gem_object *, obj) __field(u32, read_domains) __field(u32, write_domain) ), TP_fast_assign( __entry->obj = obj; - __entry->read_domains = obj->read_domains | (old_read_domains << 16); - __entry->write_domain = obj->write_domain | (old_write_domain << 16); + __entry->read_domains = obj->base.read_domains | (old_read_domains << 16); + __entry->write_domain = obj->base.write_domain | (old_write_domain << 16); ), TP_printk("obj=%p, read=%04x, write=%04x", @@ -76,36 +80,14 @@ __entry->read_domains, __entry->write_domain) ); -TRACE_EVENT(i915_gem_object_get_fence, - - TP_PROTO(struct drm_gem_object *obj, int fence, int tiling_mode), - - TP_ARGS(obj, fence, tiling_mode), - - TP_STRUCT__entry( - __field(struct drm_gem_object *, obj) - __field(int, fence) - __field(int, tiling_mode) - ), - - TP_fast_assign( - __entry->obj = obj; - __entry->fence = fence; - __entry->tiling_mode = tiling_mode; - ), - - TP_printk("obj=%p, fence=%d, tiling=%d", - __entry->obj, __entry->fence, __entry->tiling_mode) -); - DECLARE_EVENT_CLASS(i915_gem_object, - TP_PROTO(struct drm_gem_object *obj), + TP_PROTO(struct drm_i915_gem_object *obj), TP_ARGS(obj), TP_STRUCT__entry( - __field(struct drm_gem_object *, obj) + __field(struct drm_i915_gem_object *, obj) ), TP_fast_assign( @@ -117,21 +99,21 @@ DEFINE_EVENT(i915_gem_object, i915_gem_object_clflush, - TP_PROTO(struct drm_gem_object *obj), + TP_PROTO(struct drm_i915_gem_object *obj), TP_ARGS(obj) ); DEFINE_EVENT(i915_gem_object, i915_gem_object_unbind, - TP_PROTO(struct drm_gem_object *obj), + TP_PROTO(struct drm_i915_gem_object *obj), TP_ARGS(obj) ); DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy, - TP_PROTO(struct drm_gem_object *obj), + TP_PROTO(struct drm_i915_gem_object *obj), TP_ARGS(obj) ); @@ -263,13 +245,13 @@ ); TRACE_EVENT(i915_flip_request, - TP_PROTO(int plane, struct drm_gem_object *obj), + TP_PROTO(int plane, struct drm_i915_gem_object *obj), TP_ARGS(plane, obj), TP_STRUCT__entry( __field(int, plane) - __field(struct drm_gem_object *, obj) + __field(struct drm_i915_gem_object *, obj) ), TP_fast_assign( @@ -281,13 +263,13 @@ ); TRACE_EVENT(i915_flip_complete, - TP_PROTO(int plane, struct drm_gem_object *obj), + TP_PROTO(int plane, struct drm_i915_gem_object *obj), TP_ARGS(plane, obj), TP_STRUCT__entry( __field(int, plane) - __field(struct drm_gem_object *, obj) + __field(struct drm_i915_gem_object *, obj) ), TP_fast_assign( @@ -298,6 +280,29 @@ TP_printk("plane=%d, obj=%p", __entry->plane, __entry->obj) ); +TRACE_EVENT(i915_reg_rw, + TP_PROTO(int cmd, uint32_t reg, uint64_t val, int len), + + TP_ARGS(cmd, reg, val, len), + + TP_STRUCT__entry( + __field(int, cmd) + __field(uint32_t, reg) + __field(uint64_t, val) + __field(int, len) + ), + + TP_fast_assign( + __entry->cmd = cmd; + __entry->reg = reg; + __entry->val = (uint64_t)val; + __entry->len = len; + ), + + TP_printk("cmd=%c, reg=0x%x, val=0x%llx, len=%d", + __entry->cmd, __entry->reg, __entry->val, __entry->len) +); + #endif /* _I915_TRACE_H_ */ /* This part must be outside protection */ --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_display.c +++ linux-2.6.37/drivers/gpu/drm/i915/intel_display.c @@ -642,26 +642,23 @@ .find_pll = intel_find_pll_ironlake_dp, }; -static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc) +static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc, + int refclk) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; const intel_limit_t *limit; - int refclk = 120; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if (dev_priv->lvds_use_ssc && dev_priv->lvds_ssc_freq == 100) - refclk = 100; - if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) { /* LVDS dual channel */ - if (refclk == 100) + if (refclk == 100000) limit = &intel_limits_ironlake_dual_lvds_100m; else limit = &intel_limits_ironlake_dual_lvds; } else { - if (refclk == 100) + if (refclk == 100000) limit = &intel_limits_ironlake_single_lvds_100m; else limit = &intel_limits_ironlake_single_lvds; @@ -702,13 +699,13 @@ return limit; } -static const intel_limit_t *intel_limit(struct drm_crtc *crtc) +static const intel_limit_t *intel_limit(struct drm_crtc *crtc, int refclk) { struct drm_device *dev = crtc->dev; const intel_limit_t *limit; if (HAS_PCH_SPLIT(dev)) - limit = intel_ironlake_limit(crtc); + limit = intel_ironlake_limit(crtc, refclk); else if (IS_G4X(dev)) { limit = intel_g4x_limit(crtc); } else if (IS_PINEVIEW(dev)) { @@ -773,11 +770,10 @@ * the given connectors. */ -static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock) +static bool intel_PLL_is_valid(struct drm_device *dev, + const intel_limit_t *limit, + const intel_clock_t *clock) { - const intel_limit_t *limit = intel_limit (crtc); - struct drm_device *dev = crtc->dev; - if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) INTELPllInvalid ("p1 out of range\n"); if (clock->p < limit->p.min || limit->p.max < clock->p) @@ -849,8 +845,8 @@ int this_err; intel_clock(dev, refclk, &clock); - - if (!intel_PLL_is_valid(crtc, &clock)) + if (!intel_PLL_is_valid(dev, limit, + &clock)) continue; this_err = abs(clock.dot - target); @@ -912,9 +908,11 @@ int this_err; intel_clock(dev, refclk, &clock); - if (!intel_PLL_is_valid(crtc, &clock)) + if (!intel_PLL_is_valid(dev, limit, + &clock)) continue; - this_err = abs(clock.dot - target) ; + + this_err = abs(clock.dot - target); if (this_err < err_most) { *best_clock = clock; err_most = this_err; @@ -1066,13 +1064,13 @@ struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *fb = crtc->fb; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj); + struct drm_i915_gem_object *obj = intel_fb->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int plane, i; u32 fbc_ctl, fbc_ctl2; if (fb->pitch == dev_priv->cfb_pitch && - obj_priv->fence_reg == dev_priv->cfb_fence && + obj->fence_reg == dev_priv->cfb_fence && intel_crtc->plane == dev_priv->cfb_plane && I915_READ(FBC_CONTROL) & FBC_CTL_EN) return; @@ -1086,7 +1084,7 @@ /* FBC_CTL wants 64B units */ dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; - dev_priv->cfb_fence = obj_priv->fence_reg; + dev_priv->cfb_fence = obj->fence_reg; dev_priv->cfb_plane = intel_crtc->plane; plane = dev_priv->cfb_plane == 0 ? FBC_CTL_PLANEA : FBC_CTL_PLANEB; @@ -1096,7 +1094,7 @@ /* Set it up... */ fbc_ctl2 = FBC_CTL_FENCE_DBL | FBC_CTL_IDLE_IMM | plane; - if (obj_priv->tiling_mode != I915_TILING_NONE) + if (obj->tiling_mode != I915_TILING_NONE) fbc_ctl2 |= FBC_CTL_CPU_FENCE; I915_WRITE(FBC_CONTROL2, fbc_ctl2); I915_WRITE(FBC_FENCE_OFF, crtc->y); @@ -1107,7 +1105,7 @@ fbc_ctl |= FBC_CTL_C3_IDLE; /* 945 needs special SR handling */ fbc_ctl |= (dev_priv->cfb_pitch & 0xff) << FBC_CTL_STRIDE_SHIFT; fbc_ctl |= (interval & 0x2fff) << FBC_CTL_INTERVAL_SHIFT; - if (obj_priv->tiling_mode != I915_TILING_NONE) + if (obj->tiling_mode != I915_TILING_NONE) fbc_ctl |= dev_priv->cfb_fence; I915_WRITE(FBC_CONTROL, fbc_ctl); @@ -1150,7 +1148,7 @@ struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *fb = crtc->fb; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj); + struct drm_i915_gem_object *obj = intel_fb->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; unsigned long stall_watermark = 200; @@ -1159,7 +1157,7 @@ dpfc_ctl = I915_READ(DPFC_CONTROL); if (dpfc_ctl & DPFC_CTL_EN) { if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 && - dev_priv->cfb_fence == obj_priv->fence_reg && + dev_priv->cfb_fence == obj->fence_reg && dev_priv->cfb_plane == intel_crtc->plane && dev_priv->cfb_y == crtc->y) return; @@ -1170,12 +1168,12 @@ } dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; - dev_priv->cfb_fence = obj_priv->fence_reg; + dev_priv->cfb_fence = obj->fence_reg; dev_priv->cfb_plane = intel_crtc->plane; dev_priv->cfb_y = crtc->y; dpfc_ctl = plane | DPFC_SR_EN | DPFC_CTL_LIMIT_1X; - if (obj_priv->tiling_mode != I915_TILING_NONE) { + if (obj->tiling_mode != I915_TILING_NONE) { dpfc_ctl |= DPFC_CTL_FENCE_EN | dev_priv->cfb_fence; I915_WRITE(DPFC_CHICKEN, DPFC_HT_MODIFY); } else { @@ -1221,7 +1219,7 @@ struct drm_i915_private *dev_priv = dev->dev_private; struct drm_framebuffer *fb = crtc->fb; struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_i915_gem_object *obj_priv = to_intel_bo(intel_fb->obj); + struct drm_i915_gem_object *obj = intel_fb->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int plane = intel_crtc->plane == 0 ? DPFC_CTL_PLANEA : DPFC_CTL_PLANEB; unsigned long stall_watermark = 200; @@ -1230,9 +1228,9 @@ dpfc_ctl = I915_READ(ILK_DPFC_CONTROL); if (dpfc_ctl & DPFC_CTL_EN) { if (dev_priv->cfb_pitch == dev_priv->cfb_pitch / 64 - 1 && - dev_priv->cfb_fence == obj_priv->fence_reg && + dev_priv->cfb_fence == obj->fence_reg && dev_priv->cfb_plane == intel_crtc->plane && - dev_priv->cfb_offset == obj_priv->gtt_offset && + dev_priv->cfb_offset == obj->gtt_offset && dev_priv->cfb_y == crtc->y) return; @@ -1242,14 +1240,14 @@ } dev_priv->cfb_pitch = (dev_priv->cfb_pitch / 64) - 1; - dev_priv->cfb_fence = obj_priv->fence_reg; + dev_priv->cfb_fence = obj->fence_reg; dev_priv->cfb_plane = intel_crtc->plane; - dev_priv->cfb_offset = obj_priv->gtt_offset; + dev_priv->cfb_offset = obj->gtt_offset; dev_priv->cfb_y = crtc->y; dpfc_ctl &= DPFC_RESERVED; dpfc_ctl |= (plane | DPFC_CTL_LIMIT_1X); - if (obj_priv->tiling_mode != I915_TILING_NONE) { + if (obj->tiling_mode != I915_TILING_NONE) { dpfc_ctl |= (DPFC_CTL_FENCE_EN | dev_priv->cfb_fence); I915_WRITE(ILK_DPFC_CHICKEN, DPFC_HT_MODIFY); } else { @@ -1260,10 +1258,16 @@ (stall_watermark << DPFC_RECOMP_STALL_WM_SHIFT) | (interval << DPFC_RECOMP_TIMER_COUNT_SHIFT)); I915_WRITE(ILK_DPFC_FENCE_YOFF, crtc->y); - I915_WRITE(ILK_FBC_RT_BASE, obj_priv->gtt_offset | ILK_FBC_RT_VALID); + I915_WRITE(ILK_FBC_RT_BASE, obj->gtt_offset | ILK_FBC_RT_VALID); /* enable it... */ I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl | DPFC_CTL_EN); + if (IS_GEN6(dev)) { + I915_WRITE(SNB_DPFC_CTL_SA, + SNB_CPU_FENCE_ENABLE | dev_priv->cfb_fence); + I915_WRITE(DPFC_CPU_FENCE_OFFSET, crtc->y); + } + DRM_DEBUG_KMS("enabled fbc on plane %d\n", intel_crtc->plane); } @@ -1345,7 +1349,7 @@ struct intel_crtc *intel_crtc; struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; DRM_DEBUG_KMS("\n"); @@ -1384,9 +1388,9 @@ intel_crtc = to_intel_crtc(crtc); fb = crtc->fb; intel_fb = to_intel_framebuffer(fb); - obj_priv = to_intel_bo(intel_fb->obj); + obj = intel_fb->obj; - if (intel_fb->obj->size > dev_priv->cfb_size) { + if (intel_fb->obj->base.size > dev_priv->cfb_size) { DRM_DEBUG_KMS("framebuffer too large, disabling " "compression\n"); dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; @@ -1410,7 +1414,7 @@ dev_priv->no_fbc_reason = FBC_BAD_PLANE; goto out_disable; } - if (obj_priv->tiling_mode != I915_TILING_X) { + if (obj->tiling_mode != I915_TILING_X) { DRM_DEBUG_KMS("framebuffer not tiled, disabling compression\n"); dev_priv->no_fbc_reason = FBC_NOT_TILED; goto out_disable; @@ -1433,14 +1437,13 @@ int intel_pin_and_fence_fb_obj(struct drm_device *dev, - struct drm_gem_object *obj, - bool pipelined) + struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); u32 alignment; int ret; - switch (obj_priv->tiling_mode) { + switch (obj->tiling_mode) { case I915_TILING_NONE: if (IS_BROADWATER(dev) || IS_CRESTLINE(dev)) alignment = 128 * 1024; @@ -1461,7 +1464,7 @@ BUG(); } - ret = i915_gem_object_pin(obj, alignment); + ret = i915_gem_object_pin(obj, alignment, true); if (ret) return ret; @@ -1474,9 +1477,8 @@ * framebuffer compression. For simplicity, we always install * a fence as the cost is not that onerous. */ - if (obj_priv->fence_reg == I915_FENCE_REG_NONE && - obj_priv->tiling_mode != I915_TILING_NONE) { - ret = i915_gem_object_get_fence_reg(obj, false); + if (obj->tiling_mode != I915_TILING_NONE) { + ret = i915_gem_object_get_fence(obj, pipelined, false); if (ret) goto err_unpin; } @@ -1497,8 +1499,7 @@ struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_framebuffer *intel_fb; - struct drm_i915_gem_object *obj_priv; - struct drm_gem_object *obj; + struct drm_i915_gem_object *obj; int plane = intel_crtc->plane; unsigned long Start, Offset; u32 dspcntr; @@ -1515,7 +1516,6 @@ intel_fb = to_intel_framebuffer(fb); obj = intel_fb->obj; - obj_priv = to_intel_bo(obj); reg = DSPCNTR(plane); dspcntr = I915_READ(reg); @@ -1540,7 +1540,7 @@ return -EINVAL; } if (INTEL_INFO(dev)->gen >= 4) { - if (obj_priv->tiling_mode != I915_TILING_NONE) + if (obj->tiling_mode != I915_TILING_NONE) dspcntr |= DISPPLANE_TILED; else dspcntr &= ~DISPPLANE_TILED; @@ -1552,7 +1552,7 @@ I915_WRITE(reg, dspcntr); - Start = obj_priv->gtt_offset; + Start = obj->gtt_offset; Offset = y * fb->pitch + x * (fb->bits_per_pixel / 8); DRM_DEBUG_KMS("Writing base %08lX %08lX %d %d %d\n", @@ -1598,7 +1598,7 @@ mutex_lock(&dev->struct_mutex); ret = intel_pin_and_fence_fb_obj(dev, to_intel_framebuffer(crtc->fb)->obj, - false); + NULL); if (ret != 0) { mutex_unlock(&dev->struct_mutex); return ret; @@ -1606,18 +1606,17 @@ if (old_fb) { struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_gem_object *obj = to_intel_framebuffer(old_fb)->obj; - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); + struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj; wait_event(dev_priv->pending_flip_queue, - atomic_read(&obj_priv->pending_flip) == 0); + atomic_read(&obj->pending_flip) == 0); /* Big Hammer, we also need to ensure that any pending * MI_WAIT_FOR_EVENT inside a user batch buffer on the * current scanout is retired before unpinning the old * framebuffer. */ - ret = i915_gem_object_flush_gpu(obj_priv, false); + ret = i915_gem_object_flush_gpu(obj, false); if (ret) { i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); mutex_unlock(&dev->struct_mutex); @@ -1633,8 +1632,10 @@ return ret; } - if (old_fb) + if (old_fb) { + intel_wait_for_vblank(dev, intel_crtc->pipe); i915_gem_object_unpin(to_intel_framebuffer(old_fb)->obj); + } mutex_unlock(&dev->struct_mutex); @@ -1996,31 +1997,31 @@ static void intel_clear_scanline_wait(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring; u32 tmp; if (IS_GEN2(dev)) /* Can't break the hang on i8xx */ return; - tmp = I915_READ(PRB0_CTL); - if (tmp & RING_WAIT) { - I915_WRITE(PRB0_CTL, tmp); - POSTING_READ(PRB0_CTL); - } + ring = LP_RING(dev_priv); + tmp = I915_READ_CTL(ring); + if (tmp & RING_WAIT) + I915_WRITE_CTL(ring, tmp); } static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) { - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; struct drm_i915_private *dev_priv; if (crtc->fb == NULL) return; - obj_priv = to_intel_bo(to_intel_framebuffer(crtc->fb)->obj); + obj = to_intel_framebuffer(crtc->fb)->obj; dev_priv = crtc->dev->dev_private; wait_event(dev_priv->pending_flip_queue, - atomic_read(&obj_priv->pending_flip) == 0); + atomic_read(&obj->pending_flip) == 0); } static void ironlake_crtc_enable(struct drm_crtc *crtc) @@ -2850,6 +2851,39 @@ ILK_FIFO_LINE_SIZE }; +static struct intel_watermark_params sandybridge_display_wm_info = { + SNB_DISPLAY_FIFO, + SNB_DISPLAY_MAXWM, + SNB_DISPLAY_DFTWM, + 2, + SNB_FIFO_LINE_SIZE +}; + +static struct intel_watermark_params sandybridge_cursor_wm_info = { + SNB_CURSOR_FIFO, + SNB_CURSOR_MAXWM, + SNB_CURSOR_DFTWM, + 2, + SNB_FIFO_LINE_SIZE +}; + +static struct intel_watermark_params sandybridge_display_srwm_info = { + SNB_DISPLAY_SR_FIFO, + SNB_DISPLAY_MAX_SRWM, + SNB_DISPLAY_DFT_SRWM, + 2, + SNB_FIFO_LINE_SIZE +}; + +static struct intel_watermark_params sandybridge_cursor_srwm_info = { + SNB_CURSOR_SR_FIFO, + SNB_CURSOR_MAX_SRWM, + SNB_CURSOR_DFT_SRWM, + 2, + SNB_FIFO_LINE_SIZE +}; + + /** * intel_calculate_wm - calculate watermark level * @clock_in_khz: pixel clock @@ -3383,6 +3417,10 @@ static bool ironlake_compute_wm0(struct drm_device *dev, int pipe, + const struct intel_watermark_params *display, + int display_latency_ns, + const struct intel_watermark_params *cursor, + int cursor_latency_ns, int *plane_wm, int *cursor_wm) { @@ -3400,37 +3438,135 @@ pixel_size = crtc->fb->bits_per_pixel / 8; /* Use the small buffer method to calculate plane watermark */ - entries = ((clock * pixel_size / 1000) * ILK_LP0_PLANE_LATENCY) / 1000; - entries = DIV_ROUND_UP(entries, - ironlake_display_wm_info.cacheline_size); - *plane_wm = entries + ironlake_display_wm_info.guard_size; - if (*plane_wm > (int)ironlake_display_wm_info.max_wm) - *plane_wm = ironlake_display_wm_info.max_wm; + entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000; + entries = DIV_ROUND_UP(entries, display->cacheline_size); + *plane_wm = entries + display->guard_size; + if (*plane_wm > (int)display->max_wm) + *plane_wm = display->max_wm; /* Use the large buffer method to calculate cursor watermark */ line_time_us = ((htotal * 1000) / clock); - line_count = (ILK_LP0_CURSOR_LATENCY / line_time_us + 1000) / 1000; + line_count = (cursor_latency_ns / line_time_us + 1000) / 1000; entries = line_count * 64 * pixel_size; - entries = DIV_ROUND_UP(entries, - ironlake_cursor_wm_info.cacheline_size); - *cursor_wm = entries + ironlake_cursor_wm_info.guard_size; - if (*cursor_wm > ironlake_cursor_wm_info.max_wm) - *cursor_wm = ironlake_cursor_wm_info.max_wm; + entries = DIV_ROUND_UP(entries, cursor->cacheline_size); + *cursor_wm = entries + cursor->guard_size; + if (*cursor_wm > (int)cursor->max_wm) + *cursor_wm = (int)cursor->max_wm; return true; } +/* + * Check the wm result. + * + * If any calculated watermark values is larger than the maximum value that + * can be programmed into the associated watermark register, that watermark + * must be disabled. + */ +static bool ironlake_check_srwm(struct drm_device *dev, int level, + int fbc_wm, int display_wm, int cursor_wm, + const struct intel_watermark_params *display, + const struct intel_watermark_params *cursor) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + DRM_DEBUG_KMS("watermark %d: display plane %d, fbc lines %d," + " cursor %d\n", level, display_wm, fbc_wm, cursor_wm); + + if (fbc_wm > SNB_FBC_MAX_SRWM) { + DRM_DEBUG_KMS("fbc watermark(%d) is too large(%d), disabling wm%d+\n", + fbc_wm, SNB_FBC_MAX_SRWM, level); + + /* fbc has it's own way to disable FBC WM */ + I915_WRITE(DISP_ARB_CTL, + I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS); + return false; + } + + if (display_wm > display->max_wm) { + DRM_DEBUG_KMS("display watermark(%d) is too large(%d), disabling wm%d+\n", + display_wm, SNB_DISPLAY_MAX_SRWM, level); + return false; + } + + if (cursor_wm > cursor->max_wm) { + DRM_DEBUG_KMS("cursor watermark(%d) is too large(%d), disabling wm%d+\n", + cursor_wm, SNB_CURSOR_MAX_SRWM, level); + return false; + } + + if (!(fbc_wm || display_wm || cursor_wm)) { + DRM_DEBUG_KMS("latency %d is 0, disabling wm%d+\n", level, level); + return false; + } + + return true; +} + +/* + * Compute watermark values of WM[1-3], + */ +static bool ironlake_compute_srwm(struct drm_device *dev, int level, + int hdisplay, int htotal, + int pixel_size, int clock, int latency_ns, + const struct intel_watermark_params *display, + const struct intel_watermark_params *cursor, + int *fbc_wm, int *display_wm, int *cursor_wm) +{ + + unsigned long line_time_us; + int line_count, line_size; + int small, large; + int entries; + + if (!latency_ns) { + *fbc_wm = *display_wm = *cursor_wm = 0; + return false; + } + + line_time_us = (htotal * 1000) / clock; + line_count = (latency_ns / line_time_us + 1000) / 1000; + line_size = hdisplay * pixel_size; + + /* Use the minimum of the small and large buffer method for primary */ + small = ((clock * pixel_size / 1000) * latency_ns) / 1000; + large = line_count * line_size; + + entries = DIV_ROUND_UP(min(small, large), display->cacheline_size); + *display_wm = entries + display->guard_size; + + /* + * Spec says: + * FBC WM = ((Final Primary WM * 64) / number of bytes per line) + 2 + */ + *fbc_wm = DIV_ROUND_UP(*display_wm * 64, line_size) + 2; + + /* calculate the self-refresh watermark for display cursor */ + entries = line_count * pixel_size * 64; + entries = DIV_ROUND_UP(entries, cursor->cacheline_size); + *cursor_wm = entries + cursor->guard_size; + + return ironlake_check_srwm(dev, level, + *fbc_wm, *display_wm, *cursor_wm, + display, cursor); +} + static void ironlake_update_wm(struct drm_device *dev, int planea_clock, int planeb_clock, - int sr_hdisplay, int sr_htotal, + int hdisplay, int htotal, int pixel_size) { struct drm_i915_private *dev_priv = dev->dev_private; - int plane_wm, cursor_wm, enabled; - int tmp; + int fbc_wm, plane_wm, cursor_wm, enabled; + int clock; enabled = 0; - if (ironlake_compute_wm0(dev, 0, &plane_wm, &cursor_wm)) { + if (ironlake_compute_wm0(dev, 0, + &ironlake_display_wm_info, + ILK_LP0_PLANE_LATENCY, + &ironlake_cursor_wm_info, + ILK_LP0_CURSOR_LATENCY, + &plane_wm, &cursor_wm)) { I915_WRITE(WM0_PIPEA_ILK, (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); DRM_DEBUG_KMS("FIFO watermarks For pipe A -" @@ -3439,7 +3575,12 @@ enabled++; } - if (ironlake_compute_wm0(dev, 1, &plane_wm, &cursor_wm)) { + if (ironlake_compute_wm0(dev, 1, + &ironlake_display_wm_info, + ILK_LP0_PLANE_LATENCY, + &ironlake_cursor_wm_info, + ILK_LP0_CURSOR_LATENCY, + &plane_wm, &cursor_wm)) { I915_WRITE(WM0_PIPEB_ILK, (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); DRM_DEBUG_KMS("FIFO watermarks For pipe B -" @@ -3452,57 +3593,151 @@ * Calculate and update the self-refresh watermark only when one * display plane is used. */ - tmp = 0; - if (enabled == 1 && /* XXX disabled due to buggy implmentation? */ 0) { - unsigned long line_time_us; - int small, large, plane_fbc; - int sr_clock, entries; - int line_count, line_size; - /* Read the self-refresh latency. The unit is 0.5us */ - int ilk_sr_latency = I915_READ(MLTR_ILK) & ILK_SRLT_MASK; + I915_WRITE(WM3_LP_ILK, 0); + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); - sr_clock = planea_clock ? planea_clock : planeb_clock; - line_time_us = (sr_htotal * 1000) / sr_clock; + if (enabled != 1) + return; - /* Use ns/us then divide to preserve precision */ - line_count = ((ilk_sr_latency * 500) / line_time_us + 1000) - / 1000; - line_size = sr_hdisplay * pixel_size; - - /* Use the minimum of the small and large buffer method for primary */ - small = ((sr_clock * pixel_size / 1000) * (ilk_sr_latency * 500)) / 1000; - large = line_count * line_size; - - entries = DIV_ROUND_UP(min(small, large), - ironlake_display_srwm_info.cacheline_size); - - plane_fbc = entries * 64; - plane_fbc = DIV_ROUND_UP(plane_fbc, line_size); - - plane_wm = entries + ironlake_display_srwm_info.guard_size; - if (plane_wm > (int)ironlake_display_srwm_info.max_wm) - plane_wm = ironlake_display_srwm_info.max_wm; - - /* calculate the self-refresh watermark for display cursor */ - entries = line_count * pixel_size * 64; - entries = DIV_ROUND_UP(entries, - ironlake_cursor_srwm_info.cacheline_size); - - cursor_wm = entries + ironlake_cursor_srwm_info.guard_size; - if (cursor_wm > (int)ironlake_cursor_srwm_info.max_wm) - cursor_wm = ironlake_cursor_srwm_info.max_wm; - - /* configure watermark and enable self-refresh */ - tmp = (WM1_LP_SR_EN | - (ilk_sr_latency << WM1_LP_LATENCY_SHIFT) | - (plane_fbc << WM1_LP_FBC_SHIFT) | - (plane_wm << WM1_LP_SR_SHIFT) | - cursor_wm); - DRM_DEBUG_KMS("self-refresh watermark: display plane %d, fbc lines %d," - " cursor %d\n", plane_wm, plane_fbc, cursor_wm); + clock = planea_clock ? planea_clock : planeb_clock; + + /* WM1 */ + if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size, + clock, ILK_READ_WM1_LATENCY() * 500, + &ironlake_display_srwm_info, + &ironlake_cursor_srwm_info, + &fbc_wm, &plane_wm, &cursor_wm)) + return; + + I915_WRITE(WM1_LP_ILK, + WM1_LP_SR_EN | + (ILK_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) | + (fbc_wm << WM1_LP_FBC_SHIFT) | + (plane_wm << WM1_LP_SR_SHIFT) | + cursor_wm); + + /* WM2 */ + if (!ironlake_compute_srwm(dev, 2, hdisplay, htotal, pixel_size, + clock, ILK_READ_WM2_LATENCY() * 500, + &ironlake_display_srwm_info, + &ironlake_cursor_srwm_info, + &fbc_wm, &plane_wm, &cursor_wm)) + return; + + I915_WRITE(WM2_LP_ILK, + WM2_LP_EN | + (ILK_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) | + (fbc_wm << WM1_LP_FBC_SHIFT) | + (plane_wm << WM1_LP_SR_SHIFT) | + cursor_wm); + + /* + * WM3 is unsupported on ILK, probably because we don't have latency + * data for that power state + */ +} + +static void sandybridge_update_wm(struct drm_device *dev, + int planea_clock, int planeb_clock, + int hdisplay, int htotal, + int pixel_size) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int latency = SNB_READ_WM0_LATENCY() * 100; /* In unit 0.1us */ + int fbc_wm, plane_wm, cursor_wm, enabled; + int clock; + + enabled = 0; + if (ironlake_compute_wm0(dev, 0, + &sandybridge_display_wm_info, latency, + &sandybridge_cursor_wm_info, latency, + &plane_wm, &cursor_wm)) { + I915_WRITE(WM0_PIPEA_ILK, + (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); + DRM_DEBUG_KMS("FIFO watermarks For pipe A -" + " plane %d, " "cursor: %d\n", + plane_wm, cursor_wm); + enabled++; } - I915_WRITE(WM1_LP_ILK, tmp); - /* XXX setup WM2 and WM3 */ + + if (ironlake_compute_wm0(dev, 1, + &sandybridge_display_wm_info, latency, + &sandybridge_cursor_wm_info, latency, + &plane_wm, &cursor_wm)) { + I915_WRITE(WM0_PIPEB_ILK, + (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); + DRM_DEBUG_KMS("FIFO watermarks For pipe B -" + " plane %d, cursor: %d\n", + plane_wm, cursor_wm); + enabled++; + } + + /* + * Calculate and update the self-refresh watermark only when one + * display plane is used. + * + * SNB support 3 levels of watermark. + * + * WM1/WM2/WM2 watermarks have to be enabled in the ascending order, + * and disabled in the descending order + * + */ + I915_WRITE(WM3_LP_ILK, 0); + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); + + if (enabled != 1) + return; + + clock = planea_clock ? planea_clock : planeb_clock; + + /* WM1 */ + if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size, + clock, SNB_READ_WM1_LATENCY() * 500, + &sandybridge_display_srwm_info, + &sandybridge_cursor_srwm_info, + &fbc_wm, &plane_wm, &cursor_wm)) + return; + + I915_WRITE(WM1_LP_ILK, + WM1_LP_SR_EN | + (SNB_READ_WM1_LATENCY() << WM1_LP_LATENCY_SHIFT) | + (fbc_wm << WM1_LP_FBC_SHIFT) | + (plane_wm << WM1_LP_SR_SHIFT) | + cursor_wm); + + /* WM2 */ + if (!ironlake_compute_srwm(dev, 2, + hdisplay, htotal, pixel_size, + clock, SNB_READ_WM2_LATENCY() * 500, + &sandybridge_display_srwm_info, + &sandybridge_cursor_srwm_info, + &fbc_wm, &plane_wm, &cursor_wm)) + return; + + I915_WRITE(WM2_LP_ILK, + WM2_LP_EN | + (SNB_READ_WM2_LATENCY() << WM1_LP_LATENCY_SHIFT) | + (fbc_wm << WM1_LP_FBC_SHIFT) | + (plane_wm << WM1_LP_SR_SHIFT) | + cursor_wm); + + /* WM3 */ + if (!ironlake_compute_srwm(dev, 3, + hdisplay, htotal, pixel_size, + clock, SNB_READ_WM3_LATENCY() * 500, + &sandybridge_display_srwm_info, + &sandybridge_cursor_srwm_info, + &fbc_wm, &plane_wm, &cursor_wm)) + return; + + I915_WRITE(WM3_LP_ILK, + WM3_LP_EN | + (SNB_READ_WM3_LATENCY() << WM1_LP_LATENCY_SHIFT) | + (fbc_wm << WM1_LP_FBC_SHIFT) | + (plane_wm << WM1_LP_SR_SHIFT) | + cursor_wm); } /** @@ -3660,7 +3895,7 @@ * refclk, or FALSE. The returned values represent the clock equation: * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. */ - limit = intel_limit(crtc); + limit = intel_limit(crtc, refclk); ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); if (!ok) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); @@ -3857,6 +4092,22 @@ reduced_clock.m2; } + /* Enable autotuning of the PLL clock (if permissible) */ + if (HAS_PCH_SPLIT(dev)) { + int factor = 21; + + if (is_lvds) { + if ((dev_priv->lvds_use_ssc && + dev_priv->lvds_ssc_freq == 100) || + (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) + factor = 25; + } else if (is_sdvo && is_tv) + factor = 20; + + if (clock.m1 < factor * clock.n) + fp |= FP_CB_TUNE; + } + dpll = 0; if (!HAS_PCH_SPLIT(dev)) dpll = DPLL_VGA_MODE_DIS; @@ -4071,7 +4322,6 @@ } if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) { - I915_WRITE(fp_reg, fp); I915_WRITE(dpll_reg, dpll); /* Wait for the clocks to stabilize. */ @@ -4089,13 +4339,13 @@ } I915_WRITE(DPLL_MD(pipe), temp); } else { - /* write it again -- the BIOS does, after all */ + /* The pixel multiplier can only be updated once the + * DPLL is enabled and the clocks are stable. + * + * So write it again. + */ I915_WRITE(dpll_reg, dpll); } - - /* Wait for the clocks to stabilize. */ - POSTING_READ(dpll_reg); - udelay(150); } intel_crtc->lowfreq_avail = false; @@ -4331,15 +4581,14 @@ } static int intel_crtc_cursor_set(struct drm_crtc *crtc, - struct drm_file *file_priv, + struct drm_file *file, uint32_t handle, uint32_t width, uint32_t height) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct drm_gem_object *bo; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; uint32_t addr; int ret; @@ -4349,7 +4598,7 @@ if (!handle) { DRM_DEBUG_KMS("cursor off\n"); addr = 0; - bo = NULL; + obj = NULL; mutex_lock(&dev->struct_mutex); goto finish; } @@ -4360,13 +4609,11 @@ return -EINVAL; } - bo = drm_gem_object_lookup(dev, file_priv, handle); - if (!bo) + obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle)); + if (!obj) return -ENOENT; - obj_priv = to_intel_bo(bo); - - if (bo->size < width * height * 4) { + if (obj->base.size < width * height * 4) { DRM_ERROR("buffer is to small\n"); ret = -ENOMEM; goto fail; @@ -4375,29 +4622,41 @@ /* we only need to pin inside GTT if cursor is non-phy */ mutex_lock(&dev->struct_mutex); if (!dev_priv->info->cursor_needs_physical) { - ret = i915_gem_object_pin(bo, PAGE_SIZE); + if (obj->tiling_mode) { + DRM_ERROR("cursor cannot be tiled\n"); + ret = -EINVAL; + goto fail_locked; + } + + ret = i915_gem_object_pin(obj, PAGE_SIZE, true); if (ret) { DRM_ERROR("failed to pin cursor bo\n"); goto fail_locked; } - ret = i915_gem_object_set_to_gtt_domain(bo, 0); + ret = i915_gem_object_set_to_gtt_domain(obj, 0); + if (ret) { + DRM_ERROR("failed to move cursor bo into the GTT\n"); + goto fail_unpin; + } + + ret = i915_gem_object_put_fence(obj); if (ret) { DRM_ERROR("failed to move cursor bo into the GTT\n"); goto fail_unpin; } - addr = obj_priv->gtt_offset; + addr = obj->gtt_offset; } else { int align = IS_I830(dev) ? 16 * 1024 : 256; - ret = i915_gem_attach_phys_object(dev, bo, + ret = i915_gem_attach_phys_object(dev, obj, (intel_crtc->pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1, align); if (ret) { DRM_ERROR("failed to attach phys object\n"); goto fail_locked; } - addr = obj_priv->phys_obj->handle->busaddr; + addr = obj->phys_obj->handle->busaddr; } if (IS_GEN2(dev)) @@ -4406,17 +4665,17 @@ finish: if (intel_crtc->cursor_bo) { if (dev_priv->info->cursor_needs_physical) { - if (intel_crtc->cursor_bo != bo) + if (intel_crtc->cursor_bo != obj) i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo); } else i915_gem_object_unpin(intel_crtc->cursor_bo); - drm_gem_object_unreference(intel_crtc->cursor_bo); + drm_gem_object_unreference(&intel_crtc->cursor_bo->base); } mutex_unlock(&dev->struct_mutex); intel_crtc->cursor_addr = addr; - intel_crtc->cursor_bo = bo; + intel_crtc->cursor_bo = obj; intel_crtc->cursor_width = width; intel_crtc->cursor_height = height; @@ -4424,11 +4683,11 @@ return 0; fail_unpin: - i915_gem_object_unpin(bo); + i915_gem_object_unpin(obj); fail_locked: mutex_unlock(&dev->struct_mutex); fail: - drm_gem_object_unreference_unlocked(bo); + drm_gem_object_unreference_unlocked(&obj->base); return ret; } @@ -4739,8 +4998,14 @@ struct drm_device *dev = (struct drm_device *)arg; drm_i915_private_t *dev_priv = dev->dev_private; - dev_priv->busy = false; + if (!list_empty(&dev_priv->mm.active_list)) { + /* Still processing requests, so just re-arm the timer. */ + mod_timer(&dev_priv->idle_timer, jiffies + + msecs_to_jiffies(GPU_IDLE_TIMEOUT)); + return; + } + dev_priv->busy = false; queue_work(dev_priv->wq, &dev_priv->idle_work); } @@ -4751,9 +5016,17 @@ struct intel_crtc *intel_crtc = (struct intel_crtc *)arg; struct drm_crtc *crtc = &intel_crtc->base; drm_i915_private_t *dev_priv = crtc->dev->dev_private; + struct intel_framebuffer *intel_fb; - intel_crtc->busy = false; + intel_fb = to_intel_framebuffer(crtc->fb); + if (intel_fb && intel_fb->obj->active) { + /* The framebuffer is still being accessed by the GPU. */ + mod_timer(&intel_crtc->idle_timer, jiffies + + msecs_to_jiffies(CRTC_IDLE_TIMEOUT)); + return; + } + intel_crtc->busy = false; queue_work(dev_priv->wq, &dev_priv->idle_work); } @@ -4763,8 +5036,8 @@ drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; - int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; - int dpll = I915_READ(dpll_reg); + int dpll_reg = DPLL(pipe); + int dpll; if (HAS_PCH_SPLIT(dev)) return; @@ -4772,17 +5045,19 @@ if (!dev_priv->lvds_downclock_avail) return; + dpll = I915_READ(dpll_reg); if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) { DRM_DEBUG_DRIVER("upclocking LVDS\n"); /* Unlock panel regs */ - I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | - PANEL_UNLOCK_REGS); + I915_WRITE(PP_CONTROL, + I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); dpll &= ~DISPLAY_RATE_SELECT_FPA1; I915_WRITE(dpll_reg, dpll); - dpll = I915_READ(dpll_reg); + POSTING_READ(dpll_reg); intel_wait_for_vblank(dev, pipe); + dpll = I915_READ(dpll_reg); if (dpll & DISPLAY_RATE_SELECT_FPA1) DRM_DEBUG_DRIVER("failed to upclock LVDS!\n"); @@ -4888,7 +5163,7 @@ * buffer), we'll also mark the display as busy, so we know to increase its * clock frequency. */ -void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj) +void intel_mark_busy(struct drm_device *dev, struct drm_i915_gem_object *obj) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_crtc *crtc = NULL; @@ -4969,8 +5244,9 @@ mutex_lock(&work->dev->struct_mutex); i915_gem_object_unpin(work->old_fb_obj); - drm_gem_object_unreference(work->pending_flip_obj); - drm_gem_object_unreference(work->old_fb_obj); + drm_gem_object_unreference(&work->pending_flip_obj->base); + drm_gem_object_unreference(&work->old_fb_obj->base); + mutex_unlock(&work->dev->struct_mutex); kfree(work); } @@ -4981,15 +5257,17 @@ drm_i915_private_t *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; struct drm_pending_vblank_event *e; - struct timeval now; + struct timeval tnow, tvbl; unsigned long flags; /* Ignore early vblank irqs */ if (intel_crtc == NULL) return; + do_gettimeofday(&tnow); + spin_lock_irqsave(&dev->event_lock, flags); work = intel_crtc->unpin_work; if (work == NULL || !work->pending) { @@ -4998,26 +5276,49 @@ } intel_crtc->unpin_work = NULL; - drm_vblank_put(dev, intel_crtc->pipe); if (work->event) { e = work->event; - do_gettimeofday(&now); - e->event.sequence = drm_vblank_count(dev, intel_crtc->pipe); - e->event.tv_sec = now.tv_sec; - e->event.tv_usec = now.tv_usec; + e->event.sequence = drm_vblank_count_and_time(dev, intel_crtc->pipe, &tvbl); + + /* Called before vblank count and timestamps have + * been updated for the vblank interval of flip + * completion? Need to increment vblank count and + * add one videorefresh duration to returned timestamp + * to account for this. We assume this happened if we + * get called over 0.9 frame durations after the last + * timestamped vblank. + * + * This calculation can not be used with vrefresh rates + * below 5Hz (10Hz to be on the safe side) without + * promoting to 64 integers. + */ + if (10 * (timeval_to_ns(&tnow) - timeval_to_ns(&tvbl)) > + 9 * crtc->framedur_ns) { + e->event.sequence++; + tvbl = ns_to_timeval(timeval_to_ns(&tvbl) + + crtc->framedur_ns); + } + + e->event.tv_sec = tvbl.tv_sec; + e->event.tv_usec = tvbl.tv_usec; + list_add_tail(&e->base.link, &e->base.file_priv->event_list); wake_up_interruptible(&e->base.file_priv->event_wait); } + drm_vblank_put(dev, intel_crtc->pipe); + spin_unlock_irqrestore(&dev->event_lock, flags); - obj_priv = to_intel_bo(work->old_fb_obj); + obj = work->old_fb_obj; + atomic_clear_mask(1 << intel_crtc->plane, - &obj_priv->pending_flip.counter); - if (atomic_read(&obj_priv->pending_flip) == 0) + &obj->pending_flip.counter); + if (atomic_read(&obj->pending_flip) == 0) wake_up(&dev_priv->pending_flip_queue); + schedule_work(&work->work); trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); @@ -5063,8 +5364,7 @@ struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct intel_framebuffer *intel_fb; - struct drm_i915_gem_object *obj_priv; - struct drm_gem_object *obj; + struct drm_i915_gem_object *obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; unsigned long flags, offset; @@ -5098,13 +5398,13 @@ obj = intel_fb->obj; mutex_lock(&dev->struct_mutex); - ret = intel_pin_and_fence_fb_obj(dev, obj, true); + ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); if (ret) goto cleanup_work; /* Reference the objects for the scheduled work. */ - drm_gem_object_reference(work->old_fb_obj); - drm_gem_object_reference(obj); + drm_gem_object_reference(&work->old_fb_obj->base); + drm_gem_object_reference(&obj->base); crtc->fb = fb; @@ -5112,22 +5412,16 @@ if (ret) goto cleanup_objs; - /* Block clients from rendering to the new back buffer until - * the flip occurs and the object is no longer visible. - */ - atomic_add(1 << intel_crtc->plane, - &to_intel_bo(work->old_fb_obj)->pending_flip); - - work->pending_flip_obj = obj; - obj_priv = to_intel_bo(obj); - if (IS_GEN3(dev) || IS_GEN2(dev)) { u32 flip_mask; /* Can't queue multiple flips, so wait for the previous * one to finish before executing the next. */ - BEGIN_LP_RING(2); + ret = BEGIN_LP_RING(2); + if (ret) + goto cleanup_objs; + if (intel_crtc->plane) flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; else @@ -5137,18 +5431,28 @@ ADVANCE_LP_RING(); } + work->pending_flip_obj = obj; + work->enable_stall_check = true; /* Offset into the new buffer for cases of shared fbs between CRTCs */ offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; - BEGIN_LP_RING(4); - switch(INTEL_INFO(dev)->gen) { + ret = BEGIN_LP_RING(4); + if (ret) + goto cleanup_objs; + + /* Block clients from rendering to the new back buffer until + * the flip occurs and the object is no longer visible. + */ + atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); + + switch (INTEL_INFO(dev)->gen) { case 2: OUT_RING(MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); OUT_RING(fb->pitch); - OUT_RING(obj_priv->gtt_offset + offset); + OUT_RING(obj->gtt_offset + offset); OUT_RING(MI_NOOP); break; @@ -5156,7 +5460,7 @@ OUT_RING(MI_DISPLAY_FLIP_I915 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); OUT_RING(fb->pitch); - OUT_RING(obj_priv->gtt_offset + offset); + OUT_RING(obj->gtt_offset + offset); OUT_RING(MI_NOOP); break; @@ -5169,7 +5473,7 @@ OUT_RING(MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); OUT_RING(fb->pitch); - OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); + OUT_RING(obj->gtt_offset | obj->tiling_mode); /* XXX Enabling the panel-fitter across page-flip is so far * untested on non-native modes, so ignore it for now. @@ -5183,8 +5487,8 @@ case 6: OUT_RING(MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); - OUT_RING(fb->pitch | obj_priv->tiling_mode); - OUT_RING(obj_priv->gtt_offset); + OUT_RING(fb->pitch | obj->tiling_mode); + OUT_RING(obj->gtt_offset); pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff; @@ -5200,8 +5504,8 @@ return 0; cleanup_objs: - drm_gem_object_unreference(work->old_fb_obj); - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&work->old_fb_obj->base); + drm_gem_object_unreference(&obj->base); cleanup_work: mutex_unlock(&dev->struct_mutex); @@ -5338,7 +5642,7 @@ } int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, - struct drm_file *file_priv) + struct drm_file *file) { drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_get_pipe_from_crtc_id *pipe_from_crtc_id = data; @@ -5505,19 +5809,19 @@ struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); drm_framebuffer_cleanup(fb); - drm_gem_object_unreference_unlocked(intel_fb->obj); + drm_gem_object_unreference_unlocked(&intel_fb->obj->base); kfree(intel_fb); } static int intel_user_framebuffer_create_handle(struct drm_framebuffer *fb, - struct drm_file *file_priv, + struct drm_file *file, unsigned int *handle) { struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); - struct drm_gem_object *object = intel_fb->obj; + struct drm_i915_gem_object *obj = intel_fb->obj; - return drm_gem_handle_create(file_priv, object, handle); + return drm_gem_handle_create(file, &obj->base, handle); } static const struct drm_framebuffer_funcs intel_fb_funcs = { @@ -5528,12 +5832,11 @@ int intel_framebuffer_init(struct drm_device *dev, struct intel_framebuffer *intel_fb, struct drm_mode_fb_cmd *mode_cmd, - struct drm_gem_object *obj) + struct drm_i915_gem_object *obj) { - struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); int ret; - if (obj_priv->tiling_mode == I915_TILING_Y) + if (obj->tiling_mode == I915_TILING_Y) return -EINVAL; if (mode_cmd->pitch & 63) @@ -5565,11 +5868,11 @@ struct drm_file *filp, struct drm_mode_fb_cmd *mode_cmd) { - struct drm_gem_object *obj; + struct drm_i915_gem_object *obj; struct intel_framebuffer *intel_fb; int ret; - obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle); + obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle)); if (!obj) return ERR_PTR(-ENOENT); @@ -5577,10 +5880,9 @@ if (!intel_fb) return ERR_PTR(-ENOMEM); - ret = intel_framebuffer_init(dev, intel_fb, - mode_cmd, obj); + ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj); if (ret) { - drm_gem_object_unreference_unlocked(obj); + drm_gem_object_unreference_unlocked(&obj->base); kfree(intel_fb); return ERR_PTR(ret); } @@ -5593,10 +5895,10 @@ .output_poll_changed = intel_fb_output_poll_changed, }; -static struct drm_gem_object * +static struct drm_i915_gem_object * intel_alloc_context_page(struct drm_device *dev) { - struct drm_gem_object *ctx; + struct drm_i915_gem_object *ctx; int ret; ctx = i915_gem_alloc_object(dev, 4096); @@ -5606,7 +5908,7 @@ } mutex_lock(&dev->struct_mutex); - ret = i915_gem_object_pin(ctx, 4096); + ret = i915_gem_object_pin(ctx, 4096, true); if (ret) { DRM_ERROR("failed to pin power context: %d\n", ret); goto err_unref; @@ -5624,7 +5926,7 @@ err_unpin: i915_gem_object_unpin(ctx); err_unref: - drm_gem_object_unreference(ctx); + drm_gem_object_unreference(&ctx->base); mutex_unlock(&dev->struct_mutex); return NULL; } @@ -5736,6 +6038,25 @@ } +void gen6_set_rps(struct drm_device *dev, u8 val) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 swreq; + + swreq = (val & 0x3ff) << 25; + I915_WRITE(GEN6_RPNSWREQ, swreq); +} + +void gen6_disable_rps(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + I915_WRITE(GEN6_RPNSWREQ, 1 << 31); + I915_WRITE(GEN6_PMINTRMSK, 0xffffffff); + I915_WRITE(GEN6_PMIER, 0); + I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR)); +} + static unsigned long intel_pxfreq(u32 vidfreq) { unsigned long freq; @@ -5822,7 +6143,123 @@ dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK); } -void intel_init_clock_gating(struct drm_device *dev) +void gen6_enable_rps(struct drm_i915_private *dev_priv) +{ + u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); + u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); + u32 pcu_mbox; + int cur_freq, min_freq, max_freq; + int i; + + /* Here begins a magic sequence of register writes to enable + * auto-downclocking. + * + * Perhaps there might be some value in exposing these to + * userspace... + */ + I915_WRITE(GEN6_RC_STATE, 0); + __gen6_force_wake_get(dev_priv); + + /* disable the counters and set deterministic thresholds */ + I915_WRITE(GEN6_RC_CONTROL, 0); + + I915_WRITE(GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16); + I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30); + I915_WRITE(GEN6_RC6pp_WAKE_RATE_LIMIT, 30); + I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); + I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); + + for (i = 0; i < I915_NUM_RINGS; i++) + I915_WRITE(RING_MAX_IDLE(dev_priv->ring[i].mmio_base), 10); + + I915_WRITE(GEN6_RC_SLEEP, 0); + I915_WRITE(GEN6_RC1e_THRESHOLD, 1000); + I915_WRITE(GEN6_RC6_THRESHOLD, 50000); + I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); + I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ + + I915_WRITE(GEN6_RC_CONTROL, + GEN6_RC_CTL_RC6p_ENABLE | + GEN6_RC_CTL_RC6_ENABLE | + GEN6_RC_CTL_EI_MODE(1) | + GEN6_RC_CTL_HW_ENABLE); + + I915_WRITE(GEN6_RPNSWREQ, + GEN6_FREQUENCY(10) | + GEN6_OFFSET(0) | + GEN6_AGGRESSIVE_TURBO); + I915_WRITE(GEN6_RC_VIDEO_FREQ, + GEN6_FREQUENCY(12)); + + I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); + I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, + 18 << 24 | + 6 << 16); + I915_WRITE(GEN6_RP_UP_THRESHOLD, 90000); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 100000); + I915_WRITE(GEN6_RP_UP_EI, 100000); + I915_WRITE(GEN6_RP_DOWN_EI, 300000); + I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); + I915_WRITE(GEN6_RP_CONTROL, + GEN6_RP_MEDIA_TURBO | + GEN6_RP_USE_NORMAL_FREQ | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_MAX | + GEN6_RP_DOWN_BUSY_MIN); + + if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, + 500)) + DRM_ERROR("timeout waiting for pcode mailbox to become idle\n"); + + I915_WRITE(GEN6_PCODE_DATA, 0); + I915_WRITE(GEN6_PCODE_MAILBOX, + GEN6_PCODE_READY | + GEN6_PCODE_WRITE_MIN_FREQ_TABLE); + if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, + 500)) + DRM_ERROR("timeout waiting for pcode mailbox to finish\n"); + + min_freq = (rp_state_cap & 0xff0000) >> 16; + max_freq = rp_state_cap & 0xff; + cur_freq = (gt_perf_status & 0xff00) >> 8; + + /* Check for overclock support */ + if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, + 500)) + DRM_ERROR("timeout waiting for pcode mailbox to become idle\n"); + I915_WRITE(GEN6_PCODE_MAILBOX, GEN6_READ_OC_PARAMS); + pcu_mbox = I915_READ(GEN6_PCODE_DATA); + if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, + 500)) + DRM_ERROR("timeout waiting for pcode mailbox to finish\n"); + if (pcu_mbox & (1<<31)) { /* OC supported */ + max_freq = pcu_mbox & 0xff; + DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 100); + } + + /* In units of 100MHz */ + dev_priv->max_delay = max_freq; + dev_priv->min_delay = min_freq; + dev_priv->cur_delay = cur_freq; + + /* requires MSI enabled */ + I915_WRITE(GEN6_PMIER, + GEN6_PM_MBOX_EVENT | + GEN6_PM_THERMAL_EVENT | + GEN6_PM_RP_DOWN_TIMEOUT | + GEN6_PM_RP_UP_THRESHOLD | + GEN6_PM_RP_DOWN_THRESHOLD | + GEN6_PM_RP_UP_EI_EXPIRED | + GEN6_PM_RP_DOWN_EI_EXPIRED); + I915_WRITE(GEN6_PMIMR, 0); + /* enable all PM interrupts */ + I915_WRITE(GEN6_PMINTRMSK, 0); + + __gen6_force_wake_put(dev_priv); +} + +void intel_enable_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5872,9 +6309,9 @@ I915_WRITE(DISP_ARB_CTL, (I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS)); - I915_WRITE(WM3_LP_ILK, 0); - I915_WRITE(WM2_LP_ILK, 0); - I915_WRITE(WM1_LP_ILK, 0); + I915_WRITE(WM3_LP_ILK, 0); + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); } /* * Based on the document from hardware guys the following bits @@ -5896,7 +6333,49 @@ ILK_DPFC_DIS2 | ILK_CLK_FBC); } - return; + + I915_WRITE(ILK_DISPLAY_CHICKEN2, + I915_READ(ILK_DISPLAY_CHICKEN2) | + ILK_ELPIN_409_SELECT); + + if (IS_GEN5(dev)) { + I915_WRITE(_3D_CHICKEN2, + _3D_CHICKEN2_WM_READ_PIPELINED << 16 | + _3D_CHICKEN2_WM_READ_PIPELINED); + } + + if (IS_GEN6(dev)) { + I915_WRITE(WM3_LP_ILK, 0); + I915_WRITE(WM2_LP_ILK, 0); + I915_WRITE(WM1_LP_ILK, 0); + + /* + * According to the spec the following bits should be + * set in order to enable memory self-refresh and fbc: + * The bit21 and bit22 of 0x42000 + * The bit21 and bit22 of 0x42004 + * The bit5 and bit7 of 0x42020 + * The bit14 of 0x70180 + * The bit14 of 0x71180 + */ + I915_WRITE(ILK_DISPLAY_CHICKEN1, + I915_READ(ILK_DISPLAY_CHICKEN1) | + ILK_FBCQ_DIS | ILK_PABSTRETCH_DIS); + I915_WRITE(ILK_DISPLAY_CHICKEN2, + I915_READ(ILK_DISPLAY_CHICKEN2) | + ILK_DPARB_GATE | ILK_VSDPFD_FULL); + I915_WRITE(ILK_DSPCLK_GATE, + I915_READ(ILK_DSPCLK_GATE) | + ILK_DPARB_CLK_GATE | + ILK_DPFD_CLK_GATE); + + I915_WRITE(DSPACNTR, + I915_READ(DSPACNTR) | + DISPPLANE_TRICKLE_FEED_DISABLE); + I915_WRITE(DSPBCNTR, + I915_READ(DSPBCNTR) | + DISPPLANE_TRICKLE_FEED_DISABLE); + } } else if (IS_G4X(dev)) { uint32_t dspclk_gate; I915_WRITE(RENCLK_GATE_D1, 0); @@ -5939,20 +6418,18 @@ * GPU can automatically power down the render unit if given a page * to save state. */ - if (IS_IRONLAKE_M(dev)) { + if (IS_IRONLAKE_M(dev) && 0) { /* XXX causes a failure during suspend */ if (dev_priv->renderctx == NULL) dev_priv->renderctx = intel_alloc_context_page(dev); if (dev_priv->renderctx) { - struct drm_i915_gem_object *obj_priv; - obj_priv = to_intel_bo(dev_priv->renderctx); - if (obj_priv) { - BEGIN_LP_RING(4); + struct drm_i915_gem_object *obj = dev_priv->renderctx; + if (BEGIN_LP_RING(4) == 0) { OUT_RING(MI_SET_CONTEXT); - OUT_RING(obj_priv->gtt_offset | - MI_MM_SPACE_GTT | - MI_SAVE_EXT_STATE_EN | - MI_RESTORE_EXT_STATE_EN | - MI_RESTORE_INHIBIT); + OUT_RING(obj->gtt_offset | + MI_MM_SPACE_GTT | + MI_SAVE_EXT_STATE_EN | + MI_RESTORE_EXT_STATE_EN | + MI_RESTORE_INHIBIT); OUT_RING(MI_NOOP); OUT_RING(MI_FLUSH); ADVANCE_LP_RING(); @@ -5962,29 +6439,45 @@ "Disable RC6\n"); } - if (I915_HAS_RC6(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) { - struct drm_i915_gem_object *obj_priv = NULL; - + if (IS_GEN4(dev) && IS_MOBILE(dev)) { + if (dev_priv->pwrctx == NULL) + dev_priv->pwrctx = intel_alloc_context_page(dev); if (dev_priv->pwrctx) { - obj_priv = to_intel_bo(dev_priv->pwrctx); - } else { - struct drm_gem_object *pwrctx; - - pwrctx = intel_alloc_context_page(dev); - if (pwrctx) { - dev_priv->pwrctx = pwrctx; - obj_priv = to_intel_bo(pwrctx); - } - } - - if (obj_priv) { - I915_WRITE(PWRCTXA, obj_priv->gtt_offset | PWRCTX_EN); + struct drm_i915_gem_object *obj = dev_priv->pwrctx; + I915_WRITE(PWRCTXA, obj->gtt_offset | PWRCTX_EN); I915_WRITE(MCHBAR_RENDER_STANDBY, I915_READ(MCHBAR_RENDER_STANDBY) & ~RCX_SW_EXIT); } } } +void intel_disable_clock_gating(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->renderctx) { + struct drm_i915_gem_object *obj = dev_priv->renderctx; + + I915_WRITE(CCID, 0); + POSTING_READ(CCID); + + i915_gem_object_unpin(obj); + drm_gem_object_unreference(&obj->base); + dev_priv->renderctx = NULL; + } + + if (dev_priv->pwrctx) { + struct drm_i915_gem_object *obj = dev_priv->pwrctx; + + I915_WRITE(PWRCTXA, 0); + POSTING_READ(PWRCTXA); + + i915_gem_object_unpin(obj); + drm_gem_object_unreference(&obj->base); + dev_priv->pwrctx = NULL; + } +} + /* Set up chip specific display functions */ static void intel_init_display(struct drm_device *dev) { @@ -5997,7 +6490,7 @@ dev_priv->display.dpms = i9xx_crtc_dpms; if (I915_HAS_FBC(dev)) { - if (IS_IRONLAKE_M(dev)) { + if (HAS_PCH_SPLIT(dev)) { dev_priv->display.fbc_enabled = ironlake_fbc_enabled; dev_priv->display.enable_fbc = ironlake_enable_fbc; dev_priv->display.disable_fbc = ironlake_disable_fbc; @@ -6046,6 +6539,14 @@ "Disable CxSR\n"); dev_priv->display.update_wm = NULL; } + } else if (IS_GEN6(dev)) { + if (SNB_READ_WM0_LATENCY()) { + dev_priv->display.update_wm = sandybridge_update_wm; + } else { + DRM_DEBUG_KMS("Failed to read display plane latency. " + "Disable CxSR\n"); + dev_priv->display.update_wm = NULL; + } } else dev_priv->display.update_wm = NULL; } else if (IS_PINEVIEW(dev)) { @@ -6191,12 +6692,7 @@ dev->mode_config.max_width = 8192; dev->mode_config.max_height = 8192; } - - /* set memory base */ - if (IS_GEN2(dev)) - dev->mode_config.fb_base = pci_resource_start(dev->pdev, 0); - else - dev->mode_config.fb_base = pci_resource_start(dev->pdev, 2); + dev->mode_config.fb_base = dev->agp->base; if (IS_MOBILE(dev) || !IS_GEN2(dev)) dev_priv->num_pipe = 2; @@ -6211,7 +6707,7 @@ intel_setup_outputs(dev); - intel_init_clock_gating(dev); + intel_enable_clock_gating(dev); /* Just disable it once at startup */ i915_disable_vga(dev); @@ -6221,6 +6717,9 @@ intel_init_emon(dev); } + if (IS_GEN6(dev)) + gen6_enable_rps(dev_priv); + INIT_WORK(&dev_priv->idle_work, intel_idle_update); setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, (unsigned long)dev); @@ -6252,28 +6751,12 @@ if (dev_priv->display.disable_fbc) dev_priv->display.disable_fbc(dev); - if (dev_priv->renderctx) { - struct drm_i915_gem_object *obj_priv; - - obj_priv = to_intel_bo(dev_priv->renderctx); - I915_WRITE(CCID, obj_priv->gtt_offset &~ CCID_EN); - I915_READ(CCID); - i915_gem_object_unpin(dev_priv->renderctx); - drm_gem_object_unreference(dev_priv->renderctx); - } - - if (dev_priv->pwrctx) { - struct drm_i915_gem_object *obj_priv; - - obj_priv = to_intel_bo(dev_priv->pwrctx); - I915_WRITE(PWRCTXA, obj_priv->gtt_offset &~ PWRCTX_EN); - I915_READ(PWRCTXA); - i915_gem_object_unpin(dev_priv->pwrctx); - drm_gem_object_unreference(dev_priv->pwrctx); - } - if (IS_IRONLAKE_M(dev)) ironlake_disable_drps(dev); + if (IS_GEN6(dev)) + gen6_disable_rps(dev); + + intel_disable_clock_gating(dev); mutex_unlock(&dev->struct_mutex); @@ -6325,3 +6808,113 @@ pci_write_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, gmch_ctrl); return 0; } + +#ifdef CONFIG_DEBUG_FS +#include + +struct intel_display_error_state { + struct intel_cursor_error_state { + u32 control; + u32 position; + u32 base; + u32 size; + } cursor[2]; + + struct intel_pipe_error_state { + u32 conf; + u32 source; + + u32 htotal; + u32 hblank; + u32 hsync; + u32 vtotal; + u32 vblank; + u32 vsync; + } pipe[2]; + + struct intel_plane_error_state { + u32 control; + u32 stride; + u32 size; + u32 pos; + u32 addr; + u32 surface; + u32 tile_offset; + } plane[2]; +}; + +struct intel_display_error_state * +intel_display_capture_error_state(struct drm_device *dev) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_display_error_state *error; + int i; + + error = kmalloc(sizeof(*error), GFP_ATOMIC); + if (error == NULL) + return NULL; + + for (i = 0; i < 2; i++) { + error->cursor[i].control = I915_READ(CURCNTR(i)); + error->cursor[i].position = I915_READ(CURPOS(i)); + error->cursor[i].base = I915_READ(CURBASE(i)); + + error->plane[i].control = I915_READ(DSPCNTR(i)); + error->plane[i].stride = I915_READ(DSPSTRIDE(i)); + error->plane[i].size = I915_READ(DSPSIZE(i)); + error->plane[i].pos= I915_READ(DSPPOS(i)); + error->plane[i].addr = I915_READ(DSPADDR(i)); + if (INTEL_INFO(dev)->gen >= 4) { + error->plane[i].surface = I915_READ(DSPSURF(i)); + error->plane[i].tile_offset = I915_READ(DSPTILEOFF(i)); + } + + error->pipe[i].conf = I915_READ(PIPECONF(i)); + error->pipe[i].source = I915_READ(PIPESRC(i)); + error->pipe[i].htotal = I915_READ(HTOTAL(i)); + error->pipe[i].hblank = I915_READ(HBLANK(i)); + error->pipe[i].hsync = I915_READ(HSYNC(i)); + error->pipe[i].vtotal = I915_READ(VTOTAL(i)); + error->pipe[i].vblank = I915_READ(VBLANK(i)); + error->pipe[i].vsync = I915_READ(VSYNC(i)); + } + + return error; +} + +void +intel_display_print_error_state(struct seq_file *m, + struct drm_device *dev, + struct intel_display_error_state *error) +{ + int i; + + for (i = 0; i < 2; i++) { + seq_printf(m, "Pipe [%d]:\n", i); + seq_printf(m, " CONF: %08x\n", error->pipe[i].conf); + seq_printf(m, " SRC: %08x\n", error->pipe[i].source); + seq_printf(m, " HTOTAL: %08x\n", error->pipe[i].htotal); + seq_printf(m, " HBLANK: %08x\n", error->pipe[i].hblank); + seq_printf(m, " HSYNC: %08x\n", error->pipe[i].hsync); + seq_printf(m, " VTOTAL: %08x\n", error->pipe[i].vtotal); + seq_printf(m, " VBLANK: %08x\n", error->pipe[i].vblank); + seq_printf(m, " VSYNC: %08x\n", error->pipe[i].vsync); + + seq_printf(m, "Plane [%d]:\n", i); + seq_printf(m, " CNTR: %08x\n", error->plane[i].control); + seq_printf(m, " STRIDE: %08x\n", error->plane[i].stride); + seq_printf(m, " SIZE: %08x\n", error->plane[i].size); + seq_printf(m, " POS: %08x\n", error->plane[i].pos); + seq_printf(m, " ADDR: %08x\n", error->plane[i].addr); + if (INTEL_INFO(dev)->gen >= 4) { + seq_printf(m, " SURF: %08x\n", error->plane[i].surface); + seq_printf(m, " TILEOFF: %08x\n", error->plane[i].tile_offset); + } + + seq_printf(m, "Cursor [%d]:\n", i); + seq_printf(m, " CNTR: %08x\n", error->cursor[i].control); + seq_printf(m, " POS: %08x\n", error->cursor[i].position); + seq_printf(m, " BASE: %08x\n", error->cursor[i].base); + } +} +#endif --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_dp.c +++ linux-2.6.37/drivers/gpu/drm/i915/intel_dp.c @@ -1442,8 +1442,7 @@ /* Changes to enable or select take place the vblank * after being written. */ - intel_wait_for_vblank(intel_dp->base.base.dev, - intel_crtc->pipe); + intel_wait_for_vblank(dev, intel_crtc->pipe); } I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_drv.h +++ linux-2.6.37/drivers/gpu/drm/i915/intel_drv.h @@ -127,7 +127,7 @@ struct intel_framebuffer { struct drm_framebuffer base; - struct drm_gem_object *obj; + struct drm_i915_gem_object *obj; }; struct intel_fbdev { @@ -166,7 +166,7 @@ struct intel_unpin_work *unpin_work; int fdi_lanes; - struct drm_gem_object *cursor_bo; + struct drm_i915_gem_object *cursor_bo; uint32_t cursor_addr; int16_t cursor_x, cursor_y; int16_t cursor_width, cursor_height; @@ -220,8 +220,8 @@ struct intel_unpin_work { struct work_struct work; struct drm_device *dev; - struct drm_gem_object *old_fb_obj; - struct drm_gem_object *pending_flip_obj; + struct drm_i915_gem_object *old_fb_obj; + struct drm_i915_gem_object *pending_flip_obj; struct drm_pending_vblank_event *event; int pending; bool enable_stall_check; @@ -236,7 +236,8 @@ extern bool intel_sdvo_init(struct drm_device *dev, int output_device); extern void intel_dvo_init(struct drm_device *dev); extern void intel_tv_init(struct drm_device *dev); -extern void intel_mark_busy(struct drm_device *dev, struct drm_gem_object *obj); +extern void intel_mark_busy(struct drm_device *dev, + struct drm_i915_gem_object *obj); extern bool intel_lvds_init(struct drm_device *dev); extern void intel_dp_init(struct drm_device *dev, int dp_reg); void @@ -293,19 +294,22 @@ u16 blue, int regno); extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, int regno); -extern void intel_init_clock_gating(struct drm_device *dev); +extern void intel_enable_clock_gating(struct drm_device *dev); +extern void intel_disable_clock_gating(struct drm_device *dev); extern void ironlake_enable_drps(struct drm_device *dev); extern void ironlake_disable_drps(struct drm_device *dev); +extern void gen6_enable_rps(struct drm_i915_private *dev_priv); +extern void gen6_disable_rps(struct drm_device *dev); extern void intel_init_emon(struct drm_device *dev); extern int intel_pin_and_fence_fb_obj(struct drm_device *dev, - struct drm_gem_object *obj, - bool pipelined); + struct drm_i915_gem_object *obj, + struct intel_ring_buffer *pipelined); extern int intel_framebuffer_init(struct drm_device *dev, struct intel_framebuffer *ifb, struct drm_mode_fb_cmd *mode_cmd, - struct drm_gem_object *obj); + struct drm_i915_gem_object *obj); extern int intel_fbdev_init(struct drm_device *dev); extern void intel_fbdev_fini(struct drm_device *dev); --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_fb.c +++ linux-2.6.37/drivers/gpu/drm/i915/intel_fb.c @@ -62,11 +62,11 @@ struct drm_fb_helper_surface_size *sizes) { struct drm_device *dev = ifbdev->helper.dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct fb_info *info; struct drm_framebuffer *fb; struct drm_mode_fb_cmd mode_cmd; - struct drm_gem_object *fbo = NULL; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; struct device *device = &dev->pdev->dev; int size, ret, mmio_bar = IS_GEN2(dev) ? 1 : 0; @@ -78,23 +78,22 @@ mode_cmd.height = sizes->surface_height; mode_cmd.bpp = sizes->surface_bpp; - mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64); + mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64); mode_cmd.depth = sizes->surface_depth; size = mode_cmd.pitch * mode_cmd.height; size = ALIGN(size, PAGE_SIZE); - fbo = i915_gem_alloc_object(dev, size); - if (!fbo) { + obj = i915_gem_alloc_object(dev, size); + if (!obj) { DRM_ERROR("failed to allocate framebuffer\n"); ret = -ENOMEM; goto out; } - obj_priv = to_intel_bo(fbo); mutex_lock(&dev->struct_mutex); /* Flush everything out, we'll be doing GTT only from now on */ - ret = intel_pin_and_fence_fb_obj(dev, fbo, false); + ret = intel_pin_and_fence_fb_obj(dev, obj, false); if (ret) { DRM_ERROR("failed to pin fb: %d\n", ret); goto out_unref; @@ -108,7 +107,7 @@ info->par = ifbdev; - ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, fbo); + ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj); if (ret) goto out_unpin; @@ -122,6 +121,11 @@ info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; info->fbops = &intelfb_ops; + ret = fb_alloc_cmap(&info->cmap, 256, 0); + if (ret) { + ret = -ENOMEM; + goto out_unpin; + } /* setup aperture base/size for vesafb takeover */ info->apertures = alloc_apertures(1); if (!info->apertures) { @@ -129,26 +133,17 @@ goto out_unpin; } info->apertures->ranges[0].base = dev->mode_config.fb_base; - if (!IS_GEN2(dev)) - info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 2); - else - info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); + info->apertures->ranges[0].size = + dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; - info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; + info->fix.smem_start = dev->mode_config.fb_base + obj->gtt_offset; info->fix.smem_len = size; - info->screen_base = ioremap_wc(dev->agp->base + obj_priv->gtt_offset, - size); + info->screen_base = ioremap_wc(dev->agp->base + obj->gtt_offset, size); if (!info->screen_base) { ret = -ENOSPC; goto out_unpin; } - - ret = fb_alloc_cmap(&info->cmap, 256, 0); - if (ret) { - ret = -ENOMEM; - goto out_unpin; - } info->screen_size = size; // memset(info->screen_base, 0, size); @@ -168,7 +163,7 @@ DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", fb->width, fb->height, - obj_priv->gtt_offset, fbo); + obj->gtt_offset, obj); mutex_unlock(&dev->struct_mutex); @@ -176,9 +171,9 @@ return 0; out_unpin: - i915_gem_object_unpin(fbo); + i915_gem_object_unpin(obj); out_unref: - drm_gem_object_unreference(fbo); + drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); out: return ret; @@ -225,7 +220,7 @@ drm_framebuffer_cleanup(&ifb->base); if (ifb->obj) { - drm_gem_object_unreference_unlocked(ifb->obj); + drm_gem_object_unreference_unlocked(&ifb->obj->base); ifb->obj = NULL; } } --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_i2c.c +++ linux-2.6.37/drivers/gpu/drm/i915/intel_i2c.c @@ -85,8 +85,9 @@ /* On most chips, these bits must be preserved in software. */ if (!IS_I830(dev) && !IS_845G(dev)) - reserved = I915_READ(gpio->reg) & (GPIO_DATA_PULLUP_DISABLE | - GPIO_CLOCK_PULLUP_DISABLE); + reserved = I915_READ_NOTRACE(gpio->reg) & + (GPIO_DATA_PULLUP_DISABLE | + GPIO_CLOCK_PULLUP_DISABLE); return reserved; } @@ -96,9 +97,9 @@ struct intel_gpio *gpio = data; struct drm_i915_private *dev_priv = gpio->dev_priv; u32 reserved = get_reserved(gpio); - I915_WRITE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK); - I915_WRITE(gpio->reg, reserved); - return (I915_READ(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0; + I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_CLOCK_DIR_MASK); + I915_WRITE_NOTRACE(gpio->reg, reserved); + return (I915_READ_NOTRACE(gpio->reg) & GPIO_CLOCK_VAL_IN) != 0; } static int get_data(void *data) @@ -106,9 +107,9 @@ struct intel_gpio *gpio = data; struct drm_i915_private *dev_priv = gpio->dev_priv; u32 reserved = get_reserved(gpio); - I915_WRITE(gpio->reg, reserved | GPIO_DATA_DIR_MASK); - I915_WRITE(gpio->reg, reserved); - return (I915_READ(gpio->reg) & GPIO_DATA_VAL_IN) != 0; + I915_WRITE_NOTRACE(gpio->reg, reserved | GPIO_DATA_DIR_MASK); + I915_WRITE_NOTRACE(gpio->reg, reserved); + return (I915_READ_NOTRACE(gpio->reg) & GPIO_DATA_VAL_IN) != 0; } static void set_clock(void *data, int state_high) @@ -124,7 +125,7 @@ clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_VAL_MASK; - I915_WRITE(gpio->reg, reserved | clock_bits); + I915_WRITE_NOTRACE(gpio->reg, reserved | clock_bits); POSTING_READ(gpio->reg); } @@ -141,7 +142,7 @@ data_bits = GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | GPIO_DATA_VAL_MASK; - I915_WRITE(gpio->reg, reserved | data_bits); + I915_WRITE_NOTRACE(gpio->reg, reserved | data_bits); POSTING_READ(gpio->reg); } --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_lvds.c +++ linux-2.6.37/drivers/gpu/drm/i915/intel_lvds.c @@ -304,14 +304,13 @@ u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; - pfit_control |= PFIT_ENABLE; /* 965+ is easy, it does everything in hw */ if (scaled_width > scaled_height) - pfit_control |= PFIT_SCALING_PILLAR; + pfit_control |= PFIT_ENABLE | PFIT_SCALING_PILLAR; else if (scaled_width < scaled_height) - pfit_control |= PFIT_SCALING_LETTER; - else - pfit_control |= PFIT_SCALING_AUTO; + pfit_control |= PFIT_ENABLE | PFIT_SCALING_LETTER; + else if (adjusted_mode->hdisplay != mode->hdisplay) + pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; } else { u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay; u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay; @@ -358,13 +357,17 @@ * Full scaling, even if it changes the aspect ratio. * Fortunately this is all done for us in hw. */ - pfit_control |= PFIT_ENABLE; - if (INTEL_INFO(dev)->gen >= 4) - pfit_control |= PFIT_SCALING_AUTO; - else - pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | - VERT_INTERP_BILINEAR | - HORIZ_INTERP_BILINEAR); + if (mode->vdisplay != adjusted_mode->vdisplay || + mode->hdisplay != adjusted_mode->hdisplay) { + pfit_control |= PFIT_ENABLE; + if (INTEL_INFO(dev)->gen >= 4) + pfit_control |= PFIT_SCALING_AUTO; + else + pfit_control |= (VERT_AUTO_SCALE | + VERT_INTERP_BILINEAR | + HORIZ_AUTO_SCALE | + HORIZ_INTERP_BILINEAR); + } break; default: @@ -914,6 +917,8 @@ intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); intel_encoder->crtc_mask = (1 << 1); + if (INTEL_INFO(dev)->gen >= 5) + intel_encoder->crtc_mask |= (1 << 0); drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); connector->display_info.subpixel_order = SubPixelHorizontalRGB; @@ -1019,10 +1024,18 @@ out: if (HAS_PCH_SPLIT(dev)) { u32 pwm; - /* make sure PWM is enabled */ + + pipe = (I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) ? 1 : 0; + + /* make sure PWM is enabled and locked to the LVDS pipe */ pwm = I915_READ(BLC_PWM_CPU_CTL2); - pwm |= (PWM_ENABLE | PWM_PIPE_B); - I915_WRITE(BLC_PWM_CPU_CTL2, pwm); + if (pipe == 0 && (pwm & PWM_PIPE_B)) + I915_WRITE(BLC_PWM_CPU_CTL2, pwm & ~PWM_ENABLE); + if (pipe) + pwm |= PWM_PIPE_B; + else + pwm &= ~PWM_PIPE_B; + I915_WRITE(BLC_PWM_CPU_CTL2, pwm | PWM_ENABLE); pwm = I915_READ(BLC_PWM_PCH_CTL1); pwm |= PWM_PCH_ENABLE; --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_opregion.c +++ linux-2.6.37/drivers/gpu/drm/i915/intel_opregion.c @@ -273,14 +273,8 @@ struct opregion_asle *asle = dev_priv->opregion.asle; if (asle) { - if (IS_MOBILE(dev)) { - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); + if (IS_MOBILE(dev)) intel_enable_asle(dev); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, - irqflags); - } asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN | ASLE_PFMB_EN; --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_overlay.c +++ linux-2.6.37/drivers/gpu/drm/i915/intel_overlay.c @@ -221,15 +221,16 @@ int ret; BUG_ON(overlay->last_flip_req); - overlay->last_flip_req = - i915_add_request(dev, NULL, request, &dev_priv->render_ring); - if (overlay->last_flip_req == 0) - return -ENOMEM; - + ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv)); + if (ret) { + kfree(request); + return ret; + } + overlay->last_flip_req = request->seqno; overlay->flip_tail = tail; ret = i915_do_wait_request(dev, overlay->last_flip_req, true, - &dev_priv->render_ring); + LP_RING(dev_priv)); if (ret) return ret; @@ -289,6 +290,7 @@ static int intel_overlay_on(struct intel_overlay *overlay) { struct drm_device *dev = overlay->dev; + struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_request *request; int pipe_a_quirk = 0; int ret; @@ -308,7 +310,12 @@ goto out; } - BEGIN_LP_RING(4); + ret = BEGIN_LP_RING(4); + if (ret) { + kfree(request); + goto out; + } + OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_ON); OUT_RING(overlay->flip_addr | OFC_UPDATE); OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); @@ -332,6 +339,7 @@ struct drm_i915_gem_request *request; u32 flip_addr = overlay->flip_addr; u32 tmp; + int ret; BUG_ON(!overlay->active); @@ -347,36 +355,44 @@ if (tmp & (1 << 17)) DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp); - BEGIN_LP_RING(2); + ret = BEGIN_LP_RING(2); + if (ret) { + kfree(request); + return ret; + } OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); OUT_RING(flip_addr); ADVANCE_LP_RING(); - overlay->last_flip_req = - i915_add_request(dev, NULL, request, &dev_priv->render_ring); + ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv)); + if (ret) { + kfree(request); + return ret; + } + + overlay->last_flip_req = request->seqno; return 0; } static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay) { - struct drm_gem_object *obj = &overlay->old_vid_bo->base; + struct drm_i915_gem_object *obj = overlay->old_vid_bo; i915_gem_object_unpin(obj); - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); overlay->old_vid_bo = NULL; } static void intel_overlay_off_tail(struct intel_overlay *overlay) { - struct drm_gem_object *obj; + struct drm_i915_gem_object *obj = overlay->vid_bo; /* never have the overlay hw on without showing a frame */ BUG_ON(!overlay->vid_bo); - obj = &overlay->vid_bo->base; i915_gem_object_unpin(obj); - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); overlay->vid_bo = NULL; overlay->crtc->overlay = NULL; @@ -389,8 +405,10 @@ bool interruptible) { struct drm_device *dev = overlay->dev; + struct drm_i915_private *dev_priv = dev->dev_private; u32 flip_addr = overlay->flip_addr; struct drm_i915_gem_request *request; + int ret; BUG_ON(!overlay->active); @@ -404,7 +422,11 @@ * of the hw. Do it in both cases */ flip_addr |= OFC_UPDATE; - BEGIN_LP_RING(6); + ret = BEGIN_LP_RING(6); + if (ret) { + kfree(request); + return ret; + } /* wait for overlay to go idle */ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE); OUT_RING(flip_addr); @@ -432,7 +454,7 @@ return 0; ret = i915_do_wait_request(dev, overlay->last_flip_req, - interruptible, &dev_priv->render_ring); + interruptible, LP_RING(dev_priv)); if (ret) return ret; @@ -467,7 +489,12 @@ if (request == NULL) return -ENOMEM; - BEGIN_LP_RING(2); + ret = BEGIN_LP_RING(2); + if (ret) { + kfree(request); + return ret; + } + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); OUT_RING(MI_NOOP); ADVANCE_LP_RING(); @@ -736,13 +763,12 @@ } static int intel_overlay_do_put_image(struct intel_overlay *overlay, - struct drm_gem_object *new_bo, + struct drm_i915_gem_object *new_bo, struct put_image_params *params) { int ret, tmp_width; struct overlay_registers *regs; bool scale_changed = false; - struct drm_i915_gem_object *bo_priv = to_intel_bo(new_bo); struct drm_device *dev = overlay->dev; BUG_ON(!mutex_is_locked(&dev->struct_mutex)); @@ -753,7 +779,7 @@ if (ret != 0) return ret; - ret = i915_gem_object_pin(new_bo, PAGE_SIZE); + ret = i915_gem_object_pin(new_bo, PAGE_SIZE, true); if (ret != 0) return ret; @@ -761,6 +787,10 @@ if (ret != 0) goto out_unpin; + ret = i915_gem_object_put_fence(new_bo); + if (ret) + goto out_unpin; + if (!overlay->active) { regs = intel_overlay_map_regs(overlay); if (!regs) { @@ -797,7 +827,7 @@ regs->SWIDTHSW = calc_swidthsw(overlay->dev, params->offset_Y, tmp_width); regs->SHEIGHT = params->src_h; - regs->OBUF_0Y = bo_priv->gtt_offset + params-> offset_Y; + regs->OBUF_0Y = new_bo->gtt_offset + params-> offset_Y; regs->OSTRIDE = params->stride_Y; if (params->format & I915_OVERLAY_YUV_PLANAR) { @@ -811,8 +841,8 @@ params->src_w/uv_hscale); regs->SWIDTHSW |= max_t(u32, tmp_U, tmp_V) << 16; regs->SHEIGHT |= (params->src_h/uv_vscale) << 16; - regs->OBUF_0U = bo_priv->gtt_offset + params->offset_U; - regs->OBUF_0V = bo_priv->gtt_offset + params->offset_V; + regs->OBUF_0U = new_bo->gtt_offset + params->offset_U; + regs->OBUF_0V = new_bo->gtt_offset + params->offset_V; regs->OSTRIDE |= params->stride_UV << 16; } @@ -829,7 +859,7 @@ goto out_unpin; overlay->old_vid_bo = overlay->vid_bo; - overlay->vid_bo = to_intel_bo(new_bo); + overlay->vid_bo = new_bo; return 0; @@ -942,7 +972,7 @@ static int check_overlay_src(struct drm_device *dev, struct drm_intel_overlay_put_image *rec, - struct drm_gem_object *new_bo) + struct drm_i915_gem_object *new_bo) { int uv_hscale = uv_hsubsampling(rec->flags); int uv_vscale = uv_vsubsampling(rec->flags); @@ -1027,7 +1057,7 @@ return -EINVAL; tmp = rec->stride_Y*rec->src_height; - if (rec->offset_Y + tmp > new_bo->size) + if (rec->offset_Y + tmp > new_bo->base.size) return -EINVAL; break; @@ -1038,12 +1068,12 @@ return -EINVAL; tmp = rec->stride_Y * rec->src_height; - if (rec->offset_Y + tmp > new_bo->size) + if (rec->offset_Y + tmp > new_bo->base.size) return -EINVAL; tmp = rec->stride_UV * (rec->src_height / uv_vscale); - if (rec->offset_U + tmp > new_bo->size || - rec->offset_V + tmp > new_bo->size) + if (rec->offset_U + tmp > new_bo->base.size || + rec->offset_V + tmp > new_bo->base.size) return -EINVAL; break; } @@ -1086,7 +1116,7 @@ struct intel_overlay *overlay; struct drm_mode_object *drmmode_obj; struct intel_crtc *crtc; - struct drm_gem_object *new_bo; + struct drm_i915_gem_object *new_bo; struct put_image_params *params; int ret; @@ -1125,8 +1155,8 @@ } crtc = to_intel_crtc(obj_to_crtc(drmmode_obj)); - new_bo = drm_gem_object_lookup(dev, file_priv, - put_image_rec->bo_handle); + new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv, + put_image_rec->bo_handle)); if (!new_bo) { ret = -ENOENT; goto out_free; @@ -1135,6 +1165,12 @@ mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->struct_mutex); + if (new_bo->tiling_mode) { + DRM_ERROR("buffer used for overlay image can not be tiled\n"); + ret = -EINVAL; + goto out_unlock; + } + ret = intel_overlay_recover_from_interrupt(overlay, true); if (ret != 0) goto out_unlock; @@ -1217,7 +1253,7 @@ out_unlock: mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->mode_config.mutex); - drm_gem_object_unreference_unlocked(new_bo); + drm_gem_object_unreference_unlocked(&new_bo->base); out_free: kfree(params); @@ -1370,7 +1406,7 @@ { drm_i915_private_t *dev_priv = dev->dev_private; struct intel_overlay *overlay; - struct drm_gem_object *reg_bo; + struct drm_i915_gem_object *reg_bo; struct overlay_registers *regs; int ret; @@ -1385,7 +1421,7 @@ reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); if (!reg_bo) goto out_free; - overlay->reg_bo = to_intel_bo(reg_bo); + overlay->reg_bo = reg_bo; if (OVERLAY_NEEDS_PHYSICAL(dev)) { ret = i915_gem_attach_phys_object(dev, reg_bo, @@ -1395,14 +1431,14 @@ DRM_ERROR("failed to attach phys overlay regs\n"); goto out_free_bo; } - overlay->flip_addr = overlay->reg_bo->phys_obj->handle->busaddr; + overlay->flip_addr = reg_bo->phys_obj->handle->busaddr; } else { - ret = i915_gem_object_pin(reg_bo, PAGE_SIZE); + ret = i915_gem_object_pin(reg_bo, PAGE_SIZE, true); if (ret) { DRM_ERROR("failed to pin overlay register bo\n"); goto out_free_bo; } - overlay->flip_addr = overlay->reg_bo->gtt_offset; + overlay->flip_addr = reg_bo->gtt_offset; ret = i915_gem_object_set_to_gtt_domain(reg_bo, true); if (ret) { @@ -1434,7 +1470,7 @@ out_unpin_bo: i915_gem_object_unpin(reg_bo); out_free_bo: - drm_gem_object_unreference(reg_bo); + drm_gem_object_unreference(®_bo->base); out_free: kfree(overlay); return; --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_panel.c +++ linux-2.6.37/drivers/gpu/drm/i915/intel_panel.c @@ -125,15 +125,55 @@ return 0; } +static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv) +{ + u32 val; + + /* Restore the CTL value if it lost, e.g. GPU reset */ + + if (HAS_PCH_SPLIT(dev_priv->dev)) { + val = I915_READ(BLC_PWM_PCH_CTL2); + if (dev_priv->saveBLC_PWM_CTL2 == 0) { + dev_priv->saveBLC_PWM_CTL2 = val; + } else if (val == 0) { + I915_WRITE(BLC_PWM_PCH_CTL2, + dev_priv->saveBLC_PWM_CTL); + val = dev_priv->saveBLC_PWM_CTL; + } + } else { + val = I915_READ(BLC_PWM_CTL); + if (dev_priv->saveBLC_PWM_CTL == 0) { + dev_priv->saveBLC_PWM_CTL = val; + dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_CTL2); + } else if (val == 0) { + I915_WRITE(BLC_PWM_CTL, + dev_priv->saveBLC_PWM_CTL); + I915_WRITE(BLC_PWM_CTL2, + dev_priv->saveBLC_PWM_CTL2); + val = dev_priv->saveBLC_PWM_CTL; + } + } + + return val; +} + u32 intel_panel_get_max_backlight(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 max; + max = i915_read_blc_pwm_ctl(dev_priv); + if (max == 0) { + /* XXX add code here to query mode clock or hardware clock + * and program max PWM appropriately. + */ + printk_once(KERN_WARNING "fixme: max PWM is zero.\n"); + return 1; + } + if (HAS_PCH_SPLIT(dev)) { - max = I915_READ(BLC_PWM_PCH_CTL2) >> 16; + max >>= 16; } else { - max = I915_READ(BLC_PWM_CTL); if (IS_PINEVIEW(dev)) { max >>= 17; } else { @@ -146,14 +186,6 @@ max *= 0xff; } - if (max == 0) { - /* XXX add code here to query mode clock or hardware clock - * and program max PWM appropriately. - */ - DRM_ERROR("fixme: max PWM is zero.\n"); - max = 1; - } - DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max); return max; } --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_ringbuffer.c +++ linux-2.6.37/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -48,14 +48,15 @@ return seqno; } -static void -render_ring_flush(struct drm_device *dev, - struct intel_ring_buffer *ring, +static int +render_ring_flush(struct intel_ring_buffer *ring, u32 invalidate_domains, u32 flush_domains) { + struct drm_device *dev = ring->dev; drm_i915_private_t *dev_priv = dev->dev_private; u32 cmd; + int ret; #if WATCH_EXEC DRM_INFO("%s: invalidate %08x flush %08x\n", __func__, @@ -109,49 +110,54 @@ if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION) cmd |= MI_EXE_FLUSH; + if (invalidate_domains & I915_GEM_DOMAIN_COMMAND && + (IS_G4X(dev) || IS_GEN5(dev))) + cmd |= MI_INVALIDATE_ISP; + #if WATCH_EXEC DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd); #endif - intel_ring_begin(dev, ring, 2); - intel_ring_emit(dev, ring, cmd); - intel_ring_emit(dev, ring, MI_NOOP); - intel_ring_advance(dev, ring); + ret = intel_ring_begin(ring, 2); + if (ret) + return ret; + + intel_ring_emit(ring, cmd); + intel_ring_emit(ring, MI_NOOP); + intel_ring_advance(ring); } + + return 0; } -static void ring_write_tail(struct drm_device *dev, - struct intel_ring_buffer *ring, +static void ring_write_tail(struct intel_ring_buffer *ring, u32 value) { - drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_private_t *dev_priv = ring->dev->dev_private; I915_WRITE_TAIL(ring, value); } -u32 intel_ring_get_active_head(struct drm_device *dev, - struct intel_ring_buffer *ring) +u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = dev->dev_private; - u32 acthd_reg = INTEL_INFO(dev)->gen >= 4 ? + drm_i915_private_t *dev_priv = ring->dev->dev_private; + u32 acthd_reg = INTEL_INFO(ring->dev)->gen >= 4 ? RING_ACTHD(ring->mmio_base) : ACTHD; return I915_READ(acthd_reg); } -static int init_ring_common(struct drm_device *dev, - struct intel_ring_buffer *ring) +static int init_ring_common(struct intel_ring_buffer *ring) { + drm_i915_private_t *dev_priv = ring->dev->dev_private; + struct drm_i915_gem_object *obj = ring->obj; u32 head; - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; - obj_priv = to_intel_bo(ring->gem_object); /* Stop the ring if it's running. */ I915_WRITE_CTL(ring, 0); I915_WRITE_HEAD(ring, 0); - ring->write_tail(dev, ring, 0); + ring->write_tail(ring, 0); /* Initialize the ring. */ - I915_WRITE_START(ring, obj_priv->gtt_offset); + I915_WRITE_START(ring, obj->gtt_offset); head = I915_READ_HEAD(ring) & HEAD_ADDR; /* G45 ring initialization fails to reset head to zero */ @@ -178,12 +184,13 @@ } I915_WRITE_CTL(ring, - ((ring->gem_object->size - PAGE_SIZE) & RING_NR_PAGES) + ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | RING_REPORT_64K | RING_VALID); - head = I915_READ_HEAD(ring) & HEAD_ADDR; /* If the head is still not zero, the ring is dead */ - if (head != 0) { + if ((I915_READ_CTL(ring) & RING_VALID) == 0 || + I915_READ_START(ring) != obj->gtt_offset || + (I915_READ_HEAD(ring) & HEAD_ADDR) != 0) { DRM_ERROR("%s initialization failed " "ctl %08x head %08x tail %08x start %08x\n", ring->name, @@ -194,8 +201,8 @@ return -EIO; } - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - i915_kernel_lost_context(dev); + if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) + i915_kernel_lost_context(ring->dev); else { ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; @@ -203,335 +210,562 @@ if (ring->space < 0) ring->space += ring->size; } + return 0; } -static int init_render_ring(struct drm_device *dev, - struct intel_ring_buffer *ring) +/* + * 965+ support PIPE_CONTROL commands, which provide finer grained control + * over cache flushing. + */ +struct pipe_control { + struct drm_i915_gem_object *obj; + volatile u32 *cpu_page; + u32 gtt_offset; +}; + +static int +init_pipe_control(struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = dev->dev_private; - int ret = init_ring_common(dev, ring); - int mode; + struct pipe_control *pc; + struct drm_i915_gem_object *obj; + int ret; + + if (ring->private) + return 0; + + pc = kmalloc(sizeof(*pc), GFP_KERNEL); + if (!pc) + return -ENOMEM; + + obj = i915_gem_alloc_object(ring->dev, 4096); + if (obj == NULL) { + DRM_ERROR("Failed to allocate seqno page\n"); + ret = -ENOMEM; + goto err; + } + obj->agp_type = AGP_USER_CACHED_MEMORY; + + ret = i915_gem_object_pin(obj, 4096, true); + if (ret) + goto err_unref; + + pc->gtt_offset = obj->gtt_offset; + pc->cpu_page = kmap(obj->pages[0]); + if (pc->cpu_page == NULL) + goto err_unpin; + + pc->obj = obj; + ring->private = pc; + return 0; + +err_unpin: + i915_gem_object_unpin(obj); +err_unref: + drm_gem_object_unreference(&obj->base); +err: + kfree(pc); + return ret; +} + +static void +cleanup_pipe_control(struct intel_ring_buffer *ring) +{ + struct pipe_control *pc = ring->private; + struct drm_i915_gem_object *obj; + + if (!ring->private) + return; + + obj = pc->obj; + kunmap(obj->pages[0]); + i915_gem_object_unpin(obj); + drm_gem_object_unreference(&obj->base); + + kfree(pc); + ring->private = NULL; +} + +static int init_render_ring(struct intel_ring_buffer *ring) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int ret = init_ring_common(ring); if (INTEL_INFO(dev)->gen > 3) { - mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH; + int mode = VS_TIMER_DISPATCH << 16 | VS_TIMER_DISPATCH; if (IS_GEN6(dev)) mode |= MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE; I915_WRITE(MI_MODE, mode); } + + if (INTEL_INFO(dev)->gen >= 6) { + } else if (IS_GEN5(dev)) { + ret = init_pipe_control(ring); + if (ret) + return ret; + } + return ret; } -#define PIPE_CONTROL_FLUSH(addr) \ +static void render_ring_cleanup(struct intel_ring_buffer *ring) +{ + if (!ring->private) + return; + + cleanup_pipe_control(ring); +} + +static void +update_semaphore(struct intel_ring_buffer *ring, int i, u32 seqno) +{ + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int id; + + /* + * cs -> 1 = vcs, 0 = bcs + * vcs -> 1 = bcs, 0 = cs, + * bcs -> 1 = cs, 0 = vcs. + */ + id = ring - dev_priv->ring; + id += 2 - i; + id %= 3; + + intel_ring_emit(ring, + MI_SEMAPHORE_MBOX | + MI_SEMAPHORE_REGISTER | + MI_SEMAPHORE_UPDATE); + intel_ring_emit(ring, seqno); + intel_ring_emit(ring, + RING_SYNC_0(dev_priv->ring[id].mmio_base) + 4*i); +} + +static int +gen6_add_request(struct intel_ring_buffer *ring, + u32 *result) +{ + u32 seqno; + int ret; + + ret = intel_ring_begin(ring, 10); + if (ret) + return ret; + + seqno = i915_gem_get_seqno(ring->dev); + update_semaphore(ring, 0, seqno); + update_semaphore(ring, 1, seqno); + + intel_ring_emit(ring, MI_STORE_DWORD_INDEX); + intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); + intel_ring_emit(ring, seqno); + intel_ring_emit(ring, MI_USER_INTERRUPT); + intel_ring_advance(ring); + + *result = seqno; + return 0; +} + +int +intel_ring_sync(struct intel_ring_buffer *ring, + struct intel_ring_buffer *to, + u32 seqno) +{ + int ret; + + ret = intel_ring_begin(ring, 4); + if (ret) + return ret; + + intel_ring_emit(ring, + MI_SEMAPHORE_MBOX | + MI_SEMAPHORE_REGISTER | + intel_ring_sync_index(ring, to) << 17 | + MI_SEMAPHORE_COMPARE); + intel_ring_emit(ring, seqno); + intel_ring_emit(ring, 0); + intel_ring_emit(ring, MI_NOOP); + intel_ring_advance(ring); + + return 0; +} + +#define PIPE_CONTROL_FLUSH(ring__, addr__) \ do { \ - OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \ + intel_ring_emit(ring__, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \ PIPE_CONTROL_DEPTH_STALL | 2); \ - OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT); \ - OUT_RING(0); \ - OUT_RING(0); \ + intel_ring_emit(ring__, (addr__) | PIPE_CONTROL_GLOBAL_GTT); \ + intel_ring_emit(ring__, 0); \ + intel_ring_emit(ring__, 0); \ } while (0) -/** - * Creates a new sequence number, emitting a write of it to the status page - * plus an interrupt, which will trigger i915_user_interrupt_handler. - * - * Must be called with struct_lock held. - * - * Returned sequence numbers are nonzero on success. - */ -static u32 -render_ring_add_request(struct drm_device *dev, - struct intel_ring_buffer *ring, - u32 flush_domains) +static int +pc_render_add_request(struct intel_ring_buffer *ring, + u32 *result) { - drm_i915_private_t *dev_priv = dev->dev_private; - u32 seqno; + struct drm_device *dev = ring->dev; + u32 seqno = i915_gem_get_seqno(dev); + struct pipe_control *pc = ring->private; + u32 scratch_addr = pc->gtt_offset + 128; + int ret; - seqno = i915_gem_get_seqno(dev); + /* For Ironlake, MI_USER_INTERRUPT was deprecated and apparently + * incoherent with writes to memory, i.e. completely fubar, + * so we need to use PIPE_NOTIFY instead. + * + * However, we also need to workaround the qword write + * incoherence by flushing the 6 PIPE_NOTIFY buffers out to + * memory before requesting an interrupt. + */ + ret = intel_ring_begin(ring, 32); + if (ret) + return ret; - if (IS_GEN6(dev)) { - BEGIN_LP_RING(6); - OUT_RING(GFX_OP_PIPE_CONTROL | 3); - OUT_RING(PIPE_CONTROL_QW_WRITE | - PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_IS_FLUSH | - PIPE_CONTROL_NOTIFY); - OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT); - OUT_RING(seqno); - OUT_RING(0); - OUT_RING(0); - ADVANCE_LP_RING(); - } else if (HAS_PIPE_CONTROL(dev)) { - u32 scratch_addr = dev_priv->seqno_gfx_addr + 128; + intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | + PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH); + intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); + intel_ring_emit(ring, seqno); + intel_ring_emit(ring, 0); + PIPE_CONTROL_FLUSH(ring, scratch_addr); + scratch_addr += 128; /* write to separate cachelines */ + PIPE_CONTROL_FLUSH(ring, scratch_addr); + scratch_addr += 128; + PIPE_CONTROL_FLUSH(ring, scratch_addr); + scratch_addr += 128; + PIPE_CONTROL_FLUSH(ring, scratch_addr); + scratch_addr += 128; + PIPE_CONTROL_FLUSH(ring, scratch_addr); + scratch_addr += 128; + PIPE_CONTROL_FLUSH(ring, scratch_addr); + intel_ring_emit(ring, GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | + PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH | + PIPE_CONTROL_NOTIFY); + intel_ring_emit(ring, pc->gtt_offset | PIPE_CONTROL_GLOBAL_GTT); + intel_ring_emit(ring, seqno); + intel_ring_emit(ring, 0); + intel_ring_advance(ring); - /* - * Workaround qword write incoherence by flushing the - * PIPE_NOTIFY buffers out to memory before requesting - * an interrupt. - */ - BEGIN_LP_RING(32); - OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | - PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH); - OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT); - OUT_RING(seqno); - OUT_RING(0); - PIPE_CONTROL_FLUSH(scratch_addr); - scratch_addr += 128; /* write to separate cachelines */ - PIPE_CONTROL_FLUSH(scratch_addr); - scratch_addr += 128; - PIPE_CONTROL_FLUSH(scratch_addr); - scratch_addr += 128; - PIPE_CONTROL_FLUSH(scratch_addr); - scratch_addr += 128; - PIPE_CONTROL_FLUSH(scratch_addr); - scratch_addr += 128; - PIPE_CONTROL_FLUSH(scratch_addr); - OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | - PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH | - PIPE_CONTROL_NOTIFY); - OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT); - OUT_RING(seqno); - OUT_RING(0); - ADVANCE_LP_RING(); - } else { - BEGIN_LP_RING(4); - OUT_RING(MI_STORE_DWORD_INDEX); - OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - OUT_RING(seqno); + *result = seqno; + return 0; +} - OUT_RING(MI_USER_INTERRUPT); - ADVANCE_LP_RING(); - } - return seqno; +static int +render_ring_add_request(struct intel_ring_buffer *ring, + u32 *result) +{ + struct drm_device *dev = ring->dev; + u32 seqno = i915_gem_get_seqno(dev); + int ret; + + ret = intel_ring_begin(ring, 4); + if (ret) + return ret; + + intel_ring_emit(ring, MI_STORE_DWORD_INDEX); + intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); + intel_ring_emit(ring, seqno); + intel_ring_emit(ring, MI_USER_INTERRUPT); + intel_ring_advance(ring); + + *result = seqno; + return 0; } static u32 -render_ring_get_seqno(struct drm_device *dev, - struct intel_ring_buffer *ring) +ring_get_seqno(struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - if (HAS_PIPE_CONTROL(dev)) - return ((volatile u32 *)(dev_priv->seqno_page))[0]; - else - return intel_read_status_page(ring, I915_GEM_HWS_INDEX); + return intel_read_status_page(ring, I915_GEM_HWS_INDEX); +} + +static u32 +pc_render_get_seqno(struct intel_ring_buffer *ring) +{ + struct pipe_control *pc = ring->private; + return pc->cpu_page[0]; } static void -render_ring_get_user_irq(struct drm_device *dev, - struct intel_ring_buffer *ring) +ironlake_enable_irq(drm_i915_private_t *dev_priv, u32 mask) +{ + dev_priv->gt_irq_mask &= ~mask; + I915_WRITE(GTIMR, dev_priv->gt_irq_mask); + POSTING_READ(GTIMR); +} + +static void +ironlake_disable_irq(drm_i915_private_t *dev_priv, u32 mask) +{ + dev_priv->gt_irq_mask |= mask; + I915_WRITE(GTIMR, dev_priv->gt_irq_mask); + POSTING_READ(GTIMR); +} + +static void +i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask) +{ + dev_priv->irq_mask &= ~mask; + I915_WRITE(IMR, dev_priv->irq_mask); + POSTING_READ(IMR); +} + +static void +i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask) +{ + dev_priv->irq_mask |= mask; + I915_WRITE(IMR, dev_priv->irq_mask); + POSTING_READ(IMR); +} + +static bool +render_ring_get_irq(struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long irqflags; + struct drm_device *dev = ring->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + + if (!dev->irq_enabled) + return false; - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - if (dev->irq_enabled && (++ring->user_irq_refcount == 1)) { + spin_lock(&ring->irq_lock); + if (ring->irq_refcount++ == 0) { if (HAS_PCH_SPLIT(dev)) - ironlake_enable_graphics_irq(dev_priv, GT_PIPE_NOTIFY); + ironlake_enable_irq(dev_priv, + GT_PIPE_NOTIFY | GT_USER_INTERRUPT); else i915_enable_irq(dev_priv, I915_USER_INTERRUPT); } - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock(&ring->irq_lock); + + return true; } static void -render_ring_put_user_irq(struct drm_device *dev, - struct intel_ring_buffer *ring) +render_ring_put_irq(struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - unsigned long irqflags; + struct drm_device *dev = ring->dev; + drm_i915_private_t *dev_priv = dev->dev_private; - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - BUG_ON(dev->irq_enabled && ring->user_irq_refcount <= 0); - if (dev->irq_enabled && (--ring->user_irq_refcount == 0)) { + spin_lock(&ring->irq_lock); + if (--ring->irq_refcount == 0) { if (HAS_PCH_SPLIT(dev)) - ironlake_disable_graphics_irq(dev_priv, GT_PIPE_NOTIFY); + ironlake_disable_irq(dev_priv, + GT_USER_INTERRUPT | + GT_PIPE_NOTIFY); else i915_disable_irq(dev_priv, I915_USER_INTERRUPT); } - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock(&ring->irq_lock); } -void intel_ring_setup_status_page(struct drm_device *dev, - struct intel_ring_buffer *ring) +void intel_ring_setup_status_page(struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = dev->dev_private; - if (IS_GEN6(dev)) { - I915_WRITE(RING_HWS_PGA_GEN6(ring->mmio_base), - ring->status_page.gfx_addr); - I915_READ(RING_HWS_PGA_GEN6(ring->mmio_base)); /* posting read */ - } else { - I915_WRITE(RING_HWS_PGA(ring->mmio_base), - ring->status_page.gfx_addr); - I915_READ(RING_HWS_PGA(ring->mmio_base)); /* posting read */ - } - + drm_i915_private_t *dev_priv = ring->dev->dev_private; + u32 mmio = IS_GEN6(ring->dev) ? + RING_HWS_PGA_GEN6(ring->mmio_base) : + RING_HWS_PGA(ring->mmio_base); + I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); + POSTING_READ(mmio); } -static void -bsd_ring_flush(struct drm_device *dev, - struct intel_ring_buffer *ring, - u32 invalidate_domains, - u32 flush_domains) +static int +bsd_ring_flush(struct intel_ring_buffer *ring, + u32 invalidate_domains, + u32 flush_domains) { - intel_ring_begin(dev, ring, 2); - intel_ring_emit(dev, ring, MI_FLUSH); - intel_ring_emit(dev, ring, MI_NOOP); - intel_ring_advance(dev, ring); -} + int ret; -static int init_bsd_ring(struct drm_device *dev, - struct intel_ring_buffer *ring) -{ - return init_ring_common(dev, ring); + if ((flush_domains & I915_GEM_DOMAIN_RENDER) == 0) + return 0; + + ret = intel_ring_begin(ring, 2); + if (ret) + return ret; + + intel_ring_emit(ring, MI_FLUSH); + intel_ring_emit(ring, MI_NOOP); + intel_ring_advance(ring); + return 0; } -static u32 -ring_add_request(struct drm_device *dev, - struct intel_ring_buffer *ring, - u32 flush_domains) +static int +ring_add_request(struct intel_ring_buffer *ring, + u32 *result) { u32 seqno; + int ret; - seqno = i915_gem_get_seqno(dev); + ret = intel_ring_begin(ring, 4); + if (ret) + return ret; - intel_ring_begin(dev, ring, 4); - intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX); - intel_ring_emit(dev, ring, - I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - intel_ring_emit(dev, ring, seqno); - intel_ring_emit(dev, ring, MI_USER_INTERRUPT); - intel_ring_advance(dev, ring); + seqno = i915_gem_get_seqno(ring->dev); + + intel_ring_emit(ring, MI_STORE_DWORD_INDEX); + intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); + intel_ring_emit(ring, seqno); + intel_ring_emit(ring, MI_USER_INTERRUPT); + intel_ring_advance(ring); DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno); + *result = seqno; + return 0; +} - return seqno; +static bool +ring_get_irq(struct intel_ring_buffer *ring, u32 flag) +{ + struct drm_device *dev = ring->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + + if (!dev->irq_enabled) + return false; + + spin_lock(&ring->irq_lock); + if (ring->irq_refcount++ == 0) + ironlake_enable_irq(dev_priv, flag); + spin_unlock(&ring->irq_lock); + + return true; } static void -bsd_ring_get_user_irq(struct drm_device *dev, - struct intel_ring_buffer *ring) +ring_put_irq(struct intel_ring_buffer *ring, u32 flag) { - /* do nothing */ + struct drm_device *dev = ring->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + + spin_lock(&ring->irq_lock); + if (--ring->irq_refcount == 0) + ironlake_disable_irq(dev_priv, flag); + spin_unlock(&ring->irq_lock); } + +static bool +gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag) +{ + struct drm_device *dev = ring->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + + if (!dev->irq_enabled) + return false; + + spin_lock(&ring->irq_lock); + if (ring->irq_refcount++ == 0) { + ring->irq_mask &= ~rflag; + I915_WRITE_IMR(ring, ring->irq_mask); + ironlake_enable_irq(dev_priv, gflag); + } + spin_unlock(&ring->irq_lock); + + return true; +} + static void -bsd_ring_put_user_irq(struct drm_device *dev, - struct intel_ring_buffer *ring) +gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag) { - /* do nothing */ + struct drm_device *dev = ring->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + + spin_lock(&ring->irq_lock); + if (--ring->irq_refcount == 0) { + ring->irq_mask |= rflag; + I915_WRITE_IMR(ring, ring->irq_mask); + ironlake_disable_irq(dev_priv, gflag); + } + spin_unlock(&ring->irq_lock); } -static u32 -ring_status_page_get_seqno(struct drm_device *dev, - struct intel_ring_buffer *ring) +static bool +bsd_ring_get_irq(struct intel_ring_buffer *ring) { - return intel_read_status_page(ring, I915_GEM_HWS_INDEX); + return ring_get_irq(ring, GT_BSD_USER_INTERRUPT); +} +static void +bsd_ring_put_irq(struct intel_ring_buffer *ring) +{ + ring_put_irq(ring, GT_BSD_USER_INTERRUPT); } static int -ring_dispatch_gem_execbuffer(struct drm_device *dev, - struct intel_ring_buffer *ring, - struct drm_i915_gem_execbuffer2 *exec, - struct drm_clip_rect *cliprects, - uint64_t exec_offset) -{ - uint32_t exec_start; - exec_start = (uint32_t) exec_offset + exec->batch_start_offset; - intel_ring_begin(dev, ring, 2); - intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START | - (2 << 6) | MI_BATCH_NON_SECURE_I965); - intel_ring_emit(dev, ring, exec_start); - intel_ring_advance(dev, ring); +ring_dispatch_execbuffer(struct intel_ring_buffer *ring, u32 offset, u32 length) +{ + int ret; + + ret = intel_ring_begin(ring, 2); + if (ret) + return ret; + + intel_ring_emit(ring, + MI_BATCH_BUFFER_START | (2 << 6) | + MI_BATCH_NON_SECURE_I965); + intel_ring_emit(ring, offset); + intel_ring_advance(ring); + return 0; } static int -render_ring_dispatch_gem_execbuffer(struct drm_device *dev, - struct intel_ring_buffer *ring, - struct drm_i915_gem_execbuffer2 *exec, - struct drm_clip_rect *cliprects, - uint64_t exec_offset) +render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, + u32 offset, u32 len) { + struct drm_device *dev = ring->dev; drm_i915_private_t *dev_priv = dev->dev_private; - int nbox = exec->num_cliprects; - int i = 0, count; - uint32_t exec_start, exec_len; - exec_start = (uint32_t) exec_offset + exec->batch_start_offset; - exec_len = (uint32_t) exec->batch_len; + int ret; trace_i915_gem_request_submit(dev, dev_priv->next_seqno + 1); - count = nbox ? nbox : 1; + if (IS_I830(dev) || IS_845G(dev)) { + ret = intel_ring_begin(ring, 4); + if (ret) + return ret; - for (i = 0; i < count; i++) { - if (i < nbox) { - int ret = i915_emit_box(dev, cliprects, i, - exec->DR1, exec->DR4); - if (ret) - return ret; - } + intel_ring_emit(ring, MI_BATCH_BUFFER); + intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE); + intel_ring_emit(ring, offset + len - 8); + intel_ring_emit(ring, 0); + } else { + ret = intel_ring_begin(ring, 2); + if (ret) + return ret; - if (IS_I830(dev) || IS_845G(dev)) { - intel_ring_begin(dev, ring, 4); - intel_ring_emit(dev, ring, MI_BATCH_BUFFER); - intel_ring_emit(dev, ring, - exec_start | MI_BATCH_NON_SECURE); - intel_ring_emit(dev, ring, exec_start + exec_len - 4); - intel_ring_emit(dev, ring, 0); + if (INTEL_INFO(dev)->gen >= 4) { + intel_ring_emit(ring, + MI_BATCH_BUFFER_START | (2 << 6) | + MI_BATCH_NON_SECURE_I965); + intel_ring_emit(ring, offset); } else { - intel_ring_begin(dev, ring, 2); - if (INTEL_INFO(dev)->gen >= 4) { - intel_ring_emit(dev, ring, - MI_BATCH_BUFFER_START | (2 << 6) - | MI_BATCH_NON_SECURE_I965); - intel_ring_emit(dev, ring, exec_start); - } else { - intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START - | (2 << 6)); - intel_ring_emit(dev, ring, exec_start | - MI_BATCH_NON_SECURE); - } + intel_ring_emit(ring, + MI_BATCH_BUFFER_START | (2 << 6)); + intel_ring_emit(ring, offset | MI_BATCH_NON_SECURE); } - intel_ring_advance(dev, ring); - } - - if (IS_G4X(dev) || IS_GEN5(dev)) { - intel_ring_begin(dev, ring, 2); - intel_ring_emit(dev, ring, MI_FLUSH | - MI_NO_WRITE_FLUSH | - MI_INVALIDATE_ISP ); - intel_ring_emit(dev, ring, MI_NOOP); - intel_ring_advance(dev, ring); } - /* XXX breadcrumb */ + intel_ring_advance(ring); return 0; } -static void cleanup_status_page(struct drm_device *dev, - struct intel_ring_buffer *ring) +static void cleanup_status_page(struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + drm_i915_private_t *dev_priv = ring->dev->dev_private; + struct drm_i915_gem_object *obj; obj = ring->status_page.obj; if (obj == NULL) return; - obj_priv = to_intel_bo(obj); - kunmap(obj_priv->pages[0]); + kunmap(obj->pages[0]); i915_gem_object_unpin(obj); - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); ring->status_page.obj = NULL; memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); } -static int init_status_page(struct drm_device *dev, - struct intel_ring_buffer *ring) +static int init_status_page(struct intel_ring_buffer *ring) { + struct drm_device *dev = ring->dev; drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_gem_object *obj; - struct drm_i915_gem_object *obj_priv; + struct drm_i915_gem_object *obj; int ret; obj = i915_gem_alloc_object(dev, 4096); @@ -540,16 +774,15 @@ ret = -ENOMEM; goto err; } - obj_priv = to_intel_bo(obj); - obj_priv->agp_type = AGP_USER_CACHED_MEMORY; + obj->agp_type = AGP_USER_CACHED_MEMORY; - ret = i915_gem_object_pin(obj, 4096); + ret = i915_gem_object_pin(obj, 4096, true); if (ret != 0) { goto err_unref; } - ring->status_page.gfx_addr = obj_priv->gtt_offset; - ring->status_page.page_addr = kmap(obj_priv->pages[0]); + ring->status_page.gfx_addr = obj->gtt_offset; + ring->status_page.page_addr = kmap(obj->pages[0]); if (ring->status_page.page_addr == NULL) { memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); goto err_unpin; @@ -557,7 +790,7 @@ ring->status_page.obj = obj; memset(ring->status_page.page_addr, 0, PAGE_SIZE); - intel_ring_setup_status_page(dev, ring); + intel_ring_setup_status_page(ring); DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", ring->name, ring->status_page.gfx_addr); @@ -566,7 +799,7 @@ err_unpin: i915_gem_object_unpin(obj); err_unref: - drm_gem_object_unreference(obj); + drm_gem_object_unreference(&obj->base); err: return ret; } @@ -574,9 +807,7 @@ int intel_init_ring_buffer(struct drm_device *dev, struct intel_ring_buffer *ring) { - struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_i915_gem_object *obj_priv; - struct drm_gem_object *obj; + struct drm_i915_gem_object *obj; int ret; ring->dev = dev; @@ -584,8 +815,11 @@ INIT_LIST_HEAD(&ring->request_list); INIT_LIST_HEAD(&ring->gpu_write_list); + spin_lock_init(&ring->irq_lock); + ring->irq_mask = ~0; + if (I915_NEED_GFX_HWS(dev)) { - ret = init_status_page(dev, ring); + ret = init_status_page(ring); if (ret) return ret; } @@ -597,15 +831,14 @@ goto err_hws; } - ring->gem_object = obj; + ring->obj = obj; - ret = i915_gem_object_pin(obj, PAGE_SIZE); + ret = i915_gem_object_pin(obj, PAGE_SIZE, true); if (ret) goto err_unref; - obj_priv = to_intel_bo(obj); ring->map.size = ring->size; - ring->map.offset = dev->agp->base + obj_priv->gtt_offset; + ring->map.offset = dev->agp->base + obj->gtt_offset; ring->map.type = 0; ring->map.flags = 0; ring->map.mtrr = 0; @@ -618,60 +851,64 @@ } ring->virtual_start = ring->map.handle; - ret = ring->init(dev, ring); + ret = ring->init(ring); if (ret) goto err_unmap; - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - i915_kernel_lost_context(dev); - else { - ring->head = I915_READ_HEAD(ring) & HEAD_ADDR; - ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; - ring->space = ring->head - (ring->tail + 8); - if (ring->space < 0) - ring->space += ring->size; - } - return ret; + /* Workaround an erratum on the i830 which causes a hang if + * the TAIL pointer points to within the last 2 cachelines + * of the buffer. + */ + ring->effective_size = ring->size; + if (IS_I830(ring->dev)) + ring->effective_size -= 128; + + return 0; err_unmap: drm_core_ioremapfree(&ring->map, dev); err_unpin: i915_gem_object_unpin(obj); err_unref: - drm_gem_object_unreference(obj); - ring->gem_object = NULL; + drm_gem_object_unreference(&obj->base); + ring->obj = NULL; err_hws: - cleanup_status_page(dev, ring); + cleanup_status_page(ring); return ret; } -void intel_cleanup_ring_buffer(struct drm_device *dev, - struct intel_ring_buffer *ring) +void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) { - if (ring->gem_object == NULL) + struct drm_i915_private *dev_priv; + int ret; + + if (ring->obj == NULL) return; - drm_core_ioremapfree(&ring->map, dev); + /* Disable the ring buffer. The ring must be idle at this point */ + dev_priv = ring->dev->dev_private; + ret = intel_wait_ring_buffer(ring, ring->size - 8); + I915_WRITE_CTL(ring, 0); + + drm_core_ioremapfree(&ring->map, ring->dev); - i915_gem_object_unpin(ring->gem_object); - drm_gem_object_unreference(ring->gem_object); - ring->gem_object = NULL; + i915_gem_object_unpin(ring->obj); + drm_gem_object_unreference(&ring->obj->base); + ring->obj = NULL; if (ring->cleanup) ring->cleanup(ring); - cleanup_status_page(dev, ring); + cleanup_status_page(ring); } -static int intel_wrap_ring_buffer(struct drm_device *dev, - struct intel_ring_buffer *ring) +static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring) { unsigned int *virt; - int rem; - rem = ring->size - ring->tail; + int rem = ring->size - ring->tail; if (ring->space < rem) { - int ret = intel_wait_ring_buffer(dev, ring, rem); + int ret = intel_wait_ring_buffer(ring, rem); if (ret) return ret; } @@ -689,11 +926,11 @@ return 0; } -int intel_wait_ring_buffer(struct drm_device *dev, - struct intel_ring_buffer *ring, int n) +int intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n) { + struct drm_device *dev = ring->dev; + struct drm_i915_private *dev_priv = dev->dev_private; unsigned long end; - drm_i915_private_t *dev_priv = dev->dev_private; u32 head; trace_i915_ring_wait_begin (dev); @@ -711,7 +948,7 @@ if (ring->space < 0) ring->space += ring->size; if (ring->space >= n) { - trace_i915_ring_wait_end (dev); + trace_i915_ring_wait_end(dev); return 0; } @@ -722,29 +959,39 @@ } msleep(1); + if (atomic_read(&dev_priv->mm.wedged)) + return -EAGAIN; } while (!time_after(jiffies, end)); trace_i915_ring_wait_end (dev); return -EBUSY; } -void intel_ring_begin(struct drm_device *dev, - struct intel_ring_buffer *ring, - int num_dwords) +int intel_ring_begin(struct intel_ring_buffer *ring, + int num_dwords) { int n = 4*num_dwords; - if (unlikely(ring->tail + n > ring->size)) - intel_wrap_ring_buffer(dev, ring); - if (unlikely(ring->space < n)) - intel_wait_ring_buffer(dev, ring, n); + int ret; + + if (unlikely(ring->tail + n > ring->effective_size)) { + ret = intel_wrap_ring_buffer(ring); + if (unlikely(ret)) + return ret; + } + + if (unlikely(ring->space < n)) { + ret = intel_wait_ring_buffer(ring, n); + if (unlikely(ret)) + return ret; + } ring->space -= n; + return 0; } -void intel_ring_advance(struct drm_device *dev, - struct intel_ring_buffer *ring) +void intel_ring_advance(struct intel_ring_buffer *ring) { ring->tail &= ring->size - 1; - ring->write_tail(dev, ring, ring->tail); + ring->write_tail(ring, ring->tail); } static const struct intel_ring_buffer render_ring = { @@ -756,10 +1003,11 @@ .write_tail = ring_write_tail, .flush = render_ring_flush, .add_request = render_ring_add_request, - .get_seqno = render_ring_get_seqno, - .user_irq_get = render_ring_get_user_irq, - .user_irq_put = render_ring_put_user_irq, - .dispatch_gem_execbuffer = render_ring_dispatch_gem_execbuffer, + .get_seqno = ring_get_seqno, + .irq_get = render_ring_get_irq, + .irq_put = render_ring_put_irq, + .dispatch_execbuffer = render_ring_dispatch_execbuffer, + .cleanup = render_ring_cleanup, }; /* ring buffer for bit-stream decoder */ @@ -769,22 +1017,21 @@ .id = RING_BSD, .mmio_base = BSD_RING_BASE, .size = 32 * PAGE_SIZE, - .init = init_bsd_ring, + .init = init_ring_common, .write_tail = ring_write_tail, .flush = bsd_ring_flush, .add_request = ring_add_request, - .get_seqno = ring_status_page_get_seqno, - .user_irq_get = bsd_ring_get_user_irq, - .user_irq_put = bsd_ring_put_user_irq, - .dispatch_gem_execbuffer = ring_dispatch_gem_execbuffer, + .get_seqno = ring_get_seqno, + .irq_get = bsd_ring_get_irq, + .irq_put = bsd_ring_put_irq, + .dispatch_execbuffer = ring_dispatch_execbuffer, }; -static void gen6_bsd_ring_write_tail(struct drm_device *dev, - struct intel_ring_buffer *ring, +static void gen6_bsd_ring_write_tail(struct intel_ring_buffer *ring, u32 value) { - drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_private_t *dev_priv = ring->dev->dev_private; /* Every tail move must follow the sequence below */ I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, @@ -803,69 +1050,109 @@ GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE); } -static void gen6_ring_flush(struct drm_device *dev, - struct intel_ring_buffer *ring, - u32 invalidate_domains, - u32 flush_domains) -{ - intel_ring_begin(dev, ring, 4); - intel_ring_emit(dev, ring, MI_FLUSH_DW); - intel_ring_emit(dev, ring, 0); - intel_ring_emit(dev, ring, 0); - intel_ring_emit(dev, ring, 0); - intel_ring_advance(dev, ring); +static int gen6_ring_flush(struct intel_ring_buffer *ring, + u32 invalidate_domains, + u32 flush_domains) +{ + int ret; + + if ((flush_domains & I915_GEM_DOMAIN_RENDER) == 0) + return 0; + + ret = intel_ring_begin(ring, 4); + if (ret) + return ret; + + intel_ring_emit(ring, MI_FLUSH_DW); + intel_ring_emit(ring, 0); + intel_ring_emit(ring, 0); + intel_ring_emit(ring, 0); + intel_ring_advance(ring); + return 0; } static int -gen6_ring_dispatch_gem_execbuffer(struct drm_device *dev, - struct intel_ring_buffer *ring, - struct drm_i915_gem_execbuffer2 *exec, - struct drm_clip_rect *cliprects, - uint64_t exec_offset) -{ - uint32_t exec_start; - - exec_start = (uint32_t) exec_offset + exec->batch_start_offset; - - intel_ring_begin(dev, ring, 2); - intel_ring_emit(dev, ring, - MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965); +gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring, + u32 offset, u32 len) +{ + int ret; + + ret = intel_ring_begin(ring, 2); + if (ret) + return ret; + + intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965); /* bit0-7 is the length on GEN6+ */ - intel_ring_emit(dev, ring, exec_start); - intel_ring_advance(dev, ring); + intel_ring_emit(ring, offset); + intel_ring_advance(ring); return 0; } +static bool +gen6_render_ring_get_irq(struct intel_ring_buffer *ring) +{ + return gen6_ring_get_irq(ring, + GT_USER_INTERRUPT, + GEN6_RENDER_USER_INTERRUPT); +} + +static void +gen6_render_ring_put_irq(struct intel_ring_buffer *ring) +{ + return gen6_ring_put_irq(ring, + GT_USER_INTERRUPT, + GEN6_RENDER_USER_INTERRUPT); +} + +static bool +gen6_bsd_ring_get_irq(struct intel_ring_buffer *ring) +{ + return gen6_ring_get_irq(ring, + GT_GEN6_BSD_USER_INTERRUPT, + GEN6_BSD_USER_INTERRUPT); +} + +static void +gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring) +{ + return gen6_ring_put_irq(ring, + GT_GEN6_BSD_USER_INTERRUPT, + GEN6_BSD_USER_INTERRUPT); +} + /* ring buffer for Video Codec for Gen6+ */ static const struct intel_ring_buffer gen6_bsd_ring = { - .name = "gen6 bsd ring", - .id = RING_BSD, - .mmio_base = GEN6_BSD_RING_BASE, - .size = 32 * PAGE_SIZE, - .init = init_bsd_ring, - .write_tail = gen6_bsd_ring_write_tail, - .flush = gen6_ring_flush, - .add_request = ring_add_request, - .get_seqno = ring_status_page_get_seqno, - .user_irq_get = bsd_ring_get_user_irq, - .user_irq_put = bsd_ring_put_user_irq, - .dispatch_gem_execbuffer = gen6_ring_dispatch_gem_execbuffer, + .name = "gen6 bsd ring", + .id = RING_BSD, + .mmio_base = GEN6_BSD_RING_BASE, + .size = 32 * PAGE_SIZE, + .init = init_ring_common, + .write_tail = gen6_bsd_ring_write_tail, + .flush = gen6_ring_flush, + .add_request = gen6_add_request, + .get_seqno = ring_get_seqno, + .irq_get = gen6_bsd_ring_get_irq, + .irq_put = gen6_bsd_ring_put_irq, + .dispatch_execbuffer = gen6_ring_dispatch_execbuffer, }; /* Blitter support (SandyBridge+) */ -static void -blt_ring_get_user_irq(struct drm_device *dev, - struct intel_ring_buffer *ring) +static bool +blt_ring_get_irq(struct intel_ring_buffer *ring) { - /* do nothing */ + return gen6_ring_get_irq(ring, + GT_BLT_USER_INTERRUPT, + GEN6_BLITTER_USER_INTERRUPT); } + static void -blt_ring_put_user_irq(struct drm_device *dev, - struct intel_ring_buffer *ring) +blt_ring_put_irq(struct intel_ring_buffer *ring) { - /* do nothing */ + gen6_ring_put_irq(ring, + GT_BLT_USER_INTERRUPT, + GEN6_BLITTER_USER_INTERRUPT); } @@ -883,32 +1170,31 @@ return ring->private; } -static int blt_ring_init(struct drm_device *dev, - struct intel_ring_buffer *ring) +static int blt_ring_init(struct intel_ring_buffer *ring) { - if (NEED_BLT_WORKAROUND(dev)) { + if (NEED_BLT_WORKAROUND(ring->dev)) { struct drm_i915_gem_object *obj; - u32 __iomem *ptr; + u32 *ptr; int ret; - obj = to_intel_bo(i915_gem_alloc_object(dev, 4096)); + obj = i915_gem_alloc_object(ring->dev, 4096); if (obj == NULL) return -ENOMEM; - ret = i915_gem_object_pin(&obj->base, 4096); + ret = i915_gem_object_pin(obj, 4096, true); if (ret) { drm_gem_object_unreference(&obj->base); return ret; } ptr = kmap(obj->pages[0]); - iowrite32(MI_BATCH_BUFFER_END, ptr); - iowrite32(MI_NOOP, ptr+1); + *ptr++ = MI_BATCH_BUFFER_END; + *ptr++ = MI_NOOP; kunmap(obj->pages[0]); - ret = i915_gem_object_set_to_gtt_domain(&obj->base, false); + ret = i915_gem_object_set_to_gtt_domain(obj, false); if (ret) { - i915_gem_object_unpin(&obj->base); + i915_gem_object_unpin(obj); drm_gem_object_unreference(&obj->base); return ret; } @@ -916,51 +1202,44 @@ ring->private = obj; } - return init_ring_common(dev, ring); + return init_ring_common(ring); } -static void blt_ring_begin(struct drm_device *dev, - struct intel_ring_buffer *ring, +static int blt_ring_begin(struct intel_ring_buffer *ring, int num_dwords) { if (ring->private) { - intel_ring_begin(dev, ring, num_dwords+2); - intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START); - intel_ring_emit(dev, ring, to_blt_workaround(ring)->gtt_offset); + int ret = intel_ring_begin(ring, num_dwords+2); + if (ret) + return ret; + + intel_ring_emit(ring, MI_BATCH_BUFFER_START); + intel_ring_emit(ring, to_blt_workaround(ring)->gtt_offset); + + return 0; } else - intel_ring_begin(dev, ring, 4); + return intel_ring_begin(ring, 4); } -static void blt_ring_flush(struct drm_device *dev, - struct intel_ring_buffer *ring, +static int blt_ring_flush(struct intel_ring_buffer *ring, u32 invalidate_domains, u32 flush_domains) { - blt_ring_begin(dev, ring, 4); - intel_ring_emit(dev, ring, MI_FLUSH_DW); - intel_ring_emit(dev, ring, 0); - intel_ring_emit(dev, ring, 0); - intel_ring_emit(dev, ring, 0); - intel_ring_advance(dev, ring); -} + int ret; -static u32 -blt_ring_add_request(struct drm_device *dev, - struct intel_ring_buffer *ring, - u32 flush_domains) -{ - u32 seqno = i915_gem_get_seqno(dev); + if ((flush_domains & I915_GEM_DOMAIN_RENDER) == 0) + return 0; - blt_ring_begin(dev, ring, 4); - intel_ring_emit(dev, ring, MI_STORE_DWORD_INDEX); - intel_ring_emit(dev, ring, - I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT); - intel_ring_emit(dev, ring, seqno); - intel_ring_emit(dev, ring, MI_USER_INTERRUPT); - intel_ring_advance(dev, ring); + ret = blt_ring_begin(ring, 4); + if (ret) + return ret; - DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno); - return seqno; + intel_ring_emit(ring, MI_FLUSH_DW); + intel_ring_emit(ring, 0); + intel_ring_emit(ring, 0); + intel_ring_emit(ring, 0); + intel_ring_advance(ring); + return 0; } static void blt_ring_cleanup(struct intel_ring_buffer *ring) @@ -981,47 +1260,56 @@ .init = blt_ring_init, .write_tail = ring_write_tail, .flush = blt_ring_flush, - .add_request = blt_ring_add_request, - .get_seqno = ring_status_page_get_seqno, - .user_irq_get = blt_ring_get_user_irq, - .user_irq_put = blt_ring_put_user_irq, - .dispatch_gem_execbuffer = gen6_ring_dispatch_gem_execbuffer, + .add_request = gen6_add_request, + .get_seqno = ring_get_seqno, + .irq_get = blt_ring_get_irq, + .irq_put = blt_ring_put_irq, + .dispatch_execbuffer = gen6_ring_dispatch_execbuffer, .cleanup = blt_ring_cleanup, }; int intel_init_render_ring_buffer(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring = &dev_priv->ring[RCS]; - dev_priv->render_ring = render_ring; + *ring = render_ring; + if (INTEL_INFO(dev)->gen >= 6) { + ring->add_request = gen6_add_request; + ring->irq_get = gen6_render_ring_get_irq; + ring->irq_put = gen6_render_ring_put_irq; + } else if (IS_GEN5(dev)) { + ring->add_request = pc_render_add_request; + ring->get_seqno = pc_render_get_seqno; + } if (!I915_NEED_GFX_HWS(dev)) { - dev_priv->render_ring.status_page.page_addr - = dev_priv->status_page_dmah->vaddr; - memset(dev_priv->render_ring.status_page.page_addr, - 0, PAGE_SIZE); + ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr; + memset(ring->status_page.page_addr, 0, PAGE_SIZE); } - return intel_init_ring_buffer(dev, &dev_priv->render_ring); + return intel_init_ring_buffer(dev, ring); } int intel_init_bsd_ring_buffer(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring = &dev_priv->ring[VCS]; if (IS_GEN6(dev)) - dev_priv->bsd_ring = gen6_bsd_ring; + *ring = gen6_bsd_ring; else - dev_priv->bsd_ring = bsd_ring; + *ring = bsd_ring; - return intel_init_ring_buffer(dev, &dev_priv->bsd_ring); + return intel_init_ring_buffer(dev, ring); } int intel_init_blt_ring_buffer(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; - dev_priv->blt_ring = gen6_blt_ring; + *ring = gen6_blt_ring; - return intel_init_ring_buffer(dev, &dev_priv->blt_ring); + return intel_init_ring_buffer(dev, ring); } --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_ringbuffer.h +++ linux-2.6.37/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -1,22 +1,40 @@ #ifndef _INTEL_RINGBUFFER_H_ #define _INTEL_RINGBUFFER_H_ +enum { + RCS = 0x0, + VCS, + BCS, + I915_NUM_RINGS, +}; + struct intel_hw_status_page { - void *page_addr; + u32 __iomem *page_addr; unsigned int gfx_addr; - struct drm_gem_object *obj; + struct drm_i915_gem_object *obj; }; -#define I915_READ_TAIL(ring) I915_READ(RING_TAIL(ring->mmio_base)) -#define I915_WRITE_TAIL(ring, val) I915_WRITE(RING_TAIL(ring->mmio_base), val) -#define I915_READ_START(ring) I915_READ(RING_START(ring->mmio_base)) -#define I915_WRITE_START(ring, val) I915_WRITE(RING_START(ring->mmio_base), val) -#define I915_READ_HEAD(ring) I915_READ(RING_HEAD(ring->mmio_base)) -#define I915_WRITE_HEAD(ring, val) I915_WRITE(RING_HEAD(ring->mmio_base), val) -#define I915_READ_CTL(ring) I915_READ(RING_CTL(ring->mmio_base)) -#define I915_WRITE_CTL(ring, val) I915_WRITE(RING_CTL(ring->mmio_base), val) +#define I915_RING_READ(reg) i915_safe_read(dev_priv, reg) + +#define I915_READ_TAIL(ring) I915_RING_READ(RING_TAIL((ring)->mmio_base)) +#define I915_WRITE_TAIL(ring, val) I915_WRITE(RING_TAIL((ring)->mmio_base), val) + +#define I915_READ_START(ring) I915_RING_READ(RING_START((ring)->mmio_base)) +#define I915_WRITE_START(ring, val) I915_WRITE(RING_START((ring)->mmio_base), val) + +#define I915_READ_HEAD(ring) I915_RING_READ(RING_HEAD((ring)->mmio_base)) +#define I915_WRITE_HEAD(ring, val) I915_WRITE(RING_HEAD((ring)->mmio_base), val) + +#define I915_READ_CTL(ring) I915_RING_READ(RING_CTL((ring)->mmio_base)) +#define I915_WRITE_CTL(ring, val) I915_WRITE(RING_CTL((ring)->mmio_base), val) + +#define I915_WRITE_IMR(ring, val) I915_WRITE(RING_IMR((ring)->mmio_base), val) +#define I915_READ_IMR(ring) I915_RING_READ(RING_IMR((ring)->mmio_base)) + +#define I915_READ_NOPID(ring) I915_RING_READ(RING_NOPID((ring)->mmio_base)) +#define I915_READ_SYNC_0(ring) I915_RING_READ(RING_SYNC_0((ring)->mmio_base)) +#define I915_READ_SYNC_1(ring) I915_RING_READ(RING_SYNC_1((ring)->mmio_base)) -struct drm_i915_gem_execbuffer2; struct intel_ring_buffer { const char *name; enum intel_ring_id { @@ -25,45 +43,39 @@ RING_BLT = 0x4, } id; u32 mmio_base; - unsigned long size; void *virtual_start; struct drm_device *dev; - struct drm_gem_object *gem_object; + struct drm_i915_gem_object *obj; u32 actual_head; u32 head; u32 tail; int space; + int size; + int effective_size; struct intel_hw_status_page status_page; - u32 irq_gem_seqno; /* last seq seem at irq time */ - u32 waiting_gem_seqno; - int user_irq_refcount; - void (*user_irq_get)(struct drm_device *dev, - struct intel_ring_buffer *ring); - void (*user_irq_put)(struct drm_device *dev, - struct intel_ring_buffer *ring); + spinlock_t irq_lock; + u32 irq_refcount; + u32 irq_mask; + u32 irq_seqno; /* last seq seem at irq time */ + u32 waiting_seqno; + u32 sync_seqno[I915_NUM_RINGS-1]; + bool __must_check (*irq_get)(struct intel_ring_buffer *ring); + void (*irq_put)(struct intel_ring_buffer *ring); - int (*init)(struct drm_device *dev, - struct intel_ring_buffer *ring); + int (*init)(struct intel_ring_buffer *ring); - void (*write_tail)(struct drm_device *dev, - struct intel_ring_buffer *ring, + void (*write_tail)(struct intel_ring_buffer *ring, u32 value); - void (*flush)(struct drm_device *dev, - struct intel_ring_buffer *ring, - u32 invalidate_domains, - u32 flush_domains); - u32 (*add_request)(struct drm_device *dev, - struct intel_ring_buffer *ring, - u32 flush_domains); - u32 (*get_seqno)(struct drm_device *dev, - struct intel_ring_buffer *ring); - int (*dispatch_gem_execbuffer)(struct drm_device *dev, - struct intel_ring_buffer *ring, - struct drm_i915_gem_execbuffer2 *exec, - struct drm_clip_rect *cliprects, - uint64_t exec_offset); + int __must_check (*flush)(struct intel_ring_buffer *ring, + u32 invalidate_domains, + u32 flush_domains); + int (*add_request)(struct intel_ring_buffer *ring, + u32 *seqno); + u32 (*get_seqno)(struct intel_ring_buffer *ring); + int (*dispatch_execbuffer)(struct intel_ring_buffer *ring, + u32 offset, u32 length); void (*cleanup)(struct intel_ring_buffer *ring); /** @@ -96,7 +108,7 @@ /** * Do we have some not yet emitted requests outstanding? */ - bool outstanding_lazy_request; + u32 outstanding_lazy_request; wait_queue_head_t irq_queue; drm_local_map_t map; @@ -105,44 +117,54 @@ }; static inline u32 +intel_ring_sync_index(struct intel_ring_buffer *ring, + struct intel_ring_buffer *other) +{ + int idx; + + /* + * cs -> 0 = vcs, 1 = bcs + * vcs -> 0 = bcs, 1 = cs, + * bcs -> 0 = cs, 1 = vcs. + */ + + idx = (other - ring) - 1; + if (idx < 0) + idx += I915_NUM_RINGS; + + return idx; +} + +static inline u32 intel_read_status_page(struct intel_ring_buffer *ring, - int reg) + int reg) { - u32 *regs = ring->status_page.page_addr; - return regs[reg]; + return ioread32(ring->status_page.page_addr + reg); } -int intel_init_ring_buffer(struct drm_device *dev, - struct intel_ring_buffer *ring); -void intel_cleanup_ring_buffer(struct drm_device *dev, - struct intel_ring_buffer *ring); -int intel_wait_ring_buffer(struct drm_device *dev, - struct intel_ring_buffer *ring, int n); -void intel_ring_begin(struct drm_device *dev, - struct intel_ring_buffer *ring, int n); - -static inline void intel_ring_emit(struct drm_device *dev, - struct intel_ring_buffer *ring, - unsigned int data) +void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring); +int __must_check intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n); +int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n); + +static inline void intel_ring_emit(struct intel_ring_buffer *ring, + u32 data) { - unsigned int *virt = ring->virtual_start + ring->tail; - *virt = data; + iowrite32(data, ring->virtual_start + ring->tail); ring->tail += 4; } -void intel_ring_advance(struct drm_device *dev, - struct intel_ring_buffer *ring); +void intel_ring_advance(struct intel_ring_buffer *ring); -u32 intel_ring_get_seqno(struct drm_device *dev, - struct intel_ring_buffer *ring); +u32 intel_ring_get_seqno(struct intel_ring_buffer *ring); +int intel_ring_sync(struct intel_ring_buffer *ring, + struct intel_ring_buffer *to, + u32 seqno); int intel_init_render_ring_buffer(struct drm_device *dev); int intel_init_bsd_ring_buffer(struct drm_device *dev); int intel_init_blt_ring_buffer(struct drm_device *dev); -u32 intel_ring_get_active_head(struct drm_device *dev, - struct intel_ring_buffer *ring); -void intel_ring_setup_status_page(struct drm_device *dev, - struct intel_ring_buffer *ring); +u32 intel_ring_get_active_head(struct intel_ring_buffer *ring); +void intel_ring_setup_status_page(struct intel_ring_buffer *ring); #endif /* _INTEL_RINGBUFFER_H_ */ --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_sdvo.c +++ linux-2.6.37/drivers/gpu/drm/i915/intel_sdvo.c @@ -1045,7 +1045,9 @@ /* Set the SDVO control regs. */ if (INTEL_INFO(dev)->gen >= 4) { - sdvox = SDVO_BORDER_ENABLE; + sdvox = 0; + if (INTEL_INFO(dev)->gen < 5) + sdvox |= SDVO_BORDER_ENABLE; if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) sdvox |= SDVO_VSYNC_ACTIVE_HIGH; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) @@ -1075,7 +1077,8 @@ sdvox |= (pixel_multiplier - 1) << SDVO_PORT_MULTIPLY_SHIFT; } - if (input_dtd.part2.sdvo_flags & SDVO_NEED_TO_STALL) + if (input_dtd.part2.sdvo_flags & SDVO_NEED_TO_STALL && + INTEL_INFO(dev)->gen < 5) sdvox |= SDVO_STALL_SELECT; intel_sdvo_write_sdvox(intel_sdvo, sdvox); } --- linux-2.6.37.orig/drivers/gpu/drm/i915/intel_tv.c +++ linux-2.6.37/drivers/gpu/drm/i915/intel_tv.c @@ -1245,10 +1245,11 @@ int type; /* Disable TV interrupts around load detect or we'll recurse */ - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - i915_disable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE | + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + i915_disable_pipestat(dev_priv, 0, + PIPE_HOTPLUG_INTERRUPT_ENABLE | PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); save_tv_dac = tv_dac = I915_READ(TV_DAC); save_tv_ctl = tv_ctl = I915_READ(TV_CTL); @@ -1301,10 +1302,11 @@ I915_WRITE(TV_CTL, save_tv_ctl); /* Restore interrupt config */ - spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); - i915_enable_pipestat(dev_priv, 0, PIPE_HOTPLUG_INTERRUPT_ENABLE | + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + i915_enable_pipestat(dev_priv, 0, + PIPE_HOTPLUG_INTERRUPT_ENABLE | PIPE_HOTPLUG_TV_INTERRUPT_ENABLE); - spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return type; } --- linux-2.6.37.orig/drivers/gpu/drm/radeon/Makefile +++ linux-2.6.37/drivers/gpu/drm/radeon/Makefile @@ -65,10 +65,13 @@ rs400.o rs600.o rs690.o rv515.o r520.o r600.o rv770.o radeon_test.o \ r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \ r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \ - evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o + evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \ + radeon_trace_points.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o radeon-$(CONFIG_ACPI) += radeon_acpi.o obj-$(CONFIG_DRM_RADEON)+= radeon.o + +CFLAGS_radeon_trace_points.o := -I$(src) \ No newline at end of file --- linux-2.6.37.orig/drivers/gpu/drm/radeon/ObjectID.h +++ linux-2.6.37/drivers/gpu/drm/radeon/ObjectID.h @@ -37,6 +37,8 @@ #define GRAPH_OBJECT_TYPE_CONNECTOR 0x3 #define GRAPH_OBJECT_TYPE_ROUTER 0x4 /* deleted */ +#define GRAPH_OBJECT_TYPE_DISPLAY_PATH 0x6 +#define GRAPH_OBJECT_TYPE_GENERIC 0x7 /****************************************************/ /* Encoder Object ID Definition */ @@ -64,6 +66,9 @@ #define ENCODER_OBJECT_ID_VT1623 0x10 #define ENCODER_OBJECT_ID_HDMI_SI1930 0x11 #define ENCODER_OBJECT_ID_HDMI_INTERNAL 0x12 +#define ENCODER_OBJECT_ID_ALMOND 0x22 +#define ENCODER_OBJECT_ID_TRAVIS 0x23 +#define ENCODER_OBJECT_ID_NUTMEG 0x22 /* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */ #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 0x13 #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 0x14 @@ -108,6 +113,7 @@ #define CONNECTOR_OBJECT_ID_DISPLAYPORT 0x13 #define CONNECTOR_OBJECT_ID_eDP 0x14 #define CONNECTOR_OBJECT_ID_MXM 0x15 +#define CONNECTOR_OBJECT_ID_LVDS_eDP 0x16 /* deleted */ @@ -124,6 +130,7 @@ #define GENERIC_OBJECT_ID_GLSYNC 0x01 #define GENERIC_OBJECT_ID_PX2_NON_DRIVABLE 0x02 #define GENERIC_OBJECT_ID_MXM_OPM 0x03 +#define GENERIC_OBJECT_ID_STEREO_PIN 0x04 //This object could show up from Misc Object table, it follows ATOM_OBJECT format, and contains one ATOM_OBJECT_GPIO_CNTL_RECORD for the stereo pin /****************************************************/ /* Graphics Object ENUM ID Definition */ @@ -360,6 +367,26 @@ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT) +#define ENCODER_ALMOND_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_ALMOND << OBJECT_ID_SHIFT) + +#define ENCODER_ALMOND_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_ALMOND << OBJECT_ID_SHIFT) + +#define ENCODER_TRAVIS_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_TRAVIS << OBJECT_ID_SHIFT) + +#define ENCODER_TRAVIS_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_TRAVIS << OBJECT_ID_SHIFT) + +#define ENCODER_NUTMEG_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + ENCODER_OBJECT_ID_NUTMEG << OBJECT_ID_SHIFT) + /****************************************************/ /* Connector Object ID definition - Shared with BIOS */ /****************************************************/ @@ -421,6 +448,14 @@ GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) +#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID3 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) + +#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID4 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) + #define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) @@ -512,6 +547,7 @@ #define CONNECTOR_7PIN_DIN_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT) + #define CONNECTOR_7PIN_DIN_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT) @@ -593,6 +629,14 @@ GRAPH_OBJECT_ENUM_ID7 << ENUM_ID_SHIFT |\ CONNECTOR_OBJECT_ID_MXM << OBJECT_ID_SHIFT) //Mapping to MXM_DAC +#define CONNECTOR_LVDS_eDP_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_LVDS_eDP << OBJECT_ID_SHIFT) + +#define CONNECTOR_LVDS_eDP_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ + CONNECTOR_OBJECT_ID_LVDS_eDP << OBJECT_ID_SHIFT) + /****************************************************/ /* Router Object ID definition - Shared with BIOS */ /****************************************************/ @@ -621,6 +665,10 @@ GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ GENERIC_OBJECT_ID_MXM_OPM << OBJECT_ID_SHIFT) +#define GENERICOBJECT_STEREO_PIN_ENUM_ID1 (GRAPH_OBJECT_TYPE_GENERIC << OBJECT_TYPE_SHIFT |\ + GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ + GENERIC_OBJECT_ID_STEREO_PIN << OBJECT_ID_SHIFT) + /****************************************************/ /* Object Cap definition - Shared with BIOS */ /****************************************************/ --- linux-2.6.37.orig/drivers/gpu/drm/radeon/atombios.h +++ linux-2.6.37/drivers/gpu/drm/radeon/atombios.h @@ -73,8 +73,18 @@ #define ATOM_PPLL1 0 #define ATOM_PPLL2 1 #define ATOM_DCPLL 2 +#define ATOM_PPLL0 2 +#define ATOM_EXT_PLL1 8 +#define ATOM_EXT_PLL2 9 +#define ATOM_EXT_CLOCK 10 #define ATOM_PPLL_INVALID 0xFF +#define ENCODER_REFCLK_SRC_P1PLL 0 +#define ENCODER_REFCLK_SRC_P2PLL 1 +#define ENCODER_REFCLK_SRC_DCPLL 2 +#define ENCODER_REFCLK_SRC_EXTCLK 3 +#define ENCODER_REFCLK_SRC_INVALID 0xFF + #define ATOM_SCALER1 0 #define ATOM_SCALER2 1 @@ -192,6 +202,9 @@ /*Image can't be updated, while Driver needs to carry the new table! */ }ATOM_COMMON_TABLE_HEADER; +/****************************************************************************/ +// Structure stores the ROM header. +/****************************************************************************/ typedef struct _ATOM_ROM_HEADER { ATOM_COMMON_TABLE_HEADER sHeader; @@ -221,6 +234,9 @@ #define USHORT void* #endif +/****************************************************************************/ +// Structures used in Command.mtb +/****************************************************************************/ typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES{ USHORT ASIC_Init; //Function Table, used by various SW components,latest version 1.1 USHORT GetDisplaySurfaceSize; //Atomic Table, Used by Bios when enabling HW ICON @@ -312,6 +328,7 @@ #define SetUniphyInstance ASIC_StaticPwrMgtStatusChange #define HPDInterruptService ReadHWAssistedI2CStatus #define EnableVGA_Access GetSCLKOverMCLKRatio +#define GetDispObjectInfo EnableYUV typedef struct _ATOM_MASTER_COMMAND_TABLE { @@ -357,6 +374,24 @@ /****************************************************************************/ #define COMPUTE_MEMORY_PLL_PARAM 1 #define COMPUTE_ENGINE_PLL_PARAM 2 +#define ADJUST_MC_SETTING_PARAM 3 + +/****************************************************************************/ +// Structures used by AdjustMemoryControllerTable +/****************************************************************************/ +typedef struct _ATOM_ADJUST_MEMORY_CLOCK_FREQ +{ +#if ATOM_BIG_ENDIAN + ULONG ulPointerReturnFlag:1; // BYTE_3[7]=1 - Return the pointer to the right Data Block; BYTE_3[7]=0 - Program the right Data Block + ULONG ulMemoryModuleNumber:7; // BYTE_3[6:0] + ULONG ulClockFreq:24; +#else + ULONG ulClockFreq:24; + ULONG ulMemoryModuleNumber:7; // BYTE_3[6:0] + ULONG ulPointerReturnFlag:1; // BYTE_3[7]=1 - Return the pointer to the right Data Block; BYTE_3[7]=0 - Program the right Data Block +#endif +}ATOM_ADJUST_MEMORY_CLOCK_FREQ; +#define POINTER_RETURN_FLAG 0x80 typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS { @@ -440,6 +475,26 @@ #endif }COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4; +typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 +{ + union + { + ATOM_COMPUTE_CLOCK_FREQ ulClock; //Input Parameter + ATOM_S_MPLL_FB_DIVIDER ulFbDiv; //Output Parameter + }; + UCHAR ucRefDiv; //Output Parameter + UCHAR ucPostDiv; //Output Parameter + union + { + UCHAR ucCntlFlag; //Output Flags + UCHAR ucInputFlag; //Input Flags. ucInputFlag[0] - Strobe(1)/Performance(0) mode + }; + UCHAR ucReserved; +}COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5; + +// ucInputFlag +#define ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN 1 // 1-StrobeMode, 0-PerformanceMode + typedef struct _DYNAMICE_MEMORY_SETTINGS_PARAMETER { ATOM_COMPUTE_CLOCK_FREQ ulClock; @@ -583,6 +638,7 @@ #define ATOM_ENCODER_CONFIG_DPLINKRATE_MASK 0x01 #define ATOM_ENCODER_CONFIG_DPLINKRATE_1_62GHZ 0x00 #define ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ 0x01 +#define ATOM_ENCODER_CONFIG_DPLINKRATE_5_40GHZ 0x02 #define ATOM_ENCODER_CONFIG_LINK_SEL_MASK 0x04 #define ATOM_ENCODER_CONFIG_LINKA 0x00 #define ATOM_ENCODER_CONFIG_LINKB 0x04 @@ -608,6 +664,9 @@ #define ATOM_ENCODER_MODE_TV 13 #define ATOM_ENCODER_MODE_CV 14 #define ATOM_ENCODER_MODE_CRT 15 +#define ATOM_ENCODER_MODE_DVO 16 +#define ATOM_ENCODER_MODE_DP_SST ATOM_ENCODER_MODE_DP // For DP1.2 +#define ATOM_ENCODER_MODE_DP_MST 5 // For DP1.2 typedef struct _ATOM_DIG_ENCODER_CONFIG_V2 { @@ -661,6 +720,7 @@ #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_START 0x08 #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN1 0x09 #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN2 0x0a +#define ATOM_ENCODER_CMD_DP_LINK_TRAINING_PATTERN3 0x13 #define ATOM_ENCODER_CMD_DP_LINK_TRAINING_COMPLETE 0x0b #define ATOM_ENCODER_CMD_DP_VIDEO_OFF 0x0c #define ATOM_ENCODER_CMD_DP_VIDEO_ON 0x0d @@ -671,24 +731,34 @@ #define ATOM_ENCODER_STATUS_LINK_TRAINING_COMPLETE 0x10 #define ATOM_ENCODER_STATUS_LINK_TRAINING_INCOMPLETE 0x00 +//ucTableFormatRevision=1 +//ucTableContentRevision=3 // Following function ENABLE sub-function will be used by driver when TMDS/HDMI/LVDS is used, disable function will be used by driver typedef struct _ATOM_DIG_ENCODER_CONFIG_V3 { #if ATOM_BIG_ENDIAN UCHAR ucReserved1:1; - UCHAR ucDigSel:3; // =0: DIGA/B/C/D/E/F + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) UCHAR ucReserved:3; UCHAR ucDPLinkRate:1; // =0: 1.62Ghz, =1: 2.7Ghz #else UCHAR ucDPLinkRate:1; // =0: 1.62Ghz, =1: 2.7Ghz UCHAR ucReserved:3; - UCHAR ucDigSel:3; // =0: DIGA/B/C/D/E/F + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) UCHAR ucReserved1:1; #endif }ATOM_DIG_ENCODER_CONFIG_V3; +#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_MASK 0x03 +#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ 0x00 +#define ATOM_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ 0x01 #define ATOM_ENCODER_CONFIG_V3_ENCODER_SEL 0x70 - +#define ATOM_ENCODER_CONFIG_V3_DIG0_ENCODER 0x00 +#define ATOM_ENCODER_CONFIG_V3_DIG1_ENCODER 0x10 +#define ATOM_ENCODER_CONFIG_V3_DIG2_ENCODER 0x20 +#define ATOM_ENCODER_CONFIG_V3_DIG3_ENCODER 0x30 +#define ATOM_ENCODER_CONFIG_V3_DIG4_ENCODER 0x40 +#define ATOM_ENCODER_CONFIG_V3_DIG5_ENCODER 0x50 typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V3 { @@ -707,6 +777,56 @@ UCHAR ucReserved; }DIG_ENCODER_CONTROL_PARAMETERS_V3; +//ucTableFormatRevision=1 +//ucTableContentRevision=4 +// start from NI +// Following function ENABLE sub-function will be used by driver when TMDS/HDMI/LVDS is used, disable function will be used by driver +typedef struct _ATOM_DIG_ENCODER_CONFIG_V4 +{ +#if ATOM_BIG_ENDIAN + UCHAR ucReserved1:1; + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) + UCHAR ucReserved:2; + UCHAR ucDPLinkRate:2; // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz <= Changed comparing to previous version +#else + UCHAR ucDPLinkRate:2; // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz <= Changed comparing to previous version + UCHAR ucReserved:2; + UCHAR ucDigSel:3; // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F) + UCHAR ucReserved1:1; +#endif +}ATOM_DIG_ENCODER_CONFIG_V4; + +#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_MASK 0x03 +#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_1_62GHZ 0x00 +#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_2_70GHZ 0x01 +#define ATOM_ENCODER_CONFIG_V4_DPLINKRATE_5_40GHZ 0x02 +#define ATOM_ENCODER_CONFIG_V4_ENCODER_SEL 0x70 +#define ATOM_ENCODER_CONFIG_V4_DIG0_ENCODER 0x00 +#define ATOM_ENCODER_CONFIG_V4_DIG1_ENCODER 0x10 +#define ATOM_ENCODER_CONFIG_V4_DIG2_ENCODER 0x20 +#define ATOM_ENCODER_CONFIG_V4_DIG3_ENCODER 0x30 +#define ATOM_ENCODER_CONFIG_V4_DIG4_ENCODER 0x40 +#define ATOM_ENCODER_CONFIG_V4_DIG5_ENCODER 0x50 + +typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V4 +{ + USHORT usPixelClock; // in 10KHz; for bios convenient + union{ + ATOM_DIG_ENCODER_CONFIG_V4 acConfig; + UCHAR ucConfig; + }; + UCHAR ucAction; + UCHAR ucEncoderMode; + // =0: DP encoder + // =1: LVDS encoder + // =2: DVI encoder + // =3: HDMI encoder + // =4: SDVO encoder + // =5: DP audio + UCHAR ucLaneNum; // how many lanes to enable + UCHAR ucBitPerColor; // only valid for DP mode when ucAction = ATOM_ENCODER_CMD_SETUP + UCHAR ucHPD_ID; // HPD ID (1-6). =0 means to skip HDP programming. New comparing to previous version +}DIG_ENCODER_CONTROL_PARAMETERS_V4; // define ucBitPerColor: #define PANEL_BPC_UNDEFINE 0x00 @@ -893,6 +1013,7 @@ #endif }ATOM_DIG_TRANSMITTER_CONFIG_V3; + typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V3 { union @@ -936,6 +1057,149 @@ #define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER2 0x40 //CD #define ATOM_TRANSMITTER_CONFIG_V3_TRANSMITTER3 0x80 //EF + +/****************************************************************************/ +// Structures used by UNIPHYTransmitterControlTable V1.4 +// ASIC Families: NI +// ucTableFormatRevision=1 +// ucTableContentRevision=4 +/****************************************************************************/ +typedef struct _ATOM_DP_VS_MODE_V4 +{ + UCHAR ucLaneSel; + union + { + UCHAR ucLaneSet; + struct { +#if ATOM_BIG_ENDIAN + UCHAR ucPOST_CURSOR2:2; //Bit[7:6] Post Cursor2 Level <= New in V4 + UCHAR ucPRE_EMPHASIS:3; //Bit[5:3] Pre-emphasis Level + UCHAR ucVOLTAGE_SWING:3; //Bit[2:0] Voltage Swing Level +#else + UCHAR ucVOLTAGE_SWING:3; //Bit[2:0] Voltage Swing Level + UCHAR ucPRE_EMPHASIS:3; //Bit[5:3] Pre-emphasis Level + UCHAR ucPOST_CURSOR2:2; //Bit[7:6] Post Cursor2 Level <= New in V4 +#endif + }; + }; +}ATOM_DP_VS_MODE_V4; + +typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V4 +{ +#if ATOM_BIG_ENDIAN + UCHAR ucTransmitterSel:2; //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) + // =1 Dig Transmitter 2 ( Uniphy CD ) + // =2 Dig Transmitter 3 ( Uniphy EF ) + UCHAR ucRefClkSource:2; //bit5:4: PPLL1 =0, PPLL2=1, DCPLL=2, EXT_CLK=3 <= New + UCHAR ucEncoderSel:1; //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F + UCHAR ucLinkSel:1; //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E + // =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F + UCHAR fCoherentMode:1; //bit1=1: Coherent Mode ( for DVI/HDMI mode ) + UCHAR fDualLinkConnector:1; //bit0=1: Dual Link DVI connector +#else + UCHAR fDualLinkConnector:1; //bit0=1: Dual Link DVI connector + UCHAR fCoherentMode:1; //bit1=1: Coherent Mode ( for DVI/HDMI mode ) + UCHAR ucLinkSel:1; //bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E + // =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F + UCHAR ucEncoderSel:1; //bit3=0: Data/Clk path source from DIGA/C/E. =1: Data/clk path source from DIGB/D/F + UCHAR ucRefClkSource:2; //bit5:4: PPLL1 =0, PPLL2=1, DCPLL=2, EXT_CLK=3 <= New + UCHAR ucTransmitterSel:2; //bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) + // =1 Dig Transmitter 2 ( Uniphy CD ) + // =2 Dig Transmitter 3 ( Uniphy EF ) +#endif +}ATOM_DIG_TRANSMITTER_CONFIG_V4; + +typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V4 +{ + union + { + USHORT usPixelClock; // in 10KHz; for bios convenient + USHORT usInitInfo; // when init uniphy,lower 8bit is used for connector type defined in objectid.h + ATOM_DP_VS_MODE_V4 asMode; // DP Voltage swing mode Redefined comparing to previous version + }; + union + { + ATOM_DIG_TRANSMITTER_CONFIG_V4 acConfig; + UCHAR ucConfig; + }; + UCHAR ucAction; // define as ATOM_TRANSMITER_ACTION_XXX + UCHAR ucLaneNum; + UCHAR ucReserved[3]; +}DIG_TRANSMITTER_CONTROL_PARAMETERS_V4; + +//ucConfig +//Bit0 +#define ATOM_TRANSMITTER_CONFIG_V4_DUAL_LINK_CONNECTOR 0x01 +//Bit1 +#define ATOM_TRANSMITTER_CONFIG_V4_COHERENT 0x02 +//Bit2 +#define ATOM_TRANSMITTER_CONFIG_V4_LINK_SEL_MASK 0x04 +#define ATOM_TRANSMITTER_CONFIG_V4_LINKA 0x00 +#define ATOM_TRANSMITTER_CONFIG_V4_LINKB 0x04 +// Bit3 +#define ATOM_TRANSMITTER_CONFIG_V4_ENCODER_SEL_MASK 0x08 +#define ATOM_TRANSMITTER_CONFIG_V4_DIG1_ENCODER 0x00 +#define ATOM_TRANSMITTER_CONFIG_V4_DIG2_ENCODER 0x08 +// Bit5:4 +#define ATOM_TRANSMITTER_CONFIG_V4_REFCLK_SEL_MASK 0x30 +#define ATOM_TRANSMITTER_CONFIG_V4_P1PLL 0x00 +#define ATOM_TRANSMITTER_CONFIG_V4_P2PLL 0x10 +#define ATOM_TRANSMITTER_CONFIG_V4_DCPLL 0x20 // New in _V4 +#define ATOM_TRANSMITTER_CONFIG_V4_REFCLK_SRC_EXT 0x30 // Changed comparing to V3 +// Bit7:6 +#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER_SEL_MASK 0xC0 +#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER1 0x00 //AB +#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER2 0x40 //CD +#define ATOM_TRANSMITTER_CONFIG_V4_TRANSMITTER3 0x80 //EF + + +/****************************************************************************/ +// Structures used by ExternalEncoderControlTable V1.3 +// ASIC Families: Evergreen, Llano, NI +// ucTableFormatRevision=1 +// ucTableContentRevision=3 +/****************************************************************************/ + +typedef struct _EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 +{ + union{ + USHORT usPixelClock; // pixel clock in 10Khz, valid when ucAction=SETUP/ENABLE_OUTPUT + USHORT usConnectorId; // connector id, valid when ucAction = INIT + }; + UCHAR ucConfig; // indicate which encoder, and DP link rate when ucAction = SETUP/ENABLE_OUTPUT + UCHAR ucAction; // + UCHAR ucEncoderMode; // encoder mode, only used when ucAction = SETUP/ENABLE_OUTPUT + UCHAR ucLaneNum; // lane number, only used when ucAction = SETUP/ENABLE_OUTPUT + UCHAR ucBitPerColor; // output bit per color, only valid when ucAction = SETUP/ENABLE_OUTPUT and ucEncodeMode= DP + UCHAR ucReserved; +}EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3; + +// ucAction +#define EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT 0x00 +#define EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT 0x01 +#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT 0x07 +#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP 0x0f +#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF 0x10 +#define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING 0x11 +#define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION 0x12 + +// ucConfig +#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK 0x03 +#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_1_62GHZ 0x00 +#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ 0x01 +#define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ 0x02 +#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER_SEL_MASK 0x70 +#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER1 0x00 +#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER2 0x10 +#define EXTERNAL_ENCODER_CONFIG_V3_ENCODER3 0x20 + +typedef struct _EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 +{ + EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3 sExtEncoder; + ULONG ulReserved[2]; +}EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3; + + /****************************************************************************/ // Structures used by DAC1OuputControlTable // DAC2OuputControlTable @@ -1142,6 +1406,7 @@ #define PIXEL_CLOCK_V4_MISC_SS_ENABLE 0x10 #define PIXEL_CLOCK_V4_MISC_COHERENT_MODE 0x20 + typedef struct _PIXEL_CLOCK_PARAMETERS_V3 { USHORT usPixelClock; // in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) @@ -1202,6 +1467,55 @@ #define PIXEL_CLOCK_V5_MISC_HDMI_32BPP 0x08 #define PIXEL_CLOCK_V5_MISC_REF_DIV_SRC 0x10 +typedef struct _CRTC_PIXEL_CLOCK_FREQ +{ +#if ATOM_BIG_ENDIAN + ULONG ucCRTC:8; // ATOM_CRTC1~6, indicate the CRTC controller to + // drive the pixel clock. not used for DCPLL case. + ULONG ulPixelClock:24; // target the pixel clock to drive the CRTC timing. + // 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to previous version. +#else + ULONG ulPixelClock:24; // target the pixel clock to drive the CRTC timing. + // 0 means disable PPLL/DCPLL. Expanded to 24 bits comparing to previous version. + ULONG ucCRTC:8; // ATOM_CRTC1~6, indicate the CRTC controller to + // drive the pixel clock. not used for DCPLL case. +#endif +}CRTC_PIXEL_CLOCK_FREQ; + +typedef struct _PIXEL_CLOCK_PARAMETERS_V6 +{ + union{ + CRTC_PIXEL_CLOCK_FREQ ulCrtcPclkFreq; // pixel clock and CRTC id frequency + ULONG ulDispEngClkFreq; // dispclk frequency + }; + USHORT usFbDiv; // feedback divider integer part. + UCHAR ucPostDiv; // post divider. + UCHAR ucRefDiv; // Reference divider + UCHAR ucPpll; // ATOM_PPLL1/ATOM_PPLL2/ATOM_DCPLL + UCHAR ucTransmitterID; // ASIC encoder id defined in objectId.h, + // indicate which graphic encoder will be used. + UCHAR ucEncoderMode; // Encoder mode: + UCHAR ucMiscInfo; // bit[0]= Force program PPLL + // bit[1]= when VGA timing is used. + // bit[3:2]= HDMI panel bit depth: =0: 24bpp =1:30bpp, =2:32bpp + // bit[4]= RefClock source for PPLL. + // =0: XTLAIN( default mode ) + // =1: other external clock source, which is pre-defined + // by VBIOS depend on the feature required. + // bit[7:5]: reserved. + ULONG ulFbDivDecFrac; // 20 bit feedback divider decimal fraction part, range from 1~999999 ( 0.000001 to 0.999999 ) + +}PIXEL_CLOCK_PARAMETERS_V6; + +#define PIXEL_CLOCK_V6_MISC_FORCE_PROG_PPLL 0x01 +#define PIXEL_CLOCK_V6_MISC_VGA_MODE 0x02 +#define PIXEL_CLOCK_V6_MISC_HDMI_BPP_MASK 0x0c +#define PIXEL_CLOCK_V6_MISC_HDMI_24BPP 0x00 +#define PIXEL_CLOCK_V6_MISC_HDMI_36BPP 0x04 +#define PIXEL_CLOCK_V6_MISC_HDMI_30BPP 0x08 +#define PIXEL_CLOCK_V6_MISC_HDMI_48BPP 0x0c +#define PIXEL_CLOCK_V6_MISC_REF_DIV_SRC 0x10 + typedef struct _GET_DISP_PLL_STATUS_INPUT_PARAMETERS_V2 { PIXEL_CLOCK_PARAMETERS_V3 sDispClkInput; @@ -1241,10 +1555,11 @@ typedef struct _ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3 { USHORT usPixelClock; // target pixel clock - UCHAR ucTransmitterID; // transmitter id defined in objectid.h + UCHAR ucTransmitterID; // GPU transmitter id defined in objectid.h UCHAR ucEncodeMode; // encoder mode: CRT, LVDS, DP, TMDS or HDMI UCHAR ucDispPllConfig; // display pll configure parameter defined as following DISPPLL_CONFIG_XXXX - UCHAR ucReserved[3]; + UCHAR ucExtTransmitterID; // external encoder id. + UCHAR ucReserved[2]; }ADJUST_DISPLAY_PLL_INPUT_PARAMETERS_V3; // usDispPllConfig v1.2 for RoadRunner @@ -1358,6 +1673,7 @@ /**************************************************************************/ #define SPEED_FAN_CONTROL_PS_ALLOCATION WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS + /****************************************************************************/ // Structures used by PowerConnectorDetectionTable /****************************************************************************/ @@ -1438,6 +1754,31 @@ #define ATOM_PPLL_SS_AMOUNT_V2_NFRAC_MASK 0x0F00 #define ATOM_PPLL_SS_AMOUNT_V2_NFRAC_SHIFT 8 +// Used by DCE5.0 + typedef struct _ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3 +{ + USHORT usSpreadSpectrumAmountFrac; // SS_AMOUNT_DSFRAC New in DCE5.0 + UCHAR ucSpreadSpectrumType; // Bit[0]: 0-Down Spread,1-Center Spread. + // Bit[1]: 1-Ext. 0-Int. + // Bit[3:2]: =0 P1PLL =1 P2PLL =2 DCPLL + // Bits[7:4] reserved + UCHAR ucEnable; // ATOM_ENABLE or ATOM_DISABLE + USHORT usSpreadSpectrumAmount; // Includes SS_AMOUNT_FBDIV[7:0] and SS_AMOUNT_NFRAC_SLIP[11:8] + USHORT usSpreadSpectrumStep; // SS_STEP_SIZE_DSFRAC +}ENABLE_SPREAD_SPECTRUM_ON_PPLL_V3; + +#define ATOM_PPLL_SS_TYPE_V3_DOWN_SPREAD 0x00 +#define ATOM_PPLL_SS_TYPE_V3_CENTRE_SPREAD 0x01 +#define ATOM_PPLL_SS_TYPE_V3_EXT_SPREAD 0x02 +#define ATOM_PPLL_SS_TYPE_V3_PPLL_SEL_MASK 0x0c +#define ATOM_PPLL_SS_TYPE_V3_P1PLL 0x00 +#define ATOM_PPLL_SS_TYPE_V3_P2PLL 0x04 +#define ATOM_PPLL_SS_TYPE_V3_DCPLL 0x08 +#define ATOM_PPLL_SS_AMOUNT_V3_FBDIV_MASK 0x00FF +#define ATOM_PPLL_SS_AMOUNT_V3_FBDIV_SHIFT 0 +#define ATOM_PPLL_SS_AMOUNT_V3_NFRAC_MASK 0x0F00 +#define ATOM_PPLL_SS_AMOUNT_V3_NFRAC_SHIFT 8 + #define ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION ENABLE_SPREAD_SPECTRUM_ON_PPLL /**************************************************************************/ @@ -1706,7 +2047,7 @@ USHORT StandardVESA_Timing; // Only used by Bios USHORT FirmwareInfo; // Shared by various SW components,latest version 1.4 USHORT DAC_Info; // Will be obsolete from R600 - USHORT LVDS_Info; // Shared by various SW components,latest version 1.1 + USHORT LCD_Info; // Shared by various SW components,latest version 1.3, was called LVDS_Info USHORT TMDS_Info; // Will be obsolete from R600 USHORT AnalogTV_Info; // Shared by various SW components,latest version 1.1 USHORT SupportedDevicesInfo; // Will be obsolete from R600 @@ -1736,12 +2077,16 @@ USHORT PowerSourceInfo; // Shared by various SW components, latest versoin 1.1 }ATOM_MASTER_LIST_OF_DATA_TABLES; +// For backward compatible +#define LVDS_Info LCD_Info + typedef struct _ATOM_MASTER_DATA_TABLE { ATOM_COMMON_TABLE_HEADER sHeader; ATOM_MASTER_LIST_OF_DATA_TABLES ListOfDataTables; }ATOM_MASTER_DATA_TABLE; + /****************************************************************************/ // Structure used in MultimediaCapabilityInfoTable /****************************************************************************/ @@ -1776,6 +2121,7 @@ UCHAR ucVideoInput4Info;// Video Input 4 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) }ATOM_MULTIMEDIA_CONFIG_INFO; + /****************************************************************************/ // Structures used in FirmwareInfoTable /****************************************************************************/ @@ -2031,8 +2377,47 @@ UCHAR ucReserved4[3]; }ATOM_FIRMWARE_INFO_V2_1; +//the structure below to be used from NI +//ucTableFormatRevision=2 +//ucTableContentRevision=2 +typedef struct _ATOM_FIRMWARE_INFO_V2_2 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ULONG ulFirmwareRevision; + ULONG ulDefaultEngineClock; //In 10Khz unit + ULONG ulDefaultMemoryClock; //In 10Khz unit + ULONG ulReserved[2]; + ULONG ulReserved1; //Was ulMaxEngineClockPLL_Output; //In 10Khz unit* + ULONG ulReserved2; //Was ulMaxMemoryClockPLL_Output; //In 10Khz unit* + ULONG ulMaxPixelClockPLL_Output; //In 10Khz unit + ULONG ulBinaryAlteredInfo; //Was ulASICMaxEngineClock ? + ULONG ulDefaultDispEngineClkFreq; //In 10Khz unit. This is the frequency before DCDTO, corresponding to usBootUpVDDCVoltage. + UCHAR ucReserved3; //Was ucASICMaxTemperature; + UCHAR ucMinAllowedBL_Level; + USHORT usBootUpVDDCVoltage; //In MV unit + USHORT usLcdMinPixelClockPLL_Output; // In MHz unit + USHORT usLcdMaxPixelClockPLL_Output; // In MHz unit + ULONG ulReserved4; //Was ulAsicMaximumVoltage + ULONG ulMinPixelClockPLL_Output; //In 10Khz unit + ULONG ulReserved5; //Was usMinEngineClockPLL_Input and usMaxEngineClockPLL_Input + ULONG ulReserved6; //Was usMinEngineClockPLL_Output and usMinMemoryClockPLL_Input + ULONG ulReserved7; //Was usMaxMemoryClockPLL_Input and usMinMemoryClockPLL_Output + USHORT usReserved11; //Was usMaxPixelClock; //In 10Khz unit, Max. Pclk used only for DAC + USHORT usMinPixelClockPLL_Input; //In 10Khz unit + USHORT usMaxPixelClockPLL_Input; //In 10Khz unit + USHORT usBootUpVDDCIVoltage; //In unit of mv; Was usMinPixelClockPLL_Output; + ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; + USHORT usCoreReferenceClock; //In 10Khz unit + USHORT usMemoryReferenceClock; //In 10Khz unit + USHORT usUniphyDPModeExtClkFreq; //In 10Khz unit, if it is 0, In DP Mode Uniphy Input clock from internal PPLL, otherwise Input clock from external Spread clock + UCHAR ucMemoryModule_ID; //Indicate what is the board design + UCHAR ucReserved9[3]; + USHORT usBootUpMVDDCVoltage; //In unit of mv; Was usMinPixelClockPLL_Output; + USHORT usReserved12; + ULONG ulReserved10[3]; // New added comparing to previous version +}ATOM_FIRMWARE_INFO_V2_2; -#define ATOM_FIRMWARE_INFO_LAST ATOM_FIRMWARE_INFO_V2_1 +#define ATOM_FIRMWARE_INFO_LAST ATOM_FIRMWARE_INFO_V2_2 /****************************************************************************/ // Structures used in IntegratedSystemInfoTable @@ -2212,7 +2597,7 @@ ucDockingPinBit: which bit in this register to read the pin status; ucDockingPinPolarity:Polarity of the pin when docked; -ulCPUCapInfo: [7:0]=1:Griffin;[7:0]=2:Greyhound;[7:0]=3:K8, other bits reserved for now and must be 0x0 +ulCPUCapInfo: [7:0]=1:Griffin;[7:0]=2:Greyhound;[7:0]=3:K8, [7:0]=4:Pharaoh, other bits reserved for now and must be 0x0 usNumberOfCyclesInPeriod:Indicate how many cycles when PWM duty is 100%. @@ -2250,6 +2635,14 @@ usMinDownStreamHTLinkWidth: same as above. */ +// ATOM_INTEGRATED_SYSTEM_INFO::ulCPUCapInfo - CPU type definition +#define INTEGRATED_SYSTEM_INFO__UNKNOWN_CPU 0 +#define INTEGRATED_SYSTEM_INFO__AMD_CPU__GRIFFIN 1 +#define INTEGRATED_SYSTEM_INFO__AMD_CPU__GREYHOUND 2 +#define INTEGRATED_SYSTEM_INFO__AMD_CPU__K8 3 +#define INTEGRATED_SYSTEM_INFO__AMD_CPU__PHARAOH 4 + +#define INTEGRATED_SYSTEM_INFO__AMD_CPU__MAX_CODE INTEGRATED_SYSTEM_INFO__AMD_CPU__PHARAOH // this deff reflects max defined CPU code #define SYSTEM_CONFIG_POWEREXPRESS_ENABLE 0x00000001 #define SYSTEM_CONFIG_RUN_AT_OVERDRIVE_ENGINE 0x00000002 @@ -2778,8 +3171,88 @@ #define PANEL_RANDOM_DITHER 0x80 #define PANEL_RANDOM_DITHER_MASK 0x80 +#define ATOM_LVDS_INFO_LAST ATOM_LVDS_INFO_V12 // no need to change this + +/****************************************************************************/ +// Structures used by LCD_InfoTable V1.3 Note: previous version was called ATOM_LVDS_INFO_V12 +// ASIC Families: NI +// ucTableFormatRevision=1 +// ucTableContentRevision=3 +/****************************************************************************/ +typedef struct _ATOM_LCD_INFO_V13 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + ATOM_DTD_FORMAT sLCDTiming; + USHORT usExtInfoTableOffset; + USHORT usSupportedRefreshRate; //Refer to panel info table in ATOMBIOS extension Spec. + ULONG ulReserved0; + UCHAR ucLCD_Misc; // Reorganized in V13 + // Bit0: {=0:single, =1:dual}, + // Bit1: {=0:LDI format for RGB888, =1 FPDI format for RGB888} // was {=0:666RGB, =1:888RGB}, + // Bit3:2: {Grey level} + // Bit6:4 Color Bit Depth definition (see below definition in EDID V1.4 @BYTE 14h) + // Bit7 Reserved. was for ATOM_PANEL_MISC_API_ENABLED, still need it? + UCHAR ucPanelDefaultRefreshRate; + UCHAR ucPanelIdentification; + UCHAR ucSS_Id; + USHORT usLCDVenderID; + USHORT usLCDProductID; + UCHAR ucLCDPanel_SpecialHandlingCap; // Reorganized in V13 + // Bit0: Once DAL sees this CAP is set, it will read EDID from LCD on its own + // Bit1: See LCDPANEL_CAP_DRR_SUPPORTED + // Bit2: a quick reference whether an embadded panel (LCD1 ) is LVDS (0) or eDP (1) + // Bit7-3: Reserved + UCHAR ucPanelInfoSize; // start from ATOM_DTD_FORMAT to end of panel info, include ExtInfoTable + USHORT usBacklightPWM; // Backlight PWM in Hz. New in _V13 + + UCHAR ucPowerSequenceDIGONtoDE_in4Ms; + UCHAR ucPowerSequenceDEtoVARY_BL_in4Ms; + UCHAR ucPowerSequenceDEtoDIGON_in4Ms; + UCHAR ucPowerSequenceVARY_BLtoDE_in4Ms; + + UCHAR ucOffDelay_in4Ms; + UCHAR ucPowerSequenceVARY_BLtoBLON_in4Ms; + UCHAR ucPowerSequenceBLONtoVARY_BL_in4Ms; + UCHAR ucReserved1; + + ULONG ulReserved[4]; +}ATOM_LCD_INFO_V13; + +#define ATOM_LCD_INFO_LAST ATOM_LCD_INFO_V13 + +//Definitions for ucLCD_Misc +#define ATOM_PANEL_MISC_V13_DUAL 0x00000001 +#define ATOM_PANEL_MISC_V13_FPDI 0x00000002 +#define ATOM_PANEL_MISC_V13_GREY_LEVEL 0x0000000C +#define ATOM_PANEL_MISC_V13_GREY_LEVEL_SHIFT 2 +#define ATOM_PANEL_MISC_V13_COLOR_BIT_DEPTH_MASK 0x70 +#define ATOM_PANEL_MISC_V13_6BIT_PER_COLOR 0x10 +#define ATOM_PANEL_MISC_V13_8BIT_PER_COLOR 0x20 + +//Color Bit Depth definition in EDID V1.4 @BYTE 14h +//Bit 6 5 4 + // 0 0 0 - Color bit depth is undefined + // 0 0 1 - 6 Bits per Primary Color + // 0 1 0 - 8 Bits per Primary Color + // 0 1 1 - 10 Bits per Primary Color + // 1 0 0 - 12 Bits per Primary Color + // 1 0 1 - 14 Bits per Primary Color + // 1 1 0 - 16 Bits per Primary Color + // 1 1 1 - Reserved + +//Definitions for ucLCDPanel_SpecialHandlingCap: + +//Once DAL sees this CAP is set, it will read EDID from LCD on its own instead of using sLCDTiming in ATOM_LVDS_INFO_V12. +//Other entries in ATOM_LVDS_INFO_V12 are still valid/useful to DAL +#define LCDPANEL_CAP_V13_READ_EDID 0x1 // = LCDPANEL_CAP_READ_EDID no change comparing to previous version -#define ATOM_LVDS_INFO_LAST ATOM_LVDS_INFO_V12 +//If a design supports DRR (dynamic refresh rate) on internal panels (LVDS or EDP), this cap is set in ucLCDPanel_SpecialHandlingCap together +//with multiple supported refresh rates@usSupportedRefreshRate. This cap should not be set when only slow refresh rate is supported (static +//refresh rate switch by SW. This is only valid from ATOM_LVDS_INFO_V12 +#define LCDPANEL_CAP_V13_DRR_SUPPORTED 0x2 // = LCDPANEL_CAP_DRR_SUPPORTED no change comparing to previous version + +//Use this cap bit for a quick reference whether an embadded panel (LCD1 ) is LVDS or eDP. +#define LCDPANEL_CAP_V13_eDP 0x4 // = LCDPANEL_CAP_eDP no change comparing to previous version typedef struct _ATOM_PATCH_RECORD_MODE { @@ -2944,9 +3417,9 @@ #define MAX_DTD_MODE_IN_VRAM 6 #define ATOM_DTD_MODE_SUPPORT_TBL_SIZE (MAX_DTD_MODE_IN_VRAM*28) //28= (SIZEOF ATOM_DTD_FORMAT) #define ATOM_STD_MODE_SUPPORT_TBL_SIZE 32*8 //32 is a predefined number,8= (SIZEOF ATOM_STD_FORMAT) -#define DFP_ENCODER_TYPE_OFFSET 0x80 -#define DP_ENCODER_LANE_NUM_OFFSET 0x84 -#define DP_ENCODER_LINK_RATE_OFFSET 0x88 +//20 bytes for Encoder Type and DPCD in STD EDID area +#define DFP_ENCODER_TYPE_OFFSET (ATOM_EDID_RAW_DATASIZE + ATOM_DTD_MODE_SUPPORT_TBL_SIZE + ATOM_STD_MODE_SUPPORT_TBL_SIZE - 20) +#define ATOM_DP_DPCD_OFFSET (DFP_ENCODER_TYPE_OFFSET + 4 ) #define ATOM_HWICON1_SURFACE_ADDR 0 #define ATOM_HWICON2_SURFACE_ADDR (ATOM_HWICON1_SURFACE_ADDR + ATOM_HWICON_SURFACE_SIZE) @@ -2997,14 +3470,16 @@ #define ATOM_DFP5_DTD_MODE_TBL_ADDR (ATOM_DFP5_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) #define ATOM_DFP5_STD_MODE_TBL_ADDR (ATOM_DFP5_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) -#define ATOM_DP_TRAINING_TBL_ADDR (ATOM_DFP5_STD_MODE_TBL_ADDR+ATOM_STD_MODE_SUPPORT_TBL_SIZE) +#define ATOM_DP_TRAINING_TBL_ADDR (ATOM_DFP5_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) -#define ATOM_STACK_STORAGE_START (ATOM_DP_TRAINING_TBL_ADDR+256) -#define ATOM_STACK_STORAGE_END ATOM_STACK_STORAGE_START+512 +#define ATOM_STACK_STORAGE_START (ATOM_DP_TRAINING_TBL_ADDR + 1024) +#define ATOM_STACK_STORAGE_END ATOM_STACK_STORAGE_START + 512 //The size below is in Kb! #define ATOM_VRAM_RESERVE_SIZE ((((ATOM_STACK_STORAGE_END - ATOM_HWICON1_SURFACE_ADDR)>>10)+4)&0xFFFC) +#define ATOM_VRAM_RESERVE_V2_SIZE 32 + #define ATOM_VRAM_OPERATION_FLAGS_MASK 0xC0000000L #define ATOM_VRAM_OPERATION_FLAGS_SHIFT 30 #define ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION 0x1 @@ -3206,6 +3681,15 @@ USHORT usGraphicObjIds[1]; //1st Encoder Obj source from GPU to last Graphic Obj destinate to connector. }ATOM_DISPLAY_OBJECT_PATH; +typedef struct _ATOM_DISPLAY_EXTERNAL_OBJECT_PATH +{ + USHORT usDeviceTag; //supported device + USHORT usSize; //the size of ATOM_DISPLAY_OBJECT_PATH + USHORT usConnObjectId; //Connector Object ID + USHORT usGPUObjectId; //GPU ID + USHORT usGraphicObjIds[2]; //usGraphicObjIds[0]= GPU internal encoder, usGraphicObjIds[1]= external encoder +}ATOM_DISPLAY_EXTERNAL_OBJECT_PATH; + typedef struct _ATOM_DISPLAY_OBJECT_PATH_TABLE { UCHAR ucNumOfDispPath; @@ -3261,6 +3745,47 @@ #define EXT_AUXDDC_LUTINDEX_7 7 #define MAX_NUMBER_OF_EXT_AUXDDC_LUT_ENTRIES (EXT_AUXDDC_LUTINDEX_7+1) +//ucChannelMapping are defined as following +//for DP connector, eDP, DP to VGA/LVDS +//Bit[1:0]: Define which pin connect to DP connector DP_Lane0, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[3:2]: Define which pin connect to DP connector DP_Lane1, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[5:4]: Define which pin connect to DP connector DP_Lane2, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[7:6]: Define which pin connect to DP connector DP_Lane3, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +typedef struct _ATOM_DP_CONN_CHANNEL_MAPPING +{ +#if ATOM_BIG_ENDIAN + UCHAR ucDP_Lane3_Source:2; + UCHAR ucDP_Lane2_Source:2; + UCHAR ucDP_Lane1_Source:2; + UCHAR ucDP_Lane0_Source:2; +#else + UCHAR ucDP_Lane0_Source:2; + UCHAR ucDP_Lane1_Source:2; + UCHAR ucDP_Lane2_Source:2; + UCHAR ucDP_Lane3_Source:2; +#endif +}ATOM_DP_CONN_CHANNEL_MAPPING; + +//for DVI/HDMI, in dual link case, both links have to have same mapping. +//Bit[1:0]: Define which pin connect to DVI connector data Lane2, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[3:2]: Define which pin connect to DVI connector data Lane1, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[5:4]: Define which pin connect to DVI connector data Lane0, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +//Bit[7:6]: Define which pin connect to DVI connector clock lane, =0: source from GPU pin TX0, =1: from GPU pin TX1, =2: from GPU pin TX2, =3 from GPU pin TX3 +typedef struct _ATOM_DVI_CONN_CHANNEL_MAPPING +{ +#if ATOM_BIG_ENDIAN + UCHAR ucDVI_CLK_Source:2; + UCHAR ucDVI_DATA0_Source:2; + UCHAR ucDVI_DATA1_Source:2; + UCHAR ucDVI_DATA2_Source:2; +#else + UCHAR ucDVI_DATA2_Source:2; + UCHAR ucDVI_DATA1_Source:2; + UCHAR ucDVI_DATA0_Source:2; + UCHAR ucDVI_CLK_Source:2; +#endif +}ATOM_DVI_CONN_CHANNEL_MAPPING; + typedef struct _EXT_DISPLAY_PATH { USHORT usDeviceTag; //A bit vector to show what devices are supported @@ -3269,7 +3794,13 @@ UCHAR ucExtAUXDDCLutIndex; //An index into external AUX/DDC channel LUT UCHAR ucExtHPDPINLutIndex; //An index into external HPD pin LUT USHORT usExtEncoderObjId; //external encoder object id - USHORT usReserved[3]; + union{ + UCHAR ucChannelMapping; // if ucChannelMapping=0, using default one to one mapping + ATOM_DP_CONN_CHANNEL_MAPPING asDPMapping; + ATOM_DVI_CONN_CHANNEL_MAPPING asDVIMapping; + }; + UCHAR ucReserved; + USHORT usReserved[2]; }EXT_DISPLAY_PATH; #define NUMBER_OF_UCHAR_FOR_GUID 16 @@ -3281,7 +3812,8 @@ UCHAR ucGuid [NUMBER_OF_UCHAR_FOR_GUID]; // a GUID is a 16 byte long string EXT_DISPLAY_PATH sPath[MAX_NUMBER_OF_EXT_DISPLAY_PATH]; // total of fixed 7 entries. UCHAR ucChecksum; // a simple Checksum of the sum of whole structure equal to 0x0. - UCHAR Reserved [7]; // for potential expansion + UCHAR uc3DStereoPinId; // use for eDP panel + UCHAR Reserved [6]; // for potential expansion }ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO; //Related definitions, all records are differnt but they have a commond header @@ -3311,10 +3843,11 @@ #define ATOM_CONNECTOR_AUXDDC_LUT_RECORD_TYPE 17 //This is for the case when connectors are not known to object table #define ATOM_OBJECT_LINK_RECORD_TYPE 18 //Once this record is present under one object, it indicats the oobject is linked to another obj described by the record #define ATOM_CONNECTOR_REMOTE_CAP_RECORD_TYPE 19 +#define ATOM_ENCODER_CAP_RECORD_TYPE 20 //Must be updated when new record type is added,equal to that record definition! -#define ATOM_MAX_OBJECT_RECORD_NUMBER ATOM_CONNECTOR_REMOTE_CAP_RECORD_TYPE +#define ATOM_MAX_OBJECT_RECORD_NUMBER ATOM_ENCODER_CAP_RECORD_TYPE typedef struct _ATOM_I2C_RECORD { @@ -3441,6 +3974,26 @@ UCHAR ucPadding[2]; }ATOM_ENCODER_DVO_CF_RECORD; +// Bit maps for ATOM_ENCODER_CAP_RECORD.ucEncoderCap +#define ATOM_ENCODER_CAP_RECORD_HBR2 0x01 // DP1.2 HBR2 is supported by this path + +typedef struct _ATOM_ENCODER_CAP_RECORD +{ + ATOM_COMMON_RECORD_HEADER sheader; + union { + USHORT usEncoderCap; + struct { +#if ATOM_BIG_ENDIAN + USHORT usReserved:15; // Bit1-15 may be defined for other capability in future + USHORT usHBR2Cap:1; // Bit0 is for DP1.2 HBR2 capability. +#else + USHORT usHBR2Cap:1; // Bit0 is for DP1.2 HBR2 capability. + USHORT usReserved:15; // Bit1-15 may be defined for other capability in future +#endif + }; + }; +}ATOM_ENCODER_CAP_RECORD; + // value for ATOM_CONNECTOR_CF_RECORD.ucConnectedDvoBundle #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_UPPER12BITBUNDLEA 1 #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_LOWER12BITBUNDLEB 2 @@ -3580,6 +4133,11 @@ #define VOLTAGE_CONTROL_ID_DAC 0x02 //I2C control, used for R5xx/R6xx MVDDC,MVDDQ or VDDCI #define VOLTAGE_CONTROL_ID_VT116xM 0x03 //I2C control, used for R6xx Core Voltage #define VOLTAGE_CONTROL_ID_DS4402 0x04 +#define VOLTAGE_CONTROL_ID_UP6266 0x05 +#define VOLTAGE_CONTROL_ID_SCORPIO 0x06 +#define VOLTAGE_CONTROL_ID_VT1556M 0x07 +#define VOLTAGE_CONTROL_ID_CHL822x 0x08 +#define VOLTAGE_CONTROL_ID_VT1586M 0x09 typedef struct _ATOM_VOLTAGE_OBJECT { @@ -3670,66 +4228,157 @@ #define POWER_SENSOR_GPIO 0x01 #define POWER_SENSOR_I2C 0x02 +typedef struct _ATOM_CLK_VOLT_CAPABILITY +{ + ULONG ulVoltageIndex; // The Voltage Index indicated by FUSE, same voltage index shared with SCLK DPM fuse table + ULONG ulMaximumSupportedCLK; // Maximum clock supported with specified voltage index, unit in 10kHz +}ATOM_CLK_VOLT_CAPABILITY; + +typedef struct _ATOM_AVAILABLE_SCLK_LIST +{ + ULONG ulSupportedSCLK; // Maximum clock supported with specified voltage index, unit in 10kHz + USHORT usVoltageIndex; // The Voltage Index indicated by FUSE for specified SCLK + USHORT usVoltageID; // The Voltage ID indicated by FUSE for specified SCLK +}ATOM_AVAILABLE_SCLK_LIST; + +// ATOM_INTEGRATED_SYSTEM_INFO_V6 ulSystemConfig cap definition +#define ATOM_IGP_INFO_V6_SYSTEM_CONFIG__PCIE_POWER_GATING_ENABLE 1 // refer to ulSystemConfig bit[0] + +// this IntegrateSystemInfoTable is used for Liano/Ontario APU typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 { ATOM_COMMON_TABLE_HEADER sHeader; ULONG ulBootUpEngineClock; ULONG ulDentistVCOFreq; ULONG ulBootUpUMAClock; - ULONG ulReserved1[8]; + ATOM_CLK_VOLT_CAPABILITY sDISPCLK_Voltage[4]; ULONG ulBootUpReqDisplayVector; ULONG ulOtherDisplayMisc; ULONG ulGPUCapInfo; - ULONG ulReserved2[3]; + ULONG ulSB_MMIO_Base_Addr; + USHORT usRequestedPWMFreqInHz; + UCHAR ucHtcTmpLmt; + UCHAR ucHtcHystLmt; + ULONG ulMinEngineClock; ULONG ulSystemConfig; ULONG ulCPUCapInfo; - USHORT usMaxNBVoltage; - USHORT usMinNBVoltage; - USHORT usBootUpNBVoltage; - USHORT usExtDispConnInfoOffset; - UCHAR ucHtcTmpLmt; - UCHAR ucTjOffset; + USHORT usNBP0Voltage; + USHORT usNBP1Voltage; + USHORT usBootUpNBVoltage; + USHORT usExtDispConnInfoOffset; + USHORT usPanelRefreshRateRange; UCHAR ucMemoryType; UCHAR ucUMAChannelNumber; ULONG ulCSR_M3_ARB_CNTL_DEFAULT[10]; ULONG ulCSR_M3_ARB_CNTL_UVD[10]; ULONG ulCSR_M3_ARB_CNTL_FS3D[10]; - ULONG ulReserved3[42]; + ATOM_AVAILABLE_SCLK_LIST sAvail_SCLK[5]; + ULONG ulGMCRestoreResetTime; + ULONG ulMinimumNClk; + ULONG ulIdleNClk; + ULONG ulDDR_DLL_PowerUpTime; + ULONG ulDDR_PLL_PowerUpTime; + USHORT usPCIEClkSSPercentage; + USHORT usPCIEClkSSType; + USHORT usLvdsSSPercentage; + USHORT usLvdsSSpreadRateIn10Hz; + USHORT usHDMISSPercentage; + USHORT usHDMISSpreadRateIn10Hz; + USHORT usDVISSPercentage; + USHORT usDVISSpreadRateIn10Hz; + ULONG ulReserved3[21]; ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO sExtDispConnInfo; }ATOM_INTEGRATED_SYSTEM_INFO_V6; +// ulGPUCapInfo +#define INTEGRATED_SYSTEM_INFO_V6_GPUCAPINFO__TMDSHDMI_COHERENT_SINGLEPLL_MODE 0x01 +#define INTEGRATED_SYSTEM_INFO_V6_GPUCAPINFO__DISABLE_AUX_HW_MODE_DETECTION 0x08 + +// ulOtherDisplayMisc +#define INTEGRATED_SYSTEM_INFO__GET_EDID_CALLBACK_FUNC_SUPPORT 0x01 + + /********************************************************************************************************************** -// ATOM_INTEGRATED_SYSTEM_INFO_V6 Description -//ulBootUpEngineClock: VBIOS bootup Engine clock frequency, in 10kHz unit. -//ulDentistVCOFreq: Dentist VCO clock in 10kHz unit. -//ulBootUpUMAClock: System memory boot up clock frequency in 10Khz unit. -//ulReserved1[8] Reserved by now, must be 0x0. -//ulBootUpReqDisplayVector VBIOS boot up display IDs -// ATOM_DEVICE_CRT1_SUPPORT 0x0001 -// ATOM_DEVICE_CRT2_SUPPORT 0x0010 -// ATOM_DEVICE_DFP1_SUPPORT 0x0008 -// ATOM_DEVICE_DFP6_SUPPORT 0x0040 -// ATOM_DEVICE_DFP2_SUPPORT 0x0080 -// ATOM_DEVICE_DFP3_SUPPORT 0x0200 -// ATOM_DEVICE_DFP4_SUPPORT 0x0400 -// ATOM_DEVICE_DFP5_SUPPORT 0x0800 -// ATOM_DEVICE_LCD1_SUPPORT 0x0002 -//ulOtherDisplayMisc Other display related flags, not defined yet. -//ulGPUCapInfo TBD -//ulReserved2[3] must be 0x0 for the reserved. -//ulSystemConfig TBD -//ulCPUCapInfo TBD -//usMaxNBVoltage High NB voltage in unit of mv, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse. -//usMinNBVoltage Low NB voltage in unit of mv, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse. -//usBootUpNBVoltage Boot up NB voltage in unit of mv. -//ucHtcTmpLmt Bit [22:16] of D24F3x64 Thermal Control (HTC) Register. -//ucTjOffset Bit [28:22] of D24F3xE4 Thermtrip Status Register,may not be needed. -//ucMemoryType [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved. -//ucUMAChannelNumber System memory channel numbers. -//usExtDispConnectionInfoOffset ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO offset relative to beginning of this table. -//ulCSR_M3_ARB_CNTL_DEFAULT[10] Arrays with values for CSR M3 arbiter for default -//ulCSR_M3_ARB_CNTL_UVD[10] Arrays with values for CSR M3 arbiter for UVD playback. -//ulCSR_M3_ARB_CNTL_FS3D[10] Arrays with values for CSR M3 arbiter for Full Screen 3D applications. + ATOM_INTEGRATED_SYSTEM_INFO_V6 Description +ulBootUpEngineClock: VBIOS bootup Engine clock frequency, in 10kHz unit. if it is equal 0, then VBIOS use pre-defined bootup engine clock +ulDentistVCOFreq: Dentist VCO clock in 10kHz unit. +ulBootUpUMAClock: System memory boot up clock frequency in 10Khz unit. +sDISPCLK_Voltage: Report Display clock voltage requirement. + +ulBootUpReqDisplayVector: VBIOS boot up display IDs, following are supported devices in Liano/Ontaio projects: + ATOM_DEVICE_CRT1_SUPPORT 0x0001 + ATOM_DEVICE_CRT2_SUPPORT 0x0010 + ATOM_DEVICE_DFP1_SUPPORT 0x0008 + ATOM_DEVICE_DFP6_SUPPORT 0x0040 + ATOM_DEVICE_DFP2_SUPPORT 0x0080 + ATOM_DEVICE_DFP3_SUPPORT 0x0200 + ATOM_DEVICE_DFP4_SUPPORT 0x0400 + ATOM_DEVICE_DFP5_SUPPORT 0x0800 + ATOM_DEVICE_LCD1_SUPPORT 0x0002 +ulOtherDisplayMisc: Other display related flags, not defined yet. +ulGPUCapInfo: bit[0]=0: TMDS/HDMI Coherent Mode use cascade PLL mode. + =1: TMDS/HDMI Coherent Mode use signel PLL mode. + bit[3]=0: Enable HW AUX mode detection logic + =1: Disable HW AUX mode dettion logic +ulSB_MMIO_Base_Addr: Physical Base address to SB MMIO space. Driver needs to initialize it for SMU usage. + +usRequestedPWMFreqInHz: When it's set to 0x0 by SBIOS: the LCD BackLight is not controlled by GPU(SW). + Any attempt to change BL using VBIOS function or enable VariBri from PP table is not effective since ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==0; + + When it's set to a non-zero frequency, the BackLight is controlled by GPU (SW) in one of two ways below: + 1. SW uses the GPU BL PWM output to control the BL, in chis case, this non-zero frequency determines what freq GPU should use; + VBIOS will set up proper PWM frequency and ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1,as the result, + Changing BL using VBIOS function is functional in both driver and non-driver present environment; + and enabling VariBri under the driver environment from PP table is optional. + + 2. SW uses other means to control BL (like DPCD),this non-zero frequency serves as a flag only indicating + that BL control from GPU is expected. + VBIOS will NOT set up PWM frequency but make ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU==1 + Changing BL using VBIOS function could be functional in both driver and non-driver present environment,but + it's per platform + and enabling VariBri under the driver environment from PP table is optional. + +ucHtcTmpLmt: Refer to D18F3x64 bit[22:16], HtcTmpLmt. + Threshold on value to enter HTC_active state. +ucHtcHystLmt: Refer to D18F3x64 bit[27:24], HtcHystLmt. + To calculate threshold off value to exit HTC_active state, which is Threshold on vlaue minus ucHtcHystLmt. +ulMinEngineClock: Minimum SCLK allowed in 10kHz unit. This is calculated based on WRCK Fuse settings. +ulSystemConfig: Bit[0]=0: PCIE Power Gating Disabled + =1: PCIE Power Gating Enabled + Bit[1]=0: DDR-DLL shut-down feature disabled. + 1: DDR-DLL shut-down feature enabled. + Bit[2]=0: DDR-PLL Power down feature disabled. + 1: DDR-PLL Power down feature enabled. +ulCPUCapInfo: TBD +usNBP0Voltage: VID for voltage on NB P0 State +usNBP1Voltage: VID for voltage on NB P1 State +usBootUpNBVoltage: Voltage Index of GNB voltage configured by SBIOS, which is suffcient to support VBIOS DISPCLK requirement. +usExtDispConnInfoOffset: Offset to sExtDispConnInfo inside the structure +usPanelRefreshRateRange: Bit vector for LCD supported refresh rate range. If DRR is requestd by the platform, at least two bits need to be set + to indicate a range. + SUPPORTED_LCD_REFRESHRATE_30Hz 0x0004 + SUPPORTED_LCD_REFRESHRATE_40Hz 0x0008 + SUPPORTED_LCD_REFRESHRATE_50Hz 0x0010 + SUPPORTED_LCD_REFRESHRATE_60Hz 0x0020 +ucMemoryType: [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved. +ucUMAChannelNumber: System memory channel numbers. +ulCSR_M3_ARB_CNTL_DEFAULT[10]: Arrays with values for CSR M3 arbiter for default +ulCSR_M3_ARB_CNTL_UVD[10]: Arrays with values for CSR M3 arbiter for UVD playback. +ulCSR_M3_ARB_CNTL_FS3D[10]: Arrays with values for CSR M3 arbiter for Full Screen 3D applications. +sAvail_SCLK[5]: Arrays to provide availabe list of SLCK and corresponding voltage, order from low to high +ulGMCRestoreResetTime: GMC power restore and GMC reset time to calculate data reconnection latency. Unit in ns. +ulMinimumNClk: Minimum NCLK speed among all NB-Pstates to calcualte data reconnection latency. Unit in 10kHz. +ulIdleNClk: NCLK speed while memory runs in self-refresh state. Unit in 10kHz. +ulDDR_DLL_PowerUpTime: DDR PHY DLL power up time. Unit in ns. +ulDDR_PLL_PowerUpTime: DDR PHY PLL power up time. Unit in ns. +usPCIEClkSSPercentage: PCIE Clock Spred Spectrum Percentage in unit 0.01%; 100 mean 1%. +usPCIEClkSSType: PCIE Clock Spred Spectrum Type. 0 for Down spread(default); 1 for Center spread. +usLvdsSSPercentage: LVDS panel ( not include eDP ) Spread Spectrum Percentage in unit of 0.01%, =0, use VBIOS default setting. +usLvdsSSpreadRateIn10Hz: LVDS panel ( not include eDP ) Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. +usHDMISSPercentage: HDMI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting. +usHDMISSpreadRateIn10Hz: HDMI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. +usDVISSPercentage: DVI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%, =0, use VBIOS default setting. +usDVISSpreadRateIn10Hz: DVI Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. **********************************************************************************************************************/ /**************************************************************************/ @@ -3790,6 +4439,7 @@ #define ASIC_INTERNAL_SS_ON_LVDS 6 #define ASIC_INTERNAL_SS_ON_DP 7 #define ASIC_INTERNAL_SS_ON_DCPLL 8 +#define ASIC_EXTERNAL_SS_ON_DP_CLOCK 9 typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V2 { @@ -3903,6 +4553,7 @@ #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_AC 1 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_DC 2 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LITEAC 3 +#define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LIT2AC 4 //Byte aligned defintion for BIOS usage #define ATOM_S0_CRT1_MONOb0 0x01 @@ -4529,7 +5180,8 @@ #define INDEX_ACCESS_RANGE_BEGIN (VALUE_DWORD + 1) #define INDEX_ACCESS_RANGE_END (INDEX_ACCESS_RANGE_BEGIN + 1) #define VALUE_INDEX_ACCESS_SINGLE (INDEX_ACCESS_RANGE_END + 1) - +//#define ACCESS_MCIODEBUGIND 0x40 //defined in BIOS code +#define ACCESS_PLACEHOLDER 0x80 typedef struct _ATOM_MC_INIT_PARAM_TABLE { @@ -4554,6 +5206,10 @@ #define _32Mx32 0x33 #define _64Mx8 0x41 #define _64Mx16 0x42 +#define _64Mx32 0x43 +#define _128Mx8 0x51 +#define _128Mx16 0x52 +#define _256Mx8 0x61 #define SAMSUNG 0x1 #define INFINEON 0x2 @@ -4569,10 +5225,11 @@ #define QIMONDA INFINEON #define PROMOS MOSEL #define KRETON INFINEON +#define ELIXIR NANYA /////////////Support for GDDR5 MC uCode to reside in upper 64K of ROM///////////// -#define UCODE_ROM_START_ADDRESS 0x1c000 +#define UCODE_ROM_START_ADDRESS 0x1b800 #define UCODE_SIGNATURE 0x4375434d // 'MCuC' - MC uCode //uCode block header for reference @@ -4903,7 +5560,34 @@ ATOM_MEMORY_TIMING_FORMAT_V2 asMemTiming[5];//Memory Timing block sort from lower clock to higher clock }ATOM_VRAM_MODULE_V6; - +typedef struct _ATOM_VRAM_MODULE_V7 +{ +// Design Specific Values + ULONG ulChannelMapCfg; // mmMC_SHARED_CHREMAP + USHORT usModuleSize; // Size of ATOM_VRAM_MODULE_V7 + USHORT usPrivateReserved; // MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) + USHORT usReserved; + UCHAR ucExtMemoryID; // Current memory module ID + UCHAR ucMemoryType; // MEM_TYPE_DDR2/DDR3/GDDR3/GDDR5 + UCHAR ucChannelNum; // Number of mem. channels supported in this module + UCHAR ucChannelWidth; // CHANNEL_16BIT/CHANNEL_32BIT/CHANNEL_64BIT + UCHAR ucDensity; // _8Mx32, _16Mx32, _16Mx16, _32Mx16 + UCHAR ucReserve; // Former container for Mx_FLAGS like DBI_AC_MODE_ENABLE_ASIC for GDDR4. Not used now. + UCHAR ucMisc; // RANK_OF_THISMEMORY etc. + UCHAR ucVREFI; // Not used. + UCHAR ucNPL_RT; // Round trip delay (MC_SEQ_CAS_TIMING [28:24]:TCL=CL+NPL_RT-2). Always 2. + UCHAR ucPreamble; // [7:4] Write Preamble, [3:0] Read Preamble + UCHAR ucMemorySize; // Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros + UCHAR ucReserved[3]; +// Memory Module specific values + USHORT usEMRS2Value; // EMRS2/MR2 Value. + USHORT usEMRS3Value; // EMRS3/MR3 Value. + UCHAR ucMemoryVenderID; // [7:4] Revision, [3:0] Vendor code + UCHAR ucRefreshRateFactor; // [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) + UCHAR ucFIFODepth; // FIFO depth can be detected during vendor detection, here is hardcoded per memory + UCHAR ucCDR_Bandwidth; // [0:3]=Read CDR bandwidth, [4:7] - Write CDR Bandwidth + char strMemPNString[20]; // part number end with '0'. +}ATOM_VRAM_MODULE_V7; typedef struct _ATOM_VRAM_INFO_V2 { @@ -4942,6 +5626,20 @@ // ATOM_INIT_REG_BLOCK aMemAdjust; }ATOM_VRAM_INFO_V4; +typedef struct _ATOM_VRAM_INFO_HEADER_V2_1 +{ + ATOM_COMMON_TABLE_HEADER sHeader; + USHORT usMemAdjustTblOffset; // offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting + USHORT usMemClkPatchTblOffset; // offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting + USHORT usReserved[4]; + UCHAR ucNumOfVRAMModule; // indicate number of VRAM module + UCHAR ucMemoryClkPatchTblVer; // version of memory AC timing register list + UCHAR ucVramModuleVer; // indicate ATOM_VRAM_MODUE version + UCHAR ucReserved; + ATOM_VRAM_MODULE_V7 aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE]; // just for allocation, real number of blocks is in ucNumOfVRAMModule; +}ATOM_VRAM_INFO_HEADER_V2_1; + + typedef struct _ATOM_VRAM_GPIO_DETECTION_INFO { ATOM_COMMON_TABLE_HEADER sHeader; @@ -5182,6 +5880,16 @@ UCHAR ucReserved; }ASIC_TRANSMITTER_INFO; +#define ASIC_TRANSMITTER_INFO_CONFIG__DVO_SDR_MODE 0x01 +#define ASIC_TRANSMITTER_INFO_CONFIG__COHERENT_MODE 0x02 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODEROBJ_ID_MASK 0xc4 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_A 0x00 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_B 0x04 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_C 0x40 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_D 0x44 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_E 0x80 +#define ASIC_TRANSMITTER_INFO_CONFIG__ENCODER_F 0x84 + typedef struct _ASIC_ENCODER_INFO { UCHAR ucEncoderID; @@ -5284,6 +5992,28 @@ /* /obselete */ #define DP_ENCODER_SERVICE_PS_ALLOCATION WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS + +typedef struct _DP_ENCODER_SERVICE_PARAMETERS_V2 +{ + USHORT usExtEncoderObjId; // External Encoder Object Id, output parameter only, use when ucAction = DP_SERVICE_V2_ACTION_DET_EXT_CONNECTION + UCHAR ucAuxId; + UCHAR ucAction; + UCHAR ucSinkType; // Iput and Output parameters. + UCHAR ucHPDId; // Input parameter, used when ucAction = DP_SERVICE_V2_ACTION_DET_EXT_CONNECTION + UCHAR ucReserved[2]; +}DP_ENCODER_SERVICE_PARAMETERS_V2; + +typedef struct _DP_ENCODER_SERVICE_PS_ALLOCATION_V2 +{ + DP_ENCODER_SERVICE_PARAMETERS_V2 asDPServiceParam; + PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 asAuxParam; +}DP_ENCODER_SERVICE_PS_ALLOCATION_V2; + +// ucAction +#define DP_SERVICE_V2_ACTION_GET_SINK_TYPE 0x01 +#define DP_SERVICE_V2_ACTION_DET_LCD_CONNECTION 0x02 + + // DP_TRAINING_TABLE #define DPCD_SET_LINKRATE_LANENUM_PATTERN1_TBL_ADDR ATOM_DP_TRAINING_TBL_ADDR #define DPCD_SET_SS_CNTL_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 8 ) @@ -5339,6 +6069,7 @@ #define SELECT_DCIO_IMPCAL 4 #define SELECT_DCIO_DIG 6 #define SELECT_CRTC_PIXEL_RATE 7 +#define SELECT_VGA_BLK 8 /****************************************************************************/ //Portion VI: Definitinos for vbios MC scratch registers that driver used @@ -5744,7 +6475,17 @@ #define ATOM_PP_THERMALCONTROLLER_ADT7473 9 #define ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO 11 #define ATOM_PP_THERMALCONTROLLER_EVERGREEN 12 +#define ATOM_PP_THERMALCONTROLLER_EMC2103 13 /* 0x0D */ // Only fan control will be implemented, do NOT show this in PPGen. +#define ATOM_PP_THERMALCONTROLLER_SUMO 14 /* 0x0E */ // Sumo type, used internally +#define ATOM_PP_THERMALCONTROLLER_NISLANDS 15 + +// Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. +// We probably should reserve the bit 0x80 for this use. +// To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here). +// The driver can pick the correct internal controller based on the ASIC. + #define ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89 // ADT7473 Fan Control + Internal Thermal Controller +#define ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D // EMC2103 Fan Control + Internal Thermal Controller typedef struct _ATOM_PPLIB_STATE { @@ -5841,6 +6582,29 @@ USHORT usExtendendedHeaderOffset; } ATOM_PPLIB_POWERPLAYTABLE3, *LPATOM_PPLIB_POWERPLAYTABLE3; +typedef struct _ATOM_PPLIB_POWERPLAYTABLE4 +{ + ATOM_PPLIB_POWERPLAYTABLE3 basicTable3; + ULONG ulGoldenPPID; // PPGen use only + ULONG ulGoldenRevision; // PPGen use only + USHORT usVddcDependencyOnSCLKOffset; + USHORT usVddciDependencyOnMCLKOffset; + USHORT usVddcDependencyOnMCLKOffset; + USHORT usMaxClockVoltageOnDCOffset; + USHORT usReserved[2]; +} ATOM_PPLIB_POWERPLAYTABLE4, *LPATOM_PPLIB_POWERPLAYTABLE4; + +typedef struct _ATOM_PPLIB_POWERPLAYTABLE5 +{ + ATOM_PPLIB_POWERPLAYTABLE4 basicTable4; + ULONG ulTDPLimit; + ULONG ulNearTDPLimit; + ULONG ulSQRampingThreshold; + USHORT usCACLeakageTableOffset; // Points to ATOM_PPLIB_CAC_Leakage_Table + ULONG ulCACLeakage; // TBD, this parameter is still under discussion. Change to ulReserved if not needed. + ULONG ulReserved; +} ATOM_PPLIB_POWERPLAYTABLE5, *LPATOM_PPLIB_POWERPLAYTABLE5; + //// ATOM_PPLIB_NONCLOCK_INFO::usClassification #define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 #define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 @@ -5864,6 +6628,10 @@ #define ATOM_PPLIB_CLASSIFICATION_HDSTATE 0x4000 #define ATOM_PPLIB_CLASSIFICATION_SDSTATE 0x8000 +//// ATOM_PPLIB_NONCLOCK_INFO::usClassification2 +#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001 +#define ATOM_PPLIB_CLASSIFICATION2_ULV 0x0002 + //// ATOM_PPLIB_NONCLOCK_INFO::ulCapsAndSettings #define ATOM_PPLIB_SINGLE_DISPLAY_ONLY 0x00000001 #define ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK 0x00000002 @@ -5896,9 +6664,21 @@ #define ATOM_PPLIB_M3ARB_MASK 0x00060000 #define ATOM_PPLIB_M3ARB_SHIFT 17 +#define ATOM_PPLIB_ENABLE_DRR 0x00080000 + +// remaining 16 bits are reserved +typedef struct _ATOM_PPLIB_THERMAL_STATE +{ + UCHAR ucMinTemperature; + UCHAR ucMaxTemperature; + UCHAR ucThermalAction; +}ATOM_PPLIB_THERMAL_STATE, *LPATOM_PPLIB_THERMAL_STATE; + // Contained in an array starting at the offset // in ATOM_PPLIB_POWERPLAYTABLE::usNonClockInfoArrayOffset. // referenced from ATOM_PPLIB_STATE_INFO::ucNonClockStateIndex +#define ATOM_PPLIB_NONCLOCKINFO_VER1 12 +#define ATOM_PPLIB_NONCLOCKINFO_VER2 24 typedef struct _ATOM_PPLIB_NONCLOCK_INFO { USHORT usClassification; @@ -5906,15 +6686,15 @@ UCHAR ucMaxTemperature; ULONG ulCapsAndSettings; UCHAR ucRequiredPower; - UCHAR ucUnused1[3]; + USHORT usClassification2; + ULONG ulVCLK; + ULONG ulDCLK; + UCHAR ucUnused[5]; } ATOM_PPLIB_NONCLOCK_INFO; // Contained in an array starting at the offset // in ATOM_PPLIB_POWERPLAYTABLE::usClockInfoArrayOffset. // referenced from ATOM_PPLIB_STATE::ucClockStateIndices -#define ATOM_PPLIB_NONCLOCKINFO_VER1 12 -#define ATOM_PPLIB_NONCLOCKINFO_VER2 24 - typedef struct _ATOM_PPLIB_R600_CLOCK_INFO { USHORT usEngineClockLow; @@ -5985,6 +6765,93 @@ #define ATOM_PPLIB_RS780_HTLINKFREQ_LOW 1 #define ATOM_PPLIB_RS780_HTLINKFREQ_HIGH 2 +typedef struct _ATOM_PPLIB_SUMO_CLOCK_INFO{ + USHORT usEngineClockLow; //clockfrequency & 0xFFFF. The unit is in 10khz + UCHAR ucEngineClockHigh; //clockfrequency >> 16. + UCHAR vddcIndex; //2-bit vddc index; + UCHAR leakage; //please use 8-bit absolute value, not the 6-bit % value + //please initalize to 0 + UCHAR rsv; + //please initalize to 0 + USHORT rsv1; + //please initialize to 0s + ULONG rsv2[2]; +}ATOM_PPLIB_SUMO_CLOCK_INFO; + + + +typedef struct _ATOM_PPLIB_STATE_V2 +{ + //number of valid dpm levels in this state; Driver uses it to calculate the whole + //size of the state: sizeof(ATOM_PPLIB_STATE_V2) + (ucNumDPMLevels - 1) * sizeof(UCHAR) + UCHAR ucNumDPMLevels; + + //a index to the array of nonClockInfos + UCHAR nonClockInfoIndex; + /** + * Driver will read the first ucNumDPMLevels in this array + */ + UCHAR clockInfoIndex[1]; +} ATOM_PPLIB_STATE_V2; + +typedef struct StateArray{ + //how many states we have + UCHAR ucNumEntries; + + ATOM_PPLIB_STATE_V2 states[1]; +}StateArray; + + +typedef struct ClockInfoArray{ + //how many clock levels we have + UCHAR ucNumEntries; + + //sizeof(ATOM_PPLIB_SUMO_CLOCK_INFO) + UCHAR ucEntrySize; + + //this is for Sumo + ATOM_PPLIB_SUMO_CLOCK_INFO clockInfo[1]; +}ClockInfoArray; + +typedef struct NonClockInfoArray{ + + //how many non-clock levels we have. normally should be same as number of states + UCHAR ucNumEntries; + //sizeof(ATOM_PPLIB_NONCLOCK_INFO) + UCHAR ucEntrySize; + + ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[1]; +}NonClockInfoArray; + +typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record +{ + USHORT usClockLow; + UCHAR ucClockHigh; + USHORT usVoltage; +}ATOM_PPLIB_Clock_Voltage_Dependency_Record; + +typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Table +{ + UCHAR ucNumEntries; // Number of entries. + ATOM_PPLIB_Clock_Voltage_Dependency_Record entries[1]; // Dynamically allocate entries. +}ATOM_PPLIB_Clock_Voltage_Dependency_Table; + +typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Record +{ + USHORT usSclkLow; + UCHAR ucSclkHigh; + USHORT usMclkLow; + UCHAR ucMclkHigh; + USHORT usVddc; + USHORT usVddci; +}ATOM_PPLIB_Clock_Voltage_Limit_Record; + +typedef struct _ATOM_PPLIB_Clock_Voltage_Limit_Table +{ + UCHAR ucNumEntries; // Number of entries. + ATOM_PPLIB_Clock_Voltage_Limit_Record entries[1]; // Dynamically allocate entries. +}ATOM_PPLIB_Clock_Voltage_Limit_Table; + /**************************************************************************/ --- linux-2.6.37.orig/drivers/gpu/drm/radeon/evergreen.c +++ linux-2.6.37/drivers/gpu/drm/radeon/evergreen.c @@ -40,6 +40,61 @@ static void evergreen_gpu_init(struct radeon_device *rdev); void evergreen_fini(struct radeon_device *rdev); +void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + u32 tmp; + + /* make sure flip is at vb rather than hb */ + tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); + tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN; + WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); + + /* set pageflip to happen anywhere in vblank interval */ + WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); + + /* enable the pflip int */ + radeon_irq_kms_pflip_irq_get(rdev, crtc); +} + +void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) +{ + /* disable the pflip int */ + radeon_irq_kms_pflip_irq_put(rdev, crtc); +} + +u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); + + /* Lock the graphics update lock */ + tmp |= EVERGREEN_GRPH_UPDATE_LOCK; + WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* update the scanout addresses */ + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, + upper_32_bits(crtc_base)); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, + upper_32_bits(crtc_base)); + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + + /* Wait for update_pending to go high. */ + while (!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING)); + DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); + + /* Unlock the lock, so double-buffering can take place inside vblank */ + tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK; + WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* Return current update_pending status: */ + return RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING; +} + /* get temperature in millidegrees */ u32 evergreen_get_temp(struct radeon_device *rdev) { @@ -57,6 +112,14 @@ return actual_temp * 1000; } +u32 sumo_get_temp(struct radeon_device *rdev) +{ + u32 temp = RREG32(CG_THERMAL_STATUS) & 0xff; + u32 actual_temp = (temp >> 1) & 0xff; + + return actual_temp * 1000; +} + void evergreen_pm_misc(struct radeon_device *rdev) { int req_ps_idx = rdev->pm.requested_power_state_index; @@ -890,31 +953,39 @@ save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); - save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); - save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); - save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); - save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); + if (!(rdev->flags & RADEON_IS_IGP)) { + save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); + save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); + save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); + save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); + } /* Stop all video */ WREG32(VGA_RENDER_CONTROL, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); + if (!(rdev->flags & RADEON_IS_IGP)) { + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); + } WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + if (!(rdev->flags & RADEON_IS_IGP)) { + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + if (!(rdev->flags & RADEON_IS_IGP)) { + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } WREG32(D1VGA_CONTROL, 0); WREG32(D2VGA_CONTROL, 0); @@ -944,41 +1015,43 @@ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); + if (!(rdev->flags & RADEON_IS_IGP)) { + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, + upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, + upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, + (u32)rdev->mc.vram_start); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, + (u32)rdev->mc.vram_start); + + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, + upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, + upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, + (u32)rdev->mc.vram_start); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, + (u32)rdev->mc.vram_start); + + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, + upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, + upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, + (u32)rdev->mc.vram_start); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, + (u32)rdev->mc.vram_start); + + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, + upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, + upper_32_bits(rdev->mc.vram_start)); + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, + (u32)rdev->mc.vram_start); + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, + (u32)rdev->mc.vram_start); + } WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); @@ -994,22 +1067,28 @@ WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); + if (!(rdev->flags & RADEON_IS_IGP)) { + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); + } WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); + if (!(rdev->flags & RADEON_IS_IGP)) { + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); + WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); + } WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + if (!(rdev->flags & RADEON_IS_IGP)) { + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } WREG32(VGA_RENDER_CONTROL, save->vga_render_control); } @@ -1057,6 +1136,12 @@ rdev->mc.vram_end >> 12); } WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); + if (rdev->flags & RADEON_IS_IGP) { + tmp = RREG32(MC_FUS_VM_FB_OFFSET) & 0x000FFFFF; + tmp |= ((rdev->mc.vram_end >> 20) & 0xF) << 24; + tmp |= ((rdev->mc.vram_start >> 20) & 0xF) << 20; + WREG32(MC_FUS_VM_FB_OFFSET, tmp); + } tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); WREG32(MC_VM_FB_LOCATION, tmp); @@ -1285,6 +1370,7 @@ switch (rdev->family) { case CHIP_CEDAR: case CHIP_REDWOOD: + case CHIP_PALM: force_no_swizzle = false; break; case CHIP_CYPRESS: @@ -1384,6 +1470,43 @@ return backend_map; } +static void evergreen_program_channel_remap(struct radeon_device *rdev) +{ + u32 tcp_chan_steer_lo, tcp_chan_steer_hi, mc_shared_chremap, tmp; + + tmp = RREG32(MC_SHARED_CHMAP); + switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { + case 0: + case 1: + case 2: + case 3: + default: + /* default mapping */ + mc_shared_chremap = 0x00fac688; + break; + } + + switch (rdev->family) { + case CHIP_HEMLOCK: + case CHIP_CYPRESS: + tcp_chan_steer_lo = 0x54763210; + tcp_chan_steer_hi = 0x0000ba98; + break; + case CHIP_JUNIPER: + case CHIP_REDWOOD: + case CHIP_CEDAR: + case CHIP_PALM: + default: + tcp_chan_steer_lo = 0x76543210; + tcp_chan_steer_hi = 0x0000ba98; + break; + } + + WREG32(TCP_CHAN_STEER_LO, tcp_chan_steer_lo); + WREG32(TCP_CHAN_STEER_HI, tcp_chan_steer_hi); + WREG32(MC_SHARED_CHREMAP, mc_shared_chremap); +} + static void evergreen_gpu_init(struct radeon_device *rdev) { u32 cc_rb_backend_disable = 0; @@ -1495,6 +1618,27 @@ rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; break; + case CHIP_PALM: + rdev->config.evergreen.num_ses = 1; + rdev->config.evergreen.max_pipes = 2; + rdev->config.evergreen.max_tile_pipes = 2; + rdev->config.evergreen.max_simds = 2; + rdev->config.evergreen.max_backends = 1 * rdev->config.evergreen.num_ses; + rdev->config.evergreen.max_gprs = 256; + rdev->config.evergreen.max_threads = 192; + rdev->config.evergreen.max_gs_threads = 16; + rdev->config.evergreen.max_stack_entries = 256; + rdev->config.evergreen.sx_num_of_sets = 4; + rdev->config.evergreen.sx_max_export_size = 128; + rdev->config.evergreen.sx_max_export_pos_size = 32; + rdev->config.evergreen.sx_max_export_smx_size = 96; + rdev->config.evergreen.max_hw_contexts = 4; + rdev->config.evergreen.sq_num_cf_insts = 1; + + rdev->config.evergreen.sc_prim_fifo_size = 0x40; + rdev->config.evergreen.sc_hiz_tile_fifo_size = 0x30; + rdev->config.evergreen.sc_earlyz_tile_fifo_size = 0x130; + break; } /* Initialize HDP */ @@ -1687,6 +1831,8 @@ WREG32(DMIF_ADDR_CONFIG, gb_addr_config); WREG32(HDP_ADDR_CONFIG, gb_addr_config); + evergreen_program_channel_remap(rdev); + num_shader_engines = ((RREG32(GB_ADDR_CONFIG) & NUM_SHADER_ENGINES(3)) >> 12) + 1; grbm_gfx_index = INSTANCE_BROADCAST_WRITES; @@ -1769,9 +1915,15 @@ GS_PRIO(2) | ES_PRIO(3)); - if (rdev->family == CHIP_CEDAR) + switch (rdev->family) { + case CHIP_CEDAR: + case CHIP_PALM: /* no vertex cache */ sq_config &= ~VC_ENABLE; + break; + default: + break; + } sq_lds_resource_mgmt = RREG32(SQ_LDS_RESOURCE_MGMT); @@ -1783,10 +1935,15 @@ sq_gpr_resource_mgmt_3 = NUM_HS_GPRS((rdev->config.evergreen.max_gprs - (4 * 2)) * 3 / 32); sq_gpr_resource_mgmt_3 |= NUM_LS_GPRS((rdev->config.evergreen.max_gprs - (4 * 2)) * 3 / 32); - if (rdev->family == CHIP_CEDAR) + switch (rdev->family) { + case CHIP_CEDAR: + case CHIP_PALM: ps_thread_count = 96; - else + break; + default: ps_thread_count = 128; + break; + } sq_thread_resource_mgmt = NUM_PS_THREADS(ps_thread_count); sq_thread_resource_mgmt |= NUM_VS_THREADS((((rdev->config.evergreen.max_threads - ps_thread_count) / 6) / 8) * 8); @@ -1817,10 +1974,15 @@ WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) | FORCE_EOV_MAX_REZ_CNT(255))); - if (rdev->family == CHIP_CEDAR) + switch (rdev->family) { + case CHIP_CEDAR: + case CHIP_PALM: vgt_cache_invalidation = CACHE_INVALIDATION(TC_ONLY); - else + break; + default: vgt_cache_invalidation = CACHE_INVALIDATION(VC_AND_TC); + break; + } vgt_cache_invalidation |= AUTO_INVLD_EN(ES_AND_GS_AUTO); WREG32(VGT_CACHE_INVALIDATION, vgt_cache_invalidation); @@ -1904,12 +2066,18 @@ rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); /* Setup GPU memory space */ - /* size in MB on evergreen */ - rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; - rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; + if (rdev->flags & RADEON_IS_IGP) { + /* size in bytes on fusion */ + rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); + rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); + } else { + /* size in MB on evergreen */ + rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; + rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; + } rdev->mc.visible_vram_size = rdev->mc.aper_size; rdev->mc.active_vram_size = rdev->mc.visible_vram_size; - r600_vram_gtt_location(rdev, &rdev->mc); + r700_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); return 0; @@ -2011,17 +2179,21 @@ WREG32(GRBM_INT_CNTL, 0); WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + if (!(rdev->flags & RADEON_IS_IGP)) { + WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + if (!(rdev->flags & RADEON_IS_IGP)) { + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + } WREG32(DACA_AUTODETECT_INT_CONTROL, 0); WREG32(DACB_AUTODETECT_INT_CONTROL, 0); @@ -2047,6 +2219,7 @@ u32 crtc1 = 0, crtc2 = 0, crtc3 = 0, crtc4 = 0, crtc5 = 0, crtc6 = 0; u32 hpd1, hpd2, hpd3, hpd4, hpd5, hpd6; u32 grbm_int_cntl = 0; + u32 grph1 = 0, grph2 = 0, grph3 = 0, grph4 = 0, grph5 = 0, grph6 = 0; if (!rdev->irq.installed) { WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); @@ -2072,27 +2245,33 @@ cp_int_cntl |= RB_INT_ENABLE; cp_int_cntl |= TIME_STAMP_INT_ENABLE; } - if (rdev->irq.crtc_vblank_int[0]) { + if (rdev->irq.crtc_vblank_int[0] || + rdev->irq.pflip[0]) { DRM_DEBUG("evergreen_irq_set: vblank 0\n"); crtc1 |= VBLANK_INT_MASK; } - if (rdev->irq.crtc_vblank_int[1]) { + if (rdev->irq.crtc_vblank_int[1] || + rdev->irq.pflip[1]) { DRM_DEBUG("evergreen_irq_set: vblank 1\n"); crtc2 |= VBLANK_INT_MASK; } - if (rdev->irq.crtc_vblank_int[2]) { + if (rdev->irq.crtc_vblank_int[2] || + rdev->irq.pflip[2]) { DRM_DEBUG("evergreen_irq_set: vblank 2\n"); crtc3 |= VBLANK_INT_MASK; } - if (rdev->irq.crtc_vblank_int[3]) { + if (rdev->irq.crtc_vblank_int[3] || + rdev->irq.pflip[3]) { DRM_DEBUG("evergreen_irq_set: vblank 3\n"); crtc4 |= VBLANK_INT_MASK; } - if (rdev->irq.crtc_vblank_int[4]) { + if (rdev->irq.crtc_vblank_int[4] || + rdev->irq.pflip[4]) { DRM_DEBUG("evergreen_irq_set: vblank 4\n"); crtc5 |= VBLANK_INT_MASK; } - if (rdev->irq.crtc_vblank_int[5]) { + if (rdev->irq.crtc_vblank_int[5] || + rdev->irq.pflip[5]) { DRM_DEBUG("evergreen_irq_set: vblank 5\n"); crtc6 |= VBLANK_INT_MASK; } @@ -2130,10 +2309,19 @@ WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1); WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2); - WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3); - WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4); - WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5); - WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); + if (!(rdev->flags & RADEON_IS_IGP)) { + WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3); + WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4); + WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5); + WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6); + } + + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); + WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); WREG32(DC_HPD1_INT_CONTROL, hpd1); WREG32(DC_HPD2_INT_CONTROL, hpd2); @@ -2145,79 +2333,92 @@ return 0; } -static inline void evergreen_irq_ack(struct radeon_device *rdev, - u32 *disp_int, - u32 *disp_int_cont, - u32 *disp_int_cont2, - u32 *disp_int_cont3, - u32 *disp_int_cont4, - u32 *disp_int_cont5) +static inline void evergreen_irq_ack(struct radeon_device *rdev) { u32 tmp; - *disp_int = RREG32(DISP_INTERRUPT_STATUS); - *disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); - *disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2); - *disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3); - *disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4); - *disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5); + rdev->irq.stat_regs.evergreen.disp_int = RREG32(DISP_INTERRUPT_STATUS); + rdev->irq.stat_regs.evergreen.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); + rdev->irq.stat_regs.evergreen.disp_int_cont2 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE2); + rdev->irq.stat_regs.evergreen.disp_int_cont3 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE3); + rdev->irq.stat_regs.evergreen.disp_int_cont4 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE4); + rdev->irq.stat_regs.evergreen.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5); + rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); + rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); + + if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED) + WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); - if (*disp_int & LB_D1_VBLANK_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK); - if (*disp_int & LB_D1_VLINE_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VLINE_ACK); - if (*disp_int_cont & LB_D2_VBLANK_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VBLANK_ACK); - if (*disp_int_cont & LB_D2_VLINE_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK); - if (*disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); - if (*disp_int_cont2 & LB_D3_VLINE_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK); - if (*disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK); - if (*disp_int_cont3 & LB_D4_VLINE_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK); - if (*disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); - if (*disp_int_cont4 & LB_D5_VLINE_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK); - if (*disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK); - if (*disp_int_cont5 & LB_D6_VLINE_INTERRUPT) + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK); - if (*disp_int & DC_HPD1_INTERRUPT) { + if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { tmp = RREG32(DC_HPD1_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD1_INT_CONTROL, tmp); } - if (*disp_int_cont & DC_HPD2_INTERRUPT) { + if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { tmp = RREG32(DC_HPD2_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD2_INT_CONTROL, tmp); } - if (*disp_int_cont2 & DC_HPD3_INTERRUPT) { + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { tmp = RREG32(DC_HPD3_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD3_INT_CONTROL, tmp); } - if (*disp_int_cont3 & DC_HPD4_INTERRUPT) { + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { tmp = RREG32(DC_HPD4_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD4_INT_CONTROL, tmp); } - if (*disp_int_cont4 & DC_HPD5_INTERRUPT) { + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { tmp = RREG32(DC_HPD5_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD5_INT_CONTROL, tmp); } - if (*disp_int_cont5 & DC_HPD6_INTERRUPT) { + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { tmp = RREG32(DC_HPD5_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD6_INT_CONTROL, tmp); @@ -2226,14 +2427,10 @@ void evergreen_irq_disable(struct radeon_device *rdev) { - u32 disp_int, disp_int_cont, disp_int_cont2; - u32 disp_int_cont3, disp_int_cont4, disp_int_cont5; - r600_disable_interrupts(rdev); /* Wait and acknowledge irq */ mdelay(1); - evergreen_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2, - &disp_int_cont3, &disp_int_cont4, &disp_int_cont5); + evergreen_irq_ack(rdev); evergreen_disable_interrupt_state(rdev); } @@ -2273,8 +2470,6 @@ u32 rptr = rdev->ih.rptr; u32 src_id, src_data; u32 ring_index; - u32 disp_int, disp_int_cont, disp_int_cont2; - u32 disp_int_cont3, disp_int_cont4, disp_int_cont5; unsigned long flags; bool queue_hotplug = false; @@ -2295,8 +2490,7 @@ restart_ih: /* display interrupts */ - evergreen_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2, - &disp_int_cont3, &disp_int_cont4, &disp_int_cont5); + evergreen_irq_ack(rdev); rdev->ih.wptr = wptr; while (rptr != wptr) { @@ -2309,17 +2503,21 @@ case 1: /* D1 vblank/vline */ switch (src_data) { case 0: /* D1 vblank */ - if (disp_int & LB_D1_VBLANK_INTERRUPT) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - disp_int &= ~LB_D1_VBLANK_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[0]) + radeon_crtc_handle_flip(rdev, 0); + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); } break; case 1: /* D1 vline */ - if (disp_int & LB_D1_VLINE_INTERRUPT) { - disp_int &= ~LB_D1_VLINE_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; DRM_DEBUG("IH: D1 vline\n"); } break; @@ -2331,17 +2529,21 @@ case 2: /* D2 vblank/vline */ switch (src_data) { case 0: /* D2 vblank */ - if (disp_int_cont & LB_D2_VBLANK_INTERRUPT) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[1]) + radeon_crtc_handle_flip(rdev, 1); + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); } break; case 1: /* D2 vline */ - if (disp_int_cont & LB_D2_VLINE_INTERRUPT) { - disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; DRM_DEBUG("IH: D2 vline\n"); } break; @@ -2353,17 +2555,21 @@ case 3: /* D3 vblank/vline */ switch (src_data) { case 0: /* D3 vblank */ - if (disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { - drm_handle_vblank(rdev->ddev, 2); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[2]) { + drm_handle_vblank(rdev->ddev, 2); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[2]) + radeon_crtc_handle_flip(rdev, 2); + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); } break; case 1: /* D3 vline */ - if (disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { - disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; DRM_DEBUG("IH: D3 vline\n"); } break; @@ -2375,17 +2581,21 @@ case 4: /* D4 vblank/vline */ switch (src_data) { case 0: /* D4 vblank */ - if (disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { - drm_handle_vblank(rdev->ddev, 3); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[3]) { + drm_handle_vblank(rdev->ddev, 3); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[3]) + radeon_crtc_handle_flip(rdev, 3); + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); } break; case 1: /* D4 vline */ - if (disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { - disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; DRM_DEBUG("IH: D4 vline\n"); } break; @@ -2397,17 +2607,21 @@ case 5: /* D5 vblank/vline */ switch (src_data) { case 0: /* D5 vblank */ - if (disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { - drm_handle_vblank(rdev->ddev, 4); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[4]) { + drm_handle_vblank(rdev->ddev, 4); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[4]) + radeon_crtc_handle_flip(rdev, 4); + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); } break; case 1: /* D5 vline */ - if (disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { - disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; DRM_DEBUG("IH: D5 vline\n"); } break; @@ -2419,17 +2633,21 @@ case 6: /* D6 vblank/vline */ switch (src_data) { case 0: /* D6 vblank */ - if (disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { - drm_handle_vblank(rdev->ddev, 5); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[5]) { + drm_handle_vblank(rdev->ddev, 5); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[5]) + radeon_crtc_handle_flip(rdev, 5); + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); } break; case 1: /* D6 vline */ - if (disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { - disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; DRM_DEBUG("IH: D6 vline\n"); } break; @@ -2441,43 +2659,43 @@ case 42: /* HPD hotplug */ switch (src_data) { case 0: - if (disp_int & DC_HPD1_INTERRUPT) { - disp_int &= ~DC_HPD1_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD1\n"); } break; case 1: - if (disp_int_cont & DC_HPD2_INTERRUPT) { - disp_int_cont &= ~DC_HPD2_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD2\n"); } break; case 2: - if (disp_int_cont2 & DC_HPD3_INTERRUPT) { - disp_int_cont2 &= ~DC_HPD3_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD3\n"); } break; case 3: - if (disp_int_cont3 & DC_HPD4_INTERRUPT) { - disp_int_cont3 &= ~DC_HPD4_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD4\n"); } break; case 4: - if (disp_int_cont4 & DC_HPD5_INTERRUPT) { - disp_int_cont4 &= ~DC_HPD5_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD5\n"); } break; case 5: - if (disp_int_cont5 & DC_HPD6_INTERRUPT) { - disp_int_cont5 &= ~DC_HPD6_INTERRUPT; + if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { + rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD6\n"); } @@ -2658,12 +2876,16 @@ u32 reg; /* first check CRTCs */ - reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); + if (rdev->flags & RADEON_IS_IGP) + reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); + else + reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); if (reg & EVERGREEN_CRTC_MASTER_EN) return true; --- linux-2.6.37.orig/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ linux-2.6.37/drivers/gpu/drm/radeon/evergreen_blit_kms.c @@ -147,7 +147,8 @@ radeon_ring_write(rdev, 0); radeon_ring_write(rdev, SQ_TEX_VTX_VALID_BUFFER << 30); - if (rdev->family == CHIP_CEDAR) + if ((rdev->family == CHIP_CEDAR) || + (rdev->family == CHIP_PALM)) cp_set_surface_sync(rdev, PACKET3_TC_ACTION_ENA, 48, gpu_addr); else @@ -331,9 +332,31 @@ num_hs_stack_entries = 85; num_ls_stack_entries = 85; break; + case CHIP_PALM: + num_ps_gprs = 93; + num_vs_gprs = 46; + num_temp_gprs = 4; + num_gs_gprs = 31; + num_es_gprs = 31; + num_hs_gprs = 23; + num_ls_gprs = 23; + num_ps_threads = 96; + num_vs_threads = 16; + num_gs_threads = 16; + num_es_threads = 16; + num_hs_threads = 16; + num_ls_threads = 16; + num_ps_stack_entries = 42; + num_vs_stack_entries = 42; + num_gs_stack_entries = 42; + num_es_stack_entries = 42; + num_hs_stack_entries = 42; + num_ls_stack_entries = 42; + break; } - if (rdev->family == CHIP_CEDAR) + if ((rdev->family == CHIP_CEDAR) || + (rdev->family == CHIP_PALM)) sq_config = 0; else sq_config = VC_ENABLE; --- linux-2.6.37.orig/drivers/gpu/drm/radeon/evergreen_reg.h +++ linux-2.6.37/drivers/gpu/drm/radeon/evergreen_reg.h @@ -105,6 +105,11 @@ #define EVERGREEN_GRPH_Y_START 0x6830 #define EVERGREEN_GRPH_X_END 0x6834 #define EVERGREEN_GRPH_Y_END 0x6838 +#define EVERGREEN_GRPH_UPDATE 0x6844 +# define EVERGREEN_GRPH_SURFACE_UPDATE_PENDING (1 << 2) +# define EVERGREEN_GRPH_UPDATE_LOCK (1 << 16) +#define EVERGREEN_GRPH_FLIP_CONTROL 0x6848 +# define EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN (1 << 0) /* CUR blocks at 0x6998, 0x7598, 0x10198, 0x10d98, 0x11998, 0x12598 */ #define EVERGREEN_CUR_CONTROL 0x6998 @@ -178,6 +183,7 @@ # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) #define EVERGREEN_CRTC_STATUS 0x6e8c #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 +#define EVERGREEN_MASTER_UPDATE_MODE 0x6ef8 #define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 #define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0 --- linux-2.6.37.orig/drivers/gpu/drm/radeon/evergreend.h +++ linux-2.6.37/drivers/gpu/drm/radeon/evergreend.h @@ -164,11 +164,13 @@ #define SE_SC_BUSY (1 << 29) #define SE_DB_BUSY (1 << 30) #define SE_CB_BUSY (1 << 31) - +/* evergreen */ #define CG_MULT_THERMAL_STATUS 0x740 #define ASIC_T(x) ((x) << 16) #define ASIC_T_MASK 0x7FF0000 #define ASIC_T_SHIFT 16 +/* APU */ +#define CG_THERMAL_STATUS 0x678 #define HDP_HOST_PATH_CNTL 0x2C00 #define HDP_NONSURFACE_BASE 0x2C04 @@ -181,6 +183,7 @@ #define MC_SHARED_CHMAP 0x2004 #define NOOFCHAN_SHIFT 12 #define NOOFCHAN_MASK 0x00003000 +#define MC_SHARED_CHREMAP 0x2008 #define MC_ARB_RAMCFG 0x2760 #define NOOFBANK_SHIFT 0 @@ -200,6 +203,7 @@ #define MC_VM_AGP_BOT 0x202C #define MC_VM_AGP_BASE 0x2030 #define MC_VM_FB_LOCATION 0x2024 +#define MC_FUS_VM_FB_OFFSET 0x2898 #define MC_VM_MB_L1_TLB0_CNTL 0x2234 #define MC_VM_MB_L1_TLB1_CNTL 0x2238 #define MC_VM_MB_L1_TLB2_CNTL 0x223C @@ -349,6 +353,9 @@ #define SYNC_WALKER (1 << 25) #define SYNC_ALIGNER (1 << 26) +#define TCP_CHAN_STEER_LO 0x960c +#define TCP_CHAN_STEER_HI 0x9610 + #define VGT_CACHE_INVALIDATION 0x88C4 #define CACHE_INVALIDATION(x) ((x) << 0) #define VC_ONLY 0 --- linux-2.6.37.orig/drivers/gpu/drm/radeon/r100.c +++ linux-2.6.37/drivers/gpu/drm/radeon/r100.c @@ -68,6 +68,56 @@ * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ +void r100_pre_page_flip(struct radeon_device *rdev, int crtc) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + u32 tmp; + + /* make sure flip is at vb rather than hb */ + tmp = RREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset); + tmp &= ~RADEON_CRTC_OFFSET_FLIP_CNTL; + /* make sure pending bit is asserted */ + tmp |= RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN; + WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, tmp); + + /* set pageflip to happen as late as possible in the vblank interval. + * same field for crtc1/2 + */ + tmp = RREG32(RADEON_CRTC_GEN_CNTL); + tmp &= ~RADEON_CRTC_VSTAT_MODE_MASK; + WREG32(RADEON_CRTC_GEN_CNTL, tmp); + + /* enable the pflip int */ + radeon_irq_kms_pflip_irq_get(rdev, crtc); +} + +void r100_post_page_flip(struct radeon_device *rdev, int crtc) +{ + /* disable the pflip int */ + radeon_irq_kms_pflip_irq_put(rdev, crtc); +} + +u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; + + /* Lock the graphics update lock */ + /* update the scanout addresses */ + WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); + + /* Wait for update_pending to go high. */ + while (!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)); + DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); + + /* Unlock the lock, so double-buffering can take place inside vblank */ + tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK; + WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); + + /* Return current update_pending status: */ + return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; +} + void r100_pm_get_dynpm_state(struct radeon_device *rdev) { int i; @@ -526,10 +576,12 @@ if (rdev->irq.gui_idle) { tmp |= RADEON_GUI_IDLE_MASK; } - if (rdev->irq.crtc_vblank_int[0]) { + if (rdev->irq.crtc_vblank_int[0] || + rdev->irq.pflip[0]) { tmp |= RADEON_CRTC_VBLANK_MASK; } - if (rdev->irq.crtc_vblank_int[1]) { + if (rdev->irq.crtc_vblank_int[1] || + rdev->irq.pflip[1]) { tmp |= RADEON_CRTC2_VBLANK_MASK; } if (rdev->irq.hpd[0]) { @@ -600,14 +652,22 @@ } /* Vertical blank interrupts */ if (status & RADEON_CRTC_VBLANK_STAT) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[0]) + radeon_crtc_handle_flip(rdev, 0); } if (status & RADEON_CRTC2_VBLANK_STAT) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[1]) + radeon_crtc_handle_flip(rdev, 1); } if (status & RADEON_FP_DETECT_STAT) { queue_hotplug = true; --- linux-2.6.37.orig/drivers/gpu/drm/radeon/r500_reg.h +++ linux-2.6.37/drivers/gpu/drm/radeon/r500_reg.h @@ -355,6 +355,8 @@ #define AVIVO_D1CRTC_FRAME_COUNT 0x60a4 #define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 +#define AVIVO_D1MODE_MASTER_UPDATE_MODE 0x60e4 + /* master controls */ #define AVIVO_DC_CRTC_MASTER_EN 0x60f8 #define AVIVO_DC_CRTC_TV_CONTROL 0x60fc @@ -409,8 +411,10 @@ #define AVIVO_D1GRPH_X_END 0x6134 #define AVIVO_D1GRPH_Y_END 0x6138 #define AVIVO_D1GRPH_UPDATE 0x6144 +# define AVIVO_D1GRPH_SURFACE_UPDATE_PENDING (1 << 2) # define AVIVO_D1GRPH_UPDATE_LOCK (1 << 16) #define AVIVO_D1GRPH_FLIP_CONTROL 0x6148 +# define AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN (1 << 0) #define AVIVO_D1CUR_CONTROL 0x6400 # define AVIVO_D1CURSOR_EN (1 << 0) --- linux-2.6.37.orig/drivers/gpu/drm/radeon/r600.c +++ linux-2.6.37/drivers/gpu/drm/radeon/r600.c @@ -83,6 +83,9 @@ MODULE_FIRMWARE("radeon/CYPRESS_pfp.bin"); MODULE_FIRMWARE("radeon/CYPRESS_me.bin"); MODULE_FIRMWARE("radeon/CYPRESS_rlc.bin"); +MODULE_FIRMWARE("radeon/PALM_pfp.bin"); +MODULE_FIRMWARE("radeon/PALM_me.bin"); +MODULE_FIRMWARE("radeon/SUMO_rlc.bin"); int r600_debugfs_mc_info_init(struct radeon_device *rdev); @@ -1164,7 +1167,7 @@ * Note: GTT start, end, size should be initialized before calling this * function on AGP platform. */ -void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) +static void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) { u64 size_bf, size_af; @@ -2009,6 +2012,10 @@ chip_name = "CYPRESS"; rlc_chip_name = "CYPRESS"; break; + case CHIP_PALM: + chip_name = "PALM"; + rlc_chip_name = "SUMO"; + break; default: BUG(); } @@ -2874,6 +2881,8 @@ WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); WREG32(GRBM_INT_CNTL, 0); WREG32(DxMODE_INT_MASK, 0); + WREG32(D1GRPH_INTERRUPT_CONTROL, 0); + WREG32(D2GRPH_INTERRUPT_CONTROL, 0); if (ASIC_IS_DCE3(rdev)) { WREG32(DCE3_DACA_AUTODETECT_INT_CONTROL, 0); WREG32(DCE3_DACB_AUTODETECT_INT_CONTROL, 0); @@ -2998,6 +3007,7 @@ u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; u32 grbm_int_cntl = 0; u32 hdmi1, hdmi2; + u32 d1grph = 0, d2grph = 0; if (!rdev->irq.installed) { WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); @@ -3034,11 +3044,13 @@ cp_int_cntl |= RB_INT_ENABLE; cp_int_cntl |= TIME_STAMP_INT_ENABLE; } - if (rdev->irq.crtc_vblank_int[0]) { + if (rdev->irq.crtc_vblank_int[0] || + rdev->irq.pflip[0]) { DRM_DEBUG("r600_irq_set: vblank 0\n"); mode_int |= D1MODE_VBLANK_INT_MASK; } - if (rdev->irq.crtc_vblank_int[1]) { + if (rdev->irq.crtc_vblank_int[1] || + rdev->irq.pflip[1]) { DRM_DEBUG("r600_irq_set: vblank 1\n"); mode_int |= D2MODE_VBLANK_INT_MASK; } @@ -3081,6 +3093,8 @@ WREG32(CP_INT_CNTL, cp_int_cntl); WREG32(DxMODE_INT_MASK, mode_int); + WREG32(D1GRPH_INTERRUPT_CONTROL, d1grph); + WREG32(D2GRPH_INTERRUPT_CONTROL, d2grph); WREG32(GRBM_INT_CNTL, grbm_int_cntl); WREG32(R600_HDMI_BLOCK1 + R600_HDMI_CNTL, hdmi1); if (ASIC_IS_DCE3(rdev)) { @@ -3103,32 +3117,35 @@ return 0; } -static inline void r600_irq_ack(struct radeon_device *rdev, - u32 *disp_int, - u32 *disp_int_cont, - u32 *disp_int_cont2) +static inline void r600_irq_ack(struct radeon_device *rdev) { u32 tmp; if (ASIC_IS_DCE3(rdev)) { - *disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); - *disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); - *disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); - } else { - *disp_int = RREG32(DISP_INTERRUPT_STATUS); - *disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); - *disp_int_cont2 = 0; - } - - if (*disp_int & LB_D1_VBLANK_INTERRUPT) + rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); + rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); + rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); + } else { + rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS); + rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); + rdev->irq.stat_regs.r600.disp_int_cont2 = 0; + } + rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS); + rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS); + + if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED) + WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED) + WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); + if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); - if (*disp_int & LB_D1_VLINE_INTERRUPT) + if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK); - if (*disp_int & LB_D2_VBLANK_INTERRUPT) + if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); - if (*disp_int & LB_D2_VLINE_INTERRUPT) + if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK); - if (*disp_int & DC_HPD1_INTERRUPT) { + if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { if (ASIC_IS_DCE3(rdev)) { tmp = RREG32(DC_HPD1_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; @@ -3139,7 +3156,7 @@ WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); } } - if (*disp_int & DC_HPD2_INTERRUPT) { + if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { if (ASIC_IS_DCE3(rdev)) { tmp = RREG32(DC_HPD2_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; @@ -3150,7 +3167,7 @@ WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); } } - if (*disp_int_cont & DC_HPD3_INTERRUPT) { + if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { if (ASIC_IS_DCE3(rdev)) { tmp = RREG32(DC_HPD3_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; @@ -3161,18 +3178,18 @@ WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); } } - if (*disp_int_cont & DC_HPD4_INTERRUPT) { + if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { tmp = RREG32(DC_HPD4_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD4_INT_CONTROL, tmp); } if (ASIC_IS_DCE32(rdev)) { - if (*disp_int_cont2 & DC_HPD5_INTERRUPT) { + if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { tmp = RREG32(DC_HPD5_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD5_INT_CONTROL, tmp); } - if (*disp_int_cont2 & DC_HPD6_INTERRUPT) { + if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { tmp = RREG32(DC_HPD5_INT_CONTROL); tmp |= DC_HPDx_INT_ACK; WREG32(DC_HPD6_INT_CONTROL, tmp); @@ -3194,12 +3211,10 @@ void r600_irq_disable(struct radeon_device *rdev) { - u32 disp_int, disp_int_cont, disp_int_cont2; - r600_disable_interrupts(rdev); /* Wait and acknowledge irq */ mdelay(1); - r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2); + r600_irq_ack(rdev); r600_disable_interrupt_state(rdev); } @@ -3262,7 +3277,7 @@ u32 wptr = r600_get_ih_wptr(rdev); u32 rptr = rdev->ih.rptr; u32 src_id, src_data; - u32 ring_index, disp_int, disp_int_cont, disp_int_cont2; + u32 ring_index; unsigned long flags; bool queue_hotplug = false; @@ -3283,7 +3298,7 @@ restart_ih: /* display interrupts */ - r600_irq_ack(rdev, &disp_int, &disp_int_cont, &disp_int_cont2); + r600_irq_ack(rdev); rdev->ih.wptr = wptr; while (rptr != wptr) { @@ -3296,17 +3311,21 @@ case 1: /* D1 vblank/vline */ switch (src_data) { case 0: /* D1 vblank */ - if (disp_int & LB_D1_VBLANK_INTERRUPT) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - disp_int &= ~LB_D1_VBLANK_INTERRUPT; + if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[0]) + radeon_crtc_handle_flip(rdev, 0); + rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); } break; case 1: /* D1 vline */ - if (disp_int & LB_D1_VLINE_INTERRUPT) { - disp_int &= ~LB_D1_VLINE_INTERRUPT; + if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; DRM_DEBUG("IH: D1 vline\n"); } break; @@ -3318,17 +3337,21 @@ case 5: /* D2 vblank/vline */ switch (src_data) { case 0: /* D2 vblank */ - if (disp_int & LB_D2_VBLANK_INTERRUPT) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - disp_int &= ~LB_D2_VBLANK_INTERRUPT; + if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) { + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[1]) + radeon_crtc_handle_flip(rdev, 1); + rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); } break; case 1: /* D1 vline */ - if (disp_int & LB_D2_VLINE_INTERRUPT) { - disp_int &= ~LB_D2_VLINE_INTERRUPT; + if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; DRM_DEBUG("IH: D2 vline\n"); } break; @@ -3340,43 +3363,43 @@ case 19: /* HPD/DAC hotplug */ switch (src_data) { case 0: - if (disp_int & DC_HPD1_INTERRUPT) { - disp_int &= ~DC_HPD1_INTERRUPT; + if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD1\n"); } break; case 1: - if (disp_int & DC_HPD2_INTERRUPT) { - disp_int &= ~DC_HPD2_INTERRUPT; + if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD2\n"); } break; case 4: - if (disp_int_cont & DC_HPD3_INTERRUPT) { - disp_int_cont &= ~DC_HPD3_INTERRUPT; + if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD3\n"); } break; case 5: - if (disp_int_cont & DC_HPD4_INTERRUPT) { - disp_int_cont &= ~DC_HPD4_INTERRUPT; + if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD4\n"); } break; case 10: - if (disp_int_cont2 & DC_HPD5_INTERRUPT) { - disp_int_cont2 &= ~DC_HPD5_INTERRUPT; + if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD5\n"); } break; case 12: - if (disp_int_cont2 & DC_HPD6_INTERRUPT) { - disp_int_cont2 &= ~DC_HPD6_INTERRUPT; + if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { + rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; queue_hotplug = true; DRM_DEBUG("IH: HPD6\n"); } --- linux-2.6.37.orig/drivers/gpu/drm/radeon/r600d.h +++ linux-2.6.37/drivers/gpu/drm/radeon/r600d.h @@ -728,6 +728,15 @@ /* DCE 3.2 */ # define DC_HPDx_EN (1 << 28) +#define D1GRPH_INTERRUPT_STATUS 0x6158 +#define D2GRPH_INTERRUPT_STATUS 0x6958 +# define DxGRPH_PFLIP_INT_OCCURRED (1 << 0) +# define DxGRPH_PFLIP_INT_CLEAR (1 << 8) +#define D1GRPH_INTERRUPT_CONTROL 0x615c +#define D2GRPH_INTERRUPT_CONTROL 0x695c +# define DxGRPH_PFLIP_INT_MASK (1 << 0) +# define DxGRPH_PFLIP_INT_TYPE (1 << 8) + /* * PM4 */ --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_asic.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_asic.c @@ -171,6 +171,9 @@ .pm_finish = &r100_pm_finish, .pm_init_profile = &r100_pm_init_profile, .pm_get_dynpm_state = &r100_pm_get_dynpm_state, + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, }; static struct radeon_asic r200_asic = { @@ -215,6 +218,9 @@ .pm_finish = &r100_pm_finish, .pm_init_profile = &r100_pm_init_profile, .pm_get_dynpm_state = &r100_pm_get_dynpm_state, + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, }; static struct radeon_asic r300_asic = { @@ -260,6 +266,9 @@ .pm_finish = &r100_pm_finish, .pm_init_profile = &r100_pm_init_profile, .pm_get_dynpm_state = &r100_pm_get_dynpm_state, + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, }; static struct radeon_asic r300_asic_pcie = { @@ -304,6 +313,9 @@ .pm_finish = &r100_pm_finish, .pm_init_profile = &r100_pm_init_profile, .pm_get_dynpm_state = &r100_pm_get_dynpm_state, + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, }; static struct radeon_asic r420_asic = { @@ -349,6 +361,9 @@ .pm_finish = &r100_pm_finish, .pm_init_profile = &r420_pm_init_profile, .pm_get_dynpm_state = &r100_pm_get_dynpm_state, + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, }; static struct radeon_asic rs400_asic = { @@ -394,6 +409,9 @@ .pm_finish = &r100_pm_finish, .pm_init_profile = &r100_pm_init_profile, .pm_get_dynpm_state = &r100_pm_get_dynpm_state, + .pre_page_flip = &r100_pre_page_flip, + .page_flip = &r100_page_flip, + .post_page_flip = &r100_post_page_flip, }; static struct radeon_asic rs600_asic = { @@ -439,6 +457,9 @@ .pm_finish = &rs600_pm_finish, .pm_init_profile = &r420_pm_init_profile, .pm_get_dynpm_state = &r100_pm_get_dynpm_state, + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, }; static struct radeon_asic rs690_asic = { @@ -484,6 +505,9 @@ .pm_finish = &rs600_pm_finish, .pm_init_profile = &r420_pm_init_profile, .pm_get_dynpm_state = &r100_pm_get_dynpm_state, + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, }; static struct radeon_asic rv515_asic = { @@ -529,6 +553,9 @@ .pm_finish = &rs600_pm_finish, .pm_init_profile = &r420_pm_init_profile, .pm_get_dynpm_state = &r100_pm_get_dynpm_state, + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, }; static struct radeon_asic r520_asic = { @@ -574,6 +601,9 @@ .pm_finish = &rs600_pm_finish, .pm_init_profile = &r420_pm_init_profile, .pm_get_dynpm_state = &r100_pm_get_dynpm_state, + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, }; static struct radeon_asic r600_asic = { @@ -618,6 +648,9 @@ .pm_finish = &rs600_pm_finish, .pm_init_profile = &r600_pm_init_profile, .pm_get_dynpm_state = &r600_pm_get_dynpm_state, + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, }; static struct radeon_asic rs780_asic = { @@ -662,6 +695,9 @@ .pm_finish = &rs600_pm_finish, .pm_init_profile = &rs780_pm_init_profile, .pm_get_dynpm_state = &r600_pm_get_dynpm_state, + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rs600_page_flip, + .post_page_flip = &rs600_post_page_flip, }; static struct radeon_asic rv770_asic = { @@ -706,6 +742,9 @@ .pm_finish = &rs600_pm_finish, .pm_init_profile = &r600_pm_init_profile, .pm_get_dynpm_state = &r600_pm_get_dynpm_state, + .pre_page_flip = &rs600_pre_page_flip, + .page_flip = &rv770_page_flip, + .post_page_flip = &rs600_post_page_flip, }; static struct radeon_asic evergreen_asic = { @@ -749,6 +788,52 @@ .pm_finish = &evergreen_pm_finish, .pm_init_profile = &r600_pm_init_profile, .pm_get_dynpm_state = &r600_pm_get_dynpm_state, + .pre_page_flip = &evergreen_pre_page_flip, + .page_flip = &evergreen_page_flip, + .post_page_flip = &evergreen_post_page_flip, +}; + +static struct radeon_asic sumo_asic = { + .init = &evergreen_init, + .fini = &evergreen_fini, + .suspend = &evergreen_suspend, + .resume = &evergreen_resume, + .cp_commit = &r600_cp_commit, + .gpu_is_lockup = &evergreen_gpu_is_lockup, + .asic_reset = &evergreen_asic_reset, + .vga_set_state = &r600_vga_set_state, + .gart_tlb_flush = &evergreen_pcie_gart_tlb_flush, + .gart_set_page = &rs600_gart_set_page, + .ring_test = &r600_ring_test, + .ring_ib_execute = &r600_ring_ib_execute, + .irq_set = &evergreen_irq_set, + .irq_process = &evergreen_irq_process, + .get_vblank_counter = &evergreen_get_vblank_counter, + .fence_ring_emit = &r600_fence_ring_emit, + .cs_parse = &evergreen_cs_parse, + .copy_blit = &evergreen_copy_blit, + .copy_dma = &evergreen_copy_blit, + .copy = &evergreen_copy_blit, + .get_engine_clock = &radeon_atom_get_engine_clock, + .set_engine_clock = &radeon_atom_set_engine_clock, + .get_memory_clock = NULL, + .set_memory_clock = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, + .set_surface_reg = r600_set_surface_reg, + .clear_surface_reg = r600_clear_surface_reg, + .bandwidth_update = &evergreen_bandwidth_update, + .hpd_init = &evergreen_hpd_init, + .hpd_fini = &evergreen_hpd_fini, + .hpd_sense = &evergreen_hpd_sense, + .hpd_set_polarity = &evergreen_hpd_set_polarity, + .gui_idle = &r600_gui_idle, + .pm_misc = &evergreen_pm_misc, + .pm_prepare = &evergreen_pm_prepare, + .pm_finish = &evergreen_pm_finish, + .pm_init_profile = &rs780_pm_init_profile, + .pm_get_dynpm_state = &r600_pm_get_dynpm_state, }; int radeon_asic_init(struct radeon_device *rdev) @@ -835,6 +920,9 @@ case CHIP_HEMLOCK: rdev->asic = &evergreen_asic; break; + case CHIP_PALM: + rdev->asic = &sumo_asic; + break; default: /* FIXME: not supported yet */ return -EINVAL; @@ -849,7 +937,9 @@ if (rdev->flags & RADEON_SINGLE_CRTC) rdev->num_crtc = 1; else { - if (ASIC_IS_DCE4(rdev)) + if (ASIC_IS_DCE41(rdev)) + rdev->num_crtc = 2; + else if (ASIC_IS_DCE4(rdev)) rdev->num_crtc = 6; else rdev->num_crtc = 2; --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_asic.h +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_asic.h @@ -130,6 +130,9 @@ extern void r100_pm_finish(struct radeon_device *rdev); extern void r100_pm_init_profile(struct radeon_device *rdev); extern void r100_pm_get_dynpm_state(struct radeon_device *rdev); +extern void r100_pre_page_flip(struct radeon_device *rdev, int crtc); +extern u32 r100_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void r100_post_page_flip(struct radeon_device *rdev, int crtc); /* * r200,rv250,rs300,rv280 @@ -205,6 +208,9 @@ extern void rs600_pm_misc(struct radeon_device *rdev); extern void rs600_pm_prepare(struct radeon_device *rdev); extern void rs600_pm_finish(struct radeon_device *rdev); +extern void rs600_pre_page_flip(struct radeon_device *rdev, int crtc); +extern u32 rs600_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void rs600_post_page_flip(struct radeon_device *rdev, int crtc); /* * rs690,rs740 @@ -287,6 +293,7 @@ int rv770_suspend(struct radeon_device *rdev); int rv770_resume(struct radeon_device *rdev); extern void rv770_pm_misc(struct radeon_device *rdev); +extern u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); /* * evergreen @@ -314,5 +321,8 @@ extern void evergreen_pm_misc(struct radeon_device *rdev); extern void evergreen_pm_prepare(struct radeon_device *rdev); extern void evergreen_pm_finish(struct radeon_device *rdev); +extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); +extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); #endif --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_atombios.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1337,6 +1337,43 @@ return false; } +static void radeon_atombios_get_igp_ss_overrides(struct radeon_device *rdev, + struct radeon_atom_ss *ss, + int id) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); + u16 data_offset, size; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *igp_info; + u8 frev, crev; + u16 percentage = 0, rate = 0; + + /* get any igp specific overrides */ + if (atom_parse_data_header(mode_info->atom_context, index, &size, + &frev, &crev, &data_offset)) { + igp_info = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 *) + (mode_info->atom_context->bios + data_offset); + switch (id) { + case ASIC_INTERNAL_SS_ON_TMDS: + percentage = le16_to_cpu(igp_info->usDVISSPercentage); + rate = le16_to_cpu(igp_info->usDVISSpreadRateIn10Hz); + break; + case ASIC_INTERNAL_SS_ON_HDMI: + percentage = le16_to_cpu(igp_info->usHDMISSPercentage); + rate = le16_to_cpu(igp_info->usHDMISSpreadRateIn10Hz); + break; + case ASIC_INTERNAL_SS_ON_LVDS: + percentage = le16_to_cpu(igp_info->usLvdsSSPercentage); + rate = le16_to_cpu(igp_info->usLvdsSSpreadRateIn10Hz); + break; + } + if (percentage) + ss->percentage = percentage; + if (rate) + ss->rate = rate; + } +} + union asic_ss_info { struct _ATOM_ASIC_INTERNAL_SS_INFO info; struct _ATOM_ASIC_INTERNAL_SS_INFO_V2 info_2; @@ -1401,6 +1438,8 @@ le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadSpectrumPercentage); ss->type = ss_info->info_3.asSpreadSpectrum[i].ucSpreadSpectrumMode; ss->rate = le16_to_cpu(ss_info->info_3.asSpreadSpectrum[i].usSpreadRateIn10Hz); + if (rdev->flags & RADEON_IS_IGP) + radeon_atombios_get_igp_ss_overrides(rdev, ss, id); return true; } } @@ -1740,495 +1779,600 @@ "RV6xx", "RV770", "adt7473", + "NONE", "External GPIO", "Evergreen", - "adt7473 with internal", - + "emc2103", + "Sumo", }; union power_info { struct _ATOM_POWERPLAY_INFO info; struct _ATOM_POWERPLAY_INFO_V2 info_2; struct _ATOM_POWERPLAY_INFO_V3 info_3; - struct _ATOM_PPLIB_POWERPLAYTABLE info_4; + struct _ATOM_PPLIB_POWERPLAYTABLE pplib; + struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; + struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; }; -void radeon_atombios_get_power_modes(struct radeon_device *rdev) +union pplib_clock_info { + struct _ATOM_PPLIB_R600_CLOCK_INFO r600; + struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; + struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; + struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; +}; + +union pplib_power_state { + struct _ATOM_PPLIB_STATE v1; + struct _ATOM_PPLIB_STATE_V2 v2; +}; + +static void radeon_atombios_parse_misc_flags_1_3(struct radeon_device *rdev, + int state_index, + u32 misc, u32 misc2) +{ + rdev->pm.power_state[state_index].misc = misc; + rdev->pm.power_state[state_index].misc2 = misc2; + /* order matters! */ + if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_POWERSAVE; + if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BATTERY; + if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BATTERY; + if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BALANCED; + if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_PERFORMANCE; + rdev->pm.power_state[state_index].flags &= + ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + } + if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BALANCED; + if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.default_power_state_index = state_index; + rdev->pm.power_state[state_index].default_clock_mode = + &rdev->pm.power_state[state_index].clock_info[0]; + } else if (state_index == 0) { + rdev->pm.power_state[state_index].clock_info[0].flags |= + RADEON_PM_MODE_NO_DISPLAY; + } +} + +static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) { struct radeon_mode_info *mode_info = &rdev->mode_info; + u32 misc, misc2 = 0; + int num_modes = 0, i; + int state_index = 0; + struct radeon_i2c_bus_rec i2c_bus; + union power_info *power_info; int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - u16 data_offset; + u16 data_offset; u8 frev, crev; - u32 misc, misc2 = 0, sclk, mclk; - union power_info *power_info; - struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; - struct _ATOM_PPLIB_STATE *power_state; - int num_modes = 0, i, j; - int state_index = 0, mode_index = 0; - struct radeon_i2c_bus_rec i2c_bus; - rdev->pm.default_power_state_index = -1; - - if (atom_parse_data_header(mode_info->atom_context, index, NULL, - &frev, &crev, &data_offset)) { - power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); - if (frev < 4) { - /* add the i2c bus for thermal/fan chip */ - if (power_info->info.ucOverdriveThermalController > 0) { - DRM_INFO("Possible %s thermal controller at 0x%02x\n", - thermal_controller_names[power_info->info.ucOverdriveThermalController], - power_info->info.ucOverdriveControllerAddress >> 1); - i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); - rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); - if (rdev->pm.i2c_bus) { - struct i2c_board_info info = { }; - const char *name = thermal_controller_names[power_info->info. - ucOverdriveThermalController]; - info.addr = power_info->info.ucOverdriveControllerAddress >> 1; - strlcpy(info.type, name, sizeof(info.type)); - i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); - } + if (!atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return state_index; + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); + + /* add the i2c bus for thermal/fan chip */ + if (power_info->info.ucOverdriveThermalController > 0) { + DRM_INFO("Possible %s thermal controller at 0x%02x\n", + thermal_controller_names[power_info->info.ucOverdriveThermalController], + power_info->info.ucOverdriveControllerAddress >> 1); + i2c_bus = radeon_lookup_i2c_gpio(rdev, power_info->info.ucOverdriveI2cLine); + rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); + if (rdev->pm.i2c_bus) { + struct i2c_board_info info = { }; + const char *name = thermal_controller_names[power_info->info. + ucOverdriveThermalController]; + info.addr = power_info->info.ucOverdriveControllerAddress >> 1; + strlcpy(info.type, name, sizeof(info.type)); + i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); + } + } + num_modes = power_info->info.ucNumOfPowerModeEntries; + if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) + num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; + /* last mode is usually default, array is low to high */ + for (i = 0; i < num_modes; i++) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; + switch (frev) { + case 1: + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].mclk = + le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock); + rdev->pm.power_state[state_index].clock_info[0].sclk = + le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock); + /* skip invalid modes */ + if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || + (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) + continue; + rdev->pm.power_state[state_index].pcie_lanes = + power_info->info.asPowerPlayInfo[i].ucNumPciELanes; + misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo); + if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || + (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_GPIO; + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = + radeon_lookup_gpio(rdev, + power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex); + if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + true; + else + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + false; + } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_VDDC; + rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = + power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex; } - num_modes = power_info->info.ucNumOfPowerModeEntries; - if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) - num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; - /* last mode is usually default, array is low to high */ - for (i = 0; i < num_modes; i++) { - rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE; - switch (frev) { - case 1: - rdev->pm.power_state[state_index].num_clock_modes = 1; - rdev->pm.power_state[state_index].clock_info[0].mclk = - le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock); - rdev->pm.power_state[state_index].clock_info[0].sclk = - le16_to_cpu(power_info->info.asPowerPlayInfo[i].usEngineClock); - /* skip invalid modes */ - if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || - (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) - continue; - rdev->pm.power_state[state_index].pcie_lanes = - power_info->info.asPowerPlayInfo[i].ucNumPciELanes; - misc = le32_to_cpu(power_info->info.asPowerPlayInfo[i].ulMiscInfo); - if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || - (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { - rdev->pm.power_state[state_index].clock_info[0].voltage.type = - VOLTAGE_GPIO; - rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = - radeon_lookup_gpio(rdev, - power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex); - if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) - rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = - true; - else - rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = - false; - } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { - rdev->pm.power_state[state_index].clock_info[0].voltage.type = - VOLTAGE_VDDC; - rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = - power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex; - } - rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - rdev->pm.power_state[state_index].misc = misc; - /* order matters! */ - if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_POWERSAVE; - if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BATTERY; - if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BATTERY; - if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BALANCED; - if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_PERFORMANCE; - rdev->pm.power_state[state_index].flags &= - ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - } - if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_DEFAULT; - rdev->pm.default_power_state_index = state_index; - rdev->pm.power_state[state_index].default_clock_mode = - &rdev->pm.power_state[state_index].clock_info[0]; - rdev->pm.power_state[state_index].flags &= - ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - } else if (state_index == 0) { - rdev->pm.power_state[state_index].clock_info[0].flags |= - RADEON_PM_MODE_NO_DISPLAY; - } - state_index++; - break; - case 2: - rdev->pm.power_state[state_index].num_clock_modes = 1; - rdev->pm.power_state[state_index].clock_info[0].mclk = - le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock); - rdev->pm.power_state[state_index].clock_info[0].sclk = - le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock); - /* skip invalid modes */ - if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || - (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) - continue; - rdev->pm.power_state[state_index].pcie_lanes = - power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes; - misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo); - misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2); - if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || - (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { - rdev->pm.power_state[state_index].clock_info[0].voltage.type = - VOLTAGE_GPIO; - rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = - radeon_lookup_gpio(rdev, - power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex); - if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) - rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = - true; - else - rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = - false; - } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { - rdev->pm.power_state[state_index].clock_info[0].voltage.type = - VOLTAGE_VDDC; - rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = - power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex; - } - rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - rdev->pm.power_state[state_index].misc = misc; - rdev->pm.power_state[state_index].misc2 = misc2; - /* order matters! */ - if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_POWERSAVE; - if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BATTERY; - if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BATTERY; - if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BALANCED; - if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_PERFORMANCE; - rdev->pm.power_state[state_index].flags &= - ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - } - if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BALANCED; - if (misc2 & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT) - rdev->pm.power_state[state_index].flags &= - ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_DEFAULT; - rdev->pm.default_power_state_index = state_index; - rdev->pm.power_state[state_index].default_clock_mode = - &rdev->pm.power_state[state_index].clock_info[0]; - rdev->pm.power_state[state_index].flags &= - ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - } else if (state_index == 0) { - rdev->pm.power_state[state_index].clock_info[0].flags |= - RADEON_PM_MODE_NO_DISPLAY; - } - state_index++; - break; - case 3: - rdev->pm.power_state[state_index].num_clock_modes = 1; - rdev->pm.power_state[state_index].clock_info[0].mclk = - le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock); - rdev->pm.power_state[state_index].clock_info[0].sclk = - le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock); - /* skip invalid modes */ - if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || - (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) - continue; - rdev->pm.power_state[state_index].pcie_lanes = - power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes; - misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo); - misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2); - if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || - (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { - rdev->pm.power_state[state_index].clock_info[0].voltage.type = - VOLTAGE_GPIO; - rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = - radeon_lookup_gpio(rdev, - power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex); - if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) - rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = - true; - else - rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = - false; - } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { - rdev->pm.power_state[state_index].clock_info[0].voltage.type = - VOLTAGE_VDDC; - rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = - power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex; - if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) { - rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled = - true; - rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id = - power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex; - } - } - rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - rdev->pm.power_state[state_index].misc = misc; - rdev->pm.power_state[state_index].misc2 = misc2; - /* order matters! */ - if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_POWERSAVE; - if (misc & ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BATTERY; - if (misc & ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BATTERY; - if (misc & ATOM_PM_MISCINFO_LOAD_BALANCE_EN) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BALANCED; - if (misc & ATOM_PM_MISCINFO_3D_ACCELERATION_EN) { - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_PERFORMANCE; - rdev->pm.power_state[state_index].flags &= - ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - } - if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BALANCED; - if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_DEFAULT; - rdev->pm.default_power_state_index = state_index; - rdev->pm.power_state[state_index].default_clock_mode = - &rdev->pm.power_state[state_index].clock_info[0]; - } else if (state_index == 0) { - rdev->pm.power_state[state_index].clock_info[0].flags |= - RADEON_PM_MODE_NO_DISPLAY; - } - state_index++; - break; - } + rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, 0); + state_index++; + break; + case 2: + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].mclk = + le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock); + rdev->pm.power_state[state_index].clock_info[0].sclk = + le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulEngineClock); + /* skip invalid modes */ + if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || + (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) + continue; + rdev->pm.power_state[state_index].pcie_lanes = + power_info->info_2.asPowerPlayInfo[i].ucNumPciELanes; + misc = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo); + misc2 = le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMiscInfo2); + if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || + (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_GPIO; + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = + radeon_lookup_gpio(rdev, + power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex); + if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + true; + else + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + false; + } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_VDDC; + rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = + power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex; } - /* last mode is usually default */ - if (rdev->pm.default_power_state_index == -1) { - rdev->pm.power_state[state_index - 1].type = - POWER_STATE_TYPE_DEFAULT; - rdev->pm.default_power_state_index = state_index - 1; - rdev->pm.power_state[state_index - 1].default_clock_mode = - &rdev->pm.power_state[state_index - 1].clock_info[0]; - rdev->pm.power_state[state_index].flags &= - ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - rdev->pm.power_state[state_index].misc = 0; - rdev->pm.power_state[state_index].misc2 = 0; + rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2); + state_index++; + break; + case 3: + rdev->pm.power_state[state_index].num_clock_modes = 1; + rdev->pm.power_state[state_index].clock_info[0].mclk = + le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock); + rdev->pm.power_state[state_index].clock_info[0].sclk = + le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulEngineClock); + /* skip invalid modes */ + if ((rdev->pm.power_state[state_index].clock_info[0].mclk == 0) || + (rdev->pm.power_state[state_index].clock_info[0].sclk == 0)) + continue; + rdev->pm.power_state[state_index].pcie_lanes = + power_info->info_3.asPowerPlayInfo[i].ucNumPciELanes; + misc = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo); + misc2 = le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMiscInfo2); + if ((misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) || + (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH)) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_GPIO; + rdev->pm.power_state[state_index].clock_info[0].voltage.gpio = + radeon_lookup_gpio(rdev, + power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex); + if (misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH) + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + true; + else + rdev->pm.power_state[state_index].clock_info[0].voltage.active_high = + false; + } else if (misc & ATOM_PM_MISCINFO_PROGRAM_VOLTAGE) { + rdev->pm.power_state[state_index].clock_info[0].voltage.type = + VOLTAGE_VDDC; + rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = + power_info->info_3.asPowerPlayInfo[i].ucVoltageDropIndex; + if (misc2 & ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN) { + rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_enabled = + true; + rdev->pm.power_state[state_index].clock_info[0].voltage.vddci_id = + power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex; + } } + rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + radeon_atombios_parse_misc_flags_1_3(rdev, state_index, misc, misc2); + state_index++; + break; + } + } + /* last mode is usually default */ + if (rdev->pm.default_power_state_index == -1) { + rdev->pm.power_state[state_index - 1].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.default_power_state_index = state_index - 1; + rdev->pm.power_state[state_index - 1].default_clock_mode = + &rdev->pm.power_state[state_index - 1].clock_info[0]; + rdev->pm.power_state[state_index].flags &= + ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + rdev->pm.power_state[state_index].misc = 0; + rdev->pm.power_state[state_index].misc2 = 0; + } + return state_index; +} + +static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *rdev, + ATOM_PPLIB_THERMALCONTROLLER *controller) +{ + struct radeon_i2c_bus_rec i2c_bus; + + /* add the i2c bus for thermal/fan chip */ + if (controller->ucType > 0) { + if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_RV770; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + rdev->pm.int_thermal_type = THERMAL_TYPE_SUMO; + } else if ((controller->ucType == + ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || + (controller->ucType == + ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) || + (controller->ucType == + ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) { + DRM_INFO("Special thermal controller config\n"); } else { - int fw_index = GetIndexIntoMasterTable(DATA, FirmwareInfo); - uint8_t fw_frev, fw_crev; - uint16_t fw_data_offset, vddc = 0; - union firmware_info *firmware_info; - ATOM_PPLIB_THERMALCONTROLLER *controller = &power_info->info_4.sThermalController; - - if (atom_parse_data_header(mode_info->atom_context, fw_index, NULL, - &fw_frev, &fw_crev, &fw_data_offset)) { - firmware_info = - (union firmware_info *)(mode_info->atom_context->bios + - fw_data_offset); - vddc = firmware_info->info_14.usBootUpVDDCVoltage; + DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", + pp_lib_thermal_controller_names[controller->ucType], + controller->ucI2cAddress >> 1, + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); + rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); + if (rdev->pm.i2c_bus) { + struct i2c_board_info info = { }; + const char *name = pp_lib_thermal_controller_names[controller->ucType]; + info.addr = controller->ucI2cAddress >> 1; + strlcpy(info.type, name, sizeof(info.type)); + i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); } + } + } +} - /* add the i2c bus for thermal/fan chip */ - if (controller->ucType > 0) { - if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - rdev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - rdev->pm.int_thermal_type = THERMAL_TYPE_RV770; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - rdev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; - } else if ((controller->ucType == - ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) || - (controller->ucType == - ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL)) { - DRM_INFO("Special thermal controller config\n"); - } else { - DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", - pp_lib_thermal_controller_names[controller->ucType], - controller->ucI2cAddress >> 1, - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine); - rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus); - if (rdev->pm.i2c_bus) { - struct i2c_board_info info = { }; - const char *name = pp_lib_thermal_controller_names[controller->ucType]; - info.addr = controller->ucI2cAddress >> 1; - strlcpy(info.type, name, sizeof(info.type)); - i2c_new_device(&rdev->pm.i2c_bus->adapter, &info); - } +static u16 radeon_atombios_get_default_vddc(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); + u8 frev, crev; + u16 data_offset; + union firmware_info *firmware_info; + u16 vddc = 0; - } - } - /* first mode is usually default, followed by low to high */ - for (i = 0; i < power_info->info_4.ucNumStates; i++) { - mode_index = 0; - power_state = (struct _ATOM_PPLIB_STATE *) - (mode_info->atom_context->bios + - data_offset + - le16_to_cpu(power_info->info_4.usStateArrayOffset) + - i * power_info->info_4.ucStateEntrySize); - non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) - (mode_info->atom_context->bios + - data_offset + - le16_to_cpu(power_info->info_4.usNonClockInfoArrayOffset) + - (power_state->ucNonClockStateIndex * - power_info->info_4.ucNonClockSize)); - for (j = 0; j < (power_info->info_4.ucStateEntrySize - 1); j++) { - if (rdev->flags & RADEON_IS_IGP) { - struct _ATOM_PPLIB_RS780_CLOCK_INFO *clock_info = - (struct _ATOM_PPLIB_RS780_CLOCK_INFO *) - (mode_info->atom_context->bios + - data_offset + - le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) + - (power_state->ucClockStateIndices[j] * - power_info->info_4.ucClockInfoSize)); - sclk = le16_to_cpu(clock_info->usLowEngineClockLow); - sclk |= clock_info->ucLowEngineClockHigh << 16; - rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; - /* skip invalid modes */ - if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) - continue; - /* voltage works differently on IGPs */ - mode_index++; - } else if (ASIC_IS_DCE4(rdev)) { - struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *clock_info = - (struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO *) - (mode_info->atom_context->bios + - data_offset + - le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) + - (power_state->ucClockStateIndices[j] * - power_info->info_4.ucClockInfoSize)); - sclk = le16_to_cpu(clock_info->usEngineClockLow); - sclk |= clock_info->ucEngineClockHigh << 16; - mclk = le16_to_cpu(clock_info->usMemoryClockLow); - mclk |= clock_info->ucMemoryClockHigh << 16; - rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; - rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; - /* skip invalid modes */ - if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) || - (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)) - continue; - rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = - VOLTAGE_SW; - rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = - clock_info->usVDDC; - /* XXX usVDDCI */ - mode_index++; - } else { - struct _ATOM_PPLIB_R600_CLOCK_INFO *clock_info = - (struct _ATOM_PPLIB_R600_CLOCK_INFO *) - (mode_info->atom_context->bios + - data_offset + - le16_to_cpu(power_info->info_4.usClockInfoArrayOffset) + - (power_state->ucClockStateIndices[j] * - power_info->info_4.ucClockInfoSize)); - sclk = le16_to_cpu(clock_info->usEngineClockLow); - sclk |= clock_info->ucEngineClockHigh << 16; - mclk = le16_to_cpu(clock_info->usMemoryClockLow); - mclk |= clock_info->ucMemoryClockHigh << 16; - rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; - rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; - /* skip invalid modes */ - if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) || - (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)) - continue; - rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = - VOLTAGE_SW; - rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = - clock_info->usVDDC; - mode_index++; - } - } - rdev->pm.power_state[state_index].num_clock_modes = mode_index; - if (mode_index) { - misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); - misc2 = le16_to_cpu(non_clock_info->usClassification); - rdev->pm.power_state[state_index].misc = misc; - rdev->pm.power_state[state_index].misc2 = misc2; - rdev->pm.power_state[state_index].pcie_lanes = - ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> - ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; - switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { - case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BATTERY; - break; - case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_BALANCED; - break; - case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_PERFORMANCE; - break; - case ATOM_PPLIB_CLASSIFICATION_UI_NONE: - if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_PERFORMANCE; - break; - } - rdev->pm.power_state[state_index].flags = 0; - if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) - rdev->pm.power_state[state_index].flags |= - RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; - if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) { - rdev->pm.power_state[state_index].type = - POWER_STATE_TYPE_DEFAULT; - rdev->pm.default_power_state_index = state_index; - rdev->pm.power_state[state_index].default_clock_mode = - &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; - /* patch the table values with the default slck/mclk from firmware info */ - for (j = 0; j < mode_index; j++) { - rdev->pm.power_state[state_index].clock_info[j].mclk = - rdev->clock.default_mclk; - rdev->pm.power_state[state_index].clock_info[j].sclk = - rdev->clock.default_sclk; - if (vddc) - rdev->pm.power_state[state_index].clock_info[j].voltage.voltage = - vddc; - } - } - state_index++; - } - } - /* if multiple clock modes, mark the lowest as no display */ - for (i = 0; i < state_index; i++) { - if (rdev->pm.power_state[i].num_clock_modes > 1) - rdev->pm.power_state[i].clock_info[0].flags |= - RADEON_PM_MODE_NO_DISPLAY; - } - /* first mode is usually default */ - if (rdev->pm.default_power_state_index == -1) { - rdev->pm.power_state[0].type = - POWER_STATE_TYPE_DEFAULT; - rdev->pm.default_power_state_index = 0; - rdev->pm.power_state[0].default_clock_mode = - &rdev->pm.power_state[0].clock_info[0]; - } + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + firmware_info = + (union firmware_info *)(mode_info->atom_context->bios + + data_offset); + vddc = firmware_info->info_14.usBootUpVDDCVoltage; + } + + return vddc; +} + +static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev, + int state_index, int mode_index, + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info) +{ + int j; + u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings); + u32 misc2 = le16_to_cpu(non_clock_info->usClassification); + u16 vddc = radeon_atombios_get_default_vddc(rdev); + + rdev->pm.power_state[state_index].misc = misc; + rdev->pm.power_state[state_index].misc2 = misc2; + rdev->pm.power_state[state_index].pcie_lanes = + ((misc & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> + ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; + switch (misc2 & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { + case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BATTERY; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_BALANCED; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_PERFORMANCE; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_NONE: + if (misc2 & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_PERFORMANCE; + break; + } + rdev->pm.power_state[state_index].flags = 0; + if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) + rdev->pm.power_state[state_index].flags |= + RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; + if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) { + rdev->pm.power_state[state_index].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.default_power_state_index = state_index; + rdev->pm.power_state[state_index].default_clock_mode = + &rdev->pm.power_state[state_index].clock_info[mode_index - 1]; + /* patch the table values with the default slck/mclk from firmware info */ + for (j = 0; j < mode_index; j++) { + rdev->pm.power_state[state_index].clock_info[j].mclk = + rdev->clock.default_mclk; + rdev->pm.power_state[state_index].clock_info[j].sclk = + rdev->clock.default_sclk; + if (vddc) + rdev->pm.power_state[state_index].clock_info[j].voltage.voltage = + vddc; + } + } +} + +static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev, + int state_index, int mode_index, + union pplib_clock_info *clock_info) +{ + u32 sclk, mclk; + + if (rdev->flags & RADEON_IS_IGP) { + if (rdev->family >= CHIP_PALM) { + sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); + sclk |= clock_info->sumo.ucEngineClockHigh << 16; + rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; + } else { + sclk = le16_to_cpu(clock_info->rs780.usLowEngineClockLow); + sclk |= clock_info->rs780.ucLowEngineClockHigh << 16; + rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; + } + } else if (ASIC_IS_DCE4(rdev)) { + sclk = le16_to_cpu(clock_info->evergreen.usEngineClockLow); + sclk |= clock_info->evergreen.ucEngineClockHigh << 16; + mclk = le16_to_cpu(clock_info->evergreen.usMemoryClockLow); + mclk |= clock_info->evergreen.ucMemoryClockHigh << 16; + rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; + rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = + VOLTAGE_SW; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = + clock_info->evergreen.usVDDC; + } else { + sclk = le16_to_cpu(clock_info->r600.usEngineClockLow); + sclk |= clock_info->r600.ucEngineClockHigh << 16; + mclk = le16_to_cpu(clock_info->r600.usMemoryClockLow); + mclk |= clock_info->r600.ucMemoryClockHigh << 16; + rdev->pm.power_state[state_index].clock_info[mode_index].mclk = mclk; + rdev->pm.power_state[state_index].clock_info[mode_index].sclk = sclk; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.type = + VOLTAGE_SW; + rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = + clock_info->r600.usVDDC; + } + + if (rdev->flags & RADEON_IS_IGP) { + /* skip invalid modes */ + if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) + return false; + } else { + /* skip invalid modes */ + if ((rdev->pm.power_state[state_index].clock_info[mode_index].mclk == 0) || + (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)) + return false; + } + return true; +} + +static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; + union pplib_power_state *power_state; + int i, j; + int state_index = 0, mode_index = 0; + union pplib_clock_info *clock_info; + bool valid; + union power_info *power_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + + if (!atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return state_index; + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); + + radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); + /* first mode is usually default, followed by low to high */ + for (i = 0; i < power_info->pplib.ucNumStates; i++) { + mode_index = 0; + power_state = (union pplib_power_state *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usStateArrayOffset) + + i * power_info->pplib.ucStateEntrySize); + non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) + + (power_state->v1.ucNonClockStateIndex * + power_info->pplib.ucNonClockSize)); + for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) { + clock_info = (union pplib_clock_info *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) + + (power_state->v1.ucClockStateIndices[j] * + power_info->pplib.ucClockInfoSize)); + valid = radeon_atombios_parse_pplib_clock_info(rdev, + state_index, mode_index, + clock_info); + if (valid) + mode_index++; + } + rdev->pm.power_state[state_index].num_clock_modes = mode_index; + if (mode_index) { + radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, + non_clock_info); + state_index++; + } + } + /* if multiple clock modes, mark the lowest as no display */ + for (i = 0; i < state_index; i++) { + if (rdev->pm.power_state[i].num_clock_modes > 1) + rdev->pm.power_state[i].clock_info[0].flags |= + RADEON_PM_MODE_NO_DISPLAY; + } + /* first mode is usually default */ + if (rdev->pm.default_power_state_index == -1) { + rdev->pm.power_state[0].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.default_power_state_index = 0; + rdev->pm.power_state[0].default_clock_mode = + &rdev->pm.power_state[0].clock_info[0]; + } + return state_index; +} + +static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; + union pplib_power_state *power_state; + int i, j, non_clock_array_index, clock_array_index; + int state_index = 0, mode_index = 0; + union pplib_clock_info *clock_info; + struct StateArray *state_array; + struct ClockInfoArray *clock_info_array; + struct NonClockInfoArray *non_clock_info_array; + bool valid; + union power_info *power_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + + if (!atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return state_index; + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); + + radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); + state_array = (struct StateArray *) + (mode_info->atom_context->bios + data_offset + + power_info->pplib.usStateArrayOffset); + clock_info_array = (struct ClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + power_info->pplib.usClockInfoArrayOffset); + non_clock_info_array = (struct NonClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + power_info->pplib.usNonClockInfoArrayOffset); + for (i = 0; i < state_array->ucNumEntries; i++) { + mode_index = 0; + power_state = (union pplib_power_state *)&state_array->states[i]; + /* XXX this might be an inagua bug... */ + non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */ + non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) + &non_clock_info_array->nonClockInfo[non_clock_array_index]; + for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { + clock_array_index = power_state->v2.clockInfoIndex[j]; + /* XXX this might be an inagua bug... */ + if (clock_array_index >= clock_info_array->ucNumEntries) + continue; + clock_info = (union pplib_clock_info *) + &clock_info_array->clockInfo[clock_array_index]; + valid = radeon_atombios_parse_pplib_clock_info(rdev, + state_index, mode_index, + clock_info); + if (valid) + mode_index++; + } + rdev->pm.power_state[state_index].num_clock_modes = mode_index; + if (mode_index) { + radeon_atombios_parse_pplib_non_clock_info(rdev, state_index, mode_index, + non_clock_info); + state_index++; + } + } + /* if multiple clock modes, mark the lowest as no display */ + for (i = 0; i < state_index; i++) { + if (rdev->pm.power_state[i].num_clock_modes > 1) + rdev->pm.power_state[i].clock_info[0].flags |= + RADEON_PM_MODE_NO_DISPLAY; + } + /* first mode is usually default */ + if (rdev->pm.default_power_state_index == -1) { + rdev->pm.power_state[0].type = + POWER_STATE_TYPE_DEFAULT; + rdev->pm.default_power_state_index = 0; + rdev->pm.power_state[0].default_clock_mode = + &rdev->pm.power_state[0].clock_info[0]; + } + return state_index; +} + +void radeon_atombios_get_power_modes(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + int state_index = 0; + + rdev->pm.default_power_state_index = -1; + + if (atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + switch (frev) { + case 1: + case 2: + case 3: + state_index = radeon_atombios_parse_power_table_1_3(rdev); + break; + case 4: + case 5: + state_index = radeon_atombios_parse_power_table_4_5(rdev); + break; + case 6: + state_index = radeon_atombios_parse_power_table_6(rdev); + break; + default: + break; } } else { /* add the default mode */ --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_cs.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_cs.c @@ -77,13 +77,13 @@ p->relocs_ptr[i] = &p->relocs[i]; p->relocs[i].robj = p->relocs[i].gobj->driver_private; p->relocs[i].lobj.bo = p->relocs[i].robj; - p->relocs[i].lobj.rdomain = r->read_domains; p->relocs[i].lobj.wdomain = r->write_domain; + p->relocs[i].lobj.rdomain = r->read_domains; + p->relocs[i].lobj.tv.bo = &p->relocs[i].robj->tbo; p->relocs[i].handle = r->handle; p->relocs[i].flags = r->flags; - INIT_LIST_HEAD(&p->relocs[i].lobj.list); radeon_bo_list_add_object(&p->relocs[i].lobj, - &p->validated); + &p->validated); } } return radeon_bo_list_validate(&p->validated); @@ -189,10 +189,13 @@ { unsigned i; - if (!error && parser->ib) { - radeon_bo_list_fence(&parser->validated, parser->ib->fence); - } - radeon_bo_list_unreserve(&parser->validated); + + if (!error && parser->ib) + ttm_eu_fence_buffer_objects(&parser->validated, + parser->ib->fence); + else + ttm_eu_backoff_reservation(&parser->validated); + if (parser->relocs != NULL) { for (i = 0; i < parser->nrelocs; i++) { if (parser->relocs[i].gobj) --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_device.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_device.c @@ -81,6 +81,7 @@ "JUNIPER", "CYPRESS", "HEMLOCK", + "PALM", "LAST", }; @@ -335,7 +336,12 @@ uint32_t reg; /* first check CRTCs */ - if (ASIC_IS_DCE4(rdev)) { + if (ASIC_IS_DCE41(rdev)) { + reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); + if (reg & EVERGREEN_CRTC_MASTER_EN) + return true; + } else if (ASIC_IS_DCE4(rdev)) { reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_display.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_display.c @@ -183,12 +183,272 @@ kfree(radeon_crtc); } +/* + * Handle unpin events outside the interrupt handler proper. + */ +static void radeon_unpin_work_func(struct work_struct *__work) +{ + struct radeon_unpin_work *work = + container_of(__work, struct radeon_unpin_work, work); + int r; + + /* unpin of the old buffer */ + r = radeon_bo_reserve(work->old_rbo, false); + if (likely(r == 0)) { + r = radeon_bo_unpin(work->old_rbo); + if (unlikely(r != 0)) { + DRM_ERROR("failed to unpin buffer after flip\n"); + } + radeon_bo_unreserve(work->old_rbo); + } else + DRM_ERROR("failed to reserve buffer after flip\n"); + kfree(work); +} + +void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + struct radeon_unpin_work *work; + struct drm_pending_vblank_event *e; + struct timeval now; + unsigned long flags; + u32 update_pending; + int vpos, hpos; + + spin_lock_irqsave(&rdev->ddev->event_lock, flags); + work = radeon_crtc->unpin_work; + if (work == NULL || + !radeon_fence_signaled(work->fence)) { + spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); + return; + } + /* New pageflip, or just completion of a previous one? */ + if (!radeon_crtc->deferred_flip_completion) { + /* do the flip (mmio) */ + update_pending = radeon_page_flip(rdev, crtc_id, work->new_crtc_base); + } else { + /* This is just a completion of a flip queued in crtc + * at last invocation. Make sure we go directly to + * completion routine. + */ + update_pending = 0; + radeon_crtc->deferred_flip_completion = 0; + } + + /* Has the pageflip already completed in crtc, or is it certain + * to complete in this vblank? + */ + if (update_pending && + (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, + &vpos, &hpos)) && + (vpos >=0) && + (vpos < (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100)) { + /* crtc didn't flip in this target vblank interval, + * but flip is pending in crtc. It will complete it + * in next vblank interval, so complete the flip at + * next vblank irq. + */ + radeon_crtc->deferred_flip_completion = 1; + spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); + return; + } + + /* Pageflip (will be) certainly completed in this vblank. Clean up. */ + radeon_crtc->unpin_work = NULL; + + /* wakeup userspace */ + if (work->event) { + e = work->event; + e->event.sequence = drm_vblank_count_and_time(rdev->ddev, crtc_id, &now); + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; + list_add_tail(&e->base.link, &e->base.file_priv->event_list); + wake_up_interruptible(&e->base.file_priv->event_wait); + } + spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); + + drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id); + radeon_fence_unref(&work->fence); + radeon_post_page_flip(work->rdev, work->crtc_id); + schedule_work(&work->work); +} + +static int radeon_crtc_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_framebuffer *old_radeon_fb; + struct radeon_framebuffer *new_radeon_fb; + struct drm_gem_object *obj; + struct radeon_bo *rbo; + struct radeon_fence *fence; + struct radeon_unpin_work *work; + unsigned long flags; + u32 tiling_flags, pitch_pixels; + u64 base; + int r; + + work = kzalloc(sizeof *work, GFP_KERNEL); + if (work == NULL) + return -ENOMEM; + + r = radeon_fence_create(rdev, &fence); + if (unlikely(r != 0)) { + kfree(work); + DRM_ERROR("flip queue: failed to create fence.\n"); + return -ENOMEM; + } + work->event = event; + work->rdev = rdev; + work->crtc_id = radeon_crtc->crtc_id; + work->fence = radeon_fence_ref(fence); + old_radeon_fb = to_radeon_framebuffer(crtc->fb); + new_radeon_fb = to_radeon_framebuffer(fb); + /* schedule unpin of the old buffer */ + obj = old_radeon_fb->obj; + rbo = obj->driver_private; + work->old_rbo = rbo; + INIT_WORK(&work->work, radeon_unpin_work_func); + + /* We borrow the event spin lock for protecting unpin_work */ + spin_lock_irqsave(&dev->event_lock, flags); + if (radeon_crtc->unpin_work) { + spin_unlock_irqrestore(&dev->event_lock, flags); + kfree(work); + radeon_fence_unref(&fence); + + DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); + return -EBUSY; + } + radeon_crtc->unpin_work = work; + radeon_crtc->deferred_flip_completion = 0; + spin_unlock_irqrestore(&dev->event_lock, flags); + + /* pin the new buffer */ + obj = new_radeon_fb->obj; + rbo = obj->driver_private; + + DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n", + work->old_rbo, rbo); + + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) { + DRM_ERROR("failed to reserve new rbo buffer before flip\n"); + goto pflip_cleanup; + } + r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &base); + if (unlikely(r != 0)) { + radeon_bo_unreserve(rbo); + r = -EINVAL; + DRM_ERROR("failed to pin new rbo buffer before flip\n"); + goto pflip_cleanup; + } + radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); + radeon_bo_unreserve(rbo); + + if (!ASIC_IS_AVIVO(rdev)) { + /* crtc offset is from display base addr not FB location */ + base -= radeon_crtc->legacy_display_base_addr; + pitch_pixels = fb->pitch / (fb->bits_per_pixel / 8); + + if (tiling_flags & RADEON_TILING_MACRO) { + if (ASIC_IS_R300(rdev)) { + base &= ~0x7ff; + } else { + int byteshift = fb->bits_per_pixel >> 4; + int tile_addr = (((crtc->y >> 3) * pitch_pixels + crtc->x) >> (8 - byteshift)) << 11; + base += tile_addr + ((crtc->x << byteshift) % 256) + ((crtc->y % 8) << 8); + } + } else { + int offset = crtc->y * pitch_pixels + crtc->x; + switch (fb->bits_per_pixel) { + case 8: + default: + offset *= 1; + break; + case 15: + case 16: + offset *= 2; + break; + case 24: + offset *= 3; + break; + case 32: + offset *= 4; + break; + } + base += offset; + } + base &= ~7; + } + + spin_lock_irqsave(&dev->event_lock, flags); + work->new_crtc_base = base; + spin_unlock_irqrestore(&dev->event_lock, flags); + + /* update crtc fb */ + crtc->fb = fb; + + r = drm_vblank_get(dev, radeon_crtc->crtc_id); + if (r) { + DRM_ERROR("failed to get vblank before flip\n"); + goto pflip_cleanup1; + } + + /* 32 ought to cover us */ + r = radeon_ring_lock(rdev, 32); + if (r) { + DRM_ERROR("failed to lock the ring before flip\n"); + goto pflip_cleanup2; + } + + /* emit the fence */ + radeon_fence_emit(rdev, fence); + /* set the proper interrupt */ + radeon_pre_page_flip(rdev, radeon_crtc->crtc_id); + /* fire the ring */ + radeon_ring_unlock_commit(rdev); + + return 0; + +pflip_cleanup2: + drm_vblank_put(dev, radeon_crtc->crtc_id); + +pflip_cleanup1: + r = radeon_bo_reserve(rbo, false); + if (unlikely(r != 0)) { + DRM_ERROR("failed to reserve new rbo in error path\n"); + goto pflip_cleanup; + } + r = radeon_bo_unpin(rbo); + if (unlikely(r != 0)) { + radeon_bo_unreserve(rbo); + r = -EINVAL; + DRM_ERROR("failed to unpin new rbo in error path\n"); + goto pflip_cleanup; + } + radeon_bo_unreserve(rbo); + +pflip_cleanup: + spin_lock_irqsave(&dev->event_lock, flags); + radeon_crtc->unpin_work = NULL; + spin_unlock_irqrestore(&dev->event_lock, flags); + radeon_fence_unref(&fence); + kfree(work); + + return r; +} + static const struct drm_crtc_funcs radeon_crtc_funcs = { .cursor_set = radeon_crtc_cursor_set, .cursor_move = radeon_crtc_cursor_move, .gamma_set = radeon_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, .destroy = radeon_crtc_destroy, + .page_flip = radeon_crtc_page_flip, }; static void radeon_crtc_init(struct drm_device *dev, int index) @@ -225,7 +485,7 @@ radeon_legacy_init_crtc(dev, radeon_crtc); } -static const char *encoder_names[34] = { +static const char *encoder_names[36] = { "NONE", "INTERNAL_LVDS", "INTERNAL_TMDS1", @@ -260,6 +520,8 @@ "INTERNAL_KLDSCP_LVTMA", "INTERNAL_UNIPHY1", "INTERNAL_UNIPHY2", + "NUTMEG", + "TRAVIS", }; static const char *connector_names[15] = { @@ -1019,7 +1281,7 @@ /* * Retrieve current video scanout position of crtc on a given gpu. * - * \param rdev Device to query. + * \param dev Device to query. * \param crtc Crtc to query. * \param *vpos Location where vertical scanout position should be stored. * \param *hpos Location where horizontal scanout position should go. @@ -1031,72 +1293,74 @@ * * \return Flags, or'ed together as follows: * - * RADEON_SCANOUTPOS_VALID = Query successfull. - * RADEON_SCANOUTPOS_INVBL = Inside vblank. - * RADEON_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of + * DRM_SCANOUTPOS_VALID = Query successfull. + * DRM_SCANOUTPOS_INVBL = Inside vblank. + * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of * this flag means that returned position may be offset by a constant but * unknown small number of scanlines wrt. real scanout position. * */ -int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, int *hpos) +int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos) { u32 stat_crtc = 0, vbl = 0, position = 0; int vbl_start, vbl_end, vtotal, ret = 0; bool in_vbl = true; + struct radeon_device *rdev = dev->dev_private; + if (ASIC_IS_DCE4(rdev)) { if (crtc == 0) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC0_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + EVERGREEN_CRTC0_REGISTER_OFFSET); - ret |= RADEON_SCANOUTPOS_VALID; + ret |= DRM_SCANOUTPOS_VALID; } if (crtc == 1) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC1_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + EVERGREEN_CRTC1_REGISTER_OFFSET); - ret |= RADEON_SCANOUTPOS_VALID; + ret |= DRM_SCANOUTPOS_VALID; } if (crtc == 2) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC2_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + EVERGREEN_CRTC2_REGISTER_OFFSET); - ret |= RADEON_SCANOUTPOS_VALID; + ret |= DRM_SCANOUTPOS_VALID; } if (crtc == 3) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC3_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + EVERGREEN_CRTC3_REGISTER_OFFSET); - ret |= RADEON_SCANOUTPOS_VALID; + ret |= DRM_SCANOUTPOS_VALID; } if (crtc == 4) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC4_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + EVERGREEN_CRTC4_REGISTER_OFFSET); - ret |= RADEON_SCANOUTPOS_VALID; + ret |= DRM_SCANOUTPOS_VALID; } if (crtc == 5) { vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END + EVERGREEN_CRTC5_REGISTER_OFFSET); position = RREG32(EVERGREEN_CRTC_STATUS_POSITION + EVERGREEN_CRTC5_REGISTER_OFFSET); - ret |= RADEON_SCANOUTPOS_VALID; + ret |= DRM_SCANOUTPOS_VALID; } } else if (ASIC_IS_AVIVO(rdev)) { if (crtc == 0) { vbl = RREG32(AVIVO_D1CRTC_V_BLANK_START_END); position = RREG32(AVIVO_D1CRTC_STATUS_POSITION); - ret |= RADEON_SCANOUTPOS_VALID; + ret |= DRM_SCANOUTPOS_VALID; } if (crtc == 1) { vbl = RREG32(AVIVO_D2CRTC_V_BLANK_START_END); position = RREG32(AVIVO_D2CRTC_STATUS_POSITION); - ret |= RADEON_SCANOUTPOS_VALID; + ret |= DRM_SCANOUTPOS_VALID; } } else { /* Pre-AVIVO: Different encoding of scanout pos and vblank interval. */ @@ -1112,7 +1376,7 @@ if (!(stat_crtc & 1)) in_vbl = false; - ret |= RADEON_SCANOUTPOS_VALID; + ret |= DRM_SCANOUTPOS_VALID; } if (crtc == 1) { vbl = (RREG32(RADEON_CRTC2_V_TOTAL_DISP) & @@ -1122,7 +1386,7 @@ if (!(stat_crtc & 1)) in_vbl = false; - ret |= RADEON_SCANOUTPOS_VALID; + ret |= DRM_SCANOUTPOS_VALID; } } @@ -1133,13 +1397,13 @@ /* Valid vblank area boundaries from gpu retrieved? */ if (vbl > 0) { /* Yes: Decode. */ - ret |= RADEON_SCANOUTPOS_ACCURATE; + ret |= DRM_SCANOUTPOS_ACCURATE; vbl_start = vbl & 0x1fff; vbl_end = (vbl >> 16) & 0x1fff; } else { /* No: Fake something reasonable which gives at least ok results. */ - vbl_start = rdev->mode_info.crtcs[crtc]->base.mode.crtc_vdisplay; + vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay; vbl_end = 0; } @@ -1155,7 +1419,7 @@ /* Inside "upper part" of vblank area? Apply corrective offset if so: */ if (in_vbl && (*vpos >= vbl_start)) { - vtotal = rdev->mode_info.crtcs[crtc]->base.mode.crtc_vtotal; + vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal; *vpos = *vpos - vtotal; } @@ -1164,7 +1428,7 @@ /* In vblank? */ if (in_vbl) - ret |= RADEON_SCANOUTPOS_INVBL; + ret |= DRM_SCANOUTPOS_INVBL; return ret; } --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_drv.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_drv.c @@ -48,9 +48,10 @@ * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500) * 2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs + * 2.8.0 - pageflip support */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 7 +#define KMS_DRIVER_MINOR 8 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); @@ -66,6 +67,10 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc); int radeon_enable_vblank_kms(struct drm_device *dev, int crtc); void radeon_disable_vblank_kms(struct drm_device *dev, int crtc); +int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags); void radeon_driver_irq_preinstall_kms(struct drm_device *dev); int radeon_driver_irq_postinstall_kms(struct drm_device *dev); void radeon_driver_irq_uninstall_kms(struct drm_device *dev); @@ -74,6 +79,8 @@ struct drm_file *file_priv); int radeon_gem_object_init(struct drm_gem_object *obj); void radeon_gem_object_free(struct drm_gem_object *obj); +extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, + int *vpos, int *hpos); extern struct drm_ioctl_desc radeon_ioctls_kms[]; extern int radeon_max_kms_ioctl; int radeon_mmap(struct file *filp, struct vm_area_struct *vma); @@ -296,6 +303,8 @@ .get_vblank_counter = radeon_get_vblank_counter_kms, .enable_vblank = radeon_enable_vblank_kms, .disable_vblank = radeon_disable_vblank_kms, + .get_vblank_timestamp = radeon_get_vblank_timestamp_kms, + .get_scanout_position = radeon_get_crtc_scanoutpos, #if defined(CONFIG_DEBUG_FS) .debugfs_init = radeon_debugfs_init, .debugfs_cleanup = radeon_debugfs_cleanup, --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_encoders.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_encoders.c @@ -713,7 +713,7 @@ * DIG1/2 can drive UNIPHY0/1/2 link A or link B * * DCE 4.0 - * - 3 DIG transmitter blocks UNPHY0/1/2 (links A and B). + * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). * Supports up to 6 digital outputs * - 6 DIG encoder blocks. * - DIG to PHY mapping is hardcoded @@ -724,6 +724,12 @@ * DIG5 drives UNIPHY2 link A, A+B * DIG6 drives UNIPHY2 link B * + * DCE 4.1 + * - 3 DIG transmitter blocks UNIPHY0/1/2 (links A and B). + * Supports up to 6 digital outputs + * - 2 DIG encoder blocks. + * DIG1/2 can drive UNIPHY0/1/2 link A or link B + * * Routing * crtc -> dig encoder -> UNIPHY/LVTMA (1 or 2 links) * Examples: @@ -904,9 +910,15 @@ else args.v3.ucLaneNum = 4; - if (dig->linkb) { - args.v3.acConfig.ucLinkSel = 1; - args.v3.acConfig.ucEncoderSel = 1; + if (ASIC_IS_DCE41(rdev)) { + args.v3.acConfig.ucEncoderSel = dig->dig_encoder; + if (dig->linkb) + args.v3.acConfig.ucLinkSel = 1; + } else { + if (dig->linkb) { + args.v3.acConfig.ucLinkSel = 1; + args.v3.acConfig.ucEncoderSel = 1; + } } /* Select the PLL for the PHY @@ -1044,6 +1056,7 @@ union external_encoder_control { EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION v1; + EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION_V3 v3; }; static void @@ -1054,6 +1067,7 @@ struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder); union external_encoder_control args; struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); int index = GetIndexIntoMasterTable(COMMAND, ExternalEncoderControl); @@ -1061,6 +1075,7 @@ int dp_clock = 0; int dp_lane_count = 0; int connector_object_id = 0; + u32 ext_enum = (ext_radeon_encoder->encoder_enum & ENUM_ID_MASK) >> ENUM_ID_SHIFT; if (connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -1099,6 +1114,37 @@ else args.v1.sDigEncoder.ucLaneNum = 4; break; + case 3: + args.v3.sExtEncoder.ucAction = action; + if (action == EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT) + args.v3.sExtEncoder.usConnectorId = connector_object_id; + else + args.v3.sExtEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); + args.v3.sExtEncoder.ucEncoderMode = atombios_get_encoder_mode(encoder); + + if (args.v3.sExtEncoder.ucEncoderMode == ATOM_ENCODER_MODE_DP) { + if (dp_clock == 270000) + args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_2_70GHZ; + else if (dp_clock == 540000) + args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_5_40GHZ; + args.v3.sExtEncoder.ucLaneNum = dp_lane_count; + } else if (radeon_encoder->pixel_clock > 165000) + args.v3.sExtEncoder.ucLaneNum = 8; + else + args.v3.sExtEncoder.ucLaneNum = 4; + switch (ext_enum) { + case GRAPH_OBJECT_ENUM_ID1: + args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER1; + break; + case GRAPH_OBJECT_ENUM_ID2: + args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER2; + break; + case GRAPH_OBJECT_ENUM_ID3: + args.v3.sExtEncoder.ucConfig |= EXTERNAL_ENCODER_CONFIG_V3_ENCODER3; + break; + } + args.v3.sExtEncoder.ucBitPerColor = PANEL_8BIT_PER_COLOR; + break; default: DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); return; @@ -1289,12 +1335,18 @@ switch (mode) { case DRM_MODE_DPMS_ON: default: - action = ATOM_ENABLE; + if (ASIC_IS_DCE41(rdev) && (rdev->flags & RADEON_IS_IGP)) + action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT; + else + action = ATOM_ENABLE; break; case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - action = ATOM_DISABLE; + if (ASIC_IS_DCE41(rdev) && (rdev->flags & RADEON_IS_IGP)) + action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT; + else + action = ATOM_DISABLE; break; } atombios_external_encoder_setup(encoder, ext_encoder, action); @@ -1483,6 +1535,11 @@ struct radeon_encoder_atom_dig *dig; uint32_t dig_enc_in_use = 0; + /* on DCE41 and encoder can driver any phy so just crtc id */ + if (ASIC_IS_DCE41(rdev)) { + return radeon_crtc->crtc_id; + } + if (ASIC_IS_DCE4(rdev)) { dig = radeon_encoder->enc_priv; switch (radeon_encoder->encoder_id) { @@ -1610,7 +1667,13 @@ } if (ext_encoder) { - atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); + if (ASIC_IS_DCE41(rdev) && (rdev->flags & RADEON_IS_IGP)) { + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_INIT); + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); + } else + atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); } atombios_apply_encoder_quirks(encoder, adjusted_mode); @@ -2029,6 +2092,8 @@ case ENCODER_OBJECT_ID_TITFP513: case ENCODER_OBJECT_ID_VT1623: case ENCODER_OBJECT_ID_HDMI_SI1930: + case ENCODER_OBJECT_ID_TRAVIS: + case ENCODER_OBJECT_ID_NUTMEG: /* these are handled by the primary encoders */ radeon_encoder->is_ext_encoder = true; if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_family.h +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_family.h @@ -80,6 +80,7 @@ CHIP_JUNIPER, CHIP_CYPRESS, CHIP_HEMLOCK, + CHIP_PALM, CHIP_LAST, }; --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_fence.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_fence.c @@ -38,6 +38,7 @@ #include "drm.h" #include "radeon_reg.h" #include "radeon.h" +#include "radeon_trace.h" int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) { @@ -57,6 +58,7 @@ } else radeon_fence_ring_emit(rdev, fence); + trace_radeon_fence_emit(rdev->ddev, fence->seq); fence->emited = true; list_del(&fence->list); list_add_tail(&fence->list, &rdev->fence_drv.emited); @@ -213,6 +215,7 @@ retry: /* save current sequence used to check for GPU lockup */ seq = rdev->fence_drv.last_seq; + trace_radeon_fence_wait_begin(rdev->ddev, seq); if (intr) { radeon_irq_kms_sw_irq_get(rdev); r = wait_event_interruptible_timeout(rdev->fence_drv.queue, @@ -227,6 +230,7 @@ radeon_fence_signaled(fence), timeout); radeon_irq_kms_sw_irq_put(rdev); } + trace_radeon_fence_wait_end(rdev->ddev, seq); if (unlikely(!radeon_fence_signaled(fence))) { /* we were interrupted for some reason and fence isn't * isn't signaled yet, resume wait --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -71,8 +71,10 @@ rdev->irq.gui_idle = false; for (i = 0; i < rdev->num_crtc; i++) rdev->irq.crtc_vblank_int[i] = false; - for (i = 0; i < 6; i++) + for (i = 0; i < 6; i++) { rdev->irq.hpd[i] = false; + rdev->irq.pflip[i] = false; + } radeon_irq_set(rdev); /* Clear bits */ radeon_irq_process(rdev); @@ -101,8 +103,10 @@ rdev->irq.gui_idle = false; for (i = 0; i < rdev->num_crtc; i++) rdev->irq.crtc_vblank_int[i] = false; - for (i = 0; i < 6; i++) + for (i = 0; i < 6; i++) { rdev->irq.hpd[i] = false; + rdev->irq.pflip[i] = false; + } radeon_irq_set(rdev); } @@ -121,7 +125,7 @@ * chips. Disable MSI on them for now. */ if ((rdev->family >= CHIP_RV380) && - (!(rdev->flags & RADEON_IS_IGP)) && + ((!(rdev->flags & RADEON_IS_IGP)) || (rdev->family >= CHIP_PALM)) && (!(rdev->flags & RADEON_IS_AGP))) { int ret = pci_enable_msi(rdev->pdev); if (!ret) { @@ -175,3 +179,34 @@ spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags); } +void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) +{ + unsigned long irqflags; + + if (crtc < 0 || crtc >= rdev->num_crtc) + return; + + spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); + if (rdev->ddev->irq_enabled && (++rdev->irq.pflip_refcount[crtc] == 1)) { + rdev->irq.pflip[crtc] = true; + radeon_irq_set(rdev); + } + spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); +} + +void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) +{ + unsigned long irqflags; + + if (crtc < 0 || crtc >= rdev->num_crtc) + return; + + spin_lock_irqsave(&rdev->irq.pflip_lock[crtc], irqflags); + BUG_ON(rdev->ddev->irq_enabled && rdev->irq.pflip_refcount[crtc] <= 0); + if (rdev->ddev->irq_enabled && (--rdev->irq.pflip_refcount[crtc] == 0)) { + rdev->irq.pflip[crtc] = false; + radeon_irq_set(rdev); + } + spin_unlock_irqrestore(&rdev->irq.pflip_lock[crtc], irqflags); +} + --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_kms.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_kms.c @@ -277,6 +277,27 @@ radeon_irq_set(rdev); } +int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags) +{ + struct drm_crtc *drmcrtc; + struct radeon_device *rdev = dev->dev_private; + + if (crtc < 0 || crtc >= dev->num_crtcs) { + DRM_ERROR("Invalid crtc %d\n", crtc); + return -EINVAL; + } + + /* Get associated drm_crtc: */ + drmcrtc = &rdev->mode_info.crtcs[crtc]->base; + + /* Helper routine in DRM core does all the work: */ + return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error, + vblank_time, flags, + drmcrtc); +} /* * IOCTL. --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_mode.h +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_mode.h @@ -277,6 +277,9 @@ fixed20_12 hsc; struct drm_display_mode native_mode; int pll_id; + /* page flipping */ + struct radeon_unpin_work *unpin_work; + int deferred_flip_completion; }; struct radeon_encoder_primary_dac { @@ -442,10 +445,6 @@ struct drm_gem_object *obj; }; -/* radeon_get_crtc_scanoutpos() return flags */ -#define RADEON_SCANOUTPOS_VALID (1 << 0) -#define RADEON_SCANOUTPOS_INVBL (1 << 1) -#define RADEON_SCANOUTPOS_ACCURATE (1 << 2) extern enum radeon_tv_std radeon_combios_get_tv_info(struct radeon_device *rdev); @@ -562,7 +561,8 @@ extern int radeon_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); -extern int radeon_get_crtc_scanoutpos(struct radeon_device *rdev, int crtc, int *vpos, int *hpos); +extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, + int *vpos, int *hpos); extern bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev); extern struct edid * @@ -662,4 +662,7 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj); void radeon_fb_output_poll_changed(struct radeon_device *rdev); + +void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id); + #endif --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_object.h +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_object.h @@ -126,12 +126,12 @@ r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0); if (unlikely(r != 0)) return r; - spin_lock(&bo->tbo.lock); + spin_lock(&bo->tbo.bdev->fence_lock); if (mem_type) *mem_type = bo->tbo.mem.mem_type; if (bo->tbo.sync_obj) r = ttm_bo_wait(&bo->tbo, true, true, no_wait); - spin_unlock(&bo->tbo.lock); + spin_unlock(&bo->tbo.bdev->fence_lock); ttm_bo_unreserve(&bo->tbo); return r; } @@ -152,10 +152,7 @@ extern void radeon_bo_fini(struct radeon_device *rdev); extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj, struct list_head *head); -extern int radeon_bo_list_reserve(struct list_head *head); -extern void radeon_bo_list_unreserve(struct list_head *head); extern int radeon_bo_list_validate(struct list_head *head); -extern void radeon_bo_list_fence(struct list_head *head, void *fence); extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo, struct vm_area_struct *vma); extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo, --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_pm.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_pm.c @@ -449,6 +449,9 @@ case THERMAL_TYPE_EVERGREEN: temp = evergreen_get_temp(rdev); break; + case THERMAL_TYPE_SUMO: + temp = sumo_get_temp(rdev); + break; default: temp = 0; break; @@ -487,6 +490,7 @@ case THERMAL_TYPE_RV6XX: case THERMAL_TYPE_RV770: case THERMAL_TYPE_EVERGREEN: + case THERMAL_TYPE_SUMO: rdev->pm.int_hwmon_dev = hwmon_device_register(rdev->dev); if (IS_ERR(rdev->pm.int_hwmon_dev)) { err = PTR_ERR(rdev->pm.int_hwmon_dev); @@ -720,9 +724,9 @@ */ for (crtc = 0; (crtc < rdev->num_crtc) && in_vbl; crtc++) { if (rdev->pm.active_crtcs & (1 << crtc)) { - vbl_status = radeon_get_crtc_scanoutpos(rdev, crtc, &vpos, &hpos); - if ((vbl_status & RADEON_SCANOUTPOS_VALID) && - !(vbl_status & RADEON_SCANOUTPOS_INVBL)) + vbl_status = radeon_get_crtc_scanoutpos(rdev->ddev, crtc, &vpos, &hpos); + if ((vbl_status & DRM_SCANOUTPOS_VALID) && + !(vbl_status & DRM_SCANOUTPOS_INVBL)) in_vbl = false; } } --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_reg.h +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_reg.h @@ -422,6 +422,7 @@ # define RADEON_CRTC_CSYNC_EN (1 << 4) # define RADEON_CRTC_ICON_EN (1 << 15) # define RADEON_CRTC_CUR_EN (1 << 16) +# define RADEON_CRTC_VSTAT_MODE_MASK (3 << 17) # define RADEON_CRTC_CUR_MODE_MASK (7 << 20) # define RADEON_CRTC_CUR_MODE_SHIFT 20 # define RADEON_CRTC_CUR_MODE_MONO 0 @@ -509,6 +510,8 @@ # define RADEON_CRTC_TILE_EN (1 << 15) # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) # define RADEON_CRTC_STEREO_OFFSET_EN (1 << 17) +# define RADEON_CRTC_GUI_TRIG_OFFSET_LEFT_EN (1 << 28) +# define RADEON_CRTC_GUI_TRIG_OFFSET_RIGHT_EN (1 << 29) #define R300_CRTC_TILE_X0_Y0 0x0350 #define R300_CRTC2_TILE_X0_Y0 0x0358 --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_trace.h +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_trace.h @@ -0,0 +1,82 @@ +#if !defined(_RADEON_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _RADEON_TRACE_H_ + +#include +#include +#include + +#include + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM radeon +#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM) +#define TRACE_INCLUDE_FILE radeon_trace + +TRACE_EVENT(radeon_bo_create, + TP_PROTO(struct radeon_bo *bo), + TP_ARGS(bo), + TP_STRUCT__entry( + __field(struct radeon_bo *, bo) + __field(u32, pages) + ), + + TP_fast_assign( + __entry->bo = bo; + __entry->pages = bo->tbo.num_pages; + ), + TP_printk("bo=%p, pages=%u", __entry->bo, __entry->pages) +); + +DECLARE_EVENT_CLASS(radeon_fence_request, + + TP_PROTO(struct drm_device *dev, u32 seqno), + + TP_ARGS(dev, seqno), + + TP_STRUCT__entry( + __field(u32, dev) + __field(u32, seqno) + ), + + TP_fast_assign( + __entry->dev = dev->primary->index; + __entry->seqno = seqno; + ), + + TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno) +); + +DEFINE_EVENT(radeon_fence_request, radeon_fence_emit, + + TP_PROTO(struct drm_device *dev, u32 seqno), + + TP_ARGS(dev, seqno) +); + +DEFINE_EVENT(radeon_fence_request, radeon_fence_retire, + + TP_PROTO(struct drm_device *dev, u32 seqno), + + TP_ARGS(dev, seqno) +); + +DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_begin, + + TP_PROTO(struct drm_device *dev, u32 seqno), + + TP_ARGS(dev, seqno) +); + +DEFINE_EVENT(radeon_fence_request, radeon_fence_wait_end, + + TP_PROTO(struct drm_device *dev, u32 seqno), + + TP_ARGS(dev, seqno) +); + +#endif + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#include --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_trace_points.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_trace_points.c @@ -0,0 +1,9 @@ +/* Copyright Red Hat Inc 2010. + * Author : Dave Airlie + */ +#include +#include "radeon_drm.h" +#include "radeon.h" + +#define CREATE_TRACE_POINTS +#include "radeon_trace.h" --- linux-2.6.37.orig/drivers/gpu/drm/radeon/rs600.c +++ linux-2.6.37/drivers/gpu/drm/radeon/rs600.c @@ -46,6 +46,56 @@ void rs600_gpu_init(struct radeon_device *rdev); int rs600_mc_wait_for_idle(struct radeon_device *rdev); +void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; + u32 tmp; + + /* make sure flip is at vb rather than hb */ + tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); + tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN; + WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); + + /* set pageflip to happen anywhere in vblank interval */ + WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); + + /* enable the pflip int */ + radeon_irq_kms_pflip_irq_get(rdev, crtc); +} + +void rs600_post_page_flip(struct radeon_device *rdev, int crtc) +{ + /* disable the pflip int */ + radeon_irq_kms_pflip_irq_put(rdev, crtc); +} + +u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); + + /* Lock the graphics update lock */ + tmp |= AVIVO_D1GRPH_UPDATE_LOCK; + WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* update the scanout addresses */ + WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + + /* Wait for update_pending to go high. */ + while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); + DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); + + /* Unlock the lock, so double-buffering can take place inside vblank */ + tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; + WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* Return current update_pending status: */ + return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; +} + void rs600_pm_misc(struct radeon_device *rdev) { int requested_index = rdev->pm.requested_power_state_index; @@ -515,10 +565,12 @@ if (rdev->irq.gui_idle) { tmp |= S_000040_GUI_IDLE(1); } - if (rdev->irq.crtc_vblank_int[0]) { + if (rdev->irq.crtc_vblank_int[0] || + rdev->irq.pflip[0]) { mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); } - if (rdev->irq.crtc_vblank_int[1]) { + if (rdev->irq.crtc_vblank_int[1] || + rdev->irq.pflip[1]) { mode_int |= S_006540_D2MODE_VBLANK_INT_MASK(1); } if (rdev->irq.hpd[0]) { @@ -534,7 +586,7 @@ return 0; } -static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_int) +static inline u32 rs600_irq_ack(struct radeon_device *rdev) { uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS); uint32_t irq_mask = S_000044_SW_INT(1); @@ -547,27 +599,27 @@ } if (G_000044_DISPLAY_INT_STAT(irqs)) { - *r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); - if (G_007EDC_LB_D1_VBLANK_INTERRUPT(*r500_disp_int)) { + rdev->irq.stat_regs.r500.disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); + if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { WREG32(R_006534_D1MODE_VBLANK_STATUS, S_006534_D1MODE_VBLANK_ACK(1)); } - if (G_007EDC_LB_D2_VBLANK_INTERRUPT(*r500_disp_int)) { + if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { WREG32(R_006D34_D2MODE_VBLANK_STATUS, S_006D34_D2MODE_VBLANK_ACK(1)); } - if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(*r500_disp_int)) { + if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { tmp = RREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL); tmp |= S_007D08_DC_HOT_PLUG_DETECT1_INT_ACK(1); WREG32(R_007D08_DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); } - if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(*r500_disp_int)) { + if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { tmp = RREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL); tmp |= S_007D18_DC_HOT_PLUG_DETECT2_INT_ACK(1); WREG32(R_007D18_DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); } } else { - *r500_disp_int = 0; + rdev->irq.stat_regs.r500.disp_int = 0; } if (irqs) { @@ -578,32 +630,30 @@ void rs600_irq_disable(struct radeon_device *rdev) { - u32 tmp; - WREG32(R_000040_GEN_INT_CNTL, 0); WREG32(R_006540_DxMODE_INT_MASK, 0); /* Wait and acknowledge irq */ mdelay(1); - rs600_irq_ack(rdev, &tmp); + rs600_irq_ack(rdev); } int rs600_irq_process(struct radeon_device *rdev) { - uint32_t status, msi_rearm; - uint32_t r500_disp_int; + u32 status, msi_rearm; bool queue_hotplug = false; /* reset gui idle ack. the status bit is broken */ rdev->irq.gui_idle_acked = false; - status = rs600_irq_ack(rdev, &r500_disp_int); - if (!status && !r500_disp_int) { + status = rs600_irq_ack(rdev); + if (!status && !rdev->irq.stat_regs.r500.disp_int) { return IRQ_NONE; } - while (status || r500_disp_int) { + while (status || rdev->irq.stat_regs.r500.disp_int) { /* SW interrupt */ - if (G_000044_SW_INT(status)) + if (G_000044_SW_INT(status)) { radeon_fence_process(rdev); + } /* GUI idle */ if (G_000040_GUI_IDLE(status)) { rdev->irq.gui_idle_acked = true; @@ -611,25 +661,33 @@ wake_up(&rdev->irq.idle_queue); } /* Vertical blank interrupts */ - if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) { - drm_handle_vblank(rdev->ddev, 0); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); - } - if (G_007EDC_LB_D2_VBLANK_INTERRUPT(r500_disp_int)) { - drm_handle_vblank(rdev->ddev, 1); - rdev->pm.vblank_sync = true; - wake_up(&rdev->irq.vblank_queue); + if (G_007EDC_LB_D1_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { + if (rdev->irq.crtc_vblank_int[0]) { + drm_handle_vblank(rdev->ddev, 0); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[0]) + radeon_crtc_handle_flip(rdev, 0); + } + if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { + if (rdev->irq.crtc_vblank_int[1]) { + drm_handle_vblank(rdev->ddev, 1); + rdev->pm.vblank_sync = true; + wake_up(&rdev->irq.vblank_queue); + } + if (rdev->irq.pflip[1]) + radeon_crtc_handle_flip(rdev, 1); } - if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(r500_disp_int)) { + if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { queue_hotplug = true; DRM_DEBUG("HPD1\n"); } - if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(r500_disp_int)) { + if (G_007EDC_DC_HOT_PLUG_DETECT2_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { queue_hotplug = true; DRM_DEBUG("HPD2\n"); } - status = rs600_irq_ack(rdev, &r500_disp_int); + status = rs600_irq_ack(rdev); } /* reset gui idle ack. the status bit is broken */ rdev->irq.gui_idle_acked = false; --- linux-2.6.37.orig/drivers/gpu/drm/radeon/rv770.c +++ linux-2.6.37/drivers/gpu/drm/radeon/rv770.c @@ -42,6 +42,40 @@ static void rv770_gpu_init(struct radeon_device *rdev); void rv770_fini(struct radeon_device *rdev); +u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); + + /* Lock the graphics update lock */ + tmp |= AVIVO_D1GRPH_UPDATE_LOCK; + WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* update the scanout addresses */ + if (radeon_crtc->crtc_id) { + WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); + WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); + } else { + WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); + WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); + } + WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, + (u32)crtc_base); + + /* Wait for update_pending to go high. */ + while (!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)); + DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); + + /* Unlock the lock, so double-buffering can take place inside vblank */ + tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; + WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + + /* Return current update_pending status: */ + return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; +} + /* get temperature in millidegrees */ u32 rv770_get_temp(struct radeon_device *rdev) { @@ -489,6 +523,49 @@ return backend_map; } +static void rv770_program_channel_remap(struct radeon_device *rdev) +{ + u32 tcp_chan_steer, mc_shared_chremap, tmp; + bool force_no_swizzle; + + switch (rdev->family) { + case CHIP_RV770: + case CHIP_RV730: + force_no_swizzle = false; + break; + case CHIP_RV710: + case CHIP_RV740: + default: + force_no_swizzle = true; + break; + } + + tmp = RREG32(MC_SHARED_CHMAP); + switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { + case 0: + case 1: + default: + /* default mapping */ + mc_shared_chremap = 0x00fac688; + break; + case 2: + case 3: + if (force_no_swizzle) + mc_shared_chremap = 0x00fac688; + else + mc_shared_chremap = 0x00bbc298; + break; + } + + if (rdev->family == CHIP_RV740) + tcp_chan_steer = 0x00ef2a60; + else + tcp_chan_steer = 0x00fac688; + + WREG32(TCP_CHAN_STEER, tcp_chan_steer); + WREG32(MC_SHARED_CHREMAP, mc_shared_chremap); +} + static void rv770_gpu_init(struct radeon_device *rdev) { int i, j, num_qd_pipes; @@ -688,6 +765,8 @@ WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); WREG32(HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); + rv770_program_channel_remap(rdev); + WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); @@ -956,6 +1035,45 @@ radeon_bo_unref(&rdev->vram_scratch.robj); } +void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) +{ + u64 size_bf, size_af; + + if (mc->mc_vram_size > 0xE0000000) { + /* leave room for at least 512M GTT */ + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = 0xE0000000; + mc->mc_vram_size = 0xE0000000; + } + if (rdev->flags & RADEON_IS_AGP) { + size_bf = mc->gtt_start; + size_af = 0xFFFFFFFF - mc->gtt_end + 1; + if (size_bf > size_af) { + if (mc->mc_vram_size > size_bf) { + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = size_bf; + mc->mc_vram_size = size_bf; + } + mc->vram_start = mc->gtt_start - mc->mc_vram_size; + } else { + if (mc->mc_vram_size > size_af) { + dev_warn(rdev->dev, "limiting VRAM\n"); + mc->real_vram_size = size_af; + mc->mc_vram_size = size_af; + } + mc->vram_start = mc->gtt_end; + } + mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; + dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", + mc->mc_vram_size >> 20, mc->vram_start, + mc->vram_end, mc->real_vram_size >> 20); + } else { + radeon_vram_location(rdev, &rdev->mc, 0); + rdev->mc.gtt_base_align = 0; + radeon_gtt_location(rdev, mc); + } +} + int rv770_mc_init(struct radeon_device *rdev) { u32 tmp; @@ -996,7 +1114,7 @@ rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); rdev->mc.visible_vram_size = rdev->mc.aper_size; rdev->mc.active_vram_size = rdev->mc.visible_vram_size; - r600_vram_gtt_location(rdev, &rdev->mc); + r700_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); return 0; --- linux-2.6.37.orig/drivers/gpu/drm/radeon/rv770d.h +++ linux-2.6.37/drivers/gpu/drm/radeon/rv770d.h @@ -138,6 +138,7 @@ #define MC_SHARED_CHMAP 0x2004 #define NOOFCHAN_SHIFT 12 #define NOOFCHAN_MASK 0x00003000 +#define MC_SHARED_CHREMAP 0x2008 #define MC_ARB_RAMCFG 0x2760 #define NOOFBANK_SHIFT 0 @@ -303,6 +304,7 @@ #define BILINEAR_PRECISION_8_BIT (1 << 31) #define TCP_CNTL 0x9610 +#define TCP_CHAN_STEER 0x9614 #define VGT_CACHE_INVALIDATION 0x88C4 #define CACHE_INVALIDATION(x) ((x)<<0) @@ -351,4 +353,11 @@ #define SRBM_STATUS 0x0E50 +#define D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110 +#define D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x6914 +#define D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH 0x6114 +#define D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118 +#define D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x691c +#define D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH 0x611c + #endif --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon.h +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon.h @@ -69,6 +69,7 @@ #include #include #include +#include #include "radeon_family.h" #include "radeon_mode.h" @@ -180,6 +181,7 @@ extern u32 rv6xx_get_temp(struct radeon_device *rdev); extern u32 rv770_get_temp(struct radeon_device *rdev); extern u32 evergreen_get_temp(struct radeon_device *rdev); +extern u32 sumo_get_temp(struct radeon_device *rdev); /* * Fences. @@ -245,7 +247,9 @@ struct list_head list; /* Protected by tbo.reserved */ u32 placements[3]; + u32 busy_placements[3]; struct ttm_placement placement; + struct ttm_placement busy_placement; struct ttm_buffer_object tbo; struct ttm_bo_kmap_obj kmap; unsigned pin_count; @@ -259,13 +263,12 @@ }; struct radeon_bo_list { - struct list_head list; + struct ttm_validate_buffer tv; struct radeon_bo *bo; uint64_t gpu_offset; unsigned rdomain; unsigned wdomain; u32 tiling_flags; - bool reserved; }; /* @@ -377,11 +380,56 @@ /* * IRQS. */ + +struct radeon_unpin_work { + struct work_struct work; + struct radeon_device *rdev; + int crtc_id; + struct radeon_fence *fence; + struct drm_pending_vblank_event *event; + struct radeon_bo *old_rbo; + u64 new_crtc_base; +}; + +struct r500_irq_stat_regs { + u32 disp_int; +}; + +struct r600_irq_stat_regs { + u32 disp_int; + u32 disp_int_cont; + u32 disp_int_cont2; + u32 d1grph_int; + u32 d2grph_int; +}; + +struct evergreen_irq_stat_regs { + u32 disp_int; + u32 disp_int_cont; + u32 disp_int_cont2; + u32 disp_int_cont3; + u32 disp_int_cont4; + u32 disp_int_cont5; + u32 d1grph_int; + u32 d2grph_int; + u32 d3grph_int; + u32 d4grph_int; + u32 d5grph_int; + u32 d6grph_int; +}; + +union radeon_irq_stat_regs { + struct r500_irq_stat_regs r500; + struct r600_irq_stat_regs r600; + struct evergreen_irq_stat_regs evergreen; +}; + struct radeon_irq { bool installed; bool sw_int; /* FIXME: use a define max crtc rather than hardcode it */ bool crtc_vblank_int[6]; + bool pflip[6]; wait_queue_head_t vblank_queue; /* FIXME: use defines for max hpd/dacs */ bool hpd[6]; @@ -392,12 +440,17 @@ bool hdmi[2]; spinlock_t sw_lock; int sw_refcount; + union radeon_irq_stat_regs stat_regs; + spinlock_t pflip_lock[6]; + int pflip_refcount[6]; }; int radeon_irq_kms_init(struct radeon_device *rdev); void radeon_irq_kms_fini(struct radeon_device *rdev); void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev); void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev); +void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc); +void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc); /* * CP & ring. @@ -687,6 +740,7 @@ THERMAL_TYPE_RV6XX, THERMAL_TYPE_RV770, THERMAL_TYPE_EVERGREEN, + THERMAL_TYPE_SUMO, }; struct radeon_voltage { @@ -881,6 +935,10 @@ void (*pm_finish)(struct radeon_device *rdev); void (*pm_init_profile)(struct radeon_device *rdev); void (*pm_get_dynpm_state)(struct radeon_device *rdev); + /* pageflipping */ + void (*pre_page_flip)(struct radeon_device *rdev, int crtc); + u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base); + void (*post_page_flip)(struct radeon_device *rdev, int crtc); }; /* @@ -1269,6 +1327,7 @@ #define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620)) #define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730)) #define ASIC_IS_DCE4(rdev) ((rdev->family >= CHIP_CEDAR)) +#define ASIC_IS_DCE41(rdev) ((rdev->family >= CHIP_PALM)) /* * BIOS helpers. @@ -1344,6 +1403,9 @@ #define radeon_pm_finish(rdev) (rdev)->asic->pm_finish((rdev)) #define radeon_pm_init_profile(rdev) (rdev)->asic->pm_init_profile((rdev)) #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm_get_dynpm_state((rdev)) +#define radeon_pre_page_flip(rdev, crtc) rdev->asic->pre_page_flip((rdev), (crtc)) +#define radeon_page_flip(rdev, crtc, base) rdev->asic->page_flip((rdev), (crtc), (base)) +#define radeon_post_page_flip(rdev, crtc) rdev->asic->post_page_flip((rdev), (crtc)) /* Common functions */ /* AGP */ @@ -1432,7 +1494,6 @@ struct drm_display_mode *mode2); /* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */ -extern void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern bool r600_card_posted(struct radeon_device *rdev); extern void r600_cp_stop(struct radeon_device *rdev); extern int r600_cp_start(struct radeon_device *rdev); @@ -1478,6 +1539,7 @@ extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder); extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder); +extern void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); extern void r700_cp_stop(struct radeon_device *rdev); extern void r700_cp_fini(struct radeon_device *rdev); extern void evergreen_disable_interrupt_state(struct radeon_device *rdev); --- linux-2.6.37.orig/drivers/gpu/drm/radeon/radeon_object.c +++ linux-2.6.37/drivers/gpu/drm/radeon/radeon_object.c @@ -34,6 +34,7 @@ #include #include "radeon_drm.h" #include "radeon.h" +#include "radeon_trace.h" int radeon_ttm_init(struct radeon_device *rdev); @@ -66,15 +67,19 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) { - u32 c = 0; + u32 c = 0, b = 0; rbo->placement.fpfn = 0; rbo->placement.lpfn = 0; rbo->placement.placement = rbo->placements; - rbo->placement.busy_placement = rbo->placements; + rbo->placement.busy_placement = rbo->busy_placements; if (domain & RADEON_GEM_DOMAIN_VRAM) rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM; + /* add busy placement to TTM if VRAM is only option */ + if (domain == RADEON_GEM_DOMAIN_VRAM) { + rbo->busy_placements[b++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; + } if (domain & RADEON_GEM_DOMAIN_GTT) rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT; if (domain & RADEON_GEM_DOMAIN_CPU) @@ -82,7 +87,7 @@ if (!c) rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; rbo->placement.num_placement = c; - rbo->placement.num_busy_placement = c; + rbo->placement.num_busy_placement = b; } int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj, @@ -146,6 +151,7 @@ list_add_tail(&bo->list, &rdev->gem.objects); mutex_unlock(&bo->rdev->gem.mutex); } + trace_radeon_bo_create(bo); return 0; } @@ -302,34 +308,9 @@ struct list_head *head) { if (lobj->wdomain) { - list_add(&lobj->list, head); + list_add(&lobj->tv.head, head); } else { - list_add_tail(&lobj->list, head); - } -} - -int radeon_bo_list_reserve(struct list_head *head) -{ - struct radeon_bo_list *lobj; - int r; - - list_for_each_entry(lobj, head, list){ - r = radeon_bo_reserve(lobj->bo, false); - if (unlikely(r != 0)) - return r; - lobj->reserved = true; - } - return 0; -} - -void radeon_bo_list_unreserve(struct list_head *head) -{ - struct radeon_bo_list *lobj; - - list_for_each_entry(lobj, head, list) { - /* only unreserve object we successfully reserved */ - if (lobj->reserved && radeon_bo_is_reserved(lobj->bo)) - radeon_bo_unreserve(lobj->bo); + list_add_tail(&lobj->tv.head, head); } } @@ -340,14 +321,11 @@ u32 domain; int r; - list_for_each_entry(lobj, head, list) { - lobj->reserved = false; - } - r = radeon_bo_list_reserve(head); + r = ttm_eu_reserve_buffers(head); if (unlikely(r != 0)) { return r; } - list_for_each_entry(lobj, head, list) { + list_for_each_entry(lobj, head, tv.head) { bo = lobj->bo; if (!bo->pin_count) { domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain; @@ -370,25 +348,6 @@ return 0; } -void radeon_bo_list_fence(struct list_head *head, void *fence) -{ - struct radeon_bo_list *lobj; - struct radeon_bo *bo; - struct radeon_fence *old_fence = NULL; - - list_for_each_entry(lobj, head, list) { - bo = lobj->bo; - spin_lock(&bo->tbo.lock); - old_fence = (struct radeon_fence *)bo->tbo.sync_obj; - bo->tbo.sync_obj = radeon_fence_ref(fence); - bo->tbo.sync_obj_arg = NULL; - spin_unlock(&bo->tbo.lock); - if (old_fence) { - radeon_fence_unref(&old_fence); - } - } -} - int radeon_bo_fbdev_mmap(struct radeon_bo *bo, struct vm_area_struct *vma) { --- linux-2.6.37.orig/drivers/gpu/drm/ttm/ttm_bo.c +++ linux-2.6.37/drivers/gpu/drm/ttm/ttm_bo.c @@ -169,7 +169,7 @@ } EXPORT_SYMBOL(ttm_bo_wait_unreserved); -static void ttm_bo_add_to_lru(struct ttm_buffer_object *bo) +void ttm_bo_add_to_lru(struct ttm_buffer_object *bo) { struct ttm_bo_device *bdev = bo->bdev; struct ttm_mem_type_manager *man; @@ -191,11 +191,7 @@ } } -/** - * Call with the lru_lock held. - */ - -static int ttm_bo_del_from_lru(struct ttm_buffer_object *bo) +int ttm_bo_del_from_lru(struct ttm_buffer_object *bo) { int put_count = 0; @@ -227,9 +223,18 @@ /** * Deadlock avoidance for multi-bo reserving. */ - if (use_sequence && bo->seq_valid && - (sequence - bo->val_seq < (1 << 31))) { - return -EAGAIN; + if (use_sequence && bo->seq_valid) { + /** + * We've already reserved this one. + */ + if (unlikely(sequence == bo->val_seq)) + return -EDEADLK; + /** + * Already reserved by a thread that will not back + * off for us. We need to back off. + */ + if (unlikely(sequence - bo->val_seq < (1 << 31))) + return -EAGAIN; } if (no_wait) @@ -267,6 +272,13 @@ BUG(); } +void ttm_bo_list_ref_sub(struct ttm_buffer_object *bo, int count, + bool never_free) +{ + kref_sub(&bo->list_kref, count, + (never_free) ? ttm_bo_ref_bug : ttm_bo_release_list); +} + int ttm_bo_reserve(struct ttm_buffer_object *bo, bool interruptible, bool no_wait, bool use_sequence, uint32_t sequence) @@ -282,20 +294,24 @@ put_count = ttm_bo_del_from_lru(bo); spin_unlock(&glob->lru_lock); - while (put_count--) - kref_put(&bo->list_kref, ttm_bo_ref_bug); + ttm_bo_list_ref_sub(bo, put_count, true); return ret; } +void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo) +{ + ttm_bo_add_to_lru(bo); + atomic_set(&bo->reserved, 0); + wake_up_all(&bo->event_queue); +} + void ttm_bo_unreserve(struct ttm_buffer_object *bo) { struct ttm_bo_global *glob = bo->glob; spin_lock(&glob->lru_lock); - ttm_bo_add_to_lru(bo); - atomic_set(&bo->reserved, 0); - wake_up_all(&bo->event_queue); + ttm_bo_unreserve_locked(bo); spin_unlock(&glob->lru_lock); } EXPORT_SYMBOL(ttm_bo_unreserve); @@ -362,8 +378,13 @@ int ret = 0; if (old_is_pci || new_is_pci || - ((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0)) - ttm_bo_unmap_virtual(bo); + ((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0)) { + ret = ttm_mem_io_lock(old_man, true); + if (unlikely(ret != 0)) + goto out_err; + ttm_bo_unmap_virtual_locked(bo); + ttm_mem_io_unlock(old_man); + } /* * Create and bind a ttm if required. @@ -416,11 +437,9 @@ } if (bo->mem.mm_node) { - spin_lock(&bo->lock); bo->offset = (bo->mem.start << PAGE_SHIFT) + bdev->man[bo->mem.mem_type].gpu_offset; bo->cur_placement = bo->mem.placement; - spin_unlock(&bo->lock); } else bo->offset = 0; @@ -452,7 +471,6 @@ ttm_tt_destroy(bo->ttm); bo->ttm = NULL; } - ttm_bo_mem_put(bo, &bo->mem); atomic_set(&bo->reserved, 0); @@ -474,14 +492,14 @@ int put_count; int ret; - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); (void) ttm_bo_wait(bo, false, false, true); if (!bo->sync_obj) { spin_lock(&glob->lru_lock); /** - * Lock inversion between bo::reserve and bo::lock here, + * Lock inversion between bo:reserve and bdev::fence_lock here, * but that's OK, since we're only trylocking. */ @@ -490,14 +508,13 @@ if (unlikely(ret == -EBUSY)) goto queue; - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); put_count = ttm_bo_del_from_lru(bo); spin_unlock(&glob->lru_lock); ttm_bo_cleanup_memtype_use(bo); - while (put_count--) - kref_put(&bo->list_kref, ttm_bo_ref_bug); + ttm_bo_list_ref_sub(bo, put_count, true); return; } else { @@ -512,7 +529,7 @@ kref_get(&bo->list_kref); list_add_tail(&bo->ddestroy, &bdev->ddestroy); spin_unlock(&glob->lru_lock); - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); if (sync_obj) { driver->sync_obj_flush(sync_obj, sync_obj_arg); @@ -537,14 +554,15 @@ bool no_wait_reserve, bool no_wait_gpu) { + struct ttm_bo_device *bdev = bo->bdev; struct ttm_bo_global *glob = bo->glob; int put_count; int ret = 0; retry: - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu); - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); if (unlikely(ret != 0)) return ret; @@ -580,8 +598,7 @@ spin_unlock(&glob->lru_lock); ttm_bo_cleanup_memtype_use(bo); - while (put_count--) - kref_put(&bo->list_kref, ttm_bo_ref_bug); + ttm_bo_list_ref_sub(bo, put_count, true); return 0; } @@ -652,6 +669,7 @@ struct ttm_buffer_object *bo = container_of(kref, struct ttm_buffer_object, kref); struct ttm_bo_device *bdev = bo->bdev; + struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type]; if (likely(bo->vm_node != NULL)) { rb_erase(&bo->vm_rb, &bdev->addr_space_rb); @@ -659,6 +677,9 @@ bo->vm_node = NULL; } write_unlock(&bdev->vm_lock); + ttm_mem_io_lock(man, false); + ttm_mem_io_free_vm(bo); + ttm_mem_io_unlock(man); ttm_bo_cleanup_refs_or_queue(bo); kref_put(&bo->list_kref, ttm_bo_release_list); write_lock(&bdev->vm_lock); @@ -698,9 +719,9 @@ struct ttm_placement placement; int ret = 0; - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu); - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); if (unlikely(ret != 0)) { if (ret != -ERESTARTSYS) { @@ -715,7 +736,8 @@ evict_mem = bo->mem; evict_mem.mm_node = NULL; - evict_mem.bus.io_reserved = false; + evict_mem.bus.io_reserved_vm = false; + evict_mem.bus.io_reserved_count = 0; placement.fpfn = 0; placement.lpfn = 0; @@ -802,8 +824,7 @@ BUG_ON(ret != 0); - while (put_count--) - kref_put(&bo->list_kref, ttm_bo_ref_bug); + ttm_bo_list_ref_sub(bo, put_count, true); ret = ttm_bo_evict(bo, interruptible, no_wait_reserve, no_wait_gpu); ttm_bo_unreserve(bo); @@ -1036,6 +1057,7 @@ { int ret = 0; struct ttm_mem_reg mem; + struct ttm_bo_device *bdev = bo->bdev; BUG_ON(!atomic_read(&bo->reserved)); @@ -1044,15 +1066,16 @@ * Have the driver move function wait for idle when necessary, * instead of doing it here. */ - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu); - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); if (ret) return ret; mem.num_pages = bo->num_pages; mem.size = mem.num_pages << PAGE_SHIFT; mem.page_alignment = bo->mem.page_alignment; - mem.bus.io_reserved = false; + mem.bus.io_reserved_vm = false; + mem.bus.io_reserved_count = 0; /* * Determine where to move the buffer. */ @@ -1163,7 +1186,6 @@ } bo->destroy = destroy; - spin_lock_init(&bo->lock); kref_init(&bo->kref); kref_init(&bo->list_kref); atomic_set(&bo->cpu_writers, 0); @@ -1172,6 +1194,7 @@ INIT_LIST_HEAD(&bo->lru); INIT_LIST_HEAD(&bo->ddestroy); INIT_LIST_HEAD(&bo->swap); + INIT_LIST_HEAD(&bo->io_reserve_lru); bo->bdev = bdev; bo->glob = bdev->glob; bo->type = type; @@ -1181,7 +1204,8 @@ bo->mem.num_pages = bo->num_pages; bo->mem.mm_node = NULL; bo->mem.page_alignment = page_alignment; - bo->mem.bus.io_reserved = false; + bo->mem.bus.io_reserved_vm = false; + bo->mem.bus.io_reserved_count = 0; bo->buffer_start = buffer_start & PAGE_MASK; bo->priv_flags = 0; bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED); @@ -1355,6 +1379,10 @@ BUG_ON(type >= TTM_NUM_MEM_TYPES); man = &bdev->man[type]; BUG_ON(man->has_type); + man->io_reserve_fastpath = true; + man->use_io_reserve_lru = false; + mutex_init(&man->io_reserve_mutex); + INIT_LIST_HEAD(&man->io_reserve_lru); ret = bdev->driver->init_mem_type(bdev, type, man); if (ret) @@ -1527,7 +1555,8 @@ bdev->dev_mapping = NULL; bdev->glob = glob; bdev->need_dma32 = need_dma32; - + bdev->val_seq = 0; + spin_lock_init(&bdev->fence_lock); mutex_lock(&glob->device_list_mutex); list_add_tail(&bdev->device_list, &glob->device_list); mutex_unlock(&glob->device_list_mutex); @@ -1561,7 +1590,7 @@ return true; } -void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) +void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo) { struct ttm_bo_device *bdev = bo->bdev; loff_t offset = (loff_t) bo->addr_space_offset; @@ -1570,8 +1599,20 @@ if (!bdev->dev_mapping) return; unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1); - ttm_mem_io_free(bdev, &bo->mem); + ttm_mem_io_free_vm(bo); +} + +void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) +{ + struct ttm_bo_device *bdev = bo->bdev; + struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type]; + + ttm_mem_io_lock(man, false); + ttm_bo_unmap_virtual_locked(bo); + ttm_mem_io_unlock(man); } + + EXPORT_SYMBOL(ttm_bo_unmap_virtual); static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo) @@ -1651,6 +1692,7 @@ bool lazy, bool interruptible, bool no_wait) { struct ttm_bo_driver *driver = bo->bdev->driver; + struct ttm_bo_device *bdev = bo->bdev; void *sync_obj; void *sync_obj_arg; int ret = 0; @@ -1664,9 +1706,9 @@ void *tmp_obj = bo->sync_obj; bo->sync_obj = NULL; clear_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags); - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); driver->sync_obj_unref(&tmp_obj); - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); continue; } @@ -1675,29 +1717,29 @@ sync_obj = driver->sync_obj_ref(bo->sync_obj); sync_obj_arg = bo->sync_obj_arg; - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); ret = driver->sync_obj_wait(sync_obj, sync_obj_arg, lazy, interruptible); if (unlikely(ret != 0)) { driver->sync_obj_unref(&sync_obj); - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); return ret; } - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); if (likely(bo->sync_obj == sync_obj && bo->sync_obj_arg == sync_obj_arg)) { void *tmp_obj = bo->sync_obj; bo->sync_obj = NULL; clear_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags); - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); driver->sync_obj_unref(&sync_obj); driver->sync_obj_unref(&tmp_obj); - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); } else { - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); driver->sync_obj_unref(&sync_obj); - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); } } return 0; @@ -1706,6 +1748,7 @@ int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait) { + struct ttm_bo_device *bdev = bo->bdev; int ret = 0; /* @@ -1715,9 +1758,9 @@ ret = ttm_bo_reserve(bo, true, no_wait, false, 0); if (unlikely(ret != 0)) return ret; - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); ret = ttm_bo_wait(bo, false, true, no_wait); - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); if (likely(ret == 0)) atomic_inc(&bo->cpu_writers); ttm_bo_unreserve(bo); @@ -1783,16 +1826,15 @@ put_count = ttm_bo_del_from_lru(bo); spin_unlock(&glob->lru_lock); - while (put_count--) - kref_put(&bo->list_kref, ttm_bo_ref_bug); + ttm_bo_list_ref_sub(bo, put_count, true); /** * Wait for GPU, then move to system cached. */ - spin_lock(&bo->lock); + spin_lock(&bo->bdev->fence_lock); ret = ttm_bo_wait(bo, false, false, false); - spin_unlock(&bo->lock); + spin_unlock(&bo->bdev->fence_lock); if (unlikely(ret != 0)) goto out; --- linux-2.6.37.orig/drivers/gpu/drm/ttm/ttm_bo_util.c +++ linux-2.6.37/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -75,37 +75,123 @@ } EXPORT_SYMBOL(ttm_bo_move_ttm); -int ttm_mem_io_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) +int ttm_mem_io_lock(struct ttm_mem_type_manager *man, bool interruptible) { - int ret; + if (likely(man->io_reserve_fastpath)) + return 0; + + if (interruptible) + return mutex_lock_interruptible(&man->io_reserve_mutex); + + mutex_lock(&man->io_reserve_mutex); + return 0; +} - if (!mem->bus.io_reserved) { - mem->bus.io_reserved = true; +void ttm_mem_io_unlock(struct ttm_mem_type_manager *man) +{ + if (likely(man->io_reserve_fastpath)) + return; + + mutex_unlock(&man->io_reserve_mutex); +} + +static int ttm_mem_io_evict(struct ttm_mem_type_manager *man) +{ + struct ttm_buffer_object *bo; + + if (!man->use_io_reserve_lru || list_empty(&man->io_reserve_lru)) + return -EAGAIN; + + bo = list_first_entry(&man->io_reserve_lru, + struct ttm_buffer_object, + io_reserve_lru); + list_del_init(&bo->io_reserve_lru); + ttm_bo_unmap_virtual_locked(bo); + + return 0; +} + +static int ttm_mem_io_reserve(struct ttm_bo_device *bdev, + struct ttm_mem_reg *mem) +{ + struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; + int ret = 0; + + if (!bdev->driver->io_mem_reserve) + return 0; + if (likely(man->io_reserve_fastpath)) + return bdev->driver->io_mem_reserve(bdev, mem); + + if (bdev->driver->io_mem_reserve && + mem->bus.io_reserved_count++ == 0) { +retry: ret = bdev->driver->io_mem_reserve(bdev, mem); + if (ret == -EAGAIN) { + ret = ttm_mem_io_evict(man); + if (ret == 0) + goto retry; + } + } + return ret; +} + +static void ttm_mem_io_free(struct ttm_bo_device *bdev, + struct ttm_mem_reg *mem) +{ + struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; + + if (likely(man->io_reserve_fastpath)) + return; + + if (bdev->driver->io_mem_reserve && + --mem->bus.io_reserved_count == 0 && + bdev->driver->io_mem_free) + bdev->driver->io_mem_free(bdev, mem); + +} + +int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo) +{ + struct ttm_mem_reg *mem = &bo->mem; + int ret; + + if (!mem->bus.io_reserved_vm) { + struct ttm_mem_type_manager *man = + &bo->bdev->man[mem->mem_type]; + + ret = ttm_mem_io_reserve(bo->bdev, mem); if (unlikely(ret != 0)) return ret; + mem->bus.io_reserved_vm = true; + if (man->use_io_reserve_lru) + list_add_tail(&bo->io_reserve_lru, + &man->io_reserve_lru); } return 0; } -void ttm_mem_io_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) +void ttm_mem_io_free_vm(struct ttm_buffer_object *bo) { - if (bdev->driver->io_mem_reserve) { - if (mem->bus.io_reserved) { - mem->bus.io_reserved = false; - bdev->driver->io_mem_free(bdev, mem); - } + struct ttm_mem_reg *mem = &bo->mem; + + if (mem->bus.io_reserved_vm) { + mem->bus.io_reserved_vm = false; + list_del_init(&bo->io_reserve_lru); + ttm_mem_io_free(bo->bdev, mem); } } int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, void **virtual) { + struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; int ret; void *addr; *virtual = NULL; + (void) ttm_mem_io_lock(man, false); ret = ttm_mem_io_reserve(bdev, mem); + ttm_mem_io_unlock(man); if (ret || !mem->bus.is_iomem) return ret; @@ -117,7 +203,9 @@ else addr = ioremap_nocache(mem->bus.base + mem->bus.offset, mem->bus.size); if (!addr) { + (void) ttm_mem_io_lock(man, false); ttm_mem_io_free(bdev, mem); + ttm_mem_io_unlock(man); return -ENOMEM; } } @@ -134,7 +222,9 @@ if (virtual && mem->bus.addr == NULL) iounmap(virtual); + (void) ttm_mem_io_lock(man, false); ttm_mem_io_free(bdev, mem); + ttm_mem_io_unlock(man); } static int ttm_copy_io_page(void *dst, void *src, unsigned long page) @@ -231,7 +321,7 @@ struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type]; struct ttm_tt *ttm = bo->ttm; struct ttm_mem_reg *old_mem = &bo->mem; - struct ttm_mem_reg old_copy = *old_mem; + struct ttm_mem_reg old_copy; void *old_iomap; void *new_iomap; int ret; @@ -280,8 +370,7 @@ } mb(); out2: - ttm_bo_free_old_node(bo); - + old_copy = *old_mem; *old_mem = *new_mem; new_mem->mm_node = NULL; @@ -292,9 +381,10 @@ } out1: - ttm_mem_reg_iounmap(bdev, new_mem, new_iomap); + ttm_mem_reg_iounmap(bdev, old_mem, new_iomap); out: ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap); + ttm_bo_mem_put(bo, &old_copy); return ret; } EXPORT_SYMBOL(ttm_bo_move_memcpy); @@ -337,11 +427,11 @@ * TODO: Explicit member copy would probably be better here. */ - spin_lock_init(&fbo->lock); init_waitqueue_head(&fbo->event_queue); INIT_LIST_HEAD(&fbo->ddestroy); INIT_LIST_HEAD(&fbo->lru); INIT_LIST_HEAD(&fbo->swap); + INIT_LIST_HEAD(&fbo->io_reserve_lru); fbo->vm_node = NULL; atomic_set(&fbo->cpu_writers, 0); @@ -453,6 +543,8 @@ unsigned long start_page, unsigned long num_pages, struct ttm_bo_kmap_obj *map) { + struct ttm_mem_type_manager *man = + &bo->bdev->man[bo->mem.mem_type]; unsigned long offset, size; int ret; @@ -467,7 +559,9 @@ if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC)) return -EPERM; #endif + (void) ttm_mem_io_lock(man, false); ret = ttm_mem_io_reserve(bo->bdev, &bo->mem); + ttm_mem_io_unlock(man); if (ret) return ret; if (!bo->mem.bus.is_iomem) { @@ -482,12 +576,15 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) { + struct ttm_buffer_object *bo = map->bo; + struct ttm_mem_type_manager *man = + &bo->bdev->man[bo->mem.mem_type]; + if (!map->virtual) return; switch (map->bo_kmap_type) { case ttm_bo_map_iomap: iounmap(map->virtual); - ttm_mem_io_free(map->bo->bdev, &map->bo->mem); break; case ttm_bo_map_vmap: vunmap(map->virtual); @@ -500,6 +597,9 @@ default: BUG(); } + (void) ttm_mem_io_lock(man, false); + ttm_mem_io_free(map->bo->bdev, &map->bo->mem); + ttm_mem_io_unlock(man); map->virtual = NULL; map->page = NULL; } @@ -520,7 +620,7 @@ struct ttm_buffer_object *ghost_obj; void *tmp_obj = NULL; - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); if (bo->sync_obj) { tmp_obj = bo->sync_obj; bo->sync_obj = NULL; @@ -529,7 +629,7 @@ bo->sync_obj_arg = sync_obj_arg; if (evict) { ret = ttm_bo_wait(bo, false, false, false); - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); if (tmp_obj) driver->sync_obj_unref(&tmp_obj); if (ret) @@ -552,7 +652,7 @@ */ set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags); - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); if (tmp_obj) driver->sync_obj_unref(&tmp_obj); --- linux-2.6.37.orig/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ linux-2.6.37/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -83,6 +83,8 @@ int i; unsigned long address = (unsigned long)vmf->virtual_address; int retval = VM_FAULT_NOPAGE; + struct ttm_mem_type_manager *man = + &bdev->man[bo->mem.mem_type]; /* * Work around locking order reversal in fault / nopfn @@ -118,24 +120,28 @@ * move. */ - spin_lock(&bo->lock); + spin_lock(&bdev->fence_lock); if (test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)) { ret = ttm_bo_wait(bo, false, true, false); - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); if (unlikely(ret != 0)) { retval = (ret != -ERESTARTSYS) ? VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; goto out_unlock; } } else - spin_unlock(&bo->lock); + spin_unlock(&bdev->fence_lock); - - ret = ttm_mem_io_reserve(bdev, &bo->mem); - if (ret) { - retval = VM_FAULT_SIGBUS; + ret = ttm_mem_io_lock(man, true); + if (unlikely(ret != 0)) { + retval = VM_FAULT_NOPAGE; goto out_unlock; } + ret = ttm_mem_io_reserve_vm(bo); + if (unlikely(ret != 0)) { + retval = VM_FAULT_SIGBUS; + goto out_io_unlock; + } page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + bo->vm_node->start - vma->vm_pgoff; @@ -144,7 +150,7 @@ if (unlikely(page_offset >= bo->num_pages)) { retval = VM_FAULT_SIGBUS; - goto out_unlock; + goto out_io_unlock; } /* @@ -182,7 +188,7 @@ page = ttm_tt_get_page(ttm, page_offset); if (unlikely(!page && i == 0)) { retval = VM_FAULT_OOM; - goto out_unlock; + goto out_io_unlock; } else if (unlikely(!page)) { break; } @@ -200,14 +206,15 @@ else if (unlikely(ret != 0)) { retval = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; - goto out_unlock; + goto out_io_unlock; } address += PAGE_SIZE; if (unlikely(++page_offset >= page_last)) break; } - +out_io_unlock: + ttm_mem_io_unlock(man); out_unlock: ttm_bo_unreserve(bo); return retval; --- linux-2.6.37.orig/drivers/gpu/drm/ttm/ttm_execbuf_util.c +++ linux-2.6.37/drivers/gpu/drm/ttm/ttm_execbuf_util.c @@ -32,7 +32,7 @@ #include #include -void ttm_eu_backoff_reservation(struct list_head *list) +static void ttm_eu_backoff_reservation_locked(struct list_head *list) { struct ttm_validate_buffer *entry; @@ -41,10 +41,77 @@ if (!entry->reserved) continue; + if (entry->removed) { + ttm_bo_add_to_lru(bo); + entry->removed = false; + + } entry->reserved = false; - ttm_bo_unreserve(bo); + atomic_set(&bo->reserved, 0); + wake_up_all(&bo->event_queue); + } +} + +static void ttm_eu_del_from_lru_locked(struct list_head *list) +{ + struct ttm_validate_buffer *entry; + + list_for_each_entry(entry, list, head) { + struct ttm_buffer_object *bo = entry->bo; + if (!entry->reserved) + continue; + + if (!entry->removed) { + entry->put_count = ttm_bo_del_from_lru(bo); + entry->removed = true; + } + } +} + +static void ttm_eu_list_ref_sub(struct list_head *list) +{ + struct ttm_validate_buffer *entry; + + list_for_each_entry(entry, list, head) { + struct ttm_buffer_object *bo = entry->bo; + + if (entry->put_count) { + ttm_bo_list_ref_sub(bo, entry->put_count, true); + entry->put_count = 0; + } } } + +static int ttm_eu_wait_unreserved_locked(struct list_head *list, + struct ttm_buffer_object *bo) +{ + struct ttm_bo_global *glob = bo->glob; + int ret; + + ttm_eu_del_from_lru_locked(list); + spin_unlock(&glob->lru_lock); + ret = ttm_bo_wait_unreserved(bo, true); + spin_lock(&glob->lru_lock); + if (unlikely(ret != 0)) + ttm_eu_backoff_reservation_locked(list); + return ret; +} + + +void ttm_eu_backoff_reservation(struct list_head *list) +{ + struct ttm_validate_buffer *entry; + struct ttm_bo_global *glob; + + if (list_empty(list)) + return; + + entry = list_first_entry(list, struct ttm_validate_buffer, head); + glob = entry->bo->glob; + spin_lock(&glob->lru_lock); + ttm_eu_backoff_reservation_locked(list); + spin_unlock(&glob->lru_lock); +} EXPORT_SYMBOL(ttm_eu_backoff_reservation); /* @@ -59,37 +126,76 @@ * buffers in different orders. */ -int ttm_eu_reserve_buffers(struct list_head *list, uint32_t val_seq) +int ttm_eu_reserve_buffers(struct list_head *list) { + struct ttm_bo_global *glob; struct ttm_validate_buffer *entry; int ret; + uint32_t val_seq; + + if (list_empty(list)) + return 0; + + list_for_each_entry(entry, list, head) { + entry->reserved = false; + entry->put_count = 0; + entry->removed = false; + } + + entry = list_first_entry(list, struct ttm_validate_buffer, head); + glob = entry->bo->glob; retry: + spin_lock(&glob->lru_lock); + val_seq = entry->bo->bdev->val_seq++; + list_for_each_entry(entry, list, head) { struct ttm_buffer_object *bo = entry->bo; - entry->reserved = false; - ret = ttm_bo_reserve(bo, true, false, true, val_seq); - if (ret != 0) { - ttm_eu_backoff_reservation(list); - if (ret == -EAGAIN) { - ret = ttm_bo_wait_unreserved(bo, true); - if (unlikely(ret != 0)) - return ret; - goto retry; - } else +retry_this_bo: + ret = ttm_bo_reserve_locked(bo, true, true, true, val_seq); + switch (ret) { + case 0: + break; + case -EBUSY: + ret = ttm_eu_wait_unreserved_locked(list, bo); + if (unlikely(ret != 0)) { + spin_unlock(&glob->lru_lock); + ttm_eu_list_ref_sub(list); return ret; + } + goto retry_this_bo; + case -EAGAIN: + ttm_eu_backoff_reservation_locked(list); + spin_unlock(&glob->lru_lock); + ttm_eu_list_ref_sub(list); + ret = ttm_bo_wait_unreserved(bo, true); + if (unlikely(ret != 0)) + return ret; + goto retry; + default: + ttm_eu_backoff_reservation_locked(list); + spin_unlock(&glob->lru_lock); + ttm_eu_list_ref_sub(list); + return ret; } entry->reserved = true; if (unlikely(atomic_read(&bo->cpu_writers) > 0)) { - ttm_eu_backoff_reservation(list); + ttm_eu_backoff_reservation_locked(list); + spin_unlock(&glob->lru_lock); + ttm_eu_list_ref_sub(list); ret = ttm_bo_wait_cpu(bo, false); if (ret) return ret; goto retry; } } + + ttm_eu_del_from_lru_locked(list); + spin_unlock(&glob->lru_lock); + ttm_eu_list_ref_sub(list); + return 0; } EXPORT_SYMBOL(ttm_eu_reserve_buffers); @@ -97,21 +203,36 @@ void ttm_eu_fence_buffer_objects(struct list_head *list, void *sync_obj) { struct ttm_validate_buffer *entry; + struct ttm_buffer_object *bo; + struct ttm_bo_global *glob; + struct ttm_bo_device *bdev; + struct ttm_bo_driver *driver; + + if (list_empty(list)) + return; + + bo = list_first_entry(list, struct ttm_validate_buffer, head)->bo; + bdev = bo->bdev; + driver = bdev->driver; + glob = bo->glob; - list_for_each_entry(entry, list, head) { - struct ttm_buffer_object *bo = entry->bo; - struct ttm_bo_driver *driver = bo->bdev->driver; - void *old_sync_obj; + spin_lock(&bdev->fence_lock); + spin_lock(&glob->lru_lock); - spin_lock(&bo->lock); - old_sync_obj = bo->sync_obj; + list_for_each_entry(entry, list, head) { + bo = entry->bo; + entry->old_sync_obj = bo->sync_obj; bo->sync_obj = driver->sync_obj_ref(sync_obj); bo->sync_obj_arg = entry->new_sync_obj_arg; - spin_unlock(&bo->lock); - ttm_bo_unreserve(bo); + ttm_bo_unreserve_locked(bo); entry->reserved = false; - if (old_sync_obj) - driver->sync_obj_unref(&old_sync_obj); + } + spin_unlock(&glob->lru_lock); + spin_unlock(&bdev->fence_lock); + + list_for_each_entry(entry, list, head) { + if (entry->old_sync_obj) + driver->sync_obj_unref(&entry->old_sync_obj); } } EXPORT_SYMBOL(ttm_eu_fence_buffer_objects); --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/Makefile +++ linux-2.6.37/drivers/gpu/drm/nouveau/Makefile @@ -5,12 +5,13 @@ ccflags-y := -Iinclude/drm nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ nouveau_object.o nouveau_irq.o nouveau_notifier.o \ - nouveau_sgdma.o nouveau_dma.o \ + nouveau_sgdma.o nouveau_dma.o nouveau_util.o \ nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ nouveau_dp.o nouveau_ramht.o \ nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ + nouveau_mm.o nouveau_vm.o \ nv04_timer.o \ nv04_mc.o nv40_mc.o nv50_mc.o \ nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ @@ -18,14 +19,16 @@ nv04_graph.o nv10_graph.o nv20_graph.o \ nv40_graph.o nv50_graph.o nvc0_graph.o \ nv40_grctx.o nv50_grctx.o \ + nv84_crypt.o \ nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ - nv50_crtc.o nv50_dac.o nv50_sor.o \ + nv50_evo.o nv50_crtc.o nv50_dac.o nv50_sor.o \ nv50_cursor.o nv50_display.o nv50_fbcon.o \ nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ nv10_gpio.o nv50_gpio.o \ nv50_calc.o \ - nv04_pm.o nv50_pm.o nva3_pm.o + nv04_pm.o nv50_pm.o nva3_pm.o \ + nv50_vram.o nv50_vm.o nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_bios.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -6053,52 +6053,17 @@ return entry; } -static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads) +static void fabricate_dcb_output(struct dcb_table *dcb, int type, int i2c, + int heads, int or) { struct dcb_entry *entry = new_dcb_entry(dcb); - entry->type = 0; + entry->type = type; entry->i2c_index = i2c; entry->heads = heads; - entry->location = DCB_LOC_ON_CHIP; - entry->or = 1; -} - -static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads) -{ - struct dcb_entry *entry = new_dcb_entry(dcb); - - entry->type = 2; - entry->i2c_index = LEGACY_I2C_PANEL; - entry->heads = twoHeads ? 3 : 1; - entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ - entry->or = 1; /* means |0x10 gets set on CRE_LCD__INDEX */ - entry->duallink_possible = false; /* SiI164 and co. are single link */ - -#if 0 - /* - * For dvi-a either crtc probably works, but my card appears to only - * support dvi-d. "nvidia" still attempts to program it for dvi-a, - * doing the full fp output setup (program 0x6808.. fp dimension regs, - * setting 0x680848 to 0x10000111 to enable, maybe setting 0x680880); - * the monitor picks up the mode res ok and lights up, but no pixel - * data appears, so the board manufacturer probably connected up the - * sync lines, but missed the video traces / components - * - * with this introduction, dvi-a left as an exercise for the reader. - */ - fabricate_vga_output(dcb, LEGACY_I2C_PANEL, entry->heads); -#endif -} - -static void fabricate_tv_output(struct dcb_table *dcb, bool twoHeads) -{ - struct dcb_entry *entry = new_dcb_entry(dcb); - - entry->type = 1; - entry->i2c_index = LEGACY_I2C_TV; - entry->heads = twoHeads ? 3 : 1; - entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ + if (type != OUTPUT_ANALOG) + entry->location = !DCB_LOC_ON_CHIP; /* ie OFF CHIP */ + entry->or = or; } static bool @@ -6365,8 +6330,36 @@ return true; } +static void +fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios) +{ + struct dcb_table *dcb = &bios->dcb; + int all_heads = (nv_two_heads(dev) ? 3 : 1); + +#ifdef __powerpc__ + /* Apple iMac G4 NV17 */ + if (of_machine_is_compatible("PowerMac4,5")) { + fabricate_dcb_output(dcb, OUTPUT_TMDS, 0, all_heads, 1); + fabricate_dcb_output(dcb, OUTPUT_ANALOG, 1, all_heads, 2); + return; + } +#endif + + /* Make up some sane defaults */ + fabricate_dcb_output(dcb, OUTPUT_ANALOG, LEGACY_I2C_CRT, 1, 1); + + if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) + fabricate_dcb_output(dcb, OUTPUT_TV, LEGACY_I2C_TV, + all_heads, 0); + + else if (bios->tmds.output0_script_ptr || + bios->tmds.output1_script_ptr) + fabricate_dcb_output(dcb, OUTPUT_TMDS, LEGACY_I2C_PANEL, + all_heads, 1); +} + static int -parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) +parse_dcb_table(struct drm_device *dev, struct nvbios *bios) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct dcb_table *dcb = &bios->dcb; @@ -6386,12 +6379,7 @@ /* this situation likely means a really old card, pre DCB */ if (dcbptr == 0x0) { - NV_INFO(dev, "Assuming a CRT output exists\n"); - fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1); - - if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) - fabricate_tv_output(dcb, twoHeads); - + fabricate_dcb_encoder_table(dev, bios); return 0; } @@ -6451,21 +6439,7 @@ */ NV_TRACEWARN(dev, "No useful information in BIOS output table; " "adding all possible outputs\n"); - fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1); - - /* - * Attempt to detect TV before DVI because the test - * for the former is more accurate and it rules the - * latter out. - */ - if (nv04_tv_identify(dev, - bios->legacy.i2c_indices.tv) >= 0) - fabricate_tv_output(dcb, twoHeads); - - else if (bios->tmds.output0_script_ptr || - bios->tmds.output1_script_ptr) - fabricate_dvi_i_output(dcb, twoHeads); - + fabricate_dcb_encoder_table(dev, bios); return 0; } @@ -6859,7 +6833,7 @@ if (ret) return ret; - ret = parse_dcb_table(dev, bios, nv_two_heads(dev)); + ret = parse_dcb_table(dev, bios); if (ret) return ret; --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_bo.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -32,6 +32,8 @@ #include "nouveau_drm.h" #include "nouveau_drv.h" #include "nouveau_dma.h" +#include "nouveau_mm.h" +#include "nouveau_vm.h" #include #include @@ -46,82 +48,51 @@ if (unlikely(nvbo->gem)) DRM_ERROR("bo %p still attached to GEM object\n", bo); - if (nvbo->tile) - nv10_mem_expire_tiling(dev, nvbo->tile, NULL); - + nv10_mem_put_tile_region(dev, nvbo->tile, NULL); + nouveau_vm_put(&nvbo->vma); kfree(nvbo); } static void -nouveau_bo_fixup_align(struct drm_device *dev, - uint32_t tile_mode, uint32_t tile_flags, - int *align, int *size) +nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size, + int *page_shift) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - - /* - * Some of the tile_flags have a periodic structure of N*4096 bytes, - * align to to that as well as the page size. Align the size to the - * appropriate boundaries. This does imply that sizes are rounded up - * 3-7 pages, so be aware of this and do not waste memory by allocating - * many small buffers. - */ - if (dev_priv->card_type == NV_50) { - uint32_t block_size = dev_priv->vram_size >> 15; - int i; - - switch (tile_flags) { - case 0x1800: - case 0x2800: - case 0x4800: - case 0x7a00: - if (is_power_of_2(block_size)) { - for (i = 1; i < 10; i++) { - *align = 12 * i * block_size; - if (!(*align % 65536)) - break; - } - } else { - for (i = 1; i < 10; i++) { - *align = 8 * i * block_size; - if (!(*align % 65536)) - break; - } - } - *size = roundup(*size, *align); - break; - default: - break; - } + struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); - } else { - if (tile_mode) { + if (dev_priv->card_type < NV_50) { + if (nvbo->tile_mode) { if (dev_priv->chipset >= 0x40) { *align = 65536; - *size = roundup(*size, 64 * tile_mode); + *size = roundup(*size, 64 * nvbo->tile_mode); } else if (dev_priv->chipset >= 0x30) { *align = 32768; - *size = roundup(*size, 64 * tile_mode); + *size = roundup(*size, 64 * nvbo->tile_mode); } else if (dev_priv->chipset >= 0x20) { *align = 16384; - *size = roundup(*size, 64 * tile_mode); + *size = roundup(*size, 64 * nvbo->tile_mode); } else if (dev_priv->chipset >= 0x10) { *align = 16384; - *size = roundup(*size, 32 * tile_mode); + *size = roundup(*size, 32 * nvbo->tile_mode); } } + } else { + if (likely(dev_priv->chan_vm)) { + if (*size > 256 * 1024) + *page_shift = dev_priv->chan_vm->lpg_shift; + else + *page_shift = dev_priv->chan_vm->spg_shift; + } else { + *page_shift = 12; + } + + *size = roundup(*size, (1 << *page_shift)); + *align = max((1 << *page_shift), *align); } - /* ALIGN works only on powers of two. */ *size = roundup(*size, PAGE_SIZE); - - if (dev_priv->card_type == NV_50) { - *size = roundup(*size, 65536); - *align = max(65536, *align); - } } int @@ -132,7 +103,7 @@ { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_bo *nvbo; - int ret = 0; + int ret = 0, page_shift = 0; nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); if (!nvbo) @@ -145,10 +116,18 @@ nvbo->tile_flags = tile_flags; nvbo->bo.bdev = &dev_priv->ttm.bdev; - nouveau_bo_fixup_align(dev, tile_mode, nouveau_bo_tile_layout(nvbo), - &align, &size); + nouveau_bo_fixup_align(nvbo, &align, &size, &page_shift); align >>= PAGE_SHIFT; + if (!nvbo->no_vm && dev_priv->chan_vm) { + ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift, + NV_MEM_ACCESS_RW, &nvbo->vma); + if (ret) { + kfree(nvbo); + return ret; + } + } + nouveau_bo_placement_set(nvbo, flags, 0); nvbo->channel = chan; @@ -161,6 +140,11 @@ } nvbo->channel = NULL; + if (nvbo->vma.node) { + if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) + nvbo->bo.offset = nvbo->vma.offset; + } + *pnvbo = nvbo; return 0; } @@ -244,7 +228,7 @@ nouveau_bo_placement_set(nvbo, memtype, 0); - ret = ttm_bo_validate(bo, &nvbo->placement, false, false, false); + ret = nouveau_bo_validate(nvbo, false, false, false); if (ret == 0) { switch (bo->mem.mem_type) { case TTM_PL_VRAM: @@ -280,7 +264,7 @@ nouveau_bo_placement_set(nvbo, bo->mem.placement, 0); - ret = ttm_bo_validate(bo, &nvbo->placement, false, false, false); + ret = nouveau_bo_validate(nvbo, false, false, false); if (ret == 0) { switch (bo->mem.mem_type) { case TTM_PL_VRAM: @@ -319,6 +303,25 @@ ttm_bo_kunmap(&nvbo->kmap); } +int +nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible, + bool no_wait_reserve, bool no_wait_gpu) +{ + int ret; + + ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, interruptible, + no_wait_reserve, no_wait_gpu); + if (ret) + return ret; + + if (nvbo->vma.node) { + if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) + nvbo->bo.offset = nvbo->vma.offset; + } + + return 0; +} + u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index) { @@ -410,37 +413,40 @@ man->default_caching = TTM_PL_FLAG_CACHED; break; case TTM_PL_VRAM: - man->func = &ttm_bo_manager_func; + if (dev_priv->card_type == NV_50) { + man->func = &nouveau_vram_manager; + man->io_reserve_fastpath = false; + man->use_io_reserve_lru = true; + } else { + man->func = &ttm_bo_manager_func; + } man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_MAPPABLE; man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; man->default_caching = TTM_PL_FLAG_WC; - if (dev_priv->card_type == NV_50) - man->gpu_offset = 0x40000000; - else - man->gpu_offset = 0; break; case TTM_PL_TT: man->func = &ttm_bo_manager_func; switch (dev_priv->gart_info.type) { case NOUVEAU_GART_AGP: man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; - man->available_caching = TTM_PL_FLAG_UNCACHED; - man->default_caching = TTM_PL_FLAG_UNCACHED; + man->available_caching = TTM_PL_FLAG_UNCACHED | + TTM_PL_FLAG_WC; + man->default_caching = TTM_PL_FLAG_WC; break; case NOUVEAU_GART_SGDMA: man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA; man->available_caching = TTM_PL_MASK_CACHING; man->default_caching = TTM_PL_FLAG_CACHED; + man->gpu_offset = dev_priv->gart_info.aper_base; break; default: NV_ERROR(dev, "Unknown GART type: %d\n", dev_priv->gart_info.type); return -EINVAL; } - man->gpu_offset = dev_priv->vm_gart_base; break; default: NV_ERROR(dev, "Unsupported memory type %u\n", (unsigned)type); @@ -485,16 +491,9 @@ if (ret) return ret; - if (nvbo->channel) { - ret = nouveau_fence_sync(fence, nvbo->channel); - if (ret) - goto out; - } - ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, evict, no_wait_reserve, no_wait_gpu, new_mem); -out: - nouveau_fence_unref((void *)&fence); + nouveau_fence_unref(&fence); return ret; } @@ -529,14 +528,14 @@ dst_offset = new_mem->start << PAGE_SHIFT; if (!nvbo->no_vm) { if (old_mem->mem_type == TTM_PL_VRAM) - src_offset += dev_priv->vm_vram_base; + src_offset = nvbo->vma.offset; else - src_offset += dev_priv->vm_gart_base; + src_offset += dev_priv->gart_info.aper_base; if (new_mem->mem_type == TTM_PL_VRAM) - dst_offset += dev_priv->vm_vram_base; + dst_offset = nvbo->vma.offset; else - dst_offset += dev_priv->vm_gart_base; + dst_offset += dev_priv->gart_info.aper_base; } ret = RING_SPACE(chan, 3); @@ -683,17 +682,24 @@ int ret; chan = nvbo->channel; - if (!chan || nvbo->no_vm) + if (!chan || nvbo->no_vm) { chan = dev_priv->channel; + mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX); + } if (dev_priv->card_type < NV_50) ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem); else ret = nv50_bo_move_m2mf(chan, bo, &bo->mem, new_mem); - if (ret) - return ret; + if (ret == 0) { + ret = nouveau_bo_move_accel_cleanup(chan, nvbo, evict, + no_wait_reserve, + no_wait_gpu, new_mem); + } - return nouveau_bo_move_accel_cleanup(chan, nvbo, evict, no_wait_reserve, no_wait_gpu, new_mem); + if (chan == dev_priv->channel) + mutex_unlock(&chan->mutex); + return ret; } static int @@ -771,7 +777,6 @@ struct drm_device *dev = dev_priv->dev; struct nouveau_bo *nvbo = nouveau_bo(bo); uint64_t offset; - int ret; if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) { /* Nothing to do. */ @@ -781,18 +786,12 @@ offset = new_mem->start << PAGE_SHIFT; - if (dev_priv->card_type == NV_50) { - ret = nv50_mem_vm_bind_linear(dev, - offset + dev_priv->vm_vram_base, - new_mem->size, - nouveau_bo_tile_layout(nvbo), - offset); - if (ret) - return ret; - + if (dev_priv->chan_vm) { + nouveau_vm_map(&nvbo->vma, new_mem->mm_node); } else if (dev_priv->card_type >= NV_10) { *new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size, - nvbo->tile_mode); + nvbo->tile_mode, + nvbo->tile_flags); } return 0; @@ -808,9 +807,7 @@ if (dev_priv->card_type >= NV_10 && dev_priv->card_type < NV_50) { - if (*old_tile) - nv10_mem_expire_tiling(dev, *old_tile, bo->sync_obj); - + nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj); *old_tile = new_tile; } } @@ -879,6 +876,7 @@ struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); struct drm_device *dev = dev_priv->dev; + int ret; mem->bus.addr = NULL; mem->bus.offset = 0; @@ -901,9 +899,32 @@ #endif break; case TTM_PL_VRAM: - mem->bus.offset = mem->start << PAGE_SHIFT; + { + struct nouveau_vram *vram = mem->mm_node; + + if (!dev_priv->bar1_vm) { + mem->bus.offset = mem->start << PAGE_SHIFT; + mem->bus.base = pci_resource_start(dev->pdev, 1); + mem->bus.is_iomem = true; + break; + } + + ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size, 12, + NV_MEM_ACCESS_RW, &vram->bar_vma); + if (ret) + return ret; + + nouveau_vm_map(&vram->bar_vma, vram); + if (ret) { + nouveau_vm_put(&vram->bar_vma); + return ret; + } + + mem->bus.offset = vram->bar_vma.offset; + mem->bus.offset -= 0x0020000000ULL; mem->bus.base = pci_resource_start(dev->pdev, 1); mem->bus.is_iomem = true; + } break; default: return -EINVAL; @@ -914,6 +935,17 @@ static void nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) { + struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev); + struct nouveau_vram *vram = mem->mm_node; + + if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM) + return; + + if (!vram->bar_vma.node) + return; + + nouveau_vm_unmap(&vram->bar_vma); + nouveau_vm_put(&vram->bar_vma); } static int @@ -939,7 +971,23 @@ nvbo->placement.fpfn = 0; nvbo->placement.lpfn = dev_priv->fb_mappable_pages; nouveau_bo_placement_set(nvbo, TTM_PL_VRAM, 0); - return ttm_bo_validate(bo, &nvbo->placement, false, true, false); + return nouveau_bo_validate(nvbo, false, true, false); +} + +void +nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence) +{ + struct nouveau_fence *old_fence; + + if (likely(fence)) + nouveau_fence_ref(fence); + + spin_lock(&nvbo->bo.bdev->fence_lock); + old_fence = nvbo->bo.sync_obj; + nvbo->bo.sync_obj = fence; + spin_unlock(&nvbo->bo.bdev->fence_lock); + + nouveau_fence_unref(&old_fence); } struct ttm_bo_driver nouveau_bo_driver = { @@ -949,11 +997,11 @@ .evict_flags = nouveau_bo_evict_flags, .move = nouveau_bo_move, .verify_access = nouveau_bo_verify_access, - .sync_obj_signaled = nouveau_fence_signalled, - .sync_obj_wait = nouveau_fence_wait, - .sync_obj_flush = nouveau_fence_flush, - .sync_obj_unref = nouveau_fence_unref, - .sync_obj_ref = nouveau_fence_ref, + .sync_obj_signaled = __nouveau_fence_signalled, + .sync_obj_wait = __nouveau_fence_wait, + .sync_obj_flush = __nouveau_fence_flush, + .sync_obj_unref = __nouveau_fence_unref, + .sync_obj_ref = __nouveau_fence_ref, .fault_reserve_notify = &nouveau_ttm_fault_reserve_notify, .io_mem_reserve = &nouveau_ttm_io_mem_reserve, .io_mem_free = &nouveau_ttm_io_mem_free, --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_channel.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -39,22 +39,22 @@ if (dev_priv->card_type >= NV_50) { ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, - dev_priv->vm_end, NV_DMA_ACCESS_RO, - NV_DMA_TARGET_AGP, &pushbuf); + (1ULL << 40), NV_MEM_ACCESS_RO, + NV_MEM_TARGET_VM, &pushbuf); chan->pushbuf_base = pb->bo.offset; } else if (pb->bo.mem.mem_type == TTM_PL_TT) { - ret = nouveau_gpuobj_gart_dma_new(chan, 0, - dev_priv->gart_info.aper_size, - NV_DMA_ACCESS_RO, &pushbuf, - NULL); + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, + dev_priv->gart_info.aper_size, + NV_MEM_ACCESS_RO, + NV_MEM_TARGET_GART, &pushbuf); chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; } else if (dev_priv->card_type != NV_04) { ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, dev_priv->fb_available_size, - NV_DMA_ACCESS_RO, - NV_DMA_TARGET_VIDMEM, &pushbuf); + NV_MEM_ACCESS_RO, + NV_MEM_TARGET_VRAM, &pushbuf); chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; } else { /* NV04 cmdbuf hack, from original ddx.. not sure of it's @@ -62,11 +62,10 @@ * VRAM. */ ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - pci_resource_start(dev->pdev, - 1), + pci_resource_start(dev->pdev, 1), dev_priv->fb_available_size, - NV_DMA_ACCESS_RO, - NV_DMA_TARGET_PCI, &pushbuf); + NV_MEM_ACCESS_RO, + NV_MEM_TARGET_PCI, &pushbuf); chan->pushbuf_base = pb->bo.mem.start << PAGE_SHIFT; } @@ -107,74 +106,60 @@ int nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, struct drm_file *file_priv, - uint32_t vram_handle, uint32_t tt_handle) + uint32_t vram_handle, uint32_t gart_handle) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; struct nouveau_channel *chan; - int channel, user; + unsigned long flags; int ret; - /* - * Alright, here is the full story - * Nvidia cards have multiple hw fifo contexts (praise them for that, - * no complicated crash-prone context switches) - * We allocate a new context for each app and let it write to it - * directly (woo, full userspace command submission !) - * When there are no more contexts, you lost - */ - for (channel = 0; channel < pfifo->channels; channel++) { - if (dev_priv->fifos[channel] == NULL) + /* allocate and lock channel structure */ + chan = kzalloc(sizeof(*chan), GFP_KERNEL); + if (!chan) + return -ENOMEM; + chan->dev = dev; + chan->file_priv = file_priv; + chan->vram_handle = vram_handle; + chan->gart_handle = gart_handle; + + kref_init(&chan->ref); + atomic_set(&chan->users, 1); + mutex_init(&chan->mutex); + mutex_lock(&chan->mutex); + + /* allocate hw channel id */ + spin_lock_irqsave(&dev_priv->channels.lock, flags); + for (chan->id = 0; chan->id < pfifo->channels; chan->id++) { + if (!dev_priv->channels.ptr[chan->id]) { + nouveau_channel_ref(chan, &dev_priv->channels.ptr[chan->id]); break; + } } + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - /* no more fifos. you lost. */ - if (channel == pfifo->channels) - return -EINVAL; + if (chan->id == pfifo->channels) { + mutex_unlock(&chan->mutex); + kfree(chan); + return -ENODEV; + } - dev_priv->fifos[channel] = kzalloc(sizeof(struct nouveau_channel), - GFP_KERNEL); - if (!dev_priv->fifos[channel]) - return -ENOMEM; - chan = dev_priv->fifos[channel]; + NV_DEBUG(dev, "initialising channel %d\n", chan->id); INIT_LIST_HEAD(&chan->nvsw.vbl_wait); + INIT_LIST_HEAD(&chan->nvsw.flip); INIT_LIST_HEAD(&chan->fence.pending); - chan->dev = dev; - chan->id = channel; - chan->file_priv = file_priv; - chan->vram_handle = vram_handle; - chan->gart_handle = tt_handle; - - NV_INFO(dev, "Allocating FIFO number %d\n", channel); /* Allocate DMA push buffer */ chan->pushbuf_bo = nouveau_channel_user_pushbuf_alloc(dev); if (!chan->pushbuf_bo) { ret = -ENOMEM; NV_ERROR(dev, "pushbuf %d\n", ret); - nouveau_channel_free(chan); + nouveau_channel_put(&chan); return ret; } nouveau_dma_pre_init(chan); - - /* Locate channel's user control regs */ - if (dev_priv->card_type < NV_40) - user = NV03_USER(channel); - else - if (dev_priv->card_type < NV_50) - user = NV40_USER(channel); - else - user = NV50_USER(channel); - - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + user, - PAGE_SIZE); - if (!chan->user) { - NV_ERROR(dev, "ioremap of regs failed.\n"); - nouveau_channel_free(chan); - return -ENOMEM; - } chan->user_put = 0x40; chan->user_get = 0x44; @@ -182,15 +167,15 @@ ret = nouveau_notifier_init_channel(chan); if (ret) { NV_ERROR(dev, "ntfy %d\n", ret); - nouveau_channel_free(chan); + nouveau_channel_put(&chan); return ret; } /* Setup channel's default objects */ - ret = nouveau_gpuobj_channel_init(chan, vram_handle, tt_handle); + ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle); if (ret) { NV_ERROR(dev, "gpuobj %d\n", ret); - nouveau_channel_free(chan); + nouveau_channel_put(&chan); return ret; } @@ -198,7 +183,7 @@ ret = nouveau_channel_pushbuf_ctxdma_init(chan); if (ret) { NV_ERROR(dev, "pbctxdma %d\n", ret); - nouveau_channel_free(chan); + nouveau_channel_put(&chan); return ret; } @@ -206,16 +191,18 @@ pfifo->reassign(dev, false); /* Create a graphics context for new channel */ - ret = pgraph->create_context(chan); - if (ret) { - nouveau_channel_free(chan); - return ret; + if (dev_priv->card_type < NV_50) { + ret = pgraph->create_context(chan); + if (ret) { + nouveau_channel_put(&chan); + return ret; + } } /* Construct inital RAMFC for new channel */ ret = pfifo->create_context(chan); if (ret) { - nouveau_channel_free(chan); + nouveau_channel_put(&chan); return ret; } @@ -225,83 +212,108 @@ if (!ret) ret = nouveau_fence_channel_init(chan); if (ret) { - nouveau_channel_free(chan); + nouveau_channel_put(&chan); return ret; } nouveau_debugfs_channel_init(chan); - NV_INFO(dev, "%s: initialised FIFO %d\n", __func__, channel); + NV_DEBUG(dev, "channel %d initialised\n", chan->id); *chan_ret = chan; return 0; } -/* stops a fifo */ +struct nouveau_channel * +nouveau_channel_get_unlocked(struct nouveau_channel *ref) +{ + struct nouveau_channel *chan = NULL; + + if (likely(ref && atomic_inc_not_zero(&ref->users))) + nouveau_channel_ref(ref, &chan); + + return chan; +} + +struct nouveau_channel * +nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); + chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]); + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + + if (unlikely(!chan)) + return ERR_PTR(-EINVAL); + + if (unlikely(file_priv && chan->file_priv != file_priv)) { + nouveau_channel_put_unlocked(&chan); + return ERR_PTR(-EINVAL); + } + + mutex_lock(&chan->mutex); + return chan; +} + void -nouveau_channel_free(struct nouveau_channel *chan) +nouveau_channel_put_unlocked(struct nouveau_channel **pchan) { + struct nouveau_channel *chan = *pchan; struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; unsigned long flags; - int ret; - NV_INFO(dev, "%s: freeing fifo %d\n", __func__, chan->id); + /* decrement the refcount, and we're done if there's still refs */ + if (likely(!atomic_dec_and_test(&chan->users))) { + nouveau_channel_ref(NULL, pchan); + return; + } + /* noone wants the channel anymore */ + NV_DEBUG(dev, "freeing channel %d\n", chan->id); nouveau_debugfs_channel_fini(chan); - /* Give outstanding push buffers a chance to complete */ - nouveau_fence_update(chan); - if (chan->fence.sequence != chan->fence.sequence_ack) { - struct nouveau_fence *fence = NULL; - - ret = nouveau_fence_new(chan, &fence, true); - if (ret == 0) { - ret = nouveau_fence_wait(fence, NULL, false, false); - nouveau_fence_unref((void *)&fence); - } + /* give it chance to idle */ + nouveau_channel_idle(chan); - if (ret) - NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id); - } - - /* Ensure all outstanding fences are signaled. They should be if the + /* ensure all outstanding fences are signaled. they should be if the * above attempts at idling were OK, but if we failed this'll tell TTM * we're done with the buffers. */ nouveau_fence_channel_fini(chan); - /* This will prevent pfifo from switching channels. */ + /* boot it off the hardware */ pfifo->reassign(dev, false); - /* We want to give pgraph a chance to idle and get rid of all potential - * errors. We need to do this before the lock, otherwise the irq handler - * is unable to process them. + /* We want to give pgraph a chance to idle and get rid of all + * potential errors. We need to do this without the context + * switch lock held, otherwise the irq handler is unable to + * process them. */ if (pgraph->channel(dev) == chan) nouveau_wait_for_idle(dev); - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - - pgraph->fifo_access(dev, false); - if (pgraph->channel(dev) == chan) - pgraph->unload_context(dev); - pgraph->destroy_context(chan); - pgraph->fifo_access(dev, true); - - if (pfifo->channel_id(dev) == chan->id) { - pfifo->disable(dev); - pfifo->unload_context(dev); - pfifo->enable(dev); - } + /* destroy the engine specific contexts */ pfifo->destroy_context(chan); + pgraph->destroy_context(chan); + if (pcrypt->destroy_context) + pcrypt->destroy_context(chan); pfifo->reassign(dev, true); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + /* aside from its resources, the channel should now be dead, + * remove it from the channel list + */ + spin_lock_irqsave(&dev_priv->channels.lock, flags); + nouveau_channel_ref(NULL, &dev_priv->channels.ptr[chan->id]); + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); - /* Release the channel's resources */ + /* destroy any resources the channel owned */ nouveau_gpuobj_ref(NULL, &chan->pushbuf); if (chan->pushbuf_bo) { nouveau_bo_unmap(chan->pushbuf_bo); @@ -310,44 +322,80 @@ } nouveau_gpuobj_channel_takedown(chan); nouveau_notifier_takedown_channel(chan); - if (chan->user) - iounmap(chan->user); - dev_priv->fifos[chan->id] = NULL; + nouveau_channel_ref(NULL, pchan); +} + +void +nouveau_channel_put(struct nouveau_channel **pchan) +{ + mutex_unlock(&(*pchan)->mutex); + nouveau_channel_put_unlocked(pchan); +} + +static void +nouveau_channel_del(struct kref *ref) +{ + struct nouveau_channel *chan = + container_of(ref, struct nouveau_channel, ref); + kfree(chan); } +void +nouveau_channel_ref(struct nouveau_channel *chan, + struct nouveau_channel **pchan) +{ + if (chan) + kref_get(&chan->ref); + + if (*pchan) + kref_put(&(*pchan)->ref, nouveau_channel_del); + + *pchan = chan; +} + +void +nouveau_channel_idle(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct nouveau_fence *fence = NULL; + int ret; + + nouveau_fence_update(chan); + + if (chan->fence.sequence != chan->fence.sequence_ack) { + ret = nouveau_fence_new(chan, &fence, true); + if (!ret) { + ret = nouveau_fence_wait(fence, false, false); + nouveau_fence_unref(&fence); + } + + if (ret) + NV_ERROR(dev, "Failed to idle channel %d.\n", chan->id); + } +} + /* cleans up all the fifos from file_priv */ void nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->engine; + struct nouveau_channel *chan; int i; NV_DEBUG(dev, "clearing FIFO enables from file_priv\n"); for (i = 0; i < engine->fifo.channels; i++) { - struct nouveau_channel *chan = dev_priv->fifos[i]; + chan = nouveau_channel_get(dev, file_priv, i); + if (IS_ERR(chan)) + continue; - if (chan && chan->file_priv == file_priv) - nouveau_channel_free(chan); + atomic_dec(&chan->users); + nouveau_channel_put(&chan); } } -int -nouveau_channel_owner(struct drm_device *dev, struct drm_file *file_priv, - int channel) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; - - if (channel >= engine->fifo.channels) - return 0; - if (dev_priv->fifos[channel] == NULL) - return 0; - - return (dev_priv->fifos[channel]->file_priv == file_priv); -} /*********************************** * ioctls wrapping the functions @@ -395,24 +443,26 @@ /* Named memory object area */ ret = drm_gem_handle_create(file_priv, chan->notifier_bo->gem, &init->notifier_handle); - if (ret) { - nouveau_channel_free(chan); - return ret; - } - return 0; + if (ret == 0) + atomic_inc(&chan->users); /* userspace reference */ + nouveau_channel_put(&chan); + return ret; } static int nouveau_ioctl_fifo_free(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_nouveau_channel_free *cfree = data; + struct drm_nouveau_channel_free *req = data; struct nouveau_channel *chan; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan); + chan = nouveau_channel_get(dev, file_priv, req->channel); + if (IS_ERR(chan)) + return PTR_ERR(chan); - nouveau_channel_free(chan); + atomic_dec(&chan->users); + nouveau_channel_put(&chan); return 0; } @@ -421,18 +471,18 @@ ***********************************/ struct drm_ioctl_desc nouveau_ioctls[] = { - DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_ioctl_fifo_free, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_ioctl_notifier_alloc, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH), }; int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls); --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_connector.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -37,6 +37,8 @@ #include "nouveau_connector.h" #include "nouveau_hw.h" +static void nouveau_connector_hotplug(void *, int); + static struct nouveau_encoder * find_encoder_by_type(struct drm_connector *connector, int type) { @@ -94,22 +96,30 @@ } static void -nouveau_connector_destroy(struct drm_connector *drm_connector) +nouveau_connector_destroy(struct drm_connector *connector) { - struct nouveau_connector *nv_connector = - nouveau_connector(drm_connector); + struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct drm_nouveau_private *dev_priv; + struct nouveau_gpio_engine *pgpio; struct drm_device *dev; if (!nv_connector) return; dev = nv_connector->base.dev; + dev_priv = dev->dev_private; NV_DEBUG_KMS(dev, "\n"); + pgpio = &dev_priv->engine.gpio; + if (pgpio->irq_unregister) { + pgpio->irq_unregister(dev, nv_connector->dcb->gpio_tag, + nouveau_connector_hotplug, connector); + } + kfree(nv_connector->edid); - drm_sysfs_connector_remove(drm_connector); - drm_connector_cleanup(drm_connector); - kfree(drm_connector); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(connector); } static struct nouveau_i2c_chan * @@ -760,6 +770,7 @@ { const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct nouveau_connector *nv_connector = NULL; struct dcb_connector_table_entry *dcb = NULL; struct drm_connector *connector; @@ -876,6 +887,11 @@ break; } + if (pgpio->irq_register) { + pgpio->irq_register(dev, nv_connector->dcb->gpio_tag, + nouveau_connector_hotplug, connector); + } + drm_sysfs_connector_add(connector); dcb->drm = connector; return dcb->drm; @@ -886,3 +902,29 @@ return ERR_PTR(ret); } + +static void +nouveau_connector_hotplug(void *data, int plugged) +{ + struct drm_connector *connector = data; + struct drm_device *dev = connector->dev; + + NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un", + drm_get_connector_name(connector)); + + if (connector->encoder && connector->encoder->crtc && + connector->encoder->crtc->enabled) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(connector->encoder); + struct drm_encoder_helper_funcs *helper = + connector->encoder->helper_private; + + if (nv_encoder->dcb->type == OUTPUT_DP) { + if (plugged) + helper->dpms(connector->encoder, DRM_MODE_DPMS_ON); + else + helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF); + } + } + + drm_helper_hpd_irq_event(dev); +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_display.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_display.c @@ -29,6 +29,9 @@ #include "nouveau_drv.h" #include "nouveau_fb.h" #include "nouveau_fbcon.h" +#include "nouveau_hw.h" +#include "nouveau_crtc.h" +#include "nouveau_dma.h" static void nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) @@ -104,3 +107,207 @@ .output_poll_changed = nouveau_fbcon_output_poll_changed, }; +int +nouveau_vblank_enable(struct drm_device *dev, int crtc) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->card_type >= NV_50) + nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0, + NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc)); + else + NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, + NV_PCRTC_INTR_0_VBLANK); + + return 0; +} + +void +nouveau_vblank_disable(struct drm_device *dev, int crtc) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->card_type >= NV_50) + nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, + NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0); + else + NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0); +} + +static int +nouveau_page_flip_reserve(struct nouveau_bo *old_bo, + struct nouveau_bo *new_bo) +{ + int ret; + + ret = nouveau_bo_pin(new_bo, TTM_PL_FLAG_VRAM); + if (ret) + return ret; + + ret = ttm_bo_reserve(&new_bo->bo, false, false, false, 0); + if (ret) + goto fail; + + ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0); + if (ret) + goto fail_unreserve; + + return 0; + +fail_unreserve: + ttm_bo_unreserve(&new_bo->bo); +fail: + nouveau_bo_unpin(new_bo); + return ret; +} + +static void +nouveau_page_flip_unreserve(struct nouveau_bo *old_bo, + struct nouveau_bo *new_bo, + struct nouveau_fence *fence) +{ + nouveau_bo_fence(new_bo, fence); + ttm_bo_unreserve(&new_bo->bo); + + nouveau_bo_fence(old_bo, fence); + ttm_bo_unreserve(&old_bo->bo); + + nouveau_bo_unpin(old_bo); +} + +static int +nouveau_page_flip_emit(struct nouveau_channel *chan, + struct nouveau_bo *old_bo, + struct nouveau_bo *new_bo, + struct nouveau_page_flip_state *s, + struct nouveau_fence **pfence) +{ + struct drm_device *dev = chan->dev; + unsigned long flags; + int ret; + + /* Queue it to the pending list */ + spin_lock_irqsave(&dev->event_lock, flags); + list_add_tail(&s->head, &chan->nvsw.flip); + spin_unlock_irqrestore(&dev->event_lock, flags); + + /* Synchronize with the old framebuffer */ + ret = nouveau_fence_sync(old_bo->bo.sync_obj, chan); + if (ret) + goto fail; + + /* Emit the pageflip */ + ret = RING_SPACE(chan, 2); + if (ret) + goto fail; + + BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); + OUT_RING(chan, 0); + FIRE_RING(chan); + + ret = nouveau_fence_new(chan, pfence, true); + if (ret) + goto fail; + + return 0; +fail: + spin_lock_irqsave(&dev->event_lock, flags); + list_del(&s->head); + spin_unlock_irqrestore(&dev->event_lock, flags); + return ret; +} + +int +nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event) +{ + struct drm_device *dev = crtc->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; + struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; + struct nouveau_page_flip_state *s; + struct nouveau_channel *chan; + struct nouveau_fence *fence; + int ret; + + if (dev_priv->engine.graph.accel_blocked) + return -ENODEV; + + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (!s) + return -ENOMEM; + + /* Don't let the buffers go away while we flip */ + ret = nouveau_page_flip_reserve(old_bo, new_bo); + if (ret) + goto fail_free; + + /* Initialize a page flip struct */ + *s = (struct nouveau_page_flip_state) + { { }, s->event, nouveau_crtc(crtc)->index, + fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y, + new_bo->bo.offset }; + + /* Choose the channel the flip will be handled in */ + chan = nouveau_fence_channel(new_bo->bo.sync_obj); + if (!chan) + chan = nouveau_channel_get_unlocked(dev_priv->channel); + mutex_lock(&chan->mutex); + + /* Emit a page flip */ + ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); + nouveau_channel_put(&chan); + if (ret) + goto fail_unreserve; + + /* Update the crtc struct and cleanup */ + crtc->fb = fb; + + nouveau_page_flip_unreserve(old_bo, new_bo, fence); + nouveau_fence_unref(&fence); + return 0; + +fail_unreserve: + nouveau_page_flip_unreserve(old_bo, new_bo, NULL); +fail_free: + kfree(s); + return ret; +} + +int +nouveau_finish_page_flip(struct nouveau_channel *chan, + struct nouveau_page_flip_state *ps) +{ + struct drm_device *dev = chan->dev; + struct nouveau_page_flip_state *s; + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + + if (list_empty(&chan->nvsw.flip)) { + NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id); + spin_unlock_irqrestore(&dev->event_lock, flags); + return -EINVAL; + } + + s = list_first_entry(&chan->nvsw.flip, + struct nouveau_page_flip_state, head); + if (s->event) { + struct drm_pending_vblank_event *e = s->event; + struct timeval now; + + do_gettimeofday(&now); + e->event.sequence = 0; + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; + list_add_tail(&e->base.link, &e->base.file_priv->event_list); + wake_up_interruptible(&e->base.file_priv->event_wait); + } + + list_del(&s->head); + *ps = *s; + kfree(s); + + spin_unlock_irqrestore(&dev->event_lock, flags); + return 0; +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_dma.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -59,17 +59,11 @@ { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *obj = NULL; int ret, i; /* Create NV_MEMORY_TO_MEMORY_FORMAT for buffer moves */ - ret = nouveau_gpuobj_gr_new(chan, dev_priv->card_type < NV_50 ? - 0x0039 : 0x5039, &obj); - if (ret) - return ret; - - ret = nouveau_ramht_insert(chan, NvM2MF, obj); - nouveau_gpuobj_ref(NULL, &obj); + ret = nouveau_gpuobj_gr_new(chan, NvM2MF, dev_priv->card_type < NV_50 ? + 0x0039 : 0x5039); if (ret) return ret; --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_dp.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -279,7 +279,7 @@ struct bit_displayport_encoder_table *dpe; int dpe_headerlen; uint8_t config[4], status[3]; - bool cr_done, cr_max_vs, eq_done; + bool cr_done, cr_max_vs, eq_done, hpd_state; int ret = 0, i, tries, voltage; NV_DEBUG_KMS(dev, "link training!!\n"); @@ -297,7 +297,7 @@ /* disable hotplug detect, this flips around on some panels during * link training. */ - pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); + hpd_state = pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); if (dpe->script0) { NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); @@ -439,7 +439,7 @@ } /* re-enable hotplug detect */ - pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); + pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, hpd_state); return eq_done; } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_drv.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -115,6 +115,10 @@ int nouveau_perflvl_wr; module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); +MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n"); +int nouveau_msi; +module_param_named(msi, nouveau_msi, int, 0400); + int nouveau_fbpercrtc; #if 0 module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); @@ -193,23 +197,10 @@ NV_INFO(dev, "Idling channels...\n"); for (i = 0; i < pfifo->channels; i++) { - struct nouveau_fence *fence = NULL; - - chan = dev_priv->fifos[i]; - if (!chan || (dev_priv->card_type >= NV_50 && - chan == dev_priv->fifos[0])) - continue; - - ret = nouveau_fence_new(chan, &fence, true); - if (ret == 0) { - ret = nouveau_fence_wait(fence, NULL, false, false); - nouveau_fence_unref((void *)&fence); - } + chan = dev_priv->channels.ptr[i]; - if (ret) { - NV_ERROR(dev, "Failed to idle channel %d for suspend\n", - chan->id); - } + if (chan && chan->pushbuf_bo) + nouveau_channel_idle(chan); } pgraph->fifo_access(dev, false); @@ -219,17 +210,17 @@ pfifo->unload_context(dev); pgraph->unload_context(dev); - NV_INFO(dev, "Suspending GPU objects...\n"); - ret = nouveau_gpuobj_suspend(dev); + ret = pinstmem->suspend(dev); if (ret) { NV_ERROR(dev, "... failed: %d\n", ret); goto out_abort; } - ret = pinstmem->suspend(dev); + NV_INFO(dev, "Suspending GPU objects...\n"); + ret = nouveau_gpuobj_suspend(dev); if (ret) { NV_ERROR(dev, "... failed: %d\n", ret); - nouveau_gpuobj_suspend_cleanup(dev); + pinstmem->resume(dev); goto out_abort; } @@ -294,17 +285,18 @@ } } + NV_INFO(dev, "Restoring GPU objects...\n"); + nouveau_gpuobj_resume(dev); + NV_INFO(dev, "Reinitialising engines...\n"); engine->instmem.resume(dev); engine->mc.init(dev); engine->timer.init(dev); engine->fb.init(dev); engine->graph.init(dev); + engine->crypt.init(dev); engine->fifo.init(dev); - NV_INFO(dev, "Restoring GPU objects...\n"); - nouveau_gpuobj_resume(dev); - nouveau_irq_postinstall(dev); /* Re-write SKIPS, they'll have been lost over the suspend */ @@ -313,7 +305,7 @@ int j; for (i = 0; i < dev_priv->engine.fifo.channels; i++) { - chan = dev_priv->fifos[i]; + chan = dev_priv->channels.ptr[i]; if (!chan || !chan->pushbuf_bo) continue; @@ -347,13 +339,11 @@ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + u32 offset = nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT; - nv_crtc->cursor.set_offset(nv_crtc, - nv_crtc->cursor.nvbo->bo.offset - - dev_priv->vm_vram_base); - + nv_crtc->cursor.set_offset(nv_crtc, offset); nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, - nv_crtc->cursor_saved_y); + nv_crtc->cursor_saved_y); } /* Force CLUT to get re-loaded during modeset */ @@ -393,6 +383,9 @@ .irq_postinstall = nouveau_irq_postinstall, .irq_uninstall = nouveau_irq_uninstall, .irq_handler = nouveau_irq_handler, + .get_vblank_counter = drm_vblank_count, + .enable_vblank = nouveau_vblank_enable, + .disable_vblank = nouveau_vblank_disable, .reclaim_buffers = drm_core_reclaim_buffers, .ioctls = nouveau_ioctls, .fops = { @@ -403,6 +396,7 @@ .mmap = nouveau_ttm_mmap, .poll = drm_poll, .fasync = drm_fasync, + .read = drm_read, #if defined(CONFIG_COMPAT) .compat_ioctl = nouveau_compat_ioctl, #endif --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_drv.h +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -54,22 +54,36 @@ #include "nouveau_drm.h" #include "nouveau_reg.h" #include "nouveau_bios.h" +#include "nouveau_util.h" + struct nouveau_grctx; +struct nouveau_vram; +#include "nouveau_vm.h" #define MAX_NUM_DCB_ENTRIES 16 #define NOUVEAU_MAX_CHANNEL_NR 128 #define NOUVEAU_MAX_TILE_NR 15 -#define NV50_VM_MAX_VRAM (2*1024*1024*1024ULL) -#define NV50_VM_BLOCK (512*1024*1024ULL) -#define NV50_VM_VRAM_NR (NV50_VM_MAX_VRAM / NV50_VM_BLOCK) +struct nouveau_vram { + struct drm_device *dev; + + struct nouveau_vma bar_vma; + + struct list_head regions; + u32 memtype; + u64 offset; + u64 size; +}; struct nouveau_tile_reg { - struct nouveau_fence *fence; - uint32_t addr; - uint32_t size; bool used; + uint32_t addr; + uint32_t limit; + uint32_t pitch; + uint32_t zcomp; + struct drm_mm_node *tag_mem; + struct nouveau_fence *fence; }; struct nouveau_bo { @@ -88,6 +102,7 @@ struct nouveau_channel *channel; + struct nouveau_vma vma; bool mappable; bool no_vm; @@ -96,7 +111,6 @@ struct nouveau_tile_reg *tile; struct drm_gem_object *gem; - struct drm_file *cpu_filp; int pin_refcnt; }; @@ -133,20 +147,28 @@ #define NVOBJ_ENGINE_SW 0 #define NVOBJ_ENGINE_GR 1 -#define NVOBJ_ENGINE_DISPLAY 2 +#define NVOBJ_ENGINE_PPP 2 +#define NVOBJ_ENGINE_COPY 3 +#define NVOBJ_ENGINE_VP 4 +#define NVOBJ_ENGINE_CRYPT 5 +#define NVOBJ_ENGINE_BSP 6 +#define NVOBJ_ENGINE_DISPLAY 0xcafe0001 #define NVOBJ_ENGINE_INT 0xdeadbeef +#define NVOBJ_FLAG_DONT_MAP (1 << 0) #define NVOBJ_FLAG_ZERO_ALLOC (1 << 1) #define NVOBJ_FLAG_ZERO_FREE (1 << 2) +#define NVOBJ_FLAG_VM (1 << 3) + +#define NVOBJ_CINST_GLOBAL 0xdeadbeef + struct nouveau_gpuobj { struct drm_device *dev; struct kref refcount; struct list_head list; - struct drm_mm_node *im_pramin; - struct nouveau_bo *im_backing; - uint32_t *im_backing_suspend; - int im_bound; + void *node; + u32 *suspend; uint32_t flags; @@ -162,10 +184,29 @@ void *priv; }; +struct nouveau_page_flip_state { + struct list_head head; + struct drm_pending_vblank_event *event; + int crtc, bpp, pitch, x, y; + uint64_t offset; +}; + +enum nouveau_channel_mutex_class { + NOUVEAU_UCHANNEL_MUTEX, + NOUVEAU_KCHANNEL_MUTEX +}; + struct nouveau_channel { struct drm_device *dev; int id; + /* references to the channel data structure */ + struct kref ref; + /* users of the hardware channel resources, the hardware + * context will be kicked off when it reaches zero. */ + atomic_t users; + struct mutex mutex; + /* owner of this fifo */ struct drm_file *file_priv; /* mapping of the fifo itself */ @@ -202,12 +243,12 @@ /* PGRAPH context */ /* XXX may be merge 2 pointers as private data ??? */ struct nouveau_gpuobj *ramin_grctx; + struct nouveau_gpuobj *crypt_ctx; void *pgraph_ctx; /* NV50 VM */ + struct nouveau_vm *vm; struct nouveau_gpuobj *vm_pd; - struct nouveau_gpuobj *vm_gart_pt; - struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; /* Objects */ struct nouveau_gpuobj *ramin; /* Private instmem */ @@ -238,9 +279,11 @@ struct { struct nouveau_gpuobj *vblsem; + uint32_t vblsem_head; uint32_t vblsem_offset; uint32_t vblsem_rval; struct list_head vbl_wait; + struct list_head flip; } nvsw; struct { @@ -258,11 +301,11 @@ int (*suspend)(struct drm_device *dev); void (*resume)(struct drm_device *dev); - int (*populate)(struct drm_device *, struct nouveau_gpuobj *, - uint32_t *size); - void (*clear)(struct drm_device *, struct nouveau_gpuobj *); - int (*bind)(struct drm_device *, struct nouveau_gpuobj *); - int (*unbind)(struct drm_device *, struct nouveau_gpuobj *); + int (*get)(struct nouveau_gpuobj *, u32 size, u32 align); + void (*put)(struct nouveau_gpuobj *); + int (*map)(struct nouveau_gpuobj *); + void (*unmap)(struct nouveau_gpuobj *); + void (*flush)(struct drm_device *); }; @@ -279,12 +322,17 @@ struct nouveau_fb_engine { int num_tiles; + struct drm_mm tag_heap; + void *priv; int (*init)(struct drm_device *dev); void (*takedown)(struct drm_device *dev); - void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch); + void (*init_tile_region)(struct drm_device *dev, int i, + uint32_t addr, uint32_t size, + uint32_t pitch, uint32_t flags); + void (*set_tile_region)(struct drm_device *dev, int i); + void (*free_tile_region)(struct drm_device *dev, int i); }; struct nouveau_fifo_engine { @@ -310,21 +358,9 @@ void (*tlb_flush)(struct drm_device *dev); }; -struct nouveau_pgraph_object_method { - int id; - int (*exec)(struct nouveau_channel *chan, int grclass, int mthd, - uint32_t data); -}; - -struct nouveau_pgraph_object_class { - int id; - bool software; - struct nouveau_pgraph_object_method *methods; -}; - struct nouveau_pgraph_engine { - struct nouveau_pgraph_object_class *grclass; bool accel_blocked; + bool registered; int grctx_size; /* NV2x/NV3x context table (0x400780) */ @@ -342,8 +378,7 @@ int (*unload_context)(struct drm_device *); void (*tlb_flush)(struct drm_device *dev); - void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch); + void (*set_tile_region)(struct drm_device *dev, int i); }; struct nouveau_display_engine { @@ -355,13 +390,19 @@ }; struct nouveau_gpio_engine { + void *priv; + int (*init)(struct drm_device *); void (*takedown)(struct drm_device *); int (*get)(struct drm_device *, enum dcb_gpio_tag); int (*set)(struct drm_device *, enum dcb_gpio_tag, int state); - void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); + int (*irq_register)(struct drm_device *, enum dcb_gpio_tag, + void (*)(void *, int), void *); + void (*irq_unregister)(struct drm_device *, enum dcb_gpio_tag, + void (*)(void *, int), void *); + bool (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); }; struct nouveau_pm_voltage_level { @@ -437,6 +478,7 @@ struct nouveau_pm_level *cur; struct device *hwmon; + struct notifier_block acpi_nb; int (*clock_get)(struct drm_device *, u32 id); void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, @@ -449,6 +491,25 @@ int (*temp_get)(struct drm_device *); }; +struct nouveau_crypt_engine { + bool registered; + + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *); + int (*create_context)(struct nouveau_channel *); + void (*destroy_context)(struct nouveau_channel *); + void (*tlb_flush)(struct drm_device *dev); +}; + +struct nouveau_vram_engine { + int (*init)(struct drm_device *); + int (*get)(struct drm_device *, u64, u32 align, u32 size_nc, + u32 type, struct nouveau_vram **); + void (*put)(struct drm_device *, struct nouveau_vram **); + + bool (*flags_valid)(struct drm_device *, u32 tile_flags); +}; + struct nouveau_engine { struct nouveau_instmem_engine instmem; struct nouveau_mc_engine mc; @@ -459,6 +520,8 @@ struct nouveau_display_engine display; struct nouveau_gpio_engine gpio; struct nouveau_pm_engine pm; + struct nouveau_crypt_engine crypt; + struct nouveau_vram_engine vram; }; struct nouveau_pll_vals { @@ -577,18 +640,15 @@ bool ramin_available; struct drm_mm ramin_heap; struct list_head gpuobj_list; + struct list_head classes; struct nouveau_bo *vga_ram; + /* interrupt handling */ + void (*irq_handler[32])(struct drm_device *); + bool msi_enabled; struct workqueue_struct *wq; struct work_struct irq_work; - struct work_struct hpd_work; - - struct { - spinlock_t lock; - uint32_t hpd0_bits; - uint32_t hpd1_bits; - } hpd_state; struct list_head vbl_waiting; @@ -605,8 +665,10 @@ struct nouveau_bo *bo; } fence; - int fifo_alloc_count; - struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR]; + struct { + spinlock_t lock; + struct nouveau_channel *ptr[NOUVEAU_MAX_CHANNEL_NR]; + } channels; struct nouveau_engine engine; struct nouveau_channel *channel; @@ -632,12 +694,14 @@ uint64_t aper_free; struct nouveau_gpuobj *sg_ctxdma; - struct page *sg_dummy_page; - dma_addr_t sg_dummy_bus; + struct nouveau_vma vma; } gart_info; /* nv10-nv40 tiling regions */ - struct nouveau_tile_reg tile[NOUVEAU_MAX_TILE_NR]; + struct { + struct nouveau_tile_reg reg[NOUVEAU_MAX_TILE_NR]; + spinlock_t lock; + } tile; /* VRAM/fb configuration */ uint64_t vram_size; @@ -650,14 +714,12 @@ uint64_t fb_aper_free; int fb_mtrr; + /* BAR control (NV50-) */ + struct nouveau_vm *bar1_vm; + struct nouveau_vm *bar3_vm; + /* G8x/G9x virtual address space */ - uint64_t vm_gart_base; - uint64_t vm_gart_size; - uint64_t vm_vram_base; - uint64_t vm_vram_size; - uint64_t vm_end; - struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR]; - int vm_vram_pt_nr; + struct nouveau_vm *chan_vm; struct nvbios vbios; @@ -674,6 +736,7 @@ struct backlight_device *backlight; struct nouveau_channel *evo; + u32 evo_alloc; struct { struct dcb_entry *dcb; u16 script; @@ -719,16 +782,6 @@ return 0; } -#define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do { \ - struct drm_nouveau_private *nv = dev->dev_private; \ - if (!nouveau_channel_owner(dev, (cl), (id))) { \ - NV_ERROR(dev, "pid %d doesn't own channel %d\n", \ - DRM_CURRENTPID, (id)); \ - return -EPERM; \ - } \ - (ch) = nv->fifos[(id)]; \ -} while (0) - /* nouveau_drv.c */ extern int nouveau_agpmode; extern int nouveau_duallink; @@ -748,6 +801,7 @@ extern int nouveau_override_conntype; extern char *nouveau_perflvl; extern int nouveau_perflvl_wr; +extern int nouveau_msi; extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); extern int nouveau_pci_resume(struct pci_dev *pdev); @@ -762,8 +816,10 @@ struct drm_file *); extern int nouveau_ioctl_setparam(struct drm_device *, void *data, struct drm_file *); -extern bool nouveau_wait_until(struct drm_device *, uint64_t timeout, - uint32_t reg, uint32_t mask, uint32_t val); +extern bool nouveau_wait_eq(struct drm_device *, uint64_t timeout, + uint32_t reg, uint32_t mask, uint32_t val); +extern bool nouveau_wait_ne(struct drm_device *, uint64_t timeout, + uint32_t reg, uint32_t mask, uint32_t val); extern bool nouveau_wait_for_idle(struct drm_device *); extern int nouveau_card_init(struct drm_device *); @@ -775,18 +831,15 @@ extern int nouveau_mem_init_agp(struct drm_device *); extern int nouveau_mem_reset_agp(struct drm_device *); extern void nouveau_mem_close(struct drm_device *); -extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev, - uint32_t addr, - uint32_t size, - uint32_t pitch); -extern void nv10_mem_expire_tiling(struct drm_device *dev, - struct nouveau_tile_reg *tile, - struct nouveau_fence *fence); -extern int nv50_mem_vm_bind_linear(struct drm_device *, uint64_t virt, - uint32_t size, uint32_t flags, - uint64_t phys); -extern void nv50_mem_vm_unbind(struct drm_device *, uint64_t virt, - uint32_t size); +extern int nouveau_mem_detect(struct drm_device *); +extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags); +extern struct nouveau_tile_reg *nv10_mem_set_tiling( + struct drm_device *dev, uint32_t addr, uint32_t size, + uint32_t pitch, uint32_t flags); +extern void nv10_mem_put_tile_region(struct drm_device *dev, + struct nouveau_tile_reg *tile, + struct nouveau_fence *fence); +extern const struct ttm_mem_type_manager_func nouveau_vram_manager; /* nouveau_notifier.c */ extern int nouveau_notifier_init_channel(struct nouveau_channel *); @@ -803,21 +856,44 @@ extern struct drm_ioctl_desc nouveau_ioctls[]; extern int nouveau_max_ioctl; extern void nouveau_channel_cleanup(struct drm_device *, struct drm_file *); -extern int nouveau_channel_owner(struct drm_device *, struct drm_file *, - int channel); extern int nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan, struct drm_file *file_priv, uint32_t fb_ctxdma, uint32_t tt_ctxdma); -extern void nouveau_channel_free(struct nouveau_channel *); +extern struct nouveau_channel * +nouveau_channel_get_unlocked(struct nouveau_channel *); +extern struct nouveau_channel * +nouveau_channel_get(struct drm_device *, struct drm_file *, int id); +extern void nouveau_channel_put_unlocked(struct nouveau_channel **); +extern void nouveau_channel_put(struct nouveau_channel **); +extern void nouveau_channel_ref(struct nouveau_channel *chan, + struct nouveau_channel **pchan); +extern void nouveau_channel_idle(struct nouveau_channel *chan); /* nouveau_object.c */ +#define NVOBJ_CLASS(d,c,e) do { \ + int ret = nouveau_gpuobj_class_new((d), (c), NVOBJ_ENGINE_##e); \ + if (ret) \ + return ret; \ +} while(0) + +#define NVOBJ_MTHD(d,c,m,e) do { \ + int ret = nouveau_gpuobj_mthd_new((d), (c), (m), (e)); \ + if (ret) \ + return ret; \ +} while(0) + extern int nouveau_gpuobj_early_init(struct drm_device *); extern int nouveau_gpuobj_init(struct drm_device *); extern void nouveau_gpuobj_takedown(struct drm_device *); extern int nouveau_gpuobj_suspend(struct drm_device *dev); -extern void nouveau_gpuobj_suspend_cleanup(struct drm_device *dev); extern void nouveau_gpuobj_resume(struct drm_device *dev); +extern int nouveau_gpuobj_class_new(struct drm_device *, u32 class, u32 eng); +extern int nouveau_gpuobj_mthd_new(struct drm_device *, u32 class, u32 mthd, + int (*exec)(struct nouveau_channel *, + u32 class, u32 mthd, u32 data)); +extern int nouveau_gpuobj_mthd_call(struct nouveau_channel *, u32, u32, u32); +extern int nouveau_gpuobj_mthd_call2(struct drm_device *, int, u32, u32, u32); extern int nouveau_gpuobj_channel_init(struct nouveau_channel *, uint32_t vram_h, uint32_t tt_h); extern void nouveau_gpuobj_channel_takedown(struct nouveau_channel *); @@ -832,21 +908,25 @@ extern int nouveau_gpuobj_dma_new(struct nouveau_channel *, int class, uint64_t offset, uint64_t size, int access, int target, struct nouveau_gpuobj **); -extern int nouveau_gpuobj_gart_dma_new(struct nouveau_channel *, - uint64_t offset, uint64_t size, - int access, struct nouveau_gpuobj **, - uint32_t *o_ret); -extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, int class, - struct nouveau_gpuobj **); -extern int nouveau_gpuobj_sw_new(struct nouveau_channel *, int class, - struct nouveau_gpuobj **); +extern int nouveau_gpuobj_gr_new(struct nouveau_channel *, u32 handle, int class); +extern int nv50_gpuobj_dma_new(struct nouveau_channel *, int class, u64 base, + u64 size, int target, int access, u32 type, + u32 comp, struct nouveau_gpuobj **pobj); +extern void nv50_gpuobj_dma_init(struct nouveau_gpuobj *, u32 offset, + int class, u64 base, u64 size, int target, + int access, u32 type, u32 comp); extern int nouveau_ioctl_grobj_alloc(struct drm_device *, void *data, struct drm_file *); extern int nouveau_ioctl_gpuobj_free(struct drm_device *, void *data, struct drm_file *); /* nouveau_irq.c */ +extern int nouveau_irq_init(struct drm_device *); +extern void nouveau_irq_fini(struct drm_device *); extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); +extern void nouveau_irq_register(struct drm_device *, int status_bit, + void (*)(struct drm_device *)); +extern void nouveau_irq_unregister(struct drm_device *, int status_bit); extern void nouveau_irq_preinstall(struct drm_device *); extern int nouveau_irq_postinstall(struct drm_device *); extern void nouveau_irq_uninstall(struct drm_device *); @@ -854,8 +934,8 @@ /* nouveau_sgdma.c */ extern int nouveau_sgdma_init(struct drm_device *); extern void nouveau_sgdma_takedown(struct drm_device *); -extern int nouveau_sgdma_get_page(struct drm_device *, uint32_t offset, - uint32_t *page); +extern uint32_t nouveau_sgdma_get_physical(struct drm_device *, + uint32_t offset); extern struct ttm_backend *nouveau_sgdma_init_ttm(struct drm_device *); /* nouveau_debugfs.c */ @@ -966,18 +1046,25 @@ /* nv10_fb.c */ extern int nv10_fb_init(struct drm_device *); extern void nv10_fb_takedown(struct drm_device *); -extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t, - uint32_t, uint32_t); +extern void nv10_fb_init_tile_region(struct drm_device *dev, int i, + uint32_t addr, uint32_t size, + uint32_t pitch, uint32_t flags); +extern void nv10_fb_set_tile_region(struct drm_device *dev, int i); +extern void nv10_fb_free_tile_region(struct drm_device *dev, int i); /* nv30_fb.c */ extern int nv30_fb_init(struct drm_device *); extern void nv30_fb_takedown(struct drm_device *); +extern void nv30_fb_init_tile_region(struct drm_device *dev, int i, + uint32_t addr, uint32_t size, + uint32_t pitch, uint32_t flags); +extern void nv30_fb_free_tile_region(struct drm_device *dev, int i); /* nv40_fb.c */ extern int nv40_fb_init(struct drm_device *); extern void nv40_fb_takedown(struct drm_device *); -extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, - uint32_t, uint32_t); +extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); + /* nv50_fb.c */ extern int nv50_fb_init(struct drm_device *); extern void nv50_fb_takedown(struct drm_device *); @@ -989,6 +1076,7 @@ /* nv04_fifo.c */ extern int nv04_fifo_init(struct drm_device *); +extern void nv04_fifo_fini(struct drm_device *); extern void nv04_fifo_disable(struct drm_device *); extern void nv04_fifo_enable(struct drm_device *); extern bool nv04_fifo_reassign(struct drm_device *, bool); @@ -998,19 +1086,18 @@ extern void nv04_fifo_destroy_context(struct nouveau_channel *); extern int nv04_fifo_load_context(struct nouveau_channel *); extern int nv04_fifo_unload_context(struct drm_device *); +extern void nv04_fifo_isr(struct drm_device *); /* nv10_fifo.c */ extern int nv10_fifo_init(struct drm_device *); extern int nv10_fifo_channel_id(struct drm_device *); extern int nv10_fifo_create_context(struct nouveau_channel *); -extern void nv10_fifo_destroy_context(struct nouveau_channel *); extern int nv10_fifo_load_context(struct nouveau_channel *); extern int nv10_fifo_unload_context(struct drm_device *); /* nv40_fifo.c */ extern int nv40_fifo_init(struct drm_device *); extern int nv40_fifo_create_context(struct nouveau_channel *); -extern void nv40_fifo_destroy_context(struct nouveau_channel *); extern int nv40_fifo_load_context(struct nouveau_channel *); extern int nv40_fifo_unload_context(struct drm_device *); @@ -1038,7 +1125,6 @@ extern int nvc0_fifo_unload_context(struct drm_device *); /* nv04_graph.c */ -extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; extern int nv04_graph_init(struct drm_device *); extern void nv04_graph_takedown(struct drm_device *); extern void nv04_graph_fifo_access(struct drm_device *, bool); @@ -1047,10 +1133,11 @@ extern void nv04_graph_destroy_context(struct nouveau_channel *); extern int nv04_graph_load_context(struct nouveau_channel *); extern int nv04_graph_unload_context(struct drm_device *); -extern void nv04_graph_context_switch(struct drm_device *); +extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data); +extern struct nouveau_bitfield nv04_graph_nsource[]; /* nv10_graph.c */ -extern struct nouveau_pgraph_object_class nv10_graph_grclass[]; extern int nv10_graph_init(struct drm_device *); extern void nv10_graph_takedown(struct drm_device *); extern struct nouveau_channel *nv10_graph_channel(struct drm_device *); @@ -1058,13 +1145,11 @@ extern void nv10_graph_destroy_context(struct nouveau_channel *); extern int nv10_graph_load_context(struct nouveau_channel *); extern int nv10_graph_unload_context(struct drm_device *); -extern void nv10_graph_context_switch(struct drm_device *); -extern void nv10_graph_set_region_tiling(struct drm_device *, int, uint32_t, - uint32_t, uint32_t); +extern void nv10_graph_set_tile_region(struct drm_device *dev, int i); +extern struct nouveau_bitfield nv10_graph_intr[]; +extern struct nouveau_bitfield nv10_graph_nstatus[]; /* nv20_graph.c */ -extern struct nouveau_pgraph_object_class nv20_graph_grclass[]; -extern struct nouveau_pgraph_object_class nv30_graph_grclass[]; extern int nv20_graph_create_context(struct nouveau_channel *); extern void nv20_graph_destroy_context(struct nouveau_channel *); extern int nv20_graph_load_context(struct nouveau_channel *); @@ -1072,11 +1157,9 @@ extern int nv20_graph_init(struct drm_device *); extern void nv20_graph_takedown(struct drm_device *); extern int nv30_graph_init(struct drm_device *); -extern void nv20_graph_set_region_tiling(struct drm_device *, int, uint32_t, - uint32_t, uint32_t); +extern void nv20_graph_set_tile_region(struct drm_device *dev, int i); /* nv40_graph.c */ -extern struct nouveau_pgraph_object_class nv40_graph_grclass[]; extern int nv40_graph_init(struct drm_device *); extern void nv40_graph_takedown(struct drm_device *); extern struct nouveau_channel *nv40_graph_channel(struct drm_device *); @@ -1085,11 +1168,9 @@ extern int nv40_graph_load_context(struct nouveau_channel *); extern int nv40_graph_unload_context(struct drm_device *); extern void nv40_grctx_init(struct nouveau_grctx *); -extern void nv40_graph_set_region_tiling(struct drm_device *, int, uint32_t, - uint32_t, uint32_t); +extern void nv40_graph_set_tile_region(struct drm_device *dev, int i); /* nv50_graph.c */ -extern struct nouveau_pgraph_object_class nv50_graph_grclass[]; extern int nv50_graph_init(struct drm_device *); extern void nv50_graph_takedown(struct drm_device *); extern void nv50_graph_fifo_access(struct drm_device *, bool); @@ -1098,7 +1179,6 @@ extern void nv50_graph_destroy_context(struct nouveau_channel *); extern int nv50_graph_load_context(struct nouveau_channel *); extern int nv50_graph_unload_context(struct drm_device *); -extern void nv50_graph_context_switch(struct drm_device *); extern int nv50_grctx_init(struct nouveau_grctx *); extern void nv50_graph_tlb_flush(struct drm_device *dev); extern void nv86_graph_tlb_flush(struct drm_device *dev); @@ -1113,16 +1193,22 @@ extern int nvc0_graph_load_context(struct nouveau_channel *); extern int nvc0_graph_unload_context(struct drm_device *); +/* nv84_crypt.c */ +extern int nv84_crypt_init(struct drm_device *dev); +extern void nv84_crypt_fini(struct drm_device *dev); +extern int nv84_crypt_create_context(struct nouveau_channel *); +extern void nv84_crypt_destroy_context(struct nouveau_channel *); +extern void nv84_crypt_tlb_flush(struct drm_device *dev); + /* nv04_instmem.c */ extern int nv04_instmem_init(struct drm_device *); extern void nv04_instmem_takedown(struct drm_device *); extern int nv04_instmem_suspend(struct drm_device *); extern void nv04_instmem_resume(struct drm_device *); -extern int nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, - uint32_t *size); -extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); -extern int nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); -extern int nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); +extern int nv04_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align); +extern void nv04_instmem_put(struct nouveau_gpuobj *); +extern int nv04_instmem_map(struct nouveau_gpuobj *); +extern void nv04_instmem_unmap(struct nouveau_gpuobj *); extern void nv04_instmem_flush(struct drm_device *); /* nv50_instmem.c */ @@ -1130,25 +1216,22 @@ extern void nv50_instmem_takedown(struct drm_device *); extern int nv50_instmem_suspend(struct drm_device *); extern void nv50_instmem_resume(struct drm_device *); -extern int nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, - uint32_t *size); -extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); -extern int nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); -extern int nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); +extern int nv50_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align); +extern void nv50_instmem_put(struct nouveau_gpuobj *); +extern int nv50_instmem_map(struct nouveau_gpuobj *); +extern void nv50_instmem_unmap(struct nouveau_gpuobj *); extern void nv50_instmem_flush(struct drm_device *); extern void nv84_instmem_flush(struct drm_device *); -extern void nv50_vm_flush(struct drm_device *, int engine); /* nvc0_instmem.c */ extern int nvc0_instmem_init(struct drm_device *); extern void nvc0_instmem_takedown(struct drm_device *); extern int nvc0_instmem_suspend(struct drm_device *); extern void nvc0_instmem_resume(struct drm_device *); -extern int nvc0_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, - uint32_t *size); -extern void nvc0_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); -extern int nvc0_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); -extern int nvc0_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); +extern int nvc0_instmem_get(struct nouveau_gpuobj *, u32 size, u32 align); +extern void nvc0_instmem_put(struct nouveau_gpuobj *); +extern int nvc0_instmem_map(struct nouveau_gpuobj *); +extern void nvc0_instmem_unmap(struct nouveau_gpuobj *); extern void nvc0_instmem_flush(struct drm_device *); /* nv04_mc.c */ @@ -1219,6 +1302,9 @@ extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); +extern void nouveau_bo_fence(struct nouveau_bo *, struct nouveau_fence *); +extern int nouveau_bo_validate(struct nouveau_bo *, bool interruptible, + bool no_wait_reserve, bool no_wait_gpu); /* nouveau_fence.c */ struct nouveau_fence; @@ -1234,12 +1320,35 @@ void (*work)(void *priv, bool signalled), void *priv); struct nouveau_channel *nouveau_fence_channel(struct nouveau_fence *); -extern bool nouveau_fence_signalled(void *obj, void *arg); -extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); + +extern bool __nouveau_fence_signalled(void *obj, void *arg); +extern int __nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr); +extern int __nouveau_fence_flush(void *obj, void *arg); +extern void __nouveau_fence_unref(void **obj); +extern void *__nouveau_fence_ref(void *obj); + +static inline bool nouveau_fence_signalled(struct nouveau_fence *obj) +{ + return __nouveau_fence_signalled(obj, NULL); +} +static inline int +nouveau_fence_wait(struct nouveau_fence *obj, bool lazy, bool intr) +{ + return __nouveau_fence_wait(obj, NULL, lazy, intr); +} extern int nouveau_fence_sync(struct nouveau_fence *, struct nouveau_channel *); -extern int nouveau_fence_flush(void *obj, void *arg); -extern void nouveau_fence_unref(void **obj); -extern void *nouveau_fence_ref(void *obj); +static inline int nouveau_fence_flush(struct nouveau_fence *obj) +{ + return __nouveau_fence_flush(obj, NULL); +} +static inline void nouveau_fence_unref(struct nouveau_fence **obj) +{ + __nouveau_fence_unref((void **)obj); +} +static inline struct nouveau_fence *nouveau_fence_ref(struct nouveau_fence *obj) +{ + return __nouveau_fence_ref(obj); +} /* nouveau_gem.c */ extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *, @@ -1259,15 +1368,28 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *, struct drm_file *); +/* nouveau_display.c */ +int nouveau_vblank_enable(struct drm_device *dev, int crtc); +void nouveau_vblank_disable(struct drm_device *dev, int crtc); +int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event); +int nouveau_finish_page_flip(struct nouveau_channel *, + struct nouveau_page_flip_state *); + /* nv10_gpio.c */ int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); /* nv50_gpio.c */ int nv50_gpio_init(struct drm_device *dev); +void nv50_gpio_fini(struct drm_device *dev); int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); -void nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on); +int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag, + void (*)(void *, int), void *); +void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag, + void (*)(void *, int), void *); +bool nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on); /* nv50_calc. */ int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, @@ -1334,7 +1456,9 @@ } #define nv_wait(dev, reg, mask, val) \ - nouveau_wait_until(dev, 2000000000ULL, (reg), (mask), (val)) + nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val)) +#define nv_wait_ne(dev, reg, mask, val) \ + nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val)) /* PRAMIN access */ static inline u32 nv_ri32(struct drm_device *dev, unsigned offset) @@ -1447,6 +1571,23 @@ dev->pdev->subsystem_device == sub_device; } +/* memory type/access flags, do not match hardware values */ +#define NV_MEM_ACCESS_RO 1 +#define NV_MEM_ACCESS_WO 2 +#define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO) +#define NV_MEM_ACCESS_SYS 4 +#define NV_MEM_ACCESS_VM 8 + +#define NV_MEM_TARGET_VRAM 0 +#define NV_MEM_TARGET_PCI 1 +#define NV_MEM_TARGET_PCI_NOSNOOP 2 +#define NV_MEM_TARGET_VM 3 +#define NV_MEM_TARGET_GART 4 + +#define NV_MEM_TYPE_VM 0x7f +#define NV_MEM_COMP_VM 0x03 + +/* NV_SW object class */ #define NV_SW 0x0000506e #define NV_SW_DMA_SEMAPHORE 0x00000060 #define NV_SW_SEMAPHORE_OFFSET 0x00000064 @@ -1457,5 +1598,6 @@ #define NV_SW_VBLSEM_OFFSET 0x00000400 #define NV_SW_VBLSEM_RELEASE_VALUE 0x00000404 #define NV_SW_VBLSEM_RELEASE 0x00000408 +#define NV_SW_PAGE_FLIP 0x00000500 #endif /* __NOUVEAU_DRV_H__ */ --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -49,6 +49,96 @@ #include "nouveau_fbcon.h" #include "nouveau_dma.h" +static void +nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + struct nouveau_fbdev *nfbdev = info->par; + struct drm_device *dev = nfbdev->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + if (info->state != FBINFO_STATE_RUNNING) + return; + + ret = -ENODEV; + if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && + mutex_trylock(&dev_priv->channel->mutex)) { + if (dev_priv->card_type < NV_50) + ret = nv04_fbcon_fillrect(info, rect); + else + if (dev_priv->card_type < NV_C0) + ret = nv50_fbcon_fillrect(info, rect); + mutex_unlock(&dev_priv->channel->mutex); + } + + if (ret == 0) + return; + + if (ret != -ENODEV) + nouveau_fbcon_gpu_lockup(info); + cfb_fillrect(info, rect); +} + +static void +nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) +{ + struct nouveau_fbdev *nfbdev = info->par; + struct drm_device *dev = nfbdev->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + if (info->state != FBINFO_STATE_RUNNING) + return; + + ret = -ENODEV; + if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && + mutex_trylock(&dev_priv->channel->mutex)) { + if (dev_priv->card_type < NV_50) + ret = nv04_fbcon_copyarea(info, image); + else + if (dev_priv->card_type < NV_C0) + ret = nv50_fbcon_copyarea(info, image); + mutex_unlock(&dev_priv->channel->mutex); + } + + if (ret == 0) + return; + + if (ret != -ENODEV) + nouveau_fbcon_gpu_lockup(info); + cfb_copyarea(info, image); +} + +static void +nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) +{ + struct nouveau_fbdev *nfbdev = info->par; + struct drm_device *dev = nfbdev->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + if (info->state != FBINFO_STATE_RUNNING) + return; + + ret = -ENODEV; + if (!in_interrupt() && !(info->flags & FBINFO_HWACCEL_DISABLED) && + mutex_trylock(&dev_priv->channel->mutex)) { + if (dev_priv->card_type < NV_50) + ret = nv04_fbcon_imageblit(info, image); + else + if (dev_priv->card_type < NV_C0) + ret = nv50_fbcon_imageblit(info, image); + mutex_unlock(&dev_priv->channel->mutex); + } + + if (ret == 0) + return; + + if (ret != -ENODEV) + nouveau_fbcon_gpu_lockup(info); + cfb_imageblit(info, image); +} + static int nouveau_fbcon_sync(struct fb_info *info) { @@ -58,12 +148,17 @@ struct nouveau_channel *chan = dev_priv->channel; int ret, i; - if (!chan || !chan->accel_done || + if (!chan || !chan->accel_done || in_interrupt() || info->state != FBINFO_STATE_RUNNING || info->flags & FBINFO_HWACCEL_DISABLED) return 0; - if (RING_SPACE(chan, 4)) { + if (!mutex_trylock(&chan->mutex)) + return 0; + + ret = RING_SPACE(chan, 4); + if (ret) { + mutex_unlock(&chan->mutex); nouveau_fbcon_gpu_lockup(info); return 0; } @@ -74,6 +169,7 @@ OUT_RING(chan, 0); nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy + 3, 0xffffffff); FIRE_RING(chan); + mutex_unlock(&chan->mutex); ret = -EBUSY; for (i = 0; i < 100000; i++) { @@ -97,9 +193,9 @@ .owner = THIS_MODULE, .fb_check_var = drm_fb_helper_check_var, .fb_set_par = drm_fb_helper_set_par, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, + .fb_fillrect = nouveau_fbcon_fillrect, + .fb_copyarea = nouveau_fbcon_copyarea, + .fb_imageblit = nouveau_fbcon_imageblit, .fb_sync = nouveau_fbcon_sync, .fb_pan_display = drm_fb_helper_pan_display, .fb_blank = drm_fb_helper_blank, @@ -108,29 +204,13 @@ .fb_debug_leave = drm_fb_helper_debug_leave, }; -static struct fb_ops nv04_fbcon_ops = { +static struct fb_ops nouveau_fbcon_sw_ops = { .owner = THIS_MODULE, .fb_check_var = drm_fb_helper_check_var, .fb_set_par = drm_fb_helper_set_par, - .fb_fillrect = nv04_fbcon_fillrect, - .fb_copyarea = nv04_fbcon_copyarea, - .fb_imageblit = nv04_fbcon_imageblit, - .fb_sync = nouveau_fbcon_sync, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_blank = drm_fb_helper_blank, - .fb_setcmap = drm_fb_helper_setcmap, - .fb_debug_enter = drm_fb_helper_debug_enter, - .fb_debug_leave = drm_fb_helper_debug_leave, -}; - -static struct fb_ops nv50_fbcon_ops = { - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, - .fb_fillrect = nv50_fbcon_fillrect, - .fb_copyarea = nv50_fbcon_copyarea, - .fb_imageblit = nv50_fbcon_imageblit, - .fb_sync = nouveau_fbcon_sync, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, .fb_pan_display = drm_fb_helper_pan_display, .fb_blank = drm_fb_helper_blank, .fb_setcmap = drm_fb_helper_setcmap, @@ -257,9 +337,9 @@ FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; info->flags |= FBINFO_CAN_FORCE_OUTPUT; - info->fbops = &nouveau_fbcon_ops; - info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - - dev_priv->vm_vram_base; + info->fbops = &nouveau_fbcon_sw_ops; + info->fix.smem_start = dev->mode_config.fb_base + + (nvbo->bo.mem.start << PAGE_SHIFT); info->fix.smem_len = size; info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo); @@ -285,19 +365,18 @@ info->pixmap.flags = FB_PIXMAP_SYSTEM; info->pixmap.scan_align = 1; + mutex_unlock(&dev->struct_mutex); + if (dev_priv->channel && !nouveau_nofbaccel) { - switch (dev_priv->card_type) { - case NV_C0: - break; - case NV_50: - nv50_fbcon_accel_init(info); - info->fbops = &nv50_fbcon_ops; - break; - default: - nv04_fbcon_accel_init(info); - info->fbops = &nv04_fbcon_ops; - break; - }; + ret = -ENODEV; + if (dev_priv->card_type < NV_50) + ret = nv04_fbcon_accel_init(info); + else + if (dev_priv->card_type < NV_C0) + ret = nv50_fbcon_accel_init(info); + + if (ret == 0) + info->fbops = &nouveau_fbcon_ops; } nouveau_fbcon_zfill(dev, nfbdev); @@ -308,7 +387,6 @@ nouveau_fb->base.height, nvbo->bo.offset, nvbo); - mutex_unlock(&dev->struct_mutex); vga_switcheroo_client_fb_set(dev->pdev, info); return 0; --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_fbcon.h @@ -40,13 +40,13 @@ void nouveau_fbcon_restore(void); -void nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); -void nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -void nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); +int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); +int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); +int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); int nv04_fbcon_accel_init(struct fb_info *info); -void nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); -void nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); -void nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); +int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect); +int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region); +int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image); int nv50_fbcon_accel_init(struct fb_info *info); void nouveau_fbcon_gpu_lockup(struct fb_info *info); --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_fence.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -64,6 +64,7 @@ struct nouveau_fence *fence = container_of(ref, struct nouveau_fence, refcount); + nouveau_channel_ref(NULL, &fence->channel); kfree(fence); } @@ -76,14 +77,17 @@ spin_lock(&chan->fence.lock); - if (USE_REFCNT(dev)) - sequence = nvchan_rd32(chan, 0x48); - else - sequence = atomic_read(&chan->fence.last_sequence_irq); - - if (chan->fence.sequence_ack == sequence) - goto out; - chan->fence.sequence_ack = sequence; + /* Fetch the last sequence if the channel is still up and running */ + if (likely(!list_empty(&chan->fence.pending))) { + if (USE_REFCNT(dev)) + sequence = nvchan_rd32(chan, 0x48); + else + sequence = atomic_read(&chan->fence.last_sequence_irq); + + if (chan->fence.sequence_ack == sequence) + goto out; + chan->fence.sequence_ack = sequence; + } list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { sequence = fence->sequence; @@ -113,13 +117,13 @@ if (!fence) return -ENOMEM; kref_init(&fence->refcount); - fence->channel = chan; + nouveau_channel_ref(chan, &fence->channel); if (emit) ret = nouveau_fence_emit(fence); if (ret) - nouveau_fence_unref((void *)&fence); + nouveau_fence_unref(&fence); *pfence = fence; return ret; } @@ -127,7 +131,7 @@ struct nouveau_channel * nouveau_fence_channel(struct nouveau_fence *fence) { - return fence ? fence->channel : NULL; + return fence ? nouveau_channel_get_unlocked(fence->channel) : NULL; } int @@ -182,7 +186,7 @@ } void -nouveau_fence_unref(void **sync_obj) +__nouveau_fence_unref(void **sync_obj) { struct nouveau_fence *fence = nouveau_fence(*sync_obj); @@ -192,7 +196,7 @@ } void * -nouveau_fence_ref(void *sync_obj) +__nouveau_fence_ref(void *sync_obj) { struct nouveau_fence *fence = nouveau_fence(sync_obj); @@ -201,7 +205,7 @@ } bool -nouveau_fence_signalled(void *sync_obj, void *sync_arg) +__nouveau_fence_signalled(void *sync_obj, void *sync_arg) { struct nouveau_fence *fence = nouveau_fence(sync_obj); struct nouveau_channel *chan = fence->channel; @@ -214,13 +218,14 @@ } int -nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) +__nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) { unsigned long timeout = jiffies + (3 * DRM_HZ); + unsigned long sleep_time = jiffies + 1; int ret = 0; while (1) { - if (nouveau_fence_signalled(sync_obj, sync_arg)) + if (__nouveau_fence_signalled(sync_obj, sync_arg)) break; if (time_after_eq(jiffies, timeout)) { @@ -230,7 +235,7 @@ __set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); - if (lazy) + if (lazy && time_after_eq(jiffies, sleep_time)) schedule_timeout(1); if (intr && signal_pending(current)) { @@ -368,7 +373,7 @@ kref_get(&sema->ref); nouveau_fence_work(fence, semaphore_work, sema); - nouveau_fence_unref((void *)&fence); + nouveau_fence_unref(&fence); return 0; } @@ -380,33 +385,49 @@ struct nouveau_channel *chan = nouveau_fence_channel(fence); struct drm_device *dev = wchan->dev; struct nouveau_semaphore *sema; - int ret; + int ret = 0; - if (likely(!fence || chan == wchan || - nouveau_fence_signalled(fence, NULL))) - return 0; + if (likely(!chan || chan == wchan || + nouveau_fence_signalled(fence))) + goto out; sema = alloc_semaphore(dev); if (!sema) { /* Early card or broken userspace, fall back to * software sync. */ - return nouveau_fence_wait(fence, NULL, false, false); + ret = nouveau_fence_wait(fence, true, false); + goto out; + } + + /* try to take chan's mutex, if we can't take it right away + * we have to fallback to software sync to prevent locking + * order issues + */ + if (!mutex_trylock(&chan->mutex)) { + ret = nouveau_fence_wait(fence, true, false); + goto out_unref; } /* Make wchan wait until it gets signalled */ ret = emit_semaphore(wchan, NV_SW_SEMAPHORE_ACQUIRE, sema); if (ret) - goto out; + goto out_unlock; /* Signal the semaphore from chan */ ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema); -out: + +out_unlock: + mutex_unlock(&chan->mutex); +out_unref: kref_put(&sema->ref, free_semaphore); +out: + if (chan) + nouveau_channel_put_unlocked(&chan); return ret; } int -nouveau_fence_flush(void *sync_obj, void *sync_arg) +__nouveau_fence_flush(void *sync_obj, void *sync_arg) { return 0; } @@ -420,12 +441,7 @@ int ret; /* Create an NV_SW object for various sync purposes */ - ret = nouveau_gpuobj_sw_new(chan, NV_SW, &obj); - if (ret) - return ret; - - ret = nouveau_ramht_insert(chan, NvSw, obj); - nouveau_gpuobj_ref(NULL, &obj); + ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); if (ret) return ret; @@ -437,13 +453,12 @@ /* Create a DMA object for the shared cross-channel sync area. */ if (USE_SEMA(dev)) { - struct drm_mm_node *mem = dev_priv->fence.bo->bo.mem.mm_node; + struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, mem->start << PAGE_SHIFT, - mem->size << PAGE_SHIFT, - NV_DMA_ACCESS_RW, - NV_DMA_TARGET_VIDMEM, &obj); + mem->size, NV_MEM_ACCESS_RW, + NV_MEM_TARGET_VRAM, &obj); if (ret) return ret; @@ -473,6 +488,8 @@ { struct nouveau_fence *tmp, *fence; + spin_lock(&chan->fence.lock); + list_for_each_entry_safe(fence, tmp, &chan->fence.pending, entry) { fence->signalled = true; list_del(&fence->entry); @@ -482,6 +499,8 @@ kref_put(&fence->refcount, nouveau_fence_del); } + + spin_unlock(&chan->fence.lock); } int --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_gem.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -48,9 +48,6 @@ return; nvbo->gem = NULL; - if (unlikely(nvbo->cpu_filp)) - ttm_bo_synccpu_write_release(bo); - if (unlikely(nvbo->pin_refcnt)) { nvbo->pin_refcnt = 1; nouveau_bo_unpin(nvbo); @@ -106,32 +103,6 @@ return 0; } -static bool -nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (dev_priv->card_type >= NV_50) { - switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) { - case 0x0000: - case 0x1800: - case 0x2800: - case 0x4800: - case 0x7000: - case 0x7400: - case 0x7a00: - case 0xe000: - return true; - } - } else { - if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)) - return true; - } - - NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags); - return false; -} - int nouveau_gem_ioctl_new(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -146,11 +117,6 @@ if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL)) dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping; - if (req->channel_hint) { - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel_hint, - file_priv, chan); - } - if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM) flags |= TTM_PL_FLAG_VRAM; if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART) @@ -158,13 +124,23 @@ if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU) flags |= TTM_PL_FLAG_SYSTEM; - if (!nouveau_gem_tile_flags_valid(dev, req->info.tile_flags)) + if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) { + NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags); return -EINVAL; + } + + if (req->channel_hint) { + chan = nouveau_channel_get(dev, file_priv, req->channel_hint); + if (IS_ERR(chan)) + return PTR_ERR(chan); + } ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags, req->info.tile_mode, req->info.tile_flags, false, (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE), &nvbo); + if (chan) + nouveau_channel_put(&chan); if (ret) return ret; @@ -231,15 +207,8 @@ list_for_each_safe(entry, tmp, list) { nvbo = list_entry(entry, struct nouveau_bo, entry); - if (likely(fence)) { - struct nouveau_fence *prev_fence; - spin_lock(&nvbo->bo.lock); - prev_fence = nvbo->bo.sync_obj; - nvbo->bo.sync_obj = nouveau_fence_ref(fence); - spin_unlock(&nvbo->bo.lock); - nouveau_fence_unref((void *)&prev_fence); - } + nouveau_bo_fence(nvbo, fence); if (unlikely(nvbo->validate_mapped)) { ttm_bo_kunmap(&nvbo->kmap); @@ -299,14 +268,15 @@ return -EINVAL; } - ret = ttm_bo_reserve(&nvbo->bo, false, false, true, sequence); + ret = ttm_bo_reserve(&nvbo->bo, true, false, true, sequence); if (ret) { validate_fini(op, NULL); - if (ret == -EAGAIN) - ret = ttm_bo_wait_unreserved(&nvbo->bo, false); + if (unlikely(ret == -EAGAIN)) + ret = ttm_bo_wait_unreserved(&nvbo->bo, true); drm_gem_object_unreference_unlocked(gem); - if (ret) { - NV_ERROR(dev, "fail reserve\n"); + if (unlikely(ret)) { + if (ret != -ERESTARTSYS) + NV_ERROR(dev, "fail reserve\n"); return ret; } goto retry; @@ -331,25 +301,6 @@ validate_fini(op, NULL); return -EINVAL; } - - if (unlikely(atomic_read(&nvbo->bo.cpu_writers) > 0)) { - validate_fini(op, NULL); - - if (nvbo->cpu_filp == file_priv) { - NV_ERROR(dev, "bo %p mapped by process trying " - "to validate it!\n", nvbo); - return -EINVAL; - } - - mutex_unlock(&drm_global_mutex); - ret = ttm_bo_wait_cpu(&nvbo->bo, false); - mutex_lock(&drm_global_mutex); - if (ret) { - NV_ERROR(dev, "fail wait_cpu\n"); - return ret; - } - goto retry; - } } return 0; @@ -383,11 +334,11 @@ } nvbo->channel = (b->read_domains & (1 << 31)) ? NULL : chan; - ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, - false, false, false); + ret = nouveau_bo_validate(nvbo, true, false, false); nvbo->channel = NULL; if (unlikely(ret)) { - NV_ERROR(dev, "fail ttm_validate\n"); + if (ret != -ERESTARTSYS) + NV_ERROR(dev, "fail ttm_validate\n"); return ret; } @@ -439,13 +390,15 @@ ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); if (unlikely(ret)) { - NV_ERROR(dev, "validate_init\n"); + if (ret != -ERESTARTSYS) + NV_ERROR(dev, "validate_init\n"); return ret; } ret = validate_list(chan, &op->vram_list, pbbo, user_buffers); if (unlikely(ret < 0)) { - NV_ERROR(dev, "validate vram_list\n"); + if (ret != -ERESTARTSYS) + NV_ERROR(dev, "validate vram_list\n"); validate_fini(op, NULL); return ret; } @@ -453,7 +406,8 @@ ret = validate_list(chan, &op->gart_list, pbbo, user_buffers); if (unlikely(ret < 0)) { - NV_ERROR(dev, "validate gart_list\n"); + if (ret != -ERESTARTSYS) + NV_ERROR(dev, "validate gart_list\n"); validate_fini(op, NULL); return ret; } @@ -461,7 +415,8 @@ ret = validate_list(chan, &op->both_list, pbbo, user_buffers); if (unlikely(ret < 0)) { - NV_ERROR(dev, "validate both_list\n"); + if (ret != -ERESTARTSYS) + NV_ERROR(dev, "validate both_list\n"); validate_fini(op, NULL); return ret; } @@ -557,9 +512,9 @@ data |= r->vor; } - spin_lock(&nvbo->bo.lock); + spin_lock(&nvbo->bo.bdev->fence_lock); ret = ttm_bo_wait(&nvbo->bo, false, false, false); - spin_unlock(&nvbo->bo.lock); + spin_unlock(&nvbo->bo.bdev->fence_lock); if (ret) { NV_ERROR(dev, "reloc wait_idle failed: %d\n", ret); break; @@ -585,7 +540,9 @@ struct nouveau_fence *fence = NULL; int i, j, ret = 0, do_reloc = 0; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan); + chan = nouveau_channel_get(dev, file_priv, req->channel); + if (IS_ERR(chan)) + return PTR_ERR(chan); req->vram_available = dev_priv->fb_aper_free; req->gart_available = dev_priv->gart_info.aper_free; @@ -595,28 +552,34 @@ if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) { NV_ERROR(dev, "pushbuf push count exceeds limit: %d max %d\n", req->nr_push, NOUVEAU_GEM_MAX_PUSH); + nouveau_channel_put(&chan); return -EINVAL; } if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) { NV_ERROR(dev, "pushbuf bo count exceeds limit: %d max %d\n", req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS); + nouveau_channel_put(&chan); return -EINVAL; } if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) { NV_ERROR(dev, "pushbuf reloc count exceeds limit: %d max %d\n", req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS); + nouveau_channel_put(&chan); return -EINVAL; } push = u_memcpya(req->push, req->nr_push, sizeof(*push)); - if (IS_ERR(push)) + if (IS_ERR(push)) { + nouveau_channel_put(&chan); return PTR_ERR(push); + } bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); if (IS_ERR(bo)) { kfree(push); + nouveau_channel_put(&chan); return PTR_ERR(bo); } @@ -639,7 +602,8 @@ ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers, req->nr_buffers, &op, &do_reloc); if (ret) { - NV_ERROR(dev, "validate: %d\n", ret); + if (ret != -ERESTARTSYS) + NV_ERROR(dev, "validate: %d\n", ret); goto out; } @@ -732,7 +696,7 @@ out: validate_fini(&op, fence); - nouveau_fence_unref((void**)&fence); + nouveau_fence_unref(&fence); kfree(bo); kfree(push); @@ -750,6 +714,7 @@ req->suffix1 = 0x00000000; } + nouveau_channel_put(&chan); return ret; } @@ -781,26 +746,9 @@ return -ENOENT; nvbo = nouveau_gem_object(gem); - if (nvbo->cpu_filp) { - if (nvbo->cpu_filp == file_priv) - goto out; - - ret = ttm_bo_wait_cpu(&nvbo->bo, no_wait); - if (ret) - goto out; - } - - if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) { - spin_lock(&nvbo->bo.lock); - ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait); - spin_unlock(&nvbo->bo.lock); - } else { - ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait); - if (ret == 0) - nvbo->cpu_filp = file_priv; - } - -out: + spin_lock(&nvbo->bo.bdev->fence_lock); + ret = ttm_bo_wait(&nvbo->bo, true, true, no_wait); + spin_unlock(&nvbo->bo.bdev->fence_lock); drm_gem_object_unreference_unlocked(gem); return ret; } @@ -809,26 +757,7 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_nouveau_gem_cpu_prep *req = data; - struct drm_gem_object *gem; - struct nouveau_bo *nvbo; - int ret = -EINVAL; - - gem = drm_gem_object_lookup(dev, file_priv, req->handle); - if (!gem) - return -ENOENT; - nvbo = nouveau_gem_object(gem); - - if (nvbo->cpu_filp != file_priv) - goto out; - nvbo->cpu_filp = NULL; - - ttm_bo_synccpu_write_release(&nvbo->bo); - ret = 0; - -out: - drm_gem_object_unreference_unlocked(gem); - return ret; + return 0; } int --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_hw.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_hw.c @@ -953,7 +953,7 @@ NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850); reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900); - if (regp->crtc_cfg == NV_PCRTC_CONFIG_START_ADDRESS_HSYNC) + if (regp->crtc_cfg == NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC) NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 | 0x10000); else NVWriteRAMDAC(dev, head, NV_PRAMDAC_900, reg900 & ~0x10000); @@ -999,8 +999,8 @@ if (dev_priv->card_type == NV_10) { /* Not waiting for vertical retrace before modifying CRE_53/CRE_54 causes lockups. */ - nouveau_wait_until(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8); - nouveau_wait_until(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); + nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8); + nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); } wr_cio_state(dev, head, regp, NV_CIO_CRE_53); @@ -1017,8 +1017,9 @@ NVWriteCRTC(dev, head, NV_PCRTC_START, regp->fb_start); - /* Setting 1 on this value gives you interrupts for every vblank period. */ - NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, 0); + /* Enable vblank interrupts. */ + NVWriteCRTC(dev, head, NV_PCRTC_INTR_EN_0, + (dev->vblank_enabled[head] ? 1 : 0)); NVWriteCRTC(dev, head, NV_PCRTC_INTR_0, NV_PCRTC_INTR_0_VBLANK); } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_irq.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -36,18 +36,7 @@ #include "nouveau_drv.h" #include "nouveau_reg.h" #include "nouveau_ramht.h" -#include - -/* needed for hotplug irq */ -#include "nouveau_connector.h" -#include "nv50_display.h" - -static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); - -static int nouveau_ratelimit(void) -{ - return __ratelimit(&nouveau_ratelimit_state); -} +#include "nouveau_util.h" void nouveau_irq_preinstall(struct drm_device *dev) @@ -57,19 +46,19 @@ /* Master disable */ nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); - if (dev_priv->card_type >= NV_50) { - INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); - INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); - spin_lock_init(&dev_priv->hpd_state.lock); - INIT_LIST_HEAD(&dev_priv->vbl_waiting); - } + INIT_LIST_HEAD(&dev_priv->vbl_waiting); } int nouveau_irq_postinstall(struct drm_device *dev) { + struct drm_nouveau_private *dev_priv = dev->dev_private; + /* Master enable */ nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE); + if (dev_priv->msi_enabled) + nv_wr08(dev, 0x00088068, 0xff); + return 0; } @@ -80,1178 +69,83 @@ nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); } -static int -nouveau_call_method(struct nouveau_channel *chan, int class, int mthd, int data) -{ - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; - struct nouveau_pgraph_object_method *grm; - struct nouveau_pgraph_object_class *grc; - - grc = dev_priv->engine.graph.grclass; - while (grc->id) { - if (grc->id == class) - break; - grc++; - } - - if (grc->id != class || !grc->methods) - return -ENOENT; - - grm = grc->methods; - while (grm->id) { - if (grm->id == mthd) - return grm->exec(chan, class, mthd, data); - grm++; - } - - return -ENOENT; -} - -static bool -nouveau_fifo_swmthd(struct nouveau_channel *chan, uint32_t addr, uint32_t data) -{ - struct drm_device *dev = chan->dev; - const int subc = (addr >> 13) & 0x7; - const int mthd = addr & 0x1ffc; - - if (mthd == 0x0000) { - struct nouveau_gpuobj *gpuobj; - - gpuobj = nouveau_ramht_find(chan, data); - if (!gpuobj) - return false; - - if (gpuobj->engine != NVOBJ_ENGINE_SW) - return false; - - chan->sw_subchannel[subc] = gpuobj->class; - nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_rd32(dev, - NV04_PFIFO_CACHE1_ENGINE) & ~(0xf << subc * 4)); - return true; - } - - /* hw object */ - if (nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE) & (1 << (subc*4))) - return false; - - if (nouveau_call_method(chan, chan->sw_subchannel[subc], mthd, data)) - return false; - - return true; -} - -static void -nouveau_fifo_irq_handler(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; - uint32_t status, reassign; - int cnt = 0; - - reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1; - while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { - struct nouveau_channel *chan = NULL; - uint32_t chid, get; - - nv_wr32(dev, NV03_PFIFO_CACHES, 0); - - chid = engine->fifo.channel_id(dev); - if (chid >= 0 && chid < engine->fifo.channels) - chan = dev_priv->fifos[chid]; - get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET); - - if (status & NV_PFIFO_INTR_CACHE_ERROR) { - uint32_t mthd, data; - int ptr; - - /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before - * wrapping on my G80 chips, but CACHE1 isn't big - * enough for this much data.. Tests show that it - * wraps around to the start at GET=0x800.. No clue - * as to why.. - */ - ptr = (get & 0x7ff) >> 2; - - if (dev_priv->card_type < NV_40) { - mthd = nv_rd32(dev, - NV04_PFIFO_CACHE1_METHOD(ptr)); - data = nv_rd32(dev, - NV04_PFIFO_CACHE1_DATA(ptr)); - } else { - mthd = nv_rd32(dev, - NV40_PFIFO_CACHE1_METHOD(ptr)); - data = nv_rd32(dev, - NV40_PFIFO_CACHE1_DATA(ptr)); - } - - if (!chan || !nouveau_fifo_swmthd(chan, mthd, data)) { - NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d " - "Mthd 0x%04x Data 0x%08x\n", - chid, (mthd >> 13) & 7, mthd & 0x1ffc, - data); - } - - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0); - nv_wr32(dev, NV03_PFIFO_INTR_0, - NV_PFIFO_INTR_CACHE_ERROR); - - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, - nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1); - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); - nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, - nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); - - nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, - nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); - - status &= ~NV_PFIFO_INTR_CACHE_ERROR; - } - - if (status & NV_PFIFO_INTR_DMA_PUSHER) { - u32 dma_get = nv_rd32(dev, 0x003244); - u32 dma_put = nv_rd32(dev, 0x003240); - u32 push = nv_rd32(dev, 0x003220); - u32 state = nv_rd32(dev, 0x003228); - - if (dev_priv->card_type == NV_50) { - u32 ho_get = nv_rd32(dev, 0x003328); - u32 ho_put = nv_rd32(dev, 0x003320); - u32 ib_get = nv_rd32(dev, 0x003334); - u32 ib_put = nv_rd32(dev, 0x003330); - - if (nouveau_ratelimit()) - NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " - "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " - "State 0x%08x Push 0x%08x\n", - chid, ho_get, dma_get, ho_put, - dma_put, ib_get, ib_put, state, - push); - - /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ - nv_wr32(dev, 0x003364, 0x00000000); - if (dma_get != dma_put || ho_get != ho_put) { - nv_wr32(dev, 0x003244, dma_put); - nv_wr32(dev, 0x003328, ho_put); - } else - if (ib_get != ib_put) { - nv_wr32(dev, 0x003334, ib_put); - } - } else { - NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " - "Put 0x%08x State 0x%08x Push 0x%08x\n", - chid, dma_get, dma_put, state, push); - - if (dma_get != dma_put) - nv_wr32(dev, 0x003244, dma_put); - } - - nv_wr32(dev, 0x003228, 0x00000000); - nv_wr32(dev, 0x003220, 0x00000001); - nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); - status &= ~NV_PFIFO_INTR_DMA_PUSHER; - } - - if (status & NV_PFIFO_INTR_SEMAPHORE) { - uint32_t sem; - - status &= ~NV_PFIFO_INTR_SEMAPHORE; - nv_wr32(dev, NV03_PFIFO_INTR_0, - NV_PFIFO_INTR_SEMAPHORE); - - sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE); - nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); - - nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); - nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); - } - - if (dev_priv->card_type == NV_50) { - if (status & 0x00000010) { - nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT"); - status &= ~0x00000010; - nv_wr32(dev, 0x002100, 0x00000010); - } - } - - if (status) { - if (nouveau_ratelimit()) - NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", - status, chid); - nv_wr32(dev, NV03_PFIFO_INTR_0, status); - status = 0; - } - - nv_wr32(dev, NV03_PFIFO_CACHES, reassign); - } - - if (status) { - NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt); - nv_wr32(dev, 0x2140, 0); - nv_wr32(dev, 0x140, 0); - } - - nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); -} - -struct nouveau_bitfield_names { - uint32_t mask; - const char *name; -}; - -static struct nouveau_bitfield_names nstatus_names[] = -{ - { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, - { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, - { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, - { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" } -}; - -static struct nouveau_bitfield_names nstatus_names_nv10[] = -{ - { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, - { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, - { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, - { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" } -}; - -static struct nouveau_bitfield_names nsource_names[] = -{ - { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, - { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, - { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, - { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" }, - { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" }, - { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" }, - { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" }, - { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" }, - { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" }, - { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" }, - { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" }, - { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" }, - { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" }, - { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" }, - { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" }, - { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" }, - { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" }, - { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" }, - { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" }, -}; - -static void -nouveau_print_bitfield_names_(uint32_t value, - const struct nouveau_bitfield_names *namelist, - const int namelist_len) -{ - /* - * Caller must have already printed the KERN_* log level for us. - * Also the caller is responsible for adding the newline. - */ - int i; - for (i = 0; i < namelist_len; ++i) { - uint32_t mask = namelist[i].mask; - if (value & mask) { - printk(" %s", namelist[i].name); - value &= ~mask; - } - } - if (value) - printk(" (unknown bits 0x%08x)", value); -} -#define nouveau_print_bitfield_names(val, namelist) \ - nouveau_print_bitfield_names_((val), (namelist), ARRAY_SIZE(namelist)) - -struct nouveau_enum_names { - uint32_t value; - const char *name; -}; - -static void -nouveau_print_enum_names_(uint32_t value, - const struct nouveau_enum_names *namelist, - const int namelist_len) -{ - /* - * Caller must have already printed the KERN_* log level for us. - * Also the caller is responsible for adding the newline. - */ - int i; - for (i = 0; i < namelist_len; ++i) { - if (value == namelist[i].value) { - printk("%s", namelist[i].name); - return; - } - } - printk("unknown value 0x%08x", value); -} -#define nouveau_print_enum_names(val, namelist) \ - nouveau_print_enum_names_((val), (namelist), ARRAY_SIZE(namelist)) - -static int -nouveau_graph_chid_from_grctx(struct drm_device *dev) +irqreturn_t +nouveau_irq_handler(DRM_IRQ_ARGS) { + struct drm_device *dev = (struct drm_device *)arg; struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t inst; + unsigned long flags; + u32 stat; int i; - if (dev_priv->card_type < NV_40) - return dev_priv->engine.fifo.channels; - else - if (dev_priv->card_type < NV_50) { - inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 4; - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { - struct nouveau_channel *chan = dev_priv->fifos[i]; - - if (!chan || !chan->ramin_grctx) - continue; - - if (inst == chan->ramin_grctx->pinst) - break; - } - } else { - inst = (nv_rd32(dev, 0x40032c) & 0xfffff) << 12; - - for (i = 0; i < dev_priv->engine.fifo.channels; i++) { - struct nouveau_channel *chan = dev_priv->fifos[i]; - - if (!chan || !chan->ramin) - continue; - - if (inst == chan->ramin->vinst) - break; - } - } - - - return i; -} - -static int -nouveau_graph_trapped_channel(struct drm_device *dev, int *channel_ret) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; - int channel; - - if (dev_priv->card_type < NV_10) - channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0xf; - else - if (dev_priv->card_type < NV_40) - channel = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; - else - channel = nouveau_graph_chid_from_grctx(dev); - - if (channel >= engine->fifo.channels || !dev_priv->fifos[channel]) { - NV_ERROR(dev, "AIII, invalid/inactive channel id %d\n", channel); - return -EINVAL; - } - - *channel_ret = channel; - return 0; -} - -struct nouveau_pgraph_trap { - int channel; - int class; - int subc, mthd, size; - uint32_t data, data2; - uint32_t nsource, nstatus; -}; - -static void -nouveau_graph_trap_info(struct drm_device *dev, - struct nouveau_pgraph_trap *trap) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t address; - - trap->nsource = trap->nstatus = 0; - if (dev_priv->card_type < NV_50) { - trap->nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); - trap->nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); - } - - if (nouveau_graph_trapped_channel(dev, &trap->channel)) - trap->channel = -1; - address = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); - - trap->mthd = address & 0x1FFC; - trap->data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); - if (dev_priv->card_type < NV_10) { - trap->subc = (address >> 13) & 0x7; - } else { - trap->subc = (address >> 16) & 0x7; - trap->data2 = nv_rd32(dev, NV10_PGRAPH_TRAPPED_DATA_HIGH); - } - - if (dev_priv->card_type < NV_10) - trap->class = nv_rd32(dev, 0x400180 + trap->subc*4) & 0xFF; - else if (dev_priv->card_type < NV_40) - trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFF; - else if (dev_priv->card_type < NV_50) - trap->class = nv_rd32(dev, 0x400160 + trap->subc*4) & 0xFFFF; - else - trap->class = nv_rd32(dev, 0x400814); -} - -static void -nouveau_graph_dump_trap_info(struct drm_device *dev, const char *id, - struct nouveau_pgraph_trap *trap) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t nsource = trap->nsource, nstatus = trap->nstatus; - - if (dev_priv->card_type < NV_50) { - NV_INFO(dev, "%s - nSource:", id); - nouveau_print_bitfield_names(nsource, nsource_names); - printk(", nStatus:"); - if (dev_priv->card_type < NV_10) - nouveau_print_bitfield_names(nstatus, nstatus_names); - else - nouveau_print_bitfield_names(nstatus, nstatus_names_nv10); - printk("\n"); - } - - NV_INFO(dev, "%s - Ch %d/%d Class 0x%04x Mthd 0x%04x " - "Data 0x%08x:0x%08x\n", - id, trap->channel, trap->subc, - trap->class, trap->mthd, - trap->data2, trap->data); -} - -static int -nouveau_pgraph_intr_swmthd(struct drm_device *dev, - struct nouveau_pgraph_trap *trap) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - if (trap->channel < 0 || - trap->channel >= dev_priv->engine.fifo.channels || - !dev_priv->fifos[trap->channel]) - return -ENODEV; - - return nouveau_call_method(dev_priv->fifos[trap->channel], - trap->class, trap->mthd, trap->data); -} - -static inline void -nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource) -{ - struct nouveau_pgraph_trap trap; - int unhandled = 0; + stat = nv_rd32(dev, NV03_PMC_INTR_0); + if (!stat) + return IRQ_NONE; - nouveau_graph_trap_info(dev, &trap); + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + for (i = 0; i < 32 && stat; i++) { + if (!(stat & (1 << i)) || !dev_priv->irq_handler[i]) + continue; - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - if (nouveau_pgraph_intr_swmthd(dev, &trap)) - unhandled = 1; - } else { - unhandled = 1; + dev_priv->irq_handler[i](dev); + stat &= ~(1 << i); } - if (unhandled) - nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap); -} - - -static inline void -nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource) -{ - struct nouveau_pgraph_trap trap; - int unhandled = 0; - - nouveau_graph_trap_info(dev, &trap); - trap.nsource = nsource; - - if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { - if (nouveau_pgraph_intr_swmthd(dev, &trap)) - unhandled = 1; - } else if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { - uint32_t v = nv_rd32(dev, 0x402000); - nv_wr32(dev, 0x402000, v); - - /* dump the error anyway for now: it's useful for - Gallium development */ - unhandled = 1; - } else { - unhandled = 1; - } + if (dev_priv->msi_enabled) + nv_wr08(dev, 0x00088068, 0xff); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - if (unhandled && nouveau_ratelimit()) - nouveau_graph_dump_trap_info(dev, "PGRAPH_ERROR", &trap); + if (stat && nouveau_ratelimit()) + NV_ERROR(dev, "PMC - unhandled INTR 0x%08x\n", stat); + return IRQ_HANDLED; } -static inline void -nouveau_pgraph_intr_context_switch(struct drm_device *dev) +int +nouveau_irq_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; - uint32_t chid; - - chid = engine->fifo.channel_id(dev); - NV_DEBUG(dev, "PGRAPH context switch interrupt channel %x\n", chid); - - switch (dev_priv->card_type) { - case NV_04: - nv04_graph_context_switch(dev); - break; - case NV_10: - nv10_graph_context_switch(dev); - break; - default: - NV_ERROR(dev, "Context switch not implemented\n"); - break; - } -} - -static void -nouveau_pgraph_irq_handler(struct drm_device *dev) -{ - uint32_t status; - - while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) { - uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); - - if (status & NV_PGRAPH_INTR_NOTIFY) { - nouveau_pgraph_intr_notify(dev, nsource); - - status &= ~NV_PGRAPH_INTR_NOTIFY; - nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_NOTIFY); - } - - if (status & NV_PGRAPH_INTR_ERROR) { - nouveau_pgraph_intr_error(dev, nsource); - - status &= ~NV_PGRAPH_INTR_ERROR; - nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_ERROR); - } - - if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { - status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - nv_wr32(dev, NV03_PGRAPH_INTR, - NV_PGRAPH_INTR_CONTEXT_SWITCH); + int ret; - nouveau_pgraph_intr_context_switch(dev); + if (nouveau_msi != 0 && dev_priv->card_type >= NV_50) { + ret = pci_enable_msi(dev->pdev); + if (ret == 0) { + NV_INFO(dev, "enabled MSI\n"); + dev_priv->msi_enabled = true; } - - if (status) { - NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", status); - nv_wr32(dev, NV03_PGRAPH_INTR, status); - } - - if ((nv_rd32(dev, NV04_PGRAPH_FIFO) & (1 << 0)) == 0) - nv_wr32(dev, NV04_PGRAPH_FIFO, 1); } - nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); + return drm_irq_install(dev); } -static struct nouveau_enum_names nv50_mp_exec_error_names[] = -{ - { 3, "STACK_UNDERFLOW" }, - { 4, "QUADON_ACTIVE" }, - { 8, "TIMEOUT" }, - { 0x10, "INVALID_OPCODE" }, - { 0x40, "BREAKPOINT" }, -}; - -static void -nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t units = nv_rd32(dev, 0x1540); - uint32_t addr, mp10, status, pc, oplow, ophigh; - int i; - int mps = 0; - for (i = 0; i < 4; i++) { - if (!(units & 1 << (i+24))) - continue; - if (dev_priv->chipset < 0xa0) - addr = 0x408200 + (tpid << 12) + (i << 7); - else - addr = 0x408100 + (tpid << 11) + (i << 7); - mp10 = nv_rd32(dev, addr + 0x10); - status = nv_rd32(dev, addr + 0x14); - if (!status) - continue; - if (display) { - nv_rd32(dev, addr + 0x20); - pc = nv_rd32(dev, addr + 0x24); - oplow = nv_rd32(dev, addr + 0x70); - ophigh= nv_rd32(dev, addr + 0x74); - NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - " - "TP %d MP %d: ", tpid, i); - nouveau_print_enum_names(status, - nv50_mp_exec_error_names); - printk(" at %06x warp %d, opcode %08x %08x\n", - pc&0xffffff, pc >> 24, - oplow, ophigh); - } - nv_wr32(dev, addr + 0x10, mp10); - nv_wr32(dev, addr + 0x14, 0); - mps++; - } - if (!mps && display) - NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: " - "No MPs claiming errors?\n", tpid); -} - -static void -nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, - uint32_t ustatus_new, int display, const char *name) +void +nouveau_irq_fini(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - int tps = 0; - uint32_t units = nv_rd32(dev, 0x1540); - int i, r; - uint32_t ustatus_addr, ustatus; - for (i = 0; i < 16; i++) { - if (!(units & (1 << i))) - continue; - if (dev_priv->chipset < 0xa0) - ustatus_addr = ustatus_old + (i << 12); - else - ustatus_addr = ustatus_new + (i << 11); - ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff; - if (!ustatus) - continue; - tps++; - switch (type) { - case 6: /* texture error... unknown for now */ - nv50_fb_vm_trap(dev, display, name); - if (display) { - NV_ERROR(dev, "magic set %d:\n", i); - for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) - NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, - nv_rd32(dev, r)); - } - break; - case 7: /* MP error */ - if (ustatus & 0x00010000) { - nv50_pgraph_mp_trap(dev, i, display); - ustatus &= ~0x00010000; - } - break; - case 8: /* TPDMA error */ - { - uint32_t e0c = nv_rd32(dev, ustatus_addr + 4); - uint32_t e10 = nv_rd32(dev, ustatus_addr + 8); - uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc); - uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10); - uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); - uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); - uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); - nv50_fb_vm_trap(dev, display, name); - /* 2d engine destination */ - if (ustatus & 0x00000010) { - if (display) { - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n", - i, e14, e10); - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", - i, e0c, e18, e1c, e20, e24); - } - ustatus &= ~0x00000010; - } - /* Render target */ - if (ustatus & 0x00000040) { - if (display) { - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n", - i, e14, e10); - NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", - i, e0c, e18, e1c, e20, e24); - } - ustatus &= ~0x00000040; - } - /* CUDA memory: l[], g[] or stack. */ - if (ustatus & 0x00000080) { - if (display) { - if (e18 & 0x80000000) { - /* g[] read fault? */ - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n", - i, e14, e10 | ((e18 >> 24) & 0x1f)); - e18 &= ~0x1f000000; - } else if (e18 & 0xc) { - /* g[] write fault? */ - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n", - i, e14, e10 | ((e18 >> 7) & 0x1f)); - e18 &= ~0x00000f80; - } else { - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n", - i, e14, e10); - } - NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", - i, e0c, e18, e1c, e20, e24); - } - ustatus &= ~0x00000080; - } - } - break; - } - if (ustatus) { - if (display) - NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus); - } - nv_wr32(dev, ustatus_addr, 0xc0000000); - } - - if (!tps && display) - NV_INFO(dev, "%s - No TPs claiming errors?\n", name); -} - -static void -nv50_pgraph_trap_handler(struct drm_device *dev) -{ - struct nouveau_pgraph_trap trap; - uint32_t status = nv_rd32(dev, 0x400108); - uint32_t ustatus; - int display = nouveau_ratelimit(); - - - if (!status && display) { - nouveau_graph_trap_info(dev, &trap); - nouveau_graph_dump_trap_info(dev, "PGRAPH_TRAP", &trap); - NV_INFO(dev, "PGRAPH_TRAP - no units reporting traps?\n"); - } - - /* DISPATCH: Relays commands to other units and handles NOTIFY, - * COND, QUERY. If you get a trap from it, the command is still stuck - * in DISPATCH and you need to do something about it. */ - if (status & 0x001) { - ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff; - if (!ustatus && display) { - NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n"); - } - - /* Known to be triggered by screwed up NOTIFY and COND... */ - if (ustatus & 0x00000001) { - nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_FAULT"); - nv_wr32(dev, 0x400500, 0); - if (nv_rd32(dev, 0x400808) & 0x80000000) { - if (display) { - if (nouveau_graph_trapped_channel(dev, &trap.channel)) - trap.channel = -1; - trap.class = nv_rd32(dev, 0x400814); - trap.mthd = nv_rd32(dev, 0x400808) & 0x1ffc; - trap.subc = (nv_rd32(dev, 0x400808) >> 16) & 0x7; - trap.data = nv_rd32(dev, 0x40080c); - trap.data2 = nv_rd32(dev, 0x400810); - nouveau_graph_dump_trap_info(dev, - "PGRAPH_TRAP_DISPATCH_FAULT", &trap); - NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400808: %08x\n", nv_rd32(dev, 0x400808)); - NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - 400848: %08x\n", nv_rd32(dev, 0x400848)); - } - nv_wr32(dev, 0x400808, 0); - } else if (display) { - NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_FAULT - No stuck command?\n"); - } - nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3); - nv_wr32(dev, 0x400848, 0); - ustatus &= ~0x00000001; - } - if (ustatus & 0x00000002) { - nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_DISPATCH_QUERY"); - nv_wr32(dev, 0x400500, 0); - if (nv_rd32(dev, 0x40084c) & 0x80000000) { - if (display) { - if (nouveau_graph_trapped_channel(dev, &trap.channel)) - trap.channel = -1; - trap.class = nv_rd32(dev, 0x400814); - trap.mthd = nv_rd32(dev, 0x40084c) & 0x1ffc; - trap.subc = (nv_rd32(dev, 0x40084c) >> 16) & 0x7; - trap.data = nv_rd32(dev, 0x40085c); - trap.data2 = 0; - nouveau_graph_dump_trap_info(dev, - "PGRAPH_TRAP_DISPATCH_QUERY", &trap); - NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - 40084c: %08x\n", nv_rd32(dev, 0x40084c)); - } - nv_wr32(dev, 0x40084c, 0); - } else if (display) { - NV_INFO(dev, "PGRAPH_TRAP_DISPATCH_QUERY - No stuck command?\n"); - } - ustatus &= ~0x00000002; - } - if (ustatus && display) - NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - Unhandled ustatus 0x%08x\n", ustatus); - nv_wr32(dev, 0x400804, 0xc0000000); - nv_wr32(dev, 0x400108, 0x001); - status &= ~0x001; - } - - /* TRAPs other than dispatch use the "normal" trap regs. */ - if (status && display) { - nouveau_graph_trap_info(dev, &trap); - nouveau_graph_dump_trap_info(dev, - "PGRAPH_TRAP", &trap); - } - - /* M2MF: Memory to memory copy engine. */ - if (status & 0x002) { - ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff; - if (!ustatus && display) { - NV_INFO(dev, "PGRAPH_TRAP_M2MF - no ustatus?\n"); - } - if (ustatus & 0x00000001) { - nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_NOTIFY"); - ustatus &= ~0x00000001; - } - if (ustatus & 0x00000002) { - nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_IN"); - ustatus &= ~0x00000002; - } - if (ustatus & 0x00000004) { - nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_M2MF_OUT"); - ustatus &= ~0x00000004; - } - NV_INFO (dev, "PGRAPH_TRAP_M2MF - %08x %08x %08x %08x\n", - nv_rd32(dev, 0x406804), - nv_rd32(dev, 0x406808), - nv_rd32(dev, 0x40680c), - nv_rd32(dev, 0x406810)); - if (ustatus && display) - NV_INFO(dev, "PGRAPH_TRAP_M2MF - Unhandled ustatus 0x%08x\n", ustatus); - /* No sane way found yet -- just reset the bugger. */ - nv_wr32(dev, 0x400040, 2); - nv_wr32(dev, 0x400040, 0); - nv_wr32(dev, 0x406800, 0xc0000000); - nv_wr32(dev, 0x400108, 0x002); - status &= ~0x002; - } - - /* VFETCH: Fetches data from vertex buffers. */ - if (status & 0x004) { - ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff; - if (!ustatus && display) { - NV_INFO(dev, "PGRAPH_TRAP_VFETCH - no ustatus?\n"); - } - if (ustatus & 0x00000001) { - nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_VFETCH_FAULT"); - NV_INFO (dev, "PGRAPH_TRAP_VFETCH_FAULT - %08x %08x %08x %08x\n", - nv_rd32(dev, 0x400c00), - nv_rd32(dev, 0x400c08), - nv_rd32(dev, 0x400c0c), - nv_rd32(dev, 0x400c10)); - ustatus &= ~0x00000001; - } - if (ustatus && display) - NV_INFO(dev, "PGRAPH_TRAP_VFETCH - Unhandled ustatus 0x%08x\n", ustatus); - nv_wr32(dev, 0x400c04, 0xc0000000); - nv_wr32(dev, 0x400108, 0x004); - status &= ~0x004; - } - - /* STRMOUT: DirectX streamout / OpenGL transform feedback. */ - if (status & 0x008) { - ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff; - if (!ustatus && display) { - NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - no ustatus?\n"); - } - if (ustatus & 0x00000001) { - nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_STRMOUT_FAULT"); - NV_INFO (dev, "PGRAPH_TRAP_STRMOUT_FAULT - %08x %08x %08x %08x\n", - nv_rd32(dev, 0x401804), - nv_rd32(dev, 0x401808), - nv_rd32(dev, 0x40180c), - nv_rd32(dev, 0x401810)); - ustatus &= ~0x00000001; - } - if (ustatus && display) - NV_INFO(dev, "PGRAPH_TRAP_STRMOUT - Unhandled ustatus 0x%08x\n", ustatus); - /* No sane way found yet -- just reset the bugger. */ - nv_wr32(dev, 0x400040, 0x80); - nv_wr32(dev, 0x400040, 0); - nv_wr32(dev, 0x401800, 0xc0000000); - nv_wr32(dev, 0x400108, 0x008); - status &= ~0x008; - } - - /* CCACHE: Handles code and c[] caches and fills them. */ - if (status & 0x010) { - ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff; - if (!ustatus && display) { - NV_INFO(dev, "PGRAPH_TRAP_CCACHE - no ustatus?\n"); - } - if (ustatus & 0x00000001) { - nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_CCACHE_FAULT"); - NV_INFO (dev, "PGRAPH_TRAP_CCACHE_FAULT - %08x %08x %08x %08x %08x %08x %08x\n", - nv_rd32(dev, 0x405800), - nv_rd32(dev, 0x405804), - nv_rd32(dev, 0x405808), - nv_rd32(dev, 0x40580c), - nv_rd32(dev, 0x405810), - nv_rd32(dev, 0x405814), - nv_rd32(dev, 0x40581c)); - ustatus &= ~0x00000001; - } - if (ustatus && display) - NV_INFO(dev, "PGRAPH_TRAP_CCACHE - Unhandled ustatus 0x%08x\n", ustatus); - nv_wr32(dev, 0x405018, 0xc0000000); - nv_wr32(dev, 0x400108, 0x010); - status &= ~0x010; - } - - /* Unknown, not seen yet... 0x402000 is the only trap status reg - * remaining, so try to handle it anyway. Perhaps related to that - * unknown DMA slot on tesla? */ - if (status & 0x20) { - nv50_fb_vm_trap(dev, display, "PGRAPH_TRAP_UNKC04"); - ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; - if (display) - NV_INFO(dev, "PGRAPH_TRAP_UNKC04 - Unhandled ustatus 0x%08x\n", ustatus); - nv_wr32(dev, 0x402000, 0xc0000000); - /* no status modifiction on purpose */ - } - - /* TEXTURE: CUDA texturing units */ - if (status & 0x040) { - nv50_pgraph_tp_trap (dev, 6, 0x408900, 0x408600, display, - "PGRAPH_TRAP_TEXTURE"); - nv_wr32(dev, 0x400108, 0x040); - status &= ~0x040; - } - - /* MP: CUDA execution engines. */ - if (status & 0x080) { - nv50_pgraph_tp_trap (dev, 7, 0x408314, 0x40831c, display, - "PGRAPH_TRAP_MP"); - nv_wr32(dev, 0x400108, 0x080); - status &= ~0x080; - } - - /* TPDMA: Handles TP-initiated uncached memory accesses: - * l[], g[], stack, 2d surfaces, render targets. */ - if (status & 0x100) { - nv50_pgraph_tp_trap (dev, 8, 0x408e08, 0x408708, display, - "PGRAPH_TRAP_TPDMA"); - nv_wr32(dev, 0x400108, 0x100); - status &= ~0x100; - } - if (status) { - if (display) - NV_INFO(dev, "PGRAPH_TRAP - Unknown trap 0x%08x\n", - status); - nv_wr32(dev, 0x400108, status); - } + drm_irq_uninstall(dev); + if (dev_priv->msi_enabled) + pci_disable_msi(dev->pdev); } -/* There must be a *lot* of these. Will take some time to gather them up. */ -static struct nouveau_enum_names nv50_data_error_names[] = -{ - { 4, "INVALID_VALUE" }, - { 5, "INVALID_ENUM" }, - { 8, "INVALID_OBJECT" }, - { 0xc, "INVALID_BITFIELD" }, - { 0x28, "MP_NO_REG_SPACE" }, - { 0x2b, "MP_BLOCK_SIZE_MISMATCH" }, -}; - -static void -nv50_pgraph_irq_handler(struct drm_device *dev) -{ - struct nouveau_pgraph_trap trap; - int unhandled = 0; - uint32_t status; - - while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) { - /* NOTIFY: You've set a NOTIFY an a command and it's done. */ - if (status & 0x00000001) { - nouveau_graph_trap_info(dev, &trap); - if (nouveau_ratelimit()) - nouveau_graph_dump_trap_info(dev, - "PGRAPH_NOTIFY", &trap); - status &= ~0x00000001; - nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001); - } - - /* COMPUTE_QUERY: Purpose and exact cause unknown, happens - * when you write 0x200 to 0x50c0 method 0x31c. */ - if (status & 0x00000002) { - nouveau_graph_trap_info(dev, &trap); - if (nouveau_ratelimit()) - nouveau_graph_dump_trap_info(dev, - "PGRAPH_COMPUTE_QUERY", &trap); - status &= ~0x00000002; - nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000002); - } - - /* Unknown, never seen: 0x4 */ - - /* ILLEGAL_MTHD: You used a wrong method for this class. */ - if (status & 0x00000010) { - nouveau_graph_trap_info(dev, &trap); - if (nouveau_pgraph_intr_swmthd(dev, &trap)) - unhandled = 1; - if (unhandled && nouveau_ratelimit()) - nouveau_graph_dump_trap_info(dev, - "PGRAPH_ILLEGAL_MTHD", &trap); - status &= ~0x00000010; - nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010); - } - - /* ILLEGAL_CLASS: You used a wrong class. */ - if (status & 0x00000020) { - nouveau_graph_trap_info(dev, &trap); - if (nouveau_ratelimit()) - nouveau_graph_dump_trap_info(dev, - "PGRAPH_ILLEGAL_CLASS", &trap); - status &= ~0x00000020; - nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000020); - } - - /* DOUBLE_NOTIFY: You tried to set a NOTIFY on another NOTIFY. */ - if (status & 0x00000040) { - nouveau_graph_trap_info(dev, &trap); - if (nouveau_ratelimit()) - nouveau_graph_dump_trap_info(dev, - "PGRAPH_DOUBLE_NOTIFY", &trap); - status &= ~0x00000040; - nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000040); - } - - /* CONTEXT_SWITCH: PGRAPH needs us to load a new context */ - if (status & 0x00001000) { - nv_wr32(dev, 0x400500, 0x00000000); - nv_wr32(dev, NV03_PGRAPH_INTR, - NV_PGRAPH_INTR_CONTEXT_SWITCH); - nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev, - NV40_PGRAPH_INTR_EN) & - ~NV_PGRAPH_INTR_CONTEXT_SWITCH); - nv_wr32(dev, 0x400500, 0x00010001); - - nv50_graph_context_switch(dev); - - status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; - } - - /* BUFFER_NOTIFY: Your m2mf transfer finished */ - if (status & 0x00010000) { - nouveau_graph_trap_info(dev, &trap); - if (nouveau_ratelimit()) - nouveau_graph_dump_trap_info(dev, - "PGRAPH_BUFFER_NOTIFY", &trap); - status &= ~0x00010000; - nv_wr32(dev, NV03_PGRAPH_INTR, 0x00010000); - } - - /* DATA_ERROR: Invalid value for this method, or invalid - * state in current PGRAPH context for this operation */ - if (status & 0x00100000) { - nouveau_graph_trap_info(dev, &trap); - if (nouveau_ratelimit()) { - nouveau_graph_dump_trap_info(dev, - "PGRAPH_DATA_ERROR", &trap); - NV_INFO (dev, "PGRAPH_DATA_ERROR - "); - nouveau_print_enum_names(nv_rd32(dev, 0x400110), - nv50_data_error_names); - printk("\n"); - } - status &= ~0x00100000; - nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000); - } - - /* TRAP: Something bad happened in the middle of command - * execution. Has a billion types, subtypes, and even - * subsubtypes. */ - if (status & 0x00200000) { - nv50_pgraph_trap_handler(dev); - status &= ~0x00200000; - nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000); - } - - /* Unknown, never seen: 0x00400000 */ - - /* SINGLE_STEP: Happens on every method if you turned on - * single stepping in 40008c */ - if (status & 0x01000000) { - nouveau_graph_trap_info(dev, &trap); - if (nouveau_ratelimit()) - nouveau_graph_dump_trap_info(dev, - "PGRAPH_SINGLE_STEP", &trap); - status &= ~0x01000000; - nv_wr32(dev, NV03_PGRAPH_INTR, 0x01000000); - } - - /* 0x02000000 happens when you pause a ctxprog... - * but the only way this can happen that I know is by - * poking the relevant MMIO register, and we don't - * do that. */ - - if (status) { - NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", - status); - nv_wr32(dev, NV03_PGRAPH_INTR, status); - } - - { - const int isb = (1 << 16) | (1 << 0); - - if ((nv_rd32(dev, 0x400500) & isb) != isb) - nv_wr32(dev, 0x400500, - nv_rd32(dev, 0x400500) | isb); - } - } - - nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); - if (nv_rd32(dev, 0x400824) & (1 << 31)) - nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); -} - -static void -nouveau_crtc_irq_handler(struct drm_device *dev, int crtc) +void +nouveau_irq_register(struct drm_device *dev, int status_bit, + void (*handler)(struct drm_device *)) { - if (crtc & 1) - nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK); + struct drm_nouveau_private *dev_priv = dev->dev_private; + unsigned long flags; - if (crtc & 2) - nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + dev_priv->irq_handler[status_bit] = handler; + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); } -irqreturn_t -nouveau_irq_handler(DRM_IRQ_ARGS) +void +nouveau_irq_unregister(struct drm_device *dev, int status_bit) { - struct drm_device *dev = (struct drm_device *)arg; struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t status; unsigned long flags; - status = nv_rd32(dev, NV03_PMC_INTR_0); - if (!status) - return IRQ_NONE; - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - - if (status & NV_PMC_INTR_0_PFIFO_PENDING) { - nouveau_fifo_irq_handler(dev); - status &= ~NV_PMC_INTR_0_PFIFO_PENDING; - } - - if (status & NV_PMC_INTR_0_PGRAPH_PENDING) { - if (dev_priv->card_type >= NV_50) - nv50_pgraph_irq_handler(dev); - else - nouveau_pgraph_irq_handler(dev); - - status &= ~NV_PMC_INTR_0_PGRAPH_PENDING; - } - - if (status & NV_PMC_INTR_0_CRTCn_PENDING) { - nouveau_crtc_irq_handler(dev, (status>>24)&3); - status &= ~NV_PMC_INTR_0_CRTCn_PENDING; - } - - if (status & (NV_PMC_INTR_0_NV50_DISPLAY_PENDING | - NV_PMC_INTR_0_NV50_I2C_PENDING)) { - nv50_display_irq_handler(dev); - status &= ~(NV_PMC_INTR_0_NV50_DISPLAY_PENDING | - NV_PMC_INTR_0_NV50_I2C_PENDING); - } - - if (status) - NV_ERROR(dev, "Unhandled PMC INTR status bits 0x%08x\n", status); - + dev_priv->irq_handler[status_bit] = NULL; spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); - - return IRQ_HANDLED; } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_mem.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -36,183 +36,112 @@ #include "nouveau_drv.h" #include "nouveau_pm.h" +#include "nouveau_mm.h" +#include "nouveau_vm.h" /* * NV10-NV40 tiling helpers */ static void -nv10_mem_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch) +nv10_mem_update_tile_region(struct drm_device *dev, + struct nouveau_tile_reg *tile, uint32_t addr, + uint32_t size, uint32_t pitch, uint32_t flags) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct nouveau_tile_reg *tile = &dev_priv->tile[i]; + int i = tile - dev_priv->tile.reg; + unsigned long save; - tile->addr = addr; - tile->size = size; - tile->used = !!pitch; - nouveau_fence_unref((void **)&tile->fence); + nouveau_fence_unref(&tile->fence); + if (tile->pitch) + pfb->free_tile_region(dev, i); + + if (pitch) + pfb->init_tile_region(dev, i, addr, size, pitch, flags); + + spin_lock_irqsave(&dev_priv->context_switch_lock, save); pfifo->reassign(dev, false); pfifo->cache_pull(dev, false); nouveau_wait_for_idle(dev); - pgraph->set_region_tiling(dev, i, addr, size, pitch); - pfb->set_region_tiling(dev, i, addr, size, pitch); + pfb->set_tile_region(dev, i); + pgraph->set_tile_region(dev, i); pfifo->cache_pull(dev, true); pfifo->reassign(dev, true); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, save); } -struct nouveau_tile_reg * -nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, - uint32_t pitch) +static struct nouveau_tile_reg * +nv10_mem_get_tile_region(struct drm_device *dev, int i) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; - struct nouveau_tile_reg *found = NULL; - unsigned long i, flags; - - spin_lock_irqsave(&dev_priv->context_switch_lock, flags); - - for (i = 0; i < pfb->num_tiles; i++) { - struct nouveau_tile_reg *tile = &dev_priv->tile[i]; - - if (tile->used) - /* Tile region in use. */ - continue; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - if (tile->fence && - !nouveau_fence_signalled(tile->fence, NULL)) - /* Pending tile region. */ - continue; - - if (max(tile->addr, addr) < - min(tile->addr + tile->size, addr + size)) - /* Kill an intersecting tile region. */ - nv10_mem_set_region_tiling(dev, i, 0, 0, 0); - - if (pitch && !found) { - /* Free tile region. */ - nv10_mem_set_region_tiling(dev, i, addr, size, pitch); - found = tile; - } - } + spin_lock(&dev_priv->tile.lock); - spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + if (!tile->used && + (!tile->fence || nouveau_fence_signalled(tile->fence))) + tile->used = true; + else + tile = NULL; - return found; + spin_unlock(&dev_priv->tile.lock); + return tile; } void -nv10_mem_expire_tiling(struct drm_device *dev, struct nouveau_tile_reg *tile, - struct nouveau_fence *fence) -{ - if (fence) { - /* Mark it as pending. */ - tile->fence = fence; - nouveau_fence_ref(fence); - } - - tile->used = false; -} - -/* - * NV50 VM helpers - */ -int -nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, - uint32_t flags, uint64_t phys) +nv10_mem_put_tile_region(struct drm_device *dev, struct nouveau_tile_reg *tile, + struct nouveau_fence *fence) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *pgt; - unsigned block; - int i; - virt = ((virt - dev_priv->vm_vram_base) >> 16) << 1; - size = (size >> 16) << 1; - - phys |= ((uint64_t)flags << 32); - phys |= 1; - if (dev_priv->vram_sys_base) { - phys += dev_priv->vram_sys_base; - phys |= 0x30; - } - - while (size) { - unsigned offset_h = upper_32_bits(phys); - unsigned offset_l = lower_32_bits(phys); - unsigned pte, end; - - for (i = 7; i >= 0; i--) { - block = 1 << (i + 1); - if (size >= block && !(virt & (block - 1))) - break; + if (tile) { + spin_lock(&dev_priv->tile.lock); + if (fence) { + /* Mark it as pending. */ + tile->fence = fence; + nouveau_fence_ref(fence); } - offset_l |= (i << 7); - - phys += block << 15; - size -= block; - while (block) { - pgt = dev_priv->vm_vram_pt[virt >> 14]; - pte = virt & 0x3ffe; - - end = pte + block; - if (end > 16384) - end = 16384; - block -= (end - pte); - virt += (end - pte); - - while (pte < end) { - nv_wo32(pgt, (pte * 4) + 0, offset_l); - nv_wo32(pgt, (pte * 4) + 4, offset_h); - pte += 2; - } - } + tile->used = false; + spin_unlock(&dev_priv->tile.lock); } - - dev_priv->engine.instmem.flush(dev); - dev_priv->engine.fifo.tlb_flush(dev); - dev_priv->engine.graph.tlb_flush(dev); - nv50_vm_flush(dev, 6); - return 0; } -void -nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) +struct nouveau_tile_reg * +nv10_mem_set_tiling(struct drm_device *dev, uint32_t addr, uint32_t size, + uint32_t pitch, uint32_t flags) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *pgt; - unsigned pages, pte, end; - - virt -= dev_priv->vm_vram_base; - pages = (size >> 16) << 1; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct nouveau_tile_reg *tile, *found = NULL; + int i; - while (pages) { - pgt = dev_priv->vm_vram_pt[virt >> 29]; - pte = (virt & 0x1ffe0000ULL) >> 15; + for (i = 0; i < pfb->num_tiles; i++) { + tile = nv10_mem_get_tile_region(dev, i); - end = pte + pages; - if (end > 16384) - end = 16384; - pages -= (end - pte); - virt += (end - pte) << 15; + if (pitch && !found) { + found = tile; + continue; - while (pte < end) { - nv_wo32(pgt, (pte * 4), 0); - pte++; + } else if (tile && tile->pitch) { + /* Kill an unused tile region. */ + nv10_mem_update_tile_region(dev, tile, 0, 0, 0, 0); } + + nv10_mem_put_tile_region(dev, tile, NULL); } - dev_priv->engine.instmem.flush(dev); - dev_priv->engine.fifo.tlb_flush(dev); - dev_priv->engine.graph.tlb_flush(dev); - nv50_vm_flush(dev, 6); + if (found) + nv10_mem_update_tile_region(dev, found, addr, size, + pitch, flags); + return found; } /* @@ -312,62 +241,7 @@ return 0; } -static void -nv50_vram_preinit(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i, parts, colbits, rowbitsa, rowbitsb, banks; - u64 rowsize, predicted; - u32 r0, r4, rt, ru; - - r0 = nv_rd32(dev, 0x100200); - r4 = nv_rd32(dev, 0x100204); - rt = nv_rd32(dev, 0x100250); - ru = nv_rd32(dev, 0x001540); - NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); - - for (i = 0, parts = 0; i < 8; i++) { - if (ru & (0x00010000 << i)) - parts++; - } - - colbits = (r4 & 0x0000f000) >> 12; - rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; - rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; - banks = ((r4 & 0x01000000) ? 8 : 4); - - rowsize = parts * banks * (1 << colbits) * 8; - predicted = rowsize << rowbitsa; - if (r0 & 0x00000004) - predicted += rowsize << rowbitsb; - - if (predicted != dev_priv->vram_size) { - NV_WARN(dev, "memory controller reports %dMiB VRAM\n", - (u32)(dev_priv->vram_size >> 20)); - NV_WARN(dev, "we calculated %dMiB VRAM\n", - (u32)(predicted >> 20)); - } - - dev_priv->vram_rblock_size = rowsize >> 12; - if (rt & 1) - dev_priv->vram_rblock_size *= 3; - - NV_DEBUG(dev, "rblock %lld bytes\n", - (u64)dev_priv->vram_rblock_size << 12); -} - -static void -nvaa_vram_preinit(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - /* To our knowledge, there's no large scale reordering of pages - * that occurs on IGP chipsets. - */ - dev_priv->vram_rblock_size = 1; -} - -static int +int nouveau_mem_detect(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -381,40 +255,25 @@ if (dev_priv->card_type < NV_50) { dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; - } else - if (dev_priv->card_type < NV_C0) { - dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); - dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; - dev_priv->vram_size &= 0xffffffff00ll; - - switch (dev_priv->chipset) { - case 0xaa: - case 0xac: - case 0xaf: - dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); - dev_priv->vram_sys_base <<= 12; - nvaa_vram_preinit(dev); - break; - default: - nv50_vram_preinit(dev); - break; - } } else { dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; dev_priv->vram_size *= nv_rd32(dev, 0x121c74); } - NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); - if (dev_priv->vram_sys_base) { - NV_INFO(dev, "Stolen system memory at: 0x%010llx\n", - dev_priv->vram_sys_base); - } - if (dev_priv->vram_size) return 0; return -ENOMEM; } +bool +nouveau_mem_flags_valid(struct drm_device *dev, u32 tile_flags) +{ + if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)) + return true; + + return false; +} + #if __OS_HAS_AGP static unsigned long get_agp_mode(struct drm_device *dev, unsigned long mode) @@ -547,10 +406,6 @@ if (ret) return ret; - ret = nouveau_mem_detect(dev); - if (ret) - return ret; - dev_priv->fb_phys = pci_resource_start(dev->pdev, 1); ret = nouveau_ttm_global_init(dev_priv); @@ -566,13 +421,6 @@ return ret; } - dev_priv->fb_available_size = dev_priv->vram_size; - dev_priv->fb_mappable_pages = dev_priv->fb_available_size; - if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) - dev_priv->fb_mappable_pages = - pci_resource_len(dev->pdev, 1); - dev_priv->fb_mappable_pages >>= PAGE_SHIFT; - /* reserve space at end of VRAM for PRAMIN */ if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 || dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) @@ -583,6 +431,22 @@ else dev_priv->ramin_rsvd_vram = (512 * 1024); + ret = dev_priv->engine.vram.init(dev); + if (ret) + return ret; + + NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); + if (dev_priv->vram_sys_base) { + NV_INFO(dev, "Stolen system memory at: 0x%010llx\n", + dev_priv->vram_sys_base); + } + + dev_priv->fb_available_size = dev_priv->vram_size; + dev_priv->fb_mappable_pages = dev_priv->fb_available_size; + if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1)) + dev_priv->fb_mappable_pages = pci_resource_len(dev->pdev, 1); + dev_priv->fb_mappable_pages >>= PAGE_SHIFT; + dev_priv->fb_available_size -= dev_priv->ramin_rsvd_vram; dev_priv->fb_aper_free = dev_priv->fb_available_size; @@ -799,3 +663,114 @@ kfree(mem->timing); } + +static int +nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long p_size) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct nouveau_mm *mm; + u32 b_size; + int ret; + + p_size = (p_size << PAGE_SHIFT) >> 12; + b_size = dev_priv->vram_rblock_size >> 12; + + ret = nouveau_mm_init(&mm, 0, p_size, b_size); + if (ret) + return ret; + + man->priv = mm; + return 0; +} + +static int +nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) +{ + struct nouveau_mm *mm = man->priv; + int ret; + + ret = nouveau_mm_fini(&mm); + if (ret) + return ret; + + man->priv = NULL; + return 0; +} + +static void +nouveau_vram_manager_del(struct ttm_mem_type_manager *man, + struct ttm_mem_reg *mem) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + struct drm_device *dev = dev_priv->dev; + + vram->put(dev, (struct nouveau_vram **)&mem->mm_node); +} + +static int +nouveau_vram_manager_new(struct ttm_mem_type_manager *man, + struct ttm_buffer_object *bo, + struct ttm_placement *placement, + struct ttm_mem_reg *mem) +{ + struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev); + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + struct drm_device *dev = dev_priv->dev; + struct nouveau_bo *nvbo = nouveau_bo(bo); + struct nouveau_vram *node; + u32 size_nc = 0; + int ret; + + if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) + size_nc = 1 << nvbo->vma.node->type; + + ret = vram->get(dev, mem->num_pages << PAGE_SHIFT, + mem->page_alignment << PAGE_SHIFT, size_nc, + (nvbo->tile_flags >> 8) & 0xff, &node); + if (ret) + return ret; + + mem->mm_node = node; + mem->start = node->offset >> PAGE_SHIFT; + return 0; +} + +void +nouveau_vram_manager_debug(struct ttm_mem_type_manager *man, const char *prefix) +{ + struct nouveau_mm *mm = man->priv; + struct nouveau_mm_node *r; + u64 total = 0, ttotal[3] = {}, tused[3] = {}, tfree[3] = {}; + int i; + + mutex_lock(&mm->mutex); + list_for_each_entry(r, &mm->nodes, nl_entry) { + printk(KERN_DEBUG "%s %s-%d: 0x%010llx 0x%010llx\n", + prefix, r->free ? "free" : "used", r->type, + ((u64)r->offset << 12), + (((u64)r->offset + r->length) << 12)); + total += r->length; + ttotal[r->type] += r->length; + if (r->free) + tfree[r->type] += r->length; + else + tused[r->type] += r->length; + } + mutex_unlock(&mm->mutex); + + printk(KERN_DEBUG "%s total: 0x%010llx\n", prefix, total << 12); + for (i = 0; i < 3; i++) { + printk(KERN_DEBUG "%s type %d: 0x%010llx, " + "used 0x%010llx, free 0x%010llx\n", prefix, + i, ttotal[i] << 12, tused[i] << 12, tfree[i] << 12); + } +} + +const struct ttm_mem_type_manager_func nouveau_vram_manager = { + nouveau_vram_manager_init, + nouveau_vram_manager_fini, + nouveau_vram_manager_new, + nouveau_vram_manager_del, + nouveau_vram_manager_debug +}; --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_mm.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_mm.c @@ -0,0 +1,271 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_mm.h" + +static inline void +region_put(struct nouveau_mm *rmm, struct nouveau_mm_node *a) +{ + list_del(&a->nl_entry); + list_del(&a->fl_entry); + kfree(a); +} + +static struct nouveau_mm_node * +region_split(struct nouveau_mm *rmm, struct nouveau_mm_node *a, u32 size) +{ + struct nouveau_mm_node *b; + + if (a->length == size) + return a; + + b = kmalloc(sizeof(*b), GFP_KERNEL); + if (unlikely(b == NULL)) + return NULL; + + b->offset = a->offset; + b->length = size; + b->free = a->free; + b->type = a->type; + a->offset += size; + a->length -= size; + list_add_tail(&b->nl_entry, &a->nl_entry); + if (b->free) + list_add_tail(&b->fl_entry, &a->fl_entry); + return b; +} + +static struct nouveau_mm_node * +nouveau_mm_merge(struct nouveau_mm *rmm, struct nouveau_mm_node *this) +{ + struct nouveau_mm_node *prev, *next; + + /* try to merge with free adjacent entries of same type */ + prev = list_entry(this->nl_entry.prev, struct nouveau_mm_node, nl_entry); + if (this->nl_entry.prev != &rmm->nodes) { + if (prev->free && prev->type == this->type) { + prev->length += this->length; + region_put(rmm, this); + this = prev; + } + } + + next = list_entry(this->nl_entry.next, struct nouveau_mm_node, nl_entry); + if (this->nl_entry.next != &rmm->nodes) { + if (next->free && next->type == this->type) { + next->offset = this->offset; + next->length += this->length; + region_put(rmm, this); + this = next; + } + } + + return this; +} + +void +nouveau_mm_put(struct nouveau_mm *rmm, struct nouveau_mm_node *this) +{ + u32 block_s, block_l; + + this->free = true; + list_add(&this->fl_entry, &rmm->free); + this = nouveau_mm_merge(rmm, this); + + /* any entirely free blocks now? we'll want to remove typing + * on them now so they can be use for any memory allocation + */ + block_s = roundup(this->offset, rmm->block_size); + if (block_s + rmm->block_size > this->offset + this->length) + return; + + /* split off any still-typed region at the start */ + if (block_s != this->offset) { + if (!region_split(rmm, this, block_s - this->offset)) + return; + } + + /* split off the soon-to-be-untyped block(s) */ + block_l = rounddown(this->length, rmm->block_size); + if (block_l != this->length) { + this = region_split(rmm, this, block_l); + if (!this) + return; + } + + /* mark as having no type, and retry merge with any adjacent + * untyped blocks + */ + this->type = 0; + nouveau_mm_merge(rmm, this); +} + +int +nouveau_mm_get(struct nouveau_mm *rmm, int type, u32 size, u32 size_nc, + u32 align, struct nouveau_mm_node **pnode) +{ + struct nouveau_mm_node *this, *tmp, *next; + u32 splitoff, avail, alloc; + + list_for_each_entry_safe(this, tmp, &rmm->free, fl_entry) { + next = list_entry(this->nl_entry.next, struct nouveau_mm_node, nl_entry); + if (this->nl_entry.next == &rmm->nodes) + next = NULL; + + /* skip wrongly typed blocks */ + if (this->type && this->type != type) + continue; + + /* account for alignment */ + splitoff = this->offset & (align - 1); + if (splitoff) + splitoff = align - splitoff; + + if (this->length <= splitoff) + continue; + + /* determine total memory available from this, and + * the next block (if appropriate) + */ + avail = this->length; + if (next && next->free && (!next->type || next->type == type)) + avail += next->length; + + avail -= splitoff; + + /* determine allocation size */ + if (size_nc) { + alloc = min(avail, size); + alloc = rounddown(alloc, size_nc); + if (alloc == 0) + continue; + } else { + alloc = size; + if (avail < alloc) + continue; + } + + /* untyped block, split off a chunk that's a multiple + * of block_size and type it + */ + if (!this->type) { + u32 block = roundup(alloc + splitoff, rmm->block_size); + if (this->length < block) + continue; + + this = region_split(rmm, this, block); + if (!this) + return -ENOMEM; + + this->type = type; + } + + /* stealing memory from adjacent block */ + if (alloc > this->length) { + u32 amount = alloc - (this->length - splitoff); + + if (!next->type) { + amount = roundup(amount, rmm->block_size); + + next = region_split(rmm, next, amount); + if (!next) + return -ENOMEM; + + next->type = type; + } + + this->length += amount; + next->offset += amount; + next->length -= amount; + if (!next->length) { + list_del(&next->nl_entry); + list_del(&next->fl_entry); + kfree(next); + } + } + + if (splitoff) { + if (!region_split(rmm, this, splitoff)) + return -ENOMEM; + } + + this = region_split(rmm, this, alloc); + if (this == NULL) + return -ENOMEM; + + this->free = false; + list_del(&this->fl_entry); + *pnode = this; + return 0; + } + + return -ENOMEM; +} + +int +nouveau_mm_init(struct nouveau_mm **prmm, u32 offset, u32 length, u32 block) +{ + struct nouveau_mm *rmm; + struct nouveau_mm_node *heap; + + heap = kzalloc(sizeof(*heap), GFP_KERNEL); + if (!heap) + return -ENOMEM; + heap->free = true; + heap->offset = roundup(offset, block); + heap->length = rounddown(offset + length, block) - heap->offset; + + rmm = kzalloc(sizeof(*rmm), GFP_KERNEL); + if (!rmm) { + kfree(heap); + return -ENOMEM; + } + rmm->block_size = block; + mutex_init(&rmm->mutex); + INIT_LIST_HEAD(&rmm->nodes); + INIT_LIST_HEAD(&rmm->free); + list_add(&heap->nl_entry, &rmm->nodes); + list_add(&heap->fl_entry, &rmm->free); + + *prmm = rmm; + return 0; +} + +int +nouveau_mm_fini(struct nouveau_mm **prmm) +{ + struct nouveau_mm *rmm = *prmm; + struct nouveau_mm_node *heap = + list_first_entry(&rmm->nodes, struct nouveau_mm_node, nl_entry); + + if (!list_is_singular(&rmm->nodes)) + return -EBUSY; + + kfree(heap); + kfree(rmm); + *prmm = NULL; + return 0; +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_mm.h +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_mm.h @@ -0,0 +1,62 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#ifndef __NOUVEAU_REGION_H__ +#define __NOUVEAU_REGION_H__ + +struct nouveau_mm_node { + struct list_head nl_entry; + struct list_head fl_entry; + struct list_head rl_entry; + + bool free; + int type; + + u32 offset; + u32 length; +}; + +struct nouveau_mm { + struct list_head nodes; + struct list_head free; + + struct mutex mutex; + + u32 block_size; +}; + +int nouveau_mm_init(struct nouveau_mm **, u32 offset, u32 length, u32 block); +int nouveau_mm_fini(struct nouveau_mm **); +int nouveau_mm_pre(struct nouveau_mm *); +int nouveau_mm_get(struct nouveau_mm *, int type, u32 size, u32 size_nc, + u32 align, struct nouveau_mm_node **); +void nouveau_mm_put(struct nouveau_mm *, struct nouveau_mm_node *); + +int nv50_vram_init(struct drm_device *); +int nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc, + u32 memtype, struct nouveau_vram **); +void nv50_vram_del(struct drm_device *, struct nouveau_vram **); +bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags); + +#endif --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_notifier.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_notifier.c @@ -99,7 +99,6 @@ int size, uint32_t *b_offset) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *nobj = NULL; struct drm_mm_node *mem; uint32_t offset; @@ -113,31 +112,15 @@ return -ENOMEM; } - offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; - if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) { - target = NV_DMA_TARGET_VIDMEM; - } else - if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_TT) { - if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA && - dev_priv->card_type < NV_50) { - ret = nouveau_sgdma_get_page(dev, offset, &offset); - if (ret) - return ret; - target = NV_DMA_TARGET_PCI; - } else { - target = NV_DMA_TARGET_AGP; - if (dev_priv->card_type >= NV_50) - offset += dev_priv->vm_gart_base; - } - } else { - NV_ERROR(dev, "Bad DMA target, mem_type %d!\n", - chan->notifier_bo->bo.mem.mem_type); - return -EINVAL; - } + if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM) + target = NV_MEM_TARGET_VRAM; + else + target = NV_MEM_TARGET_GART; + offset = chan->notifier_bo->bo.mem.start << PAGE_SHIFT; offset += mem->start; ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset, - mem->size, NV_DMA_ACCESS_RW, target, + mem->size, NV_MEM_ACCESS_RW, target, &nobj); if (ret) { drm_mm_put_block(mem); @@ -185,11 +168,11 @@ struct nouveau_channel *chan; int ret; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan); + chan = nouveau_channel_get(dev, file_priv, na->channel); + if (IS_ERR(chan)) + return PTR_ERR(chan); ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset); - if (ret) - return ret; - - return 0; + nouveau_channel_put(&chan); + return ret; } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_object.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_object.c @@ -35,6 +35,102 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" #include "nouveau_ramht.h" +#include "nouveau_vm.h" + +struct nouveau_gpuobj_method { + struct list_head head; + u32 mthd; + int (*exec)(struct nouveau_channel *, u32 class, u32 mthd, u32 data); +}; + +struct nouveau_gpuobj_class { + struct list_head head; + struct list_head methods; + u32 id; + u32 engine; +}; + +int +nouveau_gpuobj_class_new(struct drm_device *dev, u32 class, u32 engine) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj_class *oc; + + oc = kzalloc(sizeof(*oc), GFP_KERNEL); + if (!oc) + return -ENOMEM; + + INIT_LIST_HEAD(&oc->methods); + oc->id = class; + oc->engine = engine; + list_add(&oc->head, &dev_priv->classes); + return 0; +} + +int +nouveau_gpuobj_mthd_new(struct drm_device *dev, u32 class, u32 mthd, + int (*exec)(struct nouveau_channel *, u32, u32, u32)) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj_method *om; + struct nouveau_gpuobj_class *oc; + + list_for_each_entry(oc, &dev_priv->classes, head) { + if (oc->id == class) + goto found; + } + + return -EINVAL; + +found: + om = kzalloc(sizeof(*om), GFP_KERNEL); + if (!om) + return -ENOMEM; + + om->mthd = mthd; + om->exec = exec; + list_add(&om->head, &oc->methods); + return 0; +} + +int +nouveau_gpuobj_mthd_call(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nouveau_gpuobj_method *om; + struct nouveau_gpuobj_class *oc; + + list_for_each_entry(oc, &dev_priv->classes, head) { + if (oc->id != class) + continue; + + list_for_each_entry(om, &oc->methods, head) { + if (om->mthd == mthd) + return om->exec(chan, class, mthd, data); + } + } + + return -ENOENT; +} + +int +nouveau_gpuobj_mthd_call2(struct drm_device *dev, int chid, + u32 class, u32 mthd, u32 data) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = NULL; + unsigned long flags; + int ret = -EINVAL; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); + if (chid > 0 && chid < dev_priv->engine.fifo.channels) + chan = dev_priv->channels.ptr[chid]; + if (chan) + ret = nouveau_gpuobj_mthd_call(chan, class, mthd, data); + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + return ret; +} /* NVidia uses context objects to drive drawing operations. @@ -73,17 +169,14 @@ struct nouveau_gpuobj **gpuobj_ret) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; + struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; struct nouveau_gpuobj *gpuobj; struct drm_mm_node *ramin = NULL; - int ret; + int ret, i; NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n", chan ? chan->id : -1, size, align, flags); - if (!dev_priv || !gpuobj_ret || *gpuobj_ret != NULL) - return -EINVAL; - gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); if (!gpuobj) return -ENOMEM; @@ -98,88 +191,41 @@ spin_unlock(&dev_priv->ramin_lock); if (chan) { - NV_DEBUG(dev, "channel heap\n"); - ramin = drm_mm_search_free(&chan->ramin_heap, size, align, 0); if (ramin) ramin = drm_mm_get_block(ramin, size, align); - if (!ramin) { nouveau_gpuobj_ref(NULL, &gpuobj); return -ENOMEM; } - } else { - NV_DEBUG(dev, "global heap\n"); - /* allocate backing pages, sets vinst */ - ret = engine->instmem.populate(dev, gpuobj, &size); - if (ret) { - nouveau_gpuobj_ref(NULL, &gpuobj); - return ret; - } - - /* try and get aperture space */ - do { - if (drm_mm_pre_get(&dev_priv->ramin_heap)) - return -ENOMEM; - - spin_lock(&dev_priv->ramin_lock); - ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, - align, 0); - if (ramin == NULL) { - spin_unlock(&dev_priv->ramin_lock); - nouveau_gpuobj_ref(NULL, &gpuobj); - return -ENOMEM; - } - - ramin = drm_mm_get_block_atomic(ramin, size, align); - spin_unlock(&dev_priv->ramin_lock); - } while (ramin == NULL); - - /* on nv50 it's ok to fail, we have a fallback path */ - if (!ramin && dev_priv->card_type < NV_50) { - nouveau_gpuobj_ref(NULL, &gpuobj); - return -ENOMEM; - } - } + gpuobj->pinst = chan->ramin->pinst; + if (gpuobj->pinst != ~0) + gpuobj->pinst += ramin->start; - /* if we got a chunk of the aperture, map pages into it */ - gpuobj->im_pramin = ramin; - if (!chan && gpuobj->im_pramin && dev_priv->ramin_available) { - ret = engine->instmem.bind(dev, gpuobj); + gpuobj->cinst = ramin->start; + gpuobj->vinst = ramin->start + chan->ramin->vinst; + gpuobj->node = ramin; + } else { + ret = instmem->get(gpuobj, size, align); if (ret) { nouveau_gpuobj_ref(NULL, &gpuobj); return ret; } - } - /* calculate the various different addresses for the object */ - if (chan) { - gpuobj->pinst = chan->ramin->pinst; - if (gpuobj->pinst != ~0) - gpuobj->pinst += gpuobj->im_pramin->start; - - if (dev_priv->card_type < NV_50) { - gpuobj->cinst = gpuobj->pinst; - } else { - gpuobj->cinst = gpuobj->im_pramin->start; - gpuobj->vinst = gpuobj->im_pramin->start + - chan->ramin->vinst; - } - } else { - if (gpuobj->im_pramin) - gpuobj->pinst = gpuobj->im_pramin->start; - else + ret = -ENOSYS; + if (!(flags & NVOBJ_FLAG_DONT_MAP)) + ret = instmem->map(gpuobj); + if (ret) gpuobj->pinst = ~0; - gpuobj->cinst = 0xdeadbeef; + + gpuobj->cinst = NVOBJ_CINST_GLOBAL; } if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { - int i; - for (i = 0; i < gpuobj->size; i += 4) nv_wo32(gpuobj, i, 0); - engine->instmem.flush(dev); + instmem->flush(dev); } @@ -195,6 +241,7 @@ NV_DEBUG(dev, "\n"); INIT_LIST_HEAD(&dev_priv->gpuobj_list); + INIT_LIST_HEAD(&dev_priv->classes); spin_lock_init(&dev_priv->ramin_lock); dev_priv->ramin_base = ~0; @@ -205,9 +252,20 @@ nouveau_gpuobj_takedown(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj_method *om, *tm; + struct nouveau_gpuobj_class *oc, *tc; NV_DEBUG(dev, "\n"); + list_for_each_entry_safe(oc, tc, &dev_priv->classes, head) { + list_for_each_entry_safe(om, tm, &oc->methods, head) { + list_del(&om->head); + kfree(om); + } + list_del(&oc->head); + kfree(oc); + } + BUG_ON(!list_empty(&dev_priv->gpuobj_list)); } @@ -219,26 +277,34 @@ container_of(ref, struct nouveau_gpuobj, refcount); struct drm_device *dev = gpuobj->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_engine *engine = &dev_priv->engine; + struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; int i; NV_DEBUG(dev, "gpuobj %p\n", gpuobj); - if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { + if (gpuobj->node && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) { for (i = 0; i < gpuobj->size; i += 4) nv_wo32(gpuobj, i, 0); - engine->instmem.flush(dev); + instmem->flush(dev); } if (gpuobj->dtor) gpuobj->dtor(dev, gpuobj); - if (gpuobj->im_backing) - engine->instmem.clear(dev, gpuobj); + if (gpuobj->cinst == NVOBJ_CINST_GLOBAL) { + if (gpuobj->node) { + instmem->unmap(gpuobj); + instmem->put(gpuobj); + } + } else { + if (gpuobj->node) { + spin_lock(&dev_priv->ramin_lock); + drm_mm_put_block(gpuobj->node); + spin_unlock(&dev_priv->ramin_lock); + } + } spin_lock(&dev_priv->ramin_lock); - if (gpuobj->im_pramin) - drm_mm_put_block(gpuobj->im_pramin); list_del(&gpuobj->list); spin_unlock(&dev_priv->ramin_lock); @@ -278,7 +344,7 @@ kref_init(&gpuobj->refcount); gpuobj->size = size; gpuobj->pinst = pinst; - gpuobj->cinst = 0xdeadbeef; + gpuobj->cinst = NVOBJ_CINST_GLOBAL; gpuobj->vinst = vinst; if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) { @@ -335,113 +401,150 @@ The method below creates a DMA object in instance RAM and returns a handle to it that can be used to set up context objects. */ -int -nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, - uint64_t offset, uint64_t size, int access, - int target, struct nouveau_gpuobj **gpuobj) -{ - struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; - int ret; - NV_DEBUG(dev, "ch%d class=0x%04x offset=0x%llx size=0x%llx\n", - chan->id, class, offset, size); - NV_DEBUG(dev, "access=%d target=%d\n", access, target); +void +nv50_gpuobj_dma_init(struct nouveau_gpuobj *obj, u32 offset, int class, + u64 base, u64 size, int target, int access, + u32 type, u32 comp) +{ + struct drm_nouveau_private *dev_priv = obj->dev->dev_private; + struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + u32 flags0; + + flags0 = (comp << 29) | (type << 22) | class; + flags0 |= 0x00100000; + + switch (access) { + case NV_MEM_ACCESS_RO: flags0 |= 0x00040000; break; + case NV_MEM_ACCESS_RW: + case NV_MEM_ACCESS_WO: flags0 |= 0x00080000; break; + default: + break; + } switch (target) { - case NV_DMA_TARGET_AGP: - offset += dev_priv->gart_info.aper_base; + case NV_MEM_TARGET_VRAM: + flags0 |= 0x00010000; + break; + case NV_MEM_TARGET_PCI: + flags0 |= 0x00020000; + break; + case NV_MEM_TARGET_PCI_NOSNOOP: + flags0 |= 0x00030000; break; + case NV_MEM_TARGET_GART: + base += dev_priv->gart_info.aper_base; default: + flags0 &= ~0x00100000; break; } - ret = nouveau_gpuobj_new(dev, chan, - nouveau_gpuobj_class_instmem_size(dev, class), - 16, NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, gpuobj); - if (ret) { - NV_ERROR(dev, "Error creating gpuobj: %d\n", ret); - return ret; - } + /* convert to base + limit */ + size = (base + size) - 1; - if (dev_priv->card_type < NV_50) { - uint32_t frame, adjust, pte_flags = 0; - - if (access != NV_DMA_ACCESS_RO) - pte_flags |= (1<<1); - adjust = offset & 0x00000fff; - frame = offset & ~0x00000fff; - - nv_wo32(*gpuobj, 0, ((1<<12) | (1<<13) | (adjust << 20) | - (access << 14) | (target << 16) | - class)); - nv_wo32(*gpuobj, 4, size - 1); - nv_wo32(*gpuobj, 8, frame | pte_flags); - nv_wo32(*gpuobj, 12, frame | pte_flags); - } else { - uint64_t limit = offset + size - 1; - uint32_t flags0, flags5; + nv_wo32(obj, offset + 0x00, flags0); + nv_wo32(obj, offset + 0x04, lower_32_bits(size)); + nv_wo32(obj, offset + 0x08, lower_32_bits(base)); + nv_wo32(obj, offset + 0x0c, upper_32_bits(size) << 24 | + upper_32_bits(base)); + nv_wo32(obj, offset + 0x10, 0x00000000); + nv_wo32(obj, offset + 0x14, 0x00000000); - if (target == NV_DMA_TARGET_VIDMEM) { - flags0 = 0x00190000; - flags5 = 0x00010000; - } else { - flags0 = 0x7fc00000; - flags5 = 0x00080000; - } + pinstmem->flush(obj->dev); +} - nv_wo32(*gpuobj, 0, flags0 | class); - nv_wo32(*gpuobj, 4, lower_32_bits(limit)); - nv_wo32(*gpuobj, 8, lower_32_bits(offset)); - nv_wo32(*gpuobj, 12, ((upper_32_bits(limit) & 0xff) << 24) | - (upper_32_bits(offset) & 0xff)); - nv_wo32(*gpuobj, 20, flags5); - } +int +nv50_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, u64 size, + int target, int access, u32 type, u32 comp, + struct nouveau_gpuobj **pobj) +{ + struct drm_device *dev = chan->dev; + int ret; - instmem->flush(dev); + ret = nouveau_gpuobj_new(dev, chan, 24, 16, NVOBJ_FLAG_ZERO_FREE, pobj); + if (ret) + return ret; - (*gpuobj)->engine = NVOBJ_ENGINE_SW; - (*gpuobj)->class = class; + nv50_gpuobj_dma_init(*pobj, 0, class, base, size, target, + access, type, comp); return 0; } int -nouveau_gpuobj_gart_dma_new(struct nouveau_channel *chan, - uint64_t offset, uint64_t size, int access, - struct nouveau_gpuobj **gpuobj, - uint32_t *o_ret) +nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class, u64 base, + u64 size, int access, int target, + struct nouveau_gpuobj **pobj) { + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *obj; + u32 flags0, flags2; int ret; - if (dev_priv->gart_info.type == NOUVEAU_GART_AGP || - (dev_priv->card_type >= NV_50 && - dev_priv->gart_info.type == NOUVEAU_GART_SGDMA)) { - ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - offset + dev_priv->vm_gart_base, - size, access, NV_DMA_TARGET_AGP, - gpuobj); - if (o_ret) - *o_ret = 0; - } else - if (dev_priv->gart_info.type == NOUVEAU_GART_SGDMA) { - nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, gpuobj); - if (offset & ~0xffffffffULL) { - NV_ERROR(dev, "obj offset exceeds 32-bits\n"); - return -EINVAL; - } - if (o_ret) - *o_ret = (uint32_t)offset; - ret = (*gpuobj != NULL) ? 0 : -EINVAL; - } else { - NV_ERROR(dev, "Invalid GART type %d\n", dev_priv->gart_info.type); - return -EINVAL; + if (dev_priv->card_type >= NV_50) { + u32 comp = (target == NV_MEM_TARGET_VM) ? NV_MEM_COMP_VM : 0; + u32 type = (target == NV_MEM_TARGET_VM) ? NV_MEM_TYPE_VM : 0; + + return nv50_gpuobj_dma_new(chan, class, base, size, + target, access, type, comp, pobj); } - return ret; + if (target == NV_MEM_TARGET_GART) { + if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { + target = NV_MEM_TARGET_PCI_NOSNOOP; + base += dev_priv->gart_info.aper_base; + } else + if (base != 0) { + base = nouveau_sgdma_get_physical(dev, base); + target = NV_MEM_TARGET_PCI; + } else { + nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, pobj); + return 0; + } + } + + flags0 = class; + flags0 |= 0x00003000; /* PT present, PT linear */ + flags2 = 0; + + switch (target) { + case NV_MEM_TARGET_PCI: + flags0 |= 0x00020000; + break; + case NV_MEM_TARGET_PCI_NOSNOOP: + flags0 |= 0x00030000; + break; + default: + break; + } + + switch (access) { + case NV_MEM_ACCESS_RO: + flags0 |= 0x00004000; + break; + case NV_MEM_ACCESS_WO: + flags0 |= 0x00008000; + default: + flags2 |= 0x00000002; + break; + } + + flags0 |= (base & 0x00000fff) << 20; + flags2 |= (base & 0xfffff000); + + ret = nouveau_gpuobj_new(dev, chan, 16, 16, NVOBJ_FLAG_ZERO_FREE, &obj); + if (ret) + return ret; + + nv_wo32(obj, 0x00, flags0); + nv_wo32(obj, 0x04, size - 1); + nv_wo32(obj, 0x08, flags2); + nv_wo32(obj, 0x0c, flags2); + + obj->engine = NVOBJ_ENGINE_SW; + obj->class = class; + *pobj = obj; + return 0; } /* Context objects in the instance RAM have the following structure. @@ -495,82 +598,122 @@ entry[5]: set to 0? */ +static int +nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, + struct nouveau_gpuobj **gpuobj_ret) +{ + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; + struct nouveau_gpuobj *gpuobj; + + gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); + if (!gpuobj) + return -ENOMEM; + gpuobj->dev = chan->dev; + gpuobj->engine = NVOBJ_ENGINE_SW; + gpuobj->class = class; + kref_init(&gpuobj->refcount); + gpuobj->cinst = 0x40; + + spin_lock(&dev_priv->ramin_lock); + list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); + spin_unlock(&dev_priv->ramin_lock); + *gpuobj_ret = gpuobj; + return 0; +} + int -nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class, - struct nouveau_gpuobj **gpuobj) +nouveau_gpuobj_gr_new(struct nouveau_channel *chan, u32 handle, int class) { + struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj_class *oc; + struct nouveau_gpuobj *gpuobj; int ret; NV_DEBUG(dev, "ch%d class=0x%04x\n", chan->id, class); + list_for_each_entry(oc, &dev_priv->classes, head) { + if (oc->id == class) + goto found; + } + + NV_ERROR(dev, "illegal object class: 0x%x\n", class); + return -EINVAL; + +found: + switch (oc->engine) { + case NVOBJ_ENGINE_SW: + ret = nouveau_gpuobj_sw_new(chan, class, &gpuobj); + if (ret) + return ret; + goto insert; + case NVOBJ_ENGINE_GR: + if (dev_priv->card_type >= NV_50 && !chan->ramin_grctx) { + struct nouveau_pgraph_engine *pgraph = + &dev_priv->engine.graph; + + ret = pgraph->create_context(chan); + if (ret) + return ret; + } + break; + case NVOBJ_ENGINE_CRYPT: + if (!chan->crypt_ctx) { + struct nouveau_crypt_engine *pcrypt = + &dev_priv->engine.crypt; + + ret = pcrypt->create_context(chan); + if (ret) + return ret; + } + break; + } + ret = nouveau_gpuobj_new(dev, chan, nouveau_gpuobj_class_instmem_size(dev, class), 16, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, - gpuobj); + &gpuobj); if (ret) { - NV_ERROR(dev, "Error creating gpuobj: %d\n", ret); + NV_ERROR(dev, "error creating gpuobj: %d\n", ret); return ret; } if (dev_priv->card_type >= NV_50) { - nv_wo32(*gpuobj, 0, class); - nv_wo32(*gpuobj, 20, 0x00010000); + nv_wo32(gpuobj, 0, class); + nv_wo32(gpuobj, 20, 0x00010000); } else { switch (class) { case NV_CLASS_NULL: - nv_wo32(*gpuobj, 0, 0x00001030); - nv_wo32(*gpuobj, 4, 0xFFFFFFFF); + nv_wo32(gpuobj, 0, 0x00001030); + nv_wo32(gpuobj, 4, 0xFFFFFFFF); break; default: if (dev_priv->card_type >= NV_40) { - nv_wo32(*gpuobj, 0, class); + nv_wo32(gpuobj, 0, class); #ifdef __BIG_ENDIAN - nv_wo32(*gpuobj, 8, 0x01000000); + nv_wo32(gpuobj, 8, 0x01000000); #endif } else { #ifdef __BIG_ENDIAN - nv_wo32(*gpuobj, 0, class | 0x00080000); + nv_wo32(gpuobj, 0, class | 0x00080000); #else - nv_wo32(*gpuobj, 0, class); + nv_wo32(gpuobj, 0, class); #endif } } } dev_priv->engine.instmem.flush(dev); - (*gpuobj)->engine = NVOBJ_ENGINE_GR; - (*gpuobj)->class = class; - return 0; -} - -int -nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, - struct nouveau_gpuobj **gpuobj_ret) -{ - struct drm_nouveau_private *dev_priv; - struct nouveau_gpuobj *gpuobj; - - if (!chan || !gpuobj_ret || *gpuobj_ret != NULL) - return -EINVAL; - dev_priv = chan->dev->dev_private; - - gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); - if (!gpuobj) - return -ENOMEM; - gpuobj->dev = chan->dev; - gpuobj->engine = NVOBJ_ENGINE_SW; - gpuobj->class = class; - kref_init(&gpuobj->refcount); - gpuobj->cinst = 0x40; + gpuobj->engine = oc->engine; + gpuobj->class = oc->id; - spin_lock(&dev_priv->ramin_lock); - list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list); - spin_unlock(&dev_priv->ramin_lock); - *gpuobj_ret = gpuobj; - return 0; +insert: + ret = nouveau_ramht_insert(chan, handle, gpuobj); + if (ret) + NV_ERROR(dev, "error adding gpuobj to RAMHT: %d\n", ret); + nouveau_gpuobj_ref(NULL, &gpuobj); + return ret; } static int @@ -585,7 +728,7 @@ NV_DEBUG(dev, "ch%d\n", chan->id); /* Base amount for object storage (4KiB enough?) */ - size = 0x1000; + size = 0x2000; base = 0; /* PGRAPH context */ @@ -624,9 +767,8 @@ { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; struct nouveau_gpuobj *vram = NULL, *tt = NULL; - int ret, i; + int ret; NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h); @@ -637,16 +779,14 @@ return ret; } - /* NV50 VM + /* NV50/NVC0 VM * - Allocate per-channel page-directory - * - Map GART and VRAM into the channel's address space at the - * locations determined during init. + * - Link with shared channel VM */ - if (dev_priv->card_type >= NV_50) { + if (dev_priv->chan_vm) { u32 pgd_offs = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; u64 vm_vinst = chan->ramin->vinst + pgd_offs; u32 vm_pinst = chan->ramin->pinst; - u32 pde; if (vm_pinst != ~0) vm_pinst += pgd_offs; @@ -655,29 +795,8 @@ 0, &chan->vm_pd); if (ret) return ret; - for (i = 0; i < 0x4000; i += 8) { - nv_wo32(chan->vm_pd, i + 0, 0x00000000); - nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe); - } - - nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, - &chan->vm_gart_pt); - pde = (dev_priv->vm_gart_base / (512*1024*1024)) * 8; - nv_wo32(chan->vm_pd, pde + 0, chan->vm_gart_pt->vinst | 3); - nv_wo32(chan->vm_pd, pde + 4, 0x00000000); - - pde = (dev_priv->vm_vram_base / (512*1024*1024)) * 8; - for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { - nouveau_gpuobj_ref(dev_priv->vm_vram_pt[i], - &chan->vm_vram_pt[i]); - - nv_wo32(chan->vm_pd, pde + 0, - chan->vm_vram_pt[i]->vinst | 0x61); - nv_wo32(chan->vm_pd, pde + 4, 0x00000000); - pde += 8; - } - instmem->flush(dev); + nouveau_vm_ref(dev_priv->chan_vm, &chan->vm, chan->vm_pd); } /* RAMHT */ @@ -700,9 +819,8 @@ /* VRAM ctxdma */ if (dev_priv->card_type >= NV_50) { ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - 0, dev_priv->vm_end, - NV_DMA_ACCESS_RW, - NV_DMA_TARGET_AGP, &vram); + 0, (1ULL << 40), NV_MEM_ACCESS_RW, + NV_MEM_TARGET_VM, &vram); if (ret) { NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); return ret; @@ -710,8 +828,8 @@ } else { ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0, dev_priv->fb_available_size, - NV_DMA_ACCESS_RW, - NV_DMA_TARGET_VIDMEM, &vram); + NV_MEM_ACCESS_RW, + NV_MEM_TARGET_VRAM, &vram); if (ret) { NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); return ret; @@ -728,21 +846,13 @@ /* TT memory ctxdma */ if (dev_priv->card_type >= NV_50) { ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, - 0, dev_priv->vm_end, - NV_DMA_ACCESS_RW, - NV_DMA_TARGET_AGP, &tt); - if (ret) { - NV_ERROR(dev, "Error creating VRAM ctxdma: %d\n", ret); - return ret; - } - } else - if (dev_priv->gart_info.type != NOUVEAU_GART_NONE) { - ret = nouveau_gpuobj_gart_dma_new(chan, 0, - dev_priv->gart_info.aper_size, - NV_DMA_ACCESS_RW, &tt, NULL); + 0, (1ULL << 40), NV_MEM_ACCESS_RW, + NV_MEM_TARGET_VM, &tt); } else { - NV_ERROR(dev, "Invalid GART type %d\n", dev_priv->gart_info.type); - ret = -EINVAL; + ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, + 0, dev_priv->gart_info.aper_size, + NV_MEM_ACCESS_RW, + NV_MEM_TARGET_GART, &tt); } if (ret) { @@ -763,9 +873,7 @@ void nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) { - struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct drm_device *dev = chan->dev; - int i; NV_DEBUG(dev, "ch%d\n", chan->id); @@ -774,10 +882,8 @@ nouveau_ramht_ref(NULL, &chan->ramht, chan); + nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); nouveau_gpuobj_ref(NULL, &chan->vm_pd); - nouveau_gpuobj_ref(NULL, &chan->vm_gart_pt); - for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) - nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]); if (chan->ramin_heap.free_stack.next) drm_mm_takedown(&chan->ramin_heap); @@ -791,147 +897,91 @@ struct nouveau_gpuobj *gpuobj; int i; - if (dev_priv->card_type < NV_50) { - dev_priv->susres.ramin_copy = vmalloc(dev_priv->ramin_rsvd_vram); - if (!dev_priv->susres.ramin_copy) - return -ENOMEM; - - for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4) - dev_priv->susres.ramin_copy[i/4] = nv_ri32(dev, i); - return 0; - } - list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { - if (!gpuobj->im_backing) + if (gpuobj->cinst != NVOBJ_CINST_GLOBAL) continue; - gpuobj->im_backing_suspend = vmalloc(gpuobj->size); - if (!gpuobj->im_backing_suspend) { + gpuobj->suspend = vmalloc(gpuobj->size); + if (!gpuobj->suspend) { nouveau_gpuobj_resume(dev); return -ENOMEM; } for (i = 0; i < gpuobj->size; i += 4) - gpuobj->im_backing_suspend[i/4] = nv_ro32(gpuobj, i); + gpuobj->suspend[i/4] = nv_ro32(gpuobj, i); } return 0; } void -nouveau_gpuobj_suspend_cleanup(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *gpuobj; - - if (dev_priv->card_type < NV_50) { - vfree(dev_priv->susres.ramin_copy); - dev_priv->susres.ramin_copy = NULL; - return; - } - - list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { - if (!gpuobj->im_backing_suspend) - continue; - - vfree(gpuobj->im_backing_suspend); - gpuobj->im_backing_suspend = NULL; - } -} - -void nouveau_gpuobj_resume(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *gpuobj; int i; - if (dev_priv->card_type < NV_50) { - for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4) - nv_wi32(dev, i, dev_priv->susres.ramin_copy[i/4]); - nouveau_gpuobj_suspend_cleanup(dev); - return; - } - list_for_each_entry(gpuobj, &dev_priv->gpuobj_list, list) { - if (!gpuobj->im_backing_suspend) + if (!gpuobj->suspend) continue; for (i = 0; i < gpuobj->size; i += 4) - nv_wo32(gpuobj, i, gpuobj->im_backing_suspend[i/4]); - dev_priv->engine.instmem.flush(dev); + nv_wo32(gpuobj, i, gpuobj->suspend[i/4]); + + vfree(gpuobj->suspend); + gpuobj->suspend = NULL; } - nouveau_gpuobj_suspend_cleanup(dev); + dev_priv->engine.instmem.flush(dev); } int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_grobj_alloc *init = data; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct nouveau_pgraph_object_class *grc; - struct nouveau_gpuobj *gr = NULL; struct nouveau_channel *chan; int ret; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan); - if (init->handle == ~0) return -EINVAL; - grc = pgraph->grclass; - while (grc->id) { - if (grc->id == init->class) - break; - grc++; - } + chan = nouveau_channel_get(dev, file_priv, init->channel); + if (IS_ERR(chan)) + return PTR_ERR(chan); - if (!grc->id) { - NV_ERROR(dev, "Illegal object class: 0x%x\n", init->class); - return -EPERM; + if (nouveau_ramht_find(chan, init->handle)) { + ret = -EEXIST; + goto out; } - if (nouveau_ramht_find(chan, init->handle)) - return -EEXIST; - - if (!grc->software) - ret = nouveau_gpuobj_gr_new(chan, grc->id, &gr); - else - ret = nouveau_gpuobj_sw_new(chan, grc->id, &gr); + ret = nouveau_gpuobj_gr_new(chan, init->handle, init->class); if (ret) { NV_ERROR(dev, "Error creating object: %d (%d/0x%08x)\n", ret, init->channel, init->handle); - return ret; - } - - ret = nouveau_ramht_insert(chan, init->handle, gr); - nouveau_gpuobj_ref(NULL, &gr); - if (ret) { - NV_ERROR(dev, "Error referencing object: %d (%d/0x%08x)\n", - ret, init->channel, init->handle); - return ret; } - return 0; +out: + nouveau_channel_put(&chan); + return ret; } int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_nouveau_gpuobj_free *objfree = data; - struct nouveau_gpuobj *gpuobj; struct nouveau_channel *chan; + int ret; - NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan); + chan = nouveau_channel_get(dev, file_priv, objfree->channel); + if (IS_ERR(chan)) + return PTR_ERR(chan); - gpuobj = nouveau_ramht_find(chan, objfree->handle); - if (!gpuobj) - return -ENOENT; + /* Synchronize with the user channel */ + nouveau_channel_idle(chan); - nouveau_ramht_remove(chan, objfree->handle); - return 0; + ret = nouveau_ramht_remove(chan, objfree->handle); + nouveau_channel_put(&chan); + return ret; } u32 --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_pm.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -27,6 +27,10 @@ #include "nouveau_drv.h" #include "nouveau_pm.h" +#ifdef CONFIG_ACPI +#include +#endif +#include #include #include @@ -446,6 +450,25 @@ #endif } +#ifdef CONFIG_ACPI +static int +nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data) +{ + struct drm_nouveau_private *dev_priv = + container_of(nb, struct drm_nouveau_private, engine.pm.acpi_nb); + struct drm_device *dev = dev_priv->dev; + struct acpi_bus_event *entry = (struct acpi_bus_event *)data; + + if (strcmp(entry->device_class, "ac_adapter") == 0) { + bool ac = power_supply_is_system_supplied(); + + NV_DEBUG(dev, "power supply changed: %s\n", ac ? "AC" : "DC"); + } + + return NOTIFY_OK; +} +#endif + int nouveau_pm_init(struct drm_device *dev) { @@ -485,6 +508,10 @@ nouveau_sysfs_init(dev); nouveau_hwmon_init(dev); +#ifdef CONFIG_ACPI + pm->acpi_nb.notifier_call = nouveau_pm_acpi_event; + register_acpi_notifier(&pm->acpi_nb); +#endif return 0; } @@ -503,6 +530,9 @@ nouveau_perf_fini(dev); nouveau_volt_fini(dev); +#ifdef CONFIG_ACPI + unregister_acpi_notifier(&pm->acpi_nb); +#endif nouveau_hwmon_fini(dev); nouveau_sysfs_fini(dev); } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_ramht.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_ramht.c @@ -104,17 +104,17 @@ nouveau_gpuobj_ref(gpuobj, &entry->gpuobj); if (dev_priv->card_type < NV_40) { - ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->cinst >> 4) | + ctx = NV_RAMHT_CONTEXT_VALID | (gpuobj->pinst >> 4) | (chan->id << NV_RAMHT_CONTEXT_CHANNEL_SHIFT) | (gpuobj->engine << NV_RAMHT_CONTEXT_ENGINE_SHIFT); } else if (dev_priv->card_type < NV_50) { - ctx = (gpuobj->cinst >> 4) | + ctx = (gpuobj->pinst >> 4) | (chan->id << NV40_RAMHT_CONTEXT_CHANNEL_SHIFT) | (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT); } else { if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) { - ctx = (gpuobj->cinst << 10) | 2; + ctx = (gpuobj->cinst << 10) | chan->id; } else { ctx = (gpuobj->cinst >> 4) | ((gpuobj->engine << @@ -214,18 +214,19 @@ spin_unlock_irqrestore(&chan->ramht->lock, flags); } -void +int nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle) { struct nouveau_ramht_entry *entry; entry = nouveau_ramht_remove_entry(chan, handle); if (!entry) - return; + return -ENOENT; nouveau_ramht_remove_hash(chan, entry->handle); nouveau_gpuobj_ref(NULL, &entry->gpuobj); kfree(entry); + return 0; } struct nouveau_gpuobj * --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_ramht.h +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_ramht.h @@ -48,7 +48,7 @@ extern int nouveau_ramht_insert(struct nouveau_channel *, u32 handle, struct nouveau_gpuobj *); -extern void nouveau_ramht_remove(struct nouveau_channel *, u32 handle); +extern int nouveau_ramht_remove(struct nouveau_channel *, u32 handle); extern struct nouveau_gpuobj * nouveau_ramht_find(struct nouveau_channel *chan, u32 handle); --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_reg.h +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_reg.h @@ -45,6 +45,11 @@ # define NV04_PFB_REF_CMD_REFRESH (1 << 0) #define NV04_PFB_PRE 0x001002d4 # define NV04_PFB_PRE_CMD_PRECHARGE (1 << 0) +#define NV20_PFB_ZCOMP(i) (0x00100300 + 4*(i)) +# define NV20_PFB_ZCOMP_MODE_32 (4 << 24) +# define NV20_PFB_ZCOMP_EN (1 << 31) +# define NV25_PFB_ZCOMP_MODE_16 (1 << 20) +# define NV25_PFB_ZCOMP_MODE_32 (2 << 20) #define NV10_PFB_CLOSE_PAGE2 0x0010033c #define NV04_PFB_SCRAMBLE(i) (0x00100400 + 4 * (i)) #define NV40_PFB_TILE(i) (0x00100600 + (i*16)) @@ -74,17 +79,6 @@ # define NV40_RAMHT_CONTEXT_ENGINE_SHIFT 20 # define NV40_RAMHT_CONTEXT_INSTANCE_SHIFT 0 -/* DMA object defines */ -#define NV_DMA_ACCESS_RW 0 -#define NV_DMA_ACCESS_RO 1 -#define NV_DMA_ACCESS_WO 2 -#define NV_DMA_TARGET_VIDMEM 0 -#define NV_DMA_TARGET_PCI 2 -#define NV_DMA_TARGET_AGP 3 -/* The following is not a real value used by the card, it's changed by - * nouveau_object_dma_create */ -#define NV_DMA_TARGET_PCI_NONLINEAR 8 - /* Some object classes we care about in the drm */ #define NV_CLASS_DMA_FROM_MEMORY 0x00000002 #define NV_CLASS_DMA_TO_MEMORY 0x00000003 @@ -332,6 +326,7 @@ #define NV04_PGRAPH_BSWIZZLE5 0x004006A0 #define NV03_PGRAPH_STATUS 0x004006B0 #define NV04_PGRAPH_STATUS 0x00400700 +# define NV40_PGRAPH_STATUS_SYNC_STALL 0x00004000 #define NV04_PGRAPH_TRAPPED_ADDR 0x00400704 #define NV04_PGRAPH_TRAPPED_DATA 0x00400708 #define NV04_PGRAPH_SURFACE 0x0040070C @@ -378,6 +373,7 @@ #define NV20_PGRAPH_TLIMIT(i) (0x00400904 + (i*16)) #define NV20_PGRAPH_TSIZE(i) (0x00400908 + (i*16)) #define NV20_PGRAPH_TSTATUS(i) (0x0040090C + (i*16)) +#define NV20_PGRAPH_ZCOMP(i) (0x00400980 + 4*(i)) #define NV10_PGRAPH_TILE(i) (0x00400B00 + (i*16)) #define NV10_PGRAPH_TLIMIT(i) (0x00400B04 + (i*16)) #define NV10_PGRAPH_TSIZE(i) (0x00400B08 + (i*16)) @@ -714,31 +710,32 @@ #define NV50_PDISPLAY_INTR_1_CLK_UNK10 0x00000010 #define NV50_PDISPLAY_INTR_1_CLK_UNK20 0x00000020 #define NV50_PDISPLAY_INTR_1_CLK_UNK40 0x00000040 -#define NV50_PDISPLAY_INTR_EN 0x0061002c -#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC 0x0000000c -#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(n) (1 << ((n) + 2)) -#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_0 0x00000004 -#define NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_1 0x00000008 -#define NV50_PDISPLAY_INTR_EN_CLK_UNK10 0x00000010 -#define NV50_PDISPLAY_INTR_EN_CLK_UNK20 0x00000020 -#define NV50_PDISPLAY_INTR_EN_CLK_UNK40 0x00000040 +#define NV50_PDISPLAY_INTR_EN_0 0x00610028 +#define NV50_PDISPLAY_INTR_EN_1 0x0061002c +#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC 0x0000000c +#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(n) (1 << ((n) + 2)) +#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_0 0x00000004 +#define NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_1 0x00000008 +#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 0x00000010 +#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 0x00000020 +#define NV50_PDISPLAY_INTR_EN_1_CLK_UNK40 0x00000040 #define NV50_PDISPLAY_UNK30_CTRL 0x00610030 #define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0 0x00000200 #define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1 0x00000400 #define NV50_PDISPLAY_UNK30_CTRL_PENDING 0x80000000 -#define NV50_PDISPLAY_TRAPPED_ADDR 0x00610080 -#define NV50_PDISPLAY_TRAPPED_DATA 0x00610084 -#define NV50_PDISPLAY_CHANNEL_STAT(i) ((i) * 0x10 + 0x00610200) -#define NV50_PDISPLAY_CHANNEL_STAT_DMA 0x00000010 -#define NV50_PDISPLAY_CHANNEL_STAT_DMA_DISABLED 0x00000000 -#define NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED 0x00000010 -#define NV50_PDISPLAY_CHANNEL_DMA_CB(i) ((i) * 0x10 + 0x00610204) -#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION 0x00000002 -#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM 0x00000000 -#define NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_SYSTEM 0x00000002 -#define NV50_PDISPLAY_CHANNEL_DMA_CB_VALID 0x00000001 -#define NV50_PDISPLAY_CHANNEL_UNK2(i) ((i) * 0x10 + 0x00610208) -#define NV50_PDISPLAY_CHANNEL_UNK3(i) ((i) * 0x10 + 0x0061020c) +#define NV50_PDISPLAY_TRAPPED_ADDR(i) ((i) * 0x08 + 0x00610080) +#define NV50_PDISPLAY_TRAPPED_DATA(i) ((i) * 0x08 + 0x00610084) +#define NV50_PDISPLAY_EVO_CTRL(i) ((i) * 0x10 + 0x00610200) +#define NV50_PDISPLAY_EVO_CTRL_DMA 0x00000010 +#define NV50_PDISPLAY_EVO_CTRL_DMA_DISABLED 0x00000000 +#define NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED 0x00000010 +#define NV50_PDISPLAY_EVO_DMA_CB(i) ((i) * 0x10 + 0x00610204) +#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION 0x00000002 +#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM 0x00000000 +#define NV50_PDISPLAY_EVO_DMA_CB_LOCATION_SYSTEM 0x00000002 +#define NV50_PDISPLAY_EVO_DMA_CB_VALID 0x00000001 +#define NV50_PDISPLAY_EVO_UNK2(i) ((i) * 0x10 + 0x00610208) +#define NV50_PDISPLAY_EVO_HASH_TAG(i) ((i) * 0x10 + 0x0061020c) #define NV50_PDISPLAY_CURSOR 0x00610270 #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i) ((i) * 0x10 + 0x00610270) @@ -746,15 +743,11 @@ #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS 0x00030000 #define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE 0x00010000 -#define NV50_PDISPLAY_CTRL_STATE 0x00610300 -#define NV50_PDISPLAY_CTRL_STATE_PENDING 0x80000000 -#define NV50_PDISPLAY_CTRL_STATE_METHOD 0x00001ffc -#define NV50_PDISPLAY_CTRL_STATE_ENABLE 0x00000001 -#define NV50_PDISPLAY_CTRL_VAL 0x00610304 -#define NV50_PDISPLAY_UNK_380 0x00610380 -#define NV50_PDISPLAY_RAM_AMOUNT 0x00610384 -#define NV50_PDISPLAY_UNK_388 0x00610388 -#define NV50_PDISPLAY_UNK_38C 0x0061038c +#define NV50_PDISPLAY_PIO_CTRL 0x00610300 +#define NV50_PDISPLAY_PIO_CTRL_PENDING 0x80000000 +#define NV50_PDISPLAY_PIO_CTRL_MTHD 0x00001ffc +#define NV50_PDISPLAY_PIO_CTRL_ENABLED 0x00000001 +#define NV50_PDISPLAY_PIO_DATA 0x00610304 #define NV50_PDISPLAY_CRTC_P(i, r) ((i) * 0x540 + NV50_PDISPLAY_CRTC_##r) #define NV50_PDISPLAY_CRTC_C(i, r) (4 + (i) * 0x540 + NV50_PDISPLAY_CRTC_##r) --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -14,7 +14,7 @@ dma_addr_t *pages; unsigned nr_pages; - unsigned pte_start; + u64 offset; bool bound; }; @@ -74,18 +74,6 @@ } } -static inline unsigned -nouveau_sgdma_pte(struct drm_device *dev, uint64_t offset) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - unsigned pte = (offset >> NV_CTXDMA_PAGE_SHIFT); - - if (dev_priv->card_type < NV_50) - return pte + 2; - - return pte << 1; -} - static int nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) { @@ -97,32 +85,17 @@ NV_DEBUG(dev, "pg=0x%lx\n", mem->start); - pte = nouveau_sgdma_pte(nvbe->dev, mem->start << PAGE_SHIFT); - nvbe->pte_start = pte; + nvbe->offset = mem->start << PAGE_SHIFT; + pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2; for (i = 0; i < nvbe->nr_pages; i++) { dma_addr_t dma_offset = nvbe->pages[i]; uint32_t offset_l = lower_32_bits(dma_offset); - uint32_t offset_h = upper_32_bits(dma_offset); - - for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { - if (dev_priv->card_type < NV_50) { - nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3); - pte += 1; - } else { - nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 0x21); - nv_wo32(gpuobj, (pte * 4) + 4, offset_h & 0xff); - pte += 2; - } + for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) { + nv_wo32(gpuobj, (pte * 4) + 0, offset_l | 3); dma_offset += NV_CTXDMA_PAGE_SIZE; } } - dev_priv->engine.instmem.flush(nvbe->dev); - - if (dev_priv->card_type == NV_50) { - dev_priv->engine.fifo.tlb_flush(dev); - dev_priv->engine.graph.tlb_flush(dev); - } nvbe->bound = true; return 0; @@ -142,28 +115,10 @@ if (!nvbe->bound) return 0; - pte = nvbe->pte_start; + pte = (nvbe->offset >> NV_CTXDMA_PAGE_SHIFT) + 2; for (i = 0; i < nvbe->nr_pages; i++) { - dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus; - - for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++) { - if (dev_priv->card_type < NV_50) { - nv_wo32(gpuobj, (pte * 4) + 0, dma_offset | 3); - pte += 1; - } else { - nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000); - nv_wo32(gpuobj, (pte * 4) + 4, 0x00000000); - pte += 2; - } - - dma_offset += NV_CTXDMA_PAGE_SIZE; - } - } - dev_priv->engine.instmem.flush(nvbe->dev); - - if (dev_priv->card_type == NV_50) { - dev_priv->engine.fifo.tlb_flush(dev); - dev_priv->engine.graph.tlb_flush(dev); + for (j = 0; j < PAGE_SIZE / NV_CTXDMA_PAGE_SIZE; j++, pte++) + nv_wo32(gpuobj, (pte * 4) + 0, 0x00000000); } nvbe->bound = false; @@ -186,6 +141,35 @@ } } +static int +nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) +{ + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + + nvbe->offset = mem->start << PAGE_SHIFT; + + nouveau_vm_map_sg(&dev_priv->gart_info.vma, nvbe->offset, + nvbe->nr_pages << PAGE_SHIFT, nvbe->pages); + nvbe->bound = true; + return 0; +} + +static int +nv50_sgdma_unbind(struct ttm_backend *be) +{ + struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; + struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private; + + if (!nvbe->bound) + return 0; + + nouveau_vm_unmap_at(&dev_priv->gart_info.vma, nvbe->offset, + nvbe->nr_pages << PAGE_SHIFT); + nvbe->bound = false; + return 0; +} + static struct ttm_backend_func nouveau_sgdma_backend = { .populate = nouveau_sgdma_populate, .clear = nouveau_sgdma_clear, @@ -194,23 +178,30 @@ .destroy = nouveau_sgdma_destroy }; +static struct ttm_backend_func nv50_sgdma_backend = { + .populate = nouveau_sgdma_populate, + .clear = nouveau_sgdma_clear, + .bind = nv50_sgdma_bind, + .unbind = nv50_sgdma_unbind, + .destroy = nouveau_sgdma_destroy +}; + struct ttm_backend * nouveau_sgdma_init_ttm(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_sgdma_be *nvbe; - if (!dev_priv->gart_info.sg_ctxdma) - return NULL; - nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL); if (!nvbe) return NULL; nvbe->dev = dev; - nvbe->backend.func = &nouveau_sgdma_backend; - + if (dev_priv->card_type < NV_50) + nvbe->backend.func = &nouveau_sgdma_backend; + else + nvbe->backend.func = &nv50_sgdma_backend; return &nvbe->backend; } @@ -218,7 +209,6 @@ nouveau_sgdma_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct pci_dev *pdev = dev->pdev; struct nouveau_gpuobj *gpuobj = NULL; uint32_t aper_size, obj_size; int i, ret; @@ -231,68 +221,40 @@ obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; obj_size += 8; /* ctxdma header */ - } else { - /* 1 entire VM page table */ - aper_size = (512 * 1024 * 1024); - obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 8; - } - - ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, - NVOBJ_FLAG_ZERO_ALLOC | - NVOBJ_FLAG_ZERO_FREE, &gpuobj); - if (ret) { - NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); - return ret; - } - dev_priv->gart_info.sg_dummy_page = - alloc_page(GFP_KERNEL|__GFP_DMA32|__GFP_ZERO); - if (!dev_priv->gart_info.sg_dummy_page) { - nouveau_gpuobj_ref(NULL, &gpuobj); - return -ENOMEM; - } - - set_bit(PG_locked, &dev_priv->gart_info.sg_dummy_page->flags); - dev_priv->gart_info.sg_dummy_bus = - pci_map_page(pdev, dev_priv->gart_info.sg_dummy_page, 0, - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(pdev, dev_priv->gart_info.sg_dummy_bus)) { - nouveau_gpuobj_ref(NULL, &gpuobj); - return -EFAULT; - } + ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16, + NVOBJ_FLAG_ZERO_ALLOC | + NVOBJ_FLAG_ZERO_FREE, &gpuobj); + if (ret) { + NV_ERROR(dev, "Error creating sgdma object: %d\n", ret); + return ret; + } - if (dev_priv->card_type < NV_50) { - /* special case, allocated from global instmem heap so - * cinst is invalid, we use it on all channels though so - * cinst needs to be valid, set it the same as pinst - */ - gpuobj->cinst = gpuobj->pinst; - - /* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and - * confirmed to work on c51. Perhaps means NV_DMA_TARGET_PCIE - * on those cards? */ nv_wo32(gpuobj, 0, NV_CLASS_DMA_IN_MEMORY | (1 << 12) /* PT present */ | (0 << 13) /* PT *not* linear */ | - (NV_DMA_ACCESS_RW << 14) | - (NV_DMA_TARGET_PCI << 16)); + (0 << 14) /* RW */ | + (2 << 16) /* PCI */); nv_wo32(gpuobj, 4, aper_size - 1); - for (i = 2; i < 2 + (aper_size >> 12); i++) { - nv_wo32(gpuobj, i * 4, - dev_priv->gart_info.sg_dummy_bus | 3); - } - } else { - for (i = 0; i < obj_size; i += 8) { - nv_wo32(gpuobj, i + 0, 0x00000000); - nv_wo32(gpuobj, i + 4, 0x00000000); - } + for (i = 2; i < 2 + (aper_size >> 12); i++) + nv_wo32(gpuobj, i * 4, 0x00000000); + + dev_priv->gart_info.sg_ctxdma = gpuobj; + dev_priv->gart_info.aper_base = 0; + dev_priv->gart_info.aper_size = aper_size; + } else + if (dev_priv->chan_vm) { + ret = nouveau_vm_get(dev_priv->chan_vm, 512 * 1024 * 1024, + 12, NV_MEM_ACCESS_RW, + &dev_priv->gart_info.vma); + if (ret) + return ret; + + dev_priv->gart_info.aper_base = dev_priv->gart_info.vma.offset; + dev_priv->gart_info.aper_size = 512 * 1024 * 1024; } - dev_priv->engine.instmem.flush(dev); dev_priv->gart_info.type = NOUVEAU_GART_SGDMA; - dev_priv->gart_info.aper_base = 0; - dev_priv->gart_info.aper_size = aper_size; - dev_priv->gart_info.sg_ctxdma = gpuobj; return 0; } @@ -301,31 +263,19 @@ { struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->gart_info.sg_dummy_page) { - pci_unmap_page(dev->pdev, dev_priv->gart_info.sg_dummy_bus, - NV_CTXDMA_PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - unlock_page(dev_priv->gart_info.sg_dummy_page); - __free_page(dev_priv->gart_info.sg_dummy_page); - dev_priv->gart_info.sg_dummy_page = NULL; - dev_priv->gart_info.sg_dummy_bus = 0; - } - nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma); + nouveau_vm_put(&dev_priv->gart_info.vma); } -int -nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page) +uint32_t +nouveau_sgdma_get_physical(struct drm_device *dev, uint32_t offset) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma; - int pte; + int pte = (offset >> NV_CTXDMA_PAGE_SHIFT) + 2; - pte = (offset >> NV_CTXDMA_PAGE_SHIFT) << 2; - if (dev_priv->card_type < NV_50) { - *page = nv_ro32(gpuobj, (pte + 8)) & ~NV_CTXDMA_PAGE_MASK; - return 0; - } + BUG_ON(dev_priv->card_type >= NV_50); - NV_ERROR(dev, "Unimplemented on NV50\n"); - return -EINVAL; + return (nv_ro32(gpuobj, 4 * pte) & ~NV_CTXDMA_PAGE_MASK) | + (offset & NV_CTXDMA_PAGE_MASK); } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_state.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_state.c @@ -53,10 +53,10 @@ engine->instmem.takedown = nv04_instmem_takedown; engine->instmem.suspend = nv04_instmem_suspend; engine->instmem.resume = nv04_instmem_resume; - engine->instmem.populate = nv04_instmem_populate; - engine->instmem.clear = nv04_instmem_clear; - engine->instmem.bind = nv04_instmem_bind; - engine->instmem.unbind = nv04_instmem_unbind; + engine->instmem.get = nv04_instmem_get; + engine->instmem.put = nv04_instmem_put; + engine->instmem.map = nv04_instmem_map; + engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; engine->mc.init = nv04_mc_init; engine->mc.takedown = nv04_mc_takedown; @@ -65,7 +65,6 @@ engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv04_fb_init; engine->fb.takedown = nv04_fb_takedown; - engine->graph.grclass = nv04_graph_grclass; engine->graph.init = nv04_graph_init; engine->graph.takedown = nv04_graph_takedown; engine->graph.fifo_access = nv04_graph_fifo_access; @@ -76,7 +75,7 @@ engine->graph.unload_context = nv04_graph_unload_context; engine->fifo.channels = 16; engine->fifo.init = nv04_fifo_init; - engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.takedown = nv04_fifo_fini; engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; @@ -99,16 +98,20 @@ engine->pm.clock_get = nv04_pm_clock_get; engine->pm.clock_pre = nv04_pm_clock_pre; engine->pm.clock_set = nv04_pm_clock_set; + engine->crypt.init = nouveau_stub_init; + engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x10: engine->instmem.init = nv04_instmem_init; engine->instmem.takedown = nv04_instmem_takedown; engine->instmem.suspend = nv04_instmem_suspend; engine->instmem.resume = nv04_instmem_resume; - engine->instmem.populate = nv04_instmem_populate; - engine->instmem.clear = nv04_instmem_clear; - engine->instmem.bind = nv04_instmem_bind; - engine->instmem.unbind = nv04_instmem_unbind; + engine->instmem.get = nv04_instmem_get; + engine->instmem.put = nv04_instmem_put; + engine->instmem.map = nv04_instmem_map; + engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; engine->mc.init = nv04_mc_init; engine->mc.takedown = nv04_mc_takedown; @@ -117,8 +120,9 @@ engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv10_fb_init; engine->fb.takedown = nv10_fb_takedown; - engine->fb.set_region_tiling = nv10_fb_set_region_tiling; - engine->graph.grclass = nv10_graph_grclass; + engine->fb.init_tile_region = nv10_fb_init_tile_region; + engine->fb.set_tile_region = nv10_fb_set_tile_region; + engine->fb.free_tile_region = nv10_fb_free_tile_region; engine->graph.init = nv10_graph_init; engine->graph.takedown = nv10_graph_takedown; engine->graph.channel = nv10_graph_channel; @@ -127,17 +131,17 @@ engine->graph.fifo_access = nv04_graph_fifo_access; engine->graph.load_context = nv10_graph_load_context; engine->graph.unload_context = nv10_graph_unload_context; - engine->graph.set_region_tiling = nv10_graph_set_region_tiling; + engine->graph.set_tile_region = nv10_graph_set_tile_region; engine->fifo.channels = 32; engine->fifo.init = nv10_fifo_init; - engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.takedown = nv04_fifo_fini; engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; - engine->fifo.destroy_context = nv10_fifo_destroy_context; + engine->fifo.destroy_context = nv04_fifo_destroy_context; engine->fifo.load_context = nv10_fifo_load_context; engine->fifo.unload_context = nv10_fifo_unload_context; engine->display.early_init = nv04_display_early_init; @@ -153,16 +157,20 @@ engine->pm.clock_get = nv04_pm_clock_get; engine->pm.clock_pre = nv04_pm_clock_pre; engine->pm.clock_set = nv04_pm_clock_set; + engine->crypt.init = nouveau_stub_init; + engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x20: engine->instmem.init = nv04_instmem_init; engine->instmem.takedown = nv04_instmem_takedown; engine->instmem.suspend = nv04_instmem_suspend; engine->instmem.resume = nv04_instmem_resume; - engine->instmem.populate = nv04_instmem_populate; - engine->instmem.clear = nv04_instmem_clear; - engine->instmem.bind = nv04_instmem_bind; - engine->instmem.unbind = nv04_instmem_unbind; + engine->instmem.get = nv04_instmem_get; + engine->instmem.put = nv04_instmem_put; + engine->instmem.map = nv04_instmem_map; + engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; engine->mc.init = nv04_mc_init; engine->mc.takedown = nv04_mc_takedown; @@ -171,8 +179,9 @@ engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv10_fb_init; engine->fb.takedown = nv10_fb_takedown; - engine->fb.set_region_tiling = nv10_fb_set_region_tiling; - engine->graph.grclass = nv20_graph_grclass; + engine->fb.init_tile_region = nv10_fb_init_tile_region; + engine->fb.set_tile_region = nv10_fb_set_tile_region; + engine->fb.free_tile_region = nv10_fb_free_tile_region; engine->graph.init = nv20_graph_init; engine->graph.takedown = nv20_graph_takedown; engine->graph.channel = nv10_graph_channel; @@ -181,17 +190,17 @@ engine->graph.fifo_access = nv04_graph_fifo_access; engine->graph.load_context = nv20_graph_load_context; engine->graph.unload_context = nv20_graph_unload_context; - engine->graph.set_region_tiling = nv20_graph_set_region_tiling; + engine->graph.set_tile_region = nv20_graph_set_tile_region; engine->fifo.channels = 32; engine->fifo.init = nv10_fifo_init; - engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.takedown = nv04_fifo_fini; engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; - engine->fifo.destroy_context = nv10_fifo_destroy_context; + engine->fifo.destroy_context = nv04_fifo_destroy_context; engine->fifo.load_context = nv10_fifo_load_context; engine->fifo.unload_context = nv10_fifo_unload_context; engine->display.early_init = nv04_display_early_init; @@ -207,16 +216,20 @@ engine->pm.clock_get = nv04_pm_clock_get; engine->pm.clock_pre = nv04_pm_clock_pre; engine->pm.clock_set = nv04_pm_clock_set; + engine->crypt.init = nouveau_stub_init; + engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x30: engine->instmem.init = nv04_instmem_init; engine->instmem.takedown = nv04_instmem_takedown; engine->instmem.suspend = nv04_instmem_suspend; engine->instmem.resume = nv04_instmem_resume; - engine->instmem.populate = nv04_instmem_populate; - engine->instmem.clear = nv04_instmem_clear; - engine->instmem.bind = nv04_instmem_bind; - engine->instmem.unbind = nv04_instmem_unbind; + engine->instmem.get = nv04_instmem_get; + engine->instmem.put = nv04_instmem_put; + engine->instmem.map = nv04_instmem_map; + engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; engine->mc.init = nv04_mc_init; engine->mc.takedown = nv04_mc_takedown; @@ -225,8 +238,9 @@ engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv30_fb_init; engine->fb.takedown = nv30_fb_takedown; - engine->fb.set_region_tiling = nv10_fb_set_region_tiling; - engine->graph.grclass = nv30_graph_grclass; + engine->fb.init_tile_region = nv30_fb_init_tile_region; + engine->fb.set_tile_region = nv10_fb_set_tile_region; + engine->fb.free_tile_region = nv30_fb_free_tile_region; engine->graph.init = nv30_graph_init; engine->graph.takedown = nv20_graph_takedown; engine->graph.fifo_access = nv04_graph_fifo_access; @@ -235,17 +249,17 @@ engine->graph.destroy_context = nv20_graph_destroy_context; engine->graph.load_context = nv20_graph_load_context; engine->graph.unload_context = nv20_graph_unload_context; - engine->graph.set_region_tiling = nv20_graph_set_region_tiling; + engine->graph.set_tile_region = nv20_graph_set_tile_region; engine->fifo.channels = 32; engine->fifo.init = nv10_fifo_init; - engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.takedown = nv04_fifo_fini; engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv10_fifo_create_context; - engine->fifo.destroy_context = nv10_fifo_destroy_context; + engine->fifo.destroy_context = nv04_fifo_destroy_context; engine->fifo.load_context = nv10_fifo_load_context; engine->fifo.unload_context = nv10_fifo_unload_context; engine->display.early_init = nv04_display_early_init; @@ -263,6 +277,10 @@ engine->pm.clock_set = nv04_pm_clock_set; engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; + engine->crypt.init = nouveau_stub_init; + engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x40: case 0x60: @@ -270,10 +288,10 @@ engine->instmem.takedown = nv04_instmem_takedown; engine->instmem.suspend = nv04_instmem_suspend; engine->instmem.resume = nv04_instmem_resume; - engine->instmem.populate = nv04_instmem_populate; - engine->instmem.clear = nv04_instmem_clear; - engine->instmem.bind = nv04_instmem_bind; - engine->instmem.unbind = nv04_instmem_unbind; + engine->instmem.get = nv04_instmem_get; + engine->instmem.put = nv04_instmem_put; + engine->instmem.map = nv04_instmem_map; + engine->instmem.unmap = nv04_instmem_unmap; engine->instmem.flush = nv04_instmem_flush; engine->mc.init = nv40_mc_init; engine->mc.takedown = nv40_mc_takedown; @@ -282,8 +300,9 @@ engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv40_fb_init; engine->fb.takedown = nv40_fb_takedown; - engine->fb.set_region_tiling = nv40_fb_set_region_tiling; - engine->graph.grclass = nv40_graph_grclass; + engine->fb.init_tile_region = nv30_fb_init_tile_region; + engine->fb.set_tile_region = nv40_fb_set_tile_region; + engine->fb.free_tile_region = nv30_fb_free_tile_region; engine->graph.init = nv40_graph_init; engine->graph.takedown = nv40_graph_takedown; engine->graph.fifo_access = nv04_graph_fifo_access; @@ -292,17 +311,17 @@ engine->graph.destroy_context = nv40_graph_destroy_context; engine->graph.load_context = nv40_graph_load_context; engine->graph.unload_context = nv40_graph_unload_context; - engine->graph.set_region_tiling = nv40_graph_set_region_tiling; + engine->graph.set_tile_region = nv40_graph_set_tile_region; engine->fifo.channels = 32; engine->fifo.init = nv40_fifo_init; - engine->fifo.takedown = nouveau_stub_takedown; + engine->fifo.takedown = nv04_fifo_fini; engine->fifo.disable = nv04_fifo_disable; engine->fifo.enable = nv04_fifo_enable; engine->fifo.reassign = nv04_fifo_reassign; engine->fifo.cache_pull = nv04_fifo_cache_pull; engine->fifo.channel_id = nv10_fifo_channel_id; engine->fifo.create_context = nv40_fifo_create_context; - engine->fifo.destroy_context = nv40_fifo_destroy_context; + engine->fifo.destroy_context = nv04_fifo_destroy_context; engine->fifo.load_context = nv40_fifo_load_context; engine->fifo.unload_context = nv40_fifo_unload_context; engine->display.early_init = nv04_display_early_init; @@ -321,6 +340,10 @@ engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; engine->pm.temp_get = nv40_temp_get; + engine->crypt.init = nouveau_stub_init; + engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; case 0x50: case 0x80: /* gotta love NVIDIA's consistency.. */ @@ -330,10 +353,10 @@ engine->instmem.takedown = nv50_instmem_takedown; engine->instmem.suspend = nv50_instmem_suspend; engine->instmem.resume = nv50_instmem_resume; - engine->instmem.populate = nv50_instmem_populate; - engine->instmem.clear = nv50_instmem_clear; - engine->instmem.bind = nv50_instmem_bind; - engine->instmem.unbind = nv50_instmem_unbind; + engine->instmem.get = nv50_instmem_get; + engine->instmem.put = nv50_instmem_put; + engine->instmem.map = nv50_instmem_map; + engine->instmem.unmap = nv50_instmem_unmap; if (dev_priv->chipset == 0x50) engine->instmem.flush = nv50_instmem_flush; else @@ -345,7 +368,6 @@ engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nv50_fb_init; engine->fb.takedown = nv50_fb_takedown; - engine->graph.grclass = nv50_graph_grclass; engine->graph.init = nv50_graph_init; engine->graph.takedown = nv50_graph_takedown; engine->graph.fifo_access = nv50_graph_fifo_access; @@ -381,24 +403,32 @@ engine->display.init = nv50_display_init; engine->display.destroy = nv50_display_destroy; engine->gpio.init = nv50_gpio_init; - engine->gpio.takedown = nouveau_stub_takedown; + engine->gpio.takedown = nv50_gpio_fini; engine->gpio.get = nv50_gpio_get; engine->gpio.set = nv50_gpio_set; + engine->gpio.irq_register = nv50_gpio_irq_register; + engine->gpio.irq_unregister = nv50_gpio_irq_unregister; engine->gpio.irq_enable = nv50_gpio_irq_enable; switch (dev_priv->chipset) { - case 0xa3: - case 0xa5: - case 0xa8: - case 0xaf: - engine->pm.clock_get = nva3_pm_clock_get; - engine->pm.clock_pre = nva3_pm_clock_pre; - engine->pm.clock_set = nva3_pm_clock_set; - break; - default: + case 0x84: + case 0x86: + case 0x92: + case 0x94: + case 0x96: + case 0x98: + case 0xa0: + case 0xaa: + case 0xac: + case 0x50: engine->pm.clock_get = nv50_pm_clock_get; engine->pm.clock_pre = nv50_pm_clock_pre; engine->pm.clock_set = nv50_pm_clock_set; break; + default: + engine->pm.clock_get = nva3_pm_clock_get; + engine->pm.clock_pre = nva3_pm_clock_pre; + engine->pm.clock_set = nva3_pm_clock_set; + break; } engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; @@ -406,16 +436,38 @@ engine->pm.temp_get = nv84_temp_get; else engine->pm.temp_get = nv40_temp_get; + switch (dev_priv->chipset) { + case 0x84: + case 0x86: + case 0x92: + case 0x94: + case 0x96: + case 0xa0: + engine->crypt.init = nv84_crypt_init; + engine->crypt.takedown = nv84_crypt_fini; + engine->crypt.create_context = nv84_crypt_create_context; + engine->crypt.destroy_context = nv84_crypt_destroy_context; + engine->crypt.tlb_flush = nv84_crypt_tlb_flush; + break; + default: + engine->crypt.init = nouveau_stub_init; + engine->crypt.takedown = nouveau_stub_takedown; + break; + } + engine->vram.init = nv50_vram_init; + engine->vram.get = nv50_vram_new; + engine->vram.put = nv50_vram_del; + engine->vram.flags_valid = nv50_vram_flags_valid; break; case 0xC0: engine->instmem.init = nvc0_instmem_init; engine->instmem.takedown = nvc0_instmem_takedown; engine->instmem.suspend = nvc0_instmem_suspend; engine->instmem.resume = nvc0_instmem_resume; - engine->instmem.populate = nvc0_instmem_populate; - engine->instmem.clear = nvc0_instmem_clear; - engine->instmem.bind = nvc0_instmem_bind; - engine->instmem.unbind = nvc0_instmem_unbind; + engine->instmem.get = nvc0_instmem_get; + engine->instmem.put = nvc0_instmem_put; + engine->instmem.map = nvc0_instmem_map; + engine->instmem.unmap = nvc0_instmem_unmap; engine->instmem.flush = nvc0_instmem_flush; engine->mc.init = nv50_mc_init; engine->mc.takedown = nv50_mc_takedown; @@ -424,7 +476,6 @@ engine->timer.takedown = nv04_timer_takedown; engine->fb.init = nvc0_fb_init; engine->fb.takedown = nvc0_fb_takedown; - engine->graph.grclass = NULL; //nvc0_graph_grclass; engine->graph.init = nvc0_graph_init; engine->graph.takedown = nvc0_graph_takedown; engine->graph.fifo_access = nvc0_graph_fifo_access; @@ -453,7 +504,13 @@ engine->gpio.takedown = nouveau_stub_takedown; engine->gpio.get = nv50_gpio_get; engine->gpio.set = nv50_gpio_set; + engine->gpio.irq_register = nv50_gpio_irq_register; + engine->gpio.irq_unregister = nv50_gpio_irq_unregister; engine->gpio.irq_enable = nv50_gpio_irq_enable; + engine->crypt.init = nouveau_stub_init; + engine->crypt.takedown = nouveau_stub_takedown; + engine->vram.init = nouveau_mem_detect; + engine->vram.flags_valid = nouveau_mem_flags_valid; break; default: NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); @@ -495,7 +552,7 @@ ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, 0, dev_priv->vram_size, - NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, + NV_MEM_ACCESS_RW, NV_MEM_TARGET_VRAM, &gpuobj); if (ret) goto out_err; @@ -505,9 +562,10 @@ if (ret) goto out_err; - ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, - dev_priv->gart_info.aper_size, - NV_DMA_ACCESS_RW, &gpuobj, NULL); + ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, + 0, dev_priv->gart_info.aper_size, + NV_MEM_ACCESS_RW, NV_MEM_TARGET_GART, + &gpuobj); if (ret) goto out_err; @@ -516,11 +574,11 @@ if (ret) goto out_err; + mutex_unlock(&dev_priv->channel->mutex); return 0; out_err: - nouveau_channel_free(dev_priv->channel); - dev_priv->channel = NULL; + nouveau_channel_put(&dev_priv->channel); return ret; } @@ -567,6 +625,8 @@ if (ret) goto out; engine = &dev_priv->engine; + spin_lock_init(&dev_priv->channels.lock); + spin_lock_init(&dev_priv->tile.lock); spin_lock_init(&dev_priv->context_switch_lock); /* Make the CRTCs and I2C buses accessible */ @@ -625,26 +685,28 @@ if (ret) goto out_fb; + /* PCRYPT */ + ret = engine->crypt.init(dev); + if (ret) + goto out_graph; + /* PFIFO */ ret = engine->fifo.init(dev); if (ret) - goto out_graph; + goto out_crypt; } ret = engine->display.create(dev); if (ret) goto out_fifo; - /* this call irq_preinstall, register irq handler and - * call irq_postinstall - */ - ret = drm_irq_install(dev); + ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1); if (ret) - goto out_display; + goto out_vblank; - ret = drm_vblank_init(dev, 0); + ret = nouveau_irq_init(dev); if (ret) - goto out_irq; + goto out_vblank; /* what about PVIDEO/PCRTC/PRAMDAC etc? */ @@ -669,12 +731,16 @@ out_fence: nouveau_fence_fini(dev); out_irq: - drm_irq_uninstall(dev); -out_display: + nouveau_irq_fini(dev); +out_vblank: + drm_vblank_cleanup(dev); engine->display.destroy(dev); out_fifo: if (!nouveau_noaccel) engine->fifo.takedown(dev); +out_crypt: + if (!nouveau_noaccel) + engine->crypt.takedown(dev); out_graph: if (!nouveau_noaccel) engine->graph.takedown(dev); @@ -713,12 +779,12 @@ if (!engine->graph.accel_blocked) { nouveau_fence_fini(dev); - nouveau_channel_free(dev_priv->channel); - dev_priv->channel = NULL; + nouveau_channel_put_unlocked(&dev_priv->channel); } if (!nouveau_noaccel) { engine->fifo.takedown(dev); + engine->crypt.takedown(dev); engine->graph.takedown(dev); } engine->fb.takedown(dev); @@ -737,7 +803,8 @@ nouveau_gpuobj_takedown(dev); nouveau_mem_vram_fini(dev); - drm_irq_uninstall(dev); + nouveau_irq_fini(dev); + drm_vblank_cleanup(dev); nouveau_pm_fini(dev); nouveau_bios_takedown(dev); @@ -1024,21 +1091,6 @@ else getparam->value = NV_PCI; break; - case NOUVEAU_GETPARAM_FB_PHYSICAL: - getparam->value = dev_priv->fb_phys; - break; - case NOUVEAU_GETPARAM_AGP_PHYSICAL: - getparam->value = dev_priv->gart_info.aper_base; - break; - case NOUVEAU_GETPARAM_PCI_PHYSICAL: - if (dev->sg) { - getparam->value = (unsigned long)dev->sg->virtual; - } else { - NV_ERROR(dev, "Requested PCIGART address, " - "while no PCIGART was created\n"); - return -EINVAL; - } - break; case NOUVEAU_GETPARAM_FB_SIZE: getparam->value = dev_priv->fb_available_size; break; @@ -1046,7 +1098,7 @@ getparam->value = dev_priv->gart_info.aper_size; break; case NOUVEAU_GETPARAM_VM_VRAM_BASE: - getparam->value = dev_priv->vm_vram_base; + getparam->value = 0; /* deprecated */ break; case NOUVEAU_GETPARAM_PTIMER_TIME: getparam->value = dev_priv->engine.timer.read(dev); @@ -1054,6 +1106,9 @@ case NOUVEAU_GETPARAM_HAS_BO_USAGE: getparam->value = 1; break; + case NOUVEAU_GETPARAM_HAS_PAGEFLIP: + getparam->value = (dev_priv->card_type < NV_50); + break; case NOUVEAU_GETPARAM_GRAPH_UNITS: /* NV40 and NV50 versions are quite different, but register * address is the same. User is supposed to know the card @@ -1087,8 +1142,9 @@ } /* Wait until (value(reg) & mask) == val, up until timeout has hit */ -bool nouveau_wait_until(struct drm_device *dev, uint64_t timeout, - uint32_t reg, uint32_t mask, uint32_t val) +bool +nouveau_wait_eq(struct drm_device *dev, uint64_t timeout, + uint32_t reg, uint32_t mask, uint32_t val) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; @@ -1102,10 +1158,33 @@ return false; } +/* Wait until (value(reg) & mask) != val, up until timeout has hit */ +bool +nouveau_wait_ne(struct drm_device *dev, uint64_t timeout, + uint32_t reg, uint32_t mask, uint32_t val) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; + uint64_t start = ptimer->read(dev); + + do { + if ((nv_rd32(dev, reg) & mask) != val) + return true; + } while (ptimer->read(dev) - start < timeout); + + return false; +} + /* Waits for PGRAPH to go completely idle */ bool nouveau_wait_for_idle(struct drm_device *dev) { - if (!nv_wait(dev, NV04_PGRAPH_STATUS, 0xffffffff, 0x00000000)) { + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t mask = ~0; + + if (dev_priv->card_type == NV_40) + mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL; + + if (!nv_wait(dev, NV04_PGRAPH_STATUS, mask, 0)) { NV_ERROR(dev, "PGRAPH idle timed out with status 0x%08x\n", nv_rd32(dev, NV04_PGRAPH_STATUS)); return false; --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_util.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_util.c @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2010 Nouveau Project + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include + +#include "nouveau_util.h" + +static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); + +void +nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value) +{ + while (bf->name) { + if (value & bf->mask) { + printk(" %s", bf->name); + value &= ~bf->mask; + } + + bf++; + } + + if (value) + printk(" (unknown bits 0x%08x)", value); +} + +void +nouveau_enum_print(const struct nouveau_enum *en, u32 value) +{ + while (en->name) { + if (value == en->value) { + printk("%s", en->name); + return; + } + + en++; + } + + printk("(unknown enum 0x%08x)", value); +} + +int +nouveau_ratelimit(void) +{ + return __ratelimit(&nouveau_ratelimit_state); +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_util.h +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_util.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2010 Nouveau Project + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __NOUVEAU_UTIL_H__ +#define __NOUVEAU_UTIL_H__ + +struct nouveau_bitfield { + u32 mask; + const char *name; +}; + +struct nouveau_enum { + u32 value; + const char *name; +}; + +void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value); +void nouveau_enum_print(const struct nouveau_enum *, u32 value); +int nouveau_ratelimit(void); + +#endif --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_vm.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_vm.c @@ -0,0 +1,421 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_mm.h" +#include "nouveau_vm.h" + +void +nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram) +{ + struct nouveau_vm *vm = vma->vm; + struct nouveau_mm_node *r; + u32 offset = vma->node->offset + (delta >> 12); + u32 bits = vma->node->type - 12; + u32 pde = (offset >> vm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vm->pgt_bits - bits); + u32 end, len; + + list_for_each_entry(r, &vram->regions, rl_entry) { + u64 phys = (u64)r->offset << 12; + u32 num = r->length >> bits; + + while (num) { + struct nouveau_gpuobj *pgt = vm->pgt[pde].obj; + + end = (pte + num); + if (unlikely(end >= max)) + end = max; + len = end - pte; + + vm->map(vma, pgt, vram, pte, len, phys); + + num -= len; + pte += len; + if (unlikely(end >= max)) { + pde++; + pte = 0; + } + } + } + + vm->flush(vm); +} + +void +nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_vram *vram) +{ + nouveau_vm_map_at(vma, 0, vram); +} + +void +nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, + dma_addr_t *list) +{ + struct nouveau_vm *vm = vma->vm; + u32 offset = vma->node->offset + (delta >> 12); + u32 bits = vma->node->type - 12; + u32 num = length >> vma->node->type; + u32 pde = (offset >> vm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vm->pgt_bits - bits); + u32 end, len; + + while (num) { + struct nouveau_gpuobj *pgt = vm->pgt[pde].obj; + + end = (pte + num); + if (unlikely(end >= max)) + end = max; + len = end - pte; + + vm->map_sg(vma, pgt, pte, list, len); + + num -= len; + pte += len; + list += len; + if (unlikely(end >= max)) { + pde++; + pte = 0; + } + } + + vm->flush(vm); +} + +void +nouveau_vm_unmap_at(struct nouveau_vma *vma, u64 delta, u64 length) +{ + struct nouveau_vm *vm = vma->vm; + u32 offset = vma->node->offset + (delta >> 12); + u32 bits = vma->node->type - 12; + u32 num = length >> vma->node->type; + u32 pde = (offset >> vm->pgt_bits) - vm->fpde; + u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits; + u32 max = 1 << (vm->pgt_bits - bits); + u32 end, len; + + while (num) { + struct nouveau_gpuobj *pgt = vm->pgt[pde].obj; + + end = (pte + num); + if (unlikely(end >= max)) + end = max; + len = end - pte; + + vm->unmap(pgt, pte, len); + + num -= len; + pte += len; + if (unlikely(end >= max)) { + pde++; + pte = 0; + } + } + + vm->flush(vm); +} + +void +nouveau_vm_unmap(struct nouveau_vma *vma) +{ + nouveau_vm_unmap_at(vma, 0, (u64)vma->node->length << 12); +} + +static void +nouveau_vm_unmap_pgt(struct nouveau_vm *vm, u32 fpde, u32 lpde) +{ + struct nouveau_vm_pgd *vpgd; + struct nouveau_vm_pgt *vpgt; + struct nouveau_gpuobj *pgt; + u32 pde; + + for (pde = fpde; pde <= lpde; pde++) { + vpgt = &vm->pgt[pde - vm->fpde]; + if (--vpgt->refcount) + continue; + + list_for_each_entry(vpgd, &vm->pgd_list, head) { + vm->unmap_pgt(vpgd->obj, pde); + } + + pgt = vpgt->obj; + vpgt->obj = NULL; + + mutex_unlock(&vm->mm->mutex); + nouveau_gpuobj_ref(NULL, &pgt); + mutex_lock(&vm->mm->mutex); + } +} + +static int +nouveau_vm_map_pgt(struct nouveau_vm *vm, u32 pde, u32 type) +{ + struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; + struct nouveau_vm_pgd *vpgd; + struct nouveau_gpuobj *pgt; + u32 pgt_size; + int ret; + + pgt_size = (1 << (vm->pgt_bits + 12)) >> type; + pgt_size *= 8; + + mutex_unlock(&vm->mm->mutex); + ret = nouveau_gpuobj_new(vm->dev, NULL, pgt_size, 0x1000, + NVOBJ_FLAG_ZERO_ALLOC, &pgt); + mutex_lock(&vm->mm->mutex); + if (unlikely(ret)) + return ret; + + /* someone beat us to filling the PDE while we didn't have the lock */ + if (unlikely(vpgt->refcount++)) { + mutex_unlock(&vm->mm->mutex); + nouveau_gpuobj_ref(NULL, &pgt); + mutex_lock(&vm->mm->mutex); + return 0; + } + + list_for_each_entry(vpgd, &vm->pgd_list, head) { + vm->map_pgt(vpgd->obj, type, pde, pgt); + } + + vpgt->page_shift = type; + vpgt->obj = pgt; + return 0; +} + +int +nouveau_vm_get(struct nouveau_vm *vm, u64 size, u32 page_shift, + u32 access, struct nouveau_vma *vma) +{ + u32 align = (1 << page_shift) >> 12; + u32 msize = size >> 12; + u32 fpde, lpde, pde; + int ret; + + mutex_lock(&vm->mm->mutex); + ret = nouveau_mm_get(vm->mm, page_shift, msize, 0, align, &vma->node); + if (unlikely(ret != 0)) { + mutex_unlock(&vm->mm->mutex); + return ret; + } + + fpde = (vma->node->offset >> vm->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; + for (pde = fpde; pde <= lpde; pde++) { + struct nouveau_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; + + if (likely(vpgt->refcount)) { + vpgt->refcount++; + continue; + } + + ret = nouveau_vm_map_pgt(vm, pde, vma->node->type); + if (ret) { + if (pde != fpde) + nouveau_vm_unmap_pgt(vm, fpde, pde - 1); + nouveau_mm_put(vm->mm, vma->node); + mutex_unlock(&vm->mm->mutex); + vma->node = NULL; + return ret; + } + } + mutex_unlock(&vm->mm->mutex); + + vma->vm = vm; + vma->offset = (u64)vma->node->offset << 12; + vma->access = access; + return 0; +} + +void +nouveau_vm_put(struct nouveau_vma *vma) +{ + struct nouveau_vm *vm = vma->vm; + u32 fpde, lpde; + + if (unlikely(vma->node == NULL)) + return; + fpde = (vma->node->offset >> vm->pgt_bits); + lpde = (vma->node->offset + vma->node->length - 1) >> vm->pgt_bits; + + mutex_lock(&vm->mm->mutex); + nouveau_mm_put(vm->mm, vma->node); + vma->node = NULL; + nouveau_vm_unmap_pgt(vm, fpde, lpde); + mutex_unlock(&vm->mm->mutex); +} + +int +nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, + u8 pgt_bits, u8 spg_shift, u8 lpg_shift, + struct nouveau_vm **pvm) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_vm *vm; + u64 mm_length = (offset + length) - mm_offset; + u32 block; + int ret; + + vm = kzalloc(sizeof(*vm), GFP_KERNEL); + if (!vm) + return -ENOMEM; + + if (dev_priv->card_type == NV_50) { + vm->map_pgt = nv50_vm_map_pgt; + vm->unmap_pgt = nv50_vm_unmap_pgt; + vm->map = nv50_vm_map; + vm->map_sg = nv50_vm_map_sg; + vm->unmap = nv50_vm_unmap; + vm->flush = nv50_vm_flush; + } else { + kfree(vm); + return -ENOSYS; + } + + vm->fpde = offset >> pgt_bits; + vm->lpde = (offset + length - 1) >> pgt_bits; + vm->pgt = kcalloc(vm->lpde - vm->fpde + 1, sizeof(*vm->pgt), GFP_KERNEL); + if (!vm->pgt) { + kfree(vm); + return -ENOMEM; + } + + INIT_LIST_HEAD(&vm->pgd_list); + vm->dev = dev; + vm->refcount = 1; + vm->pgt_bits = pgt_bits - 12; + vm->spg_shift = spg_shift; + vm->lpg_shift = lpg_shift; + + block = (1 << pgt_bits); + if (length < block) + block = length; + + ret = nouveau_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12, + block >> 12); + if (ret) { + kfree(vm); + return ret; + } + + *pvm = vm; + return 0; +} + +static int +nouveau_vm_link(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) +{ + struct nouveau_vm_pgd *vpgd; + int i; + + if (!pgd) + return 0; + + vpgd = kzalloc(sizeof(*vpgd), GFP_KERNEL); + if (!vpgd) + return -ENOMEM; + + nouveau_gpuobj_ref(pgd, &vpgd->obj); + + mutex_lock(&vm->mm->mutex); + for (i = vm->fpde; i <= vm->lpde; i++) { + struct nouveau_vm_pgt *vpgt = &vm->pgt[i - vm->fpde]; + + if (!vpgt->obj) { + vm->unmap_pgt(pgd, i); + continue; + } + + vm->map_pgt(pgd, vpgt->page_shift, i, vpgt->obj); + } + list_add(&vpgd->head, &vm->pgd_list); + mutex_unlock(&vm->mm->mutex); + return 0; +} + +static void +nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *pgd) +{ + struct nouveau_vm_pgd *vpgd, *tmp; + + if (!pgd) + return; + + mutex_lock(&vm->mm->mutex); + list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { + if (vpgd->obj != pgd) + continue; + + list_del(&vpgd->head); + nouveau_gpuobj_ref(NULL, &vpgd->obj); + kfree(vpgd); + } + mutex_unlock(&vm->mm->mutex); +} + +static void +nouveau_vm_del(struct nouveau_vm *vm) +{ + struct nouveau_vm_pgd *vpgd, *tmp; + + list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { + nouveau_vm_unlink(vm, vpgd->obj); + } + WARN_ON(nouveau_mm_fini(&vm->mm) != 0); + + kfree(vm->pgt); + kfree(vm); +} + +int +nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr, + struct nouveau_gpuobj *pgd) +{ + struct nouveau_vm *vm; + int ret; + + vm = ref; + if (vm) { + ret = nouveau_vm_link(vm, pgd); + if (ret) + return ret; + + vm->refcount++; + } + + vm = *ptr; + *ptr = ref; + + if (vm) { + nouveau_vm_unlink(vm, pgd); + + if (--vm->refcount == 0) + nouveau_vm_del(vm); + } + + return 0; +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nouveau_vm.h +++ linux-2.6.37/drivers/gpu/drm/nouveau/nouveau_vm.h @@ -0,0 +1,107 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#ifndef __NOUVEAU_VM_H__ +#define __NOUVEAU_VM_H__ + +#include "drmP.h" + +#include "nouveau_drv.h" +#include "nouveau_mm.h" + +struct nouveau_vm_pgt { + struct nouveau_gpuobj *obj; + u32 page_shift; + u32 refcount; +}; + +struct nouveau_vm_pgd { + struct list_head head; + struct nouveau_gpuobj *obj; +}; + +struct nouveau_vma { + struct nouveau_vm *vm; + struct nouveau_mm_node *node; + u64 offset; + u32 access; +}; + +struct nouveau_vm { + struct drm_device *dev; + struct nouveau_mm *mm; + int refcount; + + struct list_head pgd_list; + atomic_t pgraph_refs; + atomic_t pcrypt_refs; + + struct nouveau_vm_pgt *pgt; + u32 fpde; + u32 lpde; + + u32 pgt_bits; + u8 spg_shift; + u8 lpg_shift; + + void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 type, u32 pde, + struct nouveau_gpuobj *pgt); + void (*unmap_pgt)(struct nouveau_gpuobj *pgd, u32 pde); + void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *, + struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); + void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, + u32 pte, dma_addr_t *, u32 cnt); + void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); + void (*flush)(struct nouveau_vm *); +}; + +/* nouveau_vm.c */ +int nouveau_vm_new(struct drm_device *, u64 offset, u64 length, u64 mm_offset, + u8 pgt_bits, u8 spg_shift, u8 lpg_shift, + struct nouveau_vm **); +int nouveau_vm_ref(struct nouveau_vm *, struct nouveau_vm **, + struct nouveau_gpuobj *pgd); +int nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift, + u32 access, struct nouveau_vma *); +void nouveau_vm_put(struct nouveau_vma *); +void nouveau_vm_map(struct nouveau_vma *, struct nouveau_vram *); +void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_vram *); +void nouveau_vm_unmap(struct nouveau_vma *); +void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); +void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, + dma_addr_t *); + +/* nv50_vm.c */ +void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 type, u32 pde, + struct nouveau_gpuobj *pgt); +void nv50_vm_unmap_pgt(struct nouveau_gpuobj *pgd, u32 pde); +void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *, + struct nouveau_vram *, u32 pte, u32 cnt, u64 phys); +void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *, + u32 pte, dma_addr_t *, u32 cnt); +void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt); +void nv50_vm_flush(struct nouveau_vm *); +void nv50_vm_flush_engine(struct drm_device *, int engine); + +#endif --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv04_crtc.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -551,7 +551,10 @@ if (dev_priv->card_type >= NV_30) regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT); - regp->crtc_cfg = NV_PCRTC_CONFIG_START_ADDRESS_HSYNC; + if (dev_priv->card_type >= NV_10) + regp->crtc_cfg = NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC; + else + regp->crtc_cfg = NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC; /* Some misc regs */ if (dev_priv->card_type == NV_40) { @@ -669,6 +672,7 @@ if (nv_two_heads(dev)) NVSetOwner(dev, nv_crtc->index); + drm_vblank_pre_modeset(dev, nv_crtc->index); funcs->dpms(crtc, DRM_MODE_DPMS_OFF); NVBlankScreen(dev, nv_crtc->index, true); @@ -701,6 +705,7 @@ #endif funcs->dpms(crtc, DRM_MODE_DPMS_ON); + drm_vblank_post_modeset(dev, nv_crtc->index); } static void nv_crtc_destroy(struct drm_crtc *crtc) @@ -986,6 +991,7 @@ .cursor_move = nv04_crtc_cursor_move, .gamma_set = nv_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, + .page_flip = nouveau_crtc_page_flip, .destroy = nv_crtc_destroy, }; --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv04_dac.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv04_dac.c @@ -74,14 +74,14 @@ * use a 10ms timeout (guards against crtc being inactive, in * which case blank state would never change) */ - if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR, - 0x00000001, 0x00000000)) + if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, + 0x00000001, 0x00000000)) return -EBUSY; - if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR, - 0x00000001, 0x00000001)) + if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, + 0x00000001, 0x00000001)) return -EBUSY; - if (!nouveau_wait_until(dev, 10000000, NV_PRMCIO_INP0__COLOR, - 0x00000001, 0x00000000)) + if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, + 0x00000001, 0x00000000)) return -EBUSY; udelay(100); --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv04_display.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv04_display.c @@ -32,6 +32,9 @@ #include "nouveau_encoder.h" #include "nouveau_connector.h" +static void nv04_vblank_crtc0_isr(struct drm_device *); +static void nv04_vblank_crtc1_isr(struct drm_device *); + static void nv04_display_store_initial_head_owner(struct drm_device *dev) { @@ -197,6 +200,8 @@ func->save(encoder); } + nouveau_irq_register(dev, 24, nv04_vblank_crtc0_isr); + nouveau_irq_register(dev, 25, nv04_vblank_crtc1_isr); return 0; } @@ -208,6 +213,9 @@ NV_DEBUG_KMS(dev, "\n"); + nouveau_irq_unregister(dev, 24); + nouveau_irq_unregister(dev, 25); + /* Turn every CRTC off. */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct drm_mode_set modeset = { @@ -258,3 +266,16 @@ return 0; } +static void +nv04_vblank_crtc0_isr(struct drm_device *dev) +{ + nv_wr32(dev, NV_CRTC0_INTSTAT, NV_CRTC_INTR_VBLANK); + drm_handle_vblank(dev, 0); +} + +static void +nv04_vblank_crtc1_isr(struct drm_device *dev) +{ + nv_wr32(dev, NV_CRTC1_INTSTAT, NV_CRTC_INTR_VBLANK); + drm_handle_vblank(dev, 1); +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv04_fbcon.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv04_fbcon.c @@ -28,52 +28,39 @@ #include "nouveau_ramht.h" #include "nouveau_fbcon.h" -void +int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) { struct nouveau_fbdev *nfbdev = info->par; struct drm_device *dev = nfbdev->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; + int ret; - if (info->state != FBINFO_STATE_RUNNING) - return; - - if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 4)) { - nouveau_fbcon_gpu_lockup(info); - } - - if (info->flags & FBINFO_HWACCEL_DISABLED) { - cfb_copyarea(info, region); - return; - } + ret = RING_SPACE(chan, 4); + if (ret) + return ret; BEGIN_RING(chan, NvSubImageBlit, 0x0300, 3); OUT_RING(chan, (region->sy << 16) | region->sx); OUT_RING(chan, (region->dy << 16) | region->dx); OUT_RING(chan, (region->height << 16) | region->width); FIRE_RING(chan); + return 0; } -void +int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct nouveau_fbdev *nfbdev = info->par; struct drm_device *dev = nfbdev->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; + int ret; - if (info->state != FBINFO_STATE_RUNNING) - return; - - if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 7)) { - nouveau_fbcon_gpu_lockup(info); - } - - if (info->flags & FBINFO_HWACCEL_DISABLED) { - cfb_fillrect(info, rect); - return; - } + ret = RING_SPACE(chan, 7); + if (ret) + return ret; BEGIN_RING(chan, NvSubGdiRect, 0x02fc, 1); OUT_RING(chan, (rect->rop != ROP_COPY) ? 1 : 3); @@ -87,9 +74,10 @@ OUT_RING(chan, (rect->dx << 16) | rect->dy); OUT_RING(chan, (rect->width << 16) | rect->height); FIRE_RING(chan); + return 0; } -void +int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) { struct nouveau_fbdev *nfbdev = info->par; @@ -101,23 +89,14 @@ uint32_t dsize; uint32_t width; uint32_t *data = (uint32_t *)image->data; + int ret; - if (info->state != FBINFO_STATE_RUNNING) - return; - - if (image->depth != 1) { - cfb_imageblit(info, image); - return; - } + if (image->depth != 1) + return -ENODEV; - if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 8)) { - nouveau_fbcon_gpu_lockup(info); - } - - if (info->flags & FBINFO_HWACCEL_DISABLED) { - cfb_imageblit(info, image); - return; - } + ret = RING_SPACE(chan, 8); + if (ret) + return ret; width = ALIGN(image->width, 8); dsize = ALIGN(width * image->height, 32) >> 5; @@ -144,11 +123,9 @@ while (dsize) { int iter_len = dsize > 128 ? 128 : dsize; - if (RING_SPACE(chan, iter_len + 1)) { - nouveau_fbcon_gpu_lockup(info); - cfb_imageblit(info, image); - return; - } + ret = RING_SPACE(chan, iter_len + 1); + if (ret) + return ret; BEGIN_RING(chan, NvSubGdiRect, 0x0c00, iter_len); OUT_RINGp(chan, data, iter_len); @@ -157,22 +134,7 @@ } FIRE_RING(chan); -} - -static int -nv04_fbcon_grobj_new(struct drm_device *dev, int class, uint32_t handle) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *obj = NULL; - int ret; - - ret = nouveau_gpuobj_gr_new(dev_priv->channel, class, &obj); - if (ret) - return ret; - - ret = nouveau_ramht_insert(dev_priv->channel, handle, obj); - nouveau_gpuobj_ref(NULL, &obj); - return ret; + return 0; } int @@ -214,29 +176,31 @@ return -EINVAL; } - ret = nv04_fbcon_grobj_new(dev, dev_priv->card_type >= NV_10 ? - 0x0062 : 0x0042, NvCtxSurf2D); + ret = nouveau_gpuobj_gr_new(chan, NvCtxSurf2D, + dev_priv->card_type >= NV_10 ? + 0x0062 : 0x0042); if (ret) return ret; - ret = nv04_fbcon_grobj_new(dev, 0x0019, NvClipRect); + ret = nouveau_gpuobj_gr_new(chan, NvClipRect, 0x0019); if (ret) return ret; - ret = nv04_fbcon_grobj_new(dev, 0x0043, NvRop); + ret = nouveau_gpuobj_gr_new(chan, NvRop, 0x0043); if (ret) return ret; - ret = nv04_fbcon_grobj_new(dev, 0x0044, NvImagePatt); + ret = nouveau_gpuobj_gr_new(chan, NvImagePatt, 0x0044); if (ret) return ret; - ret = nv04_fbcon_grobj_new(dev, 0x004a, NvGdiRect); + ret = nouveau_gpuobj_gr_new(chan, NvGdiRect, 0x004a); if (ret) return ret; - ret = nv04_fbcon_grobj_new(dev, dev_priv->chipset >= 0x11 ? - 0x009f : 0x005f, NvImageBlit); + ret = nouveau_gpuobj_gr_new(chan, NvImageBlit, + dev_priv->chipset >= 0x11 ? + 0x009f : 0x005f); if (ret) return ret; --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv04_fifo.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv04_fifo.c @@ -28,6 +28,7 @@ #include "drm.h" #include "nouveau_drv.h" #include "nouveau_ramht.h" +#include "nouveau_util.h" #define NV04_RAMFC(c) (dev_priv->ramfc->pinst + ((c) * NV04_RAMFC__SIZE)) #define NV04_RAMFC__SIZE 32 @@ -128,6 +129,11 @@ if (ret) return ret; + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV03_USER(chan->id), PAGE_SIZE); + if (!chan->user) + return -ENOMEM; + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); /* Setup initial state */ @@ -151,10 +157,31 @@ nv04_fifo_destroy_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + unsigned long flags; - nv_wr32(dev, NV04_PFIFO_MODE, - nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + pfifo->reassign(dev, false); + /* Unload the context if it's the currently active one */ + if (pfifo->channel_id(dev) == chan->id) { + pfifo->disable(dev); + pfifo->unload_context(dev); + pfifo->enable(dev); + } + + /* Keep it from being rescheduled */ + nv_mask(dev, NV04_PFIFO_MODE, 1 << chan->id, 0); + + pfifo->reassign(dev, true); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* Free the channel resources */ + if (chan->user) { + iounmap(chan->user); + chan->user = NULL; + } nouveau_gpuobj_ref(NULL, &chan->ramfc); } @@ -208,7 +235,7 @@ if (chid < 0 || chid >= dev_priv->engine.fifo.channels) return 0; - chan = dev_priv->fifos[chid]; + chan = dev_priv->channels.ptr[chid]; if (!chan) { NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); return -EINVAL; @@ -267,6 +294,7 @@ static void nv04_fifo_init_intr(struct drm_device *dev) { + nouveau_irq_register(dev, 8, nv04_fifo_isr); nv_wr32(dev, 0x002100, 0xffffffff); nv_wr32(dev, 0x002140, 0xffffffff); } @@ -289,7 +317,7 @@ pfifo->reassign(dev, true); for (i = 0; i < dev_priv->engine.fifo.channels; i++) { - if (dev_priv->fifos[i]) { + if (dev_priv->channels.ptr[i]) { uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); } @@ -298,3 +326,207 @@ return 0; } +void +nv04_fifo_fini(struct drm_device *dev) +{ + nv_wr32(dev, 0x2140, 0x00000000); + nouveau_irq_unregister(dev, 8); +} + +static bool +nouveau_fifo_swmthd(struct drm_device *dev, u32 chid, u32 addr, u32 data) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan = NULL; + struct nouveau_gpuobj *obj; + unsigned long flags; + const int subc = (addr >> 13) & 0x7; + const int mthd = addr & 0x1ffc; + bool handled = false; + u32 engine; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); + if (likely(chid >= 0 && chid < dev_priv->engine.fifo.channels)) + chan = dev_priv->channels.ptr[chid]; + if (unlikely(!chan)) + goto out; + + switch (mthd) { + case 0x0000: /* bind object to subchannel */ + obj = nouveau_ramht_find(chan, data); + if (unlikely(!obj || obj->engine != NVOBJ_ENGINE_SW)) + break; + + chan->sw_subchannel[subc] = obj->class; + engine = 0x0000000f << (subc * 4); + + nv_mask(dev, NV04_PFIFO_CACHE1_ENGINE, engine, 0x00000000); + handled = true; + break; + default: + engine = nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE); + if (unlikely(((engine >> (subc * 4)) & 0xf) != 0)) + break; + + if (!nouveau_gpuobj_mthd_call(chan, chan->sw_subchannel[subc], + mthd, data)) + handled = true; + break; + } + +out: + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + return handled; +} + +void +nv04_fifo_isr(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->engine; + uint32_t status, reassign; + int cnt = 0; + + reassign = nv_rd32(dev, NV03_PFIFO_CACHES) & 1; + while ((status = nv_rd32(dev, NV03_PFIFO_INTR_0)) && (cnt++ < 100)) { + uint32_t chid, get; + + nv_wr32(dev, NV03_PFIFO_CACHES, 0); + + chid = engine->fifo.channel_id(dev); + get = nv_rd32(dev, NV03_PFIFO_CACHE1_GET); + + if (status & NV_PFIFO_INTR_CACHE_ERROR) { + uint32_t mthd, data; + int ptr; + + /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before + * wrapping on my G80 chips, but CACHE1 isn't big + * enough for this much data.. Tests show that it + * wraps around to the start at GET=0x800.. No clue + * as to why.. + */ + ptr = (get & 0x7ff) >> 2; + + if (dev_priv->card_type < NV_40) { + mthd = nv_rd32(dev, + NV04_PFIFO_CACHE1_METHOD(ptr)); + data = nv_rd32(dev, + NV04_PFIFO_CACHE1_DATA(ptr)); + } else { + mthd = nv_rd32(dev, + NV40_PFIFO_CACHE1_METHOD(ptr)); + data = nv_rd32(dev, + NV40_PFIFO_CACHE1_DATA(ptr)); + } + + if (!nouveau_fifo_swmthd(dev, chid, mthd, data)) { + NV_INFO(dev, "PFIFO_CACHE_ERROR - Ch %d/%d " + "Mthd 0x%04x Data 0x%08x\n", + chid, (mthd >> 13) & 7, mthd & 0x1ffc, + data); + } + + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, 0); + nv_wr32(dev, NV03_PFIFO_INTR_0, + NV_PFIFO_INTR_CACHE_ERROR); + + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) & ~1); + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); + nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(dev, NV03_PFIFO_CACHE1_PUSH0) | 1); + nv_wr32(dev, NV04_PFIFO_CACHE1_HASH, 0); + + nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUSH, + nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + + status &= ~NV_PFIFO_INTR_CACHE_ERROR; + } + + if (status & NV_PFIFO_INTR_DMA_PUSHER) { + u32 dma_get = nv_rd32(dev, 0x003244); + u32 dma_put = nv_rd32(dev, 0x003240); + u32 push = nv_rd32(dev, 0x003220); + u32 state = nv_rd32(dev, 0x003228); + + if (dev_priv->card_type == NV_50) { + u32 ho_get = nv_rd32(dev, 0x003328); + u32 ho_put = nv_rd32(dev, 0x003320); + u32 ib_get = nv_rd32(dev, 0x003334); + u32 ib_put = nv_rd32(dev, 0x003330); + + if (nouveau_ratelimit()) + NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " + "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " + "State 0x%08x Push 0x%08x\n", + chid, ho_get, dma_get, ho_put, + dma_put, ib_get, ib_put, state, + push); + + /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ + nv_wr32(dev, 0x003364, 0x00000000); + if (dma_get != dma_put || ho_get != ho_put) { + nv_wr32(dev, 0x003244, dma_put); + nv_wr32(dev, 0x003328, ho_put); + } else + if (ib_get != ib_put) { + nv_wr32(dev, 0x003334, ib_put); + } + } else { + NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " + "Put 0x%08x State 0x%08x Push 0x%08x\n", + chid, dma_get, dma_put, state, push); + + if (dma_get != dma_put) + nv_wr32(dev, 0x003244, dma_put); + } + + nv_wr32(dev, 0x003228, 0x00000000); + nv_wr32(dev, 0x003220, 0x00000001); + nv_wr32(dev, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); + status &= ~NV_PFIFO_INTR_DMA_PUSHER; + } + + if (status & NV_PFIFO_INTR_SEMAPHORE) { + uint32_t sem; + + status &= ~NV_PFIFO_INTR_SEMAPHORE; + nv_wr32(dev, NV03_PFIFO_INTR_0, + NV_PFIFO_INTR_SEMAPHORE); + + sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE); + nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1); + + nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4); + nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1); + } + + if (dev_priv->card_type == NV_50) { + if (status & 0x00000010) { + nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT"); + status &= ~0x00000010; + nv_wr32(dev, 0x002100, 0x00000010); + } + } + + if (status) { + if (nouveau_ratelimit()) + NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", + status, chid); + nv_wr32(dev, NV03_PFIFO_INTR_0, status); + status = 0; + } + + nv_wr32(dev, NV03_PFIFO_CACHES, reassign); + } + + if (status) { + NV_INFO(dev, "PFIFO still angry after %d spins, halt\n", cnt); + nv_wr32(dev, 0x2140, 0); + nv_wr32(dev, 0x140, 0); + } + + nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PFIFO_PENDING); +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv04_graph.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv04_graph.c @@ -26,6 +26,11 @@ #include "drm.h" #include "nouveau_drm.h" #include "nouveau_drv.h" +#include "nouveau_hw.h" +#include "nouveau_util.h" + +static int nv04_graph_register(struct drm_device *dev); +static void nv04_graph_isr(struct drm_device *dev); static uint32_t nv04_graph_ctx_regs[] = { 0x0040053c, @@ -357,10 +362,10 @@ if (chid >= dev_priv->engine.fifo.channels) return NULL; - return dev_priv->fifos[chid]; + return dev_priv->channels.ptr[chid]; } -void +static void nv04_graph_context_switch(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -368,7 +373,6 @@ struct nouveau_channel *chan = NULL; int chid; - pgraph->fifo_access(dev, false); nouveau_wait_for_idle(dev); /* If previous context is valid, we need to save it */ @@ -376,11 +380,9 @@ /* Load context for next channel */ chid = dev_priv->engine.fifo.channel_id(dev); - chan = dev_priv->fifos[chid]; + chan = dev_priv->channels.ptr[chid]; if (chan) nv04_graph_load_context(chan); - - pgraph->fifo_access(dev, true); } static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg) @@ -412,10 +414,25 @@ void nv04_graph_destroy_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct graph_state *pgraph_ctx = chan->pgraph_ctx; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + pgraph->fifo_access(dev, false); + + /* Unload the context if it's the currently active one */ + if (pgraph->channel(dev) == chan) + pgraph->unload_context(dev); + /* Free the context resources */ kfree(pgraph_ctx); chan->pgraph_ctx = NULL; + + pgraph->fifo_access(dev, true); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); } int nv04_graph_load_context(struct nouveau_channel *chan) @@ -468,13 +485,19 @@ { struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t tmp; + int ret; nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); + ret = nv04_graph_register(dev); + if (ret) + return ret; + /* Enable PGRAPH interrupts */ + nouveau_irq_register(dev, 12, nv04_graph_isr); nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); @@ -510,6 +533,8 @@ void nv04_graph_takedown(struct drm_device *dev) { + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); + nouveau_irq_unregister(dev, 12); } void @@ -524,13 +549,27 @@ } static int -nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_set_ref(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { atomic_set(&chan->fence.last_sequence_irq, data); return 0; } +int +nv04_graph_mthd_page_flip(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + struct drm_device *dev = chan->dev; + struct nouveau_page_flip_state s; + + if (!nouveau_finish_page_flip(chan, &s)) + nv_set_crtc_base(dev, s.crtc, + s.offset + s.y * s.pitch + s.x * s.bpp / 8); + + return 0; +} + /* * Software methods, why they are needed, and how they all work: * @@ -606,12 +645,12 @@ */ static void -nv04_graph_set_ctx1(struct nouveau_channel *chan, uint32_t mask, uint32_t value) +nv04_graph_set_ctx1(struct nouveau_channel *chan, u32 mask, u32 value) { struct drm_device *dev = chan->dev; - uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; + u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7; - uint32_t tmp; + u32 tmp; tmp = nv_ri32(dev, instance); tmp &= ~mask; @@ -623,11 +662,11 @@ } static void -nv04_graph_set_ctx_val(struct nouveau_channel *chan, uint32_t mask, uint32_t value) +nv04_graph_set_ctx_val(struct nouveau_channel *chan, u32 mask, u32 value) { struct drm_device *dev = chan->dev; - uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; - uint32_t tmp, ctx1; + u32 instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4; + u32 tmp, ctx1; int class, op, valid = 1; ctx1 = nv_ri32(dev, instance); @@ -672,13 +711,13 @@ } static int -nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_set_operation(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { if (data > 5) return 1; /* Old versions of the objects only accept first three operations. */ - if (data > 2 && grclass < 0x40) + if (data > 2 && class < 0x40) return 1; nv04_graph_set_ctx1(chan, 0x00038000, data << 15); /* changing operation changes set of objects needed for validation */ @@ -687,8 +726,8 @@ } static int -nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { uint32_t min = data & 0xffff, max; uint32_t w = data >> 16; @@ -706,8 +745,8 @@ } static int -nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { uint32_t min = data & 0xffff, max; uint32_t w = data >> 16; @@ -725,8 +764,8 @@ } static int -nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -742,8 +781,8 @@ } static int -nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -763,8 +802,8 @@ } static int -nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -778,8 +817,8 @@ } static int -nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -793,8 +832,8 @@ } static int -nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -808,8 +847,8 @@ } static int -nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -823,8 +862,8 @@ } static int -nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -838,8 +877,8 @@ } static int -nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -853,8 +892,8 @@ } static int -nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -868,8 +907,8 @@ } static int -nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -883,8 +922,8 @@ } static int -nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -898,8 +937,8 @@ } static int -nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -913,8 +952,8 @@ } static int -nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { switch (nv_ri32(chan->dev, data << 4) & 0xff) { case 0x30: @@ -930,194 +969,346 @@ return 1; } -static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = { - { 0x0150, nv04_graph_mthd_set_ref }, - {} -}; - -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_gdirect[] = { - { 0x0184, nv04_graph_mthd_bind_nv01_patt }, - { 0x0188, nv04_graph_mthd_bind_rop }, - { 0x018c, nv04_graph_mthd_bind_beta1 }, - { 0x0190, nv04_graph_mthd_bind_surf_dst }, - { 0x02fc, nv04_graph_mthd_set_operation }, - {}, -}; - -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_gdirect[] = { - { 0x0188, nv04_graph_mthd_bind_nv04_patt }, - { 0x018c, nv04_graph_mthd_bind_rop }, - { 0x0190, nv04_graph_mthd_bind_beta1 }, - { 0x0194, nv04_graph_mthd_bind_beta4 }, - { 0x0198, nv04_graph_mthd_bind_surf2d }, - { 0x02fc, nv04_graph_mthd_set_operation }, - {}, -}; - -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_imageblit[] = { - { 0x0184, nv04_graph_mthd_bind_chroma }, - { 0x0188, nv04_graph_mthd_bind_clip }, - { 0x018c, nv04_graph_mthd_bind_nv01_patt }, - { 0x0190, nv04_graph_mthd_bind_rop }, - { 0x0194, nv04_graph_mthd_bind_beta1 }, - { 0x0198, nv04_graph_mthd_bind_surf_dst }, - { 0x019c, nv04_graph_mthd_bind_surf_src }, - { 0x02fc, nv04_graph_mthd_set_operation }, - {}, -}; - -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_imageblit_ifc[] = { - { 0x0184, nv04_graph_mthd_bind_chroma }, - { 0x0188, nv04_graph_mthd_bind_clip }, - { 0x018c, nv04_graph_mthd_bind_nv04_patt }, - { 0x0190, nv04_graph_mthd_bind_rop }, - { 0x0194, nv04_graph_mthd_bind_beta1 }, - { 0x0198, nv04_graph_mthd_bind_beta4 }, - { 0x019c, nv04_graph_mthd_bind_surf2d }, - { 0x02fc, nv04_graph_mthd_set_operation }, - {}, -}; - -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_iifc[] = { - { 0x0188, nv04_graph_mthd_bind_chroma }, - { 0x018c, nv04_graph_mthd_bind_clip }, - { 0x0190, nv04_graph_mthd_bind_nv04_patt }, - { 0x0194, nv04_graph_mthd_bind_rop }, - { 0x0198, nv04_graph_mthd_bind_beta1 }, - { 0x019c, nv04_graph_mthd_bind_beta4 }, - { 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf }, - { 0x03e4, nv04_graph_mthd_set_operation }, - {}, -}; - -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_ifc[] = { - { 0x0184, nv04_graph_mthd_bind_chroma }, - { 0x0188, nv04_graph_mthd_bind_clip }, - { 0x018c, nv04_graph_mthd_bind_nv01_patt }, - { 0x0190, nv04_graph_mthd_bind_rop }, - { 0x0194, nv04_graph_mthd_bind_beta1 }, - { 0x0198, nv04_graph_mthd_bind_surf_dst }, - { 0x02fc, nv04_graph_mthd_set_operation }, - {}, -}; - -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifc[] = { - { 0x0184, nv04_graph_mthd_bind_chroma }, - { 0x0188, nv04_graph_mthd_bind_nv01_patt }, - { 0x018c, nv04_graph_mthd_bind_rop }, - { 0x0190, nv04_graph_mthd_bind_beta1 }, - { 0x0194, nv04_graph_mthd_bind_surf_dst }, - { 0x02fc, nv04_graph_mthd_set_operation }, - {}, -}; +static int +nv04_graph_register(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifc[] = { - { 0x0184, nv04_graph_mthd_bind_chroma }, - { 0x0188, nv04_graph_mthd_bind_nv04_patt }, - { 0x018c, nv04_graph_mthd_bind_rop }, - { 0x0190, nv04_graph_mthd_bind_beta1 }, - { 0x0194, nv04_graph_mthd_bind_beta4 }, - { 0x0198, nv04_graph_mthd_bind_surf2d }, - { 0x02fc, nv04_graph_mthd_set_operation }, - {}, -}; + if (dev_priv->engine.graph.registered) + return 0; -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifm[] = { - { 0x0188, nv04_graph_mthd_bind_nv01_patt }, - { 0x018c, nv04_graph_mthd_bind_rop }, - { 0x0190, nv04_graph_mthd_bind_beta1 }, - { 0x0194, nv04_graph_mthd_bind_surf_dst }, - { 0x0304, nv04_graph_mthd_set_operation }, - {}, -}; + /* dvd subpicture */ + NVOBJ_CLASS(dev, 0x0038, GR); -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifm[] = { - { 0x0188, nv04_graph_mthd_bind_nv04_patt }, - { 0x018c, nv04_graph_mthd_bind_rop }, - { 0x0190, nv04_graph_mthd_bind_beta1 }, - { 0x0194, nv04_graph_mthd_bind_beta4 }, - { 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf }, - { 0x0304, nv04_graph_mthd_set_operation }, - {}, -}; + /* m2mf */ + NVOBJ_CLASS(dev, 0x0039, GR); -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_shape[] = { - { 0x0184, nv04_graph_mthd_bind_clip }, - { 0x0188, nv04_graph_mthd_bind_nv01_patt }, - { 0x018c, nv04_graph_mthd_bind_rop }, - { 0x0190, nv04_graph_mthd_bind_beta1 }, - { 0x0194, nv04_graph_mthd_bind_surf_dst }, - { 0x02fc, nv04_graph_mthd_set_operation }, - {}, -}; + /* nv03 gdirect */ + NVOBJ_CLASS(dev, 0x004b, GR); + NVOBJ_MTHD (dev, 0x004b, 0x0184, nv04_graph_mthd_bind_nv01_patt); + NVOBJ_MTHD (dev, 0x004b, 0x0188, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x004b, 0x018c, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x004b, 0x0190, nv04_graph_mthd_bind_surf_dst); + NVOBJ_MTHD (dev, 0x004b, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv04 gdirect */ + NVOBJ_CLASS(dev, 0x004a, GR); + NVOBJ_MTHD (dev, 0x004a, 0x0188, nv04_graph_mthd_bind_nv04_patt); + NVOBJ_MTHD (dev, 0x004a, 0x018c, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x004a, 0x0190, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x004a, 0x0194, nv04_graph_mthd_bind_beta4); + NVOBJ_MTHD (dev, 0x004a, 0x0198, nv04_graph_mthd_bind_surf2d); + NVOBJ_MTHD (dev, 0x004a, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv01 imageblit */ + NVOBJ_CLASS(dev, 0x001f, GR); + NVOBJ_MTHD (dev, 0x001f, 0x0184, nv04_graph_mthd_bind_chroma); + NVOBJ_MTHD (dev, 0x001f, 0x0188, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x001f, 0x018c, nv04_graph_mthd_bind_nv01_patt); + NVOBJ_MTHD (dev, 0x001f, 0x0190, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x001f, 0x0194, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x001f, 0x0198, nv04_graph_mthd_bind_surf_dst); + NVOBJ_MTHD (dev, 0x001f, 0x019c, nv04_graph_mthd_bind_surf_src); + NVOBJ_MTHD (dev, 0x001f, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv04 imageblit */ + NVOBJ_CLASS(dev, 0x005f, GR); + NVOBJ_MTHD (dev, 0x005f, 0x0184, nv04_graph_mthd_bind_chroma); + NVOBJ_MTHD (dev, 0x005f, 0x0188, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x005f, 0x018c, nv04_graph_mthd_bind_nv04_patt); + NVOBJ_MTHD (dev, 0x005f, 0x0190, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x005f, 0x0194, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x005f, 0x0198, nv04_graph_mthd_bind_beta4); + NVOBJ_MTHD (dev, 0x005f, 0x019c, nv04_graph_mthd_bind_surf2d); + NVOBJ_MTHD (dev, 0x005f, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv04 iifc */ + NVOBJ_CLASS(dev, 0x0060, GR); + NVOBJ_MTHD (dev, 0x0060, 0x0188, nv04_graph_mthd_bind_chroma); + NVOBJ_MTHD (dev, 0x0060, 0x018c, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x0060, 0x0190, nv04_graph_mthd_bind_nv04_patt); + NVOBJ_MTHD (dev, 0x0060, 0x0194, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x0060, 0x0198, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x0060, 0x019c, nv04_graph_mthd_bind_beta4); + NVOBJ_MTHD (dev, 0x0060, 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf); + NVOBJ_MTHD (dev, 0x0060, 0x03e4, nv04_graph_mthd_set_operation); + + /* nv05 iifc */ + NVOBJ_CLASS(dev, 0x0064, GR); + + /* nv01 ifc */ + NVOBJ_CLASS(dev, 0x0021, GR); + NVOBJ_MTHD (dev, 0x0021, 0x0184, nv04_graph_mthd_bind_chroma); + NVOBJ_MTHD (dev, 0x0021, 0x0188, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x0021, 0x018c, nv04_graph_mthd_bind_nv01_patt); + NVOBJ_MTHD (dev, 0x0021, 0x0190, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x0021, 0x0194, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x0021, 0x0198, nv04_graph_mthd_bind_surf_dst); + NVOBJ_MTHD (dev, 0x0021, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv04 ifc */ + NVOBJ_CLASS(dev, 0x0061, GR); + NVOBJ_MTHD (dev, 0x0061, 0x0184, nv04_graph_mthd_bind_chroma); + NVOBJ_MTHD (dev, 0x0061, 0x0188, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x0061, 0x018c, nv04_graph_mthd_bind_nv04_patt); + NVOBJ_MTHD (dev, 0x0061, 0x0190, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x0061, 0x0194, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x0061, 0x0198, nv04_graph_mthd_bind_beta4); + NVOBJ_MTHD (dev, 0x0061, 0x019c, nv04_graph_mthd_bind_surf2d); + NVOBJ_MTHD (dev, 0x0061, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv05 ifc */ + NVOBJ_CLASS(dev, 0x0065, GR); + + /* nv03 sifc */ + NVOBJ_CLASS(dev, 0x0036, GR); + NVOBJ_MTHD (dev, 0x0036, 0x0184, nv04_graph_mthd_bind_chroma); + NVOBJ_MTHD (dev, 0x0036, 0x0188, nv04_graph_mthd_bind_nv01_patt); + NVOBJ_MTHD (dev, 0x0036, 0x018c, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x0036, 0x0190, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x0036, 0x0194, nv04_graph_mthd_bind_surf_dst); + NVOBJ_MTHD (dev, 0x0036, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv04 sifc */ + NVOBJ_CLASS(dev, 0x0076, GR); + NVOBJ_MTHD (dev, 0x0076, 0x0184, nv04_graph_mthd_bind_chroma); + NVOBJ_MTHD (dev, 0x0076, 0x0188, nv04_graph_mthd_bind_nv04_patt); + NVOBJ_MTHD (dev, 0x0076, 0x018c, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x0076, 0x0190, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x0076, 0x0194, nv04_graph_mthd_bind_beta4); + NVOBJ_MTHD (dev, 0x0076, 0x0198, nv04_graph_mthd_bind_surf2d); + NVOBJ_MTHD (dev, 0x0076, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv05 sifc */ + NVOBJ_CLASS(dev, 0x0066, GR); + + /* nv03 sifm */ + NVOBJ_CLASS(dev, 0x0037, GR); + NVOBJ_MTHD (dev, 0x0037, 0x0188, nv04_graph_mthd_bind_nv01_patt); + NVOBJ_MTHD (dev, 0x0037, 0x018c, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x0037, 0x0190, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x0037, 0x0194, nv04_graph_mthd_bind_surf_dst); + NVOBJ_MTHD (dev, 0x0037, 0x0304, nv04_graph_mthd_set_operation); + + /* nv04 sifm */ + NVOBJ_CLASS(dev, 0x0077, GR); + NVOBJ_MTHD (dev, 0x0077, 0x0188, nv04_graph_mthd_bind_nv04_patt); + NVOBJ_MTHD (dev, 0x0077, 0x018c, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x0077, 0x0190, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x0077, 0x0194, nv04_graph_mthd_bind_beta4); + NVOBJ_MTHD (dev, 0x0077, 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf); + NVOBJ_MTHD (dev, 0x0077, 0x0304, nv04_graph_mthd_set_operation); + + /* null */ + NVOBJ_CLASS(dev, 0x0030, GR); + + /* surf2d */ + NVOBJ_CLASS(dev, 0x0042, GR); + + /* rop */ + NVOBJ_CLASS(dev, 0x0043, GR); + + /* beta1 */ + NVOBJ_CLASS(dev, 0x0012, GR); + + /* beta4 */ + NVOBJ_CLASS(dev, 0x0072, GR); + + /* cliprect */ + NVOBJ_CLASS(dev, 0x0019, GR); + + /* nv01 pattern */ + NVOBJ_CLASS(dev, 0x0018, GR); + + /* nv04 pattern */ + NVOBJ_CLASS(dev, 0x0044, GR); + + /* swzsurf */ + NVOBJ_CLASS(dev, 0x0052, GR); + + /* surf3d */ + NVOBJ_CLASS(dev, 0x0053, GR); + NVOBJ_MTHD (dev, 0x0053, 0x02f8, nv04_graph_mthd_surf3d_clip_h); + NVOBJ_MTHD (dev, 0x0053, 0x02fc, nv04_graph_mthd_surf3d_clip_v); + + /* nv03 tex_tri */ + NVOBJ_CLASS(dev, 0x0048, GR); + NVOBJ_MTHD (dev, 0x0048, 0x0188, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x0048, 0x018c, nv04_graph_mthd_bind_surf_color); + NVOBJ_MTHD (dev, 0x0048, 0x0190, nv04_graph_mthd_bind_surf_zeta); + + /* tex_tri */ + NVOBJ_CLASS(dev, 0x0054, GR); + + /* multitex_tri */ + NVOBJ_CLASS(dev, 0x0055, GR); + + /* nv01 chroma */ + NVOBJ_CLASS(dev, 0x0017, GR); + + /* nv04 chroma */ + NVOBJ_CLASS(dev, 0x0057, GR); + + /* surf_dst */ + NVOBJ_CLASS(dev, 0x0058, GR); + + /* surf_src */ + NVOBJ_CLASS(dev, 0x0059, GR); + + /* surf_color */ + NVOBJ_CLASS(dev, 0x005a, GR); + + /* surf_zeta */ + NVOBJ_CLASS(dev, 0x005b, GR); + + /* nv01 line */ + NVOBJ_CLASS(dev, 0x001c, GR); + NVOBJ_MTHD (dev, 0x001c, 0x0184, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x001c, 0x0188, nv04_graph_mthd_bind_nv01_patt); + NVOBJ_MTHD (dev, 0x001c, 0x018c, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x001c, 0x0190, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x001c, 0x0194, nv04_graph_mthd_bind_surf_dst); + NVOBJ_MTHD (dev, 0x001c, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv04 line */ + NVOBJ_CLASS(dev, 0x005c, GR); + NVOBJ_MTHD (dev, 0x005c, 0x0184, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x005c, 0x0188, nv04_graph_mthd_bind_nv04_patt); + NVOBJ_MTHD (dev, 0x005c, 0x018c, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x005c, 0x0190, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x005c, 0x0194, nv04_graph_mthd_bind_beta4); + NVOBJ_MTHD (dev, 0x005c, 0x0198, nv04_graph_mthd_bind_surf2d); + NVOBJ_MTHD (dev, 0x005c, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv01 tri */ + NVOBJ_CLASS(dev, 0x001d, GR); + NVOBJ_MTHD (dev, 0x001d, 0x0184, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x001d, 0x0188, nv04_graph_mthd_bind_nv01_patt); + NVOBJ_MTHD (dev, 0x001d, 0x018c, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x001d, 0x0190, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x001d, 0x0194, nv04_graph_mthd_bind_surf_dst); + NVOBJ_MTHD (dev, 0x001d, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv04 tri */ + NVOBJ_CLASS(dev, 0x005d, GR); + NVOBJ_MTHD (dev, 0x005d, 0x0184, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x005d, 0x0188, nv04_graph_mthd_bind_nv04_patt); + NVOBJ_MTHD (dev, 0x005d, 0x018c, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x005d, 0x0190, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x005d, 0x0194, nv04_graph_mthd_bind_beta4); + NVOBJ_MTHD (dev, 0x005d, 0x0198, nv04_graph_mthd_bind_surf2d); + NVOBJ_MTHD (dev, 0x005d, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv01 rect */ + NVOBJ_CLASS(dev, 0x001e, GR); + NVOBJ_MTHD (dev, 0x001e, 0x0184, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x001e, 0x0188, nv04_graph_mthd_bind_nv01_patt); + NVOBJ_MTHD (dev, 0x001e, 0x018c, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x001e, 0x0190, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x001e, 0x0194, nv04_graph_mthd_bind_surf_dst); + NVOBJ_MTHD (dev, 0x001e, 0x02fc, nv04_graph_mthd_set_operation); + + /* nv04 rect */ + NVOBJ_CLASS(dev, 0x005e, GR); + NVOBJ_MTHD (dev, 0x005e, 0x0184, nv04_graph_mthd_bind_clip); + NVOBJ_MTHD (dev, 0x005e, 0x0188, nv04_graph_mthd_bind_nv04_patt); + NVOBJ_MTHD (dev, 0x005e, 0x018c, nv04_graph_mthd_bind_rop); + NVOBJ_MTHD (dev, 0x005e, 0x0190, nv04_graph_mthd_bind_beta1); + NVOBJ_MTHD (dev, 0x005e, 0x0194, nv04_graph_mthd_bind_beta4); + NVOBJ_MTHD (dev, 0x005e, 0x0198, nv04_graph_mthd_bind_surf2d); + NVOBJ_MTHD (dev, 0x005e, 0x02fc, nv04_graph_mthd_set_operation); + + /* nvsw */ + NVOBJ_CLASS(dev, 0x506e, SW); + NVOBJ_MTHD (dev, 0x506e, 0x0150, nv04_graph_mthd_set_ref); + NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_shape[] = { - { 0x0184, nv04_graph_mthd_bind_clip }, - { 0x0188, nv04_graph_mthd_bind_nv04_patt }, - { 0x018c, nv04_graph_mthd_bind_rop }, - { 0x0190, nv04_graph_mthd_bind_beta1 }, - { 0x0194, nv04_graph_mthd_bind_beta4 }, - { 0x0198, nv04_graph_mthd_bind_surf2d }, - { 0x02fc, nv04_graph_mthd_set_operation }, - {}, + dev_priv->engine.graph.registered = true; + return 0; }; -static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_tex_tri[] = { - { 0x0188, nv04_graph_mthd_bind_clip }, - { 0x018c, nv04_graph_mthd_bind_surf_color }, - { 0x0190, nv04_graph_mthd_bind_surf_zeta }, - {}, +static struct nouveau_bitfield nv04_graph_intr[] = { + { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, + {} }; -static struct nouveau_pgraph_object_method nv04_graph_mthds_surf3d[] = { - { 0x02f8, nv04_graph_mthd_surf3d_clip_h }, - { 0x02fc, nv04_graph_mthd_surf3d_clip_v }, - {}, +static struct nouveau_bitfield nv04_graph_nstatus[] = +{ + { NV04_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, + { NV04_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, + { NV04_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, + { NV04_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" }, + {} }; -struct nouveau_pgraph_object_class nv04_graph_grclass[] = { - { 0x0038, false, NULL }, /* dvd subpicture */ - { 0x0039, false, NULL }, /* m2mf */ - { 0x004b, false, nv04_graph_mthds_nv03_gdirect }, /* nv03 gdirect */ - { 0x004a, false, nv04_graph_mthds_nv04_gdirect }, /* nv04 gdirect */ - { 0x001f, false, nv04_graph_mthds_nv01_imageblit }, /* nv01 imageblit */ - { 0x005f, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 imageblit */ - { 0x0060, false, nv04_graph_mthds_nv04_iifc }, /* nv04 iifc */ - { 0x0064, false, NULL }, /* nv05 iifc */ - { 0x0021, false, nv04_graph_mthds_nv01_ifc }, /* nv01 ifc */ - { 0x0061, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 ifc */ - { 0x0065, false, NULL }, /* nv05 ifc */ - { 0x0036, false, nv04_graph_mthds_nv03_sifc }, /* nv03 sifc */ - { 0x0076, false, nv04_graph_mthds_nv04_sifc }, /* nv04 sifc */ - { 0x0066, false, NULL }, /* nv05 sifc */ - { 0x0037, false, nv04_graph_mthds_nv03_sifm }, /* nv03 sifm */ - { 0x0077, false, nv04_graph_mthds_nv04_sifm }, /* nv04 sifm */ - { 0x0030, false, NULL }, /* null */ - { 0x0042, false, NULL }, /* surf2d */ - { 0x0043, false, NULL }, /* rop */ - { 0x0012, false, NULL }, /* beta1 */ - { 0x0072, false, NULL }, /* beta4 */ - { 0x0019, false, NULL }, /* cliprect */ - { 0x0018, false, NULL }, /* nv01 pattern */ - { 0x0044, false, NULL }, /* nv04 pattern */ - { 0x0052, false, NULL }, /* swzsurf */ - { 0x0053, false, nv04_graph_mthds_surf3d }, /* surf3d */ - { 0x0048, false, nv04_graph_mthds_nv03_tex_tri }, /* nv03 tex_tri */ - { 0x0054, false, NULL }, /* tex_tri */ - { 0x0055, false, NULL }, /* multitex_tri */ - { 0x0017, false, NULL }, /* nv01 chroma */ - { 0x0057, false, NULL }, /* nv04 chroma */ - { 0x0058, false, NULL }, /* surf_dst */ - { 0x0059, false, NULL }, /* surf_src */ - { 0x005a, false, NULL }, /* surf_color */ - { 0x005b, false, NULL }, /* surf_zeta */ - { 0x001c, false, nv04_graph_mthds_nv01_shape }, /* nv01 line */ - { 0x005c, false, nv04_graph_mthds_nv04_shape }, /* nv04 line */ - { 0x001d, false, nv04_graph_mthds_nv01_shape }, /* nv01 tri */ - { 0x005d, false, nv04_graph_mthds_nv04_shape }, /* nv04 tri */ - { 0x001e, false, nv04_graph_mthds_nv01_shape }, /* nv01 rect */ - { 0x005e, false, nv04_graph_mthds_nv04_shape }, /* nv04 rect */ - { 0x506e, true, nv04_graph_mthds_sw }, +struct nouveau_bitfield nv04_graph_nsource[] = +{ + { NV03_PGRAPH_NSOURCE_NOTIFICATION, "NOTIFICATION" }, + { NV03_PGRAPH_NSOURCE_DATA_ERROR, "DATA_ERROR" }, + { NV03_PGRAPH_NSOURCE_PROTECTION_ERROR, "PROTECTION_ERROR" }, + { NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION, "RANGE_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_LIMIT_COLOR, "LIMIT_COLOR" }, + { NV03_PGRAPH_NSOURCE_LIMIT_ZETA, "LIMIT_ZETA" }, + { NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD, "ILLEGAL_MTHD" }, + { NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION, "DMA_R_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION, "DMA_W_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION, "FORMAT_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION, "PATCH_EXCEPTION" }, + { NV03_PGRAPH_NSOURCE_STATE_INVALID, "STATE_INVALID" }, + { NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY, "DOUBLE_NOTIFY" }, + { NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE, "NOTIFY_IN_USE" }, + { NV03_PGRAPH_NSOURCE_METHOD_CNT, "METHOD_CNT" }, + { NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION, "BFR_NOTIFICATION" }, + { NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" }, + { NV03_PGRAPH_NSOURCE_DMA_WIDTH_A, "DMA_WIDTH_A" }, + { NV03_PGRAPH_NSOURCE_DMA_WIDTH_B, "DMA_WIDTH_B" }, {} }; +static void +nv04_graph_isr(struct drm_device *dev) +{ + u32 stat; + + while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { + u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); + u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); + u32 chid = (addr & 0x0f000000) >> 24; + u32 subc = (addr & 0x0000e000) >> 13; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(dev, 0x400180 + subc * 4) & 0xff; + u32 show = stat; + + if (stat & NV_PGRAPH_INTR_NOTIFY) { + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { + if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) + show &= ~NV_PGRAPH_INTR_NOTIFY; + } + } + + if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { + nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); + stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + nv04_graph_context_switch(dev); + } + + nv_wr32(dev, NV03_PGRAPH_INTR, stat); + nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); + + if (show && nouveau_ratelimit()) { + NV_INFO(dev, "PGRAPH -"); + nouveau_bitfield_print(nv04_graph_intr, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv04_graph_nstatus, nstatus); + printk("\n"); + NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); + } + } +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv04_instmem.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv04_instmem.c @@ -98,42 +98,66 @@ } int -nv04_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, - uint32_t *sz) +nv04_instmem_suspend(struct drm_device *dev) { return 0; } void -nv04_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +nv04_instmem_resume(struct drm_device *dev) { } int -nv04_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +nv04_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) { - return 0; -} + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct drm_mm_node *ramin = NULL; -int -nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) -{ + do { + if (drm_mm_pre_get(&dev_priv->ramin_heap)) + return -ENOMEM; + + spin_lock(&dev_priv->ramin_lock); + ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); + if (ramin == NULL) { + spin_unlock(&dev_priv->ramin_lock); + return -ENOMEM; + } + + ramin = drm_mm_get_block_atomic(ramin, size, align); + spin_unlock(&dev_priv->ramin_lock); + } while (ramin == NULL); + + gpuobj->node = ramin; + gpuobj->vinst = ramin->start; return 0; } void -nv04_instmem_flush(struct drm_device *dev) +nv04_instmem_put(struct nouveau_gpuobj *gpuobj) { + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + + spin_lock(&dev_priv->ramin_lock); + drm_mm_put_block(gpuobj->node); + gpuobj->node = NULL; + spin_unlock(&dev_priv->ramin_lock); } int -nv04_instmem_suspend(struct drm_device *dev) +nv04_instmem_map(struct nouveau_gpuobj *gpuobj) { + gpuobj->pinst = gpuobj->vinst; return 0; } void -nv04_instmem_resume(struct drm_device *dev) +nv04_instmem_unmap(struct nouveau_gpuobj *gpuobj) { } +void +nv04_instmem_flush(struct drm_device *dev) +{ +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv10_fb.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv10_fb.c @@ -3,23 +3,109 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" +static struct drm_mm_node * +nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + struct drm_mm_node *mem; + int ret; + + ret = drm_mm_pre_get(&pfb->tag_heap); + if (ret) + return NULL; + + spin_lock(&dev_priv->tile.lock); + mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0); + if (mem) + mem = drm_mm_get_block_atomic(mem, size, 0); + spin_unlock(&dev_priv->tile.lock); + + return mem; +} + +static void +nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node *mem) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + spin_lock(&dev_priv->tile.lock); + drm_mm_put_block(mem); + spin_unlock(&dev_priv->tile.lock); +} + +void +nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch, uint32_t flags) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16); + + tile->addr = addr; + tile->limit = max(1u, addr + size) - 1; + tile->pitch = pitch; + + if (dev_priv->card_type == NV_20) { + if (flags & NOUVEAU_GEM_TILE_ZETA) { + /* + * Allocate some of the on-die tag memory, + * used to store Z compression meta-data (most + * likely just a bitmap determining if a given + * tile is compressed or not). + */ + tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256); + + if (tile->tag_mem) { + /* Enable Z compression */ + if (dev_priv->chipset >= 0x25) + tile->zcomp = tile->tag_mem->start | + (bpp == 16 ? + NV25_PFB_ZCOMP_MODE_16 : + NV25_PFB_ZCOMP_MODE_32); + else + tile->zcomp = tile->tag_mem->start | + NV20_PFB_ZCOMP_EN | + (bpp == 16 ? 0 : + NV20_PFB_ZCOMP_MODE_32); + } + + tile->addr |= 3; + } else { + tile->addr |= 1; + } + + } else { + tile->addr |= 1 << 31; + } +} + void -nv10_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch) +nv10_fb_free_tile_region(struct drm_device *dev, int i) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t limit = max(1u, addr + size) - 1; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - if (pitch) { - if (dev_priv->card_type >= NV_20) - addr |= 1; - else - addr |= 1 << 31; + if (tile->tag_mem) { + nv20_fb_free_tag(dev, tile->tag_mem); + tile->tag_mem = NULL; } - nv_wr32(dev, NV10_PFB_TLIMIT(i), limit); - nv_wr32(dev, NV10_PFB_TSIZE(i), pitch); - nv_wr32(dev, NV10_PFB_TILE(i), addr); + tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; +} + +void +nv10_fb_set_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); + nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); + nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); + + if (dev_priv->card_type == NV_20) + nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp); } int @@ -31,9 +117,14 @@ pfb->num_tiles = NV10_PFB_TILE__SIZE; + if (dev_priv->card_type == NV_20) + drm_mm_init(&pfb->tag_heap, 0, + (dev_priv->chipset >= 0x25 ? + 64 * 1024 : 32 * 1024)); + /* Turn all the tiling regions off. */ for (i = 0; i < pfb->num_tiles; i++) - pfb->set_region_tiling(dev, i, 0, 0, 0); + pfb->set_tile_region(dev, i); return 0; } @@ -41,4 +132,13 @@ void nv10_fb_takedown(struct drm_device *dev) { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; + int i; + + for (i = 0; i < pfb->num_tiles; i++) + pfb->free_tile_region(dev, i); + + if (dev_priv->card_type == NV_20) + drm_mm_takedown(&pfb->tag_heap); } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv10_fifo.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv10_fifo.c @@ -53,6 +53,11 @@ if (ret) return ret; + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV03_USER(chan->id), PAGE_SIZE); + if (!chan->user) + return -ENOMEM; + /* Fill entries that are seen filled in dumps of nvidia driver just * after channel's is put into DMA mode */ @@ -73,17 +78,6 @@ return 0; } -void -nv10_fifo_destroy_context(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - - nv_wr32(dev, NV04_PFIFO_MODE, - nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); - - nouveau_gpuobj_ref(NULL, &chan->ramfc); -} - static void nv10_fifo_do_load_context(struct drm_device *dev, int chid) { @@ -219,6 +213,7 @@ static void nv10_fifo_init_intr(struct drm_device *dev) { + nouveau_irq_register(dev, 8, nv04_fifo_isr); nv_wr32(dev, 0x002100, 0xffffffff); nv_wr32(dev, 0x002140, 0xffffffff); } @@ -241,7 +236,7 @@ pfifo->reassign(dev, true); for (i = 0; i < dev_priv->engine.fifo.channels; i++) { - if (dev_priv->fifos[i]) { + if (dev_priv->channels.ptr[i]) { uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv10_graph.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv10_graph.c @@ -26,6 +26,10 @@ #include "drm.h" #include "nouveau_drm.h" #include "nouveau_drv.h" +#include "nouveau_util.h" + +static int nv10_graph_register(struct drm_device *); +static void nv10_graph_isr(struct drm_device *); #define NV10_FIFO_NUMBER 32 @@ -786,15 +790,13 @@ return 0; } -void +static void nv10_graph_context_switch(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct nouveau_channel *chan = NULL; int chid; - pgraph->fifo_access(dev, false); nouveau_wait_for_idle(dev); /* If previous context is valid, we need to save it */ @@ -802,11 +804,9 @@ /* Load context for next channel */ chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f; - chan = dev_priv->fifos[chid]; + chan = dev_priv->channels.ptr[chid]; if (chan && chan->pgraph_ctx) nv10_graph_load_context(chan); - - pgraph->fifo_access(dev, true); } #define NV_WRITE_CTX(reg, val) do { \ @@ -833,7 +833,7 @@ if (chid >= dev_priv->engine.fifo.channels) return NULL; - return dev_priv->fifos[chid]; + return dev_priv->channels.ptr[chid]; } int nv10_graph_create_context(struct nouveau_channel *chan) @@ -875,37 +875,54 @@ void nv10_graph_destroy_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; struct graph_state *pgraph_ctx = chan->pgraph_ctx; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + pgraph->fifo_access(dev, false); + + /* Unload the context if it's the currently active one */ + if (pgraph->channel(dev) == chan) + pgraph->unload_context(dev); + /* Free the context resources */ kfree(pgraph_ctx); chan->pgraph_ctx = NULL; + + pgraph->fifo_access(dev, true); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); } void -nv10_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch) +nv10_graph_set_tile_region(struct drm_device *dev, int i) { - uint32_t limit = max(1u, addr + size) - 1; - - if (pitch) - addr |= 1 << 31; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), limit); - nv_wr32(dev, NV10_PGRAPH_TSIZE(i), pitch); - nv_wr32(dev, NV10_PGRAPH_TILE(i), addr); + nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(dev, NV10_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(dev, NV10_PGRAPH_TILE(i), tile->addr); } int nv10_graph_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t tmp; - int i; + int ret, i; nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); + ret = nv10_graph_register(dev); + if (ret) + return ret; + + nouveau_irq_register(dev, 12, nv10_graph_isr); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); @@ -928,7 +945,7 @@ /* Turn all the tiling regions off. */ for (i = 0; i < NV10_PFB_TILE__SIZE; i++) - nv10_graph_set_region_tiling(dev, i, 0, 0, 0); + nv10_graph_set_tile_region(dev, i); nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); @@ -948,17 +965,17 @@ void nv10_graph_takedown(struct drm_device *dev) { + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); + nouveau_irq_unregister(dev, 12); } static int -nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv17_graph_mthd_lma_window(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { struct drm_device *dev = chan->dev; struct graph_state *ctx = chan->pgraph_ctx; struct pipe_state *pipe = &ctx->pipe_state; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3]; uint32_t xfmode0, xfmode1; int i; @@ -1025,18 +1042,14 @@ nouveau_wait_for_idle(dev); - pgraph->fifo_access(dev, true); - return 0; } static int -nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { struct drm_device *dev = chan->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; nouveau_wait_for_idle(dev); @@ -1045,40 +1058,118 @@ nv_wr32(dev, 0x004006b0, nv_rd32(dev, 0x004006b0) | 0x8 << 24); - pgraph->fifo_access(dev, true); + return 0; +} + +static int +nv10_graph_register(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->engine.graph.registered) + return 0; + + NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ + NVOBJ_CLASS(dev, 0x0030, GR); /* null */ + NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ + NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ + NVOBJ_CLASS(dev, 0x005f, GR); /* imageblit */ + NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ + NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ + NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ + NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ + NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ + NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ + NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ + NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ + NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ + NVOBJ_CLASS(dev, 0x0052, GR); /* swzsurf */ + NVOBJ_CLASS(dev, 0x0093, GR); /* surf3d */ + NVOBJ_CLASS(dev, 0x0094, GR); /* tex_tri */ + NVOBJ_CLASS(dev, 0x0095, GR); /* multitex_tri */ + + /* celcius */ + if (dev_priv->chipset <= 0x10) { + NVOBJ_CLASS(dev, 0x0056, GR); + } else + if (dev_priv->chipset < 0x17 || dev_priv->chipset == 0x1a) { + NVOBJ_CLASS(dev, 0x0096, GR); + } else { + NVOBJ_CLASS(dev, 0x0099, GR); + NVOBJ_MTHD (dev, 0x0099, 0x1638, nv17_graph_mthd_lma_window); + NVOBJ_MTHD (dev, 0x0099, 0x163c, nv17_graph_mthd_lma_window); + NVOBJ_MTHD (dev, 0x0099, 0x1640, nv17_graph_mthd_lma_window); + NVOBJ_MTHD (dev, 0x0099, 0x1644, nv17_graph_mthd_lma_window); + NVOBJ_MTHD (dev, 0x0099, 0x1658, nv17_graph_mthd_lma_enable); + } + + /* nvsw */ + NVOBJ_CLASS(dev, 0x506e, SW); + NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); + dev_priv->engine.graph.registered = true; return 0; } -static struct nouveau_pgraph_object_method nv17_graph_celsius_mthds[] = { - { 0x1638, nv17_graph_mthd_lma_window }, - { 0x163c, nv17_graph_mthd_lma_window }, - { 0x1640, nv17_graph_mthd_lma_window }, - { 0x1644, nv17_graph_mthd_lma_window }, - { 0x1658, nv17_graph_mthd_lma_enable }, +struct nouveau_bitfield nv10_graph_intr[] = { + { NV_PGRAPH_INTR_NOTIFY, "NOTIFY" }, + { NV_PGRAPH_INTR_ERROR, "ERROR" }, {} }; -struct nouveau_pgraph_object_class nv10_graph_grclass[] = { - { 0x0030, false, NULL }, /* null */ - { 0x0039, false, NULL }, /* m2mf */ - { 0x004a, false, NULL }, /* gdirect */ - { 0x005f, false, NULL }, /* imageblit */ - { 0x009f, false, NULL }, /* imageblit (nv12) */ - { 0x008a, false, NULL }, /* ifc */ - { 0x0089, false, NULL }, /* sifm */ - { 0x0062, false, NULL }, /* surf2d */ - { 0x0043, false, NULL }, /* rop */ - { 0x0012, false, NULL }, /* beta1 */ - { 0x0072, false, NULL }, /* beta4 */ - { 0x0019, false, NULL }, /* cliprect */ - { 0x0044, false, NULL }, /* pattern */ - { 0x0052, false, NULL }, /* swzsurf */ - { 0x0093, false, NULL }, /* surf3d */ - { 0x0094, false, NULL }, /* tex_tri */ - { 0x0095, false, NULL }, /* multitex_tri */ - { 0x0056, false, NULL }, /* celcius (nv10) */ - { 0x0096, false, NULL }, /* celcius (nv11) */ - { 0x0099, false, nv17_graph_celsius_mthds }, /* celcius (nv17) */ +struct nouveau_bitfield nv10_graph_nstatus[] = +{ + { NV10_PGRAPH_NSTATUS_STATE_IN_USE, "STATE_IN_USE" }, + { NV10_PGRAPH_NSTATUS_INVALID_STATE, "INVALID_STATE" }, + { NV10_PGRAPH_NSTATUS_BAD_ARGUMENT, "BAD_ARGUMENT" }, + { NV10_PGRAPH_NSTATUS_PROTECTION_FAULT, "PROTECTION_FAULT" }, {} }; + +static void +nv10_graph_isr(struct drm_device *dev) +{ + u32 stat; + + while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { + u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); + u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); + u32 chid = (addr & 0x01f00000) >> 20; + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff; + u32 show = stat; + + if (stat & NV_PGRAPH_INTR_ERROR) { + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { + if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) + show &= ~NV_PGRAPH_INTR_ERROR; + } + } + + if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) { + nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); + stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; + nv10_graph_context_switch(dev); + } + + nv_wr32(dev, NV03_PGRAPH_INTR, stat); + nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); + + if (show && nouveau_ratelimit()) { + NV_INFO(dev, "PGRAPH -"); + nouveau_bitfield_print(nv10_graph_intr, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv10_graph_nstatus, nstatus); + printk("\n"); + NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); + } + } +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv20_graph.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv20_graph.c @@ -32,6 +32,10 @@ #define NV34_GRCTX_SIZE (18140) #define NV35_36_GRCTX_SIZE (22396) +static int nv20_graph_register(struct drm_device *); +static int nv30_graph_register(struct drm_device *); +static void nv20_graph_isr(struct drm_device *); + static void nv20_graph_context_init(struct drm_device *dev, struct nouveau_gpuobj *ctx) { @@ -425,9 +429,21 @@ struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + unsigned long flags; - nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + pgraph->fifo_access(dev, false); + + /* Unload the context if it's the currently active one */ + if (pgraph->channel(dev) == chan) + pgraph->unload_context(dev); + + pgraph->fifo_access(dev, true); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* Free the context resources */ nv_wo32(pgraph->ctx_table, chan->id * 4, 0); + nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); } int @@ -496,24 +512,27 @@ } void -nv20_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch) +nv20_graph_set_tile_region(struct drm_device *dev, int i) { - uint32_t limit = max(1u, addr + size) - 1; - - if (pitch) - addr |= 1; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; - nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); - nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); - nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); + nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0030 + 4 * i); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, limit); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->limit); nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0050 + 4 * i); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, pitch); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->pitch); nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0010 + 4 * i); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, addr); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->addr); + + if (dev_priv->card_type == NV_20) { + nv_wr32(dev, NV20_PGRAPH_ZCOMP(i), tile->zcomp); + nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00ea0090 + 4 * i); + nv_wr32(dev, NV10_PGRAPH_RDI_DATA, tile->zcomp); + } } int @@ -560,6 +579,13 @@ nv20_graph_rdi(dev); + ret = nv20_graph_register(dev); + if (ret) { + nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); + return ret; + } + + nouveau_irq_register(dev, 12, nv20_graph_isr); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); @@ -571,16 +597,17 @@ nv_wr32(dev, 0x40009C , 0x00000040); if (dev_priv->chipset >= 0x25) { - nv_wr32(dev, 0x400890, 0x00080000); + nv_wr32(dev, 0x400890, 0x00a8cfff); nv_wr32(dev, 0x400610, 0x304B1FB6); - nv_wr32(dev, 0x400B80, 0x18B82880); + nv_wr32(dev, 0x400B80, 0x1cbd3883); nv_wr32(dev, 0x400B84, 0x44000000); nv_wr32(dev, 0x400098, 0x40000080); nv_wr32(dev, 0x400B88, 0x000000ff); + } else { - nv_wr32(dev, 0x400880, 0x00080000); /* 0x0008c7df */ + nv_wr32(dev, 0x400880, 0x0008c7df); nv_wr32(dev, 0x400094, 0x00000005); - nv_wr32(dev, 0x400B80, 0x45CAA208); /* 0x45eae20e */ + nv_wr32(dev, 0x400B80, 0x45eae20e); nv_wr32(dev, 0x400B84, 0x24000000); nv_wr32(dev, 0x400098, 0x00000040); nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00E00038); @@ -591,14 +618,8 @@ /* Turn all the tiling regions off. */ for (i = 0; i < NV10_PFB_TILE__SIZE; i++) - nv20_graph_set_region_tiling(dev, i, 0, 0, 0); + nv20_graph_set_tile_region(dev, i); - for (i = 0; i < 8; i++) { - nv_wr32(dev, 0x400980 + i * 4, nv_rd32(dev, 0x100300 + i * 4)); - nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA0090 + i * 4); - nv_wr32(dev, NV10_PGRAPH_RDI_DATA, - nv_rd32(dev, 0x100300 + i * 4)); - } nv_wr32(dev, 0x4009a0, nv_rd32(dev, 0x100324)); nv_wr32(dev, NV10_PGRAPH_RDI_INDEX, 0x00EA000C); nv_wr32(dev, NV10_PGRAPH_RDI_DATA, nv_rd32(dev, 0x100324)); @@ -642,6 +663,9 @@ struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); + nouveau_irq_unregister(dev, 12); + nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); } @@ -684,9 +708,16 @@ return ret; } + ret = nv30_graph_register(dev); + if (ret) { + nouveau_gpuobj_ref(NULL, &pgraph->ctx_table); + return ret; + } + nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_TABLE, pgraph->ctx_table->pinst >> 4); + nouveau_irq_register(dev, 12, nv20_graph_isr); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF); @@ -724,7 +755,7 @@ /* Turn all the tiling regions off. */ for (i = 0; i < NV10_PFB_TILE__SIZE; i++) - nv20_graph_set_region_tiling(dev, i, 0, 0, 0); + nv20_graph_set_tile_region(dev, i); nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100); nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); @@ -744,46 +775,125 @@ return 0; } -struct nouveau_pgraph_object_class nv20_graph_grclass[] = { - { 0x0030, false, NULL }, /* null */ - { 0x0039, false, NULL }, /* m2mf */ - { 0x004a, false, NULL }, /* gdirect */ - { 0x009f, false, NULL }, /* imageblit (nv12) */ - { 0x008a, false, NULL }, /* ifc */ - { 0x0089, false, NULL }, /* sifm */ - { 0x0062, false, NULL }, /* surf2d */ - { 0x0043, false, NULL }, /* rop */ - { 0x0012, false, NULL }, /* beta1 */ - { 0x0072, false, NULL }, /* beta4 */ - { 0x0019, false, NULL }, /* cliprect */ - { 0x0044, false, NULL }, /* pattern */ - { 0x009e, false, NULL }, /* swzsurf */ - { 0x0096, false, NULL }, /* celcius */ - { 0x0097, false, NULL }, /* kelvin (nv20) */ - { 0x0597, false, NULL }, /* kelvin (nv25) */ - {} -}; - -struct nouveau_pgraph_object_class nv30_graph_grclass[] = { - { 0x0030, false, NULL }, /* null */ - { 0x0039, false, NULL }, /* m2mf */ - { 0x004a, false, NULL }, /* gdirect */ - { 0x009f, false, NULL }, /* imageblit (nv12) */ - { 0x008a, false, NULL }, /* ifc */ - { 0x038a, false, NULL }, /* ifc (nv30) */ - { 0x0089, false, NULL }, /* sifm */ - { 0x0389, false, NULL }, /* sifm (nv30) */ - { 0x0062, false, NULL }, /* surf2d */ - { 0x0362, false, NULL }, /* surf2d (nv30) */ - { 0x0043, false, NULL }, /* rop */ - { 0x0012, false, NULL }, /* beta1 */ - { 0x0072, false, NULL }, /* beta4 */ - { 0x0019, false, NULL }, /* cliprect */ - { 0x0044, false, NULL }, /* pattern */ - { 0x039e, false, NULL }, /* swzsurf */ - { 0x0397, false, NULL }, /* rankine (nv30) */ - { 0x0497, false, NULL }, /* rankine (nv35) */ - { 0x0697, false, NULL }, /* rankine (nv34) */ - {} -}; +static int +nv20_graph_register(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + if (dev_priv->engine.graph.registered) + return 0; + + NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ + NVOBJ_CLASS(dev, 0x0030, GR); /* null */ + NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ + NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ + NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ + NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ + NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ + NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ + NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ + NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ + NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ + NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ + NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ + NVOBJ_CLASS(dev, 0x009e, GR); /* swzsurf */ + NVOBJ_CLASS(dev, 0x0096, GR); /* celcius */ + + /* kelvin */ + if (dev_priv->chipset < 0x25) + NVOBJ_CLASS(dev, 0x0097, GR); + else + NVOBJ_CLASS(dev, 0x0597, GR); + + /* nvsw */ + NVOBJ_CLASS(dev, 0x506e, SW); + NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); + + dev_priv->engine.graph.registered = true; + return 0; +} + +static int +nv30_graph_register(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->engine.graph.registered) + return 0; + + NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ + NVOBJ_CLASS(dev, 0x0030, GR); /* null */ + NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ + NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ + NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ + NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ + NVOBJ_CLASS(dev, 0x038a, GR); /* ifc (nv30) */ + NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ + NVOBJ_CLASS(dev, 0x0389, GR); /* sifm (nv30) */ + NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ + NVOBJ_CLASS(dev, 0x0362, GR); /* surf2d (nv30) */ + NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ + NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ + NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ + NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ + NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ + NVOBJ_CLASS(dev, 0x039e, GR); /* swzsurf */ + + /* rankine */ + if (0x00000003 & (1 << (dev_priv->chipset & 0x0f))) + NVOBJ_CLASS(dev, 0x0397, GR); + else + if (0x00000010 & (1 << (dev_priv->chipset & 0x0f))) + NVOBJ_CLASS(dev, 0x0697, GR); + else + if (0x000001e0 & (1 << (dev_priv->chipset & 0x0f))) + NVOBJ_CLASS(dev, 0x0497, GR); + + /* nvsw */ + NVOBJ_CLASS(dev, 0x506e, SW); + NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); + + dev_priv->engine.graph.registered = true; + return 0; +} + +static void +nv20_graph_isr(struct drm_device *dev) +{ + u32 stat; + + while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { + u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); + u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); + u32 chid = (addr & 0x01f00000) >> 20; + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xfff; + u32 show = stat; + + if (stat & NV_PGRAPH_INTR_ERROR) { + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { + if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) + show &= ~NV_PGRAPH_INTR_ERROR; + } + } + + nv_wr32(dev, NV03_PGRAPH_INTR, stat); + nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); + + if (show && nouveau_ratelimit()) { + NV_INFO(dev, "PGRAPH -"); + nouveau_bitfield_print(nv10_graph_intr, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv10_graph_nstatus, nstatus); + printk("\n"); + NV_INFO(dev, "PGRAPH - ch %d/%d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); + } + } +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv30_fb.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv30_fb.c @@ -29,6 +29,27 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" +void +nv30_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, + uint32_t size, uint32_t pitch, uint32_t flags) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + tile->addr = addr | 1; + tile->limit = max(1u, addr + size) - 1; + tile->pitch = pitch; +} + +void +nv30_fb_free_tile_region(struct drm_device *dev, int i) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; + + tile->addr = tile->limit = tile->pitch = 0; +} + static int calc_bias(struct drm_device *dev, int k, int i, int j) { @@ -65,7 +86,7 @@ /* Turn all the tiling regions off. */ for (i = 0; i < pfb->num_tiles; i++) - pfb->set_region_tiling(dev, i, 0, 0, 0); + pfb->set_tile_region(dev, i); /* Init the memory timing regs at 0x10037c/0x1003ac */ if (dev_priv->chipset == 0x30 || --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv40_fb.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv40_fb.c @@ -4,26 +4,22 @@ #include "nouveau_drm.h" void -nv40_fb_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch) +nv40_fb_set_tile_region(struct drm_device *dev, int i) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t limit = max(1u, addr + size) - 1; - - if (pitch) - addr |= 1; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; switch (dev_priv->chipset) { case 0x40: - nv_wr32(dev, NV10_PFB_TLIMIT(i), limit); - nv_wr32(dev, NV10_PFB_TSIZE(i), pitch); - nv_wr32(dev, NV10_PFB_TILE(i), addr); + nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); + nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); + nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); break; default: - nv_wr32(dev, NV40_PFB_TLIMIT(i), limit); - nv_wr32(dev, NV40_PFB_TSIZE(i), pitch); - nv_wr32(dev, NV40_PFB_TILE(i), addr); + nv_wr32(dev, NV40_PFB_TLIMIT(i), tile->limit); + nv_wr32(dev, NV40_PFB_TSIZE(i), tile->pitch); + nv_wr32(dev, NV40_PFB_TILE(i), tile->addr); break; } } @@ -64,7 +60,7 @@ /* Turn all the tiling regions off. */ for (i = 0; i < pfb->num_tiles; i++) - pfb->set_region_tiling(dev, i, 0, 0, 0); + pfb->set_tile_region(dev, i); return 0; } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv40_fifo.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv40_fifo.c @@ -47,6 +47,11 @@ if (ret) return ret; + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV40_USER(chan->id), PAGE_SIZE); + if (!chan->user) + return -ENOMEM; + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_wi32(dev, fc + 0, chan->pushbuf_base); @@ -70,17 +75,6 @@ return 0; } -void -nv40_fifo_destroy_context(struct nouveau_channel *chan) -{ - struct drm_device *dev = chan->dev; - - nv_wr32(dev, NV04_PFIFO_MODE, - nv_rd32(dev, NV04_PFIFO_MODE) & ~(1 << chan->id)); - - nouveau_gpuobj_ref(NULL, &chan->ramfc); -} - static void nv40_fifo_do_load_context(struct drm_device *dev, int chid) { @@ -279,6 +273,7 @@ static void nv40_fifo_init_intr(struct drm_device *dev) { + nouveau_irq_register(dev, 8, nv04_fifo_isr); nv_wr32(dev, 0x002100, 0xffffffff); nv_wr32(dev, 0x002140, 0xffffffff); } @@ -301,7 +296,7 @@ pfifo->reassign(dev, true); for (i = 0; i < dev_priv->engine.fifo.channels; i++) { - if (dev_priv->fifos[i]) { + if (dev_priv->channels.ptr[i]) { uint32_t mode = nv_rd32(dev, NV04_PFIFO_MODE); nv_wr32(dev, NV04_PFIFO_MODE, mode | (1 << i)); } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv40_graph.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv40_graph.c @@ -29,6 +29,9 @@ #include "nouveau_drv.h" #include "nouveau_grctx.h" +static int nv40_graph_register(struct drm_device *); +static void nv40_graph_isr(struct drm_device *); + struct nouveau_channel * nv40_graph_channel(struct drm_device *dev) { @@ -42,7 +45,7 @@ inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; for (i = 0; i < dev_priv->engine.fifo.channels; i++) { - struct nouveau_channel *chan = dev_priv->fifos[i]; + struct nouveau_channel *chan = dev_priv->channels.ptr[i]; if (chan && chan->ramin_grctx && chan->ramin_grctx->pinst == inst) @@ -79,6 +82,22 @@ void nv40_graph_destroy_context(struct nouveau_channel *chan) { + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + unsigned long flags; + + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + pgraph->fifo_access(dev, false); + + /* Unload the context if it's the currently active one */ + if (pgraph->channel(dev) == chan) + pgraph->unload_context(dev); + + pgraph->fifo_access(dev, true); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* Free the context resources */ nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); } @@ -174,43 +193,39 @@ } void -nv40_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr, - uint32_t size, uint32_t pitch) +nv40_graph_set_tile_region(struct drm_device *dev, int i) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t limit = max(1u, addr + size) - 1; - - if (pitch) - addr |= 1; + struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; switch (dev_priv->chipset) { case 0x44: case 0x4a: case 0x4e: - nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); - nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); - nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); + nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); break; case 0x46: case 0x47: case 0x49: case 0x4b: - nv_wr32(dev, NV47_PGRAPH_TSIZE(i), pitch); - nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), limit); - nv_wr32(dev, NV47_PGRAPH_TILE(i), addr); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr); + nv_wr32(dev, NV47_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(dev, NV47_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(dev, NV47_PGRAPH_TILE(i), tile->addr); + nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); + nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); + nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); break; default: - nv_wr32(dev, NV20_PGRAPH_TSIZE(i), pitch); - nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), limit); - nv_wr32(dev, NV20_PGRAPH_TILE(i), addr); - nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), pitch); - nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), limit); - nv_wr32(dev, NV40_PGRAPH_TILE1(i), addr); + nv_wr32(dev, NV20_PGRAPH_TSIZE(i), tile->pitch); + nv_wr32(dev, NV20_PGRAPH_TLIMIT(i), tile->limit); + nv_wr32(dev, NV20_PGRAPH_TILE(i), tile->addr); + nv_wr32(dev, NV40_PGRAPH_TSIZE1(i), tile->pitch); + nv_wr32(dev, NV40_PGRAPH_TLIMIT1(i), tile->limit); + nv_wr32(dev, NV40_PGRAPH_TILE1(i), tile->addr); break; } } @@ -232,7 +247,7 @@ struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; struct nouveau_grctx ctx = {}; uint32_t vramsz, *cp; - int i, j; + int ret, i, j; nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~NV_PMC_ENABLE_PGRAPH); @@ -256,9 +271,14 @@ kfree(cp); + ret = nv40_graph_register(dev); + if (ret) + return ret; + /* No context present currently */ nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); + nouveau_irq_register(dev, 12, nv40_graph_isr); nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); @@ -347,7 +367,7 @@ /* Turn all the tiling regions off. */ for (i = 0; i < pfb->num_tiles; i++) - nv40_graph_set_region_tiling(dev, i, 0, 0, 0); + nv40_graph_set_tile_region(dev, i); /* begin RAM config */ vramsz = pci_resource_len(dev->pdev, 0) - 1; @@ -390,26 +410,111 @@ void nv40_graph_takedown(struct drm_device *dev) { + nouveau_irq_unregister(dev, 12); +} + +static int +nv40_graph_register(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->engine.graph.registered) + return 0; + + NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ + NVOBJ_CLASS(dev, 0x0030, GR); /* null */ + NVOBJ_CLASS(dev, 0x0039, GR); /* m2mf */ + NVOBJ_CLASS(dev, 0x004a, GR); /* gdirect */ + NVOBJ_CLASS(dev, 0x009f, GR); /* imageblit (nv12) */ + NVOBJ_CLASS(dev, 0x008a, GR); /* ifc */ + NVOBJ_CLASS(dev, 0x0089, GR); /* sifm */ + NVOBJ_CLASS(dev, 0x3089, GR); /* sifm (nv40) */ + NVOBJ_CLASS(dev, 0x0062, GR); /* surf2d */ + NVOBJ_CLASS(dev, 0x3062, GR); /* surf2d (nv40) */ + NVOBJ_CLASS(dev, 0x0043, GR); /* rop */ + NVOBJ_CLASS(dev, 0x0012, GR); /* beta1 */ + NVOBJ_CLASS(dev, 0x0072, GR); /* beta4 */ + NVOBJ_CLASS(dev, 0x0019, GR); /* cliprect */ + NVOBJ_CLASS(dev, 0x0044, GR); /* pattern */ + NVOBJ_CLASS(dev, 0x309e, GR); /* swzsurf */ + + /* curie */ + if (dev_priv->chipset >= 0x60 || + 0x00005450 & (1 << (dev_priv->chipset & 0x0f))) + NVOBJ_CLASS(dev, 0x4497, GR); + else + NVOBJ_CLASS(dev, 0x4097, GR); + + /* nvsw */ + NVOBJ_CLASS(dev, 0x506e, SW); + NVOBJ_MTHD (dev, 0x506e, 0x0500, nv04_graph_mthd_page_flip); + + dev_priv->engine.graph.registered = true; + return 0; +} + +static int +nv40_graph_isr_chid(struct drm_device *dev, u32 inst) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan; + unsigned long flags; + int i; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); + for (i = 0; i < dev_priv->engine.fifo.channels; i++) { + chan = dev_priv->channels.ptr[i]; + if (!chan || !chan->ramin_grctx) + continue; + + if (inst == chan->ramin_grctx->pinst) + break; + } + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + return i; } -struct nouveau_pgraph_object_class nv40_graph_grclass[] = { - { 0x0030, false, NULL }, /* null */ - { 0x0039, false, NULL }, /* m2mf */ - { 0x004a, false, NULL }, /* gdirect */ - { 0x009f, false, NULL }, /* imageblit (nv12) */ - { 0x008a, false, NULL }, /* ifc */ - { 0x0089, false, NULL }, /* sifm */ - { 0x3089, false, NULL }, /* sifm (nv40) */ - { 0x0062, false, NULL }, /* surf2d */ - { 0x3062, false, NULL }, /* surf2d (nv40) */ - { 0x0043, false, NULL }, /* rop */ - { 0x0012, false, NULL }, /* beta1 */ - { 0x0072, false, NULL }, /* beta4 */ - { 0x0019, false, NULL }, /* cliprect */ - { 0x0044, false, NULL }, /* pattern */ - { 0x309e, false, NULL }, /* swzsurf */ - { 0x4097, false, NULL }, /* curie (nv40) */ - { 0x4497, false, NULL }, /* curie (nv44) */ - {} -}; +static void +nv40_graph_isr(struct drm_device *dev) +{ + u32 stat; + + while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { + u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); + u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); + u32 inst = (nv_rd32(dev, 0x40032c) & 0x000fffff) << 4; + u32 chid = nv40_graph_isr_chid(dev, inst); + u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xffff; + u32 show = stat; + + if (stat & NV_PGRAPH_INTR_ERROR) { + if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { + if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) + show &= ~NV_PGRAPH_INTR_ERROR; + } else + if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { + nv_mask(dev, 0x402000, 0, 0); + } + } + + nv_wr32(dev, NV03_PGRAPH_INTR, stat); + nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); + if (show && nouveau_ratelimit()) { + NV_INFO(dev, "PGRAPH -"); + nouveau_bitfield_print(nv10_graph_intr, show); + printk(" nsource:"); + nouveau_bitfield_print(nv04_graph_nsource, nsource); + printk(" nstatus:"); + nouveau_bitfield_print(nv10_graph_nstatus, nstatus); + printk("\n"); + NV_INFO(dev, "PGRAPH - ch %d (0x%08x) subc %d " + "class 0x%04x mthd 0x%04x data 0x%08x\n", + chid, inst, subc, class, mthd, data); + } + } +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_crtc.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -345,7 +345,6 @@ uint32_t buffer_handle, uint32_t width, uint32_t height) { struct drm_device *dev = crtc->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_bo *cursor = NULL; struct drm_gem_object *gem; @@ -374,8 +373,7 @@ nouveau_bo_unmap(cursor); - nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.offset - - dev_priv->vm_vram_base); + nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.nvbo->bo.mem.start << PAGE_SHIFT); nv_crtc->cursor.show(nv_crtc, true); out: @@ -437,6 +435,7 @@ .cursor_move = nv50_crtc_cursor_move, .gamma_set = nv50_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, + .page_flip = nouveau_crtc_page_flip, .destroy = nv50_crtc_destroy, }; @@ -453,6 +452,7 @@ NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + drm_vblank_pre_modeset(dev, nv_crtc->index); nv50_crtc_blank(nv_crtc, true); } @@ -468,6 +468,7 @@ NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); nv50_crtc_blank(nv_crtc, false); + drm_vblank_post_modeset(dev, nv_crtc->index); ret = RING_SPACE(evo, 2); if (ret) { @@ -545,7 +546,7 @@ return -EINVAL; } - nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base; + nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT; nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) { --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_display.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_display.c @@ -33,6 +33,8 @@ #include "nouveau_ramht.h" #include "drm_crtc_helper.h" +static void nv50_display_isr(struct drm_device *); + static inline int nv50_sor_nr(struct drm_device *dev) { @@ -46,159 +48,6 @@ return 4; } -static void -nv50_evo_channel_del(struct nouveau_channel **pchan) -{ - struct nouveau_channel *chan = *pchan; - - if (!chan) - return; - *pchan = NULL; - - nouveau_gpuobj_channel_takedown(chan); - nouveau_bo_unmap(chan->pushbuf_bo); - nouveau_bo_ref(NULL, &chan->pushbuf_bo); - - if (chan->user) - iounmap(chan->user); - - kfree(chan); -} - -static int -nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, - uint32_t tile_flags, uint32_t magic_flags, - uint32_t offset, uint32_t limit) -{ - struct drm_nouveau_private *dev_priv = evo->dev->dev_private; - struct drm_device *dev = evo->dev; - struct nouveau_gpuobj *obj = NULL; - int ret; - - ret = nouveau_gpuobj_new(dev, evo, 6*4, 32, 0, &obj); - if (ret) - return ret; - obj->engine = NVOBJ_ENGINE_DISPLAY; - - nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); - nv_wo32(obj, 4, limit); - nv_wo32(obj, 8, offset); - nv_wo32(obj, 12, 0x00000000); - nv_wo32(obj, 16, 0x00000000); - if (dev_priv->card_type < NV_C0) - nv_wo32(obj, 20, 0x00010000); - else - nv_wo32(obj, 20, 0x00020000); - dev_priv->engine.instmem.flush(dev); - - ret = nouveau_ramht_insert(evo, name, obj); - nouveau_gpuobj_ref(NULL, &obj); - if (ret) { - return ret; - } - - return 0; -} - -static int -nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pchan) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *ramht = NULL; - struct nouveau_channel *chan; - int ret; - - chan = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL); - if (!chan) - return -ENOMEM; - *pchan = chan; - - chan->id = -1; - chan->dev = dev; - chan->user_get = 4; - chan->user_put = 0; - - ret = nouveau_gpuobj_new(dev, NULL, 32768, 0x1000, - NVOBJ_FLAG_ZERO_ALLOC, &chan->ramin); - if (ret) { - NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); - nv50_evo_channel_del(pchan); - return ret; - } - - ret = drm_mm_init(&chan->ramin_heap, 0, 32768); - if (ret) { - NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); - nv50_evo_channel_del(pchan); - return ret; - } - - ret = nouveau_gpuobj_new(dev, chan, 4096, 16, 0, &ramht); - if (ret) { - NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); - nv50_evo_channel_del(pchan); - return ret; - } - - ret = nouveau_ramht_new(dev, ramht, &chan->ramht); - nouveau_gpuobj_ref(NULL, &ramht); - if (ret) { - nv50_evo_channel_del(pchan); - return ret; - } - - if (dev_priv->chipset != 0x50) { - ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB16, 0x70, 0x19, - 0, 0xffffffff); - if (ret) { - nv50_evo_channel_del(pchan); - return ret; - } - - - ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoFB32, 0x7a, 0x19, - 0, 0xffffffff); - if (ret) { - nv50_evo_channel_del(pchan); - return ret; - } - } - - ret = nv50_evo_dmaobj_new(chan, 0x3d, NvEvoVRAM, 0, 0x19, - 0, dev_priv->vram_size); - if (ret) { - nv50_evo_channel_del(pchan); - return ret; - } - - ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, - false, true, &chan->pushbuf_bo); - if (ret == 0) - ret = nouveau_bo_pin(chan->pushbuf_bo, TTM_PL_FLAG_VRAM); - if (ret) { - NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret); - nv50_evo_channel_del(pchan); - return ret; - } - - ret = nouveau_bo_map(chan->pushbuf_bo); - if (ret) { - NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret); - nv50_evo_channel_del(pchan); - return ret; - } - - chan->user = ioremap(pci_resource_start(dev->pdev, 0) + - NV50_PDISPLAY_USER(0), PAGE_SIZE); - if (!chan->user) { - NV_ERROR(dev, "Error mapping EVO control regs.\n"); - nv50_evo_channel_del(pchan); - return -ENOMEM; - } - - return 0; -} - int nv50_display_early_init(struct drm_device *dev) { @@ -214,17 +63,16 @@ nv50_display_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - struct nouveau_channel *evo = dev_priv->evo; struct drm_connector *connector; - uint32_t val, ram_amount; - uint64_t start; + struct nouveau_channel *evo; int ret, i; + u32 val; NV_DEBUG_KMS(dev, "\n"); nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004)); + /* * I think the 0x006101XX range is some kind of main control area * that enables things. @@ -240,16 +88,19 @@ val = nv_rd32(dev, 0x0061610c + (i * 0x800)); nv_wr32(dev, 0x0061019c + (i * 0x10), val); } + /* DAC */ for (i = 0; i < 3; i++) { val = nv_rd32(dev, 0x0061a000 + (i * 0x800)); nv_wr32(dev, 0x006101d0 + (i * 0x04), val); } + /* SOR */ for (i = 0; i < nv50_sor_nr(dev); i++) { val = nv_rd32(dev, 0x0061c000 + (i * 0x800)); nv_wr32(dev, 0x006101e0 + (i * 0x04), val); } + /* EXT */ for (i = 0; i < 3; i++) { val = nv_rd32(dev, 0x0061e000 + (i * 0x800)); @@ -262,17 +113,6 @@ nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001); } - /* This used to be in crtc unblank, but seems out of place there. */ - nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0); - /* RAM is clamped to 256 MiB. */ - ram_amount = dev_priv->vram_size; - NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount); - if (ram_amount > 256*1024*1024) - ram_amount = 256*1024*1024; - nv_wr32(dev, NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1); - nv_wr32(dev, NV50_PDISPLAY_UNK_388, 0x150000); - nv_wr32(dev, NV50_PDISPLAY_UNK_38C, 0); - /* The precise purpose is unknown, i suspect it has something to do * with text mode. */ @@ -287,37 +127,6 @@ } } - /* taken from nv bug #12637, attempts to un-wedge the hw if it's - * stuck in some unspecified state - */ - start = ptimer->read(dev); - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x2b00); - while ((val = nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))) & 0x1e0000) { - if ((val & 0x9f0000) == 0x20000) - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), - val | 0x800000); - - if ((val & 0x3f0000) == 0x30000) - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), - val | 0x200000); - - if (ptimer->read(dev) - start > 1000000000ULL) { - NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) != 0\n"); - NV_ERROR(dev, "0x610200 = 0x%08x\n", val); - return -EBUSY; - } - } - - nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, NV50_PDISPLAY_CTRL_STATE_ENABLE); - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1000b03); - if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0), - 0x40000000, 0x40000000)) { - NV_ERROR(dev, "timeout: (0x610200 & 0x40000000) == 0x40000000\n"); - NV_ERROR(dev, "0x610200 = 0x%08x\n", - nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); - return -EBUSY; - } - for (i = 0; i < 2; i++) { nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), @@ -341,39 +150,31 @@ } } - nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); + nv_wr32(dev, NV50_PDISPLAY_PIO_CTRL, 0x00000000); + nv_mask(dev, NV50_PDISPLAY_INTR_0, 0x00000000, 0x00000000); + nv_wr32(dev, NV50_PDISPLAY_INTR_EN_0, 0x00000000); + nv_mask(dev, NV50_PDISPLAY_INTR_1, 0x00000000, 0x00000000); + nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, + NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 | + NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 | + NV50_PDISPLAY_INTR_EN_1_CLK_UNK40); + + /* enable hotplug interrupts */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct nouveau_connector *conn = nouveau_connector(connector); - /* initialise fifo */ - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_DMA_CB(0), - ((evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT) >> 8) | - NV50_PDISPLAY_CHANNEL_DMA_CB_LOCATION_VRAM | - NV50_PDISPLAY_CHANNEL_DMA_CB_VALID); - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK2(0), 0x00010000); - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_UNK3(0), 0x00000002); - if (!nv_wait(dev, 0x610200, 0x80000000, 0x00000000)) { - NV_ERROR(dev, "timeout: (0x610200 & 0x80000000) == 0\n"); - NV_ERROR(dev, "0x610200 = 0x%08x\n", nv_rd32(dev, 0x610200)); - return -EBUSY; - } - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), - (nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0)) & ~0x00000003) | - NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED); - nv_wr32(dev, NV50_PDISPLAY_USER_PUT(0), 0); - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x01000003 | - NV50_PDISPLAY_CHANNEL_STAT_DMA_ENABLED); - nv_wr32(dev, 0x610300, nv_rd32(dev, 0x610300) & ~1); - - evo->dma.max = (4096/4) - 2; - evo->dma.put = 0; - evo->dma.cur = evo->dma.put; - evo->dma.free = evo->dma.max - evo->dma.cur; + if (conn->dcb->gpio_tag == 0xff) + continue; - ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS); + pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); + } + + ret = nv50_evo_init(dev); if (ret) return ret; + evo = dev_priv->evo; - for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) - OUT_RING(evo, 0); + nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); ret = RING_SPACE(evo, 11); if (ret) @@ -393,21 +194,6 @@ if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) NV_ERROR(dev, "evo pushbuf stalled\n"); - /* enable clock change interrupts. */ - nv_wr32(dev, 0x610028, 0x00010001); - nv_wr32(dev, NV50_PDISPLAY_INTR_EN, (NV50_PDISPLAY_INTR_EN_CLK_UNK10 | - NV50_PDISPLAY_INTR_EN_CLK_UNK20 | - NV50_PDISPLAY_INTR_EN_CLK_UNK40)); - - /* enable hotplug interrupts */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct nouveau_connector *conn = nouveau_connector(connector); - - if (conn->dcb->gpio_tag == 0xff) - continue; - - pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); - } return 0; } @@ -452,13 +238,7 @@ } } - nv_wr32(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0); - nv_wr32(dev, NV50_PDISPLAY_CTRL_STATE, 0); - if (!nv_wait(dev, NV50_PDISPLAY_CHANNEL_STAT(0), 0x1e0000, 0)) { - NV_ERROR(dev, "timeout: (0x610200 & 0x1e0000) == 0\n"); - NV_ERROR(dev, "0x610200 = 0x%08x\n", - nv_rd32(dev, NV50_PDISPLAY_CHANNEL_STAT(0))); - } + nv50_evo_fini(dev); for (i = 0; i < 3; i++) { if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i), @@ -470,7 +250,7 @@ } /* disable interrupts. */ - nv_wr32(dev, NV50_PDISPLAY_INTR_EN, 0x00000000); + nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, 0x00000000); /* disable hotplug interrupts */ nv_wr32(dev, 0xe054, 0xffffffff); @@ -508,13 +288,6 @@ dev->mode_config.fb_base = dev_priv->fb_phys; - /* Create EVO channel */ - ret = nv50_evo_channel_new(dev, &dev_priv->evo); - if (ret) { - NV_ERROR(dev, "Error creating EVO channel: %d\n", ret); - return ret; - } - /* Create CRTC objects */ for (i = 0; i < 2; i++) nv50_crtc_create(dev, i); @@ -557,6 +330,9 @@ } } + INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); + nouveau_irq_register(dev, 26, nv50_display_isr); + ret = nv50_display_init(dev); if (ret) { nv50_display_destroy(dev); @@ -569,14 +345,12 @@ void nv50_display_destroy(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - NV_DEBUG_KMS(dev, "\n"); drm_mode_config_cleanup(dev); nv50_display_disable(dev); - nv50_evo_channel_del(&dev_priv->evo); + nouveau_irq_unregister(dev, 26); } static u16 @@ -660,32 +434,32 @@ nv50_display_vblank_crtc_handler(struct drm_device *dev, int crtc) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan; - struct list_head *entry, *tmp; + struct nouveau_channel *chan, *tmp; - list_for_each_safe(entry, tmp, &dev_priv->vbl_waiting) { - chan = list_entry(entry, struct nouveau_channel, nvsw.vbl_wait); + list_for_each_entry_safe(chan, tmp, &dev_priv->vbl_waiting, + nvsw.vbl_wait) { + if (chan->nvsw.vblsem_head != crtc) + continue; nouveau_bo_wr32(chan->notifier_bo, chan->nvsw.vblsem_offset, chan->nvsw.vblsem_rval); list_del(&chan->nvsw.vbl_wait); + drm_vblank_put(dev, crtc); } + + drm_handle_vblank(dev, crtc); } static void nv50_display_vblank_handler(struct drm_device *dev, uint32_t intr) { - intr &= NV50_PDISPLAY_INTR_1_VBLANK_CRTC; - if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_0) nv50_display_vblank_crtc_handler(dev, 0); if (intr & NV50_PDISPLAY_INTR_1_VBLANK_CRTC_1) nv50_display_vblank_crtc_handler(dev, 1); - nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev, - NV50_PDISPLAY_INTR_EN) & ~intr); - nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr); + nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_VBLANK_CRTC); } static void @@ -1011,108 +785,31 @@ static void nv50_display_error_handler(struct drm_device *dev) { - uint32_t addr, data; - - nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000); - addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR); - data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA); - - NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x (0x%04x 0x%02x)\n", - 0, addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); - - nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR, 0x90000000); -} - -void -nv50_display_irq_hotplug_bh(struct work_struct *work) -{ - struct drm_nouveau_private *dev_priv = - container_of(work, struct drm_nouveau_private, hpd_work); - struct drm_device *dev = dev_priv->dev; - struct drm_connector *connector; - const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; - uint32_t unplug_mask, plug_mask, change_mask; - uint32_t hpd0, hpd1; - - spin_lock_irq(&dev_priv->hpd_state.lock); - hpd0 = dev_priv->hpd_state.hpd0_bits; - dev_priv->hpd_state.hpd0_bits = 0; - hpd1 = dev_priv->hpd_state.hpd1_bits; - dev_priv->hpd_state.hpd1_bits = 0; - spin_unlock_irq(&dev_priv->hpd_state.lock); - - hpd0 &= nv_rd32(dev, 0xe050); - if (dev_priv->chipset >= 0x90) - hpd1 &= nv_rd32(dev, 0xe070); - - plug_mask = (hpd0 & 0x0000ffff) | (hpd1 << 16); - unplug_mask = (hpd0 >> 16) | (hpd1 & 0xffff0000); - change_mask = plug_mask | unplug_mask; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct drm_encoder_helper_funcs *helper; - struct nouveau_connector *nv_connector = - nouveau_connector(connector); - struct nouveau_encoder *nv_encoder; - struct dcb_gpio_entry *gpio; - uint32_t reg; - bool plugged; - - if (!nv_connector->dcb) - continue; - - gpio = nouveau_bios_gpio_entry(dev, nv_connector->dcb->gpio_tag); - if (!gpio || !(change_mask & (1 << gpio->line))) - continue; + u32 channels = (nv_rd32(dev, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16; + u32 addr, data; + int chid; + + for (chid = 0; chid < 5; chid++) { + if (!(channels & (1 << chid))) + continue; + + nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000 << chid); + addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid)); + data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA(chid)); + NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x " + "(0x%04x 0x%02x)\n", chid, + addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); - reg = nv_rd32(dev, gpio_reg[gpio->line >> 3]); - plugged = !!(reg & (4 << ((gpio->line & 7) << 2))); - NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un", - drm_get_connector_name(connector)) ; - - if (!connector->encoder || !connector->encoder->crtc || - !connector->encoder->crtc->enabled) - continue; - nv_encoder = nouveau_encoder(connector->encoder); - helper = connector->encoder->helper_private; - - if (nv_encoder->dcb->type != OUTPUT_DP) - continue; - - if (plugged) - helper->dpms(connector->encoder, DRM_MODE_DPMS_ON); - else - helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF); + nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000); } - - drm_helper_hpd_irq_event(dev); } -void -nv50_display_irq_handler(struct drm_device *dev) +static void +nv50_display_isr(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; uint32_t delayed = 0; - if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) { - uint32_t hpd0_bits, hpd1_bits = 0; - - hpd0_bits = nv_rd32(dev, 0xe054); - nv_wr32(dev, 0xe054, hpd0_bits); - - if (dev_priv->chipset >= 0x90) { - hpd1_bits = nv_rd32(dev, 0xe074); - nv_wr32(dev, 0xe074, hpd1_bits); - } - - spin_lock(&dev_priv->hpd_state.lock); - dev_priv->hpd_state.hpd0_bits |= hpd0_bits; - dev_priv->hpd_state.hpd1_bits |= hpd1_bits; - spin_unlock(&dev_priv->hpd_state.lock); - - queue_work(dev_priv->wq, &dev_priv->hpd_work); - } - while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); @@ -1123,9 +820,9 @@ if (!intr0 && !(intr1 & ~delayed)) break; - if (intr0 & 0x00010000) { + if (intr0 & 0x001f0000) { nv50_display_error_handler(dev); - intr0 &= ~0x00010000; + intr0 &= ~0x001f0000; } if (intr1 & NV50_PDISPLAY_INTR_1_VBLANK_CRTC) { @@ -1156,4 +853,3 @@ } } } - --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_display.h +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_display.h @@ -35,9 +35,7 @@ #include "nouveau_crtc.h" #include "nv50_evo.h" -void nv50_display_irq_handler(struct drm_device *dev); void nv50_display_irq_handler_bh(struct work_struct *work); -void nv50_display_irq_hotplug_bh(struct work_struct *work); int nv50_display_early_init(struct drm_device *dev); void nv50_display_late_takedown(struct drm_device *dev); int nv50_display_create(struct drm_device *dev); --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_evo.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_evo.c @@ -0,0 +1,318 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "drmP.h" + +#include "nouveau_drv.h" +#include "nouveau_dma.h" +#include "nouveau_ramht.h" + +static void +nv50_evo_channel_del(struct nouveau_channel **pevo) +{ + struct drm_nouveau_private *dev_priv; + struct nouveau_channel *evo = *pevo; + + if (!evo) + return; + *pevo = NULL; + + dev_priv = evo->dev->dev_private; + dev_priv->evo_alloc &= ~(1 << evo->id); + + nouveau_gpuobj_channel_takedown(evo); + nouveau_bo_unmap(evo->pushbuf_bo); + nouveau_bo_ref(NULL, &evo->pushbuf_bo); + + if (evo->user) + iounmap(evo->user); + + kfree(evo); +} + +int +nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name, + u32 tile_flags, u32 magic_flags, u32 offset, u32 limit) +{ + struct drm_nouveau_private *dev_priv = evo->dev->dev_private; + struct drm_device *dev = evo->dev; + struct nouveau_gpuobj *obj = NULL; + int ret; + + ret = nouveau_gpuobj_new(dev, dev_priv->evo, 6*4, 32, 0, &obj); + if (ret) + return ret; + obj->engine = NVOBJ_ENGINE_DISPLAY; + + nv_wo32(obj, 0, (tile_flags << 22) | (magic_flags << 16) | class); + nv_wo32(obj, 4, limit); + nv_wo32(obj, 8, offset); + nv_wo32(obj, 12, 0x00000000); + nv_wo32(obj, 16, 0x00000000); + if (dev_priv->card_type < NV_C0) + nv_wo32(obj, 20, 0x00010000); + else + nv_wo32(obj, 20, 0x00020000); + dev_priv->engine.instmem.flush(dev); + + ret = nouveau_ramht_insert(evo, name, obj); + nouveau_gpuobj_ref(NULL, &obj); + if (ret) { + return ret; + } + + return 0; +} + +static int +nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *evo; + int ret; + + evo = kzalloc(sizeof(struct nouveau_channel), GFP_KERNEL); + if (!evo) + return -ENOMEM; + *pevo = evo; + + for (evo->id = 0; evo->id < 5; evo->id++) { + if (dev_priv->evo_alloc & (1 << evo->id)) + continue; + + dev_priv->evo_alloc |= (1 << evo->id); + break; + } + + if (evo->id == 5) { + kfree(evo); + return -ENODEV; + } + + evo->dev = dev; + evo->user_get = 4; + evo->user_put = 0; + + ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, + false, true, &evo->pushbuf_bo); + if (ret == 0) + ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); + if (ret) { + NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret); + nv50_evo_channel_del(pevo); + return ret; + } + + ret = nouveau_bo_map(evo->pushbuf_bo); + if (ret) { + NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret); + nv50_evo_channel_del(pevo); + return ret; + } + + evo->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV50_PDISPLAY_USER(evo->id), PAGE_SIZE); + if (!evo->user) { + NV_ERROR(dev, "Error mapping EVO control regs.\n"); + nv50_evo_channel_del(pevo); + return -ENOMEM; + } + + /* bind primary evo channel's ramht to the channel */ + if (dev_priv->evo && evo != dev_priv->evo) + nouveau_ramht_ref(dev_priv->evo->ramht, &evo->ramht, NULL); + + return 0; +} + +static int +nv50_evo_channel_init(struct nouveau_channel *evo) +{ + struct drm_device *dev = evo->dev; + int id = evo->id, ret, i; + u64 pushbuf = evo->pushbuf_bo->bo.mem.start << PAGE_SHIFT; + u32 tmp; + + tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); + if ((tmp & 0x009f0000) == 0x00020000) + nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00800000); + + tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); + if ((tmp & 0x003f0000) == 0x00030000) + nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00600000); + + /* initialise fifo */ + nv_wr32(dev, NV50_PDISPLAY_EVO_DMA_CB(id), pushbuf >> 8 | + NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM | + NV50_PDISPLAY_EVO_DMA_CB_VALID); + nv_wr32(dev, NV50_PDISPLAY_EVO_UNK2(id), 0x00010000); + nv_wr32(dev, NV50_PDISPLAY_EVO_HASH_TAG(id), id); + nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), NV50_PDISPLAY_EVO_CTRL_DMA, + NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); + + nv_wr32(dev, NV50_PDISPLAY_USER_PUT(id), 0x00000000); + nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x01000003 | + NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); + if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x80000000, 0x00000000)) { + NV_ERROR(dev, "EvoCh %d init timeout: 0x%08x\n", id, + nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id))); + return -EBUSY; + } + + /* enable error reporting on the channel */ + nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id); + + evo->dma.max = (4096/4) - 2; + evo->dma.put = 0; + evo->dma.cur = evo->dma.put; + evo->dma.free = evo->dma.max - evo->dma.cur; + + ret = RING_SPACE(evo, NOUVEAU_DMA_SKIPS); + if (ret) + return ret; + + for (i = 0; i < NOUVEAU_DMA_SKIPS; i++) + OUT_RING(evo, 0); + + return 0; +} + +static void +nv50_evo_channel_fini(struct nouveau_channel *evo) +{ + struct drm_device *dev = evo->dev; + int id = evo->id; + + nv_mask(dev, 0x610028, 0x00010001 << id, 0x00000000); + nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00001010, 0x00001000); + nv_wr32(dev, NV50_PDISPLAY_INTR_0, (1 << id)); + nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00000003, 0x00000000); + if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x001e0000, 0x00000000)) { + NV_ERROR(dev, "EvoCh %d takedown timeout: 0x%08x\n", id, + nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id))); + } +} + +static int +nv50_evo_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ramht = NULL; + struct nouveau_channel *evo; + int ret; + + /* create primary evo channel, the one we use for modesetting + * purporses + */ + ret = nv50_evo_channel_new(dev, &dev_priv->evo); + if (ret) + return ret; + evo = dev_priv->evo; + + /* setup object management on it, any other evo channel will + * use this also as there's no per-channel support on the + * hardware + */ + ret = nouveau_gpuobj_new(dev, NULL, 32768, 65536, + NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin); + if (ret) { + NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); + nv50_evo_channel_del(&dev_priv->evo); + return ret; + } + + ret = drm_mm_init(&evo->ramin_heap, 0, 32768); + if (ret) { + NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret); + nv50_evo_channel_del(&dev_priv->evo); + return ret; + } + + ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht); + if (ret) { + NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret); + nv50_evo_channel_del(&dev_priv->evo); + return ret; + } + + ret = nouveau_ramht_new(dev, ramht, &evo->ramht); + nouveau_gpuobj_ref(NULL, &ramht); + if (ret) { + nv50_evo_channel_del(&dev_priv->evo); + return ret; + } + + /* create some default objects for the scanout memtypes we support */ + if (dev_priv->chipset != 0x50) { + ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19, + 0, 0xffffffff); + if (ret) { + nv50_evo_channel_del(&dev_priv->evo); + return ret; + } + + + ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19, + 0, 0xffffffff); + if (ret) { + nv50_evo_channel_del(&dev_priv->evo); + return ret; + } + } + + ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19, + 0, dev_priv->vram_size); + if (ret) { + nv50_evo_channel_del(&dev_priv->evo); + return ret; + } + + return 0; +} + +int +nv50_evo_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int ret; + + if (!dev_priv->evo) { + ret = nv50_evo_create(dev); + if (ret) + return ret; + } + + return nv50_evo_channel_init(dev_priv->evo); +} + +void +nv50_evo_fini(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->evo) { + nv50_evo_channel_fini(dev_priv->evo); + nv50_evo_channel_del(&dev_priv->evo); + } +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_evo.h +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_evo.h @@ -24,6 +24,15 @@ * */ +#ifndef __NV50_EVO_H__ +#define __NV50_EVO_H__ + +int nv50_evo_init(struct drm_device *dev); +void nv50_evo_fini(struct drm_device *dev); +int nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name, + u32 tile_flags, u32 magic_flags, + u32 offset, u32 limit); + #define NV50_EVO_UPDATE 0x00000080 #define NV50_EVO_UNK84 0x00000084 #define NV50_EVO_UNK84_NOTIFY 0x40000000 @@ -111,3 +120,4 @@ #define NV50_EVO_CRTC_SCALE_RES1 0x000008d8 #define NV50_EVO_CRTC_SCALE_RES2 0x000008dc +#endif --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_fb.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_fb.c @@ -3,30 +3,75 @@ #include "nouveau_drv.h" #include "nouveau_drm.h" +struct nv50_fb_priv { + struct page *r100c08_page; + dma_addr_t r100c08; +}; + +static int +nv50_fb_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_fb_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!priv->r100c08_page) { + kfree(priv); + return -ENOMEM; + } + + priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, + PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { + __free_page(priv->r100c08_page); + kfree(priv); + return -EFAULT; + } + + dev_priv->engine.fb.priv = priv; + return 0; +} + int nv50_fb_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_fb_priv *priv; + int ret; + + if (!dev_priv->engine.fb.priv) { + ret = nv50_fb_create(dev); + if (ret) + return ret; + } + priv = dev_priv->engine.fb.priv; /* Not a clue what this is exactly. Without pointing it at a * scratch page, VRAM->GART blits with M2MF (as in DDX DFS) * cause IOMMU "read from address 0" errors (rh#561267) */ - nv_wr32(dev, 0x100c08, dev_priv->gart_info.sg_dummy_bus >> 8); + nv_wr32(dev, 0x100c08, priv->r100c08 >> 8); /* This is needed to get meaningful information from 100c90 * on traps. No idea what these values mean exactly. */ switch (dev_priv->chipset) { case 0x50: - nv_wr32(dev, 0x100c90, 0x0707ff); + nv_wr32(dev, 0x100c90, 0x000707ff); break; case 0xa3: case 0xa5: case 0xa8: - nv_wr32(dev, 0x100c90, 0x0d0fff); + nv_wr32(dev, 0x100c90, 0x000d0fff); + break; + case 0xaf: + nv_wr32(dev, 0x100c90, 0x089d1fff); break; default: - nv_wr32(dev, 0x100c90, 0x1d07ff); + nv_wr32(dev, 0x100c90, 0x001d07ff); break; } @@ -36,12 +81,25 @@ void nv50_fb_takedown(struct drm_device *dev) { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nv50_fb_priv *priv; + + priv = dev_priv->engine.fb.priv; + if (!priv) + return; + dev_priv->engine.fb.priv = NULL; + + pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + __free_page(priv->r100c08_page); + kfree(priv); } void nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) { struct drm_nouveau_private *dev_priv = dev->dev_private; + unsigned long flags; u32 trap[6], idx, chinst; int i, ch; @@ -60,8 +118,10 @@ return; chinst = (trap[2] << 16) | trap[1]; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { - struct nouveau_channel *chan = dev_priv->fifos[ch]; + struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; if (!chan || !chan->ramin) continue; @@ -69,6 +129,7 @@ if (chinst == chan->ramin->vinst >> 12) break; } + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x " "channel %d (0x%08x)\n", --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -3,27 +3,20 @@ #include "nouveau_dma.h" #include "nouveau_ramht.h" #include "nouveau_fbcon.h" +#include "nouveau_mm.h" -void +int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { struct nouveau_fbdev *nfbdev = info->par; struct drm_device *dev = nfbdev->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; + int ret; - if (info->state != FBINFO_STATE_RUNNING) - return; - - if (!(info->flags & FBINFO_HWACCEL_DISABLED) && - RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11)) { - nouveau_fbcon_gpu_lockup(info); - } - - if (info->flags & FBINFO_HWACCEL_DISABLED) { - cfb_fillrect(info, rect); - return; - } + ret = RING_SPACE(chan, rect->rop == ROP_COPY ? 7 : 11); + if (ret) + return ret; if (rect->rop != ROP_COPY) { BEGIN_RING(chan, NvSub2D, 0x02ac, 1); @@ -45,27 +38,21 @@ OUT_RING(chan, 3); } FIRE_RING(chan); + return 0; } -void +int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) { struct nouveau_fbdev *nfbdev = info->par; struct drm_device *dev = nfbdev->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; + int ret; - if (info->state != FBINFO_STATE_RUNNING) - return; - - if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 12)) { - nouveau_fbcon_gpu_lockup(info); - } - - if (info->flags & FBINFO_HWACCEL_DISABLED) { - cfb_copyarea(info, region); - return; - } + ret = RING_SPACE(chan, 12); + if (ret) + return ret; BEGIN_RING(chan, NvSub2D, 0x0110, 1); OUT_RING(chan, 0); @@ -80,9 +67,10 @@ OUT_RING(chan, 0); OUT_RING(chan, region->sy); FIRE_RING(chan); + return 0; } -void +int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) { struct nouveau_fbdev *nfbdev = info->par; @@ -92,23 +80,14 @@ uint32_t width, dwords, *data = (uint32_t *)image->data; uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); uint32_t *palette = info->pseudo_palette; + int ret; - if (info->state != FBINFO_STATE_RUNNING) - return; - - if (image->depth != 1) { - cfb_imageblit(info, image); - return; - } - - if (!(info->flags & FBINFO_HWACCEL_DISABLED) && RING_SPACE(chan, 11)) { - nouveau_fbcon_gpu_lockup(info); - } + if (image->depth != 1) + return -ENODEV; - if (info->flags & FBINFO_HWACCEL_DISABLED) { - cfb_imageblit(info, image); - return; - } + ret = RING_SPACE(chan, 11); + if (ret) + return ret; width = ALIGN(image->width, 32); dwords = (width * image->height) >> 5; @@ -134,11 +113,9 @@ while (dwords) { int push = dwords > 2047 ? 2047 : dwords; - if (RING_SPACE(chan, push + 1)) { - nouveau_fbcon_gpu_lockup(info); - cfb_imageblit(info, image); - return; - } + ret = RING_SPACE(chan, push + 1); + if (ret) + return ret; dwords -= push; @@ -148,6 +125,7 @@ } FIRE_RING(chan); + return 0; } int @@ -157,12 +135,9 @@ struct drm_device *dev = nfbdev->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_channel *chan = dev_priv->channel; - struct nouveau_gpuobj *eng2d = NULL; - uint64_t fb; + struct nouveau_bo *nvbo = nfbdev->nouveau_fb.nvbo; int ret, format; - fb = info->fix.smem_start - dev_priv->fb_phys + dev_priv->vm_vram_base; - switch (info->var.bits_per_pixel) { case 8: format = 0xf3; @@ -190,12 +165,7 @@ return -EINVAL; } - ret = nouveau_gpuobj_gr_new(dev_priv->channel, 0x502d, &eng2d); - if (ret) - return ret; - - ret = nouveau_ramht_insert(dev_priv->channel, Nv2D, eng2d); - nouveau_gpuobj_ref(NULL, &eng2d); + ret = nouveau_gpuobj_gr_new(dev_priv->channel, Nv2D, 0x502d); if (ret) return ret; @@ -253,8 +223,8 @@ OUT_RING(chan, info->fix.line_length); OUT_RING(chan, info->var.xres_virtual); OUT_RING(chan, info->var.yres_virtual); - OUT_RING(chan, upper_32_bits(fb)); - OUT_RING(chan, lower_32_bits(fb)); + OUT_RING(chan, upper_32_bits(nvbo->vma.offset)); + OUT_RING(chan, lower_32_bits(nvbo->vma.offset)); BEGIN_RING(chan, NvSub2D, 0x0230, 2); OUT_RING(chan, format); OUT_RING(chan, 1); @@ -262,8 +232,8 @@ OUT_RING(chan, info->fix.line_length); OUT_RING(chan, info->var.xres_virtual); OUT_RING(chan, info->var.yres_virtual); - OUT_RING(chan, upper_32_bits(fb)); - OUT_RING(chan, lower_32_bits(fb)); + OUT_RING(chan, upper_32_bits(nvbo->vma.offset)); + OUT_RING(chan, lower_32_bits(nvbo->vma.offset)); return 0; } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_fifo.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_fifo.c @@ -28,6 +28,7 @@ #include "drm.h" #include "nouveau_drv.h" #include "nouveau_ramht.h" +#include "nouveau_vm.h" static void nv50_fifo_playlist_update(struct drm_device *dev) @@ -44,7 +45,8 @@ /* We never schedule channel 0 or 127 */ for (i = 1, nr = 0; i < 127; i++) { - if (dev_priv->fifos[i] && dev_priv->fifos[i]->ramfc) { + if (dev_priv->channels.ptr[i] && + dev_priv->channels.ptr[i]->ramfc) { nv_wo32(cur, (nr * 4), i); nr++; } @@ -60,7 +62,7 @@ nv50_fifo_channel_enable(struct drm_device *dev, int channel) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->fifos[channel]; + struct nouveau_channel *chan = dev_priv->channels.ptr[channel]; uint32_t inst; NV_DEBUG(dev, "ch%d\n", channel); @@ -105,6 +107,7 @@ { NV_DEBUG(dev, "\n"); + nouveau_irq_register(dev, 8, nv04_fifo_isr); nv_wr32(dev, NV03_PFIFO_INTR_0, 0xFFFFFFFF); nv_wr32(dev, NV03_PFIFO_INTR_EN_0, 0xFFFFFFFF); } @@ -118,7 +121,7 @@ NV_DEBUG(dev, "\n"); for (i = 0; i < NV50_PFIFO_CTX_TABLE__SIZE; i++) { - if (dev_priv->fifos[i]) + if (dev_priv->channels.ptr[i]) nv50_fifo_channel_enable(dev, i); else nv50_fifo_channel_disable(dev, i); @@ -206,6 +209,9 @@ if (!pfifo->playlist[0]) return; + nv_wr32(dev, 0x2140, 0x00000000); + nouveau_irq_unregister(dev, 8); + nouveau_gpuobj_ref(NULL, &pfifo->playlist[0]); nouveau_gpuobj_ref(NULL, &pfifo->playlist[1]); } @@ -256,6 +262,11 @@ } ramfc = chan->ramfc; + chan->user = ioremap(pci_resource_start(dev->pdev, 0) + + NV50_USER(chan->id), PAGE_SIZE); + if (!chan->user) + return -ENOMEM; + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); nv_wo32(ramfc, 0x48, chan->pushbuf->cinst >> 4); @@ -291,10 +302,23 @@ nv50_fifo_destroy_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; struct nouveau_gpuobj *ramfc = NULL; + unsigned long flags; NV_DEBUG(dev, "ch%d\n", chan->id); + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + pfifo->reassign(dev, false); + + /* Unload the context if it's the currently active one */ + if (pfifo->channel_id(dev) == chan->id) { + pfifo->disable(dev); + pfifo->unload_context(dev); + pfifo->enable(dev); + } + /* This will ensure the channel is seen as disabled. */ nouveau_gpuobj_ref(chan->ramfc, &ramfc); nouveau_gpuobj_ref(NULL, &chan->ramfc); @@ -305,6 +329,14 @@ nv50_fifo_channel_disable(dev, 127); nv50_fifo_playlist_update(dev); + pfifo->reassign(dev, true); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + + /* Free the channel resources */ + if (chan->user) { + iounmap(chan->user); + chan->user = NULL; + } nouveau_gpuobj_ref(NULL, &ramfc); nouveau_gpuobj_ref(NULL, &chan->cache); } @@ -392,7 +424,7 @@ if (chid < 1 || chid >= dev_priv->engine.fifo.channels - 1) return 0; - chan = dev_priv->fifos[chid]; + chan = dev_priv->channels.ptr[chid]; if (!chan) { NV_ERROR(dev, "Inactive channel on PFIFO: %d\n", chid); return -EINVAL; @@ -467,5 +499,5 @@ void nv50_fifo_tlb_flush(struct drm_device *dev) { - nv50_vm_flush(dev, 5); + nv50_vm_flush_engine(dev, 5); } --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_gpio.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -26,6 +26,28 @@ #include "nouveau_drv.h" #include "nouveau_hw.h" +#include "nv50_display.h" + +static void nv50_gpio_isr(struct drm_device *dev); +static void nv50_gpio_isr_bh(struct work_struct *work); + +struct nv50_gpio_priv { + struct list_head handlers; + spinlock_t lock; +}; + +struct nv50_gpio_handler { + struct drm_device *dev; + struct list_head head; + struct work_struct work; + bool inhibit; + + struct dcb_gpio_entry *gpio; + + void (*handler)(void *data, int state); + void *data; +}; + static int nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift) { @@ -75,29 +97,123 @@ return 0; } +int +nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag, + void (*handler)(void *, int), void *data) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nv50_gpio_priv *priv = pgpio->priv; + struct nv50_gpio_handler *gpioh; + struct dcb_gpio_entry *gpio; + unsigned long flags; + + gpio = nouveau_bios_gpio_entry(dev, tag); + if (!gpio) + return -ENOENT; + + gpioh = kzalloc(sizeof(*gpioh), GFP_KERNEL); + if (!gpioh) + return -ENOMEM; + + INIT_WORK(&gpioh->work, nv50_gpio_isr_bh); + gpioh->dev = dev; + gpioh->gpio = gpio; + gpioh->handler = handler; + gpioh->data = data; + + spin_lock_irqsave(&priv->lock, flags); + list_add(&gpioh->head, &priv->handlers); + spin_unlock_irqrestore(&priv->lock, flags); + return 0; +} + void -nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on) +nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag, + void (*handler)(void *, int), void *data) { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nv50_gpio_priv *priv = pgpio->priv; + struct nv50_gpio_handler *gpioh, *tmp; struct dcb_gpio_entry *gpio; - u32 reg, mask; + unsigned long flags; gpio = nouveau_bios_gpio_entry(dev, tag); - if (!gpio) { - NV_ERROR(dev, "gpio tag 0x%02x not found\n", tag); + if (!gpio) return; + + spin_lock_irqsave(&priv->lock, flags); + list_for_each_entry_safe(gpioh, tmp, &priv->handlers, head) { + if (gpioh->gpio != gpio || + gpioh->handler != handler || + gpioh->data != data) + continue; + list_del(&gpioh->head); + kfree(gpioh); } + spin_unlock_irqrestore(&priv->lock, flags); +} + +bool +nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on) +{ + struct dcb_gpio_entry *gpio; + u32 reg, mask; + + gpio = nouveau_bios_gpio_entry(dev, tag); + if (!gpio) + return false; reg = gpio->line < 16 ? 0xe050 : 0xe070; mask = 0x00010001 << (gpio->line & 0xf); nv_wr32(dev, reg + 4, mask); - nv_mask(dev, reg + 0, mask, on ? mask : 0); + reg = nv_mask(dev, reg + 0, mask, on ? mask : 0); + return (reg & mask) == mask; +} + +static int +nv50_gpio_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nv50_gpio_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + INIT_LIST_HEAD(&priv->handlers); + spin_lock_init(&priv->lock); + pgpio->priv = priv; + return 0; +} + +static void +nv50_gpio_destroy(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + + kfree(pgpio->priv); + pgpio->priv = NULL; } int nv50_gpio_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nv50_gpio_priv *priv; + int ret; + + if (!pgpio->priv) { + ret = nv50_gpio_create(dev); + if (ret) + return ret; + } + priv = pgpio->priv; /* disable, and ack any pending gpio interrupts */ nv_wr32(dev, 0xe050, 0x00000000); @@ -107,5 +223,77 @@ nv_wr32(dev, 0xe074, 0xffffffff); } + nouveau_irq_register(dev, 21, nv50_gpio_isr); return 0; } + +void +nv50_gpio_fini(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + nv_wr32(dev, 0xe050, 0x00000000); + if (dev_priv->chipset >= 0x90) + nv_wr32(dev, 0xe070, 0x00000000); + nouveau_irq_unregister(dev, 21); + + nv50_gpio_destroy(dev); +} + +static void +nv50_gpio_isr_bh(struct work_struct *work) +{ + struct nv50_gpio_handler *gpioh = + container_of(work, struct nv50_gpio_handler, work); + struct drm_nouveau_private *dev_priv = gpioh->dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nv50_gpio_priv *priv = pgpio->priv; + unsigned long flags; + int state; + + state = pgpio->get(gpioh->dev, gpioh->gpio->tag); + if (state < 0) + return; + + gpioh->handler(gpioh->data, state); + + spin_lock_irqsave(&priv->lock, flags); + gpioh->inhibit = false; + spin_unlock_irqrestore(&priv->lock, flags); +} + +static void +nv50_gpio_isr(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nv50_gpio_priv *priv = pgpio->priv; + struct nv50_gpio_handler *gpioh; + u32 intr0, intr1 = 0; + u32 hi, lo, ch; + + intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); + if (dev_priv->chipset >= 0x90) + intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); + + hi = (intr0 & 0x0000ffff) | (intr1 << 16); + lo = (intr0 >> 16) | (intr1 & 0xffff0000); + ch = hi | lo; + + nv_wr32(dev, 0xe054, intr0); + if (dev_priv->chipset >= 0x90) + nv_wr32(dev, 0xe074, intr1); + + spin_lock(&priv->lock); + list_for_each_entry(gpioh, &priv->handlers, head) { + if (!(ch & (1 << gpioh->gpio->line))) + continue; + + if (gpioh->inhibit) + continue; + gpioh->inhibit = true; + + queue_work(dev_priv->wq, &gpioh->work); + } + spin_unlock(&priv->lock); +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_graph.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_graph.c @@ -29,6 +29,12 @@ #include "nouveau_drv.h" #include "nouveau_ramht.h" #include "nouveau_grctx.h" +#include "nouveau_dma.h" +#include "nouveau_vm.h" +#include "nv50_evo.h" + +static int nv50_graph_register(struct drm_device *); +static void nv50_graph_isr(struct drm_device *); static void nv50_graph_init_reset(struct drm_device *dev) @@ -46,6 +52,7 @@ { NV_DEBUG(dev, "\n"); + nouveau_irq_register(dev, 12, nv50_graph_isr); nv_wr32(dev, NV03_PGRAPH_INTR, 0xffffffff); nv_wr32(dev, 0x400138, 0xffffffff); nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xffffffff); @@ -145,12 +152,15 @@ nv50_graph_init_reset(dev); nv50_graph_init_regs__nv(dev); nv50_graph_init_regs(dev); - nv50_graph_init_intr(dev); ret = nv50_graph_init_ctxctl(dev); if (ret) return ret; + ret = nv50_graph_register(dev); + if (ret) + return ret; + nv50_graph_init_intr(dev); return 0; } @@ -158,6 +168,8 @@ nv50_graph_takedown(struct drm_device *dev) { NV_DEBUG(dev, "\n"); + nv_wr32(dev, 0x40013c, 0x00000000); + nouveau_irq_unregister(dev, 12); } void @@ -190,7 +202,7 @@ inst = (inst & NV50_PGRAPH_CTXCTL_CUR_INSTANCE) << 12; for (i = 0; i < dev_priv->engine.fifo.channels; i++) { - struct nouveau_channel *chan = dev_priv->fifos[i]; + struct nouveau_channel *chan = dev_priv->channels.ptr[i]; if (chan && chan->ramin && chan->ramin->vinst == inst) return chan; @@ -211,7 +223,7 @@ NV_DEBUG(dev, "ch%d\n", chan->id); - ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 0x1000, + ret = nouveau_gpuobj_new(dev, chan, pgraph->grctx_size, 0, NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx); if (ret) @@ -234,6 +246,7 @@ nv_wo32(chan->ramin_grctx, 0x00000, chan->ramin->vinst >> 12); dev_priv->engine.instmem.flush(dev); + atomic_inc(&chan->vm->pgraph_refs); return 0; } @@ -242,18 +255,31 @@ { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; + unsigned long flags; NV_DEBUG(dev, "ch%d\n", chan->id); if (!chan->ramin) return; + spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + pgraph->fifo_access(dev, false); + + if (pgraph->channel(dev) == chan) + pgraph->unload_context(dev); + for (i = hdr; i < hdr + 24; i += 4) nv_wo32(chan->ramin, i, 0); dev_priv->engine.instmem.flush(dev); + pgraph->fifo_access(dev, true); + spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); + nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); + + atomic_dec(&chan->vm->pgraph_refs); } static int @@ -306,7 +332,7 @@ return 0; } -void +static void nv50_graph_context_switch(struct drm_device *dev) { uint32_t inst; @@ -322,8 +348,8 @@ } static int -nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv50_graph_nvsw_dma_vblsem(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { struct nouveau_gpuobj *gpuobj; @@ -340,8 +366,8 @@ } static int -nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv50_graph_nvsw_vblsem_offset(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { if (nouveau_notifier_offset(chan->nvsw.vblsem, &data)) return -ERANGE; @@ -351,16 +377,16 @@ } static int -nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv50_graph_nvsw_vblsem_release_val(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { chan->nvsw.vblsem_rval = data; return 0; } static int -nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, int grclass, - int mthd, uint32_t data) +nv50_graph_nvsw_vblsem_release(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -368,45 +394,85 @@ if (!chan->nvsw.vblsem || chan->nvsw.vblsem_offset == ~0 || data > 1) return -EINVAL; - if (!(nv_rd32(dev, NV50_PDISPLAY_INTR_EN) & - NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data))) { - nv_wr32(dev, NV50_PDISPLAY_INTR_1, - NV50_PDISPLAY_INTR_1_VBLANK_CRTC_(data)); - nv_wr32(dev, NV50_PDISPLAY_INTR_EN, nv_rd32(dev, - NV50_PDISPLAY_INTR_EN) | - NV50_PDISPLAY_INTR_EN_VBLANK_CRTC_(data)); - } + drm_vblank_get(dev, data); + chan->nvsw.vblsem_head = data; list_add(&chan->nvsw.vbl_wait, &dev_priv->vbl_waiting); + return 0; } -static struct nouveau_pgraph_object_method nv50_graph_nvsw_methods[] = { - { 0x018c, nv50_graph_nvsw_dma_vblsem }, - { 0x0400, nv50_graph_nvsw_vblsem_offset }, - { 0x0404, nv50_graph_nvsw_vblsem_release_val }, - { 0x0408, nv50_graph_nvsw_vblsem_release }, - {} -}; +static int +nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan, + u32 class, u32 mthd, u32 data) +{ + struct nouveau_page_flip_state s; -struct nouveau_pgraph_object_class nv50_graph_grclass[] = { - { 0x506e, true, nv50_graph_nvsw_methods }, /* nvsw */ - { 0x0030, false, NULL }, /* null */ - { 0x5039, false, NULL }, /* m2mf */ - { 0x502d, false, NULL }, /* 2d */ - { 0x50c0, false, NULL }, /* compute */ - { 0x85c0, false, NULL }, /* compute (nva3, nva5, nva8) */ - { 0x5097, false, NULL }, /* tesla (nv50) */ - { 0x8297, false, NULL }, /* tesla (nv8x/nv9x) */ - { 0x8397, false, NULL }, /* tesla (nva0, nvaa, nvac) */ - { 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */ - {} -}; + if (!nouveau_finish_page_flip(chan, &s)) { + /* XXX - Do something here */ + } + + return 0; +} + +static int +nv50_graph_register(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if (dev_priv->engine.graph.registered) + return 0; + + NVOBJ_CLASS(dev, 0x506e, SW); /* nvsw */ + NVOBJ_MTHD (dev, 0x506e, 0x018c, nv50_graph_nvsw_dma_vblsem); + NVOBJ_MTHD (dev, 0x506e, 0x0400, nv50_graph_nvsw_vblsem_offset); + NVOBJ_MTHD (dev, 0x506e, 0x0404, nv50_graph_nvsw_vblsem_release_val); + NVOBJ_MTHD (dev, 0x506e, 0x0408, nv50_graph_nvsw_vblsem_release); + NVOBJ_MTHD (dev, 0x506e, 0x0500, nv50_graph_nvsw_mthd_page_flip); + + NVOBJ_CLASS(dev, 0x0030, GR); /* null */ + NVOBJ_CLASS(dev, 0x5039, GR); /* m2mf */ + NVOBJ_CLASS(dev, 0x502d, GR); /* 2d */ + + /* tesla */ + if (dev_priv->chipset == 0x50) + NVOBJ_CLASS(dev, 0x5097, GR); /* tesla (nv50) */ + else + if (dev_priv->chipset < 0xa0) + NVOBJ_CLASS(dev, 0x8297, GR); /* tesla (nv8x/nv9x) */ + else { + switch (dev_priv->chipset) { + case 0xa0: + case 0xaa: + case 0xac: + NVOBJ_CLASS(dev, 0x8397, GR); + break; + case 0xa3: + case 0xa5: + case 0xa8: + NVOBJ_CLASS(dev, 0x8597, GR); + break; + case 0xaf: + NVOBJ_CLASS(dev, 0x8697, GR); + break; + } + } + + /* compute */ + NVOBJ_CLASS(dev, 0x50c0, GR); + if (dev_priv->chipset > 0xa0 && + dev_priv->chipset != 0xaa && + dev_priv->chipset != 0xac) + NVOBJ_CLASS(dev, 0x85c0, GR); + + dev_priv->engine.graph.registered = true; + return 0; +} void nv50_graph_tlb_flush(struct drm_device *dev) { - nv50_vm_flush(dev, 0); + nv50_vm_flush_engine(dev, 0); } void @@ -449,8 +515,500 @@ nv_rd32(dev, 0x400384), nv_rd32(dev, 0x400388)); } - nv50_vm_flush(dev, 0); + nv50_vm_flush_engine(dev, 0); nv_mask(dev, 0x400500, 0x00000001, 0x00000001); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); } + +static struct nouveau_enum nv50_mp_exec_error_names[] = +{ + { 3, "STACK_UNDERFLOW" }, + { 4, "QUADON_ACTIVE" }, + { 8, "TIMEOUT" }, + { 0x10, "INVALID_OPCODE" }, + { 0x40, "BREAKPOINT" }, + {} +}; + +static struct nouveau_bitfield nv50_graph_trap_m2mf[] = { + { 0x00000001, "NOTIFY" }, + { 0x00000002, "IN" }, + { 0x00000004, "OUT" }, + {} +}; + +static struct nouveau_bitfield nv50_graph_trap_vfetch[] = { + { 0x00000001, "FAULT" }, + {} +}; + +static struct nouveau_bitfield nv50_graph_trap_strmout[] = { + { 0x00000001, "FAULT" }, + {} +}; + +static struct nouveau_bitfield nv50_graph_trap_ccache[] = { + { 0x00000001, "FAULT" }, + {} +}; + +/* There must be a *lot* of these. Will take some time to gather them up. */ +static struct nouveau_enum nv50_data_error_names[] = { + { 4, "INVALID_VALUE" }, + { 5, "INVALID_ENUM" }, + { 8, "INVALID_OBJECT" }, + { 0xc, "INVALID_BITFIELD" }, + { 0x28, "MP_NO_REG_SPACE" }, + { 0x2b, "MP_BLOCK_SIZE_MISMATCH" }, + {} +}; + +static struct nouveau_bitfield nv50_graph_intr[] = { + { 0x00000001, "NOTIFY" }, + { 0x00000002, "COMPUTE_QUERY" }, + { 0x00000010, "ILLEGAL_MTHD" }, + { 0x00000020, "ILLEGAL_CLASS" }, + { 0x00000040, "DOUBLE_NOTIFY" }, + { 0x00001000, "CONTEXT_SWITCH" }, + { 0x00010000, "BUFFER_NOTIFY" }, + { 0x00100000, "DATA_ERROR" }, + { 0x00200000, "TRAP" }, + { 0x01000000, "SINGLE_STEP" }, + {} +}; + +static void +nv50_pgraph_mp_trap(struct drm_device *dev, int tpid, int display) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t units = nv_rd32(dev, 0x1540); + uint32_t addr, mp10, status, pc, oplow, ophigh; + int i; + int mps = 0; + for (i = 0; i < 4; i++) { + if (!(units & 1 << (i+24))) + continue; + if (dev_priv->chipset < 0xa0) + addr = 0x408200 + (tpid << 12) + (i << 7); + else + addr = 0x408100 + (tpid << 11) + (i << 7); + mp10 = nv_rd32(dev, addr + 0x10); + status = nv_rd32(dev, addr + 0x14); + if (!status) + continue; + if (display) { + nv_rd32(dev, addr + 0x20); + pc = nv_rd32(dev, addr + 0x24); + oplow = nv_rd32(dev, addr + 0x70); + ophigh= nv_rd32(dev, addr + 0x74); + NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - " + "TP %d MP %d: ", tpid, i); + nouveau_enum_print(nv50_mp_exec_error_names, status); + printk(" at %06x warp %d, opcode %08x %08x\n", + pc&0xffffff, pc >> 24, + oplow, ophigh); + } + nv_wr32(dev, addr + 0x10, mp10); + nv_wr32(dev, addr + 0x14, 0); + mps++; + } + if (!mps && display) + NV_INFO(dev, "PGRAPH_TRAP_MP_EXEC - TP %d: " + "No MPs claiming errors?\n", tpid); +} + +static void +nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, + uint32_t ustatus_new, int display, const char *name) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int tps = 0; + uint32_t units = nv_rd32(dev, 0x1540); + int i, r; + uint32_t ustatus_addr, ustatus; + for (i = 0; i < 16; i++) { + if (!(units & (1 << i))) + continue; + if (dev_priv->chipset < 0xa0) + ustatus_addr = ustatus_old + (i << 12); + else + ustatus_addr = ustatus_new + (i << 11); + ustatus = nv_rd32(dev, ustatus_addr) & 0x7fffffff; + if (!ustatus) + continue; + tps++; + switch (type) { + case 6: /* texture error... unknown for now */ + nv50_fb_vm_trap(dev, display, name); + if (display) { + NV_ERROR(dev, "magic set %d:\n", i); + for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) + NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, + nv_rd32(dev, r)); + } + break; + case 7: /* MP error */ + if (ustatus & 0x00010000) { + nv50_pgraph_mp_trap(dev, i, display); + ustatus &= ~0x00010000; + } + break; + case 8: /* TPDMA error */ + { + uint32_t e0c = nv_rd32(dev, ustatus_addr + 4); + uint32_t e10 = nv_rd32(dev, ustatus_addr + 8); + uint32_t e14 = nv_rd32(dev, ustatus_addr + 0xc); + uint32_t e18 = nv_rd32(dev, ustatus_addr + 0x10); + uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); + uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); + uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); + nv50_fb_vm_trap(dev, display, name); + /* 2d engine destination */ + if (ustatus & 0x00000010) { + if (display) { + NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - Unknown fault at address %02x%08x\n", + i, e14, e10); + NV_INFO(dev, "PGRAPH_TRAP_TPDMA_2D - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", + i, e0c, e18, e1c, e20, e24); + } + ustatus &= ~0x00000010; + } + /* Render target */ + if (ustatus & 0x00000040) { + if (display) { + NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - Unknown fault at address %02x%08x\n", + i, e14, e10); + NV_INFO(dev, "PGRAPH_TRAP_TPDMA_RT - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", + i, e0c, e18, e1c, e20, e24); + } + ustatus &= ~0x00000040; + } + /* CUDA memory: l[], g[] or stack. */ + if (ustatus & 0x00000080) { + if (display) { + if (e18 & 0x80000000) { + /* g[] read fault? */ + NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global read fault at address %02x%08x\n", + i, e14, e10 | ((e18 >> 24) & 0x1f)); + e18 &= ~0x1f000000; + } else if (e18 & 0xc) { + /* g[] write fault? */ + NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Global write fault at address %02x%08x\n", + i, e14, e10 | ((e18 >> 7) & 0x1f)); + e18 &= ~0x00000f80; + } else { + NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - Unknown CUDA fault at address %02x%08x\n", + i, e14, e10); + } + NV_INFO(dev, "PGRAPH_TRAP_TPDMA - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n", + i, e0c, e18, e1c, e20, e24); + } + ustatus &= ~0x00000080; + } + } + break; + } + if (ustatus) { + if (display) + NV_INFO(dev, "%s - TP%d: Unhandled ustatus 0x%08x\n", name, i, ustatus); + } + nv_wr32(dev, ustatus_addr, 0xc0000000); + } + + if (!tps && display) + NV_INFO(dev, "%s - No TPs claiming errors?\n", name); +} + +static int +nv50_pgraph_trap_handler(struct drm_device *dev, u32 display, u64 inst, u32 chid) +{ + u32 status = nv_rd32(dev, 0x400108); + u32 ustatus; + + if (!status && display) { + NV_INFO(dev, "PGRAPH - TRAP: no units reporting traps?\n"); + return 1; + } + + /* DISPATCH: Relays commands to other units and handles NOTIFY, + * COND, QUERY. If you get a trap from it, the command is still stuck + * in DISPATCH and you need to do something about it. */ + if (status & 0x001) { + ustatus = nv_rd32(dev, 0x400804) & 0x7fffffff; + if (!ustatus && display) { + NV_INFO(dev, "PGRAPH_TRAP_DISPATCH - no ustatus?\n"); + } + + nv_wr32(dev, 0x400500, 0x00000000); + + /* Known to be triggered by screwed up NOTIFY and COND... */ + if (ustatus & 0x00000001) { + u32 addr = nv_rd32(dev, 0x400808); + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 datal = nv_rd32(dev, 0x40080c); + u32 datah = nv_rd32(dev, 0x400810); + u32 class = nv_rd32(dev, 0x400814); + u32 r848 = nv_rd32(dev, 0x400848); + + NV_INFO(dev, "PGRAPH - TRAP DISPATCH_FAULT\n"); + if (display && (addr & 0x80000000)) { + NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) " + "subc %d class 0x%04x mthd 0x%04x " + "data 0x%08x%08x " + "400808 0x%08x 400848 0x%08x\n", + chid, inst, subc, class, mthd, datah, + datal, addr, r848); + } else + if (display) { + NV_INFO(dev, "PGRAPH - no stuck command?\n"); + } + + nv_wr32(dev, 0x400808, 0); + nv_wr32(dev, 0x4008e8, nv_rd32(dev, 0x4008e8) & 3); + nv_wr32(dev, 0x400848, 0); + ustatus &= ~0x00000001; + } + + if (ustatus & 0x00000002) { + u32 addr = nv_rd32(dev, 0x40084c); + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(dev, 0x40085c); + u32 class = nv_rd32(dev, 0x400814); + + NV_INFO(dev, "PGRAPH - TRAP DISPATCH_QUERY\n"); + if (display && (addr & 0x80000000)) { + NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) " + "subc %d class 0x%04x mthd 0x%04x " + "data 0x%08x 40084c 0x%08x\n", + chid, inst, subc, class, mthd, + data, addr); + } else + if (display) { + NV_INFO(dev, "PGRAPH - no stuck command?\n"); + } + + nv_wr32(dev, 0x40084c, 0); + ustatus &= ~0x00000002; + } + + if (ustatus && display) { + NV_INFO(dev, "PGRAPH - TRAP_DISPATCH (unknown " + "0x%08x)\n", ustatus); + } + + nv_wr32(dev, 0x400804, 0xc0000000); + nv_wr32(dev, 0x400108, 0x001); + status &= ~0x001; + if (!status) + return 0; + } + + /* M2MF: Memory to memory copy engine. */ + if (status & 0x002) { + u32 ustatus = nv_rd32(dev, 0x406800) & 0x7fffffff; + if (display) { + NV_INFO(dev, "PGRAPH - TRAP_M2MF"); + nouveau_bitfield_print(nv50_graph_trap_m2mf, ustatus); + printk("\n"); + NV_INFO(dev, "PGRAPH - TRAP_M2MF %08x %08x %08x %08x\n", + nv_rd32(dev, 0x406804), nv_rd32(dev, 0x406808), + nv_rd32(dev, 0x40680c), nv_rd32(dev, 0x406810)); + + } + + /* No sane way found yet -- just reset the bugger. */ + nv_wr32(dev, 0x400040, 2); + nv_wr32(dev, 0x400040, 0); + nv_wr32(dev, 0x406800, 0xc0000000); + nv_wr32(dev, 0x400108, 0x002); + status &= ~0x002; + } + + /* VFETCH: Fetches data from vertex buffers. */ + if (status & 0x004) { + u32 ustatus = nv_rd32(dev, 0x400c04) & 0x7fffffff; + if (display) { + NV_INFO(dev, "PGRAPH - TRAP_VFETCH"); + nouveau_bitfield_print(nv50_graph_trap_vfetch, ustatus); + printk("\n"); + NV_INFO(dev, "PGRAPH - TRAP_VFETCH %08x %08x %08x %08x\n", + nv_rd32(dev, 0x400c00), nv_rd32(dev, 0x400c08), + nv_rd32(dev, 0x400c0c), nv_rd32(dev, 0x400c10)); + } + + nv_wr32(dev, 0x400c04, 0xc0000000); + nv_wr32(dev, 0x400108, 0x004); + status &= ~0x004; + } + + /* STRMOUT: DirectX streamout / OpenGL transform feedback. */ + if (status & 0x008) { + ustatus = nv_rd32(dev, 0x401800) & 0x7fffffff; + if (display) { + NV_INFO(dev, "PGRAPH - TRAP_STRMOUT"); + nouveau_bitfield_print(nv50_graph_trap_strmout, ustatus); + printk("\n"); + NV_INFO(dev, "PGRAPH - TRAP_STRMOUT %08x %08x %08x %08x\n", + nv_rd32(dev, 0x401804), nv_rd32(dev, 0x401808), + nv_rd32(dev, 0x40180c), nv_rd32(dev, 0x401810)); + + } + + /* No sane way found yet -- just reset the bugger. */ + nv_wr32(dev, 0x400040, 0x80); + nv_wr32(dev, 0x400040, 0); + nv_wr32(dev, 0x401800, 0xc0000000); + nv_wr32(dev, 0x400108, 0x008); + status &= ~0x008; + } + + /* CCACHE: Handles code and c[] caches and fills them. */ + if (status & 0x010) { + ustatus = nv_rd32(dev, 0x405018) & 0x7fffffff; + if (display) { + NV_INFO(dev, "PGRAPH - TRAP_CCACHE"); + nouveau_bitfield_print(nv50_graph_trap_ccache, ustatus); + printk("\n"); + NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x" + " %08x %08x %08x\n", + nv_rd32(dev, 0x405800), nv_rd32(dev, 0x405804), + nv_rd32(dev, 0x405808), nv_rd32(dev, 0x40580c), + nv_rd32(dev, 0x405810), nv_rd32(dev, 0x405814), + nv_rd32(dev, 0x40581c)); + + } + + nv_wr32(dev, 0x405018, 0xc0000000); + nv_wr32(dev, 0x400108, 0x010); + status &= ~0x010; + } + + /* Unknown, not seen yet... 0x402000 is the only trap status reg + * remaining, so try to handle it anyway. Perhaps related to that + * unknown DMA slot on tesla? */ + if (status & 0x20) { + ustatus = nv_rd32(dev, 0x402000) & 0x7fffffff; + if (display) + NV_INFO(dev, "PGRAPH - TRAP_UNKC04 0x%08x\n", ustatus); + nv_wr32(dev, 0x402000, 0xc0000000); + /* no status modifiction on purpose */ + } + + /* TEXTURE: CUDA texturing units */ + if (status & 0x040) { + nv50_pgraph_tp_trap(dev, 6, 0x408900, 0x408600, display, + "PGRAPH - TRAP_TEXTURE"); + nv_wr32(dev, 0x400108, 0x040); + status &= ~0x040; + } + + /* MP: CUDA execution engines. */ + if (status & 0x080) { + nv50_pgraph_tp_trap(dev, 7, 0x408314, 0x40831c, display, + "PGRAPH - TRAP_MP"); + nv_wr32(dev, 0x400108, 0x080); + status &= ~0x080; + } + + /* TPDMA: Handles TP-initiated uncached memory accesses: + * l[], g[], stack, 2d surfaces, render targets. */ + if (status & 0x100) { + nv50_pgraph_tp_trap(dev, 8, 0x408e08, 0x408708, display, + "PGRAPH - TRAP_TPDMA"); + nv_wr32(dev, 0x400108, 0x100); + status &= ~0x100; + } + + if (status) { + if (display) + NV_INFO(dev, "PGRAPH - TRAP: unknown 0x%08x\n", status); + nv_wr32(dev, 0x400108, status); + } + + return 1; +} + +static int +nv50_graph_isr_chid(struct drm_device *dev, u64 inst) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_channel *chan; + unsigned long flags; + int i; + + spin_lock_irqsave(&dev_priv->channels.lock, flags); + for (i = 0; i < dev_priv->engine.fifo.channels; i++) { + chan = dev_priv->channels.ptr[i]; + if (!chan || !chan->ramin) + continue; + + if (inst == chan->ramin->vinst) + break; + } + spin_unlock_irqrestore(&dev_priv->channels.lock, flags); + return i; +} + +static void +nv50_graph_isr(struct drm_device *dev) +{ + u32 stat; + + while ((stat = nv_rd32(dev, 0x400100))) { + u64 inst = (u64)(nv_rd32(dev, 0x40032c) & 0x0fffffff) << 12; + u32 chid = nv50_graph_isr_chid(dev, inst); + u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); + u32 subc = (addr & 0x00070000) >> 16; + u32 mthd = (addr & 0x00001ffc); + u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); + u32 class = nv_rd32(dev, 0x400814); + u32 show = stat; + + if (stat & 0x00000010) { + if (!nouveau_gpuobj_mthd_call2(dev, chid, class, + mthd, data)) + show &= ~0x00000010; + } + + if (stat & 0x00001000) { + nv_wr32(dev, 0x400500, 0x00000000); + nv_wr32(dev, 0x400100, 0x00001000); + nv_mask(dev, 0x40013c, 0x00001000, 0x00000000); + nv50_graph_context_switch(dev); + stat &= ~0x00001000; + show &= ~0x00001000; + } + + show = (show && nouveau_ratelimit()) ? show : 0; + + if (show & 0x00100000) { + u32 ecode = nv_rd32(dev, 0x400110); + NV_INFO(dev, "PGRAPH - DATA_ERROR "); + nouveau_enum_print(nv50_data_error_names, ecode); + printk("\n"); + } + + if (stat & 0x00200000) { + if (!nv50_pgraph_trap_handler(dev, show, inst, chid)) + show &= ~0x00200000; + } + + nv_wr32(dev, 0x400100, stat); + nv_wr32(dev, 0x400500, 0x00010001); + + if (show) { + NV_INFO(dev, "PGRAPH -"); + nouveau_bitfield_print(nv50_graph_intr, show); + printk("\n"); + NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d " + "class 0x%04x mthd 0x%04x data 0x%08x\n", + chid, inst, subc, class, mthd, data); + } + } + + if (nv_rd32(dev, 0x400824) & (1 << 31)) + nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_instmem.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_instmem.c @@ -27,14 +27,20 @@ #include "drmP.h" #include "drm.h" + #include "nouveau_drv.h" +#include "nouveau_vm.h" + +#define BAR1_VM_BASE 0x0020000000ULL +#define BAR1_VM_SIZE pci_resource_len(dev->pdev, 1) +#define BAR3_VM_BASE 0x0000000000ULL +#define BAR3_VM_SIZE pci_resource_len(dev->pdev, 3) struct nv50_instmem_priv { uint32_t save1700[5]; /* 0x1700->0x1710 */ - struct nouveau_gpuobj *pramin_pt; - struct nouveau_gpuobj *pramin_bar; - struct nouveau_gpuobj *fb_bar; + struct nouveau_gpuobj *bar1_dmaobj; + struct nouveau_gpuobj *bar3_dmaobj; }; static void @@ -48,6 +54,7 @@ return; nouveau_gpuobj_ref(NULL, &chan->ramfc); + nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd); nouveau_gpuobj_ref(NULL, &chan->vm_pd); if (chan->ramin_heap.free_stack.next) drm_mm_takedown(&chan->ramin_heap); @@ -56,14 +63,14 @@ } static int -nv50_channel_new(struct drm_device *dev, u32 size, +nv50_channel_new(struct drm_device *dev, u32 size, struct nouveau_vm *vm, struct nouveau_channel **pchan) { struct drm_nouveau_private *dev_priv = dev->dev_private; u32 pgd = (dev_priv->chipset == 0x50) ? 0x1400 : 0x0200; u32 fc = (dev_priv->chipset == 0x50) ? 0x0000 : 0x4200; struct nouveau_channel *chan; - int ret; + int ret, i; chan = kzalloc(sizeof(*chan), GFP_KERNEL); if (!chan) @@ -92,6 +99,17 @@ return ret; } + for (i = 0; i < 0x4000; i += 8) { + nv_wo32(chan->vm_pd, i + 0, 0x00000000); + nv_wo32(chan->vm_pd, i + 4, 0xdeadcafe); + } + + ret = nouveau_vm_ref(vm, &chan->vm, chan->vm_pd); + if (ret) { + nv50_channel_del(&chan); + return ret; + } + ret = nouveau_gpuobj_new_fake(dev, chan->ramin->pinst == ~0 ? ~0 : chan->ramin->pinst + fc, chan->ramin->vinst + fc, 0x100, @@ -111,6 +129,7 @@ struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_instmem_priv *priv; struct nouveau_channel *chan; + struct nouveau_vm *vm; int ret, i; u32 tmp; @@ -127,112 +146,89 @@ ret = drm_mm_init(&dev_priv->ramin_heap, 0, dev_priv->ramin_size); if (ret) { NV_ERROR(dev, "Failed to init RAMIN heap\n"); - return -ENOMEM; + goto error; } - /* we need a channel to plug into the hw to control the BARs */ - ret = nv50_channel_new(dev, 128*1024, &dev_priv->fifos[0]); + /* BAR3 */ + ret = nouveau_vm_new(dev, BAR3_VM_BASE, BAR3_VM_SIZE, BAR3_VM_BASE, + 29, 12, 16, &dev_priv->bar3_vm); if (ret) - return ret; - chan = dev_priv->fifos[127] = dev_priv->fifos[0]; + goto error; - /* allocate page table for PRAMIN BAR */ - ret = nouveau_gpuobj_new(dev, chan, (dev_priv->ramin_size >> 12) * 8, - 0x1000, NVOBJ_FLAG_ZERO_ALLOC, - &priv->pramin_pt); + ret = nouveau_gpuobj_new(dev, NULL, (BAR3_VM_SIZE >> 12) * 8, + 0x1000, NVOBJ_FLAG_DONT_MAP | + NVOBJ_FLAG_ZERO_ALLOC, + &dev_priv->bar3_vm->pgt[0].obj); if (ret) - return ret; + goto error; + dev_priv->bar3_vm->pgt[0].page_shift = 12; + dev_priv->bar3_vm->pgt[0].refcount = 1; - nv_wo32(chan->vm_pd, 0x0000, priv->pramin_pt->vinst | 0x63); - nv_wo32(chan->vm_pd, 0x0004, 0); + nv50_instmem_map(dev_priv->bar3_vm->pgt[0].obj); - /* DMA object for PRAMIN BAR */ - ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->pramin_bar); + ret = nv50_channel_new(dev, 128 * 1024, dev_priv->bar3_vm, &chan); if (ret) - return ret; - nv_wo32(priv->pramin_bar, 0x00, 0x7fc00000); - nv_wo32(priv->pramin_bar, 0x04, dev_priv->ramin_size - 1); - nv_wo32(priv->pramin_bar, 0x08, 0x00000000); - nv_wo32(priv->pramin_bar, 0x0c, 0x00000000); - nv_wo32(priv->pramin_bar, 0x10, 0x00000000); - nv_wo32(priv->pramin_bar, 0x14, 0x00000000); + goto error; + dev_priv->channels.ptr[0] = dev_priv->channels.ptr[127] = chan; - /* map channel into PRAMIN, gpuobj didn't do it for us */ - ret = nv50_instmem_bind(dev, chan->ramin); + ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR3_VM_BASE, BAR3_VM_SIZE, + NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, + NV_MEM_TYPE_VM, NV_MEM_COMP_VM, + &priv->bar3_dmaobj); if (ret) - return ret; + goto error; - /* poke regs... */ nv_wr32(dev, 0x001704, 0x00000000 | (chan->ramin->vinst >> 12)); nv_wr32(dev, 0x001704, 0x40000000 | (chan->ramin->vinst >> 12)); - nv_wr32(dev, 0x00170c, 0x80000000 | (priv->pramin_bar->cinst >> 4)); - - tmp = nv_ri32(dev, 0); - nv_wi32(dev, 0, ~tmp); - if (nv_ri32(dev, 0) != ~tmp) { - NV_ERROR(dev, "PRAMIN readback failed\n"); - return -EIO; - } - nv_wi32(dev, 0, tmp); + nv_wr32(dev, 0x00170c, 0x80000000 | (priv->bar3_dmaobj->cinst >> 4)); + dev_priv->engine.instmem.flush(dev); dev_priv->ramin_available = true; - /* Determine VM layout */ - dev_priv->vm_gart_base = roundup(NV50_VM_BLOCK, NV50_VM_BLOCK); - dev_priv->vm_gart_size = NV50_VM_BLOCK; - - dev_priv->vm_vram_base = dev_priv->vm_gart_base + dev_priv->vm_gart_size; - dev_priv->vm_vram_size = dev_priv->vram_size; - if (dev_priv->vm_vram_size > NV50_VM_MAX_VRAM) - dev_priv->vm_vram_size = NV50_VM_MAX_VRAM; - dev_priv->vm_vram_size = roundup(dev_priv->vm_vram_size, NV50_VM_BLOCK); - dev_priv->vm_vram_pt_nr = dev_priv->vm_vram_size / NV50_VM_BLOCK; - - dev_priv->vm_end = dev_priv->vm_vram_base + dev_priv->vm_vram_size; - - NV_DEBUG(dev, "NV50VM: GART 0x%016llx-0x%016llx\n", - dev_priv->vm_gart_base, - dev_priv->vm_gart_base + dev_priv->vm_gart_size - 1); - NV_DEBUG(dev, "NV50VM: VRAM 0x%016llx-0x%016llx\n", - dev_priv->vm_vram_base, - dev_priv->vm_vram_base + dev_priv->vm_vram_size - 1); - - /* VRAM page table(s), mapped into VM at +1GiB */ - for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) { - ret = nouveau_gpuobj_new(dev, NULL, NV50_VM_BLOCK / 0x10000 * 8, - 0, NVOBJ_FLAG_ZERO_ALLOC, - &chan->vm_vram_pt[i]); - if (ret) { - NV_ERROR(dev, "Error creating VRAM PGT: %d\n", ret); - dev_priv->vm_vram_pt_nr = i; - return ret; - } - dev_priv->vm_vram_pt[i] = chan->vm_vram_pt[i]; - - nv_wo32(chan->vm_pd, 0x10 + (i*8), - chan->vm_vram_pt[i]->vinst | 0x61); - nv_wo32(chan->vm_pd, 0x14 + (i*8), 0); + tmp = nv_ro32(chan->ramin, 0); + nv_wo32(chan->ramin, 0, ~tmp); + if (nv_ro32(chan->ramin, 0) != ~tmp) { + NV_ERROR(dev, "PRAMIN readback failed\n"); + ret = -EIO; + goto error; } + nv_wo32(chan->ramin, 0, tmp); - /* DMA object for FB BAR */ - ret = nouveau_gpuobj_new(dev, chan, 6*4, 16, 0, &priv->fb_bar); + /* BAR1 */ + ret = nouveau_vm_new(dev, BAR1_VM_BASE, BAR1_VM_SIZE, BAR1_VM_BASE, + 29, 12, 16, &vm); if (ret) - return ret; - nv_wo32(priv->fb_bar, 0x00, 0x7fc00000); - nv_wo32(priv->fb_bar, 0x04, 0x40000000 + - pci_resource_len(dev->pdev, 1) - 1); - nv_wo32(priv->fb_bar, 0x08, 0x40000000); - nv_wo32(priv->fb_bar, 0x0c, 0x00000000); - nv_wo32(priv->fb_bar, 0x10, 0x00000000); - nv_wo32(priv->fb_bar, 0x14, 0x00000000); + goto error; - dev_priv->engine.instmem.flush(dev); + ret = nouveau_vm_ref(vm, &dev_priv->bar1_vm, chan->vm_pd); + if (ret) + goto error; + nouveau_vm_ref(NULL, &vm, NULL); + + ret = nv50_gpuobj_dma_new(chan, 0x0000, BAR1_VM_BASE, BAR1_VM_SIZE, + NV_MEM_TARGET_VM, NV_MEM_ACCESS_VM, + NV_MEM_TYPE_VM, NV_MEM_COMP_VM, + &priv->bar1_dmaobj); + if (ret) + goto error; - nv_wr32(dev, 0x001708, 0x80000000 | (priv->fb_bar->cinst >> 4)); + nv_wr32(dev, 0x001708, 0x80000000 | (priv->bar1_dmaobj->cinst >> 4)); for (i = 0; i < 8; i++) nv_wr32(dev, 0x1900 + (i*4), 0); + /* Create shared channel VM, space is reserved at the beginning + * to catch "NULL pointer" references + */ + ret = nouveau_vm_new(dev, 0, (1ULL << 40), 0x0020000000ULL, + 29, 12, 16, &dev_priv->chan_vm); + if (ret) + return ret; + return 0; + +error: + nv50_instmem_takedown(dev); + return ret; } void @@ -240,7 +236,7 @@ { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; - struct nouveau_channel *chan = dev_priv->fifos[0]; + struct nouveau_channel *chan = dev_priv->channels.ptr[0]; int i; NV_DEBUG(dev, "\n"); @@ -250,23 +246,23 @@ dev_priv->ramin_available = false; - /* Restore state from before init */ + nouveau_vm_ref(NULL, &dev_priv->chan_vm, NULL); + for (i = 0x1700; i <= 0x1710; i += 4) nv_wr32(dev, i, priv->save1700[(i - 0x1700) / 4]); - nouveau_gpuobj_ref(NULL, &priv->fb_bar); - nouveau_gpuobj_ref(NULL, &priv->pramin_bar); - nouveau_gpuobj_ref(NULL, &priv->pramin_pt); - - /* Destroy dummy channel */ - if (chan) { - for (i = 0; i < dev_priv->vm_vram_pt_nr; i++) - nouveau_gpuobj_ref(NULL, &chan->vm_vram_pt[i]); - dev_priv->vm_vram_pt_nr = 0; + nouveau_gpuobj_ref(NULL, &priv->bar3_dmaobj); + nouveau_gpuobj_ref(NULL, &priv->bar1_dmaobj); - nv50_channel_del(&dev_priv->fifos[0]); - dev_priv->fifos[127] = NULL; - } + nouveau_vm_ref(NULL, &dev_priv->bar1_vm, chan->vm_pd); + dev_priv->channels.ptr[127] = 0; + nv50_channel_del(&dev_priv->channels.ptr[0]); + + nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj); + nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL); + + if (dev_priv->ramin_heap.free_stack.next) + drm_mm_takedown(&dev_priv->ramin_heap); dev_priv->engine.instmem.priv = NULL; kfree(priv); @@ -276,16 +272,8 @@ nv50_instmem_suspend(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_channel *chan = dev_priv->fifos[0]; - struct nouveau_gpuobj *ramin = chan->ramin; - int i; - ramin->im_backing_suspend = vmalloc(ramin->size); - if (!ramin->im_backing_suspend) - return -ENOMEM; - - for (i = 0; i < ramin->size; i += 4) - ramin->im_backing_suspend[i/4] = nv_ri32(dev, i); + dev_priv->ramin_available = false; return 0; } @@ -294,146 +282,121 @@ { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; - struct nouveau_channel *chan = dev_priv->fifos[0]; - struct nouveau_gpuobj *ramin = chan->ramin; + struct nouveau_channel *chan = dev_priv->channels.ptr[0]; int i; - dev_priv->ramin_available = false; - dev_priv->ramin_base = ~0; - for (i = 0; i < ramin->size; i += 4) - nv_wo32(ramin, i, ramin->im_backing_suspend[i/4]); - dev_priv->ramin_available = true; - vfree(ramin->im_backing_suspend); - ramin->im_backing_suspend = NULL; - /* Poke the relevant regs, and pray it works :) */ nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12)); nv_wr32(dev, NV50_PUNK_UNK1710, 0); nv_wr32(dev, NV50_PUNK_BAR_CFG_BASE, (chan->ramin->vinst >> 12) | NV50_PUNK_BAR_CFG_BASE_VALID); - nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->fb_bar->cinst >> 4) | + nv_wr32(dev, NV50_PUNK_BAR1_CTXDMA, (priv->bar1_dmaobj->cinst >> 4) | NV50_PUNK_BAR1_CTXDMA_VALID); - nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->pramin_bar->cinst >> 4) | + nv_wr32(dev, NV50_PUNK_BAR3_CTXDMA, (priv->bar3_dmaobj->cinst >> 4) | NV50_PUNK_BAR3_CTXDMA_VALID); for (i = 0; i < 8; i++) nv_wr32(dev, 0x1900 + (i*4), 0); + + dev_priv->ramin_available = true; } +struct nv50_gpuobj_node { + struct nouveau_vram *vram; + struct nouveau_vma chan_vma; + u32 align; +}; + + int -nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, - uint32_t *sz) +nv50_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) { + struct drm_device *dev = gpuobj->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + struct nv50_gpuobj_node *node = NULL; int ret; - if (gpuobj->im_backing) - return -EINVAL; + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + node->align = align; - *sz = ALIGN(*sz, 4096); - if (*sz == 0) - return -EINVAL; + size = (size + 4095) & ~4095; + align = max(align, (u32)4096); - ret = nouveau_bo_new(dev, NULL, *sz, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, - true, false, &gpuobj->im_backing); + ret = vram->get(dev, size, align, 0, 0, &node->vram); if (ret) { - NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); + kfree(node); return ret; } - ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM); - if (ret) { - NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret); - nouveau_bo_ref(NULL, &gpuobj->im_backing); - return ret; + gpuobj->vinst = node->vram->offset; + + if (gpuobj->flags & NVOBJ_FLAG_VM) { + ret = nouveau_vm_get(dev_priv->chan_vm, size, 12, + NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS, + &node->chan_vma); + if (ret) { + vram->put(dev, &node->vram); + kfree(node); + return ret; + } + + nouveau_vm_map(&node->chan_vma, node->vram); + gpuobj->vinst = node->chan_vma.offset; } - gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT; + gpuobj->size = size; + gpuobj->node = node; return 0; } void -nv50_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +nv50_instmem_put(struct nouveau_gpuobj *gpuobj) { + struct drm_device *dev = gpuobj->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_vram_engine *vram = &dev_priv->engine.vram; + struct nv50_gpuobj_node *node; + + node = gpuobj->node; + gpuobj->node = NULL; - if (gpuobj && gpuobj->im_backing) { - if (gpuobj->im_bound) - dev_priv->engine.instmem.unbind(dev, gpuobj); - nouveau_bo_unpin(gpuobj->im_backing); - nouveau_bo_ref(NULL, &gpuobj->im_backing); - gpuobj->im_backing = NULL; + if (node->chan_vma.node) { + nouveau_vm_unmap(&node->chan_vma); + nouveau_vm_put(&node->chan_vma); } + vram->put(dev, &node->vram); + kfree(node); } int -nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +nv50_instmem_map(struct nouveau_gpuobj *gpuobj) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; - struct nouveau_gpuobj *pramin_pt = priv->pramin_pt; - uint32_t pte, pte_end; - uint64_t vram; - - if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) - return -EINVAL; - - NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n", - gpuobj->im_pramin->start, gpuobj->im_pramin->size); - - pte = (gpuobj->im_pramin->start >> 12) << 1; - pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; - vram = gpuobj->vinst; - - NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", - gpuobj->im_pramin->start, pte, pte_end); - NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst); - - vram |= 1; - if (dev_priv->vram_sys_base) { - vram += dev_priv->vram_sys_base; - vram |= 0x30; - } - - while (pte < pte_end) { - nv_wo32(pramin_pt, (pte * 4) + 0, lower_32_bits(vram)); - nv_wo32(pramin_pt, (pte * 4) + 4, upper_32_bits(vram)); - vram += 0x1000; - pte += 2; - } - dev_priv->engine.instmem.flush(dev); + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct nv50_gpuobj_node *node = gpuobj->node; + int ret; - nv50_vm_flush(dev, 6); + ret = nouveau_vm_get(dev_priv->bar3_vm, gpuobj->size, 12, + NV_MEM_ACCESS_RW, &node->vram->bar_vma); + if (ret) + return ret; - gpuobj->im_bound = 1; + nouveau_vm_map(&node->vram->bar_vma, node->vram); + gpuobj->pinst = node->vram->bar_vma.offset; return 0; } -int -nv50_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +void +nv50_instmem_unmap(struct nouveau_gpuobj *gpuobj) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_instmem_priv *priv = dev_priv->engine.instmem.priv; - uint32_t pte, pte_end; - - if (gpuobj->im_bound == 0) - return -EINVAL; + struct nv50_gpuobj_node *node = gpuobj->node; - /* can happen during late takedown */ - if (unlikely(!dev_priv->ramin_available)) - return 0; - - pte = (gpuobj->im_pramin->start >> 12) << 1; - pte_end = ((gpuobj->im_pramin->size >> 12) << 1) + pte; - - while (pte < pte_end) { - nv_wo32(priv->pramin_pt, (pte * 4) + 0, 0x00000000); - nv_wo32(priv->pramin_pt, (pte * 4) + 4, 0x00000000); - pte += 2; + if (node->vram->bar_vma.node) { + nouveau_vm_unmap(&node->vram->bar_vma); + nouveau_vm_put(&node->vram->bar_vma); } - dev_priv->engine.instmem.flush(dev); - - gpuobj->im_bound = 0; - return 0; } void @@ -452,11 +415,3 @@ NV_ERROR(dev, "PRAMIN flush timeout\n"); } -void -nv50_vm_flush(struct drm_device *dev, int engine) -{ - nv_wr32(dev, 0x100c80, (engine << 16) | 1); - if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) - NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); -} - --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_vm.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_vm.c @@ -0,0 +1,178 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "drmP.h" + +#include "nouveau_drv.h" +#include "nouveau_vm.h" + +void +nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 type, u32 pde, + struct nouveau_gpuobj *pgt) +{ + struct drm_nouveau_private *dev_priv = pgd->dev->dev_private; + u32 coverage = (pgt->size >> 3) << type; + u64 phys; + + phys = pgt->vinst; + phys |= 0x01; /* present */ + phys |= (type == 12) ? 0x02 : 0x00; /* 4KiB pages */ + if (dev_priv->vram_sys_base) { + phys += dev_priv->vram_sys_base; + phys |= 0x30; + } + + if (coverage <= 32 * 1024 * 1024) + phys |= 0x60; + else if (coverage <= 64 * 1024 * 1024) + phys |= 0x40; + else if (coverage < 128 * 1024 * 1024) + phys |= 0x20; + + nv_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys)); + nv_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys)); +} + +void +nv50_vm_unmap_pgt(struct nouveau_gpuobj *pgd, u32 pde) +{ + nv_wo32(pgd, (pde * 8) + 0, 0x00000000); + nv_wo32(pgd, (pde * 8) + 4, 0xdeadcafe); +} + +static inline u64 +nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + u64 phys, u32 memtype, u32 target) +{ + struct drm_nouveau_private *dev_priv = pgt->dev->dev_private; + + phys |= 1; /* present */ + phys |= (u64)memtype << 40; + + /* IGPs don't have real VRAM, re-target to stolen system memory */ + if (target == 0 && dev_priv->vram_sys_base) { + phys += dev_priv->vram_sys_base; + target = 3; + } + + phys |= target << 4; + + if (vma->access & NV_MEM_ACCESS_SYS) + phys |= (1 << 6); + + if (!(vma->access & NV_MEM_ACCESS_WO)) + phys |= (1 << 3); + + return phys; +} + +void +nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys) +{ + u32 block, i; + + phys = nv50_vm_addr(vma, pgt, phys, mem->memtype, 0); + pte <<= 3; + cnt <<= 3; + + while (cnt) { + u32 offset_h = upper_32_bits(phys); + u32 offset_l = lower_32_bits(phys); + + for (i = 7; i >= 0; i--) { + block = 1 << (i + 3); + if (cnt >= block && !(pte & (block - 1))) + break; + } + offset_l |= (i << 7); + + phys += block << (vma->node->type - 3); + cnt -= block; + + while (block) { + nv_wo32(pgt, pte + 0, offset_l); + nv_wo32(pgt, pte + 4, offset_h); + pte += 8; + block -= 8; + } + } +} + +void +nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, + u32 pte, dma_addr_t *list, u32 cnt) +{ + pte <<= 3; + while (cnt--) { + u64 phys = nv50_vm_addr(vma, pgt, (u64)*list++, 0, 2); + nv_wo32(pgt, pte + 0, lower_32_bits(phys)); + nv_wo32(pgt, pte + 4, upper_32_bits(phys)); + pte += 8; + } +} + +void +nv50_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) +{ + pte <<= 3; + while (cnt--) { + nv_wo32(pgt, pte + 0, 0x00000000); + nv_wo32(pgt, pte + 4, 0x00000000); + pte += 8; + } +} + +void +nv50_vm_flush(struct nouveau_vm *vm) +{ + struct drm_nouveau_private *dev_priv = vm->dev->dev_private; + struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; + + pinstmem->flush(vm->dev); + + /* BAR */ + if (vm != dev_priv->chan_vm) { + nv50_vm_flush_engine(vm->dev, 6); + return; + } + + pfifo->tlb_flush(vm->dev); + + if (atomic_read(&vm->pgraph_refs)) + pgraph->tlb_flush(vm->dev); + if (atomic_read(&vm->pcrypt_refs)) + pcrypt->tlb_flush(vm->dev); +} + +void +nv50_vm_flush_engine(struct drm_device *dev, int engine) +{ + nv_wr32(dev, 0x100c80, (engine << 16) | 1); + if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000)) + NV_ERROR(dev, "vm flush timeout: engine %d\n", engine); +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv50_vram.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv50_vram.c @@ -0,0 +1,190 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_mm.h" + +static int types[0x80] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 +}; + +bool +nv50_vram_flags_valid(struct drm_device *dev, u32 tile_flags) +{ + int type = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8; + + if (likely(type < sizeof(types) && types[type])) + return true; + return false; +} + +void +nv50_vram_del(struct drm_device *dev, struct nouveau_vram **pvram) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; + struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; + struct nouveau_mm *mm = man->priv; + struct nouveau_mm_node *this; + struct nouveau_vram *vram; + + vram = *pvram; + *pvram = NULL; + if (unlikely(vram == NULL)) + return; + + mutex_lock(&mm->mutex); + while (!list_empty(&vram->regions)) { + this = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); + + list_del(&this->rl_entry); + nouveau_mm_put(mm, this); + } + mutex_unlock(&mm->mutex); + + kfree(vram); +} + +int +nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc, + u32 type, struct nouveau_vram **pvram) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct ttm_bo_device *bdev = &dev_priv->ttm.bdev; + struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM]; + struct nouveau_mm *mm = man->priv; + struct nouveau_mm_node *r; + struct nouveau_vram *vram; + int ret; + + if (!types[type]) + return -EINVAL; + size >>= 12; + align >>= 12; + size_nc >>= 12; + + vram = kzalloc(sizeof(*vram), GFP_KERNEL); + if (!vram) + return -ENOMEM; + + INIT_LIST_HEAD(&vram->regions); + vram->dev = dev_priv->dev; + vram->memtype = type; + vram->size = size; + + mutex_lock(&mm->mutex); + do { + ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r); + if (ret) { + mutex_unlock(&mm->mutex); + nv50_vram_del(dev, &vram); + return ret; + } + + list_add_tail(&r->rl_entry, &vram->regions); + size -= r->length; + } while (size); + mutex_unlock(&mm->mutex); + + r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry); + vram->offset = (u64)r->offset << 12; + *pvram = vram; + return 0; +} + +static u32 +nv50_vram_rblock(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + int i, parts, colbits, rowbitsa, rowbitsb, banks; + u64 rowsize, predicted; + u32 r0, r4, rt, ru, rblock_size; + + r0 = nv_rd32(dev, 0x100200); + r4 = nv_rd32(dev, 0x100204); + rt = nv_rd32(dev, 0x100250); + ru = nv_rd32(dev, 0x001540); + NV_DEBUG(dev, "memcfg 0x%08x 0x%08x 0x%08x 0x%08x\n", r0, r4, rt, ru); + + for (i = 0, parts = 0; i < 8; i++) { + if (ru & (0x00010000 << i)) + parts++; + } + + colbits = (r4 & 0x0000f000) >> 12; + rowbitsa = ((r4 & 0x000f0000) >> 16) + 8; + rowbitsb = ((r4 & 0x00f00000) >> 20) + 8; + banks = ((r4 & 0x01000000) ? 8 : 4); + + rowsize = parts * banks * (1 << colbits) * 8; + predicted = rowsize << rowbitsa; + if (r0 & 0x00000004) + predicted += rowsize << rowbitsb; + + if (predicted != dev_priv->vram_size) { + NV_WARN(dev, "memory controller reports %dMiB VRAM\n", + (u32)(dev_priv->vram_size >> 20)); + NV_WARN(dev, "we calculated %dMiB VRAM\n", + (u32)(predicted >> 20)); + } + + rblock_size = rowsize; + if (rt & 1) + rblock_size *= 3; + + NV_DEBUG(dev, "rblock %d bytes\n", rblock_size); + return rblock_size; +} + +int +nv50_vram_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + dev_priv->vram_size = nv_rd32(dev, 0x10020c); + dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; + dev_priv->vram_size &= 0xffffffff00ULL; + + switch (dev_priv->chipset) { + case 0xaa: + case 0xac: + case 0xaf: + dev_priv->vram_sys_base = (u64)nv_rd32(dev, 0x100e10) << 12; + dev_priv->vram_rblock_size = 4096; + break; + default: + dev_priv->vram_rblock_size = nv50_vram_rblock(dev); + break; + } + + return 0; +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nv84_crypt.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nv84_crypt.c @@ -0,0 +1,140 @@ +/* + * Copyright 2010 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_util.h" +#include "nouveau_vm.h" + +static void nv84_crypt_isr(struct drm_device *); + +int +nv84_crypt_create_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *ramin = chan->ramin; + int ret; + + NV_DEBUG(dev, "ch%d\n", chan->id); + + ret = nouveau_gpuobj_new(dev, chan, 256, 0, + NVOBJ_FLAG_ZERO_ALLOC | NVOBJ_FLAG_ZERO_FREE, + &chan->crypt_ctx); + if (ret) + return ret; + + nv_wo32(ramin, 0xa0, 0x00190000); + nv_wo32(ramin, 0xa4, chan->crypt_ctx->vinst + 0xff); + nv_wo32(ramin, 0xa8, chan->crypt_ctx->vinst); + nv_wo32(ramin, 0xac, 0); + nv_wo32(ramin, 0xb0, 0); + nv_wo32(ramin, 0xb4, 0); + + dev_priv->engine.instmem.flush(dev); + atomic_inc(&chan->vm->pcrypt_refs); + return 0; +} + +void +nv84_crypt_destroy_context(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + u32 inst; + + if (!chan->crypt_ctx) + return; + + inst = (chan->ramin->vinst >> 12); + inst |= 0x80000000; + + /* mark context as invalid if still on the hardware, not + * doing this causes issues the next time PCRYPT is used, + * unsurprisingly :) + */ + nv_wr32(dev, 0x10200c, 0x00000000); + if (nv_rd32(dev, 0x102188) == inst) + nv_mask(dev, 0x102188, 0x80000000, 0x00000000); + if (nv_rd32(dev, 0x10218c) == inst) + nv_mask(dev, 0x10218c, 0x80000000, 0x00000000); + nv_wr32(dev, 0x10200c, 0x00000010); + + nouveau_gpuobj_ref(NULL, &chan->crypt_ctx); + atomic_dec(&chan->vm->pcrypt_refs); +} + +void +nv84_crypt_tlb_flush(struct drm_device *dev) +{ + nv50_vm_flush_engine(dev, 0x0a); +} + +int +nv84_crypt_init(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_crypt_engine *pcrypt = &dev_priv->engine.crypt; + + if (!pcrypt->registered) { + NVOBJ_CLASS(dev, 0x74c1, CRYPT); + pcrypt->registered = true; + } + + nv_mask(dev, 0x000200, 0x00004000, 0x00000000); + nv_mask(dev, 0x000200, 0x00004000, 0x00004000); + + nouveau_irq_register(dev, 14, nv84_crypt_isr); + nv_wr32(dev, 0x102130, 0xffffffff); + nv_wr32(dev, 0x102140, 0xffffffbf); + + nv_wr32(dev, 0x10200c, 0x00000010); + return 0; +} + +void +nv84_crypt_fini(struct drm_device *dev) +{ + nv_wr32(dev, 0x102140, 0x00000000); + nouveau_irq_unregister(dev, 14); +} + +static void +nv84_crypt_isr(struct drm_device *dev) +{ + u32 stat = nv_rd32(dev, 0x102130); + u32 mthd = nv_rd32(dev, 0x102190); + u32 data = nv_rd32(dev, 0x102194); + u32 inst = nv_rd32(dev, 0x102188) & 0x7fffffff; + int show = nouveau_ratelimit(); + + if (show) { + NV_INFO(dev, "PCRYPT_INTR: 0x%08x 0x%08x 0x%08x 0x%08x\n", + stat, mthd, data, inst); + } + + nv_wr32(dev, 0x102130, stat); + nv_wr32(dev, 0x10200c, 0x10); + + nv50_fb_vm_trap(dev, show, "PCRYPT"); +} --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nvc0_instmem.c +++ linux-2.6.37/drivers/gpu/drm/nouveau/nvc0_instmem.c @@ -26,67 +26,89 @@ #include "nouveau_drv.h" +struct nvc0_gpuobj_node { + struct nouveau_bo *vram; + struct drm_mm_node *ramin; + u32 align; +}; + int -nvc0_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, - uint32_t *size) +nvc0_instmem_get(struct nouveau_gpuobj *gpuobj, u32 size, u32 align) { + struct drm_device *dev = gpuobj->dev; + struct nvc0_gpuobj_node *node = NULL; int ret; - *size = ALIGN(*size, 4096); - if (*size == 0) - return -EINVAL; + node = kzalloc(sizeof(*node), GFP_KERNEL); + if (!node) + return -ENOMEM; + node->align = align; - ret = nouveau_bo_new(dev, NULL, *size, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, - true, false, &gpuobj->im_backing); + ret = nouveau_bo_new(dev, NULL, size, align, TTM_PL_FLAG_VRAM, + 0, 0x0000, true, false, &node->vram); if (ret) { NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); return ret; } - ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM); + ret = nouveau_bo_pin(node->vram, TTM_PL_FLAG_VRAM); if (ret) { NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret); - nouveau_bo_ref(NULL, &gpuobj->im_backing); + nouveau_bo_ref(NULL, &node->vram); return ret; } - gpuobj->vinst = gpuobj->im_backing->bo.mem.start << PAGE_SHIFT; + gpuobj->vinst = node->vram->bo.mem.start << PAGE_SHIFT; + gpuobj->size = node->vram->bo.mem.num_pages << PAGE_SHIFT; + gpuobj->node = node; return 0; } void -nvc0_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +nvc0_instmem_put(struct nouveau_gpuobj *gpuobj) { - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvc0_gpuobj_node *node; - if (gpuobj && gpuobj->im_backing) { - if (gpuobj->im_bound) - dev_priv->engine.instmem.unbind(dev, gpuobj); - nouveau_bo_unpin(gpuobj->im_backing); - nouveau_bo_ref(NULL, &gpuobj->im_backing); - gpuobj->im_backing = NULL; - } + node = gpuobj->node; + gpuobj->node = NULL; + + nouveau_bo_unpin(node->vram); + nouveau_bo_ref(NULL, &node->vram); + kfree(node); } int -nvc0_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +nvc0_instmem_map(struct nouveau_gpuobj *gpuobj) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t pte, pte_end; - uint64_t vram; + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct nvc0_gpuobj_node *node = gpuobj->node; + struct drm_device *dev = gpuobj->dev; + struct drm_mm_node *ramin = NULL; + u32 pte, pte_end; + u64 vram; + + do { + if (drm_mm_pre_get(&dev_priv->ramin_heap)) + return -ENOMEM; + + spin_lock(&dev_priv->ramin_lock); + ramin = drm_mm_search_free(&dev_priv->ramin_heap, gpuobj->size, + node->align, 0); + if (ramin == NULL) { + spin_unlock(&dev_priv->ramin_lock); + return -ENOMEM; + } + + ramin = drm_mm_get_block_atomic(ramin, gpuobj->size, node->align); + spin_unlock(&dev_priv->ramin_lock); + } while (ramin == NULL); - if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) - return -EINVAL; - - NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n", - gpuobj->im_pramin->start, gpuobj->im_pramin->size); - - pte = gpuobj->im_pramin->start >> 12; - pte_end = (gpuobj->im_pramin->size >> 12) + pte; + pte = (ramin->start >> 12) << 1; + pte_end = ((ramin->size >> 12) << 1) + pte; vram = gpuobj->vinst; NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", - gpuobj->im_pramin->start, pte, pte_end); + ramin->start, pte, pte_end); NV_DEBUG(dev, "first vram page: 0x%010llx\n", gpuobj->vinst); while (pte < pte_end) { @@ -103,30 +125,35 @@ nv_wr32(dev, 0x100cbc, 0x80000005); } - gpuobj->im_bound = 1; + node->ramin = ramin; + gpuobj->pinst = ramin->start; return 0; } -int -nvc0_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) +void +nvc0_instmem_unmap(struct nouveau_gpuobj *gpuobj) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t pte, pte_end; + struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; + struct nvc0_gpuobj_node *node = gpuobj->node; + u32 pte, pte_end; + + if (!node->ramin || !dev_priv->ramin_available) + return; - if (gpuobj->im_bound == 0) - return -EINVAL; + pte = (node->ramin->start >> 12) << 1; + pte_end = ((node->ramin->size >> 12) << 1) + pte; - pte = gpuobj->im_pramin->start >> 12; - pte_end = (gpuobj->im_pramin->size >> 12) + pte; while (pte < pte_end) { - nv_wr32(dev, 0x702000 + (pte * 8), 0); - nv_wr32(dev, 0x702004 + (pte * 8), 0); + nv_wr32(gpuobj->dev, 0x702000 + (pte * 8), 0); + nv_wr32(gpuobj->dev, 0x702004 + (pte * 8), 0); pte++; } - dev_priv->engine.instmem.flush(dev); + dev_priv->engine.instmem.flush(gpuobj->dev); - gpuobj->im_bound = 0; - return 0; + spin_lock(&dev_priv->ramin_lock); + drm_mm_put_block(node->ramin); + node->ramin = NULL; + spin_unlock(&dev_priv->ramin_lock); } void --- linux-2.6.37.orig/drivers/gpu/drm/nouveau/nvreg.h +++ linux-2.6.37/drivers/gpu/drm/nouveau/nvreg.h @@ -153,7 +153,8 @@ #define NV_PCRTC_START 0x00600800 #define NV_PCRTC_CONFIG 0x00600804 # define NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA (1 << 0) -# define NV_PCRTC_CONFIG_START_ADDRESS_HSYNC (2 << 0) +# define NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC (4 << 0) +# define NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC (2 << 0) #define NV_PCRTC_CURSOR_CONFIG 0x00600810 # define NV_PCRTC_CURSOR_CONFIG_ENABLE_ENABLE (1 << 0) # define NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE (1 << 4) --- linux-2.6.37.orig/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ linux-2.6.37/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -264,7 +264,6 @@ */ struct vmw_sw_context ctx; - uint32_t val_seq; struct mutex cmdbuf_mutex; /** --- linux-2.6.37.orig/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ linux-2.6.37/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -653,8 +653,7 @@ ret = vmw_cmd_check_all(dev_priv, sw_context, cmd, arg->command_size); if (unlikely(ret != 0)) goto out_err; - ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes, - dev_priv->val_seq++); + ret = ttm_eu_reserve_buffers(&sw_context->validate_nodes); if (unlikely(ret != 0)) goto out_err; --- linux-2.6.37.orig/drivers/hid/hid-magicmouse.c +++ linux-2.6.37/drivers/hid/hid-magicmouse.c @@ -433,6 +433,11 @@ if (!msc->input) msc->input = hi->input; + /* Magic Trackpad does not give relative data after switching to MT */ + if (hi->input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD && + field->flags & HID_MAIN_ITEM_RELATIVE) + return -1; + return 0; } --- linux-2.6.37.orig/drivers/hid/hid-ntrig.c +++ linux-2.6.37/drivers/hid/hid-ntrig.c @@ -3,6 +3,7 @@ * * Copyright (c) 2008-2010 Rafi Rubin * Copyright (c) 2009-2010 Stephane Chatty + * Copyright (c) 2010 Canonical, Ltd. * */ @@ -24,69 +25,33 @@ #define NTRIG_DUPLICATE_USAGES 0x001 -static unsigned int min_width; -module_param(min_width, uint, 0644); -MODULE_PARM_DESC(min_width, "Minimum touch contact width to accept."); - -static unsigned int min_height; -module_param(min_height, uint, 0644); -MODULE_PARM_DESC(min_height, "Minimum touch contact height to accept."); - -static unsigned int activate_slack = 1; -module_param(activate_slack, uint, 0644); -MODULE_PARM_DESC(activate_slack, "Number of touch frames to ignore at " - "the start of touch input."); - -static unsigned int deactivate_slack = 4; -module_param(deactivate_slack, uint, 0644); -MODULE_PARM_DESC(deactivate_slack, "Number of empty frames to ignore before " - "deactivating touch."); - -static unsigned int activation_width = 64; -module_param(activation_width, uint, 0644); -MODULE_PARM_DESC(activation_width, "Width threshold to immediately start " - "processing touch events."); - -static unsigned int activation_height = 32; -module_param(activation_height, uint, 0644); -MODULE_PARM_DESC(activation_height, "Height threshold to immediately start " - "processing touch events."); +#define MAX_SLOTS 20 +#define MAX_EVENTS 120 -struct ntrig_data { - /* Incoming raw values for a single contact */ - __u16 x, y, w, h; - __u16 id; - - bool tipswitch; - bool confidence; - bool first_contact_touch; - - bool reading_mt; - - __u8 mt_footer[4]; - __u8 mt_foot_count; - - /* The current activation state. */ - __s8 act_state; - - /* Empty frames to ignore before recognizing the end of activity */ - __s8 deactivate_slack; - - /* Frames to ignore before acknowledging the start of activity */ - __s8 activate_slack; +#define SN_MOVE_X 128 +#define SN_MOVE_Y 92 +#define SN_MAJOR 48 + +#define HOLD_MIN 3 +#define HOLD_MED 7 +#define HOLD_MAX 10 + +#define DIV_MIN 8 +#define DIV_MED 40 +#define DIV_MAX 100 - /* Minimum size contact to accept */ - __u16 min_width; - __u16 min_height; - - /* Threshold to override activation slack */ - __u16 activation_width; - __u16 activation_height; +struct ntrig_contact { + int x, y, w, h; +}; - __u16 sensor_logical_width; - __u16 sensor_logical_height; - __u16 sensor_physical_width; - __u16 sensor_physical_height; +struct ntrig_data { + struct ntrig_contact row[MAX_SLOTS], col[MAX_SLOTS]; + int dmin, dmed, dmax; + int nrow, ncol; + int index, nindex; + int nhold; + bool touch; + bool hasmt; }; @@ -139,286 +104,6 @@ kfree(data); } -static ssize_t show_phys_width(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->sensor_physical_width); -} - -static DEVICE_ATTR(sensor_physical_width, S_IRUGO, show_phys_width, NULL); - -static ssize_t show_phys_height(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->sensor_physical_height); -} - -static DEVICE_ATTR(sensor_physical_height, S_IRUGO, show_phys_height, NULL); - -static ssize_t show_log_width(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->sensor_logical_width); -} - -static DEVICE_ATTR(sensor_logical_width, S_IRUGO, show_log_width, NULL); - -static ssize_t show_log_height(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->sensor_logical_height); -} - -static DEVICE_ATTR(sensor_logical_height, S_IRUGO, show_log_height, NULL); - -static ssize_t show_min_width(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->min_width * - nd->sensor_physical_width / - nd->sensor_logical_width); -} - -static ssize_t set_min_width(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - if (val > nd->sensor_physical_width) - return -EINVAL; - - nd->min_width = val * nd->sensor_logical_width / - nd->sensor_physical_width; - - return count; -} - -static DEVICE_ATTR(min_width, S_IWUSR | S_IRUGO, show_min_width, set_min_width); - -static ssize_t show_min_height(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->min_height * - nd->sensor_physical_height / - nd->sensor_logical_height); -} - -static ssize_t set_min_height(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - if (val > nd->sensor_physical_height) - return -EINVAL; - - nd->min_height = val * nd->sensor_logical_height / - nd->sensor_physical_height; - - return count; -} - -static DEVICE_ATTR(min_height, S_IWUSR | S_IRUGO, show_min_height, - set_min_height); - -static ssize_t show_activate_slack(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->activate_slack); -} - -static ssize_t set_activate_slack(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - if (val > 0x7f) - return -EINVAL; - - nd->activate_slack = val; - - return count; -} - -static DEVICE_ATTR(activate_slack, S_IWUSR | S_IRUGO, show_activate_slack, - set_activate_slack); - -static ssize_t show_activation_width(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->activation_width * - nd->sensor_physical_width / - nd->sensor_logical_width); -} - -static ssize_t set_activation_width(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - if (val > nd->sensor_physical_width) - return -EINVAL; - - nd->activation_width = val * nd->sensor_logical_width / - nd->sensor_physical_width; - - return count; -} - -static DEVICE_ATTR(activation_width, S_IWUSR | S_IRUGO, show_activation_width, - set_activation_width); - -static ssize_t show_activation_height(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", nd->activation_height * - nd->sensor_physical_height / - nd->sensor_logical_height); -} - -static ssize_t set_activation_height(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - if (val > nd->sensor_physical_height) - return -EINVAL; - - nd->activation_height = val * nd->sensor_logical_height / - nd->sensor_physical_height; - - return count; -} - -static DEVICE_ATTR(activation_height, S_IWUSR | S_IRUGO, - show_activation_height, set_activation_height); - -static ssize_t show_deactivate_slack(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - return sprintf(buf, "%d\n", -nd->deactivate_slack); -} - -static ssize_t set_deactivate_slack(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct hid_device *hdev = container_of(dev, struct hid_device, dev); - struct ntrig_data *nd = hid_get_drvdata(hdev); - - unsigned long val; - - if (strict_strtoul(buf, 0, &val)) - return -EINVAL; - - /* - * No more than 8 terminal frames have been observed so far - * and higher slack is highly likely to leave the single - * touch emulation stuck down. - */ - if (val > 7) - return -EINVAL; - - nd->deactivate_slack = -val; - - return count; -} - -static DEVICE_ATTR(deactivate_slack, S_IWUSR | S_IRUGO, show_deactivate_slack, - set_deactivate_slack); - -static struct attribute *sysfs_attrs[] = { - &dev_attr_sensor_physical_width.attr, - &dev_attr_sensor_physical_height.attr, - &dev_attr_sensor_logical_width.attr, - &dev_attr_sensor_logical_height.attr, - &dev_attr_min_height.attr, - &dev_attr_min_width.attr, - &dev_attr_activate_slack.attr, - &dev_attr_activation_width.attr, - &dev_attr_activation_height.attr, - &dev_attr_deactivate_slack.attr, - NULL -}; - -static struct attribute_group ntrig_attribute_group = { - .attrs = sysfs_attrs -}; - /* * this driver is aimed at two firmware versions in circulation: * - dual pen/finger single touch @@ -427,9 +112,13 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) + unsigned long **bit, int *max) { struct ntrig_data *nd = hid_get_drvdata(hdev); + struct input_dev *input = hi->input; + int f1 = field->logical_minimum; + int f2 = field->logical_maximum; + int df = f2 - f1; /* No special mappings needed for the pen and single touch */ if (field->physical) @@ -439,48 +128,21 @@ case HID_UP_GENDESK: switch (usage->hid) { case HID_GD_X: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_X); - input_set_abs_params(hi->input, ABS_X, - field->logical_minimum, - field->logical_maximum, 0, 0); - - if (!nd->sensor_logical_width) { - nd->sensor_logical_width = - field->logical_maximum - - field->logical_minimum; - nd->sensor_physical_width = - field->physical_maximum - - field->physical_minimum; - nd->activation_width = activation_width * - nd->sensor_logical_width / - nd->sensor_physical_width; - nd->min_width = min_width * - nd->sensor_logical_width / - nd->sensor_physical_width; - } + hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_X); + input_set_abs_params(input, ABS_X, + f1, f2, df / SN_MOVE_X, 0); + input_set_abs_params(input, ABS_MT_POSITION_X, + f1, f2, df / SN_MOVE_X, 0); + nd->dmin = df / DIV_MIN; + nd->dmed = df / DIV_MED; + nd->dmax = df / DIV_MAX; return 1; case HID_GD_Y: - hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_POSITION_Y); - input_set_abs_params(hi->input, ABS_Y, - field->logical_minimum, - field->logical_maximum, 0, 0); - - if (!nd->sensor_logical_height) { - nd->sensor_logical_height = - field->logical_maximum - - field->logical_minimum; - nd->sensor_physical_height = - field->physical_maximum - - field->physical_minimum; - nd->activation_height = activation_height * - nd->sensor_logical_height / - nd->sensor_physical_height; - nd->min_height = min_height * - nd->sensor_logical_height / - nd->sensor_physical_height; - } + hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_Y); + input_set_abs_params(input, ABS_Y, + f1, f2, df / SN_MOVE_Y, 0); + input_set_abs_params(input, ABS_MT_POSITION_Y, + f1, f2, df / SN_MOVE_Y, 0); return 1; } return 0; @@ -492,23 +154,42 @@ case HID_DG_INPUTMODE: case HID_DG_DEVICEINDEX: case HID_DG_CONTACTMAX: + case HID_DG_CONTACTCOUNT: + case HID_DG_INRANGE: + case HID_DG_CONFIDENCE: return -1; + case HID_DG_TIPSWITCH: + hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); + input_set_capability(input, EV_KEY, BTN_TOUCH); + return 1; + /* width/height mapped on TouchMajor/TouchMinor/Orientation */ case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MAJOR); + EV_ABS, ABS_MT_TOUCH_MAJOR); + input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, + f1, f2, df / SN_MAJOR, 0); return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MINOR); - input_set_abs_params(hi->input, ABS_MT_ORIENTATION, + EV_ABS, ABS_MT_TOUCH_MINOR); + input_set_abs_params(input, ABS_MT_TOUCH_MINOR, + f1, f2, df / SN_MAJOR, 0); + input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0); + input_set_events_per_packet(input, MAX_EVENTS); return 1; } return 0; case 0xff000000: + switch (usage->hid) { + case 0xff000001: + /* multi-touch firmware */ + nd->hasmt = true; + break; + } /* we do not want to map these: no input-oriented meaning */ return -1; } @@ -524,11 +205,123 @@ if (field->physical) return 0; - if (usage->type == EV_KEY || usage->type == EV_REL - || usage->type == EV_ABS) - clear_bit(usage->code, *bit); + /* tell hid-input to skip setup of these event types */ + if (usage->type == EV_KEY || usage->type == EV_ABS) + set_bit(usage->type, hi->input->evbit); + return -1; +} - return 0; +static bool copy_best_column(struct ntrig_data *nd, unsigned *used, int i) +{ + int j, jbest = -1, d, dbest; + for (j = 0; j < nd->ncol; ++j) { + if (*used & (1 << j)) + continue; + d = abs(nd->row[i].x - nd->col[j].x) + + abs(nd->row[i].y - nd->col[j].y); + if (jbest < 0 || d < dbest) { + jbest = j; + dbest = d; + } + } + if (jbest < 0) + return false; + *used |= (1 << jbest); + if (nd->nrow > 2) + nd->col[jbest].y = (nd->row[i].y + nd->col[jbest].y) >> 1; + nd->row[i] = nd->col[jbest]; + return true; +} + +static bool copy_next_column(struct ntrig_data *nd, unsigned *used, int i) +{ + int j; + for (j = 0; j < nd->ncol; ++j) { + if (*used & (1 << j)) + continue; + *used |= (1 << j); + nd->row[i] = nd->col[j]; + return true; + } + return false; +} + +static int ghost_distance(const struct ntrig_data *nd, int j) +{ + int i, d, dbest = INT_MAX; + for (i = 0; i < nd->nrow; ++i) { + d = abs(nd->row[i].x - nd->col[j].x); + dbest = min(dbest, d); + d = abs(nd->row[i].y - nd->col[j].y); + dbest = min(dbest, d); + } + return dbest; +} + +static void discard_ghosts(struct ntrig_data *nd, unsigned *used) +{ + int j, d; + for (j = 0; j < nd->ncol; ++j) { + if (*used & (1 << j)) + continue; + d = ghost_distance(nd, j); + if ((nd->nhold < HOLD_MIN && d < nd->dmin) || + (nd->nhold < HOLD_MED && d < nd->dmed) || + (nd->nhold < HOLD_MAX && d < nd->dmax)) + *used |= (1 << j); + } +} + +static void report_frame(struct input_dev *input, struct ntrig_data *nd) +{ + struct ntrig_contact *oldest = 0; + unsigned used = 0; + int i; + + if (nd->nrow < nd->ncol) { + for (i = 0; i < nd->nrow; ++i) + copy_best_column(nd, &used, i); + if (nd->ncol > 2) + discard_ghosts(nd, &used); + while (copy_next_column(nd, &used, i)) + i++; + nd->nrow = i; + nd->nhold++; + } else if (nd->nrow > nd->ncol) { + for (i = 0; i < nd->ncol; ++i) + nd->row[i] = nd->col[i]; + nd->nrow = nd->ncol; + nd->nhold = 0; + } else { + unsigned used = 0; + for (i = 0; i < nd->nrow; ++i) + copy_best_column(nd, &used, i); + nd->nhold = 0; + } + + for (i = 0; i < nd->nrow; ++i) { + struct ntrig_contact *f = &nd->row[i]; + int wide = (f->w > f->h); + int major = max(f->w, f->h); + int minor = min(f->w, f->h); + if (!oldest) + oldest = f; + input_event(input, EV_ABS, ABS_MT_POSITION_X, f->x); + input_event(input, EV_ABS, ABS_MT_POSITION_Y, f->y); + input_event(input, EV_ABS, ABS_MT_ORIENTATION, wide); + input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); + input_event(input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); + input_mt_sync(input); + } + + /* touchscreen emulation */ + if (oldest) { + input_event(input, EV_KEY, BTN_TOUCH, 1); + input_event(input, EV_ABS, ABS_X, oldest->x); + input_event(input, EV_ABS, ABS_Y, oldest->y); + } else { + input_event(input, EV_KEY, BTN_TOUCH, 0); + } } /* @@ -549,265 +342,39 @@ if (hid->claimed & HID_CLAIMED_INPUT) { switch (usage->hid) { - case 0xff000001: - /* Tag indicating the start of a multitouch group */ - nd->reading_mt = 1; - nd->first_contact_touch = 0; - break; case HID_DG_TIPSWITCH: - nd->tipswitch = value; - /* Prevent emission of touch until validated */ - return 1; - case HID_DG_CONFIDENCE: - nd->confidence = value; + nd->touch = value; + if (nd->nindex < MAX_SLOTS) + nd->index = nd->nindex++; break; case HID_GD_X: - nd->x = value; - /* Clear the contact footer */ - nd->mt_foot_count = 0; + nd->col[nd->index].x = value; break; case HID_GD_Y: - nd->y = value; - break; - case HID_DG_CONTACTID: - nd->id = value; + nd->col[nd->index].y = value; break; case HID_DG_WIDTH: - nd->w = value; + nd->col[nd->index].w = value; break; case HID_DG_HEIGHT: - nd->h = value; - /* - * when in single touch mode, this is the last - * report received in a finger event. We want - * to emit a normal (X, Y) position - */ - if (!nd->reading_mt) { - /* - * TipSwitch indicates the presence of a - * finger in single touch mode. - */ - input_report_key(input, BTN_TOUCH, - nd->tipswitch); - input_report_key(input, BTN_TOOL_DOUBLETAP, - nd->tipswitch); - input_event(input, EV_ABS, ABS_X, nd->x); - input_event(input, EV_ABS, ABS_Y, nd->y); - } - break; - case 0xff000002: - /* - * we receive this when the device is in multitouch - * mode. The first of the three values tagged with - * this usage tells if the contact point is real - * or a placeholder - */ - - /* Shouldn't get more than 4 footer packets, so skip */ - if (nd->mt_foot_count >= 4) - break; - - nd->mt_footer[nd->mt_foot_count++] = value; - - /* if the footer isn't complete break */ - if (nd->mt_foot_count != 4) - break; - - /* Pen activity signal. */ - if (nd->mt_footer[2]) { - /* - * When the pen deactivates touch, we see a - * bogus frame with ContactCount > 0. - * We can - * save a bit of work by ensuring act_state < 0 - * even if deactivation slack is turned off. - */ - nd->act_state = deactivate_slack - 1; - nd->confidence = 0; - break; - } - - /* - * The first footer value indicates the presence of a - * finger. - */ - if (nd->mt_footer[0]) { - /* - * We do not want to process contacts under - * the size threshold, but do not want to - * ignore them for activation state - */ - if (nd->w < nd->min_width || - nd->h < nd->min_height) - nd->confidence = 0; - } else - break; - - if (nd->act_state > 0) { - /* - * Contact meets the activation size threshold - */ - if (nd->w >= nd->activation_width && - nd->h >= nd->activation_height) { - if (nd->id) - /* - * first contact, activate now - */ - nd->act_state = 0; - else { - /* - * avoid corrupting this frame - * but ensure next frame will - * be active - */ - nd->act_state = 1; - break; - } - } else - /* - * Defer adjusting the activation state - * until the end of the frame. - */ - break; - } - - /* Discarding this contact */ - if (!nd->confidence) - break; - - /* emit a normal (X, Y) for the first point only */ - if (nd->id == 0) { - /* - * TipSwitch is superfluous in multitouch - * mode. The footer events tell us - * if there is a finger on the screen or - * not. - */ - nd->first_contact_touch = nd->confidence; - input_event(input, EV_ABS, ABS_X, nd->x); - input_event(input, EV_ABS, ABS_Y, nd->y); + nd->col[nd->index].h = value; + if (!nd->hasmt) { + nd->nindex = 0; + nd->ncol = nd->touch; + report_frame(input, nd); } - - /* Emit MT events */ - input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x); - input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y); - - /* - * Translate from height and width to size - * and orientation. - */ - if (nd->w > nd->h) { - input_event(input, EV_ABS, - ABS_MT_ORIENTATION, 1); - input_event(input, EV_ABS, - ABS_MT_TOUCH_MAJOR, nd->w); - input_event(input, EV_ABS, - ABS_MT_TOUCH_MINOR, nd->h); - } else { - input_event(input, EV_ABS, - ABS_MT_ORIENTATION, 0); - input_event(input, EV_ABS, - ABS_MT_TOUCH_MAJOR, nd->h); - input_event(input, EV_ABS, - ABS_MT_TOUCH_MINOR, nd->w); - } - input_mt_sync(field->hidinput->input); break; - case HID_DG_CONTACTCOUNT: /* End of a multitouch group */ - if (!nd->reading_mt) /* Just to be sure */ + if (!nd->hasmt) break; - - nd->reading_mt = 0; - - - /* - * Activation state machine logic: - * - * Fundamental states: - * state > 0: Inactive - * state <= 0: Active - * state < -deactivate_slack: - * Pen termination of touch - * - * Specific values of interest - * state == activate_slack - * no valid input since the last reset - * - * state == 0 - * general operational state - * - * state == -deactivate_slack - * read sufficient empty frames to accept - * the end of input and reset - */ - - if (nd->act_state > 0) { /* Currently inactive */ - if (value) - /* - * Consider each live contact as - * evidence of intentional activity. - */ - nd->act_state = (nd->act_state > value) - ? nd->act_state - value - : 0; - else - /* - * Empty frame before we hit the - * activity threshold, reset. - */ - nd->act_state = nd->activate_slack; - - /* - * Entered this block inactive and no - * coordinates sent this frame, so hold off - * on button state. - */ + nd->nindex = 0; + nd->ncol = value; + /* skip pen switch events */ + if (nd->ncol == 1 && + nd->col[0].w == 10 && nd->col[0].h == 10) break; - } else { /* Currently active */ - if (value && nd->act_state >= - nd->deactivate_slack) - /* - * Live point: clear accumulated - * deactivation count. - */ - nd->act_state = 0; - else if (nd->act_state <= nd->deactivate_slack) - /* - * We've consumed the deactivation - * slack, time to deactivate and reset. - */ - nd->act_state = - nd->activate_slack; - else { /* Move towards deactivation */ - nd->act_state--; - break; - } - } - - if (nd->first_contact_touch && nd->act_state <= 0) { - /* - * Check to see if we're ready to start - * emitting touch events. - * - * Note: activation slack will decrease over - * the course of the frame, and it will be - * inconsistent from the start to the end of - * the frame. However if the frame starts - * with slack, first_contact_touch will still - * be 0 and we will not get to this point. - */ - input_report_key(input, BTN_TOOL_DOUBLETAP, 1); - input_report_key(input, BTN_TOUCH, 1); - } else { - input_report_key(input, BTN_TOOL_DOUBLETAP, 0); - input_report_key(input, BTN_TOUCH, 0); - } + report_frame(input, nd); break; - - default: - /* fall-back to the generic hidinput handling */ - return 0; } } @@ -826,26 +393,15 @@ struct input_dev *input; struct hid_report *report; - if (id->driver_data) + if (id->driver_data & NTRIG_DUPLICATE_USAGES) hdev->quirks |= HID_QUIRK_MULTI_INPUT; - nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL); + nd = kzalloc(sizeof(struct ntrig_data), GFP_KERNEL); if (!nd) { dev_err(&hdev->dev, "cannot allocate N-Trig data\n"); return -ENOMEM; } - nd->reading_mt = 0; - nd->min_width = 0; - nd->min_height = 0; - nd->activate_slack = activate_slack; - nd->act_state = activate_slack; - nd->deactivate_slack = -deactivate_slack; - nd->sensor_logical_width = 0; - nd->sensor_logical_height = 0; - nd->sensor_physical_width = 0; - nd->sensor_physical_height = 0; - hid_set_drvdata(hdev, nd); ret = hid_parse(hdev); @@ -871,18 +427,6 @@ input->name = "N-Trig Pen"; break; case HID_DG_TOUCHSCREEN: - /* These keys are redundant for fingers, clear them - * to prevent incorrect identification */ - __clear_bit(BTN_TOOL_PEN, input->keybit); - __clear_bit(BTN_TOOL_FINGER, input->keybit); - __clear_bit(BTN_0, input->keybit); - __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); - /* - * The physical touchscreen (single touch) - * input has a value for physical, whereas - * the multitouch only has logical input - * fields. - */ input->name = (hidinput->report->field[0] ->physical) ? @@ -899,9 +443,6 @@ ntrig_report_version(hdev); - ret = sysfs_create_group(&hdev->dev.kobj, - &ntrig_attribute_group); - return 0; err_free: kfree(nd); @@ -910,51 +451,15 @@ static void ntrig_remove(struct hid_device *hdev) { - sysfs_remove_group(&hdev->dev.kobj, - &ntrig_attribute_group); hid_hw_stop(hdev); kfree(hid_get_drvdata(hdev)); } +#define NTRIG_DEVICE(id) \ + { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, id), \ + .driver_data = NTRIG_DUPLICATE_USAGES } static const struct hid_device_id ntrig_devices[] = { - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_2), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_3), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_4), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_5), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_6), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_7), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_8), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_9), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_10), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_11), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_12), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_13), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_14), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_15), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17), - .driver_data = NTRIG_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18), - .driver_data = NTRIG_DUPLICATE_USAGES }, + NTRIG_DEVICE(0x0001), { } }; MODULE_DEVICE_TABLE(hid, ntrig_devices); --- linux-2.6.37.orig/drivers/input/keyboard/atkbd.c +++ linux-2.6.37/drivers/input/keyboard/atkbd.c @@ -936,6 +936,14 @@ }; /* + * Fujitsu Siemens system with broken key release on volume keys and mute key + */ + +static unsigned int atkbd_amilo_xi_2428_forced_release_keys[] = { + 0xa0, 0xae, 0xb0, -1U +}; + +/* * Soltech TA12 system with broken key release on volume keys and mute key */ static unsigned int atkdb_soltech_ta12_forced_release_keys[] = { @@ -1709,6 +1717,35 @@ .driver_data = atkbd_amilo_xi3650_forced_release_keys, }, { + .ident = "Znote 6615WD", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Zepto"), + DMI_MATCH(DMI_PRODUCT_NAME, "Znote 6615WD"), + }, + .callback = atkbd_setup_forced_release, + .driver_data = atkbd_volume_forced_release_keys, + }, + { + .ident = "Znote 6625WD", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Zepto"), + DMI_MATCH(DMI_PRODUCT_NAME, "Znote"), + DMI_MATCH(DMI_PRODUCT_VERSION, "6625WD"), + }, + .callback = atkbd_setup_forced_release, + .driver_data = atkbd_volume_forced_release_keys, + }, + { + .ident = "AMILO Xi 2428", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 2428"), + }, + .callback = atkbd_setup_forced_release, + .driver_data = atkbd_amilo_xi_2428_forced_release_keys, + }, + { + .ident = "Soltech Corporation TA12", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Soltech Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "TA12"), --- linux-2.6.37.orig/drivers/input/mouse/alps.c +++ linux-2.6.37/drivers/input/mouse/alps.c @@ -15,6 +15,7 @@ * the Free Software Foundation. */ +#include #include #include #include @@ -63,6 +64,8 @@ /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, + /* Dell Precision 4500 */ + { { 0x73, 0x02, 0x64 }, 0x80, 0x80, 0 }, { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ { { 0x52, 0x01, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ @@ -111,6 +114,92 @@ * on a dualpoint, etc. */ +static const struct dmi_system_id dell_quirk_table[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_CHASSIS_TYPE, "8"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_CHASSIS_TYPE, "9"), + }, + }, + { } +}; + +int alps_model_quirk_enabled; +static void dell_e2_model_init(void *data); + + /* Magic Sequence to enable Intellimouse Mode on Dell E2 Touchpads*/ + +static int dell_e2_setup_intellimouse_mode(void *data) +{ + struct psmouse *psmouse = (struct psmouse *)(data); + struct ps2dev *ps2dev = &psmouse->ps2dev; + unsigned char param[] = {0, 0, 0}; + + if (!dmi_check_system(dell_quirk_table)) + return -1; + + if (ps2_command(ps2dev, param, 0x00f5) || + ps2_command(ps2dev, param, 0x00ea) || + ps2_command(ps2dev, param, 0x00ec) || + ps2_command(ps2dev, param, 0x00ec) || + ps2_command(ps2dev, param, 0x00ec) || + ps2_command(ps2dev, param, 0x03e9)) + return -1; + + dbg("alps:dell_e2_setup: param[0]: %x," + "param[1]: %x, param[2]: %x\n", param[0], + param[1], param[2]); + /* Check for supported model to continue */ + + if (!((param[0] == 0x88) && (param[1] == 0x07) + && ((param[2] == 0x9D) || (param[2] == 0x9B)))) + return -1; + + if (ps2_command(ps2dev, NULL, 0x00ec) || + ps2_command(ps2dev, NULL, 0x00f0) || + ps2_command(ps2dev, NULL, 0x00f0) || + ps2_command(ps2dev, NULL, 0x00f0) || + ps2_command(ps2dev, NULL, 0x00f3) || + ps2_command(ps2dev, NULL, 0x0028) || + ps2_command(ps2dev, NULL, 0x00f0) || + ps2_command(ps2dev, NULL, 0x00f6) || + ps2_command(ps2dev, NULL, 0x00ea) || + ps2_command(ps2dev, NULL, 0x00f4)) + return -1; + + return 0; +} + +static const struct alps_model_quirk alps_model_init_quirk_tbl[] = { + + { {0x73, 0x02, 0x64}, dell_e2_setup_intellimouse_mode, dell_e2_model_init } +}; + +static int alps_model_hw_init_quirk(struct psmouse *psmouse, + const struct alps_model_info *model) +{ + int rc = 1; + int i; + + for (i = 0; i < ARRAY_SIZE(alps_model_init_quirk_tbl); i++) { + if (!memcmp(model->signature, + alps_model_init_quirk_tbl[i].signature, + sizeof(alps_model_init_quirk_tbl[i].signature))) { + rc = alps_model_init_quirk_tbl[i].alps_model_quirk_hw_init(psmouse); + alps_model_quirk_enabled = i + 1; + break; + } + } + + return rc; +} + static bool alps_is_valid_first_byte(const struct alps_model_info *model, unsigned char data) { @@ -599,6 +688,10 @@ struct alps_data *priv = psmouse->private; const struct alps_model_info *model = priv->i; + if (alps_model_hw_init_quirk(psmouse, model)) { + alps_model_quirk_enabled = 0; + } + if ((model->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, true)) { return -1; @@ -651,6 +744,21 @@ kfree(priv); } +static void dell_e2_model_init(void *data) +{ + struct psmouse *psmouse = (struct psmouse *)(data); + struct input_dev *dev = psmouse->dev; + + __set_bit(BTN_MIDDLE, dev->keybit); + __set_bit(REL_WHEEL, dev->relbit); + + psmouse->pktsize = 4; + psmouse->type = PSMOUSE_IMPS; + psmouse->disconnect = alps_disconnect; + psmouse->reconnect = alps_reconnect; + +} + int alps_init(struct psmouse *psmouse) { struct alps_data *priv; @@ -677,6 +785,12 @@ if (alps_hw_init(psmouse)) goto init_fail; + if (alps_model_quirk_enabled) { + printk(KERN_WARNING "alps.c: Enabled hardware quirk, falling back to psmouse-core\n"); + alps_model_init_quirk_tbl[alps_model_quirk_enabled-1].alps_model_quirk_init(psmouse); + return 0; + } + /* * Undo part of setup done for us by psmouse core since touchpad * is not a relative device. --- linux-2.6.37.orig/drivers/input/mouse/alps.h +++ linux-2.6.37/drivers/input/mouse/alps.h @@ -26,6 +26,12 @@ struct timer_list timer; }; +struct alps_model_quirk { +unsigned char signature[3]; +int (*alps_model_quirk_hw_init)(void *data); +void (*alps_model_quirk_init)(void *data); +}; + #ifdef CONFIG_MOUSE_PS2_ALPS int alps_detect(struct psmouse *psmouse, bool set_properties); int alps_init(struct psmouse *psmouse); --- linux-2.6.37.orig/drivers/input/mouse/psmouse-base.c +++ linux-2.6.37/drivers/input/mouse/psmouse-base.c @@ -661,7 +661,8 @@ ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); if (alps_detect(psmouse, set_properties) == 0) { if (!set_properties || alps_init(psmouse) == 0) - return PSMOUSE_ALPS; +/* If ALPS model quirk was applied, don't change the settings */ + return psmouse->type ? psmouse->type : PSMOUSE_ALPS; /* * Init failed, try basic relative protocols */ --- linux-2.6.37.orig/drivers/md/dm.c +++ linux-2.6.37/drivers/md/dm.c @@ -2597,6 +2597,7 @@ { return md->disk; } +EXPORT_SYMBOL_GPL(dm_disk); struct kobject *dm_kobject(struct mapped_device *md) { --- linux-2.6.37.orig/drivers/mmc/host/omap_hsmmc.c +++ linux-2.6.37/drivers/mmc/host/omap_hsmmc.c @@ -2058,7 +2058,7 @@ host->slot_id = 0; host->mapbase = res->start; host->base = ioremap(host->mapbase, SZ_4K); - host->power_mode = MMC_POWER_OFF; + host->power_mode = -1; platform_set_drvdata(pdev, host); INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect); --- linux-2.6.37.orig/drivers/net/wireless/hostap/hostap_hw.c +++ linux-2.6.37/drivers/net/wireless/hostap/hostap_hw.c @@ -68,7 +68,7 @@ module_param_string(essid, essid, sizeof(essid), 0444); MODULE_PARM_DESC(essid, "Host AP's ESSID"); -static int iw_mode[MAX_PARM_DEVICES] = { IW_MODE_MASTER, DEF_INTS }; +static int iw_mode[MAX_PARM_DEVICES] = { IW_MODE_INFRA, DEF_INTS }; module_param_array(iw_mode, int, NULL, 0444); MODULE_PARM_DESC(iw_mode, "Initial operation mode"); --- linux-2.6.37.orig/drivers/parport/Kconfig +++ linux-2.6.37/drivers/parport/Kconfig @@ -36,7 +36,7 @@ config PARPORT_PC tristate "PC-style hardware" depends on (!SPARC64 || PCI) && !SPARC32 && !M32R && !FRV && \ - (!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN + (!M68K || ISA) && !MN10300 && !AVR32 && !BLACKFIN && !ARCH_OMAP ---help--- You should say Y here if you have a PC-style parallel port. All IBM PC compatible computers and some Alphas have PC-style --- linux-2.6.37.orig/drivers/platform/x86/sony-laptop.c +++ linux-2.6.37/drivers/platform/x86/sony-laptop.c @@ -1450,6 +1450,10 @@ struct sonypi_event *events; }; +struct sony_pic_quirk_entry { + u8 set_wwan_power; +}; + struct sony_pic_dev { struct acpi_device *acpi_dev; struct sony_pic_irq *cur_irq; @@ -1460,6 +1464,7 @@ struct sonypi_eventtypes *event_types; int (*handle_irq)(const u8, const u8); int model; + struct sony_pic_quirk_entry *quirks; u16 evport_offset; u8 camera_power; u8 bluetooth_power; @@ -2891,6 +2896,12 @@ if (result) goto err_remove_pf; + if (spic_dev.quirks && spic_dev.quirks->set_wwan_power) { + /* + * Power isn't enabled by default. + */ + __sony_pic_set_wwanpower(1); + } return 0; err_remove_pf: @@ -2961,6 +2972,16 @@ }, }; +static struct sony_pic_quirk_entry sony_pic_vaio_vgn = { + .set_wwan_power = 1, +}; + +static int dmi_matched(const struct dmi_system_id *dmi) +{ + spic_dev.quirks = dmi->driver_data; + return 0; +} + static struct dmi_system_id __initdata sonypi_dmi_table[] = { { .ident = "Sony Vaio", @@ -2975,6 +2996,8 @@ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"), }, + .callback = dmi_matched, + .driver_data = &sony_pic_vaio_vgn, }, { } }; --- linux-2.6.37.orig/drivers/pnp/isapnp/core.c +++ linux-2.6.37/drivers/pnp/isapnp/core.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include "../base.h" @@ -1001,7 +1002,7 @@ .disable = isapnp_disable_resources, }; -static int __init isapnp_init(void) +static int __init real_isapnp_init(void) { int cards; struct pnp_card *card; @@ -1095,6 +1096,15 @@ return 0; } +static void __init async_isapnp_init(void *unused, async_cookie_t cookie) +{ + (void)real_isapnp_init(); +} + +static int __init isapnp_init(void) +{ + async_schedule(async_isapnp_init, NULL); +} device_initcall(isapnp_init); /* format is: noisapnp */ --- linux-2.6.37.orig/drivers/staging/easycap/easycap.h +++ linux-2.6.37/drivers/staging/easycap/easycap.h @@ -89,6 +89,7 @@ #include #include #include +#include /*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ #if defined(EASYCAP_IS_VIDEODEV_CLIENT) --- linux-2.6.37.orig/drivers/usb/core/hub.c +++ linux-2.6.37/drivers/usb/core/hub.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -1853,6 +1854,10 @@ */ int usb_deauthorize_device(struct usb_device *usb_dev) { + char *product = NULL; + char *manufacturer = NULL; + char *serial = NULL; + usb_lock_device(usb_dev); if (usb_dev->authorized == 0) goto out_unauthorized; @@ -1860,11 +1865,12 @@ usb_dev->authorized = 0; usb_set_configuration(usb_dev, -1); - kfree(usb_dev->product); + product = usb_dev->product; + manufacturer = usb_dev->manufacturer; + serial = usb_dev->serial; + usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); - kfree(usb_dev->manufacturer); usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); - kfree(usb_dev->serial); usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); usb_destroy_configuration(usb_dev); @@ -1872,6 +1878,12 @@ out_unauthorized: usb_unlock_device(usb_dev); + if (product || manufacturer || serial) { + synchronize_rcu(); + kfree(product); + kfree(manufacturer); + kfree(serial); + } return 0; } @@ -1879,6 +1891,9 @@ int usb_authorize_device(struct usb_device *usb_dev) { int result = 0, c; + char *product = NULL; + char *manufacturer = NULL; + char *serial = NULL; usb_lock_device(usb_dev); if (usb_dev->authorized == 1) @@ -1897,11 +1912,12 @@ goto error_device_descriptor; } - kfree(usb_dev->product); + product = usb_dev->product; + manufacturer = usb_dev->manufacturer; + serial = usb_dev->serial; + usb_dev->product = NULL; - kfree(usb_dev->manufacturer); usb_dev->manufacturer = NULL; - kfree(usb_dev->serial); usb_dev->serial = NULL; usb_dev->authorized = 1; @@ -1929,6 +1945,12 @@ error_autoresume: out_authorized: usb_unlock_device(usb_dev); // complements locktree + if (product || manufacturer || serial) { + synchronize_rcu(); + kfree(product); + kfree(manufacturer); + kfree(serial); + } return result; } --- linux-2.6.37.orig/drivers/usb/core/sysfs.c +++ linux-2.6.37/drivers/usb/core/sysfs.c @@ -85,9 +85,9 @@ int retval; \ \ udev = to_usb_device(dev); \ - usb_lock_device(udev); \ - retval = sprintf(buf, "%s\n", udev->name); \ - usb_unlock_device(udev); \ + rcu_read_lock(); \ + retval = sprintf(buf, "%s\n", rcu_dereference(udev->name)); \ + rcu_read_unlock(); \ return retval; \ } \ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); --- linux-2.6.37.orig/drivers/usb/storage/unusual_devs.h +++ linux-2.6.37/drivers/usb/storage/unusual_devs.h @@ -1144,6 +1144,13 @@ USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init, 0), +/* Reported by Timo Aaltonen */ +UNUSUAL_DEV( 0x0af0, 0x7011, 0x0000, 0x9999, + "Option", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, option_ms_init, + 0 ), + /* Reported by F. Aben * This device (wrongly) has a vendor-specific device descriptor. * The entry is needed so usb-storage can bind to it's mass-storage --- linux-2.6.37.orig/drivers/video/Kconfig +++ linux-2.6.37/drivers/video/Kconfig @@ -711,8 +711,8 @@ If unsure, say N. config FB_VESA - bool "VESA VGA graphics support" - depends on (FB = y) && X86 + tristate "VESA VGA graphics support" + depends on FB && X86 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT --- linux-2.6.37.orig/drivers/video/fbmem.c +++ linux-2.6.37/drivers/video/fbmem.c @@ -42,6 +42,8 @@ #define FBPIXMAPSIZE (1024 * 8) +/* Protects the registered framebuffer list and count. */ +static DEFINE_SPINLOCK(registered_lock); struct fb_info *registered_fb[FB_MAX] __read_mostly; int num_registered_fb __read_mostly; @@ -694,9 +696,7 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; - struct inode *inode = file->f_path.dentry->d_inode; - int fbidx = iminor(inode); - struct fb_info *info = registered_fb[fbidx]; + struct fb_info *info = file->private_data; u8 *buffer, *dst; u8 __iomem *src; int c, cnt = 0, err = 0; @@ -705,19 +705,28 @@ if (!info || ! info->screen_base) return -ENODEV; - if (info->state != FBINFO_STATE_RUNNING) - return -EPERM; + if (!lock_fb_info(info)) + return -ENODEV; + + if (info->state != FBINFO_STATE_RUNNING) { + err = -EPERM; + goto out_fb_info; + } - if (info->fbops->fb_read) - return info->fbops->fb_read(info, buf, count, ppos); + if (info->fbops->fb_read) { + err = info->fbops->fb_read(info, buf, count, ppos); + goto out_fb_info; + } total_size = info->screen_size; if (total_size == 0) total_size = info->fix.smem_len; - if (p >= total_size) - return 0; + if (p >= total_size) { + err = 0; + goto out_fb_info; + } if (count >= total_size) count = total_size; @@ -727,8 +736,10 @@ buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); - if (!buffer) - return -ENOMEM; + if (!buffer) { + err = -ENOMEM; + goto out_fb_info; + } src = (u8 __iomem *) (info->screen_base + p); @@ -751,19 +762,21 @@ cnt += c; count -= c; } + if (!err) + err = cnt; kfree(buffer); +out_fb_info: + unlock_fb_info(info); - return (err) ? err : cnt; + return err; } static ssize_t fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; - struct inode *inode = file->f_path.dentry->d_inode; - int fbidx = iminor(inode); - struct fb_info *info = registered_fb[fbidx]; + struct fb_info *info = file->private_data; u8 *buffer, *src; u8 __iomem *dst; int c, cnt = 0, err = 0; @@ -772,8 +785,13 @@ if (!info || !info->screen_base) return -ENODEV; - if (info->state != FBINFO_STATE_RUNNING) - return -EPERM; + if (!lock_fb_info(info)) + return -ENODEV; + + if (info->state != FBINFO_STATE_RUNNING) { + err = -EPERM; + goto out_fb_info; + } if (info->fbops->fb_write) return info->fbops->fb_write(info, buf, count, ppos); @@ -783,8 +801,10 @@ if (total_size == 0) total_size = info->fix.smem_len; - if (p > total_size) - return -EFBIG; + if (p > total_size) { + err = -EFBIG; + goto out_fb_info; + } if (count > total_size) { err = -EFBIG; @@ -800,8 +820,10 @@ buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); - if (!buffer) - return -ENOMEM; + if (!buffer) { + err = -ENOMEM; + goto out_fb_info; + } dst = (u8 __iomem *) (info->screen_base + p); @@ -825,10 +847,14 @@ cnt += c; count -= c; } + if (cnt) + err = cnt; kfree(buffer); +out_fb_info: + unlock_fb_info(info); - return (cnt) ? cnt : err; + return err; } int @@ -1303,8 +1329,7 @@ static int fb_mmap(struct file *file, struct vm_area_struct * vma) { - int fbidx = iminor(file->f_path.dentry->d_inode); - struct fb_info *info = registered_fb[fbidx]; + struct fb_info * const info = file->private_data; struct fb_ops *fb = info->fbops; unsigned long off; unsigned long start; @@ -1316,6 +1341,11 @@ if (!fb) return -ENODEV; mutex_lock(&info->mm_lock); + if (info->state == FBINFO_STATE_REMOVED) { + mutex_unlock(&info->mm_lock); + return -ENODEV; + } + if (fb->fb_mmap) { int res; res = fb->fb_mmap(info, vma); @@ -1352,6 +1382,35 @@ return 0; } +static struct fb_info *get_framebuffer_info(int idx) +__acquires(®istered_lock) +__releases(®istered_lock) +{ + struct fb_info *fb_info; + + spin_lock(®istered_lock); + fb_info = registered_fb[idx]; + if (fb_info) + fb_info->ref_count++; + spin_unlock(®istered_lock); + + return fb_info; +} + +static void put_framebuffer_info(struct fb_info *fb_info) +__acquires(®istered_lock) +__releases(®istered_lock) +{ + int keep; + + spin_lock(®istered_lock); + keep = --fb_info->ref_count; + spin_unlock(®istered_lock); + + if (!keep && fb_info->fbops->fb_destroy) + fb_info->fbops->fb_destroy(fb_info); +} + static int fb_open(struct inode *inode, struct file *file) __acquires(&info->lock) @@ -1363,13 +1422,17 @@ if (fbidx >= FB_MAX) return -ENODEV; - info = registered_fb[fbidx]; + info = get_framebuffer_info(fbidx); if (!info) request_module("fb%d", fbidx); - info = registered_fb[fbidx]; + info = get_framebuffer_info(fbidx); if (!info) return -ENODEV; mutex_lock(&info->lock); + if (info->state == FBINFO_STATE_REMOVED) { + res = -ENODEV; + goto out; + } if (!try_module_get(info->fbops->owner)) { res = -ENODEV; goto out; @@ -1386,6 +1449,8 @@ #endif out: mutex_unlock(&info->lock); + if (res) + put_framebuffer_info(info); return res; } @@ -1401,6 +1466,7 @@ info->fbops->fb_release(info,1); module_put(info->fbops->owner); mutex_unlock(&info->lock); + put_framebuffer_info(info); return 0; } @@ -1549,6 +1615,7 @@ fb_info->node = i; mutex_init(&fb_info->lock); mutex_init(&fb_info->mm_lock); + fb_info->ref_count = 1; fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), NULL, "fb%d", i); @@ -1592,7 +1659,6 @@ return 0; } - /** * unregister_framebuffer - releases a frame buffer device * @fb_info: frame buffer info structure @@ -1627,6 +1693,16 @@ return -ENODEV; event.info = fb_info; ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); + if (!ret) { + mutex_lock(&fb_info->mm_lock); + /* + * We must prevent any operations for this transition, we + * already have info->lock so grab the info->mm_lock to hold + * the remainder. + */ + fb_info->state = FBINFO_STATE_REMOVED; + mutex_unlock(&fb_info->mm_lock); + } unlock_fb_info(fb_info); if (ret) { @@ -1646,8 +1722,7 @@ fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); /* this may free fb info */ - if (fb_info->fbops->fb_destroy) - fb_info->fbops->fb_destroy(fb_info); + put_framebuffer_info(fb_info); done: return ret; } --- linux-2.6.37.orig/drivers/video/vesafb.c +++ linux-2.6.37/drivers/video/vesafb.c @@ -27,6 +27,12 @@ #define dac_reg (0x3c8) #define dac_val (0x3c9) +struct vesafb_info +{ + u32 pseudo_palette[256]; + int mtrr_hdl; +}; + /* --------------------------------------------------------------------- */ static struct fb_var_screeninfo vesafb_defined __initdata = { @@ -46,16 +52,37 @@ .accel = FB_ACCEL_NONE, }; +#ifndef MODULE static int inverse __read_mostly; +#endif static int mtrr __read_mostly; /* disable mtrr */ static int vram_remap __initdata; /* Set amount of memory to be used */ static int vram_total __initdata; /* Set total amount of memory */ static int pmi_setpal __read_mostly = 1; /* pmi for palette changes ??? */ +static int redraw __read_mostly; static int ypan __read_mostly; /* 0..nothing, 1..ypan, 2..ywrap */ +static int ywrap __read_mostly; static void (*pmi_start)(void) __read_mostly; static void (*pmi_pal) (void) __read_mostly; static int depth __read_mostly; static int vga_compat __read_mostly; + +module_param(redraw, bool, 0); +module_param(ypan, bool, 0); +module_param(ywrap, bool, 0); +module_param_named(vgapal, pmi_setpal, invbool, 0); +MODULE_PARM_DESC(vgapal, "Use VGA for setting palette (default)"); +module_param_named(pmipal, pmi_setpal, bool, 0); +MODULE_PARM_DESC(pmipal, "Use PMI for setting palette"); +module_param(mtrr, bool, 0); +MODULE_PARM_DESC(mtrr, "Enable MTRR support (default)"); +module_param_named(nomtrr, mtrr, invbool, 0); +MODULE_PARM_DESC(nomtrr, "Disable MTRR support"); +module_param(vram_remap, int, 0); +MODULE_PARM_DESC(vram_remap, "Set total amount of memory to be used"); +module_param(vram_total, int, 0); +MODULE_PARM_DESC(vram_total, "Total amount of memory"); + /* --------------------------------------------------------------------- */ static int vesafb_pan_display(struct fb_var_screeninfo *var, @@ -191,6 +218,7 @@ .fb_imageblit = cfb_imageblit, }; +#ifndef MODULE static int __init vesafb_setup(char *options) { char *this_opt; @@ -224,10 +252,12 @@ } return 0; } +#endif static int __init vesafb_probe(struct platform_device *dev) { struct fb_info *info; + struct vesafb_info *vfb_info; int i, err; unsigned int size_vmode; unsigned int size_remap; @@ -286,13 +316,14 @@ spaces our resource handlers simply don't know about */ } - info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev); + info = framebuffer_alloc(sizeof(struct vesafb_info), &dev->dev); if (!info) { release_mem_region(vesafb_fix.smem_start, size_total); return -ENOMEM; } - info->pseudo_palette = info->par; - info->par = NULL; + vfb_info = (struct vesafb_info *) info->par; + vfb_info->mtrr_hdl = -1; + info->pseudo_palette = vfb_info->pseudo_palette; /* set vesafb aperture size for generic probing */ info->apertures = alloc_apertures(1); @@ -435,18 +466,16 @@ } if (type) { - int rc; - /* Find the largest power-of-two */ while (temp_size & (temp_size - 1)) temp_size &= (temp_size - 1); /* Try and find a power of two to add */ do { - rc = mtrr_add(vesafb_fix.smem_start, temp_size, + vfb_info->mtrr_hdl = mtrr_add(vesafb_fix.smem_start, temp_size, type, 1); temp_size >>= 1; - } while (temp_size >= PAGE_SIZE && rc == -EINVAL); + } while (temp_size >= PAGE_SIZE && vfb_info->mtrr_hdl == -EINVAL); } } #endif @@ -480,7 +509,27 @@ return err; } +static int __exit vesafb_remove(struct platform_device *device) +{ + struct fb_info *info = dev_get_drvdata(&device->dev); + + unregister_framebuffer(info); +#ifdef CONFIG_MTRR + { + struct vesafb_info *vfb_info = (struct vesafb_info *) info->par; + if (vfb_info->mtrr_hdl >= 0) + mtrr_del(vfb_info->mtrr_hdl, 0, 0); + } +#endif + iounmap(info->screen_base); + framebuffer_release(info); + release_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len); + + return 0; +} + static struct platform_driver vesafb_driver = { + .remove = vesafb_remove, .driver = { .name = "vesafb", }, @@ -491,11 +540,18 @@ static int __init vesafb_init(void) { int ret; +#ifndef MODULE char *option = NULL; /* ignore error return of fb_get_options */ fb_get_options("vesafb", &option); vesafb_setup(option); +#else + if (redraw) + ypan = 0; + if (ywrap) + ypan = 2; +#endif vesafb_device = platform_device_alloc("vesafb", 0); if (!vesafb_device) @@ -515,6 +571,14 @@ return ret; } + +static void __exit vesafb_exit(void) +{ + platform_device_unregister(vesafb_device); + platform_driver_unregister(&vesafb_driver); +} + module_init(vesafb_init); +module_exit(vesafb_exit); MODULE_LICENSE("GPL"); --- linux-2.6.37.orig/drivers/video/omap2/dss/dispc.c +++ linux-2.6.37/drivers/video/omap2/dss/dispc.c @@ -2101,7 +2101,7 @@ static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, int vsw, int vfp, int vbp) { - if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { + if (cpu_is_omap24xx() || (cpu_is_omap34xx() && omap_rev_lt_3_0())) { if (hsw < 1 || hsw > 64 || hfp < 1 || hfp > 256 || hbp < 1 || hbp > 256 || @@ -2134,7 +2134,7 @@ { u32 timing_h, timing_v; - if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { + if (cpu_is_omap24xx() || (cpu_is_omap34xx() && omap_rev_lt_3_0())) { timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | FLD_VAL(hbp-1, 27, 20); --- linux-2.6.37.orig/drivers/video/omap2/dss/dpi.c +++ linux-2.6.37/drivers/video/omap2/dss/dpi.c @@ -177,7 +177,12 @@ #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL dss_clk_enable(DSS_CLK_FCK2); - r = dsi_pll_init(dssdev, 0, 1); + + if (cpu_is_omap3630()) + r = dsi_pll_init(dssdev, 1, 1); + else + r = dsi_pll_init(dssdev, 0, 1); + if (r) goto err3; #endif --- linux-2.6.37.orig/drivers/tty/vt/vt.c +++ linux-2.6.37/drivers/tty/vt/vt.c @@ -106,6 +106,7 @@ #include #include #include +#include #define MAX_NR_CON_DRIVER 16 @@ -148,7 +149,7 @@ static int con_open(struct tty_struct *, struct file *); static void vc_init(struct vc_data *vc, unsigned int rows, - unsigned int cols, int do_clear); + unsigned int cols, int do_clear, int mode); static void gotoxy(struct vc_data *vc, int new_x, int new_y); static void save_cur(struct vc_data *vc); static void reset_terminal(struct vc_data *vc, int do_clear); @@ -169,6 +170,9 @@ static int cur_default = CUR_DEFAULT; module_param(cur_default, int, S_IRUGO | S_IWUSR); +int vt_handoff = 0; +module_param_named(handoff, vt_handoff, int, S_IRUGO | S_IWUSR); + /* * ignore_poke: don't unblank the screen when things are typed. This is * mainly for the privacy of braille terminal users. @@ -688,6 +692,13 @@ save_screen(old_vc); set_origin(old_vc); } + /* + * If we are switching away from a transparent VT the contents + * will be lost, convert it into a blank text console then + * it will be repainted blank if we ever switch back. + */ + if (old_vc->vc_mode == KD_TRANSPARENT) + old_vc->vc_mode = KD_TEXT; } else { hide_cursor(vc); redraw = 1; @@ -801,7 +812,7 @@ if (global_cursor_default == -1) global_cursor_default = 1; - vc_init(vc, vc->vc_rows, vc->vc_cols, 1); + vc_init(vc, vc->vc_rows, vc->vc_cols, 1, KD_TEXT); vcs_make_sysfs(currcons); atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m); } @@ -2846,7 +2857,7 @@ module_param_named(underline, default_underline_color, int, S_IRUGO | S_IWUSR); static void vc_init(struct vc_data *vc, unsigned int rows, - unsigned int cols, int do_clear) + unsigned int cols, int do_clear, int mode) { int j, k ; @@ -2857,7 +2868,7 @@ set_origin(vc); vc->vc_pos = vc->vc_origin; - reset_vc(vc); + reset_vc(vc, mode); for (j=k=0; j<16; j++) { vc->vc_palette[k++] = default_red[j] ; vc->vc_palette[k++] = default_grn[j] ; @@ -2883,6 +2894,13 @@ struct vc_data *vc; unsigned int currcons = 0, i; + if (screen_info.flags & VIDEO_FLAGS_HANDOFF) { + if (vt_handoff == 0) + vt_handoff = 8; + printk(KERN_INFO "vt handoff: grub requested handoff (vt#%d)\n", + vt_handoff); + } + acquire_console_sem(); if (conswitchp) @@ -2914,16 +2932,31 @@ mod_timer(&console_timer, jiffies + (blankinterval * HZ)); } + if (vt_handoff > 0 && vt_handoff <= MAX_NR_CONSOLES) { + currcons = vt_handoff - 1; + vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); + INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); + visual_init(vc, currcons, 1); + vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); + vc_init(vc, vc->vc_rows, vc->vc_cols, 0, KD_TRANSPARENT); + } for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { + if (currcons == vt_handoff - 1) + continue; vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); tty_port_init(&vc->port); visual_init(vc, currcons, 1); vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); vc_init(vc, vc->vc_rows, vc->vc_cols, - currcons || !vc->vc_sw->con_save_screen); + currcons || !vc->vc_sw->con_save_screen, KD_TEXT); } currcons = fg_console = 0; + if (vt_handoff > 0) { + printk(KERN_INFO "vt handoff: transparent VT on vt#%d\n", + vt_handoff); + currcons = fg_console = vt_handoff - 1; + } master_display_fg = vc = vc_cons[currcons].d; set_origin(vc); save_screen(vc); --- linux-2.6.37.orig/drivers/tty/vt/vt_ioctl.c +++ linux-2.6.37/drivers/tty/vt/vt_ioctl.c @@ -38,6 +38,8 @@ #include #include +#define max_font_size 65536 + char vt_dont_switch; extern struct tty_driver *console_driver; @@ -1344,9 +1346,9 @@ goto out; } -void reset_vc(struct vc_data *vc) +void reset_vc(struct vc_data *vc, int mode) { - vc->vc_mode = KD_TEXT; + vc->vc_mode = mode; kbd_table[vc->vc_num].kbdmode = default_utf8 ? VC_UNICODE : VC_XLATE; vc->vt_mode.mode = VT_AUTO; vc->vt_mode.waitv = 0; @@ -1377,7 +1379,7 @@ */ if (tty) __do_SAK(tty); - reset_vc(vc); + reset_vc(vc, KD_TEXT); } release_console_sem(); } @@ -1592,6 +1594,7 @@ { unsigned char old_vc_mode; int old = fg_console; + struct vc_data *oldvc = vc_cons[fg_console].d; last_console = fg_console; @@ -1600,9 +1603,31 @@ * KD_TEXT mode or vice versa, which means we need to blank or * unblank the screen later. */ - old_vc_mode = vc_cons[fg_console].d->vc_mode; + old_vc_mode = oldvc->vc_mode; + +#if defined(CONFIG_VGA_CONSOLE) + if (old_vc_mode == KD_TEXT && oldvc->vc_sw == &vga_con && + oldvc->vc_sw->con_font_get) { + if (!oldvc->vc_font.data) + oldvc->vc_font.data = kmalloc(max_font_size, + GFP_KERNEL); + lock_kernel(); + oldvc->vc_sw->con_font_get(oldvc, &oldvc->vc_font); + unlock_kernel(); + } +#endif switch_screen(vc); +#if defined(CONFIG_VGA_CONSOLE) + if (vc->vc_mode == KD_TEXT && vc->vc_sw == &vga_con && + vc->vc_sw->con_font_set) { + if (vc->vc_font.data) { + lock_kernel(); + vc->vc_sw->con_font_set(vc, &vc->vc_font, 0); + unlock_kernel(); + } + } +#endif /* * This can't appear below a successful kill_pid(). If it did, * then the *blank_screen operation could occur while X, having @@ -1641,7 +1666,7 @@ * this outside of VT_PROCESS but there is no single process * to account for and tracking tty count may be undesirable. */ - reset_vc(vc); + reset_vc(vc, KD_TEXT); if (old_vc_mode != vc->vc_mode) { if (vc->vc_mode == KD_TEXT) @@ -1713,7 +1738,7 @@ * this outside of VT_PROCESS but there is no single process * to account for and tracking tty count may be undesirable. */ - reset_vc(vc); + reset_vc(vc, KD_TEXT); /* * Fall through to normal (VT_AUTO) handling of the switch... --- linux-2.6.37.orig/fs/binfmt_elf.c +++ linux-2.6.37/fs/binfmt_elf.c @@ -717,6 +717,15 @@ if (retval) goto out_free_dentry; +#ifdef CONFIG_X86_32 + /* + * Turn off the CS limit completely if exec-shield disabled or + * NX active: + */ + if (disable_nx || executable_stack != EXSTACK_DISABLE_X || (__supported_pte_mask & _PAGE_NX)) + arch_add_exec_range(current->mm, -1); +#endif + /* OK, This is the point of no return */ current->flags &= ~PF_FORKNOEXEC; current->mm->def_flags = def_flags; --- linux-2.6.37.orig/fs/exec.c +++ linux-2.6.37/fs/exec.c @@ -56,6 +56,8 @@ #include #include +#include + #include #include #include @@ -737,6 +739,8 @@ fsnotify_open(file); + trace_open_exec(name); + err = deny_write_access(file); if (err) goto exit; --- linux-2.6.37.orig/fs/file_table.c +++ linux-2.6.37/fs/file_table.c @@ -393,6 +393,8 @@ } } +EXPORT_SYMBOL(file_sb_list_del); + #ifdef CONFIG_SMP /* --- linux-2.6.37.orig/fs/fs-writeback.c +++ linux-2.6.37/fs/fs-writeback.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "internal.h" /* @@ -952,6 +953,8 @@ if ((inode->i_state & flags) == flags) return; + trace_dirty_inode(inode, current); + if (unlikely(block_dump)) block_dump___mark_inode_dirty(inode); --- linux-2.6.37.orig/fs/inode.c +++ linux-2.6.37/fs/inode.c @@ -82,6 +82,7 @@ * the i_state of an inode while it is in use.. */ DEFINE_SPINLOCK(inode_lock); +EXPORT_SYMBOL(inode_lock); /* * iprune_sem provides exclusion between the kswapd or try_to_free_pages @@ -1708,3 +1709,7 @@ inode->i_mode = mode; } EXPORT_SYMBOL(inode_init_owner); + +#define CREATE_TRACE_POINTS +#include + --- linux-2.6.37.orig/fs/namei.c +++ linux-2.6.37/fs/namei.c @@ -347,6 +347,7 @@ return 0; } +EXPORT_SYMBOL(deny_write_access); /** * path_get - get a reference to a path @@ -1161,12 +1162,13 @@ * needs parent already locked. Doesn't follow mounts. * SMP-safe. */ -static struct dentry *lookup_hash(struct nameidata *nd) +struct dentry *lookup_hash(struct nameidata *nd) { return __lookup_hash(&nd->last, nd->path.dentry, nd); } +EXPORT_SYMBOL(lookup_hash); -static int __lookup_one_len(const char *name, struct qstr *this, +int __lookup_one_len(const char *name, struct qstr *this, struct dentry *base, int len) { unsigned long hash; @@ -1187,6 +1189,7 @@ this->hash = end_name_hash(hash); return 0; } +EXPORT_SYMBOL(__lookup_one_len); /** * lookup_one_len - filesystem helper to lookup single pathname component --- linux-2.6.37.orig/fs/namespace.c +++ linux-2.6.37/fs/namespace.c @@ -1321,6 +1321,7 @@ } return 0; } +EXPORT_SYMBOL(iterate_mounts); static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end) { --- linux-2.6.37.orig/fs/open.c +++ linux-2.6.37/fs/open.c @@ -33,6 +33,9 @@ #include "internal.h" +#define CREATE_TRACE_POINTS +#include + int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, struct file *filp) { @@ -60,6 +63,7 @@ mutex_unlock(&dentry->d_inode->i_mutex); return ret; } +EXPORT_SYMBOL(do_truncate); static long do_sys_truncate(const char __user *pathname, loff_t length) { @@ -890,6 +894,7 @@ } else { fsnotify_open(f); fd_install(fd, f); + trace_do_sys_open(tmp, flags, mode); } } putname(tmp); --- linux-2.6.37.orig/fs/splice.c +++ linux-2.6.37/fs/splice.c @@ -1092,8 +1092,8 @@ /* * Attempt to initiate a splice from pipe to file. */ -static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, - loff_t *ppos, size_t len, unsigned int flags) +long do_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) { ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); @@ -1116,13 +1116,14 @@ return splice_write(pipe, out, ppos, len, flags); } +EXPORT_SYMBOL(do_splice_from); /* * Attempt to initiate a splice from a file to a pipe. */ -static long do_splice_to(struct file *in, loff_t *ppos, - struct pipe_inode_info *pipe, size_t len, - unsigned int flags) +long do_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) { ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); @@ -1142,6 +1143,7 @@ return splice_read(in, ppos, pipe, len, flags); } +EXPORT_SYMBOL(do_splice_to); /** * splice_direct_to_actor - splices data directly between two non-pipes --- linux-2.6.37.orig/fs/notify/group.c +++ linux-2.6.37/fs/notify/group.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "fsnotify.h" @@ -70,6 +71,7 @@ if (atomic_dec_and_test(&group->refcnt)) fsnotify_destroy_group(group); } +EXPORT_SYMBOL(fsnotify_put_group); /* * Create a new fsnotify_group and hold a reference for the group returned. @@ -102,3 +104,4 @@ return group; } +EXPORT_SYMBOL(fsnotify_alloc_group); --- linux-2.6.37.orig/fs/notify/mark.c +++ linux-2.6.37/fs/notify/mark.c @@ -113,6 +113,7 @@ if (atomic_dec_and_test(&mark->refcnt)) mark->free_mark(mark); } +EXPORT_SYMBOL(fsnotify_put_mark); /* * Any time a mark is getting freed we end up here. @@ -190,6 +191,7 @@ if (unlikely(atomic_dec_and_test(&group->num_marks))) fsnotify_final_destroy_group(group); } +EXPORT_SYMBOL(fsnotify_destroy_mark); void fsnotify_set_mark_mask_locked(struct fsnotify_mark *mark, __u32 mask) { @@ -277,6 +279,7 @@ return ret; } +EXPORT_SYMBOL(fsnotify_add_mark); /* * clear any marks in a group in which mark->flags & flags is true @@ -332,6 +335,7 @@ atomic_set(&mark->refcnt, 1); mark->free_mark = free_mark; } +EXPORT_SYMBOL(fsnotify_init_mark); static int fsnotify_mark_destroy(void *ignored) { --- linux-2.6.37.orig/fs/proc/Makefile +++ linux-2.6.37/fs/proc/Makefile @@ -26,3 +26,4 @@ proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o proc-$(CONFIG_PRINTK) += kmsg.o proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o +proc-y += version_signature.o --- linux-2.6.37.orig/fs/proc/base.c +++ linux-2.6.37/fs/proc/base.c @@ -1407,6 +1407,82 @@ #endif +#ifdef CONFIG_SCHED_AUTOGROUP +/* + * Print out autogroup related information: + */ +static int sched_autogroup_show(struct seq_file *m, void *v) +{ + struct inode *inode = m->private; + struct task_struct *p; + + p = get_proc_task(inode); + if (!p) + return -ESRCH; + proc_sched_autogroup_show_task(p, m); + + put_task_struct(p); + + return 0; +} + +static ssize_t +sched_autogroup_write(struct file *file, const char __user *buf, + size_t count, loff_t *offset) +{ + struct inode *inode = file->f_path.dentry->d_inode; + struct task_struct *p; + char buffer[PROC_NUMBUF]; + long nice; + int err; + + memset(buffer, 0, sizeof(buffer)); + if (count > sizeof(buffer) - 1) + count = sizeof(buffer) - 1; + if (copy_from_user(buffer, buf, count)) + return -EFAULT; + + err = strict_strtol(strstrip(buffer), 0, &nice); + if (err) + return -EINVAL; + + p = get_proc_task(inode); + if (!p) + return -ESRCH; + + err = nice; + err = proc_sched_autogroup_set_nice(p, &err); + if (err) + count = err; + + put_task_struct(p); + + return count; +} + +static int sched_autogroup_open(struct inode *inode, struct file *filp) +{ + int ret; + + ret = single_open(filp, sched_autogroup_show, NULL); + if (!ret) { + struct seq_file *m = filp->private_data; + + m->private = inode; + } + return ret; +} + +static const struct file_operations proc_pid_sched_autogroup_operations = { + .open = sched_autogroup_open, + .read = seq_read, + .write = sched_autogroup_write, + .llseek = seq_lseek, + .release = single_release, +}; + +#endif /* CONFIG_SCHED_AUTOGROUP */ + static ssize_t comm_write(struct file *file, const char __user *buf, size_t count, loff_t *offset) { @@ -2733,6 +2809,9 @@ #ifdef CONFIG_SCHED_DEBUG REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations), #endif +#ifdef CONFIG_SCHED_AUTOGROUP + REG("autogroup", S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations), +#endif REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations), #ifdef CONFIG_HAVE_ARCH_TRACEHOOK INF("syscall", S_IRUSR, proc_pid_syscall), --- linux-2.6.37.orig/fs/proc/version_signature.c +++ linux-2.6.37/fs/proc/version_signature.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include +#include + +static int version_signature_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "%s\n", CONFIG_VERSION_SIGNATURE); + return 0; +} + +static int version_signature_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, version_signature_proc_show, NULL); +} + +static const struct file_operations version_signature_proc_fops = { + .open = version_signature_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init proc_version_signature_init(void) +{ + proc_create("version_signature", 0, NULL, &version_signature_proc_fops); + return 0; +} +module_init(proc_version_signature_init); --- linux-2.6.37.orig/include/Kbuild +++ linux-2.6.37/include/Kbuild @@ -9,4 +9,3 @@ header-y += video/ header-y += drm/ header-y += xen/ -header-y += scsi/ --- linux-2.6.37.orig/include/asm-generic/vmlinux.lds.h +++ linux-2.6.37/include/asm-generic/vmlinux.lds.h @@ -606,6 +606,7 @@ *(.initcall0s.init) \ *(.initcall1.init) \ *(.initcall1s.init) \ + *(.initcallearlyrootfs.init) \ *(.initcall2.init) \ *(.initcall2s.init) \ *(.initcall3.init) \ --- linux-2.6.37.orig/include/drm/drmP.h +++ linux-2.6.37/include/drm/drmP.h @@ -683,6 +683,21 @@ void *driver_priv; /**< Private structure for driver to use */ }; +/* Size of ringbuffer for vblank timestamps. Just double-buffer + * in initial implementation. + */ +#define DRM_VBLANKTIME_RBSIZE 2 + +/* Flags and return codes for get_vblank_timestamp() driver function. */ +#define DRM_CALLED_FROM_VBLIRQ 1 +#define DRM_VBLANKTIME_SCANOUTPOS_METHOD (1 << 0) +#define DRM_VBLANKTIME_INVBL (1 << 1) + +/* get_scanout_position() return flags */ +#define DRM_SCANOUTPOS_VALID (1 << 0) +#define DRM_SCANOUTPOS_INVBL (1 << 1) +#define DRM_SCANOUTPOS_ACCURATE (1 << 2) + /** * DRM driver structure. This structure represent the common code for * a family of cards. There will one drm_device for each card present @@ -760,6 +775,68 @@ */ int (*device_is_agp) (struct drm_device *dev); + /** + * Called by vblank timestamping code. + * + * Return the current display scanout position from a crtc. + * + * \param dev DRM device. + * \param crtc Id of the crtc to query. + * \param *vpos Target location for current vertical scanout position. + * \param *hpos Target location for current horizontal scanout position. + * + * Returns vpos as a positive number while in active scanout area. + * Returns vpos as a negative number inside vblank, counting the number + * of scanlines to go until end of vblank, e.g., -1 means "one scanline + * until start of active scanout / end of vblank." + * + * \return Flags, or'ed together as follows: + * + * DRM_SCANOUTPOS_VALID = Query successfull. + * DRM_SCANOUTPOS_INVBL = Inside vblank. + * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of + * this flag means that returned position may be offset by a constant + * but unknown small number of scanlines wrt. real scanout position. + * + */ + int (*get_scanout_position) (struct drm_device *dev, int crtc, + int *vpos, int *hpos); + + /** + * Called by \c drm_get_last_vbltimestamp. Should return a precise + * timestamp when the most recent VBLANK interval ended or will end. + * + * Specifically, the timestamp in @vblank_time should correspond as + * closely as possible to the time when the first video scanline of + * the video frame after the end of VBLANK will start scanning out, + * the time immmediately after end of the VBLANK interval. If the + * @crtc is currently inside VBLANK, this will be a time in the future. + * If the @crtc is currently scanning out a frame, this will be the + * past start time of the current scanout. This is meant to adhere + * to the OpenML OML_sync_control extension specification. + * + * \param dev dev DRM device handle. + * \param crtc crtc for which timestamp should be returned. + * \param *max_error Maximum allowable timestamp error in nanoseconds. + * Implementation should strive to provide timestamp + * with an error of at most *max_error nanoseconds. + * Returns true upper bound on error for timestamp. + * \param *vblank_time Target location for returned vblank timestamp. + * \param flags 0 = Defaults, no special treatment needed. + * \param DRM_CALLED_FROM_VBLIRQ = Function is called from vblank + * irq handler. Some drivers need to apply some workarounds + * for gpu-specific vblank irq quirks if flag is set. + * + * \returns + * Zero if timestamping isn't supported in current display mode or a + * negative number on failure. A positive status code on success, + * which describes how the vblank_time timestamp was computed. + */ + int (*get_vblank_timestamp) (struct drm_device *dev, int crtc, + int *max_error, + struct timeval *vblank_time, + unsigned flags); + /* these have to be filled in */ irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); @@ -983,6 +1060,8 @@ wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */ atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */ + struct timeval *_vblank_time; /**< timestamp of current vblank_count (drivers must alloc right number of fields) */ + spinlock_t vblank_time_lock; /**< Protects vblank count and time updates during vblank enable/disable */ spinlock_t vbl_lock; atomic_t *vblank_refcount; /* number of users of vblank interruptsper crtc */ u32 *last_vblank; /* protected by dev->vbl_lock, used */ @@ -1041,8 +1120,6 @@ /*@{ */ spinlock_t object_name_lock; struct idr object_name_idr; - uint32_t invalidate_domains; /* domains pending invalidation */ - uint32_t flush_domains; /* domains pending flush */ /*@} */ }; @@ -1284,11 +1361,22 @@ struct drm_file *filp); extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); extern u32 drm_vblank_count(struct drm_device *dev, int crtc); +extern u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, + struct timeval *vblanktime); extern void drm_handle_vblank(struct drm_device *dev, int crtc); extern int drm_vblank_get(struct drm_device *dev, int crtc); extern void drm_vblank_put(struct drm_device *dev, int crtc); extern void drm_vblank_off(struct drm_device *dev, int crtc); extern void drm_vblank_cleanup(struct drm_device *dev); +extern u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, + struct timeval *tvblank, unsigned flags); +extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, + int crtc, int *max_error, + struct timeval *vblank_time, + unsigned flags, + struct drm_crtc *refcrtc); +extern void drm_calc_timestamping_constants(struct drm_crtc *crtc); + /* Modesetting support */ extern void drm_vblank_pre_modeset(struct drm_device *dev, int crtc); extern void drm_vblank_post_modeset(struct drm_device *dev, int crtc); @@ -1321,7 +1409,6 @@ extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request); extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern void drm_agp_chipset_flush(struct drm_device *dev); /* Stub support (drm_stub.h) */ extern int drm_setmaster_ioctl(struct drm_device *dev, void *data, @@ -1340,6 +1427,9 @@ extern int drm_put_minor(struct drm_minor **minor); extern unsigned int drm_debug; +extern unsigned int drm_vblank_offdelay; +extern unsigned int drm_timestamp_precision; + extern struct class *drm_class; extern struct proc_dir_entry *drm_proc_root; extern struct dentry *drm_debugfs_root; --- linux-2.6.37.orig/include/drm/drm_crtc.h +++ linux-2.6.37/include/drm/drm_crtc.h @@ -351,8 +351,14 @@ bool enabled; + /* Requested mode from modesetting. */ struct drm_display_mode mode; + /* Programmed mode in hw, after adjustments for encoders, + * crtc, panel scaling etc. Needed for timestamping etc. + */ + struct drm_display_mode hwmode; + int x, y; const struct drm_crtc_funcs *funcs; @@ -360,6 +366,9 @@ uint32_t gamma_size; uint16_t *gamma_store; + /* Constants needed for precise vblank and swap timestamping. */ + s64 framedur_ns, linedur_ns, pixeldur_ns; + /* if you are using the helper */ void *helper_private; }; --- linux-2.6.37.orig/include/drm/drm_mm.h +++ linux-2.6.37/include/drm/drm_mm.h @@ -62,11 +62,14 @@ struct list_head unused_nodes; int num_unused; spinlock_t unused_lock; + unsigned int scan_check_range : 1; unsigned scan_alignment; unsigned long scan_size; unsigned long scan_hit_start; unsigned scan_hit_size; unsigned scanned_blocks; + unsigned long scan_start; + unsigned long scan_end; }; /* @@ -145,6 +148,10 @@ void drm_mm_init_scan(struct drm_mm *mm, unsigned long size, unsigned alignment); +void drm_mm_init_scan_with_range(struct drm_mm *mm, unsigned long size, + unsigned alignment, + unsigned long start, + unsigned long end); int drm_mm_scan_add_block(struct drm_mm_node *node); int drm_mm_scan_remove_block(struct drm_mm_node *node); --- linux-2.6.37.orig/include/drm/drm_pciids.h +++ linux-2.6.37/include/drm/drm_pciids.h @@ -419,6 +419,10 @@ {0x1002, 0x9713, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9714, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9715, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS880|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9804, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0, 0, 0} #define r128_PCI_IDS \ --- linux-2.6.37.orig/include/drm/i915_drm.h +++ linux-2.6.37/include/drm/i915_drm.h @@ -289,6 +289,7 @@ #define I915_PARAM_HAS_BLT 11 #define I915_PARAM_HAS_RELAXED_FENCING 12 #define I915_PARAM_HAS_COHERENT_RINGS 13 +#define I915_PARAM_HAS_EXEC_CONSTANTS 14 typedef struct drm_i915_getparam { int param; @@ -635,6 +636,17 @@ #define I915_EXEC_RENDER (1<<0) #define I915_EXEC_BSD (2<<0) #define I915_EXEC_BLT (3<<0) + +/* Used for switching the constants addressing mode on gen4+ RENDER ring. + * Gen6+ only supports relative addressing to dynamic state (default) and + * absolute addressing. + * + * These flags are ignored for the BSD and BLT rings. + */ +#define I915_EXEC_CONSTANTS_MASK (3<<6) +#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */ +#define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6) +#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */ __u64 flags; __u64 rsvd1; __u64 rsvd2; --- linux-2.6.37.orig/include/drm/intel-gtt.h +++ linux-2.6.37/include/drm/intel-gtt.h @@ -2,17 +2,40 @@ #ifndef _DRM_INTEL_GTT_H #define _DRM_INTEL_GTT_H -struct intel_gtt { - /* Number of stolen gtt entries at the beginning. */ - unsigned int gtt_stolen_entries; + +const struct intel_gtt { + /* Size of memory reserved for graphics by the BIOS */ + unsigned int stolen_size; /* Total number of gtt entries. */ unsigned int gtt_total_entries; /* Part of the gtt that is mappable by the cpu, for those chips where * this is not the full gtt. */ unsigned int gtt_mappable_entries; -}; + /* Whether i915 needs to use the dmar apis or not. */ + unsigned int needs_dmar : 1; +} *intel_gtt_get(void); -struct intel_gtt *intel_gtt_get(void); +void intel_gtt_chipset_flush(void); +void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg); +void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries); +int intel_gtt_map_memory(struct page **pages, unsigned int num_entries, + struct scatterlist **sg_list, int *num_sg); +void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, + unsigned int sg_len, + unsigned int pg_start, + unsigned int flags); +void intel_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries, + struct page **pages, unsigned int flags); -#endif +/* Special gtt memory types */ +#define AGP_DCACHE_MEMORY 1 +#define AGP_PHYS_MEMORY 2 + +/* New caching attributes for gen6/sandybridge */ +#define AGP_USER_CACHED_MEMORY_LLC_MLC (AGP_USER_TYPES + 2) +#define AGP_USER_UNCACHED_MEMORY (AGP_USER_TYPES + 4) +/* flag for GFDT type */ +#define AGP_USER_CACHED_MEMORY_GFDT (1 << 3) + +#endif --- linux-2.6.37.orig/include/drm/nouveau_drm.h +++ linux-2.6.37/include/drm/nouveau_drm.h @@ -71,16 +71,14 @@ #define NOUVEAU_GETPARAM_PCI_VENDOR 3 #define NOUVEAU_GETPARAM_PCI_DEVICE 4 #define NOUVEAU_GETPARAM_BUS_TYPE 5 -#define NOUVEAU_GETPARAM_FB_PHYSICAL 6 -#define NOUVEAU_GETPARAM_AGP_PHYSICAL 7 #define NOUVEAU_GETPARAM_FB_SIZE 8 #define NOUVEAU_GETPARAM_AGP_SIZE 9 -#define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 #define NOUVEAU_GETPARAM_CHIPSET_ID 11 #define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 #define NOUVEAU_GETPARAM_GRAPH_UNITS 13 #define NOUVEAU_GETPARAM_PTIMER_TIME 14 #define NOUVEAU_GETPARAM_HAS_BO_USAGE 15 +#define NOUVEAU_GETPARAM_HAS_PAGEFLIP 16 struct drm_nouveau_getparam { uint64_t param; uint64_t value; @@ -171,7 +169,6 @@ }; #define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001 -#define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002 #define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004 struct drm_nouveau_gem_cpu_prep { uint32_t handle; --- linux-2.6.37.orig/include/drm/ttm/ttm_bo_api.h +++ linux-2.6.37/include/drm/ttm/ttm_bo_api.h @@ -74,6 +74,8 @@ * @is_iomem: is this io memory ? * @size: size in byte * @offset: offset from the base address + * @io_reserved_vm: The VM system has a refcount in @io_reserved_count + * @io_reserved_count: Refcounting the numbers of callers to ttm_mem_io_reserve * * Structure indicating the bus placement of an object. */ @@ -83,7 +85,8 @@ unsigned long size; unsigned long offset; bool is_iomem; - bool io_reserved; + bool io_reserved_vm; + uint64_t io_reserved_count; }; @@ -154,7 +157,6 @@ * keeps one refcount. When this refcount reaches zero, * the object is destroyed. * @event_queue: Queue for processes waiting on buffer object status change. - * @lock: spinlock protecting mostly synchronization members. * @mem: structure describing current placement. * @persistant_swap_storage: Usually the swap storage is deleted for buffers * pinned in physical memory. If this behaviour is not desired, this member @@ -213,7 +215,6 @@ struct kref kref; struct kref list_kref; wait_queue_head_t event_queue; - spinlock_t lock; /** * Members protected by the bo::reserved lock. @@ -237,6 +238,7 @@ struct list_head lru; struct list_head ddestroy; struct list_head swap; + struct list_head io_reserve_lru; uint32_t val_seq; bool seq_valid; @@ -248,10 +250,10 @@ atomic_t reserved; /** - * Members protected by the bo::lock + * Members protected by struct buffer_object_device::fence_lock * In addition, setting sync_obj to anything else * than NULL requires bo::reserved to be held. This allows for - * checking NULL while reserved but not holding bo::lock. + * checking NULL while reserved but not holding the mentioned lock. */ void *sync_obj_arg; @@ -364,6 +366,44 @@ */ extern void ttm_bo_unref(struct ttm_buffer_object **bo); + +/** + * ttm_bo_list_ref_sub + * + * @bo: The buffer object. + * @count: The number of references with which to decrease @bo::list_kref; + * @never_free: The refcount should not reach zero with this operation. + * + * Release @count lru list references to this buffer object. + */ +extern void ttm_bo_list_ref_sub(struct ttm_buffer_object *bo, int count, + bool never_free); + +/** + * ttm_bo_add_to_lru + * + * @bo: The buffer object. + * + * Add this bo to the relevant mem type lru and, if it's backed by + * system pages (ttms) to the swap list. + * This function must be called with struct ttm_bo_global::lru_lock held, and + * is typically called immediately prior to unreserving a bo. + */ +extern void ttm_bo_add_to_lru(struct ttm_buffer_object *bo); + +/** + * ttm_bo_del_from_lru + * + * @bo: The buffer object. + * + * Remove this bo from all lru lists used to lookup and reserve an object. + * This function must be called with struct ttm_bo_global::lru_lock held, + * and is usually called just immediately after the bo has been reserved to + * avoid recursive reservation from lru lists. + */ +extern int ttm_bo_del_from_lru(struct ttm_buffer_object *bo); + + /** * ttm_bo_lock_delayed_workqueue * --- linux-2.6.37.orig/include/drm/ttm/ttm_bo_driver.h +++ linux-2.6.37/include/drm/ttm/ttm_bo_driver.h @@ -179,30 +179,6 @@ #define TTM_MEMTYPE_FLAG_MAPPABLE (1 << 1) /* Memory mappable */ #define TTM_MEMTYPE_FLAG_CMA (1 << 3) /* Can't map aperture */ -/** - * struct ttm_mem_type_manager - * - * @has_type: The memory type has been initialized. - * @use_type: The memory type is enabled. - * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory - * managed by this memory type. - * @gpu_offset: If used, the GPU offset of the first managed page of - * fixed memory or the first managed location in an aperture. - * @size: Size of the managed region. - * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX, - * as defined in ttm_placement_common.h - * @default_caching: The default caching policy used for a buffer object - * placed in this memory type if the user doesn't provide one. - * @manager: The range manager used for this memory type. FIXME: If the aperture - * has a page size different from the underlying system, the granularity - * of this manager should take care of this. But the range allocating code - * in ttm_bo.c needs to be modified for this. - * @lru: The lru list for this memory type. - * - * This structure is used to identify and manage memory types for a device. - * It's set up by the ttm_bo_driver::init_mem_type method. - */ - struct ttm_mem_type_manager; struct ttm_mem_type_manager_func { @@ -287,6 +263,36 @@ void (*debug)(struct ttm_mem_type_manager *man, const char *prefix); }; +/** + * struct ttm_mem_type_manager + * + * @has_type: The memory type has been initialized. + * @use_type: The memory type is enabled. + * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory + * managed by this memory type. + * @gpu_offset: If used, the GPU offset of the first managed page of + * fixed memory or the first managed location in an aperture. + * @size: Size of the managed region. + * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX, + * as defined in ttm_placement_common.h + * @default_caching: The default caching policy used for a buffer object + * placed in this memory type if the user doesn't provide one. + * @func: structure pointer implementing the range manager. See above + * @priv: Driver private closure for @func. + * @io_reserve_mutex: Mutex optionally protecting shared io_reserve structures + * @use_io_reserve_lru: Use an lru list to try to unreserve io_mem_regions + * reserved by the TTM vm system. + * @io_reserve_lru: Optional lru list for unreserving io mem regions. + * @io_reserve_fastpath: Only use bdev::driver::io_mem_reserve to obtain + * static information. bdev::driver::io_mem_free is never used. + * @lru: The lru list for this memory type. + * + * This structure is used to identify and manage memory types for a device. + * It's set up by the ttm_bo_driver::init_mem_type method. + */ + + + struct ttm_mem_type_manager { struct ttm_bo_device *bdev; @@ -303,6 +309,15 @@ uint32_t default_caching; const struct ttm_mem_type_manager_func *func; void *priv; + struct mutex io_reserve_mutex; + bool use_io_reserve_lru; + bool io_reserve_fastpath; + + /* + * Protected by @io_reserve_mutex: + */ + + struct list_head io_reserve_lru; /* * Protected by the global->lru_lock. @@ -510,9 +525,12 @@ * * @driver: Pointer to a struct ttm_bo_driver struct setup by the driver. * @man: An array of mem_type_managers. + * @fence_lock: Protects the synchronizing members on *all* bos belonging + * to this device. * @addr_space_mm: Range manager for the device address space. * lru_lock: Spinlock that protects the buffer+device lru lists and * ddestroy lists. + * @val_seq: Current validation sequence. * @nice_mode: Try nicely to wait for buffer idle when cleaning a manager. * If a GPU lockup has been detected, this is forced to 0. * @dev_mapping: A pointer to the struct address_space representing the @@ -531,6 +549,7 @@ struct ttm_bo_driver *driver; rwlock_t vm_lock; struct ttm_mem_type_manager man[TTM_NUM_MEM_TYPES]; + spinlock_t fence_lock; /* * Protected by the vm lock. */ @@ -541,6 +560,7 @@ * Protected by the global:lru lock. */ struct list_head ddestroy; + uint32_t val_seq; /* * Protected by load / firstopen / lastclose /unload sync. @@ -753,31 +773,6 @@ extern int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait); -/** - * ttm_bo_pci_offset - Get the PCI offset for the buffer object memory. - * - * @bo Pointer to a struct ttm_buffer_object. - * @bus_base On return the base of the PCI region - * @bus_offset On return the byte offset into the PCI region - * @bus_size On return the byte size of the buffer object or zero if - * the buffer object memory is not accessible through a PCI region. - * - * Returns: - * -EINVAL if the buffer object is currently not mappable. - * 0 otherwise. - */ - -extern int ttm_bo_pci_offset(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem, - unsigned long *bus_base, - unsigned long *bus_offset, - unsigned long *bus_size); - -extern int ttm_mem_io_reserve(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem); -extern void ttm_mem_io_free(struct ttm_bo_device *bdev, - struct ttm_mem_reg *mem); - extern void ttm_bo_global_release(struct drm_global_reference *ref); extern int ttm_bo_global_init(struct drm_global_reference *ref); @@ -810,6 +805,22 @@ extern void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); /** + * ttm_bo_unmap_virtual + * + * @bo: tear down the virtual mappings for this BO + * + * The caller must take ttm_mem_io_lock before calling this function. + */ +extern void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo); + +extern int ttm_mem_io_reserve_vm(struct ttm_buffer_object *bo); +extern void ttm_mem_io_free_vm(struct ttm_buffer_object *bo); +extern int ttm_mem_io_lock(struct ttm_mem_type_manager *man, + bool interruptible); +extern void ttm_mem_io_unlock(struct ttm_mem_type_manager *man); + + +/** * ttm_bo_reserve: * * @bo: A pointer to a struct ttm_buffer_object. @@ -859,11 +870,44 @@ * try again. (only if use_sequence == 1). * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by * a signal. Release all buffer reservations and return to user-space. + * -EBUSY: The function needed to sleep, but @no_wait was true + * -EDEADLK: Bo already reserved using @sequence. This error code will only + * be returned if @use_sequence is set to true. */ extern int ttm_bo_reserve(struct ttm_buffer_object *bo, bool interruptible, bool no_wait, bool use_sequence, uint32_t sequence); + +/** + * ttm_bo_reserve_locked: + * + * @bo: A pointer to a struct ttm_buffer_object. + * @interruptible: Sleep interruptible if waiting. + * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. + * @use_sequence: If @bo is already reserved, Only sleep waiting for + * it to become unreserved if @sequence < (@bo)->sequence. + * + * Must be called with struct ttm_bo_global::lru_lock held, + * and will not remove reserved buffers from the lru lists. + * The function may release the LRU spinlock if it needs to sleep. + * Otherwise identical to ttm_bo_reserve. + * + * Returns: + * -EAGAIN: The reservation may cause a deadlock. + * Release all buffer reservations, wait for @bo to become unreserved and + * try again. (only if use_sequence == 1). + * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by + * a signal. Release all buffer reservations and return to user-space. + * -EBUSY: The function needed to sleep, but @no_wait was true + * -EDEADLK: Bo already reserved using @sequence. This error code will only + * be returned if @use_sequence is set to true. + */ +extern int ttm_bo_reserve_locked(struct ttm_buffer_object *bo, + bool interruptible, + bool no_wait, bool use_sequence, + uint32_t sequence); + /** * ttm_bo_unreserve * @@ -874,6 +918,16 @@ extern void ttm_bo_unreserve(struct ttm_buffer_object *bo); /** + * ttm_bo_unreserve_locked + * + * @bo: A pointer to a struct ttm_buffer_object. + * + * Unreserve a previous reservation of @bo. + * Needs to be called with struct ttm_bo_global::lru_lock held. + */ +extern void ttm_bo_unreserve_locked(struct ttm_buffer_object *bo); + +/** * ttm_bo_wait_unreserved * * @bo: A pointer to a struct ttm_buffer_object. --- linux-2.6.37.orig/include/drm/ttm/ttm_execbuf_util.h +++ linux-2.6.37/include/drm/ttm/ttm_execbuf_util.h @@ -41,7 +41,10 @@ * @bo: refcounted buffer object pointer. * @new_sync_obj_arg: New sync_obj_arg for @bo, to be used once * adding a new sync object. - * @reservied: Indicates whether @bo has been reserved for validation. + * @reserved: Indicates whether @bo has been reserved for validation. + * @removed: Indicates whether @bo has been removed from lru lists. + * @put_count: Number of outstanding references on bo::list_kref. + * @old_sync_obj: Pointer to a sync object about to be unreferenced */ struct ttm_validate_buffer { @@ -49,6 +52,9 @@ struct ttm_buffer_object *bo; void *new_sync_obj_arg; bool reserved; + bool removed; + int put_count; + void *old_sync_obj; }; /** @@ -66,7 +72,6 @@ * function ttm_eu_reserve_buffers * * @list: thread private list of ttm_validate_buffer structs. - * @val_seq: A unique sequence number. * * Tries to reserve bos pointed to by the list entries for validation. * If the function returns 0, all buffers are marked as "unfenced", @@ -88,7 +93,7 @@ * has failed. */ -extern int ttm_eu_reserve_buffers(struct list_head *list, uint32_t val_seq); +extern int ttm_eu_reserve_buffers(struct list_head *list); /** * function ttm_eu_fence_buffer_objects. --- linux-2.6.37.orig/include/linux/fb.h +++ linux-2.6.37/include/linux/fb.h @@ -832,6 +832,7 @@ struct fb_info { int node; int flags; + int ref_count; struct mutex lock; /* Lock for open/release/ioctl funcs */ struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */ struct fb_var_screeninfo var; /* Current var */ @@ -871,6 +872,7 @@ void *pseudo_palette; /* Fake palette of 16 colors */ #define FBINFO_STATE_RUNNING 0 #define FBINFO_STATE_SUSPENDED 1 +#define FBINFO_STATE_REMOVED 2 u32 state; /* Hardware state i.e suspend */ void *fbcon_par; /* fbcon use-only private area */ /* From here on everything is device dependent */ --- linux-2.6.37.orig/include/linux/init.h +++ linux-2.6.37/include/linux/init.h @@ -195,6 +195,7 @@ #define core_initcall(fn) __define_initcall("1",fn,1) #define core_initcall_sync(fn) __define_initcall("1s",fn,1s) +#define earlyrootfs_initcall(fn) __define_initcall("earlyrootfs",fn,rootfs) #define postcore_initcall(fn) __define_initcall("2",fn,2) #define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s) #define arch_initcall(fn) __define_initcall("3",fn,3) @@ -222,6 +223,8 @@ static initcall_t __initcall_##fn \ __used __section(.security_initcall.init) = fn +extern struct list_head populate_rootfs_domain; + struct obs_kernel_param { const char *str; int (*setup_func)(char *); --- linux-2.6.37.orig/include/linux/input.h +++ linux-2.6.37/include/linux/input.h @@ -91,7 +91,6 @@ * (depending on which element was used to perform lookup). */ struct input_keymap_entry { -#define INPUT_KEYMAP_BY_INDEX (1 << 0) __u8 flags; __u8 len; __u16 index; @@ -99,6 +98,8 @@ __u8 scancode[32]; }; +#define INPUT_KEYMAP_BY_INDEX (1 << 0) + #define EVIOCGVERSION _IOR('E', 0x01, int) /* get driver version */ #define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */ #define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) /* get repeat settings */ --- linux-2.6.37.orig/include/linux/kd.h +++ linux-2.6.37/include/linux/kd.h @@ -45,6 +45,7 @@ #define KD_GRAPHICS 0x01 #define KD_TEXT0 0x02 /* obsolete */ #define KD_TEXT1 0x03 /* obsolete */ +#define KD_TRANSPARENT 0x04 #define KDGETMODE 0x4B3B /* get current mode */ #define KDMAPDISP 0x4B3C /* map display into address space */ --- linux-2.6.37.orig/include/linux/lsm_audit.h +++ linux-2.6.37/include/linux/lsm_audit.h @@ -123,6 +123,10 @@ u32 denied; uid_t ouid; } fs; + struct { + int type, protocol; + struct sock *sk; + } net; }; } apparmor_audit_data; #endif --- linux-2.6.37.orig/include/linux/mm.h +++ linux-2.6.37/include/linux/mm.h @@ -1295,7 +1295,13 @@ unsigned long addr, unsigned long len, unsigned long flags, struct page **pages); -extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); +extern unsigned long get_unmapped_area_prot(struct file *, unsigned long, unsigned long, unsigned long, unsigned long, int); + +static inline unsigned long get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + return get_unmapped_area_prot(file, addr, len, pgoff, flags, 0); +} extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, --- linux-2.6.37.orig/include/linux/mm_types.h +++ linux-2.6.37/include/linux/mm_types.h @@ -227,6 +227,9 @@ unsigned long (*get_unmapped_area) (struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags); + unsigned long (*get_unmapped_exec_area) (struct file *filp, + unsigned long addr, unsigned long len, + unsigned long pgoff, unsigned long flags); void (*unmap_area) (struct mm_struct *mm, unsigned long addr); #endif unsigned long mmap_base; /* base of mmap area */ --- linux-2.6.37.orig/include/linux/module.h +++ linux-2.6.37/include/linux/module.h @@ -308,6 +308,9 @@ /* The size of the executable code in each section. */ unsigned int init_text_size, core_text_size; + /* Size of RO sections of the module (text+rodata) */ + unsigned int init_ro_size, core_ro_size; + /* Arch-specific module values */ struct mod_arch_specific arch; @@ -672,7 +675,6 @@ { return 0; } - #endif /* CONFIG_MODULES */ #ifdef CONFIG_SYSFS @@ -687,6 +689,13 @@ #define __MODULE_STRING(x) __stringify(x) +#ifdef CONFIG_DEBUG_SET_MODULE_RONX +extern void set_all_modules_text_rw(void); +extern void set_all_modules_text_ro(void); +#else +static inline void set_all_modules_text_rw(void) { } +static inline void set_all_modules_text_ro(void) { } +#endif #ifdef CONFIG_GENERIC_BUG void module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *, --- linux-2.6.37.orig/include/linux/moduleparam.h +++ linux-2.6.37/include/linux/moduleparam.h @@ -265,7 +265,7 @@ char *args, const struct kernel_param *params, unsigned num, - int (*unknown)(char *param, char *val)); + int (*handle)(char *param, char *val, int known)); /* Called by module remove. */ #ifdef CONFIG_SYSFS --- linux-2.6.37.orig/include/linux/namei.h +++ linux-2.6.37/include/linux/namei.h @@ -73,6 +73,9 @@ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, int (*open)(struct inode *, struct file *)); +extern struct dentry *lookup_hash(struct nameidata *nd); +extern int __lookup_one_len(const char *name, struct qstr *this, + struct dentry *base, int len); extern struct dentry *lookup_one_len(const char *, struct dentry *, int); extern int follow_down(struct path *); --- linux-2.6.37.orig/include/linux/page-flags.h +++ linux-2.6.37/include/linux/page-flags.h @@ -108,6 +108,7 @@ #ifdef CONFIG_MEMORY_FAILURE PG_hwpoison, /* hardware poisoned page. Don't touch */ #endif + PG_readaheadunused, /* user oriented readahead as yet unused*/ __NR_PAGEFLAGS, /* Filesystems */ @@ -237,6 +238,8 @@ PAGEFLAG(Reclaim, reclaim) TESTCLEARFLAG(Reclaim, reclaim) PAGEFLAG(Readahead, reclaim) /* Reminder to do async read-ahead */ +PAGEFLAG(ReadaheadUnused, readaheadunused) + #ifdef CONFIG_HIGHMEM /* * Must use a macro here due to header dependency issues. page_zone() is not --- linux-2.6.37.orig/include/linux/prctl.h +++ linux-2.6.37/include/linux/prctl.h @@ -102,4 +102,10 @@ #define PR_MCE_KILL_GET 34 +/* + * Set specific pid that is allowed to PTRACE the current task. + * A value of 0 mean "no process". + */ +#define PR_SET_PTRACER 0x59616d61 + #endif /* _LINUX_PRCTL_H */ --- linux-2.6.37.orig/include/linux/sched.h +++ linux-2.6.37/include/linux/sched.h @@ -101,6 +101,9 @@ struct fs_struct; struct perf_event_context; +extern int disable_nx; +extern int print_fatal_signals; + /* * List of flags we want to share for kernel threads, * if only because they are not used by them anyway. @@ -385,6 +388,10 @@ extern unsigned long arch_get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); + +extern unsigned long +arch_get_unmapped_exec_area(struct file *, unsigned long, unsigned long, + unsigned long, unsigned long); extern unsigned long arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, @@ -509,6 +516,8 @@ spinlock_t lock; }; +struct autogroup; + /* * NOTE! "signal_struct" does not have it's own * locking, because a shared signal_struct always @@ -576,6 +585,9 @@ struct tty_struct *tty; /* NULL if no tty */ +#ifdef CONFIG_SCHED_AUTOGROUP + struct autogroup *autogroup; +#endif /* * Cumulative resource counters for dead threads in the group, * and for reaped dead child processes forked by this group. @@ -1931,6 +1943,24 @@ extern unsigned int sysctl_sched_compat_yield; +#ifdef CONFIG_SCHED_AUTOGROUP +extern unsigned int sysctl_sched_autogroup_enabled; + +extern void sched_autogroup_create_attach(struct task_struct *p); +extern void sched_autogroup_detach(struct task_struct *p); +extern void sched_autogroup_fork(struct signal_struct *sig); +extern void sched_autogroup_exit(struct signal_struct *sig); +#ifdef CONFIG_PROC_FS +extern void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m); +extern int proc_sched_autogroup_set_nice(struct task_struct *p, int *nice); +#endif +#else +static inline void sched_autogroup_create_attach(struct task_struct *p) { } +static inline void sched_autogroup_detach(struct task_struct *p) { } +static inline void sched_autogroup_fork(struct signal_struct *sig) { } +static inline void sched_autogroup_exit(struct signal_struct *sig) { } +#endif + #ifdef CONFIG_RT_MUTEXES extern int rt_mutex_getprio(struct task_struct *p); extern void rt_mutex_setprio(struct task_struct *p, int prio); --- linux-2.6.37.orig/include/linux/screen_info.h +++ linux-2.6.37/include/linux/screen_info.h @@ -67,6 +67,7 @@ #define VIDEO_TYPE_EFI 0x70 /* EFI graphic mode */ #define VIDEO_FLAGS_NOCURSOR (1 << 0) /* The video mode has no cursor set */ +#define VIDEO_FLAGS_HANDOFF (1 << 1) /* Video buffer is alredy painted */ #ifdef __KERNEL__ extern struct screen_info screen_info; --- linux-2.6.37.orig/include/linux/security.h +++ linux-2.6.37/include/linux/security.h @@ -637,6 +637,9 @@ * manual page for definitions of the @clone_flags. * @clone_flags contains the flags indicating what should be shared. * Return 0 if permission is granted. + * @task_free: + * @task task being freed + * Handle release of task-related resources. * @cred_alloc_blank: * @cred points to the credentials. * @gfp indicates the atomicity of any memory allocations. @@ -1491,6 +1494,7 @@ int (*dentry_open) (struct file *file, const struct cred *cred); int (*task_create) (unsigned long clone_flags); + void (*task_free) (struct task_struct *task); int (*cred_alloc_blank) (struct cred *cred, gfp_t gfp); void (*cred_free) (struct cred *cred); int (*cred_prepare)(struct cred *new, const struct cred *old, @@ -1745,6 +1749,7 @@ int security_file_receive(struct file *file); int security_dentry_open(struct file *file, const struct cred *cred); int security_task_create(unsigned long clone_flags); +void security_task_free(struct task_struct *task); int security_cred_alloc_blank(struct cred *cred, gfp_t gfp); void security_cred_free(struct cred *cred); int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp); @@ -2245,6 +2250,9 @@ return 0; } +static inline void security_task_free(struct task_struct *task) +{ } + static inline int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) { return 0; --- linux-2.6.37.orig/include/linux/splice.h +++ linux-2.6.37/include/linux/splice.h @@ -89,4 +89,10 @@ extern void splice_shrink_spd(struct pipe_inode_info *, struct splice_pipe_desc *); +extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags); +extern long do_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags); + #endif --- linux-2.6.37.orig/include/linux/swap.h +++ linux-2.6.37/include/linux/swap.h @@ -185,6 +185,7 @@ struct block_device *bdev; /* swap device or bdev of swap file */ struct file *swap_file; /* seldom referenced */ unsigned int old_block_size; /* seldom referenced */ + void (*notify_swap_entry_free_fn) (unsigned long); }; struct swap_list_t { @@ -342,6 +343,7 @@ extern int reuse_swap_page(struct page *); extern int try_to_free_swap(struct page *); struct backing_dev_info; +extern void set_notify_swap_entry_free(unsigned, void (*) (unsigned long)); /* linux/mm/thrash.c */ extern struct mm_struct *swap_token_mm; --- linux-2.6.37.orig/include/linux/vt_kern.h +++ linux-2.6.37/include/linux/vt_kern.h @@ -130,7 +130,7 @@ void vt_event_post(unsigned int event, unsigned int old, unsigned int new); int vt_waitactive(int n); void change_console(struct vc_data *new_vc); -void reset_vc(struct vc_data *vc); +void reset_vc(struct vc_data *vc, int mode); extern int unbind_con_driver(const struct consw *csw, int first, int last, int deflt); int vty_init(const struct file_operations *console_fops); --- linux-2.6.37.orig/include/linux/agp_backend.h +++ linux-2.6.37/include/linux/agp_backend.h @@ -102,10 +102,8 @@ extern int agp_copy_info(struct agp_bridge_data *, struct agp_kern_info *); extern int agp_bind_memory(struct agp_memory *, off_t); extern int agp_unbind_memory(struct agp_memory *); -extern int agp_rebind_memory(void); extern void agp_enable(struct agp_bridge_data *, u32); extern struct agp_bridge_data *agp_backend_acquire(struct pci_dev *); extern void agp_backend_release(struct agp_bridge_data *); -extern void agp_flush_chipset(struct agp_bridge_data *); #endif /* _AGP_BACKEND_H */ --- linux-2.6.37.orig/include/linux/kref.h +++ linux-2.6.37/include/linux/kref.h @@ -24,5 +24,7 @@ void kref_init(struct kref *kref); void kref_get(struct kref *kref); int kref_put(struct kref *kref, void (*release) (struct kref *kref)); +int kref_sub(struct kref *kref, unsigned int count, + void (*release) (struct kref *kref)); #endif /* _KREF_H_ */ --- linux-2.6.37.orig/include/trace/events/fs.h +++ linux-2.6.37/include/trace/events/fs.h @@ -0,0 +1,53 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM fs + +#if !defined(_TRACE_FS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_FS_H + +#include +#include + +TRACE_EVENT(do_sys_open, + + TP_PROTO(char *filename, int flags, int mode), + + TP_ARGS(filename, flags, mode), + + TP_STRUCT__entry( + __string( filename, filename ) + __field( int, flags ) + __field( int, mode ) + ), + + TP_fast_assign( + __assign_str(filename, filename); + __entry->flags = flags; + __entry->mode = mode; + ), + + TP_printk("\"%s\" %x %o", + __get_str(filename), __entry->flags, __entry->mode) +); + +TRACE_EVENT(open_exec, + + TP_PROTO(char *filename), + + TP_ARGS(filename), + + TP_STRUCT__entry( + __string( filename, filename ) + ), + + TP_fast_assign( + __assign_str(filename, filename); + ), + + TP_printk("\"%s\"", + __get_str(filename)) +); + +#endif /* _TRACE_FS_H */ + +/* This part must be outside protection */ +#include --- linux-2.6.37.orig/include/trace/events/vfs.h +++ linux-2.6.37/include/trace/events/vfs.h @@ -0,0 +1,53 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM vfs + +#if !defined(_TRACE_VFS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_VFS_H + +/* + * Tracepoint for dirtying an inode: + */ +TRACE_EVENT(dirty_inode, + + TP_PROTO(struct inode *inode, struct task_struct *task), + + TP_ARGS(inode, task), + + TP_STRUCT__entry( + __array( char, comm, TASK_COMM_LEN ) + __field( pid_t, pid ) + __array( char, dev, 16 ) + __array( char, file, 32 ) + ), + + TP_fast_assign( + if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) { + struct dentry *dentry; + const char *name = "?"; + + dentry = d_find_alias(inode); + if (dentry) { + spin_lock(&dentry->d_lock); + name = (const char *) dentry->d_name.name; + } + + memcpy(__entry->comm, task->comm, TASK_COMM_LEN); + __entry->pid = task->pid; + strlcpy(__entry->file, name, 32); + strlcpy(__entry->dev, inode->i_sb->s_id, 16); + + if (dentry) { + spin_unlock(&dentry->d_lock); + dput(dentry); + } + } + ), + + TP_printk("task=%i (%s) file=%s dev=%s", + __entry->pid, __entry->comm, __entry->file, __entry->dev) +); + +#endif /* _TRACE_VFS_H */ + +/* This part must be outside protection */ +#include --- linux-2.6.37.orig/include/xen/interface/io/blkif.h +++ linux-2.6.37/include/xen/interface/io/blkif.h @@ -87,6 +87,18 @@ DEFINE_RING_TYPES(blkif, struct blkif_request, struct blkif_response); +/* + * Maximum number of pages used for a blkif ring + * max-ring-pages advertised by blkback to blkfront may be lowered at blkback + * mod load time. Load time param set to default. + */ +#define BLKIF_MAX_NUM_RING_PAGES 16 +#define BLKIF_MAX_NUM_RING_PAGES_DFLT 4 +#if BLKIF_MAX_NUM_RING_PAGES < BLKIF_MAX_NUM_RING_PAGES_DFLT +#undef BLKIF_MAX_NUM_RING_PAGES_DFLT +#define BLKIF_MAX_NUM_RING_PAGES_DFLT BLKIF_MAX_NUM_RING_PAGES +#endif + #define VDISK_CDROM 0x1 #define VDISK_REMOVABLE 0x2 #define VDISK_READONLY 0x4 --- linux-2.6.37.orig/init/Kconfig +++ linux-2.6.37/init/Kconfig @@ -82,6 +82,13 @@ Maximum of each of the number of arguments and environment variables passed to init from the kernel command line. +config INIT_PASS_ALL_PARAMS + bool "Pass all (known and unknown) kernel parameters to init" + default n + help + Pass all kernel command line parameters to init, this includes + those consumed by kernel modules. This is useful for upstart + based systems. If in doubt say N. config CROSS_COMPILE string "Cross-compiler tool prefix" @@ -191,6 +198,15 @@ endchoice +config VERSION_SIGNATURE + string "Arbitrary version signature" + help + This string will be created in a file, /proc/version_signature. It + is useful in determining arbitrary data about your kernel. For instance, + if you have several kernels of the same version, but need to keep track + of a revision of the same kernel, but not affect it's ability to load + compatible modules, this is the easiest way to do that. + config SWAP bool "Support for paging of anonymous memory (swap)" depends on MMU && BLOCK @@ -741,6 +757,18 @@ endif # NAMESPACES +config SCHED_AUTOGROUP + bool "Automatic process group scheduling" + select CGROUPS + select CGROUP_SCHED + select FAIR_GROUP_SCHED + help + This option optimizes the scheduler for common desktop workloads by + automatically creating and populating task groups. This separation + of workloads isolates aggressive CPU burners (like build jobs) from + desktop applications. Task group autogeneration is currently based + upon task session. + config MM_OWNER bool --- linux-2.6.37.orig/init/initramfs.c +++ linux-2.6.37/init/initramfs.c @@ -8,6 +8,7 @@ #include #include #include +#include static __initdata char *message; static void __init error(char *x) @@ -569,7 +570,9 @@ } #endif -static int __init populate_rootfs(void) +LIST_HEAD(populate_rootfs_domain); + +static void __init async_populate_rootfs(void) { char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size); if (err) @@ -582,7 +585,7 @@ initrd_end - initrd_start); if (!err) { free_initrd(); - return 0; + return; } else { clean_rootfs(); unpack_to_rootfs(__initramfs_start, __initramfs_size); @@ -606,6 +609,25 @@ free_initrd(); #endif } - return 0; + return; } + +static int __initdata rootfs_populated; + +static int __init populate_rootfs_early(void) +{ + if (num_online_cpus() > 1) { + rootfs_populated = 1; + async_schedule_domain(async_populate_rootfs, NULL, + &populate_rootfs_domain); + } +} +static int __init populate_rootfs(void) +{ + if (!rootfs_populated) + async_schedule_domain(async_populate_rootfs, NULL, + &populate_rootfs_domain); +} + +earlyrootfs_initcall(populate_rootfs_early); rootfs_initcall(populate_rootfs); --- linux-2.6.37.orig/init/main.c +++ linux-2.6.37/init/main.c @@ -103,6 +103,11 @@ */ #define MAX_INIT_ARGS CONFIG_INIT_ENV_ARG_LIMIT #define MAX_INIT_ENVS CONFIG_INIT_ENV_ARG_LIMIT +#ifdef CONFIG_INIT_PASS_ALL_PARAMS +#define INIT_PASS_FUNCTION pass_all_bootoptions +#else +#define INIT_PASS_FUNCTION pass_unknown_bootoptions +#endif extern void time_init(void); /* Default late time init is NULL. archs can override this later. */ @@ -247,7 +252,7 @@ static int __init quiet_kernel(char *str) { - console_loglevel = 4; + console_loglevel = 2; return 0; } @@ -263,10 +268,11 @@ early_param("loglevel", loglevel); /* - * Unknown boot options get handed to init, unless they look like - * unused parameters (modprobe will find them in /proc/cmdline). + * Select boot options to hand to init. If all is set hand off them all + * otherwise only hand off unused ones which do not apply to modules + * (modprobe will find them in /proc/cmdline). */ -static int __init unknown_bootoption(char *param, char *val) +static int __init pass_bootoption(char *param, char *val, int all) { /* Change NUL term back to "=", to make "param" the whole string. */ if (val) { @@ -282,11 +288,11 @@ } /* Handle obsolete-style parameters */ - if (obsolete_checksetup(param)) + if (obsolete_checksetup(param) && !all) return 0; /* Unused module parameter. */ - if (strchr(param, '.') && (!val || strchr(param, '.') < val)) + if (!all && strchr(param, '.') && (!val || strchr(param, '.') < val)) return 0; if (panic_later) @@ -317,6 +323,16 @@ } return 0; } +static int __init pass_unknown_bootoptions(char *param, char *val, int known) +{ + if (known) + return 0; + return pass_bootoption(param, val, 0); +} +static int __init pass_all_bootoptions(char *param, char *val, int known) +{ + return pass_bootoption(param, val, 1); +} #ifdef CONFIG_DEBUG_PAGEALLOC int __read_mostly debug_pagealloc_enabled = 0; @@ -454,10 +470,13 @@ } /* Check for early params. */ -static int __init do_early_param(char *param, char *val) +static int __init do_early_param(char *param, char *val, int known) { const struct obs_kernel_param *p; + if (known) + return 0; + for (p = __setup_start; p < __setup_end; p++) { if ((p->early && strcmp(param, p->str) == 0) || (strcmp(param, "console") == 0 && @@ -577,7 +596,7 @@ parse_early_param(); parse_args("Booting kernel", static_command_line, __start___param, __stop___param - __start___param, - &unknown_bootoption); + &INIT_PASS_FUNCTION); /* * These use large bootmem allocations and must precede * kmem_cache_init() @@ -895,6 +914,12 @@ (void) sys_dup(0); (void) sys_dup(0); /* + * We need to ensure that the filesystem is ready by this point, wait for + * async_populate_rootfs to complete. + */ + async_synchronize_full_domain(&populate_rootfs_domain); + + /* * check if there is an early userspace init. If yes, let it do all * the work */ --- linux-2.6.37.orig/init/noinitramfs.c +++ linux-2.6.37/init/noinitramfs.c @@ -22,6 +22,8 @@ #include #include +LIST_HEAD(populate_rootfs_domain); + /* * Create a simple rootfs that is similar to the default initramfs */ --- linux-2.6.37.orig/init/version.c +++ linux-2.6.37/init/version.c @@ -39,7 +39,11 @@ /* FIXED STRINGS! Don't touch! */ const char linux_banner[] = "Linux version " UTS_RELEASE " (" LINUX_COMPILE_BY "@" - LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION "\n"; + LINUX_COMPILE_HOST ") (" LINUX_COMPILER ") " UTS_VERSION +#ifdef CONFIG_VERSION_SIGNATURE + " (" CONFIG_VERSION_SIGNATURE ")" +#endif + "\n"; const char linux_proc_banner[] = "%s version %s" --- linux-2.6.37.orig/kernel/fork.c +++ linux-2.6.37/kernel/fork.c @@ -174,8 +174,10 @@ static inline void put_signal_struct(struct signal_struct *sig) { - if (atomic_dec_and_test(&sig->sigcnt)) + if (atomic_dec_and_test(&sig->sigcnt)) { + sched_autogroup_exit(sig); free_signal_struct(sig); + } } void __put_task_struct(struct task_struct *tsk) @@ -184,6 +186,7 @@ WARN_ON(atomic_read(&tsk->usage)); WARN_ON(tsk == current); + security_task_free(tsk); exit_creds(tsk); delayacct_tsk_free(tsk); put_signal_struct(tsk->signal); @@ -905,6 +908,7 @@ posix_cpu_timers_init_group(sig); tty_audit_fork(sig); + sched_autogroup_fork(sig); sig->oom_adj = current->signal->oom_adj; sig->oom_score_adj = current->signal->oom_score_adj; --- linux-2.6.37.orig/kernel/module.c +++ linux-2.6.37/kernel/module.c @@ -56,6 +56,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -70,6 +71,26 @@ #define ARCH_SHF_SMALL 0 #endif +/* + * Modules' sections will be aligned on page boundaries + * to ensure complete separation of code and data, but + * only when CONFIG_DEBUG_SET_MODULE_RONX=y + */ +#ifdef CONFIG_DEBUG_SET_MODULE_RONX +# define debug_align(X) ALIGN(X, PAGE_SIZE) +#else +# define debug_align(X) (X) +#endif + +/* + * Given BASE and SIZE this macro calculates the number of pages the + * memory regions occupies + */ +#define MOD_NUMBER_OF_PAGES(BASE, SIZE) (((SIZE) > 0) ? \ + (PFN_DOWN((unsigned long)(BASE) + (SIZE) - 1) - \ + PFN_DOWN((unsigned long)BASE) + 1) \ + : (0UL)) + /* If this is set, the section belongs in the init part of the module */ #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) @@ -1542,6 +1563,115 @@ return 0; } +#ifdef CONFIG_DEBUG_SET_MODULE_RONX +/* + * LKM RO/NX protection: protect module's text/ro-data + * from modification and any data from execution. + */ +void set_page_attributes(void *start, void *end, int (*set)(unsigned long start, int num_pages)) +{ + unsigned long begin_pfn = PFN_DOWN((unsigned long)start); + unsigned long end_pfn = PFN_DOWN((unsigned long)end); + + if (end_pfn > begin_pfn) + set(begin_pfn << PAGE_SHIFT, end_pfn - begin_pfn); +} + +static void set_section_ro_nx(void *base, + unsigned long text_size, + unsigned long ro_size, + unsigned long total_size) +{ + /* begin and end PFNs of the current subsection */ + unsigned long begin_pfn; + unsigned long end_pfn; + + /* + * Set RO for module text and RO-data: + * - Always protect first page. + * - Do not protect last partial page. + */ + if (ro_size > 0) + set_page_attributes(base, base + ro_size, set_memory_ro); + + /* + * Set NX permissions for module data: + * - Do not protect first partial page. + * - Always protect last page. + */ + if (total_size > text_size) { + begin_pfn = PFN_UP((unsigned long)base + text_size); + end_pfn = PFN_UP((unsigned long)base + total_size); + if (end_pfn > begin_pfn) + set_memory_nx(begin_pfn << PAGE_SHIFT, end_pfn - begin_pfn); + } +} + +/* Setting memory back to RW+NX before releasing it */ +void unset_section_ro_nx(struct module *mod, void *module_region) +{ + unsigned long total_pages; + + if (mod->module_core == module_region) { + /* Set core as NX+RW */ + total_pages = MOD_NUMBER_OF_PAGES(mod->module_core, mod->core_size); + set_memory_nx((unsigned long)mod->module_core, total_pages); + set_memory_rw((unsigned long)mod->module_core, total_pages); + + } else if (mod->module_init == module_region) { + /* Set init as NX+RW */ + total_pages = MOD_NUMBER_OF_PAGES(mod->module_init, mod->init_size); + set_memory_nx((unsigned long)mod->module_init, total_pages); + set_memory_rw((unsigned long)mod->module_init, total_pages); + } +} + +/* Iterate through all modules and set each module's text as RW */ +void set_all_modules_text_rw() +{ + struct module *mod; + + mutex_lock(&module_mutex); + list_for_each_entry_rcu(mod, &modules, list) { + if ((mod->module_core) && (mod->core_text_size)) { + set_page_attributes(mod->module_core, + mod->module_core + mod->core_text_size, + set_memory_rw); + } + if ((mod->module_init) && (mod->init_text_size)) { + set_page_attributes(mod->module_init, + mod->module_init + mod->init_text_size, + set_memory_rw); + } + } + mutex_unlock(&module_mutex); +} + +/* Iterate through all modules and set each module's text as RO */ +void set_all_modules_text_ro() +{ + struct module *mod; + + mutex_lock(&module_mutex); + list_for_each_entry_rcu(mod, &modules, list) { + if ((mod->module_core) && (mod->core_text_size)) { + set_page_attributes(mod->module_core, + mod->module_core + mod->core_text_size, + set_memory_ro); + } + if ((mod->module_init) && (mod->init_text_size)) { + set_page_attributes(mod->module_init, + mod->module_init + mod->init_text_size, + set_memory_ro); + } + } + mutex_unlock(&module_mutex); +} +#else +static inline void set_section_ro_nx(void *base, unsigned long text_size, unsigned long ro_size, unsigned long total_size) { } +static inline void unset_section_ro_nx(struct module *mod, void *module_region) { } +#endif + /* Free a module, remove from lists, etc. */ static void free_module(struct module *mod) { @@ -1566,6 +1696,7 @@ destroy_params(mod->kp, mod->num_kp); /* This may be NULL, but that's OK */ + unset_section_ro_nx(mod, mod->module_init); module_free(mod, mod->module_init); kfree(mod->args); percpu_modfree(mod); @@ -1574,6 +1705,7 @@ lockdep_free_key_range(mod->module_core, mod->core_size); /* Finally, free the core (containing the module structure) */ + unset_section_ro_nx(mod, mod->module_core); module_free(mod, mod->module_core); #ifdef CONFIG_MPU @@ -1777,8 +1909,19 @@ s->sh_entsize = get_offset(mod, &mod->core_size, s, i); DEBUGP("\t%s\n", name); } - if (m == 0) + switch (m) { + case 0: /* executable */ + mod->core_size = debug_align(mod->core_size); mod->core_text_size = mod->core_size; + break; + case 1: /* RO: text and ro-data */ + mod->core_size = debug_align(mod->core_size); + mod->core_ro_size = mod->core_size; + break; + case 3: /* whole core */ + mod->core_size = debug_align(mod->core_size); + break; + } } DEBUGP("Init section allocation order:\n"); @@ -1796,8 +1939,19 @@ | INIT_OFFSET_MASK); DEBUGP("\t%s\n", sname); } - if (m == 0) + switch (m) { + case 0: /* executable */ + mod->init_size = debug_align(mod->init_size); mod->init_text_size = mod->init_size; + break; + case 1: /* RO: text and ro-data */ + mod->init_size = debug_align(mod->init_size); + mod->init_ro_size = mod->init_size; + break; + case 3: /* whole init */ + mod->init_size = debug_align(mod->init_size); + break; + } } } @@ -2722,6 +2876,18 @@ blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_COMING, mod); + /* Set RO and NX regions for core */ + set_section_ro_nx(mod->module_core, + mod->core_text_size, + mod->core_ro_size, + mod->core_size); + + /* Set RO and NX regions for init */ + set_section_ro_nx(mod->module_init, + mod->init_text_size, + mod->init_ro_size, + mod->init_size); + do_mod_ctors(mod); /* Start the module */ if (mod->init != NULL) @@ -2765,6 +2931,7 @@ mod->symtab = mod->core_symtab; mod->strtab = mod->core_strtab; #endif + unset_section_ro_nx(mod, mod->module_init); module_free(mod, mod->module_init); mod->module_init = NULL; mod->init_size = 0; --- linux-2.6.37.orig/kernel/params.c +++ linux-2.6.37/kernel/params.c @@ -87,7 +87,7 @@ char *val, const struct kernel_param *params, unsigned num_params, - int (*handle_unknown)(char *param, char *val)) + int (*handle_arg)(char *param, char *val, int known)) { unsigned int i; int err; @@ -98,6 +98,14 @@ /* Noone handled NULL, so do it here. */ if (!val && params[i].ops->set != param_set_bool) return -EINVAL; + if (handle_arg) { + int ret; + DEBUGP("Valid argument: calling %p\n", + handle_arg); + ret = handle_arg(param, val, 1); + if (ret) + return ret; + } DEBUGP("They are equal! Calling %p\n", params[i].ops->set); mutex_lock(¶m_lock); @@ -107,9 +115,9 @@ } } - if (handle_unknown) { - DEBUGP("Unknown argument: calling %p\n", handle_unknown); - return handle_unknown(param, val); + if (handle_arg) { + DEBUGP("Unknown argument: calling %p\n", handle_arg); + return handle_arg(param, val, 0); } DEBUGP("Unknown argument `%s'\n", param); @@ -173,7 +181,7 @@ char *args, const struct kernel_param *params, unsigned num, - int (*unknown)(char *param, char *val)) + int (*handle_arg)(char *param, char *val, int arg)) { char *param, *val; @@ -188,7 +196,7 @@ args = next_arg(args, ¶m, &val); irq_was_disabled = irqs_disabled(); - ret = parse_one(param, val, params, num, unknown); + ret = parse_one(param, val, params, num, handle_arg); if (irq_was_disabled && !irqs_disabled()) { printk(KERN_WARNING "parse_args(): option '%s' enabled " "irq's!\n", param); --- linux-2.6.37.orig/kernel/sched.c +++ linux-2.6.37/kernel/sched.c @@ -78,6 +78,7 @@ #include "sched_cpupri.h" #include "workqueue_sched.h" +#include "sched_autogroup.h" #define CREATE_TRACE_POINTS #include @@ -268,6 +269,10 @@ struct task_group *parent; struct list_head siblings; struct list_head children; + +#ifdef CONFIG_SCHED_AUTOGROUP + struct autogroup *autogroup; +#endif }; #define root_task_group init_task_group @@ -605,11 +610,14 @@ */ static inline struct task_group *task_group(struct task_struct *p) { + struct task_group *tg; struct cgroup_subsys_state *css; css = task_subsys_state_check(p, cpu_cgroup_subsys_id, lockdep_is_held(&task_rq(p)->lock)); - return container_of(css, struct task_group, css); + tg = container_of(css, struct task_group, css); + + return autogroup_task_group(p, tg); } /* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */ @@ -2063,6 +2071,7 @@ #include "sched_idletask.c" #include "sched_fair.c" #include "sched_rt.c" +#include "sched_autogroup.c" #include "sched_stoptask.c" #ifdef CONFIG_SCHED_DEBUG # include "sched_debug.c" @@ -8164,7 +8173,7 @@ #ifdef CONFIG_CGROUP_SCHED list_add(&init_task_group.list, &task_groups); INIT_LIST_HEAD(&init_task_group.children); - + autogroup_init(&init_task); #endif /* CONFIG_CGROUP_SCHED */ #if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP --- linux-2.6.37.orig/kernel/sched_autogroup.c +++ linux-2.6.37/kernel/sched_autogroup.c @@ -0,0 +1,243 @@ +#ifdef CONFIG_SCHED_AUTOGROUP + +#include +#include +#include +#include + +unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1; + +struct autogroup { + struct task_group *tg; + struct kref kref; + struct rw_semaphore lock; + unsigned long id; + int nice; +}; + +static struct autogroup autogroup_default; +static atomic_t autogroup_seq_nr; + +static void autogroup_init(struct task_struct *init_task) +{ + autogroup_default.tg = &init_task_group; + init_task_group.autogroup = &autogroup_default; + kref_init(&autogroup_default.kref); + init_rwsem(&autogroup_default.lock); + init_task->signal->autogroup = &autogroup_default; +} + +static inline void autogroup_destroy(struct kref *kref) +{ + struct autogroup *ag = container_of(kref, struct autogroup, kref); + struct task_group *tg = ag->tg; + + kfree(ag); + sched_destroy_group(tg); +} + +static inline void autogroup_kref_put(struct autogroup *ag) +{ + kref_put(&ag->kref, autogroup_destroy); +} + +static inline struct autogroup *autogroup_kref_get(struct autogroup *ag) +{ + kref_get(&ag->kref); + return ag; +} + +static inline struct autogroup *autogroup_create(void) +{ + struct autogroup *ag = kzalloc(sizeof(*ag), GFP_KERNEL); + + if (!ag) + goto out_fail; + + ag->tg = sched_create_group(&init_task_group); + + if (IS_ERR(ag->tg)) + goto out_fail; + + ag->tg->autogroup = ag; + kref_init(&ag->kref); + init_rwsem(&ag->lock); + ag->id = atomic_inc_return(&autogroup_seq_nr); + + return ag; + +out_fail: + if (ag) { + kfree(ag); + WARN_ON(1); + } else + WARN_ON(1); + + return autogroup_kref_get(&autogroup_default); +} + +static inline bool +task_wants_autogroup(struct task_struct *p, struct task_group *tg) +{ + if (tg != &root_task_group) + return false; + + if (p->sched_class != &fair_sched_class) + return false; + + /* + * We can only assume the task group can't go away on us if + * autogroup_move_group() can see us on ->thread_group list. + */ + if (p->flags & PF_EXITING) + return false; + + return true; +} + +static inline struct task_group * +autogroup_task_group(struct task_struct *p, struct task_group *tg) +{ + int enabled = ACCESS_ONCE(sysctl_sched_autogroup_enabled); + + if (enabled && task_wants_autogroup(p, tg)) + return p->signal->autogroup->tg; + + return tg; +} + +static void +autogroup_move_group(struct task_struct *p, struct autogroup *ag) +{ + struct autogroup *prev; + struct task_struct *t; + + spin_lock(&p->sighand->siglock); + + prev = p->signal->autogroup; + if (prev == ag) { + spin_unlock(&p->sighand->siglock); + return; + } + + p->signal->autogroup = autogroup_kref_get(ag); + t = p; + + do { + sched_move_task(p); + } while_each_thread(p, t); + + spin_unlock(&p->sighand->siglock); + + autogroup_kref_put(prev); +} + +/* Allocates GFP_KERNEL, cannot be called under any spinlock */ +void sched_autogroup_create_attach(struct task_struct *p) +{ + struct autogroup *ag = autogroup_create(); + + autogroup_move_group(p, ag); + /* drop extra refrence added by autogroup_create() */ + autogroup_kref_put(ag); +} +EXPORT_SYMBOL(sched_autogroup_create_attach); + +/* Cannot be called under siglock. Currently has no users */ +void sched_autogroup_detach(struct task_struct *p) +{ + autogroup_move_group(p, &autogroup_default); +} +EXPORT_SYMBOL(sched_autogroup_detach); + +void sched_autogroup_fork(struct signal_struct *sig) +{ + struct sighand_struct *sighand = current->sighand; + + spin_lock(&sighand->siglock); + sig->autogroup = autogroup_kref_get(current->signal->autogroup); + spin_unlock(&sighand->siglock); +} + +void sched_autogroup_exit(struct signal_struct *sig) +{ + autogroup_kref_put(sig->autogroup); +} + +static int __init setup_autogroup(char *str) +{ + sysctl_sched_autogroup_enabled = 0; + + return 1; +} + +__setup("noautogroup", setup_autogroup); + +#ifdef CONFIG_PROC_FS + +static inline struct autogroup *autogroup_get(struct task_struct *p) +{ + struct autogroup *ag; + + /* task may be moved after we unlock.. tough */ + spin_lock(&p->sighand->siglock); + ag = autogroup_kref_get(p->signal->autogroup); + spin_unlock(&p->sighand->siglock); + + return ag; +} + +int proc_sched_autogroup_set_nice(struct task_struct *p, int *nice) +{ + static unsigned long next = INITIAL_JIFFIES; + struct autogroup *ag; + int err; + + if (*nice < -20 || *nice > 19) + return -EINVAL; + + err = security_task_setnice(current, *nice); + if (err) + return err; + + if (*nice < 0 && !can_nice(current, *nice)) + return -EPERM; + + /* this is a heavy operation taking global locks.. */ + if (!capable(CAP_SYS_ADMIN) && time_before(jiffies, next)) + return -EAGAIN; + + next = HZ / 10 + jiffies;; + ag = autogroup_get(p); + + down_write(&ag->lock); + err = sched_group_set_shares(ag->tg, prio_to_weight[*nice + 20]); + if (!err) + ag->nice = *nice; + up_write(&ag->lock); + + autogroup_kref_put(ag); + + return err; +} + +void proc_sched_autogroup_show_task(struct task_struct *p, struct seq_file *m) +{ + struct autogroup *ag = autogroup_get(p); + + down_read(&ag->lock); + seq_printf(m, "/autogroup-%ld nice %d\n", ag->id, ag->nice); + up_read(&ag->lock); + + autogroup_kref_put(ag); +} +#endif /* CONFIG_PROC_FS */ + +#ifdef CONFIG_SCHED_DEBUG +static inline int autogroup_path(struct task_group *tg, char *buf, int buflen) +{ + return snprintf(buf, buflen, "%s-%ld", "/autogroup", tg->autogroup->id); +} +#endif /* CONFIG_SCHED_DEBUG */ + +#endif /* CONFIG_SCHED_AUTOGROUP */ --- linux-2.6.37.orig/kernel/sched_autogroup.h +++ linux-2.6.37/kernel/sched_autogroup.h @@ -0,0 +1,23 @@ +#ifdef CONFIG_SCHED_AUTOGROUP + +static inline struct task_group * +autogroup_task_group(struct task_struct *p, struct task_group *tg); + +#else /* !CONFIG_SCHED_AUTOGROUP */ + +static inline void autogroup_init(struct task_struct *init_task) { } + +static inline struct task_group * +autogroup_task_group(struct task_struct *p, struct task_group *tg) +{ + return tg; +} + +#ifdef CONFIG_SCHED_DEBUG +static inline int autogroup_path(struct task_group *tg, char *buf, int buflen) +{ + return 0; +} +#endif + +#endif /* CONFIG_SCHED_AUTOGROUP */ --- linux-2.6.37.orig/kernel/sched_debug.c +++ linux-2.6.37/kernel/sched_debug.c @@ -87,6 +87,20 @@ } #endif +#if defined(CONFIG_CGROUP_SCHED) && \ + (defined(CONFIG_FAIR_GROUP_SCHED) || defined(CONFIG_RT_GROUP_SCHED)) +static void task_group_path(struct task_group *tg, char *buf, int buflen) +{ + /* may be NULL if the underlying cgroup isn't fully-created yet */ + if (!tg->css.cgroup) { + if (!autogroup_path(tg, buf, buflen)) + buf[0] = '\0'; + return; + } + cgroup_path(tg->css.cgroup, buf, buflen); +} +#endif + static void print_task(struct seq_file *m, struct rq *rq, struct task_struct *p) { @@ -115,7 +129,7 @@ char path[64]; rcu_read_lock(); - cgroup_path(task_group(p)->css.cgroup, path, sizeof(path)); + task_group_path(task_group(p), path, sizeof(path)); rcu_read_unlock(); SEQ_printf(m, " %s", path); } @@ -147,19 +161,6 @@ read_unlock_irqrestore(&tasklist_lock, flags); } -#if defined(CONFIG_CGROUP_SCHED) && \ - (defined(CONFIG_FAIR_GROUP_SCHED) || defined(CONFIG_RT_GROUP_SCHED)) -static void task_group_path(struct task_group *tg, char *buf, int buflen) -{ - /* may be NULL if the underlying cgroup isn't fully-created yet */ - if (!tg->css.cgroup) { - buf[0] = '\0'; - return; - } - cgroup_path(tg->css.cgroup, buf, buflen); -} -#endif - void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) { s64 MIN_vruntime = -1, min_vruntime, max_vruntime = -1, --- linux-2.6.37.orig/kernel/sys.c +++ linux-2.6.37/kernel/sys.c @@ -1080,8 +1080,10 @@ err = session; out: write_unlock_irq(&tasklist_lock); - if (err > 0) + if (err > 0) { proc_sid_connector(group_leader); + sched_autogroup_create_attach(group_leader); + } return err; } --- linux-2.6.37.orig/kernel/sysctl.c +++ linux-2.6.37/kernel/sysctl.c @@ -382,6 +382,17 @@ .mode = 0644, .proc_handler = proc_dointvec, }, +#ifdef CONFIG_SCHED_AUTOGROUP + { + .procname = "sched_autogroup_enabled", + .data = &sysctl_sched_autogroup_enabled, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec, + .extra1 = &zero, + .extra2 = &one, + }, +#endif #ifdef CONFIG_PROVE_LOCKING { .procname = "prove_locking", --- linux-2.6.37.orig/lib/kref.c +++ linux-2.6.37/lib/kref.c @@ -62,6 +62,36 @@ return 0; } + +/** + * kref_sub - subtract a number of refcounts for object. + * @kref: object. + * @count: Number of recounts to subtract. + * @release: pointer to the function that will clean up the object when the + * last reference to the object is released. + * This pointer is required, and it is not acceptable to pass kfree + * in as this function. + * + * Subtract @count from the refcount, and if 0, call release(). + * Return 1 if the object was removed, otherwise return 0. Beware, if this + * function returns 0, you still can not count on the kref from remaining in + * memory. Only use the return value if you want to see if the kref is now + * gone, not present. + */ +int kref_sub(struct kref *kref, unsigned int count, + void (*release)(struct kref *kref)) +{ + WARN_ON(release == NULL); + WARN_ON(release == (void (*)(struct kref *))kfree); + + if (atomic_sub_and_test((int) count, &kref->refcount)) { + release(kref); + return 1; + } + return 0; +} + EXPORT_SYMBOL(kref_init); EXPORT_SYMBOL(kref_get); EXPORT_SYMBOL(kref_put); +EXPORT_SYMBOL(kref_sub); --- linux-2.6.37.orig/mm/filemap.c +++ linux-2.6.37/mm/filemap.c @@ -1207,6 +1207,9 @@ if (size > count) size = count; + if (PageReadaheadUnused(page)) + ClearPageReadaheadUnused(page); + /* * Faults on the destination of a read are common, so do it before * taking the kmap. --- linux-2.6.37.orig/mm/memory.c +++ linux-2.6.37/mm/memory.c @@ -2952,10 +2952,15 @@ else VM_BUG_ON(!PageLocked(vmf.page)); + page = vmf.page; + + /* Mark the page as used on fault. */ + if (PageReadaheadUnused(page)) + ClearPageReadaheadUnused(page); + /* * Should we do an early C-O-W break? */ - page = vmf.page; if (flags & FAULT_FLAG_WRITE) { if (!(vma->vm_flags & VM_SHARED)) { anon = 1; --- linux-2.6.37.orig/mm/mincore.c +++ linux-2.6.37/mm/mincore.c @@ -77,6 +77,8 @@ page = find_get_page(mapping, pgoff); if (page) { present = PageUptodate(page); + if (present) + present |= (PageReadaheadUnused(page) << 7); page_cache_release(page); } --- linux-2.6.37.orig/mm/mmap.c +++ linux-2.6.37/mm/mmap.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,18 @@ #define arch_rebalance_pgtables(addr, len) (addr) #endif +/* No sane architecture will #define these to anything else */ +#ifndef arch_add_exec_range +#define arch_add_exec_range(mm, limit) do { ; } while (0) +#endif +#ifndef arch_flush_exec_range +#define arch_flush_exec_range(mm) do { ; } while (0) +#endif +#ifndef arch_remove_exec_range +#define arch_remove_exec_range(mm, limit) do { ; } while (0) +#endif + + static void unmap_region(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, unsigned long start, unsigned long end); @@ -391,6 +404,9 @@ { struct vm_area_struct *next; + if (vma->vm_flags & VM_EXEC) + arch_add_exec_range(mm, vma->vm_end); + vma->vm_prev = prev; if (prev) { next = prev->vm_next; @@ -498,6 +514,8 @@ rb_erase(&vma->vm_rb, &mm->mm_rb); if (mm->mmap_cache == vma) mm->mmap_cache = prev; + if (vma->vm_flags & VM_EXEC) + arch_remove_exec_range(mm, vma->vm_end); } /* @@ -813,6 +831,8 @@ } else /* cases 2, 5, 7 */ err = vma_adjust(prev, prev->vm_start, end, prev->vm_pgoff, NULL); + if (prev->vm_flags & VM_EXEC) + arch_add_exec_range(mm, prev->vm_end); if (err) return NULL; return prev; @@ -1005,7 +1025,8 @@ /* Obtain the address to map to. we verify (or select) it and ensure * that it represents a valid section of the address space. */ - addr = get_unmapped_area(file, addr, len, pgoff, flags); + addr = get_unmapped_area_prot(file, addr, len, pgoff, flags, + prot & PROT_EXEC); if (addr & ~PAGE_MASK) return addr; @@ -1558,8 +1579,8 @@ } unsigned long -get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, - unsigned long pgoff, unsigned long flags) +get_unmapped_area_prot(struct file *file, unsigned long addr, unsigned long len, + unsigned long pgoff, unsigned long flags, int exec) { unsigned long (*get_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); @@ -1572,7 +1593,11 @@ if (len > TASK_SIZE) return -ENOMEM; - get_area = current->mm->get_unmapped_area; + if (exec && current->mm->get_unmapped_exec_area) + get_area = current->mm->get_unmapped_exec_area; + else + get_area = current->mm->get_unmapped_area; + if (file && file->f_op && file->f_op->get_unmapped_area) get_area = file->f_op->get_unmapped_area; addr = get_area(file, addr, len, pgoff, flags); @@ -1586,8 +1611,83 @@ return arch_rebalance_pgtables(addr, len); } +EXPORT_SYMBOL(get_unmapped_area_prot); + +static bool should_randomize(void) +{ + return (current->flags & PF_RANDOMIZE) && + !(current->personality & ADDR_NO_RANDOMIZE); +} + +#define SHLIB_BASE 0x00110000 + +unsigned long +arch_get_unmapped_exec_area(struct file *filp, unsigned long addr0, + unsigned long len0, unsigned long pgoff, unsigned long flags) +{ + unsigned long addr = addr0, len = len0; + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long tmp; + + if (len > TASK_SIZE) + return -ENOMEM; + + if (flags & MAP_FIXED) + return addr; + + if (!addr) + addr = !should_randomize() ? SHLIB_BASE : + randomize_range(SHLIB_BASE, 0x01000000, len); + + if (addr) { + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } + + addr = SHLIB_BASE; + for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) + return -ENOMEM; + + if (!vma || addr + len <= vma->vm_start) { + /* + * Must not let a PROT_EXEC mapping get into the + * brk area: + */ + if (addr + len > mm->brk) + goto failed; + + /* + * Up until the brk area we randomize addresses + * as much as possible: + */ + if (addr >= 0x01000000 && should_randomize()) { + tmp = randomize_range(0x01000000, + PAGE_ALIGN(max(mm->start_brk, + (unsigned long)0x08000000)), len); + vma = find_vma(mm, tmp); + if (TASK_SIZE - len >= tmp && + (!vma || tmp + len <= vma->vm_start)) + return tmp; + } + /* + * Ok, randomization didnt work out - return + * the result of the linear search: + */ + return addr; + } + addr = vma->vm_end; + } + +failed: + return current->mm->get_unmapped_area(filp, addr0, len0, pgoff, flags); +} -EXPORT_SYMBOL(get_unmapped_area); /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) @@ -1993,10 +2093,14 @@ if (new->vm_ops && new->vm_ops->open) new->vm_ops->open(new); - if (new_below) + if (new_below) { + unsigned long old_end = vma->vm_end; + err = vma_adjust(vma, addr, vma->vm_end, vma->vm_pgoff + ((addr - new->vm_start) >> PAGE_SHIFT), new); - else + if (vma->vm_flags & VM_EXEC) + arch_remove_exec_range(mm, old_end); + } else err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new); /* Success. */ @@ -2283,6 +2387,7 @@ free_pgtables(tlb, vma, FIRST_USER_ADDRESS, 0); tlb_finish_mmu(tlb, 0, end); + arch_flush_exec_range(mm); /* * Walk the list again, actually closing and freeing it, --- linux-2.6.37.orig/mm/mprotect.c +++ linux-2.6.37/mm/mprotect.c @@ -25,9 +25,14 @@ #include #include #include +#include #include #include +#ifndef arch_remove_exec_range +#define arch_remove_exec_range(mm, limit) do { ; } while (0) +#endif + #ifndef pgprot_modify static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) { @@ -138,7 +143,7 @@ struct mm_struct *mm = vma->vm_mm; unsigned long oldflags = vma->vm_flags; long nrpages = (end - start) >> PAGE_SHIFT; - unsigned long charged = 0; + unsigned long charged = 0, old_end = vma->vm_end; pgoff_t pgoff; int error; int dirty_accountable = 0; @@ -203,6 +208,9 @@ dirty_accountable = 1; } + if (oldflags & VM_EXEC) + arch_remove_exec_range(current->mm, old_end); + mmu_notifier_invalidate_range_start(mm, start, end); if (is_vm_hugetlb_page(vma)) hugetlb_change_protection(vma, start, end, vma->vm_page_prot); --- linux-2.6.37.orig/mm/mremap.c +++ linux-2.6.37/mm/mremap.c @@ -487,10 +487,10 @@ if (vma->vm_flags & VM_MAYSHARE) map_flags |= MAP_SHARED; - new_addr = get_unmapped_area(vma->vm_file, 0, new_len, + new_addr = get_unmapped_area_prot(vma->vm_file, 0, new_len, vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT), - map_flags); + map_flags, vma->vm_flags & VM_EXEC); if (new_addr & ~PAGE_MASK) { ret = new_addr; goto out; --- linux-2.6.37.orig/mm/readahead.c +++ linux-2.6.37/mm/readahead.c @@ -181,6 +181,7 @@ list_add(&page->lru, &page_pool); if (page_idx == nr_to_read - lookahead_size) SetPageReadahead(page); + SetPageReadaheadUnused(page); ret++; } --- linux-2.6.37.orig/mm/swapfile.c +++ linux-2.6.37/mm/swapfile.c @@ -594,6 +594,12 @@ disk->fops->swap_slot_free_notify(p->bdev, offset); } + if (!swap_count(count)) { + mem_cgroup_uncharge_swap(entry); + if (p->notify_swap_entry_free_fn) + p->notify_swap_entry_free_fn(offset); + } + return usage; } @@ -2291,6 +2297,23 @@ } /* + * Sets callback for event when swap_map[offset] == 0 + * i.e. page at this swap offset is not longer used. + * + * type: identifies swap file + * fn: callback function + */ +void set_notify_swap_entry_free(unsigned type, void (*fn) (unsigned long)) +{ + struct swap_info_struct *sis; + sis = swap_info[type]; + BUG_ON(!sis); + sis->notify_swap_entry_free_fn = fn; + return; +} +EXPORT_SYMBOL(set_notify_swap_entry_free); + +/* * swap_lock prevents swap_map being freed. Don't grab an extra * reference on the swaphandle, it doesn't matter if it becomes unused. */ --- linux-2.6.37.orig/security/Kconfig +++ linux-2.6.37/security/Kconfig @@ -153,6 +153,7 @@ source security/smack/Kconfig source security/tomoyo/Kconfig source security/apparmor/Kconfig +source security/yama/Kconfig source security/integrity/ima/Kconfig @@ -162,6 +163,7 @@ default DEFAULT_SECURITY_SMACK if SECURITY_SMACK default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR + default DEFAULT_SECURITY_YAMA if SECURITY_YAMA default DEFAULT_SECURITY_DAC help @@ -180,6 +182,9 @@ config DEFAULT_SECURITY_APPARMOR bool "AppArmor" if SECURITY_APPARMOR=y + config DEFAULT_SECURITY_YAMA + bool "Yama" if SECURITY_YAMA=y + config DEFAULT_SECURITY_DAC bool "Unix Discretionary Access Controls" @@ -191,6 +196,7 @@ default "smack" if DEFAULT_SECURITY_SMACK default "tomoyo" if DEFAULT_SECURITY_TOMOYO default "apparmor" if DEFAULT_SECURITY_APPARMOR + default "yama" if DEFAULT_SECURITY_YAMA default "" if DEFAULT_SECURITY_DAC endmenu --- linux-2.6.37.orig/security/Makefile +++ linux-2.6.37/security/Makefile @@ -7,6 +7,7 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor +subdir-$(CONFIG_SECURITY_YAMA) += yama # always enable default capabilities obj-y += commoncap.o @@ -21,6 +22,7 @@ obj-$(CONFIG_AUDIT) += lsm_audit.o obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o +obj-$(CONFIG_SECURITY_YAMA) += yama/built-in.o obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o # Object integrity file lists --- linux-2.6.37.orig/security/capability.c +++ linux-2.6.37/security/capability.c @@ -358,6 +358,9 @@ return 0; } +static void cap_task_free(struct task_struct *task) +{ } + static int cap_cred_alloc_blank(struct cred *cred, gfp_t gfp) { return 0; @@ -954,6 +957,7 @@ set_to_cap_if_null(ops, file_receive); set_to_cap_if_null(ops, dentry_open); set_to_cap_if_null(ops, task_create); + set_to_cap_if_null(ops, task_free); set_to_cap_if_null(ops, cred_alloc_blank); set_to_cap_if_null(ops, cred_free); set_to_cap_if_null(ops, cred_prepare); --- linux-2.6.37.orig/security/commoncap.c +++ linux-2.6.37/security/commoncap.c @@ -929,3 +929,4 @@ } return ret; } +EXPORT_SYMBOL(cap_file_mmap); --- linux-2.6.37.orig/security/device_cgroup.c +++ linux-2.6.37/security/device_cgroup.c @@ -515,6 +515,7 @@ return -EPERM; } +EXPORT_SYMBOL(devcgroup_inode_permission); int devcgroup_inode_mknod(int mode, dev_t dev) { --- linux-2.6.37.orig/security/security.c +++ linux-2.6.37/security/security.c @@ -22,6 +22,18 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = CONFIG_DEFAULT_SECURITY; +#if CONFIG_SECURITY_YAMA +extern int yama_ptrace_access_check(struct task_struct *child, + unsigned int mode); +extern int yama_path_link(struct dentry *old_dentry, struct path *new_dir, + struct dentry *new_dentry); +extern int yama_inode_follow_link(struct dentry *dentry, + struct nameidata *nameidata); +extern void yama_task_free(struct task_struct *task); +extern int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3, + unsigned long arg4, unsigned long arg5); +#endif + /* things that live in capability.c */ extern void __init security_fixup_ops(struct security_operations *ops); @@ -129,6 +141,12 @@ int security_ptrace_access_check(struct task_struct *child, unsigned int mode) { +#if CONFIG_SECURITY_YAMA + int rc; + rc = yama_ptrace_access_check(child, mode); + if (rc || security_ops->ptrace_access_check == yama_ptrace_access_check) + return rc; +#endif return security_ops->ptrace_access_check(child, mode); } @@ -360,6 +378,7 @@ return 0; return security_ops->path_mkdir(dir, dentry, mode); } +EXPORT_SYMBOL(security_path_mkdir); int security_path_rmdir(struct path *dir, struct dentry *dentry) { @@ -367,6 +386,7 @@ return 0; return security_ops->path_rmdir(dir, dentry); } +EXPORT_SYMBOL(security_path_rmdir); int security_path_unlink(struct path *dir, struct dentry *dentry) { @@ -374,6 +394,7 @@ return 0; return security_ops->path_unlink(dir, dentry); } +EXPORT_SYMBOL(security_path_unlink); int security_path_symlink(struct path *dir, struct dentry *dentry, const char *old_name) @@ -382,14 +403,21 @@ return 0; return security_ops->path_symlink(dir, dentry, old_name); } +EXPORT_SYMBOL(security_path_symlink); int security_path_link(struct dentry *old_dentry, struct path *new_dir, struct dentry *new_dentry) { if (unlikely(IS_PRIVATE(old_dentry->d_inode))) return 0; +#if CONFIG_SECURITY_YAMA + int rc = yama_path_link(old_dentry, new_dir, new_dentry); + if (rc || security_ops->path_link == yama_path_link) + return rc; +#endif return security_ops->path_link(old_dentry, new_dir, new_dentry); } +EXPORT_SYMBOL(security_path_link); int security_path_rename(struct path *old_dir, struct dentry *old_dentry, struct path *new_dir, struct dentry *new_dentry) @@ -400,6 +428,7 @@ return security_ops->path_rename(old_dir, old_dentry, new_dir, new_dentry); } +EXPORT_SYMBOL(security_path_rename); int security_path_truncate(struct path *path) { @@ -407,6 +436,7 @@ return 0; return security_ops->path_truncate(path); } +EXPORT_SYMBOL(security_path_truncate); int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt, mode_t mode) @@ -415,6 +445,7 @@ return 0; return security_ops->path_chmod(dentry, mnt, mode); } +EXPORT_SYMBOL(security_path_chmod); int security_path_chown(struct path *path, uid_t uid, gid_t gid) { @@ -422,6 +453,7 @@ return 0; return security_ops->path_chown(path, uid, gid); } +EXPORT_SYMBOL(security_path_chown); int security_path_chroot(struct path *path) { @@ -498,11 +530,17 @@ return 0; return security_ops->inode_readlink(dentry); } +EXPORT_SYMBOL(security_inode_readlink); int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd) { if (unlikely(IS_PRIVATE(dentry->d_inode))) return 0; +#if CONFIG_SECURITY_YAMA + int rc = yama_inode_follow_link(dentry, nd); + if (rc || security_ops->inode_follow_link == yama_inode_follow_link) + return rc; +#endif return security_ops->inode_follow_link(dentry, nd); } @@ -512,6 +550,7 @@ return 0; return security_ops->inode_permission(inode, mask); } +EXPORT_SYMBOL(security_inode_permission); int security_inode_setattr(struct dentry *dentry, struct iattr *attr) { @@ -611,6 +650,7 @@ return fsnotify_perm(file, mask); } +EXPORT_SYMBOL(security_file_permission); int security_file_alloc(struct file *file) { @@ -638,6 +678,7 @@ return ret; return ima_file_mmap(file, prot); } +EXPORT_SYMBOL(security_file_mmap); int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot) @@ -687,6 +728,16 @@ return security_ops->task_create(clone_flags); } +void security_task_free(struct task_struct *task) +{ +#if CONFIG_SECURITY_YAMA + yama_task_free(task); + if (security_ops->task_free == yama_task_free) + return; +#endif + security_ops->task_free(task); +} + int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) { return security_ops->cred_alloc_blank(cred, gfp); @@ -799,6 +850,12 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { +#if CONFIG_SECURITY_YAMA + int rc; + rc = yama_task_prctl(option, arg2, arg3, arg4, arg5); + if (rc != -ENOSYS || security_ops->task_prctl == yama_task_prctl) + return rc; +#endif return security_ops->task_prctl(option, arg2, arg3, arg4, arg5); } --- linux-2.6.37.orig/security/apparmor/Kconfig +++ linux-2.6.37/security/apparmor/Kconfig @@ -29,3 +29,12 @@ boot. If you are unsure how to answer this question, answer 1. + +config SECURITY_APPARMOR_COMPAT_24 + bool "Enable AppArmor 2.4 compatability" + depends on SECURITY_APPARMOR + default y + help + This option enables compatability with AppArmor 2.4. It is + recommended if compatability with older versions of AppArmor + is desired. --- linux-2.6.37.orig/security/apparmor/Makefile +++ linux-2.6.37/security/apparmor/Makefile @@ -4,17 +4,23 @@ apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ - resource.o sid.o file.o + resource.o sid.o file.o net.o + +apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o clean-files: capability_names.h af_names.h quiet_cmd_make-caps = GEN $@ cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ +quiet_cmd_make-af = GEN $@ +cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ + quiet_cmd_make-rlim = GEN $@ cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2] = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@ $(obj)/capability.o : $(obj)/capability_names.h +$(obj)/net.o : $(obj)/af_names.h $(obj)/resource.o : $(obj)/rlim_names.h $(obj)/capability_names.h : $(srctree)/include/linux/capability.h $(call cmd,make-caps) --- linux-2.6.37.orig/security/apparmor/apparmorfs-24.c +++ linux-2.6.37/security/apparmor/apparmorfs-24.c @@ -0,0 +1,287 @@ +/* + * AppArmor security module + * + * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions + * + * Copyright (C) 1998-2008 Novell/SUSE + * Copyright 2009-2010 Canonical Ltd. + * + * 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, version 2 of the + * License. + * + * + * This file contain functions providing an interface for <= AppArmor 2.4 + * compatibility. It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24 + * being set (see Makefile). + */ + +#include +#include +#include +#include +#include +#include + +#include "include/apparmor.h" +#include "include/audit.h" +#include "include/context.h" +#include "include/policy.h" + + +/* apparmor/matching */ +static ssize_t aa_matching_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + const char matching[] = "pattern=aadfa audit perms=crwxamlk/ " + "user::other"; + + return simple_read_from_buffer(buf, size, ppos, matching, + sizeof(matching) - 1); +} + +const struct file_operations aa_fs_matching_fops = { + .read = aa_matching_read, +}; + +/* apparmor/features */ +static ssize_t aa_features_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + const char features[] = "file=3.1 capability=2.0 network=1.0 " + "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1"; + + return simple_read_from_buffer(buf, size, ppos, features, + sizeof(features) - 1); +} + +const struct file_operations aa_fs_features_fops = { + .read = aa_features_read, +}; + +/** + * __next_namespace - find the next namespace to list + * @root: root namespace to stop search at (NOT NULL) + * @ns: current ns position (NOT NULL) + * + * Find the next namespace from @ns under @root and handle all locking needed + * while switching current namespace. + * + * Returns: next namespace or NULL if at last namespace under @root + * NOTE: will not unlock root->lock + */ +static struct aa_namespace *__next_namespace(struct aa_namespace *root, + struct aa_namespace *ns) +{ + struct aa_namespace *parent; + + /* is next namespace a child */ + if (!list_empty(&ns->sub_ns)) { + struct aa_namespace *next; + next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list); + read_lock(&next->lock); + return next; + } + + /* check if the next ns is a sibling, parent, gp, .. */ + parent = ns->parent; + while (parent) { + read_unlock(&ns->lock); + list_for_each_entry_continue(ns, &parent->sub_ns, base.list) { + read_lock(&ns->lock); + return ns; + } + if (parent == root) + return NULL; + ns = parent; + parent = parent->parent; + } + + return NULL; +} + +/** + * __first_profile - find the first profile in a namespace + * @root: namespace that is root of profiles being displayed (NOT NULL) + * @ns: namespace to start in (NOT NULL) + * + * Returns: unrefcounted profile or NULL if no profile + */ +static struct aa_profile *__first_profile(struct aa_namespace *root, + struct aa_namespace *ns) +{ + for ( ; ns; ns = __next_namespace(root, ns)) { + if (!list_empty(&ns->base.profiles)) + return list_first_entry(&ns->base.profiles, + struct aa_profile, base.list); + } + return NULL; +} + +/** + * __next_profile - step to the next profile in a profile tree + * @profile: current profile in tree (NOT NULL) + * + * Perform a depth first taversal on the profile tree in a namespace + * + * Returns: next profile or NULL if done + * Requires: profile->ns.lock to be held + */ +static struct aa_profile *__next_profile(struct aa_profile *p) +{ + struct aa_profile *parent; + struct aa_namespace *ns = p->ns; + + /* is next profile a child */ + if (!list_empty(&p->base.profiles)) + return list_first_entry(&p->base.profiles, typeof(*p), + base.list); + + /* is next profile a sibling, parent sibling, gp, subling, .. */ + parent = p->parent; + while (parent) { + list_for_each_entry_continue(p, &parent->base.profiles, + base.list) + return p; + p = parent; + parent = parent->parent; + } + + /* is next another profile in the namespace */ + list_for_each_entry_continue(p, &ns->base.profiles, base.list) + return p; + + return NULL; +} + +/** + * next_profile - step to the next profile in where ever it may be + * @root: root namespace (NOT NULL) + * @profile: current profile (NOT NULL) + * + * Returns: next profile or NULL if there isn't one + */ +static struct aa_profile *next_profile(struct aa_namespace *root, + struct aa_profile *profile) +{ + struct aa_profile *next = __next_profile(profile); + if (next) + return next; + + /* finished all profiles in namespace move to next namespace */ + return __first_profile(root, __next_namespace(root, profile->ns)); +} + +/** + * p_start - start a depth first traversal of profile tree + * @f: seq_file to fill + * @pos: current position + * + * Returns: first profile under current namespace or NULL if none found + * + * acquires first ns->lock + */ +static void *p_start(struct seq_file *f, loff_t *pos) + __acquires(root->lock) +{ + struct aa_profile *profile = NULL; + struct aa_namespace *root = aa_current_profile()->ns; + loff_t l = *pos; + f->private = aa_get_namespace(root); + + + /* find the first profile */ + read_lock(&root->lock); + profile = __first_profile(root, root); + + /* skip to position */ + for (; profile && l > 0; l--) + profile = next_profile(root, profile); + + return profile; +} + +/** + * p_next - read the next profile entry + * @f: seq_file to fill + * @p: profile previously returned + * @pos: current position + * + * Returns: next profile after @p or NULL if none + * + * may acquire/release locks in namespace tree as necessary + */ +static void *p_next(struct seq_file *f, void *p, loff_t *pos) +{ + struct aa_profile *profile = p; + struct aa_namespace *root = f->private; + (*pos)++; + + return next_profile(root, profile); +} + +/** + * p_stop - stop depth first traversal + * @f: seq_file we are filling + * @p: the last profile writen + * + * Release all locking done by p_start/p_next on namespace tree + */ +static void p_stop(struct seq_file *f, void *p) + __releases(root->lock) +{ + struct aa_profile *profile = p; + struct aa_namespace *root = f->private, *ns; + + if (profile) { + for (ns = profile->ns; ns && ns != root; ns = ns->parent) + read_unlock(&ns->lock); + } + read_unlock(&root->lock); + aa_put_namespace(root); +} + +/** + * seq_show_profile - show a profile entry + * @f: seq_file to file + * @p: current position (profile) (NOT NULL) + * + * Returns: error on failure + */ +static int seq_show_profile(struct seq_file *f, void *p) +{ + struct aa_profile *profile = (struct aa_profile *)p; + struct aa_namespace *root = f->private; + + if (profile->ns != root) + seq_printf(f, ":%s://", aa_ns_name(root, profile->ns)); + seq_printf(f, "%s (%s)\n", profile->base.hname, + COMPLAIN_MODE(profile) ? "complain" : "enforce"); + + return 0; +} + +static const struct seq_operations aa_fs_profiles_op = { + .start = p_start, + .next = p_next, + .stop = p_stop, + .show = seq_show_profile, +}; + +static int profiles_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &aa_fs_profiles_op); +} + +static int profiles_release(struct inode *inode, struct file *file) +{ + return seq_release(inode, file); +} + +const struct file_operations aa_fs_profiles_fops = { + .open = profiles_open, + .read = seq_read, + .llseek = seq_lseek, + .release = profiles_release, +}; --- linux-2.6.37.orig/security/apparmor/apparmorfs.c +++ linux-2.6.37/security/apparmor/apparmorfs.c @@ -187,7 +187,11 @@ aafs_remove(".remove"); aafs_remove(".replace"); aafs_remove(".load"); - +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24 + aafs_remove("profiles"); + aafs_remove("matching"); + aafs_remove("features"); +#endif securityfs_remove(aa_fs_dentry); aa_fs_dentry = NULL; } @@ -218,7 +222,17 @@ aa_fs_dentry = NULL; goto error; } - +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24 + error = aafs_create("matching", 0444, &aa_fs_matching_fops); + if (error) + goto error; + error = aafs_create("features", 0444, &aa_fs_features_fops); + if (error) + goto error; +#endif + error = aafs_create("profiles", 0440, &aa_fs_profiles_fops); + if (error) + goto error; error = aafs_create(".load", 0640, &aa_fs_profile_load); if (error) goto error; --- linux-2.6.37.orig/security/apparmor/lsm.c +++ linux-2.6.37/security/apparmor/lsm.c @@ -31,6 +31,7 @@ #include "include/context.h" #include "include/file.h" #include "include/ipc.h" +#include "include/net.h" #include "include/path.h" #include "include/policy.h" #include "include/procattr.h" @@ -619,6 +620,104 @@ return error; } +static int apparmor_socket_create(int family, int type, int protocol, int kern) +{ + struct aa_profile *profile; + int error = 0; + + if (kern) + return 0; + + profile = __aa_current_profile(); + if (!unconfined(profile)) + error = aa_net_perm(OP_CREATE, profile, family, type, protocol, + NULL); + return error; +} + +static int apparmor_socket_bind(struct socket *sock, + struct sockaddr *address, int addrlen) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_BIND, sk); +} + +static int apparmor_socket_connect(struct socket *sock, + struct sockaddr *address, int addrlen) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_CONNECT, sk); +} + +static int apparmor_socket_listen(struct socket *sock, int backlog) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_LISTEN, sk); +} + +static int apparmor_socket_accept(struct socket *sock, struct socket *newsock) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_ACCEPT, sk); +} + +static int apparmor_socket_sendmsg(struct socket *sock, + struct msghdr *msg, int size) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_SENDMSG, sk); +} + +static int apparmor_socket_recvmsg(struct socket *sock, + struct msghdr *msg, int size, int flags) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_RECVMSG, sk); +} + +static int apparmor_socket_getsockname(struct socket *sock) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_GETSOCKNAME, sk); +} + +static int apparmor_socket_getpeername(struct socket *sock) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_GETPEERNAME, sk); +} + +static int apparmor_socket_getsockopt(struct socket *sock, int level, + int optname) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_GETSOCKOPT, sk); +} + +static int apparmor_socket_setsockopt(struct socket *sock, int level, + int optname) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_SETSOCKOPT, sk); +} + +static int apparmor_socket_shutdown(struct socket *sock, int how) +{ + struct sock *sk = sock->sk; + + return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk); +} + static struct security_operations apparmor_ops = { .name = "apparmor", @@ -650,6 +749,19 @@ .getprocattr = apparmor_getprocattr, .setprocattr = apparmor_setprocattr, + .socket_create = apparmor_socket_create, + .socket_bind = apparmor_socket_bind, + .socket_connect = apparmor_socket_connect, + .socket_listen = apparmor_socket_listen, + .socket_accept = apparmor_socket_accept, + .socket_sendmsg = apparmor_socket_sendmsg, + .socket_recvmsg = apparmor_socket_recvmsg, + .socket_getsockname = apparmor_socket_getsockname, + .socket_getpeername = apparmor_socket_getpeername, + .socket_getsockopt = apparmor_socket_getsockopt, + .socket_setsockopt = apparmor_socket_setsockopt, + .socket_shutdown = apparmor_socket_shutdown, + .cred_alloc_blank = apparmor_cred_alloc_blank, .cred_free = apparmor_cred_free, .cred_prepare = apparmor_cred_prepare, --- linux-2.6.37.orig/security/apparmor/match.c +++ linux-2.6.37/security/apparmor/match.c @@ -57,8 +57,17 @@ if (bsize < tsize) goto out; + /* Pad table allocation for next/check by 256 entries to remain + * backwards compatible with old (buggy) tools and remain safe without + * run time checks + */ + if (th.td_id == YYTD_ID_NXT || th.td_id == YYTD_ID_CHK) + tsize += 256 * th.td_flags; + table = kvmalloc(tsize); if (table) { + /* ensure the pad is clear, else there will be errors */ + memset(table, 0, tsize); *table = th; if (th.td_flags == YYTD_DATA8) UNPACK_ARRAY(table->td_data, blob, th.td_lolen, @@ -134,11 +143,19 @@ goto out; if (flags & DFA_FLAG_VERIFY_STATES) { + int warning = 0; for (i = 0; i < state_count; i++) { if (DEFAULT_TABLE(dfa)[i] >= state_count) goto out; /* TODO: do check that DEF state recursion terminates */ if (BASE_TABLE(dfa)[i] + 255 >= trans_count) { + if (warning) + continue; + printk(KERN_WARNING "AppArmor DFA next/check " + "upper bounds error fixed, upgrade " + "user space tools \n"); + warning = 1; + } else if (BASE_TABLE(dfa)[i] >= trans_count) { printk(KERN_ERR "AppArmor DFA next/check upper " "bounds error\n"); goto out; --- linux-2.6.37.orig/security/apparmor/net.c +++ linux-2.6.37/security/apparmor/net.c @@ -0,0 +1,170 @@ +/* + * AppArmor security module + * + * This file contains AppArmor network mediation + * + * Copyright (C) 1998-2008 Novell/SUSE + * Copyright 2009-2010 Canonical Ltd. + * + * 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, version 2 of the + * License. + */ + +#include "include/apparmor.h" +#include "include/audit.h" +#include "include/context.h" +#include "include/net.h" +#include "include/policy.h" + +#include "af_names.h" + +static const char *sock_type_names[] = { + "unknown(0)", + "stream", + "dgram", + "raw", + "rdm", + "seqpacket", + "dccp", + "unknown(7)", + "unknown(8)", + "unknown(9)", + "packet", +}; + +/* audit callback for net specific fields */ +static void audit_cb(struct audit_buffer *ab, void *va) +{ + struct common_audit_data *sa = va; + + audit_log_format(ab, " family="); + if (address_family_names[sa->u.net.family]) { + audit_log_string(ab, address_family_names[sa->u.net.family]); + } else { + audit_log_format(ab, " \"unknown(%d)\"", sa->u.net.family); + } + + audit_log_format(ab, " sock_type="); + if (sock_type_names[sa->aad.net.type]) { + audit_log_string(ab, sock_type_names[sa->aad.net.type]); + } else { + audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type); + } + + audit_log_format(ab, " protocol=%d", sa->aad.net.protocol); +} + +/** + * audit_net - audit network access + * @profile: profile being enforced (NOT NULL) + * @op: operation being checked + * @family: network family + * @type: network type + * @protocol: network protocol + * @sk: socket auditing is being applied to + * @error: error code for failure else 0 + * + * Returns: %0 or sa->error else other errorcode on failure + */ +static int audit_net(struct aa_profile *profile, int op, u16 family, int type, + int protocol, struct sock *sk, int error) +{ + int audit_type = AUDIT_APPARMOR_AUTO; + struct common_audit_data sa; + if (sk) { + COMMON_AUDIT_DATA_INIT(&sa, NET); + } else { + COMMON_AUDIT_DATA_INIT(&sa, NONE); + } + /* todo fill in socket addr info */ + + sa.aad.op = op, + sa.u.net.family = family; + sa.u.net.sk = sk; + sa.aad.net.type = type; + sa.aad.net.protocol = protocol; + sa.aad.error = error; + + if (likely(!sa.aad.error)) { + u16 audit_mask = profile->net.audit[sa.u.net.family]; + if (likely((AUDIT_MODE(profile) != AUDIT_ALL) && + !(1 << sa.aad.net.type & audit_mask))) + return 0; + audit_type = AUDIT_APPARMOR_AUDIT; + } else { + u16 quiet_mask = profile->net.quiet[sa.u.net.family]; + u16 kill_mask = 0; + u16 denied = (1 << sa.aad.net.type) & ~quiet_mask; + + if (denied & kill_mask) + audit_type = AUDIT_APPARMOR_KILL; + + if ((denied & quiet_mask) && + AUDIT_MODE(profile) != AUDIT_NOQUIET && + AUDIT_MODE(profile) != AUDIT_ALL) + return COMPLAIN_MODE(profile) ? 0 : sa.aad.error; + } + + return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb); +} + +/** + * aa_net_perm - very course network access check + * @op: operation being checked + * @profile: profile being enforced (NOT NULL) + * @family: network family + * @type: network type + * @protocol: network protocol + * + * Returns: %0 else error if permission denied + */ +int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type, + int protocol, struct sock *sk) +{ + u16 family_mask; + int error; + + if ((family < 0) || (family >= AF_MAX)) + return -EINVAL; + + if ((type < 0) || (type >= SOCK_MAX)) + return -EINVAL; + + /* unix domain and netlink sockets are handled by ipc */ + if (family == AF_UNIX || family == AF_NETLINK) + return 0; + + family_mask = profile->net.allow[family]; + + error = (family_mask & (1 << type)) ? 0 : -EACCES; + + return audit_net(profile, op, family, type, protocol, sk, error); +} + +/** + * aa_revalidate_sk - Revalidate access to a sock + * @op: operation being checked + * @sk: sock being revalidated (NOT NULL) + * + * Returns: %0 else error if permission denied + */ +int aa_revalidate_sk(int op, struct sock *sk) +{ + struct aa_profile *profile; + int error = 0; + + /* aa_revalidate_sk should not be called from interrupt context + * don't mediate these calls as they are not task related + */ + if (in_interrupt()) + return 0; + + profile = __aa_current_profile(); + if (!unconfined(profile)) + error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type, + sk->sk_protocol, sk); + + return error; +} --- linux-2.6.37.orig/security/apparmor/policy.c +++ linux-2.6.37/security/apparmor/policy.c @@ -745,6 +745,7 @@ aa_free_file_rules(&profile->file); aa_free_cap_rules(&profile->caps); + aa_free_net_rules(&profile->net); aa_free_rlimit_rules(&profile->rlimits); aa_free_sid(profile->sid); --- linux-2.6.37.orig/security/apparmor/policy_unpack.c +++ linux-2.6.37/security/apparmor/policy_unpack.c @@ -190,6 +190,19 @@ return 0; } +static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name) +{ + if (unpack_nameX(e, AA_U16, name)) { + if (!inbounds(e, sizeof(u16))) + return 0; + if (data) + *data = le16_to_cpu(get_unaligned((u16 *) e->pos)); + e->pos += sizeof(u16); + return 1; + } + return 0; +} + static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) { if (unpack_nameX(e, AA_U32, name)) { @@ -468,7 +481,8 @@ { struct aa_profile *profile = NULL; const char *name = NULL; - int error = -EPROTO; + size_t size = 0; + int i, error = -EPROTO; kernel_cap_t tmpcap; u32 tmp; @@ -559,6 +573,38 @@ if (!unpack_rlimits(e, profile)) goto fail; + size = unpack_array(e, "net_allowed_af"); + if (size) { + + for (i = 0; i < size; i++) { + /* discard extraneous rules that this kernel will + * never request + */ + if (i >= AF_MAX) { + u16 tmp; + if (!unpack_u16(e, &tmp, NULL) || + !unpack_u16(e, &tmp, NULL) || + !unpack_u16(e, &tmp, NULL)) + goto fail; + continue; + } + if (!unpack_u16(e, &profile->net.allow[i], NULL)) + goto fail; + if (!unpack_u16(e, &profile->net.audit[i], NULL)) + goto fail; + if (!unpack_u16(e, &profile->net.quiet[i], NULL)) + goto fail; + } + if (!unpack_nameX(e, AA_ARRAYEND, NULL)) + goto fail; + /* + * allow unix domain and netlink sockets they are handled + * by IPC + */ + } + profile->net.allow[AF_UNIX] = 0xffff; + profile->net.allow[AF_NETLINK] = 0xffff; + /* get file rules */ profile->file.dfa = unpack_dfa(e); if (IS_ERR(profile->file.dfa)) { --- linux-2.6.37.orig/security/apparmor/include/apparmorfs.h +++ linux-2.6.37/security/apparmor/include/apparmorfs.h @@ -17,4 +17,10 @@ extern void __init aa_destroy_aafs(void); +#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24 +extern const struct file_operations aa_fs_matching_fops; +extern const struct file_operations aa_fs_features_fops; +extern const struct file_operations aa_fs_profiles_fops; +#endif + #endif /* __AA_APPARMORFS_H */ --- linux-2.6.37.orig/security/apparmor/include/net.h +++ linux-2.6.37/security/apparmor/include/net.h @@ -0,0 +1,40 @@ +/* + * AppArmor security module + * + * This file contains AppArmor network mediation definitions. + * + * Copyright (C) 1998-2008 Novell/SUSE + * Copyright 2009-2010 Canonical Ltd. + * + * 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, version 2 of the + * License. + */ + +#ifndef __AA_NET_H +#define __AA_NET_H + +#include + +/* struct aa_net - network confinement data + * @allowed: basic network families permissions + * @audit_network: which network permissions to force audit + * @quiet_network: which network permissions to quiet rejects + */ +struct aa_net { + u16 allow[AF_MAX]; + u16 audit[AF_MAX]; + u16 quiet[AF_MAX]; +}; + +extern int aa_net_perm(int op, struct aa_profile *profile, u16 family, + int type, int protocol, struct sock *sk); +extern int aa_revalidate_sk(int op, struct sock *sk); + +static inline void aa_free_net_rules(struct aa_net *new) +{ + /* NOP */ +} + +#endif /* __AA_NET_H */ --- linux-2.6.37.orig/security/apparmor/include/policy.h +++ linux-2.6.37/security/apparmor/include/policy.h @@ -27,6 +27,7 @@ #include "capability.h" #include "domain.h" #include "file.h" +#include "net.h" #include "resource.h" extern const char *profile_mode_names[]; @@ -145,6 +146,7 @@ * @size: the memory consumed by this profiles rules * @file: The set of rules governing basic file access and domain transitions * @caps: capabilities for the profile + * @net: network controls for the profile * @rlimits: rlimits for the profile * * The AppArmor profile contains the basic confinement data. Each profile @@ -181,6 +183,7 @@ struct aa_file_rules file; struct aa_caps caps; + struct aa_net net; struct aa_rlimit rlimits; }; --- linux-2.6.37.orig/security/yama/Kconfig +++ linux-2.6.37/security/yama/Kconfig @@ -0,0 +1,13 @@ +config SECURITY_YAMA + bool "Yama NAC Support" + depends on SECURITY + select SECURITYFS + select SECURITY_PATH + default n + help + This selects Yama, the NAKed Access Control system which + provides additional global security settings above regular + Linux discretionary access controls. Currently available + are symlink, hardlink, and PTRACE scope restrictions. + + If you are unsure how to answer this question, answer N. --- linux-2.6.37.orig/security/yama/Makefile +++ linux-2.6.37/security/yama/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_SECURITY_YAMA) := yama.o + +yama-y := yama_lsm.o --- linux-2.6.37.orig/security/yama/yama_lsm.c +++ linux-2.6.37/security/yama/yama_lsm.c @@ -0,0 +1,433 @@ +/* + * Yama Linux Security Module + * + * Author: Kees Cook + * + * Copyright (C) 2010 Canonical, Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +static int ptrace_scope = 1; +static int protected_sticky_symlinks = 1; +static int protected_nonaccess_hardlinks = 1; + +/* describe a PTRACE relationship for potential exception */ +struct ptrace_relation { + struct task_struct *tracer; + struct task_struct *tracee; + struct list_head node; +}; + +static LIST_HEAD(ptracer_relations); +static DEFINE_SPINLOCK(ptracer_relations_lock); + +/** + * yama_ptracer_add - add/replace an exception for this tracer/tracee pair + * @tracer: the task_struct of the process doing the PTRACE + * @tracee: the task_struct of the process to be PTRACEd + * + * Returns 0 if relationship was added, -ve on error. + */ +static int yama_ptracer_add(struct task_struct *tracer, + struct task_struct *tracee) +{ + int rc = 0; + struct ptrace_relation *added; + struct ptrace_relation *entry, *relation = NULL; + + added = kmalloc(sizeof(*added), GFP_KERNEL); + spin_lock(&ptracer_relations_lock); + list_for_each_entry(entry, &ptracer_relations, node) + if (entry->tracee == tracee) { + relation = entry; + break; + } + if (!relation) { + relation = added; + if (!relation) { + rc = -ENOMEM; + goto unlock_out; + } + relation->tracee = tracee; + list_add(&relation->node, &ptracer_relations); + } + relation->tracer = tracer; + +unlock_out: + spin_unlock(&ptracer_relations_lock); + if (added && added != relation) + kfree(added); + + return rc; +} + +/** + * yama_ptracer_del - remove exceptions related to the given tasks + * @tracer: remove any relation where tracer task matches + * @tracee: remove any relation where tracee task matches + */ +static void yama_ptracer_del(struct task_struct *tracer, + struct task_struct *tracee) +{ + struct ptrace_relation *relation; + struct list_head *list, *safe; + + spin_lock(&ptracer_relations_lock); + list_for_each_safe(list, safe, &ptracer_relations) { + relation = list_entry(list, struct ptrace_relation, node); + if (relation->tracee == tracee || + relation->tracer == tracer) { + list_del(&relation->node); + kfree(relation); + } + } + spin_unlock(&ptracer_relations_lock); +} + +/** + * yama_task_free - check for task_pid to remove from exception list + * @task: task being removed + */ +void yama_task_free(struct task_struct *task) +{ + yama_ptracer_del(task, task); +} + +/** + * yama_task_prctl - check for Yama-specific prctl operations + * @option: operation + * @arg2: argument + * @arg3: argument + * @arg4: argument + * @arg5: argument + * + * Return 0 on success, -ve on error. -ENOSYS is returned when Yama + * does not handle the given option. + */ +int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3, + unsigned long arg4, unsigned long arg5) +{ + int rc; + + rc = cap_task_prctl(option, arg2, arg3, arg4, arg5); + if (rc != -ENOSYS) + return rc; + + switch (option) { + case PR_SET_PTRACER: + if (arg2 == 0) { + yama_ptracer_del(NULL, current); + rc = 0; + } + else { + struct task_struct *tracer; + + rcu_read_lock(); + tracer = find_task_by_vpid(arg2); + if (tracer) + get_task_struct(tracer); + else + rc = -EINVAL; + rcu_read_unlock(); + + if (tracer) { + rc = yama_ptracer_add(tracer, current); + put_task_struct(tracer); + } + } + break; + } + + return rc; +} + +/** + * task_is_descendant - walk up a process family tree looking for a match + * @parent: the process to compare against while walking up from child + * @child: the process to start from while looking upwards for parent + * + * Returns 1 if child is a descendant of parent, 0 if not. + */ +static int task_is_descendant(struct task_struct *parent, + struct task_struct *child) +{ + int rc = 0; + struct task_struct *walker = child; + + if (!parent || !child) + return 0; + + rcu_read_lock(); + read_lock(&tasklist_lock); + while (walker->pid > 0) { + if (!thread_group_leader(walker)) + walker = walker->group_leader; + if (walker == parent) { + rc = 1; + break; + } + walker = walker->real_parent; + } + read_unlock(&tasklist_lock); + rcu_read_unlock(); + + return rc; +} + +/** + * ptracer_exception_found - tracer registered as exception for this tracee + * @tracer: the task_struct of the process attempting PTRACE + * @tracee: the task_struct of the process to be PTRACEd + * + * Returns 1 if tracer has is ptracer exception ancestor for tracee. + */ +static int ptracer_exception_found(struct task_struct *tracer, + struct task_struct *tracee) +{ + int rc = 0; + struct ptrace_relation *relation; + struct task_struct *parent = NULL; + + spin_lock(&ptracer_relations_lock); + + rcu_read_lock(); + read_lock(&tasklist_lock); + if (!thread_group_leader(tracee)) + tracee = tracee->group_leader; + list_for_each_entry(relation, &ptracer_relations, node) + if (relation->tracee == tracee) { + parent = relation->tracer; + break; + } + read_unlock(&tasklist_lock); + rcu_read_unlock(); + + if (task_is_descendant(parent, tracer)) + rc = 1; + spin_unlock(&ptracer_relations_lock); + + return rc; +} + +/** + * yama_ptrace_access_check - validate PTRACE_ATTACH calls + * @child: task that current task is attempting to PTRACE + * @mode: ptrace attach mode + * + * Returns 0 if following the ptrace is allowed, -ve on error. + */ +int yama_ptrace_access_check(struct task_struct *child, + unsigned int mode) +{ + int rc; + + /* If standard caps disallows it, so does Yama. We should + * only tighten restrictions further. + */ + rc = cap_ptrace_access_check(child, mode); + if (rc) + return rc; + + /* require ptrace target be a child of ptracer on attach */ + if (mode == PTRACE_MODE_ATTACH && + ptrace_scope && + !capable(CAP_SYS_PTRACE) && + !task_is_descendant(current, child) && + !ptracer_exception_found(current, child)) + rc = -EPERM; + + if (rc) { + char name[sizeof(current->comm)]; + printk_ratelimited(KERN_INFO "ptrace of non-child" + " pid %d was attempted by: %s (pid %d)\n", + child->pid, + get_task_comm(name, current), + current->pid); + } + + return rc; +} + +/** + * yama_inode_follow_link - check for symlinks in sticky world-writeable dirs + * @dentry: The inode/dentry of the symlink + * @nameidata: The path data of the symlink + * + * In the case of the protected_sticky_symlinks sysctl being enabled, + * CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is + * in a sticky world-writable directory. This is to protect privileged + * processes from failing races against path names that may change out + * from under them by way of other users creating malicious symlinks. + * It will permit symlinks to only be followed when outside a sticky + * world-writable directory, or when the uid of the symlink and follower + * match, or when the directory owner matches the symlink's owner. + * + * Returns 0 if following the symlink is allowed, -ve on error. + */ +int yama_inode_follow_link(struct dentry *dentry, + struct nameidata *nameidata) +{ + int rc = 0; + const struct inode *parent; + const struct inode *inode; + const struct cred *cred; + + if (!protected_sticky_symlinks) + return 0; + + /* if inode isn't a symlink, don't try to evaluate blocking it */ + inode = dentry->d_inode; + if (!S_ISLNK(inode->i_mode)) + return 0; + + /* owner and follower match? */ + cred = current_cred(); + if (cred->fsuid == inode->i_uid) + return 0; + + /* check parent directory mode and owner */ + spin_lock(&dentry->d_lock); + parent = dentry->d_parent->d_inode; + if ((parent->i_mode & (S_ISVTX|S_IWOTH)) == (S_ISVTX|S_IWOTH) && + parent->i_uid != inode->i_uid) { + rc = -EACCES; + } + spin_unlock(&dentry->d_lock); + + if (rc) { + char name[sizeof(current->comm)]; + printk_ratelimited(KERN_NOTICE "non-matching-uid symlink " + "following attempted in sticky world-writable " + "directory by %s (fsuid %d != %d)\n", + get_task_comm(name, current), + cred->fsuid, inode->i_uid); + } + + return rc; +} + +/** + * yama_path_link - verify that hardlinking is allowed + * @old_dentry: the source inode/dentry to hardlink from + * @new_dir: target directory + * @new_dentry: the target inode/dentry to hardlink to + * + * Block hardlink when all of: + * - fsuid does not match inode + * - not CAP_FOWNER + * - and at least one of: + * - inode is not a regular file + * - inode is setuid + * - inode is setgid and group-exec + * - access failure for read and write + * + * Returns 0 if successful, -ve on error. + */ +int yama_path_link(struct dentry *old_dentry, struct path *new_dir, + struct dentry *new_dentry) +{ + int rc = 0; + struct inode *inode = old_dentry->d_inode; + const int mode = inode->i_mode; + const struct cred *cred = current_cred(); + + if (!protected_nonaccess_hardlinks) + return 0; + + if (cred->fsuid != inode->i_uid && + (!S_ISREG(mode) || (mode & S_ISUID) || + ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) || + (generic_permission(inode, MAY_READ | MAY_WRITE, NULL))) && + !capable(CAP_FOWNER)) { + char name[sizeof(current->comm)]; + printk_ratelimited(KERN_INFO "non-accessible hardlink" + " creation was attempted by: %s (fsuid %d)\n", + get_task_comm(name, current), + cred->fsuid); + rc = -EPERM; + } + + return rc; +} + +static struct security_operations yama_ops = { + .name = "yama", + + .ptrace_access_check = yama_ptrace_access_check, + .inode_follow_link = yama_inode_follow_link, + .path_link = yama_path_link, + .task_prctl = yama_task_prctl, + .task_free = yama_task_free, +}; + +#ifdef CONFIG_SYSCTL +static int zero; +static int one = 1; + +struct ctl_path yama_sysctl_path[] = { + { .procname = "kernel", }, + { .procname = "yama", }, + { } +}; + +static struct ctl_table yama_sysctl_table[] = { + { + .procname = "protected_sticky_symlinks", + .data = &protected_sticky_symlinks, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, + { + .procname = "protected_nonaccess_hardlinks", + .data = &protected_nonaccess_hardlinks, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, + { + .procname = "ptrace_scope", + .data = &ptrace_scope, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, + { } +}; +#endif /* CONFIG_SYSCTL */ + +static __init int yama_init(void) +{ + printk(KERN_INFO "Yama: becoming mindful.\n"); + +#ifdef CONFIG_SYSCTL + if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table)) + panic("Yama: sysctl registration failed.\n"); +#endif + + if (!security_module_enable(&yama_ops)) + return 0; + + if (register_security(&yama_ops)) + panic("Yama: kernel registration failed.\n"); + + return 0; +} + +security_initcall(yama_init); --- linux-2.6.37.orig/sound/oss/ad1848.c +++ linux-2.6.37/sound/oss/ad1848.c @@ -458,7 +458,7 @@ return mask; } -static void change_bits(ad1848_info * devc, unsigned char *regval, +static void __change_bits(ad1848_info * devc, unsigned char *regval, unsigned char *muteval, int dev, int chn, int newval) { unsigned char mask; @@ -516,10 +516,10 @@ if (muteregoffs != regoffs) { muteval = ad_read(devc, muteregoffs); - change_bits(devc, &val, &muteval, dev, channel, value); + __change_bits(devc, &val, &muteval, dev, channel, value); } else - change_bits(devc, &val, &val, dev, channel, value); + __change_bits(devc, &val, &val, dev, channel, value); spin_lock_irqsave(&devc->lock,flags); ad_write(devc, regoffs, val); --- linux-2.6.37.orig/sound/oss/sb_mixer.c +++ linux-2.6.37/sound/oss/sb_mixer.c @@ -232,7 +232,7 @@ return 1; } -static void change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval) +static void __change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval) { unsigned char mask; int shift; @@ -284,7 +284,7 @@ return -EINVAL; val = sb_getmixer(devc, regoffs); - change_bits(devc, &val, dev, LEFT_CHN, left); + __change_bits(devc, &val, dev, LEFT_CHN, left); if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs) /* * Change register @@ -304,7 +304,7 @@ * Read the new one */ } - change_bits(devc, &val, dev, RIGHT_CHN, right); + __change_bits(devc, &val, dev, RIGHT_CHN, right); sb_setmixer(devc, regoffs, val); --- linux-2.6.37.orig/sound/pci/hda/hda_intel.c +++ linux-2.6.37/sound/pci/hda/hda_intel.c @@ -2018,6 +2018,7 @@ struct azx_pcm *apcm; int pcm_dev = cpcm->device; int s, err; + size_t prealloc_min = 64*1024; /* 64KB */ if (pcm_dev >= HDA_MAX_PCMS) { snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n", @@ -2051,10 +2052,21 @@ if (cpcm->stream[s].substreams) snd_pcm_set_ops(pcm, s, &azx_pcm_ops); } + /* buffer pre-allocation */ + + /* subtle, don't allocate a big buffer for modems... + * also, don't just test 32BIT_MASK, since azx supports + * 64-bit DMA in some cases. + */ + /* lennart wants a 2.2MB buffer for 2sec of 48khz */ + if (pcm->dev_class == SNDRV_PCM_CLASS_GENERIC && + chip->pci->dma_mask >= DMA_32BIT_MASK) + prealloc_min = 4 * 1024 * 1024; /* 4MB */ + snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(chip->pci), - 1024 * 64, 32 * 1024 * 1024); + prealloc_min, 32 * 1024 * 1024); return 0; } --- linux-2.6.37.orig/sound/pci/hda/patch_conexant.c +++ linux-2.6.37/sound/pci/hda/patch_conexant.c @@ -3111,6 +3111,7 @@ SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), + SND_PCI_QUIRK(0x17aa, 0x21c8, "Thinkpad Edge 11", CXT5066_THINKPAD), SND_PCI_QUIRK(0x17aa, 0x21b4, "Thinkpad Edge", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x21c8, "Thinkpad Edge 11", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD), --- linux-2.6.37.orig/debian.master/NOTES +++ linux-2.6.37/debian.master/NOTES @@ -0,0 +1,4 @@ +eSCO patch removed. Replaced upstream with a disable_esco module parm. +airprime: Module gone, use option driver instead +AppArmor: Patch is all there and ported. Ooops when enabled, so default + off (still can be enabled apparmor=1) --- linux-2.6.37.orig/debian.master/copyright +++ linux-2.6.37/debian.master/copyright @@ -0,0 +1,29 @@ +This is the Ubuntu prepackaged version of the Linux kernel. +Linux was written by Linus Torvalds +and others. + +This package was put together by the Ubuntu Kernel Team, from +sources retrieved from upstream linux git. +The sources may be found at most Linux ftp sites, including +ftp://ftp.kernel.org/pub/linux/kernel/ + +This package is currently maintained by the +Ubuntu Kernel Team + +Linux is copyrighted by Linus Torvalds and others. + + 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; version 2 dated June, 1991. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Ubuntu Linux systems, the complete text of the GNU General +Public License v2 can be found in `/usr/share/common-licenses/GPL-2'. --- linux-2.6.37.orig/debian.master/control.stub.in +++ linux-2.6.37/debian.master/control.stub.in @@ -0,0 +1,21 @@ +Source: linux +Section: devel +Priority: optional +Maintainer: Ubuntu Kernel Team +Standards-Version: 3.8.4.0 +Build-Depends: debhelper (>= 5), cpio, module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [amd64 i386], device-tree-compiler [powerpc], libelf-dev, binutils-dev, rsync, libdw-dev +Build-Depends-Indep: bzip2, sharutils +Build-Conflicts: findutils (= 4.4.1-1ubuntu1) +Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-maverick.git + +Package: linux-headers-PKGVER-ABINUM +Architecture: all +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0) +Provides: SRCPKGNAME-headers, SRCPKGNAME-headers-2.6 +Description: Header files related to Linux kernel version PKGVER + This package provides kernel header files for version PKGVER, for sites + that want the latest kernel headers. Please read + /usr/share/doc/SRCPKGNAME-headers-PKGVER-ABINUM/debian.README.gz for details + --- linux-2.6.37.orig/debian.master/changelog +++ linux-2.6.37/debian.master/changelog @@ -0,0 +1,4962 @@ +linux (2.6.37-graphics2+12.26~lucid) lucid; urgency=low + + * Final 2.6.37 + * Merge git://git.kernel.org/pub/scm/linux/kernel/git/ickle/drm-intel.git drm-intel-next + - Up to 7fd1179aa58aeb239bddb669ddfe1326497e7012 + * Apply patch at https://bugs.freedesktop.org/show_bug.cgi?id=27187#c291 + - Poke HIC bit + wbinv + cache coherency checker + + -- Brian Rogers Wed, 05 Jan 2011 08:55:32 -0800 + +linux (2.6.37-12.26) natty; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.37-rc8 + * [Config] armel -- reenable omap flavour + * [Config] disable CONFIG_MACH_OMAP3517EVM to fix FTBS on armel omap + * [Config] disable CONFIG_GPIO_VX855 to fix FTBS on omap armel + * [Config] disable CONFIG_WESTBRIDGE_ASTORIA to fix FTBS on omap armel + * [Config] disable CONFIG_TI_DAVINCI_EMAC to fix FTBS on omap armel + * rebase to mainline 989d873fc5b6a96695b97738dea8d9f02a60f8ab + * [Config] track missing modules + * rebase to v2.6.37 final + + [ Chase Douglas ] + + * SAUCE: (drop after 2.6.37) HID: magicmouse: Don't report REL_{X, Y} for + Magic Trackpad + + [ Stefan Bader ] + + * Revert "SAUCE: blkfront: default to sd devices" + - LP: #684875 + + [ Tim Gardner ] + + * Revert "SAUCE: (no-up) libata: Ignore HPA by default." + - LP: #380138 + * [Config] Added autofs4.ko to -virtual flavour + - LP: #692917 + + [ Upstream Kernel Changes ] + + * Add support for Intellimouse Mode in ALPS touchpad on Dell E2 series + Laptops + - LP: #632884 + + [ Upstream Kernel Changes ] + + * rebase to v2.6.37-rc8 + * rebase to mainline 989d873fc5b6a96695b97738dea8d9f02a60f8ab + * rebase to v2.6.37 final + + -- Andy Whitcroft Thu, 23 Dec 2010 18:34:13 +0000 + +linux (2.6.37-11.25) natty; urgency=low + + [ Andy Whitcroft ] + + * [Config] d-i -- add hpsa to the list of block devices + - LP: #684304 + * [Config] add vmw-balloon driver to -virtual flavour + - LP: #592039 + * rebase to v2.6.37-rc7 + + [ Upstream Kernel Changes ] + + * rebase to v2.6.37-rc7 + + -- Andy Whitcroft Tue, 21 Dec 2010 13:35:28 +0000 + +linux (2.6.37-10.24) natty; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.37-rc6 + * updateconfigs following rebase to v2.6.37-rc6 + + [ Upstream Kernel Changes ] + + * rebase to v2.6.37-rc6 + + -- Andy Whitcroft Thu, 16 Dec 2010 12:34:19 +0000 + +linux (2.6.37-9.23) natty; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: vt -- fix handoff numbering to 1..n and add range checks + - LP: #689606 + * SAUCE: vt -- fix handoff numbering to 1..n and add range checks (grub) + - LP: #689606 + + [ Kees Cook ] + + * SAUCE: RO/NX protection for loadable kernel, fix ftrace + - LP: #690190 + + -- Andy Whitcroft Wed, 15 Dec 2010 19:29:57 +0000 + +linux (2.6.37-9.22) natty; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.35-rc5 + * [Config] updateconfigs following rebase to v2.6.37-rc5 + * (no-up) add support for installed header files to ubuntu directory + - LP: #684666 + * ubuntu: AUFS -- include the aufs_types.h file in linux-libc-headers + - LP: #684666 + * ubuntu: dm-raid4-5 -- follow changes to bio flags + * ubuntu: dm-raid4-5 -- re-enable + * ubuntu: omnibook -- update BOM + * ubuntu: ndiswrapper -- update BOM to match actual version + * ubuntu: ndiswrapper -- follow removal of the BKL and locked ioctl + * ubuntu: ndiswrapper -- re-enable + * ubuntu: iscsitarget -- re-instate copy_io_context + * ubuntu: iscsitarget -- follow changes to semaphore initialisation + * ubuntu: iscsitarget -- convert NIPQUAD to %pI4 + * ubuntu: iscsitarget -- re-enable + + [ Kees Cook ] + + * [Config] update config for CONFIG_DEBUG_SET_MODULE_RONX + + [ Manoj Iyer ] + + * SAUCE: Enable jack sense for Thinkpad Edge 13 + - LP: #685015 + + [ Tim Gardner ] + + * [Config] CONFIG_9P_FSCACHE=y,CONFIG_9P_FS_POSIX_ACL=y + * [Config] CONFIG_CRYPTO_CRC32C=y + - LP: #681819 + * [Config] CONFIG_9P_FSCACHE=n + * [Config] Add nfsd modules to -virtual flavour + - LP: #688070 + + [ Upstream Kernel Changes ] + + * Revert "Staging: zram: work around oops due to startup ordering snafu" + * NFS: Fix panic after nfs_umount() + - LP: #683938 + * x86: Add NX protection for kernel data + * x86: Add RO/NX protection for loadable kernel modules + * x86: Resume trampoline must be executable + * x86: RO/NX protection for loadable kernel, jump_table fix + + [ Upstream Kernel Changes ] + + * rebase to v2.6.37-rc5 + + -- Andy Whitcroft Thu, 09 Dec 2010 18:15:35 +0000 + +linux (2.6.37-8.21) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "ubuntu: AUFS -- include the aufs_types.h file in + linux-libc-headers" + * Revert "(no-up) add support for installed header files to ubuntu + directory" + + -- Andy Whitcroft Sun, 05 Dec 2010 17:33:28 +0000 + +linux (2.6.37-8.20) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Upstream] drivers/serial/mfd.c: Fix ARM compile error" + * Revert "SAUCE: Nouveau: Disable acceleration on MacBook Pros" + * Revert "SAUCE: Nouveau: Add quirk framework to disable acceleration" + * Revert "SAUCE: i915 -- disable powersave by default" + * SAUCE: enable Marvell 9128 PCIe SATA controller + - LP: #658521 + * [Config] evtchn has been renamed + * (no-up) add support for installed header files to ubuntu directory + - LP: #684666 + * ubuntu: AUFS -- include the aufs_types.h file in linux-libc-headers + - LP: #684666 + + [ Tim Gardner ] + + * [Config] MISS: evtchn, NEW : xen-evtchn + * rebase to v2.6.37-rc4 + + [ Upstream Kernel Changes ] + + * drm/i915: Clean conflicting modesetting registers upon init + - LP: #683775 + * rebase to v2.6.37-rc4 + + -- Andy Whitcroft Fri, 03 Dec 2010 18:42:07 +0000 + +linux (2.6.37-7.19) natty; urgency=low + + [ Tim Gardner ] + + * [Config] Add bnx2 firmware to nic-modules udeb + - LP: #676245 + + -- Andy Whitcroft Fri, 26 Nov 2010 17:53:45 +0000 + +linux (2.6.37-7.18) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Upstream] USB: option: Remove duplicate AMOI_VENDOR_ID" + * Revert "SAUCE: Add extra headers to linux-libc-dev" + * Revert "SAUCE: Enable speedstep for sonoma processors." + * [Config] enable CONFIG_BT_HCIUART_ATH3K + * [Config] enable CONFIG_IWLWIFI_DEBUGFS + * [Config] standardise CONFIG_MII + * [Config] standardise CONFIG_PRISM2_USB + * [Config] standardise CONFIG_SCSI_QLA_ISCSI + * [Config] build in CONFIG_AGP + * [Config] build in CONFIG_AGP_INTEL + * [Config] build in CONFIG_AGP_AMD + * [Config] build in CONFIG_AGP_AMD64 + * [Config] build in CONFIG_AGP_NVIDIA + * [Config] build in CONFIG_AGP_VIA + * [Config] disable CONFIG_SCSI_QLA_ISCSI for FTBS (arm) + * (no-up): document the new ## scheme + * [Config] harmonise CONFIG_SERIAL_8250_NR_UARTS + * [Config] update CONFIG_SERIAL_8250_RUNTIME_UARTS=32 + - LP: #675453 + + [ Mathieu J. Poirier ] + + * SAUCE: ARM: Adding vdd_sdi regulator supply to OMAP3EVM + + [ Upstream Kernel Changes ] + + * nx-emu: fix inverted report of disable_nx + + -- Andy Whitcroft Tue, 23 Nov 2010 21:00:39 +0000 + +linux (2.6.37-6.17) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "ubuntu: AUFS -- aufs2-standalone.patch + aufs2.1-36-UNRELEASED-20101103" + * Revert "ubuntu: AUFS -- aufs2-base.patch + aufs2.1-36-UNRELEASED-20101103" + * [Config] standardise CONFIG_BT + * [Config] standardise CONFIG_IRDA + * [Config] standardise CONFIG_LAPB + * [Config] standardise CONFIG_RDS + * [Config] standardise CONFIG_RFKILL + * [Config] standardise CONFIG_TIPC + * [Config] standardise CONFIG_X25 + * [Config] standardise CONFIG_INPUT_EVDEV + * [Config] standardise CONFIG_INPUT_JOYDEV + * [Config] standardise CONFIG_INPUT_JOYSTICK + * [Config] standardise CONFIG_INPUT_TOUCHSCREEN + * [Config] CONFIG_INPUT_TOUCHSCREEN=n for FTBS (arm) + * [Config] CONFIG_IRDA=n for FTBS (arm) + * ubuntu: AUFS -- aufs2-base.patch aufs2.1-37 + * ubuntu: AUFS -- aufs2-standalone.patch aufs2.1-37 + * ubuntu: AUFS -- update to 097bf62d6f49619359d34bf17f242df38562489a + + [ Tim Gardner ] + + * SAUCE: Fix drivers/staging/easycap FTBS + * [Config] CONFIG_EASYCAP=m after fixing FTBS + + [ Upstream Kernel Changes ] + + * Revert "x86: Add NX protection for kernel data" + + -- Andy Whitcroft Mon, 22 Nov 2010 18:09:10 +0000 + +linux (2.6.37-6.16) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Config] update config for CONFIG_DEBUG_SET_MODULE_RONX" + * rebase to v2.6.37-rc3 + + [ Tim Gardner ] + + * [Config] CONFIG_SCHED_AUTOGROUP=y + + [ Upstream Kernel Changes ] + + * Revert "x86: Add RO/NX protection for loadable kernel modules" + * sched: automated per session task groups + * rebase to v2.6.37-rc3 + + -- Andy Whitcroft Mon, 22 Nov 2010 10:11:13 +0000 + +linux (2.6.37-6.15) natty; urgency=low + + [ Andy Whitcroft ] + + * [Config] standardise CONFIG_CEPH_FS + * [Config] standardise CONFIG_SCSI_LPFC_DEBUG_FS + * [Config] standardise CONFIG_SCSI_PROC_FS + * [Config] standardise CONFIG_UBIFS_FS + * [Config] standardise CONFIG_USB_GADGET_DEBUG_FS + + [ Kees Cook ] + + * [Config] update config for CONFIG_DEBUG_SET_MODULE_RONX + + [ Manoj Iyer ] + + * SAUCE: Enable jack sense for Thinkpad Edge 11 + - LP: #677210 + * SAUCE: enable rfkill for rtl8192se driver + - LP: #640992 + + [ Tim Gardner ] + + * [Config] CONFIG_EASYCAP=n for FTBS + * Rebase to v2.6.32-rc2+git + + [ Upstream Kernel Changes ] + + * x86: Fix improper large page preservation + * x86: Add NX protection for kernel data + * x86: Add RO/NX protection for loadable kernel modules + + [ Upstream Kernel Changes ] + + * Rebase to Linus 2.6.37-rc2+git + + -- Andy Whitcroft Sat, 20 Nov 2010 11:40:00 +0000 + +linux (2.6.37-5.14) natty; urgency=low + + [ Upstream Kernel Changes ] + + * PCI: fix offset check for sysfs mmapped files + - LP: #676963 + + -- Andy Whitcroft Thu, 18 Nov 2010 18:12:27 +0000 + +linux (2.6.37-5.13) natty; urgency=low + + [ Andy Whitcroft ] + + * rebased to v2.6.37-rc2 + * updateconfigs following rebase to v2.6.37-rc2 + + [ Tim Gardner ] + + * [Config] Added NFS and related modules to virtual flavour + - LP: #659084 + + [ Upstream Kernel Changes ] + + * x86, cpu: Rename verify_cpu_64.S to verify_cpu.S + * x86, cpu: Clear XD_DISABLED flag on Intel to regain NX + * x86, cpu: Call verify_cpu during 32bit CPU startup + * x86, cpu: Only CPU features determine NX capabilities + + [ Upstream Changes ] + + * rebased to v2.67.37-rc2 + + -- Andy Whitcroft Tue, 16 Nov 2010 13:13:29 +0000 + +linux (2.6.37-4.12) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Upstream] HID: magicmouse: add param for scroll speed" + * Revert "[Upstream] HID: magicmouse: properly account for scroll + movement in state" + * Revert "[Upstream] HID: magicmouse: disable and add module param for + scroll acceleration" + * Revert "[Upstream] HID: magicmouse: scroll on entire surface, not just + middle of mouse" + + [ Henrik Rydberg ] + + * SAUCE: hid: ntrig: remove sysfs nodes + * SAUCE: hid: ntrig: Setup input filtering manually + * SAUCE: hid: ntrig: New ghost-filtering event logic + + [ Manoj Iyer ] + + * SAUCE: Added quirk to recognize GE0301 3G modem as an interface. + - LP: #348861 + + [ Upstream Kernel Changes ] + + * Revert "mmc: fix all hangs related to mmc/sd card insert/removal during + suspend/resume" + * Revert "[ARM] implement arch_randomize_brk()" + * Revert "ARM: stack protector: change the canary value per task" + * Revert "ARM: initial stack protector (-fstack-protector) support" + * Revert "ALSA: hda - Handle pin NID 0x1a on ALC259/269" + * Revert "ALSA: hda - Handle missing NID 0x1b on ALC259 codec" + * Revert "perf probe: Add kernel source path option" + * hid: ntrig: Support single-touch devices + * hid: ntrig: Mask pen switch events + * net: rtnetlink.h -- only include linux/netdevice.h when used by the + kernel + - LP: #673073 + * Fix userspace build of linux/fs.h + + -- Andy Whitcroft Mon, 15 Nov 2010 19:31:44 +0000 + +linux (2.6.37-3.11) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "ubuntu: AUFS -- update to + b37c575759dc4535ccc03241c584ad5fe69e3b25" + * Revert "ubuntu: AUFS -- track changes to the arguements to fop fsync()" + * Revert "ubuntu: AUFS -- update to standalone 2.6.35-rcN as at 20100601" + * Revert "ubuntu: AUFS -- update to standalone 2.6.34 as at 20100601" + * Revert "ubuntu: AUFS -- aufs2 base patch for linux-2.6.34" + * [Config] Disable intel_idle for -virtual kernels + - LP: #651370 + * [Config] enforcer -- ensure we never enable CONFIG_IMA + * debian -- pass the correct flavour name when checking configs + * [Config] enforcer -- ensure CONFIG_INTEL_IDLE is off for -virtual + * [Config] ensure CONFIG_IPV6=y for powerpc + * [Config] enforcer -- ensure CONFIG_IPV6=y + * ubuntu: AUFS -- aufs2-base.patch aufs2.1-36-UNRELEASED-20101103 + * ubuntu: AUFS -- aufs2-standalone.patch aufs2.1-36-UNRELEASED-20101103 + * ubuntu: AUFS -- update to aufs2.1-36-UNRELEASED-20101103 + * ubuntu: AUFS -- re-enable + * ubuntu: AUFS -- track changes to work queue initialisation + * ubuntu: AUFS -- track changes to llseek in v2.6.37-rc1 + * SAUCE: fbcon -- fix race between open and removal of framebuffers + * SAUCE: fbcon -- fix OOPs triggered by race prevention fixes + - LP: #614008 + * SAUCE: drm -- stop early access to drm devices + + [ Jeremy Kerr ] + + * [Config] Build-in powermac ZILOG serial driver + - LP: #673346 + + [ Kees Cook ] + + * SAUCE: nx-emu: use upstream ASLR when possible + + [ Tim Gardner ] + + * [Config] Use correct be2iscsi module name in d-i/modules/scsi-modules + - LP: #628776 + + [ Upstream Kernel Changes ] + + * i386: NX emulation + * nx-emu: drop exec-shield sysctl, merge with disable_nx + * nx-emu: standardize boottime message prefix + * mmap randomization for executable mappings on 32-bit + * exec-randomization: brk away from exec rand area + + -- Andy Whitcroft Thu, 11 Nov 2010 23:46:37 +0000 + +linux (2.6.37-2.10) natty; urgency=low + + [ Andy Whitcroft ] + + * reinstate armel config changes: + * [Config] CONFIG_GPIO_PCH=n for armel FTBS + * [Config] CONFIG_GPIO_VX855=n for armel FTBS + + -- Andy Whitcroft Wed, 03 Nov 2010 22:20:35 +0000 + +linux (2.6.37-2.9) natty; urgency=low + + [ Andy Whitcroft ] + + * config -- fix genportsconfig + * [Config] move powerpc over from ports to distro + * bump master version number to match contained kernel + * SAUCE: fix documentation strings for struct input_keymap_entry + * usb: gadget: goku_udc: add registered flag bit + + -- Andy Whitcroft Tue, 02 Nov 2010 15:14:11 +0000 + +linux (2.6.36-2.8) natty; urgency=low + + [ Tim Gardner ] + + * [Config]: fix changed CONFIG_SYSFS_DEPRECATED_V2 enforcement rules + * [Config]: TWL4030_CORE=n for FTBS + * [Config]: CONFIG_ATH6K_LEGACY=n for FTBS + * [Config]: CONFIG_SOLO6X10=n for FTBS + * [Config]: CONFIG_GPIO_PCH=n for armel FTBS + * [Config]: CONFIG_GPIO_VX855=n for armel FTBS + * [Config]: CONFIG_DRM_NOUVEAU=n for armel FTBS + * [Config]: CONFIG_LINE6_USB=n for armel FTBS + * [Config]: CONFIG_SENSORS_AK8975=n for armel FTBS + * [Config]: CONFIG_I2C_I801=n for armel FTBS + * UBUNTU: SAUCE: AppArmor: Fix unpack of network tables. + * AppArmor: compatibility patch for v5 interface + * AppArmor: compatibility patch for v5 network controll + * Dropped (pre-stable): input: Support Clickpad devices in ClickZone mode + * Dropped: UBUNTU: SAUCE: libata: Add ALPM power state accounting to the AHCI driver + * Dropped: UBUNTU: SAUCE: Added quirk to recognize GE0301 3G modem as an interface. + * Dropped: hid: 3m: Convert to MT slots + * Dropped: HID: magicmouse: don't allow hidinput to initialize the device + * Dropped: HID: magicmouse: simplify touch data bit manipulation + * Dropped: HID: magicmouse: simplify touch down logic + * Dropped: HID: magicmouse: enable Magic Trackpad support + * Dropped: UBUNTU: SAUCE: hid: ntrig: remove sysfs nodes + * Dropped: UBUNTU: SAUCE: hid: ntrig: Setup input filtering manually + * Dropped: UBUNTU: SAUCE: hid: ntrig: New ghost-filtering event logic + * Dropped: UBUNTU: SAUCE: hid: ntrig: identify firmware version (wiggled) + * Dropped: UBUNTU: (pre-stable): input: Support Clickpad devices in ClickZone mode + * Dropped: UBUNTU: SAUCE: KMS: cache the EDID information of the LVDS + * Dropped: UBUNTU: SAUCE: fbcon -- fix race between open and removal of framebuffers + * Dropped: UBUNTU: SAUCE: fbcon -- fix OOPs triggered by race prevention fixes + * Dropped: UBUNTU: SAUCE: x86: implement cs-limit nx-emulation for ia32 + * Dropped: UBUNTU: SAUCE: x86: more tightly confine cs-limit nx-emulation to ia32 only + * Dropped: UBUNTU: SAUCE: [um] Don't use nx_enabled under UML + * Dropped: UBUNTU: SAUCE: x86: brk away from exec rand area + + [ Upstream Kernel Changes ] + + * rebased against 2.6.27-rc1 + + -- Tim Gardner Fri, 22 Oct 2010 19:35:05 -0600 + +linux (2.6.36-1.7) natty; urgency=low + + [ Andy Whitcroft ] + + * rebased to v2.6.36 final + * [Config] update configs following rebase to v2.6.36 final + * [Config] update ports configs following rebase to v2.6.36 final + + [ Upstream Kernel Changes ] + + * rebased to v2.6.36 final + + -- Andy Whitcroft Thu, 21 Oct 2010 14:28:57 +0100 + +linux (2.6.36-1.6) natty; urgency=low + + [ Upstream Kernel Changes ] + + * drop broadcom staging driver preview: + * Revert "Staging: Add initial release of brcm80211 - Broadcom 802.11n + wireless LAN driver." + + -- Andy Whitcroft Wed, 20 Oct 2010 10:41:25 +0100 + +linux (2.6.36-1.5) natty; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.36-rc8 + * updateconfigs following rebase to v2.6.36-rc8 + * updateportsconfigs following rebase to v2.6.36-rc8 + * config -- simplify the kernelconfig interface + * config -- add new config mode 'dumpconfigs' + + [ Tim Gardner ] + + * Simplify the use of CROSS_COMPILER + + [ Upstream Kernel Changes ] + + * drop broadcom staging driver preview: + * Revert "staging: brcm80211: Make compiling of brcm80211.ko and + brcmfmac.ko mutually exclusive." + * Revert "staging: brcm80211: Fix compile issue when BRCM80211_PCI is not + set." + * Revert "Staging: brcm80211: remove driver specific -W options" + * Revert "Staging: brcm80211: clean up makefile cflag lines" + * Revert "staging: brcm80211: add fullmac driver" + * Revert "staging: brcm80211: use string native library" + * Revert "staging: brcm80211: use native ctype library" + * Revert "staging: brcm80211: fix remaining checkpatch errors." + * Revert "staging: brcm80211: fix "ERROR: trailing whitespace."" + * Revert "staging: brcm80211: fix "ERROR: spaces required around that + ..."" + * Revert "staging: brcm80211: fix "ERROR: spaces prohibited around that + ':' ..."" + * Revert "staging: brcm80211: fix "ERROR: space required before that + ..."" + * Revert "staging: brcm80211: fix "ERROR: space required after that ..."" + * Revert "staging: brcm80211: fix "ERROR: space required after that close + brace"" + * Revert "staging: brcm80211: fix "ERROR: space prohibited before + ...close square bracket"" + * Revert "staging: brcm80211: fix "ERROR: space prohibited after that + ..."" + * Revert "staging: brcm80211: fix "ERROR: need consistent spacing around + '*'"" + * Revert "staging: brcm80211: fix 'ERROR: "(foo*)" should be "(foo *)"'" + * Revert "staging: brcm80211: fix "ERROR: Macros w/ mult. statements ... + do - while loop"" + * Revert "staging: brcm80211: fix "ERROR: Macros w/ complex values ... + parenthesis"" + * Revert "staging: brcm80211: fix "ERROR: do not initialise statics to 0 + or NULL"" + * Revert "staging: brcm80211: fix "ERROR: do not initialise globals to 0 + or NULL"" + * Revert "staging: brcm80211: fix "ERROR: while should follow close brace + '}'"" + * Revert "staging: brcm80211: fix "ERROR: that open brace { ... prev + line"" + * Revert "staging: brcm80211: fix "ERROR: trailing statements should be + on next line"" + * Revert "staging: brcm80211: fix "ERROR: do not use assignment in if + condition"" + * Revert "staging: brcm80211: fix "ERROR: return is not a function, + paren..."" + * Revert "staging: brcm80211: fix "ERROR: open brace '{' following + function dec..."" + * Revert "staging: brcm80211: fix 'ERROR: "foo * bar" should be "foo + *bar"'" + * Revert "staging: brcm80211: Fix URLs for firmware files." + * Revert "staging: brcm80211: use '%pM' format to print MAC address" + * Revert "staging: brcm80211: Add contact info to TODO list." + * Revert "staging: brcm80211: Fix some initialisation failure paths" + * Export dump_{write,seek} to binary loader modules + * rebase to v2.6.36-rc8. + + -- Andy Whitcroft Tue, 19 Oct 2010 18:58:11 +0100 + +linux (2.6.36-0.4) natty; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: perf: increase stack footprint to avoid stack-protector warning + (fixes FTBS on powerpc) + + -- Andy Whitcroft Thu, 14 Oct 2010 13:16:16 +0100 + +linux (2.6.36-0.3) natty; urgency=low + + [ Andy Whitcroft ] + + * [Config] disable CONFIG_SCSI_QLA_ISCSI to fix FTBS on powerpc + + -- Andy Whitcroft Thu, 14 Oct 2010 03:01:30 +0100 + +linux (2.6.36-0.2) natty; urgency=low + + [ Andy Whitcroft ] + + * [Config] updateportsconfigs following rebase to 2.6.36-rc7 + (fix FTBS on powerpc) + + -- Andy Whitcroft Wed, 13 Oct 2010 23:25:12 +0100 + +linux (2.6.36-0.1) natty; urgency=low + + [ Andy Whitcroft ] + + * reduce disk usage during buildd builds + - LP: #645653 + * [Config] enforcer -- ensure CONFIG_INIT_PASS_ALL_PARAMS is y + * [Config] armel -- drop omap flavour + + [ Tim Gardner ] + + * Added dropped patch list + * more dropped patches + * [Config] Disable aufs, dmraid-4.5, ndis-wrapper + * [Config] Add support for cross compiling armel + * [Config] CONFIG_SCSI_QLA_ISCSI=n for armel + * [Upstream] drivers/serial/mfd.c: Fix ARM compile error + * [Config]: updateconfigs after adding brcm80211 + * staging: brcm80211: Fix Makefile syntax error + * rebased to v2.6.36-rc7 + + [ Upstream Kernel Changes ] + + * (upstream) IPS driver: don't toggle CPU turbo on unsupported CPUs + * (upstream) IPS driver: verify BIOS provided limits + * intel_ips: Print MCP limit exceeded values. + * Staging: Add initial release of brcm80211 - Broadcom 802.11n wireless + LAN driver. + * staging: brcm80211: Fix some initialisation failure paths + * staging: brcm80211: Add contact info to TODO list. + * staging: brcm80211: use '%pM' format to print MAC address + * staging: brcm80211: Fix URLs for firmware files. + * staging: brcm80211: fix 'ERROR: "foo * bar" should be "foo *bar"' + * staging: brcm80211: fix "ERROR: open brace '{' following function + dec..." + * staging: brcm80211: fix "ERROR: return is not a function, paren..." + * staging: brcm80211: fix "ERROR: do not use assignment in if condition" + * staging: brcm80211: fix "ERROR: trailing statements should be on next + line" + * staging: brcm80211: fix "ERROR: that open brace { ... prev line" + * staging: brcm80211: fix "ERROR: while should follow close brace '}'" + * staging: brcm80211: fix "ERROR: do not initialise globals to 0 or NULL" + * staging: brcm80211: fix "ERROR: do not initialise statics to 0 or NULL" + * staging: brcm80211: fix "ERROR: Macros w/ complex values ... + parenthesis" + * staging: brcm80211: fix "ERROR: Macros w/ mult. statements ... do - + while loop" + * staging: brcm80211: fix 'ERROR: "(foo*)" should be "(foo *)"' + * staging: brcm80211: fix "ERROR: need consistent spacing around '*'" + * staging: brcm80211: fix "ERROR: space prohibited after that ..." + * staging: brcm80211: fix "ERROR: space prohibited before ...close square + bracket" + * staging: brcm80211: fix "ERROR: space required after that close brace" + * staging: brcm80211: fix "ERROR: space required after that ..." + * staging: brcm80211: fix "ERROR: space required before that ..." + * staging: brcm80211: fix "ERROR: spaces prohibited around that ':' ..." + * staging: brcm80211: fix "ERROR: spaces required around that ..." + * staging: brcm80211: fix "ERROR: trailing whitespace." + * staging: brcm80211: fix remaining checkpatch errors. + * staging: brcm80211: use native ctype library + * staging: brcm80211: use string native library + * staging: brcm80211: add fullmac driver + * Staging: brcm80211: clean up makefile cflag lines + * Staging: brcm80211: remove driver specific -W options + * staging: brcm80211: Fix compile issue when BRCM80211_PCI is not set. + * staging: brcm80211: Make compiling of brcm80211.ko and brcmfmac.ko + mutually exclusive. + + -- Andy Whitcroft Tue, 12 Oct 2010 16:00:27 +0100 + +linux (2.6.35-22.33) maverick; urgency=low + + [ Andy Whitcroft ] + + * Revert "SAUCE: Add support for Intellimouse Mode in ALPS touchpad on + Dell E2 series Laptops" + - LP: #641320 + + [ Brian Rogers ] + + * SAUCE: ir-core: Fix null dereferences in the protocols sysfs interface + - LP: #624701 + + [ Christopher James Halse Rogers ] + + * SAUCE: Nouveau: Add quirk framework to disable acceleration + - LP: #544088, #546393 + * SAUCE: Nouveau: Disable acceleration on MacBook Pros + - LP: #546393 + + [ John Johansen ] + + * Revert "SAUCE: AppArmor: allow newer tools to load policy on older + kernels" + * SAUCE: AppArmor: allow newer tools to load policy on older kernels + - LP: #639758 + + [ Mathieu J. Poirier ] + + * SAUCE: Adding vdd_sdi regulator supply to OMAP3EVM + + [ Upstream Kernel Changes ] + + * ALSA: HDA: Enable internal speaker on Dell M101z + - LP: #640254 + + -- Leann Ogasawara Fri, 17 Sep 2010 13:21:28 -0700 + +linux (2.6.35-22.32) maverick; urgency=low + + [ Arjan van de Ven ] + + * SAUCE: libata: Add ALPM power state accounting to the AHCI driver + + [ David Henningsson ] + + * SAUCE: ALSA: HDA: Enable internal mic on Dell E6410 and Dell E6510 + - LP: #605047, #628961 + + [ John Johansen ] + + * [Upstream] AppArmor: Fix splitting an fqname into separate namespace + and profile names + - LP: #615947 + * [Upstream] AppArmor: Fix locking from removal of profile namespace + - LP: #615947 + * SAUCE: AppArmor: allow newer tools to load policy on older kernels + - LP: #639758 + * SAUCE: Improve Amazon EBS performance for EC2 + - LP: #634316 + + [ Leann Ogasawara ] + + * Revert "SAUCE: i915 KMS -- blacklist i855" + * Revert "SAUCE: i915 KMS -- blacklist i845g" + * Revert "SAUCE: i915 KMS -- blacklist i830" + * Revert "SAUCE: i915 KMS -- support disabling KMS for known broken + devices" + * execute module-inclusion within a subshell + - LP: #621175 + + [ Upstream Kernel Changes ] + + * (pre-stable) bounce: call flush_dcache_page() after bounce_copy_vec() + - LP: #633227 + * (pre-stable) drm/i915: don't enable self-refresh on Ironlake + - LP: #629711 + * (pre-stable) mm: Move vma_stack_continue into mm.h + * x86, hwmon: Fix unsafe smp_processor_id() in thermal_throttle_add_dev + - LP: #601073 + * PM / Runtime: Make runtime_status attribute not debug-only (v. 2) + * PM / Runtime: Add runtime PM statistics (v3) + * compat: Make compat_alloc_user_space() incorporate the access_ok() + - CVE-2010-3081 + * x86-64, compat: Test %rax for the syscall number, not %eax + - CVE-2010-3301 + * x86-64, compat: Retruncate rax after ia32 syscall entry tracing + - CVE-2010-3301 + + -- Leann Ogasawara Tue, 14 Sep 2010 08:46:49 -0700 + +linux (2.6.35-21.31) maverick; urgency=low + + [ Andy Whitcroft ] + + * bodge linux-libc-dev package version due to ti-omap4 error + * linux-libc-dev -- ensure we can only build this on debian.master + + -- Leann Ogasawara Mon, 13 Sep 2010 09:54:31 -0700 + +linux (2.6.35-21.30) maverick; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: fbcon -- fix OOPs triggered by race prevention fixes + - LP: #614008 + + [ Daniel Lezcano ] + + * SAUCE: fix compilation warning when CONFIG_SECURITY is not set + + [ Henrik Rydberg ] + + * SAUCE: Input: wacom - add fuzz parameters to features + * SAUCE: Input: wacom - collect device quirks into single function + * SAUCE: Input: wacom - add support for the Bamboo Touch trackpad + * SAUCE: Input: wacom - add a quirk for low resolution Bamboo devices + * SAUCE: hid: ntrig: Remove unused device ids + * SAUCE: hid: ntrig: remove sysfs nodes + * SAUCE: hid: ntrig: Correct logic for quirks + * SAUCE: hid: ntrig: zero-initialize ntrig struct + * SAUCE: hid: ntrig: Setup input filtering manually + * SAUCE: hid: ntrig: New ghost-filtering event logic + + [ Leann Ogasawara ] + + * SAUCE: ndiswrapper: Initialize buffer index and check its value + - LP: #613796 + + [ Manoj Iyer ] + + * SAUCE: Add support for Intellimouse Mode in ALPS touchpad on Dell E2 + series Laptops + - LP: #632884 + + [ Ping Cheng ] + + * SAUCE: Input: wacom - parse the Bamboo device family + + [ Rafi Rubin ] + + * SAUCE: hid: ntrig: identify firmware version (wiggled) + + [ Tim Gardner ] + + * [Config] CONFIG_NL80211_TESTMODE=n + + [ Upstream Kernel Changes ] + + * Revert "input: mt: Add support for the Bamboo Touch trackpad" + * e1000e: initial support for 82579 LOMs + * e1000e: correct MAC-PHY interconnect register offset for 82579 + * (pre-stable) ALSA: hda - Add a new hp-laptop model for Conexant 5066, + tested on HP G60 + - LP: #587388 + * DSS2: Don't power off a panel twice + - LP: #588243 + * mmc: build fix: mmc_pm_notify is only available with CONFIG_PM=y + * Input: i8042 - reset keyboard controller wehen resuming from S2R + - LP: #86820 + * ALSA: hda - Fix beep frequency on IDT 92HD73xx and 92HD71Bxx codecs + - LP: #414795 + * agp/intel: Support the extended physical addressing bits on + Sandybridge. + - LP: #632488 + * drm/i915,intel_agp: Add support for Sandybridge D0 + - LP: #632488 + * (pre-stable) intel_agp,i915: Add more sandybridge graphics device ids + - LP: #632488 + * mmc: omap: fix for bus width which improves SD card's peformance. + + -- Leann Ogasawara Tue, 07 Sep 2010 09:58:52 -0700 + +linux (2.6.35-20.29) maverick; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: i915 KMS -- support disabling KMS for known broken devices + - LP: #563277 + * SAUCE: i915 KMS -- blacklist i830 + - LP: #542208, #563277 + * SAUCE: i915 KMS -- blacklist i845g + - LP: #541492, #563277 + * SAUCE: i915 KMS -- blacklist i855 + - LP: #511001, #541511, #563277 + + [ Leann Ogasawara ] + + * [Config] Enable CONFIG_SENSORS_PKGTEMP=m + - LP: #601073 + * ARM: Temporarily disable module check for armel + * rebase to v2.6.35.4 + * [Config] update configs following rebase to v2.6.35.4 + + [ Ricardo Salveti de Araujo ] + + * [Config] Change CONFIG_LEDS_TRIGGER_HEARTBEAT from module to built-in + in Omap + + [ Tim Gardner ] + + * [Config] Added be2net, be2scsi to udebs + - LP: #628776 + + [ Upstream Kernel Changes ] + + * x86, cpu: Package Level Thermal Control, Power Limit Notification + definitions + - LP: #601073 + * x86, hwmon: Package Level Thermal/Power: pkgtemp hwmon driver + - LP: #601073 + * x86, hwmon: Package Level Thermal/Power: thermal throttling handler + - LP: #601073 + * x86, hwmon: Package Level Thermal/Power: power limit + - LP: #601073 + * x86, hwmon: Package Level Thermal/Power: pkgtemp documentation + - LP: #601073 + * hid: 3m: Adjust to sequential MT HID protocol + * hid: 3m: Convert to MT slots + * hid: 3m: Correct touchscreen emulation + * hid: 3m: Adjust major / minor axes to scale + * input: bcm5974: Adjust major / minor to scale + * HID: magicmouse: don't allow hidinput to initialize the device + * HID: magicmouse: simplify multitouch feature request + * HID: magicmouse: simplify touch data bit manipulation + * HID: magicmouse: simplify touch down logic + * HID: magicmouse: remove timestamp logic + * HID: magicmouse: enable Magic Trackpad support + * HID: magicmouse: Adjust major / minor axes to scale + * mmc: fix all hangs related to mmc/sd card insert/removal during + suspend/resume + - LP: #477106 + * drm/i915: fix VGA plane disable for Ironlake+ + - LP: #602281 + + -- Leann Ogasawara Mon, 30 Aug 2010 08:38:01 -0700 + +linux (2.6.35-19.28) maverick; urgency=low + + [ Leann Ogasawara ] + + * No changes from 2.6.35-19.27. Some armel udebs were accidentally deleted + from the archive and a no-change rebuild was attempted. However, the ABI + did not get bumped and resulted in build failures for 2.6.35-19.27. Fix + up the ABI and re-upload. + + -- Leann Ogasawara Sat, 28 Aug 2010 16:42:27 -0700 + +linux (2.6.35-19.27) maverick; urgency=low + + [ Leann Ogasawara ] + + * No changes from 2.6.35-19.26. Some armel udebs were accidentally deleted + from the archive. + + -- Leann Ogasawara Fri, 27 Aug 2010 08:58:35 -0700 + +linux (2.6.35-19.26) maverick; urgency=low + + [ Upstream Kernel Changes ] + + * ARM: OMAP: Beagle: revision detection + * ARM: OMAP: Beagle: only Cx boards use pin 23 for write protect + * ARM: OMAP: Beagle: no gpio_wp pin connection on xM + + -- Leann Ogasawara Thu, 26 Aug 2010 09:15:09 -0700 + +linux (2.6.35-19.25) maverick; urgency=low + + [ Jarod Wilson ] + + * SAUCE: Bring in staging/lirc from 2.6.36 + - LP: #609234 + * SAUCE: Update ir-core to linuxtv/other which should be merged for + 2.6.36. + - LP: #609234 + * SAUCE: Fix memleaks in imon and mceusb drivers + - LP: #609234 + * SAUCE: Bring in streamzap support from linuxtv/other + - LP: #609234 + + [ Mario Limonciello ] + + * Remove ubuntu/lirc in favor of staging/lirc from 2.6.36 + - LP: #609234 + + [ Mathieu J. Poirier ] + + * SAUCE: ARM: adding i2c eeprom driver to read EDID + - LP: #608279 + + [ Upstream Kernel Changes ] + + * intel_idle: disable module support + - LP: #615265 + * (pre-stable) ALSA: hda - Ensure codec patch files are checked for the + correct codec ID + * (pre-stable) ALSA: hda - Rename iMic to Int Mic on Lenovo NB0763 + - LP: #605101 + * (pre-stable) ALSA: HDA: Use model=auto for LG R510 + - LP: #495134 + * (pre-stable) ALSA: HDA: Add Sony VAIO quirk for ALC269 + - LP: #519066 + * (pre-stable) ALSA: HDA: Fix front mic on Dell Precision M6500 + - LP: #519066 + * input: mt: Initialize slots to unused (rev2) + * input: mt: Add support for the Bamboo Touch trackpad + * hid: Add a hid quirk for input sync override + + -- Leann Ogasawara Mon, 23 Aug 2010 12:42:52 -0700 + +linux (2.6.35-18.24) maverick; urgency=low + + [ Colin Watson ] + + * Pass DEB_MAINT_PARAMS to hook scripts + + [ Leann Ogasawara ] + + * [Config] Add CONFIG_INPUT_UINPUT=y to config enforcer + - LP: #584812 + * rebase to v2.6.35.3 + + [ Upstream Kernel Changes ] + + * (pre-stable) dell-wmi: Add support for eject key on Dell Studio 1555 + - LP: #609234 + * can: add limit for nframes and clean up signed/unsigned variables + - CVE-2010-2959 + * drm: Initialize ioctl struct when no user data is present + - CVE-2010-2803 + * ARM: initial stack protector (-fstack-protector) support + * ARM: stack protector: change the canary value per task + * [ARM] implement arch_randomize_brk() + * [ARM] add address randomization to mmap() + * ARM: fix ASLR of PIE executables + + -- Leann Ogasawara Sun, 22 Aug 2010 19:22:04 -0700 + +linux (2.6.35-17.23) maverick; urgency=low + + [ Jeremy Kerr ] + + * [Config] build-in uinput module + - LP: #584812 + + [ Leann Ogasawara ] + + * Revert "[Config] [FTBS] ia64: Temporarily disable CONFIG_CEPH_FS" + * Revert "[Config] [FTBS] ia64: Temporarily disable gpiolib" + * Revert "[Config] [FTBS] sparc: Temporarily disable + CONFIG_MTD_NAND_DENALI" + * Revert "[Config] [FTBS] sparc: Temporarily disable + CONFIG_MFD_JANZ_CMODIO" + * Revert "[Config] [FTBS] sparc: Temporarily disable + CONFIG_INFINIBAND_QIB" + * [Config] Enable INTEL_IPS + - LP: #601057 + * Remove ia64 support + * [Config] Update portsconfigs after removing ia64 support + * Remove sparc support + * [Config] Update portsconfigs after removing sparc support + + [ Linus Torvalds ] + + * (pre-stable) mm: fix page table unmap for stack guard page properly + + [ Mathieu J. Poirier ] + + * SAUCE: (no-up) ARM: Resetting power_mode to its original value. + - LP: #591941 + + [ Upstream Kernel Changes ] + + * timer: add on-stack deferrable timer interfaces + - LP: #601057 + * x86 platform driver: intelligent power sharing driver + - LP: #601057 + * IPS driver: add GPU busy and turbo checking + - LP: #601057 + * X86: intel_ips, check for kzalloc properly + - LP: #601057 + * ips driver: make it less chatty + - LP: #601057 + + -- Leann Ogasawara Tue, 17 Aug 2010 09:38:08 -0700 + +linux (2.6.35-16.22) maverick; urgency=low + + [ Andy Whitcroft ] + + * debian -- more agressivly clean up after depmod on purge + - LP: #618591 + + [ Henrik Rydberg ] + + * SAUCE: hid: 3m: Simplify touchsreen emulation logic + + [ Leann Ogasawara ] + + * ubuntu: iscsitarget -- version 1.4.20.2 + * ubuntu: rtl8192se -- update to version 0017.0507.2010 + * rebase to v2.6.35.2 + * [Config] update configs following rebase to v2.6.35.2 + * [Config] update ports configs following rebase to v2.6.35.2 + + [ Luke Yelavich ] + + * [Config] Enable new firewire stack on powerpc + + [ Mathieu J. Poirier ] + + * SAUCE: (drop after 2.6.35) ARM: Using gpmc function to init nand flash. + - LP: #608266 + + -- Leann Ogasawara Thu, 12 Aug 2010 09:58:01 -0700 + +linux (2.6.35-15.21) maverick; urgency=low + + [ Luke Yelavich ] + + * [Config] CONFIG_SND_USB_UA101=m for all architectures + + [ Upstream Kernel Changes ] + + * Input: introduce MT event slots + * Input: document the MT event slot protocol + * (pre-stable) sched: Revert nohz_ratelimit() for now + * (pre-stable) drm/radeon/kms: add missing copy from user + - LP: #606081 + + [ Leann Ogasawara ] + + * rebase to v2.6.35.1 + + -- Leann Ogasawara Mon, 09 Aug 2010 09:24:04 -0700 + +linux (2.6.35-14.20) maverick; urgency=low + + [ Andy Whitcroft ] + + * update Vcs-Git to point to maverick repo + * debian -- include the debian packaging in the -source package + - LP: #608674 + * select debian source format 1.0 + * add support for building selected stages of kernel + - LP: #603087 + * cleanup conditional dependancy handling + - LP: #603087 + + [ Upstream Kernel Changes ] + + * ALSA: hda - Handle missing NID 0x1b on ALC259 codec + - LP: #582199, #586418, #588031 + * ALSA: hda - Handle pin NID 0x1a on ALC259/269 + - LP: #582199, #586418, #588031 + * sched: Revert nohz_ratelimit() for now + + -- Leann Ogasawara Tue, 03 Aug 2010 08:46:47 -0700 + +linux (2.6.35-14.19) maverick; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.35 + + -- Leann Ogasawara Sun, 01 Aug 2010 10:35:56 -0700 + +linux (2.6.35-13.18) maverick; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: (no-up) Modularize vesafb -- fix initialisation + * SAUCE: add tracing for user initiated readahead requests + * SAUCE: vt -- maintain bootloader screen mode and content until vt + switch + * SAUCE: vt -- allow grub to request automatic vt_handoff + * SAUCE: fbcon -- fix race between open and removal of framebuffers + * SAUCE: drm -- stop early access to drm devices + + [ Bryan Wu ] + + * CONFIG: compile in OTG driver and Transceiver driver + - LP: #566645 + * remove OTG modules from modules list file + + [ John Johansen ] + + * SAUCE: AppArmor: -- sync to AppArmor mainline 2010-07-27 + - LP: #581525, #599450 + * SAUCE: AppArmor: -- sync to AppArmor mainline 2010-07-29 + * SAUCE: AppArmor 2.4 compatibility patch + * SAUCE: AppArmor: Allow dfa backward compatibility with broken userspace + * SAUCE: fix pv-ops for legacy Xen + * SAUCE: blkfront: default to sd devices + * [Config] Build in drivers required for Xen pv-ops + + [ Leann Ogasawara ] + + * Revert "[Upstream] i915: Use the correct mask to detect i830 aperture + size." + + [ Lee Jones ] + + * SAUCE: ARM: OMAP: Add macros for comparing silicon revision + - LP: #608095 + * SAUCE: OMAP: DSS2: check for both cpu type and revision, rather than + just revision + - LP: #608095 + * SAUCE: OMAP: DSS2: enable hsclk in dsi_pll_init for OMAP36XX + - LP: #608095 + * SAUCE: ARM: OMAP: Beagle: support twl gpio differences on xM + - LP: #608095 + + [ Upstream Kernel Changes ] + + * agp/intel: Use the correct mask to detect i830 aperture size. + - LP: #597075 + + -- Leann Ogasawara Fri, 30 Jul 2010 15:46:59 -0700 + +linux (2.6.35-12.17) maverick; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.35-rc6 + * [Config] update configs following rebase to v2.6.35-rc6 + * [Config] update ports configs following rebase to v2.6.35-rc6 + * SAUCE: [FTBS] armel: define KEY_F10 and KEYF11 + + [ Leann Ogasawara ] + + * rebase to v2.6.35-rc6 + + -- Leann Ogasawara Fri, 23 Jul 2010 16:16:38 +0200 + +linux (2.6.35-11.16) maverick; urgency=low + + [ Leann Ogasawara ] + + * Bump ABI for new compiler update + + -- Leann Ogasawara Fri, 23 Jul 2010 10:24:58 +0200 + +linux (2.6.35-10.15) maverick; urgency=low + + [ Leann Ogasawara ] + + * Revert "SAUCE: ensure vga16fb loads if no other driver claims the VGA + device" + * [Config] Enable CONFIG_M686=y + - LP: #592495 + + [ Upstream Kernel Changes ] + + * tracing: Add alignment to syscall metadata declarations + + -- Leann Ogasawara Tue, 20 Jul 2010 18:18:49 +0200 + +linux (2.6.35-9.14) maverick; urgency=low + + [ Andy Whitcroft ] + + * ubuntu: AUFS -- add BOM and automated update script + * ubuntu: AUFS -- update to b37c575759dc4535ccc03241c584ad5fe69e3b25 + + [ John Johansen ] + + * [Config] Enable DRBD as a module + + [ Kees Cook ] + + * SAUCE: Yama: verify inode is symlink to avoid bind mounts + - LP: #604407 + + [ Leann Ogasawara ] + + * [Config] Disable CONFIG_DRM_VMWGFX (staging driver) + - LP: #606139 + * [Config] ports: Disable CONFIG_DRM_VMWGFX (staging driver) + - LP: #606139 + * [Config] Enable CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y + * [Config] ports: Enable CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y + + [ Lee Jones ] + + * Stop ARM boards crashing when CUPS is loaded + - LP: #601226 + + [ Upstream Kernel Changes ] + + * perf probe: Support tracing an entry of array + * perf probe: Support static and global variables + + -- Leann Ogasawara Fri, 16 Jul 2010 14:38:17 -0700 + +linux (2.6.35-8.13) maverick; urgency=low + + [ Kees Cook ] + + * SAUCE: Yama: check PTRACE using thread group leader + * SAUCE: Yama: search for PTRACE exceptions via thread group leader + - LP: #603716 + + [ Leann Ogasawara ] + + * rebase to v2.6.35-rc5 + * [Config] update configs following rebase to v2.6.35-rc5 + + [ Nicolas Pitre ] + + * SAUCE: make ndiswrapper available on X86 only + + [ Tim Gardner ] + + * [Config] Added ums-cypress to udeb + - LP: #576066 + * SAUCE: fix build error with CONFIG_BLK_DEV_INITRD=n + * [Config] CONFIG_NDISWRAPPER=m across all configs + + [ Upstream Kernel Changes ] + + * HID: magicmouse: report last touch up + * rebase to 2.6.35-rc5 + + -- Leann Ogasawara Tue, 13 Jul 2010 18:57:59 -0700 + +linux (2.6.35-7.12) maverick; urgency=low + + [ Tim Gardner ] + + * [Upstream] i915: Use the correct mask to detect i830 aperture size. + - LP: #597075 + + [ Upstream Kernel Changes ] + + * (drop after 2.6.35) drm/radeon/kms: add ioport register access + (squashed) + + -- Tim Gardner Thu, 08 Jul 2010 09:53:13 -0600 + +linux (2.6.35-7.11) maverick; urgency=low + + [ Tim Gardner ] + + * [Config] CONFIG_X86_MRST=n + + [ Upstream Kernel Changes ] + + * (drop after 2.6.35-rc5) writeback: remove writeback_inodes_wbc + * (drop after 2.6.35-rc5) writeback: split writeback_inodes_wb + * (drop after 2.6.35-rc5) writeback: simplify the write back thread queue + + -- Tim Gardner Tue, 06 Jul 2010 18:39:08 -0600 + +linux (2.6.35-7.10) maverick; urgency=low + + [ Kees Cook ] + + * SAUCE: security: create task_free security callback + * SAUCE: Yama: add PTRACE exception tracking and interface + * SAUCE: security: unconditionally chain to Yama LSM + * Revert "SAUCE: ptrace: restrict ptrace scope to children" + * Revert "SAUCE: fs: block hardlinks to non-accessible sources" + * Revert "SAUCE: fs: block cross-uid sticky symlinks" + * [Upstream] security: Yama LSM + * [Config] Enable CONFIG_SECURITY_YAMA=y + + [ Tim Gardner ] + + * [Config] updateconfigs/updateportsconfigs after rebase to 2.6.35-rc4 + + [ Upstream Kernel Changes ] + + * rebase to 2.6.35-rc4 + + -- Leann Ogasawara Thu, 01 Jul 2010 08:55:57 -0700 + +linux (2.6.35-6.9) maverick; urgency=low + + [ Tim Gardner ] + + * [Upstream] direct_splice_actor() should not use pos in sd + - LP: #588861 + + -- Leann Ogasawara Mon, 28 Jun 2010 12:35:49 -0700 + +linux (2.6.35-6.8) maverick; urgency=low + + [ Mathieu J. Poirier ] + + * ARM: Adding regulator supply for vdds_sdi. + - LP: #597904 + + -- Leann Ogasawara Sun, 27 Jun 2010 16:34:43 -0700 + +linux (2.6.35-6.7) maverick; urgency=low + + [ Alberto Milone ] + + * [Upstream] Add support for the ATIF ACPI method to the radeon driver + + [ Chase Douglas ] + + * [Upstream] HID: magicmouse: scroll on entire surface, not just middle + of mouse + * [Upstream] HID: magicmouse: disable and add module param for scroll + acceleration + * [Upstream] HID: magicmouse: properly account for scroll movement in + state + * [Upstream] HID: magicmouse: add param for scroll speed + * [Upstream] HID: magicmouse: enable horizontal scrolling + + [ Henrik Rydberg ] + + * [Upstream] Input: evdev - convert to dynamic event buffer + * [Upstream] Input: evdev - use driver hint to compute size of event + buffer + * [Upstream] Input: bcm5974 - set the average number of events per MT + event packet + * [Upstream] Input: hid-input - use a larger event buffer for MT devices + * [Upstream] Input: evdev - never leave the client buffer empty after + write + + [ John Johansen ] + + * SAUCE: AppArmor: -- mainline 2010-06-23 + * SAUCE: AppArmor 2.4 compatibility patch + * SAUCE: fs: block hardlinks to non-accessible sources AppArmor portion + + [ Leann Ogasawara ] + + * [Config] Enable CONFIG_INTR_REMAP=y + - LP: #597091 + * [Config] Enable CONFIG_X86_X2APIC + - LP: #597091 + + [ Mathieu J. Poirier ] + + * [Config] ARM: Turning off CONFIG_CPU_IDLE on omap + - LP: #594382 + + -- Leann Ogasawara Thu, 24 Jun 2010 12:19:48 -0700 + +linux (2.6.35-5.6) maverick; urgency=low + + [ Amit Kucheria ] + + * [Config] update omap flavour description + + [ Andy Whitcroft ] + + * update to ubuntu-debian:508b7aa34b578c0d1e51bfb571f2bfb824dc65ac + - LP: #570500, #576274 + * SAUCE: add option to hand off all kernel parameters to init + - LP: #586386 + * [Config] enable passing all kernel command line to init + - LP: #586386 + * [Config] disable CONFIG_VMI + - LP: #537601 + * [Config] enable CONFIG_IPV6_SIT_6RD + - LP: #591869 + * [Config] enable CONFIG_VMWARE_BALOON as module + - LP: #592039 + + [ Leann Ogasawara ] + + * Revert "SAUCE: pm: Config option to disable handling of console during + suspend/resume" + - LP: #594885 + * [Config] Remove CONFIG_PM_DISABLE_CONSOLE + * [Config] ports: enable passing all kernel command line to init + - LP: #586386 + * [Config] Enable CONFIG_FB_VESA=y for x86 + * [Config] Add CONFIG_FRAMEBUFFER_CONSOLE=y to config enforcer + * [Config] Add CONFIG_FB_VESA=y for x86 to config enforcer + * [Config] Enable CONFIG_TASK_DELAY_ACCT=y + - LP: #493156 + + [ Mathieu Poirier ] + + * ARM: Adding MosChip MCS7830 to nic-usb + - LP: #584920 + + [ Upstream Kernel Changes ] + + * Revert "[Upstream] docbook: need xmldoclinks for all doc types" + * docbook: need xmldoclinks for all doc types + * perf probe: Add kernel source path option + + -- Leann Ogasawara Thu, 17 Jun 2010 08:05:29 -0700 + +linux (2.6.35-4.5) maverick; urgency=low + + [ Leann Ogasawara ] + + * Revert "[Upstream] (evdev) Use driver hint to compute the evdev buffer + size (rev2)" + * Revert "[Upstream] (evdev) Convert to dynamic event buffer (rev4)" + * Revert "[Upstream] (evdev) Use multi-reader buffer to save space + (rev4)" + * Revert "SAUCE: drivers: Remove some duplicate device entries in various + modules" + * [Upstream] USB: option: Remove duplicate AMOI_VENDOR_ID + * [Upstream] Revert "USB: Adding support for HTC Smartphones to ipaq" + * [Upstream] p54usb: Comment out duplicate Medion MD40900 device id + + [ Tim Gardner ] + + * [Config] CONFIG_NFS_FSCACHE=y + - LP: #440522 + * [Config] CONFIG_FSCACHE_STATS=y, CONFIG_FSCACHE_HISTOGRAM=y + - LP: #440522 + + -- Leann Ogasawara Wed, 16 Jun 2010 08:43:07 -0700 + +linux (2.6.35-3.4) maverick; urgency=low + + [ Andy Whitcroft ] + + * debian -- ensure the version number is clean + + [ Henrik Rydberg ] + + * [Upstream] Introduce MT event slots (rev 5) + * [Upstream] Document the MT event slot protocol (rev5) + * [Upstream] (evdev) Use multi-reader buffer to save space (rev4) + * [Upstream] (evdev) Convert to dynamic event buffer (rev4) + * [Upstream] (evdev) Use driver hint to compute the evdev buffer size + (rev2) + + [ Leann Ogasawara ] + + * Revert "SAUCE: Add MODULE_ALIAS for Dell WMI module" + * Revert "SAUCE: hostap: send events on data interface as well as master + interface" + * Revert "Fix webcam having USB ID 0ac8:303b" + * Revert "SAUCE: toshiba_acpi -- pull in current -dev version of driver" + * rebase to v2.6.35-rc3 + + [ Maxim Levitsky ] + + * [Config] Enable new Smartmedia/xD translation layer + - LP: #202490 + + [ Upstream Kernel Changes ] + + * net: fix deliver_no_wcard regression on loopback device + + [ Upstream changes ] + + * rebased to v2.6.35-rc3 + + -- Leann Ogasawara Thu, 10 Jun 2010 16:15:22 -0700 + +linux (2.6.35-2.3) maverick; urgency=low + + [ Bryan Wu ] + + * CONFIG: enforce -- make sure we disable CONFIG_LOCALVERSION_AUTO + + [ Leann Ogasawara ] + + * [Config] armel: Enable CONFIG_BNX2=m + * [Config] ports: Enable CONFIG_BNX2X=m + * SAUCE: armel: define get_dma_ops to fix FTBS + + [ Tim Gardner ] + + * [Upstream] net: Print num_rx_queues imbalance warning only when there + are allocated queues + - LP: #591416 + + -- Leann Ogasawara Wed, 09 Jun 2010 08:27:41 -0700 + +linux (2.6.35-2.2) maverick; urgency=low + + [ Andy Whitcroft ] + + * [Config] d-i: make armel configuration versatile flavour specific + - LP: #588805 + * [Config] d-i: enable .udebs for omap flavour + - LP: #588805 + + [ Kees Cook ] + + * ptrace: limit scope to attach only (allow read) + - LP: #589656 + + [ Leann Ogasawara ] + + * rebase to v2.6.35-rc2 + * [Config] update configs following rebase to v2.6.35-rc2 + * [Config] update port configs following rebase to v2.6.35-rc2 + + [ Lee Jones ] + + * Enable perf to be more helpful when perf_ does not exist. + - LP: #570500 + * 'fdr editconfig' modification. Easily skip over unwanted menuconfigs. + + [ Tim Gardner ] + + * [Config] Update bnx2 udeb firmware files + - LP: #589304 + + [ Upstream changes ] + + * rebased to v2.6.35-rc2 + + -- Leann Ogasawara Mon, 07 Jun 2010 09:45:04 -0700 + +linux (2.6.35-1.1) maverick; urgency=low + + [ Andy Whitcroft ] + + * ubuntu: AUFS -- update to standalone 2.6.35-rcN as at 20100601 + - LP: #587888 + * ubuntu: AUFS -- track changes to the arguements to fop fsync() + + [ Leann Ogasawara ] + + * rebase to v2.6.35-rc1 + * [Config] update configs following rebase to v2.6.35-rc1 + * [Config] update port configs following rebase to v2.6.35-rc1 + * SAUCE: lirc: rename usb_buffer_alloc() and usb_buffer_free() + * SAUCE: ndiswrapper: rename usb_buffer_alloc() and usb_buffer_free() + * SAUCE: ndiswrapper: convert multicast list to list_head + * [Config] [FTBS] armel: Temporarily disable CONFIG_GPIO_JANZ_TTL + * [Config] [FTBS] ia64: Temporarily disable gpiolib + * [Config] [FTBS] ia64: Temporarily disable CONFIG_CEPH_FS + * [Config] [FTBS] sparc: Temporarily disable CONFIG_INFINIBAND_QIB + * [Config] [FTBS] sparc: Temporarily disable CONFIG_MFD_JANZ_CMODIO + * [Config] [FTBS] armel: Temporarily disable CONFIG_MFD_JANZ_CMODIO + * [Config] [FTBS] armel: Temporarily disable CONFIG_DT3155 + * [Config] [FTBS] sparc: Temporarily disable CONFIG_MTD_NAND_DENALI + * [Config] [FTBS] armel: Temporarily disable bnx2 + * [Config] [FTBS] armel: Temporarily disable CONFIG_SERIAL_UARTLITE + * SAUCE: [FTBS] armel: Don't include asm/agp.h for ttm + * SAUCE: [FTBS] armel: include linux/dma-mapping.h + * SAUCE: [FTBS] armel: replace omap_set_gpio_debounce with + gpio_set_debounce + + [ Upstream Kernel Changes ] + + * of/usb: fix build error due to of_node pointer move + * n2_crypto: Fix build after of_device/of_platform_driver changes. + * powerpc/fsl-booke: fix the case where we are not in the first page + * powerpc/fsl-booke: Move the entry setup code into a seperate file + * powerpc/kexec: Add support for FSL-BookE + * greth: Fix build after OF device conversions. + + [ Upstream changes ] + + * rebased to v2.6.35-rc1 + + -- Leann Ogasawara Fri, 04 Jun 2010 23:01:52 -0700 + +linux (2.6.35-1.0) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * Null entry. + + -- Leann Ogasawara Wed, 02 Jun 2010 15:17:41 -0700 + +linux (2.6.34-5.14) maverick; urgency=low + + [ Tim Gardner ] + + * [Config] Added module inclusion support + * [Config] Added virtual flavour module inclusion list and d-i package + definitions + + -- Leann Ogasawara Wed, 02 Jun 2010 12:58:14 -0700 + +linux (2.6.34-5.13) maverick; urgency=low + + [ Andy Whitcroft ] + + * Revert "ubuntu: AUFS -- aufs2 20091209" + * Revert "ubuntu: AUFS -- export various core functions + (aufs2-standalone.patch)" + * Revert "ubuntu: AUFS -- export various core functions + (aufs2-base.patch)" + * ubuntu: AUFS -- aufs2 base patch for linux-2.6.34 + - LP: #587888 + * ubuntu: AUFS -- aufs2 standalone patch for linux-2.6.34 + - LP: #587888 + * ubuntu: AUFS -- update to standalone 2.6.34 as at 20100601 + - LP: #587888 + * [Config] AUFS -- enable aufs options + - LP: #587888 + + -- Leann Ogasawara Tue, 01 Jun 2010 08:56:43 -0700 + +linux (2.6.34-5.12) maverick; urgency=low + + [ Andy Whitcroft ] + + * enforce -- ensure SYSFS compatibility is disabled + + [ Chase Douglas ] + + * build with libdw-dev for perf probe symbol support + * maverick ftrace configuration changes + + [ Kees Cook ] + + * Revert "SAUCE: x86: brk away from exec rand area" + * Revert "SAUCE: [um] Don't use nx_enabled under UML" + * Revert "SAUCE: [x86] implement cs-limit nx-emulation for ia32" + * SAUCE: x86: implement cs-limit nx-emulation for ia32 + - LP: #369978 + * SAUCE: x86: more tightly confine cs-limit nx-emulation to ia32 only + * SAUCE: x86: brk away from exec rand area + - LP: #452175 + * SAUCE: ptrace: restrict ptrace scope to children + + [ Leann Ogasawara ] + + * Add new omap flavour to getabis + * [Config] Enable CONFIG_FRAMEBUFFER_CONSOLE=y for all archs + - LP: #585490 + * build/modules: Temorarily add ignore.modules + * ubuntu: iscsitarget -- version 1.4.20.1 + + [ Loïc Minier ] + + * SAUCE: [um] Don't use nx_enabled under UML + - LP: #524849 + + -- Leann Ogasawara Fri, 28 May 2010 08:27:17 -0700 + +linux (2.6.34-4.11) maverick; urgency=low + + [ Amit Kucheria ] + + * SAUCE: omap: remove calls to usb_nop_xceiv_register from board files + * [Config] Add support for OMAP-mainline flavour + + [ Andy Whitcroft ] + + * SAUCE: powerpc: fix compile error when ptrace.h is included from + userspace + - LP: #583733 + + [ Chase Douglas ] + + * Revert "SAUCE: Don't register vga16fb framebuffer if other framebuffers + are present" + * Revert "SAUCE: Disable function tracing after hitting __schedule_bug" + * Revert "SAUCE: drm/i915: don't change DRM configuration when releasing + load detect pipe" + + [ Kees Cook ] + + * SAUCE: fs: block cross-uid sticky symlinks + * SAUCE: fs: block hardlinks to non-accessible sources + + [ Koen Kooi ] + + * SAUCE: board-omap3-beagle: add DSS2 support + + [ Leann Ogasawara ] + + * Revert "staging/go7007 -- disable" + * Revert "[Config] staging/winbond -- disable" + * Revert "Disable 4MB page tables for Atom, work around errata AAE44" + * Revert "SAUCE: sync before umount to reduce time taken by ext4 umount" + * Revert "SAUCE: Enable an e1000e Intel Corporation 82567 Gigabit + controller" + * Revert "SAUCE: Fix MODULE_IMPORT/MODULE_EXPORT" + * Revert "SAUCE: Created MODULE_EXPORT/MODULE_IMPORT macros" + * Revert "SAUCE: input/mouse/alps: Do not call psmouse_reset() for alps" + * Revert "SAUCE: r8169: disable TSO by default for RTL8111/8168B + chipsets." + * Revert "[Upstream] b43: Declare all possible firmware files." + * Revert "add Breaks: against hardy lvm2" + * Revert "SAUCE: Guest OS does not recognize a lun with non zero target + id on Vmware ESX Server" + * Revert "SAUCE: Catch nonsense keycodes and silently ignore" + * [Config] Enable CONFIG_ECRYPT_FS=y for ports + * [Config] Enable CONFIG_USB=y for armel and sparc + * [Config] Enable CONFIG_SCSI=y for ia64 and sparc + * [Config] Enable CONFIG_RFKILL=y for ports + * [Config] Enable CONFIG_ATH9K_DEBUGFS=y + * [Config] Enable CONFIG_IWMC3200TOP_DEBUGFS=y + * [Config] Enable CONFIG_RCU_FAST_NO_HZ=y + * [Config] Enable CONFIG_IWLWIFI_DEVICE_TRACING=y + * [Config] Enable CONFIG_LIBERTAS_MESH=y + * [Config] Enable CONFIG_MMC_RICOH_MMC=y + * [Config] CONFIG_RT2800USB_UNKNOWN=y + * [Config] Enable CONFIG_VGA_SWITCHEROO=y + * [Config] Enable CONFIG_CEPH_FS=m + * [Config] Enable CONFIG_CRYPTO_PCRYPT=m + * [Config] Enable CONFIG_EEEPC_WMI=m + * [Config] Enable CONFIG_RT2800PCI=m + * [Config] Enable CONFIG_SCSI_HPSA=m + * [Config] Enable CONFIG_VHOST_NET=m + * [Config] Disable CONFIG_SND_HDA_INPUT_BEEP_MODE by default + - LP: #582350 + * [Config] Disable CONFIG_SOUND_OSS* and CONFIG_SND_*OSS + - LP: #579300 + * [Config] Enable CONFIG_PCIEASPM=y + - LP: #333990 + * [Config] updateconfigs for OMAP flavour + + [ Loïc Minier ] + + * Enable perf tools on armel + + [ Tim Gardner ] + + * SAUCE: Updated ndiswrapper to 1.56 + - LP: #582555 + * [Config] Added virtual flavour + * [Config] Remove support for sub-flavours + * [Config] Removed amd64 preempt flavour + * [Config] updateconfigs, updateportsconfigs after flavour munging + + -- Leann Ogasawara Tue, 25 May 2010 09:34:55 -0700 + +linux (2.6.34-3.10) maverick; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.34 + + [ Upstream changes ] + + * rebased to v2.6.34 + + -- Leann Ogasawara Tue, 18 May 2010 17:35:35 -0700 + +linux (2.6.34-2.9) maverick; urgency=low + + [ Leann Ogasawara ] + + * [Config] [FTBS] Disable comedi for armel + + -- Leann Ogasawara Thu, 13 May 2010 23:20:55 +0200 + +linux (2.6.34-2.8) maverick; urgency=low + + [ Leann Ogasawara ] + + * Drop lpia + * [Config] [FTBS] disable KVM + * [Config] [FTBS] disable ipr for armel + + -- Leann Ogasawara Thu, 13 May 2010 16:07:52 +0200 + +linux (2.6.34-2.7) maverick; urgency=low + + [ Leann Ogasawara ] + + * [Config] disable CONFIG_SCSI_IPR on powerpc + * [Config] Remove 386 flavour per UDS discussion + + -- Leann Ogasawara Wed, 12 May 2010 18:26:43 +0200 + +linux (2.6.34-1.6) maverick; urgency=low + + [ Chase Douglas ] + + * enforce CONFIG_TMPFS_POSIX_ACL=y + - LP: #575940 + * don't force module dependency checking + - LP: #577029 + + [ Kees Cook ] + + * SAUCE: mmap_min_addr check CAP_SYS_RAWIO only for write + - LP: #568844 + + [ Leann Ogasawara ] + + * Revert "SAUCE: ata: blacklist FUJITSU MHW2160BH PL" + * rebase to v2.6.34-rc7 + * [Config] update configs following rebase to v2.6.34-rc7 + * [Config] update port configs following rebase to v2.6.34-rc7 + * Add btrfs to the udebs + + [ Tim Gardner ] + + * [Config] Add atl1c to nic-modules udeb + - LP: #557130 + + [ Upstream changes ] + + * rebased to v2.6.34-rc7 + + -- Leann Ogasawara Tue, 11 May 2010 11:29:08 +0200 + +linux (2.6.34-1.5) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.34-rc6 + * [Config] update configs following rebase to v2.6.34-rc6 + * [Config] update port configs following rebase to v2.6.34-rc6 + + [ Upstream changes ] + + * rebased to v2.6.34-rc6 + + -- Leann Ogasawara Fri, 30 Apr 2010 15:54:05 +0100 + +linux (2.6.34-1.4) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.34-rc5 + * [Config] update ports configs following rebase to v2.6.34-rc5 + + [ Upstream changes ] + + * rebased to v2.6.34-rc5 + + -- Leann Ogasawara Thu, 22 Apr 2010 15:36:12 -0700 + +linux (2.6.34-1.3) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.34-rc4 + * [Config] update configs following rebase to v2.6.34-rc4 + * [Config] update port configs following rebase to v2.6.34-rc4 + * ubuntu: dm-raid4-5 -- update to compile with 2.6.34-rc4 + + [ Upstream changes ] + + * rebased to v2.6.34-rc4 + + -- Leann Ogasawara Tue, 13 Apr 2010 18:33:44 -0700 + +linux (2.6.34-1.2) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * Temorarily disable building linux-doc + * rebase to v2.6.34-rc3 + * [Config] update configs following rebase to v2.6.34-rc3 + * [Config] update port configs following rebase to v2.6.34-rc3 + + [ Upstream changes ] + + * rebased to v2.6.34-rc3 + + -- Leann Ogasawara Tue, 30 Mar 2010 16:55:44 -0700 + +linux (2.6.34-1.1) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.34-rc2 + * ubuntu: dm-raid4-5 -- update to compile with 2.6.34-rc2 + * [Config] update port configs following rebase to v2.6.34-rc2 + * [Config] update configs following rebase to v2.6.34-rc2 + + [ Upstream changes ] + + * rebased to v2.6.34-rc2 + + -- Leann Ogasawara Wed, 24 Mar 2010 23:00:39 -0700 + +linux (2.6.33-1.1) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * ubuntu: dm-raid4-5 -- update to compile with 2.6.33 + * ubuntu: lirc -- drop explicit include of linux/autoconf.h + * ubuntu: lirc -- pass kfifo to kfifo_alloc and move spinlock + * ubuntu: lirc -- rename kfifo_put and kfifo_get + * ubuntu: iscsitarget -- rename daddr inet_sock field + * rebased to v2.6.33 + * [Config] update configs following rebase to v2.6.33 + * [Config] update ports configs following rebase to v2.6.33 + + [ Upstream changes ] + + * rebased to v2.6.33 + + -- Leann Ogasawara Tue, 23 Mar 2010 03:55:46 -0700 + +linux (2.6.33-0.0) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * Null entry. + + -- Leann Ogasawara Wed, 17 Mar 2010 07:48:56 -0700 + +linux (2.6.32-16.25) lucid; urgency=low + + [ Andy Whitcroft ] + + * linux-tools -- move to Suggests: with explicit seeding + - LP: #534635 + + [ Tim Gardner ] + + * [Config] CONFIG_HID=m + + [ Upstream Kernel Changes ] + + * (pre-stable) sched: Fix SMT scheduler regression in + find_busiest_queue() + * KVM: introduce kvm_vcpu_on_spin + * KVM: VMX: Add support for Pause-Loop Exiting + + -- Andy Whitcroft Tue, 09 Mar 2010 14:13:51 +0000 + +linux (2.6.32-16.24) lucid; urgency=low + + [ Andy Whitcroft ] + + * armel -- perf userspace does not support arm + * ia64 -- libelf-dev/binutils-dev to not provide necessary libraries + + -- Andy Whitcroft Sat, 06 Mar 2010 11:42:12 +0000 + +linux (2.6.32-16.23) lucid; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: PM report driver and device suspend/resume times -- move config + * update to standards version 3.8.4.0 + * printenv -- expose all of the package selectors + * source package -- cleanup source content control + * doc package -- ensure we do build package content on buildd + * lintian -- correct the address in the debian/copyright + * lintian -- update debhelper package version dependancy + * lintian -- fix ghostscript dependancy + * lintian -- add required misc:Depends + * lintian -- move our debhelper compat level to debian/compat + * perf -- build the kernel carried tools + * perf -- add linux-tools carrying the version switches and manuals + * SAUCE: fix up Kconfig for staging drivers + * [Config] enable NOUVEAU etc following drm backport + * update DRM to mainline v2.6.33 + * [Config] Remove AppArmor config options that no longer exist (ports) + * [Config] updateportsconfigs following drm update + + [ John Johansen ] + + * ubuntu: AppArmor -- update to mainline 2010-03-04 + * SAUCE: AppArmor: Reintroduce AppArmor 2.4 compatibility + * SAUCE: AppArmor: replace strim with strstrip for 2.6.32 kernels + * [Config] Remove AppArmor config options that no longer exist + + [ Manoj Iyer ] + + * ubuntu: rtl8192se -- version 2010-0115,0014 + - LP: #530275 + * [Config] added CONFIG_RTL8192SE module. + - LP: #530275 + + [ Tim Gardner ] + + * [Config] Added vmw_pvscsi to d-i/scsi-modules + - LP: #531017 + * [Upstream] netfilter: xt_recent: Add an entry reaper + + [ Upstream Kernel Changes ] + + * Revert "KVM: x86 emulator: Check CPL level during privilege instruction + emulation" + * Revert "KVM: x86 emulator: Fix popf emulation" + * Revert "KVM: x86 emulator: Check IOPL level during io instruction + emulation" + * Revert "KVM: x86 emulator: Add Virtual-8086 mode of emulation" + * Revert "KVM: fix memory access during x86 emulation." + * Add vlan (8021.Q) module package for d-i. + * (pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP, Dell + Inspiron 700m + - LP: #515246 + * [Upstream] docbook: need xmldoclinks for all doc types + * x86: set_personality_ia32() misses force_personality32 + * lib: Introduce generic list_sort function + * drm/nv50: Implement ctxprog/state generation. + * drm/nv50: Remove redundant/incorrect ctxvals initialisation. + * (pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP, Dell + Inspiron 700m + - LP: #515246 + + -- Andy Whitcroft Fri, 05 Mar 2010 15:40:38 +0000 + +linux (2.6.32-15.22) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Config] added new config option CONFIG_SR_REPORT_TIME_LIMIT" + * Revert "SAUCE: PM report driver and device suspend/resume times." + * [Config] set CONFIG_SR_REPORT_TIME_LIMIT + + [ Manoj Iyer ] + + * SAUCE: PM report driver and device suspend/resume times. + + -- Andy Whitcroft Tue, 02 Mar 2010 01:35:37 +0000 + +linux (2.6.32-15.21) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "(pre-stable) drm/i915: Increase fb alignment to 64k" + * Revert "[Config] lenovo-sl-laptop -- enable" + * Revert "ubuntu: lenovo-sl-laptop -- git tip (b19a08f81f)" + * armel -- cramfs module will no longer be built + * d-i -- make all modules optional + * rename the debug packages to match archive standard + - LP: #527837 + * lenovo-sl-laptop is no longer built + + [ Colin Ian King ] + + * Disable 4MB page tables for Atom, work around errata AAE44 + - LP: #523112 + + [ Colin Watson ] + + * ubuntu: dm-raid4-5: Depend on XOR_BLOCKS + * ubuntu: fsam7400: Depend on CHECK_SIGNATURE + + [ Jesse Barnes ] + + * SAUCE: drm/i915: don't change DRM configuration when releasing load + detect pipe + - LP: #488328 + + [ Loïc Minier ] + + * [Config] armel Update versatile initrd configs + - LP: #524893 + * SAUCE: [um] Don't use nx_enabled under UML + - LP: #524849 + + [ Manoj Iyer ] + + * [Config] added new config option CONFIG_SR_REPORT_TIME_LIMIT + + [ Mario Limonciello ] + + * SAUCE: v3 - Add Dell Business Class Netbook LED driver + + [ Rafael J. Wysocki ] + + * SAUCE: PM report driver and device suspend/resume times. + + [ Surbhi Palande ] + + * Revert "[Upstream] e1000e: enhance frame fragment detection" + - CVE-2009-4538 + * Revert "[Upstream] e1000: enhance frame fragment detection" + - CVE-2009-4536 + + [ Tim Gardner ] + + * [Config] Enabled CONFIG_LEDS_DELL_NETBOOKS=m + * SAUCE: (pre-stable) netfilter: xt_recent: fix buffer overflow + * SAUCE: (pre-stable) netfilter: xt_recent: fix false match + + [ Upstream Kernel Changes ] + + * Revert "(pre-stable) eCryptfs: Add getattr function" + * Fix potential crash with sys_move_pages + * futex_lock_pi() key refcnt fix + * futex: Handle user space corruption gracefully + * futex: Handle futex value corruption gracefully + * Fix race in tty_fasync() properly + * hwmon: (w83781d) Request I/O ports individually for probing + * hwmon: (lm78) Request I/O ports individually for probing + * hwmon: (adt7462) Wrong ADT7462_VOLT_COUNT + * ALSA: ctxfi - fix PTP address initialization + * drm/i915: disable hotplug detect before Ironlake CRT detect + * drm/i915: enable self-refresh on 965 + * drm/i915: Disable SR when more than one pipe is enabled + * drm/i915: Fix DDC on some systems by clearing BIOS GMBUS setup. + * drm/i915: Add HP nx9020/SamsungSX20S to ACPI LID quirk list + * drm/i915: Fix the incorrect DMI string for Samsung SX20S laptop + * drm/i915: Add MALATA PC-81005 to ACPI LID quirk list + * usb: r8a66597-hcd: Flush the D-cache for the pipe-in transfer buffers. + * i2c-tiny-usb: Fix on big-endian systems + * drm/i915: handle FBC and self-refresh better + * drm/i915: Increase fb alignment to 64k + * drm/i915: Update write_domains on active list after flush. + * regulator: Fix display of null constraints for regulators + * ALSA: hda-intel: Avoid divide by zero crash + * CPUFREQ: Fix use after free of struct powernow_k8_data + * freeze_bdev: don't deactivate successfully frozen MS_RDONLY sb + * cciss: Make cciss_seq_show handle holes in the h->drv[] array + * ioat: fix infinite timeout checking in ioat2_quiesce + * resource: add helpers for fetching rlimits + * fs/exec.c: restrict initial stack space expansion to rlimit + * cifs: fix length calculation for converted unicode readdir names + * NFS: Fix a reference leak in nfs_wb_cancel_page() + * NFS: Try to commit unstable writes in nfs_release_page() + * NFSv4: Don't allow posix locking against servers that don't support it + * NFSv4: Ensure that the NFSv4 locking can recover from stateid errors + * NFS: Fix an Oops when truncating a file + * NFS: Fix a umount race + * NFS: Fix a bug in nfs_fscache_release_page() + * NFS: Fix the mapping of the NFSERR_SERVERFAULT error + * md: fix 'degraded' calculation when starting a reshape. + * V4L/DVB: dvb-core: fix initialization of feeds list in demux filter + * Export the symbol of getboottime and mmonotonic_to_bootbased + * kvmclock: count total_sleep_time when updating guest clock + * KVM: PIT: control word is write-only + * tpm_infineon: fix suspend/resume handler for pnp_driver + * amd64_edac: Do not falsely trigger kerneloops + * netfilter: nf_conntrack: fix memory corruption with multiple namespaces + * netfilter: nf_conntrack: per netns nf_conntrack_cachep + * netfilter: nf_conntrack: restrict runtime expect hashsize modifications + * netfilter: xtables: compat out of scope fix + * netfilter: nf_conntrack: fix hash resizing with namespaces + * drm/i915: remove full registers dump debug + * drm/i915: add i915_lp_ring_sync helper + * drm/i915: Don't wait interruptible for possible plane buffer flush + * dasd: remove strings from s390dbf + * crypto: padlock-sha - Add import/export support + * wmi: Free the allocated acpi objects through wmi_get_event_data + * dell-wmi, hp-wmi, msi-wmi: check wmi_get_event_data() return value + * /dev/mem: introduce size_inside_page() + * devmem: check vmalloc address on kmem read/write + * devmem: fix kmem write bug on memory holes + * SCSI: mptfusion : mptscsih_abort return value should be SUCCESS instead + of value 0. + * sh: Couple kernel and user write page perm bits for CONFIG_X2TLB + * ALSA: hda - use WARN_ON_ONCE() for zero-division detection + * dst: call cond_resched() in dst_gc_task() + * ALSA: hda - Improved MacBook (Pro) 5,1 / 5,2 support + * befs: fix leak + * rtc-fm3130: add missing braces + * Call flush_dcache_page after PIO data transfers in libata-sff.c + * ahci: add Acer G725 to broken suspend list + * pktgen: Fix freezing problem + * x86/amd-iommu: Fix IOMMU-API initialization for iommu=pt + * x86/amd-iommu: Fix deassignment of a device from the pt_domain + * x86: Re-get cfg_new in case reuse/move irq_desc + * Staging: fix rtl8187se compilation errors with mac80211 + * ALSA: usb-audio - Avoid Oops after disconnect + * serial: 8250: add serial transmitter fully empty test + * sysfs: sysfs_sd_setattr set iattrs unconditionally + * class: Free the class private data in class_release + * USB: usbfs: only copy the actual data received + * USB: usbfs: properly clean up the as structure on error paths + * rtl8187: Add new device ID + * ACPI: Add NULL pointer check in acpi_bus_start + * ACPI: fix High cpu temperature with 2.6.32 + * drm/radeon/kms: use udelay for short delays + * NFS: Too many GETATTR and ACCESS calls after direct I/O + * eCryptfs: Add getattr function + * b43: Fix throughput regression + * ath9k: Fix sequence numbers for PAE frames + * mac80211: Fix probe request filtering in IBSS mode + * iwlwifi: Fix to set correct ht configuration + * dm stripe: avoid divide by zero with invalid stripe count + * dm log: userspace fix overhead_size calcuations + * Linux 2.6.32.9 + * sfc: Fix SFE4002 initialisation + * sfc: Fix sign of efx_mcdi_poll_reboot() error in efx_mcdi_poll() + * sfc: SFE4002/SFN4112F: Widen temperature and voltage tolerances + * (pre-stable) HID: handle joysticks with large number of buttons + - LP: #492056 + * (pre-stable) HID: extend mask for BUTTON usage page + - LP: #492056 + * PM: Measure device suspend and resume times + * e1000: enhance frame fragment detection + - CVE-2009-4536 + * e1000e: enhance frame fragment detection + - CVE-2009-4538 + * KVM: fix memory access during x86 emulation. + - CVE-2010-0306 + * KVM: x86 emulator: Add Virtual-8086 mode of emulation + - CVE-2010-0306 + * KVM: x86 emulator: Check IOPL level during io instruction emulation + - CVE-2010-0306 + * KVM: x86 emulator: Fix popf emulation + - CVE-2010-0306 + * KVM: x86 emulator: Check CPL level during privilege instruction + emulation + - CVE-2010-0306 + * Input: wacom - ensure the device is initialized properly upon resume + * Input: wacom - add defines for packet lengths of various devices + * Input: wacom - add support for new LCD tablets + - LP: #516777 + + -- Andy Whitcroft Mon, 01 Mar 2010 22:56:28 +0000 + +linux (2.6.32-14.20) lucid; urgency=low + + [ Andy Whitcroft ] + + * rebuild following the GCC update to match compiler for out of tree modules + * Revert "[Config] drbd -- enable" + * Revert "ubuntu: drbd -- version 8.3.1" + * SAUCE: khubd -- switch USB product/manufacturer/serial handling to RCU + - LP: #510937 + + -- Andy Whitcroft Fri, 19 Feb 2010 18:47:18 +0000 + +linux (2.6.32-14.19) lucid; urgency=low + + [ Andy Whitcroft ] + + * ensure we build the source package contents when enabled + - LP: #522308 + * [Config] enable CONFIG_X86_MCE_XEON75XX + * SAUCE: AppArmor -- add linux/kref.h for struct kref + * [Config] enable CONFIG_HID_ORTEK + * enable udeb generation for arm versatile flavour + - LP: #522515 + + [ John Johansen ] + + * ubuntu: AppArmor -- update to mainline 2010-02-18 + - LP: #439560, #496110, #507069 + + [ Johnathon Harris ] + + * SAUCE: HID: add support for Ortek WKB-2000 + - LP: #405390 + + [ Upstream Kernel Changes ] + + * tpm_tis: TPM_STS_DATA_EXPECT workaround + - LP: #490487 + * x86, mce: Xeon75xx specific interface to get corrected memory error + information + * x86, mce: Rename cpu_specific_poll to mce_cpu_specific_poll + * x86, mce: Make xeon75xx memory driver dependent on PCI + * drm/edid: Unify detailed block parsing between base and extension + blocks + - LP: #500999 + * (pre-stable) eCryptfs: Add getattr function + - LP: #390833 + + -- Andy Whitcroft Thu, 18 Feb 2010 19:22:02 +0000 + +linux (2.6.32-13.18) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "enforcer -- make the enforcement configuration common" + * Revert "(pre-stable) Input: ALPS - add interleaved protocol support + (Dell E6x00 series)" + * Revert "(pre-stable) driver-core: fix devtmpfs crash on s390" + * Revert "(pre-stable) Driver-Core: devtmpfs - set root directory mode to + 0755" + * Revert "SAUCE: Adds support for COMPAL JHL90 webcam" + * Revert "SAUCE: fix kernel oops in VirtualBox during paravirt patching" + * Revert "SAUCE: make fc transport removal of target configurable" + * enforcer -- make the enforcement configuration common + * getabis -- add preempt flavour to the list + * [Config] enforce DEVTMPFS options + * [Config] armel -- cleanup to-be builtin modules + * [Config] cleanup ports configs + * [Config] enable CRYPTO_GHASH_CLMUL_NI_INTEL + - LP: #485536 + * add printdebian target to find branch target + * distclean -- do not remove debian.env + * [Config] generic-pae switch to M586TSC + - LP: #519448 + * git-ubuntu-log -- commonise duplicated log handling + * git-ubuntu-log -- tighten up Bug: NNNN matching + * git-ubuntu-log -- sort the bug numbers + + [ Chris Wilson ] + + * (pre-stable) drm/i915: Increase fb alignment to 64k + - LP: #404064 + + [ Eric Miao ] + + * arm -- enable ubuntu/ directory + + [ Huang Ying ] + + * SAUCE: crypto: ghash - Add PCLMULQDQ accelerated implementation + * SAUCE: crypto: ghash-intel - Fix building failure on x86_32 + + [ Loïc Minier ] + + * [Config] cleanup preempt configuration + * [Config] versatile: Fix video output + - LP: #517594 + * [Config] armel DEFAULT_MMAP_MIN_ADDR=32768 + * [Config] Large update to armel/versatile + * [Config] versatile: Add RTC support + * [Config] armel: Enable NEON + * [Config] versatile: Builtin MMC support + * [Config] versatile Builtin SCSI controller + * [Config] armel Disable dma_cache_sync callers + * [Config] armel Disable asm/time.h users + * [Config] armel Disable out of range udelay() + * [Config] armel Disable flush_cache_range() users + * [Config] armel -- Enable ubuntu/ drivers + + [ Steve Conklin ] + + * SAUCE: drm/i915: Add display hotplug event on Ironlake + * SAUCE: drm/i915: Add ACPI OpRegion support for Ironlake + + [ Upstream Kernel Changes ] + + * Revert "[Upstream]: oprofile/x86: add Xeon 7500 series support" + * Revert "Revert "[Bluetooth] Eliminate checks for impossible conditions + in IRQ handler"" + * clockevent: Don't remove broadcast device when cpu is dead + * clockevents: Add missing include to pacify sparse + * ACPI: don't cond_resched if irq is disabled + * be2net: Add support for next generation of BladeEngine device. + * be2net: Add the new PCI IDs to PCI_DEVICE_TABLE. + * mpt2sas: New device SAS2208 support is added + * ar9170: Add support for D-Link DWA 160 A2 + * powerpc/fsl: Add PCI device ids for new QoirQ chips + * davinci: dm646x: Add support for 3.x silicon revision + * Input: ALPS - add interleaved protocol support (Dell E6x00 series) + * Driver-Core: devtmpfs - set root directory mode to 0755 + * driver-core: fix devtmpfs crash on s390 + * vfs: get_sb_single() - do not pass options twice + * ALSA: hda - Add PCI IDs for Nvidia G2xx-series + * V4L/DVB (13569): smsusb: add autodetection support for five additional + Hauppauge USB IDs + * USB: mos7840: add device IDs for B&B electronics devices + * USB: ftdi_sio: add USB device ID's for B&B Electronics line + * V4L/DVB (13168): Add support for Asus Europa Hybrid DVB-T card (SAA7134 + SubVendor ID: 0x1043 Device ID: 0x4847) + * iTCO_wdt: Add support for Intel Ibex Peak + * atl1c:use common_task instead of reset_task and link_chg_task + * atl1e:disable NETIF_F_TSO6 for hardware limit + * V4L/DVB (13680a): DocBook/media: copy images after building HTML + * V4L/DVB (13680b): DocBook/media: create links for included sources + * netfilter: xtables: fix conntrack match v1 ipt-save output + * partitions: read whole sector with EFI GPT header + * partitions: use sector size for EFI GPT + * ALSA: ice1724 - Patch for suspend/resume for ESI Juli@ + * sched: Fix isolcpus boot option + * sched: Fix missing sched tunable recalculation on cpu add/remove + * nohz: Prevent clocksource wrapping during idle + * nfsd: Fix sort_pacl in fs/nfsd/nf4acl.c to actually sort groups + * timers, init: Limit the number of per cpu calibration bootup messages + * PCI: Always set prefetchable base/limit upper32 registers + * iscsi class: modify handling of replacement timeout + * NFS: Revert default r/wsize behavior + * HID: fixup quirk for NCR devices + * scsi_devinfo: update Hitachi entries (v2) + * scsi_dh: create sysfs file, dh_state for all SCSI disk devices + * scsi_transport_fc: remove invalid BUG_ON + * lpfc: fix hang on SGI ia64 platform + * libfc: fix typo in retry check on received PRLI + * libfc: fix ddp in fc_fcp for 0 xid + * fcoe: remove redundant checking of netdev->netdev_ops + * libfc: Fix wrong scsi return status under FC_DATA_UNDRUN + * libfc: lport: fix minor documentation errors + * libfc: don't WARN_ON in lport_timeout for RESET state + * fcoe: initialize return value in fcoe_destroy + * libfc: Fix frags in frame exceeding SKB_MAX_FRAGS in fc_fcp_send_data + * libfc: fix memory corruption caused by double frees and bad error + handling + * libfc: fix free of fc_rport_priv with timer pending + * libfc: remote port gets stuck in restart state without really + restarting + * fcoe, libfc: fix an libfc issue with queue ramp down in libfc + * fcoe: Fix checking san mac address + * fcoe: Fix getting san mac for VLAN interface + * qlge: Remove explicit setting of PCI Dev CTL reg. + * qlge: Set PCIE max read request size. + * qlge: Don't fail open when port is not initialized. + * qlge: Add handler for DCBX firmware event. + * qlge: Bonding fix for mode 6. + * PCI: AER: fix aer inject result in kernel oops + * DMI: allow omitting ident strings in DMI tables + * Input: i8042 - remove identification strings from DMI tables + * Input: i8042 - add Gigabyte M1022M to the noloop list + * Input: i8042 - add Dritek quirk for Acer Aspire 5610. + * ALSA: hda - select IbexPeak handler for Calpella + * ALSA: hda - Fix quirk for Maxdata obook4-1 + * ALSA: hda - Add missing Line-Out and PCM switches as slave + * iTCO_wdt.c - cleanup chipset documentation + * iTCO_wdt: add PCI ID for the Intel EP80579 (Tolapai) SoC + * iTCO_wdt: Add Intel Cougar Point and PCH DeviceIDs + * ahci: disable SNotification capability for ich8 + * ata_piix: fix MWDMA handling on PIIX3 + * md: fix small irregularity with start_ro module parameter + * V4L/DVB (13826): uvcvideo: Fix controls blacklisting + * cio: fix double free in case of probe failure + * cio: dont panic in non-fatal conditions + * netiucv: displayed TX bytes value much too high + * ipc ns: fix memory leak (idr) + * ALSA: hda - Fix HP T5735 automute + * hwmon: (fschmd) Fix a memleak on multiple opens of /dev/watchdog + * UBI: fix memory leak in update path + * UBI: initialise update marker + * ASoC: fix a memory-leak in wm8903 + * mac80211: check that ieee80211_set_power_mgmt only handles STA + interfaces. + * cfg80211: fix channel setting for wext + * KVM: S390: fix potential array overrun in intercept handling + * KVM: only allow one gsi per fd + * KVM: Fix race between APIC TMR and IRR + * KVM: MMU: bail out pagewalk on kvm_read_guest error + * KVM: x86: Fix host_mapping_level() + * KVM: x86: Fix probable memory leak of vcpu->arch.mce_banks + * KVM: x86: Fix leak of free lapic date in kvm_arch_vcpu_init() + * KVM: fix lock imbalance in kvm_*_irq_source_id() + * KVM: only clear irq_source_id if irqchip is present + * IPoIB: Clear ipoib_neigh.dgid in ipoib_neigh_alloc() + * x86: Reenable TSC sync check at boot, even with NONSTOP_TSC + * ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C + - LP: #516325 + * iwlwifi: Fix throughput stall issue in HT mode for 5000 + * fnctl: f_modown should call write_lock_irqsave/restore + * x86, msr/cpuid: Pass the number of minors when unregistering MSR and + CPUID drivers. + * Linux 2.6.32.7 + * scsi_lib: Fix bug in completion of bidi commands + * mptsas: Fix issue with chain pools allocation on katmai + * mm: add new 'read_cache_page_gfp()' helper function + * drm/i915: Selectively enable self-reclaim + * firewire: ohci: fix crashes with TSB43AB23 on 64bit systems + * S390: fix single stepped svcs with TRACE_IRQFLAGS=y + * x86: Set hotpluggable nodes in nodes_possible_map + * x86: Remove "x86 CPU features in debugfs" (CONFIG_X86_CPU_DEBUG) + * libata: retry FS IOs even if it has failed with AC_ERR_INVALID + * zcrypt: Do not remove coprocessor for error 8/72 + * dasd: fix possible NULL pointer errors + * ACPI: Add a generic API for _OSC -v2 + * ACPI: Add platform-wide _OSC support. + * ACPI: fix OSC regression that caused aer and pciehp not to load + * ACPI: Advertise to BIOS in _OSC: _OST on _PPC changes + * UBI: fix volume creation input checking + * e1000/e1000e: don't use small hardware rx buffers + * drm/i915: Reload hangcheck timer too for Ironlake + * Fix a leak in affs_fill_super() + * Fix failure exits in bfs_fill_super() + * fix oops in fs/9p late mount failure + * fix leak in romfs_fill_super() + * Fix remount races with symlink handling in affs + * fix affs parse_options() + * Fix failure exit in ipathfs + * mm: fix migratetype bug which slowed swapping + * FDPIC: Respect PT_GNU_STACK exec protection markings when creating + NOMMU stack + * Split 'flush_old_exec' into two functions + * sparc: TIF_ABI_PENDING bit removal + * x86: get rid of the insane TIF_ABI_PENDING bit + * Input: winbond-cir - remove dmesg spam + * x86: Disable HPET MSI on ATI SB700/SB800 + * iwlwifi: set default aggregation frame count limit to 31 + * drm/i915: only enable hotplug for detected outputs + * firewire: core: add_descriptor size check + * SECURITY: selinux, fix update_rlimit_cpu parameter + * regulator: Specify REGULATOR_CHANGE_STATUS for WM835x LED constraints + * x86: Add Dell OptiPlex 760 reboot quirk + - LP: #488319 + * x86: Add quirk for Intel DG45FC board to avoid low memory corruption + * x86/amd-iommu: Fix possible integer overflow + * clocksource: fix compilation if no GENERIC_TIME + * tcp: update the netstamp_needed counter when cloning sockets + * sky2: Fix oops in sky2_xmit_frame() after TX timeout + * net: restore ip source validation + * af_packet: Don't use skb after dev_queue_xmit() + * ax25: netrom: rose: Fix timer oopses + * KVM: allow userspace to adjust kvmclock offset + * oprofile/x86: add Xeon 7500 series support + * oprofile/x86: fix crash when profiling more than 28 events + * libata: retry link resume if necessary + * mm: percpu-vmap fix RCU list walking + * mm: purge fragmented percpu vmap blocks + * block: fix bio_add_page for non trivial merge_bvec_fn case + * Fix 'flush_old_exec()/setup_new_exec()' split + * random: drop weird m_time/a_time manipulation + * random: Remove unused inode variable + * block: fix bugs in bio-integrity mempool usage + * usb: r8a66597-hdc disable interrupts fix + * connector: Delete buggy notification code. + * be2net: Bug fix to support newer generation of BE ASIC + * be2net: Fix memset() arg ordering. + * mm: flush dcache before writing into page to avoid alias + * mac80211: fix NULL pointer dereference when ftrace is enabled + * imxfb: correct location of callbacks in suspend and resume + * mx3fb: some debug and initialisation fixes + * starfire: clean up properly if firmware loading fails + * kernel/cred.c: use kmem_cache_free + * uartlite: fix crash when using as console + * pktcdvd: removing device does not remove its sysfs dir + * ath9k: fix eeprom INI values override for 2GHz-only cards + * ath9k: fix beacon slot/buffer leak + * powerpc: TIF_ABI_PENDING bit removal + * NET: fix oops at bootime in sysctl code + * Linux 2.6.32.8 + + -- Andy Whitcroft Wed, 10 Feb 2010 18:56:52 +0000 + +linux (2.6.32-12.17) lucid; urgency=low + + [ Andy Whitcroft ] + + * restore linux-image prefix -- master + * enforce -- we require SELINUX enabled -- master + * enforce -- ensure APPARMOR is our default LSM -- master + * make doc package completely optional -- master + * make source package completely optional -- master + * make linux-libc-dev completly optional -- master + * convert package disable to a deps list -- master + * allow common headers to switch from indep to arch -- master + * convert binary package disable to a deps list -- master + * add configuration option for a full source build tree -- master + * add support for uImage kernels in package control scripts + * getabis -- cleanup and parameterise repository list -- master + * getabis -- move configuration to etc/getabi -- master + * kernelconfig -- move configuration to etc -- master + * rules -- make debian/debian.env master for branch name + * set the current branch name -- master + * pull back common debian.master files into debian -- master + * enforcer -- make the enforcement configuration common + * insert-changes -- correctly link to debian/rules in DROOT + + [ Colin Watson ] + + * future-proof ddeb handling against buildd changes + + [ Eric Miao ] + + * SAUCE: Make CONFIG_{OMNIBOOK, AVERATEC_5100P, PACKARDBELL_E5} depend on + X86 + + [ Loïc Minier ] + + * Add modules.builtin.bin to prerm rm list + - LP: #516584 + + [ Tim Gardner ] + + * [Config] Implement the amd64 preempt flavour + + [ Upstream Kernel Changes ] + + * syslog: distinguish between /proc/kmsg and syscalls + - LP: #515623 + * sfc: Fix polling for slow MCDI operations + * sfc: Fix conditions for MDIO self-test + * sfc: QT202x: Remove unreliable MMD check at initialisation + * sfc: Add workspace for GMAC bug workaround to MCDI MAC_STATS buffer + * sfc: Use fixed-size buffers for MCDI NVRAM requests + + -- Andy Whitcroft Fri, 05 Feb 2010 07:09:31 +0000 + +linux (2.6.32-12.16) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "SAUCE: acpi battery -- delay first lookup of the battery until + first use" + * SAUCE: acpi battery -- move first lookup asynchronous + - LP: #507211 + * [Config] update configs to cleanup generic configs + * [Config] disable CONFIG_X86_CPU_DEBUG for amd64 + * [Config] enable USER_NS + - LP: #480739, #509808 + + [ Heiko Carstens ] + + * (pre-stable) driver-core: fix devtmpfs crash on s390 + - LP: #512370 + + [ John Johansen ] + + * [Config] for server and virtual flavours make CONFIG_SCSI_SYM53C8XX_2=y + - LP: #494565 + * [Config] VIRTIO=y for server/virtual flavours + - LP: #494565 + + [ Kay Sievers ] + + * (pre-stable) Driver-Core: devtmpfs - set root directory mode to 0755 + - LP: #512370 + + [ Kees Cook ] + + * SAUCE: x86: brk away from exec rand area + - LP: #452175 + + [ Leann Ogasawara ] + + * [Upstream] e1000: enhance frame fragment detection + - CVE-2009-4536 + * [Upstream] e1000e: enhance frame fragment detection + - CVE-2009-4538 + + [ Sebastian Kapfer ] + + * (pre-stable) Input: ALPS - add interleaved protocol support (Dell E6x00 + series) + - LP: #296610 + + [ Upstream Kernel Changes ] + + * inotify: do not reuse watch descriptors + - LP: #485556 + * inotify: only warn once for inotify problems + * revert "drivers/video/s3c-fb.c: fix clock setting for Samsung SoC + Framebuffer" + * memcg: ensure list is empty at rmdir + * drm/i915: remove loop in Ironlake interrupt handler + * block: Fix incorrect reporting of partition alignment + * x86, mce: Thermal monitoring depends on APIC being enabled + * futexes: Remove rw parameter from get_futex_key() + * page allocator: update NR_FREE_PAGES only when necessary + * x86, apic: use physical mode for IBM summit platforms + * edac: i5000_edac critical fix panic out of bounds + * x86: SGI UV: Fix mapping of MMIO registers + * mfd: WM835x GPIO direction register is not locked + * mfd: Correct WM835x ISINK ramp time defines + * ALSA: hda - Fix missing capture mixer for ALC861/660 codecs + * V4L/DVB (13868): gspca - sn9c20x: Fix test of unsigned. + * reiserfs: truncate blocks not used by a write + * HID: add device IDs for new model of Apple Wireless Keyboard + * PCI/cardbus: Add a fixup hook and fix powerpc + * Input: pmouse - move Sentelic probe down the list + * asus-laptop: add Lenovo SL hotkey support + * sched: Fix cpu_clock() in NMIs, on !CONFIG_HAVE_UNSTABLE_SCHED_CLOCK + * sparc64: Fix NMI programming when perf events are active. + * sparc64: Fix Niagara2 perf event handling. + * i2c: Do not use device name after device_unregister + * i2c/pca: Don't use *_interruptible + * serial/8250_pnp: add a new Fujitsu Wacom Tablet PC device + * sched: Fix task priority bug + * vfs: Fix vmtruncate() regression + * Linux 2.6.32.5 + * x86, msr/cpuid: Register enough minors for the MSR and CPUID drivers + * V4L/DVB (13900): gspca - sunplus: Fix bridge exchanges. + * Staging: asus_oled: fix oops in 2.6.32.2 + * Staging: hv: fix smp problems in the hyperv core code + * tty: fix race in tty_fasync + * ecryptfs: use after free + * ecryptfs: initialize private persistent file before dereferencing + pointer + * nozomi: quick fix for the close/close bug + * serial: 8250_pnp: use wildcard for serial Wacom tablets + * usb: serial: fix memory leak in generic driver + * USB: fix bitmask merge error + * USB: Don't use GFP_KERNEL while we cannot reset a storage device + * USB: EHCI: fix handling of unusual interrupt intervals + * USB: EHCI & UHCI: fix race between root-hub suspend and port resume + * USB: add missing delay during remote wakeup + * USB: add speed values for USB 3.0 and wireless controllers + * ACPI: EC: Accelerate query execution + * ACPI: EC: Add wait for irq storm + * SCSI: enclosure: fix oops while iterating enclosure_status array + * drm/i915: Read the response after issuing DDC bus switch command + * drm/i915: try another possible DDC bus for the SDVO device with + multiple outputs + * block: bdev_stack_limits wrapper + * DM: Fix device mapper topology stacking + * x86/PCI/PAT: return EINVAL for pci mmap WC request for !pat_enabled + * USB: fix usbstorage for 2770:915d delivers no FAT + * vmalloc: remove BUG_ON due to racy counting of VM_LAZY_FREE + * perf timechart: Use tid not pid for COMM change + * perf events: Dont report side-band events on each cpu for + per-task-per-cpu events + * perf: Honour event state for aux stream data + * Linux 2.6.32.6 + + -- Andy Whitcroft Wed, 27 Jan 2010 16:40:23 +0000 + +linux (2.6.32-11.15) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "(pre-stable) drm/radeon/kms: fix crtc vblank update for r600" + * Revert "(pre-stable) sched: Fix balance vs hotplug race" + * Revert "[Upstream] acerhdf: Limit modalias matching to supported + boards" + * Revert "[Upstream] mmc: prevent dangling block device from accessing + stale queues" + * Revert "SAUCE: Fix nx_enable reporting" + * Revert "SAUCE: [x86] fix report of cs-limit nx-emulation" + * Revert "SAUCE: [x86] implement cs-limit nx-emulation for ia32" + * SAUCE: i915 -- disable powersave by default + - LP: #492392 + + [ Kees Cook ] + + * SAUCE: [x86] implement cs-limit nx-emulation for ia32 + - LP: #369978 + * SAUCE: [x86] fix report of cs-limit nx-emulation + - LP: #454285 + * SAUCE: Fix nx_enable reporting + - LP: #454285 + + [ Tim Gardner ] + + * [Upstream] b43: Declare all possible firmware files. + - LP: #488636 + * [Config] updateconfigs after adding pvscsi + - LP: #497156 + * [Config] CONFIG_BT=m + + [ Upstream Kernel Changes ] + + * Revert "x86: Side-step lguest problem by only building cmpxchg8b_emu + for pre-Pentium" + * SCSI: ipr: fix EEH recovery + * SCSI: qla2xxx: dpc thread can execute before scsi host has been added + * SCSI: st: fix mdata->page_order handling + * SCSI: fc class: fix fc_transport_init error handling + * sched: Fix task_hot() test order + * x86, cpuid: Add "volatile" to asm in native_cpuid() + * sched: Select_task_rq_fair() must honour SD_LOAD_BALANCE + * clockevents: Prevent clockevent_devices list corruption on cpu hotplug + * pata_hpt3x2n: fix clock turnaround + * pata_cmd64x: fix overclocking of UDMA0-2 modes + * ASoC: wm8974: fix a wrong bit definition + * sound: sgio2audio/pdaudiocf/usb-audio: initialize PCM buffer + * ALSA: hda - Fix missing capsrc_nids for ALC88x + * acerhdf: limit modalias matching to supported + - LP: #435958 + * ACPI: EC: Fix MSI DMI detection + * ACPI: Use the return result of ACPI lid notifier chain correctly + * powerpc: Handle VSX alignment faults correctly in little-endian mode + * ASoC: Do not write to invalid registers on the wm9712. + * drm/radeon: fix build on 64-bit with some compilers. + * USB: emi62: fix crash when trying to load EMI 6|2 firmware + * USB: option: support hi speed for modem Haier CE100 + * USB: Fix a bug on appledisplay.c regarding signedness + * USB: musb: gadget_ep0: avoid SetupEnd interrupt + * Bluetooth: Prevent ill-timed autosuspend in USB driver + * USB: rename usb_configure_device + * USB: fix bugs in usb_(de)authorize_device + * drivers/net/usb: Correct code taking the size of a pointer + * x86: SGI UV: Fix writes to led registers on remote uv hubs + * md: Fix unfortunate interaction with evms + * dma: at_hdmac: correct incompatible type for argument 1 of + 'spin_lock_bh' + * dma-debug: Do not add notifier when dma debugging is disabled. + * dma-debug: Fix bug causing build warning + * cifs: NULL out tcon, pSesInfo, and srvTcp pointers when chasing DFS + referrals + * x86/amd-iommu: Fix initialization failure panic + * ioat3: fix p-disabled q-continuation + * ioat2,3: put channel hardware in known state at init + * KVM: MMU: remove prefault from invlpg handler + * KVM: LAPIC: make sure IRR bitmap is scanned after vm load + * Libertas: fix buffer overflow in lbs_get_essid() + * iwmc3200wifi: fix array out-of-boundary access + * mac80211: fix propagation of failed hardware reconfigurations + * mac80211: fix WMM AP settings application + * mac80211: Fix IBSS merge + * cfg80211: fix race between deauth and assoc response + * ath5k: fix SWI calibration interrupt storm + * ath9k: wake hardware for interface IBSS/AP/Mesh removal + * ath9k: Fix TX queue draining + * ath9k: fix missed error codes in the tx status check + * ath9k: wake hardware during AMPDU TX actions + * ath9k: fix suspend by waking device prior to stop + * ath9k_hw: Fix possible OOB array indexing in gen_timer_index[] on + 64-bit + * ath9k_hw: Fix AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB and its shift value + in 0x4054 + * iwl3945: disable power save + * iwl3945: fix panic in iwl3945 driver + * iwlwifi: fix EEPROM/OTP reading endian annotations and a bug + * iwlwifi: fix more eeprom endian bugs + * iwlwifi: fix 40MHz operation setting on cards that do not allow it + * mac80211: fix race with suspend and dynamic_ps_disable_work + * NOMMU: Optimise away the {dac_,}mmap_min_addr tests + * 'sysctl_max_map_count' should be non-negative + * kernel/sysctl.c: fix the incomplete part of + sysctl_max_map_count-should-be-non-negative.patch + * V4L/DVB (13596): ov511.c typo: lock => unlock + * x86/ptrace: make genregs[32]_get/set more robust + * memcg: avoid oom-killing innocent task in case of use_hierarchy + * e100: Fix broken cbs accounting due to missing memset. + * ipv6: reassembly: use seperate reassembly queues for conntrack and + local delivery + * netfilter: fix crashes in bridge netfilter caused by fragment jumps + * hwmon: (sht15) Off-by-one error in array index + incorrect constants + * b43: avoid PPC fault during resume + * Keys: KEYCTL_SESSION_TO_PARENT needs TIF_NOTIFY_RESUME architecture + support + * sched: Fix balance vs hotplug race + * drm/radeon/kms: fix crtc vblank update for r600 + * drm: disable all the possible outputs/crtcs before entering KMS mode + * S390: dasd: support DIAG access for read-only devices + * xen: fix is_disconnected_device/exists_disconnected_device + * xen: improvement to wait_for_devices() + * xen: wait up to 5 minutes for device connetion + * orinoco: fix GFP_KERNEL in orinoco_set_key with interrupts disabled + * udf: Try harder when looking for VAT inode + * Add unlocked version of inode_add_bytes() function + * quota: decouple fs reserved space from quota reservation + * ext4: Convert to generic reserved quota's space management. + * ext4: fix sleep inside spinlock issue with quota and dealloc (#14739) + * x86, msr: Unify rdmsr_on_cpus/wrmsr_on_cpus + * cpumask: use modern cpumask style in drivers/edac/amd64_edac.c + * amd64_edac: unify MCGCTL ECC switching + * x86, msr: Add support for non-contiguous cpumasks + * x86, msr: msrs_alloc/free for CONFIG_SMP=n + * amd64_edac: fix driver instance freeing + * amd64_edac: make driver loading more robust + * amd64_edac: fix forcing module load/unload + * sched: Sched_rt_periodic_timer vs cpu hotplug + * ext4: Update documentation to correct the inode_readahead_blks option + name + * lguest: fix bug in setting guest GDT entry + * vmscan: do not evict inactive pages when skipping an active list scan + * ksm: fix mlockfreed to munlocked + * rt2x00: Disable powersaving for rt61pci and rt2800pci. + * generic_permission: MAY_OPEN is not write access + * Linux 2.6.32.3 + * untangle the do_mremap() mess + * fasync: split 'fasync_helper()' into separate add/remove functions + * ASoC: fix params_rate() macro use in several codecs + * modules: Skip empty sections when exporting section notes + * exofs: simple_write_end does not mark_inode_dirty + * nfsd: make sure data is on disk before calling ->fsync + * sunrpc: fix peername failed on closed listener + * SUNRPC: Fix up an error return value in + gss_import_sec_context_kerberos() + * SUNRPC: Fix the return value in gss_import_sec_context() + * sunrpc: on successful gss error pipe write, don't return error + * drm/i915: Update LVDS connector status when receiving ACPI LID event + * drm/i915: fix order of fence release wrt flushing + * drm/i915: Permit pinning whilst the device is 'suspended' + * drm: remove address mask param for drm_pci_alloc() + * drm/i915: Enable/disable the dithering for LVDS based on VBT setting + * drm/i915: Make the BPC in FDI rx/transcoder be consistent with that in + pipeconf on Ironlake + * drm/i915: Select the correct BPC for LVDS on Ironlake + * drm/i915: fix unused var + * rtc_cmos: convert shutdown to new pnp_driver->shutdown + * drivers/cpuidle/governors/menu.c: fix undefined reference to + `__udivdi3' + * cgroups: fix 2.6.32 regression causing BUG_ON() in cgroup_diput() + * lib/rational.c needs module.h + * dma-debug: allow DMA_BIDIRECTIONAL mappings to be synced with + DMA_FROM_DEVICE and + * kernel/signal.c: fix kernel information leak with print-fatal-signals=1 + * mmc_block: add dev_t initialization check + * mmc_block: fix probe error cleanup bug + * mmc_block: fix queue cleanup + * ALSA: hda - Fix ALC861-VD capture source mixer + * ALSA: ac97: Add Dell Dimension 2400 to Headphone/Line Jack Sense + blacklist + * ALSA: atiixp: Specify codec for Foxconn RC4107MA-RS2 + - LP: #498863 + * ASoC: Fix WM8350 DSP mode B configuration + * netfilter: ebtables: enforce CAP_NET_ADMIN + * netfilter: nf_ct_ftp: fix out of bounds read in update_nl_seq() + * hwmon: (coretemp) Fix TjMax for Atom N450/D410/D510 CPUs + * hwmon: (adt7462) Fix pin 28 monitoring + * quota: Fix dquot_transfer for filesystems different from ext4 + * xen: fix hang on suspend. + * iwlwifi: fix iwl_queue_used bug when read_ptr == write_ptr + * ath5k: Fix eeprom checksum check for custom sized eeproms + * cfg80211: fix syntax error on user regulatory hints + * iwl: off by one bug + * mac80211: add missing sanity checks for action frames + * drm/i915: remove render reclock support + * libertas: Remove carrier signaling from the scan code + * kernel/sysctl.c: fix stable merge error in NOMMU mmap_min_addr + * mac80211: fix skb buffering issue (and fixes to that) + * fix braindamage in audit_tree.c untag_chunk() + * fix more leaks in audit_tree.c tag_chunk() + * module: handle ppc64 relocating kcrctabs when CONFIG_RELOCATABLE=y + * ipv6: skb_dst() can be NULL in ipv6_hop_jumbo(). + * agp/intel-agp: Clear entire GTT on startup + * Linux 2.6.32.4 + * ethtool: Add reset operation + * gro: Name the GRO result enumeration type + * gro: Change all receive functions to return GRO result codes + * sfc: 10Xpress: Initialise pause advertising flags + * sfc: 10Xpress: Report support for pause frames + * sfc: Remove redundant header gmii.h + * sfc: Remove redundant hardware initialisation + * sfc: Rename Falcon-specific board code and types + * sfc: Remove boards.h, moving last remaining declaration to falcon.h + * sfc: Remove versioned bitfield macros + * sfc: Move RX data FIFO thresholds out of struct efx_nic_type + * sfc: Update hardware definitions for Siena + * sfc: Rename register I/O header and functions used by both Falcon and + Siena + * sfc: Eliminate indirect lookups of queue size constants + * sfc: Define DMA address mask explicitly in terms of descriptor field + width + * sfc: Move all TX DMA length limiting into tx.c + * sfc: Change order of device removal to reverse of probe order + * sfc: Remove declarations of nonexistent functions + * sfc: Move efx_xmit_done() declaration into correct stanza + * sfc: Move shared members of struct falcon_nic_data into struct efx_nic + * sfc: Maintain interrupt moderation values in ticks, not microseconds + * sfc: Removed kernel-doc for nonexistent member of efx_phy_operations + * sfc: Remove pointless abstraction of memory BAR number + * sfc: Remove incorrect assertion from efx_pci_remove_main() + * sfc: Remove unnecessary tests of efx->membase + * sfc: Move MTD probe after netdev registration and name allocation + * sfc: Remove unused code for non-autoneg speed/duplex switching + * sfc: Rename 'xfp' file and functions to reflect reality + * sfc: Really allow RX checksum offload to be disabled + * sfc: Feed GRO result into RX allocation policy and interrupt moderation + * sfc: Enable heuristic selection between page and skb RX buffers + * sfc: Remove pointless abstraction of memory BAR number (2) + * sfc: Remove redundant gotos from __efx_rx_packet() + * sfc: Remove ridiculously paranoid assertions + * sfc: Move assertions and buffer cleanup earlier in efx_rx_packet_lro() + * sfc: Record RX queue number on GRO path + * sfc: SFT9001: Reset LED configuration correctly after blinking + * sfc: Use a single blink implementation + * sfc: Rename efx_board::init_leds to init_phy and use for SFN4111T + * sfc: Make board information explicitly Falcon-specific + * sfc: Move definition of struct falcon_nic_data into falcon.h + * sfc: Move struct falcon_board into struct falcon_nic_data + * sfc: Move all I2C stuff into struct falcon_board + * sfc: Gather link state fields in struct efx_nic into new struct + efx_link_state + * sfc: Remove unnecessary casts to struct sk_buff * + * sfc: Remove redundant efx_xmit() function + * sfc: Combine high-level header files + * sfc: Log interrupt and reset type names, not numbers + * sfc: Fix descriptor cache sizes + * sfc: Treat all MAC registers as 128-bit + * sfc: Strengthen EFX_ASSERT_RESET_SERIALISED + * sfc: Comment corrections + * sfc: Remove unused constant + * sfc: Clean up struct falcon_board and struct falcon_board_data + * sfc: Fix bugs in RX queue flushing + * sfc: Remove unused function efx_flush_queues() + * sfc: Only switch Falcon MAC clocks as necessary + * sfc: Hold MAC lock for longer in efx_init_port() + * sfc: Split MAC stats DMA initiation and completion + * sfc: Move Falcon board/PHY/MAC monitoring code to falcon.c + * sfc: Simplify XMAC link polling + * sfc: Change MAC promiscuity and multicast hash at the same time + * sfc: Move inline comment into kernel-doc + * sfc: Do not set net_device::trans_start in self-test + * sfc: Simplify PHY polling + * sfc: QT202x: Reset before reading PHY id + * sfc: Replace MDIO spinlock with mutex + * sfc: Always start Falcon using the XMAC + * sfc: Limit some hardware workarounds to Falcon + * sfc: Remove EFX_WORKAROUND_9141 macro + * sfc: Remove another unused workaround macro + * sfc: Remove some redundant whitespace + * sfc: Decouple NIC revision number from Falcon PCI revision number + * sfc: Move descriptor cache base addresses to struct efx_nic_type + * sfc: Clean up RX event handling + * sfc: Remove redundant writes to INT_ADR_KER + * sfc: Remove duplicate hardware structure definitions + * sfc: Turn pause frame generation on and off at the MAC, not the RX FIFO + * sfc: Move Falcon NIC operations to efx_nic_type + * sfc: Refactor link configuration + * sfc: Generalise link state monitoring + * sfc: Add power-management and wake-on-LAN support + * sfc: Implement ethtool reset operation + * sfc: Add efx_nic_type operation for register self-test + * sfc: Add efx_nic_type operation for NVRAM self-test + * sfc: Add efx_nic_type operation for identity LED control + * sfc: Separate shared NIC code from Falcon-specific and rename + accordingly + * sfc: Fold falcon_probe_nic_variant() into falcon_probe_nic() + * sfc: Extend loopback mode enumeration + * sfc: Remove static PHY data and enumerations + * sfc: Extend MTD driver for use with new NICs + * sfc: Allow for additional checksum offload features + * sfc: Rename falcon.h to nic.h + * sfc: Move shared NIC code from falcon.c to new source file nic.c + * sfc: Add firmware protocol definitions (MCDI) + * sfc: Add support for SFC9000 family (1) + * sfc: Add support for SFC9000 family (2) + * sfc: Implement TSO for TCP/IPv6 + * sfc: Update version, copyright dates, authors + * drivers/net/sfc: Correct code taking the size of a pointer + * sfc: Move PHY software state initialisation from init() into probe() + * sfc: Include XGXS in XMAC link status check except in XGMII loopback + * sfc: Fix DMA mapping cleanup in case of an error in TSO + * sfc: QT2025C: Work around PHY bug + * sfc: QT2025C: Switch into self-configure mode when not in loopback + * sfc: QT2025C: Work around PHY firmware initialisation bug + * sfc: QT2025C: Add error message for suspected bad SFP+ cables + * sfc: Disable TX descriptor prefetch watchdog + * [SCSI] vmw_pvscsi: SCSI driver for VMware's virtual HBA. + - LP: #497156 + + -- Andy Whitcroft Tue, 19 Jan 2010 16:12:47 +0000 + +linux (2.6.32-10.14) lucid; urgency=low + + [ Alex Deucher ] + + * SAUCE: drm/radeon/kms: fix LVDS setup on r4xx + - LP: #493795 + + [ Andy Whitcroft ] + + * Revert "(pre-stable) acpi: Use the ARB_DISABLE for the CPU which model + id is less than 0x0f." + * config-check -- ensure the checks get run at build time + * config-check -- check the processed config during updateconfigs + * config-check -- CONFIG_SECCOMP may not be present + * TUN is now built in ignore + * SAUCE: acpi battery -- delay first lookup of the battery until first + use + * SAUCE: async_populate_rootfs: move rootfs init earlier + * ubuntu: AppArmor -- update to mainline 2010-01-06 + * SAUCE: move RLIMIT_CORE pipe dumper marker to 1 + - LP: #498525 + + [ Dave Airlie ] + + * (pre-stable) drm/radeon/kms: fix crtc vblank update for r600 + + [ Leann Ogasawara ] + + * Add asix to nic-usb-modules file + - LP: #499785 + + [ Peter Zijlstra ] + + * (pre-stable) sched: Fix balance vs hotplug race + + [ Tim Gardner ] + + * [Config] Enable CONFIG_FUNCTION_TRACER + - LP: #497989 + * [Config] Drop lpia from getabis + * [Config] Build in TUN/TAP driver + - LP: #499491 + * [Config] DH_COMPAT=5 + + [ Upstream Kernel Changes ] + + * Revert "(pre-stable) drm/i915: Avoid NULL dereference with + component_only tv_modes" + * Revert "(pre-stable) drm/i915: Fix sync to vblank when VGA output is + turned off" + * USB: usb-storage: fix bug in fill_inquiry + * USB: option: add pid for ZTE + * firewire: ohci: handle receive packets with a data length of zero + * rcu: Prepare for synchronization fixes: clean up for non-NO_HZ handling + of ->completed counter + * rcu: Fix synchronization for rcu_process_gp_end() uses of ->completed + counter + * rcu: Fix note_new_gpnum() uses of ->gpnum + * rcu: Remove inline from forward-referenced functions + * perf_event: Fix invalid type in ioctl definition + * perf_event: Initialize data.period in perf_swevent_hrtimer() + * perf: Don't free perf_mmap_data until work has been done + * PM / Runtime: Fix lockdep warning in __pm_runtime_set_status() + * sched: Check for an idle shared cache in select_task_rq_fair() + * sched: Fix affinity logic in select_task_rq_fair() + * sched: Rate-limit newidle + * sched: Fix and clean up rate-limit newidle code + * x86/amd-iommu: attach devices to pre-allocated domains early + * x86/amd-iommu: un__init iommu_setup_msi + * x86, Calgary IOMMU quirk: Find nearest matching Calgary while walking + up the PCI tree + * x86: Fix iommu=nodac parameter handling + * x86: GART: pci-gart_64.c: Use correct length in strncmp + * x86: ASUS P4S800 reboot=bios quirk + - LP: #366682 + * x86, apic: Enable lapic nmi watchdog on AMD Family 11h + * ssb: Fix range check in sprom write + * ath5k: allow setting txpower to 0 + * ath5k: enable EEPROM checksum check + * hrtimer: Fix /proc/timer_list regression + * ALSA: hrtimer - Fix lock-up + * ALSA: hda - Terradici HDA controllers does not support 64-bit mode + * KVM: x86 emulator: limit instructions to 15 bytes + * KVM: s390: Fix prefix register checking in arch/s390/kvm/sigp.c + * KVM: s390: Make psw available on all exits, not just a subset + * KVM: fix irq_source_id size verification + * KVM: x86: include pvclock MSRs in msrs_to_save + * x86: Prevent GCC 4.4.x (pentium-mmx et al) function prologue wreckage + * x86: Use -maccumulate-outgoing-args for sane mcount prologues + * x86, mce: don't restart timer if disabled + * x86/mce: Set up timer unconditionally + * x86: SGI UV: Fix BAU initialization + * x86: Fix duplicated UV BAU interrupt vector + * x86: Add new Intel CPU cache size descriptors + * x86: Fix typo in Intel CPU cache size descriptor + * pata_hpt{37x|3x2n}: fix timing register masks (take 2) + * s390: clear high-order bits of registers after sam64 + * V4L/DVB: Fix test in copy_reg_bits() + * bsdacct: fix uid/gid misreporting + * UBI: flush wl before clearing update marker + * jbd2: don't wipe the journal on a failed journal checksum + * USB: xhci: Add correct email and files to MAINTAINERS entry. + * USB: musb_gadget_ep0: fix unhandled endpoint 0 IRQs, again + * USB: option.c: add support for D-Link DWM-162-U5 + * USB: usbtmc: repeat usb_bulk_msg until whole message is transfered + * USB: usb-storage: add BAD_SENSE flag + * USB: Close usb_find_interface race v3 + * pxa/em-x270: fix usb hub power up/reset sequence + * hfs: fix a potential buffer overflow + * SUNRPC: IS_ERR/PTR_ERR confusion + * NFS: Fix nfs_migrate_page() + * md/bitmap: protect against bitmap removal while being updated. + * futex: Take mmap_sem for get_user_pages in fault_in_user_writeable + * devpts_get_tty() should validate inode + * debugfs: fix create mutex racy fops and private data + * Driver core: fix race in dev_driver_string + * Serial: Do not read IIR in serial8250_start_tx when UART_BUG_TXEN + * mac80211: Fix bug in computing crc over dynamic IEs in beacon + * mac80211: Fixed bug in mesh portal paths + * mac80211: Revert 'Use correct sign for mesh active path refresh' + * mac80211: fix scan abort sanity checks + * wireless: correctly report signal value for IEEE80211_HW_SIGNAL_UNSPEC + * rtl8187: Fix wrong rfkill switch mask for some models + * x86: Fix bogus warning in apic_noop.apic_write() + * mm: hugetlb: fix hugepage memory leak in mincore() + * mm: hugetlb: fix hugepage memory leak in walk_page_range() + * powerpc/windfarm: Add detection for second cpu pump + * powerpc/therm_adt746x: Record pwm invert bit at module load time] + * powerpc: Fix usage of 64-bit instruction in 32-bit altivec code + * drm/radeon/kms: Add quirk for HIS X1300 board + * drm/radeon/kms: handle vblanks properly with dpms on + * drm/radeon/kms: fix legacy crtc2 dpms + * drm/radeon/kms: fix vram setup on rs600 + * drm/radeon/kms: rs6xx/rs740: clamp vram to aperture size + * drm/ttm: Fix build failure due to missing struct page + * drm/i915: Set the error code after failing to insert new offset into mm + ht. + * drm/i915: Add the missing clonemask for display port on Ironlake + * xen/xenbus: make DEVICE_ATTR()s static + * xen: re-register runstate area earlier on resume. + * xen: restore runstate_info even if !have_vcpu_info_placement + * xen: correctly restore pfn_to_mfn_list_list after resume + * xen: register timer interrupt with IRQF_TIMER + * xen: register runstate on secondary CPUs + * xen: don't call dpm_resume_noirq() with interrupts disabled. + * xen: register runstate info for boot CPU early + * xen: call clock resume notifier on all CPUs + * xen: improve error handling in do_suspend. + * xen: don't leak IRQs over suspend/resume. + * xen: use iret for return from 64b kernel to 32b usermode + * xen: explicitly create/destroy stop_machine workqueues outside + suspend/resume region. + * Xen balloon: fix totalram_pages counting. + * xen: try harder to balloon up under memory pressure. + * dm exception store: free tmp_store on persistent flag error + * dm snapshot: only take lock for statustype info not table + * dm crypt: move private iv fields to structs + * dm crypt: restructure essiv error path + * dm: avoid _hash_lock deadlock + * dm snapshot: cope with chunk size larger than origin + * dm crypt: separate essiv allocation from initialisation + * dm crypt: make wipe message also wipe essiv key + * slc90e66: fix UDMA handling + * tcp: Stalling connections: Fix timeout calculation routine + * ip_fragment: also adjust skb->truesize for packets not owned by a + socket + * b44 WOL setup: one-bit-off stack corruption kernel panic fix + * sparc64: Don't specify IRQF_SHARED for LDC interrupts. + * sparc64: Fix overly strict range type matching for PCI devices. + * sparc64: Fix stack debugging IRQ stack regression. + * sparc: Set UTS_MACHINE correctly. + * b43legacy: avoid PPC fault during resume + * tracing: Fix event format export + * ath9k: Fix TX hang poll routine + * ath9k: fix processing of TX PS null data frames + * ath9k: Fix maximum tx fifo settings for single stream devices + * ath9k: fix tx status reporting + * mac80211: Fix dynamic power save for scanning. + * drm/i915: Fix sync to vblank when VGA output is turned off + * memcg: fix memory.memsw.usage_in_bytes for root cgroup + * thinkpad-acpi: fix default brightness_mode for R50e/R51 + * thinkpad-acpi: preserve rfkill state across suspend/resume + * ipw2100: fix rebooting hang with driver loaded + * matroxfb: fix problems with display stability + * acerhdf: add new BIOS versions + * asus-laptop: change light sens default values. + * vmalloc: conditionalize build of pcpu_get_vm_areas() + * ACPI: Use the ARB_DISABLE for the CPU which model id is less than 0x0f. + * net: Fix userspace RTM_NEWLINK notifications. + * ext3: Fix data / filesystem corruption when write fails to copy data + * V4L/DVB (13116): gspca - ov519: Webcam 041e:4067 added. + * bcm63xx_enet: fix compilation failure after get_stats_count removal + * x86: Under BIOS control, restore AP's APIC_LVTTHMR to the BSP value + * drm/i915: Avoid NULL dereference with component_only tv_modes + * drm/i915: PineView only has LVDS and CRT ports + * drm/i915: Fix LVDS stability issue on Ironlake + * mm: sigbus instead of abusing oom + * ipvs: zero usvc and udest + * jffs2: Fix long-standing bug with symlink garbage collection. + * intel-iommu: Detect DMAR in hyperspace at probe time. + * intel-iommu: Apply BIOS sanity checks for interrupt remapping too. + * intel-iommu: Check for an RMRR which ends before it starts. + * intel-iommu: Fix oops with intel_iommu=igfx_off + * intel-iommu: ignore page table validation in pass through mode + * netfilter: xtables: document minimal required version + * perf_event: Fix incorrect range check on cpu number + * implement early_io{re,un}map for ia64 + * Linux 2.6.32.2 + + -- Andy Whitcroft Thu, 07 Jan 2010 15:28:43 +0000 + +linux (2.6.32-9.13) lucid; urgency=low + + [ Andy Whitcroft ] + + * [Config] enable CONFIG_B43_PHY_LP + - LP: #493059 + * include modules.builtin in the binary debs + * config-check -- add a configuration enforcer + * config-check -- add a unit-test suite to the checker + * [Config] Enable CONFIG_SYN_COOKIES for versatile + * [Config] Enable CONFIG_SECURITY_SMACK for ports + * [Config] Enable CONFIG_SECURITY_FILE_CAPABILITIES for ports + * [Config] Disable CONFIG_COMPAT_BRK for ports + * getabis -- add armel versatile to the list + + [ Brad Figg ] + + * SAUCE: Increase the default prealloc buffer for HDA audio devices + (non-modem) + + [ Manoj Iyer ] + + * ubuntu: onmibook -- Added missing BOM file + + [ Tim Gardner ] + + * ubuntu: fsam7400 -- Cleanup Makefile + + [ Upstream Kernel Changes ] + + * Revert "ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT" + * signal: Fix alternate signal stack check + * SCSI: scsi_lib_dma: fix bug with dma maps on nested scsi objects + * SCSI: osd_protocol.h: Add missing #include + * SCSI: megaraid_sas: fix 64 bit sense pointer truncation + * ext4: fix potential buffer head leak when add_dirent_to_buf() returns + ENOSPC + * ext4: avoid divide by zero when trying to mount a corrupted file system + * ext4: fix the returned block count if EXT4_IOC_MOVE_EXT fails + * ext4: fix lock order problem in ext4_move_extents() + * ext4: fix possible recursive locking warning in EXT4_IOC_MOVE_EXT + * ext4: plug a buffer_head leak in an error path of ext4_iget() + * ext4: make sure directory and symlink blocks are revoked + * ext4: fix i_flags access in ext4_da_writepages_trans_blocks() + * ext4: journal all modifications in ext4_xattr_set_handle + * ext4: don't update the superblock in ext4_statfs() + * ext4: fix uninit block bitmap initialization when s_meta_first_bg is + non-zero + * ext4: fix block validity checks so they work correctly with meta_bg + * ext4: avoid issuing unnecessary barriers + * ext4: fix error handling in ext4_ind_get_blocks() + * ext4: make trim/discard optional (and off by default) + * ext4: make "norecovery" an alias for "noload" + * ext4: Fix double-free of blocks with EXT4_IOC_MOVE_EXT + * ext4: initialize moved_len before calling ext4_move_extents() + * ext4: move_extent_per_page() cleanup + * jbd2: Add ENOMEM checking in and for + jbd2_journal_write_metadata_buffer() + * ext4: Return the PTR_ERR of the correct pointer in + setup_new_group_blocks() + * ext4: Avoid data / filesystem corruption when write fails to copy data + * ext4: wait for log to commit when umounting + * ext4: remove blocks from inode prealloc list on failure + * ext4: ext4_get_reserved_space() must return bytes instead of blocks + * ext4: quota macros cleanup + * ext4: fix incorrect block reservation on quota transfer. + * ext4: Wait for proper transaction commit on fsync + * ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT + * ext4: Fix potential fiemap deadlock (mmap_sem vs. i_data_sem) + * Linux 2.6.32.1 + * kbuild: generate modules.builtin + * (pre-stable) drm/i915: Fix sync to vblank when VGA output is turned off + - LP: #494461 + * (pre-stable) drm/i915: Avoid NULL dereference with component_only + tv_modes + - LP: #494045 + + [ Zhao Yakui ] + + * (pre-stable) acpi: Use the ARB_DISABLE for the CPU which model id is + less than 0x0f. + - LP: #481765 + + -- Andy Whitcroft Thu, 17 Dec 2009 15:41:21 +0000 + +linux (2.6.32-8.12) lucid; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: AppArmor -- add linux/err.h for ERR_PTR + + -- Andy Whitcroft Sat, 12 Dec 2009 10:56:16 +0000 + +linux (2.6.32-8.11) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "SAUCE: default ATI Radeon KMS to off until userspace catches + up" + * Revert "SAUCE: AppArmor: Fix oops there is no tracer and doing unsafe + transition." + * Revert "SAUCE: AppArmor: Fix refcounting bug causing leak of creds" + * Revert "SAUCE: AppArmor: Fix cap audit_caching preemption disabling" + * Revert "SAUCE: AppArmor: Fix Oops when in apparmor_bprm_set_creds" + * Revert "SAUCE: AppArmor: Fix oops after profile removal" + * Revert "SAUCE: AppArmor: AppArmor disallows truncate of deleted files." + * Revert "SAUCE: AppArmor: AppArmor fails to audit change_hat correctly" + * Revert "SAUCE: AppArmor: Policy load and replacement can fail to alloc + mem" + * Revert "SAUCE: AppArmor: AppArmor wrongly reports allow perms as + denied" + * Revert "SAUCE: AppArmor: Fix mediation of "deleted" paths" + * Revert "SAUCE: AppArmor: Fix off by 2 error in getprocattr mem + allocation" + * Revert "SAUCE: AppArmor: Set error code after structure + initialization." + * Revert "AppArmor -- fix pstrace_may_access rename" + * Revert "ubuntu: AppArmor security module" + * Revert "SAUCE: Add config option to set a default LSM" + * Revert "ubuntu: fsam7400 -- sw kill switch driver" + * Revert "[Config] fsam7400 -- enable" + * Revert "[Config] AUFS -- enable" + * Revert "ubuntu: AUFS -- aufs2-30 20090727" + * Revert "ubuntu: AUFS -- export various core functions -- fixes" + * Revert "ubuntu: AUFS -- export various core functions" + * Revert "[Config] ubuntu/iscsitarget -- disable" + * Revert "[Config] iscsitarget -- enable" + * Revert "ubuntu: iscsitarget -- SVN revision r214" + * update Vcs-Git to point to the correct repository + - LP: #493589 + * update build environment overrides to lucid + - LP: #493589 + * [Config] enable CONFIG_DEVTMPFS + * [Config] update all configs following AppArmor 2009-12-08 update + * SAUCE: isapnp_init: make isa PNP scans occur async + * [Config] fsam7400 -- enable + * [Config] omnibook -- enable + * [Config] cleanup CONFIG_AUDIT + * ubuntu: AUFS -- export various core functions (aufs2-base.patch) + * ubuntu: AUFS -- export various core functions (aufs2-standalone.patch) + * ubuntu: AUFS -- aufs2 20091209 + * [Config] AUFS -- enable + * [Config] iscsitarget -- enable + + [ Arjan van de Ven ] + + * SAUCE: KMS: cache the EDID information of the LVDS + + [ Colin Watson ] + + * bnx2: update d-i firmware filenames + - LP: #494052 + * add cdc_ether to nic-usb-modules udeb + - LP: #495060 + + [ John Johansen ] + + * ubuntu: AppArmor -- mainline 2009-10-08 + + [ Manoj Iyer ] + + * ubuntu: fsam7400 -- kill switch for Fujitsu Siemens Amilo M 7400 + * ubuntu: omnibook -- support Toshiba (HP) netbooks + * ubuntu: iscsitarget --- version 1.4.19 + - LP: #494693 + + [ Surbhi Palande ] + + * SAUCE: Make populate_rootfs asynchronous + + [ Tim Gardner ] + + * Parallelize flavour builds and packaging + * [Config] Enable CONFIG_KSM + + [ Upstream Kernel Changes ] + + * Config option to set a default LSM + * LSM: Add security_path_chroot(). + * LSM: Add security_path_chroot(). + * LSM: Move security_path_chmod()/security_path_chown() to after + mutex_lock(). + * ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT + + -- Andy Whitcroft Fri, 11 Dec 2009 17:45:19 +0000 + +linux (2.6.32-7.10) lucid; urgency=low + + [ Andy Whitcroft ] + + * [Config] disable CONFIG_THUMB2_KERNEL to fix arm FTBFS + + -- Andy Whitcroft Sun, 06 Dec 2009 12:56:48 +0000 + +linux (2.6.32-7.9) lucid; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: set /proc/acpi/video/*/DOS to 4 by default + - LP: #458982 + * SAUCE: ensure vga16fb loads if no other driver claims the VGA device + * [Config] update configs following versatile switch to V7 + * rebased to v2.6.32 + * [Config] update configs following rebase to v2.6.32 + * [Config] update ports configs following rebase to v2.6.32 + * SAUCE: default ATI Radeon KMS to off until userspace catches up + + [ Arjan van de Ven ] + + * SAUCE: vfs: Add a trace point in the mark_inode_dirty function + + [ Leann Ogasawara ] + + * [SCSI] megaraid_sas: remove sysfs poll_mode_io world writeable + permissions + - CVE-2009-3939 + + [ Loic Minier ] + + * SAUCE: select a v7 CPU for versatile + + [ Takashi Iwai ] + + * SAUCE: ALSA: hda - Add power on/off counter + + [ Upstream changes ] + + * rebased to v2.6.32 + + -- Andy Whitcroft Fri, 04 Dec 2009 10:44:50 +0000 + +linux (2.6.32-6.8) lucid; urgency=low + + [ Andy Whitcroft ] + + * [Config] disable SSB devices for armel + + -- Andy Whitcroft Sat, 28 Nov 2009 12:16:40 +0000 + +linux (2.6.32-6.7) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "SAUCE: default ATI Radeon KMS to off until userspace catches up" + * Revert "SAUCE: Dell XPS710 reboot quirk" + * Revert "SAUCE: Link acpi-cpufreq.o first" + * Revert "SAUCE: LPIA Logical reset of USB port on resume" + * Revert "SAUCE: LPIA Reboot fix for Intel Crownbeach development boards" + * Revert "SAUCE: Enable HDMI audio codec on Studio XPS 1340" + * Revert "SAUCE: Dell laptop digital mic does not work, PCI 1028:0271" + * Revert "Add Dell Dimension 9200 reboot quirk" + * Revert "SAUCE: Correctly blacklist Thinkpad r40e in ACPI" + * Revert "SAUCE: tulip: Define ULI PCI ID's" + * Revert "SAUCE: Lower warning level of some PCI messages" + * Revert "mac80211: fix two issues in debugfs" + Drop a number of known redundant commits as identified in the Ubuntu + delta review blueprint. + + * reenable armel versatile flavour + * [Config] disable CONFIG_USB_DEVICEFS + + [ Tim Gardner ] + + * [Config] udeb: Add squashfs to fs-core-modules + - LP: #352615 + * [Config] Create a real squashfs udeb + - LP: #352615 + + + -- Andy Whitcroft Fri, 27 Nov 2009 17:31:16 +0000 + +linux (2.6.32-5.6) lucid; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.32-rc8 + * update configs following rebase to v2.6.32-rc8 + * update ports configs since rebase to v2.6.32-rc8 + * [Config] enable cgroup options + - LP: #480739 + + [ Upstream Kernel Changes ] + + * rebase to v2.6.32-rc8 + + -- Andy Whitcroft Mon, 23 Nov 2009 11:16:14 +0000 + +linux (2.6.32-4.5) lucid; urgency=low + + [ Andy Whitcroft ] + + * [Config] SERIO_LIBPS2 and SERIO_I8042 must match + * rebase to v2.6.32-rc7 + * resync with Karmic proposed + + [ John Johansen ] + + * SAUCE: AppArmor: Fix oops after profile removal + - LP: #475619 + * SAUCE: AppArmor: Fix Oops when in apparmor_bprm_set_creds + - LP: #437258 + * SAUCE: AppArmor: Fix cap audit_caching preemption disabling + - LP: #479102 + * SAUCE: AppArmor: Fix refcounting bug causing leak of creds + - LP: #479115 + * SAUCE: AppArmor: Fix oops there is no tracer and doing unsafe + transition. + - LP: #480112 + + [ Ubuntu Changes ] + + * resync with Karmic proposed (ddbc670a86a3dee18541a3734149f250ff307adf) + + [ Upstream Kernel Changes ] + + * rebase to v2.6.32-rc7 + + -- Andy Whitcroft Fri, 13 Nov 2009 11:35:13 +0000 + +linux (2.6.32-3.4) lucid; urgency=low + + [ Andy Whitcroft ] + + * [Config] SERIO_LIBPS2 and SERIO_I8042 must match + * [Upstream] add local prefix to oss local change_bits + + [ Upstream Kernel Changes ] + + * mtd/maps: gpio-addr-flash: pull in linux/ headers rather than asm/ + * mtd/maps: gpio-addr-flash: depend on GPIO arch support + + -- Andy Whitcroft Wed, 11 Nov 2009 14:47:04 +0000 + +linux (2.6.32-3.3) lucid; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.32-rc6 + * [Config] update configs following rebase to v2.6.32-rc6 + * [Config] update ports configs following rebase to v2.6.32-rc6 + * resync with Karmic Ubuntu-2.6.31-15.49 + * [Config] add module ignores for broken drivers + + [ John Johansen ] + + * SAUCE: AppArmor: AppArmor wrongly reports allow perms as denied + - LP: #453335 + * SAUCE: AppArmor: Policy load and replacement can fail to alloc mem + - LP: #458299 + * SAUCE: AppArmor: AppArmor fails to audit change_hat correctly + - LP: #462824 + * SAUCE: AppArmor: AppArmor disallows truncate of deleted files. + - LP: #451375 + + [ Kees Cook ] + + * SAUCE: Fix nx_enable reporting + - LP: #454285 + + [ Scott James Remnant ] + + * Revert "SAUCE: trace: add trace_event for the open() syscall" + * SAUCE: trace: add trace events for open(), exec() and uselib() + - LP: #462111 + + [ Stefan Bader ] + + * SAUCE: Fix sub-flavour script to not stop on missing directories + - LP: #453073 + + [ Ubuntu Changes ] + + * resync with Karmic Ubuntu-2.6.31-15.49 + + [ Upstream Kernel Changes ] + + * rebase to v2.6.32-rc6 + - LP: #464552 + + -- Andy Whitcroft Tue, 10 Nov 2009 15:00:57 +0000 + +linux (2.6.32-2.2) lucid; urgency=low + + [ Andy Whitcroft ] + + * install the full changelog with the binary package + * changelog -- explicitly note rebases and clean history + * reinstate armel.mk with no flavours + - LP: #449637 + * [Upstream] block: silently error unsupported empty barriers too + - LP: #420423 + * [Config] udate configs following karmic resync + * [Config] update ports configs following karmic resync + * [Upstream] lirc -- follow removal of .id element + + [ Colin Watson ] + + * Use section 'admin' rather than 'base' + * Add more e100 firmware to nic-modules + - LP: #451872 + * Add qla1280 firmware to scsi-modules + - LP: #381037 + + [ John Johansen ] + + * SAUCE: AppArmor: Set error code after structure initialization. + - LP: #427948 + * SAUCE: AppArmor: Fix off by 2 error in getprocattr mem allocation + - LP: #446595 + * SAUCE: AppArmor: Fix mediation of "deleted" paths + + [ Kees Cook ] + + * SAUCE: [x86] fix report of cs-limit nx-emulation + - LP: #454285 + + [ Leann Ogasawara ] + + * SAUCE: (drop after 2.6.31) input: Add support for filtering input + events + - LP: #430809 + * SAUCE: (drop after 2.6.31) dell-laptop: Trigger rfkill updates on wifi + toggle switch press + - LP: #430809 + + [ Luke Yelavich ] + + * SAUCE: Add sr_mod to the scsi-modules udeb for powerpc + * [Config] Add sd_mod to scsi-modules udeb for powerpc + + [ Mario Limonciello ] + + * SAUCE: Update to LIRC 0.8.6 + - LP: #432678 + * SAUCE: dell-laptop: Store the HW switch status internally rather than + requerying every time + - LP: #430809 + * SAUCE: dell-laptop: Blacklist machines not supporting dell-laptop + - LP: #430809 + + [ Stefan Bader ] + + * [Upstream] acerhdf: Limit modalias matching to supported boards + - LP: #435958 + + [ Tim Gardner ] + + * [Upstream] i915: Fix i2c init message + - LP: #409361 + * [Config] Add sym53c8xx.ko to virtual sub-flavour + - LP: #439415 + * [Config] Add d101m_ucode.bin to d-i/firmware/nic-modules + - LP: #439456 + * [Config] Set default I/O scheduler back to CFQ for desktop flavours + - LP: #381300 + * SAUCE: Created MODULE_EXPORT/MODULE_IMPORT macros + - LP: #430694 + * SAUCE: Use MODULE_IMPORT macro to tie intel_agp to i915 + - LP: #430694 + * [Config] CONFIG_GFS2_FS_LOCKING_DLM=y + - LP: #416325 + * SAUCE: Fix MODULE_IMPORT/MODULE_EXPORT + - LP: #430694 + * SAUCE: Raise the default console 'quiet' level to 2 + * [Config] CONFIG_X86_PAT=y + * [Config] Add armel arch to linux-libc-dev arches. + - LP: #449637 + * [Config] CONFIG_X86_MCE + * [Upstream] (drop after 2.6.31) Input: synaptics - add another Protege + M300 to rate blacklist + - LP: #433801 + + [ Upstream Kernel Changes ] + + * sgi-gru: Fix kernel stack buffer overrun, CVE-2009-2584 + * drm/i915: Fix FDI M/N setting according with correct color depth + - LP: #416792 + + -- Andy Whitcroft Thu, 22 Oct 2009 16:53:33 +0100 + +linux (2.6.32-1.1) lucid; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.32-rc3 + * [Config] update configs following rebase to 2.6.32-rc3 + * [Config] update ports configs following rebase to 2.6.32-rc3 + * AppArmor -- fix pstrace_may_access rename + * staging/android -- disable + * ubuntu: dm-raid-45 -- update to compile with 2.6.32 + * ubuntu: drbd -- disable + * staging/comdi -- disable + * staging/go7007 -- disable + * [Config] staging/winbond -- disable + * [Config] ubuntu/iscsitarget -- disable + * [d-i] cbc and ecb are builtin make them optional in udebs + * rebase to v2.6.32-rc5 + * [Config] update configs following rebase to v2.6.32-rc5 + * [Config] update ports configs following rebase to v2.6.31-rc5 + + [ Tim Gardner ] + + * [Config] Add cpio as a build dependency. + + [ Upstream Kernel Changes ] + + * rebase to v2.6.32-rc3 + * rebase to v2.6.32-rc5 + + -- Andy Whitcroft Mon, 05 Oct 2009 15:48:58 +0100 + +linux (2.6.31-11.37) karmic; urgency=low + + [ Tim Gardner ] + + * [Config] Increase kernel log buffer to 256K for amd64 flavours + - LP: #424810 + * [Config] Set HZ=100 for amd64 flavours + - LP: #438234 + * [Upstream] e1000e: Emit notice instead of an error when + pci_enable_pcie_error_reporting() fails + - LP: #436370 + + [ Upstream Kernel Changes ] + + * n_tty: honor opost flag for echoes + * n_tty: move echoctl check and clean up logic + - LP: #438310 + + * Revert "[Upstream] drm/i915: Check that the relocation points to within + the target" - Use upstream cherry-pick. + * drm/i915: Check that the relocation points to within the target + - LP: #429241 + + * drm/i915: fix tiling on IGDNG + * drm/i915: add B43 chipset support + * agp/intel: Add B43 chipset support + Intel request from kernel team mailing list. + + * HID: completely remove apple mightymouse from blacklist + - LP: #428111 + + -- Tim Gardner Mon, 28 Sep 2009 11:47:29 -0600 + +linux (2.6.31-11.36) karmic; urgency=low + + [ Brian Rogers ] + + * SAUCE: (drop after 2.6.31) em28xx: ir-kbd-i2c init data needs a + persistent object + * SAUCE: (drop after 2.6.31) saa7134: ir-kbd-i2c init data needs a + persistent object + + [ Takashi Iwai ] + + * [Upstream] ALSA: hda - Add another entry for Nvidia HDMI device + - LP: #416482 + + [ Tyler Hicks ] + + * SAUCE: (drop after 2.6.31) eCryptfs: Prevent lower dentry from going + negative during unlink + + [ Upstream Kernel Changes ] + + * sg: fix oops in the error path in sg_build_indirect() + * mpt2sas : Rescan topology from Interrupt context instead of work thread + * mpt2sas: Prevent sending command to FW while Host Reset + * mpt2sas: setting SDEV into RUNNING state from Interrupt context + * mpt2sas: Raid 10 Volume is showing as Raid 1E in dmesg + * SCSI: fix oops during scsi scanning + * SCSI: libsrp: fix memory leak in srp_ring_free() + * cfg80211: fix looping soft lockup in find_ie() + * ath5k: write PCU registers on initial reset + * binfmt_elf: fix PT_INTERP bss handling + * TPM: Fixup boot probe timeout for tpm_tis driver + * md: Fix "strchr" [drivers/md/dm-log-userspace.ko] undefined! + * x86/amd-iommu: fix broken check in amd_iommu_flush_all_devices + * fix undefined reference to user_shm_unlock + * perf_counter: Fix buffer overflow in perf_copy_attr() + * perf_counter: Start counting time enabled when group leader gets + enabled + * powerpc/perf_counters: Reduce stack usage of power_check_constraints + * powerpc: Fix bug where perf_counters breaks oprofile + * powerpc/ps3: Workaround for flash memory I/O error + * block: don't assume device has a request list backing in nr_requests + store + * agp/intel: remove restore in resume + * ALSA: cs46xx - Fix minimum period size + * ASoC: Fix WM835x Out4 capture enumeration + * sound: oxygen: work around MCE when changing volume + * mlx4_core: Allocate and map sufficient ICM memory for EQ context + * perf stat: Change noise calculation to use stddev + * x86: Fix x86_model test in es7000_apic_is_cluster() + * x86/i386: Make sure stack-protector segment base is cache aligned + * PCI: apply nv_msi_ht_cap_quirk on resume too + * x86, pat: Fix cacheflush address in change_page_attr_set_clr() + * ARM: 5691/1: fix cache aliasing issues between kmap() and kmap_atomic() + with highmem + * KVM guest: do not batch pte updates from interrupt context + * KVM: Fix coalesced interrupt reporting in IOAPIC + * KVM: VMX: Check cpl before emulating debug register access + * KVM guest: fix bogus wallclock physical address calculation + * KVM: x86: Disallow hypercalls for guest callers in rings > 0 + * KVM: VMX: Fix cr8 exiting control clobbering by EPT + * KVM: x86 emulator: Implement zero-extended immediate decoding + * KVM: MMU: make __kvm_mmu_free_some_pages handle empty list + * KVM: x86 emulator: fix jmp far decoding (opcode 0xea) + * KVM: limit lapic periodic timer frequency + * libata: fix off-by-one error in ata_tf_read_block() + * PCI quirk: update 82576 device ids in SR-IOV quirks list + * PCI: Unhide the SMBus on the Compaq Evo D510 USDT + * powerpc/pseries: Fix to handle slb resize across migration + * Linux 2.6.31.1 + + -- Tim Gardner Thu, 24 Sep 2009 13:04:28 -0600 + +linux (2.6.31-10.35) karmic; urgency=low + + [ Amit Kucheria ] + + * Disable CONFIG_UEVENT_HELPER_PATH + + [ Andy Whitcroft ] + + * [Config] Enable CONFIG_USB_GADGET_DUMMY_HCD + * remove the tlsup driver + * remove lmpcm logitech driver support + + [ Bryan Wu ] + + * Add 3 missing files to prerm remove file list + - LP: #345623, #415832 + + [ Chris Wilson ] + + * [Upstream] drm/i915: Check that the relocation points to within the + target + - LP: #429241 + + [ Luke Yelavich ] + + * [Config] Set CONFIG_EXT4_FS=y on ports architectures + + [ Manoj Iyer ] + + * SAUCE: Added quirk to recognize GE0301 3G modem as an interface. + - LP: #348861 + + [ Tim Gardner ] + + * Revert "[Upstream] ACPI: Add Thinkpad W500, W700, & W700ds to OSI(Linux) white-list" + * Revert "[Upstream] ACPI: Add Thinkpad R400 & Thinkpad R500 to OSI(Linux) white-list" + * Revert "[Upstream] ACPI: Add Thinkpad X300 & Thinkpad X301 to OSI(Linux) white-list" + * Revert "[Upstream] ACPI: Add Thinkpad X200, X200s, X200t to OSI(Linux) white-list" + * Revert "[Upstream] ACPI: Add Thinkpad T400 & Thinkpad T500 to OSI(Linux) white-list" + Upstream suggests that this is not the right approach. + + * [Config] Set default I/O scheduler to DEADLINE + CFQ seems to have some load related problems which are often exacerbated by sreadahead. + - LP: #381300 + + [ ubuntu@tjworld.net ] + + * SAUCE: ipw2200: Enable LED by default + - LP: #21367 + + [ Upstream Kernel Changes ] + + * ALSA: hda - Add support for new AMD HD audio devices + - LP: #430564 + + -- Andy Whitcroft Wed, 16 Sep 2009 15:37:49 +0100 + +linux (2.6.31-10.34) karmic; urgency=low + + [ Ted Tso ] + + * [Upstream] ext3: Don't update superblock write time when filesystem is + read-only + - LP: #427822 + + -- Tim Gardner Tue, 15 Sep 2009 16:00:45 -0600 + +linux (2.6.31-10.33) karmic; urgency=low + + [ Leann Ogasawara ] + + * [Upstream] dvb-usb: fix tuning with Cinergy T2 + - LP: #421258 + + [ Tim Gardner ] + + * [Config] Unconditionally copy files from sub-flavours lists. + (really, really fix it this time) + - LP: #423426 + * [Config] Set CONFIG_CACHEFILES=m for all flavours + + [ Upstream Kernel Changes ] + + * ext4: Don't update superblock write time when filesystem is read-only + - LP: #427822 + + -- Tim Gardner Tue, 15 Sep 2009 07:50:21 -0600 + +linux (2.6.31-10.32) karmic; urgency=low + + [ Eric Miao ] + + * [Config] enable module support for memory stick + - LP: #159951 + + [ Tim Gardner ] + + * [Config] Unconditionally copy files from sub-flavours lists. + - LP: #423426 + + -- Tim Gardner Thu, 10 Sep 2009 15:57:55 -0600 + +linux (2.6.31-10.31) karmic; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.31 final + + [ Colin Watson ] + + * [Config] Recommend grub-pc in linux-image + - LP: #385741 + + [ Ike Panhc ] + + * [Upstream] Pull latest update of lenovo-sl-laptop + + [ Peter Feuerer ] + + * [Upstream] (drop after 2.6.31) acerhdf: fix fan control for AOA150 + model + - LP: #426691 + + [ Tim Gardner ] + + * [Config] De-macro some package names. + + [ Upstream Changes ] + + * rebase to 2.6.31 final. + + -- Andy Whitcroft Thu, 10 Sep 2009 09:38:10 +0100 + +linux (2.6.31-10.30) karmic; urgency=low + + [ Amit Kucheria ] + + * [Config] Enable CONFIG_USB_DEVICEFS + - LP: #417748 + * [Config] Populate the config-update template a bit more + + [ Andy Whitcroft ] + + * rebase to v2.6.31-rc9 + * [Config] update configs following rebase to v2.6.31-rc9 + * [Config] update ports configs following rebase to v2.6.31-rc9 + + [ Colin Ian King ] + + * SAUCE: wireless: hostap, fix oops due to early probing interrupt + - LP: #254837 + + [ Jerone Young ] + + * [Upstream] ACPI: Add Thinkpad T400 & Thinkpad T500 to OSI(Linux) + white-list + - LP: #281732 + * [Upstream] ACPI: Add Thinkpad X200, X200s, X200t to OSI(Linux) + white-list + - LP: #281732 + * [Upstream] ACPI: Add Thinkpad X300 & Thinkpad X301 to OSI(Linux) + white-list + - LP: #281732 + * [Upstream] ACPI: Add Thinkpad R400 & Thinkpad R500 to OSI(Linux) + white-list + - LP: #281732 + * [Upstream] ACPI: Add Thinkpad W500, W700, & W700ds to OSI(Linux) + white-list + - LP: #281732 + + [ John Johansen ] + + * SAUCE: AppArmor: Fix profile attachment for regexp based profile names + - LP: #419308 + * SAUCE: AppArmor: Return the correct error codes on profile + addition/removal + - LP: #408473 + * SAUCE: AppArmor: Fix OOPS in profile listing, and display full list + - LP: #408454 + * SAUCE: AppArmor: Fix mapping of pux to new internal permission format + - LP: #419222 + * SAUCE: AppArmor: Fix change_profile failure + - LP: #401931 + * SAUCE: AppArmor: Tell git to ignore generated include files + - LP: #419505 + + [ Stefan Bader ] + + * [Upstream] acpi: video: Loosen strictness of video bus detection code + - LP: #333386 + * SAUCE: Remove ov511 driver from ubuntu subdirectory + + [ Tim Gardner ] + + * [Config] Exclude char-modules from non-x86 udeb creation + * SAUCE: Notify the ACPI call chain of AC events + * [Config] CONFIG_SATA_VIA=m + - LP: #403385 + * [Config] Build in all phylib support modules. + * [Config] Don't fail when sub-flavour files are missing + - LP: #423426 + * [Config] Set CONFIG_LSM_MMAP_MIN_ADDR=0 + - LP: #423513 + + [ Upstream ] + + * Rebased against v2.6.31-rc9 + + -- Andy Whitcroft Mon, 07 Sep 2009 11:33:45 +0100 + +linux (2.6.31-9.29) karmic; urgency=low + + [ Leann Ogasawara ] + + * [Upstream] agp/intel: support for new chip variant of IGDNG mobile + - LP: #419993 + * [Config] d-i/modules: Add new char-modules file, initialize with + intel-agp + - LP: #420605 + + [ Upstream ] + + * Rebased against 2.6.31-rc8 plus some inotify regression patches: + up through git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git + adda766193ea1cf3137484a9521972d080d0b7af. + + -- Tim Gardner Fri, 28 Aug 2009 06:31:30 -0600 + +linux (2.6.31-8.28) karmic; urgency=low + + [ Ike Panhc ] + + * [Config] Let nic-shared-modules depends on crypto-modules + - LP: #360966 + + [ Leann Ogasawara ] + + * [Upstream] (drop after 2.6.31) drm/i915: increase default latency + constant + - LP: #412492 + + [ Mario Limonciello ] + + * [Upstream]: (drop after 2.6.31) dell-laptop: don't change softblock + status if HW switch is disabled + - LP: #418721 + * [Upstream]: (drop after 2.6.31) compal-laptop: Add support for known + Compal made Dell laptops + * [Upstream]: (drop after 2.6.31) compal-laptop: Replace sysfs support + with rfkill support + + [ Tim Gardner ] + + * [Config] Add acpiphp to virtual sub-flavour + - LP: #364916 + * Drop KSM patch set for now because of instabilities with encrypted swap. + - LP: #418781 + + -- Tim Gardner Wed, 26 Aug 2009 08:14:26 -0600 + +linux (2.6.31-7.27) karmic; urgency=low + + [ Tim Gardner ] + + * [Config] updateconfigs updateportsconfigs after 2.6.31-rc7 rebase + * SAUCE: (drop after 2.6.31) Added KSM from mmotm-2009-08-20-19-18 + Replaces previous ksm patches from 2.6.31-6.25 + * [Config] KSM=y + + [ Upstream ] + + * Rebased against v2.6.31-rc7 + + -- Tim Gardner Sat, 22 Aug 2009 20:32:11 -0600 + +linux (2.6.31-6.26) karmic; urgency=low + + [ Andy Whitcroft ] + + * [Config] enable CONFIG_AUFS_BR_RAMFS + - LP: #414738 + * split out debian directory ready for abstraction + * add printdebian target to find branch target + * abstracted debian -- debian/files is not abstracted + * abstracted debian -- packages must be built in debian/ + * abstracted debian -- kernel-wedge needs to work in debian/ + * abstracted debian -- ensure we install the copyright file + * abstracted-debian -- drop the debian directories from headers + * abstracted-debian -- drop the debian directories from headers part 2 + * SAUCE: ubuntu-insert-changes -- follow abstracted debian + * [Upstream] aoe: ensure we initialise the request_queue correctly V2 + - LP: #410198 + + [ Luke Yelavich ] + + * [Config] Ports: Disable CONFIG_CPU_FREQ_DEBUG on powerpc-smp + * [Config] Ports: Re-enable windfarm modules on powerpc64-smp + - LP: #413150 + * [Config] Ports: Build all cpu frequency scaling governors into ports + kernels + * [Config] Ports: Build ext2 and ext3 modules into ports kernels + * [Config] Ports: CONFIG_PACKET=y for all ports kernels + * [Config] Ports: Enable PS3 network driver + + [ Stefan Bader ] + + * abstracted debian -- call $(DEBIAN)/rules using make + + [ Tim Gardner ] + + * [Config] Abstract the debian directory + * SAUCE: Improve error reporting in postinst + - LP: #358564 + + -- Tim Gardner Sun, 16 Aug 2009 20:33:28 -0600 + +linux (2.6.31-6.25) karmic; urgency=low + + [ Andy Whitcroft ] + + * script to generate Ubuntu changes from changelog + * [Config] standardise ANDROID options + * [Config] standardise CONFIG_ATM as module + * [Config] standardise CONFIG_LIB80211 as module + * [Config] disable CONFIG_PRINT_QUOTA_WARNING + * [Config] set CONFIG_CRAMFS as module + * [Config] enable CONFIG_DAB and modules + * [Config] set CONFIG_MAC80211_HWSIM as module + * [Config] set CONFIG_NET_CLS_FLOW as module + * [Config] set CONFIG_NF_CONNTRACK_SANE as module + * [Config] set CONFIG_NF_CT_PROTO_DCCP as module + * [Config] set CONFIG_RTC_DRV_DS1511 as module + * [Config] set CONFIG_RTC_DRV_R9701 as module + * [Config] set CONFIG_RTC_DRV_S35390A as module + * [Config] set CONFIG_TOIM3232_DONGLE as module + * [Config] standardise CONFIG_USB_MIDI_GADGET as module + * [Config] standardise CONFIG_USB_G_PRINTER as module + * [Config] standardise CONFIG_USB_SERIAL_IR as module + * [Config] set CONFIG_USB_SERIAL_IUU as module + * [Config] standardise CONFIG_USB_STORAGE_CYPRESS_ATACB as module + * [Config] standardise CONFIG_USB_STORAGE_ONETOUCH as module + * cleanup remains of dm-loop + * drop thinkpad ec and smapi support + * drop appleir + * [Config] update configs following rebase to v2.6.31-rc6 + * rebase to v2.6.31-rc6 + + [ Hugh Dickins ] + + * SAUCE: ksm patch 1, drop after 2.6.31 + * SAUCE: ksm patch 2, drop after 2.6.31 + * SAUCE: ksm patch 3, drop after 2.6.31 + * SAUCE: ksm patch 4, drop after 2.6.31 + * SAUCE: ksm patch 5, drop after 2.6.31 + * SAUCE: ksm patch 7, drop after 2.6.31 + + [ Izik Eidus ] + + * SAUCE: ksm patch 0, drop after 2.6.31 + * SAUCE: ksm patch 6, drop after 2.6.31 + * SAUCE: ksm patch 8, drop after 2.6.31 + * SAUCE: ksm patch 9, drop after 2.6.31 + + [ Luke Yelavich ] + + * [Config] Ports: Re-add PS3 modules to udebs + + [ Michael Casadevall ] + + * [Config] Update SPARC config and d-i files to reflect what can be built + + [ Tim Gardner ] + + * [Config] Removed armel package support + * [Config] Enabled CONFIG_KSM=y + + [ Upstream Kernel Changes ] + + * Rebased against v2.6.31-rc6 + * ARM: Cleanup: Revert "ARM: Add more cache memory types macros" + * ARM: Cleanup: Revert "Do not use OOB with MLC NAND" + * ARM: Cleanup: Revert "ARM: Make ARM arch aware of ubuntu/ drivers" + * ARM: Cleanup: Revert "ARM: IMX51: Make video capture drivers compile" + * ARM: Cleanup: Revert "ARM: IMX51: Fix isl29003 HWMON driver for i2c + changes" + * ARM: Cleanup: Revert "ARM: IMX51: IPU irq handler deadlock fix" + * ARM: Cleanup: Revert "ARM: IMX51: Babbage 2.5 needs a different system + revision" + * ARM: Cleanup: Revert "ARM: IMX51: Compile-in the IMX51 cpufreq driver + by default" + * ARM: Cleanup: Revert "ARM: IMX51: Enable ZONE_DMA for ARCH_MXC" + * ARM: Cleanup: Revert "ARM: IMX51: Make ARCH_MXC auto-enable + ARCH_MXC_CANONICAL" + * ARM: Cleanup: Revert "ARM: IMX51: Unconditionally disable + CONFIG_GPIOLIB" + * ARM: Cleanup: Revert "ARM: IMX51: Minimal changes for USB to work on + 2.6.31" + * ARM: Cleanup: Revert "ARM: IMX51: Fix plat-mxc/timer.c to handle imx51" + * ARM: Cleanup: Revert "ARM: IMX51: Make it compile." + * ARM: Cleanup: Revert "ARM: IMX51: Clean-up the craziness of including + mxc_uart.h _everywhere_" + * ARM: Cleanup: Revert "ARM: IMX51: Move board-mx51* header files to the + correct location" + * ARM: Cleanup: Revert "ARM: IMX51: Changed from snd_card_new to + snd_card_create" + * ARM: Cleanup: Revert "ARM: IMX51: Fix up merge error in Kconfig" + * ARM: Cleanup: Revert "ARM: IMX51: mxc_timer_init prototype" + * ARM: Cleanup: Revert "ARM: IMX51: Removed the mxc_gpio_port structure." + * ARM: Cleanup: Revert "ARM: IMX51: Added external declaration for + mxc_map_io." + * ARM: Cleanup: Revert "ARM: IMX51: Get to bus_id by calling dev_name." + * ARM: Cleanup: Revert "ARM: IMX51: Get to bus_id by calling dev_name." + * ARM: Cleanup: Revert "ARM: IMX51: snd_soc_machine structure replaced + with snd_soc_card." + * ARM: Cleanup: Revert "ARM: IMX51: codec structure was moved to the card + structure" + * ARM: Cleanup: Revert "ARM: IMX51: Hack to add defines for + DMA_MODE_READ/WRITE/MASK" + * ARM: Cleanup: Revert "ARM: IMX51: Add SoC and board support for + Freescale mx51 platform" + * Driver core: add new device to bus's list before probing + * [Upstream] (drop after 2.6.31) ALSA: hda - Reduce click noise at + power-saving + - LP: #381693, #399750, #380892 + + -- Andy Whitcroft Fri, 14 Aug 2009 11:32:23 +0100 + +linux (2.6.31-5.24) karmic; urgency=low + + [ Amit Kucheria ] + + * ARM: IMX51: Make video capture drivers compile + * [Config] IMX51: Config updates + + [ Andy Whitcroft ] + + * remove leftovers of dm-bbr + + [ Leann Ogasawara ] + + * Add pata_cs5535 to pata-modules + - LP: #318805 + + [ Luke Yelavich ] + + * [Config] CONFIG_PPC64=y for powerpc64-smp + * [Config] Set the maximum number of CPUs to 1024 for powerpc64-smp + * [Config] CONFIG_PPC_PS3=y for powerpc64-smp + * [Config] CONFIG_PPC_MAPLE=y on powerpc64-smp + * [Config] CONFIG_PPC_PASEMI=y on powerpc64-smp + * [Config] CONFIG_CPU_FREQ_PMAC64=y on powerpc64-smp + * [Config] Enable all PS3 drivers in powerpc64-smp + + [ Mario Limonciello ] + + * LIRC -- fix lirc-i2c 2.6.31 compilation + + [ Matthew Garrett ] + + * [Upstream] dell-laptop: Fix rfkill state queries + + [ Tim Gardner ] + + * [Config] Ignore armel ABI and module changes + * [Config] Update configs after rebase against 2.6.31-rc5 + + [ Upstream ] + + * Rebased to 2.6.31-rc5 + + -- Andy Whitcroft Tue, 28 Jul 2009 10:10:09 +0100 + +linux (2.6.31-4.23) karmic; urgency=low + + [ Andy Whitcroft ] + + * AUFS -- update to aufs2-30 20090727 + * [Config] enable AUFS FUSE support + + [ Luke Yelavich ] + + * [Config] CONFIG_JFS_FS=m on sparc + + [ Tim Gardner ] + + * [Upstream] dell-laptop: Fix rfkill state setting. + + -- Andy Whitcroft Mon, 27 Jul 2009 11:11:47 +0100 + +linux (2.6.31-4.22) karmic; urgency=low + + [ Amit Kucheria ] + + * ARM: IMX51: Add SoC and board support for Freescale mx51 platform + * ARM: IMX51: Move board-mx51* header files to the correct location + * ARM: IMX51: Clean-up the craziness of including mxc_uart.h _everywhere_ + * ARM: IMX51: Make it compile. + * ARM: IMX51: Unconditionally disable CONFIG_GPIOLIB + * ARM: IMX51: Make ARCH_MXC auto-enable ARCH_MXC_CANONICAL + * ARM: IMX51: Enable ZONE_DMA for ARCH_MXC + * ARM: IMX51: Compile-in the IMX51 cpufreq driver by default + * ARM: IMX51: Fix isl29003 HWMON driver for i2c changes + * ARM: USB: musb: Refer to musb_otg_timer_func under correct #ifdef + * ARM: staging: udlfb: Add vmalloc.h include + * UBUNTU [Config]: Bring imx51 config upto date with other flavours + + [ Brad Figg ] + + * ARM: IMX51: Hack to add defines for DMA_MODE_READ/WRITE/MASK + * ARM: IMX51: codec structure was moved to the card structure + * ARM: IMX51: snd_soc_machine structure replaced with snd_soc_card. + * ARM: IMX51: Get to bus_id by calling dev_name. + * ARM: IMX51: Get to bus_id by calling dev_name. + * ARM: IMX51: Added external declaration for mxc_map_io. + * ARM: IMX51: Removed the mxc_gpio_port structure. + * ARM: IMX51: mxc_timer_init prototype + * ARM: IMX51: Fix up merge error in Kconfig + * ARM: IMX51: Changed from snd_card_new to snd_card_create + + [ Dinh Nguyen ] + + * ARM: IMX51: Fix plat-mxc/timer.c to handle imx51 + * ARM: IMX51: Minimal changes for USB to work on 2.6.31 + * ARM: IMX51: Babbage 2.5 needs a different system revision + * ARM: IMX51: IPU irq handler deadlock fix + + [ Tim Gardner ] + + * [Config] Enabled CONFIG_CAN=m + - LP: #327243 + * [Config] Enabled CONFIG_SERIAL=m + - LP: #397189 + + -- Tim Gardner Fri, 24 Jul 2009 06:19:10 -0600 + +linux (2.6.31-4.21) karmic; urgency=low + + [ Amit Kucheria ] + + * dm-raid-4-5: Add missing brackets around test_bit() + + [ John Johansen ] + + * AppArmor: Fix change_profile failing lpn401931 + * AppArmor: Fix determination of forced AUDIT messages. + * AppArmor: Fix oops in auditing of the policy interface offset + + -- Andy Whitcroft Thu, 23 Jul 2009 19:18:30 +0100 + +linux (2.6.31-4.20) karmic; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: iscsitarget -- update to SVN revision r214 + * SAUCE: iscsitarget -- renable driver + * [Config] consolidate lpia/lpia and i386/generic configs + * [Config] enable CRYPTO modules for all architectures + * [Config] enable cryptoloop + * [Config] enable various filesystems for armel + * [Config] sync i386 generic and generic-pae + * [Config] add the 386 (486 processors and above) flavour + * [Config] re-set DEFAULT_MMAP_MIN_ADDR + - LP: #399914 + * add genconfigs/genportsconfigs to extract the built configs + * updateconfigs -- alter concatenation order allow easier updates + * intelfb -- INTELFB now conflicts with DRM_I915 + * printchanges -- rebase tree does not have stable tags use changelog + * AppArmor: fix argument size missmatch on 64 bit builds + + [ Ike Panhc ] + + * Ship bnx2x firmware in nic-modules udeb + - LP: #360966 + + [ Jeff Mahoney ] + + * AppArmor: fix build failure on ia64 + + [ John Johansen ] + + * AppArmour: ensure apparmor enabled parmater is off if AppArmor fails to + initialize. + * AppArmour: fix auditing of domain transitions to include target profile + information + * AppArmor: fix C99 violation + * AppArmor: revert reporting of create to write permission. + * SAUCE: Add config option to set a default LSM + * [Config] enable AppArmor by default + * AppArmor: Fix NULL pointer dereference oops in profile attachment. + + [ Keith Packard ] + + * SAUCE: drm/i915: Allow frame buffers up to 4096x4096 on 915/945 class + hardware + - LP: #351756 + + [ Luke Yelavich ] + + * [Config] add .o files found in arch/powerpc/lib to all powerpc kernel + header packages + - LP: #355344 + + [ Michael Casadevall ] + + * [Config] update SPARC config files to allow success build + + [ Scott James Remnant ] + + * SAUCE: trace: add trace_event for the open() syscall + + [ Stefan Bader ] + + * SAUCE: jfs: Fix early release of acl in jfs_get_acl + - LP: #396780 + + [ Tim Gardner ] + + * [Upstream] Fix Soltech TA12 volume hotkeys not sending key release + - LP: #397499 + * [Upstream] USB Option driver - Add USB ID for Novatel MC727/U727/USB727 + refresh + - LP: #365291 + * [Config] SSB/B44 are common across all arches/flavours. + + [ Upstream ] + + * Rebased to 2.6.31-rc4 + + -- Andy Whitcroft Thu, 23 Jul 2009 08:41:39 +0100 + +linux (2.6.31-3.19) karmic; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Config] Disabled NDISWRAPPER" + * ndiswrapper -- fix i386 compilation failures on cmpxchg8b + * AUFS -- export various core functions + * AUFS -- export various core functions -- fixes + * AUFS -- core filesystem + * AUFS -- track changes in v2.6.31 + * [Config] Enable AUFS + * droppped 'iwl3945: do not send scan command if channel count zero' as it + is already upstream but failed to auto-drop on rebase. + + [ Eric Paris ] + + * SAUCE: fsnotify: use def_bool in kconfig instead of letting the user + choose + * SAUCE: inotify: check filename before dropping repeat events + * SAUCE: fsnotify: fix inotify tail drop check with path entries + + -- Andy Whitcroft Tue, 14 Jul 2009 12:52:55 +0100 + +linux (2.6.31-3.18) karmic; urgency=low + + [ Andy Whitcroft ] + + * Revert "Add splice-2.6.23.patch from AUFS to export a symbol needed by + AUFS" + * Revert "Add put_filp.patch from AUFS to export a symbol needed by AUFS" + * Revert "Add sec_perm-2.6.24.patch from AUFS - export + security_inode_permission" + * clear out left over AUFS files and modifications + + [ Luke Yelavich ] + + * [Config] Enable CONFIG_USB_ISP116X_HCD on sparc + * SAUCE: Explicitly include header files to allow apparmor to build on + powerpc + * [Config] Enable CONFIG_BLK_DEV_IDECD on powerpc + + [ Tim Gardner ] + + * [Config] Dropped ubuntu/misc/wireless/acx + * [Config] Disabled NDISWRAPPER until the compile issues are fixed. + + [ Upstream ] + + * Rebased to 2.6.31-rc3 + + -- Andy Whitcroft Fri, 10 Jul 2009 18:59:33 +0100 + +linux (2.6.31-2.17) karmic; urgency=low + + [ Andy Whitcroft ] + + * [Config] CONFIG_BLK_DEV_CRYPTOLOOP=m for sparc + * compcache -- remove redundant Kconfig entries part 2 + * compcache -- clean up CCFLAGS declarations + * [Config] enable AppArmor + * AppArmor: fix operator precidence issue in as_path_link + + [ John Johansen ] + + * AppArmor security module + * AppArmor: Correct mapping of file permissions. + * AppArmor: Turn auditing of ptrace on + + [ Luke Yelavich ] + + * [Config] disable CONFIG_DM_RAID45 on powerpc + + -- Andy Whitcroft Fri, 10 Jul 2009 15:02:05 +0100 + +linux (2.6.31-2.16) karmic; urgency=low + + [ Andy Whitcroft ] + + * compcache -- remove redundant Kconfig entries + added ignore and ignore.modules for all arches since the compcache update + changes the modules names as well as some compcache ABI values. + + [ Manoj Iyer ] + + * SAUCE: updated dm-raid45 module version to 2009.04.24 (2.6.30-rc3) + * SAUCE: update compcache version to 0.5.3 + + [ Tim Gardner ] + + * [Config]: Fix sparc FTBS by adding ignore.modules + + -- Tim Gardner Mon, 06 Jul 2009 13:35:29 -0600 + +linux (2.6.31-2.15) karmic; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: default ATI Radeon KMS to off until userspace catches up + * [Config] Update configs following rebase to 2.6.31-rc2 + * [Config] update ports configs following update to 2.6.31-rc2 + + [ Luke Yelavich ] + + * [Config] powerpc - Disable CONFIG_RDS + + [ Matt Zimmerman ] + + * Rename linux-doc-PKGVER to linux-doc and clean up its description + - LP: #382115 + + [ Upstream Kernel Changes ] + + * rebased to mainline 2.6.31-rc2 + + -- Andy Whitcroft Sat, 04 Jul 2009 17:39:13 +0100 + +linux (2.6.31-1.14) karmic; urgency=low + + [ Andy Whitcroft ] + + * update ndiswrapper to 1.55 + * remove leftovers of gfs + * [Config] powerpc: enable CONFIG_PPC_DISABLE_WERROR + + [ Luke Yelavich ] + + * [Config] re-enable and build the ide-pmac driver into powerpc kernels + * [Config] Build the ServerWorks Frodo / Apple K2 SATA driver into the + kernel + + [ Manoj Iyer ] + + * Remove snd-bt-sco ubuntu driver + + [ Michael Casadevall ] + + * [Config] updates ia64 config and d-i folders to allow succesful build + * [Config] Update powerpc and sparc for 2.6.31 + + [ Upstream Kernel Changes ] + + * intel-iommu: fix Identity Mapping to be arch independent + - LP: #384695 + * ACPI: video: prevent NULL deref in acpi_get_pci_dev() + + -- Andy Whitcroft Tue, 30 Jun 2009 17:47:32 +0100 + +linux (2.6.31-1.13) karmic; urgency=low + + [ Andy Whitcroft ] + + * REBASE: rebased to mainline 2.6.31-rc1 + - "UBUNTU: SAUCE: UHCI USB quirk for resume" + no longer applies, using deprecated interfaces, LPIA only, dropped + - "UBUNTU: SAUCE: Mask off garbage in Dell WMI scan code data" + changes now upstream, dropped + * [Config] Update configs following rebase to 2.6.31-rc1 + * [Config] update ports configs following update to 2.6.31-rc1 + + * [Config] disable broken staging driver CONFIG_STLC45XX + * SAUCE: fix compcache to use updates accessors + * [Config] disable staging driver CONFIG_VT6655 + * SAUCE: fix DRDB to use updates accessors + * [Disable] ndiswrapper needs update + * [Disable] LIRC I2C needs update + * [Disable] CONFIG_LENOVO_SL_LAPTOP needs update + * [Config] disable I2C_DESIGNWARE does not compile + * [Config] disable CONFIG_TLSUP for lpia + * [Config] disable CONFIG_FB_UDL for arm + * SAUCE: disable adding scsi headers to linux-libc-dev + + [ Mario Limonciello ] + + * SAUCE: Add LIRC drivers + + -- Andy Whitcroft Thu, 25 Jun 2009 12:06:22 +0100 + +linux (2.6.30-10.12) karmic; urgency=low + + [ Andy Whitcroft ] + + * [Config] split out the ports configs into their own family + * [Config] update configs following introduction of ports family + + [ Upstream Kernel Changes ] + + * Revert "Rename linux-doc-PKGVER to linux-doc and clean up its + description". Fixes linux-doc package name conflicts for now. + - LP: #382115 + + -- Tim Gardner Mon, 22 Jun 2009 09:17:14 -0600 + +linux (2.6.30-10.11) karmic; urgency=low + + [ Amit Kucheria ] + + * [Config] Comment splitconfig.pl and misc cleanup + * [Config] Rename all configs to the new naming scheme + * [Config] Splitconfig rework + * [Config] Rename scripts/misc/oldconfig to kernelconfig + * [Config] Fix build system for new config split + * [Config] Run updateconfigs after the splitconfig rework + + [ Andy Whitcroft ] + + * Revert "SAUCE: Default to i915.modeset=0 if CONFIG_DRM_I915_KMS=y" + * [Config] standardise CONFIG_STAGING=y + * [Config] standardise CONFIG_RD_LZMA=y + * [Config] CONFIG_PCI_IOV=y + * [Config] CONFIG_PCI_STUB=m + * [Config] merge kernel configs more agressively + + [ Colin Watson ] + + * [Config] Run kernel-wedge in $(builddir) rather than at the top level + * [Config] Add support for including firmware in udebs + * [Config] Ship bnx2 firmware in nic-modules udeb + - LP: #384861 + + [ Luke Yelavich ] + + * [Config] ports - Import of ports architectures into kernel packaging + infrastructure + * [Config] ports - Do not update ports kernel configurations by default + * [Config] ports - Disable ABI checking for ports architectures + * [Config] ports - Build drivers in ubuntu sub-directory on powerpc + * [Config] ports - Add control.d/vars.* files for ports architectures + * [Config] ports - Add ports architectures for linux-libc-dev + * [Config] ports - Create powerpc specific message-modules and + block-modules udebs + * [Config] ports - Add configuration files for ports architectures + + [ Manoj Iyer ] + + * [Config] Enable CONFIG_BLK_DEV_AEC62XX=m for amd64 and i386 + - LP: #329864 + + [ Michael Casadevall ] + + * [Config] ports - Fix compression of kernels + + [ Stefan Bader ] + + * [Upstream] mmc: prevent dangling block device from accessing stale + queues + - LP: #383668 + + [ Tim Gardner ] + + * [Config] Recommend grub-pc in linux-image + - LP: #385741 + * [Config] Implement i386 generic and generic-pae flavours + * [Config] ports - Add control info after integrating ports arches + * [Config] Removed auto-generated files from git + * [Config] Added netxen_nic to nic-modules + - LP: #389603 + + [ Matt Zimmerman ] + + * Rename linux-doc-PKGVER to linux-doc and clean up its description + - LP: #382115 + + -- Tim Gardner Mon, 15 Jun 2009 14:38:26 -0600 + +linux (2.6.30-9.10) karmic; urgency=low + + [ Andy Whitcroft ] + + * [Config] CONFIG_SECURITY_TOMOYO=y (amd64, i386, lpia) + * [Config] CONFIG_KEXEC_JUMP=y (amd64, lpia) + * [Config] CONFIG_LENOVO_SL_LAPTOP=m (amd64, lpia) + * [Config] CONFIG_POHMELFS_CRYPTO=y (i386, amd64) + * [Config] CONFIG_SERIAL_MAX3100=m (i386, amd64, lpia) + * [Config] CONFIG_VIDEO_GO7007=m (amd64, i386) + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30 final + + -- Andy Whitcroft Fri, 05 Jun 2009 11:42:53 +0100 + +linux (2.6.30-8.9) karmic; urgency=low + + [ Andy Whitcroft ] + + * Config update removed the following options: + CONFIG_EDAC_AMD8111=m + CONFIG_EDAC_AMD8131=m + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30-rc8 + + -- Andy Whitcroft Wed, 03 Jun 2009 09:21:13 +0100 + +linux (2.6.30-7.8) karmic; urgency=low + + [ Andy Whitcroft ] + + * Enabled NEW configration options: + Paravirtualization layer for spinlocks (PARAVIRT_SPINLOCKS) [N/y/?] Y + Cisco FNIC Driver (FCOE_FNIC) [N/m/y/?] M + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30-rc7 + + -- Andy Whitcroft Sat, 23 May 2009 23:47:24 +0100 + +linux (2.6.30-6.7) karmic; urgency=low + + [ Andy Whitcroft ] + + * Dropped: UBUNTU: SAUCE: input: Blacklist digitizers from joydev.c (now + upstream) + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30-rc6 + + -- Andy Whitcroft Mon, 18 May 2009 18:05:54 +0100 + +linux (2.6.30-5.6) karmic; urgency=low + + [ Tim Gardner ] + + * [Config] Enable Keyspan USB serial device firmware in kernel module + - LP: #334285 + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30-rc5 + + -- Tim Gardner Mon, 11 May 2009 12:02:16 -0600 + +linux (2.6.30-4.5) karmic; urgency=low + + [ Colin Watson ] + + * Build-Conflict with findutils (= 4.4.1-1ubuntu1), to avoid + /usr/include/asm/* going missing + - LP: #373214 + + -- Stefan Bader Fri, 08 May 2009 11:09:08 +0200 + +linux (2.6.30-3.4) karmic; urgency=low + + [ Kees Cook ] + + * SAUCE: [x86] implement cs-limit nx-emulation for ia32 + - LP: #369978 + + [ Stefan Bader ] + + * SAUCE: input: Blacklist digitizers from joydev.c + - LP: #300143 + + -- Tim Gardner Fri, 01 May 2009 14:00:42 -0600 + +linux (2.6.30-2.3) karmic; urgency=low + + [ Tim Gardner ] + + * [Config] Enabled CC_STACKPROTECTOR=y for all x86en + - LP: #369152 + * SAUCE: Default to i915_modeset=0 if CONFIG_DRM_I915_KMS=y + * [Config] CONFIG_DRM_I915_KMS=y + * [Config] Set CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR to appropriate ARCH + minimums + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30-rc4 + + -- Tim Gardner Thu, 30 Apr 2009 09:17:05 -0600 + +linux (2.6.30-1.2) karmic; urgency=low + + [ Tim Gardner ] + + * [Config] armel: disable staging drivers, fixes FTBS + * [Config] armel imx51: Disable CONFIG_MTD_NAND_MXC, fixes FTBS + + [ Upstream Kernel Changes ] + + * mpt2sas: Change reset_type enum to avoid namespace collision. + Submitted upstream. + + -- Tim Gardner Tue, 28 Apr 2009 16:54:41 -0600 + +linux (2.6.30-1.1) karmic; urgency=low + + * Initial release after rebasing against v2.6.30-rc3 + + -- Tim Gardner Thu, 12 Mar 2009 19:16:07 -0600 --- linux-2.6.37.orig/debian.master/control.stub +++ linux-2.6.37/debian.master/control.stub @@ -0,0 +1,516 @@ +Source: linux +Section: devel +Priority: optional +Maintainer: Ubuntu Kernel Team +Standards-Version: 3.8.4.0 +Build-Depends: debhelper (>= 5), cpio, module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [amd64 i386], device-tree-compiler [powerpc], libelf-dev, binutils-dev, rsync, libdw-dev +Build-Depends-Indep: bzip2, sharutils +Build-Conflicts: findutils (= 4.4.1-1ubuntu1) +Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-maverick.git + +Package: linux-headers-2.6.37-graphics2+12 +Architecture: all +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0) +Provides: linux-headers, linux-headers-2.6 +Description: Header files related to Linux kernel version 2.6.37 + This package provides kernel header files for version 2.6.37, for sites + that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details + + +Package: linux-image-2.6.37-graphics2+12-generic +Architecture: i386 amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Generic processors. + . + Geared toward desktop systems. + . + You likely do not want to install this package directly. Instead, install + the linux-generic meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-generic +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86/x86_64 + This package provides kernel header files for version 2.6.37 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-generic-dbgsym +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86/x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-generic-pae +Architecture: i386 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86 + This package contains the Linux kernel image for version 2.6.37 on + x86. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Generic processors. + . + Geared toward 32 bit desktop systems with more then 4GB RAM. + . + You likely do not want to install this package directly. Instead, install + the linux-generic-pae meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-generic-pae +Architecture: i386 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86 + This package provides kernel header files for version 2.6.37 on + x86. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-generic-pae-dbgsym +Architecture: i386 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86 + This package provides a kernel debug image for version 2.6.37 on + x86. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-omap +Architecture: armel +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: flash-kernel +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on TI OMAP3-based systems + This package contains the Linux kernel image for version 2.6.37 on + TI OMAP3-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports TI OMAP3 processors. + . + Targeted towards boards such as Beagleboard, Gumstix, IGEPv2, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-omap meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-omap +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on TI OMAP3-based systems + This package provides kernel header files for version 2.6.37 on + TI OMAP3-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-omap-dbgsym +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on TI OMAP3-based systems + This package provides a kernel debug image for version 2.6.37 on + TI OMAP3-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 32-bit PowerPC + This package contains the Linux kernel image for version 2.6.37 on + 32-bit PowerPC. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 32-bit PowerPC processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 32-bit PowerPC + This package provides kernel header files for version 2.6.37 on + 32-bit PowerPC. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 32-bit PowerPC + This package provides a kernel debug image for version 2.6.37 on + 32-bit PowerPC. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc64-smp +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 64-bit PowerPC SMP + This package contains the Linux kernel image for version 2.6.37 on + 64-bit PowerPC SMP. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 64-bit PowerPC SMP processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc64-smp meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc64-smp +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 64-bit PowerPC SMP + This package provides kernel header files for version 2.6.37 on + 64-bit PowerPC SMP. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc64-smp-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 64-bit PowerPC SMP + This package provides a kernel debug image for version 2.6.37 on + 64-bit PowerPC SMP. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc-smp +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 32-bit PowerPC SMP + This package contains the Linux kernel image for version 2.6.37 on + 32-bit PowerPC SMP. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 32-bit PowerPC SMP processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc-smp meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc-smp +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 32-bit PowerPC SMP + This package provides kernel header files for version 2.6.37 on + 32-bit PowerPC SMP. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc-smp-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 32-bit PowerPC SMP + This package provides a kernel debug image for version 2.6.37 on + 32-bit PowerPC SMP. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-server +Architecture: amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, kvm-api-4, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Server processors. + . + Geared toward 64 bit server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-server meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-server +Architecture: amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86_64 + This package provides kernel header files for version 2.6.37 on + x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-server-dbgsym +Architecture: amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-versatile +Architecture: armel +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on Versatile-based systems + This package contains the Linux kernel image for version 2.6.37 on + Versatile-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Versatile processors. + . + PB, AB, Qemu, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-versatile meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-versatile +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on Versatile-based systems + This package provides kernel header files for version 2.6.37 on + Versatile-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-versatile-dbgsym +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on Versatile-based systems + This package provides a kernel debug image for version 2.6.37 on + Versatile-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-virtual +Architecture: i386 amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Virtual processors. + . + Geared toward virtual appliances. + . + You likely do not want to install this package directly. Instead, install + the linux-virtual meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-virtual +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86/x86_64 + This package provides kernel header files for version 2.6.37 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-virtual-dbgsym +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86/x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. --- linux-2.6.37.orig/debian.master/control +++ linux-2.6.37/debian.master/control @@ -0,0 +1,516 @@ +Source: linux +Section: devel +Priority: optional +Maintainer: Ubuntu Kernel Team +Standards-Version: 3.8.4.0 +Build-Depends: debhelper (>= 5), cpio, module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [amd64 i386], device-tree-compiler [powerpc], libelf-dev, binutils-dev, rsync, libdw-dev +Build-Depends-Indep: bzip2, sharutils +Build-Conflicts: findutils (= 4.4.1-1ubuntu1) +Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-maverick.git + +Package: linux-headers-2.6.37-graphics2+12 +Architecture: all +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0) +Provides: linux-headers, linux-headers-2.6 +Description: Header files related to Linux kernel version 2.6.37 + This package provides kernel header files for version 2.6.37, for sites + that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details + + +Package: linux-image-2.6.37-graphics2+12-generic +Architecture: i386 amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Generic processors. + . + Geared toward desktop systems. + . + You likely do not want to install this package directly. Instead, install + the linux-generic meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-generic +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86/x86_64 + This package provides kernel header files for version 2.6.37 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-generic-dbgsym +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86/x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-generic-pae +Architecture: i386 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86 + This package contains the Linux kernel image for version 2.6.37 on + x86. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Generic processors. + . + Geared toward 32 bit desktop systems with more then 4GB RAM. + . + You likely do not want to install this package directly. Instead, install + the linux-generic-pae meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-generic-pae +Architecture: i386 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86 + This package provides kernel header files for version 2.6.37 on + x86. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-generic-pae-dbgsym +Architecture: i386 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86 + This package provides a kernel debug image for version 2.6.37 on + x86. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-omap +Architecture: armel +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: flash-kernel +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on TI OMAP3-based systems + This package contains the Linux kernel image for version 2.6.37 on + TI OMAP3-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports TI OMAP3 processors. + . + Targeted towards boards such as Beagleboard, Gumstix, IGEPv2, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-omap meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-omap +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on TI OMAP3-based systems + This package provides kernel header files for version 2.6.37 on + TI OMAP3-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-omap-dbgsym +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on TI OMAP3-based systems + This package provides a kernel debug image for version 2.6.37 on + TI OMAP3-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 32-bit PowerPC + This package contains the Linux kernel image for version 2.6.37 on + 32-bit PowerPC. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 32-bit PowerPC processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 32-bit PowerPC + This package provides kernel header files for version 2.6.37 on + 32-bit PowerPC. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 32-bit PowerPC + This package provides a kernel debug image for version 2.6.37 on + 32-bit PowerPC. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc64-smp +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 64-bit PowerPC SMP + This package contains the Linux kernel image for version 2.6.37 on + 64-bit PowerPC SMP. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 64-bit PowerPC SMP processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc64-smp meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc64-smp +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 64-bit PowerPC SMP + This package provides kernel header files for version 2.6.37 on + 64-bit PowerPC SMP. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc64-smp-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 64-bit PowerPC SMP + This package provides a kernel debug image for version 2.6.37 on + 64-bit PowerPC SMP. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc-smp +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 32-bit PowerPC SMP + This package contains the Linux kernel image for version 2.6.37 on + 32-bit PowerPC SMP. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 32-bit PowerPC SMP processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc-smp meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc-smp +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 32-bit PowerPC SMP + This package provides kernel header files for version 2.6.37 on + 32-bit PowerPC SMP. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc-smp-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 32-bit PowerPC SMP + This package provides a kernel debug image for version 2.6.37 on + 32-bit PowerPC SMP. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-server +Architecture: amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, kvm-api-4, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Server processors. + . + Geared toward 64 bit server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-server meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-server +Architecture: amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86_64 + This package provides kernel header files for version 2.6.37 on + x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-server-dbgsym +Architecture: amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-versatile +Architecture: armel +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on Versatile-based systems + This package contains the Linux kernel image for version 2.6.37 on + Versatile-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Versatile processors. + . + PB, AB, Qemu, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-versatile meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-versatile +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on Versatile-based systems + This package provides kernel header files for version 2.6.37 on + Versatile-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-versatile-dbgsym +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on Versatile-based systems + This package provides a kernel debug image for version 2.6.37 on + Versatile-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-virtual +Architecture: i386 amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Virtual processors. + . + Geared toward virtual appliances. + . + You likely do not want to install this package directly. Instead, install + the linux-virtual meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-virtual +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86/x86_64 + This package provides kernel header files for version 2.6.37 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-virtual-dbgsym +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86/x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. --- linux-2.6.37.orig/debian.master/config/config.common.ports +++ linux-2.6.37/debian.master/config/config.common.ports @@ -0,0 +1 @@ + --- linux-2.6.37.orig/debian.master/config/config.common.ubuntu +++ linux-2.6.37/debian.master/config/config.common.ubuntu @@ -0,0 +1,5404 @@ +# +# Common config options automatically generated by splitconfig.pl +# +CONFIG_32BIT=y +CONFIG_3C359=m +CONFIG_3C515=m +# CONFIG_40x is not set +# CONFIG_44x is not set +CONFIG_60XX_WDT=m +CONFIG_6PACK=m +CONFIG_6xx=y +CONFIG_8139CP=m +CONFIG_8139TOO=m +CONFIG_8139TOO_8129=y +CONFIG_8139TOO_PIO=y +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139_OLD_RX_RESET is not set +CONFIG_9P_FS=m +# CONFIG_9P_FSCACHE is not set +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_AB3100_CORE=y +CONFIG_AB3100_OTP=m +CONFIG_AB3550_CORE=y +CONFIG_ABX500_CORE=y +CONFIG_ABYSS=m +CONFIG_AC3200=m +CONFIG_AC97_BUS=m +# CONFIG_ACCESSIBILITY is not set +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_ACERHDF=m +CONFIG_ACER_WMI=m +CONFIG_ACORN_PARTITION=y +# CONFIG_ACORN_PARTITION_ADFS is not set +# CONFIG_ACORN_PARTITION_CUMANA is not set +# CONFIG_ACORN_PARTITION_EESOX is not set +CONFIG_ACORN_PARTITION_ICS=y +# CONFIG_ACORN_PARTITION_POWERTEC is not set +CONFIG_ACORN_PARTITION_RISCIX=y +CONFIG_ACPI=y +CONFIG_ACPI_AC=y +CONFIG_ACPI_APEI=y +CONFIG_ACPI_APEI_EINJ=m +CONFIG_ACPI_APEI_ERST_DEBUG=m +CONFIG_ACPI_APEI_GHES=m +# CONFIG_ACPI_ASUS is not set +CONFIG_ACPI_BATTERY=y +CONFIG_ACPI_BUTTON=y +CONFIG_ACPI_CMPC=m +CONFIG_ACPI_CONTAINER=y +# CONFIG_ACPI_CUSTOM_DSDT is not set +CONFIG_ACPI_CUSTOM_DSDT_FILE="" +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_DOCK=y +CONFIG_ACPI_EC_DEBUGFS=m +CONFIG_ACPI_FAN=y +CONFIG_ACPI_HED=m +CONFIG_ACPI_HOTPLUG_CPU=y +CONFIG_ACPI_HOTPLUG_MEMORY=m +CONFIG_ACPI_NUMA=y +CONFIG_ACPI_PCI_SLOT=y +CONFIG_ACPI_POWER_METER=m +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_PROCESSOR_AGGREGATOR=m +CONFIG_ACPI_PROCFS=y +CONFIG_ACPI_PROCFS_POWER=y +CONFIG_ACPI_PROC_EVENT=y +CONFIG_ACPI_QUICKSTART=m +CONFIG_ACPI_SBS=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_THERMAL=y +CONFIG_ACPI_TOSHIBA=m +CONFIG_ACPI_VIDEO=m +CONFIG_ACPI_WMI=y +CONFIG_ACQUIRE_WDT=m +CONFIG_ACT200L_DONGLE=m +CONFIG_ACTISYS_DONGLE=m +CONFIG_AD525X_DPOT=m +CONFIG_AD525X_DPOT_I2C=m +CONFIG_AD525X_DPOT_SPI=m +CONFIG_AD7476=m +CONFIG_AD799X=m +CONFIG_AD799X_RING_BUFFER=y +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ADB=y +CONFIG_ADB_CUDA=y +CONFIG_ADB_MACIO=y +CONFIG_ADB_PMU=y +CONFIG_ADB_PMU_LED=y +# CONFIG_ADB_PMU_LED_IDE is not set +CONFIG_ADFS_FS=m +# CONFIG_ADFS_FS_RW is not set +CONFIG_ADIS16209=m +CONFIG_ADIS16220=m +CONFIG_ADIS16240=m +CONFIG_ADIS16255=m +CONFIG_ADIS16260=m +CONFIG_ADIS16300=m +CONFIG_ADIS16350=m +CONFIG_ADIS16400=m +CONFIG_ADM8211=m +# CONFIG_ADVANCED_OPTIONS is not set +CONFIG_ADVANTECH_WDT=m +CONFIG_AEABI=y +CONFIG_AFFS_FS=m +# CONFIG_AFS_DEBUG is not set +CONFIG_AFS_FS=m +# CONFIG_AFS_FSCACHE is not set +CONFIG_AF_RXRPC=m +# CONFIG_AF_RXRPC_DEBUG is not set +CONFIG_AGP=y +CONFIG_AGP_ALI=m +CONFIG_AGP_AMD=y +CONFIG_AGP_AMD64=y +CONFIG_AGP_ATI=m +CONFIG_AGP_EFFICEON=m +CONFIG_AGP_INTEL=y +CONFIG_AGP_NVIDIA=y +CONFIG_AGP_SIS=m +CONFIG_AGP_SWORKS=m +CONFIG_AGP_UNINORTH=m +CONFIG_AGP_VIA=y +CONFIG_AIC79XX_CMDS_PER_DEVICE=32 +CONFIG_AIC79XX_DEBUG_ENABLE=y +CONFIG_AIC79XX_DEBUG_MASK=0 +CONFIG_AIC79XX_REG_PRETTY_PRINT=y +CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 +CONFIG_AIC7XXX_DEBUG_ENABLE=y +CONFIG_AIC7XXX_DEBUG_MASK=0 +CONFIG_AIC7XXX_REG_PRETTY_PRINT=y +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC94XX_DEBUG is not set +CONFIG_AIO=y +CONFIG_AIRO=m +CONFIG_AIRO_CS=m +CONFIG_ALIGNMENT_TRAP=y +CONFIG_ALIM1535_WDT=m +CONFIG_ALI_FIR=m +CONFIG_ALTIVEC=y +CONFIG_AMBA_PL08X=y +CONFIG_AMD8111_ETH=m +CONFIG_AMD_IOMMU=y +CONFIG_AMD_IOMMU_STATS=y +CONFIG_AMD_NB=y +# CONFIG_AMIGAONE is not set +CONFIG_AMIGA_PARTITION=y +CONFIG_ANON_INODES=y +CONFIG_ANSLCD=m +CONFIG_APDS9802ALS=m +CONFIG_APM=m +# CONFIG_APM_ALLOW_INTS is not set +# CONFIG_APM_CPU_IDLE is not set +# CONFIG_APM_DISPLAY_BLANK is not set +# CONFIG_APM_DO_ENABLE is not set +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +CONFIG_APM_POWER=m +CONFIG_APPLE_AIRPORT=m +CONFIG_APPLICOM=m +CONFIG_APRICOT=m +CONFIG_AR9170_LEDS=y +CONFIG_AR9170_USB=m +# CONFIG_ARCH_AAEC2000 is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +CONFIG_ARCH_CPU_PROBE_RELEASE=y +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_EBSA110 is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +# CONFIG_ARCH_EP93XX is not set +CONFIG_ARCH_FLATMEM_ENABLE=y +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_H720X is not set +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_ARCH_HAS_CPU_RELAX=y +CONFIG_ARCH_HAS_DEFAULT_IDLE=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_HAS_ILOG2_U32=y +CONFIG_ARCH_HAS_ILOG2_U64=y +CONFIG_ARCH_HAS_WALK_MEMORY=y +CONFIG_ARCH_HIBERNATION_HEADER=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_LH7A40X is not set +# CONFIG_ARCH_LOKI is not set +# CONFIG_ARCH_LPC32XX is not set +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_ARCH_MEMORY_PROBE=y +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_MSM is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_NS9XXX is not set +# CONFIG_ARCH_NUC93X is not set +# CONFIG_ARCH_OMAP1 is not set +# CONFIG_ARCH_OMAP2 is not set +CONFIG_ARCH_OMAP2PLUS=y +CONFIG_ARCH_OMAP2PLUS_TYPICAL=y +CONFIG_ARCH_OMAP3=y +CONFIG_ARCH_OMAP3430=y +# CONFIG_ARCH_OMAP4 is not set +CONFIG_ARCH_OMAP_OTG=y +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_PNX4008 is not set +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_PROC_KCORE_TEXT=y +# CONFIG_ARCH_PXA is not set +# CONFIG_ARCH_REALVIEW is not set +CONFIG_ARCH_REQUIRE_GPIOLIB=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_S3C2410 is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P6442 is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_S5PV310 is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_SHMOBILE is not set +CONFIG_ARCH_SPARSEMEM_ENABLE=y +# CONFIG_ARCH_STMP3XXX is not set +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_ARCH_TCC_926 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_ARCH_USES_PG_UNCACHED=y +CONFIG_ARCH_VERSATILE_PB=y +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_W90X900 is not set +CONFIG_ARCH_WANTS_FREEZER_CONTROL=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +CONFIG_ARCNET=m +CONFIG_ARCNET_1051=m +CONFIG_ARCNET_1201=m +CONFIG_ARCNET_CAP=m +CONFIG_ARCNET_COM20020=m +CONFIG_ARCNET_COM20020_CS=m +CONFIG_ARCNET_COM20020_ISA=m +CONFIG_ARCNET_COM20020_PCI=m +CONFIG_ARCNET_COM90xx=m +CONFIG_ARCNET_COM90xxIO=m +CONFIG_ARCNET_RAW=m +CONFIG_ARCNET_RIM_I=m +CONFIG_ARM=y +CONFIG_ARM_AMBA=y +CONFIG_ARM_CHARLCD=y +CONFIG_ARM_DMA_MEM_BUFFERABLE=y +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +CONFIG_ARM_ERRATA_743622=y +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_SP805_WATCHDOG=m +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_ARM_TIMER_SP804=y +CONFIG_ARM_UNWIND=y +CONFIG_ARM_VIC=y +CONFIG_ARM_VIC_NR=2 +# CONFIG_ARPD is not set +CONFIG_ASK_IP_FIB_HASH=y +CONFIG_ASUS_LAPTOP=m +CONFIG_ASYNC_CORE=m +CONFIG_ASYNC_MEMCPY=m +CONFIG_ASYNC_PQ=m +CONFIG_ASYNC_RAID6_RECOV=m +CONFIG_ASYNC_RAID6_TEST=m +CONFIG_ASYNC_TX_DISABLE_PQ_VAL_DMA=y +CONFIG_ASYNC_TX_DISABLE_XOR_VAL_DMA=y +CONFIG_ASYNC_XOR=m +CONFIG_AT1700=m +CONFIG_AT76C50X_USB=m +CONFIG_ATA=y +CONFIG_ATAGS_PROC=y +CONFIG_ATARI_PARTITION=y +CONFIG_ATA_ACPI=y +CONFIG_ATA_BMDMA=y +CONFIG_ATA_OVER_ETH=m +CONFIG_ATA_SFF=y +CONFIG_ATA_VERBOSE_ERROR=y +# CONFIG_ATH5K_DEBUG is not set +# CONFIG_ATH6K_LEGACY is not set +CONFIG_ATH9K=m +CONFIG_ATH9K_COMMON=m +CONFIG_ATH9K_DEBUGFS=y +CONFIG_ATH9K_HTC=m +CONFIG_ATH9K_HTC_DEBUGFS=y +CONFIG_ATH9K_HW=m +CONFIG_ATH9K_RATE_CONTROL=y +CONFIG_ATH_COMMON=m +# CONFIG_ATH_DEBUG is not set +CONFIG_ATL1=m +CONFIG_ATL1C=m +CONFIG_ATL1E=m +CONFIG_ATL2=m +CONFIG_ATMEL=m +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_BR2684=m +CONFIG_ATM_CLIP=m +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_DRIVERS=y +CONFIG_ATM_ENI=m +# CONFIG_ATM_ENI_DEBUG is not set +# CONFIG_ATM_ENI_TUNE_BURST is not set +CONFIG_ATM_FIRESTREAM=m +CONFIG_ATM_FORE200E=m +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_FORE200E_TX_RETRY=16 +# CONFIG_ATM_FORE200E_USE_TASKLET is not set +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_IDT77252=m +# CONFIG_ATM_IDT77252_DEBUG is not set +# CONFIG_ATM_IDT77252_RCV_ALL is not set +CONFIG_ATM_IDT77252_USE_SUNI=y +CONFIG_ATM_LANAI=m +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_NICSTAR=m +# CONFIG_ATM_NICSTAR_USE_IDT77105 is not set +# CONFIG_ATM_NICSTAR_USE_SUNI is not set +CONFIG_ATM_SOLOS=m +CONFIG_ATM_TCP=m +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +CONFIG_ATP=m +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_GENERIC=y +CONFIG_AUDIT_TREE=y +CONFIG_AUDIT_WATCH=y +CONFIG_AUFS_BDEV_LOOP=y +# CONFIG_AUFS_BRANCH_MAX_1023 is not set +CONFIG_AUFS_BRANCH_MAX_127=y +# CONFIG_AUFS_BRANCH_MAX_32767 is not set +# CONFIG_AUFS_BRANCH_MAX_511 is not set +CONFIG_AUFS_BR_FUSE=y +CONFIG_AUFS_BR_HFSPLUS=y +CONFIG_AUFS_BR_RAMFS=y +# CONFIG_AUFS_DEBUG is not set +# CONFIG_AUFS_EXPORT is not set +CONFIG_AUFS_FS=m +# CONFIG_AUFS_HNOTIFY is not set +CONFIG_AUFS_POLL=y +# CONFIG_AUFS_RDU is not set +CONFIG_AUFS_SBILIST=y +# CONFIG_AUFS_SHWH is not set +# CONFIG_AUFS_SP_IATTR is not set +CONFIG_AUTOFS4_FS=m +CONFIG_AUTOFS_FS=m +# CONFIG_AUTO_IRQ_AFFINITY is not set +# CONFIG_AUTO_ZRELADDR is not set +CONFIG_AUXDISPLAY=y +CONFIG_AVERATEC_5100P=m +CONFIG_AX25=m +CONFIG_AX88796=m +# CONFIG_AX88796_93CX6 is not set +CONFIG_B43LEGACY_DEBUG=y +CONFIG_B43LEGACY_DMA=y +CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y +# CONFIG_B43LEGACY_DMA_MODE is not set +CONFIG_B43LEGACY_HWRNG=y +CONFIG_B43LEGACY_LEDS=y +CONFIG_B43LEGACY_PCICORE_AUTOSELECT=y +CONFIG_B43LEGACY_PCI_AUTOSELECT=y +CONFIG_B43LEGACY_PIO=y +# CONFIG_B43LEGACY_PIO_MODE is not set +# CONFIG_B43_DEBUG is not set +CONFIG_B43_HWRNG=y +CONFIG_B43_LEDS=y +CONFIG_B43_PCICORE_AUTOSELECT=y +CONFIG_B43_PCI_AUTOSELECT=y +# CONFIG_B43_PCMCIA is not set +CONFIG_B43_PHY_LP=y +CONFIG_B43_PIO=y +# CONFIG_B43_SDIO is not set +CONFIG_B44_PCI=y +CONFIG_B44_PCICORE_AUTOSELECT=y +CONFIG_B44_PCI_AUTOSELECT=y +CONFIG_BACKLIGHT_88PM860X=m +CONFIG_BACKLIGHT_ADP5520=m +CONFIG_BACKLIGHT_ADP8860=m +CONFIG_BACKLIGHT_CARILLO_RANCH=m +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_DA903X=m +CONFIG_BACKLIGHT_GENERIC=m +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BACKLIGHT_MAX8925=m +CONFIG_BACKLIGHT_MBP_NVIDIA=m +CONFIG_BACKLIGHT_PCF50633=m +CONFIG_BACKLIGHT_PROGEAR=m +CONFIG_BACKLIGHT_PWM=m +CONFIG_BACKLIGHT_SAHARA=m +CONFIG_BACKLIGHT_WM831X=m +# CONFIG_BACKTRACE_SELF_TEST is not set +CONFIG_BASE_FULL=y +CONFIG_BASE_SMALL=0 +CONFIG_BATMAN_ADV=m +# CONFIG_BATMAN_ADV_DEBUG is not set +CONFIG_BATTERY_BQ20Z75=m +CONFIG_BATTERY_BQ27x00=m +CONFIG_BATTERY_DA9030=m +CONFIG_BATTERY_DS2760=m +CONFIG_BATTERY_DS2782=m +CONFIG_BATTERY_MAX17040=m +CONFIG_BATTERY_OLPC=m +CONFIG_BATTERY_PMU=m +CONFIG_BAYCOM_EPP=m +CONFIG_BAYCOM_PAR=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_BCM63XX_PHY=m +CONFIG_BCM_WIMAX=m +# CONFIG_BDI_SWITCH is not set +CONFIG_BE2ISCSI=m +CONFIG_BE2NET=m +# CONFIG_BEFS_DEBUG is not set +CONFIG_BEFS_FS=m +CONFIG_BFS_FS=m +CONFIG_BINARY_PRINTF=y +CONFIG_BINFMT_AOUT=m +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m +CONFIG_BITREVERSE=y +CONFIG_BKL=y +# CONFIG_BLK_CGROUP is not set +CONFIG_BLK_CPQ_CISS_DA=m +CONFIG_BLK_CPQ_DA=m +CONFIG_BLK_DEV=y +CONFIG_BLK_DEV_3W_XXXX_RAID=m +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_CMD64X is not set +CONFIG_BLK_DEV_COMPCACHE=m +# CONFIG_BLK_DEV_COMPCACHE_DEBUG is not set +# CONFIG_BLK_DEV_COMPCACHE_STATS is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_CRYPTOLOOP=m +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +CONFIG_BLK_DEV_DAC960=m +# CONFIG_BLK_DEV_DELKIN is not set +CONFIG_BLK_DEV_DM=y +CONFIG_BLK_DEV_FD=m +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_HPT366 is not set +CONFIG_BLK_DEV_IDECD=y +CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y +# CONFIG_BLK_DEV_IDECS is not set +CONFIG_BLK_DEV_IDEDMA=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_IDEDMA_SFF=y +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDE_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y +# CONFIG_BLK_DEV_IDE_SATA is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BLK_DEV_IO_TRACE=y +# CONFIG_BLK_DEV_IT8172 is not set +# CONFIG_BLK_DEV_IT8213 is not set +# CONFIG_BLK_DEV_IT821X is not set +# CONFIG_BLK_DEV_JMICRON is not set +CONFIG_BLK_DEV_NBD=m +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_OSD=m +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_PLATFORM is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_BLK_DEV_RBD=m +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SL82C105 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_BLK_DEV_SVWKS is not set +CONFIG_BLK_DEV_SX8=m +# CONFIG_BLK_DEV_TC86C001 is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_UB is not set +CONFIG_BLK_DEV_UMEM=m +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_DEV_XIP is not set +CONFIG_BLOCK=y +CONFIG_BLOCK_COMPAT=y +CONFIG_BMAC=m +CONFIG_BMP085=m +CONFIG_BNA=m +CONFIG_BNX2=m +CONFIG_BNX2X=m +CONFIG_BONDING=m +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_BOOTX_TEXT is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_BOUNCE=y +CONFIG_BPQETHER=m +CONFIG_BRANCH_PROFILE_NONE=y +CONFIG_BRCM80211=m +CONFIG_BRCM80211_PCI=y +CONFIG_BRIDGE=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_ULOG=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_BRIDGE_NETFILTER=y +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIQ_PANEL=m +CONFIG_BROKEN_ON_SMP=y +CONFIG_BSD_DISKLABEL=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_BT=m +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_BT_ATH3K=m +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_CMTP=m +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIBTUART=m +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_H4=y +CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIVHCI=m +CONFIG_BT_HIDP=m +CONFIG_BT_L2CAP=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_SCO=m +CONFIG_BUG=y +CONFIG_C101=m +CONFIG_C2PORT=m +CONFIG_C2PORT_DURAMAR_2150=m +CONFIG_CACHEFILES=m +# CONFIG_CACHEFILES_DEBUG is not set +# CONFIG_CACHEFILES_HISTOGRAM is not set +CONFIG_CAIF=m +# CONFIG_CAIF_DEBUG is not set +CONFIG_CAIF_NETDEV=m +CONFIG_CAIF_SPI_SLAVE=m +# CONFIG_CAIF_SPI_SYNC is not set +CONFIG_CAIF_TTY=m +CONFIG_CALGARY_IOMMU=y +CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT=y +CONFIG_CAN=m +CONFIG_CAN_BCM=m +# CONFIG_CAN_CALC_BITTIMING is not set +# CONFIG_CAN_DEBUG_DEVICES is not set +CONFIG_CAN_DEV=m +CONFIG_CAN_EMS_PCI=m +CONFIG_CAN_EMS_USB=m +CONFIG_CAN_ESD_USB2=m +CONFIG_CAN_JANZ_ICAN3=m +CONFIG_CAN_KVASER_PCI=m +CONFIG_CAN_MCP251X=m +CONFIG_CAN_MSCAN=m +CONFIG_CAN_PLX_PCI=m +CONFIG_CAN_PM_TRACE=y +CONFIG_CAN_RAW=m +CONFIG_CAN_SJA1000=m +CONFIG_CAN_SJA1000_ISA=m +CONFIG_CAN_SJA1000_OF_PLATFORM=m +CONFIG_CAN_SJA1000_PLATFORM=m +# CONFIG_CAN_TI_HECC is not set +CONFIG_CAN_TSCAN1=m +CONFIG_CAN_VCAN=m +CONFIG_CAPI_AVM=y +CONFIG_CAPI_EICON=y +CONFIG_CAPI_TRACE=y +CONFIG_CARDBUS=y +CONFIG_CARL9170=m +# CONFIG_CARL9170_DEBUGFS is not set +CONFIG_CARL9170_LEDS=y +CONFIG_CARL9170_WPC=y +# CONFIG_CARMINE_DRAM_CUSTOM is not set +CONFIG_CASSINI=m +CONFIG_CB710_CORE=m +# CONFIG_CB710_DEBUG is not set +CONFIG_CB710_DEBUG_ASSUMPTIONS=y +CONFIG_CBE_CPUFREQ_SPU_GOVERNOR=m +CONFIG_CC_STACKPROTECTOR=y +CONFIG_CDROM_PKTCDVD_BUFFERS=8 +# CONFIG_CDROM_PKTCDVD_WCACHE is not set +CONFIG_CEPH_FS=m +CONFIG_CEPH_LIB=m +# CONFIG_CEPH_LIB_PRETTYDEBUG is not set +CONFIG_CFAG12864B=m +CONFIG_CFAG12864B_RATE=20 +CONFIG_CFG80211=m +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_INTERNAL_REGDB is not set +CONFIG_CFG80211_WEXT=y +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_MEM_RES_CTLR=y +CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED=y +CONFIG_CGROUP_NS=y +CONFIG_CGROUP_SCHED=y +CONFIG_CHARGER_ISP1704=m +CONFIG_CHARGER_PCF50633=m +CONFIG_CHARGER_TWL4030=m +CONFIG_CHECK_SIGNATURE=y +CONFIG_CHELSIO_T1=m +CONFIG_CHELSIO_T1_1G=y +CONFIG_CHELSIO_T3=m +CONFIG_CHELSIO_T3_DEPENDS=y +CONFIG_CHELSIO_T4=m +CONFIG_CHELSIO_T4VF=m +CONFIG_CHELSIO_T4VF_DEPENDS=y +CONFIG_CHELSIO_T4_DEPENDS=y +CONFIG_CHR_DEV_OSST=m +CONFIG_CHR_DEV_SCH=m +CONFIG_CHR_DEV_ST=m +CONFIG_CIFS=m +# CONFIG_CIFS_ACL is not set +# CONFIG_CIFS_DEBUG2 is not set +CONFIG_CIFS_DFS_UPCALL=y +# CONFIG_CIFS_FSCACHE is not set +CONFIG_CIFS_POSIX=y +# CONFIG_CIFS_STATS is not set +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CISS_SCSI_TAPE=y +CONFIG_CLOCKSOURCE_WATCHDOG=y +CONFIG_CLS_U32_MARK=y +# CONFIG_CLS_U32_PERF is not set +CONFIG_CMDLINE="" +# CONFIG_CMDLINE_BOOL is not set +CONFIG_CNIC=m +CONFIG_CODA_FS=m +# CONFIG_CODE_PATCHING_SELFTEST is not set +CONFIG_COMEDI_8255=m +CONFIG_COMEDI_ACL7225B=m +CONFIG_COMEDI_ADDI_APCI_035=m +CONFIG_COMEDI_ADDI_APCI_1032=m +CONFIG_COMEDI_ADDI_APCI_1500=m +CONFIG_COMEDI_ADDI_APCI_1516=m +CONFIG_COMEDI_ADDI_APCI_1564=m +CONFIG_COMEDI_ADDI_APCI_16XX=m +CONFIG_COMEDI_ADDI_APCI_2016=m +CONFIG_COMEDI_ADDI_APCI_2032=m +CONFIG_COMEDI_ADDI_APCI_2200=m +CONFIG_COMEDI_ADDI_APCI_3001=m +CONFIG_COMEDI_ADDI_APCI_3120=m +CONFIG_COMEDI_ADDI_APCI_3501=m +CONFIG_COMEDI_ADDI_APCI_3XXX=m +CONFIG_COMEDI_ADL_PCI6208=m +CONFIG_COMEDI_ADL_PCI7230=m +CONFIG_COMEDI_ADL_PCI7296=m +CONFIG_COMEDI_ADL_PCI7432=m +CONFIG_COMEDI_ADL_PCI8164=m +CONFIG_COMEDI_ADL_PCI9111=m +CONFIG_COMEDI_ADL_PCI9118=m +CONFIG_COMEDI_ADQ12B=m +CONFIG_COMEDI_ADV_PCI1710=m +CONFIG_COMEDI_ADV_PCI1723=m +CONFIG_COMEDI_ADV_PCI_DIO=m +CONFIG_COMEDI_AIO_AIO12_8=m +CONFIG_COMEDI_AIO_IIRO_16=m +CONFIG_COMEDI_AMPLC_DIO200=m +CONFIG_COMEDI_AMPLC_PC236=m +CONFIG_COMEDI_AMPLC_PC263=m +CONFIG_COMEDI_AMPLC_PCI224=m +CONFIG_COMEDI_AMPLC_PCI230=m +CONFIG_COMEDI_BOND=m +CONFIG_COMEDI_C6XDIGIO=m +CONFIG_COMEDI_CB_DAS16_CS=m +CONFIG_COMEDI_CB_PCIDAS=m +CONFIG_COMEDI_CB_PCIDAS64=m +CONFIG_COMEDI_CB_PCIDDA=m +CONFIG_COMEDI_CB_PCIDIO=m +CONFIG_COMEDI_CB_PCIMDAS=m +CONFIG_COMEDI_CB_PCIMDDA=m +CONFIG_COMEDI_CONTEC_PCI_DIO=m +CONFIG_COMEDI_DAQBOARD2000=m +CONFIG_COMEDI_DAS08=m +CONFIG_COMEDI_DAS08_CS=m +CONFIG_COMEDI_DAS16=m +CONFIG_COMEDI_DAS16M1=m +CONFIG_COMEDI_DAS1800=m +CONFIG_COMEDI_DAS6402=m +CONFIG_COMEDI_DAS800=m +# CONFIG_COMEDI_DEBUG is not set +CONFIG_COMEDI_DMM32AT=m +CONFIG_COMEDI_DT2801=m +CONFIG_COMEDI_DT2811=m +CONFIG_COMEDI_DT2814=m +CONFIG_COMEDI_DT2815=m +CONFIG_COMEDI_DT2817=m +CONFIG_COMEDI_DT282X=m +CONFIG_COMEDI_DT3000=m +CONFIG_COMEDI_DT9812=m +CONFIG_COMEDI_FC=m +CONFIG_COMEDI_FL512=m +CONFIG_COMEDI_GSC_HPDI=m +CONFIG_COMEDI_ICP_MULTI=m +CONFIG_COMEDI_II_PCI20KC=m +CONFIG_COMEDI_ISA_DRIVERS=m +CONFIG_COMEDI_JR3_PCI=m +CONFIG_COMEDI_KCOMEDILIB=m +CONFIG_COMEDI_KE_COUNTER=m +CONFIG_COMEDI_ME4000=m +CONFIG_COMEDI_ME_DAQ=m +CONFIG_COMEDI_MISC_DRIVERS=m +CONFIG_COMEDI_MITE=m +CONFIG_COMEDI_MPC624=m +CONFIG_COMEDI_MULTIQ3=m +CONFIG_COMEDI_NI_6527=m +CONFIG_COMEDI_NI_65XX=m +CONFIG_COMEDI_NI_660X=m +CONFIG_COMEDI_NI_670X=m +CONFIG_COMEDI_NI_ATMIO=m +CONFIG_COMEDI_NI_ATMIO16D=m +CONFIG_COMEDI_NI_AT_A2150=m +CONFIG_COMEDI_NI_AT_AO=m +CONFIG_COMEDI_NI_COMMON=m +CONFIG_COMEDI_NI_DAQ_700_CS=m +CONFIG_COMEDI_NI_DAQ_DIO24_CS=m +CONFIG_COMEDI_NI_LABPC=m +CONFIG_COMEDI_NI_LABPC_CS=m +CONFIG_COMEDI_NI_MIO_CS=m +CONFIG_COMEDI_NI_PCIDIO=m +CONFIG_COMEDI_NI_PCIMIO=m +CONFIG_COMEDI_NI_TIO=m +CONFIG_COMEDI_PARPORT=m +CONFIG_COMEDI_PCI_DRIVERS=m +CONFIG_COMEDI_PCL711=m +CONFIG_COMEDI_PCL724=m +CONFIG_COMEDI_PCL725=m +CONFIG_COMEDI_PCL726=m +CONFIG_COMEDI_PCL730=m +CONFIG_COMEDI_PCL812=m +CONFIG_COMEDI_PCL816=m +CONFIG_COMEDI_PCL818=m +CONFIG_COMEDI_PCM3724=m +CONFIG_COMEDI_PCM3730=m +CONFIG_COMEDI_PCMAD=m +CONFIG_COMEDI_PCMCIA_DRIVERS=m +CONFIG_COMEDI_PCMDA12=m +CONFIG_COMEDI_PCMMIO=m +CONFIG_COMEDI_PCMUIO=m +CONFIG_COMEDI_POC=m +CONFIG_COMEDI_QUATECH_DAQP_CS=m +CONFIG_COMEDI_RTD520=m +CONFIG_COMEDI_RTI800=m +CONFIG_COMEDI_RTI802=m +CONFIG_COMEDI_S526=m +CONFIG_COMEDI_S626=m +CONFIG_COMEDI_SERIAL2002=m +CONFIG_COMEDI_SKEL=m +CONFIG_COMEDI_SSV_DNP=m +CONFIG_COMEDI_TEST=m +CONFIG_COMEDI_UNIOXX5=m +CONFIG_COMEDI_USBDUX=m +CONFIG_COMEDI_USBDUXFAST=m +CONFIG_COMEDI_USB_DRIVERS=m +CONFIG_COMEDI_VMK80XX=m +CONFIG_COMMON_CLKDEV=y +# CONFIG_COMPACTION is not set +CONFIG_COMPAL_LAPTOP=m +CONFIG_COMPAT=y +CONFIG_COMPAT_BINFMT_ELF=y +# CONFIG_COMPAT_BRK is not set +CONFIG_COMPAT_FOR_U64_ALIGNMENT=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +# CONFIG_COMPAT_VDSO is not set +CONFIG_COMPUTONE=m +CONFIG_CONFIGFS_FS=m +CONFIG_CONSOLE_POLL=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONSTRUCTORS=y +CONFIG_CONTEXT_SWITCH_TRACER=y +# CONFIG_COPS is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COSA=m +# CONFIG_CPA_DEBUG is not set +CONFIG_CPU5_WDT=m +CONFIG_CPUSETS=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +# CONFIG_CPU_BPREDICT_DISABLE is not set +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y +# CONFIG_CPU_DCACHE_DISABLE is not set +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEBUG is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_PMAC=y +CONFIG_CPU_FREQ_PMAC64=y +CONFIG_CPU_FREQ_STAT_DETAILS=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_HAS_PMU=y +# CONFIG_CPU_ICACHE_DISABLE is not set +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_NOTIFIER_ERROR_INJECT=m +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_SUP_AMD=y +CONFIG_CPU_SUP_CENTAUR=y +CONFIG_CPU_SUP_CYRIX_32=y +CONFIG_CPU_SUP_INTEL=y +CONFIG_CPU_SUP_TRANSMETA_32=y +CONFIG_CPU_SUP_UMC_32=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_V7=y +CONFIG_CRAMFS=m +CONFIG_CRC16=y +CONFIG_CRC32=y +CONFIG_CRC7=m +CONFIG_CRC_CCITT=m +CONFIG_CRC_ITU_T=m +CONFIG_CROSS_COMPILE="" +CONFIG_CRYPTO=y +CONFIG_CRYPTO_AEAD=m +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_AES_586=m +CONFIG_CRYPTO_AES_NI_INTEL=m +CONFIG_CRYPTO_AES_X86_64=m +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_ARC4=m +CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC32C_INTEL=m +CONFIG_CRYPTO_CRYPTD=m +CONFIG_CRYPTO_CTS=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_DEV_GEODE=m +CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y +CONFIG_CRYPTO_DEV_OMAP_AES=m +CONFIG_CRYPTO_DEV_OMAP_SHAM=m +CONFIG_CRYPTO_DEV_PADLOCK=y +CONFIG_CRYPTO_DEV_PADLOCK_AES=m +CONFIG_CRYPTO_DEV_PADLOCK_SHA=m +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_FCRYPT=m +CONFIG_CRYPTO_FPU=m +CONFIG_CRYPTO_GF128MUL=m +CONFIG_CRYPTO_GHASH=m +CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL=m +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_HW=y +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=m +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_PCBC=m +CONFIG_CRYPTO_PCOMP=m +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_PCRYPT=m +CONFIG_CRYPTO_RMD128=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_RMD256=m +CONFIG_CRYPTO_RMD320=m +CONFIG_CRYPTO_RNG=m +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_SALSA20_586=m +CONFIG_CRYPTO_SALSA20_X86_64=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_TGR192=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_TWOFISH_586=m +CONFIG_CRYPTO_TWOFISH_COMMON=m +CONFIG_CRYPTO_TWOFISH_X86_64=m +CONFIG_CRYPTO_VMAC=m +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_XTS=m +CONFIG_CRYPTO_ZLIB=m +CONFIG_CRYSTALHD=m +CONFIG_CS5535_GPIO=m +# CONFIG_CS5535_MFGPT is not set +CONFIG_CS89x0=m +CONFIG_CUSE=m +CONFIG_CXT1E1=m +CONFIG_CYCLADES=m +CONFIG_CYCLADES_SYNC=m +CONFIG_CYCLOMX_X25=y +# CONFIG_CYZ_INTR is not set +CONFIG_DCA=m +CONFIG_DCB=y +CONFIG_DCDBAS=m +CONFIG_DE2104X=m +CONFIG_DE2104X_DSL=0 +CONFIG_DE4X5=m +CONFIG_DE600=m +CONFIG_DE620=m +CONFIG_DEBUGGER=y +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_BOOT_PARAMS is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_DRIVER is not set +CONFIG_DEBUG_ERRORS=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_GPIO is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_ICEDCC is not set +# CONFIG_DEBUG_INFO_REDUCED is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_LIST is not set +CONFIG_DEBUG_LL=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_NX_TEST is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_DEBUG_RODATA=y +# CONFIG_DEBUG_RODATA_TEST is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +CONFIG_DEBUG_SET_MODULE_RONX=y +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DECNET=m +CONFIG_DECNET_NF_GRABULATOR=m +# CONFIG_DECNET_ROUTER is not set +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_LZO=y +CONFIG_DEFAULT_CUBIC=y +CONFIG_DEFAULT_IO_DELAY_TYPE=1 +# CONFIG_DEFAULT_NOOP is not set +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_SECURITY="apparmor" +CONFIG_DEFAULT_SECURITY_APPARMOR=y +# CONFIG_DEFAULT_SECURITY_DAC is not set +# CONFIG_DEFAULT_SECURITY_SELINUX is not set +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_TOMOYO is not set +# CONFIG_DEFAULT_SECURITY_YAMA is not set +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_DEFAULT_UIMAGE is not set +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_DEFXX=m +# CONFIG_DEFXX_MMIO is not set +CONFIG_DELL_LAPTOP=m +CONFIG_DELL_RBU=m +CONFIG_DELL_WMI=m +CONFIG_DEPCA=m +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +CONFIG_DETECT_HUNG_TASK=y +# CONFIG_DEVKMEM is not set +CONFIG_DEVPORT=y +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DEV_APPLETALK=m +CONFIG_DE_AOC=y +CONFIG_DIGIEPCA=m +CONFIG_DIRECT_GBPAGES=y +CONFIG_DLCI=m +CONFIG_DLCI_MAX=8 +CONFIG_DLM=m +# CONFIG_DLM_DEBUG is not set +# CONFIG_DM9000 is not set +CONFIG_DM9102=m +# CONFIG_DMADEVICES_DEBUG is not set +# CONFIG_DMAR is not set +# CONFIG_DMATEST is not set +# CONFIG_DMA_API_DEBUG is not set +CONFIG_DMA_ENGINE=y +CONFIG_DMI=y +CONFIG_DMIID=y +CONFIG_DM_CRYPT=m +# CONFIG_DM_DEBUG is not set +# CONFIG_DM_DELAY is not set +# CONFIG_DM_LOG_USERSPACE is not set +CONFIG_DM_MULTIPATH_QL=m +CONFIG_DM_MULTIPATH_ST=m +CONFIG_DM_UEVENT=y +CONFIG_DM_ZERO=m +CONFIG_DNET=m +CONFIG_DNOTIFY=y +CONFIG_DNS_RESOLVER=y +CONFIG_DONGLE=y +CONFIG_DOUBLEFAULT=y +CONFIG_DRAGONRISE_FF=y +# CONFIG_DRBD_FAULT_INJECTION is not set +CONFIG_DRM=m +CONFIG_DRM_I2C_CH7006=m +CONFIG_DRM_I2C_SIL164=m +CONFIG_DRM_I810=m +CONFIG_DRM_I830=m +CONFIG_DRM_I915=m +CONFIG_DRM_I915_KMS=y +CONFIG_DRM_KMS_HELPER=m +CONFIG_DRM_MGA=m +CONFIG_DRM_NOUVEAU_BACKLIGHT=y +CONFIG_DRM_NOUVEAU_DEBUG=y +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON_KMS=y +CONFIG_DRM_SAVAGE=m +CONFIG_DRM_SIS=m +CONFIG_DRM_TDFX=m +CONFIG_DRM_TTM=m +CONFIG_DRM_VIA=m +# CONFIG_DRM_VMWGFX is not set +CONFIG_DS1682=m +CONFIG_DSCC4=m +CONFIG_DSCC4_PCISYNC=y +CONFIG_DSCC4_PCI_RST=y +# CONFIG_DT3155_CCIR is not set +CONFIG_DTC=y +CONFIG_DTLK=m +CONFIG_DUMMY=m +CONFIG_DUMMY_CONSOLE=y +CONFIG_DVB_AF9013=m +CONFIG_DVB_ATBM8830=m +CONFIG_DVB_AU8522=m +CONFIG_DVB_AV7110=m +CONFIG_DVB_AV7110_OSD=y +CONFIG_DVB_B2C2_FLEXCOP=m +# CONFIG_DVB_B2C2_FLEXCOP_DEBUG is not set +CONFIG_DVB_B2C2_FLEXCOP_PCI=m +CONFIG_DVB_B2C2_FLEXCOP_USB=m +CONFIG_DVB_BCM3510=m +CONFIG_DVB_BT8XX=m +CONFIG_DVB_BUDGET=m +CONFIG_DVB_BUDGET_AV=m +CONFIG_DVB_BUDGET_CI=m +CONFIG_DVB_BUDGET_PATCH=m +CONFIG_DVB_CAPTURE_DRIVERS=y +CONFIG_DVB_CORE=m +CONFIG_DVB_CX22700=m +CONFIG_DVB_CX22702=m +CONFIG_DVB_CX24110=m +CONFIG_DVB_CX24116=m +CONFIG_DVB_CX24123=m +CONFIG_DVB_DIB3000MB=m +CONFIG_DVB_DIB3000MC=m +CONFIG_DVB_DIB7000M=m +CONFIG_DVB_DIB7000P=m +CONFIG_DVB_DIB8000=m +CONFIG_DVB_DM1105=m +CONFIG_DVB_DRX397XD=m +CONFIG_DVB_DS3000=m +# CONFIG_DVB_DUMMY_FE is not set +CONFIG_DVB_DYNAMIC_MINORS=y +CONFIG_DVB_EC100=m +CONFIG_DVB_FIREDTV=m +CONFIG_DVB_FIREDTV_FIREWIRE=y +# CONFIG_DVB_FIREDTV_IEEE1394 is not set +CONFIG_DVB_FIREDTV_INPUT=y +CONFIG_DVB_HOPPER=m +CONFIG_DVB_ISL6405=m +CONFIG_DVB_ISL6421=m +CONFIG_DVB_ISL6423=m +CONFIG_DVB_IX2505V=m +CONFIG_DVB_L64781=m +CONFIG_DVB_LGDT3305=m +CONFIG_DVB_LGDT330X=m +CONFIG_DVB_LGS8GL5=m +CONFIG_DVB_LGS8GXX=m +CONFIG_DVB_LNBP21=m +CONFIG_DVB_MANTIS=m +CONFIG_DVB_MAX_ADAPTERS=8 +CONFIG_DVB_MB86A16=m +CONFIG_DVB_MT312=m +CONFIG_DVB_MT352=m +CONFIG_DVB_NGENE=m +CONFIG_DVB_NXT200X=m +CONFIG_DVB_NXT6000=m +CONFIG_DVB_OR51132=m +CONFIG_DVB_OR51211=m +CONFIG_DVB_PLL=m +CONFIG_DVB_PLUTO2=m +CONFIG_DVB_PT1=m +CONFIG_DVB_S5H1409=m +CONFIG_DVB_S5H1411=m +CONFIG_DVB_S5H1420=m +CONFIG_DVB_S5H1432=m +CONFIG_DVB_S921=m +CONFIG_DVB_SI21XX=m +CONFIG_DVB_SP8870=m +CONFIG_DVB_SP887X=m +CONFIG_DVB_STB0899=m +CONFIG_DVB_STB6000=m +CONFIG_DVB_STB6100=m +CONFIG_DVB_STV0288=m +CONFIG_DVB_STV0297=m +CONFIG_DVB_STV0299=m +CONFIG_DVB_STV0900=m +CONFIG_DVB_STV090x=m +CONFIG_DVB_STV6110=m +CONFIG_DVB_STV6110x=m +CONFIG_DVB_TDA10021=m +CONFIG_DVB_TDA10023=m +CONFIG_DVB_TDA10048=m +CONFIG_DVB_TDA1004X=m +CONFIG_DVB_TDA10086=m +CONFIG_DVB_TDA665x=m +CONFIG_DVB_TDA8083=m +CONFIG_DVB_TDA8261=m +CONFIG_DVB_TDA826X=m +CONFIG_DVB_TTUSB_BUDGET=m +CONFIG_DVB_TTUSB_DEC=m +CONFIG_DVB_TUA6100=m +CONFIG_DVB_TUNER_CX24113=m +CONFIG_DVB_TUNER_DIB0070=m +CONFIG_DVB_TUNER_DIB0090=m +CONFIG_DVB_TUNER_ITD1000=m +CONFIG_DVB_USB=m +CONFIG_DVB_USB_A800=m +CONFIG_DVB_USB_AF9005=m +CONFIG_DVB_USB_AF9005_REMOTE=m +CONFIG_DVB_USB_AF9015=m +CONFIG_DVB_USB_ANYSEE=m +CONFIG_DVB_USB_AU6610=m +CONFIG_DVB_USB_AZ6027=m +CONFIG_DVB_USB_CE6230=m +CONFIG_DVB_USB_CINERGY_T2=m +CONFIG_DVB_USB_CXUSB=m +# CONFIG_DVB_USB_DEBUG is not set +CONFIG_DVB_USB_DIB0700=m +CONFIG_DVB_USB_DIBUSB_MB=m +CONFIG_DVB_USB_DIBUSB_MC=m +CONFIG_DVB_USB_DIGITV=m +CONFIG_DVB_USB_DTT200U=m +CONFIG_DVB_USB_DTV5100=m +CONFIG_DVB_USB_DW2102=m +CONFIG_DVB_USB_FRIIO=m +CONFIG_DVB_USB_GL861=m +CONFIG_DVB_USB_GP8PSK=m +CONFIG_DVB_USB_LME2510=m +CONFIG_DVB_USB_M920X=m +CONFIG_DVB_USB_NOVA_T_USB2=m +CONFIG_DVB_USB_OPERA1=m +CONFIG_DVB_USB_TTUSB2=m +CONFIG_DVB_USB_UMT_010=m +CONFIG_DVB_USB_VP702X=m +CONFIG_DVB_USB_VP7045=m +CONFIG_DVB_VES1820=m +CONFIG_DVB_VES1X93=m +CONFIG_DVB_ZL10036=m +CONFIG_DVB_ZL10039=m +CONFIG_DVB_ZL10353=m +# CONFIG_DYNAMIC_DEBUG is not set +CONFIG_DYNAMIC_FTRACE=y +CONFIG_E100=m +CONFIG_E1000=m +CONFIG_E1000E=m +# CONFIG_E200 is not set +CONFIG_E2100=m +CONFIG_EARLY_PRINTK=y +# CONFIG_EARLY_PRINTK_DBGP is not set +CONFIG_EASYCAP=m +CONFIG_ECONET=m +CONFIG_ECONET_AUNUDP=y +CONFIG_ECONET_NATIVE=y +CONFIG_ECRYPT_FS=y +CONFIG_EDAC=y +CONFIG_EDAC_AMD64=m +# CONFIG_EDAC_AMD64_ERROR_INJECTION is not set +CONFIG_EDAC_AMD76X=m +# CONFIG_EDAC_AMD8111 is not set +# CONFIG_EDAC_AMD8131 is not set +# CONFIG_EDAC_CPC925 is not set +# CONFIG_EDAC_DEBUG is not set +CONFIG_EDAC_DECODE_MCE=m +CONFIG_EDAC_E752X=m +CONFIG_EDAC_E7XXX=m +CONFIG_EDAC_I3000=m +CONFIG_EDAC_I3200=m +CONFIG_EDAC_I5000=m +CONFIG_EDAC_I5100=m +CONFIG_EDAC_I5400=m +CONFIG_EDAC_I7300=m +CONFIG_EDAC_I7CORE=m +CONFIG_EDAC_I82860=m +CONFIG_EDAC_I82875P=m +CONFIG_EDAC_I82975X=m +CONFIG_EDAC_MCE=y +CONFIG_EDAC_MCE_INJ=m +CONFIG_EDAC_MM_EDAC=m +# CONFIG_EDAC_PASEMI is not set +CONFIG_EDAC_R82600=m +CONFIG_EDAC_X38=m +CONFIG_EDD=y +CONFIG_EDD_OFF=y +CONFIG_EEEPC_LAPTOP=m +CONFIG_EEEPC_WMI=m +CONFIG_EEH=y +CONFIG_EEPROM_93CX6=m +CONFIG_EEPROM_AT24=m +CONFIG_EEPROM_AT25=m +CONFIG_EEPROM_LEGACY=m +CONFIG_EEPROM_MAX6875=m +CONFIG_EEXPRESS=m +CONFIG_EEXPRESS_PRO=m +CONFIG_EFI=y +CONFIG_EFI_PARTITION=y +CONFIG_EFI_VARS=y +CONFIG_EFS_FS=m +CONFIG_EISA=y +CONFIG_EISA_NAMES=y +CONFIG_EISA_PCI_EISA=y +CONFIG_EISA_VIRTUAL_ROOT=y +CONFIG_EISA_VLB_PRIMING=y +CONFIG_EL1=m +CONFIG_EL16=m +CONFIG_EL2=m +CONFIG_EL3=m +# CONFIG_ELECTRA_CF is not set +CONFIG_ELF_CORE=y +CONFIG_ELMC=m +CONFIG_ELMC_II=m +CONFIG_ELPLUS=m +# CONFIG_EMBEDDED is not set +# CONFIG_EMBEDDED6xx is not set +# CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENC28J60 is not set +CONFIG_ENIC=m +CONFIG_EPIC100=m +CONFIG_EPOLL=y +CONFIG_EQUALIZER=m +CONFIG_ES3210=m +CONFIG_ESI_DONGLE=m +# CONFIG_ET131X_DEBUG is not set +CONFIG_ETH16I=m +CONFIG_ETHOC=m +CONFIG_EUROTECH_WDT=m +CONFIG_EVENTFD=y +CONFIG_EVENT_TRACING=y +CONFIG_EWRK3=m +# CONFIG_EXOFS_DEBUG is not set +CONFIG_EXOFS_FS=m +CONFIG_EXPERIMENTAL=y +CONFIG_EXPORTFS=m +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_DEFAULTS_TO_ORDERED=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_FS_XATTR=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_EXTRA_TARGETS="" +CONFIG_F71808E_WDT=m +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FANOTIFY=y +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y +CONFIG_FARSYNC=m +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_FAT_FS=m +# CONFIG_FAULT_INJECTION is not set +CONFIG_FB=y +# CONFIG_FB_3DFX_ACCEL is not set +CONFIG_FB_3DFX_I2C=y +CONFIG_FB_ARC=m +CONFIG_FB_ARK=m +CONFIG_FB_ASILIANT=y +CONFIG_FB_ATY128_BACKLIGHT=y +CONFIG_FB_ATY_BACKLIGHT=y +CONFIG_FB_ATY_CT=y +CONFIG_FB_ATY_GENERIC_LCD=y +CONFIG_FB_ATY_GX=y +CONFIG_FB_BROADSHEET=m +CONFIG_FB_CARILLO_RANCH=m +CONFIG_FB_CARMINE=m +CONFIG_FB_CARMINE_DRAM_EVAL=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_CIRRUS=m +CONFIG_FB_CONTROL=y +CONFIG_FB_CT65550=y +CONFIG_FB_CYBER2000=m +CONFIG_FB_DEFERRED_IO=y +CONFIG_FB_EFI=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_GEODE=y +CONFIG_FB_GEODE_GX=m +CONFIG_FB_GEODE_GX1=m +CONFIG_FB_GEODE_LX=m +CONFIG_FB_HECUBA=m +CONFIG_FB_HGA=m +# CONFIG_FB_HGA_ACCEL is not set +CONFIG_FB_I810=m +# CONFIG_FB_I810_GTF is not set +CONFIG_FB_IBM_GXT4500=m +CONFIG_FB_IMSTT=y +CONFIG_FB_KYRO=m +CONFIG_FB_LE80578=m +CONFIG_FB_MATROX_G=y +CONFIG_FB_MATROX_I2C=m +CONFIG_FB_MATROX_MAVEN=m +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MB862XX=m +CONFIG_FB_MB862XX_PCI_GDC=y +CONFIG_FB_METRONOME=m +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_N411=m +CONFIG_FB_NEOMAGIC=m +CONFIG_FB_NVIDIA=m +CONFIG_FB_NVIDIA_BACKLIGHT=y +# CONFIG_FB_NVIDIA_DEBUG is not set +CONFIG_FB_NVIDIA_I2C=y +CONFIG_FB_OF=y +CONFIG_FB_OMAP2=y +CONFIG_FB_OMAP2_DEBUG_SUPPORT=y +CONFIG_FB_OMAP2_NUM_FBS=3 +# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set +# CONFIG_FB_OMAP_LCD_VGA is not set +CONFIG_FB_PLATINUM=y +CONFIG_FB_PM2=m +CONFIG_FB_PM2_FIFO_DISCONNECT=y +CONFIG_FB_PM3=m +CONFIG_FB_PS3=y +CONFIG_FB_PS3_DEFAULT_SIZE_M=9 +CONFIG_FB_RADEON_BACKLIGHT=y +# CONFIG_FB_RADEON_DEBUG is not set +CONFIG_FB_RADEON_I2C=y +CONFIG_FB_RIVA=m +CONFIG_FB_RIVA_BACKLIGHT=y +# CONFIG_FB_RIVA_DEBUG is not set +CONFIG_FB_RIVA_I2C=y +CONFIG_FB_S3=m +CONFIG_FB_SAVAGE_ACCEL=y +CONFIG_FB_SAVAGE_I2C=y +CONFIG_FB_SIS=m +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y +CONFIG_FB_SM501=m +CONFIG_FB_SM7XX=m +CONFIG_FB_TMIO=m +CONFIG_FB_TMIO_ACCELL=y +CONFIG_FB_TRIDENT=m +CONFIG_FB_VALKYRIE=y +CONFIG_FB_VIA=m +# CONFIG_FB_VIA_DIRECT_PROCFS is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FB_VT8623=m +CONFIG_FB_XGI=m +CONFIG_FCOE=m +CONFIG_FCOE_FNIC=m +CONFIG_FDDI=y +CONFIG_FEALNX=m +CONFIG_FIB_RULES=y +CONFIG_FILE_LOCKING=y +CONFIG_FIREWIRE=m +CONFIG_FIREWIRE_NET=m +CONFIG_FIREWIRE_NOSY=m +CONFIG_FIREWIRE_OHCI=m +CONFIG_FIREWIRE_OHCI_DEBUG=y +# CONFIG_FIREWIRE_OHCI_REMOTE_DMA is not set +CONFIG_FIREWIRE_SBP2=m +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_FIRMWARE_MEMMAP=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_FONT_10x18 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +CONFIG_FONT_8x16=y +CONFIG_FONT_8x8=y +CONFIG_FONT_ACORN_8x8=y +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_SUN8x16 is not set +CONFIG_FORCEDETH=m +# CONFIG_FPE_FASTFPE is not set +CONFIG_FPE_NWFPE=y +# CONFIG_FPE_NWFPE_XP is not set +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FRAME_POINTER=y +CONFIG_FRAME_WARN=1024 +CONFIG_FREEZER=y +CONFIG_FSCACHE=m +# CONFIG_FSCACHE_DEBUG is not set +CONFIG_FSCACHE_HISTOGRAM=y +# CONFIG_FSCACHE_OBJECT_LIST is not set +CONFIG_FSCACHE_STATS=y +# CONFIG_FSL_ULI1575 is not set +CONFIG_FSNOTIFY=y +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +CONFIG_FT1000=m +CONFIG_FT1000_USB=m +CONFIG_FTRACE=y +CONFIG_FTRACE_MCOUNT_RECORD=y +CONFIG_FTRACE_NMI_ENTER=y +# CONFIG_FTRACE_STARTUP_TEST is not set +CONFIG_FTRACE_SYSCALLS=y +# CONFIG_FTR_FIXUP_SELFTEST is not set +CONFIG_FUJITSU_LAPTOP=m +# CONFIG_FUJITSU_LAPTOP_DEBUG is not set +CONFIG_FUNCTION_GRAPH_TRACER=y +CONFIG_FUNCTION_PROFILER=y +CONFIG_FUSE_FS=y +CONFIG_FUSION=y +CONFIG_FUSION_CTL=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_LAN=m +CONFIG_FUSION_LOGGING=y +CONFIG_FUSION_MAX_SGE=128 +CONFIG_FUSION_SAS=m +CONFIG_FUSION_SPI=m +CONFIG_FUTEX=y +CONFIG_FW_LOADER=y +CONFIG_GACT_PROB=y +CONFIG_GAMEPORT=m +CONFIG_GAMEPORT_EMU10K1=m +CONFIG_GAMEPORT_FM801=m +CONFIG_GAMEPORT_L4=m +CONFIG_GAMEPORT_NS558=m +CONFIG_GARP=m +CONFIG_GART_IOMMU=y +# CONFIG_GCOV_KERNEL is not set +CONFIG_GELIC_NET=m +CONFIG_GELIC_WIRELESS=y +CONFIG_GENERIC_ACL=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ATOMIC64=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_FIND_LAST_BIT=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_GPIO=y +CONFIG_GENERIC_HARDIRQS=y +# CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_NVRAM=y +CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_GENERIC_TRACER=y +CONFIG_GFS2_FS=m +CONFIG_GFS2_FS_LOCKING_DLM=y +CONFIG_GIGASET_BASE=m +# CONFIG_GIGASET_CAPI is not set +# CONFIG_GIGASET_DEBUG is not set +# CONFIG_GIGASET_DUMMYLL is not set +CONFIG_GIGASET_I4L=y +CONFIG_GIGASET_M101=m +CONFIG_GIGASET_M105=m +CONFIG_GIRBIL_DONGLE=m +CONFIG_GPIOLIB=y +CONFIG_GPIO_74X164=m +CONFIG_GPIO_ADP5520=m +CONFIG_GPIO_ADP5588=m +CONFIG_GPIO_BASIC_MMIO=m +# CONFIG_GPIO_BT8XX is not set +CONFIG_GPIO_CS5535=m +CONFIG_GPIO_IT8761E=m +CONFIG_GPIO_LANGWELL=y +CONFIG_GPIO_MAX7300=m +CONFIG_GPIO_MAX7301=m +CONFIG_GPIO_MAX730X=m +CONFIG_GPIO_MC33880=m +CONFIG_GPIO_MCP23S08=m +CONFIG_GPIO_PCA953X_IRQ=y +# CONFIG_GPIO_PL061 is not set +CONFIG_GPIO_RDC321X=m +CONFIG_GPIO_SCH=m +CONFIG_GPIO_STMPE=y +CONFIG_GPIO_SX150X=y +CONFIG_GPIO_TC35892=y +CONFIG_GPIO_TIMBERDALE=y +CONFIG_GPIO_UCB1400=y +CONFIG_GPIO_WM831X=m +CONFIG_GPIO_WM8350=m +CONFIG_GPIO_WM8994=m +CONFIG_GPIO_XILINX=y +CONFIG_GREENASIA_FF=y +CONFIG_HAMACHI=m +CONFIG_HAMRADIO=y +CONFIG_HANGCHECK_TIMER=m +CONFIG_HAPPYMEAL=m +# CONFIG_HARDLOCKUP_DETECTOR is not set +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +# CONFIG_HAS_RAPIDIO is not set +CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_HAVE_ARCH_KMEMCHECK=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_ATOMIC_IOMAP=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_FTRACE_NMI_ENTER=y +CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_IDE=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_IRQ_WORK=y +CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_KVM=y +CONFIG_HAVE_KVM_EVENTFD=y +CONFIG_HAVE_KVM_IRQCHIP=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y +CONFIG_HAVE_MMIOTRACE_SUPPORT=y +CONFIG_HAVE_MTD_OTP=y +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_PERF_EVENTS_NMI=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_HAVE_PWM=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_SPARSE_IRQ=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_SYSCALL_WRAPPERS=y +CONFIG_HAVE_TEXT_POKE_SMP=y +CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y +CONFIG_HAVE_USER_RETURN_NOTIFIER=y +# CONFIG_HCALL_STATS is not set +CONFIG_HDLC=m +CONFIG_HDLC_CISCO=m +CONFIG_HDLC_FR=m +CONFIG_HDLC_PPP=m +CONFIG_HDLC_RAW=m +CONFIG_HDLC_RAW_ETH=m +CONFIG_HDLC_X25=m +CONFIG_HDQ_MASTER_OMAP=m +# CONFIG_HEADERS_CHECK is not set +CONFIG_HERMES=m +CONFIG_HERMES_CACHE_FW_ON_INIT=y +# CONFIG_HERMES_PRISM is not set +CONFIG_HFSPLUS_FS=m +CONFIG_HFS_FS=m +CONFIG_HIBERNATION=y +CONFIG_HID=m +CONFIG_HIDRAW=y +CONFIG_HID_3M_PCT=m +CONFIG_HID_A4TECH=m +CONFIG_HID_ACRUX_FF=m +CONFIG_HID_APPLE=m +CONFIG_HID_BELKIN=m +CONFIG_HID_CANDO=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_HID_EGALAX=m +CONFIG_HID_ELECOM=m +CONFIG_HID_EZKEY=m +CONFIG_HID_GREENASIA=m +CONFIG_HID_GYRATION=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_KYE=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_MAGICMOUSE=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MOSART=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_PICOLCD_BACKLIGHT=y +CONFIG_HID_PICOLCD_FB=y +CONFIG_HID_PICOLCD_LCD=y +CONFIG_HID_PICOLCD_LEDS=y +CONFIG_HID_PID=y +CONFIG_HID_PRODIKEYS=m +CONFIG_HID_QUANTA=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_ROCCAT_KONE=m +CONFIG_HID_ROCCAT_PYRA=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_HID_SONY=m +CONFIG_HID_STANTUM=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_SUPPORT=y +CONFIG_HID_THRUSTMASTER=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WACOM=m +CONFIG_HID_WACOM_POWER_SUPPLY=y +CONFIG_HID_WALTOP=m +CONFIG_HID_ZEROPLUS=m +CONFIG_HID_ZYDACRON=m +CONFIG_HIGHPTE=y +CONFIG_HIPPI=y +CONFIG_HISAX_16_0=y +CONFIG_HISAX_16_3=y +CONFIG_HISAX_1TR6=y +CONFIG_HISAX_ASUSCOM=y +CONFIG_HISAX_AVM_A1=y +CONFIG_HISAX_AVM_A1_CS=m +CONFIG_HISAX_AVM_A1_PCMCIA=y +CONFIG_HISAX_BKM_A4T=y +# CONFIG_HISAX_DEBUG is not set +CONFIG_HISAX_DIEHLDIVA=y +CONFIG_HISAX_ELSA=y +CONFIG_HISAX_ELSA_CS=m +CONFIG_HISAX_ENTERNOW_PCI=y +CONFIG_HISAX_EURO=y +CONFIG_HISAX_FRITZPCI=y +CONFIG_HISAX_FRITZ_PCIPNP=m +CONFIG_HISAX_GAZEL=y +CONFIG_HISAX_HFC4S8S=m +CONFIG_HISAX_HFCS=y +CONFIG_HISAX_HFCUSB=m +CONFIG_HISAX_HFC_PCI=y +CONFIG_HISAX_HFC_SX=y +CONFIG_HISAX_HSTSAPHIR=y +CONFIG_HISAX_ISURF=y +CONFIG_HISAX_IX1MICROR2=y +CONFIG_HISAX_MAX_CARDS=8 +CONFIG_HISAX_MIC=y +CONFIG_HISAX_NETJET=y +CONFIG_HISAX_NETJET_U=y +CONFIG_HISAX_NI1=y +CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_NO_KEYPAD is not set +# CONFIG_HISAX_NO_LLC is not set +# CONFIG_HISAX_NO_SENDCOMPLETE is not set +CONFIG_HISAX_S0BOX=y +CONFIG_HISAX_SCT_QUADRO=y +CONFIG_HISAX_SEDLBAUER=y +CONFIG_HISAX_SEDLBAUER_CS=m +CONFIG_HISAX_SPORTSTER=y +CONFIG_HISAX_ST5481=m +CONFIG_HISAX_TELEINT=y +CONFIG_HISAX_TELESPCI=y +CONFIG_HISAX_TELES_CS=m +CONFIG_HISAX_W6692=y +CONFIG_HMC6352=m +CONFIG_HOSTAP=m +CONFIG_HOSTAP_CS=m +CONFIG_HOSTAP_FIRMWARE=y +CONFIG_HOSTAP_FIRMWARE_NVRAM=y +CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_PLX=m +CONFIG_HOSTESS_SV11=m +CONFIG_HOTPLUG=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_HOTPLUG_PCI_ACPI_IBM=m +CONFIG_HOTPLUG_PCI_COMPAQ=m +CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM=y +CONFIG_HOTPLUG_PCI_CPCI=y +CONFIG_HOTPLUG_PCI_CPCI_GENERIC=m +CONFIG_HOTPLUG_PCI_CPCI_ZT5550=m +CONFIG_HOTPLUG_PCI_FAKE=m +CONFIG_HOTPLUG_PCI_IBM=m +CONFIG_HOTPLUG_PCI_PCIE=y +CONFIG_HOTPLUG_PCI_SHPC=m +CONFIG_HP100=m +CONFIG_HPET=y +CONFIG_HPET_EMULATE_RTC=y +CONFIG_HPET_MMAP=y +CONFIG_HPET_TIMER=y +CONFIG_HPFS_FS=m +CONFIG_HPLAN=m +CONFIG_HPLAN_PLUS=m +# CONFIG_HP_WATCHDOG is not set +CONFIG_HP_WMI=m +CONFIG_HTC_I2CPLD=y +CONFIG_HTC_PASIC3=m +CONFIG_HT_IRQ=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y +# CONFIG_HVC_CONSOLE is not set +CONFIG_HVC_DRIVER=y +CONFIG_HVC_IRQ=y +CONFIG_HVC_RTAS=y +CONFIG_HVC_UDBG=y +CONFIG_HVC_XEN=y +# CONFIG_HWMON_DEBUG_CHIP is not set +CONFIG_HWMON_VID=m +# CONFIG_HWPOISON_INJECT is not set +CONFIG_HW_CONSOLE=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_AMD=m +CONFIG_HW_RANDOM_GEODE=m +CONFIG_HW_RANDOM_INTEL=m +CONFIG_HW_RANDOM_PASEMI=y +CONFIG_HW_RANDOM_TIMERIOMEM=m +CONFIG_HW_RANDOM_VIA=m +CONFIG_HW_RANDOM_VIRTIO=m +CONFIG_HYPERV=m +CONFIG_HYPERV_BLOCK=m +CONFIG_HYPERV_NET=m +CONFIG_HYPERV_STORAGE=m +CONFIG_HYPERV_UTILS=m +CONFIG_HYSDN=m +CONFIG_HYSDN_CAPI=y +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_300 is not set +CONFIG_I2C=y +CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALI1535=m +CONFIG_I2C_ALI1563=m +CONFIG_I2C_ALI15X3=m +CONFIG_I2C_AMD756=m +CONFIG_I2C_AMD756_S4882=m +CONFIG_I2C_AMD8111=m +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_COMPAT=y +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CORE is not set +CONFIG_I2C_DESIGNWARE=m +CONFIG_I2C_HYDRA=m +CONFIG_I2C_INTEL_MID=m +CONFIG_I2C_ISCH=m +CONFIG_I2C_MPC=m +CONFIG_I2C_MUX=m +CONFIG_I2C_MUX_PCA9541=m +CONFIG_I2C_MUX_PCA954x=m +CONFIG_I2C_NFORCE2=m +CONFIG_I2C_NFORCE2_S4985=m +CONFIG_I2C_OCORES=m +CONFIG_I2C_OMAP=y +CONFIG_I2C_PARPORT=m +CONFIG_I2C_PARPORT_LIGHT=m +# CONFIG_I2C_PASEMI is not set +CONFIG_I2C_PCA_ISA=m +CONFIG_I2C_PCA_PLATFORM=m +CONFIG_I2C_PIIX4=m +CONFIG_I2C_POWERMAC=y +CONFIG_I2C_SCMI=m +CONFIG_I2C_SI470X=m +CONFIG_I2C_SI4713=m +CONFIG_I2C_SIMTEC=m +CONFIG_I2C_SIS5595=m +CONFIG_I2C_SIS630=m +CONFIG_I2C_SIS96X=m +CONFIG_I2C_SMBUS=m +CONFIG_I2C_STUB=m +CONFIG_I2C_TAOS_EVM=m +CONFIG_I2C_TINY_USB=m +CONFIG_I2C_VERSATILE=m +CONFIG_I2C_VIA=m +CONFIG_I2C_VIAPRO=m +CONFIG_I2C_XILINX=m +CONFIG_I2O=m +CONFIG_I2O_BLOCK=m +CONFIG_I2O_BUS=m +CONFIG_I2O_CONFIG=m +CONFIG_I2O_CONFIG_OLD_IOCTL=y +CONFIG_I2O_EXT_ADAPTEC=y +CONFIG_I2O_EXT_ADAPTEC_DMA64=y +CONFIG_I2O_LCT_NOTIFY_ON_CHANGES=y +CONFIG_I2O_PROC=m +CONFIG_I2O_SCSI=m +CONFIG_I6300ESB_WDT=m +CONFIG_I7300_IDLE=m +CONFIG_I7300_IDLE_IOAT_CHANNEL=y +CONFIG_I82092=m +CONFIG_I82365=m +CONFIG_I8K=m +# CONFIG_IA32_AOUT is not set +CONFIG_IA32_EMULATION=y +CONFIG_IB700_WDT=m +CONFIG_IBMASR=m +# CONFIG_IBMEBUS is not set +CONFIG_IBMLANA=m +CONFIG_IBMLS=m +# CONFIG_IBMMCA_SCSI_DEV_RESET is not set +CONFIG_IBMMCA_SCSI_ORDER_STANDARD=y +CONFIG_IBMOL=m +CONFIG_IBMTR=m +# CONFIG_IBMVETH is not set +CONFIG_IBMVIO=y +CONFIG_IBM_ASM=m +# CONFIG_IBM_BSR is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +CONFIG_IBM_RTL=m +CONFIG_ICS932S401=m +CONFIG_ICST=y +CONFIG_IDEAPAD_LAPTOP=m +CONFIG_IDEPCI_PCIBUS_ORDER=y +CONFIG_IDE_ATAPI=y +CONFIG_IDE_GD=y +CONFIG_IDE_GD_ATA=y +# CONFIG_IDE_GD_ATAPI is not set +CONFIG_IDE_PROC_FS=y +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TIMINGS=y +CONFIG_IDE_XFER_MODE=y +CONFIG_IEEE802154=m +CONFIG_IEEE802154_DRIVERS=m +# CONFIG_IEEE802154_FAKEHARD is not set +CONFIG_IFB=m +CONFIG_IGBVF=m +CONFIG_IGB_DCA=y +CONFIG_IIO_GPIO_TRIGGER=m +CONFIG_IIO_PERIODIC_RTC_TRIGGER=m +CONFIG_IIO_RING_BUFFER=y +CONFIG_IIO_SW_RING=m +CONFIG_IIO_TRIGGER=y +# CONFIG_IKCONFIG is not set +# CONFIG_IMA is not set +CONFIG_INET=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_INET6_TUNNEL=m +CONFIG_INET6_XFRM_MODE_BEET=m +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_INET6_XFRM_MODE_TRANSPORT=m +CONFIG_INET6_XFRM_MODE_TUNNEL=m +CONFIG_INET6_XFRM_TUNNEL=m +CONFIG_INET_AH=m +CONFIG_INET_DCCP_DIAG=m +CONFIG_INET_DIAG=y +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_LRO=y +CONFIG_INET_TCP_DIAG=y +CONFIG_INET_TUNNEL=m +CONFIG_INET_XFRM_MODE_BEET=m +CONFIG_INET_XFRM_MODE_TRANSPORT=m +CONFIG_INET_XFRM_MODE_TUNNEL=m +CONFIG_INET_XFRM_TUNNEL=m +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_ADDR_TRANS=y +CONFIG_INFINIBAND_AMSO1100=m +CONFIG_INFINIBAND_AMSO1100_DEBUG=y +CONFIG_INFINIBAND_CXGB3=m +# CONFIG_INFINIBAND_CXGB3_DEBUG is not set +CONFIG_INFINIBAND_CXGB4=m +CONFIG_INFINIBAND_IPATH=m +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_CM=y +CONFIG_INFINIBAND_IPOIB_DEBUG=y +# CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set +CONFIG_INFINIBAND_ISER=m +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_MTHCA_DEBUG=y +# CONFIG_INFINIBAND_NES is not set +CONFIG_INFINIBAND_QIB=m +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_MEM=y +CONFIG_INFTL=m +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_INIT_PASS_ALL_PARAMS=y +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +CONFIG_INLINE_READ_UNLOCK=y +# CONFIG_INLINE_READ_UNLOCK_BH is not set +CONFIG_INLINE_READ_UNLOCK_IRQ=y +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +CONFIG_INLINE_WRITE_UNLOCK=y +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +CONFIG_INOTIFY_USER=y +CONFIG_INPUT=y +CONFIG_INPUT_88PM860X_ONKEY=m +CONFIG_INPUT_AD714X=m +CONFIG_INPUT_AD714X_I2C=m +CONFIG_INPUT_AD714X_SPI=m +CONFIG_INPUT_ADBHID=y +CONFIG_INPUT_ADXL34X=m +CONFIG_INPUT_ADXL34X_I2C=m +CONFIG_INPUT_ADXL34X_SPI=m +# CONFIG_INPUT_APANEL is not set +CONFIG_INPUT_ATI_REMOTE=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_ATLAS_BTNS=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_EVBUG=m +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_FF_MEMLESS=m +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_INPUT_KEYBOARD=y +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_MAX8925_ONKEY=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_MOUSE=y +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_PCAP=m +CONFIG_INPUT_PCF50633_PMU=m +CONFIG_INPUT_PCF8574=m +CONFIG_INPUT_PCSPKR=m +CONFIG_INPUT_POLLDEV=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_PWM_BEEPER=m +CONFIG_INPUT_SPARSEKMAP=m +CONFIG_INPUT_TABLET=y +CONFIG_INPUT_TWL4030_PWRBUTTON=m +CONFIG_INPUT_TWL4030_VIBRA=m +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_WINBOND_CIR=m +CONFIG_INPUT_WISTRON_BTNS=m +CONFIG_INPUT_WM831X_ON=m +CONFIG_INPUT_YEALINK=m +CONFIG_INSTRUCTION_DECODER=y +CONFIG_INTEL_IOATDMA=m +CONFIG_INTEL_IPS=m +CONFIG_INTEL_MENLOW=m +CONFIG_INTEL_MID_DMAC=m +# CONFIG_IOMMU_DEBUG is not set +# CONFIG_IOMMU_STRESS is not set +CONFIG_IOSCHED_CFQ=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_NOOP=y +# CONFIG_IO_DELAY_0X80 is not set +CONFIG_IO_DELAY_0XED=y +# CONFIG_IO_DELAY_NONE is not set +CONFIG_IO_DELAY_TYPE_0X80=0 +CONFIG_IO_DELAY_TYPE_0XED=1 +CONFIG_IO_DELAY_TYPE_NONE=3 +CONFIG_IO_DELAY_TYPE_UDELAY=2 +# CONFIG_IO_DELAY_UDELAY is not set +CONFIG_IP1000=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_QUEUE=m +CONFIG_IP6_NF_RAW=m +CONFIG_IP6_NF_SECURITY=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_TARGET_LOG=m +CONFIG_IP6_NF_TARGET_REJECT=m +CONFIG_IPDDP=m +CONFIG_IPDDP_DECAP=y +CONFIG_IPDDP_ENCAP=y +# CONFIG_IPIC is not set +CONFIG_IPMI_DEVICE_INTERFACE=m +# CONFIG_IPMI_PANIC_EVENT is not set +CONFIG_IPMI_POWEROFF=m +CONFIG_IPMI_SI=m +CONFIG_IPMI_WATCHDOG=m +CONFIG_IPPP_FILTER=y +CONFIG_IPV6=y +# CONFIG_IPV6_MIP6 is not set +# CONFIG_IPV6_MROUTE is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_OPTIMISTIC_DAD is not set +CONFIG_IPV6_PRIVACY=y +# CONFIG_IPV6_ROUTER_PREF is not set +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +# CONFIG_IPV6_SUBTREES is not set +CONFIG_IPV6_TUNNEL=m +CONFIG_IPW2100=m +# CONFIG_IPW2100_DEBUG is not set +CONFIG_IPW2100_MONITOR=y +CONFIG_IPW2200=m +# CONFIG_IPW2200_DEBUG is not set +CONFIG_IPW2200_MONITOR=y +CONFIG_IPW2200_PROMISCUOUS=y +CONFIG_IPW2200_QOS=y +CONFIG_IPW2200_RADIOTAP=y +CONFIG_IPX=m +# CONFIG_IPX_INTERN is not set +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_DCCP=m +# CONFIG_IP_DCCP_CCID2_DEBUG is not set +CONFIG_IP_DCCP_CCID3=y +# CONFIG_IP_DCCP_CCID3_DEBUG is not set +# CONFIG_IP_DCCP_DEBUG is not set +CONFIG_IP_DCCP_TFRC_LIB=y +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_MROUTE=y +# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set +CONFIG_IP_MULTICAST=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_IP_NF_FILTER=m +CONFIG_IP_NF_IPTABLES=m +CONFIG_IP_NF_MANGLE=m +CONFIG_IP_NF_MATCH_ADDRTYPE=m +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_QUEUE=m +CONFIG_IP_NF_RAW=m +CONFIG_IP_NF_SECURITY=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_LOG=m +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_REJECT=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_TARGET_ULOG=m +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +# CONFIG_IP_PNP is not set +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_SCTP=m +CONFIG_IP_VS=m +# CONFIG_IP_VS_DEBUG is not set +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_NFCT=y +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_PE_SIP=m +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_AH_ESP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_TAB_BITS=12 +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_WRR=m +CONFIG_IRCOMM=m +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_DEBUG=y +CONFIG_IRDA_FAST_RR=y +CONFIG_IRDA_ULTRA=y +CONFIG_IRLAN=m +CONFIG_IRNET=m +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_IRQ_ALL_CPUS is not set +# CONFIG_IRQ_TIME_ACCOUNTING is not set +CONFIG_IRQ_WORK=y +CONFIG_IRTTY_SIR=m +CONFIG_IR_CORE=m +CONFIG_IR_ENE=m +CONFIG_IR_IMON=m +CONFIG_IR_JVC_DECODER=m +CONFIG_IR_LIRC_CODEC=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_NEC_DECODER=m +CONFIG_IR_NUVOTON=m +CONFIG_IR_RC5_DECODER=m +CONFIG_IR_RC5_SZ_DECODER=m +CONFIG_IR_RC6_DECODER=m +CONFIG_IR_SONY_DECODER=m +CONFIG_IR_STREAMZAP=m +CONFIG_ISAPNP=y +CONFIG_ISA_DMA_API=y +CONFIG_ISCSI_BOOT_SYSFS=m +CONFIG_ISCSI_IBFT=m +CONFIG_ISCSI_IBFT_FIND=y +CONFIG_ISCSI_TCP=m +CONFIG_ISDN_AUDIO=y +CONFIG_ISDN_CAPI=m +CONFIG_ISDN_CAPI_CAPI20=m +CONFIG_ISDN_CAPI_CAPIDRV=m +CONFIG_ISDN_CAPI_CAPIFS=m +CONFIG_ISDN_CAPI_CAPIFS_BOOL=y +CONFIG_ISDN_CAPI_MIDDLEWARE=y +CONFIG_ISDN_DIVAS=m +CONFIG_ISDN_DIVAS_BRIPCI=y +CONFIG_ISDN_DIVAS_DIVACAPI=m +CONFIG_ISDN_DIVAS_MAINT=m +CONFIG_ISDN_DIVAS_PRIPCI=y +CONFIG_ISDN_DIVAS_USERIDI=m +CONFIG_ISDN_DIVERSION=m +CONFIG_ISDN_DRV_ACT2000=m +CONFIG_ISDN_DRV_AVMB1_AVM_CS=m +CONFIG_ISDN_DRV_AVMB1_B1ISA=m +CONFIG_ISDN_DRV_AVMB1_B1PCI=m +CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +CONFIG_ISDN_DRV_AVMB1_B1PCMCIA=m +CONFIG_ISDN_DRV_AVMB1_C4=m +CONFIG_ISDN_DRV_AVMB1_T1ISA=m +CONFIG_ISDN_DRV_AVMB1_T1PCI=m +CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y +CONFIG_ISDN_DRV_GIGASET=m +CONFIG_ISDN_DRV_HISAX=m +CONFIG_ISDN_DRV_ICN=m +CONFIG_ISDN_DRV_LOOP=m +CONFIG_ISDN_DRV_PCBIT=m +CONFIG_ISDN_DRV_SC=m +CONFIG_ISDN_HDLC=m +CONFIG_ISDN_I4L=m +CONFIG_ISDN_MPP=y +CONFIG_ISDN_PPP=y +CONFIG_ISDN_PPP_BSDCOMP=m +CONFIG_ISDN_PPP_VJ=y +CONFIG_ISDN_TTY_FAX=y +CONFIG_ISDN_X25=y +# CONFIG_ISI is not set +CONFIG_ISL29003=m +CONFIG_ISL29020=m +CONFIG_ISO9660_FS=m +CONFIG_ISP1301_OMAP=m +CONFIG_ISTALLION=m +CONFIG_IT8712F_WDT=m +CONFIG_IT87_WDT=m +CONFIG_ITCO_VENDOR_SUPPORT=y +CONFIG_ITCO_WDT=m +CONFIG_IWL5000=y +CONFIG_IWLAGN=m +CONFIG_IWLWIFI=m +# CONFIG_IWLWIFI_DEBUG is not set +CONFIG_IWLWIFI_DEBUGFS=y +CONFIG_IWLWIFI_DEVICE_TRACING=y +CONFIG_IWM=m +CONFIG_IWMC3200TOP=m +# CONFIG_IWMC3200TOP_DEBUG is not set +# CONFIG_IWM_DEBUG is not set +CONFIG_IWM_TRACING=y +CONFIG_IXGB=m +CONFIG_IXGBE=m +CONFIG_IXGBEVF=m +CONFIG_IXGBE_DCA=y +CONFIG_IXGBE_DCB=y +CONFIG_JBD=y +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +# CONFIG_JBD_DEBUG is not set +CONFIG_JFFS2_CMODE_FAVOURLZO=y +# CONFIG_JFFS2_CMODE_NONE is not set +# CONFIG_JFFS2_CMODE_PRIORITY is not set +# CONFIG_JFFS2_CMODE_SIZE is not set +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_XATTR is not set +CONFIG_JFFS2_LZO=y +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_JFFS2_SUMMARY is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFS_DEBUG is not set +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_JFS_STATISTICS=y +CONFIG_JME=m +CONFIG_JOLIET=y +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_DB9=m +CONFIG_JOYSTICK_GAMECON=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_232=y +CONFIG_JOYSTICK_IFORCE_USB=y +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_TURBOGRAFX=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_WALKERA0701=m +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_JUMP_LABEL=y +CONFIG_K8_NUMA=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_KARMA_PARTITION=y +CONFIG_KDB_KEYBOARD=y +# CONFIG_KERNEL_BZIP2 is not set +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_KEXEC=y +CONFIG_KEXEC_JUMP=y +CONFIG_KEYBOARD_ADP5520=m +CONFIG_KEYBOARD_ADP5588=m +CONFIG_KEYBOARD_ATKBD=y +CONFIG_KEYBOARD_GPIO=m +CONFIG_KEYBOARD_GPIO_POLLED=m +CONFIG_KEYBOARD_LM8323=m +CONFIG_KEYBOARD_MATRIX=m +CONFIG_KEYBOARD_MAX7359=m +CONFIG_KEYBOARD_MCS=m +CONFIG_KEYBOARD_OPENCORES=m +# CONFIG_KEYBOARD_QT2160 is not set +CONFIG_KEYBOARD_STMPE=m +CONFIG_KEYBOARD_STOWAWAY=m +CONFIG_KEYBOARD_TCA6416=m +CONFIG_KEYBOARD_TWL4030=m +CONFIG_KEYS=y +CONFIG_KEYS_COMPAT=y +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +CONFIG_KGDB_KDB=y +CONFIG_KGDB_LOW_LEVEL_TRAP=y +CONFIG_KGDB_SERIAL_CONSOLE=y +# CONFIG_KGDB_TESTS is not set +CONFIG_KINGSUN_DONGLE=m +CONFIG_KPROBES=y +# CONFIG_KPROBES_SANITY_TEST is not set +CONFIG_KPROBE_EVENT=y +CONFIG_KRETPROBES=y +CONFIG_KS0108=m +CONFIG_KS0108_DELAY=2 +CONFIG_KS0108_PORT=0x378 +CONFIG_KS8842=m +CONFIG_KS8851=m +CONFIG_KS8851_MLL=m +CONFIG_KS959_DONGLE=m +CONFIG_KSDAZZLE_DONGLE=m +CONFIG_KSZ884X_PCI=m +CONFIG_KVM_AMD=m +CONFIG_KVM_APIC_ARCHITECTURE=y +CONFIG_KVM_BOOK3S_32=m +CONFIG_KVM_BOOK3S_32_HANDLER=y +# CONFIG_KVM_BOOK3S_64 is not set +CONFIG_KVM_BOOK3S_HANDLER=y +CONFIG_KVM_CLOCK=y +CONFIG_KVM_GUEST=y +CONFIG_KVM_INTEL=m +CONFIG_KVM_MMIO=y +# CONFIG_KVM_MMU_AUDIT is not set +CONFIG_KXSD9=m +CONFIG_L2TP=m +CONFIG_L2TP_DEBUGFS=m +# CONFIG_L2TP_V3 is not set +CONFIG_LANCE=m +CONFIG_LANMEDIA=m +CONFIG_LAPB=m +CONFIG_LBDAF=y +CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_ILI9320=m +CONFIG_LCD_L4F00242T03=m +CONFIG_LCD_LMS283GF05=m +CONFIG_LCD_LTV350QV=m +CONFIG_LCD_PLATFORM=m +CONFIG_LCD_S6E63M0=m +CONFIG_LCD_TDO24M=m +CONFIG_LCD_VGG2432A4=m +# CONFIG_LDM_DEBUG is not set +CONFIG_LDM_PARTITION=y +CONFIG_LEDS=y +CONFIG_LEDS_88PM860X=m +CONFIG_LEDS_ADP5520=m +CONFIG_LEDS_ALIX2=m +CONFIG_LEDS_BD2802=m +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLEVO_MAIL is not set +CONFIG_LEDS_CPU=y +CONFIG_LEDS_DA903X=m +CONFIG_LEDS_DAC124S085=m +CONFIG_LEDS_DELL_NETBOOKS=m +CONFIG_LEDS_GPIO_PLATFORM=y +CONFIG_LEDS_INTEL_SS4200=m +CONFIG_LEDS_LP3944=m +CONFIG_LEDS_LP5521=m +CONFIG_LEDS_LP5523=m +CONFIG_LEDS_LT3593=m +CONFIG_LEDS_MC13783=m +CONFIG_LEDS_NET48XX=m +CONFIG_LEDS_NET5501=m +CONFIG_LEDS_PWM=m +CONFIG_LEDS_REGULATOR=m +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=m +CONFIG_LEDS_TRIGGER_GPIO=m +# CONFIG_LEDS_TRIGGER_IDE_DISK is not set +CONFIG_LEDS_WM831X_STATUS=m +CONFIG_LEDS_WM8350=m +CONFIG_LEDS_WRAP=m +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=0 +# CONFIG_LGUEST is not set +# CONFIG_LGUEST_GUEST is not set +CONFIG_LIB80211=m +CONFIG_LIB80211_CRYPT_CCMP=m +CONFIG_LIB80211_CRYPT_TKIP=m +CONFIG_LIB80211_CRYPT_WEP=m +# CONFIG_LIB80211_DEBUG is not set +CONFIG_LIBCRC32C=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_CS=m +# CONFIG_LIBERTAS_DEBUG is not set +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_SPI=m +CONFIG_LIBERTAS_THINFIRM=m +# CONFIG_LIBERTAS_THINFIRM_DEBUG is not set +CONFIG_LIBERTAS_THINFIRM_USB=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBFC=m +CONFIG_LIBFCOE=m +CONFIG_LIBIPW=m +# CONFIG_LINE6_USB_DEBUG is not set +# CONFIG_LINE6_USB_DUMP_CTRL is not set +# CONFIG_LINE6_USB_DUMP_MIDI is not set +# CONFIG_LINE6_USB_DUMP_PCM is not set +# CONFIG_LINE6_USB_IMPULSE_RESPONSE is not set +# CONFIG_LINE6_USB_RAW is not set +CONFIG_LIRC=m +CONFIG_LIRC_BT829=m +CONFIG_LIRC_I2C=m +CONFIG_LIRC_IGORPLUGUSB=m +CONFIG_LIRC_IMON=m +CONFIG_LIRC_IT87=m +CONFIG_LIRC_ITE8709=m +# CONFIG_LIRC_PARALLEL is not set +CONFIG_LIRC_SASEM=m +CONFIG_LIRC_SERIAL=m +CONFIG_LIRC_SERIAL_TRANSMITTER=y +CONFIG_LIRC_SIR=m +CONFIG_LIRC_STAGING=y +CONFIG_LIRC_TTUSBIR=m +CONFIG_LIRC_ZILOG=m +CONFIG_LIS3L02DQ=m +CONFIG_LITELINK_DONGLE=m +# CONFIG_LKDTM is not set +CONFIG_LNE390=m +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_LOCKD=m +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_LOCKD_V4=y +# CONFIG_LOCKUP_DETECTOR is not set +CONFIG_LOCK_KERNEL=y +# CONFIG_LOCK_STAT is not set +# CONFIG_LOGFS is not set +CONFIG_LOGIG940_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGITECH_FF=y +CONFIG_LOGIWII_FF=y +# CONFIG_LOGO is not set +CONFIG_LOWMEM_SIZE=0x30000000 +CONFIG_LP486E=m +# CONFIG_LPARCFG is not set +CONFIG_LPC_SCH=m +# CONFIG_LP_CONSOLE is not set +CONFIG_LRU_CACHE=m +CONFIG_LSM_MMAP_MIN_ADDR=0 +CONFIG_LTPC=m +CONFIG_LZO_DECOMPRESS=y +CONFIG_M25PXX_USE_FAST_READ=y +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586MMX is not set +# CONFIG_M586TSC is not set +CONFIG_MA600_DONGLE=m +CONFIG_MAC80211=m +CONFIG_MAC80211_DEBUGFS=y +# CONFIG_MAC80211_DEBUG_MENU is not set +CONFIG_MAC80211_HAS_RC=y +CONFIG_MAC80211_HWSIM=m +CONFIG_MAC80211_LEDS=y +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" +CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL=y +CONFIG_MAC80211_RC_MINSTREL_HT=y +CONFIG_MACE=m +# CONFIG_MACE_AAUI_PORT is not set +CONFIG_MACHZ_WDT=m +# CONFIG_MACH_CM_T35 is not set +CONFIG_MACH_CM_T3517=y +# CONFIG_MACH_DEVKIT8000 is not set +CONFIG_MACH_IGEP0020=y +CONFIG_MACH_IGEP0030=y +CONFIG_MACH_NOKIA_RX51=y +# CONFIG_MACH_OMAP3517EVM is not set +CONFIG_MACH_OMAP3530_LV_SOM=y +CONFIG_MACH_OMAP3EVM=y +CONFIG_MACH_OMAP3_BEAGLE=y +CONFIG_MACH_OMAP3_PANDORA=y +CONFIG_MACH_OMAP3_TORPEDO=y +CONFIG_MACH_OMAP3_TOUCHBOOK=y +CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL=y +CONFIG_MACH_OMAP_3430SDP=y +CONFIG_MACH_OMAP_3630SDP=y +CONFIG_MACH_OMAP_LDP=y +CONFIG_MACH_OMAP_ZOOM2=y +CONFIG_MACH_OMAP_ZOOM3=y +CONFIG_MACH_OVERO=y +CONFIG_MACH_SBC3530=y +CONFIG_MACH_VERSATILE_AB=y +CONFIG_MACINTOSH_DRIVERS=y +CONFIG_MACVLAN=m +# CONFIG_MACVTAP is not set +CONFIG_MAC_EMUMOUSEBTN=y +CONFIG_MAC_FLOPPY=m +CONFIG_MAC_PARTITION=y +CONFIG_MADGEMC=m +CONFIG_MAGIC_SYSRQ=y +CONFIG_MANTIS_CORE=m +# CONFIG_MATH_EMULATION is not set +# CONFIG_MATOM is not set +CONFIG_MAX1363=m +CONFIG_MAX1363_RING_BUFFER=y +CONFIG_MAX63XX_WATCHDOG=m +CONFIG_MAX8925_POWER=m +# CONFIG_MAXSMP is not set +CONFIG_MAX_RAW_DEVS=256 +CONFIG_MCA=y +CONFIG_MCA_LEGACY=y +# CONFIG_MCA_PROC_FS is not set +# CONFIG_MCORE2 is not set +CONFIG_MCP2120_DONGLE=m +# CONFIG_MCRUSOE is not set +CONFIG_MCS_FIR=m +# CONFIG_MCYRIXIII is not set +CONFIG_MD=y +CONFIG_MDA_CONSOLE=m +CONFIG_MDIO=m +CONFIG_MD_AUTODETECT=y +CONFIG_MD_FAULTY=m +CONFIG_MD_LINEAR=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID10=m +CONFIG_MD_RAID456=m +CONFIG_MEDIA_ATTACH=y +CONFIG_MEDIA_SUPPORT=m +CONFIG_MEDIA_TUNER=m +# CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_MAX2165=m +CONFIG_MEDIA_TUNER_MC44S803=m +CONFIG_MEDIA_TUNER_MT2060=m +CONFIG_MEDIA_TUNER_MT20XX=m +CONFIG_MEDIA_TUNER_MT2131=m +CONFIG_MEDIA_TUNER_MT2266=m +CONFIG_MEDIA_TUNER_MXL5005S=m +CONFIG_MEDIA_TUNER_MXL5007T=m +CONFIG_MEDIA_TUNER_QT1010=m +CONFIG_MEDIA_TUNER_SIMPLE=m +CONFIG_MEDIA_TUNER_TDA18218=m +CONFIG_MEDIA_TUNER_TDA18271=m +CONFIG_MEDIA_TUNER_TDA827X=m +CONFIG_MEDIA_TUNER_TDA8290=m +CONFIG_MEDIA_TUNER_TDA9887=m +CONFIG_MEDIA_TUNER_TEA5761=m +CONFIG_MEDIA_TUNER_TEA5767=m +CONFIG_MEDIA_TUNER_XC2028=m +CONFIG_MEDIA_TUNER_XC5000=m +# CONFIG_MEFFICEON is not set +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_SAS=m +CONFIG_MEMORY_FAILURE=y +CONFIG_MEMORY_HOTPLUG_SPARSE=y +# CONFIG_MEMSTICK_DEBUG is not set +CONFIG_MEMSTICK_JMICRON_38X=m +CONFIG_MEMSTICK_TIFM_MS=m +# CONFIG_MEMSTICK_UNSAFE_RESUME is not set +# CONFIG_MEMTEST is not set +CONFIG_MFD_88PM860X=y +CONFIG_MFD_CORE=y +CONFIG_MFD_MAX8925=y +CONFIG_MFD_MAX8998=y +CONFIG_MFD_MC13783=m +CONFIG_MFD_MC13XXX=m +CONFIG_MFD_PCF50633=m +CONFIG_MFD_RDC321X=m +CONFIG_MFD_SM501=m +# CONFIG_MFD_SM501_GPIO is not set +CONFIG_MFD_STMPE=y +CONFIG_MFD_SUPPORT=y +CONFIG_MFD_TC35892=y +CONFIG_MFD_TIMBERDALE=m +CONFIG_MFD_TPS6586X=y +CONFIG_MFD_VX855=m +CONFIG_MFD_WM831X=y +CONFIG_MFD_WM831X_I2C=y +CONFIG_MFD_WM831X_SPI=y +CONFIG_MFD_WM8350=y +CONFIG_MFD_WM8350_I2C=y +CONFIG_MFD_WM8400=m +CONFIG_MFD_WM8994=y +# CONFIG_MGEODEGX1 is not set +# CONFIG_MGEODE_LX is not set +CONFIG_MG_DISK=m +CONFIG_MG_DISK_RES=0 +CONFIG_MICREL_PHY=m +CONFIG_MICROCODE=m +CONFIG_MICROCODE_AMD=y +CONFIG_MICROCODE_INTEL=y +CONFIG_MICROCODE_OLD_INTERFACE=y +CONFIG_MIGRATION=y +CONFIG_MII=y +CONFIG_MINIX_FS=m +CONFIG_MINIX_SUBPARTITION=y +CONFIG_MISC_DEVICES=y +CONFIG_MISC_FILESYSTEMS=y +CONFIG_MISDN=m +CONFIG_MISDN_AVMFRITZ=m +CONFIG_MISDN_DSP=m +CONFIG_MISDN_HFCMULTI=m +CONFIG_MISDN_HFCPCI=m +CONFIG_MISDN_HFCUSB=m +CONFIG_MISDN_INFINEON=m +CONFIG_MISDN_IPAC=m +CONFIG_MISDN_ISAR=m +CONFIG_MISDN_L1OIP=m +CONFIG_MISDN_NETJET=m +CONFIG_MISDN_SPEEDFAX=m +CONFIG_MISDN_W6692=m +CONFIG_MIXCOMWD=m +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MK8 is not set +CONFIG_MKISS=m +CONFIG_MLX4_CORE=m +CONFIG_MLX4_DEBUG=y +CONFIG_MLX4_EN=m +CONFIG_MLX4_INFINIBAND=m +CONFIG_MMC_BLOCK_BOUNCE=y +CONFIG_MMC_BLOCK_MINORS=8 +CONFIG_MMC_CB710=m +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_OMAP=m +CONFIG_MMC_OMAP_HS=y +CONFIG_MMC_RICOH_MMC=y +CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +CONFIG_MMC_SDHCI_OF=m +CONFIG_MMC_SDHCI_OF_ESDHC=y +CONFIG_MMC_SDHCI_OF_HLWD=y +CONFIG_MMC_SDHCI_PCI=m +CONFIG_MMC_SDHCI_PLTFM=m +CONFIG_MMC_SDRICOH_CS=m +CONFIG_MMC_SPI=m +# CONFIG_MMC_TEST is not set +CONFIG_MMC_TIFM_SD=m +# CONFIG_MMC_TMIO is not set +# CONFIG_MMC_UNSAFE_RESUME is not set +CONFIG_MMC_USHC=m +CONFIG_MMC_VIA_SDMMC=m +CONFIG_MMC_WBSD=m +CONFIG_MMIOTRACE=y +# CONFIG_MMIOTRACE_TEST is not set +CONFIG_MMU=y +CONFIG_MMU_NOTIFIER=y +CONFIG_MM_OWNER=y +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MOUSE_APPLETOUCH=m +# CONFIG_MOUSE_ATIXL is not set +CONFIG_MOUSE_BCM5974=m +CONFIG_MOUSE_GPIO=m +CONFIG_MOUSE_INPORT=m +CONFIG_MOUSE_LOGIBM=m +CONFIG_MOUSE_PC110PAD=m +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_ELANTECH=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_OLPC=y +CONFIG_MOUSE_PS2_SENTELIC=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +CONFIG_MOUSE_PS2_TRACKPOINT=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_SYNAPTICS_I2C=m +CONFIG_MOXA_INTELLIO=m +# CONFIG_MPENTIUM4 is not set +# CONFIG_MPENTIUMII is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUMM is not set +CONFIG_MPIC=y +CONFIG_MPIC_BROKEN_REGREAD=y +# CONFIG_MPIC_WEIRD is not set +# CONFIG_MPSC is not set +CONFIG_MSDOS_FS=m +CONFIG_MSDOS_PARTITION=y +# CONFIG_MSI_BITMAP_SELFTEST is not set +CONFIG_MSI_LAPTOP=m +CONFIG_MSI_WMI=m +CONFIG_MSPRO_BLOCK=m +CONFIG_MTDRAM_ERASE_SIZE=128 +CONFIG_MTDRAM_TOTAL_SIZE=4096 +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_AMD76XROM=m +CONFIG_MTD_BLOCK2MTD=m +CONFIG_MTD_BLOCK_RO=m +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_NOSWAP=y +CONFIG_MTD_CK804XROM=m +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_DATAFLASH_OTP=y +# CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_DOCECC=m +CONFIG_MTD_DOCPROBE=m +CONFIG_MTD_DOCPROBE_ADDRESS=0 +# CONFIG_MTD_DOCPROBE_ADVANCED is not set +CONFIG_MTD_ESB2ROM=m +CONFIG_MTD_ICHXROM=m +# CONFIG_MTD_IMPA7 is not set +CONFIG_MTD_INTEL_VR_NOR=m +CONFIG_MTD_L440GX=m +CONFIG_MTD_LPDDR=m +CONFIG_MTD_M25P80=m +CONFIG_MTD_MAP_BANK_WIDTH_1=y +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +CONFIG_MTD_NAND_CAFE=m +CONFIG_MTD_NAND_CS553X=m +CONFIG_MTD_NAND_DENALI=m +CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018 +CONFIG_MTD_NAND_DISKONCHIP=m +# CONFIG_MTD_NAND_DISKONCHIP_BBTWRITE is not set +CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS=0 +# CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADVANCED is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_FSL_ELBC is not set +# CONFIG_MTD_NAND_GPIO is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +CONFIG_MTD_NAND_OMAP2=y +CONFIG_MTD_NAND_OMAP_PREFETCH=y +CONFIG_MTD_NAND_OMAP_PREFETCH_DMA=y +# CONFIG_MTD_NAND_PASEMI is not set +CONFIG_MTD_NAND_RICOH=m +# CONFIG_MTD_NAND_TMIO is not set +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +CONFIG_MTD_NETSC520=m +CONFIG_MTD_NETtel=m +# CONFIG_MTD_OF_PARTS is not set +CONFIG_MTD_ONENAND_2X_PROGRAM=y +CONFIG_MTD_ONENAND_GENERIC=m +CONFIG_MTD_ONENAND_OMAP2=m +# CONFIG_MTD_ONENAND_OTP is not set +CONFIG_MTD_ONENAND_SIM=m +CONFIG_MTD_ONENAND_VERIFY_WRITE=y +CONFIG_MTD_OOPS=m +# CONFIG_MTD_OTP is not set +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_PCI=m +CONFIG_MTD_PCMCIA=m +# CONFIG_MTD_PCMCIA_ANONYMOUS is not set +# CONFIG_MTD_PHYSMAP_COMPAT is not set +CONFIG_MTD_PHYSMAP_OF=m +CONFIG_MTD_PISMO=m +CONFIG_MTD_PMC551=m +# CONFIG_MTD_PMC551_BUGFIX is not set +# CONFIG_MTD_PMC551_DEBUG is not set +CONFIG_MTD_QINFO_PROBE=m +CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 +# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set +# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set +CONFIG_MTD_SBC_GXX=m +CONFIG_MTD_SC520CDP=m +CONFIG_MTD_SCB2_FLASH=m +CONFIG_MTD_SCx200_DOCFLASH=m +CONFIG_MTD_TESTS=m +CONFIG_MTD_TS5500=m +CONFIG_MTD_UBI=m +CONFIG_MTD_UBI_BEB_RESERVE=1 +# CONFIG_MTD_UBI_DEBUG is not set +CONFIG_MTD_UBI_GLUEBI=m +CONFIG_MTD_UBI_WL_THRESHOLD=4096 +CONFIG_MTRR=y +CONFIG_MTRR_SANITIZER=y +CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0 +CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 +# CONFIG_MULTICORE_RAID456 is not set +# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_MV643XX_ETH=m +# CONFIG_MVIAC3_2 is not set +# CONFIG_MVIAC7 is not set +CONFIG_MWAVE=m +# CONFIG_MWINCHIP3D is not set +# CONFIG_MWINCHIPC6 is not set +CONFIG_MWL8K=m +CONFIG_MYRI10GE=m +CONFIG_MYRI10GE_DCA=y +CONFIG_N2=m +CONFIG_NAMESPACES=y +CONFIG_NATSEMI=m +CONFIG_NCPFS_EXTRAS=y +CONFIG_NCPFS_IOCTL_LOCKING=y +CONFIG_NCPFS_NFS_NS=y +CONFIG_NCPFS_NLS=y +CONFIG_NCPFS_OS2_NS=y +CONFIG_NCPFS_PACKET_SIGNING=y +# CONFIG_NCPFS_SMALLDOS is not set +CONFIG_NCPFS_STRONG=y +CONFIG_NCP_FS=m +CONFIG_NDISWRAPPER=m +CONFIG_NE2000=m +CONFIG_NE2K_PCI=m +CONFIG_NE2_MCA=m +CONFIG_NE3210=m +CONFIG_NEED_MULTIPLE_NODES=y +CONFIG_NEED_PER_CPU_KM=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NEON=y +CONFIG_NET=y +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_NETDEVICES=y +CONFIG_NETDEV_1000=y +CONFIG_NETDEV_10000=y +CONFIG_NETFILTER=y +CONFIG_NETFILTER_ADVANCED=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_NETLINK=m +CONFIG_NETFILTER_NETLINK_LOG=m +CONFIG_NETFILTER_NETLINK_QUEUE=m +CONFIG_NETFILTER_TPROXY=m +CONFIG_NETFILTER_XTABLES=m +CONFIG_NETFILTER_XT_CONNMARK=m +CONFIG_NETFILTER_XT_MARK=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_HL=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SCTP=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=m +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_CT=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETLABEL=y +CONFIG_NETPOLL=y +# CONFIG_NETPOLL_TRAP is not set +CONFIG_NETROM=m +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETWORK_SECMARK=y +CONFIG_NETXEN_NIC=m +CONFIG_NET_9P=m +# CONFIG_NET_9P_DEBUG is not set +CONFIG_NET_9P_RDMA=m +CONFIG_NET_9P_VIRTIO=m +CONFIG_NET_ACT_CSUM=m +CONFIG_NET_ACT_GACT=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_CLS=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_FW=m +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_CLS_ROUTE=y +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_DMA=y +# CONFIG_NET_DROP_MONITOR is not set +CONFIG_NET_DSA=y +CONFIG_NET_DSA_MV88E6060=y +CONFIG_NET_DSA_MV88E6123_61_65=y +CONFIG_NET_DSA_MV88E6131=y +CONFIG_NET_DSA_MV88E6XXX=y +CONFIG_NET_DSA_MV88E6XXX_NEED_PPU=y +CONFIG_NET_DSA_TAG_DSA=y +CONFIG_NET_DSA_TAG_EDSA=y +CONFIG_NET_DSA_TAG_TRAILER=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_ETHERNET=y +CONFIG_NET_FC=y +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPIP=m +CONFIG_NET_ISA=y +CONFIG_NET_KEY=m +# CONFIG_NET_KEY_MIGRATE is not set +CONFIG_NET_NS=y +CONFIG_NET_PCI=y +CONFIG_NET_PCMCIA=y +CONFIG_NET_PKTGEN=m +CONFIG_NET_POLL_CONTROLLER=y +CONFIG_NET_SB1000=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_FIFO=y +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCTPPROBE=m +CONFIG_NET_TULIP=y +CONFIG_NET_VENDOR_3COM=y +CONFIG_NET_VENDOR_RACAL=y +CONFIG_NET_VENDOR_SMC=y +CONFIG_NEW_LEDS=y +CONFIG_NFSD=m +CONFIG_NFSD_DEPRECATED=y +CONFIG_NFSD_V2_ACL=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFS_ACL_SUPPORT=m +CONFIG_NFS_COMMON=y +CONFIG_NFS_FS=m +CONFIG_NFS_FSCACHE=y +CONFIG_NFS_USE_KERNEL_DNS=y +# CONFIG_NFS_USE_LEGACY_DNS is not set +# CONFIG_NFS_USE_NEW_IDMAPPER is not set +CONFIG_NFS_V3=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +CONFIG_NFTL_RW=y +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IPV4=m +CONFIG_NF_CONNTRACK_IPV6=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_CT_PROTO_DCCP=m +CONFIG_NF_CT_PROTO_GRE=m +CONFIG_NF_CT_PROTO_SCTP=m +CONFIG_NF_CT_PROTO_UDPLITE=m +CONFIG_NF_DEFRAG_IPV4=m +CONFIG_NF_DEFRAG_IPV6=m +CONFIG_NF_NAT=m +CONFIG_NF_NAT_AMANDA=m +CONFIG_NF_NAT_FTP=m +CONFIG_NF_NAT_H323=m +CONFIG_NF_NAT_IRC=m +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PPTP=m +CONFIG_NF_NAT_PROTO_DCCP=m +CONFIG_NF_NAT_PROTO_GRE=m +CONFIG_NF_NAT_PROTO_SCTP=m +CONFIG_NF_NAT_PROTO_UDPLITE=m +CONFIG_NF_NAT_SIP=m +CONFIG_NF_NAT_SNMP_BASIC=m +CONFIG_NF_NAT_TFTP=m +CONFIG_NI52=m +CONFIG_NI65=m +CONFIG_NILFS2_FS=m +# CONFIG_NL80211_TESTMODE is not set +CONFIG_NLATTR=y +CONFIG_NLS=y +CONFIG_NLS_ASCII=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m +CONFIG_NODES_SPAN_OTHER_NODES=y +# CONFIG_NOHIGHMEM is not set +CONFIG_NOP_TRACER=y +CONFIG_NO_BOOTMEM=y +CONFIG_NR_IRQS=512 +CONFIG_NS83820=m +CONFIG_NSC_FIR=m +CONFIG_NSC_GPIO=m +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_FS=m +# CONFIG_NTFS_RW is not set +CONFIG_NUMA=y +# CONFIG_NUMA_EMU is not set +# CONFIG_N_GSM is not set +CONFIG_N_HDLC=m +CONFIG_OABI_COMPAT=y +# CONFIG_OCFS2_DEBUG_FS is not set +CONFIG_OCFS2_DEBUG_MASKLOG=y +CONFIG_OCFS2_FS=m +CONFIG_OCFS2_FS_O2CB=m +CONFIG_OCFS2_FS_STATS=y +CONFIG_OCFS2_FS_USERSPACE_CLUSTER=m +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DEVICE=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_I2C=y +CONFIG_OF_IRQ=y +CONFIG_OF_MDIO=y +CONFIG_OF_SPI=y +CONFIG_OLD_BELKIN_DONGLE=m +CONFIG_OLPC=y +CONFIG_OLPC_OPENFIRMWARE=y +CONFIG_OLPC_XO1=m +CONFIG_OMAP2_DSS=y +# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set +CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y +CONFIG_OMAP2_DSS_DPI=y +# CONFIG_OMAP2_DSS_DSI is not set +# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set +CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=0 +# CONFIG_OMAP2_DSS_RFBI is not set +CONFIG_OMAP2_DSS_SDI=y +CONFIG_OMAP2_DSS_VENC=y +CONFIG_OMAP2_VRAM=y +CONFIG_OMAP2_VRAM_SIZE=6 +CONFIG_OMAP2_VRFB=y +CONFIG_OMAP3_EMU=y +# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set +# CONFIG_OMAP3_SDRC_AC_TIMING is not set +CONFIG_OMAP_32K_TIMER=y +CONFIG_OMAP_32K_TIMER_HZ=128 +CONFIG_OMAP_DM_TIMER=y +CONFIG_OMAP_MBOX_FWK=m +CONFIG_OMAP_MBOX_KFIFO_SIZE=256 +CONFIG_OMAP_MCBSP=y +# CONFIG_OMAP_MPU_TIMER is not set +CONFIG_OMAP_MUX=y +# CONFIG_OMAP_MUX_DEBUG is not set +CONFIG_OMAP_MUX_WARNINGS=y +CONFIG_OMAP_PACKAGE_CBB=y +CONFIG_OMAP_PACKAGE_CBP=y +CONFIG_OMAP_PACKAGE_CUS=y +# CONFIG_OMAP_PM_NONE is not set +CONFIG_OMAP_PM_NOOP=y +CONFIG_OMAP_RESET_CLOCKS=y +CONFIG_OMAP_WATCHDOG=m +CONFIG_OMFS_FS=m +CONFIG_OMNIBOOK=m +CONFIG_OPROFILE=m +# CONFIG_OPROFILE_EVENT_MULTIPLEX is not set +CONFIG_OPTIMIZE_INLINING=y +CONFIG_OPTPROBES=y +CONFIG_ORINOCO_USB=m +CONFIG_OSF_PARTITION=y +CONFIG_P54_COMMON=m +CONFIG_P54_LEDS=y +CONFIG_P54_PCI=m +CONFIG_P54_SPI=m +# CONFIG_P54_SPI_DEFAULT_EEPROM is not set +CONFIG_P54_USB=m +CONFIG_PACKARDBELL_E5=m +CONFIG_PACKET=y +CONFIG_PADATA=y +CONFIG_PAGEFLAGS_EXTENDED=y +# CONFIG_PAGE_POISONING is not set +CONFIG_PANASONIC_LAPTOP=m +CONFIG_PANEL_ACX565AKM=m +# CONFIG_PANEL_CHANGE_MESSAGE is not set +CONFIG_PANEL_GENERIC=y +CONFIG_PANEL_PARPORT=0 +CONFIG_PANEL_PROFILE=5 +CONFIG_PANEL_SHARP_LQ043T1DG01=y +CONFIG_PANEL_SHARP_LS037V7DW01=y +CONFIG_PANEL_TOPPOLY_TDO35S=y +CONFIG_PANEL_TPO_TD043MTEA1=y +CONFIG_PANTHERLORD_FF=y +CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_CLOCK=y +# CONFIG_PARAVIRT_DEBUG is not set +CONFIG_PARAVIRT_GUEST=y +CONFIG_PARAVIRT_SPINLOCKS=y +CONFIG_PARIDE=m +CONFIG_PARIDE_ATEN=m +CONFIG_PARIDE_BPCK=m +CONFIG_PARIDE_BPCK6=m +CONFIG_PARIDE_COMM=m +CONFIG_PARIDE_DSTR=m +CONFIG_PARIDE_EPAT=m +# CONFIG_PARIDE_EPATC8 is not set +CONFIG_PARIDE_EPIA=m +CONFIG_PARIDE_FIT2=m +CONFIG_PARIDE_FIT3=m +CONFIG_PARIDE_FRIQ=m +CONFIG_PARIDE_FRPW=m +CONFIG_PARIDE_KBIC=m +CONFIG_PARIDE_KTTI=m +CONFIG_PARIDE_ON20=m +CONFIG_PARIDE_ON26=m +CONFIG_PARIDE_PCD=m +CONFIG_PARIDE_PD=m +CONFIG_PARIDE_PF=m +CONFIG_PARIDE_PG=m +CONFIG_PARIDE_PT=m +CONFIG_PARPORT_1284=y +CONFIG_PARPORT_AX88796=m +# CONFIG_PARPORT_GSC is not set +CONFIG_PARPORT_NOT_PC=y +CONFIG_PARPORT_PC=m +CONFIG_PARPORT_PC_FIFO=y +CONFIG_PARPORT_PC_PCMCIA=m +# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_SERIAL=m +CONFIG_PARTITION_ADVANCED=y +# CONFIG_PASEMI_MAC is not set +CONFIG_PATA_ACPI=y +CONFIG_PATA_AMD=m +CONFIG_PATA_ATP867X=m +CONFIG_PATA_CS5520=m +CONFIG_PATA_CS5535=m +CONFIG_PATA_CS5536=m +CONFIG_PATA_EFAR=m +# CONFIG_PATA_HPT3X3_DMA is not set +CONFIG_PATA_ISAPNP=m +CONFIG_PATA_IT8213=m +CONFIG_PATA_IT821X=m +CONFIG_PATA_JMICRON=m +CONFIG_PATA_LEGACY=m +CONFIG_PATA_MACIO=m +CONFIG_PATA_MARVELL=m +CONFIG_PATA_MPIIX=m +CONFIG_PATA_NETCELL=m +CONFIG_PATA_NINJA32=m +CONFIG_PATA_OF_PLATFORM=m +CONFIG_PATA_OLDPIIX=m +CONFIG_PATA_PCMCIA=m +CONFIG_PATA_PDC2027X=m +CONFIG_PATA_PLATFORM=m +CONFIG_PATA_QDI=m +CONFIG_PATA_RDC=m +CONFIG_PATA_RZ1000=m +CONFIG_PATA_SCH=m +CONFIG_PATA_SERVERWORKS=m +CONFIG_PATA_SIL680=m +# CONFIG_PATA_TOSHIBA is not set +CONFIG_PATA_TRIFLEX=m +CONFIG_PATA_VIA=m +CONFIG_PATA_WINBOND=m +CONFIG_PATA_WINBOND_VLB=m +# CONFIG_PC300TOO is not set +CONFIG_PC8736x_GPIO=m +CONFIG_PC87413_WDT=m +CONFIG_PCCARD_NONSTATIC=y +CONFIG_PCF50633_ADC=m +CONFIG_PCF50633_GPIO=m +CONFIG_PCH_CAN=m +CONFIG_PCH_DMA=m +CONFIG_PCH_GBE=m +CONFIG_PCH_PHUB=m +CONFIG_PCI=y +CONFIG_PCI200SYN=m +CONFIG_PCIEAER=y +# CONFIG_PCIEAER_INJECT is not set +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEBUG is not set +CONFIG_PCIEPORTBUS=y +# CONFIG_PCIE_ECRC is not set +CONFIG_PCIE_PME=y +CONFIG_PCIPCWATCHDOG=m +CONFIG_PCI_ATMEL=m +CONFIG_PCI_BIOS=y +CONFIG_PCI_CNB20LE_QUIRK=y +# CONFIG_PCI_DEBUG is not set +CONFIG_PCI_DIRECT=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_GOANY=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GODIRECT is not set +# CONFIG_PCI_GOMMCONFIG is not set +# CONFIG_PCI_GOOLPC is not set +CONFIG_PCI_IOAPIC=y +CONFIG_PCI_MMCONFIG=y +CONFIG_PCI_MSI=y +CONFIG_PCI_OLPC=y +CONFIG_PCI_QUIRKS=y +CONFIG_PCI_XEN=y +CONFIG_PCMCIA=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_3C589=m +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_ATMEL=m +CONFIG_PCMCIA_AXNET=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_FMVJ18X=m +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_IBMTR=m +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_PCMCIA_PCNET=m +CONFIG_PCMCIA_PROBE=y +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_RAYCS=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_PCMCIA_SPECTRUM=m +CONFIG_PCMCIA_SYM53C500=m +CONFIG_PCMCIA_WL3501=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_PCNET32=m +CONFIG_PCSPKR_PLATFORM=y +CONFIG_PCWATCHDOG=m +CONFIG_PD6729=m +CONFIG_PDA_POWER=m +CONFIG_PERF_COUNTERS=y +CONFIG_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y +CONFIG_PHANTOM=m +CONFIG_PHONE=m +CONFIG_PHONET=m +# CONFIG_PHONET_PIPECTRLR is not set +CONFIG_PHONE_IXJ=m +CONFIG_PHONE_IXJ_PCMCIA=m +CONFIG_PHYLIB=y +# CONFIG_PHYP_DUMP is not set +# CONFIG_PLAT_SPEAR is not set +CONFIG_PLAT_VERSATILE=y +CONFIG_PLIP=m +CONFIG_PM=y +CONFIG_PMAC_APM_EMU=m +CONFIG_PMAC_BACKLIGHT=y +CONFIG_PMAC_BACKLIGHT_LEGACY=y +CONFIG_PMAC_MEDIABAY=y +CONFIG_PMAC_RACKMETER=m +CONFIG_PMAC_SMU=y +CONFIG_PMIC_ADP5520=y +CONFIG_PMIC_DA903X=y +# CONFIG_PM_ADVANCED_DEBUG is not set +CONFIG_PM_OPS=y +CONFIG_PM_RUNTIME=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_STD_PARTITION="" +CONFIG_PM_TEST_SUSPEND=y +CONFIG_PM_TRACE=y +CONFIG_PM_TRACE_RTC=y +# CONFIG_PM_VERBOSE is not set +CONFIG_PNP=y +CONFIG_PNPACPI=y +CONFIG_PNPBIOS=y +CONFIG_PNPBIOS_PROC_FS=y +CONFIG_PNP_DEBUG_MESSAGES=y +CONFIG_POHMELFS_CRYPTO=y +# CONFIG_POHMELFS_DEBUG is not set +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +CONFIG_POWER3=y +CONFIG_POWER4=y +# CONFIG_POWER4_ONLY is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +CONFIG_PPC=y +CONFIG_PPC32=y +# CONFIG_PPC601_SYNC_FIX is not set +CONFIG_PPC_4K_PAGES=y +# CONFIG_PPC_64K_PAGES is not set +# CONFIG_PPC_82xx is not set +# CONFIG_PPC_83xx is not set +# CONFIG_PPC_85xx is not set +# CONFIG_PPC_86xx is not set +# CONFIG_PPC_8xx is not set +# CONFIG_PPC_BOOK3E_64 is not set +CONFIG_PPC_BOOK3S=y +CONFIG_PPC_BOOK3S_32=y +CONFIG_PPC_BOOK3S_64=y +# CONFIG_PPC_CELLEB is not set +# CONFIG_PPC_CELL_NATIVE is not set +# CONFIG_PPC_CELL_QPACE is not set +CONFIG_PPC_CHRP=y +# CONFIG_PPC_CLOCK is not set +# CONFIG_PPC_DCR_MMIO is not set +# CONFIG_PPC_DCR_NATIVE is not set +CONFIG_PPC_DISABLE_WERROR=y +# CONFIG_PPC_EARLY_DEBUG is not set +# CONFIG_PPC_EMULATED_STATS is not set +CONFIG_PPC_FPU=y +CONFIG_PPC_HAS_HASH_64K=y +CONFIG_PPC_HAVE_PMU_SUPPORT=y +CONFIG_PPC_I8259=y +# CONFIG_PPC_IBM_CELL_BLADE is not set +# CONFIG_PPC_INDIRECT_IO is not set +# CONFIG_PPC_ISERIES is not set +CONFIG_PPC_MAPLE=y +# CONFIG_PPC_MPC512x is not set +# CONFIG_PPC_MPC52xx is not set +CONFIG_PPC_MSI_BITMAP=y +CONFIG_PPC_NATIVE=y +CONFIG_PPC_OF=y +CONFIG_PPC_OF_BOOT_TRAMPOLINE=y +# CONFIG_PPC_OF_PLATFORM_PCI is not set +CONFIG_PPC_PASEMI=y +CONFIG_PPC_PASEMI_CPUFREQ=y +CONFIG_PPC_PASEMI_IOMMU=y +# CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE is not set +CONFIG_PPC_PASEMI_MDIO=y +CONFIG_PPC_PCI_CHOICE=y +CONFIG_PPC_PERF_CTRS=y +CONFIG_PPC_PMAC=y +CONFIG_PPC_PMAC64=y +CONFIG_PPC_PS3=y +CONFIG_PPC_PSERIES=y +CONFIG_PPC_RTAS=y +CONFIG_PPC_RTAS_DAEMON=y +# CONFIG_PPC_SMLPAR is not set +# CONFIG_PPC_SPLPAR is not set +CONFIG_PPC_STD_MMU=y +CONFIG_PPC_STD_MMU_32=y +CONFIG_PPC_STD_MMU_64=y +CONFIG_PPC_UDBG_16550=y +CONFIG_PPDEV=m +CONFIG_PPPOATM=m +CONFIG_PPPOE=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPS=m +# CONFIG_PPS_CLIENT_KTIMER is not set +CONFIG_PPS_CLIENT_LDISC=m +# CONFIG_PPS_DEBUG is not set +CONFIG_PPTP=m +# CONFIG_PQ2ADS is not set +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_NOTIFIERS=y +# CONFIG_PREEMPT_RCU is not set +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_PRINTER=m +CONFIG_PRINTK=y +CONFIG_PRINTK_TIME=y +CONFIG_PRINT_STACK_DEPTH=64 +CONFIG_PRISM2_USB=m +CONFIG_PRISM54=m +CONFIG_PROC_DEVICETREE=y +CONFIG_PROC_EVENTS=y +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_PROC_PID_CPUSET=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_VMCORE=y +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +CONFIG_PROFILING=y +CONFIG_PROTEON=m +# CONFIG_PROVE_LOCKING is not set +# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set +# CONFIG_PS3_ADVANCED is not set +CONFIG_PS3_DISK=m +# CONFIG_PS3_DYNAMIC_DMA is not set +CONFIG_PS3_FLASH=m +CONFIG_PS3_HTAB_SIZE=20 +CONFIG_PS3_LPM=m +CONFIG_PS3_PS3AV=y +CONFIG_PS3_ROM=m +CONFIG_PS3_STORAGE=m +CONFIG_PS3_SYS_MANAGER=y +CONFIG_PS3_VRAM=m +CONFIG_PS3_VUART=y +CONFIG_PSERIES_MSI=y +CONFIG_QFMT_V1=m +CONFIG_QFMT_V2=m +CONFIG_QLA3XXX=m +CONFIG_QLCNIC=m +CONFIG_QLGE=m +CONFIG_QNX4FS_FS=m +CONFIG_QUOTA=y +CONFIG_QUOTACTL=y +CONFIG_QUOTACTL_COMPAT=y +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_QUOTA_TREE=m +# CONFIG_R6040 is not set +CONFIG_R8169=m +CONFIG_R8169_VLAN=y +CONFIG_R8187SE=m +CONFIG_R8712U=m +# CONFIG_R8712_AP is not set +CONFIG_RADIO_ADAPTERS=y +CONFIG_RADIO_AZTECH=m +CONFIG_RADIO_CADET=m +CONFIG_RADIO_GEMTEK=m +CONFIG_RADIO_GEMTEK_PCI=m +CONFIG_RADIO_MAESTRO=m +CONFIG_RADIO_MAXIRADIO=m +CONFIG_RADIO_MIROPCM20=m +CONFIG_RADIO_RTRACK=m +CONFIG_RADIO_RTRACK2=m +CONFIG_RADIO_SAA7706H=m +CONFIG_RADIO_SF16FMI=m +CONFIG_RADIO_SF16FMR2=m +CONFIG_RADIO_SI470X=y +CONFIG_RADIO_SI4713=m +CONFIG_RADIO_TEA5764=m +CONFIG_RADIO_TEF6862=m +CONFIG_RADIO_TERRATEC=m +CONFIG_RADIO_TIMBERDALE=m +CONFIG_RADIO_TRUST=m +CONFIG_RADIO_TYPHOON=m +CONFIG_RADIO_ZOLTRIX=m +CONFIG_RAID6_PQ=m +CONFIG_RAID_ATTRS=m +CONFIG_RAMOOPS=m +CONFIG_RAW_DRIVER=m +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_RCU_FANOUT_EXACT is not set +CONFIG_RCU_FAST_NO_HZ=y +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +CONFIG_RC_MAP=m +CONFIG_RDS=m +# CONFIG_RDS_DEBUG is not set +CONFIG_RDS_RDMA=m +CONFIG_RDS_TCP=m +CONFIG_RD_BZIP2=y +CONFIG_RD_GZIP=y +CONFIG_RD_LZMA=y +CONFIG_RD_LZO=y +CONFIG_REED_SOLOMON=m +CONFIG_REED_SOLOMON_DEC16=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_88PM8607=y +CONFIG_REGULATOR_AB3100=m +CONFIG_REGULATOR_AD5398=m +CONFIG_REGULATOR_BQ24022=m +CONFIG_REGULATOR_DA903X=m +# CONFIG_REGULATOR_DUMMY is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +CONFIG_REGULATOR_ISL6271A=m +CONFIG_REGULATOR_LP3971=m +CONFIG_REGULATOR_LP3972=m +CONFIG_REGULATOR_MAX1586=m +CONFIG_REGULATOR_MAX8649=m +CONFIG_REGULATOR_MAX8660=m +CONFIG_REGULATOR_MAX8925=m +CONFIG_REGULATOR_MAX8952=m +CONFIG_REGULATOR_MAX8998=m +CONFIG_REGULATOR_MC13783=m +# CONFIG_REGULATOR_PCAP is not set +CONFIG_REGULATOR_PCF50633=m +CONFIG_REGULATOR_TPS65023=m +CONFIG_REGULATOR_TPS6507X=m +CONFIG_REGULATOR_TPS6586X=m +CONFIG_REGULATOR_TWL4030=y +CONFIG_REGULATOR_USERSPACE_CONSUMER=m +CONFIG_REGULATOR_VIRTUAL_CONSUMER=m +CONFIG_REGULATOR_WM831X=m +CONFIG_REGULATOR_WM8350=m +CONFIG_REGULATOR_WM8400=m +CONFIG_REGULATOR_WM8994=m +# CONFIG_REISERFS_CHECK is not set +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_REISERFS_FS_XATTR=y +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_RELAY=y +CONFIG_RFKILL=y +CONFIG_RFKILL_INPUT=y +CONFIG_RFKILL_LEDS=y +CONFIG_RING_BUFFER=y +CONFIG_RING_BUFFER_ALLOW_SWAP=y +# CONFIG_RING_BUFFER_BENCHMARK is not set +CONFIG_ROADRUNNER=m +# CONFIG_ROADRUNNER_LARGE_RINGS is not set +CONFIG_ROCKETPORT=m +CONFIG_ROMFS_BACKED_BY_BLOCK=y +# CONFIG_ROMFS_BACKED_BY_BOTH is not set +# CONFIG_ROMFS_BACKED_BY_MTD is not set +CONFIG_ROMFS_FS=m +CONFIG_ROMFS_ON_BLOCK=y +CONFIG_ROSE=m +CONFIG_RPCSEC_GSS_KRB5=m +CONFIG_RPS=y +CONFIG_RT2400PCI=m +CONFIG_RT2500PCI=m +CONFIG_RT2500USB=m +CONFIG_RT2800PCI=m +CONFIG_RT2800PCI_PCI=y +CONFIG_RT2800PCI_RT30XX=y +CONFIG_RT2800PCI_RT35XX=y +CONFIG_RT2800USB=m +# CONFIG_RT2800USB_RT30XX is not set +# CONFIG_RT2800USB_RT35XX is not set +CONFIG_RT2800_LIB=m +CONFIG_RT2860=m +CONFIG_RT2870=m +CONFIG_RT2X00=m +# CONFIG_RT2X00_DEBUG is not set +CONFIG_RT2X00_LIB=m +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_HT=y +CONFIG_RT2X00_LIB_LEDS=y +CONFIG_RT2X00_LIB_PCI=m +CONFIG_RT2X00_LIB_USB=m +CONFIG_RT61PCI=m +CONFIG_RT73USB=m +CONFIG_RTAS_ERROR_LOGGING=y +# CONFIG_RTAS_FLASH is not set +CONFIG_RTAS_PROC=y +CONFIG_RTC_CLASS=y +# CONFIG_RTC_DEBUG is not set +CONFIG_RTC_DRV_AB3100=m +CONFIG_RTC_DRV_BQ32K=m +CONFIG_RTC_DRV_BQ4802=m +CONFIG_RTC_DRV_DS1286=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1374=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_DS1511=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_DS3232=m +CONFIG_RTC_DRV_DS3234=m +CONFIG_RTC_DRV_FM3130=m +CONFIG_RTC_DRV_GENERIC=m +CONFIG_RTC_DRV_ISL12022=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_M41T80=m +CONFIG_RTC_DRV_M41T80_WDT=y +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_M48T35=m +CONFIG_RTC_DRV_M48T59=m +CONFIG_RTC_DRV_M48T86=m +CONFIG_RTC_DRV_MAX6900=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_MAX8925=m +CONFIG_RTC_DRV_MAX8998=m +CONFIG_RTC_DRV_MC13XXX=m +CONFIG_RTC_DRV_MSM6242=m +CONFIG_RTC_DRV_PCAP=m +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_PCF50633=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_PS3=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RP5C01=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_RS5C372=m +CONFIG_RTC_DRV_RX8025=m +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_S35390A=m +CONFIG_RTC_DRV_STK17TA8=m +CONFIG_RTC_DRV_V3020=m +CONFIG_RTC_DRV_WM831X=m +CONFIG_RTC_DRV_WM8350=m +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_LIB=y +CONFIG_RTL8187=m +CONFIG_RTL8187_LEDS=y +CONFIG_RTL8192SE=m +CONFIG_RTL8192U=m +CONFIG_RT_GROUP_SCHED=y +CONFIG_RT_MUTEXES=y +# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_RXKAD=m +CONFIG_S2IO=m +# CONFIG_SAMPLES is not set +CONFIG_SAMSUNG_LAPTOP=m +CONFIG_SATA_AHCI=m +CONFIG_SATA_AHCI_PLATFORM=m +CONFIG_SATA_INIC162X=m +CONFIG_SATA_MV=m +CONFIG_SATA_NV=m +CONFIG_SATA_PMP=y +CONFIG_SATA_PROMISE=m +CONFIG_SATA_QSTOR=m +CONFIG_SATA_SIL=m +CONFIG_SATA_SIL24=m +CONFIG_SATA_SIS=m +CONFIG_SATA_SX4=m +CONFIG_SATA_ULI=m +CONFIG_SATA_VIA=m +CONFIG_SATA_VITESSE=m +CONFIG_SBC7240_WDT=m +CONFIG_SBC8360_WDT=m +CONFIG_SBC_EPX_C3_WATCHDOG=m +CONFIG_SBC_FITPC2_WATCHDOG=m +CONFIG_SBE_2T3E3=m +CONFIG_SBE_PMCC4_NCOMM=y +CONFIG_SBNI=m +# CONFIG_SBNI_MULTILINE is not set +CONFIG_SC1200_WDT=m +CONFIG_SC520_WDT=m +CONFIG_SC92031=m +CONFIG_SCA3000=m +# CONFIG_SCANLOG is not set +CONFIG_SCC=m +# CONFIG_SCC_DELAY is not set +# CONFIG_SCC_TRXECHO is not set +CONFIG_SCHED_AUTOGROUP=y +CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_HRTICK=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +CONFIG_SCHED_SMT=y +CONFIG_SCSI=y +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_3W_SAS=m +CONFIG_SCSI_7000FASST=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AHA1740=m +CONFIG_SCSI_AIC79XX=m +CONFIG_SCSI_AIC7XXX=m +# CONFIG_SCSI_AIC7XXX_OLD is not set +CONFIG_SCSI_AIC94XX=m +CONFIG_SCSI_ARCMSR=m +CONFIG_SCSI_ARCMSR_AER=y +CONFIG_SCSI_BFA_FC=m +CONFIG_SCSI_BNX2_ISCSI=m +CONFIG_SCSI_BUSLOGIC=m +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_CXGB3_ISCSI=m +CONFIG_SCSI_CXGB4_ISCSI=m +CONFIG_SCSI_DC390T=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_DEBUG=m +CONFIG_SCSI_DH_ALUA=m +CONFIG_SCSI_DH_EMC=m +CONFIG_SCSI_DH_HP_SW=m +CONFIG_SCSI_DH_RDAC=m +CONFIG_SCSI_DMA=y +CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_DPT_I2O=m +CONFIG_SCSI_DTC3280=m +CONFIG_SCSI_EATA=m +CONFIG_SCSI_EATA_LINKED_COMMANDS=y +CONFIG_SCSI_EATA_MAX_TAGS=16 +CONFIG_SCSI_EATA_TAGGED_QUEUE=y +CONFIG_SCSI_ENCLOSURE=m +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_FC_TGT_ATTRS=y +CONFIG_SCSI_FD_MCS=m +# CONFIG_SCSI_FLASHPOINT is not set +CONFIG_SCSI_FUTURE_DOMAIN=m +CONFIG_SCSI_GDTH=m +CONFIG_SCSI_GENERIC_NCR5380=m +CONFIG_SCSI_GENERIC_NCR5380_MMIO=m +CONFIG_SCSI_GENERIC_NCR53C400=y +CONFIG_SCSI_HPSA=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_IBMMCA=m +# CONFIG_SCSI_IBMVFC is not set +# CONFIG_SCSI_IBMVSCSI is not set +# CONFIG_SCSI_IBMVSCSIS is not set +CONFIG_SCSI_IMM=m +CONFIG_SCSI_IN2000=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_INITIO=m +# CONFIG_SCSI_IPR_DUMP is not set +# CONFIG_SCSI_IPR_TRACE is not set +CONFIG_SCSI_IPS=m +CONFIG_SCSI_ISCSI_ATTRS=m +# CONFIG_SCSI_IZIP_EPP16 is not set +# CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_LOWLEVEL=y +CONFIG_SCSI_LOWLEVEL_PCMCIA=y +CONFIG_SCSI_LPFC=m +CONFIG_SCSI_LPFC_DEBUG_FS=y +CONFIG_SCSI_MAC53C94=m +CONFIG_SCSI_MESH=m +CONFIG_SCSI_MESH_RESET_DELAY_MS=4000 +CONFIG_SCSI_MESH_SYNC_RATE=5 +CONFIG_SCSI_MOD=y +CONFIG_SCSI_MPT2SAS=m +# CONFIG_SCSI_MPT2SAS_LOGGING is not set +CONFIG_SCSI_MPT2SAS_MAX_SGE=128 +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_MVSAS_DEBUG=y +CONFIG_SCSI_NCR53C406A=m +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4 +CONFIG_SCSI_NCR53C8XX_SYNC=5 +CONFIG_SCSI_NCR_D700=m +CONFIG_SCSI_NCR_Q720=m +CONFIG_SCSI_NETLINK=y +# CONFIG_SCSI_OSD_DEBUG is not set +CONFIG_SCSI_OSD_DPRINT_SENSE=1 +CONFIG_SCSI_OSD_ULD=m +CONFIG_SCSI_PAS16=m +CONFIG_SCSI_PM8001=m +CONFIG_SCSI_PMCRAID=m +CONFIG_SCSI_PPA=m +CONFIG_SCSI_PROC_FS=y +CONFIG_SCSI_QLA_FC=m +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLOGIC_FAS=m +CONFIG_SCSI_SAS_ATA=y +CONFIG_SCSI_SAS_ATTRS=m +CONFIG_SCSI_SAS_HOST_SMP=y +CONFIG_SCSI_SAS_LIBSAS=m +# CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_SIM710=m +CONFIG_SCSI_SRP=m +CONFIG_SCSI_SRP_ATTRS=m +CONFIG_SCSI_SRP_TGT_ATTRS=y +CONFIG_SCSI_STEX=m +CONFIG_SCSI_SYM53C416=m +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +CONFIG_SCSI_SYM53C8XX_MMIO=y +CONFIG_SCSI_T128=m +CONFIG_SCSI_TGT=m +CONFIG_SCSI_U14_34F=m +CONFIG_SCSI_U14_34F_LINKED_COMMANDS=y +CONFIG_SCSI_U14_34F_MAX_TAGS=8 +CONFIG_SCSI_U14_34F_TAGGED_QUEUE=y +CONFIG_SCSI_ULTRASTOR=m +CONFIG_SCSI_WAIT_SCAN=m +# CONFIG_SCTP_DBG_MSG is not set +# CONFIG_SCTP_DBG_OBJCNT is not set +CONFIG_SCTP_HMAC_MD5=y +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCx200=m +CONFIG_SCx200HR_TIMER=m +CONFIG_SCx200_ACB=m +CONFIG_SCx200_GPIO=m +CONFIG_SCx200_I2C=m +CONFIG_SCx200_I2C_SCL=12 +CONFIG_SCx200_I2C_SDA=13 +CONFIG_SCx200_WDT=m +CONFIG_SDIO_UART=m +CONFIG_SDLA=m +CONFIG_SEALEVEL_4021=m +CONFIG_SECCOMP=y +CONFIG_SECURITY=y +CONFIG_SECURITYFS=y +CONFIG_SECURITY_APPARMOR=y +CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 +CONFIG_SECURITY_APPARMOR_COMPAT_24=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +CONFIG_SECURITY_PATH=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=0 +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_DISABLE=y +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +CONFIG_SECURITY_SMACK=y +CONFIG_SECURITY_TOMOYO=y +CONFIG_SECURITY_YAMA=y +CONFIG_SEEQ8005=m +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SENSORS_ABITUGURU=m +CONFIG_SENSORS_ABITUGURU3=m +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADS7871=m +CONFIG_SENSORS_ADT7411=m +CONFIG_SENSORS_ADT7462=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7475=m +CONFIG_SENSORS_AMC6821=m +CONFIG_SENSORS_AMS=m +CONFIG_SENSORS_AMS_I2C=y +CONFIG_SENSORS_AMS_PMU=y +CONFIG_SENSORS_APDS990X=m +CONFIG_SENSORS_APPLESMC=m +CONFIG_SENSORS_ASB100=m +CONFIG_SENSORS_ASC7621=m +CONFIG_SENSORS_ATK0110=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_BH1770=m +CONFIG_SENSORS_BH1780=m +CONFIG_SENSORS_CORETEMP=m +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_EMC1403=m +CONFIG_SENSORS_EMC2103=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_FSCHMD=m +CONFIG_SENSORS_G760A=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_GPIO_FAN=m +CONFIG_SENSORS_HDAPS=m +CONFIG_SENSORS_HMC5843=m +CONFIG_SENSORS_I5K_AMB=m +CONFIG_SENSORS_IBMAEM=m +CONFIG_SENSORS_IBMPEX=m +CONFIG_SENSORS_ISL29018=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_JC42=m +CONFIG_SENSORS_K10TEMP=m +CONFIG_SENSORS_K8TEMP=m +CONFIG_SENSORS_LIS3LV02D=m +CONFIG_SENSORS_LIS3_I2C=m +CONFIG_SENSORS_LIS3_SPI=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_LM73=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_LTC4215=m +CONFIG_SENSORS_LTC4245=m +CONFIG_SENSORS_LTC4261=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_MC13783_ADC=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_PCF8591=m +CONFIG_SENSORS_PKGTEMP=m +CONFIG_SENSORS_SHT15=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_SMM665=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TMP102=m +CONFIG_SENSORS_TMP401=m +CONFIG_SENSORS_TMP421=m +CONFIG_SENSORS_TSL2550=m +CONFIG_SENSORS_TSL2563=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VIA_CPUTEMP=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +CONFIG_SENSORS_W83795=m +# CONFIG_SENSORS_W83795_FANCTRL is not set +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_WM831X=m +CONFIG_SENSORS_WM8350=m +CONFIG_SERIAL_8250_ACCENT=m +CONFIG_SERIAL_8250_BOCA=m +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_CS=m +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +CONFIG_SERIAL_8250_EXAR_ST16C554=m +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_FOURPORT=m +CONFIG_SERIAL_8250_HUB6=m +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_MCA=m +CONFIG_SERIAL_8250_NR_UARTS=48 +CONFIG_SERIAL_8250_PNP=y +CONFIG_SERIAL_8250_RSA=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=32 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_ALTERA_JTAGUART=m +CONFIG_SERIAL_ALTERA_UART=m +CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200 +CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4 +# CONFIG_SERIAL_AMBA_PL010 is not set +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_GRLIB_GAISLER_APBUART=m +# CONFIG_SERIAL_ICOM is not set +CONFIG_SERIAL_JSM=m +CONFIG_SERIAL_MAX3100=m +CONFIG_SERIAL_MAX3107=m +CONFIG_SERIAL_MFD_HSU=m +CONFIG_SERIAL_MRST_MAX3110=m +CONFIG_SERIAL_NONSTANDARD=y +CONFIG_SERIAL_OF_PLATFORM=m +CONFIG_SERIAL_OMAP=y +CONFIG_SERIAL_OMAP_CONSOLE=y +CONFIG_SERIAL_PMACZILOG_CONSOLE=y +# CONFIG_SERIAL_PMACZILOG_TTYS is not set +CONFIG_SERIAL_TIMBERDALE=m +CONFIG_SERIO=y +CONFIG_SERIO_ALTERA_PS2=m +CONFIG_SERIO_CT82C710=m +CONFIG_SERIO_I8042=y +CONFIG_SERIO_LIBPS2=y +CONFIG_SERIO_PARKBD=m +CONFIG_SERIO_PCIPS2=m +CONFIG_SERIO_PS2MULT=m +CONFIG_SERIO_RAW=m +CONFIG_SERIO_SERPORT=m +CONFIG_SERIO_XILINX_XPS_PS2=m +CONFIG_SFC=m +CONFIG_SFC_MTD=y +CONFIG_SFI=y +CONFIG_SGI_IOC4=m +CONFIG_SGI_PARTITION=y +CONFIG_SHMEM=y +CONFIG_SIGMATEL_FIR=m +CONFIG_SIGNALFD=y +CONFIG_SIMPLE_GPIO=y +CONFIG_SIS190=m +CONFIG_SIS900=m +CONFIG_SKFP=m +CONFIG_SKGE=m +# CONFIG_SKGE_DEBUG is not set +CONFIG_SKISA=m +CONFIG_SKY2=m +# CONFIG_SKY2_DEBUG is not set +CONFIG_SLABINFO=y +CONFIG_SLICOSS=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_MODE_SLIP6=y +CONFIG_SLIP_SMART=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLUB_DEBUG_ON is not set +# CONFIG_SLUB_STATS is not set +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +CONFIG_SMC911X=m +CONFIG_SMC9194=m +CONFIG_SMCTR=m +CONFIG_SMC_IRCC_FIR=m +CONFIG_SMSC37B787_WDT=m +CONFIG_SMSC911X=m +# CONFIG_SMSC911X_ARCH_HOOKS is not set +CONFIG_SMSC9420=m +CONFIG_SMSC_SCH311X_WDT=m +CONFIG_SMS_SDIO_DRV=m +CONFIG_SMS_SIANO_MDTV=m +CONFIG_SMS_USB_DRV=m +CONFIG_SND_AC97_CODEC=m +CONFIG_SND_AC97_POWER_SAVE=y +CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 +CONFIG_SND_AD1816A=m +CONFIG_SND_AD1848=m +CONFIG_SND_AD1889=m +CONFIG_SND_ADLIB=m +CONFIG_SND_ALOOP=m +CONFIG_SND_ALS100=m +CONFIG_SND_ALS300=m +CONFIG_SND_ALS4000=m +CONFIG_SND_AOA=m +CONFIG_SND_AOA_FABRIC_LAYOUT=m +CONFIG_SND_AOA_ONYX=m +CONFIG_SND_AOA_SOUNDBUS=m +CONFIG_SND_AOA_SOUNDBUS_I2S=m +CONFIG_SND_AOA_TAS=m +CONFIG_SND_AOA_TOONIE=m +CONFIG_SND_ARM=y +CONFIG_SND_ARMAACI=m +CONFIG_SND_ASIHPI=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_AW2=m +CONFIG_SND_AZT1605=m +CONFIG_SND_AZT2316=m +CONFIG_SND_AZT2320=m +CONFIG_SND_AZT3328=m +CONFIG_SND_BT87X=m +CONFIG_SND_CA0106=m +CONFIG_SND_CMI8330=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_CS4231=m +CONFIG_SND_CS4236=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS5530=m +CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_CTXFI=m +CONFIG_SND_DARLA20=m +CONFIG_SND_DARLA24=m +# CONFIG_SND_DEBUG is not set +CONFIG_SND_DMA_SGBUF=y +CONFIG_SND_DRIVERS=y +CONFIG_SND_DUMMY=m +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_ECHO3G=m +CONFIG_SND_EMU10K1=m +CONFIG_SND_EMU10K1X=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_ES1688=m +CONFIG_SND_ES18XX=m +CONFIG_SND_ES1938=m +CONFIG_SND_ES1968=m +CONFIG_SND_ES1968_INPUT=y +CONFIG_SND_FM801=m +CONFIG_SND_FM801_TEA575X=m +CONFIG_SND_FM801_TEA575X_BOOL=y +CONFIG_SND_GINA20=m +CONFIG_SND_GINA24=m +CONFIG_SND_GUSCLASSIC=m +CONFIG_SND_GUSEXTREME=m +CONFIG_SND_GUSMAX=m +CONFIG_SND_HDA_CODEC_ANALOG=y +CONFIG_SND_HDA_CODEC_CA0110=y +CONFIG_SND_HDA_CODEC_CIRRUS=y +CONFIG_SND_HDA_CODEC_CMEDIA=y +CONFIG_SND_HDA_CODEC_CONEXANT=y +CONFIG_SND_HDA_CODEC_HDMI=y +CONFIG_SND_HDA_CODEC_REALTEK=y +CONFIG_SND_HDA_CODEC_SI3054=y +CONFIG_SND_HDA_CODEC_SIGMATEL=y +CONFIG_SND_HDA_CODEC_VIA=y +CONFIG_SND_HDA_GENERIC=y +CONFIG_SND_HDA_HWDEP=y +CONFIG_SND_HDA_INPUT_BEEP=y +CONFIG_SND_HDA_INPUT_BEEP_MODE=0 +CONFIG_SND_HDA_INPUT_JACK=y +CONFIG_SND_HDA_INTEL=m +CONFIG_SND_HDA_PATCH_LOADER=y +CONFIG_SND_HDA_POWER_SAVE=y +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDA_RECONFIG=y +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_HRTIMER=m +CONFIG_SND_HWDEP=m +CONFIG_SND_ICE1712=m +CONFIG_SND_ICE1724=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_INDIGODJX=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGOIOX=m +CONFIG_SND_INTEL8X0=m +CONFIG_SND_INTEL8X0M=m +CONFIG_SND_INTERWAVE=m +CONFIG_SND_INTERWAVE_STB=m +CONFIG_SND_ISA=y +CONFIG_SND_JACK=y +CONFIG_SND_JAZZ16=m +CONFIG_SND_KORG1212=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_LX6464ES=m +CONFIG_SND_MAESTRO3=m +CONFIG_SND_MAESTRO3_INPUT=y +CONFIG_SND_MIA=m +CONFIG_SND_MIRO=m +CONFIG_SND_MIXART=m +CONFIG_SND_MONA=m +CONFIG_SND_MPU401_UART=m +CONFIG_SND_MSND_CLASSIC=m +CONFIG_SND_MSND_PINNACLE=m +CONFIG_SND_MTS64=m +CONFIG_SND_NM256=m +CONFIG_SND_OMAP_SOC=y +CONFIG_SND_OMAP_SOC_IGEP0020=y +CONFIG_SND_OMAP_SOC_MCBSP=y +CONFIG_SND_OMAP_SOC_OMAP3EVM=y +CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y +CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y +CONFIG_SND_OMAP_SOC_OVERO=y +CONFIG_SND_OMAP_SOC_RX51=m +CONFIG_SND_OMAP_SOC_SDP3430=y +CONFIG_SND_OMAP_SOC_ZOOM2=y +CONFIG_SND_OPL3SA2=m +CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL4_LIB=m +CONFIG_SND_OPTI92X_AD1848=m +CONFIG_SND_OPTI92X_CS4231=m +CONFIG_SND_OPTI93X=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_OXYGEN_LIB=m +CONFIG_SND_PCI=y +CONFIG_SND_PCMCIA=y +CONFIG_SND_PCM_OSS_PLUGINS=y +CONFIG_SND_PCSP=m +CONFIG_SND_PCXHR=m +CONFIG_SND_PDAUDIOCF=m +CONFIG_SND_PORTMAN2X4=m +CONFIG_SND_POWERMAC=m +CONFIG_SND_POWERMAC_AUTO_DRC=y +CONFIG_SND_PPC=y +CONFIG_SND_PS3=m +CONFIG_SND_PS3_DEFAULT_START_DELAY=2000 +CONFIG_SND_RAWMIDI=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_SB16=m +CONFIG_SND_SB16_CSP=y +CONFIG_SND_SB16_DSP=m +CONFIG_SND_SB8=m +CONFIG_SND_SB8_DSP=m +CONFIG_SND_SBAWE=m +CONFIG_SND_SB_COMMON=m +CONFIG_SND_SC6000=m +# CONFIG_SND_SEQUENCER_OSS is not set +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_SEQ_HRTIMER_DEFAULT=y +CONFIG_SND_SIS7019=m +CONFIG_SND_SOC_88PM860X=m +CONFIG_SND_SOC_AD1836=m +CONFIG_SND_SOC_AD193X=m +CONFIG_SND_SOC_AD73311=m +CONFIG_SND_SOC_ADS117X=m +CONFIG_SND_SOC_AK4104=m +CONFIG_SND_SOC_AK4535=m +CONFIG_SND_SOC_AK4642=m +CONFIG_SND_SOC_AK4671=m +CONFIG_SND_SOC_ALL_CODECS=m +CONFIG_SND_SOC_CS4270=m +CONFIG_SND_SOC_CS42L51=m +CONFIG_SND_SOC_CX20442=m +CONFIG_SND_SOC_DA7210=m +CONFIG_SND_SOC_L3=m +CONFIG_SND_SOC_MAX98088=m +CONFIG_SND_SOC_MAX9877=m +CONFIG_SND_SOC_PCM3008=m +CONFIG_SND_SOC_SPDIF=m +CONFIG_SND_SOC_SSM2602=m +CONFIG_SND_SOC_TLV320AIC23=m +CONFIG_SND_SOC_TLV320AIC26=m +CONFIG_SND_SOC_TLV320AIC3X=m +CONFIG_SND_SOC_TLV320DAC33=m +CONFIG_SND_SOC_TPA6130A2=m +CONFIG_SND_SOC_TWL6040=m +CONFIG_SND_SOC_UDA134X=m +CONFIG_SND_SOC_UDA1380=m +CONFIG_SND_SOC_WM2000=m +CONFIG_SND_SOC_WM8350=m +CONFIG_SND_SOC_WM8400=m +CONFIG_SND_SOC_WM8510=m +CONFIG_SND_SOC_WM8523=m +CONFIG_SND_SOC_WM8580=m +CONFIG_SND_SOC_WM8711=m +CONFIG_SND_SOC_WM8727=m +CONFIG_SND_SOC_WM8728=m +CONFIG_SND_SOC_WM8731=m +CONFIG_SND_SOC_WM8741=m +CONFIG_SND_SOC_WM8750=m +CONFIG_SND_SOC_WM8753=m +CONFIG_SND_SOC_WM8776=m +CONFIG_SND_SOC_WM8804=m +CONFIG_SND_SOC_WM8900=m +CONFIG_SND_SOC_WM8903=m +CONFIG_SND_SOC_WM8904=m +CONFIG_SND_SOC_WM8940=m +CONFIG_SND_SOC_WM8955=m +CONFIG_SND_SOC_WM8960=m +CONFIG_SND_SOC_WM8961=m +CONFIG_SND_SOC_WM8962=m +CONFIG_SND_SOC_WM8971=m +CONFIG_SND_SOC_WM8974=m +CONFIG_SND_SOC_WM8978=m +CONFIG_SND_SOC_WM8985=m +CONFIG_SND_SOC_WM8988=m +CONFIG_SND_SOC_WM8990=m +CONFIG_SND_SOC_WM8993=m +CONFIG_SND_SOC_WM8994=m +CONFIG_SND_SOC_WM9081=m +CONFIG_SND_SOC_WM9090=m +CONFIG_SND_SOC_WM_HUBS=m +CONFIG_SND_SONICVIBES=m +CONFIG_SND_SPI=y +CONFIG_SND_SSCAPE=m +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_TRIDENT=m +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_US122L=m +CONFIG_SND_USB_USX2Y=m +# CONFIG_SND_VERBOSE_PRINTK is not set +CONFIG_SND_VERBOSE_PROCFS=y +CONFIG_SND_VIA82XX=m +CONFIG_SND_VIA82XX_MODEM=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_VMASTER=y +CONFIG_SND_VX222=m +CONFIG_SND_VXPOCKET=m +CONFIG_SND_VX_LIB=m +CONFIG_SND_WAVEFRONT=m +CONFIG_SND_WSS_LIB=m +CONFIG_SND_YMFPCI=m +CONFIG_SOC_CAMERA=m +CONFIG_SOC_CAMERA_IMX074=m +CONFIG_SOC_CAMERA_MT9M001=m +CONFIG_SOC_CAMERA_MT9M111=m +CONFIG_SOC_CAMERA_MT9T031=m +CONFIG_SOC_CAMERA_MT9T112=m +CONFIG_SOC_CAMERA_MT9V022=m +CONFIG_SOC_CAMERA_OV6650=m +CONFIG_SOC_CAMERA_OV772X=m +CONFIG_SOC_CAMERA_OV9640=m +CONFIG_SOC_CAMERA_PLATFORM=m +CONFIG_SOC_CAMERA_RJ54N1=m +CONFIG_SOC_CAMERA_TW9910=m +CONFIG_SOFT_WATCHDOG=m +CONFIG_SOLARIS_X86_PARTITION=y +# CONFIG_SOLO6X10 is not set +CONFIG_SONYPI=m +CONFIG_SONYPI_COMPAT=y +CONFIG_SONY_LAPTOP=m +CONFIG_SOUND_OSS_CORE_PRECLAIM=y +# CONFIG_SOUND_PRIME is not set +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_STATIC=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +# CONFIG_SPARSE_RCU_POINTER is not set +CONFIG_SPEAKUP=m +CONFIG_SPEAKUP_SYNTH_ACNTPC=m +CONFIG_SPEAKUP_SYNTH_ACNTSA=m +CONFIG_SPEAKUP_SYNTH_APOLLO=m +CONFIG_SPEAKUP_SYNTH_AUDPTR=m +CONFIG_SPEAKUP_SYNTH_BNS=m +CONFIG_SPEAKUP_SYNTH_DECEXT=m +CONFIG_SPEAKUP_SYNTH_DECPC=m +CONFIG_SPEAKUP_SYNTH_DECTLK=m +CONFIG_SPEAKUP_SYNTH_DTLK=m +CONFIG_SPEAKUP_SYNTH_DUMMY=m +CONFIG_SPEAKUP_SYNTH_KEYPC=m +CONFIG_SPEAKUP_SYNTH_LTLK=m +CONFIG_SPEAKUP_SYNTH_SOFT=m +CONFIG_SPEAKUP_SYNTH_SPKOUT=m +CONFIG_SPEAKUP_SYNTH_TXPRT=m +CONFIG_SPECIALIX=m +CONFIG_SPI_BITBANG=m +CONFIG_SPI_BUTTERFLY=m +# CONFIG_SPI_DEBUG is not set +# CONFIG_SPI_DW_MMIO is not set +CONFIG_SPI_DW_PCI=m +CONFIG_SPI_GPIO=m +CONFIG_SPI_LM70_LLP=m +CONFIG_SPI_MASTER=y +CONFIG_SPI_OMAP24XX=m +# CONFIG_SPI_PL022 is not set +CONFIG_SPI_TLE62X0=m +CONFIG_SPI_TOPCLIFF_PCH=m +# CONFIG_SPI_XILINX is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_SPU_BASE=y +CONFIG_SPU_FS=m +CONFIG_SPU_FS_64K_LS=y +CONFIG_SQUASHFS=m +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3 +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_SR_REPORT_TIME_LIMIT=100 +CONFIG_SSB=m +CONFIG_SSB_BLOCKIO=y +# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_DRIVER_PCICORE=y +CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y +CONFIG_SSB_PCIHOST=y +CONFIG_SSB_PCIHOST_POSSIBLE=y +# CONFIG_SSB_PCMCIAHOST is not set +CONFIG_SSB_PCMCIAHOST_POSSIBLE=y +CONFIG_SSB_POSSIBLE=y +CONFIG_SSB_SDIOHOST=y +CONFIG_SSB_SDIOHOST_POSSIBLE=y +CONFIG_SSB_SPROM=y +CONFIG_SSFDC=m +CONFIG_STACKTRACE=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_STAGING=y +# CONFIG_STAGING_EXCLUDE_BUILD is not set +CONFIG_STALDRV=y +CONFIG_STALLION=m +# CONFIG_STMMAC_DA is not set +# CONFIG_STMMAC_DUAL_MAC is not set +CONFIG_STMMAC_ETH=m +CONFIG_STOP_MACHINE=y +CONFIG_STP=m +CONFIG_STRICT_DEVMEM=y +# CONFIG_STRIP_ASM_SYMS is not set +CONFIG_STUB_POULSBO=m +CONFIG_ST_BT=m +CONFIG_SUNDANCE=m +# CONFIG_SUNDANCE_MMIO is not set +CONFIG_SUNRPC=m +CONFIG_SUNRPC_GSS=m +CONFIG_SUNRPC_XPRT_RDMA=m +CONFIG_SUN_PARTITION=y +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_SUSPEND_NVS=y +CONFIG_SWAP=y +CONFIG_SWIOTLB=y +CONFIG_SWIOTLB_XEN=y +CONFIG_SYNCLINK=m +CONFIG_SYNCLINKMP=m +CONFIG_SYNCLINK_CS=m +CONFIG_SYNCLINK_GT=m +CONFIG_SYN_COOKIES=y +CONFIG_SYSCTL=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_SYSCTL_SYSCALL_CHECK=y +CONFIG_SYSFS=y +# CONFIG_SYSFS_DEPRECATED is not set +CONFIG_SYSV68_PARTITION=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_COMPAT=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_SYSV_FS=m +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_TABLET_USB_ACECAD=m +CONFIG_TABLET_USB_AIPTEK=m +CONFIG_TABLET_USB_GTCO=m +CONFIG_TABLET_USB_HANWANG=m +CONFIG_TABLET_USB_KBTAB=m +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_TASK_SIZE=0xc0000000 +CONFIG_TASK_XACCT=y +CONFIG_TAU=y +# CONFIG_TAU_AVERAGE is not set +# CONFIG_TAU_INT is not set +CONFIG_TC1100_WMI=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_INFINEON=m +CONFIG_TCG_NSC=m +CONFIG_TCIC=m +CONFIG_TCP_CONG_BIC=m +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_VEGAS=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_WESTWOOD=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_MD5SIG=y +CONFIG_TEHUTI=m +CONFIG_TEKRAM_DONGLE=m +CONFIG_TELCLOCK=m +# CONFIG_TEST_LIST_SORT is not set +CONFIG_TEST_POWER=m +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_BM=m +CONFIG_TEXTSEARCH_FSM=m +CONFIG_TEXTSEARCH_KMP=m +CONFIG_THERMAL_HWMON=y +CONFIG_THERM_ADT746X=m +CONFIG_THERM_PM72=m +CONFIG_THERM_WINDTUNNEL=m +CONFIG_THINKPAD_ACPI=m +CONFIG_THINKPAD_ACPI_ALSA_SUPPORT=y +# CONFIG_THINKPAD_ACPI_DEBUG is not set +CONFIG_THINKPAD_ACPI_DEBUGFACILITIES=y +CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y +# CONFIG_THINKPAD_ACPI_UNSAFE_LEDS is not set +CONFIG_THINKPAD_ACPI_VIDEO=y +CONFIG_THRUSTMASTER_FF=y +# CONFIG_THUMB2_KERNEL is not set +CONFIG_TICK_ONESHOT=y +CONFIG_TIDSPBRIDGE=m +# CONFIG_TIDSPBRIDGE_BACKTRACE is not set +# CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK is not set +# CONFIG_TIDSPBRIDGE_DEBUG is not set +CONFIG_TIDSPBRIDGE_MEMPOOL_SIZE=0x600000 +# CONFIG_TIDSPBRIDGE_NTFY_PWRERR is not set +CONFIG_TIDSPBRIDGE_RECOVERY=y +# CONFIG_TIDSPBRIDGE_WDT3 is not set +CONFIG_TIFM_7XX1=m +CONFIG_TIFM_CORE=m +CONFIG_TIGON3=m +CONFIG_TIMB_DMA=m +CONFIG_TIMERFD=y +CONFIG_TIMER_STATS=y +CONFIG_TINY_RCU=y +CONFIG_TIPC=m +# CONFIG_TIPC_ADVANCED is not set +# CONFIG_TIPC_DEBUG is not set +CONFIG_TI_DAC7512=m +CONFIG_TI_DAVINCI_CPDMA=m +# CONFIG_TI_DAVINCI_EMAC is not set +CONFIG_TI_DAVINCI_MDIO=m +CONFIG_TI_ST=m +CONFIG_TLAN=m +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMS380TR=m +CONFIG_TMSPCI=m +CONFIG_TOIM3232_DONGLE=m +CONFIG_TOPSTAR_LAPTOP=m +# CONFIG_TOSHIBA is not set +CONFIG_TOSHIBA_BT_RFKILL=m +CONFIG_TOSHIBA_FIR=m +CONFIG_TOUCHSCREEN_88PM860X=m +CONFIG_TOUCHSCREEN_AD7877=m +CONFIG_TOUCHSCREEN_AD7879=m +CONFIG_TOUCHSCREEN_AD7879_I2C=m +CONFIG_TOUCHSCREEN_AD7879_SPI=m +CONFIG_TOUCHSCREEN_ADS7846=m +CONFIG_TOUCHSCREEN_BU21013=m +CONFIG_TOUCHSCREEN_CY8CTMG110=m +CONFIG_TOUCHSCREEN_DA9034=m +CONFIG_TOUCHSCREEN_DYNAPRO=m +CONFIG_TOUCHSCREEN_EETI=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_FUJITSU=m +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_HAMPSHIRE=m +CONFIG_TOUCHSCREEN_HTCPEN=m +CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_MC13783=m +CONFIG_TOUCHSCREEN_MCS5000=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_PCAP=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_QT602240=m +CONFIG_TOUCHSCREEN_STMPE=m +CONFIG_TOUCHSCREEN_TOUCHIT213=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_TPS6507X=m +CONFIG_TOUCHSCREEN_TSC2007=m +CONFIG_TOUCHSCREEN_UCB1400=m +CONFIG_TOUCHSCREEN_USB_3M=y +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_USB_DMC_TSC10=y +CONFIG_TOUCHSCREEN_USB_E2I=y +CONFIG_TOUCHSCREEN_USB_EGALAX=y +CONFIG_TOUCHSCREEN_USB_ETT_TC45USB=y +CONFIG_TOUCHSCREEN_USB_ETURBO=y +CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH=y +CONFIG_TOUCHSCREEN_USB_GOTOP=y +CONFIG_TOUCHSCREEN_USB_GUNZE=y +CONFIG_TOUCHSCREEN_USB_IDEALTEK=y +CONFIG_TOUCHSCREEN_USB_IRTOUCH=y +CONFIG_TOUCHSCREEN_USB_ITM=y +CONFIG_TOUCHSCREEN_USB_JASTEC=y +CONFIG_TOUCHSCREEN_USB_NEXIO=y +CONFIG_TOUCHSCREEN_USB_PANJIT=y +CONFIG_TOUCHSCREEN_USB_ZYTRONIC=y +CONFIG_TOUCHSCREEN_W90X900=m +CONFIG_TOUCHSCREEN_WACOM_W8001=m +CONFIG_TOUCHSCREEN_WM9705=y +CONFIG_TOUCHSCREEN_WM9712=y +CONFIG_TOUCHSCREEN_WM9713=y +CONFIG_TOUCHSCREEN_WM97XX=m +CONFIG_TPS6507X=m +CONFIG_TR=y +CONFIG_TRACEPOINTS=y +CONFIG_TRACER_MAX_TRACE=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_TRACING=y +CONFIG_TRACING_SUPPORT=y +CONFIG_TREE_RCU=y +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_TULIP=m +# CONFIG_TULIP_MMIO is not set +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_NAPI is not set +# CONFIG_TUNE_CELL is not set +CONFIG_TWL4030_CODEC=y +CONFIG_TWL4030_POWER=y +CONFIG_TWL4030_WATCHDOG=m +CONFIG_TWL6030_PWM=m +CONFIG_TYPHOON=m +CONFIG_U3_DART=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +CONFIG_UBIFS_FS=m +# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set +# CONFIG_UBIFS_FS_DEBUG is not set +CONFIG_UBIFS_FS_LZO=y +CONFIG_UBIFS_FS_XATTR=y +CONFIG_UBIFS_FS_ZLIB=y +CONFIG_UCB1400_CORE=m +CONFIG_UDBG_RTAS_CONSOLE=y +CONFIG_UDF_FS=m +CONFIG_UDF_NLS=y +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_UFS_DEBUG is not set +CONFIG_UFS_FS=m +# CONFIG_UFS_FS_WRITE is not set +CONFIG_UID16=y +CONFIG_UIO=m +CONFIG_UIO_AEC=m +CONFIG_UIO_CIF=m +CONFIG_UIO_NETX=m +CONFIG_UIO_PCI_GENERIC=m +CONFIG_UIO_PDRV=m +CONFIG_UIO_PDRV_GENIRQ=m +CONFIG_UIO_SERCOS3=m +CONFIG_ULI526X=m +CONFIG_ULTRA=m +CONFIG_ULTRA32=m +CONFIG_ULTRAMCA=m +CONFIG_ULTRIX_PARTITION=y +CONFIG_UNIX=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNUSED_SYMBOLS=y +CONFIG_USB=y +CONFIG_USBPCWATCHDOG=m +CONFIG_USB_ACM=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARMLINUX=y +CONFIG_USB_ATM=m +CONFIG_USB_AUDIO=m +CONFIG_USB_BELKIN=y +CONFIG_USB_C67X00_HCD=m +CONFIG_USB_CATC=m +CONFIG_USB_CDC_COMPOSITE=m +CONFIG_USB_CDC_PHONET=m +CONFIG_USB_CXACRU=m +CONFIG_USB_CYPRESS_CY7C63=m +CONFIG_USB_CYTHERM=m +CONFIG_USB_DABUSB=m +# CONFIG_USB_DEBUG is not set +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_DEVICE_CLASS is not set +CONFIG_USB_DSBR=m +CONFIG_USB_DUMMY_HCD=m +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_EHCI_BIG_ENDIAN_DESC=y +CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y +CONFIG_USB_EHCI_HCD_PPC_OF=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EMI26=m +CONFIG_USB_EMI62=m +CONFIG_USB_ENESTORAGE=m +CONFIG_USB_EPSON2888=y +CONFIG_USB_ETH=m +# CONFIG_USB_ETH_EEM is not set +CONFIG_USB_ETH_RNDIS=y +CONFIG_USB_EZUSB=y +CONFIG_USB_FILE_STORAGE=m +# CONFIG_USB_FILE_STORAGE_TEST is not set +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_FUNCTIONFS=m +CONFIG_USB_FUNCTIONFS_ETH=y +CONFIG_USB_FUNCTIONFS_GENERIC=y +CONFIG_USB_FUNCTIONFS_RNDIS=y +CONFIG_USB_GADGETFS=m +# CONFIG_USB_GADGET_AMD5536UDC is not set +# CONFIG_USB_GADGET_CI13XXX is not set +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +# CONFIG_USB_GADGET_LANGWELL is not set +# CONFIG_USB_GADGET_M66592 is not set +# CONFIG_USB_GADGET_OMAP is not set +# CONFIG_USB_GADGET_R8A66597 is not set +CONFIG_USB_GADGET_SELECTED=y +CONFIG_USB_GADGET_VBUS_DRAW=2 +CONFIG_USB_GL860=m +CONFIG_USB_GOKU=m +CONFIG_USB_GSPCA=m +CONFIG_USB_GSPCA_BENQ=m +CONFIG_USB_GSPCA_CONEX=m +CONFIG_USB_GSPCA_CPIA1=m +CONFIG_USB_GSPCA_ETOMS=m +CONFIG_USB_GSPCA_FINEPIX=m +CONFIG_USB_GSPCA_JEILINJ=m +CONFIG_USB_GSPCA_KONICA=m +CONFIG_USB_GSPCA_MARS=m +CONFIG_USB_GSPCA_MR97310A=m +CONFIG_USB_GSPCA_OV519=m +CONFIG_USB_GSPCA_OV534=m +CONFIG_USB_GSPCA_OV534_9=m +CONFIG_USB_GSPCA_PAC207=m +CONFIG_USB_GSPCA_PAC7302=m +CONFIG_USB_GSPCA_PAC7311=m +CONFIG_USB_GSPCA_SN9C2028=m +CONFIG_USB_GSPCA_SN9C20X=m +CONFIG_USB_GSPCA_SONIXB=m +CONFIG_USB_GSPCA_SONIXJ=m +CONFIG_USB_GSPCA_SPCA1528=m +CONFIG_USB_GSPCA_SPCA500=m +CONFIG_USB_GSPCA_SPCA501=m +CONFIG_USB_GSPCA_SPCA505=m +CONFIG_USB_GSPCA_SPCA506=m +CONFIG_USB_GSPCA_SPCA508=m +CONFIG_USB_GSPCA_SPCA561=m +CONFIG_USB_GSPCA_SQ905=m +CONFIG_USB_GSPCA_SQ905C=m +CONFIG_USB_GSPCA_SQ930X=m +CONFIG_USB_GSPCA_STK014=m +CONFIG_USB_GSPCA_STV0680=m +CONFIG_USB_GSPCA_SUNPLUS=m +CONFIG_USB_GSPCA_T613=m +CONFIG_USB_GSPCA_TV8532=m +CONFIG_USB_GSPCA_VC032X=m +CONFIG_USB_GSPCA_XIRLINK_CIT=m +CONFIG_USB_GSPCA_ZC3XX=m +CONFIG_USB_G_DBGP=m +# CONFIG_USB_G_DBGP_PRINTK is not set +CONFIG_USB_G_DBGP_SERIAL=y +CONFIG_USB_G_HID=m +CONFIG_USB_G_MULTI_CDC=y +CONFIG_USB_G_MULTI_RNDIS=y +CONFIG_USB_G_NOKIA=m +CONFIG_USB_G_PRINTER=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_G_WEBCAM=m +CONFIG_USB_HID=m +CONFIG_USB_HIDDEV=y +CONFIG_USB_HSO=m +CONFIG_USB_HWA_HCD=m +CONFIG_USB_IBMCAM=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_INVENTRA_DMA=y +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_IPHETH=m +# CONFIG_USB_IP_DEBUG_ENABLE is not set +CONFIG_USB_IP_HOST=m +CONFIG_USB_IP_VHCI_HCD=m +CONFIG_USB_IRDA=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_ISP116X_HCD=m +CONFIG_USB_ISP1760_HCD=m +CONFIG_USB_KAWETH=m +CONFIG_USB_KC2190=y +CONFIG_USB_KONICAWC=m +CONFIG_USB_LCD=m +CONFIG_USB_LD=m +CONFIG_USB_LED=m +CONFIG_USB_LEGOTOWER=m +# CONFIG_USB_LIBUSUAL is not set +CONFIG_USB_M5602=m +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USB_MIDI_GADGET=m +CONFIG_USB_MR800=m +# CONFIG_USB_MUSB_AM35X is not set +# CONFIG_USB_MUSB_DEBUG is not set +CONFIG_USB_MUSB_HDRC_HCD=y +# CONFIG_USB_MUSB_HOST is not set +CONFIG_USB_MUSB_OTG=y +# CONFIG_USB_MUSB_PERIPHERAL is not set +CONFIG_USB_MUSB_SOC=y +CONFIG_USB_NET2280=m +CONFIG_USB_NET_AX8817X=m +CONFIG_USB_NET_CDCETHER=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_CDC_SUBSET=m +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_NET_NET1080=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_RNDIS_HOST=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_OHCI_HCD_OMAP3=y +CONFIG_USB_OHCI_HCD_PCI=y +CONFIG_USB_OHCI_HCD_PPC_OF=y +CONFIG_USB_OHCI_HCD_PPC_OF_BE=y +# CONFIG_USB_OHCI_HCD_PPC_OF_LE is not set +# CONFIG_USB_OHCI_HCD_SSB is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_OTG_WHITELIST is not set +CONFIG_USB_OXU210HP_HCD=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_PRINTER=m +CONFIG_USB_PWC=m +# CONFIG_USB_PWC_DEBUG is not set +CONFIG_USB_PWC_INPUT_EVDEV=y +CONFIG_USB_R8A66597_HCD=m +CONFIG_USB_RIO500=m +CONFIG_USB_RTL8150=m +CONFIG_USB_S2255=m +CONFIG_USB_SE401=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_DEBUG=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_FUNSOFT=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_HP4X=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y +CONFIG_USB_SERIAL_KEYSPAN_USA19=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA28=y +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7715_PARPORT=y +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_MOTOROLA=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SAFE=m +# CONFIG_USB_SERIAL_SAFE_PADDED is not set +CONFIG_USB_SERIAL_SAMBA=m +CONFIG_USB_SERIAL_SIEMENS_MPI=m +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_WWAN=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_ZIO=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_SISUSBVGA=m +# CONFIG_USB_SISUSBVGA_CON is not set +CONFIG_USB_SL811_CS=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_STORAGE=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_DATAFAB=m +# CONFIG_USB_STORAGE_DEBUG is not set +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STV06XX=m +CONFIG_USB_SUPPORT=y +CONFIG_USB_SUSPEND=y +CONFIG_USB_TEST=m +# CONFIG_USB_TI_CPPI_DMA is not set +CONFIG_USB_TMC=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_U132_HCD=m +CONFIG_USB_UAS=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_ULPI=y +CONFIG_USB_USBNET=m +CONFIG_USB_USS720=m +CONFIG_USB_VICAM=m +CONFIG_USB_VIDEO_CLASS=m +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_WDM=m +CONFIG_USB_WHCI_HCD=m +CONFIG_USB_WUSB=m +CONFIG_USB_WUSB_CBAF=m +# CONFIG_USB_WUSB_CBAF_DEBUG is not set +CONFIG_USB_XHCI_HCD=m +# CONFIG_USB_XHCI_HCD_DEBUGGING is not set +CONFIG_USB_XUSBATM=m +CONFIG_USB_YUREX=m +CONFIG_USB_ZD1201=m +CONFIG_USB_ZERO=m +# CONFIG_USB_ZERO_HNPTEST is not set +CONFIG_USB_ZR364XX=m +CONFIG_USER_RETURN_NOTIFIER=y +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_USE_PERCPU_NUMA_NODE_ID=y +CONFIG_UWB=m +CONFIG_UWB_HWA=m +CONFIG_UWB_I1480U=m +CONFIG_UWB_WHCI=m +CONFIG_V4L2_MEM2MEM_DEV=m +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_V4L_USB_DRIVERS=y +CONFIG_VECTORS_BASE=0xffff0000 +CONFIG_VERSION_SIGNATURE="" +CONFIG_VETH=m +CONFIG_VFAT_FS=m +CONFIG_VFP=y +CONFIG_VFPv3=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_VGA_SWITCHEROO=y +CONFIG_VHOST_NET=m +CONFIG_VIA_FIR=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_VELOCITY=m +CONFIG_VIDEOBUF_DMA_CONTIG=m +CONFIG_VIDEOBUF_DMA_SG=m +CONFIG_VIDEOBUF_DVB=m +CONFIG_VIDEOBUF_GEN=m +CONFIG_VIDEOBUF_VMALLOC=m +# CONFIG_VIDEO_ADV_DEBUG is not set +CONFIG_VIDEO_AK881X=m +CONFIG_VIDEO_ALLOW_V4L1=y +CONFIG_VIDEO_AU0828=m +CONFIG_VIDEO_BT848=m +CONFIG_VIDEO_BT848_DVB=y +CONFIG_VIDEO_BTCX=m +CONFIG_VIDEO_BWQCAM=m +CONFIG_VIDEO_CAFE_CCIC=m +CONFIG_VIDEO_CAPTURE_DRIVERS=y +CONFIG_VIDEO_CPIA2=m +CONFIG_VIDEO_CPIA_PP=m +CONFIG_VIDEO_CPIA_USB=m +CONFIG_VIDEO_CQCAM=m +CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m +CONFIG_VIDEO_CX18=m +CONFIG_VIDEO_CX18_ALSA=m +CONFIG_VIDEO_CX231XX=m +CONFIG_VIDEO_CX231XX_ALSA=m +CONFIG_VIDEO_CX231XX_DVB=m +CONFIG_VIDEO_CX2341X=m +CONFIG_VIDEO_CX23885=m +CONFIG_VIDEO_CX25821_ALSA=m +CONFIG_VIDEO_CX25840=m +CONFIG_VIDEO_CX88=m +CONFIG_VIDEO_CX88_ALSA=m +CONFIG_VIDEO_CX88_BLACKBIRD=m +CONFIG_VIDEO_CX88_DVB=m +CONFIG_VIDEO_CX88_MPEG=m +CONFIG_VIDEO_CX88_VP3054=m +CONFIG_VIDEO_DM6446_CCDC=m +CONFIG_VIDEO_DT3155=m +CONFIG_VIDEO_EM28XX=m +CONFIG_VIDEO_EM28XX_DVB=m +CONFIG_VIDEO_FB_IVTV=m +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set +CONFIG_VIDEO_GO7007_OV7640=m +CONFIG_VIDEO_GO7007_SAA7113=m +CONFIG_VIDEO_GO7007_SAA7115=m +CONFIG_VIDEO_GO7007_SONY_TUNER=m +CONFIG_VIDEO_GO7007_TW2804=m +CONFIG_VIDEO_GO7007_TW9903=m +CONFIG_VIDEO_GO7007_UDA1342=m +CONFIG_VIDEO_GO7007_USB=m +CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_IR=m +CONFIG_VIDEO_IR_I2C=m +CONFIG_VIDEO_IVTV=m +CONFIG_VIDEO_M52790=m +CONFIG_VIDEO_MEDIA=m +CONFIG_VIDEO_MEM2MEM_TESTDEV=m +CONFIG_VIDEO_MEYE=m +CONFIG_VIDEO_MSP3400=m +CONFIG_VIDEO_OMAP2_VOUT=m +CONFIG_VIDEO_OV7670=m +CONFIG_VIDEO_PMS=m +CONFIG_VIDEO_PVRUSB2=m +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_PVRUSB2_DVB=y +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_SAA711X=m +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_SAA7134=m +CONFIG_VIDEO_SAA7134_ALSA=m +CONFIG_VIDEO_SAA7134_DVB=m +CONFIG_VIDEO_SAA7134_RC=y +CONFIG_VIDEO_SAA7146=m +CONFIG_VIDEO_SAA7146_VV=m +CONFIG_VIDEO_SAA7164=m +CONFIG_VIDEO_SAA717X=m +CONFIG_VIDEO_SH_MOBILE_CEU=m +CONFIG_VIDEO_SH_MOBILE_CSI2=m +CONFIG_VIDEO_SR030PC30=m +CONFIG_VIDEO_STRADIS=m +CONFIG_VIDEO_TLG2300=m +CONFIG_VIDEO_TM6000=m +CONFIG_VIDEO_TM6000_ALSA=m +CONFIG_VIDEO_TM6000_DVB=m +CONFIG_VIDEO_TUNER=m +CONFIG_VIDEO_TVEEPROM=m +CONFIG_VIDEO_TVP7002=m +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m +CONFIG_VIDEO_USBVIDEO=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_V4L1=m +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L2_COMMON=m +CONFIG_VIDEO_VIA_CAMERA=m +CONFIG_VIDEO_VIVI=m +CONFIG_VIDEO_VP27SMPX=m +CONFIG_VIDEO_VPFE_CAPTURE=m +CONFIG_VIDEO_VPSS_SYSTEM=m +CONFIG_VIDEO_W9966=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_ZR36060=m +# CONFIG_VIRQ_DEBUG is not set +CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_CONSOLE=m +CONFIG_VIRTUALIZATION=y +CONFIG_VIRT_CPU_ACCOUNTING=y +CONFIG_VIRT_TO_BUS=y +CONFIG_VLAN_8021Q=m +CONFIG_VLAN_8021Q_GVRP=y +CONFIG_VLSI_FIR=m +CONFIG_VM86=y +CONFIG_VME_USER=m +CONFIG_VMIVME_7805=m +# CONFIG_VMSPLIT_1G is not set +# CONFIG_VMSPLIT_2G is not set +CONFIG_VMSPLIT_3G=y +CONFIG_VMWARE_BALLOON=m +CONFIG_VMWARE_PVSCSI=m +CONFIG_VMXNET3=m +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_VORTEX=m +# CONFIG_VSX is not set +CONFIG_VT=y +# CONFIG_VT6655 is not set +CONFIG_VT_CONSOLE=y +CONFIG_VXFS_FS=m +CONFIG_VXGE=m +# CONFIG_VXGE_DEBUG_TRACE_ALL is not set +CONFIG_W1=m +CONFIG_W1_CON=y +CONFIG_W1_MASTER_DS1WM=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_GPIO=m +CONFIG_W1_MASTER_MATROX=m +CONFIG_W1_SLAVE_BQ27000=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +# CONFIG_W1_SLAVE_DS2433_CRC is not set +CONFIG_W1_SLAVE_DS2760=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_THERM=m +CONFIG_W83627HF_WDT=m +CONFIG_W83697HF_WDT=m +CONFIG_W83697UG_WDT=m +CONFIG_W83877F_WDT=m +CONFIG_W83977F_WDT=m +CONFIG_WAFER_WDT=m +CONFIG_WANXL=m +CONFIG_WAN_ROUTER_DRIVERS=m +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_WATCHDOG_RTAS=m +CONFIG_WD80x3=m +CONFIG_WDT=m +CONFIG_WDTPCI=m +CONFIG_WESTBRIDGE=m +# CONFIG_WESTBRIDGE_ASTORIA is not set +# CONFIG_WESTBRIDGE_DEBUG is not set +CONFIG_WESTBRIDGE_HAL_SELECTED=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PRIV=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WIMAX=m +CONFIG_WIMAX_DEBUG_LEVEL=8 +CONFIG_WIMAX_I2400M=m +CONFIG_WIMAX_I2400M_DEBUG_LEVEL=8 +CONFIG_WIMAX_IWMC3200_SDIO=y +CONFIG_WINBOND_840=m +CONFIG_WINBOND_FIR=m +CONFIG_WINDFARM=m +CONFIG_WINDFARM_PM112=m +CONFIG_WINDFARM_PM121=m +CONFIG_WINDFARM_PM81=m +CONFIG_WINDFARM_PM91=m +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WIRELESS_EXT_SYSFS=y +CONFIG_WL1251=m +CONFIG_WL1251_SDIO=m +CONFIG_WL1251_SPI=m +CONFIG_WL1271=m +CONFIG_WL1271_SDIO=m +CONFIG_WL1271_SPI=m +CONFIG_WL12XX=m +CONFIG_WL12XX_PLATFORM_DATA=y +CONFIG_WLAGS49_H2=m +CONFIG_WLAGS49_H25=m +CONFIG_WLAN=y +CONFIG_WM831X_BACKUP=m +CONFIG_WM831X_POWER=m +CONFIG_WM831X_WATCHDOG=m +CONFIG_WM8350_POWER=m +CONFIG_X25=m +CONFIG_X86=y +# CONFIG_X86_32_NON_STANDARD is not set +CONFIG_X86_32_SMP=y +CONFIG_X86_64_ACPI_NUMA=y +CONFIG_X86_64_SMP=y +CONFIG_X86_ACPI_CPUFREQ=y +# CONFIG_X86_ANCIENT_MCE is not set +CONFIG_X86_APM_BOOT=y +# CONFIG_X86_BIGSMP is not set +CONFIG_X86_BOOTPARAM_MEMORY_CORRUPTION_CHECK=y +CONFIG_X86_BSWAP=y +CONFIG_X86_CHECK_BIOS_CORRUPTION=y +CONFIG_X86_CMOV=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_CPU=y +CONFIG_X86_CPUFREQ_NFORCE2=y +CONFIG_X86_CPUID=m +CONFIG_X86_DEBUGCTLMSR=y +# CONFIG_X86_DECODER_SELFTEST is not set +# CONFIG_X86_ELAN is not set +CONFIG_X86_EXTENDED_PLATFORM=y +CONFIG_X86_E_POWERSAVER=m +CONFIG_X86_GENERIC=y +CONFIG_X86_GX_SUSPMOD=y +CONFIG_X86_HT=y +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_INVLPG=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_L1_CACHE_SHIFT=6 +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_LONGHAUL=y +CONFIG_X86_LONGRUN=y +CONFIG_X86_MCE=y +CONFIG_X86_MCE_AMD=y +CONFIG_X86_MCE_INJECT=m +CONFIG_X86_MCE_INTEL=y +CONFIG_X86_MCE_THRESHOLD=y +CONFIG_X86_MCE_XEON75XX=m +CONFIG_X86_MPPARSE=y +# CONFIG_X86_MRST is not set +CONFIG_X86_MSR=m +CONFIG_X86_NEED_RELOCS=y +CONFIG_X86_P4_CLOCKMOD=m +CONFIG_X86_PAE=y +CONFIG_X86_PAT=y +CONFIG_X86_PCC_CPUFREQ=m +CONFIG_X86_PLATFORM_DEVICES=y +CONFIG_X86_PM_TIMER=y +CONFIG_X86_POPAD_OK=y +CONFIG_X86_POWERNOW_K6=y +CONFIG_X86_POWERNOW_K7=y +CONFIG_X86_POWERNOW_K7_ACPI=y +CONFIG_X86_POWERNOW_K8=y +CONFIG_X86_PPRO_FENCE=y +# CONFIG_X86_PTDUMP is not set +# CONFIG_X86_RDC321X is not set +CONFIG_X86_REBOOTFIXUPS=y +CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y +CONFIG_X86_RESERVE_LOW=64 +CONFIG_X86_SPEEDSTEP_CENTRINO=y +CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE=y +CONFIG_X86_SPEEDSTEP_ICH=y +CONFIG_X86_SPEEDSTEP_RELAXED_CAP_CHECK=y +CONFIG_X86_SPEEDSTEP_SMI=y +CONFIG_X86_SUPPORTS_MEMORY_FAILURE=y +CONFIG_X86_THERMAL_VECTOR=y +CONFIG_X86_TRAMPOLINE=y +CONFIG_X86_TSC=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +# CONFIG_X86_UV is not set +# CONFIG_X86_VERBOSE_BOOTUP is not set +# CONFIG_X86_VSMP is not set +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_XADD=y +CONFIG_XEN=y +CONFIG_XENFS=m +CONFIG_XEN_BALLOON=y +CONFIG_XEN_COMPAT_XENFS=y +# CONFIG_XEN_DEBUG_FS is not set +CONFIG_XEN_DEV_EVTCHN=m +CONFIG_XEN_DOM0=y +CONFIG_XEN_FBDEV_FRONTEND=m +CONFIG_XEN_KBDDEV_FRONTEND=m +CONFIG_XEN_MAX_DOMAIN_MEMORY=128 +CONFIG_XEN_PCIDEV_FRONTEND=m +CONFIG_XEN_PLATFORM_PCI=m +CONFIG_XEN_PVHVM=y +CONFIG_XEN_SAVE_RESTORE=y +CONFIG_XEN_SCRUB_PAGES=y +CONFIG_XEN_SYS_HYPERVISOR=y +CONFIG_XFRM=y +CONFIG_XFRM_IPCOMP=m +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +# CONFIG_XFRM_SUB_POLICY is not set +CONFIG_XFRM_USER=m +# CONFIG_XFS_DEBUG is not set +CONFIG_XFS_FS=m +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_RT=y +CONFIG_XICS=y +CONFIG_XILINX_EMACLITE=m +CONFIG_XILINX_LL_TEMAC=m +# CONFIG_XIP_KERNEL is not set +# CONFIG_XMON is not set +CONFIG_XO1_RFKILL=m +CONFIG_XOR_BLOCKS=m +CONFIG_XPS_USB_HCD_XILINX=y +CONFIG_YAM=m +CONFIG_YELLOWFIN=m +CONFIG_YENTA=m +CONFIG_YENTA_ENE_TUNE=y +CONFIG_YENTA_O2=y +CONFIG_YENTA_RICOH=y +CONFIG_YENTA_TI=y +CONFIG_YENTA_TOSHIBA=y +CONFIG_ZBOOT_ROM_BSS=0x0 +CONFIG_ZBOOT_ROM_TEXT=0x0 +CONFIG_ZD1211RW=m +# CONFIG_ZD1211RW_DEBUG is not set +CONFIG_ZEROPLUS_FF=y +CONFIG_ZISOFS=y +CONFIG_ZLIB_DEFLATE=m +CONFIG_ZLIB_INFLATE=y +CONFIG_ZNET=m +CONFIG_ZONE_DMA=y +CONFIG_ZRAM=m --- linux-2.6.37.orig/debian.master/config/enforce +++ linux-2.6.37/debian.master/config/enforce @@ -0,0 +1,76 @@ +# +# SECURITY items +# +# Ensure this option is enabled. +value CONFIG_COMPAT_BRK n +value CONFIG_DEVKMEM n +value CONFIG_LSM_MMAP_MIN_ADDR 0 +value CONFIG_SECURITY y +!exists CONFIG_SECURITY_FILE_CAPABILITIES | value CONFIG_SECURITY_FILE_CAPABILITIES y +value CONFIG_SECURITY_SELINUX y +value CONFIG_SECURITY_SMACK y +value CONFIG_SECURITY_YAMA y +value CONFIG_SYN_COOKIES y +value CONFIG_DEFAULT_SECURITY_APPARMOR y +# For architectures which support this option ensure it is enabled. +!exists CONFIG_SECCOMP | value CONFIG_SECCOMP y +!exists CONFIG_CC_STACKPROTECTOR | value CONFIG_CC_STACKPROTECTOR y +!exists CONFIG_DEBUG_RODATA | value CONFIG_DEBUG_RODATA y +!exists CONFIG_DEBUG_SET_MODULE_RONX | value CONFIG_DEBUG_SET_MODULE_RONX y +!exists CONFIG_STRICT_DEVMEM | value CONFIG_STRICT_DEVMEM y +# For architectures which support this option ensure it is disabled. +!exists CONFIG_COMPAT_VDSO | value CONFIG_COMPAT_VDSO n +# Default to 32768 for armel, 65536 for everything else. +( arch armel & value CONFIG_DEFAULT_MMAP_MIN_ADDR 32768 ) | \ + ( value CONFIG_DEFAULT_MMAP_MIN_ADDR 65536) + +# CONFIG_USB_DEVICE_FS breaks udev USB firmware loading and is deprecated +# ensure it is disabled. +value CONFIG_USB_DEVICEFS n + +# upstart requires DEVTMPFS be enabled and mounted by default. +value CONFIG_DEVTMPFS y +value CONFIG_DEVTMPFS_MOUNT y + +# some /dev nodes require POSIX ACLs, like /dev/dsp +value CONFIG_TMPFS_POSIX_ACL y + +# Ramdisk size should be a minimum of 64M +value CONFIG_BLK_DEV_RAM_SIZE 65536 + +# LVM requires dm_mod built in to activate correctly (LP: #560717) +value CONFIG_BLK_DEV_DM y + +# sysfs: ensure all DEPRECATED items are off +!exists CONFIG_SYSFS_DEPRECATED_V2 | value CONFIG_SYSFS_DEPRECATED_V2 n +!exists CONFIG_SYSFS_DEPRECATED | value CONFIG_SYSFS_DEPRECATED n + +# automatically add local version will cause packaging failure +value CONFIG_LOCALVERSION_AUTO n + +# provide framebuffer console form the start +# UbuntuSpec:foundations-m-grub2-boot-framebuffer +value CONFIG_FRAMEBUFFER_CONSOLE y + +# GRUB changes will rely on built in vesafb on x86, +# UbuntuSpec:foundations-m-grub2-boot-framebuffer +(( arch i386 | arch amd64 ) & value CONFIG_FB_VESA y) | \ + value CONFIG_FB_VESA m | !exists CONFIG_FB_VESA + +# Build in uinput module so that it's always available (LP: 584812) +value CONFIG_INPUT_UINPUT y + +# upstart relies on getting all of the kernel arguments +value CONFIG_INIT_PASS_ALL_PARAMS y + +# Enabling CONFIG_IMA is vastly expensive, ensure it is off +value CONFIG_IMA n + +# Ensure CONFIG_INTEL_IDLE is turned off for -virtual. +!exists CONFIG_INTEL_IDLE | \ + (flavour virtual & value CONFIG_INTEL_IDLE n) | \ + value CONFIG_INTEL_IDLE y + +# Ensure CONFIG_IPV6 is y, if this is a module we get a module load for +# every ipv6 packet, bad. +value CONFIG_IPV6 y --- linux-2.6.37.orig/debian.master/config/amd64/config.common.amd64 +++ linux-2.6.37/debian.master/config/amd64/config.common.amd64 @@ -0,0 +1,480 @@ +# +# Config options for config.common.amd64 automatically generated by splitconfig.pl +# +CONFIG_64BIT=y +CONFIG_ACPI_BLACKLIST_YEAR=0 +CONFIG_AIC79XX_RESET_DELAY_MS=5000 +CONFIG_ALIM7101_WDT=m +CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SUPPORTS_MSI=y +CONFIG_ASUS_OLED=m +# CONFIG_ASYNC_TX_DMA is not set +CONFIG_ATALK=m +CONFIG_ATA_GENERIC=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_PIIX=y +CONFIG_ATH5K=m +CONFIG_ATM=m +# CONFIG_ATM_BR2684_IPFILTER is not set +# CONFIG_ATM_DUMMY is not set +CONFIG_AUDIT_ARCH=y +CONFIG_AX25_DAMA_SLAVE=y +CONFIG_B43=m +CONFIG_B43LEGACY=m +CONFIG_B44=m +CONFIG_BLK_DEV_DRBD=m +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_MD=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=y +# CONFIG_BRCMFMAC is not set +CONFIG_BROADCOM_PHY=y +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_CDROM_PKTCDVD=y +CONFIG_CFG80211_REG_DEBUG=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CHR_DEV_SG=y +CONFIG_CICADA_PHY=y +CONFIG_CIFS_EXPERIMENTAL=y +CONFIG_CIFS_XATTR=y +CONFIG_COMEDI=m +CONFIG_CONNECTOR=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CRASH_DUMP=y +CONFIG_CRC_T10DIF=y +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_CTR=m +CONFIG_CRYPTO_DEV_HIFN_795X=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_LZO=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_SEQIV=m +CONFIG_DAB=y +CONFIG_DAVICOM_PHY=y +CONFIG_DEBUG_INFO=y +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +CONFIG_DISPLAY_SUPPORT=m +# CONFIG_DL2K is not set +CONFIG_DMADEVICES=y +CONFIG_DM_MIRROR=y +CONFIG_DM_MULTIPATH=y +CONFIG_DM_RAID45=m +CONFIG_DM_SNAPSHOT=y +CONFIG_DRM_NOUVEAU=m +CONFIG_DRM_RADEON=m +CONFIG_DT3155=m +CONFIG_DVB_BUDGET_CORE=m +# CONFIG_DVB_FE_CUSTOMISE is not set +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +# CONFIG_DVB_USB_EC168 is not set +CONFIG_ECHO=m +CONFIG_ENCLOSURE_SERVICES=m +CONFIG_ET131X=m +# CONFIG_EZX_PCAP is not set +CONFIG_FB_3DFX=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY128=m +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_BOOT_VESA_SUPPORT=y +CONFIG_FB_DDC=m +# CONFIG_FB_MACMODES is not set +CONFIG_FB_MATROX=m +CONFIG_FB_RADEON=m +CONFIG_FB_S1D13XXX=m +CONFIG_FB_SAVAGE=m +CONFIG_FB_SVGALIB=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_SYS_IMAGEBLIT=m +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_UDL=m +CONFIG_FB_UVESA=m +CONFIG_FB_VESA=y +CONFIG_FB_VGA16=m +CONFIG_FB_VOODOO1=m +CONFIG_FIRMWARE_EDID=y +# CONFIG_FLATMEM_MANUAL is not set +# CONFIG_FONTS is not set +CONFIG_FSAM7400=m +CONFIG_FTL=m +CONFIG_FUNCTION_TRACER=y +CONFIG_GENERIC_CPU=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIO_JANZ_TTL=m +CONFIG_GPIO_MAX732X=m +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_PCF857X=m +CONFIG_GPIO_PCH=m +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_TWL4030=m +CONFIG_GPIO_VX855=m +# CONFIG_HARDIRQS_SW_RESEND is not set +# CONFIG_HAVE_AOUT is not set +CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_HOTPLUG_PCI=y +CONFIG_HP_ILO=m +CONFIG_HUGETLB_PAGE=y +CONFIG_HWMON=y +CONFIG_HZ=100 +CONFIG_HZ_100=y +# CONFIG_HZ_250 is not set +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_GPIO=m +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_I801=m +CONFIG_ICPLUS_PHY=y +# CONFIG_IDE is not set +CONFIG_IDE_PHISON=m +CONFIG_IGB=m +CONFIG_IIO=m +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_INTR_REMAP=y +CONFIG_IOMMU_API=y +CONFIG_IOMMU_HELPER=y +CONFIG_IPC_NS=y +CONFIG_IPMI_HANDLER=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPWIRELESS=m +CONFIG_IRDA=m +# CONFIG_IRQ_PER_CPU is not set +CONFIG_ISDN=y +CONFIG_IWL3945=m +CONFIG_IWL4965=y +CONFIG_IWMC3200TOP_DEBUGFS=y +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KGDB=y +CONFIG_KSM=y +# CONFIG_KTIME_SCALAR is not set +CONFIG_KVM=m +CONFIG_LAPBETHER=m +CONFIG_LATENCYTOP=y +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_PCA9532=m +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LIBERTAS_MESH=y +CONFIG_LIBIPW_DEBUG=y +CONFIG_LINE6_USB=m +CONFIG_LLC=y +CONFIG_LLC2=m +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_LSI_ET1011C_PHY=y +CONFIG_LXT_PHY=y +CONFIG_LZO_COMPRESS=y +# CONFIG_M686 is not set +CONFIG_MACH_NO_WESTBRIDGE=y +CONFIG_MARVELL_PHY=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_GPIO=y +CONFIG_MEMORY_HOTREMOVE=y +CONFIG_MEMSTICK=m +CONFIG_MFD_JANZ_CMODIO=m +# CONFIG_MFD_TMIO is not set +CONFIG_MMC=y +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_MOXA_SMARTIO=m +CONFIG_MTD=m +CONFIG_MTD_ABSENT=m +CONFIG_MTD_ALAUDA=m +CONFIG_MTD_AR7_PARTS=m +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_CFI=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_CHAR=m +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_CONCAT=m +CONFIG_MTD_DATAFLASH=m +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_GEN_PROBE=m +CONFIG_MTD_GPIO_ADDR=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_MTDRAM=m +CONFIG_MTD_NAND=m +CONFIG_MTD_NAND_ECC=m +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_NANDSIM=m +CONFIG_MTD_NAND_PLATFORM=m +CONFIG_MTD_ONENAND=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_PLATRAM=m +CONFIG_MTD_RAM=m +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_ROM=m +CONFIG_MTD_SLRAM=m +CONFIG_MTD_SM_COMMON=m +CONFIG_MTD_SST25L=m +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NATIONAL_PHY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +CONFIG_NET_CLS_CGROUP=y +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_DCCPPROBE=m +CONFIG_NET_POCKET=y +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_TCPPROBE=m +CONFIG_NFTL=m +CONFIG_NIU=m +CONFIG_NODES_SHIFT=6 +CONFIG_NOP_USB_XCEIV=m +CONFIG_NORTEL_HERMES=m +CONFIG_NOZOMI=m +CONFIG_NO_HZ=y +CONFIG_NR_CPUS=64 +CONFIG_NVRAM=m +CONFIG_OUTPUT_FORMAT="elf64-x86-64" +CONFIG_PANEL=m +CONFIG_PARPORT=m +CONFIG_PATA_ALI=m +CONFIG_PATA_ARTOP=m +CONFIG_PATA_ATIIXP=m +CONFIG_PATA_CMD640_PCI=m +CONFIG_PATA_CMD64X=m +CONFIG_PATA_CS5530=m +CONFIG_PATA_CYPRESS=m +CONFIG_PATA_HPT366=m +CONFIG_PATA_HPT37X=m +CONFIG_PATA_HPT3X2N=m +CONFIG_PATA_HPT3X3=m +CONFIG_PATA_NS87410=m +CONFIG_PATA_NS87415=m +CONFIG_PATA_OPTI=m +CONFIG_PATA_OPTIDMA=m +CONFIG_PATA_PDC_OLD=m +CONFIG_PATA_RADISYS=m +CONFIG_PATA_SC1200=m +CONFIG_PATA_SIS=y +CONFIG_PCCARD=m +CONFIG_PCI_IOV=y +CONFIG_PCI_STUB=m +CONFIG_PDC_ADMA=y +CONFIG_PHYSICAL_ALIGN=0x1000000 +CONFIG_PHYSICAL_START=0x200000 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PID_NS=y +CONFIG_PLX_HERMES=m +CONFIG_PM_DEBUG=y +CONFIG_POCH=m +CONFIG_POHMELFS=m +CONFIG_PPP=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_QSEMI_PHY=y +CONFIG_R3964=m +CONFIG_RCU_FANOUT=64 +CONFIG_REALTEK_PHY=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_RELOCATABLE=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_RFD_FTL=m +CONFIG_RISCOM8=m +CONFIG_RT2800USB_UNKNOWN=y +# CONFIG_RT2X00_LIB_DEBUGFS is not set +CONFIG_RTC_DRV_CMOS=y +CONFIG_RTC_DRV_TEST=m +CONFIG_RTC_DRV_TWL4030=m +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTL8180=m +CONFIG_RTL8192E=m +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_SATA_SVW=m +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_TRACER=y +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_DH=y +CONFIG_SCSI_IPR=m +CONFIG_SCSI_ISCSITARGET=m +CONFIG_SCSI_MVSAS=m +CONFIG_SCSI_OSD_INITIATOR=m +CONFIG_SCSI_QLA_ISCSI=m +CONFIG_SENSORS_ADS7828=m +CONFIG_SENSORS_AK8975=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_PCI=y +# CONFIG_SERIAL_PMACZILOG is not set +CONFIG_SERIAL_UARTLITE=m +# CONFIG_SLAB is not set +CONFIG_SLHC=y +CONFIG_SLIP=m +CONFIG_SLUB=y +CONFIG_SMP=y +CONFIG_SMSC_PHY=y +CONFIG_SM_FTL=m +CONFIG_SND=m +CONFIG_SND_ALI5451=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_EMU10K1_SEQ=m +CONFIG_SND_HIFIER=m +# CONFIG_SND_MIXER_OSS is not set +CONFIG_SND_MPU401=m +CONFIG_SND_MTPAV=m +CONFIG_SND_OPL3_LIB_SEQ=m +# CONFIG_SND_OPL4_LIB_SEQ is not set +CONFIG_SND_OXYGEN=m +CONFIG_SND_PCM=m +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_RAWMIDI_SEQ=m +# CONFIG_SND_SBAWE_SEQ is not set +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_SOC=m +CONFIG_SND_SOC_I2C_AND_SPI=m +CONFIG_SND_SOC_TWL4030=m +CONFIG_SND_TIMER=m +CONFIG_SND_VIRTUOSO=m +CONFIG_SOUND=m +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_DESIGNWARE=y +CONFIG_SPI_SPIDEV=m +CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_STACK_TRACER=y +# CONFIG_STANDALONE is not set +CONFIG_STE10XP=y +CONFIG_SUNGEM=m +CONFIG_SYS_HYPERVISOR=y +CONFIG_TABLET_USB_WACOM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_TPM=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_THERMAL=y +CONFIG_TMD_HERMES=m +CONFIG_TPS65010=m +CONFIG_TRANZPORT=m +CONFIG_TTPCI_EEPROM=m +CONFIG_TUN=y +# CONFIG_TWL4030_CORE is not set +CONFIG_TWL4030_USB=m +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ET61X251=m +CONFIG_USB_GADGET=m +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_GADGET_DUMMY_HCD=y +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set +# CONFIG_USB_GADGET_NET2280 is not set +CONFIG_USB_GPIO_VBUS=m +# CONFIG_USB_GSPCA_SN9C20X_EVDEV is not set +# CONFIG_USB_G_MULTI is not set +CONFIG_USB_IP_COMMON=m +CONFIG_USB_ISP1362_HCD=m +CONFIG_USB_MON=y +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_USB_NET_ZAURUS=m +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OTG is not set +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_SERIAL_QUATECH2=m +CONFIG_USB_SERIAL_QUATECH_USB2=m +CONFIG_USB_SI470X=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_STV680=m +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_ZC0301=m +CONFIG_USER_NS=y +CONFIG_UTS_NS=y +CONFIG_VGASTATE=m +CONFIG_VGA_CONSOLE=y +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7343 is not set +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BT866=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CX25821=m +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_GO7007=m +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_MT9V011=m +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_SAA7110=m +CONFIG_VIDEO_SAA7185=m +# CONFIG_VIDEO_SAA7191 is not set +# CONFIG_VIDEO_TCM825X is not set +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +# CONFIG_VIDEO_TDA9875 is not set +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +CONFIG_VIDEO_TVAUDIO=m +# CONFIG_VIDEO_TVP514X is not set +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_VPX3220=m +CONFIG_VITESSE_PHY=y +CONFIG_VME_BUS=m +CONFIG_VME_CA91CX42=m +CONFIG_VME_TSI148=m +CONFIG_VT6656=m +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_W35UND=m +CONFIG_WAN=y +CONFIG_WAN_ROUTER=m +CONFIG_WATCHDOG=y +CONFIG_WIMAX_I2400M_SDIO=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_WM8350_WATCHDOG=m +CONFIG_X25_ASY=m +# CONFIG_X86_32 is not set +CONFIG_X86_64=y +CONFIG_X86_INTERNODE_CACHE_SHIFT=7 +CONFIG_X86_MINIMUM_CPU_FAMILY=64 +CONFIG_X86_SPEEDSTEP_LIB=m +CONFIG_X86_X2APIC=y +CONFIG_XEN_PRIVILEGED_GUEST=y +CONFIG_ZONE_DMA32=y +CONFIG_ZONE_DMA_FLAG=1 --- linux-2.6.37.orig/debian.master/config/amd64/config.flavour.generic +++ linux-2.6.37/debian.master/config/amd64/config.flavour.generic @@ -0,0 +1,19 @@ +# +# Config options for config.flavour.generic automatically generated by splitconfig.pl +# +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_INTEL_IDLE=y +# CONFIG_MEMORY_HOTPLUG is not set +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_VIRTIO=m +CONFIG_VIRTIO_BLK=m +CONFIG_VIRTIO_NET=m +CONFIG_VIRTIO_PCI=m +CONFIG_VIRTIO_RING=m +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_NETDEV_FRONTEND=m --- linux-2.6.37.orig/debian.master/config/amd64/config.flavour.server +++ linux-2.6.37/debian.master/config/amd64/config.flavour.server @@ -0,0 +1,19 @@ +# +# Config options for config.flavour.server automatically generated by splitconfig.pl +# +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_DEADLINE=y +CONFIG_DEFAULT_IOSCHED="deadline" +CONFIG_INTEL_IDLE=y +CONFIG_MEMORY_HOTPLUG=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_SCSI_SPI_ATTRS=y +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_NET=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_RING=y +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_NETDEV_FRONTEND=m --- linux-2.6.37.orig/debian.master/config/amd64/config.flavour.virtual +++ linux-2.6.37/debian.master/config/amd64/config.flavour.virtual @@ -0,0 +1,19 @@ +# +# Config options for config.flavour.virtual automatically generated by splitconfig.pl +# +# CONFIG_DEFAULT_CFQ is not set +CONFIG_DEFAULT_DEADLINE=y +CONFIG_DEFAULT_IOSCHED="deadline" +# CONFIG_INTEL_IDLE is not set +CONFIG_MEMORY_HOTPLUG=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_SCSI_SPI_ATTRS=y +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_NET=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_RING=y +CONFIG_XEN_BLKDEV_FRONTEND=y +CONFIG_XEN_NETDEV_FRONTEND=y --- linux-2.6.37.orig/debian.master/config/armel/config.common.armel +++ linux-2.6.37/debian.master/config/armel/config.common.armel @@ -0,0 +1,315 @@ +# +# Config options for config.common.armel automatically generated by splitconfig.pl +# +CONFIG_AIC79XX_RESET_DELAY_MS=5000 +# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set +# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_ASUS_OLED=m +CONFIG_ASYNC_TX_DMA=y +CONFIG_ATA_GENERIC=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_PIIX=y +CONFIG_ATH5K=m +CONFIG_ATM_BR2684_IPFILTER=y +CONFIG_ATM_DUMMY=m +CONFIG_AX25_DAMA_SLAVE=y +CONFIG_BLK_DEV_DRBD=m +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_MD=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=y +CONFIG_BROADCOM_PHY=y +CONFIG_CFG80211_REG_DEBUG=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CHR_DEV_SG=y +CONFIG_CICADA_PHY=y +CONFIG_CIFS_EXPERIMENTAL=y +CONFIG_CIFS_XATTR=y +# CONFIG_COMEDI is not set +CONFIG_CONNECTOR=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CRC_T10DIF=y +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_CTR=m +CONFIG_CRYPTO_DEV_HIFN_795X=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_LZO=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_SEQIV=m +CONFIG_DAB=y +CONFIG_DAVICOM_PHY=y +CONFIG_DEBUG_INFO=y +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_DEFAULT_MMAP_MIN_ADDR=32768 +# CONFIG_DL2K is not set +CONFIG_DMADEVICES=y +CONFIG_DM_MIRROR=y +CONFIG_DM_MULTIPATH=y +CONFIG_DM_SNAPSHOT=y +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_DT3155 is not set +CONFIG_DVB_BUDGET_CORE=m +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +CONFIG_ECHO=m +CONFIG_ENCLOSURE_SERVICES=m +CONFIG_ET131X=m +CONFIG_EZX_PCAP=y +CONFIG_FB_3DFX=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY128=m +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +# CONFIG_FB_MACMODES is not set +CONFIG_FB_MATROX=m +CONFIG_FB_RADEON=m +# CONFIG_FB_SAVAGE is not set +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_SYS_IMAGEBLIT=m +CONFIG_FB_UDL=m +CONFIG_FB_VESA=m +CONFIG_FB_VOODOO1=m +CONFIG_FLATMEM_MANUAL=y +CONFIG_FONTS=y +CONFIG_FORCE_MAX_ZONEORDER=11 +# CONFIG_FSAM7400 is not set +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_GPIO_JANZ_TTL is not set +# CONFIG_GPIO_PCH is not set +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_TWL4030=y +# CONFIG_GPIO_VX855 is not set +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAVE_AOUT=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +# CONFIG_HAVE_GENERIC_HARDIRQS is not set +CONFIG_HP_ILO=m +# CONFIG_HUGETLB_PAGE is not set +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_GPIO=m +# CONFIG_I2C_HELPER_AUTO is not set +# CONFIG_I2C_I801 is not set +CONFIG_ICPLUS_PHY=y +# CONFIG_IDE is not set +CONFIG_IDE_PHISON=m +CONFIG_IGB=m +CONFIG_IIO=m +# CONFIG_INTR_REMAP is not set +CONFIG_IPC_NS=y +# CONFIG_IPMI_HANDLER is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IWL3945=m +CONFIG_IWL4965=y +CONFIG_KGDB=y +# CONFIG_LAPBETHER is not set +CONFIG_LATENCYTOP=y +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_PCA9532=m +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LIBIPW_DEBUG=y +# CONFIG_LINE6_USB is not set +CONFIG_LSI_ET1011C_PHY=y +CONFIG_LXT_PHY=y +CONFIG_LZO_COMPRESS=m +# CONFIG_M686 is not set +CONFIG_MARVELL_PHY=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_GPIO=y +# CONFIG_MFD_JANZ_CMODIO is not set +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MOXA_SMARTIO=m +CONFIG_MTD=y +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CHAR=y +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_GPIO_ADDR is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_SM_COMMON is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +CONFIG_NATIONAL_PHY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +# CONFIG_NET_POCKET is not set +CONFIG_NIU=m +CONFIG_NORTEL_HERMES=m +CONFIG_NOZOMI=m +CONFIG_NVRAM=m +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PANEL=m +CONFIG_PATA_ALI=m +CONFIG_PATA_ARTOP=m +CONFIG_PATA_ATIIXP=m +CONFIG_PATA_CMD640_PCI=m +CONFIG_PATA_CMD64X=m +CONFIG_PATA_CS5530=m +CONFIG_PATA_CYPRESS=m +CONFIG_PATA_HPT366=m +CONFIG_PATA_HPT37X=m +CONFIG_PATA_HPT3X2N=m +CONFIG_PATA_HPT3X3=m +CONFIG_PATA_NS87410=m +CONFIG_PATA_NS87415=m +CONFIG_PATA_OPTI=m +CONFIG_PATA_OPTIDMA=m +CONFIG_PATA_PDC_OLD=m +CONFIG_PATA_RADISYS=m +CONFIG_PATA_SC1200=m +CONFIG_PATA_SIS=y +# CONFIG_PCCARD is not set +CONFIG_PCI_IOV=y +CONFIG_PCI_STUB=m +CONFIG_PDC_ADMA=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_PID_NS=y +CONFIG_PLX_HERMES=m +# CONFIG_PM_DEBUG is not set +# CONFIG_POCH is not set +CONFIG_POHMELFS=m +CONFIG_PPP=y +CONFIG_QSEMI_PHY=y +# CONFIG_R3964 is not set +CONFIG_RCU_FANOUT=32 +CONFIG_REALTEK_PHY=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_RESOURCE_COUNTERS=y +CONFIG_RISCOM8=m +CONFIG_RTC_DRV_TEST=m +CONFIG_RTC_DRV_TWL4030=y +CONFIG_RTL8180=m +CONFIG_RTL8192E=m +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_SATA_SVW=m +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_TRACER=y +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_ADVANSYS is not set +CONFIG_SCSI_DH=y +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_MVSAS=m +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_SCSI_QLA_ISCSI is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SENSORS_ADS7828=m +# CONFIG_SENSORS_AK8975 is not set +CONFIG_SENSORS_W83L786NG=m +CONFIG_SERIAL_8250_PCI=m +# CONFIG_SERIAL_PMACZILOG is not set +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SLHC=y +CONFIG_SMSC_PHY=y +CONFIG_SM_FTL=m +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_BT87X_OVERCLOCK is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_HIFIER=m +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +CONFIG_SND_OXYGEN=m +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_SERIAL_U16550 is not set +CONFIG_SND_SOC_TWL4030=y +CONFIG_SND_VIRTUOSO=m +# CONFIG_SPARSEMEM_MANUAL is not set +# CONFIG_SPARSE_IRQ is not set +CONFIG_SPI_DESIGNWARE=m +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SSB_B43_PCI_BRIDGE is not set +# CONFIG_STACK_TRACER is not set +CONFIG_STANDALONE=y +CONFIG_STE10XP=y +# CONFIG_SUNGEM is not set +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_TABLET_USB_WACOM=m +# CONFIG_TCG_TPM is not set +CONFIG_TMD_HERMES=m +CONFIG_TPS65010=m +CONFIG_TRANZPORT=m +CONFIG_TWL4030_USB=y +# CONFIG_USB_ET61X251 is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GADGET_MUSB_HDRC=y +CONFIG_USB_GSPCA_SN9C20X_EVDEV=y +CONFIG_USB_G_MULTI=m +CONFIG_USB_IP_COMMON=m +# CONFIG_USB_ISP1362_HCD is not set +CONFIG_USB_MON=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_USB_NET_ZAURUS=m +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +# CONFIG_USB_QUICKCAM_MESSENGER is not set +CONFIG_USB_SI470X=m +# CONFIG_USB_SN9C102 is not set +CONFIG_USB_STKWEBCAM=m +# CONFIG_USB_STV680 is not set +CONFIG_USB_UHCI_HCD=m +# CONFIG_USB_ZC0301 is not set +CONFIG_USER_NS=y +CONFIG_UTS_NS=y +# CONFIG_VGA_CONSOLE is not set +# CONFIG_VIDEO_ADV7170 is not set +# CONFIG_VIDEO_ADV7175 is not set +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7343 is not set +# CONFIG_VIDEO_BT819 is not set +# CONFIG_VIDEO_BT856 is not set +# CONFIG_VIDEO_BT866 is not set +# CONFIG_VIDEO_CPIA is not set +CONFIG_VIDEO_EM28XX_ALSA=m +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set +# CONFIG_VIDEO_KS0127 is not set +# CONFIG_VIDEO_MT9V011 is not set +# CONFIG_VIDEO_OVCAMCHIP is not set +# CONFIG_VIDEO_SAA6588 is not set +# CONFIG_VIDEO_SAA7110 is not set +# CONFIG_VIDEO_SAA7185 is not set +# CONFIG_VIDEO_SAA7191 is not set +# CONFIG_VIDEO_TCM825X is not set +# CONFIG_VIDEO_TDA7432 is not set +# CONFIG_VIDEO_TDA9840 is not set +# CONFIG_VIDEO_TDA9875 is not set +# CONFIG_VIDEO_TEA6415C is not set +# CONFIG_VIDEO_TEA6420 is not set +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_TVAUDIO is not set +# CONFIG_VIDEO_TVP514X is not set +# CONFIG_VIDEO_TVP5150 is not set +# CONFIG_VIDEO_VPX3220 is not set +CONFIG_VIRTIO=m +CONFIG_VIRTIO_BLK=m +CONFIG_VIRTIO_NET=m +CONFIG_VIRTIO_PCI=m +CONFIG_VIRTIO_RING=m +CONFIG_VITESSE_PHY=y +CONFIG_VME_BUS=m +# CONFIG_VME_CA91CX42 is not set +# CONFIG_VME_TSI148 is not set +# CONFIG_VT6656 is not set +CONFIG_W35UND=m +# CONFIG_WM8350_WATCHDOG is not set +# CONFIG_X25_ASY is not set +# CONFIG_X86_X2APIC is not set +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_ZONE_DMA_FLAG=0 --- linux-2.6.37.orig/debian.master/config/armel/config.flavour.omap +++ linux-2.6.37/debian.master/config/armel/config.flavour.omap @@ -0,0 +1,158 @@ +# +# Config options for config.flavour.omap automatically generated by splitconfig.pl +# +# CONFIG_APM_EMULATION is not set +CONFIG_ARCH_OMAP=y +# CONFIG_ARCH_VERSATILE is not set +CONFIG_ARM_ERRATA_430973=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ATALK=m +CONFIG_ATM=m +CONFIG_B43=m +CONFIG_B43LEGACY=m +CONFIG_B44=m +CONFIG_BRCMFMAC=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_CDROM_PKTCDVD=m +# CONFIG_CGROUP_MEM_RES_CTLR_SWAP is not set +CONFIG_CRYPTO_HMAC=m +CONFIG_DISPLAY_SUPPORT=y +# CONFIG_DM_RAID45 is not set +CONFIG_DVB_FE_CUSTOMISE=y +CONFIG_DVB_USB_EC168=m +CONFIG_FB_ARMCLCD=m +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_DDC is not set +CONFIG_FB_S1D13XXX=m +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_TILEBLITTING is not set +# CONFIG_FB_UVESA is not set +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FTL=m +# CONFIG_GPIO_MAX732X is not set +CONFIG_GPIO_PCA953X=y +# CONFIG_GPIO_PCF857X is not set +# CONFIG_HIGHMEM is not set +CONFIG_HIGH_RES_TIMERS=y +CONFIG_HTC_EGPIO=y +CONFIG_HWMON=y +CONFIG_HZ=128 +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_IRDA=m +CONFIG_ISDN=y +# CONFIG_IWMC3200TOP_DEBUGFS is not set +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_XTKBD=m +# CONFIG_KSM is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LIBERTAS_MESH is not set +CONFIG_LLC=m +CONFIG_LLC2=m +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_MACH_NO_WESTBRIDGE is not set +# CONFIG_MEMSTICK is not set +CONFIG_MFD_ASIC3=y +CONFIG_MFD_T7L66XB=y +CONFIG_MFD_TC6387XB=y +CONFIG_MFD_TC6393XB=y +CONFIG_MFD_TMIO=y +CONFIG_MMC_ARMMMCI=m +CONFIG_MMC_SDHCI=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_MTD_ABSENT=m +# CONFIG_MTD_AR7_PARTS is not set +# CONFIG_MTD_ARM_INTEGRATOR is not set +CONFIG_MTD_CFI=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_CONCAT=m +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_GEN_PROBE=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_MTDRAM=m +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_ECC=y +CONFIG_MTD_ONENAND=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_PLATRAM=m +CONFIG_MTD_RAM=m +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_ROM=m +CONFIG_MTD_SLRAM=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +# CONFIG_NET_CLS_CGROUP is not set +# CONFIG_NET_CLS_FLOW is not set +# CONFIG_NET_CLS_U32 is not set +# CONFIG_NET_DCCPPROBE is not set +# CONFIG_NET_SCH_INGRESS is not set +# CONFIG_NET_TCPPROBE is not set +CONFIG_NFTL=m +CONFIG_NOP_USB_XCEIV=y +CONFIG_NO_HZ=y +CONFIG_OC_ETM=y +CONFIG_PARPORT=m +# CONFIG_PCI_SYSCALL is not set +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +CONFIG_PRINT_QUOTA_WARNING=y +CONFIG_RFD_FTL=m +# CONFIG_RT2800USB_UNKNOWN is not set +CONFIG_RT2X00_LIB_DEBUGFS=y +CONFIG_RTC_DRV_CMOS=m +CONFIG_RTC_DRV_PL030=m +CONFIG_RTC_DRV_PL031=m +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_SCSI_ISCSITARGET is not set +# CONFIG_SCSI_SPI_ATTRS is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_AMBA_PL011=m +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SLAB is not set +CONFIG_SLIP=y +CONFIG_SLUB=y +CONFIG_SMC91X=m +CONFIG_SND=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_MPU401=m +CONFIG_SND_PCM=y +CONFIG_SND_PCM_OSS=m +CONFIG_SND_SOC=y +CONFIG_SND_SOC_I2C_AND_SPI=y +CONFIG_SND_TIMER=y +CONFIG_SOUND=y +CONFIG_SOUND_OSS_CORE=y +CONFIG_SPI=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_THERMAL=m +# CONFIG_TTPCI_EEPROM is not set +CONFIG_TUN=m +CONFIG_TWL4030_CORE=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_GADGET=y +CONFIG_USB_GPIO_VBUS=y +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OTG=y +# CONFIG_USB_SERIAL_QUATECH2 is not set +# CONFIG_USB_SERIAL_QUATECH_USB2 is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_DEV=m +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_WAN=y +CONFIG_WAN_ROUTER=m +CONFIG_WATCHDOG=y +# CONFIG_WIMAX_I2400M_SDIO is not set +# CONFIG_WIMAX_I2400M_USB is not set --- linux-2.6.37.orig/debian.master/config/armel/config.flavour.versatile +++ linux-2.6.37/debian.master/config/armel/config.flavour.versatile @@ -0,0 +1,158 @@ +# +# Config options for config.flavour.versatile automatically generated by splitconfig.pl +# +CONFIG_APM_EMULATION=m +# CONFIG_ARCH_OMAP is not set +CONFIG_ARCH_VERSATILE=y +# CONFIG_ARM_ERRATA_430973 is not set +CONFIG_ARM_L1_CACHE_SHIFT=5 +# CONFIG_ATALK is not set +# CONFIG_ATM is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_B44 is not set +# CONFIG_BRCMFMAC is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_CDROM_PKTCDVD is not set +CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CRYPTO_HMAC=y +CONFIG_DISPLAY_SUPPORT=m +CONFIG_DM_RAID45=m +# CONFIG_DVB_FE_CUSTOMISE is not set +# CONFIG_DVB_USB_EC168 is not set +CONFIG_FB_ARMCLCD=y +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_DDC=m +# CONFIG_FB_S1D13XXX is not set +CONFIG_FB_SVGALIB=m +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_UVESA=m +CONFIG_FIRMWARE_EDID=y +# CONFIG_FTL is not set +CONFIG_GPIO_MAX732X=m +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_PCF857X=m +CONFIG_HIGHMEM=y +# CONFIG_HIGH_RES_TIMERS is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HWMON is not set +CONFIG_HZ=100 +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_IRDA is not set +# CONFIG_ISDN is not set +CONFIG_IWMC3200TOP_DEBUGFS=y +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_KSM=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LIBERTAS_MESH=y +CONFIG_LLC=y +# CONFIG_LLC2 is not set +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_MACH_NO_WESTBRIDGE=y +CONFIG_MEMSTICK=m +# CONFIG_MFD_ASIC3 is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_MFD_TMIO is not set +CONFIG_MMC_ARMMMCI=y +CONFIG_MMC_SDHCI=m +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MTD_ABSENT is not set +CONFIG_MTD_AR7_PARTS=m +CONFIG_MTD_ARM_INTEGRATOR=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +# CONFIG_MTD_CFI_AMDSTD is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_JEDECPROBE is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_NAND is not set +CONFIG_MTD_NAND_ECC=m +# CONFIG_MTD_ONENAND is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +CONFIG_NET_CLS_CGROUP=y +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_DCCPPROBE=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_TCPPROBE=m +# CONFIG_NFTL is not set +CONFIG_NOP_USB_XCEIV=m +# CONFIG_NO_HZ is not set +# CONFIG_OC_ETM is not set +# CONFIG_PARPORT is not set +CONFIG_PCI_SYSCALL=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PRINT_QUOTA_WARNING is not set +# CONFIG_RFD_FTL is not set +CONFIG_RT2800USB_UNKNOWN=y +# CONFIG_RT2X00_LIB_DEBUGFS is not set +CONFIG_RTC_DRV_CMOS=y +# CONFIG_RTC_DRV_PL030 is not set +CONFIG_RTC_DRV_PL031=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_SCSI_ISCSITARGET=m +CONFIG_SCSI_SPI_ATTRS=y +CONFIG_SERIAL_8250=m +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIO_AMBAKMI=y +CONFIG_SLAB=y +CONFIG_SLIP=m +# CONFIG_SLUB is not set +CONFIG_SMC91X=y +CONFIG_SND=m +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_PCM=m +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_SOC=m +CONFIG_SND_SOC_I2C_AND_SPI=m +CONFIG_SND_TIMER=m +CONFIG_SOUND=m +# CONFIG_SOUND_OSS_CORE is not set +# CONFIG_SPI is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_THERMAL=y +CONFIG_TTPCI_EEPROM=m +CONFIG_TUN=y +# CONFIG_TWL4030_CORE is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_GADGET is not set +CONFIG_USB_GPIO_VBUS=m +# CONFIG_USB_MUSB_HDRC is not set +CONFIG_USB_OHCI_HCD=m +# CONFIG_USB_OTG is not set +CONFIG_USB_SERIAL_QUATECH2=m +CONFIG_USB_SERIAL_QUATECH_USB2=m +CONFIG_VGASTATE=m +# CONFIG_VIDEO_DEV is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_WAN is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_WATCHDOG is not set +CONFIG_WIMAX_I2400M_SDIO=m +CONFIG_WIMAX_I2400M_USB=m --- linux-2.6.37.orig/debian.master/config/i386/config.common.i386 +++ linux-2.6.37/debian.master/config/i386/config.common.i386 @@ -0,0 +1,480 @@ +# +# Config options for config.common.i386 automatically generated by splitconfig.pl +# +# CONFIG_64BIT is not set +CONFIG_ACPI_BLACKLIST_YEAR=2000 +CONFIG_AIC79XX_RESET_DELAY_MS=5000 +CONFIG_ALIM7101_WDT=m +CONFIG_ARCH_DEFCONFIG="arch/x86/configs/i386_defconfig" +CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-ecx -fcall-saved-edx" +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SUPPORTS_MSI=y +CONFIG_ASUS_OLED=m +CONFIG_ASYNC_TX_DMA=y +CONFIG_ATALK=m +CONFIG_ATA_GENERIC=y +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_ATA_PIIX=y +CONFIG_ATH5K=m +CONFIG_ATM=m +# CONFIG_ATM_BR2684_IPFILTER is not set +# CONFIG_ATM_DUMMY is not set +# CONFIG_AUDIT_ARCH is not set +CONFIG_AX25_DAMA_SLAVE=y +CONFIG_B43=m +CONFIG_B43LEGACY=m +CONFIG_B44=m +CONFIG_BLK_DEV_DRBD=m +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_MD=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_DEV_SR=y +# CONFIG_BRCMFMAC is not set +CONFIG_BROADCOM_PHY=y +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_CDROM_PKTCDVD=y +CONFIG_CFG80211_REG_DEBUG=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y +CONFIG_CHR_DEV_SG=y +CONFIG_CICADA_PHY=y +CONFIG_CIFS_EXPERIMENTAL=y +CONFIG_CIFS_XATTR=y +CONFIG_COMEDI=m +CONFIG_CONNECTOR=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CRASH_DUMP=y +CONFIG_CRC_T10DIF=y +CONFIG_CRYPTO_CCM=m +CONFIG_CRYPTO_CTR=m +CONFIG_CRYPTO_DEV_HIFN_795X=m +CONFIG_CRYPTO_GCM=m +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_LZO=m +CONFIG_CRYPTO_SALSA20=m +CONFIG_CRYPTO_SEQIV=m +CONFIG_DAB=y +CONFIG_DAVICOM_PHY=y +CONFIG_DEBUG_INFO=y +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +CONFIG_DISPLAY_SUPPORT=m +# CONFIG_DL2K is not set +CONFIG_DMADEVICES=y +CONFIG_DM_MIRROR=y +CONFIG_DM_MULTIPATH=y +CONFIG_DM_RAID45=m +CONFIG_DM_SNAPSHOT=y +CONFIG_DRM_NOUVEAU=m +CONFIG_DRM_RADEON=m +CONFIG_DT3155=m +CONFIG_DVB_BUDGET_CORE=m +# CONFIG_DVB_FE_CUSTOMISE is not set +# CONFIG_DVB_USB_DIBUSB_MB_FAULTY is not set +# CONFIG_DVB_USB_EC168 is not set +CONFIG_ECHO=m +CONFIG_ENCLOSURE_SERVICES=m +CONFIG_ET131X=m +# CONFIG_EZX_PCAP is not set +CONFIG_FB_3DFX=m +CONFIG_FB_ATY=m +CONFIG_FB_ATY128=m +CONFIG_FB_BACKLIGHT=y +CONFIG_FB_BOOT_VESA_SUPPORT=y +CONFIG_FB_DDC=m +# CONFIG_FB_MACMODES is not set +CONFIG_FB_MATROX=m +CONFIG_FB_RADEON=m +CONFIG_FB_S1D13XXX=m +CONFIG_FB_SAVAGE=m +CONFIG_FB_SVGALIB=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_SYS_IMAGEBLIT=m +CONFIG_FB_TILEBLITTING=y +CONFIG_FB_UDL=m +CONFIG_FB_UVESA=m +CONFIG_FB_VESA=y +CONFIG_FB_VGA16=m +CONFIG_FB_VOODOO1=m +CONFIG_FIRMWARE_EDID=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_FONTS is not set +CONFIG_FSAM7400=m +CONFIG_FTL=m +CONFIG_FUNCTION_TRACER=y +# CONFIG_GENERIC_CPU is not set +CONFIG_GENERIC_IOMAP=y +# CONFIG_GENERIC_TIME_VSYSCALL is not set +CONFIG_GPIO_JANZ_TTL=m +CONFIG_GPIO_MAX732X=m +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_PCF857X=m +CONFIG_GPIO_PCH=m +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_TWL4030=m +CONFIG_GPIO_VX855=m +# CONFIG_HARDIRQS_SW_RESEND is not set +CONFIG_HAVE_AOUT=y +# CONFIG_HAVE_CPUMASK_OF_CPU_MAP is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_HAVE_GENERIC_HARDIRQS=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_HIGHMEM=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_HOTPLUG_PCI=y +CONFIG_HP_ILO=m +CONFIG_HUGETLB_PAGE=y +CONFIG_HWMON=y +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +CONFIG_I2C_ALGOBIT=m +CONFIG_I2C_GPIO=m +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_I801=m +CONFIG_ICPLUS_PHY=y +# CONFIG_IDE is not set +CONFIG_IDE_PHISON=m +CONFIG_IGB=m +CONFIG_IIO=m +CONFIG_ILLEGAL_POINTER_VALUE=0 +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_INTR_REMAP is not set +# CONFIG_IOMMU_API is not set +CONFIG_IPC_NS=y +CONFIG_IPMI_HANDLER=m +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPWIRELESS=m +CONFIG_IRDA=m +# CONFIG_IRQ_PER_CPU is not set +CONFIG_ISA=y +CONFIG_ISDN=y +CONFIG_IWL3945=m +CONFIG_IWL4965=y +CONFIG_IWMC3200TOP_DEBUGFS=y +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KGDB=y +CONFIG_KSM=y +CONFIG_KTIME_SCALAR=y +CONFIG_KVM=m +CONFIG_LAPBETHER=m +CONFIG_LATENCYTOP=y +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_PCA9532=m +CONFIG_LEDS_PCA955X=m +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m +CONFIG_LEDS_TRIGGER_HEARTBEAT=m +CONFIG_LEDS_TRIGGER_TIMER=m +CONFIG_LIBERTAS_MESH=y +CONFIG_LIBIPW_DEBUG=y +CONFIG_LINE6_USB=m +CONFIG_LLC=y +CONFIG_LLC2=m +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LSI_ET1011C_PHY=y +CONFIG_LXT_PHY=y +CONFIG_LZO_COMPRESS=y +CONFIG_M686=y +CONFIG_MACH_NO_WESTBRIDGE=y +CONFIG_MARVELL_PHY=y +CONFIG_MDIO_BITBANG=y +CONFIG_MDIO_GPIO=y +CONFIG_MEMSTICK=m +CONFIG_MFD_JANZ_CMODIO=m +# CONFIG_MFD_TMIO is not set +CONFIG_MMC=y +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_VSXXXAA=m +CONFIG_MOXA_SMARTIO=m +CONFIG_MTD=m +CONFIG_MTD_ABSENT=m +CONFIG_MTD_ALAUDA=m +CONFIG_MTD_AR7_PARTS=m +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_CFI=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_CHAR=m +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_CONCAT=m +CONFIG_MTD_DATAFLASH=m +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_GEN_PROBE=m +CONFIG_MTD_GPIO_ADDR=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_MTDRAM=m +CONFIG_MTD_NAND=m +CONFIG_MTD_NAND_ECC=m +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_NANDSIM=m +CONFIG_MTD_NAND_PLATFORM=m +CONFIG_MTD_ONENAND=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_PLATRAM=m +CONFIG_MTD_RAM=m +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_ROM=m +CONFIG_MTD_SLRAM=m +CONFIG_MTD_SM_COMMON=m +CONFIG_MTD_SST25L=m +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NATIONAL_PHY=y +# CONFIG_NEED_DMA_MAP_STATE is not set +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_TARGET_RATEEST=m +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +CONFIG_NET_CLS_CGROUP=y +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_DCCPPROBE=m +CONFIG_NET_POCKET=y +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_TCPPROBE=m +CONFIG_NFTL=m +CONFIG_NIU=m +CONFIG_NOP_USB_XCEIV=m +CONFIG_NORTEL_HERMES=m +CONFIG_NOZOMI=m +CONFIG_NO_HZ=y +CONFIG_NR_CPUS=8 +CONFIG_NVRAM=m +CONFIG_OUTPUT_FORMAT="elf32-i386" +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_PANEL=m +CONFIG_PARPORT=m +CONFIG_PATA_ALI=m +CONFIG_PATA_ARTOP=m +CONFIG_PATA_ATIIXP=m +CONFIG_PATA_CMD640_PCI=m +CONFIG_PATA_CMD64X=m +CONFIG_PATA_CS5530=m +CONFIG_PATA_CYPRESS=m +CONFIG_PATA_HPT366=m +CONFIG_PATA_HPT37X=m +CONFIG_PATA_HPT3X2N=m +CONFIG_PATA_HPT3X3=m +CONFIG_PATA_NS87410=m +CONFIG_PATA_NS87415=m +CONFIG_PATA_OPTI=m +CONFIG_PATA_OPTIDMA=m +CONFIG_PATA_PDC_OLD=m +CONFIG_PATA_RADISYS=m +CONFIG_PATA_SC1200=m +CONFIG_PATA_SIS=y +CONFIG_PCCARD=m +CONFIG_PCI_IOV=y +CONFIG_PCI_STUB=m +CONFIG_PDC_ADMA=y +CONFIG_PHYSICAL_ALIGN=0x100000 +CONFIG_PHYSICAL_START=0x100000 +CONFIG_PID_NS=y +CONFIG_PLX_HERMES=m +CONFIG_PM_DEBUG=y +CONFIG_POCH=m +CONFIG_POHMELFS=m +CONFIG_PPP=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_QSEMI_PHY=y +CONFIG_R3964=m +CONFIG_RCU_FANOUT=32 +CONFIG_REALTEK_PHY=y +CONFIG_REGULATOR_DEBUG=y +CONFIG_RELOCATABLE=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_RFD_FTL=m +CONFIG_RISCOM8=m +CONFIG_RT2800USB_UNKNOWN=y +# CONFIG_RT2X00_LIB_DEBUGFS is not set +CONFIG_RTC_DRV_CMOS=y +CONFIG_RTC_DRV_TEST=m +CONFIG_RTC_DRV_TWL4030=m +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTL8180=m +CONFIG_RTL8192E=m +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_SATA_SVW=m +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_TRACER=y +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_DH=y +CONFIG_SCSI_IPR=m +CONFIG_SCSI_ISCSITARGET=m +CONFIG_SCSI_MVSAS=m +CONFIG_SCSI_NSP32=m +CONFIG_SCSI_OSD_INITIATOR=m +CONFIG_SCSI_QLA_ISCSI=m +CONFIG_SENSORS_ADS7828=m +CONFIG_SENSORS_AK8975=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_PCI=y +# CONFIG_SERIAL_PMACZILOG is not set +CONFIG_SERIAL_UARTLITE=m +# CONFIG_SLAB is not set +CONFIG_SLHC=y +CONFIG_SLIP=m +CONFIG_SLUB=y +CONFIG_SMP=y +CONFIG_SMSC_PHY=y +CONFIG_SM_FTL=m +CONFIG_SND=m +CONFIG_SND_ALI5451=m +# CONFIG_SND_BT87X_OVERCLOCK is not set +CONFIG_SND_EMU10K1_SEQ=m +CONFIG_SND_HIFIER=m +# CONFIG_SND_MIXER_OSS is not set +CONFIG_SND_MPU401=m +CONFIG_SND_MTPAV=m +CONFIG_SND_OPL3_LIB_SEQ=m +CONFIG_SND_OPL4_LIB_SEQ=m +CONFIG_SND_OXYGEN=m +CONFIG_SND_PCM=m +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_RAWMIDI_SEQ=m +CONFIG_SND_SBAWE_SEQ=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_SOC=m +CONFIG_SND_SOC_I2C_AND_SPI=m +CONFIG_SND_SOC_TWL4030=m +CONFIG_SND_TIMER=m +CONFIG_SND_VIRTUOSO=m +CONFIG_SOUND=m +# CONFIG_SOUND_OSS_CORE is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_DESIGNWARE=y +CONFIG_SPI_SPIDEV=m +CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_STACK_TRACER=y +# CONFIG_STANDALONE is not set +CONFIG_STE10XP=y +CONFIG_SUNGEM=m +CONFIG_TABLET_USB_WACOM=m +CONFIG_TCG_TIS=m +CONFIG_TCG_TPM=m +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_THERMAL=y +CONFIG_TMD_HERMES=m +CONFIG_TPS65010=m +CONFIG_TRANZPORT=m +CONFIG_TTPCI_EEPROM=m +CONFIG_TUN=y +# CONFIG_TWL4030_CORE is not set +CONFIG_TWL4030_USB=m +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ET61X251=m +CONFIG_USB_GADGET=m +CONFIG_USB_GADGET_DUALSPEED=y +CONFIG_USB_GADGET_DUMMY_HCD=y +# CONFIG_USB_GADGET_GOKU is not set +# CONFIG_USB_GADGET_MUSB_HDRC is not set +# CONFIG_USB_GADGET_NET2280 is not set +CONFIG_USB_GPIO_VBUS=m +# CONFIG_USB_GSPCA_SN9C20X_EVDEV is not set +# CONFIG_USB_G_MULTI is not set +CONFIG_USB_IP_COMMON=m +CONFIG_USB_ISP1362_HCD=m +CONFIG_USB_MON=y +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_USB_NET_ZAURUS=m +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OTG is not set +CONFIG_USB_QUICKCAM_MESSENGER=m +CONFIG_USB_SERIAL_QUATECH2=m +CONFIG_USB_SERIAL_QUATECH_USB2=m +CONFIG_USB_SI470X=m +CONFIG_USB_SN9C102=m +CONFIG_USB_STKWEBCAM=m +CONFIG_USB_STV680=m +CONFIG_USB_UHCI_HCD=y +CONFIG_USB_ZC0301=m +CONFIG_USER_NS=y +CONFIG_UTS_NS=y +CONFIG_VGASTATE=m +CONFIG_VGA_CONSOLE=y +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m +# CONFIG_VIDEO_ADV7180 is not set +# CONFIG_VIDEO_ADV7343 is not set +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BT866=m +CONFIG_VIDEO_CPIA=m +CONFIG_VIDEO_CX25821=m +CONFIG_VIDEO_DEV=m +CONFIG_VIDEO_EM28XX_ALSA=m +CONFIG_VIDEO_GO7007=m +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_MT9V011=m +CONFIG_VIDEO_MXB=m +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_VIDEO_OVCAMCHIP=m +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_SAA7110=m +CONFIG_VIDEO_SAA7185=m +# CONFIG_VIDEO_SAA7191 is not set +# CONFIG_VIDEO_TCM825X is not set +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +# CONFIG_VIDEO_TDA9875 is not set +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +# CONFIG_VIDEO_THS7303 is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +CONFIG_VIDEO_TVAUDIO=m +# CONFIG_VIDEO_TVP514X is not set +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_VPX3220=m +CONFIG_VITESSE_PHY=y +CONFIG_VME_BUS=m +CONFIG_VME_CA91CX42=m +CONFIG_VME_TSI148=m +CONFIG_VT6656=m +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_W35UND=m +CONFIG_WAN=y +CONFIG_WAN_ROUTER=m +CONFIG_WATCHDOG=y +CONFIG_WIMAX_I2400M_SDIO=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_WM8350_WATCHDOG=m +CONFIG_X25_ASY=m +CONFIG_X86_32=y +# CONFIG_X86_64 is not set +CONFIG_X86_INTERNODE_CACHE_SHIFT=6 +CONFIG_X86_MINIMUM_CPU_FAMILY=5 +CONFIG_X86_SPEEDSTEP_LIB=y +# CONFIG_X86_X2APIC is not set +# CONFIG_ZONE_DMA32 is not set +CONFIG_ZONE_DMA_FLAG=1 --- linux-2.6.37.orig/debian.master/config/i386/config.flavour.generic +++ linux-2.6.37/debian.master/config/i386/config.flavour.generic @@ -0,0 +1,19 @@ +# +# Config options for config.flavour.generic automatically generated by splitconfig.pl +# +# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_HIGHMEM4G=y +# CONFIG_HIGHMEM64G is not set +CONFIG_INTEL_IDLE=y +# CONFIG_IOMMU_HELPER is not set +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_SYM53C8XX_2=m +# CONFIG_SYS_HYPERVISOR is not set +CONFIG_VIRTIO=m +CONFIG_VIRTIO_BLK=m +CONFIG_VIRTIO_NET=m +CONFIG_VIRTIO_PCI=m +CONFIG_VIRTIO_RING=m +# CONFIG_XEN_PRIVILEGED_GUEST is not set --- linux-2.6.37.orig/debian.master/config/i386/config.flavour.generic-pae +++ linux-2.6.37/debian.master/config/i386/config.flavour.generic-pae @@ -0,0 +1,21 @@ +# +# Config options for config.flavour.generic-pae automatically generated by splitconfig.pl +# +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +# CONFIG_HIGHMEM4G is not set +CONFIG_HIGHMEM64G=y +CONFIG_INTEL_IDLE=y +CONFIG_IOMMU_HELPER=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_SCSI_SPI_ATTRS=y +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SYS_HYPERVISOR=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_NET=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_RING=y +CONFIG_XEN_BLKDEV_FRONTEND=m +CONFIG_XEN_NETDEV_FRONTEND=m +CONFIG_XEN_PRIVILEGED_GUEST=y --- linux-2.6.37.orig/debian.master/config/i386/config.flavour.virtual +++ linux-2.6.37/debian.master/config/i386/config.flavour.virtual @@ -0,0 +1,21 @@ +# +# Config options for config.flavour.virtual automatically generated by splitconfig.pl +# +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +# CONFIG_HIGHMEM4G is not set +CONFIG_HIGHMEM64G=y +# CONFIG_INTEL_IDLE is not set +CONFIG_IOMMU_HELPER=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_SCSI_SPI_ATTRS=y +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SYS_HYPERVISOR=y +CONFIG_VIRTIO=y +CONFIG_VIRTIO_BLK=y +CONFIG_VIRTIO_NET=y +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_RING=y +CONFIG_XEN_BLKDEV_FRONTEND=y +CONFIG_XEN_NETDEV_FRONTEND=y +CONFIG_XEN_PRIVILEGED_GUEST=y --- linux-2.6.37.orig/debian.master/config/powerpc/config.common.powerpc +++ linux-2.6.37/debian.master/config/powerpc/config.common.powerpc @@ -0,0 +1,433 @@ +# +# Config options for config.common.powerpc automatically generated by splitconfig.pl +# +CONFIG_64BIT=y +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_ALIM7101_WDT is not set +CONFIG_APM_EMULATION=m +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SUPPORTS_MSI=y +# CONFIG_ASUS_OLED is not set +CONFIG_ATALK=m +CONFIG_ATA_GENERIC=m +CONFIG_ATA_PIIX=m +# CONFIG_ATH5K is not set +CONFIG_ATM=m +# CONFIG_ATM_BR2684_IPFILTER is not set +# CONFIG_ATM_DUMMY is not set +CONFIG_AUDIT_ARCH=y +# CONFIG_AX25_DAMA_SLAVE is not set +CONFIG_B43=m +CONFIG_B43LEGACY=m +CONFIG_B44=m +# CONFIG_BLK_DEV_DRBD is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_MD=m +CONFIG_BLK_DEV_SD=m +CONFIG_BLK_DEV_SR=m +# CONFIG_BRCMFMAC is not set +CONFIG_BROADCOM_PHY=m +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_CDROM_PKTCDVD=m +# CONFIG_CGROUP_CPUACCT is not set +CONFIG_CHR_DEV_SG=m +CONFIG_CICADA_PHY=m +# CONFIG_CIFS_EXPERIMENTAL is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_COMEDI is not set +CONFIG_CONNECTOR=m +CONFIG_CPU_FREQ_STAT=m +# CONFIG_CRASH_DUMP is not set +CONFIG_CRC_T10DIF=m +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_CRYPTO_GCM is not set +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEQIV is not set +# CONFIG_DAB is not set +CONFIG_DAVICOM_PHY=m +# CONFIG_DEBUG_INFO is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 +CONFIG_DISPLAY_SUPPORT=m +CONFIG_DL2K=m +# CONFIG_DMADEVICES is not set +CONFIG_DM_MIRROR=m +CONFIG_DM_MULTIPATH=m +# CONFIG_DM_RAID45 is not set +CONFIG_DM_SNAPSHOT=m +CONFIG_DRM_NOUVEAU=m +CONFIG_DRM_RADEON=m +# CONFIG_DVB_BUDGET_CORE is not set +# CONFIG_DVB_FE_CUSTOMISE is not set +CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y +# CONFIG_DVB_USB_EC168 is not set +# CONFIG_ECHO is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_ET131X is not set +# CONFIG_EZX_PCAP is not set +CONFIG_FB_3DFX=y +CONFIG_FB_ATY=y +CONFIG_FB_ATY128=y +CONFIG_FB_BACKLIGHT=y +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_DDC=y +CONFIG_FB_MACMODES=y +CONFIG_FB_MATROX=y +CONFIG_FB_RADEON=y +CONFIG_FB_S1D13XXX=m +CONFIG_FB_SAVAGE=m +CONFIG_FB_SVGALIB=m +CONFIG_FB_TILEBLITTING=y +# CONFIG_FB_UDL is not set +CONFIG_FB_UVESA=m +# CONFIG_FB_VGA16 is not set +CONFIG_FB_VOODOO1=y +CONFIG_FIRMWARE_EDID=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_FONTS is not set +# CONFIG_FSAM7400 is not set +CONFIG_FTL=m +CONFIG_FUNCTION_TRACER=y +# CONFIG_GENERIC_IOMAP is not set +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIO_JANZ_TTL=m +CONFIG_GPIO_MAX732X=m +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_PCF857X=m +CONFIG_GPIO_PCH=m +# CONFIG_GPIO_SYSFS is not set +CONFIG_GPIO_TWL4030=m +CONFIG_GPIO_VX855=m +# CONFIG_HAVE_AOUT is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +# CONFIG_HAVE_GENERIC_HARDIRQS is not set +CONFIG_HIGHMEM=y +CONFIG_HIGH_RES_TIMERS=y +# CONFIG_HOTPLUG_PCI is not set +CONFIG_HWMON=y +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +CONFIG_I2C_ALGOBIT=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_I801=m +CONFIG_ICPLUS_PHY=m +CONFIG_IDE=y +# CONFIG_IDE_PHISON is not set +# CONFIG_IGB is not set +# CONFIG_IIO is not set +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_IOMMU_HELPER=y +# CONFIG_IPC_NS is not set +CONFIG_IPMI_HANDLER=m +# CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPWIRELESS is not set +CONFIG_IRDA=m +CONFIG_IRQ_PER_CPU=y +# CONFIG_ISA is not set +# CONFIG_ISDN is not set +# CONFIG_IWL3945 is not set +# CONFIG_IWL4965 is not set +CONFIG_IWMC3200TOP_DEBUGFS=y +CONFIG_KEYBOARD_LKKBD=m +CONFIG_KEYBOARD_NEWTON=m +CONFIG_KEYBOARD_SUNKBD=m +CONFIG_KEYBOARD_XTKBD=m +CONFIG_KSM=y +CONFIG_KVM=y +CONFIG_LAPBETHER=m +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_PCA955X is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LIBERTAS_MESH=y +# CONFIG_LIBIPW_DEBUG is not set +# CONFIG_LINE6_USB is not set +CONFIG_LLC=y +CONFIG_LLC2=m +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_LSI_ET1011C_PHY=m +CONFIG_LXT_PHY=m +CONFIG_LZO_COMPRESS=y +CONFIG_MACH_NO_WESTBRIDGE=y +CONFIG_MARVELL_PHY=m +CONFIG_MDIO_BITBANG=m +CONFIG_MDIO_GPIO=m +CONFIG_MEMORY_HOTPLUG=y +# CONFIG_MEMORY_HOTREMOVE is not set +# CONFIG_MEMSTICK is not set +CONFIG_MFD_JANZ_CMODIO=m +# CONFIG_MFD_TMIO is not set +CONFIG_MMC=m +CONFIG_MMC_BLOCK=m +CONFIG_MMC_SDHCI=m +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_VSXXXAA=m +# CONFIG_MOXA_SMARTIO is not set +CONFIG_MTD=m +CONFIG_MTD_ABSENT=m +CONFIG_MTD_ALAUDA=m +CONFIG_MTD_AR7_PARTS=m +CONFIG_MTD_BLKDEVS=m +CONFIG_MTD_BLOCK=m +CONFIG_MTD_CFI=m +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_AMDSTD=m +CONFIG_MTD_CFI_INTELEXT=m +CONFIG_MTD_CFI_STAA=m +CONFIG_MTD_CFI_UTIL=m +CONFIG_MTD_CHAR=m +CONFIG_MTD_COMPLEX_MAPPINGS=y +CONFIG_MTD_CONCAT=m +CONFIG_MTD_DATAFLASH=m +CONFIG_MTD_DOC2000=m +CONFIG_MTD_DOC2001=m +CONFIG_MTD_DOC2001PLUS=m +CONFIG_MTD_GEN_PROBE=m +CONFIG_MTD_GPIO_ADDR=m +CONFIG_MTD_JEDECPROBE=m +CONFIG_MTD_MTDRAM=m +CONFIG_MTD_NAND=m +CONFIG_MTD_NAND_ECC=m +CONFIG_MTD_NAND_IDS=m +CONFIG_MTD_NAND_NANDSIM=m +CONFIG_MTD_NAND_PLATFORM=m +CONFIG_MTD_ONENAND=m +CONFIG_MTD_PHRAM=m +CONFIG_MTD_PHYSMAP=m +CONFIG_MTD_PLATRAM=m +CONFIG_MTD_RAM=m +CONFIG_MTD_REDBOOT_PARTS=m +CONFIG_MTD_ROM=m +CONFIG_MTD_SLRAM=m +CONFIG_MTD_SM_COMMON=m +CONFIG_MTD_SST25L=m +CONFIG_NATIONAL_PHY=m +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set +CONFIG_NET_CLS_CGROUP=y +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_U32=m +CONFIG_NET_DCCPPROBE=m +CONFIG_NET_POCKET=y +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_TCPPROBE=m +CONFIG_NFTL=m +# CONFIG_NIU is not set +CONFIG_NODES_SHIFT=8 +CONFIG_NOP_USB_XCEIV=m +# CONFIG_NORTEL_HERMES is not set +# CONFIG_NOZOMI is not set +CONFIG_NO_HZ=y +CONFIG_NVRAM=y +# CONFIG_PANEL is not set +CONFIG_PARPORT=m +# CONFIG_PATA_ALI is not set +# CONFIG_PATA_ARTOP is not set +# CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD640_PCI is not set +# CONFIG_PATA_CMD64X is not set +# CONFIG_PATA_CS5530 is not set +# CONFIG_PATA_CYPRESS is not set +# CONFIG_PATA_HPT366 is not set +# CONFIG_PATA_HPT37X is not set +# CONFIG_PATA_HPT3X2N is not set +# CONFIG_PATA_HPT3X3 is not set +# CONFIG_PATA_NS87410 is not set +# CONFIG_PATA_NS87415 is not set +# CONFIG_PATA_OPTI is not set +# CONFIG_PATA_OPTIDMA is not set +# CONFIG_PATA_PDC_OLD is not set +# CONFIG_PATA_RADISYS is not set +# CONFIG_PATA_SC1200 is not set +CONFIG_PATA_SIS=m +CONFIG_PCCARD=m +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_STUB is not set +CONFIG_PCI_SYSCALL=y +CONFIG_PDC_ADMA=m +CONFIG_PHYSICAL_START=0x00000000 +# CONFIG_PID_NS is not set +# CONFIG_PLX_HERMES is not set +# CONFIG_PM_DEBUG is not set +# CONFIG_POHMELFS is not set +CONFIG_PPP=m +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_VOLUNTARY=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_QSEMI_PHY=m +CONFIG_R3964=m +# CONFIG_REALTEK_PHY is not set +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_RELOCATABLE is not set +# CONFIG_RESOURCE_COUNTERS is not set +CONFIG_RFD_FTL=m +CONFIG_RT2800USB_UNKNOWN=y +# CONFIG_RT2X00_LIB_DEBUGFS is not set +CONFIG_RTC_DRV_CMOS=m +# CONFIG_RTC_DRV_TEST is not set +CONFIG_RTC_DRV_TWL4030=m +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +# CONFIG_RTL8180 is not set +# CONFIG_RTL8192E is not set +CONFIG_SATA_SVW=y +# CONFIG_SCHED_TRACER is not set +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_DH=m +# CONFIG_SCSI_IPR is not set +CONFIG_SCSI_ISCSITARGET=m +# CONFIG_SCSI_MVSAS is not set +CONFIG_SCSI_NSP32=m +CONFIG_SCSI_OSD_INITIATOR=m +# CONFIG_SCSI_QLA_ISCSI is not set +CONFIG_SCSI_SPI_ATTRS=m +CONFIG_SCSI_SYM53C8XX_2=m +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_W83L786NG is not set +CONFIG_SERIAL_8250=m +CONFIG_SERIAL_8250_PCI=m +CONFIG_SERIAL_PMACZILOG=y +CONFIG_SERIAL_UARTLITE=m +# CONFIG_SLAB is not set +CONFIG_SLHC=m +CONFIG_SLIP=m +CONFIG_SLUB=y +CONFIG_SMSC_PHY=m +# CONFIG_SM_FTL is not set +CONFIG_SND=m +CONFIG_SND_ALI5451=m +CONFIG_SND_BT87X_OVERCLOCK=y +CONFIG_SND_EMU10K1_SEQ=m +# CONFIG_SND_HIFIER is not set +# CONFIG_SND_MIXER_OSS is not set +CONFIG_SND_MPU401=m +CONFIG_SND_MTPAV=m +CONFIG_SND_OPL3_LIB_SEQ=m +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_OXYGEN is not set +CONFIG_SND_PCM=m +# CONFIG_SND_PCM_OSS is not set +CONFIG_SND_RAWMIDI_SEQ=m +# CONFIG_SND_SBAWE_SEQ is not set +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_SOC=m +CONFIG_SND_SOC_I2C_AND_SPI=m +CONFIG_SND_SOC_TWL4030=m +CONFIG_SND_TIMER=m +# CONFIG_SND_VIRTUOSO is not set +CONFIG_SOUND=m +# CONFIG_SOUND_OSS_CORE is not set +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_DESIGNWARE=y +CONFIG_SPI_SPIDEV=m +CONFIG_SSB_B43_PCI_BRIDGE=y +# CONFIG_STACK_TRACER is not set +CONFIG_STANDALONE=y +CONFIG_STE10XP=m +CONFIG_SUNGEM=m +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_TABLET_USB_WACOM is not set +# CONFIG_TCG_TIS is not set +CONFIG_TCG_TPM=m +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_THERMAL is not set +# CONFIG_TMD_HERMES is not set +# CONFIG_TRANZPORT is not set +CONFIG_TTPCI_EEPROM=m +CONFIG_TUN=y +CONFIG_TWL4030_CORE=y +CONFIG_TWL4030_USB=m +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_ET61X251=m +CONFIG_USB_GADGET=m +# CONFIG_USB_GADGET_DUMMY_HCD is not set +CONFIG_USB_GPIO_VBUS=m +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_IP_COMMON is not set +CONFIG_USB_ISP1362_HCD=m +CONFIG_USB_MON=y +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_USB_NET_ZAURUS is not set +CONFIG_USB_OHCI_BIG_ENDIAN_DESC=y +CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_SERIAL_QUATECH2 is not set +# CONFIG_USB_SERIAL_QUATECH_USB2 is not set +# CONFIG_USB_SI470X is not set +CONFIG_USB_SN9C102=m +# CONFIG_USB_STKWEBCAM is not set +CONFIG_USB_UHCI_HCD=y +# CONFIG_USER_NS is not set +# CONFIG_UTS_NS is not set +CONFIG_VGASTATE=m +# CONFIG_VGA_CONSOLE is not set +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m +CONFIG_VIDEO_ADV7180=m +CONFIG_VIDEO_ADV7343=m +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BT866=m +CONFIG_VIDEO_CPIA=m +# CONFIG_VIDEO_CX25821 is not set +CONFIG_VIDEO_DEV=m +# CONFIG_VIDEO_EM28XX_ALSA is not set +# CONFIG_VIDEO_GO7007 is not set +# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_MT9V011=m +# CONFIG_VIDEO_MXB is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m +CONFIG_VIDEO_SAA6588=m +CONFIG_VIDEO_SAA7110=m +CONFIG_VIDEO_SAA7185=m +CONFIG_VIDEO_SAA7191=m +CONFIG_VIDEO_TCM825X=m +CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TDA9875=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m +CONFIG_VIDEO_THS7303=m +CONFIG_VIDEO_TLV320AIC23B=m +CONFIG_VIDEO_TVAUDIO=m +CONFIG_VIDEO_TVP514X=m +CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_VPX3220=m +CONFIG_VIRTIO=m +CONFIG_VIRTIO_BLK=m +CONFIG_VIRTIO_NET=m +CONFIG_VIRTIO_PCI=m +CONFIG_VIRTIO_RING=m +CONFIG_VITESSE_PHY=m +# CONFIG_VME_BUS is not set +# CONFIG_VT6656 is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_W35UND is not set +CONFIG_WAN=y +CONFIG_WAN_ROUTER=m +CONFIG_WATCHDOG=y +CONFIG_WIMAX_I2400M_SDIO=m +CONFIG_WIMAX_I2400M_USB=m +CONFIG_WM8350_WATCHDOG=m +CONFIG_X25_ASY=m +CONFIG_ZONE_DMA_FLAG=1 --- linux-2.6.37.orig/debian.master/config/powerpc/config.flavour.powerpc +++ linux-2.6.37/debian.master/config/powerpc/config.flavour.powerpc @@ -0,0 +1,44 @@ +# +# Config options for config.flavour.powerpc automatically generated by splitconfig.pl +# +# CONFIG_ARCH_NO_VIRT_TO_BUS is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CRYPTO_LZO=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_SYS_IMAGEBLIT=m +CONFIG_FORCE_MAX_ZONEORDER=11 +# CONFIG_GENERIC_TBSYNC is not set +# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set +CONFIG_HP_ILO=m +# CONFIG_HUGETLB_PAGE is not set +CONFIG_I2C_GPIO=m +CONFIG_KERNEL_START=0xc0000000 +CONFIG_KGDB=y +CONFIG_LATENCYTOP=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_MAX_ACTIVE_REGIONS=32 +# CONFIG_MMIO_NVRAM is not set +# CONFIG_MPIC_U3_HT_IRQS is not set +# CONFIG_MUTEX_SPIN_ON_OWNER is not set +# CONFIG_NEED_DMA_MAP_STATE is not set +# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set +CONFIG_PAGE_OFFSET=0xc0000000 +# CONFIG_PHYS_ADDR_T_64BIT is not set +# CONFIG_PPC64 is not set +# CONFIG_PPC_970_NAP is not set +# CONFIG_PPC_CELL is not set +CONFIG_PPC_INDIRECT_PCI=y +# CONFIG_PPC_MM_SLICES is not set +CONFIG_PPC_MPC106=y +CONFIG_RISCOM8=m +CONFIG_SCHEDSTATS=y +# CONFIG_SMP is not set +CONFIG_TPS65010=m +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_GADGET_GOKU is not set +CONFIG_USB_GADGET_NET2280=y +CONFIG_WORD_SIZE=32 --- linux-2.6.37.orig/debian.master/config/powerpc/config.flavour.powerpc-smp +++ linux-2.6.37/debian.master/config/powerpc/config.flavour.powerpc-smp @@ -0,0 +1,46 @@ +# +# Config options for config.flavour.powerpc-smp automatically generated by splitconfig.pl +# +# CONFIG_ARCH_NO_VIRT_TO_BUS is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +# CONFIG_ATA_NONSTANDARD is not set +CONFIG_CFG80211_REG_DEBUG=y +CONFIG_CRYPTO_LZO=m +CONFIG_FB_SYS_COPYAREA=m +CONFIG_FB_SYS_FILLRECT=m +CONFIG_FB_SYS_FOPS=m +CONFIG_FB_SYS_IMAGEBLIT=m +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_GENERIC_TBSYNC=y +# CONFIG_HAVE_SETUP_PER_CPU_AREA is not set +# CONFIG_HP_ILO is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_I2C_GPIO=m +CONFIG_KERNEL_START=0xc0000000 +# CONFIG_KGDB is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set +CONFIG_MAX_ACTIVE_REGIONS=32 +# CONFIG_MMIO_NVRAM is not set +# CONFIG_MPIC_U3_HT_IRQS is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +# CONFIG_NEED_DMA_MAP_STATE is not set +# CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK is not set +CONFIG_NR_CPUS=4 +CONFIG_PAGE_OFFSET=0xc0000000 +# CONFIG_PHYS_ADDR_T_64BIT is not set +# CONFIG_PPC64 is not set +# CONFIG_PPC_970_NAP is not set +# CONFIG_PPC_CELL is not set +CONFIG_PPC_INDIRECT_PCI=y +# CONFIG_PPC_MM_SLICES is not set +CONFIG_PPC_MPC106=y +CONFIG_RCU_FANOUT=32 +# CONFIG_RISCOM8 is not set +# CONFIG_SCHEDSTATS is not set +CONFIG_SMP=y +# CONFIG_TPS65010 is not set +# CONFIG_USB_GADGET_DUALSPEED is not set +CONFIG_USB_GADGET_GOKU=y +# CONFIG_USB_GADGET_NET2280 is not set +CONFIG_WORD_SIZE=32 --- linux-2.6.37.orig/debian.master/config/powerpc/config.flavour.powerpc64-smp +++ linux-2.6.37/debian.master/config/powerpc/config.flavour.powerpc64-smp @@ -0,0 +1,46 @@ +# +# Config options for config.flavour.powerpc64-smp automatically generated by splitconfig.pl +# +CONFIG_ARCH_NO_VIRT_TO_BUS=y +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_ATA_NONSTANDARD=y +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CRYPTO_LZO=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_FOPS=y +CONFIG_FB_SYS_IMAGEBLIT=y +CONFIG_FORCE_MAX_ZONEORDER=13 +CONFIG_GENERIC_TBSYNC=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_HP_ILO=m +CONFIG_HUGETLB_PAGE=y +# CONFIG_I2C_GPIO is not set +CONFIG_KERNEL_START=0xc000000000000000 +CONFIG_KGDB=y +CONFIG_LATENCYTOP=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=m +CONFIG_MAX_ACTIVE_REGIONS=256 +CONFIG_MMIO_NVRAM=y +CONFIG_MPIC_U3_HT_IRQS=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NR_CPUS=1024 +CONFIG_PAGE_OFFSET=0xc000000000000000 +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PPC64=y +CONFIG_PPC_970_NAP=y +CONFIG_PPC_CELL=y +# CONFIG_PPC_INDIRECT_PCI is not set +CONFIG_PPC_MM_SLICES=y +# CONFIG_PPC_MPC106 is not set +CONFIG_RCU_FANOUT=64 +CONFIG_RISCOM8=m +CONFIG_SCHEDSTATS=y +CONFIG_SMP=y +# CONFIG_TPS65010 is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_GADGET_GOKU is not set +CONFIG_USB_GADGET_NET2280=y +CONFIG_WORD_SIZE=64 --- linux-2.6.37.orig/debian.master/control.d/flavour-control.stub +++ linux-2.6.37/debian.master/control.d/flavour-control.stub @@ -0,0 +1,77 @@ +# Items that get replaced: +# FLAVOUR +# DESC +# ARCH +# SUPPORTED +# TARGET +# BOOTLOADER +# =PROVIDES= +# +# Items marked with =FOO= are optional +# +# This file describes the template for packages that are created for each flavour +# in debian/control.d/vars.* +# +# This file gets edited in a couple of places. See the debian/control.stub rule in +# debian/rules. PGGVER, ABINUM, and SRCPKGNAME are all converted in the +# process of creating debian/control. +# +# The flavour specific strings (ARCH, DESC, etc) are converted using values from the various +# flavour files in debian/control.d/vars.* +# +# XXX: Leave the blank line before the first package!! + +Package: linux-image-PKGVER-ABINUM-FLAVOUR +Architecture: ARCH +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, =PROVIDES= +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: BOOTLOADER +Suggests: fdutils, SRCPKGNAME-doc-PKGVER | SRCPKGNAME-source-PKGVER, SRCPKGNAME-tools +Description: Linux kernel image for version PKGVER on DESC + This package contains the Linux kernel image for version PKGVER on + DESC. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports SUPPORTED processors. + . + TARGET + . + You likely do not want to install this package directly. Instead, install + the linux-FLAVOUR meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-PKGVER-ABINUM-FLAVOUR +Architecture: ARCH +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), SRCPKGNAME-headers-PKGVER-ABINUM, ${shlibs:Depends} +Provides: SRCPKGNAME-headers, SRCPKGNAME-headers-2.6 +Description: Linux kernel headers for version PKGVER on DESC + This package provides kernel header files for version PKGVER on + DESC. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/SRCPKGNAME-headers-PKGVER-ABINUM/debian.README.gz for details. + +Package: linux-image-PKGVER-ABINUM-FLAVOUR-dbgsym +Architecture: ARCH +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version PKGVER on DESC + This package provides a kernel debug image for version PKGVER on + DESC. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. --- linux-2.6.37.orig/debian.master/control.d/vars.generic +++ linux-2.6.37/debian.master/control.d/vars.generic @@ -0,0 +1,6 @@ +arch="i386 amd64" +supported="Generic" +target="Geared toward desktop systems." +desc="x86/x86_64" +bootloader="grub-pc | grub | lilo (>= 19.1)" +provides="kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9" --- linux-2.6.37.orig/debian.master/control.d/vars.generic-pae +++ linux-2.6.37/debian.master/control.d/vars.generic-pae @@ -0,0 +1,6 @@ +arch="i386" +supported="Generic" +target="Geared toward 32 bit desktop systems with more then 4GB RAM." +desc="x86" +bootloader="grub-pc | grub | lilo (>= 19.1)" +provides="kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9" --- linux-2.6.37.orig/debian.master/control.d/vars.omap +++ linux-2.6.37/debian.master/control.d/vars.omap @@ -0,0 +1,8 @@ +arch="armel" +supported="TI OMAP3" +desc="TI OMAP3-based systems" +target="Targeted towards boards such as Beagleboard, Gumstix, IGEPv2, etc." +bootloader="flash-kernel" +provides="" +section_image="universe/base" +do_debug="Yes" --- linux-2.6.37.orig/debian.master/control.d/vars.powerpc +++ linux-2.6.37/debian.master/control.d/vars.powerpc @@ -0,0 +1,6 @@ +supported="32-bit PowerPC" +target="Geared toward desktop or server systems." +desc="32-bit PowerPC" +bootloader="yaboot" +provides="redhat-cluster-modules, ivtv-modules" +arch="powerpc" --- linux-2.6.37.orig/debian.master/control.d/vars.powerpc-smp +++ linux-2.6.37/debian.master/control.d/vars.powerpc-smp @@ -0,0 +1,6 @@ +supported="32-bit PowerPC SMP" +target="Geared toward desktop or server systems." +desc="32-bit PowerPC SMP" +bootloader="yaboot" +provides="redhat-cluster-modules, ivtv-modules" +arch="powerpc" --- linux-2.6.37.orig/debian.master/control.d/vars.powerpc64-smp +++ linux-2.6.37/debian.master/control.d/vars.powerpc64-smp @@ -0,0 +1,6 @@ +supported="64-bit PowerPC SMP" +target="Geared toward desktop or server systems." +desc="64-bit PowerPC SMP" +bootloader="yaboot" +provides="redhat-cluster-modules, ivtv-modules" +arch="powerpc" --- linux-2.6.37.orig/debian.master/control.d/vars.server +++ linux-2.6.37/debian.master/control.d/vars.server @@ -0,0 +1,6 @@ +arch="amd64" +supported="Server" +target="Geared toward 64 bit server systems." +desc="x86_64" +bootloader="grub-pc | grub | lilo (>= 19.1)" +provides="redhat-cluster-modules, kvm-api-4, ivtv-modules, ndiswrapper-modules-1.9" --- linux-2.6.37.orig/debian.master/control.d/vars.versatile +++ linux-2.6.37/debian.master/control.d/vars.versatile @@ -0,0 +1,8 @@ +arch="armel" +supported="Versatile" +desc="Versatile-based systems" +target="PB, AB, Qemu, etc." +bootloader="" +provides="" +section_image="universe/base" +do_debug="Yes" --- linux-2.6.37.orig/debian.master/control.d/vars.virtual +++ linux-2.6.37/debian.master/control.d/vars.virtual @@ -0,0 +1,6 @@ +arch="i386 amd64" +supported="Virtual" +target="Geared toward virtual appliances." +desc="x86/x86_64" +bootloader="grub-pc | grub | lilo (>= 19.1)" +provides="kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9" --- linux-2.6.37.orig/debian.master/control.d/virtual.inclusion-list +++ linux-2.6.37/debian.master/control.d/virtual.inclusion-list @@ -0,0 +1,140 @@ +arch/*/{crypto,kernel,oprofile} +crypto/* +drivers/acpi/* +drivers/ata/ahci.ko +drivers/block/nbd.ko +drivers/block/floppy.ko +drivers/block/cryptoloop.ko +drivers/block/xen-blkfront.ko +drivers/char/hangcheck-timer.ko +drivers/char/lp.ko +drivers/char/nvram.ko +drivers/char/ppdev.ko +drivers/char/raw.ko +drivers/input/evbug.ko +drivers/input/gameport/gameport.ko +drivers/input/mouse/psmouse.ko +drivers/input/serio/serio_raw.ko +drivers/input/serio/serport.ko +drivers/input/joydev.ko +drivers/input/misc/uinput.ko +drivers/input/touchscreen/usbtouchscreen.ko +drivers/input/xen-kbdfront.ko +drivers/md/* +drivers/message/fusion* +drivers/misc/vmw_balloon.ko +drivers/net/8390.ko +drivers/net/8139too.ko +drivers/net/8139cp.ko +drivers/net/appletalk/ipddp.ko +drivers/net/bonding/bonding.ko +drivers/net/bsd_comp.ko +drivers/net/dummy.ko +drivers/net/e1000/e1000.ko +drivers/net/e1000e/e1000e.ko +drivers/net/eql.ko +drivers/net/ifb.ko +drivers/net/mii.ko +drivers/net/ne2k-pci.ko +drivers/net/netconsole.ko +drivers/net/pcnet32.ko +drivers/net/ppp_async.ko +drivers/net/ppp_deflate.ko +drivers/net/ppp_mppe.ko +drivers/net/pppoe.ko +drivers/net/pppol2tp.ko +drivers/net/pppox.ko +drivers/net/ppp_synctty.ko +drivers/net/slip.ko +drivers/net/veth.ko +drivers/net/vmxnet3/vmxnet3.ko +drivers/net/xen-netfront.ko +drivers/parport/parport.ko +drivers/parport/parport_pc.ko +drivers/pci/hotplug/acpiphp.ko +drivers/net/tulip/tulip.ko +drivers/scsi/BusLogic.ko +drivers/scsi/iscsi_tcp.ko +drivers/scsi/libiscsi.ko +drivers/scsi/libiscsi_tcp.ko +drivers/scsi/libsas/* +drivers/scsi/libsas/libsas.ko +drivers/scsi/qla1280.ko +drivers/scsi/raid_class.ko +drivers/scsi/scsi_transport_fc.ko +drivers/scsi/scsi_transport_iscsi.ko +drivers/scsi/scsi_transport_sas.ko +drivers/scsi/scsi_wait_scan.ko +drivers/scsi/scsi_tgt.ko +drivers/scsi/vmw_pvscsi.ko +drivers/usb/storage/usb-storage.ko +drivers/video/cirrusfb.ko +drivers/video/output.ko +drivers/video/syscopyarea.ko +drivers/video/sysfillrect.ko +drivers/video/sysimgblt.ko +drivers/video/vesafb.ko +drivers/video/vga16fb.ko +drivers/video/vgastate.ko +drivers/video/xen-fbfront.ko +drivers/video/fb_sys_fops.ko +drivers/virtio/virtio_balloon.ko +drivers/watchdog/softdog.ko +drivers/xen/* +fs/binfmt_misc.ko +fs/btrfs/* +fs/configfs/* +fs/exportfs/* +fs/fat/* +fs/isofs/* +fs/cifs/* +fs/xfs/* +fs/ufs/* +fs/smbfs/* +fs/squashfs/* +fs/nfs/* +fs/nfsd/* +fs/nfs_common/* +fs/fscache/* +fs/lockd/* +fs/autofs4/autofs4.ko +lib/* +net/802/* +net/8021q/* +net/appletalk/* +net/atm/* +net/ax25/* +net/bridge/* +net/can/* +net/core/* +net/dccp/* +net/decnet/* +net/econet/* +net/ieee802154/* +net/ipv4/* +net/ipv6/* +net/ipx/* +net/irda/* +net/key/* +net/lapb/* +net/llc/* +net/mac80211/* +net/netfilter/* +net/netrom/* +net/phonet/* +net/rose/* +net/rxrpc/* +net/sched/* +net/sctp/* +net/tipc/* +net/wanrouter/* +net/wireless/* +net/x25/* +net/xfrm/* +net/sunrpc/auth_gss/auth_rpcgss.ko +net/sunrpc/sunrpc.ko +sound/soundcore.ko +sound/core/* +sound/pci/snd-ens1370.ko +sound/drivers/pcsp/snd-pcsp.ko +ubuntu/iscsitarget/iscsi_trgt.ko --- linux-2.6.37.orig/debian.master/d-i/exclude-firmware.armel-omap +++ linux-2.6.37/debian.master/d-i/exclude-firmware.armel-omap @@ -0,0 +1,2 @@ +nic-modules +scsi-modules --- linux-2.6.37.orig/debian.master/d-i/exclude-modules.amd64-virtual +++ linux-2.6.37/debian.master/d-i/exclude-modules.amd64-virtual @@ -0,0 +1,11 @@ +pata-modules +serial-modules +firewire-core-modules +plip-modules +usb-modules +pcmcia-storage-modules +input-modules +nic-pcmcia-modules +pcmcia-modules +nic-usb-modules +nfs-modules --- linux-2.6.37.orig/debian.master/d-i/exclude-modules.armel-omap +++ linux-2.6.37/debian.master/d-i/exclude-modules.armel-omap @@ -0,0 +1,10 @@ +serial-modules +firewire-core-modules +floppy-modules +pcmcia-storage-modules +fb-modules +nic-pcmcia-modules +pcmcia-modules +pata-modules +message-modules +virtio-modules --- linux-2.6.37.orig/debian.master/d-i/exclude-modules.armel-versatile +++ linux-2.6.37/debian.master/d-i/exclude-modules.armel-versatile @@ -0,0 +1,19 @@ +crypto-modules +fb-modules +fs-core-modules +fs-secondary-modules +nic-modules +nic-pcmcia-modules +nic-usb-modules +scsi-modules +storage-core-modules +nfs-modules +pcmcia-modules +parport-modules +serial-modules +plip-modules +pcmcia-storage-modules +mouse-modules +irda-modules +floppy-modules +virtio-modules --- linux-2.6.37.orig/debian.master/d-i/exclude-modules.i386-virtual +++ linux-2.6.37/debian.master/d-i/exclude-modules.i386-virtual @@ -0,0 +1,11 @@ +pata-modules +serial-modules +firewire-core-modules +plip-modules +usb-modules +pcmcia-storage-modules +input-modules +nic-pcmcia-modules +pcmcia-modules +nic-usb-modules +nfs-modules --- linux-2.6.37.orig/debian.master/d-i/exclude-modules.ia64 +++ linux-2.6.37/debian.master/d-i/exclude-modules.ia64 @@ -0,0 +1,4 @@ +irda-modules +floppy-modules +fb-modules +virtio-modules --- linux-2.6.37.orig/debian.master/d-i/exclude-modules.powerpc +++ linux-2.6.37/debian.master/d-i/exclude-modules.powerpc @@ -0,0 +1,4 @@ +efi-modules +fb-modules +acpi-modules +virtio-modules --- linux-2.6.37.orig/debian.master/d-i/exclude-modules.sparc +++ linux-2.6.37/debian.master/d-i/exclude-modules.sparc @@ -0,0 +1,9 @@ +efi-modules +nic-pcmcia-modules +pcmcia-modules +pcmcia-storage-modules +irda-modules +floppy-modules +fb-modules +acpi-modules +virtio-modules --- linux-2.6.37.orig/debian.master/d-i/kernel-versions.in +++ linux-2.6.37/debian.master/d-i/kernel-versions.in @@ -0,0 +1,15 @@ +# arch version flavour installedname suffix bdep +amd64 PKGVER-ABINUM generic PKGVER-ABINUM-generic - +amd64 PKGVER-ABINUM virtual PKGVER-ABINUM-virtual - + +i386 PKGVER-ABINUM generic PKGVER-ABINUM-generic - +i386 PKGVER-ABINUM generic-pae PKGVER-ABINUM-generic-pae - +i386 PKGVER-ABINUM virtual PKGVER-ABINUM-virtual - + +armel PKGVER-ABINUM versatile PKGVER-ABINUM-versatile - +armel PKGVER-ABINUM omap PKGVER-ABINUM-omap - + +# Ports +# arch version flavour installedname suffix bdep +powerpc PKGVER-ABINUM powerpc PKGVER-ABINUM-powerpc - +powerpc PKGVER-ABINUM powerpc64-smp PKGVER-ABINUM-powerpc64-smp - --- linux-2.6.37.orig/debian.master/d-i/package-list +++ linux-2.6.37/debian.master/d-i/package-list @@ -0,0 +1,185 @@ +Package: kernel-image + +Package: fat-modules +Depends: kernel-image +Priority: standard +Description: FAT filesystem support + This includes Windows FAT and VFAT support. + +Package: fb-modules +Depends: kernel-image +Priority: standard +Description: Framebuffer modules + +Package: firewire-core-modules +Depends: kernel-image, storage-core-modules +Priority: standard +Description: Firewire (IEEE-1394) Support + +Package: floppy-modules +Depends: kernel-image +Priority: standard +Description: Floppy driver support + +Package: fs-core-modules +Depends: kernel-image +Priority: standard +Provides: jfs-modules, reiserfs-modules, xfs-modules +Description: Base filesystem modules + This includes jfs, reiserfs and xfs. + +Package: fs-secondary-modules +Depends: kernel-image, fat-modules +Priority: standard +Provides: ntfs-modules, hfs-modules +Description: Extra filesystem modules + This includes support for Windows NTFS and MacOS HFS/HFSPlus + +Package: input-modules +Depends: kernel-image, usb-modules +Priority: standard +Description: Support for various input methods + +Package: irda-modules +Depends: kernel-image, nic-shared-modules +Priority: standard +Description: Support for Infrared protocols + +Package: md-modules +Depends: kernel-image +Priority: standard +Description: Multi-device support (raid, device-mapper, lvm) + +Package: nic-modules +Depends: kernel-image, nic-shared-modules, virtio-modules +Priority: standard +Description: Network interface support + +Package: nic-pcmcia-modules +Depends: kernel-image, nic-shared-modules, nic-modules +Priority: standard +Description: PCMCIA network interface support + +Package: nic-usb-modules +Depends: kernel-image, nic-shared-modules, usb-modules +Priority: standard +Description: USB network interface support + +Package: nic-shared-modules +Depends: kernel-image, crypto-modules +Priority: standard +Description: nic shared modules + This package contains modules which support nic modules + +Package: parport-modules +Depends: kernel-image +Priority: standard +Description: Parallel port support + +Package: pata-modules +Depends: kernel-image, storage-core-modules +Priority: standard +Description: PATA support modules + +Package: pcmcia-modules +Depends: kernel-image +Priority: standard +Description: PCMCIA Modules + +Package: pcmcia-storage-modules +Depends: kernel-image, scsi-modules +Priority: standard +Description: PCMCIA storage support + +Package: plip-modules +Depends: kernel-image, nic-shared-modules, parport-modules +Priority: standard +Description: PLIP (parallel port) networking support + +Package: ppp-modules +Depends: kernel-image, nic-shared-modules, serial-modules +Priority: standard +Description: PPP (serial port) networking support + +Package: sata-modules +Depends: kernel-image, storage-core-modules +Priority: standard +Description: SATA storage support + +Package: scsi-modules +Depends: kernel-image, storage-core-modules +Priority: standard +Description: SCSI storage support + +Package: serial-modules +Depends: kernel-image +Priority: standard +Description: Serial port support + +Package: storage-core-modules +Depends: kernel-image +Priority: standard +Provides: loop-modules +Description: Core storage support + Includes core SCSI, LibATA, USB-Storage. Also includes related block + devices for CD, Disk and Tape medium (and IDE Floppy). + +Package: usb-modules +Depends: kernel-image, storage-core-modules +Priority: standard +Description: Core USB support + +Package: nfs-modules +Priority: standard +Depends: kernel-image +Description: NFS filesystem drivers + Includes the NFS client driver, and supporting modules. + +Package: block-modules +Priority: standard +Depends: kernel-image, storage-core-modules, parport-modules, virtio-modules +Description: Block storage devices + This package contains the block storage devices, including DAC960 and + paraide. + +Package: message-modules +Priority: standard +Depends: kernel-image, storage-core-modules, scsi-modules +Description: Fusion and i2o storage modules + This package containes the fusion and i2o storage modules. + +Package: crypto-modules +Priority: extra +Depends: kernel-image +Description: crypto modules + This package contains crypto modules. + +Package: virtio-modules +Priority: standard +Depends: kernel-image +Description: VirtIO Modules + Includes modules for VirtIO (virtual machine, generally kvm guests) + +Package: socket-modules +Depends: kernel-image +Priority: standard +Description: Unix socket support + +Package: mouse-modules +Depends: kernel-image, input-modules, usb-modules +Priority: extra +Description: Mouse support + This package contains mouse drivers for the Linux kernel. + +Package: squashfs-modules +Depends: kernel-image +Priority: extra +Description: squashfs modules + This package contains squashfs modules. + +Package: vlan-modules +Depends: kernel-image +Priority: extra +Description: vlan modules + This package contains vlan (8021.Q) modules. + --- linux-2.6.37.orig/debian.master/d-i/kernel-versions +++ linux-2.6.37/debian.master/d-i/kernel-versions @@ -0,0 +1,15 @@ +# arch version flavour installedname suffix bdep +amd64 2.6.37-graphics2+12 generic 2.6.37-graphics2+12-generic - +amd64 2.6.37-graphics2+12 virtual 2.6.37-graphics2+12-virtual - + +i386 2.6.37-graphics2+12 generic 2.6.37-graphics2+12-generic - +i386 2.6.37-graphics2+12 generic-pae 2.6.37-graphics2+12-generic-pae - +i386 2.6.37-graphics2+12 virtual 2.6.37-graphics2+12-virtual - + +armel 2.6.37-graphics2+12 versatile 2.6.37-graphics2+12-versatile - +armel 2.6.37-graphics2+12 omap 2.6.37-graphics2+12-omap - + +# Ports +# arch version flavour installedname suffix bdep +powerpc 2.6.37-graphics2+12 powerpc 2.6.37-graphics2+12-powerpc - +powerpc 2.6.37-graphics2+12 powerpc64-smp 2.6.37-graphics2+12-powerpc64-smp - --- linux-2.6.37.orig/debian.master/d-i/firmware/README.txt +++ linux-2.6.37/debian.master/d-i/firmware/README.txt @@ -0,0 +1,4 @@ +# +# Place the names of udeb modules into this directory that require +# runtime firmware. +# --- linux-2.6.37.orig/debian.master/d-i/firmware/nic-modules +++ linux-2.6.37/debian.master/d-i/firmware/nic-modules @@ -0,0 +1,8 @@ +e100/d101m_ucode.bin +e100/d101s_ucode.bin +e100/d102e_ucode.bin +bnx2/bnx2-mips-06-6.0.15.fw +bnx2/bnx2-mips-09-6.0.17.fw +bnx2/bnx2-rv2p-06-6.0.15.fw +bnx2/bnx2-rv2p-09-6.0.17.fw +bnx2/bnx2-rv2p-09ax-6.0.17.fw --- linux-2.6.37.orig/debian.master/d-i/firmware/scsi-modules +++ linux-2.6.37/debian.master/d-i/firmware/scsi-modules @@ -0,0 +1,3 @@ +qlogic/1040.bin +qlogic/12160.bin +qlogic/1280.bin --- linux-2.6.37.orig/debian.master/d-i/modules-powerpc/block-modules +++ linux-2.6.37/debian.master/d-i/modules-powerpc/block-modules @@ -0,0 +1,31 @@ +aoe +aten +bpck +bpck6 ? +cciss +comm +cpqarray ? +DAC960 +dstr +epat +epia +fit2 +fit3 +friq +frpw +kbic +ktti +nbd +on20 +on26 +paride +pcd +pd +pf +pg +ps3disk ? +ps3vram ? +pt +sx8 +umem +virtio_blk ? --- linux-2.6.37.orig/debian.master/d-i/modules-powerpc/message-modules +++ linux-2.6.37/debian.master/d-i/modules-powerpc/message-modules @@ -0,0 +1,13 @@ +mptbase +mptctl +mptfc +mptlan +mptsas +mptscsih +mptspi +i2o_block +i2o_bus +i2o_config ? +i2o_core +i2o_proc +i2o_scsi --- linux-2.6.37.orig/debian.master/d-i/modules-powerpc/nic-modules +++ linux-2.6.37/debian.master/d-i/modules-powerpc/nic-modules @@ -0,0 +1,152 @@ +3c359 ? +3c501 ? +3c503 ? +3c505 ? +3c507 ? +3c509 ? +3c515 ? +3c523 ? +3c527 ? +3c59x ? +8139cp ? +8139too ? +82596 ? +abyss ? +ac3200 ? +adm8211 ? +airo ? +airport ? +amd8111e ? +arc4 ? +arcnet ? +arc-rawmode ? +arc-rimi ? +arlan ? +at1700 ? +atl1 ? +atl1e ? +atl2 ? +atmel ? +atmel_pci ? +b44 ? +bcm43xx ? +bcm43xx-mac80211 ? +bmac ? +bnx2 ? +bnx2x ? +bonding ? +cassini ? +com20020 ? +com20020-pci ? +com90io ? +com90xx ? +cs89x0 ? +de2104x ? +de4x5 ? +de600 ? +de620 ? +defxx ? +depca ? +dl2k ? +dmfe ? +dummy ? +e100 ? +e1000 ? +e1000e ? +e2100 ? +eepro ? +eepro100 ? +eexpress ? +epic100 ? +eql ? +es3210 ? +eth16i ? +ewrk3 ? +fealnx ? +forcedeth ? +igb ? +hamachi ? +hermes ? +hp ? +hp100 ? +hp-plus ? +ibmtr ? +ipddp ? +ipw2100 ? +ipw2200 ? +ipw3945 ? +ixgb ? +lance ? +lanstreamer ? +lasi_82596 ? +lne390 ? +lp486e ? +mace ? +mv643xx_eth ? +myri_sbus ? +natsemi ? +ne ? +ne2 ? +ne2k-pci ? +ne3210 ? +netconsole ? +netxen_nic ? +ni5010 ? +ni52 ? +ni65 ? +niu ? +ns83820 ? +olympic ? +orinoco ? +orinoco_pci ? +orinoco_plx ? +orinoco_tmd ? +pcnet32 ? +prism54 ? +ps3_gelic ? +r8169 ? +rate_control ? +rfc1051 ? +rfc1201 ? +rrunner ? +rt2400 ? +rt2500 ? +rt61pci ? +s2io ? +shaper ? +sis190 ? +sis900 ? +spidernet ? +skfp ? +skge ? +sk98lin ? +sky2 ? +smc9194 ? +smc-ultra ? +smc-ultra32 ? +starfire ? +strip ? +sunbmac ? +sundance ? +sungem ? +sungem_phy ? +sunhme ? +sunlance ? +sunqe ? +sunvnet ? +tg3 ? +tlan ? +tms380tr ? +tmspci ? +tulip ? +tun ? +typhoon ? +uli526x ? +via-rhine ? +via-velocity ? +virtio_net ? +wavelan ? +wd ? +winbond-840 ? +yellowfin ? +znet ? --- linux-2.6.37.orig/debian.master/d-i/modules-powerpc/scsi-modules +++ linux-2.6.37/debian.master/d-i/modules-powerpc/scsi-modules @@ -0,0 +1,116 @@ +# SCSI +raid_class ? +scsi_transport_spi ? +scsi_transport_fc ? +scsi_transport_iscsi ? +scsi_transport_sas ? +iscsi_tcp ? +libiscsi ? +amiga7xx ? +a3000 ? +a2091 ? +gvp11 ? +mvme147 ? +sgiwd93 ? +cyberstorm ? +cyberstormII ? +blz2060 ? +blz1230 ? +fastlane ? +oktagon_esp_mod ? +atari_scsi ? +mac_scsi ? +mac_esp ? +sun3_scsi ? +mvme16x ? +bvme6000 ? +sim710 ? +advansys ? +psi240i ? +BusLogic ? +dpt_i2o ? +u14-34f ? +ultrastor ? +aha152x ? +aha1542 ? +aha1740 ? +aic7xxx_old ? +ips ? +fd_mcs ? +fdomain ? +in2000 ? +g_NCR5380 ? +g_NCR5380_mmio ? +NCR53c406a ? +NCR_D700 ? +NCR_Q720_mod ? +sym53c416 ? +qlogicfas408 ? +qla1280 ? +pas16 ? +seagate ? +seagate ? +t128 ? +dmx3191d ? +dtc ? +zalon7xx ? +eata_pio ? +wd7000 ? +mca_53c9x ? +ibmmca ? +eata ? +dc395x ? +tmscsim ? +megaraid ? +atp870u ? +esp ? +gdth ? +initio ? +a100u2w ? +qlogicpti ? +ide-scsi ? +mesh ? +mac53c94 ? +pluto ? +dec_esp ? +3w-xxxx ? +3w-9xxx ? +ppa ? +imm ? +jazz_esp ? +sun3x_esp ? +fcal ? +lasi700 ? +nsp32 ? +ipr ? +hptiop ? +stex ? +osst ? +sg ? +ch ? +scsi_debug ? +aacraid ? +aic7xxx ? +aic79xx ? +aic94xx ? +arcmsr ? +acornscsi_mod ? +arxescsi ? +cumana_1 ? +cumana_2 ? +ecoscsi ? +oak ? +powertec ? +eesox ? +ibmvscsic ? +libsas ? +lpfc ? +megaraid_mm ? +megaraid_mbox ? +megaraid_sas ? +qla2xxx ? +sym53c8xx ? +qla4xxx ? +mvsas ? +sr_mod ? +sd_mod ? --- linux-2.6.37.orig/debian.master/d-i/modules-powerpc/storage-core-modules +++ linux-2.6.37/debian.master/d-i/modules-powerpc/storage-core-modules @@ -0,0 +1,13 @@ +# Core stacks +usb-storage ? + +# Block level + +# Loop modules +cryptoloop + +# Needs to be here for better cdrom initrd layout +isofs + +ps3stor_lib ? +ps3rom ? --- linux-2.6.37.orig/debian.master/d-i/modules-sparc/block-modules +++ linux-2.6.37/debian.master/d-i/modules-sparc/block-modules @@ -0,0 +1,9 @@ +aoe +cciss +comm +cpqarray ? +DAC960 +nbd +sx8 +umem +virtio_blk ? --- linux-2.6.37.orig/debian.master/d-i/modules-sparc/message-modules +++ linux-2.6.37/debian.master/d-i/modules-sparc/message-modules @@ -0,0 +1,13 @@ +mptbase +mptctl +mptfc +mptlan +mptsas +mptscsih +mptspi +i2o_block +i2o_bus +i2o_config ? +i2o_core +i2o_proc +i2o_scsi --- linux-2.6.37.orig/debian.master/d-i/modules/block-modules +++ linux-2.6.37/debian.master/d-i/modules/block-modules @@ -0,0 +1,31 @@ +aoe ? +aten ? +bpck ? +bpck6 ? +cciss ? +comm ? +cpqarray ? +DAC960 ? +dstr ? +epat ? +epia ? +fit2 ? +fit3 ? +friq ? +frpw ? +hpsa ? +kbic ? +ktti ? +nbd ? +on20 ? +on26 ? +paride ? +pcd ? +pd ? +pf ? +pg ? +pt ? +sx8 ? +umem ? +virtio_blk ? +xen-blkfront ? --- linux-2.6.37.orig/debian.master/d-i/modules/crypto-modules +++ linux-2.6.37/debian.master/d-i/modules/crypto-modules @@ -0,0 +1,8 @@ +aes_generic ? +blowfish ? +twofish ? +serpent ? +sha256_generic ? +cbc ? +ecb ? +crc32c ? --- linux-2.6.37.orig/debian.master/d-i/modules/fat-modules +++ linux-2.6.37/debian.master/d-i/modules/fat-modules @@ -0,0 +1,7 @@ +fat ? +vfat ? + +# Supporting modules ? +nls_cp437 ? +nls_iso8859-1 ? +nls_utf8 ? --- linux-2.6.37.orig/debian.master/d-i/modules/fb-modules +++ linux-2.6.37/debian.master/d-i/modules/fb-modules @@ -0,0 +1,3 @@ +fbcon ? +vesafb ? +vga16fb ? --- linux-2.6.37.orig/debian.master/d-i/modules/firewire-core-modules +++ linux-2.6.37/debian.master/d-i/modules/firewire-core-modules @@ -0,0 +1,4 @@ +firewire-core ? +firewire-ohci ? +firewire-sbp2 ? +firewire-net ? --- linux-2.6.37.orig/debian.master/d-i/modules/floppy-modules +++ linux-2.6.37/debian.master/d-i/modules/floppy-modules @@ -0,0 +1 @@ +floppy ? --- linux-2.6.37.orig/debian.master/d-i/modules/fs-core-modules +++ linux-2.6.37/debian.master/d-i/modules/fs-core-modules @@ -0,0 +1,3 @@ +jfs ? +reiserfs ? +xfs ? --- linux-2.6.37.orig/debian.master/d-i/modules/fs-secondary-modules +++ linux-2.6.37/debian.master/d-i/modules/fs-secondary-modules @@ -0,0 +1,5 @@ +btrfs ? +fuse ? +ntfs ? +hfs ? +hfsplus ? --- linux-2.6.37.orig/debian.master/d-i/modules/input-modules +++ linux-2.6.37/debian.master/d-i/modules/input-modules @@ -0,0 +1,21 @@ +hid-a4tech ? +hid-apple ? +hid-belkin ? +hid-bright ? +hid-cherry ? +hid-chicony ? +hid-cypress ? +hid-dell ? +hid-ezkey ? +hid-gyration ? +hid-logitech ? +hid-microsoft ? +hid-monterey ? +hid-petalynx ? +hid-pl ? +hid-samsung ? +hid-sony ? +hid-sunplus ? +hid-tmff ? +hid-zpff ? +usbhid ? --- linux-2.6.37.orig/debian.master/d-i/modules/irda-modules +++ linux-2.6.37/debian.master/d-i/modules/irda-modules @@ -0,0 +1,30 @@ +act200l-sir ? +actisys-sir ? +ali-ircc ? +donauboe ? +esi-sir ? +girbil-sir ? +ircomm ? +ircomm-tty ? +irda ? +irda-usb ? +irlan ? +irnet ? +irport ? +irtty-sir ? +kingsun-sir ? +ks959-sir ? +ksdazzle-sir ? +litelink-sir ? +ma600-sir ? +mcp2120-sir ? +mcs7780 ? +nsc-ircc ? +old_belkin-sir ? +sir-dev ? +smsc-ircc2 ? +stir4200 ? +tekram-sir ? +via-ircc ? +vlsi_ir ? +w83977af_ir ? --- linux-2.6.37.orig/debian.master/d-i/modules/md-modules +++ linux-2.6.37/debian.master/d-i/modules/md-modules @@ -0,0 +1,13 @@ +dm-crypt ? +dm-zero ? +faulty ? +linear ? +multipath ? +raid0 ? +raid1 ? +raid10 ? +raid456 ? + +# Extras +dm-raid4-5 ? +dm-loop ? --- linux-2.6.37.orig/debian.master/d-i/modules/message-modules +++ linux-2.6.37/debian.master/d-i/modules/message-modules @@ -0,0 +1,14 @@ +mptbase ? +mptctl ? +mptfc ? +mptlan ? +mptsas ? +mpt2sas ? +mptscsih ? +mptspi ? +i2o_block ? +i2o_bus ? +i2o_config ? +i2o_core ? +i2o_proc ? +i2o_scsi ? --- linux-2.6.37.orig/debian.master/d-i/modules/mouse-modules +++ linux-2.6.37/debian.master/d-i/modules/mouse-modules @@ -0,0 +1,2 @@ +psmouse ? +usbmouse ? --- linux-2.6.37.orig/debian.master/d-i/modules/nfs-modules +++ linux-2.6.37/debian.master/d-i/modules/nfs-modules @@ -0,0 +1,4 @@ +nfs ? +nfs_acl ? +lockd ? +sunrpc ? --- linux-2.6.37.orig/debian.master/d-i/modules/nic-modules +++ linux-2.6.37/debian.master/d-i/modules/nic-modules @@ -0,0 +1,156 @@ +3c359 ? +3c501 ? +3c503 ? +3c505 ? +3c507 ? +3c509 ? +3c515 ? +3c523 ? +3c527 ? +3c59x ? +8139cp ? +8139too ? +82596 ? +abyss ? +ac3200 ? +adm8211 ? +airo ? +airport ? +amd8111e ? +arc4 ? +arcnet ? +arc-rawmode ? +arc-rimi ? +arlan ? +at1700 ? +atl1 ? +atl1c ? +atl1e ? +atl2 ? +atmel ? +atmel_pci ? +b44 ? +bcm43xx ? +bcm43xx-mac80211 ? +be2net ? +bmac ? +bnx2 ? +bnx2x ? +bonding ? +cassini ? +com20020 ? +com20020-pci ? +com90io ? +com90xx ? +cs89x0 ? +de2104x ? +de4x5 ? +de600 ? +de620 ? +defxx ? +depca ? +dl2k ? +dmfe ? +dummy ? +e100 ? +e1000 ? +e1000e ? +e2100 ? +eepro ? +eepro100 ? +eexpress ? +epic100 ? +eql ? +es3210 ? +eth16i ? +ewrk3 ? +fealnx ? +forcedeth ? +igb ? +ps3_gelic ? +hamachi ? +hermes ? +hp ? +hp100 ? +hp-plus ? +ibmtr ? +ipddp ? +ipw2100 ? +ipw2200 ? +ipw3945 ? +ixgb ? +lance ? +lanstreamer ? +lasi_82596 ? +lne390 ? +lp486e ? +mace ? +mv643xx_eth ? +myri_sbus ? +natsemi ? +ne ? +ne2 ? +ne2k-pci ? +ne3210 ? +netconsole ? +netxen_nic ? +ni5010 ? +ni52 ? +ni65 ? +niu ? +ns83820 ? +olympic ? +orinoco ? +orinoco_pci ? +orinoco_plx ? +orinoco_tmd ? +pcnet32 ? +prism54 ? +r8169 ? +rate_control ? +rfc1051 ? +rfc1201 ? +rrunner ? +rt2400 ? +rt2500 ? +rt61pci ? +s2io ? +shaper ? +sis190 ? +sis900 ? +spidernet ? +skfp ? +skge ? +sk98lin ? +sky2 ? +smc9194 ? +smc-ultra ? +smc-ultra32 ? +starfire ? +strip ? +sunbmac ? +sundance ? +sungem ? +sungem_phy ? +sunhme ? +sunlance ? +sunqe ? +sunvnet ? +tg3 ? +tlan ? +tms380tr ? +tmspci ? +tulip ? +tun ? +typhoon ? +uli526x ? +via-rhine ? +via-velocity ? +virtio_net ? +wavelan ? +wd ? +winbond-840 ? +yellowfin ? +znet ? +vmxnet3 ? +xen-netfront ? --- linux-2.6.37.orig/debian.master/d-i/modules/nic-pcmcia-modules +++ linux-2.6.37/debian.master/d-i/modules/nic-pcmcia-modules @@ -0,0 +1,19 @@ +3c574_cs ? +3c589_cs ? +airo_cs ? +atmel_cs ? +axnet_cs ? +com20020_cs ? +fmvj18x_cs ? +ibmtr_cs ? +netwave_cs ? +nmclan_cs ? +orinoco_cs ? +pcnet_cs ? +ray_cs ? +smc91c92_cs ? +wavelan_cs ? +wl3501_cs ? +xirc2ps_cs ? +xircom_cb ? +xircom_tulip_cb ? --- linux-2.6.37.orig/debian.master/d-i/modules/nic-shared-modules +++ linux-2.6.37/debian.master/d-i/modules/nic-shared-modules @@ -0,0 +1,22 @@ +# PHY +8390 ? +mii ? + +# CRC modules +crc-ccitt ? +crc-itu-t ? +libcrc32c ? + +# mac80211 stuff +mac80211 ? +cfg80211 ? + +# rt2x00 lib (since rt2x00 is split across usb/pci/cb +rt2x00lib ? + +# Wireless 802.11 modules +lib80211 ? +cfg80211 ? +lib80211_crypt_ccmp ? +lib80211_crypt_tkip ? +lib80211_crypt_wep ? --- linux-2.6.37.orig/debian.master/d-i/modules/nic-usb-modules +++ linux-2.6.37/debian.master/d-i/modules/nic-usb-modules @@ -0,0 +1,27 @@ +catc ? +kaweth ? +pegasus ? +prism2_usb ? +rtl8150 ? +usbnet ? +zd1211rw ? +zd1201 ? +rt2500usb ? +rt73usb ? +rt2570 ? +cdc_ether ? +asix ? +cdc_eem ? +cdc_ether ? +cdc-phonet ? +cdc_subset ? +dm9601 ? +gl620a ? +hso ? +int51x1 ? +mcs7830 ? +net1080 ? +plusb ? +rndis_host ? +smsc95xx ? +zaurus ? --- linux-2.6.37.orig/debian.master/d-i/modules/parport-modules +++ linux-2.6.37/debian.master/d-i/modules/parport-modules @@ -0,0 +1,2 @@ +parport ? +parport_pc ? --- linux-2.6.37.orig/debian.master/d-i/modules/pata-modules +++ linux-2.6.37/debian.master/d-i/modules/pata-modules @@ -0,0 +1,46 @@ +pata_ali.ko ? +pata_amd.ko ? +pata_artop.ko ? +pata_atiixp.ko ? +pata_atp867x.ko ? +pata_cmd640.ko ? +pata_cmd64x.ko ? +pata_cs5520.ko ? +pata_cs5530.ko ? +pata_cs5535.ko ? +pata_cs5536.ko ? +pata_cypress.ko ? +pata_efar.ko ? +pata_hpt366.ko ? +pata_hpt37x.ko ? +pata_hpt3x2n.ko ? +pata_hpt3x3.ko ? +pata_isapnp.ko ? +pata_it8213.ko ? +pata_it821x.ko ? +pata_jmicron.ko ? +pata_legacy.ko ? +pata_marvell.ko ? +pata_mpiix.ko ? +pata_netcell.ko ? +pata_ninja32.ko ? +pata_ns87410.ko ? +pata_ns87415.ko ? +pata_oldpiix.ko ? +pata_optidma.ko ? +pata_opti.ko ? +pata_pcmcia.ko ? +pata_pdc2027x.ko ? +pata_pdc202xx_old.ko ? +pata_qdi.ko ? +pata_radisys.ko ? +pata_rdc.ko ? +pata_rz1000.ko ? +pata_sc1200.ko ? +pata_sch.ko ? +pata_serverworks.ko ? +pata_sil680.ko ? +pata_sl82c105.ko ? +pata_triflex.ko ? +pata_via.ko ? +pata_winbond.ko ? --- linux-2.6.37.orig/debian.master/d-i/modules/pcmcia-modules +++ linux-2.6.37/debian.master/d-i/modules/pcmcia-modules @@ -0,0 +1,8 @@ +i82092 ? +i82365 ? +pcmcia ? +pcmcia_core ? +pd6729 ? +rsrc_nonstatic ? +tcic ? +yenta_socket ? --- linux-2.6.37.orig/debian.master/d-i/modules/pcmcia-storage-modules +++ linux-2.6.37/debian.master/d-i/modules/pcmcia-storage-modules @@ -0,0 +1,6 @@ +pata_pcmcia ? +qlogic_cs ? +fdomain_cs ? +aha152x_cs ? +nsp_cs ? +sym53c500_cs ? --- linux-2.6.37.orig/debian.master/d-i/modules/plip-modules +++ linux-2.6.37/debian.master/d-i/modules/plip-modules @@ -0,0 +1 @@ +plip ? --- linux-2.6.37.orig/debian.master/d-i/modules/ppp-modules +++ linux-2.6.37/debian.master/d-i/modules/ppp-modules @@ -0,0 +1,6 @@ +ppp_async ? +ppp_deflate ? +ppp_mppe ? +pppoe ? +pppox ? +ppp_synctty ? --- linux-2.6.37.orig/debian.master/d-i/modules/sata-modules +++ linux-2.6.37/debian.master/d-i/modules/sata-modules @@ -0,0 +1,14 @@ +ahci.ko ? +sata_inic162x.ko ? +sata_mv.ko ? +sata_nv.ko ? +sata_promise.ko ? +sata_qstor.ko ? +sata_sil24.ko ? +sata_sil.ko ? +sata_sis.ko ? +sata_svw.ko ? +sata_sx4.ko ? +sata_uli.ko ? +sata_via.ko ? +sata_vsc.ko ? --- linux-2.6.37.orig/debian.master/d-i/modules/scsi-modules +++ linux-2.6.37/debian.master/d-i/modules/scsi-modules @@ -0,0 +1,117 @@ +# SCSI +raid_class ? +scsi_transport_spi ? +scsi_transport_fc ? +scsi_transport_iscsi ? +scsi_transport_sas ? +iscsi_tcp ? +libiscsi ? +amiga7xx ? +a3000 ? +a2091 ? +gvp11 ? +mvme147 ? +sgiwd93 ? +cyberstorm ? +cyberstormII ? +blz2060 ? +blz1230 ? +fastlane ? +oktagon_esp_mod ? +atari_scsi ? +mac_scsi ? +mac_esp ? +sun3_scsi ? +mvme16x ? +bvme6000 ? +sim710 ? +advansys ? +psi240i ? +BusLogic ? +dpt_i2o ? +u14-34f ? +ultrastor ? +aha152x ? +aha1542 ? +aha1740 ? +aic7xxx_old ? +ips ? +fd_mcs ? +fdomain ? +in2000 ? +g_NCR5380 ? +g_NCR5380_mmio ? +NCR53c406a ? +NCR_D700 ? +NCR_Q720_mod ? +sym53c416 ? +qlogicfas408 ? +qla1280 ? +pas16 ? +seagate ? +seagate ? +t128 ? +dmx3191d ? +dtc ? +zalon7xx ? +eata_pio ? +wd7000 ? +mca_53c9x ? +ibmmca ? +eata ? +dc395x ? +tmscsim ? +megaraid ? +atp870u ? +esp ? +gdth ? +initio ? +a100u2w ? +qlogicpti ? +ide-scsi ? +mesh ? +mac53c94 ? +pluto ? +dec_esp ? +3w-xxxx ? +3w-9xxx ? +ppa ? +imm ? +jazz_esp ? +sun3x_esp ? +fcal ? +lasi700 ? +nsp32 ? +ipr ? +hptiop ? +stex ? +osst ? +sg ? +ch ? +scsi_debug ? +aacraid ? +aic7xxx ? +aic79xx ? +aic94xx ? +arcmsr ? +acornscsi_mod ? +arxescsi ? +cumana_1 ? +cumana_2 ? +ecoscsi ? +oak ? +powertec ? +eesox ? +ibmvscsic ? +libsas ? +lpfc ? +megaraid_mm ? +megaraid_mbox ? +megaraid_sas ? +qla2xxx ? +sym53c8xx ? +qla4xxx ? +mvsas ? +vmw_pvscsi ? +ums-cypress ? +be2iscsi ? --- linux-2.6.37.orig/debian.master/d-i/modules/serial-modules +++ linux-2.6.37/debian.master/d-i/modules/serial-modules @@ -0,0 +1,3 @@ +generic_serial ? +serial_cs ? +synclink_cs ? --- linux-2.6.37.orig/debian.master/d-i/modules/squashfs-modules +++ linux-2.6.37/debian.master/d-i/modules/squashfs-modules @@ -0,0 +1 @@ +squashfs ? --- linux-2.6.37.orig/debian.master/d-i/modules/storage-core-modules +++ linux-2.6.37/debian.master/d-i/modules/storage-core-modules @@ -0,0 +1,10 @@ +# Core stacks +usb-storage ? + +# Block level + +# Loop modules +cryptoloop ? + +# Needs to be here for better cdrom initrd layout +isofs ? --- linux-2.6.37.orig/debian.master/d-i/modules/usb-modules +++ linux-2.6.37/debian.master/d-i/modules/usb-modules @@ -0,0 +1,9 @@ +ehci-hcd ? +isp116x-hcd ? +isp1760 ? +ohci-hcd ? +r8a66597-hcd ? +sl811_cs ? +sl811-hcd ? +u132-hcd ? +uhci-hcd ? --- linux-2.6.37.orig/debian.master/d-i/modules/virtio-modules +++ linux-2.6.37/debian.master/d-i/modules/virtio-modules @@ -0,0 +1,4 @@ +virtio_balloon ? +virtio_pci ? +virtio_ring ? +virtio-rng ? --- linux-2.6.37.orig/debian.master/d-i/modules/vlan-modules +++ linux-2.6.37/debian.master/d-i/modules/vlan-modules @@ -0,0 +1,3 @@ +slp ? +garp ? +8021q ? --- linux-2.6.37.orig/debian.master/etc/getabis +++ linux-2.6.37/debian.master/etc/getabis @@ -0,0 +1,13 @@ +repo_list=( + "http://archive.ubuntu.com/ubuntu/pool/main/l/linux" + "http://ports.ubuntu.com/ubuntu-ports/pool/main/l/linux" + "http://archive.ubuntu.com/ubuntu/pool/universe/l/linux" + "http://ports.ubuntu.com/ubuntu-ports/pool/universe/l/linux" +) + +getall armel versatile omap +getall amd64 generic server virtual +getall i386 generic generic-pae virtual + +# Ports arches and flavours. +getall powerpc powerpc powerpc-smp powerpc64-smp --- linux-2.6.37.orig/debian.master/etc/kernelconfig +++ linux-2.6.37/debian.master/etc/kernelconfig @@ -0,0 +1,7 @@ +if [ "$variant" = "ports" ]; then + archs="" + family='ports' +else + archs="amd64 i386 armel powerpc" + family='ubuntu' +fi --- linux-2.6.37.orig/debian.master/rules.d/armel.mk +++ linux-2.6.37/debian.master/rules.d/armel.mk @@ -0,0 +1,11 @@ +build_arch = arm +header_arch = arm +asm_link = arm +defconfig = defconfig +flavours = versatile omap +build_image = zImage +kernel_file = arch/$(build_arch)/boot/zImage +install_file = vmlinuz +no_dumpfile = true + +loader = grub --- linux-2.6.37.orig/debian.master/rules.d/powerpc.mk +++ linux-2.6.37/debian.master/rules.d/powerpc.mk @@ -0,0 +1,19 @@ +build_arch = powerpc +header_arch = $(build_arch) +asm_link = $(build_arch) +defconfig = pmac32_defconfig +flavours = powerpc powerpc-smp powerpc64-smp +build_image = vmlinux +kernel_file = $(build_image) +install_file = $(build_image) + +loader = yaboot + +custom_flavours = + +no_dumpfile = true +skipdbg = true +skipabi = true +skipmodule = true + +family=ubuntu --- linux-2.6.37.orig/debian.master/rules.d/amd64.mk +++ linux-2.6.37/debian.master/rules.d/amd64.mk @@ -0,0 +1,9 @@ +build_arch = x86_64 +header_arch = $(build_arch) +asm_link = x86 +defconfig = defconfig +flavours = generic +build_image = bzImage +kernel_file = arch/$(build_arch)/boot/bzImage +install_file = vmlinuz +loader = grub --- linux-2.6.37.orig/debian.master/rules.d/i386.mk +++ linux-2.6.37/debian.master/rules.d/i386.mk @@ -0,0 +1,9 @@ +build_arch = i386 +header_arch = x86_64 +asm_link = x86 +defconfig = defconfig +flavours = generic +build_image = bzImage +kernel_file = arch/$(build_arch)/boot/bzImage +install_file = vmlinuz +loader = grub --- linux-2.6.37.orig/debian/compat +++ linux-2.6.37/debian/compat @@ -0,0 +1 @@ +5 --- linux-2.6.37.orig/debian/debian.env +++ linux-2.6.37/debian/debian.env @@ -0,0 +1 @@ +DEBIAN=debian.master --- linux-2.6.37.orig/debian/rules +++ linux-2.6.37/debian/rules @@ -0,0 +1,235 @@ +#!/usr/bin/make -f +# +# $(DEBIAN)/rules for Ubuntu linux +# +# Use this however you want, just give credit where credit is due. +# +# Copyright (c) 2007 Ben Collins +# + +DEBIAN=$(shell awk -F= '($$1 == "DEBIAN") { print $$2 }' $$new; \ + done + flavours="$(wildcard $(DEBIAN)/control.d/vars.* $(DEBIAN)/sub-flavours/*.vars)";\ + for i in $$flavours; do \ + $(SHELL) $(DROOT)/scripts/control-create $$i | \ + sed -e 's/PKGVER/$(release)/g' \ + -e 's/ABINUM/$(abinum)/g' \ + -e 's/SRCPKGNAME/$(src_pkg_name)/g' \ + >> $(DEBIAN)/control.stub; \ + done + cp $(DEBIAN)/control.stub $(DEBIAN)/control + +.PHONY: debian/control +debian/control: $(DEBIAN)/control.stub + rm -rf $(builddir)/modules $(builddir)/firmware \ + $(builddir)/kernel-versions $(builddir)/package-list \ + $(builddir)/$(DEBIAN) + mkdir -p $(builddir)/modules/$(arch)/ + cp $(DEBIAN)/d-i/modules/* $(builddir)/modules/$(arch)/ + mkdir -p $(builddir)/firmware/$(arch)/ + cp $(DEBIAN)/d-i/firmware/* $(builddir)/firmware/$(arch)/ + cp $(DEBIAN)/d-i/package-list $(DEBIAN)/d-i/kernel-versions $(builddir)/ + touch $(builddir)/modules/$(arch)/kernel-image + # kernel-wedge needs to poke around in $(DEBIAN)/ + ln -nsf $(CURDIR)/debian $(builddir)/debian + + # Some files may need to differ between architectures + if [ -d $(DEBIAN)/d-i/modules-$(arch) ]; then \ + cp $(DEBIAN)/d-i/modules-$(arch)/* \ + $(builddir)/modules/$(arch)/; \ + fi + if [ -d $(DEBIAN)/d-i/firmware-$(arch) ]; then \ + cp $(DEBIAN)/d-i/firmware-$(arch)/* \ + $(builddir)/firmware/$(arch)/; \ + fi + + # Remove unwanted stuff for this architecture + if [ -r "$(DEBIAN)/d-i/exclude-modules.$(arch)" ]; then \ + (cat $(DEBIAN)/d-i/exclude-modules.$(arch); \ + ls $(builddir)/modules/$(arch)/) | sort | uniq -d | \ + (cd $(builddir)/modules/$(arch)/; xargs rm -f); \ + fi + if [ -r "$(DEBIAN)/d-i/exclude-firmware.$(arch)" ]; then \ + (cat $(DEBIAN)/d-i/exclude-firmware.$(arch); \ + ls $(builddir)/firmware/$(arch)/) | sort | uniq -d | \ + (cd $(builddir)/firmware/$(arch)/; xargs rm -f); \ + fi + + # Per flavour module lists + flavour_modules=`ls $(DEBIAN)/d-i/modules.$(arch)-* 2>/dev/null` \ + || true; \ + if [ "$$flavour_modules" != "" ]; then \ + for flav in $$flavour_modules; do \ + name=`echo $$flav | sed 's/.*\/modules.$(arch)-//'`; \ + mkdir $(builddir)/modules/$(arch)-$$name; \ + (cd $(builddir)/modules/; tar cf - `cat ../$$flav`) | \ + (cd $(builddir)/modules/$(arch)-$$name/; tar xf -); \ + touch $(builddir)/modules/$(arch)-$$name/kernel-image; \ + done; \ + fi + flavour_firmware=`ls $(DEBIAN)/d-i/firmware.$(arch)-* 2>/dev/null` \ + || true; \ + if [ "$$flavour_firmware" != "" ]; then \ + for flav in $$flavour_firmware; do \ + name=`echo $$flav | sed 's/.*\/firmware.$(arch)-//'`; \ + mkdir $(builddir)/firmware/$(arch)-$$name; \ + (cd $(builddir)/firmware/; tar cf - `cat ../$$flav`) | \ + (cd $(builddir)/firmware/$(arch)-$$name/; tar xf -);\ + touch $(builddir)/firmware/$(arch)-$$name/kernel-image; \ + done; \ + fi + + # Some files may need to differ between flavours + flavour_module_dirs=`ls -d $(DEBIAN)/d-i/modules-$(arch)-* 2>/dev/null`\ + || true; \ + if [ "$$flavour_module_dirs" ]; then \ + for flav in $$flavour_module_dirs; do \ + name=`echo $$flav | sed 's/.*\/modules-$(arch)-//'`; \ + [ -d $(builddir)/modules/$(arch)-$$name ] || \ + cp -a $(builddir)/modules/$(arch) \ + modules/$(arch)-$$name; \ + cp $$flav/* $(builddir)/modules/$(arch)-$$name/; \ + done; \ + fi + flavour_firmware_dirs=`ls -d $(DEBIAN)/d-i/firmware-$(arch)-* 2>/dev/null`\ + || true; \ + if [ "$$flavour_firmware_dirs" ]; then \ + for flav in $$flavour_firmware_dirs; do \ + name=`echo $$flav | sed 's/.*\/firmware-$(arch)-//'`; \ + [ -d $(builddir)/firmware/$(arch)-$$name ] || \ + cp -a $(builddir)/firmware/$(arch) \ + firmware/$(arch)-$$name; \ + cp $$flav/* $(builddir)/firmware/$(arch)-$$name/; \ + done; \ + fi + + # Remove unwanted stuff for each flavour + flavour_exclude=`ls $(DEBIAN)/d-i/exclude-modules.$(arch)-* 2>/dev/null`\ + || true; \ + if [ "$$flavour_exclude" ]; then \ + for flav in $$flavour_exclude; do \ + name=`echo $$flav | sed 's/.*\/exclude-modules.$(arch)-//'`;\ + [ -d $(builddir)/modules/$(arch)-$$name ] || \ + cp -a $(builddir)/modules/$(arch) \ + $(builddir)/modules/$(arch)-$$name; \ + (cat $$flav; \ + ls $(builddir)/modules/$(arch)-$$name) | \ + sort | uniq -d | \ + (cd $(builddir)/modules/$(arch)-$$name/; \ + xargs rm -f); \ + done; \ + fi + flavour_exclude=`ls $(DEBIAN)/d-i/exclude-firmware.$(arch)-* 2>/dev/null`\ + || true; \ + if [ "$$flavour_exclude" ]; then \ + for flav in $$flavour_exclude; do \ + name=`echo $$flav | sed 's/.*\/exclude-firmware.$(arch)-//'`;\ + [ -d $(builddir)/firmware/$(arch)-$$name ] || \ + cp -a $(builddir)/firmware/$(arch) \ + $(builddir)/firmware/$(arch)-$$name; \ + (cat $$flav; \ + ls $(builddir)/firmware/$(arch)-$$name) | \ + sort | uniq -d | \ + (cd $(builddir)/firmware/$(arch)-$$name/; \ + xargs rm -f); \ + done; \ + fi + + if [ ! -d $(builddir)/modules/$(build_arch) ]; then \ + mkdir -p $(builddir)/modules/$(build_arch); \ + cp $(builddir)/modules/$(arch)/* \ + $(builddir)/modules/$(build_arch); \ + fi + if [ ! -d $(builddir)/firmware/$(build_arch) ]; then \ + mkdir -p $(builddir)/firmware/$(build_arch); \ + cp $(builddir)/firmware/$(arch)/* \ + $(builddir)/firmware/$(build_arch); \ + fi + + cp $(DEBIAN)/control.stub debian/control.stub + cd $(builddir) && kernel-wedge gen-control > $(CURDIR)/debian/control --- linux-2.6.37.orig/debian/control.stub +++ linux-2.6.37/debian/control.stub @@ -0,0 +1,516 @@ +Source: linux +Section: devel +Priority: optional +Maintainer: Ubuntu Kernel Team +Standards-Version: 3.8.4.0 +Build-Depends: debhelper (>= 5), cpio, module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [amd64 i386], device-tree-compiler [powerpc], libelf-dev, binutils-dev, rsync, libdw-dev +Build-Depends-Indep: bzip2, sharutils +Build-Conflicts: findutils (= 4.4.1-1ubuntu1) +Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-maverick.git + +Package: linux-headers-2.6.37-graphics2+12 +Architecture: all +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0) +Provides: linux-headers, linux-headers-2.6 +Description: Header files related to Linux kernel version 2.6.37 + This package provides kernel header files for version 2.6.37, for sites + that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details + + +Package: linux-image-2.6.37-graphics2+12-generic +Architecture: i386 amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Generic processors. + . + Geared toward desktop systems. + . + You likely do not want to install this package directly. Instead, install + the linux-generic meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-generic +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86/x86_64 + This package provides kernel header files for version 2.6.37 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-generic-dbgsym +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86/x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-generic-pae +Architecture: i386 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86 + This package contains the Linux kernel image for version 2.6.37 on + x86. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Generic processors. + . + Geared toward 32 bit desktop systems with more then 4GB RAM. + . + You likely do not want to install this package directly. Instead, install + the linux-generic-pae meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-generic-pae +Architecture: i386 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86 + This package provides kernel header files for version 2.6.37 on + x86. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-generic-pae-dbgsym +Architecture: i386 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86 + This package provides a kernel debug image for version 2.6.37 on + x86. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-omap +Architecture: armel +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: flash-kernel +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on TI OMAP3-based systems + This package contains the Linux kernel image for version 2.6.37 on + TI OMAP3-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports TI OMAP3 processors. + . + Targeted towards boards such as Beagleboard, Gumstix, IGEPv2, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-omap meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-omap +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on TI OMAP3-based systems + This package provides kernel header files for version 2.6.37 on + TI OMAP3-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-omap-dbgsym +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on TI OMAP3-based systems + This package provides a kernel debug image for version 2.6.37 on + TI OMAP3-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 32-bit PowerPC + This package contains the Linux kernel image for version 2.6.37 on + 32-bit PowerPC. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 32-bit PowerPC processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 32-bit PowerPC + This package provides kernel header files for version 2.6.37 on + 32-bit PowerPC. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 32-bit PowerPC + This package provides a kernel debug image for version 2.6.37 on + 32-bit PowerPC. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc64-smp +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 64-bit PowerPC SMP + This package contains the Linux kernel image for version 2.6.37 on + 64-bit PowerPC SMP. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 64-bit PowerPC SMP processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc64-smp meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc64-smp +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 64-bit PowerPC SMP + This package provides kernel header files for version 2.6.37 on + 64-bit PowerPC SMP. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc64-smp-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 64-bit PowerPC SMP + This package provides a kernel debug image for version 2.6.37 on + 64-bit PowerPC SMP. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc-smp +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 32-bit PowerPC SMP + This package contains the Linux kernel image for version 2.6.37 on + 32-bit PowerPC SMP. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 32-bit PowerPC SMP processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc-smp meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc-smp +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 32-bit PowerPC SMP + This package provides kernel header files for version 2.6.37 on + 32-bit PowerPC SMP. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc-smp-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 32-bit PowerPC SMP + This package provides a kernel debug image for version 2.6.37 on + 32-bit PowerPC SMP. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-server +Architecture: amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, kvm-api-4, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Server processors. + . + Geared toward 64 bit server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-server meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-server +Architecture: amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86_64 + This package provides kernel header files for version 2.6.37 on + x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-server-dbgsym +Architecture: amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-versatile +Architecture: armel +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on Versatile-based systems + This package contains the Linux kernel image for version 2.6.37 on + Versatile-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Versatile processors. + . + PB, AB, Qemu, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-versatile meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-versatile +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on Versatile-based systems + This package provides kernel header files for version 2.6.37 on + Versatile-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-versatile-dbgsym +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on Versatile-based systems + This package provides a kernel debug image for version 2.6.37 on + Versatile-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-virtual +Architecture: i386 amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Virtual processors. + . + Geared toward virtual appliances. + . + You likely do not want to install this package directly. Instead, install + the linux-virtual meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-virtual +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86/x86_64 + This package provides kernel header files for version 2.6.37 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-virtual-dbgsym +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86/x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. --- linux-2.6.37.orig/debian/control +++ linux-2.6.37/debian/control @@ -0,0 +1,1099 @@ +Source: linux +Section: devel +Priority: optional +Maintainer: Ubuntu Kernel Team +Standards-Version: 3.8.4.0 +Build-Depends: debhelper (>= 5), cpio, module-init-tools, kernel-wedge (>= 2.24ubuntu1), makedumpfile [amd64 i386], device-tree-compiler [powerpc], libelf-dev, binutils-dev, rsync, libdw-dev +Build-Depends-Indep: bzip2, sharutils +Build-Conflicts: findutils (= 4.4.1-1ubuntu1) +Vcs-Git: http://kernel.ubuntu.com/git-repos/ubuntu/ubuntu-maverick.git + +Package: linux-headers-2.6.37-graphics2+12 +Architecture: all +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0) +Provides: linux-headers, linux-headers-2.6 +Description: Header files related to Linux kernel version 2.6.37 + This package provides kernel header files for version 2.6.37, for sites + that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details + + +Package: linux-image-2.6.37-graphics2+12-generic +Architecture: i386 amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Generic processors. + . + Geared toward desktop systems. + . + You likely do not want to install this package directly. Instead, install + the linux-generic meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-generic +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86/x86_64 + This package provides kernel header files for version 2.6.37 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-generic-dbgsym +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86/x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-generic-pae +Architecture: i386 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86 + This package contains the Linux kernel image for version 2.6.37 on + x86. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Generic processors. + . + Geared toward 32 bit desktop systems with more then 4GB RAM. + . + You likely do not want to install this package directly. Instead, install + the linux-generic-pae meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-generic-pae +Architecture: i386 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86 + This package provides kernel header files for version 2.6.37 on + x86. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-generic-pae-dbgsym +Architecture: i386 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86 + This package provides a kernel debug image for version 2.6.37 on + x86. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-omap +Architecture: armel +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: flash-kernel +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on TI OMAP3-based systems + This package contains the Linux kernel image for version 2.6.37 on + TI OMAP3-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports TI OMAP3 processors. + . + Targeted towards boards such as Beagleboard, Gumstix, IGEPv2, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-omap meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-omap +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on TI OMAP3-based systems + This package provides kernel header files for version 2.6.37 on + TI OMAP3-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-omap-dbgsym +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on TI OMAP3-based systems + This package provides a kernel debug image for version 2.6.37 on + TI OMAP3-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 32-bit PowerPC + This package contains the Linux kernel image for version 2.6.37 on + 32-bit PowerPC. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 32-bit PowerPC processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 32-bit PowerPC + This package provides kernel header files for version 2.6.37 on + 32-bit PowerPC. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 32-bit PowerPC + This package provides a kernel debug image for version 2.6.37 on + 32-bit PowerPC. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc64-smp +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 64-bit PowerPC SMP + This package contains the Linux kernel image for version 2.6.37 on + 64-bit PowerPC SMP. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 64-bit PowerPC SMP processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc64-smp meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc64-smp +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 64-bit PowerPC SMP + This package provides kernel header files for version 2.6.37 on + 64-bit PowerPC SMP. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc64-smp-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 64-bit PowerPC SMP + This package provides a kernel debug image for version 2.6.37 on + 64-bit PowerPC SMP. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-powerpc-smp +Architecture: powerpc +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, ivtv-modules +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: yaboot +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on 32-bit PowerPC SMP + This package contains the Linux kernel image for version 2.6.37 on + 32-bit PowerPC SMP. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports 32-bit PowerPC SMP processors. + . + Geared toward desktop or server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-powerpc-smp meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-powerpc-smp +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on 32-bit PowerPC SMP + This package provides kernel header files for version 2.6.37 on + 32-bit PowerPC SMP. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-powerpc-smp-dbgsym +Architecture: powerpc +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on 32-bit PowerPC SMP + This package provides a kernel debug image for version 2.6.37 on + 32-bit PowerPC SMP. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-server +Architecture: amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, redhat-cluster-modules, kvm-api-4, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Server processors. + . + Geared toward 64 bit server systems. + . + You likely do not want to install this package directly. Instead, install + the linux-server meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-server +Architecture: amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86_64 + This package provides kernel header files for version 2.6.37 on + x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-server-dbgsym +Architecture: amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-versatile +Architecture: armel +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on Versatile-based systems + This package contains the Linux kernel image for version 2.6.37 on + Versatile-based systems. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Versatile processors. + . + PB, AB, Qemu, etc. + . + You likely do not want to install this package directly. Instead, install + the linux-versatile meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-versatile +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on Versatile-based systems + This package provides kernel header files for version 2.6.37 on + Versatile-based systems. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-versatile-dbgsym +Architecture: armel +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on Versatile-based systems + This package provides a kernel debug image for version 2.6.37 on + Versatile-based systems. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: linux-image-2.6.37-graphics2+12-virtual +Architecture: i386 amd64 +Section: admin +Priority: optional +Pre-Depends: dpkg (>= 1.10.24) +Provides: linux-image, linux-image-2.6, fuse-module, kvm-api-4, redhat-cluster-modules, ivtv-modules, ndiswrapper-modules-1.9 +Depends: ${misc:Depends}, ${shlibs:Depends}, initramfs-tools (>= 0.36ubuntu6), coreutils | fileutils (>= 4.0), module-init-tools (>= 3.3-pre11-4ubuntu3), wireless-crda +Conflicts: hotplug (<< 0.0.20040105-1) +Recommends: grub-pc | grub | lilo (>= 19.1) +Suggests: fdutils, linux-doc-2.6.37 | linux-source-2.6.37, linux-tools +Description: Linux kernel image for version 2.6.37 on x86/x86_64 + This package contains the Linux kernel image for version 2.6.37 on + x86/x86_64. + . + Also includes the corresponding System.map file, the modules built by the + packager, and scripts that try to ensure that the system is not left in an + unbootable state after an update. + . + Supports Virtual processors. + . + Geared toward virtual appliances. + . + You likely do not want to install this package directly. Instead, install + the linux-virtual meta-package, which will ensure that upgrades work + correctly, and that supporting packages are also installed. + +Package: linux-headers-2.6.37-graphics2+12-virtual +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends}, coreutils | fileutils (>= 4.0), linux-headers-2.6.37-graphics2+12, ${shlibs:Depends} +Provides: linux-headers, linux-headers-2.6 +Description: Linux kernel headers for version 2.6.37 on x86/x86_64 + This package provides kernel header files for version 2.6.37 on + x86/x86_64. + . + This is for sites that want the latest kernel headers. Please read + /usr/share/doc/linux-headers-2.6.37-graphics2+12/debian.README.gz for details. + +Package: linux-image-2.6.37-graphics2+12-virtual-dbgsym +Architecture: i386 amd64 +Section: devel +Priority: optional +Depends: ${misc:Depends} +Provides: linux-debug +Description: Linux kernel debug image for version 2.6.37 on x86/x86_64 + This package provides a kernel debug image for version 2.6.37 on + x86/x86_64. + . + This is for sites that wish to debug the kernel. + . + The kernel image contained in this package is NOT meant to boot from. It + is uncompressed, and unstripped. This package also includes the + unstripped modules. + +Package: kernel-image-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: kernel-image +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: extra +Description: Linux kernel binary image for the Debian installer + This package contains the kernel image for the Debian installer + boot images. It does _not_ provide a usable kernel for your full + Debian system. + +Package: nic-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: nic-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, nic-shared-modules-2.6.37-graphics2+12-generic-di, virtio-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Network interface support + +Package: nic-shared-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: nic-shared-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, crypto-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: nic shared modules + This package contains modules which support nic modules + +Package: serial-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: serial-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Serial port support + +Package: ppp-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: ppp-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, nic-shared-modules-2.6.37-graphics2+12-generic-di, serial-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: PPP (serial port) networking support + +Package: pata-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: pata-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, storage-core-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: PATA support modules + +Package: firewire-core-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: firewire-core-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, storage-core-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Firewire (IEEE-1394) Support + +Package: scsi-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: scsi-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, storage-core-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: SCSI storage support + +Package: plip-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: plip-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, nic-shared-modules-2.6.37-graphics2+12-generic-di, parport-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: PLIP (parallel port) networking support + +Package: floppy-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: floppy-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Floppy driver support + +Package: fat-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: fat-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: FAT filesystem support + This includes Windows FAT and VFAT support. + +Package: nfs-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: nfs-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: NFS filesystem drivers + Includes the NFS client driver, and supporting modules. + +Package: md-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: md-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Multi-device support (raid, device-mapper, lvm) + +Package: usb-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: usb-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, storage-core-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Core USB support + +Package: pcmcia-storage-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: pcmcia-storage-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, scsi-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: PCMCIA storage support + +Package: fb-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: fb-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Framebuffer modules + +Package: input-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: input-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, usb-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Support for various input methods + +Package: mouse-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: mouse-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, input-modules-2.6.37-graphics2+12-generic-di, usb-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: extra +Description: Mouse support + This package contains mouse drivers for the Linux kernel. + +Package: irda-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: irda-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, nic-shared-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Support for Infrared protocols + +Package: parport-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: parport-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Parallel port support + +Package: nic-pcmcia-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: nic-pcmcia-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, nic-shared-modules-2.6.37-graphics2+12-generic-di, nic-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: PCMCIA network interface support + +Package: pcmcia-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: pcmcia-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: PCMCIA Modules + +Package: nic-usb-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: nic-usb-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, nic-shared-modules-2.6.37-graphics2+12-generic-di, usb-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: USB network interface support + +Package: sata-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: sata-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, storage-core-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: SATA storage support + +Package: crypto-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: crypto-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: extra +Description: crypto modules + This package contains crypto modules. + +Package: squashfs-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: squashfs-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: extra +Description: squashfs modules + This package contains squashfs modules. + +Package: virtio-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: virtio-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: VirtIO Modules + Includes modules for VirtIO (virtual machine, generally kvm guests) + +Package: fs-core-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: fs-core-modules, jfs-modules, reiserfs-modules, xfs-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Base filesystem modules + This includes jfs, reiserfs and xfs. + +Package: fs-secondary-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: fs-secondary-modules, ntfs-modules, hfs-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, fat-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Extra filesystem modules + This includes support for Windows NTFS and MacOS HFS/HFSPlus + +Package: storage-core-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: storage-core-modules, loop-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Core storage support + Includes core SCSI, LibATA, USB-Storage. Also includes related block + devices for CD, Disk and Tape medium (and IDE Floppy). + +Package: block-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: block-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, storage-core-modules-2.6.37-graphics2+12-generic-di, parport-modules-2.6.37-graphics2+12-generic-di, virtio-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Block storage devices + This package contains the block storage devices, including DAC960 and + paraide. + +Package: message-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: message-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di, storage-core-modules-2.6.37-graphics2+12-generic-di, scsi-modules-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: standard +Description: Fusion and i2o storage modules + This package containes the fusion and i2o storage modules. + +Package: vlan-modules-2.6.37-graphics2+12-generic-di +XC-Package-Type: udeb +Provides: vlan-modules +Depends: kernel-image-2.6.37-graphics2+12-generic-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-generic +Section: debian-installer +Priority: extra +Description: vlan modules + This package contains vlan (8021.Q) modules. + +Package: kernel-image-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: kernel-image +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: extra +Description: Linux kernel binary image for the Debian installer + This package contains the kernel image for the Debian installer + boot images. It does _not_ provide a usable kernel for your full + Debian system. + +Package: nic-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: nic-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di, nic-shared-modules-2.6.37-graphics2+12-virtual-di, virtio-modules-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: Network interface support + +Package: nic-shared-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: nic-shared-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di, crypto-modules-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: nic shared modules + This package contains modules which support nic modules + +Package: ppp-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: ppp-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di, nic-shared-modules-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: PPP (serial port) networking support + +Package: scsi-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: scsi-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di, storage-core-modules-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: SCSI storage support + +Package: floppy-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: floppy-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: Floppy driver support + +Package: fat-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: fat-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: FAT filesystem support + This includes Windows FAT and VFAT support. + +Package: md-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: md-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: Multi-device support (raid, device-mapper, lvm) + +Package: fb-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: fb-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: Framebuffer modules + +Package: mouse-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: mouse-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: extra +Description: Mouse support + This package contains mouse drivers for the Linux kernel. + +Package: irda-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: irda-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di, nic-shared-modules-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: Support for Infrared protocols + +Package: parport-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: parport-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: Parallel port support + +Package: sata-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: sata-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di, storage-core-modules-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: SATA storage support + +Package: crypto-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: crypto-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: extra +Description: crypto modules + This package contains crypto modules. + +Package: squashfs-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: squashfs-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: extra +Description: squashfs modules + This package contains squashfs modules. + +Package: virtio-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: virtio-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: VirtIO Modules + Includes modules for VirtIO (virtual machine, generally kvm guests) + +Package: fs-core-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: fs-core-modules, jfs-modules, reiserfs-modules, xfs-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: Base filesystem modules + This includes jfs, reiserfs and xfs. + +Package: fs-secondary-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: fs-secondary-modules, ntfs-modules, hfs-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di, fat-modules-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: Extra filesystem modules + This includes support for Windows NTFS and MacOS HFS/HFSPlus + +Package: storage-core-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: storage-core-modules, loop-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: Core storage support + Includes core SCSI, LibATA, USB-Storage. Also includes related block + devices for CD, Disk and Tape medium (and IDE Floppy). + +Package: block-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: block-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di, storage-core-modules-2.6.37-graphics2+12-virtual-di, parport-modules-2.6.37-graphics2+12-virtual-di, virtio-modules-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: Block storage devices + This package contains the block storage devices, including DAC960 and + paraide. + +Package: message-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: message-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di, storage-core-modules-2.6.37-graphics2+12-virtual-di, scsi-modules-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: standard +Description: Fusion and i2o storage modules + This package containes the fusion and i2o storage modules. + +Package: vlan-modules-2.6.37-graphics2+12-virtual-di +XC-Package-Type: udeb +Provides: vlan-modules +Depends: kernel-image-2.6.37-graphics2+12-virtual-di +Architecture: amd64 +XB-Kernel-Version: 2.6.37-graphics2+12-virtual +Section: debian-installer +Priority: extra +Description: vlan modules + This package contains vlan (8021.Q) modules. --- linux-2.6.37.orig/debian/changelog +++ linux-2.6.37/debian/changelog @@ -0,0 +1,4962 @@ +linux (2.6.37-graphics2+12.26~lucid) lucid; urgency=low + + * Final 2.6.37 + * Merge git://git.kernel.org/pub/scm/linux/kernel/git/ickle/drm-intel.git drm-intel-next + - Up to 7fd1179aa58aeb239bddb669ddfe1326497e7012 + * Apply patch at https://bugs.freedesktop.org/show_bug.cgi?id=27187#c291 + - Poke HIC bit + wbinv + cache coherency checker + + -- Brian Rogers Wed, 05 Jan 2011 08:55:32 -0800 + +linux (2.6.37-12.26) natty; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.37-rc8 + * [Config] armel -- reenable omap flavour + * [Config] disable CONFIG_MACH_OMAP3517EVM to fix FTBS on armel omap + * [Config] disable CONFIG_GPIO_VX855 to fix FTBS on omap armel + * [Config] disable CONFIG_WESTBRIDGE_ASTORIA to fix FTBS on omap armel + * [Config] disable CONFIG_TI_DAVINCI_EMAC to fix FTBS on omap armel + * rebase to mainline 989d873fc5b6a96695b97738dea8d9f02a60f8ab + * [Config] track missing modules + * rebase to v2.6.37 final + + [ Chase Douglas ] + + * SAUCE: (drop after 2.6.37) HID: magicmouse: Don't report REL_{X, Y} for + Magic Trackpad + + [ Stefan Bader ] + + * Revert "SAUCE: blkfront: default to sd devices" + - LP: #684875 + + [ Tim Gardner ] + + * Revert "SAUCE: (no-up) libata: Ignore HPA by default." + - LP: #380138 + * [Config] Added autofs4.ko to -virtual flavour + - LP: #692917 + + [ Upstream Kernel Changes ] + + * Add support for Intellimouse Mode in ALPS touchpad on Dell E2 series + Laptops + - LP: #632884 + + [ Upstream Kernel Changes ] + + * rebase to v2.6.37-rc8 + * rebase to mainline 989d873fc5b6a96695b97738dea8d9f02a60f8ab + * rebase to v2.6.37 final + + -- Andy Whitcroft Thu, 23 Dec 2010 18:34:13 +0000 + +linux (2.6.37-11.25) natty; urgency=low + + [ Andy Whitcroft ] + + * [Config] d-i -- add hpsa to the list of block devices + - LP: #684304 + * [Config] add vmw-balloon driver to -virtual flavour + - LP: #592039 + * rebase to v2.6.37-rc7 + + [ Upstream Kernel Changes ] + + * rebase to v2.6.37-rc7 + + -- Andy Whitcroft Tue, 21 Dec 2010 13:35:28 +0000 + +linux (2.6.37-10.24) natty; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.37-rc6 + * updateconfigs following rebase to v2.6.37-rc6 + + [ Upstream Kernel Changes ] + + * rebase to v2.6.37-rc6 + + -- Andy Whitcroft Thu, 16 Dec 2010 12:34:19 +0000 + +linux (2.6.37-9.23) natty; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: vt -- fix handoff numbering to 1..n and add range checks + - LP: #689606 + * SAUCE: vt -- fix handoff numbering to 1..n and add range checks (grub) + - LP: #689606 + + [ Kees Cook ] + + * SAUCE: RO/NX protection for loadable kernel, fix ftrace + - LP: #690190 + + -- Andy Whitcroft Wed, 15 Dec 2010 19:29:57 +0000 + +linux (2.6.37-9.22) natty; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.35-rc5 + * [Config] updateconfigs following rebase to v2.6.37-rc5 + * (no-up) add support for installed header files to ubuntu directory + - LP: #684666 + * ubuntu: AUFS -- include the aufs_types.h file in linux-libc-headers + - LP: #684666 + * ubuntu: dm-raid4-5 -- follow changes to bio flags + * ubuntu: dm-raid4-5 -- re-enable + * ubuntu: omnibook -- update BOM + * ubuntu: ndiswrapper -- update BOM to match actual version + * ubuntu: ndiswrapper -- follow removal of the BKL and locked ioctl + * ubuntu: ndiswrapper -- re-enable + * ubuntu: iscsitarget -- re-instate copy_io_context + * ubuntu: iscsitarget -- follow changes to semaphore initialisation + * ubuntu: iscsitarget -- convert NIPQUAD to %pI4 + * ubuntu: iscsitarget -- re-enable + + [ Kees Cook ] + + * [Config] update config for CONFIG_DEBUG_SET_MODULE_RONX + + [ Manoj Iyer ] + + * SAUCE: Enable jack sense for Thinkpad Edge 13 + - LP: #685015 + + [ Tim Gardner ] + + * [Config] CONFIG_9P_FSCACHE=y,CONFIG_9P_FS_POSIX_ACL=y + * [Config] CONFIG_CRYPTO_CRC32C=y + - LP: #681819 + * [Config] CONFIG_9P_FSCACHE=n + * [Config] Add nfsd modules to -virtual flavour + - LP: #688070 + + [ Upstream Kernel Changes ] + + * Revert "Staging: zram: work around oops due to startup ordering snafu" + * NFS: Fix panic after nfs_umount() + - LP: #683938 + * x86: Add NX protection for kernel data + * x86: Add RO/NX protection for loadable kernel modules + * x86: Resume trampoline must be executable + * x86: RO/NX protection for loadable kernel, jump_table fix + + [ Upstream Kernel Changes ] + + * rebase to v2.6.37-rc5 + + -- Andy Whitcroft Thu, 09 Dec 2010 18:15:35 +0000 + +linux (2.6.37-8.21) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "ubuntu: AUFS -- include the aufs_types.h file in + linux-libc-headers" + * Revert "(no-up) add support for installed header files to ubuntu + directory" + + -- Andy Whitcroft Sun, 05 Dec 2010 17:33:28 +0000 + +linux (2.6.37-8.20) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Upstream] drivers/serial/mfd.c: Fix ARM compile error" + * Revert "SAUCE: Nouveau: Disable acceleration on MacBook Pros" + * Revert "SAUCE: Nouveau: Add quirk framework to disable acceleration" + * Revert "SAUCE: i915 -- disable powersave by default" + * SAUCE: enable Marvell 9128 PCIe SATA controller + - LP: #658521 + * [Config] evtchn has been renamed + * (no-up) add support for installed header files to ubuntu directory + - LP: #684666 + * ubuntu: AUFS -- include the aufs_types.h file in linux-libc-headers + - LP: #684666 + + [ Tim Gardner ] + + * [Config] MISS: evtchn, NEW : xen-evtchn + * rebase to v2.6.37-rc4 + + [ Upstream Kernel Changes ] + + * drm/i915: Clean conflicting modesetting registers upon init + - LP: #683775 + * rebase to v2.6.37-rc4 + + -- Andy Whitcroft Fri, 03 Dec 2010 18:42:07 +0000 + +linux (2.6.37-7.19) natty; urgency=low + + [ Tim Gardner ] + + * [Config] Add bnx2 firmware to nic-modules udeb + - LP: #676245 + + -- Andy Whitcroft Fri, 26 Nov 2010 17:53:45 +0000 + +linux (2.6.37-7.18) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Upstream] USB: option: Remove duplicate AMOI_VENDOR_ID" + * Revert "SAUCE: Add extra headers to linux-libc-dev" + * Revert "SAUCE: Enable speedstep for sonoma processors." + * [Config] enable CONFIG_BT_HCIUART_ATH3K + * [Config] enable CONFIG_IWLWIFI_DEBUGFS + * [Config] standardise CONFIG_MII + * [Config] standardise CONFIG_PRISM2_USB + * [Config] standardise CONFIG_SCSI_QLA_ISCSI + * [Config] build in CONFIG_AGP + * [Config] build in CONFIG_AGP_INTEL + * [Config] build in CONFIG_AGP_AMD + * [Config] build in CONFIG_AGP_AMD64 + * [Config] build in CONFIG_AGP_NVIDIA + * [Config] build in CONFIG_AGP_VIA + * [Config] disable CONFIG_SCSI_QLA_ISCSI for FTBS (arm) + * (no-up): document the new ## scheme + * [Config] harmonise CONFIG_SERIAL_8250_NR_UARTS + * [Config] update CONFIG_SERIAL_8250_RUNTIME_UARTS=32 + - LP: #675453 + + [ Mathieu J. Poirier ] + + * SAUCE: ARM: Adding vdd_sdi regulator supply to OMAP3EVM + + [ Upstream Kernel Changes ] + + * nx-emu: fix inverted report of disable_nx + + -- Andy Whitcroft Tue, 23 Nov 2010 21:00:39 +0000 + +linux (2.6.37-6.17) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "ubuntu: AUFS -- aufs2-standalone.patch + aufs2.1-36-UNRELEASED-20101103" + * Revert "ubuntu: AUFS -- aufs2-base.patch + aufs2.1-36-UNRELEASED-20101103" + * [Config] standardise CONFIG_BT + * [Config] standardise CONFIG_IRDA + * [Config] standardise CONFIG_LAPB + * [Config] standardise CONFIG_RDS + * [Config] standardise CONFIG_RFKILL + * [Config] standardise CONFIG_TIPC + * [Config] standardise CONFIG_X25 + * [Config] standardise CONFIG_INPUT_EVDEV + * [Config] standardise CONFIG_INPUT_JOYDEV + * [Config] standardise CONFIG_INPUT_JOYSTICK + * [Config] standardise CONFIG_INPUT_TOUCHSCREEN + * [Config] CONFIG_INPUT_TOUCHSCREEN=n for FTBS (arm) + * [Config] CONFIG_IRDA=n for FTBS (arm) + * ubuntu: AUFS -- aufs2-base.patch aufs2.1-37 + * ubuntu: AUFS -- aufs2-standalone.patch aufs2.1-37 + * ubuntu: AUFS -- update to 097bf62d6f49619359d34bf17f242df38562489a + + [ Tim Gardner ] + + * SAUCE: Fix drivers/staging/easycap FTBS + * [Config] CONFIG_EASYCAP=m after fixing FTBS + + [ Upstream Kernel Changes ] + + * Revert "x86: Add NX protection for kernel data" + + -- Andy Whitcroft Mon, 22 Nov 2010 18:09:10 +0000 + +linux (2.6.37-6.16) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Config] update config for CONFIG_DEBUG_SET_MODULE_RONX" + * rebase to v2.6.37-rc3 + + [ Tim Gardner ] + + * [Config] CONFIG_SCHED_AUTOGROUP=y + + [ Upstream Kernel Changes ] + + * Revert "x86: Add RO/NX protection for loadable kernel modules" + * sched: automated per session task groups + * rebase to v2.6.37-rc3 + + -- Andy Whitcroft Mon, 22 Nov 2010 10:11:13 +0000 + +linux (2.6.37-6.15) natty; urgency=low + + [ Andy Whitcroft ] + + * [Config] standardise CONFIG_CEPH_FS + * [Config] standardise CONFIG_SCSI_LPFC_DEBUG_FS + * [Config] standardise CONFIG_SCSI_PROC_FS + * [Config] standardise CONFIG_UBIFS_FS + * [Config] standardise CONFIG_USB_GADGET_DEBUG_FS + + [ Kees Cook ] + + * [Config] update config for CONFIG_DEBUG_SET_MODULE_RONX + + [ Manoj Iyer ] + + * SAUCE: Enable jack sense for Thinkpad Edge 11 + - LP: #677210 + * SAUCE: enable rfkill for rtl8192se driver + - LP: #640992 + + [ Tim Gardner ] + + * [Config] CONFIG_EASYCAP=n for FTBS + * Rebase to v2.6.32-rc2+git + + [ Upstream Kernel Changes ] + + * x86: Fix improper large page preservation + * x86: Add NX protection for kernel data + * x86: Add RO/NX protection for loadable kernel modules + + [ Upstream Kernel Changes ] + + * Rebase to Linus 2.6.37-rc2+git + + -- Andy Whitcroft Sat, 20 Nov 2010 11:40:00 +0000 + +linux (2.6.37-5.14) natty; urgency=low + + [ Upstream Kernel Changes ] + + * PCI: fix offset check for sysfs mmapped files + - LP: #676963 + + -- Andy Whitcroft Thu, 18 Nov 2010 18:12:27 +0000 + +linux (2.6.37-5.13) natty; urgency=low + + [ Andy Whitcroft ] + + * rebased to v2.6.37-rc2 + * updateconfigs following rebase to v2.6.37-rc2 + + [ Tim Gardner ] + + * [Config] Added NFS and related modules to virtual flavour + - LP: #659084 + + [ Upstream Kernel Changes ] + + * x86, cpu: Rename verify_cpu_64.S to verify_cpu.S + * x86, cpu: Clear XD_DISABLED flag on Intel to regain NX + * x86, cpu: Call verify_cpu during 32bit CPU startup + * x86, cpu: Only CPU features determine NX capabilities + + [ Upstream Changes ] + + * rebased to v2.67.37-rc2 + + -- Andy Whitcroft Tue, 16 Nov 2010 13:13:29 +0000 + +linux (2.6.37-4.12) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Upstream] HID: magicmouse: add param for scroll speed" + * Revert "[Upstream] HID: magicmouse: properly account for scroll + movement in state" + * Revert "[Upstream] HID: magicmouse: disable and add module param for + scroll acceleration" + * Revert "[Upstream] HID: magicmouse: scroll on entire surface, not just + middle of mouse" + + [ Henrik Rydberg ] + + * SAUCE: hid: ntrig: remove sysfs nodes + * SAUCE: hid: ntrig: Setup input filtering manually + * SAUCE: hid: ntrig: New ghost-filtering event logic + + [ Manoj Iyer ] + + * SAUCE: Added quirk to recognize GE0301 3G modem as an interface. + - LP: #348861 + + [ Upstream Kernel Changes ] + + * Revert "mmc: fix all hangs related to mmc/sd card insert/removal during + suspend/resume" + * Revert "[ARM] implement arch_randomize_brk()" + * Revert "ARM: stack protector: change the canary value per task" + * Revert "ARM: initial stack protector (-fstack-protector) support" + * Revert "ALSA: hda - Handle pin NID 0x1a on ALC259/269" + * Revert "ALSA: hda - Handle missing NID 0x1b on ALC259 codec" + * Revert "perf probe: Add kernel source path option" + * hid: ntrig: Support single-touch devices + * hid: ntrig: Mask pen switch events + * net: rtnetlink.h -- only include linux/netdevice.h when used by the + kernel + - LP: #673073 + * Fix userspace build of linux/fs.h + + -- Andy Whitcroft Mon, 15 Nov 2010 19:31:44 +0000 + +linux (2.6.37-3.11) natty; urgency=low + + [ Andy Whitcroft ] + + * Revert "ubuntu: AUFS -- update to + b37c575759dc4535ccc03241c584ad5fe69e3b25" + * Revert "ubuntu: AUFS -- track changes to the arguements to fop fsync()" + * Revert "ubuntu: AUFS -- update to standalone 2.6.35-rcN as at 20100601" + * Revert "ubuntu: AUFS -- update to standalone 2.6.34 as at 20100601" + * Revert "ubuntu: AUFS -- aufs2 base patch for linux-2.6.34" + * [Config] Disable intel_idle for -virtual kernels + - LP: #651370 + * [Config] enforcer -- ensure we never enable CONFIG_IMA + * debian -- pass the correct flavour name when checking configs + * [Config] enforcer -- ensure CONFIG_INTEL_IDLE is off for -virtual + * [Config] ensure CONFIG_IPV6=y for powerpc + * [Config] enforcer -- ensure CONFIG_IPV6=y + * ubuntu: AUFS -- aufs2-base.patch aufs2.1-36-UNRELEASED-20101103 + * ubuntu: AUFS -- aufs2-standalone.patch aufs2.1-36-UNRELEASED-20101103 + * ubuntu: AUFS -- update to aufs2.1-36-UNRELEASED-20101103 + * ubuntu: AUFS -- re-enable + * ubuntu: AUFS -- track changes to work queue initialisation + * ubuntu: AUFS -- track changes to llseek in v2.6.37-rc1 + * SAUCE: fbcon -- fix race between open and removal of framebuffers + * SAUCE: fbcon -- fix OOPs triggered by race prevention fixes + - LP: #614008 + * SAUCE: drm -- stop early access to drm devices + + [ Jeremy Kerr ] + + * [Config] Build-in powermac ZILOG serial driver + - LP: #673346 + + [ Kees Cook ] + + * SAUCE: nx-emu: use upstream ASLR when possible + + [ Tim Gardner ] + + * [Config] Use correct be2iscsi module name in d-i/modules/scsi-modules + - LP: #628776 + + [ Upstream Kernel Changes ] + + * i386: NX emulation + * nx-emu: drop exec-shield sysctl, merge with disable_nx + * nx-emu: standardize boottime message prefix + * mmap randomization for executable mappings on 32-bit + * exec-randomization: brk away from exec rand area + + -- Andy Whitcroft Thu, 11 Nov 2010 23:46:37 +0000 + +linux (2.6.37-2.10) natty; urgency=low + + [ Andy Whitcroft ] + + * reinstate armel config changes: + * [Config] CONFIG_GPIO_PCH=n for armel FTBS + * [Config] CONFIG_GPIO_VX855=n for armel FTBS + + -- Andy Whitcroft Wed, 03 Nov 2010 22:20:35 +0000 + +linux (2.6.37-2.9) natty; urgency=low + + [ Andy Whitcroft ] + + * config -- fix genportsconfig + * [Config] move powerpc over from ports to distro + * bump master version number to match contained kernel + * SAUCE: fix documentation strings for struct input_keymap_entry + * usb: gadget: goku_udc: add registered flag bit + + -- Andy Whitcroft Tue, 02 Nov 2010 15:14:11 +0000 + +linux (2.6.36-2.8) natty; urgency=low + + [ Tim Gardner ] + + * [Config]: fix changed CONFIG_SYSFS_DEPRECATED_V2 enforcement rules + * [Config]: TWL4030_CORE=n for FTBS + * [Config]: CONFIG_ATH6K_LEGACY=n for FTBS + * [Config]: CONFIG_SOLO6X10=n for FTBS + * [Config]: CONFIG_GPIO_PCH=n for armel FTBS + * [Config]: CONFIG_GPIO_VX855=n for armel FTBS + * [Config]: CONFIG_DRM_NOUVEAU=n for armel FTBS + * [Config]: CONFIG_LINE6_USB=n for armel FTBS + * [Config]: CONFIG_SENSORS_AK8975=n for armel FTBS + * [Config]: CONFIG_I2C_I801=n for armel FTBS + * UBUNTU: SAUCE: AppArmor: Fix unpack of network tables. + * AppArmor: compatibility patch for v5 interface + * AppArmor: compatibility patch for v5 network controll + * Dropped (pre-stable): input: Support Clickpad devices in ClickZone mode + * Dropped: UBUNTU: SAUCE: libata: Add ALPM power state accounting to the AHCI driver + * Dropped: UBUNTU: SAUCE: Added quirk to recognize GE0301 3G modem as an interface. + * Dropped: hid: 3m: Convert to MT slots + * Dropped: HID: magicmouse: don't allow hidinput to initialize the device + * Dropped: HID: magicmouse: simplify touch data bit manipulation + * Dropped: HID: magicmouse: simplify touch down logic + * Dropped: HID: magicmouse: enable Magic Trackpad support + * Dropped: UBUNTU: SAUCE: hid: ntrig: remove sysfs nodes + * Dropped: UBUNTU: SAUCE: hid: ntrig: Setup input filtering manually + * Dropped: UBUNTU: SAUCE: hid: ntrig: New ghost-filtering event logic + * Dropped: UBUNTU: SAUCE: hid: ntrig: identify firmware version (wiggled) + * Dropped: UBUNTU: (pre-stable): input: Support Clickpad devices in ClickZone mode + * Dropped: UBUNTU: SAUCE: KMS: cache the EDID information of the LVDS + * Dropped: UBUNTU: SAUCE: fbcon -- fix race between open and removal of framebuffers + * Dropped: UBUNTU: SAUCE: fbcon -- fix OOPs triggered by race prevention fixes + * Dropped: UBUNTU: SAUCE: x86: implement cs-limit nx-emulation for ia32 + * Dropped: UBUNTU: SAUCE: x86: more tightly confine cs-limit nx-emulation to ia32 only + * Dropped: UBUNTU: SAUCE: [um] Don't use nx_enabled under UML + * Dropped: UBUNTU: SAUCE: x86: brk away from exec rand area + + [ Upstream Kernel Changes ] + + * rebased against 2.6.27-rc1 + + -- Tim Gardner Fri, 22 Oct 2010 19:35:05 -0600 + +linux (2.6.36-1.7) natty; urgency=low + + [ Andy Whitcroft ] + + * rebased to v2.6.36 final + * [Config] update configs following rebase to v2.6.36 final + * [Config] update ports configs following rebase to v2.6.36 final + + [ Upstream Kernel Changes ] + + * rebased to v2.6.36 final + + -- Andy Whitcroft Thu, 21 Oct 2010 14:28:57 +0100 + +linux (2.6.36-1.6) natty; urgency=low + + [ Upstream Kernel Changes ] + + * drop broadcom staging driver preview: + * Revert "Staging: Add initial release of brcm80211 - Broadcom 802.11n + wireless LAN driver." + + -- Andy Whitcroft Wed, 20 Oct 2010 10:41:25 +0100 + +linux (2.6.36-1.5) natty; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.36-rc8 + * updateconfigs following rebase to v2.6.36-rc8 + * updateportsconfigs following rebase to v2.6.36-rc8 + * config -- simplify the kernelconfig interface + * config -- add new config mode 'dumpconfigs' + + [ Tim Gardner ] + + * Simplify the use of CROSS_COMPILER + + [ Upstream Kernel Changes ] + + * drop broadcom staging driver preview: + * Revert "staging: brcm80211: Make compiling of brcm80211.ko and + brcmfmac.ko mutually exclusive." + * Revert "staging: brcm80211: Fix compile issue when BRCM80211_PCI is not + set." + * Revert "Staging: brcm80211: remove driver specific -W options" + * Revert "Staging: brcm80211: clean up makefile cflag lines" + * Revert "staging: brcm80211: add fullmac driver" + * Revert "staging: brcm80211: use string native library" + * Revert "staging: brcm80211: use native ctype library" + * Revert "staging: brcm80211: fix remaining checkpatch errors." + * Revert "staging: brcm80211: fix "ERROR: trailing whitespace."" + * Revert "staging: brcm80211: fix "ERROR: spaces required around that + ..."" + * Revert "staging: brcm80211: fix "ERROR: spaces prohibited around that + ':' ..."" + * Revert "staging: brcm80211: fix "ERROR: space required before that + ..."" + * Revert "staging: brcm80211: fix "ERROR: space required after that ..."" + * Revert "staging: brcm80211: fix "ERROR: space required after that close + brace"" + * Revert "staging: brcm80211: fix "ERROR: space prohibited before + ...close square bracket"" + * Revert "staging: brcm80211: fix "ERROR: space prohibited after that + ..."" + * Revert "staging: brcm80211: fix "ERROR: need consistent spacing around + '*'"" + * Revert "staging: brcm80211: fix 'ERROR: "(foo*)" should be "(foo *)"'" + * Revert "staging: brcm80211: fix "ERROR: Macros w/ mult. statements ... + do - while loop"" + * Revert "staging: brcm80211: fix "ERROR: Macros w/ complex values ... + parenthesis"" + * Revert "staging: brcm80211: fix "ERROR: do not initialise statics to 0 + or NULL"" + * Revert "staging: brcm80211: fix "ERROR: do not initialise globals to 0 + or NULL"" + * Revert "staging: brcm80211: fix "ERROR: while should follow close brace + '}'"" + * Revert "staging: brcm80211: fix "ERROR: that open brace { ... prev + line"" + * Revert "staging: brcm80211: fix "ERROR: trailing statements should be + on next line"" + * Revert "staging: brcm80211: fix "ERROR: do not use assignment in if + condition"" + * Revert "staging: brcm80211: fix "ERROR: return is not a function, + paren..."" + * Revert "staging: brcm80211: fix "ERROR: open brace '{' following + function dec..."" + * Revert "staging: brcm80211: fix 'ERROR: "foo * bar" should be "foo + *bar"'" + * Revert "staging: brcm80211: Fix URLs for firmware files." + * Revert "staging: brcm80211: use '%pM' format to print MAC address" + * Revert "staging: brcm80211: Add contact info to TODO list." + * Revert "staging: brcm80211: Fix some initialisation failure paths" + * Export dump_{write,seek} to binary loader modules + * rebase to v2.6.36-rc8. + + -- Andy Whitcroft Tue, 19 Oct 2010 18:58:11 +0100 + +linux (2.6.36-0.4) natty; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: perf: increase stack footprint to avoid stack-protector warning + (fixes FTBS on powerpc) + + -- Andy Whitcroft Thu, 14 Oct 2010 13:16:16 +0100 + +linux (2.6.36-0.3) natty; urgency=low + + [ Andy Whitcroft ] + + * [Config] disable CONFIG_SCSI_QLA_ISCSI to fix FTBS on powerpc + + -- Andy Whitcroft Thu, 14 Oct 2010 03:01:30 +0100 + +linux (2.6.36-0.2) natty; urgency=low + + [ Andy Whitcroft ] + + * [Config] updateportsconfigs following rebase to 2.6.36-rc7 + (fix FTBS on powerpc) + + -- Andy Whitcroft Wed, 13 Oct 2010 23:25:12 +0100 + +linux (2.6.36-0.1) natty; urgency=low + + [ Andy Whitcroft ] + + * reduce disk usage during buildd builds + - LP: #645653 + * [Config] enforcer -- ensure CONFIG_INIT_PASS_ALL_PARAMS is y + * [Config] armel -- drop omap flavour + + [ Tim Gardner ] + + * Added dropped patch list + * more dropped patches + * [Config] Disable aufs, dmraid-4.5, ndis-wrapper + * [Config] Add support for cross compiling armel + * [Config] CONFIG_SCSI_QLA_ISCSI=n for armel + * [Upstream] drivers/serial/mfd.c: Fix ARM compile error + * [Config]: updateconfigs after adding brcm80211 + * staging: brcm80211: Fix Makefile syntax error + * rebased to v2.6.36-rc7 + + [ Upstream Kernel Changes ] + + * (upstream) IPS driver: don't toggle CPU turbo on unsupported CPUs + * (upstream) IPS driver: verify BIOS provided limits + * intel_ips: Print MCP limit exceeded values. + * Staging: Add initial release of brcm80211 - Broadcom 802.11n wireless + LAN driver. + * staging: brcm80211: Fix some initialisation failure paths + * staging: brcm80211: Add contact info to TODO list. + * staging: brcm80211: use '%pM' format to print MAC address + * staging: brcm80211: Fix URLs for firmware files. + * staging: brcm80211: fix 'ERROR: "foo * bar" should be "foo *bar"' + * staging: brcm80211: fix "ERROR: open brace '{' following function + dec..." + * staging: brcm80211: fix "ERROR: return is not a function, paren..." + * staging: brcm80211: fix "ERROR: do not use assignment in if condition" + * staging: brcm80211: fix "ERROR: trailing statements should be on next + line" + * staging: brcm80211: fix "ERROR: that open brace { ... prev line" + * staging: brcm80211: fix "ERROR: while should follow close brace '}'" + * staging: brcm80211: fix "ERROR: do not initialise globals to 0 or NULL" + * staging: brcm80211: fix "ERROR: do not initialise statics to 0 or NULL" + * staging: brcm80211: fix "ERROR: Macros w/ complex values ... + parenthesis" + * staging: brcm80211: fix "ERROR: Macros w/ mult. statements ... do - + while loop" + * staging: brcm80211: fix 'ERROR: "(foo*)" should be "(foo *)"' + * staging: brcm80211: fix "ERROR: need consistent spacing around '*'" + * staging: brcm80211: fix "ERROR: space prohibited after that ..." + * staging: brcm80211: fix "ERROR: space prohibited before ...close square + bracket" + * staging: brcm80211: fix "ERROR: space required after that close brace" + * staging: brcm80211: fix "ERROR: space required after that ..." + * staging: brcm80211: fix "ERROR: space required before that ..." + * staging: brcm80211: fix "ERROR: spaces prohibited around that ':' ..." + * staging: brcm80211: fix "ERROR: spaces required around that ..." + * staging: brcm80211: fix "ERROR: trailing whitespace." + * staging: brcm80211: fix remaining checkpatch errors. + * staging: brcm80211: use native ctype library + * staging: brcm80211: use string native library + * staging: brcm80211: add fullmac driver + * Staging: brcm80211: clean up makefile cflag lines + * Staging: brcm80211: remove driver specific -W options + * staging: brcm80211: Fix compile issue when BRCM80211_PCI is not set. + * staging: brcm80211: Make compiling of brcm80211.ko and brcmfmac.ko + mutually exclusive. + + -- Andy Whitcroft Tue, 12 Oct 2010 16:00:27 +0100 + +linux (2.6.35-22.33) maverick; urgency=low + + [ Andy Whitcroft ] + + * Revert "SAUCE: Add support for Intellimouse Mode in ALPS touchpad on + Dell E2 series Laptops" + - LP: #641320 + + [ Brian Rogers ] + + * SAUCE: ir-core: Fix null dereferences in the protocols sysfs interface + - LP: #624701 + + [ Christopher James Halse Rogers ] + + * SAUCE: Nouveau: Add quirk framework to disable acceleration + - LP: #544088, #546393 + * SAUCE: Nouveau: Disable acceleration on MacBook Pros + - LP: #546393 + + [ John Johansen ] + + * Revert "SAUCE: AppArmor: allow newer tools to load policy on older + kernels" + * SAUCE: AppArmor: allow newer tools to load policy on older kernels + - LP: #639758 + + [ Mathieu J. Poirier ] + + * SAUCE: Adding vdd_sdi regulator supply to OMAP3EVM + + [ Upstream Kernel Changes ] + + * ALSA: HDA: Enable internal speaker on Dell M101z + - LP: #640254 + + -- Leann Ogasawara Fri, 17 Sep 2010 13:21:28 -0700 + +linux (2.6.35-22.32) maverick; urgency=low + + [ Arjan van de Ven ] + + * SAUCE: libata: Add ALPM power state accounting to the AHCI driver + + [ David Henningsson ] + + * SAUCE: ALSA: HDA: Enable internal mic on Dell E6410 and Dell E6510 + - LP: #605047, #628961 + + [ John Johansen ] + + * [Upstream] AppArmor: Fix splitting an fqname into separate namespace + and profile names + - LP: #615947 + * [Upstream] AppArmor: Fix locking from removal of profile namespace + - LP: #615947 + * SAUCE: AppArmor: allow newer tools to load policy on older kernels + - LP: #639758 + * SAUCE: Improve Amazon EBS performance for EC2 + - LP: #634316 + + [ Leann Ogasawara ] + + * Revert "SAUCE: i915 KMS -- blacklist i855" + * Revert "SAUCE: i915 KMS -- blacklist i845g" + * Revert "SAUCE: i915 KMS -- blacklist i830" + * Revert "SAUCE: i915 KMS -- support disabling KMS for known broken + devices" + * execute module-inclusion within a subshell + - LP: #621175 + + [ Upstream Kernel Changes ] + + * (pre-stable) bounce: call flush_dcache_page() after bounce_copy_vec() + - LP: #633227 + * (pre-stable) drm/i915: don't enable self-refresh on Ironlake + - LP: #629711 + * (pre-stable) mm: Move vma_stack_continue into mm.h + * x86, hwmon: Fix unsafe smp_processor_id() in thermal_throttle_add_dev + - LP: #601073 + * PM / Runtime: Make runtime_status attribute not debug-only (v. 2) + * PM / Runtime: Add runtime PM statistics (v3) + * compat: Make compat_alloc_user_space() incorporate the access_ok() + - CVE-2010-3081 + * x86-64, compat: Test %rax for the syscall number, not %eax + - CVE-2010-3301 + * x86-64, compat: Retruncate rax after ia32 syscall entry tracing + - CVE-2010-3301 + + -- Leann Ogasawara Tue, 14 Sep 2010 08:46:49 -0700 + +linux (2.6.35-21.31) maverick; urgency=low + + [ Andy Whitcroft ] + + * bodge linux-libc-dev package version due to ti-omap4 error + * linux-libc-dev -- ensure we can only build this on debian.master + + -- Leann Ogasawara Mon, 13 Sep 2010 09:54:31 -0700 + +linux (2.6.35-21.30) maverick; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: fbcon -- fix OOPs triggered by race prevention fixes + - LP: #614008 + + [ Daniel Lezcano ] + + * SAUCE: fix compilation warning when CONFIG_SECURITY is not set + + [ Henrik Rydberg ] + + * SAUCE: Input: wacom - add fuzz parameters to features + * SAUCE: Input: wacom - collect device quirks into single function + * SAUCE: Input: wacom - add support for the Bamboo Touch trackpad + * SAUCE: Input: wacom - add a quirk for low resolution Bamboo devices + * SAUCE: hid: ntrig: Remove unused device ids + * SAUCE: hid: ntrig: remove sysfs nodes + * SAUCE: hid: ntrig: Correct logic for quirks + * SAUCE: hid: ntrig: zero-initialize ntrig struct + * SAUCE: hid: ntrig: Setup input filtering manually + * SAUCE: hid: ntrig: New ghost-filtering event logic + + [ Leann Ogasawara ] + + * SAUCE: ndiswrapper: Initialize buffer index and check its value + - LP: #613796 + + [ Manoj Iyer ] + + * SAUCE: Add support for Intellimouse Mode in ALPS touchpad on Dell E2 + series Laptops + - LP: #632884 + + [ Ping Cheng ] + + * SAUCE: Input: wacom - parse the Bamboo device family + + [ Rafi Rubin ] + + * SAUCE: hid: ntrig: identify firmware version (wiggled) + + [ Tim Gardner ] + + * [Config] CONFIG_NL80211_TESTMODE=n + + [ Upstream Kernel Changes ] + + * Revert "input: mt: Add support for the Bamboo Touch trackpad" + * e1000e: initial support for 82579 LOMs + * e1000e: correct MAC-PHY interconnect register offset for 82579 + * (pre-stable) ALSA: hda - Add a new hp-laptop model for Conexant 5066, + tested on HP G60 + - LP: #587388 + * DSS2: Don't power off a panel twice + - LP: #588243 + * mmc: build fix: mmc_pm_notify is only available with CONFIG_PM=y + * Input: i8042 - reset keyboard controller wehen resuming from S2R + - LP: #86820 + * ALSA: hda - Fix beep frequency on IDT 92HD73xx and 92HD71Bxx codecs + - LP: #414795 + * agp/intel: Support the extended physical addressing bits on + Sandybridge. + - LP: #632488 + * drm/i915,intel_agp: Add support for Sandybridge D0 + - LP: #632488 + * (pre-stable) intel_agp,i915: Add more sandybridge graphics device ids + - LP: #632488 + * mmc: omap: fix for bus width which improves SD card's peformance. + + -- Leann Ogasawara Tue, 07 Sep 2010 09:58:52 -0700 + +linux (2.6.35-20.29) maverick; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: i915 KMS -- support disabling KMS for known broken devices + - LP: #563277 + * SAUCE: i915 KMS -- blacklist i830 + - LP: #542208, #563277 + * SAUCE: i915 KMS -- blacklist i845g + - LP: #541492, #563277 + * SAUCE: i915 KMS -- blacklist i855 + - LP: #511001, #541511, #563277 + + [ Leann Ogasawara ] + + * [Config] Enable CONFIG_SENSORS_PKGTEMP=m + - LP: #601073 + * ARM: Temporarily disable module check for armel + * rebase to v2.6.35.4 + * [Config] update configs following rebase to v2.6.35.4 + + [ Ricardo Salveti de Araujo ] + + * [Config] Change CONFIG_LEDS_TRIGGER_HEARTBEAT from module to built-in + in Omap + + [ Tim Gardner ] + + * [Config] Added be2net, be2scsi to udebs + - LP: #628776 + + [ Upstream Kernel Changes ] + + * x86, cpu: Package Level Thermal Control, Power Limit Notification + definitions + - LP: #601073 + * x86, hwmon: Package Level Thermal/Power: pkgtemp hwmon driver + - LP: #601073 + * x86, hwmon: Package Level Thermal/Power: thermal throttling handler + - LP: #601073 + * x86, hwmon: Package Level Thermal/Power: power limit + - LP: #601073 + * x86, hwmon: Package Level Thermal/Power: pkgtemp documentation + - LP: #601073 + * hid: 3m: Adjust to sequential MT HID protocol + * hid: 3m: Convert to MT slots + * hid: 3m: Correct touchscreen emulation + * hid: 3m: Adjust major / minor axes to scale + * input: bcm5974: Adjust major / minor to scale + * HID: magicmouse: don't allow hidinput to initialize the device + * HID: magicmouse: simplify multitouch feature request + * HID: magicmouse: simplify touch data bit manipulation + * HID: magicmouse: simplify touch down logic + * HID: magicmouse: remove timestamp logic + * HID: magicmouse: enable Magic Trackpad support + * HID: magicmouse: Adjust major / minor axes to scale + * mmc: fix all hangs related to mmc/sd card insert/removal during + suspend/resume + - LP: #477106 + * drm/i915: fix VGA plane disable for Ironlake+ + - LP: #602281 + + -- Leann Ogasawara Mon, 30 Aug 2010 08:38:01 -0700 + +linux (2.6.35-19.28) maverick; urgency=low + + [ Leann Ogasawara ] + + * No changes from 2.6.35-19.27. Some armel udebs were accidentally deleted + from the archive and a no-change rebuild was attempted. However, the ABI + did not get bumped and resulted in build failures for 2.6.35-19.27. Fix + up the ABI and re-upload. + + -- Leann Ogasawara Sat, 28 Aug 2010 16:42:27 -0700 + +linux (2.6.35-19.27) maverick; urgency=low + + [ Leann Ogasawara ] + + * No changes from 2.6.35-19.26. Some armel udebs were accidentally deleted + from the archive. + + -- Leann Ogasawara Fri, 27 Aug 2010 08:58:35 -0700 + +linux (2.6.35-19.26) maverick; urgency=low + + [ Upstream Kernel Changes ] + + * ARM: OMAP: Beagle: revision detection + * ARM: OMAP: Beagle: only Cx boards use pin 23 for write protect + * ARM: OMAP: Beagle: no gpio_wp pin connection on xM + + -- Leann Ogasawara Thu, 26 Aug 2010 09:15:09 -0700 + +linux (2.6.35-19.25) maverick; urgency=low + + [ Jarod Wilson ] + + * SAUCE: Bring in staging/lirc from 2.6.36 + - LP: #609234 + * SAUCE: Update ir-core to linuxtv/other which should be merged for + 2.6.36. + - LP: #609234 + * SAUCE: Fix memleaks in imon and mceusb drivers + - LP: #609234 + * SAUCE: Bring in streamzap support from linuxtv/other + - LP: #609234 + + [ Mario Limonciello ] + + * Remove ubuntu/lirc in favor of staging/lirc from 2.6.36 + - LP: #609234 + + [ Mathieu J. Poirier ] + + * SAUCE: ARM: adding i2c eeprom driver to read EDID + - LP: #608279 + + [ Upstream Kernel Changes ] + + * intel_idle: disable module support + - LP: #615265 + * (pre-stable) ALSA: hda - Ensure codec patch files are checked for the + correct codec ID + * (pre-stable) ALSA: hda - Rename iMic to Int Mic on Lenovo NB0763 + - LP: #605101 + * (pre-stable) ALSA: HDA: Use model=auto for LG R510 + - LP: #495134 + * (pre-stable) ALSA: HDA: Add Sony VAIO quirk for ALC269 + - LP: #519066 + * (pre-stable) ALSA: HDA: Fix front mic on Dell Precision M6500 + - LP: #519066 + * input: mt: Initialize slots to unused (rev2) + * input: mt: Add support for the Bamboo Touch trackpad + * hid: Add a hid quirk for input sync override + + -- Leann Ogasawara Mon, 23 Aug 2010 12:42:52 -0700 + +linux (2.6.35-18.24) maverick; urgency=low + + [ Colin Watson ] + + * Pass DEB_MAINT_PARAMS to hook scripts + + [ Leann Ogasawara ] + + * [Config] Add CONFIG_INPUT_UINPUT=y to config enforcer + - LP: #584812 + * rebase to v2.6.35.3 + + [ Upstream Kernel Changes ] + + * (pre-stable) dell-wmi: Add support for eject key on Dell Studio 1555 + - LP: #609234 + * can: add limit for nframes and clean up signed/unsigned variables + - CVE-2010-2959 + * drm: Initialize ioctl struct when no user data is present + - CVE-2010-2803 + * ARM: initial stack protector (-fstack-protector) support + * ARM: stack protector: change the canary value per task + * [ARM] implement arch_randomize_brk() + * [ARM] add address randomization to mmap() + * ARM: fix ASLR of PIE executables + + -- Leann Ogasawara Sun, 22 Aug 2010 19:22:04 -0700 + +linux (2.6.35-17.23) maverick; urgency=low + + [ Jeremy Kerr ] + + * [Config] build-in uinput module + - LP: #584812 + + [ Leann Ogasawara ] + + * Revert "[Config] [FTBS] ia64: Temporarily disable CONFIG_CEPH_FS" + * Revert "[Config] [FTBS] ia64: Temporarily disable gpiolib" + * Revert "[Config] [FTBS] sparc: Temporarily disable + CONFIG_MTD_NAND_DENALI" + * Revert "[Config] [FTBS] sparc: Temporarily disable + CONFIG_MFD_JANZ_CMODIO" + * Revert "[Config] [FTBS] sparc: Temporarily disable + CONFIG_INFINIBAND_QIB" + * [Config] Enable INTEL_IPS + - LP: #601057 + * Remove ia64 support + * [Config] Update portsconfigs after removing ia64 support + * Remove sparc support + * [Config] Update portsconfigs after removing sparc support + + [ Linus Torvalds ] + + * (pre-stable) mm: fix page table unmap for stack guard page properly + + [ Mathieu J. Poirier ] + + * SAUCE: (no-up) ARM: Resetting power_mode to its original value. + - LP: #591941 + + [ Upstream Kernel Changes ] + + * timer: add on-stack deferrable timer interfaces + - LP: #601057 + * x86 platform driver: intelligent power sharing driver + - LP: #601057 + * IPS driver: add GPU busy and turbo checking + - LP: #601057 + * X86: intel_ips, check for kzalloc properly + - LP: #601057 + * ips driver: make it less chatty + - LP: #601057 + + -- Leann Ogasawara Tue, 17 Aug 2010 09:38:08 -0700 + +linux (2.6.35-16.22) maverick; urgency=low + + [ Andy Whitcroft ] + + * debian -- more agressivly clean up after depmod on purge + - LP: #618591 + + [ Henrik Rydberg ] + + * SAUCE: hid: 3m: Simplify touchsreen emulation logic + + [ Leann Ogasawara ] + + * ubuntu: iscsitarget -- version 1.4.20.2 + * ubuntu: rtl8192se -- update to version 0017.0507.2010 + * rebase to v2.6.35.2 + * [Config] update configs following rebase to v2.6.35.2 + * [Config] update ports configs following rebase to v2.6.35.2 + + [ Luke Yelavich ] + + * [Config] Enable new firewire stack on powerpc + + [ Mathieu J. Poirier ] + + * SAUCE: (drop after 2.6.35) ARM: Using gpmc function to init nand flash. + - LP: #608266 + + -- Leann Ogasawara Thu, 12 Aug 2010 09:58:01 -0700 + +linux (2.6.35-15.21) maverick; urgency=low + + [ Luke Yelavich ] + + * [Config] CONFIG_SND_USB_UA101=m for all architectures + + [ Upstream Kernel Changes ] + + * Input: introduce MT event slots + * Input: document the MT event slot protocol + * (pre-stable) sched: Revert nohz_ratelimit() for now + * (pre-stable) drm/radeon/kms: add missing copy from user + - LP: #606081 + + [ Leann Ogasawara ] + + * rebase to v2.6.35.1 + + -- Leann Ogasawara Mon, 09 Aug 2010 09:24:04 -0700 + +linux (2.6.35-14.20) maverick; urgency=low + + [ Andy Whitcroft ] + + * update Vcs-Git to point to maverick repo + * debian -- include the debian packaging in the -source package + - LP: #608674 + * select debian source format 1.0 + * add support for building selected stages of kernel + - LP: #603087 + * cleanup conditional dependancy handling + - LP: #603087 + + [ Upstream Kernel Changes ] + + * ALSA: hda - Handle missing NID 0x1b on ALC259 codec + - LP: #582199, #586418, #588031 + * ALSA: hda - Handle pin NID 0x1a on ALC259/269 + - LP: #582199, #586418, #588031 + * sched: Revert nohz_ratelimit() for now + + -- Leann Ogasawara Tue, 03 Aug 2010 08:46:47 -0700 + +linux (2.6.35-14.19) maverick; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.35 + + -- Leann Ogasawara Sun, 01 Aug 2010 10:35:56 -0700 + +linux (2.6.35-13.18) maverick; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: (no-up) Modularize vesafb -- fix initialisation + * SAUCE: add tracing for user initiated readahead requests + * SAUCE: vt -- maintain bootloader screen mode and content until vt + switch + * SAUCE: vt -- allow grub to request automatic vt_handoff + * SAUCE: fbcon -- fix race between open and removal of framebuffers + * SAUCE: drm -- stop early access to drm devices + + [ Bryan Wu ] + + * CONFIG: compile in OTG driver and Transceiver driver + - LP: #566645 + * remove OTG modules from modules list file + + [ John Johansen ] + + * SAUCE: AppArmor: -- sync to AppArmor mainline 2010-07-27 + - LP: #581525, #599450 + * SAUCE: AppArmor: -- sync to AppArmor mainline 2010-07-29 + * SAUCE: AppArmor 2.4 compatibility patch + * SAUCE: AppArmor: Allow dfa backward compatibility with broken userspace + * SAUCE: fix pv-ops for legacy Xen + * SAUCE: blkfront: default to sd devices + * [Config] Build in drivers required for Xen pv-ops + + [ Leann Ogasawara ] + + * Revert "[Upstream] i915: Use the correct mask to detect i830 aperture + size." + + [ Lee Jones ] + + * SAUCE: ARM: OMAP: Add macros for comparing silicon revision + - LP: #608095 + * SAUCE: OMAP: DSS2: check for both cpu type and revision, rather than + just revision + - LP: #608095 + * SAUCE: OMAP: DSS2: enable hsclk in dsi_pll_init for OMAP36XX + - LP: #608095 + * SAUCE: ARM: OMAP: Beagle: support twl gpio differences on xM + - LP: #608095 + + [ Upstream Kernel Changes ] + + * agp/intel: Use the correct mask to detect i830 aperture size. + - LP: #597075 + + -- Leann Ogasawara Fri, 30 Jul 2010 15:46:59 -0700 + +linux (2.6.35-12.17) maverick; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.35-rc6 + * [Config] update configs following rebase to v2.6.35-rc6 + * [Config] update ports configs following rebase to v2.6.35-rc6 + * SAUCE: [FTBS] armel: define KEY_F10 and KEYF11 + + [ Leann Ogasawara ] + + * rebase to v2.6.35-rc6 + + -- Leann Ogasawara Fri, 23 Jul 2010 16:16:38 +0200 + +linux (2.6.35-11.16) maverick; urgency=low + + [ Leann Ogasawara ] + + * Bump ABI for new compiler update + + -- Leann Ogasawara Fri, 23 Jul 2010 10:24:58 +0200 + +linux (2.6.35-10.15) maverick; urgency=low + + [ Leann Ogasawara ] + + * Revert "SAUCE: ensure vga16fb loads if no other driver claims the VGA + device" + * [Config] Enable CONFIG_M686=y + - LP: #592495 + + [ Upstream Kernel Changes ] + + * tracing: Add alignment to syscall metadata declarations + + -- Leann Ogasawara Tue, 20 Jul 2010 18:18:49 +0200 + +linux (2.6.35-9.14) maverick; urgency=low + + [ Andy Whitcroft ] + + * ubuntu: AUFS -- add BOM and automated update script + * ubuntu: AUFS -- update to b37c575759dc4535ccc03241c584ad5fe69e3b25 + + [ John Johansen ] + + * [Config] Enable DRBD as a module + + [ Kees Cook ] + + * SAUCE: Yama: verify inode is symlink to avoid bind mounts + - LP: #604407 + + [ Leann Ogasawara ] + + * [Config] Disable CONFIG_DRM_VMWGFX (staging driver) + - LP: #606139 + * [Config] ports: Disable CONFIG_DRM_VMWGFX (staging driver) + - LP: #606139 + * [Config] Enable CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y + * [Config] ports: Enable CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y + + [ Lee Jones ] + + * Stop ARM boards crashing when CUPS is loaded + - LP: #601226 + + [ Upstream Kernel Changes ] + + * perf probe: Support tracing an entry of array + * perf probe: Support static and global variables + + -- Leann Ogasawara Fri, 16 Jul 2010 14:38:17 -0700 + +linux (2.6.35-8.13) maverick; urgency=low + + [ Kees Cook ] + + * SAUCE: Yama: check PTRACE using thread group leader + * SAUCE: Yama: search for PTRACE exceptions via thread group leader + - LP: #603716 + + [ Leann Ogasawara ] + + * rebase to v2.6.35-rc5 + * [Config] update configs following rebase to v2.6.35-rc5 + + [ Nicolas Pitre ] + + * SAUCE: make ndiswrapper available on X86 only + + [ Tim Gardner ] + + * [Config] Added ums-cypress to udeb + - LP: #576066 + * SAUCE: fix build error with CONFIG_BLK_DEV_INITRD=n + * [Config] CONFIG_NDISWRAPPER=m across all configs + + [ Upstream Kernel Changes ] + + * HID: magicmouse: report last touch up + * rebase to 2.6.35-rc5 + + -- Leann Ogasawara Tue, 13 Jul 2010 18:57:59 -0700 + +linux (2.6.35-7.12) maverick; urgency=low + + [ Tim Gardner ] + + * [Upstream] i915: Use the correct mask to detect i830 aperture size. + - LP: #597075 + + [ Upstream Kernel Changes ] + + * (drop after 2.6.35) drm/radeon/kms: add ioport register access + (squashed) + + -- Tim Gardner Thu, 08 Jul 2010 09:53:13 -0600 + +linux (2.6.35-7.11) maverick; urgency=low + + [ Tim Gardner ] + + * [Config] CONFIG_X86_MRST=n + + [ Upstream Kernel Changes ] + + * (drop after 2.6.35-rc5) writeback: remove writeback_inodes_wbc + * (drop after 2.6.35-rc5) writeback: split writeback_inodes_wb + * (drop after 2.6.35-rc5) writeback: simplify the write back thread queue + + -- Tim Gardner Tue, 06 Jul 2010 18:39:08 -0600 + +linux (2.6.35-7.10) maverick; urgency=low + + [ Kees Cook ] + + * SAUCE: security: create task_free security callback + * SAUCE: Yama: add PTRACE exception tracking and interface + * SAUCE: security: unconditionally chain to Yama LSM + * Revert "SAUCE: ptrace: restrict ptrace scope to children" + * Revert "SAUCE: fs: block hardlinks to non-accessible sources" + * Revert "SAUCE: fs: block cross-uid sticky symlinks" + * [Upstream] security: Yama LSM + * [Config] Enable CONFIG_SECURITY_YAMA=y + + [ Tim Gardner ] + + * [Config] updateconfigs/updateportsconfigs after rebase to 2.6.35-rc4 + + [ Upstream Kernel Changes ] + + * rebase to 2.6.35-rc4 + + -- Leann Ogasawara Thu, 01 Jul 2010 08:55:57 -0700 + +linux (2.6.35-6.9) maverick; urgency=low + + [ Tim Gardner ] + + * [Upstream] direct_splice_actor() should not use pos in sd + - LP: #588861 + + -- Leann Ogasawara Mon, 28 Jun 2010 12:35:49 -0700 + +linux (2.6.35-6.8) maverick; urgency=low + + [ Mathieu J. Poirier ] + + * ARM: Adding regulator supply for vdds_sdi. + - LP: #597904 + + -- Leann Ogasawara Sun, 27 Jun 2010 16:34:43 -0700 + +linux (2.6.35-6.7) maverick; urgency=low + + [ Alberto Milone ] + + * [Upstream] Add support for the ATIF ACPI method to the radeon driver + + [ Chase Douglas ] + + * [Upstream] HID: magicmouse: scroll on entire surface, not just middle + of mouse + * [Upstream] HID: magicmouse: disable and add module param for scroll + acceleration + * [Upstream] HID: magicmouse: properly account for scroll movement in + state + * [Upstream] HID: magicmouse: add param for scroll speed + * [Upstream] HID: magicmouse: enable horizontal scrolling + + [ Henrik Rydberg ] + + * [Upstream] Input: evdev - convert to dynamic event buffer + * [Upstream] Input: evdev - use driver hint to compute size of event + buffer + * [Upstream] Input: bcm5974 - set the average number of events per MT + event packet + * [Upstream] Input: hid-input - use a larger event buffer for MT devices + * [Upstream] Input: evdev - never leave the client buffer empty after + write + + [ John Johansen ] + + * SAUCE: AppArmor: -- mainline 2010-06-23 + * SAUCE: AppArmor 2.4 compatibility patch + * SAUCE: fs: block hardlinks to non-accessible sources AppArmor portion + + [ Leann Ogasawara ] + + * [Config] Enable CONFIG_INTR_REMAP=y + - LP: #597091 + * [Config] Enable CONFIG_X86_X2APIC + - LP: #597091 + + [ Mathieu J. Poirier ] + + * [Config] ARM: Turning off CONFIG_CPU_IDLE on omap + - LP: #594382 + + -- Leann Ogasawara Thu, 24 Jun 2010 12:19:48 -0700 + +linux (2.6.35-5.6) maverick; urgency=low + + [ Amit Kucheria ] + + * [Config] update omap flavour description + + [ Andy Whitcroft ] + + * update to ubuntu-debian:508b7aa34b578c0d1e51bfb571f2bfb824dc65ac + - LP: #570500, #576274 + * SAUCE: add option to hand off all kernel parameters to init + - LP: #586386 + * [Config] enable passing all kernel command line to init + - LP: #586386 + * [Config] disable CONFIG_VMI + - LP: #537601 + * [Config] enable CONFIG_IPV6_SIT_6RD + - LP: #591869 + * [Config] enable CONFIG_VMWARE_BALOON as module + - LP: #592039 + + [ Leann Ogasawara ] + + * Revert "SAUCE: pm: Config option to disable handling of console during + suspend/resume" + - LP: #594885 + * [Config] Remove CONFIG_PM_DISABLE_CONSOLE + * [Config] ports: enable passing all kernel command line to init + - LP: #586386 + * [Config] Enable CONFIG_FB_VESA=y for x86 + * [Config] Add CONFIG_FRAMEBUFFER_CONSOLE=y to config enforcer + * [Config] Add CONFIG_FB_VESA=y for x86 to config enforcer + * [Config] Enable CONFIG_TASK_DELAY_ACCT=y + - LP: #493156 + + [ Mathieu Poirier ] + + * ARM: Adding MosChip MCS7830 to nic-usb + - LP: #584920 + + [ Upstream Kernel Changes ] + + * Revert "[Upstream] docbook: need xmldoclinks for all doc types" + * docbook: need xmldoclinks for all doc types + * perf probe: Add kernel source path option + + -- Leann Ogasawara Thu, 17 Jun 2010 08:05:29 -0700 + +linux (2.6.35-4.5) maverick; urgency=low + + [ Leann Ogasawara ] + + * Revert "[Upstream] (evdev) Use driver hint to compute the evdev buffer + size (rev2)" + * Revert "[Upstream] (evdev) Convert to dynamic event buffer (rev4)" + * Revert "[Upstream] (evdev) Use multi-reader buffer to save space + (rev4)" + * Revert "SAUCE: drivers: Remove some duplicate device entries in various + modules" + * [Upstream] USB: option: Remove duplicate AMOI_VENDOR_ID + * [Upstream] Revert "USB: Adding support for HTC Smartphones to ipaq" + * [Upstream] p54usb: Comment out duplicate Medion MD40900 device id + + [ Tim Gardner ] + + * [Config] CONFIG_NFS_FSCACHE=y + - LP: #440522 + * [Config] CONFIG_FSCACHE_STATS=y, CONFIG_FSCACHE_HISTOGRAM=y + - LP: #440522 + + -- Leann Ogasawara Wed, 16 Jun 2010 08:43:07 -0700 + +linux (2.6.35-3.4) maverick; urgency=low + + [ Andy Whitcroft ] + + * debian -- ensure the version number is clean + + [ Henrik Rydberg ] + + * [Upstream] Introduce MT event slots (rev 5) + * [Upstream] Document the MT event slot protocol (rev5) + * [Upstream] (evdev) Use multi-reader buffer to save space (rev4) + * [Upstream] (evdev) Convert to dynamic event buffer (rev4) + * [Upstream] (evdev) Use driver hint to compute the evdev buffer size + (rev2) + + [ Leann Ogasawara ] + + * Revert "SAUCE: Add MODULE_ALIAS for Dell WMI module" + * Revert "SAUCE: hostap: send events on data interface as well as master + interface" + * Revert "Fix webcam having USB ID 0ac8:303b" + * Revert "SAUCE: toshiba_acpi -- pull in current -dev version of driver" + * rebase to v2.6.35-rc3 + + [ Maxim Levitsky ] + + * [Config] Enable new Smartmedia/xD translation layer + - LP: #202490 + + [ Upstream Kernel Changes ] + + * net: fix deliver_no_wcard regression on loopback device + + [ Upstream changes ] + + * rebased to v2.6.35-rc3 + + -- Leann Ogasawara Thu, 10 Jun 2010 16:15:22 -0700 + +linux (2.6.35-2.3) maverick; urgency=low + + [ Bryan Wu ] + + * CONFIG: enforce -- make sure we disable CONFIG_LOCALVERSION_AUTO + + [ Leann Ogasawara ] + + * [Config] armel: Enable CONFIG_BNX2=m + * [Config] ports: Enable CONFIG_BNX2X=m + * SAUCE: armel: define get_dma_ops to fix FTBS + + [ Tim Gardner ] + + * [Upstream] net: Print num_rx_queues imbalance warning only when there + are allocated queues + - LP: #591416 + + -- Leann Ogasawara Wed, 09 Jun 2010 08:27:41 -0700 + +linux (2.6.35-2.2) maverick; urgency=low + + [ Andy Whitcroft ] + + * [Config] d-i: make armel configuration versatile flavour specific + - LP: #588805 + * [Config] d-i: enable .udebs for omap flavour + - LP: #588805 + + [ Kees Cook ] + + * ptrace: limit scope to attach only (allow read) + - LP: #589656 + + [ Leann Ogasawara ] + + * rebase to v2.6.35-rc2 + * [Config] update configs following rebase to v2.6.35-rc2 + * [Config] update port configs following rebase to v2.6.35-rc2 + + [ Lee Jones ] + + * Enable perf to be more helpful when perf_ does not exist. + - LP: #570500 + * 'fdr editconfig' modification. Easily skip over unwanted menuconfigs. + + [ Tim Gardner ] + + * [Config] Update bnx2 udeb firmware files + - LP: #589304 + + [ Upstream changes ] + + * rebased to v2.6.35-rc2 + + -- Leann Ogasawara Mon, 07 Jun 2010 09:45:04 -0700 + +linux (2.6.35-1.1) maverick; urgency=low + + [ Andy Whitcroft ] + + * ubuntu: AUFS -- update to standalone 2.6.35-rcN as at 20100601 + - LP: #587888 + * ubuntu: AUFS -- track changes to the arguements to fop fsync() + + [ Leann Ogasawara ] + + * rebase to v2.6.35-rc1 + * [Config] update configs following rebase to v2.6.35-rc1 + * [Config] update port configs following rebase to v2.6.35-rc1 + * SAUCE: lirc: rename usb_buffer_alloc() and usb_buffer_free() + * SAUCE: ndiswrapper: rename usb_buffer_alloc() and usb_buffer_free() + * SAUCE: ndiswrapper: convert multicast list to list_head + * [Config] [FTBS] armel: Temporarily disable CONFIG_GPIO_JANZ_TTL + * [Config] [FTBS] ia64: Temporarily disable gpiolib + * [Config] [FTBS] ia64: Temporarily disable CONFIG_CEPH_FS + * [Config] [FTBS] sparc: Temporarily disable CONFIG_INFINIBAND_QIB + * [Config] [FTBS] sparc: Temporarily disable CONFIG_MFD_JANZ_CMODIO + * [Config] [FTBS] armel: Temporarily disable CONFIG_MFD_JANZ_CMODIO + * [Config] [FTBS] armel: Temporarily disable CONFIG_DT3155 + * [Config] [FTBS] sparc: Temporarily disable CONFIG_MTD_NAND_DENALI + * [Config] [FTBS] armel: Temporarily disable bnx2 + * [Config] [FTBS] armel: Temporarily disable CONFIG_SERIAL_UARTLITE + * SAUCE: [FTBS] armel: Don't include asm/agp.h for ttm + * SAUCE: [FTBS] armel: include linux/dma-mapping.h + * SAUCE: [FTBS] armel: replace omap_set_gpio_debounce with + gpio_set_debounce + + [ Upstream Kernel Changes ] + + * of/usb: fix build error due to of_node pointer move + * n2_crypto: Fix build after of_device/of_platform_driver changes. + * powerpc/fsl-booke: fix the case where we are not in the first page + * powerpc/fsl-booke: Move the entry setup code into a seperate file + * powerpc/kexec: Add support for FSL-BookE + * greth: Fix build after OF device conversions. + + [ Upstream changes ] + + * rebased to v2.6.35-rc1 + + -- Leann Ogasawara Fri, 04 Jun 2010 23:01:52 -0700 + +linux (2.6.35-1.0) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * Null entry. + + -- Leann Ogasawara Wed, 02 Jun 2010 15:17:41 -0700 + +linux (2.6.34-5.14) maverick; urgency=low + + [ Tim Gardner ] + + * [Config] Added module inclusion support + * [Config] Added virtual flavour module inclusion list and d-i package + definitions + + -- Leann Ogasawara Wed, 02 Jun 2010 12:58:14 -0700 + +linux (2.6.34-5.13) maverick; urgency=low + + [ Andy Whitcroft ] + + * Revert "ubuntu: AUFS -- aufs2 20091209" + * Revert "ubuntu: AUFS -- export various core functions + (aufs2-standalone.patch)" + * Revert "ubuntu: AUFS -- export various core functions + (aufs2-base.patch)" + * ubuntu: AUFS -- aufs2 base patch for linux-2.6.34 + - LP: #587888 + * ubuntu: AUFS -- aufs2 standalone patch for linux-2.6.34 + - LP: #587888 + * ubuntu: AUFS -- update to standalone 2.6.34 as at 20100601 + - LP: #587888 + * [Config] AUFS -- enable aufs options + - LP: #587888 + + -- Leann Ogasawara Tue, 01 Jun 2010 08:56:43 -0700 + +linux (2.6.34-5.12) maverick; urgency=low + + [ Andy Whitcroft ] + + * enforce -- ensure SYSFS compatibility is disabled + + [ Chase Douglas ] + + * build with libdw-dev for perf probe symbol support + * maverick ftrace configuration changes + + [ Kees Cook ] + + * Revert "SAUCE: x86: brk away from exec rand area" + * Revert "SAUCE: [um] Don't use nx_enabled under UML" + * Revert "SAUCE: [x86] implement cs-limit nx-emulation for ia32" + * SAUCE: x86: implement cs-limit nx-emulation for ia32 + - LP: #369978 + * SAUCE: x86: more tightly confine cs-limit nx-emulation to ia32 only + * SAUCE: x86: brk away from exec rand area + - LP: #452175 + * SAUCE: ptrace: restrict ptrace scope to children + + [ Leann Ogasawara ] + + * Add new omap flavour to getabis + * [Config] Enable CONFIG_FRAMEBUFFER_CONSOLE=y for all archs + - LP: #585490 + * build/modules: Temorarily add ignore.modules + * ubuntu: iscsitarget -- version 1.4.20.1 + + [ Loïc Minier ] + + * SAUCE: [um] Don't use nx_enabled under UML + - LP: #524849 + + -- Leann Ogasawara Fri, 28 May 2010 08:27:17 -0700 + +linux (2.6.34-4.11) maverick; urgency=low + + [ Amit Kucheria ] + + * SAUCE: omap: remove calls to usb_nop_xceiv_register from board files + * [Config] Add support for OMAP-mainline flavour + + [ Andy Whitcroft ] + + * SAUCE: powerpc: fix compile error when ptrace.h is included from + userspace + - LP: #583733 + + [ Chase Douglas ] + + * Revert "SAUCE: Don't register vga16fb framebuffer if other framebuffers + are present" + * Revert "SAUCE: Disable function tracing after hitting __schedule_bug" + * Revert "SAUCE: drm/i915: don't change DRM configuration when releasing + load detect pipe" + + [ Kees Cook ] + + * SAUCE: fs: block cross-uid sticky symlinks + * SAUCE: fs: block hardlinks to non-accessible sources + + [ Koen Kooi ] + + * SAUCE: board-omap3-beagle: add DSS2 support + + [ Leann Ogasawara ] + + * Revert "staging/go7007 -- disable" + * Revert "[Config] staging/winbond -- disable" + * Revert "Disable 4MB page tables for Atom, work around errata AAE44" + * Revert "SAUCE: sync before umount to reduce time taken by ext4 umount" + * Revert "SAUCE: Enable an e1000e Intel Corporation 82567 Gigabit + controller" + * Revert "SAUCE: Fix MODULE_IMPORT/MODULE_EXPORT" + * Revert "SAUCE: Created MODULE_EXPORT/MODULE_IMPORT macros" + * Revert "SAUCE: input/mouse/alps: Do not call psmouse_reset() for alps" + * Revert "SAUCE: r8169: disable TSO by default for RTL8111/8168B + chipsets." + * Revert "[Upstream] b43: Declare all possible firmware files." + * Revert "add Breaks: against hardy lvm2" + * Revert "SAUCE: Guest OS does not recognize a lun with non zero target + id on Vmware ESX Server" + * Revert "SAUCE: Catch nonsense keycodes and silently ignore" + * [Config] Enable CONFIG_ECRYPT_FS=y for ports + * [Config] Enable CONFIG_USB=y for armel and sparc + * [Config] Enable CONFIG_SCSI=y for ia64 and sparc + * [Config] Enable CONFIG_RFKILL=y for ports + * [Config] Enable CONFIG_ATH9K_DEBUGFS=y + * [Config] Enable CONFIG_IWMC3200TOP_DEBUGFS=y + * [Config] Enable CONFIG_RCU_FAST_NO_HZ=y + * [Config] Enable CONFIG_IWLWIFI_DEVICE_TRACING=y + * [Config] Enable CONFIG_LIBERTAS_MESH=y + * [Config] Enable CONFIG_MMC_RICOH_MMC=y + * [Config] CONFIG_RT2800USB_UNKNOWN=y + * [Config] Enable CONFIG_VGA_SWITCHEROO=y + * [Config] Enable CONFIG_CEPH_FS=m + * [Config] Enable CONFIG_CRYPTO_PCRYPT=m + * [Config] Enable CONFIG_EEEPC_WMI=m + * [Config] Enable CONFIG_RT2800PCI=m + * [Config] Enable CONFIG_SCSI_HPSA=m + * [Config] Enable CONFIG_VHOST_NET=m + * [Config] Disable CONFIG_SND_HDA_INPUT_BEEP_MODE by default + - LP: #582350 + * [Config] Disable CONFIG_SOUND_OSS* and CONFIG_SND_*OSS + - LP: #579300 + * [Config] Enable CONFIG_PCIEASPM=y + - LP: #333990 + * [Config] updateconfigs for OMAP flavour + + [ Loïc Minier ] + + * Enable perf tools on armel + + [ Tim Gardner ] + + * SAUCE: Updated ndiswrapper to 1.56 + - LP: #582555 + * [Config] Added virtual flavour + * [Config] Remove support for sub-flavours + * [Config] Removed amd64 preempt flavour + * [Config] updateconfigs, updateportsconfigs after flavour munging + + -- Leann Ogasawara Tue, 25 May 2010 09:34:55 -0700 + +linux (2.6.34-3.10) maverick; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.34 + + [ Upstream changes ] + + * rebased to v2.6.34 + + -- Leann Ogasawara Tue, 18 May 2010 17:35:35 -0700 + +linux (2.6.34-2.9) maverick; urgency=low + + [ Leann Ogasawara ] + + * [Config] [FTBS] Disable comedi for armel + + -- Leann Ogasawara Thu, 13 May 2010 23:20:55 +0200 + +linux (2.6.34-2.8) maverick; urgency=low + + [ Leann Ogasawara ] + + * Drop lpia + * [Config] [FTBS] disable KVM + * [Config] [FTBS] disable ipr for armel + + -- Leann Ogasawara Thu, 13 May 2010 16:07:52 +0200 + +linux (2.6.34-2.7) maverick; urgency=low + + [ Leann Ogasawara ] + + * [Config] disable CONFIG_SCSI_IPR on powerpc + * [Config] Remove 386 flavour per UDS discussion + + -- Leann Ogasawara Wed, 12 May 2010 18:26:43 +0200 + +linux (2.6.34-1.6) maverick; urgency=low + + [ Chase Douglas ] + + * enforce CONFIG_TMPFS_POSIX_ACL=y + - LP: #575940 + * don't force module dependency checking + - LP: #577029 + + [ Kees Cook ] + + * SAUCE: mmap_min_addr check CAP_SYS_RAWIO only for write + - LP: #568844 + + [ Leann Ogasawara ] + + * Revert "SAUCE: ata: blacklist FUJITSU MHW2160BH PL" + * rebase to v2.6.34-rc7 + * [Config] update configs following rebase to v2.6.34-rc7 + * [Config] update port configs following rebase to v2.6.34-rc7 + * Add btrfs to the udebs + + [ Tim Gardner ] + + * [Config] Add atl1c to nic-modules udeb + - LP: #557130 + + [ Upstream changes ] + + * rebased to v2.6.34-rc7 + + -- Leann Ogasawara Tue, 11 May 2010 11:29:08 +0200 + +linux (2.6.34-1.5) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.34-rc6 + * [Config] update configs following rebase to v2.6.34-rc6 + * [Config] update port configs following rebase to v2.6.34-rc6 + + [ Upstream changes ] + + * rebased to v2.6.34-rc6 + + -- Leann Ogasawara Fri, 30 Apr 2010 15:54:05 +0100 + +linux (2.6.34-1.4) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.34-rc5 + * [Config] update ports configs following rebase to v2.6.34-rc5 + + [ Upstream changes ] + + * rebased to v2.6.34-rc5 + + -- Leann Ogasawara Thu, 22 Apr 2010 15:36:12 -0700 + +linux (2.6.34-1.3) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.34-rc4 + * [Config] update configs following rebase to v2.6.34-rc4 + * [Config] update port configs following rebase to v2.6.34-rc4 + * ubuntu: dm-raid4-5 -- update to compile with 2.6.34-rc4 + + [ Upstream changes ] + + * rebased to v2.6.34-rc4 + + -- Leann Ogasawara Tue, 13 Apr 2010 18:33:44 -0700 + +linux (2.6.34-1.2) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * Temorarily disable building linux-doc + * rebase to v2.6.34-rc3 + * [Config] update configs following rebase to v2.6.34-rc3 + * [Config] update port configs following rebase to v2.6.34-rc3 + + [ Upstream changes ] + + * rebased to v2.6.34-rc3 + + -- Leann Ogasawara Tue, 30 Mar 2010 16:55:44 -0700 + +linux (2.6.34-1.1) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * rebase to v2.6.34-rc2 + * ubuntu: dm-raid4-5 -- update to compile with 2.6.34-rc2 + * [Config] update port configs following rebase to v2.6.34-rc2 + * [Config] update configs following rebase to v2.6.34-rc2 + + [ Upstream changes ] + + * rebased to v2.6.34-rc2 + + -- Leann Ogasawara Wed, 24 Mar 2010 23:00:39 -0700 + +linux (2.6.33-1.1) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * ubuntu: dm-raid4-5 -- update to compile with 2.6.33 + * ubuntu: lirc -- drop explicit include of linux/autoconf.h + * ubuntu: lirc -- pass kfifo to kfifo_alloc and move spinlock + * ubuntu: lirc -- rename kfifo_put and kfifo_get + * ubuntu: iscsitarget -- rename daddr inet_sock field + * rebased to v2.6.33 + * [Config] update configs following rebase to v2.6.33 + * [Config] update ports configs following rebase to v2.6.33 + + [ Upstream changes ] + + * rebased to v2.6.33 + + -- Leann Ogasawara Tue, 23 Mar 2010 03:55:46 -0700 + +linux (2.6.33-0.0) UNRELEASED; urgency=low + + [ Leann Ogasawara ] + + * Null entry. + + -- Leann Ogasawara Wed, 17 Mar 2010 07:48:56 -0700 + +linux (2.6.32-16.25) lucid; urgency=low + + [ Andy Whitcroft ] + + * linux-tools -- move to Suggests: with explicit seeding + - LP: #534635 + + [ Tim Gardner ] + + * [Config] CONFIG_HID=m + + [ Upstream Kernel Changes ] + + * (pre-stable) sched: Fix SMT scheduler regression in + find_busiest_queue() + * KVM: introduce kvm_vcpu_on_spin + * KVM: VMX: Add support for Pause-Loop Exiting + + -- Andy Whitcroft Tue, 09 Mar 2010 14:13:51 +0000 + +linux (2.6.32-16.24) lucid; urgency=low + + [ Andy Whitcroft ] + + * armel -- perf userspace does not support arm + * ia64 -- libelf-dev/binutils-dev to not provide necessary libraries + + -- Andy Whitcroft Sat, 06 Mar 2010 11:42:12 +0000 + +linux (2.6.32-16.23) lucid; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: PM report driver and device suspend/resume times -- move config + * update to standards version 3.8.4.0 + * printenv -- expose all of the package selectors + * source package -- cleanup source content control + * doc package -- ensure we do build package content on buildd + * lintian -- correct the address in the debian/copyright + * lintian -- update debhelper package version dependancy + * lintian -- fix ghostscript dependancy + * lintian -- add required misc:Depends + * lintian -- move our debhelper compat level to debian/compat + * perf -- build the kernel carried tools + * perf -- add linux-tools carrying the version switches and manuals + * SAUCE: fix up Kconfig for staging drivers + * [Config] enable NOUVEAU etc following drm backport + * update DRM to mainline v2.6.33 + * [Config] Remove AppArmor config options that no longer exist (ports) + * [Config] updateportsconfigs following drm update + + [ John Johansen ] + + * ubuntu: AppArmor -- update to mainline 2010-03-04 + * SAUCE: AppArmor: Reintroduce AppArmor 2.4 compatibility + * SAUCE: AppArmor: replace strim with strstrip for 2.6.32 kernels + * [Config] Remove AppArmor config options that no longer exist + + [ Manoj Iyer ] + + * ubuntu: rtl8192se -- version 2010-0115,0014 + - LP: #530275 + * [Config] added CONFIG_RTL8192SE module. + - LP: #530275 + + [ Tim Gardner ] + + * [Config] Added vmw_pvscsi to d-i/scsi-modules + - LP: #531017 + * [Upstream] netfilter: xt_recent: Add an entry reaper + + [ Upstream Kernel Changes ] + + * Revert "KVM: x86 emulator: Check CPL level during privilege instruction + emulation" + * Revert "KVM: x86 emulator: Fix popf emulation" + * Revert "KVM: x86 emulator: Check IOPL level during io instruction + emulation" + * Revert "KVM: x86 emulator: Add Virtual-8086 mode of emulation" + * Revert "KVM: fix memory access during x86 emulation." + * Add vlan (8021.Q) module package for d-i. + * (pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP, Dell + Inspiron 700m + - LP: #515246 + * [Upstream] docbook: need xmldoclinks for all doc types + * x86: set_personality_ia32() misses force_personality32 + * lib: Introduce generic list_sort function + * drm/nv50: Implement ctxprog/state generation. + * drm/nv50: Remove redundant/incorrect ctxvals initialisation. + * (pre-stable) drm/i915: blacklist lid status: Sony VGN-BX196VP, Dell + Inspiron 700m + - LP: #515246 + + -- Andy Whitcroft Fri, 05 Mar 2010 15:40:38 +0000 + +linux (2.6.32-15.22) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Config] added new config option CONFIG_SR_REPORT_TIME_LIMIT" + * Revert "SAUCE: PM report driver and device suspend/resume times." + * [Config] set CONFIG_SR_REPORT_TIME_LIMIT + + [ Manoj Iyer ] + + * SAUCE: PM report driver and device suspend/resume times. + + -- Andy Whitcroft Tue, 02 Mar 2010 01:35:37 +0000 + +linux (2.6.32-15.21) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "(pre-stable) drm/i915: Increase fb alignment to 64k" + * Revert "[Config] lenovo-sl-laptop -- enable" + * Revert "ubuntu: lenovo-sl-laptop -- git tip (b19a08f81f)" + * armel -- cramfs module will no longer be built + * d-i -- make all modules optional + * rename the debug packages to match archive standard + - LP: #527837 + * lenovo-sl-laptop is no longer built + + [ Colin Ian King ] + + * Disable 4MB page tables for Atom, work around errata AAE44 + - LP: #523112 + + [ Colin Watson ] + + * ubuntu: dm-raid4-5: Depend on XOR_BLOCKS + * ubuntu: fsam7400: Depend on CHECK_SIGNATURE + + [ Jesse Barnes ] + + * SAUCE: drm/i915: don't change DRM configuration when releasing load + detect pipe + - LP: #488328 + + [ Loïc Minier ] + + * [Config] armel Update versatile initrd configs + - LP: #524893 + * SAUCE: [um] Don't use nx_enabled under UML + - LP: #524849 + + [ Manoj Iyer ] + + * [Config] added new config option CONFIG_SR_REPORT_TIME_LIMIT + + [ Mario Limonciello ] + + * SAUCE: v3 - Add Dell Business Class Netbook LED driver + + [ Rafael J. Wysocki ] + + * SAUCE: PM report driver and device suspend/resume times. + + [ Surbhi Palande ] + + * Revert "[Upstream] e1000e: enhance frame fragment detection" + - CVE-2009-4538 + * Revert "[Upstream] e1000: enhance frame fragment detection" + - CVE-2009-4536 + + [ Tim Gardner ] + + * [Config] Enabled CONFIG_LEDS_DELL_NETBOOKS=m + * SAUCE: (pre-stable) netfilter: xt_recent: fix buffer overflow + * SAUCE: (pre-stable) netfilter: xt_recent: fix false match + + [ Upstream Kernel Changes ] + + * Revert "(pre-stable) eCryptfs: Add getattr function" + * Fix potential crash with sys_move_pages + * futex_lock_pi() key refcnt fix + * futex: Handle user space corruption gracefully + * futex: Handle futex value corruption gracefully + * Fix race in tty_fasync() properly + * hwmon: (w83781d) Request I/O ports individually for probing + * hwmon: (lm78) Request I/O ports individually for probing + * hwmon: (adt7462) Wrong ADT7462_VOLT_COUNT + * ALSA: ctxfi - fix PTP address initialization + * drm/i915: disable hotplug detect before Ironlake CRT detect + * drm/i915: enable self-refresh on 965 + * drm/i915: Disable SR when more than one pipe is enabled + * drm/i915: Fix DDC on some systems by clearing BIOS GMBUS setup. + * drm/i915: Add HP nx9020/SamsungSX20S to ACPI LID quirk list + * drm/i915: Fix the incorrect DMI string for Samsung SX20S laptop + * drm/i915: Add MALATA PC-81005 to ACPI LID quirk list + * usb: r8a66597-hcd: Flush the D-cache for the pipe-in transfer buffers. + * i2c-tiny-usb: Fix on big-endian systems + * drm/i915: handle FBC and self-refresh better + * drm/i915: Increase fb alignment to 64k + * drm/i915: Update write_domains on active list after flush. + * regulator: Fix display of null constraints for regulators + * ALSA: hda-intel: Avoid divide by zero crash + * CPUFREQ: Fix use after free of struct powernow_k8_data + * freeze_bdev: don't deactivate successfully frozen MS_RDONLY sb + * cciss: Make cciss_seq_show handle holes in the h->drv[] array + * ioat: fix infinite timeout checking in ioat2_quiesce + * resource: add helpers for fetching rlimits + * fs/exec.c: restrict initial stack space expansion to rlimit + * cifs: fix length calculation for converted unicode readdir names + * NFS: Fix a reference leak in nfs_wb_cancel_page() + * NFS: Try to commit unstable writes in nfs_release_page() + * NFSv4: Don't allow posix locking against servers that don't support it + * NFSv4: Ensure that the NFSv4 locking can recover from stateid errors + * NFS: Fix an Oops when truncating a file + * NFS: Fix a umount race + * NFS: Fix a bug in nfs_fscache_release_page() + * NFS: Fix the mapping of the NFSERR_SERVERFAULT error + * md: fix 'degraded' calculation when starting a reshape. + * V4L/DVB: dvb-core: fix initialization of feeds list in demux filter + * Export the symbol of getboottime and mmonotonic_to_bootbased + * kvmclock: count total_sleep_time when updating guest clock + * KVM: PIT: control word is write-only + * tpm_infineon: fix suspend/resume handler for pnp_driver + * amd64_edac: Do not falsely trigger kerneloops + * netfilter: nf_conntrack: fix memory corruption with multiple namespaces + * netfilter: nf_conntrack: per netns nf_conntrack_cachep + * netfilter: nf_conntrack: restrict runtime expect hashsize modifications + * netfilter: xtables: compat out of scope fix + * netfilter: nf_conntrack: fix hash resizing with namespaces + * drm/i915: remove full registers dump debug + * drm/i915: add i915_lp_ring_sync helper + * drm/i915: Don't wait interruptible for possible plane buffer flush + * dasd: remove strings from s390dbf + * crypto: padlock-sha - Add import/export support + * wmi: Free the allocated acpi objects through wmi_get_event_data + * dell-wmi, hp-wmi, msi-wmi: check wmi_get_event_data() return value + * /dev/mem: introduce size_inside_page() + * devmem: check vmalloc address on kmem read/write + * devmem: fix kmem write bug on memory holes + * SCSI: mptfusion : mptscsih_abort return value should be SUCCESS instead + of value 0. + * sh: Couple kernel and user write page perm bits for CONFIG_X2TLB + * ALSA: hda - use WARN_ON_ONCE() for zero-division detection + * dst: call cond_resched() in dst_gc_task() + * ALSA: hda - Improved MacBook (Pro) 5,1 / 5,2 support + * befs: fix leak + * rtc-fm3130: add missing braces + * Call flush_dcache_page after PIO data transfers in libata-sff.c + * ahci: add Acer G725 to broken suspend list + * pktgen: Fix freezing problem + * x86/amd-iommu: Fix IOMMU-API initialization for iommu=pt + * x86/amd-iommu: Fix deassignment of a device from the pt_domain + * x86: Re-get cfg_new in case reuse/move irq_desc + * Staging: fix rtl8187se compilation errors with mac80211 + * ALSA: usb-audio - Avoid Oops after disconnect + * serial: 8250: add serial transmitter fully empty test + * sysfs: sysfs_sd_setattr set iattrs unconditionally + * class: Free the class private data in class_release + * USB: usbfs: only copy the actual data received + * USB: usbfs: properly clean up the as structure on error paths + * rtl8187: Add new device ID + * ACPI: Add NULL pointer check in acpi_bus_start + * ACPI: fix High cpu temperature with 2.6.32 + * drm/radeon/kms: use udelay for short delays + * NFS: Too many GETATTR and ACCESS calls after direct I/O + * eCryptfs: Add getattr function + * b43: Fix throughput regression + * ath9k: Fix sequence numbers for PAE frames + * mac80211: Fix probe request filtering in IBSS mode + * iwlwifi: Fix to set correct ht configuration + * dm stripe: avoid divide by zero with invalid stripe count + * dm log: userspace fix overhead_size calcuations + * Linux 2.6.32.9 + * sfc: Fix SFE4002 initialisation + * sfc: Fix sign of efx_mcdi_poll_reboot() error in efx_mcdi_poll() + * sfc: SFE4002/SFN4112F: Widen temperature and voltage tolerances + * (pre-stable) HID: handle joysticks with large number of buttons + - LP: #492056 + * (pre-stable) HID: extend mask for BUTTON usage page + - LP: #492056 + * PM: Measure device suspend and resume times + * e1000: enhance frame fragment detection + - CVE-2009-4536 + * e1000e: enhance frame fragment detection + - CVE-2009-4538 + * KVM: fix memory access during x86 emulation. + - CVE-2010-0306 + * KVM: x86 emulator: Add Virtual-8086 mode of emulation + - CVE-2010-0306 + * KVM: x86 emulator: Check IOPL level during io instruction emulation + - CVE-2010-0306 + * KVM: x86 emulator: Fix popf emulation + - CVE-2010-0306 + * KVM: x86 emulator: Check CPL level during privilege instruction + emulation + - CVE-2010-0306 + * Input: wacom - ensure the device is initialized properly upon resume + * Input: wacom - add defines for packet lengths of various devices + * Input: wacom - add support for new LCD tablets + - LP: #516777 + + -- Andy Whitcroft Mon, 01 Mar 2010 22:56:28 +0000 + +linux (2.6.32-14.20) lucid; urgency=low + + [ Andy Whitcroft ] + + * rebuild following the GCC update to match compiler for out of tree modules + * Revert "[Config] drbd -- enable" + * Revert "ubuntu: drbd -- version 8.3.1" + * SAUCE: khubd -- switch USB product/manufacturer/serial handling to RCU + - LP: #510937 + + -- Andy Whitcroft Fri, 19 Feb 2010 18:47:18 +0000 + +linux (2.6.32-14.19) lucid; urgency=low + + [ Andy Whitcroft ] + + * ensure we build the source package contents when enabled + - LP: #522308 + * [Config] enable CONFIG_X86_MCE_XEON75XX + * SAUCE: AppArmor -- add linux/kref.h for struct kref + * [Config] enable CONFIG_HID_ORTEK + * enable udeb generation for arm versatile flavour + - LP: #522515 + + [ John Johansen ] + + * ubuntu: AppArmor -- update to mainline 2010-02-18 + - LP: #439560, #496110, #507069 + + [ Johnathon Harris ] + + * SAUCE: HID: add support for Ortek WKB-2000 + - LP: #405390 + + [ Upstream Kernel Changes ] + + * tpm_tis: TPM_STS_DATA_EXPECT workaround + - LP: #490487 + * x86, mce: Xeon75xx specific interface to get corrected memory error + information + * x86, mce: Rename cpu_specific_poll to mce_cpu_specific_poll + * x86, mce: Make xeon75xx memory driver dependent on PCI + * drm/edid: Unify detailed block parsing between base and extension + blocks + - LP: #500999 + * (pre-stable) eCryptfs: Add getattr function + - LP: #390833 + + -- Andy Whitcroft Thu, 18 Feb 2010 19:22:02 +0000 + +linux (2.6.32-13.18) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "enforcer -- make the enforcement configuration common" + * Revert "(pre-stable) Input: ALPS - add interleaved protocol support + (Dell E6x00 series)" + * Revert "(pre-stable) driver-core: fix devtmpfs crash on s390" + * Revert "(pre-stable) Driver-Core: devtmpfs - set root directory mode to + 0755" + * Revert "SAUCE: Adds support for COMPAL JHL90 webcam" + * Revert "SAUCE: fix kernel oops in VirtualBox during paravirt patching" + * Revert "SAUCE: make fc transport removal of target configurable" + * enforcer -- make the enforcement configuration common + * getabis -- add preempt flavour to the list + * [Config] enforce DEVTMPFS options + * [Config] armel -- cleanup to-be builtin modules + * [Config] cleanup ports configs + * [Config] enable CRYPTO_GHASH_CLMUL_NI_INTEL + - LP: #485536 + * add printdebian target to find branch target + * distclean -- do not remove debian.env + * [Config] generic-pae switch to M586TSC + - LP: #519448 + * git-ubuntu-log -- commonise duplicated log handling + * git-ubuntu-log -- tighten up Bug: NNNN matching + * git-ubuntu-log -- sort the bug numbers + + [ Chris Wilson ] + + * (pre-stable) drm/i915: Increase fb alignment to 64k + - LP: #404064 + + [ Eric Miao ] + + * arm -- enable ubuntu/ directory + + [ Huang Ying ] + + * SAUCE: crypto: ghash - Add PCLMULQDQ accelerated implementation + * SAUCE: crypto: ghash-intel - Fix building failure on x86_32 + + [ Loïc Minier ] + + * [Config] cleanup preempt configuration + * [Config] versatile: Fix video output + - LP: #517594 + * [Config] armel DEFAULT_MMAP_MIN_ADDR=32768 + * [Config] Large update to armel/versatile + * [Config] versatile: Add RTC support + * [Config] armel: Enable NEON + * [Config] versatile: Builtin MMC support + * [Config] versatile Builtin SCSI controller + * [Config] armel Disable dma_cache_sync callers + * [Config] armel Disable asm/time.h users + * [Config] armel Disable out of range udelay() + * [Config] armel Disable flush_cache_range() users + * [Config] armel -- Enable ubuntu/ drivers + + [ Steve Conklin ] + + * SAUCE: drm/i915: Add display hotplug event on Ironlake + * SAUCE: drm/i915: Add ACPI OpRegion support for Ironlake + + [ Upstream Kernel Changes ] + + * Revert "[Upstream]: oprofile/x86: add Xeon 7500 series support" + * Revert "Revert "[Bluetooth] Eliminate checks for impossible conditions + in IRQ handler"" + * clockevent: Don't remove broadcast device when cpu is dead + * clockevents: Add missing include to pacify sparse + * ACPI: don't cond_resched if irq is disabled + * be2net: Add support for next generation of BladeEngine device. + * be2net: Add the new PCI IDs to PCI_DEVICE_TABLE. + * mpt2sas: New device SAS2208 support is added + * ar9170: Add support for D-Link DWA 160 A2 + * powerpc/fsl: Add PCI device ids for new QoirQ chips + * davinci: dm646x: Add support for 3.x silicon revision + * Input: ALPS - add interleaved protocol support (Dell E6x00 series) + * Driver-Core: devtmpfs - set root directory mode to 0755 + * driver-core: fix devtmpfs crash on s390 + * vfs: get_sb_single() - do not pass options twice + * ALSA: hda - Add PCI IDs for Nvidia G2xx-series + * V4L/DVB (13569): smsusb: add autodetection support for five additional + Hauppauge USB IDs + * USB: mos7840: add device IDs for B&B electronics devices + * USB: ftdi_sio: add USB device ID's for B&B Electronics line + * V4L/DVB (13168): Add support for Asus Europa Hybrid DVB-T card (SAA7134 + SubVendor ID: 0x1043 Device ID: 0x4847) + * iTCO_wdt: Add support for Intel Ibex Peak + * atl1c:use common_task instead of reset_task and link_chg_task + * atl1e:disable NETIF_F_TSO6 for hardware limit + * V4L/DVB (13680a): DocBook/media: copy images after building HTML + * V4L/DVB (13680b): DocBook/media: create links for included sources + * netfilter: xtables: fix conntrack match v1 ipt-save output + * partitions: read whole sector with EFI GPT header + * partitions: use sector size for EFI GPT + * ALSA: ice1724 - Patch for suspend/resume for ESI Juli@ + * sched: Fix isolcpus boot option + * sched: Fix missing sched tunable recalculation on cpu add/remove + * nohz: Prevent clocksource wrapping during idle + * nfsd: Fix sort_pacl in fs/nfsd/nf4acl.c to actually sort groups + * timers, init: Limit the number of per cpu calibration bootup messages + * PCI: Always set prefetchable base/limit upper32 registers + * iscsi class: modify handling of replacement timeout + * NFS: Revert default r/wsize behavior + * HID: fixup quirk for NCR devices + * scsi_devinfo: update Hitachi entries (v2) + * scsi_dh: create sysfs file, dh_state for all SCSI disk devices + * scsi_transport_fc: remove invalid BUG_ON + * lpfc: fix hang on SGI ia64 platform + * libfc: fix typo in retry check on received PRLI + * libfc: fix ddp in fc_fcp for 0 xid + * fcoe: remove redundant checking of netdev->netdev_ops + * libfc: Fix wrong scsi return status under FC_DATA_UNDRUN + * libfc: lport: fix minor documentation errors + * libfc: don't WARN_ON in lport_timeout for RESET state + * fcoe: initialize return value in fcoe_destroy + * libfc: Fix frags in frame exceeding SKB_MAX_FRAGS in fc_fcp_send_data + * libfc: fix memory corruption caused by double frees and bad error + handling + * libfc: fix free of fc_rport_priv with timer pending + * libfc: remote port gets stuck in restart state without really + restarting + * fcoe, libfc: fix an libfc issue with queue ramp down in libfc + * fcoe: Fix checking san mac address + * fcoe: Fix getting san mac for VLAN interface + * qlge: Remove explicit setting of PCI Dev CTL reg. + * qlge: Set PCIE max read request size. + * qlge: Don't fail open when port is not initialized. + * qlge: Add handler for DCBX firmware event. + * qlge: Bonding fix for mode 6. + * PCI: AER: fix aer inject result in kernel oops + * DMI: allow omitting ident strings in DMI tables + * Input: i8042 - remove identification strings from DMI tables + * Input: i8042 - add Gigabyte M1022M to the noloop list + * Input: i8042 - add Dritek quirk for Acer Aspire 5610. + * ALSA: hda - select IbexPeak handler for Calpella + * ALSA: hda - Fix quirk for Maxdata obook4-1 + * ALSA: hda - Add missing Line-Out and PCM switches as slave + * iTCO_wdt.c - cleanup chipset documentation + * iTCO_wdt: add PCI ID for the Intel EP80579 (Tolapai) SoC + * iTCO_wdt: Add Intel Cougar Point and PCH DeviceIDs + * ahci: disable SNotification capability for ich8 + * ata_piix: fix MWDMA handling on PIIX3 + * md: fix small irregularity with start_ro module parameter + * V4L/DVB (13826): uvcvideo: Fix controls blacklisting + * cio: fix double free in case of probe failure + * cio: dont panic in non-fatal conditions + * netiucv: displayed TX bytes value much too high + * ipc ns: fix memory leak (idr) + * ALSA: hda - Fix HP T5735 automute + * hwmon: (fschmd) Fix a memleak on multiple opens of /dev/watchdog + * UBI: fix memory leak in update path + * UBI: initialise update marker + * ASoC: fix a memory-leak in wm8903 + * mac80211: check that ieee80211_set_power_mgmt only handles STA + interfaces. + * cfg80211: fix channel setting for wext + * KVM: S390: fix potential array overrun in intercept handling + * KVM: only allow one gsi per fd + * KVM: Fix race between APIC TMR and IRR + * KVM: MMU: bail out pagewalk on kvm_read_guest error + * KVM: x86: Fix host_mapping_level() + * KVM: x86: Fix probable memory leak of vcpu->arch.mce_banks + * KVM: x86: Fix leak of free lapic date in kvm_arch_vcpu_init() + * KVM: fix lock imbalance in kvm_*_irq_source_id() + * KVM: only clear irq_source_id if irqchip is present + * IPoIB: Clear ipoib_neigh.dgid in ipoib_neigh_alloc() + * x86: Reenable TSC sync check at boot, even with NONSTOP_TSC + * ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C + - LP: #516325 + * iwlwifi: Fix throughput stall issue in HT mode for 5000 + * fnctl: f_modown should call write_lock_irqsave/restore + * x86, msr/cpuid: Pass the number of minors when unregistering MSR and + CPUID drivers. + * Linux 2.6.32.7 + * scsi_lib: Fix bug in completion of bidi commands + * mptsas: Fix issue with chain pools allocation on katmai + * mm: add new 'read_cache_page_gfp()' helper function + * drm/i915: Selectively enable self-reclaim + * firewire: ohci: fix crashes with TSB43AB23 on 64bit systems + * S390: fix single stepped svcs with TRACE_IRQFLAGS=y + * x86: Set hotpluggable nodes in nodes_possible_map + * x86: Remove "x86 CPU features in debugfs" (CONFIG_X86_CPU_DEBUG) + * libata: retry FS IOs even if it has failed with AC_ERR_INVALID + * zcrypt: Do not remove coprocessor for error 8/72 + * dasd: fix possible NULL pointer errors + * ACPI: Add a generic API for _OSC -v2 + * ACPI: Add platform-wide _OSC support. + * ACPI: fix OSC regression that caused aer and pciehp not to load + * ACPI: Advertise to BIOS in _OSC: _OST on _PPC changes + * UBI: fix volume creation input checking + * e1000/e1000e: don't use small hardware rx buffers + * drm/i915: Reload hangcheck timer too for Ironlake + * Fix a leak in affs_fill_super() + * Fix failure exits in bfs_fill_super() + * fix oops in fs/9p late mount failure + * fix leak in romfs_fill_super() + * Fix remount races with symlink handling in affs + * fix affs parse_options() + * Fix failure exit in ipathfs + * mm: fix migratetype bug which slowed swapping + * FDPIC: Respect PT_GNU_STACK exec protection markings when creating + NOMMU stack + * Split 'flush_old_exec' into two functions + * sparc: TIF_ABI_PENDING bit removal + * x86: get rid of the insane TIF_ABI_PENDING bit + * Input: winbond-cir - remove dmesg spam + * x86: Disable HPET MSI on ATI SB700/SB800 + * iwlwifi: set default aggregation frame count limit to 31 + * drm/i915: only enable hotplug for detected outputs + * firewire: core: add_descriptor size check + * SECURITY: selinux, fix update_rlimit_cpu parameter + * regulator: Specify REGULATOR_CHANGE_STATUS for WM835x LED constraints + * x86: Add Dell OptiPlex 760 reboot quirk + - LP: #488319 + * x86: Add quirk for Intel DG45FC board to avoid low memory corruption + * x86/amd-iommu: Fix possible integer overflow + * clocksource: fix compilation if no GENERIC_TIME + * tcp: update the netstamp_needed counter when cloning sockets + * sky2: Fix oops in sky2_xmit_frame() after TX timeout + * net: restore ip source validation + * af_packet: Don't use skb after dev_queue_xmit() + * ax25: netrom: rose: Fix timer oopses + * KVM: allow userspace to adjust kvmclock offset + * oprofile/x86: add Xeon 7500 series support + * oprofile/x86: fix crash when profiling more than 28 events + * libata: retry link resume if necessary + * mm: percpu-vmap fix RCU list walking + * mm: purge fragmented percpu vmap blocks + * block: fix bio_add_page for non trivial merge_bvec_fn case + * Fix 'flush_old_exec()/setup_new_exec()' split + * random: drop weird m_time/a_time manipulation + * random: Remove unused inode variable + * block: fix bugs in bio-integrity mempool usage + * usb: r8a66597-hdc disable interrupts fix + * connector: Delete buggy notification code. + * be2net: Bug fix to support newer generation of BE ASIC + * be2net: Fix memset() arg ordering. + * mm: flush dcache before writing into page to avoid alias + * mac80211: fix NULL pointer dereference when ftrace is enabled + * imxfb: correct location of callbacks in suspend and resume + * mx3fb: some debug and initialisation fixes + * starfire: clean up properly if firmware loading fails + * kernel/cred.c: use kmem_cache_free + * uartlite: fix crash when using as console + * pktcdvd: removing device does not remove its sysfs dir + * ath9k: fix eeprom INI values override for 2GHz-only cards + * ath9k: fix beacon slot/buffer leak + * powerpc: TIF_ABI_PENDING bit removal + * NET: fix oops at bootime in sysctl code + * Linux 2.6.32.8 + + -- Andy Whitcroft Wed, 10 Feb 2010 18:56:52 +0000 + +linux (2.6.32-12.17) lucid; urgency=low + + [ Andy Whitcroft ] + + * restore linux-image prefix -- master + * enforce -- we require SELINUX enabled -- master + * enforce -- ensure APPARMOR is our default LSM -- master + * make doc package completely optional -- master + * make source package completely optional -- master + * make linux-libc-dev completly optional -- master + * convert package disable to a deps list -- master + * allow common headers to switch from indep to arch -- master + * convert binary package disable to a deps list -- master + * add configuration option for a full source build tree -- master + * add support for uImage kernels in package control scripts + * getabis -- cleanup and parameterise repository list -- master + * getabis -- move configuration to etc/getabi -- master + * kernelconfig -- move configuration to etc -- master + * rules -- make debian/debian.env master for branch name + * set the current branch name -- master + * pull back common debian.master files into debian -- master + * enforcer -- make the enforcement configuration common + * insert-changes -- correctly link to debian/rules in DROOT + + [ Colin Watson ] + + * future-proof ddeb handling against buildd changes + + [ Eric Miao ] + + * SAUCE: Make CONFIG_{OMNIBOOK, AVERATEC_5100P, PACKARDBELL_E5} depend on + X86 + + [ Loïc Minier ] + + * Add modules.builtin.bin to prerm rm list + - LP: #516584 + + [ Tim Gardner ] + + * [Config] Implement the amd64 preempt flavour + + [ Upstream Kernel Changes ] + + * syslog: distinguish between /proc/kmsg and syscalls + - LP: #515623 + * sfc: Fix polling for slow MCDI operations + * sfc: Fix conditions for MDIO self-test + * sfc: QT202x: Remove unreliable MMD check at initialisation + * sfc: Add workspace for GMAC bug workaround to MCDI MAC_STATS buffer + * sfc: Use fixed-size buffers for MCDI NVRAM requests + + -- Andy Whitcroft Fri, 05 Feb 2010 07:09:31 +0000 + +linux (2.6.32-12.16) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "SAUCE: acpi battery -- delay first lookup of the battery until + first use" + * SAUCE: acpi battery -- move first lookup asynchronous + - LP: #507211 + * [Config] update configs to cleanup generic configs + * [Config] disable CONFIG_X86_CPU_DEBUG for amd64 + * [Config] enable USER_NS + - LP: #480739, #509808 + + [ Heiko Carstens ] + + * (pre-stable) driver-core: fix devtmpfs crash on s390 + - LP: #512370 + + [ John Johansen ] + + * [Config] for server and virtual flavours make CONFIG_SCSI_SYM53C8XX_2=y + - LP: #494565 + * [Config] VIRTIO=y for server/virtual flavours + - LP: #494565 + + [ Kay Sievers ] + + * (pre-stable) Driver-Core: devtmpfs - set root directory mode to 0755 + - LP: #512370 + + [ Kees Cook ] + + * SAUCE: x86: brk away from exec rand area + - LP: #452175 + + [ Leann Ogasawara ] + + * [Upstream] e1000: enhance frame fragment detection + - CVE-2009-4536 + * [Upstream] e1000e: enhance frame fragment detection + - CVE-2009-4538 + + [ Sebastian Kapfer ] + + * (pre-stable) Input: ALPS - add interleaved protocol support (Dell E6x00 + series) + - LP: #296610 + + [ Upstream Kernel Changes ] + + * inotify: do not reuse watch descriptors + - LP: #485556 + * inotify: only warn once for inotify problems + * revert "drivers/video/s3c-fb.c: fix clock setting for Samsung SoC + Framebuffer" + * memcg: ensure list is empty at rmdir + * drm/i915: remove loop in Ironlake interrupt handler + * block: Fix incorrect reporting of partition alignment + * x86, mce: Thermal monitoring depends on APIC being enabled + * futexes: Remove rw parameter from get_futex_key() + * page allocator: update NR_FREE_PAGES only when necessary + * x86, apic: use physical mode for IBM summit platforms + * edac: i5000_edac critical fix panic out of bounds + * x86: SGI UV: Fix mapping of MMIO registers + * mfd: WM835x GPIO direction register is not locked + * mfd: Correct WM835x ISINK ramp time defines + * ALSA: hda - Fix missing capture mixer for ALC861/660 codecs + * V4L/DVB (13868): gspca - sn9c20x: Fix test of unsigned. + * reiserfs: truncate blocks not used by a write + * HID: add device IDs for new model of Apple Wireless Keyboard + * PCI/cardbus: Add a fixup hook and fix powerpc + * Input: pmouse - move Sentelic probe down the list + * asus-laptop: add Lenovo SL hotkey support + * sched: Fix cpu_clock() in NMIs, on !CONFIG_HAVE_UNSTABLE_SCHED_CLOCK + * sparc64: Fix NMI programming when perf events are active. + * sparc64: Fix Niagara2 perf event handling. + * i2c: Do not use device name after device_unregister + * i2c/pca: Don't use *_interruptible + * serial/8250_pnp: add a new Fujitsu Wacom Tablet PC device + * sched: Fix task priority bug + * vfs: Fix vmtruncate() regression + * Linux 2.6.32.5 + * x86, msr/cpuid: Register enough minors for the MSR and CPUID drivers + * V4L/DVB (13900): gspca - sunplus: Fix bridge exchanges. + * Staging: asus_oled: fix oops in 2.6.32.2 + * Staging: hv: fix smp problems in the hyperv core code + * tty: fix race in tty_fasync + * ecryptfs: use after free + * ecryptfs: initialize private persistent file before dereferencing + pointer + * nozomi: quick fix for the close/close bug + * serial: 8250_pnp: use wildcard for serial Wacom tablets + * usb: serial: fix memory leak in generic driver + * USB: fix bitmask merge error + * USB: Don't use GFP_KERNEL while we cannot reset a storage device + * USB: EHCI: fix handling of unusual interrupt intervals + * USB: EHCI & UHCI: fix race between root-hub suspend and port resume + * USB: add missing delay during remote wakeup + * USB: add speed values for USB 3.0 and wireless controllers + * ACPI: EC: Accelerate query execution + * ACPI: EC: Add wait for irq storm + * SCSI: enclosure: fix oops while iterating enclosure_status array + * drm/i915: Read the response after issuing DDC bus switch command + * drm/i915: try another possible DDC bus for the SDVO device with + multiple outputs + * block: bdev_stack_limits wrapper + * DM: Fix device mapper topology stacking + * x86/PCI/PAT: return EINVAL for pci mmap WC request for !pat_enabled + * USB: fix usbstorage for 2770:915d delivers no FAT + * vmalloc: remove BUG_ON due to racy counting of VM_LAZY_FREE + * perf timechart: Use tid not pid for COMM change + * perf events: Dont report side-band events on each cpu for + per-task-per-cpu events + * perf: Honour event state for aux stream data + * Linux 2.6.32.6 + + -- Andy Whitcroft Wed, 27 Jan 2010 16:40:23 +0000 + +linux (2.6.32-11.15) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "(pre-stable) drm/radeon/kms: fix crtc vblank update for r600" + * Revert "(pre-stable) sched: Fix balance vs hotplug race" + * Revert "[Upstream] acerhdf: Limit modalias matching to supported + boards" + * Revert "[Upstream] mmc: prevent dangling block device from accessing + stale queues" + * Revert "SAUCE: Fix nx_enable reporting" + * Revert "SAUCE: [x86] fix report of cs-limit nx-emulation" + * Revert "SAUCE: [x86] implement cs-limit nx-emulation for ia32" + * SAUCE: i915 -- disable powersave by default + - LP: #492392 + + [ Kees Cook ] + + * SAUCE: [x86] implement cs-limit nx-emulation for ia32 + - LP: #369978 + * SAUCE: [x86] fix report of cs-limit nx-emulation + - LP: #454285 + * SAUCE: Fix nx_enable reporting + - LP: #454285 + + [ Tim Gardner ] + + * [Upstream] b43: Declare all possible firmware files. + - LP: #488636 + * [Config] updateconfigs after adding pvscsi + - LP: #497156 + * [Config] CONFIG_BT=m + + [ Upstream Kernel Changes ] + + * Revert "x86: Side-step lguest problem by only building cmpxchg8b_emu + for pre-Pentium" + * SCSI: ipr: fix EEH recovery + * SCSI: qla2xxx: dpc thread can execute before scsi host has been added + * SCSI: st: fix mdata->page_order handling + * SCSI: fc class: fix fc_transport_init error handling + * sched: Fix task_hot() test order + * x86, cpuid: Add "volatile" to asm in native_cpuid() + * sched: Select_task_rq_fair() must honour SD_LOAD_BALANCE + * clockevents: Prevent clockevent_devices list corruption on cpu hotplug + * pata_hpt3x2n: fix clock turnaround + * pata_cmd64x: fix overclocking of UDMA0-2 modes + * ASoC: wm8974: fix a wrong bit definition + * sound: sgio2audio/pdaudiocf/usb-audio: initialize PCM buffer + * ALSA: hda - Fix missing capsrc_nids for ALC88x + * acerhdf: limit modalias matching to supported + - LP: #435958 + * ACPI: EC: Fix MSI DMI detection + * ACPI: Use the return result of ACPI lid notifier chain correctly + * powerpc: Handle VSX alignment faults correctly in little-endian mode + * ASoC: Do not write to invalid registers on the wm9712. + * drm/radeon: fix build on 64-bit with some compilers. + * USB: emi62: fix crash when trying to load EMI 6|2 firmware + * USB: option: support hi speed for modem Haier CE100 + * USB: Fix a bug on appledisplay.c regarding signedness + * USB: musb: gadget_ep0: avoid SetupEnd interrupt + * Bluetooth: Prevent ill-timed autosuspend in USB driver + * USB: rename usb_configure_device + * USB: fix bugs in usb_(de)authorize_device + * drivers/net/usb: Correct code taking the size of a pointer + * x86: SGI UV: Fix writes to led registers on remote uv hubs + * md: Fix unfortunate interaction with evms + * dma: at_hdmac: correct incompatible type for argument 1 of + 'spin_lock_bh' + * dma-debug: Do not add notifier when dma debugging is disabled. + * dma-debug: Fix bug causing build warning + * cifs: NULL out tcon, pSesInfo, and srvTcp pointers when chasing DFS + referrals + * x86/amd-iommu: Fix initialization failure panic + * ioat3: fix p-disabled q-continuation + * ioat2,3: put channel hardware in known state at init + * KVM: MMU: remove prefault from invlpg handler + * KVM: LAPIC: make sure IRR bitmap is scanned after vm load + * Libertas: fix buffer overflow in lbs_get_essid() + * iwmc3200wifi: fix array out-of-boundary access + * mac80211: fix propagation of failed hardware reconfigurations + * mac80211: fix WMM AP settings application + * mac80211: Fix IBSS merge + * cfg80211: fix race between deauth and assoc response + * ath5k: fix SWI calibration interrupt storm + * ath9k: wake hardware for interface IBSS/AP/Mesh removal + * ath9k: Fix TX queue draining + * ath9k: fix missed error codes in the tx status check + * ath9k: wake hardware during AMPDU TX actions + * ath9k: fix suspend by waking device prior to stop + * ath9k_hw: Fix possible OOB array indexing in gen_timer_index[] on + 64-bit + * ath9k_hw: Fix AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB and its shift value + in 0x4054 + * iwl3945: disable power save + * iwl3945: fix panic in iwl3945 driver + * iwlwifi: fix EEPROM/OTP reading endian annotations and a bug + * iwlwifi: fix more eeprom endian bugs + * iwlwifi: fix 40MHz operation setting on cards that do not allow it + * mac80211: fix race with suspend and dynamic_ps_disable_work + * NOMMU: Optimise away the {dac_,}mmap_min_addr tests + * 'sysctl_max_map_count' should be non-negative + * kernel/sysctl.c: fix the incomplete part of + sysctl_max_map_count-should-be-non-negative.patch + * V4L/DVB (13596): ov511.c typo: lock => unlock + * x86/ptrace: make genregs[32]_get/set more robust + * memcg: avoid oom-killing innocent task in case of use_hierarchy + * e100: Fix broken cbs accounting due to missing memset. + * ipv6: reassembly: use seperate reassembly queues for conntrack and + local delivery + * netfilter: fix crashes in bridge netfilter caused by fragment jumps + * hwmon: (sht15) Off-by-one error in array index + incorrect constants + * b43: avoid PPC fault during resume + * Keys: KEYCTL_SESSION_TO_PARENT needs TIF_NOTIFY_RESUME architecture + support + * sched: Fix balance vs hotplug race + * drm/radeon/kms: fix crtc vblank update for r600 + * drm: disable all the possible outputs/crtcs before entering KMS mode + * S390: dasd: support DIAG access for read-only devices + * xen: fix is_disconnected_device/exists_disconnected_device + * xen: improvement to wait_for_devices() + * xen: wait up to 5 minutes for device connetion + * orinoco: fix GFP_KERNEL in orinoco_set_key with interrupts disabled + * udf: Try harder when looking for VAT inode + * Add unlocked version of inode_add_bytes() function + * quota: decouple fs reserved space from quota reservation + * ext4: Convert to generic reserved quota's space management. + * ext4: fix sleep inside spinlock issue with quota and dealloc (#14739) + * x86, msr: Unify rdmsr_on_cpus/wrmsr_on_cpus + * cpumask: use modern cpumask style in drivers/edac/amd64_edac.c + * amd64_edac: unify MCGCTL ECC switching + * x86, msr: Add support for non-contiguous cpumasks + * x86, msr: msrs_alloc/free for CONFIG_SMP=n + * amd64_edac: fix driver instance freeing + * amd64_edac: make driver loading more robust + * amd64_edac: fix forcing module load/unload + * sched: Sched_rt_periodic_timer vs cpu hotplug + * ext4: Update documentation to correct the inode_readahead_blks option + name + * lguest: fix bug in setting guest GDT entry + * vmscan: do not evict inactive pages when skipping an active list scan + * ksm: fix mlockfreed to munlocked + * rt2x00: Disable powersaving for rt61pci and rt2800pci. + * generic_permission: MAY_OPEN is not write access + * Linux 2.6.32.3 + * untangle the do_mremap() mess + * fasync: split 'fasync_helper()' into separate add/remove functions + * ASoC: fix params_rate() macro use in several codecs + * modules: Skip empty sections when exporting section notes + * exofs: simple_write_end does not mark_inode_dirty + * nfsd: make sure data is on disk before calling ->fsync + * sunrpc: fix peername failed on closed listener + * SUNRPC: Fix up an error return value in + gss_import_sec_context_kerberos() + * SUNRPC: Fix the return value in gss_import_sec_context() + * sunrpc: on successful gss error pipe write, don't return error + * drm/i915: Update LVDS connector status when receiving ACPI LID event + * drm/i915: fix order of fence release wrt flushing + * drm/i915: Permit pinning whilst the device is 'suspended' + * drm: remove address mask param for drm_pci_alloc() + * drm/i915: Enable/disable the dithering for LVDS based on VBT setting + * drm/i915: Make the BPC in FDI rx/transcoder be consistent with that in + pipeconf on Ironlake + * drm/i915: Select the correct BPC for LVDS on Ironlake + * drm/i915: fix unused var + * rtc_cmos: convert shutdown to new pnp_driver->shutdown + * drivers/cpuidle/governors/menu.c: fix undefined reference to + `__udivdi3' + * cgroups: fix 2.6.32 regression causing BUG_ON() in cgroup_diput() + * lib/rational.c needs module.h + * dma-debug: allow DMA_BIDIRECTIONAL mappings to be synced with + DMA_FROM_DEVICE and + * kernel/signal.c: fix kernel information leak with print-fatal-signals=1 + * mmc_block: add dev_t initialization check + * mmc_block: fix probe error cleanup bug + * mmc_block: fix queue cleanup + * ALSA: hda - Fix ALC861-VD capture source mixer + * ALSA: ac97: Add Dell Dimension 2400 to Headphone/Line Jack Sense + blacklist + * ALSA: atiixp: Specify codec for Foxconn RC4107MA-RS2 + - LP: #498863 + * ASoC: Fix WM8350 DSP mode B configuration + * netfilter: ebtables: enforce CAP_NET_ADMIN + * netfilter: nf_ct_ftp: fix out of bounds read in update_nl_seq() + * hwmon: (coretemp) Fix TjMax for Atom N450/D410/D510 CPUs + * hwmon: (adt7462) Fix pin 28 monitoring + * quota: Fix dquot_transfer for filesystems different from ext4 + * xen: fix hang on suspend. + * iwlwifi: fix iwl_queue_used bug when read_ptr == write_ptr + * ath5k: Fix eeprom checksum check for custom sized eeproms + * cfg80211: fix syntax error on user regulatory hints + * iwl: off by one bug + * mac80211: add missing sanity checks for action frames + * drm/i915: remove render reclock support + * libertas: Remove carrier signaling from the scan code + * kernel/sysctl.c: fix stable merge error in NOMMU mmap_min_addr + * mac80211: fix skb buffering issue (and fixes to that) + * fix braindamage in audit_tree.c untag_chunk() + * fix more leaks in audit_tree.c tag_chunk() + * module: handle ppc64 relocating kcrctabs when CONFIG_RELOCATABLE=y + * ipv6: skb_dst() can be NULL in ipv6_hop_jumbo(). + * agp/intel-agp: Clear entire GTT on startup + * Linux 2.6.32.4 + * ethtool: Add reset operation + * gro: Name the GRO result enumeration type + * gro: Change all receive functions to return GRO result codes + * sfc: 10Xpress: Initialise pause advertising flags + * sfc: 10Xpress: Report support for pause frames + * sfc: Remove redundant header gmii.h + * sfc: Remove redundant hardware initialisation + * sfc: Rename Falcon-specific board code and types + * sfc: Remove boards.h, moving last remaining declaration to falcon.h + * sfc: Remove versioned bitfield macros + * sfc: Move RX data FIFO thresholds out of struct efx_nic_type + * sfc: Update hardware definitions for Siena + * sfc: Rename register I/O header and functions used by both Falcon and + Siena + * sfc: Eliminate indirect lookups of queue size constants + * sfc: Define DMA address mask explicitly in terms of descriptor field + width + * sfc: Move all TX DMA length limiting into tx.c + * sfc: Change order of device removal to reverse of probe order + * sfc: Remove declarations of nonexistent functions + * sfc: Move efx_xmit_done() declaration into correct stanza + * sfc: Move shared members of struct falcon_nic_data into struct efx_nic + * sfc: Maintain interrupt moderation values in ticks, not microseconds + * sfc: Removed kernel-doc for nonexistent member of efx_phy_operations + * sfc: Remove pointless abstraction of memory BAR number + * sfc: Remove incorrect assertion from efx_pci_remove_main() + * sfc: Remove unnecessary tests of efx->membase + * sfc: Move MTD probe after netdev registration and name allocation + * sfc: Remove unused code for non-autoneg speed/duplex switching + * sfc: Rename 'xfp' file and functions to reflect reality + * sfc: Really allow RX checksum offload to be disabled + * sfc: Feed GRO result into RX allocation policy and interrupt moderation + * sfc: Enable heuristic selection between page and skb RX buffers + * sfc: Remove pointless abstraction of memory BAR number (2) + * sfc: Remove redundant gotos from __efx_rx_packet() + * sfc: Remove ridiculously paranoid assertions + * sfc: Move assertions and buffer cleanup earlier in efx_rx_packet_lro() + * sfc: Record RX queue number on GRO path + * sfc: SFT9001: Reset LED configuration correctly after blinking + * sfc: Use a single blink implementation + * sfc: Rename efx_board::init_leds to init_phy and use for SFN4111T + * sfc: Make board information explicitly Falcon-specific + * sfc: Move definition of struct falcon_nic_data into falcon.h + * sfc: Move struct falcon_board into struct falcon_nic_data + * sfc: Move all I2C stuff into struct falcon_board + * sfc: Gather link state fields in struct efx_nic into new struct + efx_link_state + * sfc: Remove unnecessary casts to struct sk_buff * + * sfc: Remove redundant efx_xmit() function + * sfc: Combine high-level header files + * sfc: Log interrupt and reset type names, not numbers + * sfc: Fix descriptor cache sizes + * sfc: Treat all MAC registers as 128-bit + * sfc: Strengthen EFX_ASSERT_RESET_SERIALISED + * sfc: Comment corrections + * sfc: Remove unused constant + * sfc: Clean up struct falcon_board and struct falcon_board_data + * sfc: Fix bugs in RX queue flushing + * sfc: Remove unused function efx_flush_queues() + * sfc: Only switch Falcon MAC clocks as necessary + * sfc: Hold MAC lock for longer in efx_init_port() + * sfc: Split MAC stats DMA initiation and completion + * sfc: Move Falcon board/PHY/MAC monitoring code to falcon.c + * sfc: Simplify XMAC link polling + * sfc: Change MAC promiscuity and multicast hash at the same time + * sfc: Move inline comment into kernel-doc + * sfc: Do not set net_device::trans_start in self-test + * sfc: Simplify PHY polling + * sfc: QT202x: Reset before reading PHY id + * sfc: Replace MDIO spinlock with mutex + * sfc: Always start Falcon using the XMAC + * sfc: Limit some hardware workarounds to Falcon + * sfc: Remove EFX_WORKAROUND_9141 macro + * sfc: Remove another unused workaround macro + * sfc: Remove some redundant whitespace + * sfc: Decouple NIC revision number from Falcon PCI revision number + * sfc: Move descriptor cache base addresses to struct efx_nic_type + * sfc: Clean up RX event handling + * sfc: Remove redundant writes to INT_ADR_KER + * sfc: Remove duplicate hardware structure definitions + * sfc: Turn pause frame generation on and off at the MAC, not the RX FIFO + * sfc: Move Falcon NIC operations to efx_nic_type + * sfc: Refactor link configuration + * sfc: Generalise link state monitoring + * sfc: Add power-management and wake-on-LAN support + * sfc: Implement ethtool reset operation + * sfc: Add efx_nic_type operation for register self-test + * sfc: Add efx_nic_type operation for NVRAM self-test + * sfc: Add efx_nic_type operation for identity LED control + * sfc: Separate shared NIC code from Falcon-specific and rename + accordingly + * sfc: Fold falcon_probe_nic_variant() into falcon_probe_nic() + * sfc: Extend loopback mode enumeration + * sfc: Remove static PHY data and enumerations + * sfc: Extend MTD driver for use with new NICs + * sfc: Allow for additional checksum offload features + * sfc: Rename falcon.h to nic.h + * sfc: Move shared NIC code from falcon.c to new source file nic.c + * sfc: Add firmware protocol definitions (MCDI) + * sfc: Add support for SFC9000 family (1) + * sfc: Add support for SFC9000 family (2) + * sfc: Implement TSO for TCP/IPv6 + * sfc: Update version, copyright dates, authors + * drivers/net/sfc: Correct code taking the size of a pointer + * sfc: Move PHY software state initialisation from init() into probe() + * sfc: Include XGXS in XMAC link status check except in XGMII loopback + * sfc: Fix DMA mapping cleanup in case of an error in TSO + * sfc: QT2025C: Work around PHY bug + * sfc: QT2025C: Switch into self-configure mode when not in loopback + * sfc: QT2025C: Work around PHY firmware initialisation bug + * sfc: QT2025C: Add error message for suspected bad SFP+ cables + * sfc: Disable TX descriptor prefetch watchdog + * [SCSI] vmw_pvscsi: SCSI driver for VMware's virtual HBA. + - LP: #497156 + + -- Andy Whitcroft Tue, 19 Jan 2010 16:12:47 +0000 + +linux (2.6.32-10.14) lucid; urgency=low + + [ Alex Deucher ] + + * SAUCE: drm/radeon/kms: fix LVDS setup on r4xx + - LP: #493795 + + [ Andy Whitcroft ] + + * Revert "(pre-stable) acpi: Use the ARB_DISABLE for the CPU which model + id is less than 0x0f." + * config-check -- ensure the checks get run at build time + * config-check -- check the processed config during updateconfigs + * config-check -- CONFIG_SECCOMP may not be present + * TUN is now built in ignore + * SAUCE: acpi battery -- delay first lookup of the battery until first + use + * SAUCE: async_populate_rootfs: move rootfs init earlier + * ubuntu: AppArmor -- update to mainline 2010-01-06 + * SAUCE: move RLIMIT_CORE pipe dumper marker to 1 + - LP: #498525 + + [ Dave Airlie ] + + * (pre-stable) drm/radeon/kms: fix crtc vblank update for r600 + + [ Leann Ogasawara ] + + * Add asix to nic-usb-modules file + - LP: #499785 + + [ Peter Zijlstra ] + + * (pre-stable) sched: Fix balance vs hotplug race + + [ Tim Gardner ] + + * [Config] Enable CONFIG_FUNCTION_TRACER + - LP: #497989 + * [Config] Drop lpia from getabis + * [Config] Build in TUN/TAP driver + - LP: #499491 + * [Config] DH_COMPAT=5 + + [ Upstream Kernel Changes ] + + * Revert "(pre-stable) drm/i915: Avoid NULL dereference with + component_only tv_modes" + * Revert "(pre-stable) drm/i915: Fix sync to vblank when VGA output is + turned off" + * USB: usb-storage: fix bug in fill_inquiry + * USB: option: add pid for ZTE + * firewire: ohci: handle receive packets with a data length of zero + * rcu: Prepare for synchronization fixes: clean up for non-NO_HZ handling + of ->completed counter + * rcu: Fix synchronization for rcu_process_gp_end() uses of ->completed + counter + * rcu: Fix note_new_gpnum() uses of ->gpnum + * rcu: Remove inline from forward-referenced functions + * perf_event: Fix invalid type in ioctl definition + * perf_event: Initialize data.period in perf_swevent_hrtimer() + * perf: Don't free perf_mmap_data until work has been done + * PM / Runtime: Fix lockdep warning in __pm_runtime_set_status() + * sched: Check for an idle shared cache in select_task_rq_fair() + * sched: Fix affinity logic in select_task_rq_fair() + * sched: Rate-limit newidle + * sched: Fix and clean up rate-limit newidle code + * x86/amd-iommu: attach devices to pre-allocated domains early + * x86/amd-iommu: un__init iommu_setup_msi + * x86, Calgary IOMMU quirk: Find nearest matching Calgary while walking + up the PCI tree + * x86: Fix iommu=nodac parameter handling + * x86: GART: pci-gart_64.c: Use correct length in strncmp + * x86: ASUS P4S800 reboot=bios quirk + - LP: #366682 + * x86, apic: Enable lapic nmi watchdog on AMD Family 11h + * ssb: Fix range check in sprom write + * ath5k: allow setting txpower to 0 + * ath5k: enable EEPROM checksum check + * hrtimer: Fix /proc/timer_list regression + * ALSA: hrtimer - Fix lock-up + * ALSA: hda - Terradici HDA controllers does not support 64-bit mode + * KVM: x86 emulator: limit instructions to 15 bytes + * KVM: s390: Fix prefix register checking in arch/s390/kvm/sigp.c + * KVM: s390: Make psw available on all exits, not just a subset + * KVM: fix irq_source_id size verification + * KVM: x86: include pvclock MSRs in msrs_to_save + * x86: Prevent GCC 4.4.x (pentium-mmx et al) function prologue wreckage + * x86: Use -maccumulate-outgoing-args for sane mcount prologues + * x86, mce: don't restart timer if disabled + * x86/mce: Set up timer unconditionally + * x86: SGI UV: Fix BAU initialization + * x86: Fix duplicated UV BAU interrupt vector + * x86: Add new Intel CPU cache size descriptors + * x86: Fix typo in Intel CPU cache size descriptor + * pata_hpt{37x|3x2n}: fix timing register masks (take 2) + * s390: clear high-order bits of registers after sam64 + * V4L/DVB: Fix test in copy_reg_bits() + * bsdacct: fix uid/gid misreporting + * UBI: flush wl before clearing update marker + * jbd2: don't wipe the journal on a failed journal checksum + * USB: xhci: Add correct email and files to MAINTAINERS entry. + * USB: musb_gadget_ep0: fix unhandled endpoint 0 IRQs, again + * USB: option.c: add support for D-Link DWM-162-U5 + * USB: usbtmc: repeat usb_bulk_msg until whole message is transfered + * USB: usb-storage: add BAD_SENSE flag + * USB: Close usb_find_interface race v3 + * pxa/em-x270: fix usb hub power up/reset sequence + * hfs: fix a potential buffer overflow + * SUNRPC: IS_ERR/PTR_ERR confusion + * NFS: Fix nfs_migrate_page() + * md/bitmap: protect against bitmap removal while being updated. + * futex: Take mmap_sem for get_user_pages in fault_in_user_writeable + * devpts_get_tty() should validate inode + * debugfs: fix create mutex racy fops and private data + * Driver core: fix race in dev_driver_string + * Serial: Do not read IIR in serial8250_start_tx when UART_BUG_TXEN + * mac80211: Fix bug in computing crc over dynamic IEs in beacon + * mac80211: Fixed bug in mesh portal paths + * mac80211: Revert 'Use correct sign for mesh active path refresh' + * mac80211: fix scan abort sanity checks + * wireless: correctly report signal value for IEEE80211_HW_SIGNAL_UNSPEC + * rtl8187: Fix wrong rfkill switch mask for some models + * x86: Fix bogus warning in apic_noop.apic_write() + * mm: hugetlb: fix hugepage memory leak in mincore() + * mm: hugetlb: fix hugepage memory leak in walk_page_range() + * powerpc/windfarm: Add detection for second cpu pump + * powerpc/therm_adt746x: Record pwm invert bit at module load time] + * powerpc: Fix usage of 64-bit instruction in 32-bit altivec code + * drm/radeon/kms: Add quirk for HIS X1300 board + * drm/radeon/kms: handle vblanks properly with dpms on + * drm/radeon/kms: fix legacy crtc2 dpms + * drm/radeon/kms: fix vram setup on rs600 + * drm/radeon/kms: rs6xx/rs740: clamp vram to aperture size + * drm/ttm: Fix build failure due to missing struct page + * drm/i915: Set the error code after failing to insert new offset into mm + ht. + * drm/i915: Add the missing clonemask for display port on Ironlake + * xen/xenbus: make DEVICE_ATTR()s static + * xen: re-register runstate area earlier on resume. + * xen: restore runstate_info even if !have_vcpu_info_placement + * xen: correctly restore pfn_to_mfn_list_list after resume + * xen: register timer interrupt with IRQF_TIMER + * xen: register runstate on secondary CPUs + * xen: don't call dpm_resume_noirq() with interrupts disabled. + * xen: register runstate info for boot CPU early + * xen: call clock resume notifier on all CPUs + * xen: improve error handling in do_suspend. + * xen: don't leak IRQs over suspend/resume. + * xen: use iret for return from 64b kernel to 32b usermode + * xen: explicitly create/destroy stop_machine workqueues outside + suspend/resume region. + * Xen balloon: fix totalram_pages counting. + * xen: try harder to balloon up under memory pressure. + * dm exception store: free tmp_store on persistent flag error + * dm snapshot: only take lock for statustype info not table + * dm crypt: move private iv fields to structs + * dm crypt: restructure essiv error path + * dm: avoid _hash_lock deadlock + * dm snapshot: cope with chunk size larger than origin + * dm crypt: separate essiv allocation from initialisation + * dm crypt: make wipe message also wipe essiv key + * slc90e66: fix UDMA handling + * tcp: Stalling connections: Fix timeout calculation routine + * ip_fragment: also adjust skb->truesize for packets not owned by a + socket + * b44 WOL setup: one-bit-off stack corruption kernel panic fix + * sparc64: Don't specify IRQF_SHARED for LDC interrupts. + * sparc64: Fix overly strict range type matching for PCI devices. + * sparc64: Fix stack debugging IRQ stack regression. + * sparc: Set UTS_MACHINE correctly. + * b43legacy: avoid PPC fault during resume + * tracing: Fix event format export + * ath9k: Fix TX hang poll routine + * ath9k: fix processing of TX PS null data frames + * ath9k: Fix maximum tx fifo settings for single stream devices + * ath9k: fix tx status reporting + * mac80211: Fix dynamic power save for scanning. + * drm/i915: Fix sync to vblank when VGA output is turned off + * memcg: fix memory.memsw.usage_in_bytes for root cgroup + * thinkpad-acpi: fix default brightness_mode for R50e/R51 + * thinkpad-acpi: preserve rfkill state across suspend/resume + * ipw2100: fix rebooting hang with driver loaded + * matroxfb: fix problems with display stability + * acerhdf: add new BIOS versions + * asus-laptop: change light sens default values. + * vmalloc: conditionalize build of pcpu_get_vm_areas() + * ACPI: Use the ARB_DISABLE for the CPU which model id is less than 0x0f. + * net: Fix userspace RTM_NEWLINK notifications. + * ext3: Fix data / filesystem corruption when write fails to copy data + * V4L/DVB (13116): gspca - ov519: Webcam 041e:4067 added. + * bcm63xx_enet: fix compilation failure after get_stats_count removal + * x86: Under BIOS control, restore AP's APIC_LVTTHMR to the BSP value + * drm/i915: Avoid NULL dereference with component_only tv_modes + * drm/i915: PineView only has LVDS and CRT ports + * drm/i915: Fix LVDS stability issue on Ironlake + * mm: sigbus instead of abusing oom + * ipvs: zero usvc and udest + * jffs2: Fix long-standing bug with symlink garbage collection. + * intel-iommu: Detect DMAR in hyperspace at probe time. + * intel-iommu: Apply BIOS sanity checks for interrupt remapping too. + * intel-iommu: Check for an RMRR which ends before it starts. + * intel-iommu: Fix oops with intel_iommu=igfx_off + * intel-iommu: ignore page table validation in pass through mode + * netfilter: xtables: document minimal required version + * perf_event: Fix incorrect range check on cpu number + * implement early_io{re,un}map for ia64 + * Linux 2.6.32.2 + + -- Andy Whitcroft Thu, 07 Jan 2010 15:28:43 +0000 + +linux (2.6.32-9.13) lucid; urgency=low + + [ Andy Whitcroft ] + + * [Config] enable CONFIG_B43_PHY_LP + - LP: #493059 + * include modules.builtin in the binary debs + * config-check -- add a configuration enforcer + * config-check -- add a unit-test suite to the checker + * [Config] Enable CONFIG_SYN_COOKIES for versatile + * [Config] Enable CONFIG_SECURITY_SMACK for ports + * [Config] Enable CONFIG_SECURITY_FILE_CAPABILITIES for ports + * [Config] Disable CONFIG_COMPAT_BRK for ports + * getabis -- add armel versatile to the list + + [ Brad Figg ] + + * SAUCE: Increase the default prealloc buffer for HDA audio devices + (non-modem) + + [ Manoj Iyer ] + + * ubuntu: onmibook -- Added missing BOM file + + [ Tim Gardner ] + + * ubuntu: fsam7400 -- Cleanup Makefile + + [ Upstream Kernel Changes ] + + * Revert "ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT" + * signal: Fix alternate signal stack check + * SCSI: scsi_lib_dma: fix bug with dma maps on nested scsi objects + * SCSI: osd_protocol.h: Add missing #include + * SCSI: megaraid_sas: fix 64 bit sense pointer truncation + * ext4: fix potential buffer head leak when add_dirent_to_buf() returns + ENOSPC + * ext4: avoid divide by zero when trying to mount a corrupted file system + * ext4: fix the returned block count if EXT4_IOC_MOVE_EXT fails + * ext4: fix lock order problem in ext4_move_extents() + * ext4: fix possible recursive locking warning in EXT4_IOC_MOVE_EXT + * ext4: plug a buffer_head leak in an error path of ext4_iget() + * ext4: make sure directory and symlink blocks are revoked + * ext4: fix i_flags access in ext4_da_writepages_trans_blocks() + * ext4: journal all modifications in ext4_xattr_set_handle + * ext4: don't update the superblock in ext4_statfs() + * ext4: fix uninit block bitmap initialization when s_meta_first_bg is + non-zero + * ext4: fix block validity checks so they work correctly with meta_bg + * ext4: avoid issuing unnecessary barriers + * ext4: fix error handling in ext4_ind_get_blocks() + * ext4: make trim/discard optional (and off by default) + * ext4: make "norecovery" an alias for "noload" + * ext4: Fix double-free of blocks with EXT4_IOC_MOVE_EXT + * ext4: initialize moved_len before calling ext4_move_extents() + * ext4: move_extent_per_page() cleanup + * jbd2: Add ENOMEM checking in and for + jbd2_journal_write_metadata_buffer() + * ext4: Return the PTR_ERR of the correct pointer in + setup_new_group_blocks() + * ext4: Avoid data / filesystem corruption when write fails to copy data + * ext4: wait for log to commit when umounting + * ext4: remove blocks from inode prealloc list on failure + * ext4: ext4_get_reserved_space() must return bytes instead of blocks + * ext4: quota macros cleanup + * ext4: fix incorrect block reservation on quota transfer. + * ext4: Wait for proper transaction commit on fsync + * ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT + * ext4: Fix potential fiemap deadlock (mmap_sem vs. i_data_sem) + * Linux 2.6.32.1 + * kbuild: generate modules.builtin + * (pre-stable) drm/i915: Fix sync to vblank when VGA output is turned off + - LP: #494461 + * (pre-stable) drm/i915: Avoid NULL dereference with component_only + tv_modes + - LP: #494045 + + [ Zhao Yakui ] + + * (pre-stable) acpi: Use the ARB_DISABLE for the CPU which model id is + less than 0x0f. + - LP: #481765 + + -- Andy Whitcroft Thu, 17 Dec 2009 15:41:21 +0000 + +linux (2.6.32-8.12) lucid; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: AppArmor -- add linux/err.h for ERR_PTR + + -- Andy Whitcroft Sat, 12 Dec 2009 10:56:16 +0000 + +linux (2.6.32-8.11) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "SAUCE: default ATI Radeon KMS to off until userspace catches + up" + * Revert "SAUCE: AppArmor: Fix oops there is no tracer and doing unsafe + transition." + * Revert "SAUCE: AppArmor: Fix refcounting bug causing leak of creds" + * Revert "SAUCE: AppArmor: Fix cap audit_caching preemption disabling" + * Revert "SAUCE: AppArmor: Fix Oops when in apparmor_bprm_set_creds" + * Revert "SAUCE: AppArmor: Fix oops after profile removal" + * Revert "SAUCE: AppArmor: AppArmor disallows truncate of deleted files." + * Revert "SAUCE: AppArmor: AppArmor fails to audit change_hat correctly" + * Revert "SAUCE: AppArmor: Policy load and replacement can fail to alloc + mem" + * Revert "SAUCE: AppArmor: AppArmor wrongly reports allow perms as + denied" + * Revert "SAUCE: AppArmor: Fix mediation of "deleted" paths" + * Revert "SAUCE: AppArmor: Fix off by 2 error in getprocattr mem + allocation" + * Revert "SAUCE: AppArmor: Set error code after structure + initialization." + * Revert "AppArmor -- fix pstrace_may_access rename" + * Revert "ubuntu: AppArmor security module" + * Revert "SAUCE: Add config option to set a default LSM" + * Revert "ubuntu: fsam7400 -- sw kill switch driver" + * Revert "[Config] fsam7400 -- enable" + * Revert "[Config] AUFS -- enable" + * Revert "ubuntu: AUFS -- aufs2-30 20090727" + * Revert "ubuntu: AUFS -- export various core functions -- fixes" + * Revert "ubuntu: AUFS -- export various core functions" + * Revert "[Config] ubuntu/iscsitarget -- disable" + * Revert "[Config] iscsitarget -- enable" + * Revert "ubuntu: iscsitarget -- SVN revision r214" + * update Vcs-Git to point to the correct repository + - LP: #493589 + * update build environment overrides to lucid + - LP: #493589 + * [Config] enable CONFIG_DEVTMPFS + * [Config] update all configs following AppArmor 2009-12-08 update + * SAUCE: isapnp_init: make isa PNP scans occur async + * [Config] fsam7400 -- enable + * [Config] omnibook -- enable + * [Config] cleanup CONFIG_AUDIT + * ubuntu: AUFS -- export various core functions (aufs2-base.patch) + * ubuntu: AUFS -- export various core functions (aufs2-standalone.patch) + * ubuntu: AUFS -- aufs2 20091209 + * [Config] AUFS -- enable + * [Config] iscsitarget -- enable + + [ Arjan van de Ven ] + + * SAUCE: KMS: cache the EDID information of the LVDS + + [ Colin Watson ] + + * bnx2: update d-i firmware filenames + - LP: #494052 + * add cdc_ether to nic-usb-modules udeb + - LP: #495060 + + [ John Johansen ] + + * ubuntu: AppArmor -- mainline 2009-10-08 + + [ Manoj Iyer ] + + * ubuntu: fsam7400 -- kill switch for Fujitsu Siemens Amilo M 7400 + * ubuntu: omnibook -- support Toshiba (HP) netbooks + * ubuntu: iscsitarget --- version 1.4.19 + - LP: #494693 + + [ Surbhi Palande ] + + * SAUCE: Make populate_rootfs asynchronous + + [ Tim Gardner ] + + * Parallelize flavour builds and packaging + * [Config] Enable CONFIG_KSM + + [ Upstream Kernel Changes ] + + * Config option to set a default LSM + * LSM: Add security_path_chroot(). + * LSM: Add security_path_chroot(). + * LSM: Move security_path_chmod()/security_path_chown() to after + mutex_lock(). + * ext4: Fix insufficient checks in EXT4_IOC_MOVE_EXT + + -- Andy Whitcroft Fri, 11 Dec 2009 17:45:19 +0000 + +linux (2.6.32-7.10) lucid; urgency=low + + [ Andy Whitcroft ] + + * [Config] disable CONFIG_THUMB2_KERNEL to fix arm FTBFS + + -- Andy Whitcroft Sun, 06 Dec 2009 12:56:48 +0000 + +linux (2.6.32-7.9) lucid; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: set /proc/acpi/video/*/DOS to 4 by default + - LP: #458982 + * SAUCE: ensure vga16fb loads if no other driver claims the VGA device + * [Config] update configs following versatile switch to V7 + * rebased to v2.6.32 + * [Config] update configs following rebase to v2.6.32 + * [Config] update ports configs following rebase to v2.6.32 + * SAUCE: default ATI Radeon KMS to off until userspace catches up + + [ Arjan van de Ven ] + + * SAUCE: vfs: Add a trace point in the mark_inode_dirty function + + [ Leann Ogasawara ] + + * [SCSI] megaraid_sas: remove sysfs poll_mode_io world writeable + permissions + - CVE-2009-3939 + + [ Loic Minier ] + + * SAUCE: select a v7 CPU for versatile + + [ Takashi Iwai ] + + * SAUCE: ALSA: hda - Add power on/off counter + + [ Upstream changes ] + + * rebased to v2.6.32 + + -- Andy Whitcroft Fri, 04 Dec 2009 10:44:50 +0000 + +linux (2.6.32-6.8) lucid; urgency=low + + [ Andy Whitcroft ] + + * [Config] disable SSB devices for armel + + -- Andy Whitcroft Sat, 28 Nov 2009 12:16:40 +0000 + +linux (2.6.32-6.7) lucid; urgency=low + + [ Andy Whitcroft ] + + * Revert "SAUCE: default ATI Radeon KMS to off until userspace catches up" + * Revert "SAUCE: Dell XPS710 reboot quirk" + * Revert "SAUCE: Link acpi-cpufreq.o first" + * Revert "SAUCE: LPIA Logical reset of USB port on resume" + * Revert "SAUCE: LPIA Reboot fix for Intel Crownbeach development boards" + * Revert "SAUCE: Enable HDMI audio codec on Studio XPS 1340" + * Revert "SAUCE: Dell laptop digital mic does not work, PCI 1028:0271" + * Revert "Add Dell Dimension 9200 reboot quirk" + * Revert "SAUCE: Correctly blacklist Thinkpad r40e in ACPI" + * Revert "SAUCE: tulip: Define ULI PCI ID's" + * Revert "SAUCE: Lower warning level of some PCI messages" + * Revert "mac80211: fix two issues in debugfs" + Drop a number of known redundant commits as identified in the Ubuntu + delta review blueprint. + + * reenable armel versatile flavour + * [Config] disable CONFIG_USB_DEVICEFS + + [ Tim Gardner ] + + * [Config] udeb: Add squashfs to fs-core-modules + - LP: #352615 + * [Config] Create a real squashfs udeb + - LP: #352615 + + + -- Andy Whitcroft Fri, 27 Nov 2009 17:31:16 +0000 + +linux (2.6.32-5.6) lucid; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.32-rc8 + * update configs following rebase to v2.6.32-rc8 + * update ports configs since rebase to v2.6.32-rc8 + * [Config] enable cgroup options + - LP: #480739 + + [ Upstream Kernel Changes ] + + * rebase to v2.6.32-rc8 + + -- Andy Whitcroft Mon, 23 Nov 2009 11:16:14 +0000 + +linux (2.6.32-4.5) lucid; urgency=low + + [ Andy Whitcroft ] + + * [Config] SERIO_LIBPS2 and SERIO_I8042 must match + * rebase to v2.6.32-rc7 + * resync with Karmic proposed + + [ John Johansen ] + + * SAUCE: AppArmor: Fix oops after profile removal + - LP: #475619 + * SAUCE: AppArmor: Fix Oops when in apparmor_bprm_set_creds + - LP: #437258 + * SAUCE: AppArmor: Fix cap audit_caching preemption disabling + - LP: #479102 + * SAUCE: AppArmor: Fix refcounting bug causing leak of creds + - LP: #479115 + * SAUCE: AppArmor: Fix oops there is no tracer and doing unsafe + transition. + - LP: #480112 + + [ Ubuntu Changes ] + + * resync with Karmic proposed (ddbc670a86a3dee18541a3734149f250ff307adf) + + [ Upstream Kernel Changes ] + + * rebase to v2.6.32-rc7 + + -- Andy Whitcroft Fri, 13 Nov 2009 11:35:13 +0000 + +linux (2.6.32-3.4) lucid; urgency=low + + [ Andy Whitcroft ] + + * [Config] SERIO_LIBPS2 and SERIO_I8042 must match + * [Upstream] add local prefix to oss local change_bits + + [ Upstream Kernel Changes ] + + * mtd/maps: gpio-addr-flash: pull in linux/ headers rather than asm/ + * mtd/maps: gpio-addr-flash: depend on GPIO arch support + + -- Andy Whitcroft Wed, 11 Nov 2009 14:47:04 +0000 + +linux (2.6.32-3.3) lucid; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.32-rc6 + * [Config] update configs following rebase to v2.6.32-rc6 + * [Config] update ports configs following rebase to v2.6.32-rc6 + * resync with Karmic Ubuntu-2.6.31-15.49 + * [Config] add module ignores for broken drivers + + [ John Johansen ] + + * SAUCE: AppArmor: AppArmor wrongly reports allow perms as denied + - LP: #453335 + * SAUCE: AppArmor: Policy load and replacement can fail to alloc mem + - LP: #458299 + * SAUCE: AppArmor: AppArmor fails to audit change_hat correctly + - LP: #462824 + * SAUCE: AppArmor: AppArmor disallows truncate of deleted files. + - LP: #451375 + + [ Kees Cook ] + + * SAUCE: Fix nx_enable reporting + - LP: #454285 + + [ Scott James Remnant ] + + * Revert "SAUCE: trace: add trace_event for the open() syscall" + * SAUCE: trace: add trace events for open(), exec() and uselib() + - LP: #462111 + + [ Stefan Bader ] + + * SAUCE: Fix sub-flavour script to not stop on missing directories + - LP: #453073 + + [ Ubuntu Changes ] + + * resync with Karmic Ubuntu-2.6.31-15.49 + + [ Upstream Kernel Changes ] + + * rebase to v2.6.32-rc6 + - LP: #464552 + + -- Andy Whitcroft Tue, 10 Nov 2009 15:00:57 +0000 + +linux (2.6.32-2.2) lucid; urgency=low + + [ Andy Whitcroft ] + + * install the full changelog with the binary package + * changelog -- explicitly note rebases and clean history + * reinstate armel.mk with no flavours + - LP: #449637 + * [Upstream] block: silently error unsupported empty barriers too + - LP: #420423 + * [Config] udate configs following karmic resync + * [Config] update ports configs following karmic resync + * [Upstream] lirc -- follow removal of .id element + + [ Colin Watson ] + + * Use section 'admin' rather than 'base' + * Add more e100 firmware to nic-modules + - LP: #451872 + * Add qla1280 firmware to scsi-modules + - LP: #381037 + + [ John Johansen ] + + * SAUCE: AppArmor: Set error code after structure initialization. + - LP: #427948 + * SAUCE: AppArmor: Fix off by 2 error in getprocattr mem allocation + - LP: #446595 + * SAUCE: AppArmor: Fix mediation of "deleted" paths + + [ Kees Cook ] + + * SAUCE: [x86] fix report of cs-limit nx-emulation + - LP: #454285 + + [ Leann Ogasawara ] + + * SAUCE: (drop after 2.6.31) input: Add support for filtering input + events + - LP: #430809 + * SAUCE: (drop after 2.6.31) dell-laptop: Trigger rfkill updates on wifi + toggle switch press + - LP: #430809 + + [ Luke Yelavich ] + + * SAUCE: Add sr_mod to the scsi-modules udeb for powerpc + * [Config] Add sd_mod to scsi-modules udeb for powerpc + + [ Mario Limonciello ] + + * SAUCE: Update to LIRC 0.8.6 + - LP: #432678 + * SAUCE: dell-laptop: Store the HW switch status internally rather than + requerying every time + - LP: #430809 + * SAUCE: dell-laptop: Blacklist machines not supporting dell-laptop + - LP: #430809 + + [ Stefan Bader ] + + * [Upstream] acerhdf: Limit modalias matching to supported boards + - LP: #435958 + + [ Tim Gardner ] + + * [Upstream] i915: Fix i2c init message + - LP: #409361 + * [Config] Add sym53c8xx.ko to virtual sub-flavour + - LP: #439415 + * [Config] Add d101m_ucode.bin to d-i/firmware/nic-modules + - LP: #439456 + * [Config] Set default I/O scheduler back to CFQ for desktop flavours + - LP: #381300 + * SAUCE: Created MODULE_EXPORT/MODULE_IMPORT macros + - LP: #430694 + * SAUCE: Use MODULE_IMPORT macro to tie intel_agp to i915 + - LP: #430694 + * [Config] CONFIG_GFS2_FS_LOCKING_DLM=y + - LP: #416325 + * SAUCE: Fix MODULE_IMPORT/MODULE_EXPORT + - LP: #430694 + * SAUCE: Raise the default console 'quiet' level to 2 + * [Config] CONFIG_X86_PAT=y + * [Config] Add armel arch to linux-libc-dev arches. + - LP: #449637 + * [Config] CONFIG_X86_MCE + * [Upstream] (drop after 2.6.31) Input: synaptics - add another Protege + M300 to rate blacklist + - LP: #433801 + + [ Upstream Kernel Changes ] + + * sgi-gru: Fix kernel stack buffer overrun, CVE-2009-2584 + * drm/i915: Fix FDI M/N setting according with correct color depth + - LP: #416792 + + -- Andy Whitcroft Thu, 22 Oct 2009 16:53:33 +0100 + +linux (2.6.32-1.1) lucid; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.32-rc3 + * [Config] update configs following rebase to 2.6.32-rc3 + * [Config] update ports configs following rebase to 2.6.32-rc3 + * AppArmor -- fix pstrace_may_access rename + * staging/android -- disable + * ubuntu: dm-raid-45 -- update to compile with 2.6.32 + * ubuntu: drbd -- disable + * staging/comdi -- disable + * staging/go7007 -- disable + * [Config] staging/winbond -- disable + * [Config] ubuntu/iscsitarget -- disable + * [d-i] cbc and ecb are builtin make them optional in udebs + * rebase to v2.6.32-rc5 + * [Config] update configs following rebase to v2.6.32-rc5 + * [Config] update ports configs following rebase to v2.6.31-rc5 + + [ Tim Gardner ] + + * [Config] Add cpio as a build dependency. + + [ Upstream Kernel Changes ] + + * rebase to v2.6.32-rc3 + * rebase to v2.6.32-rc5 + + -- Andy Whitcroft Mon, 05 Oct 2009 15:48:58 +0100 + +linux (2.6.31-11.37) karmic; urgency=low + + [ Tim Gardner ] + + * [Config] Increase kernel log buffer to 256K for amd64 flavours + - LP: #424810 + * [Config] Set HZ=100 for amd64 flavours + - LP: #438234 + * [Upstream] e1000e: Emit notice instead of an error when + pci_enable_pcie_error_reporting() fails + - LP: #436370 + + [ Upstream Kernel Changes ] + + * n_tty: honor opost flag for echoes + * n_tty: move echoctl check and clean up logic + - LP: #438310 + + * Revert "[Upstream] drm/i915: Check that the relocation points to within + the target" - Use upstream cherry-pick. + * drm/i915: Check that the relocation points to within the target + - LP: #429241 + + * drm/i915: fix tiling on IGDNG + * drm/i915: add B43 chipset support + * agp/intel: Add B43 chipset support + Intel request from kernel team mailing list. + + * HID: completely remove apple mightymouse from blacklist + - LP: #428111 + + -- Tim Gardner Mon, 28 Sep 2009 11:47:29 -0600 + +linux (2.6.31-11.36) karmic; urgency=low + + [ Brian Rogers ] + + * SAUCE: (drop after 2.6.31) em28xx: ir-kbd-i2c init data needs a + persistent object + * SAUCE: (drop after 2.6.31) saa7134: ir-kbd-i2c init data needs a + persistent object + + [ Takashi Iwai ] + + * [Upstream] ALSA: hda - Add another entry for Nvidia HDMI device + - LP: #416482 + + [ Tyler Hicks ] + + * SAUCE: (drop after 2.6.31) eCryptfs: Prevent lower dentry from going + negative during unlink + + [ Upstream Kernel Changes ] + + * sg: fix oops in the error path in sg_build_indirect() + * mpt2sas : Rescan topology from Interrupt context instead of work thread + * mpt2sas: Prevent sending command to FW while Host Reset + * mpt2sas: setting SDEV into RUNNING state from Interrupt context + * mpt2sas: Raid 10 Volume is showing as Raid 1E in dmesg + * SCSI: fix oops during scsi scanning + * SCSI: libsrp: fix memory leak in srp_ring_free() + * cfg80211: fix looping soft lockup in find_ie() + * ath5k: write PCU registers on initial reset + * binfmt_elf: fix PT_INTERP bss handling + * TPM: Fixup boot probe timeout for tpm_tis driver + * md: Fix "strchr" [drivers/md/dm-log-userspace.ko] undefined! + * x86/amd-iommu: fix broken check in amd_iommu_flush_all_devices + * fix undefined reference to user_shm_unlock + * perf_counter: Fix buffer overflow in perf_copy_attr() + * perf_counter: Start counting time enabled when group leader gets + enabled + * powerpc/perf_counters: Reduce stack usage of power_check_constraints + * powerpc: Fix bug where perf_counters breaks oprofile + * powerpc/ps3: Workaround for flash memory I/O error + * block: don't assume device has a request list backing in nr_requests + store + * agp/intel: remove restore in resume + * ALSA: cs46xx - Fix minimum period size + * ASoC: Fix WM835x Out4 capture enumeration + * sound: oxygen: work around MCE when changing volume + * mlx4_core: Allocate and map sufficient ICM memory for EQ context + * perf stat: Change noise calculation to use stddev + * x86: Fix x86_model test in es7000_apic_is_cluster() + * x86/i386: Make sure stack-protector segment base is cache aligned + * PCI: apply nv_msi_ht_cap_quirk on resume too + * x86, pat: Fix cacheflush address in change_page_attr_set_clr() + * ARM: 5691/1: fix cache aliasing issues between kmap() and kmap_atomic() + with highmem + * KVM guest: do not batch pte updates from interrupt context + * KVM: Fix coalesced interrupt reporting in IOAPIC + * KVM: VMX: Check cpl before emulating debug register access + * KVM guest: fix bogus wallclock physical address calculation + * KVM: x86: Disallow hypercalls for guest callers in rings > 0 + * KVM: VMX: Fix cr8 exiting control clobbering by EPT + * KVM: x86 emulator: Implement zero-extended immediate decoding + * KVM: MMU: make __kvm_mmu_free_some_pages handle empty list + * KVM: x86 emulator: fix jmp far decoding (opcode 0xea) + * KVM: limit lapic periodic timer frequency + * libata: fix off-by-one error in ata_tf_read_block() + * PCI quirk: update 82576 device ids in SR-IOV quirks list + * PCI: Unhide the SMBus on the Compaq Evo D510 USDT + * powerpc/pseries: Fix to handle slb resize across migration + * Linux 2.6.31.1 + + -- Tim Gardner Thu, 24 Sep 2009 13:04:28 -0600 + +linux (2.6.31-10.35) karmic; urgency=low + + [ Amit Kucheria ] + + * Disable CONFIG_UEVENT_HELPER_PATH + + [ Andy Whitcroft ] + + * [Config] Enable CONFIG_USB_GADGET_DUMMY_HCD + * remove the tlsup driver + * remove lmpcm logitech driver support + + [ Bryan Wu ] + + * Add 3 missing files to prerm remove file list + - LP: #345623, #415832 + + [ Chris Wilson ] + + * [Upstream] drm/i915: Check that the relocation points to within the + target + - LP: #429241 + + [ Luke Yelavich ] + + * [Config] Set CONFIG_EXT4_FS=y on ports architectures + + [ Manoj Iyer ] + + * SAUCE: Added quirk to recognize GE0301 3G modem as an interface. + - LP: #348861 + + [ Tim Gardner ] + + * Revert "[Upstream] ACPI: Add Thinkpad W500, W700, & W700ds to OSI(Linux) white-list" + * Revert "[Upstream] ACPI: Add Thinkpad R400 & Thinkpad R500 to OSI(Linux) white-list" + * Revert "[Upstream] ACPI: Add Thinkpad X300 & Thinkpad X301 to OSI(Linux) white-list" + * Revert "[Upstream] ACPI: Add Thinkpad X200, X200s, X200t to OSI(Linux) white-list" + * Revert "[Upstream] ACPI: Add Thinkpad T400 & Thinkpad T500 to OSI(Linux) white-list" + Upstream suggests that this is not the right approach. + + * [Config] Set default I/O scheduler to DEADLINE + CFQ seems to have some load related problems which are often exacerbated by sreadahead. + - LP: #381300 + + [ ubuntu@tjworld.net ] + + * SAUCE: ipw2200: Enable LED by default + - LP: #21367 + + [ Upstream Kernel Changes ] + + * ALSA: hda - Add support for new AMD HD audio devices + - LP: #430564 + + -- Andy Whitcroft Wed, 16 Sep 2009 15:37:49 +0100 + +linux (2.6.31-10.34) karmic; urgency=low + + [ Ted Tso ] + + * [Upstream] ext3: Don't update superblock write time when filesystem is + read-only + - LP: #427822 + + -- Tim Gardner Tue, 15 Sep 2009 16:00:45 -0600 + +linux (2.6.31-10.33) karmic; urgency=low + + [ Leann Ogasawara ] + + * [Upstream] dvb-usb: fix tuning with Cinergy T2 + - LP: #421258 + + [ Tim Gardner ] + + * [Config] Unconditionally copy files from sub-flavours lists. + (really, really fix it this time) + - LP: #423426 + * [Config] Set CONFIG_CACHEFILES=m for all flavours + + [ Upstream Kernel Changes ] + + * ext4: Don't update superblock write time when filesystem is read-only + - LP: #427822 + + -- Tim Gardner Tue, 15 Sep 2009 07:50:21 -0600 + +linux (2.6.31-10.32) karmic; urgency=low + + [ Eric Miao ] + + * [Config] enable module support for memory stick + - LP: #159951 + + [ Tim Gardner ] + + * [Config] Unconditionally copy files from sub-flavours lists. + - LP: #423426 + + -- Tim Gardner Thu, 10 Sep 2009 15:57:55 -0600 + +linux (2.6.31-10.31) karmic; urgency=low + + [ Andy Whitcroft ] + + * rebase to v2.6.31 final + + [ Colin Watson ] + + * [Config] Recommend grub-pc in linux-image + - LP: #385741 + + [ Ike Panhc ] + + * [Upstream] Pull latest update of lenovo-sl-laptop + + [ Peter Feuerer ] + + * [Upstream] (drop after 2.6.31) acerhdf: fix fan control for AOA150 + model + - LP: #426691 + + [ Tim Gardner ] + + * [Config] De-macro some package names. + + [ Upstream Changes ] + + * rebase to 2.6.31 final. + + -- Andy Whitcroft Thu, 10 Sep 2009 09:38:10 +0100 + +linux (2.6.31-10.30) karmic; urgency=low + + [ Amit Kucheria ] + + * [Config] Enable CONFIG_USB_DEVICEFS + - LP: #417748 + * [Config] Populate the config-update template a bit more + + [ Andy Whitcroft ] + + * rebase to v2.6.31-rc9 + * [Config] update configs following rebase to v2.6.31-rc9 + * [Config] update ports configs following rebase to v2.6.31-rc9 + + [ Colin Ian King ] + + * SAUCE: wireless: hostap, fix oops due to early probing interrupt + - LP: #254837 + + [ Jerone Young ] + + * [Upstream] ACPI: Add Thinkpad T400 & Thinkpad T500 to OSI(Linux) + white-list + - LP: #281732 + * [Upstream] ACPI: Add Thinkpad X200, X200s, X200t to OSI(Linux) + white-list + - LP: #281732 + * [Upstream] ACPI: Add Thinkpad X300 & Thinkpad X301 to OSI(Linux) + white-list + - LP: #281732 + * [Upstream] ACPI: Add Thinkpad R400 & Thinkpad R500 to OSI(Linux) + white-list + - LP: #281732 + * [Upstream] ACPI: Add Thinkpad W500, W700, & W700ds to OSI(Linux) + white-list + - LP: #281732 + + [ John Johansen ] + + * SAUCE: AppArmor: Fix profile attachment for regexp based profile names + - LP: #419308 + * SAUCE: AppArmor: Return the correct error codes on profile + addition/removal + - LP: #408473 + * SAUCE: AppArmor: Fix OOPS in profile listing, and display full list + - LP: #408454 + * SAUCE: AppArmor: Fix mapping of pux to new internal permission format + - LP: #419222 + * SAUCE: AppArmor: Fix change_profile failure + - LP: #401931 + * SAUCE: AppArmor: Tell git to ignore generated include files + - LP: #419505 + + [ Stefan Bader ] + + * [Upstream] acpi: video: Loosen strictness of video bus detection code + - LP: #333386 + * SAUCE: Remove ov511 driver from ubuntu subdirectory + + [ Tim Gardner ] + + * [Config] Exclude char-modules from non-x86 udeb creation + * SAUCE: Notify the ACPI call chain of AC events + * [Config] CONFIG_SATA_VIA=m + - LP: #403385 + * [Config] Build in all phylib support modules. + * [Config] Don't fail when sub-flavour files are missing + - LP: #423426 + * [Config] Set CONFIG_LSM_MMAP_MIN_ADDR=0 + - LP: #423513 + + [ Upstream ] + + * Rebased against v2.6.31-rc9 + + -- Andy Whitcroft Mon, 07 Sep 2009 11:33:45 +0100 + +linux (2.6.31-9.29) karmic; urgency=low + + [ Leann Ogasawara ] + + * [Upstream] agp/intel: support for new chip variant of IGDNG mobile + - LP: #419993 + * [Config] d-i/modules: Add new char-modules file, initialize with + intel-agp + - LP: #420605 + + [ Upstream ] + + * Rebased against 2.6.31-rc8 plus some inotify regression patches: + up through git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git + adda766193ea1cf3137484a9521972d080d0b7af. + + -- Tim Gardner Fri, 28 Aug 2009 06:31:30 -0600 + +linux (2.6.31-8.28) karmic; urgency=low + + [ Ike Panhc ] + + * [Config] Let nic-shared-modules depends on crypto-modules + - LP: #360966 + + [ Leann Ogasawara ] + + * [Upstream] (drop after 2.6.31) drm/i915: increase default latency + constant + - LP: #412492 + + [ Mario Limonciello ] + + * [Upstream]: (drop after 2.6.31) dell-laptop: don't change softblock + status if HW switch is disabled + - LP: #418721 + * [Upstream]: (drop after 2.6.31) compal-laptop: Add support for known + Compal made Dell laptops + * [Upstream]: (drop after 2.6.31) compal-laptop: Replace sysfs support + with rfkill support + + [ Tim Gardner ] + + * [Config] Add acpiphp to virtual sub-flavour + - LP: #364916 + * Drop KSM patch set for now because of instabilities with encrypted swap. + - LP: #418781 + + -- Tim Gardner Wed, 26 Aug 2009 08:14:26 -0600 + +linux (2.6.31-7.27) karmic; urgency=low + + [ Tim Gardner ] + + * [Config] updateconfigs updateportsconfigs after 2.6.31-rc7 rebase + * SAUCE: (drop after 2.6.31) Added KSM from mmotm-2009-08-20-19-18 + Replaces previous ksm patches from 2.6.31-6.25 + * [Config] KSM=y + + [ Upstream ] + + * Rebased against v2.6.31-rc7 + + -- Tim Gardner Sat, 22 Aug 2009 20:32:11 -0600 + +linux (2.6.31-6.26) karmic; urgency=low + + [ Andy Whitcroft ] + + * [Config] enable CONFIG_AUFS_BR_RAMFS + - LP: #414738 + * split out debian directory ready for abstraction + * add printdebian target to find branch target + * abstracted debian -- debian/files is not abstracted + * abstracted debian -- packages must be built in debian/ + * abstracted debian -- kernel-wedge needs to work in debian/ + * abstracted debian -- ensure we install the copyright file + * abstracted-debian -- drop the debian directories from headers + * abstracted-debian -- drop the debian directories from headers part 2 + * SAUCE: ubuntu-insert-changes -- follow abstracted debian + * [Upstream] aoe: ensure we initialise the request_queue correctly V2 + - LP: #410198 + + [ Luke Yelavich ] + + * [Config] Ports: Disable CONFIG_CPU_FREQ_DEBUG on powerpc-smp + * [Config] Ports: Re-enable windfarm modules on powerpc64-smp + - LP: #413150 + * [Config] Ports: Build all cpu frequency scaling governors into ports + kernels + * [Config] Ports: Build ext2 and ext3 modules into ports kernels + * [Config] Ports: CONFIG_PACKET=y for all ports kernels + * [Config] Ports: Enable PS3 network driver + + [ Stefan Bader ] + + * abstracted debian -- call $(DEBIAN)/rules using make + + [ Tim Gardner ] + + * [Config] Abstract the debian directory + * SAUCE: Improve error reporting in postinst + - LP: #358564 + + -- Tim Gardner Sun, 16 Aug 2009 20:33:28 -0600 + +linux (2.6.31-6.25) karmic; urgency=low + + [ Andy Whitcroft ] + + * script to generate Ubuntu changes from changelog + * [Config] standardise ANDROID options + * [Config] standardise CONFIG_ATM as module + * [Config] standardise CONFIG_LIB80211 as module + * [Config] disable CONFIG_PRINT_QUOTA_WARNING + * [Config] set CONFIG_CRAMFS as module + * [Config] enable CONFIG_DAB and modules + * [Config] set CONFIG_MAC80211_HWSIM as module + * [Config] set CONFIG_NET_CLS_FLOW as module + * [Config] set CONFIG_NF_CONNTRACK_SANE as module + * [Config] set CONFIG_NF_CT_PROTO_DCCP as module + * [Config] set CONFIG_RTC_DRV_DS1511 as module + * [Config] set CONFIG_RTC_DRV_R9701 as module + * [Config] set CONFIG_RTC_DRV_S35390A as module + * [Config] set CONFIG_TOIM3232_DONGLE as module + * [Config] standardise CONFIG_USB_MIDI_GADGET as module + * [Config] standardise CONFIG_USB_G_PRINTER as module + * [Config] standardise CONFIG_USB_SERIAL_IR as module + * [Config] set CONFIG_USB_SERIAL_IUU as module + * [Config] standardise CONFIG_USB_STORAGE_CYPRESS_ATACB as module + * [Config] standardise CONFIG_USB_STORAGE_ONETOUCH as module + * cleanup remains of dm-loop + * drop thinkpad ec and smapi support + * drop appleir + * [Config] update configs following rebase to v2.6.31-rc6 + * rebase to v2.6.31-rc6 + + [ Hugh Dickins ] + + * SAUCE: ksm patch 1, drop after 2.6.31 + * SAUCE: ksm patch 2, drop after 2.6.31 + * SAUCE: ksm patch 3, drop after 2.6.31 + * SAUCE: ksm patch 4, drop after 2.6.31 + * SAUCE: ksm patch 5, drop after 2.6.31 + * SAUCE: ksm patch 7, drop after 2.6.31 + + [ Izik Eidus ] + + * SAUCE: ksm patch 0, drop after 2.6.31 + * SAUCE: ksm patch 6, drop after 2.6.31 + * SAUCE: ksm patch 8, drop after 2.6.31 + * SAUCE: ksm patch 9, drop after 2.6.31 + + [ Luke Yelavich ] + + * [Config] Ports: Re-add PS3 modules to udebs + + [ Michael Casadevall ] + + * [Config] Update SPARC config and d-i files to reflect what can be built + + [ Tim Gardner ] + + * [Config] Removed armel package support + * [Config] Enabled CONFIG_KSM=y + + [ Upstream Kernel Changes ] + + * Rebased against v2.6.31-rc6 + * ARM: Cleanup: Revert "ARM: Add more cache memory types macros" + * ARM: Cleanup: Revert "Do not use OOB with MLC NAND" + * ARM: Cleanup: Revert "ARM: Make ARM arch aware of ubuntu/ drivers" + * ARM: Cleanup: Revert "ARM: IMX51: Make video capture drivers compile" + * ARM: Cleanup: Revert "ARM: IMX51: Fix isl29003 HWMON driver for i2c + changes" + * ARM: Cleanup: Revert "ARM: IMX51: IPU irq handler deadlock fix" + * ARM: Cleanup: Revert "ARM: IMX51: Babbage 2.5 needs a different system + revision" + * ARM: Cleanup: Revert "ARM: IMX51: Compile-in the IMX51 cpufreq driver + by default" + * ARM: Cleanup: Revert "ARM: IMX51: Enable ZONE_DMA for ARCH_MXC" + * ARM: Cleanup: Revert "ARM: IMX51: Make ARCH_MXC auto-enable + ARCH_MXC_CANONICAL" + * ARM: Cleanup: Revert "ARM: IMX51: Unconditionally disable + CONFIG_GPIOLIB" + * ARM: Cleanup: Revert "ARM: IMX51: Minimal changes for USB to work on + 2.6.31" + * ARM: Cleanup: Revert "ARM: IMX51: Fix plat-mxc/timer.c to handle imx51" + * ARM: Cleanup: Revert "ARM: IMX51: Make it compile." + * ARM: Cleanup: Revert "ARM: IMX51: Clean-up the craziness of including + mxc_uart.h _everywhere_" + * ARM: Cleanup: Revert "ARM: IMX51: Move board-mx51* header files to the + correct location" + * ARM: Cleanup: Revert "ARM: IMX51: Changed from snd_card_new to + snd_card_create" + * ARM: Cleanup: Revert "ARM: IMX51: Fix up merge error in Kconfig" + * ARM: Cleanup: Revert "ARM: IMX51: mxc_timer_init prototype" + * ARM: Cleanup: Revert "ARM: IMX51: Removed the mxc_gpio_port structure." + * ARM: Cleanup: Revert "ARM: IMX51: Added external declaration for + mxc_map_io." + * ARM: Cleanup: Revert "ARM: IMX51: Get to bus_id by calling dev_name." + * ARM: Cleanup: Revert "ARM: IMX51: Get to bus_id by calling dev_name." + * ARM: Cleanup: Revert "ARM: IMX51: snd_soc_machine structure replaced + with snd_soc_card." + * ARM: Cleanup: Revert "ARM: IMX51: codec structure was moved to the card + structure" + * ARM: Cleanup: Revert "ARM: IMX51: Hack to add defines for + DMA_MODE_READ/WRITE/MASK" + * ARM: Cleanup: Revert "ARM: IMX51: Add SoC and board support for + Freescale mx51 platform" + * Driver core: add new device to bus's list before probing + * [Upstream] (drop after 2.6.31) ALSA: hda - Reduce click noise at + power-saving + - LP: #381693, #399750, #380892 + + -- Andy Whitcroft Fri, 14 Aug 2009 11:32:23 +0100 + +linux (2.6.31-5.24) karmic; urgency=low + + [ Amit Kucheria ] + + * ARM: IMX51: Make video capture drivers compile + * [Config] IMX51: Config updates + + [ Andy Whitcroft ] + + * remove leftovers of dm-bbr + + [ Leann Ogasawara ] + + * Add pata_cs5535 to pata-modules + - LP: #318805 + + [ Luke Yelavich ] + + * [Config] CONFIG_PPC64=y for powerpc64-smp + * [Config] Set the maximum number of CPUs to 1024 for powerpc64-smp + * [Config] CONFIG_PPC_PS3=y for powerpc64-smp + * [Config] CONFIG_PPC_MAPLE=y on powerpc64-smp + * [Config] CONFIG_PPC_PASEMI=y on powerpc64-smp + * [Config] CONFIG_CPU_FREQ_PMAC64=y on powerpc64-smp + * [Config] Enable all PS3 drivers in powerpc64-smp + + [ Mario Limonciello ] + + * LIRC -- fix lirc-i2c 2.6.31 compilation + + [ Matthew Garrett ] + + * [Upstream] dell-laptop: Fix rfkill state queries + + [ Tim Gardner ] + + * [Config] Ignore armel ABI and module changes + * [Config] Update configs after rebase against 2.6.31-rc5 + + [ Upstream ] + + * Rebased to 2.6.31-rc5 + + -- Andy Whitcroft Tue, 28 Jul 2009 10:10:09 +0100 + +linux (2.6.31-4.23) karmic; urgency=low + + [ Andy Whitcroft ] + + * AUFS -- update to aufs2-30 20090727 + * [Config] enable AUFS FUSE support + + [ Luke Yelavich ] + + * [Config] CONFIG_JFS_FS=m on sparc + + [ Tim Gardner ] + + * [Upstream] dell-laptop: Fix rfkill state setting. + + -- Andy Whitcroft Mon, 27 Jul 2009 11:11:47 +0100 + +linux (2.6.31-4.22) karmic; urgency=low + + [ Amit Kucheria ] + + * ARM: IMX51: Add SoC and board support for Freescale mx51 platform + * ARM: IMX51: Move board-mx51* header files to the correct location + * ARM: IMX51: Clean-up the craziness of including mxc_uart.h _everywhere_ + * ARM: IMX51: Make it compile. + * ARM: IMX51: Unconditionally disable CONFIG_GPIOLIB + * ARM: IMX51: Make ARCH_MXC auto-enable ARCH_MXC_CANONICAL + * ARM: IMX51: Enable ZONE_DMA for ARCH_MXC + * ARM: IMX51: Compile-in the IMX51 cpufreq driver by default + * ARM: IMX51: Fix isl29003 HWMON driver for i2c changes + * ARM: USB: musb: Refer to musb_otg_timer_func under correct #ifdef + * ARM: staging: udlfb: Add vmalloc.h include + * UBUNTU [Config]: Bring imx51 config upto date with other flavours + + [ Brad Figg ] + + * ARM: IMX51: Hack to add defines for DMA_MODE_READ/WRITE/MASK + * ARM: IMX51: codec structure was moved to the card structure + * ARM: IMX51: snd_soc_machine structure replaced with snd_soc_card. + * ARM: IMX51: Get to bus_id by calling dev_name. + * ARM: IMX51: Get to bus_id by calling dev_name. + * ARM: IMX51: Added external declaration for mxc_map_io. + * ARM: IMX51: Removed the mxc_gpio_port structure. + * ARM: IMX51: mxc_timer_init prototype + * ARM: IMX51: Fix up merge error in Kconfig + * ARM: IMX51: Changed from snd_card_new to snd_card_create + + [ Dinh Nguyen ] + + * ARM: IMX51: Fix plat-mxc/timer.c to handle imx51 + * ARM: IMX51: Minimal changes for USB to work on 2.6.31 + * ARM: IMX51: Babbage 2.5 needs a different system revision + * ARM: IMX51: IPU irq handler deadlock fix + + [ Tim Gardner ] + + * [Config] Enabled CONFIG_CAN=m + - LP: #327243 + * [Config] Enabled CONFIG_SERIAL=m + - LP: #397189 + + -- Tim Gardner Fri, 24 Jul 2009 06:19:10 -0600 + +linux (2.6.31-4.21) karmic; urgency=low + + [ Amit Kucheria ] + + * dm-raid-4-5: Add missing brackets around test_bit() + + [ John Johansen ] + + * AppArmor: Fix change_profile failing lpn401931 + * AppArmor: Fix determination of forced AUDIT messages. + * AppArmor: Fix oops in auditing of the policy interface offset + + -- Andy Whitcroft Thu, 23 Jul 2009 19:18:30 +0100 + +linux (2.6.31-4.20) karmic; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: iscsitarget -- update to SVN revision r214 + * SAUCE: iscsitarget -- renable driver + * [Config] consolidate lpia/lpia and i386/generic configs + * [Config] enable CRYPTO modules for all architectures + * [Config] enable cryptoloop + * [Config] enable various filesystems for armel + * [Config] sync i386 generic and generic-pae + * [Config] add the 386 (486 processors and above) flavour + * [Config] re-set DEFAULT_MMAP_MIN_ADDR + - LP: #399914 + * add genconfigs/genportsconfigs to extract the built configs + * updateconfigs -- alter concatenation order allow easier updates + * intelfb -- INTELFB now conflicts with DRM_I915 + * printchanges -- rebase tree does not have stable tags use changelog + * AppArmor: fix argument size missmatch on 64 bit builds + + [ Ike Panhc ] + + * Ship bnx2x firmware in nic-modules udeb + - LP: #360966 + + [ Jeff Mahoney ] + + * AppArmor: fix build failure on ia64 + + [ John Johansen ] + + * AppArmour: ensure apparmor enabled parmater is off if AppArmor fails to + initialize. + * AppArmour: fix auditing of domain transitions to include target profile + information + * AppArmor: fix C99 violation + * AppArmor: revert reporting of create to write permission. + * SAUCE: Add config option to set a default LSM + * [Config] enable AppArmor by default + * AppArmor: Fix NULL pointer dereference oops in profile attachment. + + [ Keith Packard ] + + * SAUCE: drm/i915: Allow frame buffers up to 4096x4096 on 915/945 class + hardware + - LP: #351756 + + [ Luke Yelavich ] + + * [Config] add .o files found in arch/powerpc/lib to all powerpc kernel + header packages + - LP: #355344 + + [ Michael Casadevall ] + + * [Config] update SPARC config files to allow success build + + [ Scott James Remnant ] + + * SAUCE: trace: add trace_event for the open() syscall + + [ Stefan Bader ] + + * SAUCE: jfs: Fix early release of acl in jfs_get_acl + - LP: #396780 + + [ Tim Gardner ] + + * [Upstream] Fix Soltech TA12 volume hotkeys not sending key release + - LP: #397499 + * [Upstream] USB Option driver - Add USB ID for Novatel MC727/U727/USB727 + refresh + - LP: #365291 + * [Config] SSB/B44 are common across all arches/flavours. + + [ Upstream ] + + * Rebased to 2.6.31-rc4 + + -- Andy Whitcroft Thu, 23 Jul 2009 08:41:39 +0100 + +linux (2.6.31-3.19) karmic; urgency=low + + [ Andy Whitcroft ] + + * Revert "[Config] Disabled NDISWRAPPER" + * ndiswrapper -- fix i386 compilation failures on cmpxchg8b + * AUFS -- export various core functions + * AUFS -- export various core functions -- fixes + * AUFS -- core filesystem + * AUFS -- track changes in v2.6.31 + * [Config] Enable AUFS + * droppped 'iwl3945: do not send scan command if channel count zero' as it + is already upstream but failed to auto-drop on rebase. + + [ Eric Paris ] + + * SAUCE: fsnotify: use def_bool in kconfig instead of letting the user + choose + * SAUCE: inotify: check filename before dropping repeat events + * SAUCE: fsnotify: fix inotify tail drop check with path entries + + -- Andy Whitcroft Tue, 14 Jul 2009 12:52:55 +0100 + +linux (2.6.31-3.18) karmic; urgency=low + + [ Andy Whitcroft ] + + * Revert "Add splice-2.6.23.patch from AUFS to export a symbol needed by + AUFS" + * Revert "Add put_filp.patch from AUFS to export a symbol needed by AUFS" + * Revert "Add sec_perm-2.6.24.patch from AUFS - export + security_inode_permission" + * clear out left over AUFS files and modifications + + [ Luke Yelavich ] + + * [Config] Enable CONFIG_USB_ISP116X_HCD on sparc + * SAUCE: Explicitly include header files to allow apparmor to build on + powerpc + * [Config] Enable CONFIG_BLK_DEV_IDECD on powerpc + + [ Tim Gardner ] + + * [Config] Dropped ubuntu/misc/wireless/acx + * [Config] Disabled NDISWRAPPER until the compile issues are fixed. + + [ Upstream ] + + * Rebased to 2.6.31-rc3 + + -- Andy Whitcroft Fri, 10 Jul 2009 18:59:33 +0100 + +linux (2.6.31-2.17) karmic; urgency=low + + [ Andy Whitcroft ] + + * [Config] CONFIG_BLK_DEV_CRYPTOLOOP=m for sparc + * compcache -- remove redundant Kconfig entries part 2 + * compcache -- clean up CCFLAGS declarations + * [Config] enable AppArmor + * AppArmor: fix operator precidence issue in as_path_link + + [ John Johansen ] + + * AppArmor security module + * AppArmor: Correct mapping of file permissions. + * AppArmor: Turn auditing of ptrace on + + [ Luke Yelavich ] + + * [Config] disable CONFIG_DM_RAID45 on powerpc + + -- Andy Whitcroft Fri, 10 Jul 2009 15:02:05 +0100 + +linux (2.6.31-2.16) karmic; urgency=low + + [ Andy Whitcroft ] + + * compcache -- remove redundant Kconfig entries + added ignore and ignore.modules for all arches since the compcache update + changes the modules names as well as some compcache ABI values. + + [ Manoj Iyer ] + + * SAUCE: updated dm-raid45 module version to 2009.04.24 (2.6.30-rc3) + * SAUCE: update compcache version to 0.5.3 + + [ Tim Gardner ] + + * [Config]: Fix sparc FTBS by adding ignore.modules + + -- Tim Gardner Mon, 06 Jul 2009 13:35:29 -0600 + +linux (2.6.31-2.15) karmic; urgency=low + + [ Andy Whitcroft ] + + * SAUCE: default ATI Radeon KMS to off until userspace catches up + * [Config] Update configs following rebase to 2.6.31-rc2 + * [Config] update ports configs following update to 2.6.31-rc2 + + [ Luke Yelavich ] + + * [Config] powerpc - Disable CONFIG_RDS + + [ Matt Zimmerman ] + + * Rename linux-doc-PKGVER to linux-doc and clean up its description + - LP: #382115 + + [ Upstream Kernel Changes ] + + * rebased to mainline 2.6.31-rc2 + + -- Andy Whitcroft Sat, 04 Jul 2009 17:39:13 +0100 + +linux (2.6.31-1.14) karmic; urgency=low + + [ Andy Whitcroft ] + + * update ndiswrapper to 1.55 + * remove leftovers of gfs + * [Config] powerpc: enable CONFIG_PPC_DISABLE_WERROR + + [ Luke Yelavich ] + + * [Config] re-enable and build the ide-pmac driver into powerpc kernels + * [Config] Build the ServerWorks Frodo / Apple K2 SATA driver into the + kernel + + [ Manoj Iyer ] + + * Remove snd-bt-sco ubuntu driver + + [ Michael Casadevall ] + + * [Config] updates ia64 config and d-i folders to allow succesful build + * [Config] Update powerpc and sparc for 2.6.31 + + [ Upstream Kernel Changes ] + + * intel-iommu: fix Identity Mapping to be arch independent + - LP: #384695 + * ACPI: video: prevent NULL deref in acpi_get_pci_dev() + + -- Andy Whitcroft Tue, 30 Jun 2009 17:47:32 +0100 + +linux (2.6.31-1.13) karmic; urgency=low + + [ Andy Whitcroft ] + + * REBASE: rebased to mainline 2.6.31-rc1 + - "UBUNTU: SAUCE: UHCI USB quirk for resume" + no longer applies, using deprecated interfaces, LPIA only, dropped + - "UBUNTU: SAUCE: Mask off garbage in Dell WMI scan code data" + changes now upstream, dropped + * [Config] Update configs following rebase to 2.6.31-rc1 + * [Config] update ports configs following update to 2.6.31-rc1 + + * [Config] disable broken staging driver CONFIG_STLC45XX + * SAUCE: fix compcache to use updates accessors + * [Config] disable staging driver CONFIG_VT6655 + * SAUCE: fix DRDB to use updates accessors + * [Disable] ndiswrapper needs update + * [Disable] LIRC I2C needs update + * [Disable] CONFIG_LENOVO_SL_LAPTOP needs update + * [Config] disable I2C_DESIGNWARE does not compile + * [Config] disable CONFIG_TLSUP for lpia + * [Config] disable CONFIG_FB_UDL for arm + * SAUCE: disable adding scsi headers to linux-libc-dev + + [ Mario Limonciello ] + + * SAUCE: Add LIRC drivers + + -- Andy Whitcroft Thu, 25 Jun 2009 12:06:22 +0100 + +linux (2.6.30-10.12) karmic; urgency=low + + [ Andy Whitcroft ] + + * [Config] split out the ports configs into their own family + * [Config] update configs following introduction of ports family + + [ Upstream Kernel Changes ] + + * Revert "Rename linux-doc-PKGVER to linux-doc and clean up its + description". Fixes linux-doc package name conflicts for now. + - LP: #382115 + + -- Tim Gardner Mon, 22 Jun 2009 09:17:14 -0600 + +linux (2.6.30-10.11) karmic; urgency=low + + [ Amit Kucheria ] + + * [Config] Comment splitconfig.pl and misc cleanup + * [Config] Rename all configs to the new naming scheme + * [Config] Splitconfig rework + * [Config] Rename scripts/misc/oldconfig to kernelconfig + * [Config] Fix build system for new config split + * [Config] Run updateconfigs after the splitconfig rework + + [ Andy Whitcroft ] + + * Revert "SAUCE: Default to i915.modeset=0 if CONFIG_DRM_I915_KMS=y" + * [Config] standardise CONFIG_STAGING=y + * [Config] standardise CONFIG_RD_LZMA=y + * [Config] CONFIG_PCI_IOV=y + * [Config] CONFIG_PCI_STUB=m + * [Config] merge kernel configs more agressively + + [ Colin Watson ] + + * [Config] Run kernel-wedge in $(builddir) rather than at the top level + * [Config] Add support for including firmware in udebs + * [Config] Ship bnx2 firmware in nic-modules udeb + - LP: #384861 + + [ Luke Yelavich ] + + * [Config] ports - Import of ports architectures into kernel packaging + infrastructure + * [Config] ports - Do not update ports kernel configurations by default + * [Config] ports - Disable ABI checking for ports architectures + * [Config] ports - Build drivers in ubuntu sub-directory on powerpc + * [Config] ports - Add control.d/vars.* files for ports architectures + * [Config] ports - Add ports architectures for linux-libc-dev + * [Config] ports - Create powerpc specific message-modules and + block-modules udebs + * [Config] ports - Add configuration files for ports architectures + + [ Manoj Iyer ] + + * [Config] Enable CONFIG_BLK_DEV_AEC62XX=m for amd64 and i386 + - LP: #329864 + + [ Michael Casadevall ] + + * [Config] ports - Fix compression of kernels + + [ Stefan Bader ] + + * [Upstream] mmc: prevent dangling block device from accessing stale + queues + - LP: #383668 + + [ Tim Gardner ] + + * [Config] Recommend grub-pc in linux-image + - LP: #385741 + * [Config] Implement i386 generic and generic-pae flavours + * [Config] ports - Add control info after integrating ports arches + * [Config] Removed auto-generated files from git + * [Config] Added netxen_nic to nic-modules + - LP: #389603 + + [ Matt Zimmerman ] + + * Rename linux-doc-PKGVER to linux-doc and clean up its description + - LP: #382115 + + -- Tim Gardner Mon, 15 Jun 2009 14:38:26 -0600 + +linux (2.6.30-9.10) karmic; urgency=low + + [ Andy Whitcroft ] + + * [Config] CONFIG_SECURITY_TOMOYO=y (amd64, i386, lpia) + * [Config] CONFIG_KEXEC_JUMP=y (amd64, lpia) + * [Config] CONFIG_LENOVO_SL_LAPTOP=m (amd64, lpia) + * [Config] CONFIG_POHMELFS_CRYPTO=y (i386, amd64) + * [Config] CONFIG_SERIAL_MAX3100=m (i386, amd64, lpia) + * [Config] CONFIG_VIDEO_GO7007=m (amd64, i386) + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30 final + + -- Andy Whitcroft Fri, 05 Jun 2009 11:42:53 +0100 + +linux (2.6.30-8.9) karmic; urgency=low + + [ Andy Whitcroft ] + + * Config update removed the following options: + CONFIG_EDAC_AMD8111=m + CONFIG_EDAC_AMD8131=m + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30-rc8 + + -- Andy Whitcroft Wed, 03 Jun 2009 09:21:13 +0100 + +linux (2.6.30-7.8) karmic; urgency=low + + [ Andy Whitcroft ] + + * Enabled NEW configration options: + Paravirtualization layer for spinlocks (PARAVIRT_SPINLOCKS) [N/y/?] Y + Cisco FNIC Driver (FCOE_FNIC) [N/m/y/?] M + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30-rc7 + + -- Andy Whitcroft Sat, 23 May 2009 23:47:24 +0100 + +linux (2.6.30-6.7) karmic; urgency=low + + [ Andy Whitcroft ] + + * Dropped: UBUNTU: SAUCE: input: Blacklist digitizers from joydev.c (now + upstream) + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30-rc6 + + -- Andy Whitcroft Mon, 18 May 2009 18:05:54 +0100 + +linux (2.6.30-5.6) karmic; urgency=low + + [ Tim Gardner ] + + * [Config] Enable Keyspan USB serial device firmware in kernel module + - LP: #334285 + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30-rc5 + + -- Tim Gardner Mon, 11 May 2009 12:02:16 -0600 + +linux (2.6.30-4.5) karmic; urgency=low + + [ Colin Watson ] + + * Build-Conflict with findutils (= 4.4.1-1ubuntu1), to avoid + /usr/include/asm/* going missing + - LP: #373214 + + -- Stefan Bader Fri, 08 May 2009 11:09:08 +0200 + +linux (2.6.30-3.4) karmic; urgency=low + + [ Kees Cook ] + + * SAUCE: [x86] implement cs-limit nx-emulation for ia32 + - LP: #369978 + + [ Stefan Bader ] + + * SAUCE: input: Blacklist digitizers from joydev.c + - LP: #300143 + + -- Tim Gardner Fri, 01 May 2009 14:00:42 -0600 + +linux (2.6.30-2.3) karmic; urgency=low + + [ Tim Gardner ] + + * [Config] Enabled CC_STACKPROTECTOR=y for all x86en + - LP: #369152 + * SAUCE: Default to i915_modeset=0 if CONFIG_DRM_I915_KMS=y + * [Config] CONFIG_DRM_I915_KMS=y + * [Config] Set CONFIG_SECURITY_DEFAULT_MMAP_MIN_ADDR to appropriate ARCH + minimums + + [ Upstream Kernel Changes ] + + * rebased to 2.6.30-rc4 + + -- Tim Gardner Thu, 30 Apr 2009 09:17:05 -0600 + +linux (2.6.30-1.2) karmic; urgency=low + + [ Tim Gardner ] + + * [Config] armel: disable staging drivers, fixes FTBS + * [Config] armel imx51: Disable CONFIG_MTD_NAND_MXC, fixes FTBS + + [ Upstream Kernel Changes ] + + * mpt2sas: Change reset_type enum to avoid namespace collision. + Submitted upstream. + + -- Tim Gardner Tue, 28 Apr 2009 16:54:41 -0600 + +linux (2.6.30-1.1) karmic; urgency=low + + * Initial release after rebasing against v2.6.30-rc3 + + -- Tim Gardner Thu, 12 Mar 2009 19:16:07 -0600 --- linux-2.6.37.orig/debian/copyright +++ linux-2.6.37/debian/copyright @@ -0,0 +1,29 @@ +This is the Ubuntu prepackaged version of the Linux kernel. +Linux was written by Linus Torvalds +and others. + +This package was put together by the Ubuntu Kernel Team, from +sources retrieved from upstream linux git. +The sources may be found at most Linux ftp sites, including +ftp://ftp.kernel.org/pub/linux/kernel/ + +This package is currently maintained by the +Ubuntu Kernel Team + +Linux is copyrighted by Linus Torvalds and others. + + 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; version 2 dated June, 1991. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Ubuntu Linux systems, the complete text of the GNU General +Public License v2 can be found in `/usr/share/common-licenses/GPL-2'. --- linux-2.6.37.orig/debian/commit-templates/bumpabi +++ linux-2.6.37/debian/commit-templates/bumpabi @@ -0,0 +1,3 @@ +UBUNTU: Bump ABI + +Ignore: yes --- linux-2.6.37.orig/debian/commit-templates/config-updates +++ linux-2.6.37/debian/commit-templates/config-updates @@ -0,0 +1,15 @@ +# +# This template is used for commit messages that don't need to +# show up in debian/changelog. Administrative stuff like config +# updates, ABI bumps, etc. Setting 'Ignore: yes' prevents +# 'debian/rules insertchanges' from inserting this commit meesage +# as a changelog entry. +# +# Please give a one-line description of the config change followed +# by a detailed explanation if necessary + +UBUNTU: [Config] XXXX + +# BugLink: http://bugs.launchpad.net/bugs/ +# Ignore: yes +# Other text below here. --- linux-2.6.37.orig/debian/commit-templates/external-driver +++ linux-2.6.37/debian/commit-templates/external-driver @@ -0,0 +1,20 @@ +# Ubuntu external driver commit. +# +# NOTE: This gets reformatted for README.Ubuntu-External-Drivers and +# debian/changelog. +# +# This is only needed when a driver is added, updated or removed. It is +# not needed when patches or fixes are applied to the driver. If the +# driver is being removed, add the line: +# +# Removing: yes +# +# to the commit, and you can remove all other tags (except UBUNTU:). +# +UBUNTU: + +ExternalDriver: +Description: +Url: +Mask: +Version: --- linux-2.6.37.orig/debian/commit-templates/missing-modules +++ linux-2.6.37/debian/commit-templates/missing-modules @@ -0,0 +1,3 @@ +UBUNTU: build/modules: Add modules that have intentionally gone missing + +Ignore: yes --- linux-2.6.37.orig/debian/commit-templates/newrelease +++ linux-2.6.37/debian/commit-templates/newrelease @@ -0,0 +1,3 @@ +UBUNTU: Start new release + +Ignore: yes --- linux-2.6.37.orig/debian/commit-templates/sauce-patch +++ linux-2.6.37/debian/commit-templates/sauce-patch @@ -0,0 +1,40 @@ +# Ubuntu commit template. +# +# NOTE: This gets reformatted for debian/changelog +# +# +# SAUCE refers to the fact that this patch might not go upstream, but we need to +# carry it to successive releases. In most cases you DONOT want to use this +# template. +# +# An example of a SAUCE patch is the ACPI DSDT-in-initramfs patch which has been +# refused upstream, but still provides useful functionality to users with broken +# BIOSes. +# +#------------------------------------------------------------------------- +# +# The initial UBUNTU is a flag that this is an Ubuntu commit. It will be +# referenced to the Author in the debian/changelog entry. +# +# The text following is the short message that will be placed in the +# changelog. Extra text on the following lines will be ignored, but left +# in the git commit. Lines with # will be ignored in the commit. +# +# OriginalAuthor allows for alternate attribution. +# +# OriginalLocation allows for a URL or description of where the patch came +# from. +# +# BugLink is a URL to a Malone bug. +# +# Ignore: yes will keep this commit from showing up in the changelog. +# +UBUNTU: SAUCE: + + + +# OriginalAuthor: +# OriginalLocation: +# BugLink: http://bugs.launchpad.net/bugs/ +# Ignore: yes +# Other text below here. --- linux-2.6.37.orig/debian/commit-templates/upstream-patch +++ linux-2.6.37/debian/commit-templates/upstream-patch @@ -0,0 +1,27 @@ +# Ubuntu commit template. +# +# NOTE: This gets reformatted for debian/changelog +# +# The initial UBUNTU is a flag that this is an Ubuntu commit. It will be +# referenced to the Author in the debian/changelog entry. +# +# The text following is the short message that will be placed in the +# changelog. Extra text on the following lines will be ignored, but left +# in the git commit. Lines with # will be ignored in the commit. +# +# OriginalAuthor allows for alternate attribution. +# +# OriginalLocation allows for a URL or description of where the patch came +# from. +# +# BugLink is a URL to a Malone bug. +# +# Ignore: yes will keep this commit from showing up in the changelog. +# +UBUNTU: [Upstream] + +# OriginalAuthor: +# OriginalLocation: +# BugLink: http://bugs.launchpad.net/bugs/ +# Ignore: yes +# Other text below here. --- linux-2.6.37.orig/debian/control-scripts/headers-postinst +++ linux-2.6.37/debian/control-scripts/headers-postinst @@ -0,0 +1,126 @@ +#!/usr/bin/perl +# -*- Mode: Cperl -*- +# debian.postinst --- +# Author : Manoj Srivastava ( srivasta@pilgrim.umass.edu ) +# Created On : Sat Apr 27 05:42:43 1996 +# Created On Node : melkor.pilgrim.umass.edu +# Last Modified By : Manoj Srivastava +# Last Modified On : Sat Aug 5 13:20:22 2006 +# Last Machine Used: glaurung.internal.golden-gryphon.com +# Update Count : 45 +# Status : Unknown, Use with caution! +# HISTORY : +# Description : +# +# +# +# arch-tag: 1c716174-2f0a-476d-a626-a1322e62503a +# + + +$|=1; + +# Predefined values: +my $version = "=V"; +my $kimage = "=K"; +my $package_name = "linux-image-$version"; + + +# Ignore all invocations uxcept when called on to configure. +exit 0 unless ($ARGV[0] && $ARGV[0] =~ /configure/); + +#known variables +my $image_dest = "/"; +my $realimageloc = "/boot/"; +my $silent_modules = ''; +my $modules_base = '/lib/modules'; +my $CONF_LOC = '/etc/kernel-img.conf'; +# remove multiple leading slashes; make sure there is at least one. +$realimageloc =~ s|^/*|/|o; +$realimageloc =~ s|/+|/|o; + +chdir '/usr/src' or die "Could not chdir to /usr/src:$!"; + +if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { + if (open(CONF, "$CONF_LOC")) { + while () { + chomp; + s/\#.*$//g; + next if /^\s*$/; + + $header_postinst_hook = "$1" if /^\s*header_postinst_hook\s*=\s*(\S+)/ig; + } + close CONF; + } +} + +sub exec_script { + my $type = shift; + my $script = shift; + print STDERR "Running $type hook script $script.\n"; + system ("$script $version $realimageloc$kimage-$version") && + print STDERR "User $type hook script [$script] "; + if ($?) { + if ($? == -1) { + print STDERR "failed to execute: $!\n"; + } + elsif ($? & 127) { + printf STDERR "died with signal %d, %s coredump\n", + ($? & 127), ($? & 128) ? 'with' : 'without'; + } + else { + printf STDERR "exited with value %d\n", $? >> 8; + } + exit $? >> 8; + } +} +sub run_hook { + my $type = shift; + my $script = shift; + if ($script =~ m,^/,) { + # Full path provided for the hook script + if (-x "$script") { + &exec_script($type,$script); + } + else { + die "The provided $type hook script [$script] could not be run.\n"; + } + } + else { + # Look for it in a safe path + for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { + if (-x "$path/$script") { + &exec_script($type, "$path/$script"); + return 0; + } + } + # No luck + print STDERR "Could not find $type hook script [$script].\n"; + die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; + } +} + +## Run user hook script here, if any +if (-x "$header_postinst_hook") { + &run_hook("postinst", $header_postinst_hook); +} + +if (-d "/etc/kernel/header_postinst.d") { + print STDERR "Examining /etc/kernel/header_postinst.d.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/header_postinst.d") && + die "Failed to process /etc/kernel/header_postinst.d"; +} + +if (-d "/etc/kernel/header_postinst.d/$version") { + print STDERR "Examining /etc/kernel/header_postinst.d/$version.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/header_postinst.d/$version") && + die "Failed to process /etc/kernel/header_postinst.d/$version"; +} + +exit 0; + +__END__ --- linux-2.6.37.orig/debian/control-scripts/postinst +++ linux-2.6.37/debian/control-scripts/postinst @@ -0,0 +1,1095 @@ +#! /usr/bin/perl +# OriginalAuthor : Manoj Srivastava ( srivasta@pilgrim.umass.edu ) +# +# Customized for Ubuntu by: Ben Collins + +#use strict; #for debugging +use Cwd 'abs_path'; + +$|=1; + +# Predefined values: +my $version = "=V"; +my $link_in_boot = ""; # Should be empty, mostly +my $no_symlink = ""; # Should be empty, mostly +my $reverse_symlink = ""; # Should be empty, mostly +my $do_symlink = "Yes"; # target machine defined +my $do_boot_enable = "Yes"; # target machine defined +my $do_bootfloppy = "Yes"; # target machine defined +my $do_bootloader = "Yes"; # target machine defined +my $move_image = ''; # target machine defined +my $kimage = "=K"; # Should be empty, mostly +my $loader = "=L"; # lilo, silo, quik, palo, vmelilo, nettrom, arcboot or delo +my $image_dir = "/boot"; # where the image is located +my $clobber_modules = ''; # target machine defined +my $relative_links = ""; # target machine defined +my $initrd = "YES"; # initrd kernel +my $do_initrd = ''; # Normally we do not +my $use_hard_links = ''; # hardlinks do not work across fs boundaries +my $postinst_hook = ''; #Normally we do not +my $postrm_hook = ''; #Normally we do not +my $preinst_hook = ''; #Normally we do not +my $prerm_hook = ''; #Normally we do not +my $minimal_swap = ''; # Do not swap symlinks +my $ignore_depmod_err = ''; # normally we do not +my $kernel_arch = "=B"; +my $ramdisk = "/usr/sbin/update-initramfs"; # List of tools to create initial ram fs. +my $notifier = "/usr/share/update-notifier/notify-reboot-required"; +my $package_name = "linux-image-$version"; +my $explicit_do_loader = 'Yes'; + +my $Loader = "NoLOADER"; # +$Loader = "LILO" if $loader =~ /^lilo/io; +$Loader = "SILO" if $loader =~ /^silo/io; +$Loader = "QUIK" if $loader =~ /^quik/io; +$Loader = "yaboot" if $loader =~ /^yaboot/io; +$Loader = "PALO" if $loader =~ /^palo/io; +$Loader = "NETTROM" if $loader =~ /^nettrom/io; +$Loader = "VMELILO" if $loader =~ /^vmelilo/io; +$Loader = "ZIPL" if $loader =~ /^zipl/io; +$Loader = "ELILO" if $loader =~ /^elilo/io; +$Loader = "ARCBOOT" if $loader =~ /^arcboot/io; +$Loader = "DELO" if $loader =~ /^delo/io; + +# This should not point to /tmp, because of security risks. +my $temp_file_name = "/var/log/$loader" . "_log.$$"; + +#known variables +my $image_dest = "/"; +my $realimageloc = "/$image_dir/"; +my $have_conffile = ""; +my $silent_modules = ''; +my $silent_loader = ''; +my $warn_reboot = 'Yes'; # Warn that we are installing a version of + # the kernel we are running + +my $modules_base = '/lib/modules'; +my $CONF_LOC = '/etc/kernel-img.conf'; + +# Ignore all invocations except when called on to configure. +exit 0 unless $ARGV[0] =~ /configure/; + +my $DEBUG = 0; + +# Do some preliminary sanity checks here to ensure we actually have an +# valid image dir +chdir('/') or die "could not chdir to /:$!\n"; +die "Internal Error: ($image_dir) is not a directory!\n" + unless -d $image_dir; + +# remove multiple leading slashes; make sure there is at least one. +$realimageloc =~ s|^/*|/|o; +$realimageloc =~ s|/+|/|o; +die "Internal Error: ($realimageloc) is not a directory!\n" + unless -d $realimageloc; + +if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { + if (open(CONF, "$CONF_LOC")) { + while () { + chomp; + s/\#.*$//g; + next if /^\s*$/; + + $do_symlink = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig; + $no_symlink = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig; + $reverse_symlink = "" if /^\s*reverse_symlink\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig; + $move_image = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig; + $clobber_modules = '' if /^\s*clobber_modules\s*=\s*(no|false|0)\s*$/ig; + $do_boot_enable = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig; + $do_bootfloppy = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig; + $relative_links = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig; + $do_bootloader = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig; + $explicit_do_loader = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig; + $do_initrd = '' if /^\s*do_initrd\s*=\s*(no|false|0)\s*$/ig; + $use_hard_links = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig; + $silent_modules = '' if /^\s*silent_modules\s*=\s*(no|false|0)\s*$/ig; + $silent_loader = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig; + $warn_reboot = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig; + $minimal_swap = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig; + $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig; + + $do_symlink = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $no_symlink = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $move_image = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig; + $clobber_modules = "Yes" if /^\s*clobber_modules\s*=\s*(yes|true|1)\s*$/ig; + $do_boot_enable = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig; + $do_bootfloppy = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig; + $do_bootloader = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig; + $explicit_do_loader = "YES" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig; + $relative_links = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig; + $do_initrd = "Yes" if /^\s*do_initrd\s*=\s*(yes|true|1)\s*$/ig; + $use_hard_links = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig; + $silent_modules = 'Yes' if /^\s*silent_modules\s*=\s*(yes|true|1)\s*$/ig; + $silent_loader = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig; + $warn_reboot = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig; + $minimal_swap = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig; + $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig; + + $image_dest = "$1" if /^\s*image_dest\s*=\s*(\S+)/ig; + $postinst_hook = "$1" if /^\s*postinst_hook\s*=\s*(\S+)/ig; + $postrm_hook = "$1" if /^\s*postrm_hook\s*=\s*(\S+)/ig; + $preinst_hook = "$1" if /^\s*preinst_hook\s*=\s*(\S+)/ig; + $prerm_hook = "$1" if /^\s*prerm_hook\s*=\s*(\S+)/ig; + $ramdisk = "$1" if /^\s*ramdisk\s*=\s*(.+)$/ig; + } + close CONF; + $have_conffile = "Yes"; + } +} + + + +# For some versions of kernel-package, we had this warning in the +# postinst, but the rules did not really interpolate the value in. +# Here is a sanity check. +my $pattern = "=" . "I"; +$initrd=~ s/^$pattern$//; + +if ($link_in_boot) { + $image_dest = "/$image_dir/"; # same as realimageloc +} + +# Tack on at least one trainling / +$image_dest = "$image_dest/"; +$image_dest =~ s|^/*|/|o; +$image_dest =~ s|/+$|/|o; + +if (! -d "$image_dest") { + die "Expected Image Destination dir ($image_dest) to be a valid directory!\n"; +} + +# sanity +if (!($do_bootfloppy || $do_bootloader)) { + $do_boot_enable = ''; +} +if ($do_symlink && $no_symlink) { + warn "Both do_symlinks and no_symlinks options enabled; disabling no_symlinks\n"; + $no_symlink = 0; +} + +# most of our work is done in $image_dest (nominally /) +chdir("$image_dest") or die "could not chdir to $image_dest:$!\n"; + +# Paranoid check to make sure that the correct value is put in there +if (! $kimage) { $kimage = "vmlinuz"; } # Hmm. empty +elsif ($kimage =~ m/^b?uImage$/o) { $kimage = "vmlinuz"; } # these produce vmlinuz +elsif ($kimage =~ m/^b?zImage$/o) { $kimage = "vmlinuz"; } # these produce vmlinuz +elsif ($kimage =~ m/^[iI]mage$/o) { my $nop = $kimage; } +elsif ($kimage =~ m/^vmlinux$/o) { my $nop = $kimage; } +else { $kimage = "vmlinuz"; } # Default + +$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; + + +die "Internal Error: Could not find image (" . $realimageloc + . "$kimage-$version)\n" unless -e $realimageloc + . "$kimage-$version"; + +# search for the boot loader in the path +my $loader_exec; +($loader_exec = $loader) =~ s|.*/||; +my ($loaderloc) = grep -x, map "$_/$loader_exec", + map { length($_) ? $_ : "." } split /:/, $ENV{PATH}; + + +###################################################################### +###################################################################### +########### Test whether a relative symlinkwould be OK ####### +###################################################################### +###################################################################### +sub test_relative { + my %params = @_; + my $cwd; + + die "Internal Error: Missing Required paramater 'Old Dir' " + unless $params{'Old Dir'}; + die "Internal Error: Missing Required paramater New Dir' " + unless $params{'New Dir'}; + + + die "Internal Error: No such dir $params{'Old Dir'} " + unless -d $params{'Old Dir'}; + die "Internal Error: No such dir $params{'New Dir'} " + unless -d $params{'New Dir'}; + + warn "Test relative: testing $params{'Old Dir'} -> $params{'New Dir'}" + if $DEBUG; + chomp($cwd = `pwd`); + chdir ($params{'New Dir'}) or die "Could not chdir to $params{'New Dir'}:$!"; + my $ok = 0; + $params{'Old Dir'} =~ s|^/*||o; + if (-d $params{'Old Dir'} ) { + if (defined $params{'Test File'}) { + if (-e $params{'Old Dir'} . $params{'Test File'}) { + $ok = 1; + } + } else { + $ok = 1; # well, backward compatibility + } + } + chdir ($cwd) or die "Could not chdir to $params{'New Dir'}:$!"; + return $ok; +} + +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### +# sub CanonicalizePath { +# my $path = join '/', @_; +# my @work = split '/', $path; +# my @out; +# my $is_absolute; + +# if (@work && $work[0] eq "") { +# $is_absolute = 1; shift @work; +# } + +# while (@work) { +# my $seg = shift @work; +# if ($seg eq "." || $seg eq "") { +# } +# elsif ($seg eq "..") { +# if (@out && $out[-1] ne "..") { +# pop @out; +# } +# else { +# # Leading "..", or "../..", etc. +# push @out, $seg; +# } +# } +# else { +# push @out, $seg; +# } +# } + +# unshift @out, "" if $is_absolute; +# return join('/', @out); +# } +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### + +sub spath { + my %params = @_; + + die "Missing Required paramater 'Old'" unless $params{'Old'}; + die "Missing Required paramater 'New'" unless $params{'New'}; + + my @olddir = split '/', `readlink -q -m $params{'Old'}`; + my @newdir = split '/', `readlink -q -m $params{'New'}`; + my @outdir = @olddir; + + my $out = ''; + my $i; + for ($i = 0; $i <= $#olddir && $i <= $#newdir; $i++) { + $out++ if ($olddir[$i] ne $newdir[$i]); + shift @outdir unless $out; + unshift @outdir, ".." if $out; + } + if ($#newdir > $#olddir) { + for ($i=0; $i < $#newdir; $i++) { + unshift @outdir, ".."; + } + } + return join ('/', @outdir); +} +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### + + +# This routine actually moves the kernel image +# From: $realimageloc/$kimage-$version (/boot/vmlinuz-2.6.12) +# To: $image_dest/$kimage-$version (/vmlinuz-2.6.12) +# Note that the image is moved to a versioned destination, but ordinary +# symlinks we create otherwise are not normally versioned +sub really_move_image { + my $src_dir = $_[0]; + my $target = $_[1]; + my $dest_dir = $_[2]; + + warn "Really move image: src_dir=$src_dir, target=$target,\n destdir=$dest_dir" + if $DEBUG; + if (-e "$target") { + # we should be in dir $dest_dir == $image_dest /, normally + rename("$target", "$target.$$") || + die "failed to move " . $dest_dir . "$target:$!"; + warn "mv $target $target.$$" if $DEBUG; + } + warn "mv -f $src_dir$target $target" if $DEBUG; + my $ret = system("mv -f " . $src_dir . "$target " . + " $target"); + if ($ret) { + die("Failed to move " . $src_dir . "$target to " + . $dest_dir . "$target.\n"); + } + # Ok, now we may clobber the previous .old files + if (-e "$target.$$") { + rename("$target.$$", "$target.old") || + die "failed to move " . $dest_dir . "$target:$!"; + warn "mv $target.$$ $target " if $DEBUG; + } +} + +# Normally called after really_move_image; and only called if we asked for +# reversed link this routine reverses the symbolic link that is notmally +# created. Since the real kernel image has been moved over to +# $image_dest/$kimage-$version. So, this routine links +# From: $image_dest/$kimage-$version (/vmlinuz-2.6.12) +# To: $realimageloc/$kimage-$version (/boot/vmlinuz-2.6.12) +sub really_reverse_link { + my $src_dir = $_[0]; + my $link_name = $_[1]; + my $dest_dir = $_[2]; + warn "Really reverse link: src_dir=$src_dir, link name=$link_name\n" . + "\tdestdir=$dest_dir" if $DEBUG; + + my $Old = $dest_dir; + if (test_relative ('Old Dir' => $Old, 'New Dir' => $src_dir, + 'Test File' => "$link_name")) { + $Old =~ s|^/*||o; + } + # Special case is they are in the same dir + my $rel_path = spath('Old' => "$Old", 'New' => "$src_dir" ); + $Old ="" if $rel_path =~ m/^\s*$/o; + + if ($use_hard_links =~ m/YES/i) { + link($Old . "$link_name", $src_dir . "$link_name") || + die("Failed to link " . $dest_dir . "$link_name to " . $src_dir . + "$link_name .\n"); + warn "ln " . $Old . "$link_name " . $src_dir . "$link_name" if $DEBUG; + } + else { + symlink($Old . "$link_name", $src_dir . "$link_name") || + die("Failed to symbolic-link " . $dest_dir . "$link_name to " . $src_dir + . "$link_name : $!\n"); + warn "ln -s " . $Old . "$link_name " . $src_dir . "$link_name" if $DEBUG; + } +} + +# This routine is invoked if there is a symbolic link in place +# in $image_dest/$kimage -- so a symlink exists in the destination. +# What we are trying to determine is if we need to move the symbolic link over +# to the the .old location +sub move_p { + my $kimage = $_[0]; # Name of the symbolic link + my $image_dest = $_[1]; # The directory the links goes into + my $image_name = $_[2]; + my $src_dir = $_[3]; + my $force_move = 0; + warn "Move?: kimage=$kimage, image_dest=$image_dest, \n" . + "\timage_name=$image_name, src_dir=$src_dir" if $DEBUG; + + if ($no_symlink || $reverse_symlink) { + # we do not want links, yet we have a symbolic link here! + warn "found a symbolic link in " . $image_dest . "$kimage \n" . + "even though no_symlink is defined\n" if $no_symlink; + warn "found a symbolic link in " . $image_dest . "$kimage \n" . + "even though reverse_symlink is defined\n" if $reverse_symlink; + # make sure we change this state of affairs + $force_move = 1; + return $force_move; + } + + warn "DEBUG: OK. We found symlink, and we should have a symlink here.\n" + if $DEBUG; + my $vmlinuz_target = readlink "$kimage"; + my $real_target = ''; + my $target = `readlink -q -m "${realimageloc}${kimage-$version}"`; + $real_target = abs_path($vmlinuz_target) if defined($vmlinuz_target); + + if (!defined($vmlinuz_target) || ! -f "$real_target") { + # what, a dangling symlink? + warn "The link " . $image_dest . "$kimage is a dangling link" . + "to $real_target\n"; + $force_move = 1; + return $force_move; + } + + + warn "DEBUG: The link $kimage points to ($vmlinuz_target)\n" if $DEBUG; + warn "DEBUG: ($vmlinuz_target) is really ($real_target)\n" if $DEBUG; + my $cwd; + chomp ($cwd=`pwd`); + if ($vmlinuz_target !~ m|^/|o) { + $vmlinuz_target = $cwd . "/" . $vmlinuz_target; + $vmlinuz_target =~ s|/+|/|o; + } + $vmlinuz_target = `readlink -q -m $vmlinuz_target`; + + if ("$vmlinuz_target" ne "$target") { + warn "DEBUG: We need to handle this.\n" if $DEBUG; + if ($minimal_swap) { + warn "DEBUG: Minimal swap.\n" if $DEBUG; + if (-l "$kimage.old") { + warn "DEBUG: There is an old link at $kimage.old\n" if $DEBUG; + my $old_target = readlink "$kimage.old"; + my $real_old_target = ''; + $real_old_target=abs_path($old_target) if defined ($old_target); + + if ($real_old_target && -f "$real_old_target") { + if ($old_target !~ m|^/|o) { + $old_target = $cwd . "/" . $old_target; + $old_target =~ s|/+|/|o; + } + $old_target = `readlink -q -m $old_target`; + if ("$old_target" ne "$target") { + $force_move = 1; + warn "DEBUG: Old link ($old_target) does not point to us ($target)\n" + if $DEBUG; + } + else { # The .old points to the current + warn "$kimage.old --> $target -- doing nothing"; + $force_move = 0; + } + } + else { + warn "DEBUG: Well, the old link does not exist -- so we move\n" + if $DEBUG; + $force_move = 1; + } + } + else { + warn "DEBUG: No .old link -- OK to move\n" + if $DEBUG; + $force_move = 1; + } + } + else { + warn "DEBUG: ok, minimal swap is no-- so we move.\n" + if $DEBUG; + $force_move = 1; + } + } + else { # already have proper link + warn "$kimage($vmlinuz_target) points to $target ($real_target) -- doing nothing"; + $force_move = 0; + } + return $force_move; +} + + +# This routine moves the symbolic link around (/vmlinuz -> /vmlinuz.old) +# It pays attention to whether we should the fact whether we should be using +# hard links or not. +sub really_move_link { + my $kimage = $_[0]; # Name of the symbolic link + my $image_dest = $_[1]; # The directory the links goes into + my $image_name = $_[2]; + my $src_dir = $_[3]; + warn "really_move_link: kimage=$kimage, image_dest=$image_dest\n" . + "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; + + # don't clobber $kimage.old quite yet + rename("$kimage", "$kimage.$$") || + die "failed to move " . $image_dest . "$kimage:$!"; + warn "mv $kimage $kimage.$$" if $DEBUG; + my $Old = $src_dir; + my $cwd; + + chomp($cwd=`pwd`); + if (test_relative ('Old Dir' => $Old, 'New Dir' => $cwd, + 'Test File' => "$image_name")) { + $Old =~ s|^/*||o; + } + # Special case is they are in the same dir + my $rel_path = spath('Old' => "$Old", 'New' => "$cwd" ); + $Old ="" if $rel_path =~ m/^\s*$/o; + + if ($use_hard_links =~ m/YES/i) { + warn "ln ${Old}${image_name} $kimage" if $DEBUG; + if (! link("${Old}${image_name}", "$kimage")) { + rename("$kimage.$$", "$kimage"); + die("Failed to link ${Old}${image_name} to " . + "${image_dest}${kimage}.\n"); + } + } + else { + warn "ln -s ${Old}${image_name} $kimage" if $DEBUG; + if (! symlink("${Old}${image_name}", "$kimage")) { + rename("$kimage.$$", "$kimage"); + die("Failed to symbolic-link ${Old}${image_name} to " . + "${image_dest}${kimage}: $!\n"); + } + } + + # Ok, now we may clobber the previous .old file + if (-l "$kimage.old" || ! -e "$kimage.old" ) { + rename("$kimage.$$", "$kimage.old"); + warn "mv $kimage.$$ $kimage.old" if $DEBUG; + } + else { + warn "$kimage.old is not a symlink, not clobbering\n"; + warn "rm $kimage.$$"; + unlink "$kimage.$$" if $DEBUG; + } +} + +# This routine handles a request to do symlinks, but there is no +# symlink file already there. Either we are supposed to use copy, or we are +# installing on a pristine system, or the user does not want symbolic links at +# all. We use a configuration file to tell the last two cases apart, creating +# a config file if needed. +sub handle_missing_link { + my $kimage = $_[0]; # Name of the symbolic link + my $image_dest = $_[1]; # The directory the links goes into + my $image_name = $_[2]; + my $src_dir = $_[3]; + warn "handle_missing_link: kimage=$kimage, image_dest=$image_dest\n" . + "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; + + if ($no_symlink) { + warn "cp -a --backup=t $realimageloc$image_name $kimage" if $DEBUG; + my $ret = system("cp -a --backup=t " . $realimageloc . + "$image_name " . " $kimage"); + if ($ret) { + die("Failed to copy " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + } + elsif ($reverse_symlink) { + warn "mv -f $realimageloc$image_name $kimage" if $DEBUG; + my $ret = system("mv -f " . $realimageloc . "$image_name " + . "$kimage"); + if ($ret) { + die("Failed to move " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + } + else { + if (! $have_conffile) { + my $ret; + my $answer=''; + $do_symlink = "Yes"; + + if (open(CONF, ">$CONF_LOC")) { + print CONF "# Kernel Image management overrides\n"; + print CONF "# See kernel-img.conf(5) for details\n"; + if ($loader =~ /palo/i) { + print CONF "link_in_boot = Yes\n"; + print CONF "do_symlinks = Yes\n"; + print CONF "relative_links = Yes\n"; + print CONF "do_bootloader = No\n"; + } else { + print CONF "do_symlinks = $do_symlink\n"; + } + close CONF; + } + $have_conffile = "Yes"; + } + } + + if (! $no_symlink && $do_symlink =~ /Yes/i) { + my $Old = $realimageloc; + my $New = $image_dest; + my $Name = "$image_name"; + my $Link_Dest = "$kimage"; + + if ($reverse_symlink) { + $Old = $image_dest; + $New = $realimageloc; + $Name = "$kimage"; + $Link_Dest = $realimageloc . "$image_name"; + } + if (test_relative ('Old Dir' => $Old, + 'New Dir' => $New, + 'Test File' => $Name)) { + $Old =~ s|^/*||o; + } + # Special case is they are in the same dir + my $rel_path = spath('Old' => "$Old", 'New' => "$New" ); + $Old ="" if $rel_path =~ m/^\s*$/o; + + symlink($Old . "$Name", "$Link_Dest") || + die("Failed to symbolic-link ${Old}$Name to $Link_Dest: $!\n"); + warn "ln -s ${Old}$Name $Link_Dest" if $DEBUG; + + } +} + +# This routine handles the rest of the cases, where the user has requested +# non-traditional handling, like using cp, or reverse symlinks, or hard links. +sub handle_non_symlinks { + my $kimage = $_[0]; # Name of the symbolic link + my $image_dest = $_[1]; # The directory the links goes into + my $image_name = $_[2]; + my $src_dir = $_[3]; + warn "handle_non_link: kimage=$kimage, image_dest=$image_dest\n" . + "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; + + # Save the current image. We do this in all four cases + rename("$kimage", "$kimage.$$") || + die "failed to move " . $image_dest . "$kimage:$!"; + warn "mv $kimage $kimage.$$" if $DEBUG; + + ##,#### + # case One + #`#### + if ($no_symlink) { + # Maybe /$image_dest is on a dos system? + warn "cp -a --backup=t $realimageloc$image_name $kimage" if $DEBUG; + my $ret = system("cp -a --backup=t " . $realimageloc + . "$image_name " . "$kimage"); + if ($ret) { + if (-e "$kimage.$$") { + rename("$kimage.$$", "$kimage"); + warn "mv $kimage.$$ $kimage" if $DEBUG; + } + die("Failed to copy " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + } + ##,#### + # case Two + #`#### + elsif ($reverse_symlink) { # Maybe /$image_dest is on a dos system? + warn "mv -f $realimageloc$image_name $kimage" if $DEBUG; + my $ret = system("mv -f " . $realimageloc . "$image_name " + . $image_dest . "$kimage"); + if ($ret) { + if (-e "$kimage.$$") { + rename("$kimage.$$", "$kimage"); + warn "mv $kimage.$$ $kimage" if $DEBUG; + } + die("Failed to move " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + my $Old = $image_dest; + if (test_relative ('Old Dir' => $Old, 'New Dir' => $realimageloc, + 'Test File' => "$kimage")) { + $Old =~ s|^/*||o; + } + # Special case is they are in the same dir + my $rel_path = spath('Old' => "$Old", 'New' => "$realimageloc" ); + $Old ="" if $rel_path =~ m/^\s*$/o; + + if ($use_hard_links =~ m/YES/i) { + warn "ln " . $Old . "$kimage " . $realimageloc . "$image_name" if $DEBUG; + if (! link($Old . "$kimage", $realimageloc . "$image_name")) { + warn "Could not link " . $image_dest . + "$kimage to $image_name :$!"; + } + } + else { + warn "ln -s " . $Old . "$kimage " . $realimageloc . "$image_name" if $DEBUG; + if (! symlink($Old . "$kimage", $realimageloc . "$image_name")) { + warn "Could not symlink " . $image_dest . + "$kimage to $image_name :$!"; + } + } + } + ##,#### + # case Three + #`#### + elsif ($use_hard_links =~ m/YES/i ) { + # Ok then. this ought to be a hard link, and hence fair game + # don't clobber $kimage.old quite yet + my $Old = $realimageloc; + my $cwd; + chomp($cwd=`pwd`); + if (test_relative ('Old Dir' => $Old, 'New Dir' => $cwd, + 'Test File' => "$image_name")) { + $Old =~ s|^/*||o; + } + # Special case is they are in the same dir + my $rel_path = spath('Old' => "$Old", 'New' => "$cwd" ); + $Old ="" if $rel_path =~ m/^\s*$/o; + + warn "ln " . $Old . "$image_name " . "$kimage" if $DEBUG; + if (! link($Old . "$image_name", "$kimage")) { + warn "mv $kimage.$$ $kimage" if $DEBUG; + rename("$kimage.$$", "$kimage"); + die("Failed to link " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + } + ##,#### + # case Four + #`#### + else { + # We just use cp + warn "cp -a --backup=t $realimageloc$image_name $kimage" if $DEBUG; + my $ret = system("cp -a --backup=t " . $realimageloc + . "$image_name " . "$kimage"); + if ($ret) { + if (-e "$kimage.$$") { + warn "mv $kimage.$$ $kimage" if $DEBUG; + rename("$kimage.$$", "$kimage"); + } + die("Failed to copy " . $realimageloc . "$image_name to " + . $image_dest . "$kimage .\n"); + } + } + # Ok, now we may clobber the previous .old file + warn "mv $kimage.$$ $kimage.old if -e $kimage.$$" if $DEBUG; + rename("$kimage.$$", "$kimage.old") if -e "$kimage.$$"; +} + +# This routine is responsible for setting up the symbolic links +# So, the actual kernel image lives in +# $realimageloc/$image_name (/boot/vmlinuz-2.6.12). +# This routine creates symbolic links in $image_dest/$kimage (/vmlinuz) +sub image_magic { + my $kimage = $_[0]; # Name of the symbolic link + my $image_dest = $_[1]; # The directory the links goes into + my $image_name = "$kimage-$version"; + my $src_dir = $realimageloc; + warn "image_magic: kimage=$kimage, image_dest=$image_dest\n" . + "\t image_name=$image_name, src_dir=$src_dir" if $DEBUG; + + # Well, in any case, if the destination (the symlink we are trying + # to create) is a directory, we should do nothing, except throw a + # diagnostic. + if (-d "$kimage" ) { + die ("Hmm. $kimage is a directory, which I did not expect. I am\n" . + "trying to create a symbolic link with that name linked to \n" . + "$image_dest . Since a directory exists here, my assumptions \n" . + "are way off, and I am aborting.\n" ); + exit (3); + } + + if ($move_image) { # Maybe $image_dest is in on dos, or something? + # source dir, link name, dest dir + really_move_image( $realimageloc, $image_name, $image_dest); + really_reverse_link($realimageloc, $image_name, $image_dest) + if $reverse_symlink; + return; + } + + if (-l "$kimage") { # There is a symbolic link + warn "DEBUG: There is a symlink for $kimage\n" if $DEBUG; + my $force_move = move_p($kimage, $image_dest, $image_name, $src_dir); + + if ($force_move) { + really_move_link($kimage, $image_dest, $image_name, $src_dir); + } + } + elsif (! -e "$kimage") { + # Hmm. Pristine system? How can that be? Installing from scratch? + # Or maybe the user does not want a symbolic link here. + # Possibly they do not want a link here. (we should be in / + # here[$image_dest, really] + handle_missing_link($kimage, $image_dest, $image_name, $src_dir); + } + elsif (-e "$kimage" ) { + # OK, $kimage exists -- but is not a link + handle_non_symlinks($kimage, $image_dest, $image_name, $src_dir); + } +} + +###################################################################### +###################################################################### +###################################################################### +###################################################################### + +# We may not have any modules installed +if ( -d "$modules_base/$version" ) { + print STDERR "Running depmod.\n"; + my $ret = system("depmod -a $version"); + if ($ret) { + print STDERR "Failed to run depmod\n"; + exit(1); + } +} + + + +sub find_initrd_tool { + my $hostversion = shift; + my $version = shift; + print STDERR "Finding valid ramdisk creators.\n"; + my @ramdisks = + grep { + my $args = + "$_ " . + "--supported-host-version=$hostversion " . + "--supported-target-version=$version " . + "1>/dev/null 2>&1" + ; + system($args) == 0; + } + split (/[:,\s]+/, $ramdisk); +} + +# The initrd symlink should probably be in the same dir that the +# symlinks are in +if ($initrd) { + my $success = 0; + + # Update-initramfs is called slightly different than mkinitrd and + # mkinitramfs. XXX It should really be made compatible with this stuff + # some how. + my $upgrading = 1; + if (! defined $ARGV[1] || ! $ARGV[1] || $ARGV[1] =~ m//og) { + $upgrading = 0; + } + my $ret = system("$ramdisk " . ($upgrading ? "-u" : "-c") . " -k " . $version . " >&2"); + $success = 1 unless $ret; + die "Failed to create initrd image.\n" unless $success; + if (! defined $ARGV[1] || ! $ARGV[1] || $ARGV[1] =~ m//og) { + image_magic("initrd.img", $image_dest); + } + else { + if (! -e "initrd.img") { + handle_missing_link("initrd.img", $image_dest, "initrd.img-$version", + $realimageloc); + } + else { + print STDERR + "Not updating initrd symbolic links since we are being updated/reinstalled \n"; + print STDERR + "($ARGV[1] was configured last, according to dpkg)\n"; + } + } + + if ($initrd && -l "initrd" ) { + unlink "initrd"; + } + + if ($initrd && -l "$image_dir/initrd" && ! $link_in_boot) { + unlink "$image_dir/initrd"; + } +} +else { # Not making an initrd emage + if (-l "initrd.img") { + # Ooh, last image was an initrd image? in any case, we should move it. + my $target = readlink "initrd.img"; + my $real_target = ''; + $real_target = abs_path($target) if defined ($target); + + if (!defined($target) || ! -f "$real_target") { + # Eh. dangling link. can safely be removed. + unlink("initrd.img"); + } else { + if (-l "initrd.img.old" || ! -e "initrd.img.old" ) { + rename("initrd.img", "initrd.img.old"); + } else { + warn "initrd.img.old is not a symlink, not clobbering\n"; + unlink("initrd.img"); + } + } + } +} + +# Warn of a reboot +if (-x $notifier) { + system($notifier); +} + +# Let programs know not to hibernate if the kernel that would be used for +# resume-from-hibernate is likely to differ from the currently running kernel. +system("mountpoint -q /var/run"); +if ($? eq 0) { + system("touch /var/run/do-not-hibernate"); +} + +# Only change the symlinks if we are not being upgraded +if (! defined $ARGV[1] || ! $ARGV[1] || $ARGV[1] =~ m//og) { + image_magic($kimage, $image_dest); +} +else { + if (! -e "$kimage") { + handle_missing_link($kimage, $image_dest, "$kimage-$version", + $realimageloc); + } + else { + print STDERR + "Not updating image symbolic links since we are being updated/reinstalled \n"; + print STDERR + "($ARGV[1] was configured last, according to dpkg)\n"; + } +} + +# We used to have System.* files in / +if (-e "/System.map" || -e "/System.old") { + unlink '/System.map' if -e '/System.map'; + unlink '/System.old' if -e '/System.old'; +} + +# creating some info about kernel and initrd +if ($DEBUG) { + my $ksize=sprintf("%.0f",(stat($realimageloc . + "$kimage-$version"))[7]/1024)."kB"; + my $initrdsize=''; + if ($initrd) { + $initrdsize=sprintf("%.0f",(stat($realimageloc . + "initrd.img-$version"))[7]/1024)."kB"; + } + + print STDERR <<"EOMSG"; +A new kernel image has been installed at $realimageloc$kimage-$version + (Size: $ksize) + +Symbolic links, unless otherwise specified, can be found in $image_dest + +EOMSG + ; + + if ($initrd) { + print STDERR <<"EOMSGA"; + + Initial rootdisk image: ${realimageloc}initrd.img-$version (Size: $initrdsize) +EOMSGA + ; + } +} + +# set the env var stem +$ENV{'STEM'} = "linux"; +sub exec_script { + my $type = shift; + my $script = shift; + print STDERR "Running $type hook script $script.\n"; + system ("$script $version $realimageloc$kimage-$version") && + print STDERR "User $type hook script [$script] "; + if ($?) { + if ($? == -1) { + print STDERR "failed to execute: $!\n"; + } + elsif ($? & 127) { + printf STDERR "died with signal %d, %s coredump\n", + ($? & 127), ($? & 128) ? 'with' : 'without'; + } + else { + printf STDERR "exited with value %d\n", $? >> 8; + } + exit $? >> 8; + } +} +sub run_hook { + my $type = shift; + my $script = shift; + if ($script =~ m,^/,) { + # Full path provided for the hook script + if (-x "$script") { + &exec_script($type,$script); + } + else { + die "The provided $type hook script [$script] could not be run.\n"; + } + } + else { + # Look for it in a safe path + for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { + if (-x "$path/$script") { + &exec_script($type, "$path/$script"); + return 0; + } + } + # No luck + print STDERR "Could not find $type hook script [$script].\n"; + die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; + } +} + +my $options; +for (@ARGV) { + s,','\\'',g; + $options .= " '$_'"; +} +$ENV{'DEB_MAINT_PARAMS'}="$options"; + +## Run user hook script here, if any +if ($postinst_hook) { + &run_hook("postinst", $postinst_hook); +} + +if (-d "/etc/kernel/postinst.d") { + print STDERR "Examining /etc/kernel/postinst.d.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/postinst.d") && + die "Failed to process /etc/kernel/postinst.d"; +} + +if (-d "/etc/kernel/postinst.d/$version") { + print STDERR "Examining /etc/kernel/postinst.d/$version.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/postinst.d/$version") && + die "Failed to process /etc/kernel/postinst.d/$version"; +} + +LOADER: { + last unless $do_boot_enable; # Exit if explicitly asked to + + last if $loader =~ /silo/i; # SILO does not have to be executed. + last if $loader =~ /yaboot/i; # yaboot does not have to be executed. + last if $loader =~ /milo/i; # MILO does not have to be executed. + last if $loader =~ /nettrom/i; # NETTROM does not have to be executed. + last if $loader =~ /arcboot/i; # ARCBOOT does not have to be executed. + last if $loader =~ /delo/i; # DELO does not have to be executed. + last if $loader =~ /quik/i; # maintainer asked quik invocation to be ignored + + last unless $loaderloc; + last unless -x $loaderloc; + last unless $do_bootloader; + + if (-T "/etc/$loader.conf") { + # Trust and use the existing lilo.conf. + print STDERR "You already have a $Loader configuration in /etc/$loader.conf\n"; + my $ret = &run_lilo(); + exit $ret if $ret; + } +} + + +sub run_lilo (){ + my $ret; + # Try and figure out if the user really wants lilo to be run -- + # since the default is to run the boot laoder, which is ! grub -- but + # the user may be using grub now, and not changed the default. + + # So, if the user has explicitly asked for the loader to be run, or + # if there is no postinst hook, or if there is no grub installed -- + # we are OK. Or else, we ask. + if ($explicit_do_loader || (! ($postinst_hook && -x '/usr/sbin/grub'))) { + print STDERR "Running boot loader as requested\n"; + } else { + print STDERR "Ok, not running $loader\n"; + } + if ($loader =~ /^lilo/io or $loader =~ /vmelilo/io) { + print STDERR "Testing $loader.conf ... \n"; + unlink $temp_file_name; # security + $ret = system("$loaderloc -t >$temp_file_name 2>&1"); + if ($ret) { + print STDERR "Boot loader test failed\n"; + return $ret; + } + unlink "$temp_file_name"; + print STDERR "Testing successful.\n"; + print STDERR "Installing the "; + print STDERR "partition " if $loader =~ /^lilo/io; + print STDERR "boot sector... \n"; + } + + print STDERR "Running $loaderloc ... \n"; + if ($loader =~ /^elilo/io) { + $ret = system("$loaderloc 2>&1 | tee $temp_file_name"); + } else { + $ret = system("$loaderloc >$temp_file_name 2>&1"); + } + if ($ret) { + print STDERR "Boot loader failed to run\n"; + return $ret; + } + unlink $temp_file_name; + print STDERR "Installation successful.\n"; + return 0; +} + +exit 0; + +__END__ + --- linux-2.6.37.orig/debian/control-scripts/postrm +++ linux-2.6.37/debian/control-scripts/postrm @@ -0,0 +1,361 @@ +#! /usr/bin/perl +# -*- Mode: Cperl -*- +# image.postrm --- +# Author : Manoj Srivastava ( srivasta@glaurung.green-gryphon.com ) +# Created On : Sat May 15 11:05:13 1999 +# Created On Node : glaurung.green-gryphon.com +# Last Modified By : Manoj Srivastava +# Last Modified On : Wed Sep 13 11:26:19 2006 +# Last Machine Used: glaurung.internal.golden-gryphon.com +# Update Count : 57 +# Status : Unknown, Use with caution! +# HISTORY : +# Description : +# +# $Id: image.postrm,v 1.31 2003/10/07 16:24:20 srivasta Exp $ +# + + +# +#use strict; #for debugging +use Cwd 'abs_path'; + +$|=1; + +# Predefined values: +my $version = "=V"; +my $link_in_boot = ""; # Should be empty, mostly +my $no_symlink = ""; # Should be empty, mostly +my $reverse_symlink = ""; # Should be empty, mostly +my $do_symlink = "Yes"; # target machine defined +my $do_boot_enable = "Yes"; # target machine defined +my $do_bootfloppy = "Yes"; # target machine defined +my $do_bootloader = "Yes"; # target machine defined +my $move_image = ''; # target machine defined +my $kimage = "=K"; # Should be empty, mostly +my $loader = "=L"; # lilo, silo, quik, palo, vmelilo, or nettrom +my $image_dir = "/boot"; # where the image is located +my $clobber_modules = ''; # target machine defined +my $initrd = "YES"; # initrd kernel +my $do_initrd = ''; # Normally, we don't +my $warn_initrd = 'YES'; # Normally we do +my $use_hard_links = ''; # hardlinks do not work across fs boundaries +my $postinst_hook = ''; #Normally we do not +my $postrm_hook = ''; #Normally we do not +my $preinst_hook = ''; #Normally we do not +my $prerm_hook = ''; #Normally we do not +my $minimal_swap = ''; # Do not swap symlinks +my $ignore_depmod_err = ''; # normally we do not +my $relink_build_link = 'YES'; # There is no harm in checking the link +my $force_build_link = ''; # we shall not create a dangling link +my $kernel_arch = "=B"; +my $ramdisk = "/usr/sbin/update-initramfs"; +my $package_name = "linux-image-$version"; + +my $Loader = "NoLOADER"; # +$Loader = "LILO" if $loader =~ /^lilo/io; +$Loader = "SILO" if $loader =~ /^silo/io; +$Loader = "QUIK" if $loader =~ /^quik/io; +$Loader = "yaboot" if $loader =~ /^yaboot/io; +$Loader = "PALO" if $loader =~ /^palo/io; +$Loader = "NETTROM" if $loader =~ /^nettrom/io; +$Loader = "VMELILO" if $loader =~ /^vmelilo/io; +$Loader = "ZIPL" if $loader =~ /^zipl/io; +$Loader = "ELILO" if $loader =~ /^elilo/io; + + +# This should not point to /tmp, because of security risks. +my $temp_file_name = "/var/log/$loader" . "_log.$$"; + +#known variables +my @boilerplate = (); +my @silotemplate = (); +my @quiktemplate = (); +my @palotemplate = (); +my @vmelilotemplate = (); +my $bootdevice = ''; +my $rootdevice = ''; +my $rootdisk = ''; +my $rootpartition = ''; +my $image_dest = "/"; +my $realimageloc = "/$image_dir/"; +my $have_conffile = ""; +my $CONF_LOC = '/etc/kernel-img.conf'; +my $relative_links = ''; +my $silent_modules = ''; +my $silent_loader = ''; +my $warn_reboot = 'Yes'; # Warn that we are installing a version of + # the kernel we are running + +chdir('/') or die "could not chdir to /:$!\n"; +# remove multiple leading slashes; make sure there is at least one. +$realimageloc =~ s|^/*|/|o; +$realimageloc =~ s|/+|/|o; + + +if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { + if (open(CONF, "$CONF_LOC")) { + while () { + chomp; + s/\#.*$//g; + next if /^\s*$/; + + $do_symlink = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig; + $no_symlink = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig; + $reverse_symlink = "" if /^\s*reverse_symlinks\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig; + $move_image = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig; + $clobber_modules = '' if /^\s*clobber_modules\s*=\s*(no|false|0)\s*$/ig; + $do_boot_enable = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig; + $do_bootfloppy = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig; + $relative_links = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig; + $do_bootloader = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig; + $do_initrd = '' if /^\s*do_initrd\s*=\s*(no|false|0)\s*$/ig; + $warn_initrd = '' if /^\s*warn_initrd\s*=\s*(no|false|0)\s*$/ig; + $use_hard_links = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig; + $silent_modules = '' if /^\s*silent_modules\s*=\s*(no|false|0)\s*$/ig; + $silent_loader = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig; + $warn_reboot = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig; + $minimal_swap = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig; + $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig; + $relink_build_link = '' if /^\s*relink_build_link\s*=\s*(no|false|0)\s*$/ig; + $force_build_link = '' if /^\s*force_build_link\s*=\s*(no|false|0)\s*$/ig; + + $do_symlink = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $no_symlink = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $move_image = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig; + $clobber_modules = "Yes" if /^\s*clobber_modules\s*=\s*(yes|true|1)\s*$/ig; + $do_boot_enable = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig; + $do_bootfloppy = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig; + $do_bootloader = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig; + $relative_links = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig; + $do_initrd = "Yes" if /^\s*do_initrd\s*=\s*(yes|true|1)\s*$/ig; + $warn_initrd = "Yes" if /^\s*warn_initrd\s*=\s*(yes|true|1)\s*$/ig; + $use_hard_links = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig; + $silent_modules = 'Yes' if /^\s*silent_modules\s*=\s*(yes|true|1)\s*$/ig; + $silent_loader = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig; + $warn_reboot = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig; + $minimal_swap = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig; + $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig; + $relink_build_link = 'Yes' if /^\s*relink_build_link\s*=\s*(yes|true|1)\s*$/ig; + $force_build_link = 'Yes' if /^\s*force_build_link\s*=\s*(yes|true|1)\s*$/ig; + + $image_dest = "$1" if /^\s*image_dest\s*=\s*(\S+)/ig; + $postinst_hook = "$1" if /^\s*postinst_hook\s*=\s*(\S+)/ig; + $postrm_hook = "$1" if /^\s*postrm_hook\s*=\s*(\S+)/ig; + $preinst_hook = "$1" if /^\s*preinst_hook\s*=\s*(\S+)/ig; + $prerm_hook = "$1" if /^\s*prerm_hook\s*=\s*(\S+)/ig; + $ramdisk = "$1" if /^\s*ramdisk\s*=\s*(.+)$/ig; + } + close CONF; + $have_conffile = "Yes"; + } +} + +if ($link_in_boot) { + $image_dest = "/$image_dir/"; + $image_dest =~ s|^/*|/|o; +} + +$image_dest = "$image_dest/"; +$image_dest =~ s|/+$|/|o; + +# The destdir may be gone by now. +if (-d "$image_dest") { + chdir("$image_dest") or die "could not chdir to $image_dest:$!\n"; +} + +# Paranoid check to make sure that the correct value is put in there +if (! $kimage) {$kimage = "vmlinuz"} # Hmm. empty +elsif ($kimage =~ m/^b?uImage$/o) {$kimage = "vmlinuz"} # these produce vmlinuz +elsif ($kimage =~ m/^b?zImage$/o) {$kimage = "vmlinuz"} # these produce vmlinuz +elsif ($kimage =~ m/^[iI]mage$/o) { my $nop = $kimage;} +elsif ($kimage =~ m/^vmlinux$/o) { my $nop = $kimage;} +else {$kimage = "vmlinuz"} # default + +$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; + + +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### +sub remove_sym_link { + my $bad_image = $_[0]; + + warn "Removing symbolic link $bad_image \n"; + if ($loader =~ /lilo/i) + { + warn "Unless you used the optional flag in lilo, \n"; + } + warn " you may need to re-run your boot loader" . ($loader ? "[$loader]":"") + . "\n"; + # Remove the dangling link + unlink "$bad_image"; +} + +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### +sub CanonicalizePath { + my $path = join '/', @_; + my @work = split '/', $path; + my @out; + my $is_absolute; + + if (@work && $work[0] eq "") { $is_absolute = 1; shift @work; } + + while (@work) { + my $seg = shift @work; + if ($seg eq "." || $seg eq "") { + } elsif ($seg eq "..") { + if (@out && $out[-1] ne "..") { + pop @out; + } else { + # Leading "..", or "../..", etc. + push @out, $seg; + } + } else { + push @out, $seg; + } + } + + unshift @out, "" if $is_absolute; + return join('/', @out); +} + +###################################################################### +###################################################################### +############ +###################################################################### +###################################################################### +# This removes dangling symlinks. What do we do about hard links? Surely a +# something with the nane $image_dest . "$kimage" ought not to be left behind? +sub image_magic { + my $kimage = $_[0]; + my $image_dest = $_[1]; + + if (-l "$kimage") { + # There is a symbolic link + my $force_move = 0; + my $vmlinuz_target = readlink "$kimage"; + my $real_target = ''; + $real_target = abs_path($vmlinuz_target) if defined ($vmlinuz_target); + if (!defined($vmlinuz_target) || ! -f "$real_target") { + # what, a dangling symlink? + warn "The link " . $image_dest . "$kimage is a damaged link\n"; + # Remove the dangling link + &remove_sym_link("$kimage"); + } + else { + my $canonical_target = CanonicalizePath("$vmlinuz_target"); + if (! -e $canonical_target) { + warn "The link " . $image_dest . "$kimage is a dangling link\n"; + &remove_sym_link("$kimage"); + } + } + } +} + +# set the env var stem +$ENV{'STEM'} = "linux"; + +sub exec_script { + my $type = shift; + my $script = shift; + print STDERR "Running $type hook script $script.\n"; + system ("$script $version $realimageloc$kimage-$version") && + print STDERR "User $type hook script [$script] "; + if ($?) { + if ($? == -1) { + print STDERR "failed to execute: $!\n"; + } + elsif ($? & 127) { + printf STDERR "died with signal %d, %s coredump\n", + ($? & 127), ($? & 128) ? 'with' : 'without'; + } + else { + printf STDERR "exited with value %d\n", $? >> 8; + } + } +} +sub run_hook { + my $type = shift; + my $script = shift; + if ($script =~ m,^/,) { + # Full path provided for the hook script + if (-x "$script") { + &exec_script($type,$script); + } + else { + warn "The provided $type hook script [$script] could not be run.\n"; + } + } + else { + # Look for it in a safe path + for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { + if (-x "$path/$script") { + &exec_script($type, "$path/$script"); + return 0; + } + } + # No luck + print STDERR "Could not find $type hook script [$script].\n"; + warn "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; + } +} + +my $options; +for (@ARGV) { + s,','\\'',g; + $options .= " '$_'"; +} +$ENV{'DEB_MAINT_PARAMS'}="$options"; + +## Run user hook script here, if any +if ($postrm_hook) { + &run_hook("postrm", $postrm_hook); +} +if (-d "/etc/kernel/postrm.d") { + warn "Examining /etc/kernel/postrm.d .\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/postrm.d") && + die "Failed to process /etc/kernel/postrm.d"; +} +if (-d "/etc/kernel/postrm.d/$version") { + warn "Examining /etc/kernel/postrm.d/$version .\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version " . + "/etc/kernel/postrm.d/$version") && + die "Failed to process /etc/kernel/postrm.d/$version"; +} + +# check and remove damaged and dangling symlinks +if ($ARGV[0] !~ /upgrade/) { + system("$ramdisk -d -k " . $version . " > /dev/null 2>&1"); + if (-f $realimageloc . "initrd.img-$version.bak") { + unlink $realimageloc . "initrd.img-$version.bak"; + } + image_magic($kimage, $image_dest); + image_magic($kimage . ".old", $image_dest); + image_magic("initrd.img", $image_dest) if $initrd; + image_magic("initrd.img.old", $image_dest) if $initrd; +} + +exit 0; + +__END__ + + + + + + --- linux-2.6.37.orig/debian/control-scripts/preinst +++ linux-2.6.37/debian/control-scripts/preinst @@ -0,0 +1,306 @@ +#! /usr/bin/perl +# -*- Mode: Cperl -*- +# image.preinst --- +# Author : Manoj Srivastava ( srivasta@tiamat.datasync.com ) +# Created On : Sun Jun 14 03:38:02 1998 +# Created On Node : tiamat.datasync.com +# Last Modified By : Manoj Srivastava +# Last Modified On : Sun Sep 24 14:04:42 2006 +# Last Machine Used: glaurung.internal.golden-gryphon.com +# Update Count : 99 +# Status : Unknown, Use with caution! +# HISTORY : +# Description : +# +# + +# +#use strict; #for debugging + +use Debconf::Client::ConfModule qw(:all); +version('2.0'); +my $capb=capb("backup"); + +$|=1; + +# Predefined values: +my $version = "=V"; +my $link_in_boot = ""; # Should be empty, mostly +my $no_symlink = ""; # Should be empty, mostly +my $reverse_symlink = ""; # Should be empty, mostly +my $do_symlink = "Yes"; # target machine defined +my $do_boot_enable = "Yes"; # target machine defined +my $do_bootfloppy = "Yes"; # target machine defined +my $do_bootloader = "Yes"; # target machine defined +my $move_image = ''; # target machine defined +my $kimage = "=K"; # Should be empty, mostly +my $loader = "=L"; # lilo, silo, quik, palo, vmelilo, nettrom + # or elilo +my $image_dir = "/boot"; # where the image is located +my $initrd = "YES"; # initrd kernel +my $use_hard_links = ''; # hardlinks do not wirk across fs boundaries +my $postinst_hook = ''; #Normally we do not +my $postrm_hook = ''; #Normally we do not +my $preinst_hook = ''; #Normally we do not +my $prerm_hook = ''; #Normally we do not +my $minimal_swap = ''; # Do not swap symlinks +my $ignore_depmod_err = ''; # normally we do not +my $relink_src_link = 'YES'; # There is no harm in checking the link +my $relink_build_link = 'YES'; # There is no harm in checking the link +my $force_build_link = ''; # There is no harm in checking the link +my $kernel_arch = "=B"; +my $ramdisk = "/usr/sbin/update-initramfs"; # List of tools to create initial ram fs. +my $package_name = "linux-image-$version"; + +my $Loader = "NoLOADER"; # +$Loader = "LILO" if $loader =~ /^lilo/io; +$Loader = "SILO" if $loader =~ /^silo/io; +$Loader = "QUIK" if $loader =~ /^quik/io; +$Loader = "yaboot" if $loader =~ /^yaboot/io; +$Loader = "PALO" if $loader =~ /^palo/io; +$Loader = "NETTROM" if $loader =~ /^nettrom/io; +$Loader = "VMELILO" if $loader =~ /^vmelilo/io; +$Loader = "ZIPL" if $loader =~ /^zipl/io; +$Loader = "ELILO" if $loader =~ /^elilo/io; + + +#known variables +my @boilerplate = (); +my @silotemplate = (); +my @quiktemplate = (); +my @palotemplate = (); +my @vmelilotemplate = (); +my $bootdevice = ''; +my $rootdevice = ''; +my $rootdisk = ''; +my $rootpartition = ''; +my $image_dest = "/"; +my $realimageloc = "/$image_dir/"; +my $have_conffile = ""; +my $CONF_LOC = '/etc/kernel-img.conf'; +my $relative_links = ''; +my $silent_loader = ''; +my $warn_reboot = ''; # Warn that we are installing a version of + # the kernel we are running + +my $modules_base = '/lib/modules'; + +die "Pre inst Internal error. Aborting." unless $version; + +exit 0 if $ARGV[0] =~ /abort-upgrade/; +exit 1 unless $ARGV[0] =~ /(install|upgrade)/; + +# remove multiple leading slashes; make sure there is at least one. +$realimageloc =~ s|^/*|/|o; +$realimageloc =~ s|/+|/|o; + +if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { + if (open(CONF, "$CONF_LOC")) { + while () { + chomp; + s/\#.*$//g; + next if /^\s*$/; + + $do_symlink = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig; + $no_symlink = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig; + $reverse_symlink = "" if /^\s*reverse_symlinks\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig; + $move_image = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig; + $do_boot_enable = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig; + $do_bootfloppy = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig; + $do_bootloader = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig; + $relative_links = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig; + $use_hard_links = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig; + $silent_loader = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig; + $warn_reboot = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig; + $minimal_swap = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig; + $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig; + $relink_src_link = '' if /^\s*relink_src_link\s*=\s*(no|false|0)\s*$/ig; + $relink_build_link = '' if /^\s*relink_build_link\s*=\s*(no|false|0)\s*$/ig; + $force_build_link = '' if /^\s*force_build_link\s*=\s*(no|false|0)\s*$/ig; + + $do_symlink = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $no_symlink = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $move_image = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig; + $do_boot_enable = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig; + $do_bootfloppy = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig; + $do_bootloader = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig; + $relative_links = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig; + $use_hard_links = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig; + $silent_loader = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig; + $warn_reboot = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig; + $minimal_swap = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig; + $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig; + $relink_src_link = 'Yes' if /^\s*relink_src_link\s*=\s*(yes|true|1)\s*$/ig; + $relink_build_link = 'Yes' if /^\s*relink_build_link\s*=\s*(yes|true|1)\s*$/ig; + $force_build_link = 'Yes' if /^\s*force_build_link\s*=\s*(yes|true|1)\s*$/ig; + + $image_dest = "$1" if /^\s*image_dest\s*=\s*(\S+)/ig; + $postinst_hook = "$1" if /^\s*postinst_hook\s*=\s*(\S+)/ig; + $postrm_hook = "$1" if /^\s*postrm_hook\s*=\s*(\S+)/ig; + $preinst_hook = "$1" if /^\s*preinst_hook\s*=\s*(\S+)/ig; + $prerm_hook = "$1" if /^\s*prerm_hook\s*=\s*(\S+)/ig; + $ramdisk = "$1" if /^\s*ramdisk\s*=\s*(.+)$/ig; + } + close CONF; + $have_conffile = "Yes"; + $have_conffile = "Yes"; # stop perl complaining + } +} + +$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; + +# About to upgrade this package from version $2 TO THIS VERSION. +# "prerm upgrade" has already been called for the old version of +# this package. + +sub find_initrd_tool { + my $hostversion = shift; + my $version = shift; + my @ramdisks = + grep { + my $args = + "$_ " . + "--supported-host-version=$hostversion " . + "--supported-target-version=$version " . + "1>/dev/null 2>&1" + ; + system($args) == 0; + } + split (/[:,\s]+/, $ramdisk); +} + +sub check { + my $version = shift; + my $lib_modules="$modules_base/$version"; + my $message = ''; + + if (-d "$lib_modules") { + opendir(DIR, $lib_modules) || die "can’t opendir $lib_modules: $!"; + my @children = readdir(DIR); + if ($#children > 1) { + my @dirs = grep { -d "$lib_modules/$_" } @children; + if ($#dirs > 1) { # we have subdirs + my $dir_message=''; + for my $dir (@dirs) { + if ($dir =~/kernel$/) { + $dir_message="An older install was detected.\n"; + } + else { + $dir_message="Module sub-directories were detected.\n" + unless $dir_message; + } + } + $message += $dir_message if $dir_message; + } + + my @links = grep { -l "$lib_modules/$_" } @children; + if ($#links > -1) { + my $links_message = ''; + for my $link (@links) { + next if ($link =~ /^build$/); + next if ($link =~ /^source$/); + $links_message = "Symbolic links were detected in $modules_base/$version.\n"; + } + $message += $links_message if $links_message; + } + my @files = grep { -f "$lib_modules/$_" } @children; + $message += "Additional files also exist in $modules_base/$version.\n" + if ($#files > -1); + } + } + else { $message .= "$lib_modules does not exist. ";} + return $message; +} + +if (-d "$modules_base/$version") { + my $errors=check($version); + warn "Info:\n$errors\n" if $errors; +} + +# set the env var stem +$ENV{'STEM'} = "linux"; + +sub exec_script { + my $type = shift; + my $script = shift; + print STDERR "Running $type hook script $script.\n"; + system ("$script $version $realimageloc$kimage-$version") && + print STDERR "User $type hook script [$script] "; + if ($?) { + if ($? == -1) { + print STDERR "failed to execute: $!\n"; + } + elsif ($? & 127) { + printf STDERR "died with signal %d, %s coredump\n", + ($? & 127), ($? & 128) ? 'with' : 'without'; + } + else { + printf STDERR "exited with value %d\n", $? >> 8; + } + exit $? >> 8; + } +} +sub run_hook { + my $type = shift; + my $script = shift; + if ($script =~ m,^/,) { + # Full path provided for the hook script + if (-x "$script") { + &exec_script($type,$script); + } + else { + die "The provided $type hook script [$script] could not be run.\n"; + } + } + else { + # Look for it in a safe path + for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { + if (-x "$path/$script") { + &exec_script($type, "$path/$script"); + return 0; + } + } + # No luck + print STDERR "Could not find $type hook script [$script].\n"; + die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; + } +} + + +my $options; +for (@ARGV) { + s,','\\'',g; + $options .= " '$_'"; +} +$ENV{'DEB_MAINT_PARAMS'}="$options"; + +## Run user hook script here, if any +if (-x "$preinst_hook") { + &run_hook("preinst", $preinst_hook); +} +if (-d "/etc/kernel/preinst.d") { + print STDERR "Examining /etc/kernel/preinst.d/\n"; + system ("run-parts --verbose --exit-on-error --arg=$version" . + " --arg=$realimageloc$kimage-$version" . + " /etc/kernel/preinst.d") && + die "Failed to process /etc/kernel/preinst.d"; +} +if (-d "/etc/kernel/preinst.d/$version") { + print STDERR "Examining /etc/kernel/preinst.d/$version.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version" . + " --arg=$realimageloc$kimage-$version" . + " /etc/kernel/preinst.d/$version") && + die "Failed to process /etc/kernel/preinst.d/$version"; +} +print STDERR "Done.\n"; + +exit 0; + +__END__ + + --- linux-2.6.37.orig/debian/control-scripts/prerm +++ linux-2.6.37/debian/control-scripts/prerm @@ -0,0 +1,312 @@ +#! /usr/bin/perl +# -*- Mode: Perl -*- +# image.prerm --- +# Author : root ( root@melkor.pilgrim.umass.edu ) +# Created On : Fri May 17 03:28:59 1996 +# Created On Node : melkor.pilgrim.umass.edu +# Last Modified By : Manoj Srivastava +# Last Modified On : Sat Aug 5 13:14:17 2006 +# Last Machine Used: glaurung.internal.golden-gryphon.com +# Update Count : 85 +# Status : Unknown, Use with caution! +# HISTORY : +# Description : +# +# +# $Id: image.prerm,v 1.22 2003/10/07 16:24:20 srivasta Exp $ +# +# +#use strict; + +$|=1; +# Predefined values: +my $version = "=V"; +my $link_in_boot = ""; # Should be empty, mostly +my $no_symlink = ""; # Should be empty, mostly +my $reverse_symlink = ""; # Should be empty, mostly +my $do_symlinks = "Yes"; # target machine defined +my $do_boot_enable = "Yes"; # target machine defined +my $do_bootfloppy = "Yes"; # target machine defined +my $do_bootloader = "Yes"; # target machine defined +my $move_image = ''; # target machine defined +my $kimage = "=K"; # Should be empty, mostly +my $loader = "=L"; # lilo, silo, quik, palo, vmelilo, or nettrom +my $image_dir = "/boot"; # where the image is located +my $clobber_modules = ''; # target machine defined +my $initrd = "YES"; # initrd kernel +my $use_hard_links = ''; # hardlinks do not wirk across fs boundaries +my $postinst_hook = ''; #Normally we do not +my $postrm_hook = ''; #Normally we do not +my $preinst_hook = ''; #Normally we do not +my $prerm_hook = ''; #Normally we do not +my $minimal_swap = ''; # Do not swap symlinks +my $ignore_depmod_err = ''; # normally we do not +my $relink_build_link = 'YES'; # There is no harm in checking the link +my $force_build_link = ''; # There is no harm in checking the link +my $kernel_arch = "=B"; +my $ramdisk = "/usr/sbin/update-initramfs"; +my $package_name = "linux-image-$version"; + +my $Loader = "NoLOADER"; # +$Loader = "LILO" if $loader =~ /^lilo/io; +$Loader = "SILO" if $loader =~ /^silo/io; +$Loader = "QUIK" if $loader =~ /^quik/io; +$Loader = "yaboot" if $loader =~ /^yaboot/io; +$Loader = "PALO" if $loader =~ /^palo/io; +$Loader = "NETTROM" if $loader =~ /^nettrom/io; +$Loader = "VMELILO" if $loader =~ /^vmelilo/io; +$Loader = "ZIPL" if $loader =~ /^zipl/io; +$Loader = "ELILO" if $loader =~ /^elilo/io; + + +# This should not point to /tmp, because of security risks. +my $temp_file_name = "/var/log/$loader" . "_log.$$"; + +#known variables +my $image_dest = "/"; +my $realimageloc = "/$image_dir/"; +my $have_conffile = ""; +my $CONF_LOC = '/etc/kernel-img.conf'; +my $relative_links = ''; +my $silent_loader = ''; +my $warn_reboot = 'Yes'; # Warn that we are installing a version of + # the kernel we are running + +# remove multiple leading slashes; make sure there is at least one. +$realimageloc =~ s|^/*|/|o; +$realimageloc =~ s|/+|/|o; + +my $DEBUG = 0; + +# Variables used +my $image=''; +my $ret=0; +my $seen=''; +my $answer=''; +my $running = ''; +my $WouldInvalidate = 0; + +if ($ARGV[0] && ($ARGV[0] =~ /remove/ || $ARGV[0] =~ /upgrade/)) { + if (-l "/usr/doc/linux-image-$version") { + unlink "/usr/doc/linux-image-$version"; + } +} + +# Ignore all invocations uxcept when called on to remove +exit 0 unless ($ARGV[0] && $ARGV[0] =~ /remove/) ; + +# Paranoid check to make sure that the correct value is put in there +if (! $kimage) { $kimage = "vmlinuz";} # Hmm. empty +elsif ($kimage =~ m/^b?uImage$/o) { $kimage = "vmlinuz";} # these produce vmlinuz +elsif ($kimage =~ m/^b?zImage$/o) { $kimage = "vmlinuz";} # these produce vmlinuz +elsif ($kimage =~ m/^[iI]mage$/o) { my $nop = $kimage; } +elsif ($kimage =~ m/^vmlinux$/o) { my $nop = $kimage; } +else { $kimage = "vmlinuz";} # Default + +if (-r "$CONF_LOC" && -f "$CONF_LOC" ) { + if (open(CONF, "$CONF_LOC")) { + while () { + chomp; + s/\#.*$//g; + next if /^\s*$/; + + $do_symlink = "" if /^\s*do_symlinks\s*=\s*(no|false|0)\s*$/ig; + $no_symlink = "" if /^\s*no_symlinks\s*=\s*(no|false|0)\s*$/ig; + $reverse_symlink = "" if /^\s*reverse_symlinks\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*image_in_boot\s*=\s*(no|false|0)\s*$/ig; + $link_in_boot = "" if /^\s*link_in_boot\s*=\s*(no|false|0)\s*$/ig; + $move_image = "" if /^\s*move_image\s*=\s*(no|false|0)\s*$/ig; + $clobber_modules = '' if /^\s*clobber_modules\s*=\s*(no|false|0)\s*$/ig; + $do_boot_enable = '' if /^\s*do_boot_enable\s*=\s*(no|false|0)\s*$/ig; + $do_bootfloppy = '' if /^\s*do_bootfloppy\s*=\s*(no|false|0)\s*$/ig; + $relative_links = '' if /^\s*relative_links \s*=\s*(no|false|0)\s*$/ig; + $do_bootloader = '' if /^\s*do_bootloader\s*=\s*(no|false|0)\s*$/ig; + $do_initrd = '' if /^\s*do_initrd\s*=\s*(no|false|0)\s*$/ig; + $use_hard_links = '' if /^\s*use_hard_links\s*=\s*(no|false|0)\s*$/ig; + $silent_loader = '' if /^\s*silent_loader\s*=\s*(no|false|0)\s*$/ig; + $warn_reboot = '' if /^\s*warn_reboot\s*=\s*(no|false|0)\s*$/ig; + $minimal_swap = '' if /^\s*minimal_swap\s*=\s*(no|false|0)\s*$/ig; + $ignore_depmod_err = '' if /^\s*ignore_depmod_err\s*=\s*(no|false|0)\s*$/ig; + $relink_build_link = '' if /^\s*relink_build_link\s*=\s*(no|false|0)\s*$/ig; + $force_build_link = '' if /^\s*force_build_link\s*=\s*(no|false|0)\s*$/ig; + + + $do_symlink = "Yes" if /^\s*do_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $no_symlink = "Yes" if /^\s*no_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $reverse_symlink = "Yes" if /^\s*reverse_symlinks\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*image_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $link_in_boot = "Yes" if /^\s*link_in_boot\s*=\s*(yes|true|1)\s*$/ig; + $move_image = "Yes" if /^\s*move_image\s*=\s*(yes|true|1)\s*$/ig; + $clobber_modules = "Yes" if /^\s*clobber_modules\s*=\s*(yes|true|1)\s*$/ig; + $do_boot_enable = "Yes" if /^\s*do_boot_enable\s*=\s*(yes|true|1)\s*$/ig; + $do_bootfloppy = "Yes" if /^\s*do_bootfloppy\s*=\s*(yes|true|1)\s*$/ig; + $do_bootloader = "Yes" if /^\s*do_bootloader\s*=\s*(yes|true|1)\s*$/ig; + $relative_links = "Yes" if /^\s*relative_links\s*=\s*(yes|true|1)\s*$/ig; + $do_initrd = "Yes" if /^\s*do_initrd\s*=\s*(yes|true|1)\s*$/ig; + $use_hard_links = "Yes" if /^\s*use_hard_links\s*=\s*(yes|true|1)\s*$/ig; + $silent_loader = 'Yes' if /^\s*silent_loader\s*=\s*(yes|true|1)\s*$/ig; + $warn_reboot = 'Yes' if /^\s*warn_reboot\s*=\s*(yes|true|1)\s*$/ig; + $minimal_swap = 'Yes' if /^\s*minimal_swap\s*=\s*(yes|true|1)\s*$/ig; + $ignore_depmod_err = 'Yes' if /^\s*ignore_depmod_err\s*=\s*(yes|true|1)\s*$/ig; + $relink_build_link = 'Yes' if /^\s*relink_build_link\s*=\s*(yes|true|1)\s*$/ig; + $force_build_link = 'Yes' if /^\s*force_build_link\s*=\s*(yes|true|1)\s*$/ig; + + $image_dest = "$1" if /^\s*image_dest\s*=\s*(\S+)/ig; + $postinst_hook = "$1" if /^\s*postinst_hook\s*=\s*(\S+)/ig; + $postrm_hook = "$1" if /^\s*postrm_hook\s*=\s*(\S+)/ig; + $preinst_hook = "$1" if /^\s*preinst_hook\s*=\s*(\S+)/ig; + $prerm_hook = "$1" if /^\s*prerm_hook\s*=\s*(\S+)/ig; + $ramdisk = "$1" if /^\s*ramdisk\s*=\s*(.+)$/ig; + } + close CONF; + $have_conffile = "Yes"; + } +} + + +$ENV{KERNEL_ARCH}=$kernel_arch if $kernel_arch; + +#check to see if we are trying to remove a running kernel +# if so we abort right now. +chop($running=`uname -r`); +if ($running eq $version) { + print STDERR "WARN: Proceeding with removing running kernel image.\n"; +} + +#Now, they have an alternate kernel which they are currently running + +# This is just us being nice to lilo users. + +chdir("/") or die "could not chdir to /:$!\n"; + +if (-f "/etc/$loader.conf") { #I know, could be a link, but .. + open (LILO, "/etc/$loader.conf") || &success(); # this is not critical + while () { + chop; + s/\#.*//; # nix the comments + next unless /^\s*image\s*=\s(\S+)/o; + $image = $1; + if ($image && -e $image) { + while (defined($image) && -l $image) { + $image = readlink ($image); + } + if (defined($image) && -e $image) { + $WouldInvalidate |= $image =~ /$kimage-$version/; + } + else { + &success(); # invalid $loader.conf file + } + } + else { + &success(); # invalid $loader.conf file + } + } + close (LILO); + if ($WouldInvalidate) { + print STFERR "WARN: Proceeding with removing running kernel image.\n"; + &success(); + } +} + + +# set the env var stem +$ENV{'STEM'} = "linux"; + +sub exec_script { + my $type = shift; + my $script = shift; + print STDERR "Running $type hook script $script.\n"; + system ("$script $version $realimageloc$kimage-$version") && + print STDERR "User $type hook script [$script] "; + if ($?) { + if ($? == -1) { + print STDERR "failed to execute: $!\n"; + } + elsif ($? & 127) { + printf STDERR "died with signal %d, %s coredump\n", + ($? & 127), ($? & 128) ? 'with' : 'without'; + } + else { + printf STDERR "exited with value %d\n", $? >> 8; + } + exit $? >> 8; + } +} +sub run_hook { + my $type = shift; + my $script = shift; + if ($script =~ m,^/,) { + # Full path provided for the hook script + if (-x "$script") { + &exec_script($type,$script); + } + else { + die "The provided $type hook script [$script] could not be run.\n"; + } + } + else { + # Look for it in a safe path + for my $path ('/bin', '/sbin', '/usr/bin', '/usr/sbin') { + if (-x "$path/$script") { + &exec_script($type, "$path/$script"); + return 0; + } + } + # No luck + print STDERR "Could not find $type hook script [$script].\n"; + die "Looked in: '/bin', '/sbin', '/usr/bin', '/usr/sbin'\n"; + } +} + + +my $options; +for (@ARGV) { + s,','\\'',g; + $options .= " '$_'"; +} +$ENV{'DEB_MAINT_PARAMS'}="$options"; + +## Run user hook script here, if any +if (-x "$prerm_hook") { + &run_hook("prerm", $prerm_hook); +} +if (-d "/etc/kernel/prerm.d") { + print STDERR "Examining /etc/kernel/prerm.d.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version " . + "--arg=$realimageloc$kimage-$version /etc/kernel/prerm.d") && + die "Failed to process /etc/kernel/prerm.d"; +} +if (-d "/etc/kernel/prerm.d/$version") { + print STDERR "Examining /etc/kernel/prerm.d/$version.\n"; + system ("run-parts --verbose --exit-on-error --arg=$version" . + " --arg=$realimageloc$kimage-$version " . + "/etc/kernel/prerm.d/$version") && + die "Failed to process /etc/kernel/prerm.d/$version"; +} + +sub success () { + # NOTE: need to keep this list in sync with rules.d/2-binary-arch.mk + my %files_to_keep = ( + 'modules.builtin' => 1, + 'modules.order' => 1, + ); + my $short; + for my $file () { + $short = $file; $short =~ s,.*/,,; + if (!defined $files_to_keep{$short}) { + unlink "$file"; + } + } + exit 0; +} + + + +&success(); +exit 0; +__END__ + + + + + --- linux-2.6.37.orig/debian/docs/README.inclusion-list +++ linux-2.6.37/debian/docs/README.inclusion-list @@ -0,0 +1,51 @@ +This README describes the reason for, and the use of, module +inclusion lists. + +The original Hardy release had the notion of sub-flavours, +e.g., a flavour that was constructed as a subset of an existing flavour. +For example, the virtual flavour was extracted from the server flavour using +a subset of the server flavour modules. However, there were some difficult +mainteneance issues with regard to packaging, make rules, and scripts. This +re-implementation of the sub-flavours philosophy is hopefully simpler, +and retrofitable to all releases. + +A module inclusion list looks at the problem of of constructing a package +from the perspective of what modules do we _want_ in the package, as opposed +to what modules we _don't_ want. As the kernel matures, more and more devices are added +which makes the problem of configuration maintenance a real pain in the ass. +If we took the approach of disabling all of the config options that we don't want, +then the differences between flavours will quickly become quite large, making +it difficult to quickly compare the individual flavour configs. Each time a +new config option is added then we also have to make a decision about disabling in +order to continue to keep the minimal number of modules. + +A module inclusion list is applied on a per-flavour basis. For example, +debian./control.d/${flavour}.inclusion-list. For example, the +config for virtual is very close to server and generic, but the inclusion list +causes the virtual package to be constructed with _only_ the modules described +in the inclusion list. + +The inclusion list format is a simple bash regular expression list of files. For example, + +arch/*/{crypto,kernel,oprofile} +drivers/acpi/* +drivers/ata/ahci.ko + +These 3 regular expression forms are suitable for expansion by bash and as inputs to 'find'. +See debian/scripts/module-inclusion for details. + +There are 2 log files created as a side effect of the application of the module +inclusion list; $(flavour).inclusion-list.log and $(flavour).depmod.log. + +$(flavour).inclusion-list.log : This log is created while the inclusion list +modules are being copied. If any are missing, then those warnings go in this log. +While its not considered a fatal error, you should endevour to correct your inclusion +list such that there are no missing modules. + +$(flavour).depmod.log : The log is created as a result of running depmod on the +resulting set of modules. If there are missing symbols then you'll find that information +here. Again, you should modify your inclusion list such that there are no missing +symbols. + +Tim Gardner +June 2, 2010 --- linux-2.6.37.orig/debian/rules.d/1-maintainer.mk +++ linux-2.6.37/debian/rules.d/1-maintainer.mk @@ -0,0 +1,122 @@ +# The following targets are for the maintainer only! do not run if you don't +# know what they do. + +.PHONY: printenv updateconfigs printchanges insertchanges startnewrelease diffupstream help updateportsconfigs editportsconfigs + +help: + @echo "These are the targets in addition to the normal $(DEBIAN) ones:" + @echo + @echo " printenv : Print some variables used in the build" + @echo + @echo " updateconfigs : Update core arch configs" + @echo + @echo " editconfigs : Update core arch configs interractively" + @echo " genconfigs : Generate core arch configs in CONFIGS/*" + @echo + @echo " updateportsconfigs : Update ports arch configs" + @echo + @echo " editportsconfigs : Update ports arch configs interactivly" + @echo " genportconfigs : Generate ports arch configs in CONFIGS/*" + @echo + @echo " printchanges : Print the current changelog entries (from git)" + @echo + @echo " insertchanges : Insert current changelog entries (from git)" + @echo + @echo " startnewrelease : Start a new changelog set" + @echo + @echo " diffupstream : Diff stock kernel code against upstream (git)" + @echo + @echo " help : If you are kernel hacking, you need the professional" + @echo " version of this" + @echo + @echo "Environment variables:" + @echo + @echo " NOKERNLOG : Do not add upstream kernel commits to changelog" + @echo " CONCURRENCY_LEVEL=X" + @echo " : Use -jX for kernel compile" + @echo " PRINTSHAS : Include SHAs for commits in changelog" + +printdebian: + @echo "$(DEBIAN)" + +updateconfigs defaultconfigs editconfigs genconfigs dumpconfigs: + dh_testdir; + $(SHELL) $(DROOT)/scripts/misc/kernelconfig $@ + rm -rf build + +updateportsconfigs defaultportsconfigs editportsconfigs genportsconfigs askconfigs: + dh_testdir; + $(SHELL) $(DROOT)/scripts/misc/kernelconfig $@ ports + rm -rf build + +printenv: + dh_testdir + @echo "src package name = $(src_pkg_name)" + @echo "release = $(release)" + @echo "revisions = $(revisions)" + @echo "revision = $(revision)" + @echo "uploadnum = $(uploadnum)" + @echo "prev_revisions = $(prev_revisions)" + @echo "prev_revision = $(prev_revision)" + @echo "abinum = $(abinum)" + @echo "gitver = $(gitver)" + @echo "flavours = $(flavours)" + @echo "skipabi = $(skipabi)" + @echo "skipmodule = $(skipmodule)" + @echo "skipdbg = $(skipdbg)" + @echo "ubuntu_log_opts = $(ubuntu_log_opts)" +ifneq ($(SUBLEVEL),) + @echo "SUBLEVEL = $(SUBLEVEL)" +endif + @echo "CONCURRENCY_LEVEL = $(CONCURRENCY_LEVEL)" + @echo "bin package name = $(bin_pkg_name)" + @echo "hdr package name = $(hdrs_pkg_name)" + @echo "doc package name = $(doc_pkg_name)" + @echo "do_doc_package = $(do_doc_package)" + @echo "do_doc_package_content = $(do_doc_package_content)" + @echo "do_source_package = $(do_source_package)" + @echo "do_source_package_content = $(do_source_package_content)" + @echo "do_libc_dev_package = $(do_libc_dev_package)" + @echo "do_flavour_image_package = $(do_flavour_image_package)" + @echo "do_flavour_header_package = $(do_flavour_header_package)" + @echo "do_common_headers_indep = $(do_common_headers_indep)" + @echo "do_full_source = $(do_full_source)" + @echo "do_tools = $(do_tools)" + @echo "full_build = $(full_build)" + @echo "libc_dev_version = $(libc_dev_version)" + @echo "DEB_HOST_GNU_TYPE = $(DEB_HOST_GNU_TYPE)" + @echo "DEB_BUILD_GNU_TYPE = $(DEB_BUILD_GNU_TYPE)" + @echo "DEB_HOST_ARCH = $(DEB_HOST_ARCH)" + @echo "DEB_BUILD_ARCH = $(DEB_BUILD_ARCH)" + @echo "arch = $(arch)" + @echo "kmake = $(kmake)" + +printchanges: + @baseCommit=$$(git log --pretty=format:'%H %s' | \ + awk '/UBUNTU: '".*Ubuntu-$(release)-$(prev_revision)"'$$/ { print $$1; exit }'); \ + git log "$$baseCommit"..HEAD | \ + perl -w -f $(DROOT)/scripts/misc/git-ubuntu-log $(ubuntu_log_opts) + +insertchanges: + @perl -w -f $(DROOT)/scripts/misc/insert-changes.pl $(DROOT) $(DEBIAN) + +diffupstream: + @git diff-tree -p refs/remotes/linux-2.6/master..HEAD $(shell ls | grep -vE '^(ubuntu|$(DEBIAN)|\.git.*)') + +startnewrelease: + dh_testdir + @nextminor=$(shell expr `echo $(revision) | awk -F. '{print $$2}'` + 1); \ + now="$(shell date -R)"; \ + echo "Creating new changelog set for $(abi_release).$$nextminor..."; \ + echo -e "$(src_pkg_name) ($(abi_release).$$nextminor) UNRELEASED; urgency=low\n" > $(DEBIAN)/changelog.new; \ + echo " CHANGELOG: Do not edit directly. Autogenerated at release." >> \ + $(DEBIAN)/changelog.new; \ + echo " CHANGELOG: Use the printchanges target to see the curent changes." \ + >> $(DEBIAN)/changelog.new; \ + echo " CHANGELOG: Use the insertchanges target to create the final log." \ + >> $(DEBIAN)/changelog.new; \ + echo -e "\n -- $$DEBFULLNAME <$$DEBEMAIL> $$now\n" >> \ + $(DEBIAN)/changelog.new ; \ + cat $(DEBIAN)/changelog >> $(DEBIAN)/changelog.new; \ + mv $(DEBIAN)/changelog.new $(DEBIAN)/changelog + --- linux-2.6.37.orig/debian/rules.d/4-checks.mk +++ linux-2.6.37/debian/rules.d/4-checks.mk @@ -0,0 +1,34 @@ +# Check ABI for package against last release (if not same abinum) +abi-%: $(abidir)/% + @# Empty for make to be happy +$(abidir)/%: $(stampdir)/stamp-build-% + install -d $(abidir) + sed -e 's/^\(.\+\)[[:space:]]\+\(.\+\)[[:space:]]\(.\+\)$$/\3 \2 \1/' \ + $(builddir)/build-$*/Module.symvers | sort > $@ + +abi-check-%: $(abidir)/% + @perl -f $(DROOT)/scripts/abi-check "$*" "$(prev_abinum)" "$(abinum)" \ + "$(prev_abidir)" "$(abidir)" "$(skipabi)" + +# Check the module list against the last release (always) +module-%: $(abidir)/%.modules + @# Empty for make to be happy +$(abidir)/%.modules: $(stampdir)/stamp-build-% + install -d $(abidir) + find $(builddir)/build-$*/ -name \*.ko | \ + sed -e 's/.*\/\([^\/]*\)\.ko/\1/' | sort > $@ + +module-check-%: $(abidir)/%.modules + @perl -f $(DROOT)/scripts/module-check "$*" \ + "$(prev_abidir)" "$(abidir)" $(skipmodule) + +checks-%: abi-check-% module-check-% + @# Will be calling more stuff later + +# Check the config against the known options list. +config-prepare-check-%: $(stampdir)/stamp-prepare-tree-% + @perl -f $(DROOT)/scripts/config-check \ + $(builddir)/build-$*/.config "$(arch)" "$*" "$(sharedconfdir)" "$(skipconfig)" + +prepare-checks-%: config-prepare-check-% + @# Will be calling more stuff later --- linux-2.6.37.orig/debian/rules.d/5-udebs.mk +++ linux-2.6.37/debian/rules.d/5-udebs.mk @@ -0,0 +1,38 @@ +# Do udebs if not disabled in the arch-specific makefile +binary-udebs: binary-debs debian/control +ifeq ($(disable_d_i),) + @$(MAKE) --no-print-directory -f $(DROOT)/rules DEBIAN=$(DEBIAN) \ + do-binary-udebs +endif + +do-binary-udebs: + dh_testdir + dh_testroot + + # unpack the kernels into a temporary directory + mkdir -p debian/d-i-${arch} + + imagelist=$$(cat $(builddir)/kernel-versions | grep ^${arch} | awk '{print $$4}') && \ + for i in $$imagelist; do \ + dpkg -x $$(ls ../linux-image-$$i\_$(release)-$(revision)_${arch}.deb) \ + debian/d-i-${arch}; \ + /sbin/depmod -b debian/d-i-${arch} $$i; \ + done + + # kernel-wedge will error if no modules unless this is touched + touch $(CURDIR)/debian/build/no-modules + + touch ignore-dups + export SOURCEDIR=$(CURDIR)/debian/d-i-${arch} && \ + cd $(builddir) && \ + kernel-wedge install-files && \ + kernel-wedge check + + # Build just the udebs + dilist=$$(dh_listpackages -s | grep "\-di$$") && \ + [ -z "$dilist" ] || \ + for i in $$dilist; do \ + dh_fixperms -p$$i; \ + dh_gencontrol -p$$i; \ + dh_builddeb -p$$i; \ + done --- linux-2.6.37.orig/debian/rules.d/0-common-vars.mk +++ linux-2.6.37/debian/rules.d/0-common-vars.mk @@ -0,0 +1,222 @@ +# +# The source package name will be the first token from $(DEBIAN)/changelog +# +src_pkg_name=$(shell sed -n '1s/^\(.*\) (.*).*$$/\1/p' $(DEBIAN)/changelog) + +# Get some version info +series := maverick +release := $(shell sed -n '1s/^$(src_pkg_name).*(\(.*\)-.*).*$$/\1/p' $(DEBIAN)/changelog) +revisions := $(shell sed -n 's/^$(src_pkg_name)\ .*($(release)-\(.*\)).*$$/\1/p' $(DEBIAN)/changelog | tac) +revision ?= $(word $(words $(revisions)),$(revisions)) +prev_revisions := $(filter-out $(revision),0.0 $(revisions)) +prev_revision := $(word $(words $(prev_revisions)),$(prev_revisions)) + +family=ubuntu + +# This is an internally used mechanism for the daily kernel builds. It +# creates packages whose ABI is suffixed with a minimal representation of +# the current git HEAD sha. If .git/HEAD is not present, then it uses the +# uuidgen program, +# +# AUTOBUILD can also be used by anyone wanting to build a custom kernel +# image, or rebuild the entire set of Ubuntu packages using custom patches +# or configs. +AUTOBUILD= + +# +# This is a way to support some external variables. A good example is +# a local setup for ccache and distcc See LOCAL_ENV_CC and +# LOCAL_ENV_DISTCC_HOSTS in the definition of kmake. +# For example: +# LOCAL_ENV_CC="ccache distcc" +# LOCAL_ENV_DISTCC_HOSTS="localhost 10.0.2.5 10.0.2.221" +# +-include $(CURDIR)/../.$(series)-env + +ifneq ($(AUTOBUILD),) +skipabi = true +skipmodule = true +skipdbg = true +gitver=$(shell if test -f .git/HEAD; then cat .git/HEAD; else uuidgen; fi) +gitverpre=$(shell echo $(gitver) | cut -b -3) +gitverpost=$(shell echo $(gitver) | cut -b 38-40) +abi_suffix = -$(gitverpre)$(gitverpost) +endif + +ifneq ($(NOKERNLOG),) +ubuntu_log_opts += --no-kern-log +endif +ifneq ($(PRINTSHAS),) +ubuntu_log_opts += --print-shas +endif + +# Get the kernels own extra version to be added to the release signature. +extraversion=$(shell awk '/EXTRAVERSION =/ { print $$3 }' in DEB_BUILD_OPTIONS (see #209008) +# +# These 2 environment variables set the -j value of the kernel build. For example, +# CONCURRENCY_LEVEL=16 fakeroot $(DEBIAN)/rules binary-debs +# or +# DEB_BUILD_OPTIONS=parallel=16 fakeroot $(DEBIAN)/rules binary-debs +# +# The default is to use the number of CPUs. +# +COMMA=, +DEB_BUILD_OPTIONS_PARA = $(subst parallel=,,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS)))) +ifneq (,$(DEB_BUILD_OPTIONS_PARA)) + CONCURRENCY_LEVEL := $(DEB_BUILD_OPTIONS_PARA) +endif + +ifeq ($(CONCURRENCY_LEVEL),) + # Check the environment + CONCURRENCY_LEVEL := $(shell echo $$CONCURRENCY_LEVEL) + # No? Then build with the number of CPUs on the host. + ifeq ($(CONCURRENCY_LEVEL),) + CONCURRENCY_LEVEL := $(shell expr `getconf _NPROCESSORS_ONLN` \* 1) + endif + # Oh hell, give 'em one + ifeq ($(CONCURRENCY_LEVEL),) + CONCURRENCY_LEVEL := 1 + endif +endif + +conc_level = -j$(CONCURRENCY_LEVEL) + +# target_flavour is filled in for each step +kmake = make ARCH=$(build_arch) \ + CROSS_COMPILE=$(CROSS_COMPILE) \ + EXTRAVERSION=-$(abinum)-$(target_flavour) \ + CONFIG_DEBUG_SECTION_MISMATCH=y SUBLEVEL=$(SUBLEVEL) \ + KBUILD_BUILD_VERSION="$(uploadnum)" \ + LOCALVERSION= localver-extra= +ifneq ($(LOCAL_ENV_CC),) +kmake += CC=$(LOCAL_ENV_CC) DISTCC_HOSTS=$(LOCAL_ENV_DISTCC_HOSTS) +endif + --- linux-2.6.37.orig/debian/rules.d/2-binary-arch.mk +++ linux-2.6.37/debian/rules.d/2-binary-arch.mk @@ -0,0 +1,402 @@ +# We don't want make removing intermediary stamps +.SECONDARY : + +# Prepare the out-of-tree build directory +ifeq ($(do_full_source),true) +build_cd = cd $(builddir)/build-$*; # +build_O = +else +build_cd = +build_O = O=$(builddir)/build-$* +endif + +prepare-%: $(stampdir)/stamp-prepare-% + @# Empty for make to be happy +$(stampdir)/stamp-prepare-%: $(stampdir)/stamp-prepare-tree-% prepare-checks-% + @touch $@ +$(stampdir)/stamp-prepare-tree-%: target_flavour = $* +$(stampdir)/stamp-prepare-tree-%: $(commonconfdir)/config.common.$(family) $(archconfdir)/config.common.$(arch) $(archconfdir)/config.flavour.% + @echo "Preparing $*..." + install -d $(builddir)/build-$* + touch $(builddir)/build-$*/ubuntu-build + [ "$(do_full_source)" != 'true' ] && true || \ + rsync -a --exclude debian --exclude debian.master --exclude $(DEBIAN) * $(builddir)/build-$* + cat $^ | sed -e 's/.*CONFIG_VERSION_SIGNATURE.*/CONFIG_VERSION_SIGNATURE="Ubuntu $(release)-$(revision)-$* $(release)$(extraversion)"/' > $(builddir)/build-$*/.config + find $(builddir)/build-$* -name "*.ko" | xargs rm -f + $(build_cd) $(kmake) $(build_O) silentoldconfig prepare scripts + touch $@ + +# Do the actual build, including image and modules +build-%: $(stampdir)/stamp-build-% + @# Empty for make to be happy +$(stampdir)/stamp-build-%: target_flavour = $* +$(stampdir)/stamp-build-%: prepare-% + @echo "Building $*..." + $(build_cd) $(kmake) $(build_O) $(conc_level) $(build_image) + $(build_cd) $(kmake) $(build_O) $(conc_level) modules + @touch $@ + +# Install the finished build +install-%: pkgdir = $(CURDIR)/debian/$(bin_pkg_name)-$* +install-%: bindoc = $(pkgdir)/usr/share/doc/$(bin_pkg_name)-$* +install-%: dbgpkgdir = $(CURDIR)/debian/$(bin_pkg_name)-$*-dbgsym +install-%: basepkg = $(hdrs_pkg_name) +install-%: hdrdir = $(CURDIR)/debian/$(basepkg)-$*/usr/src/$(basepkg)-$* +install-%: target_flavour = $* +install-%: $(stampdir)/stamp-build-% checks-% + dh_testdir + dh_testroot + dh_clean -k -p$(bin_pkg_name)-$* + dh_clean -k -p$(hdrs_pkg_name)-$* + dh_clean -k -p$(dbg_pkg_name)-$* + + # The main image + # compress_file logic required because not all architectures + # generate a zImage automatically out of the box +ifeq ($(compress_file),) + install -m644 -D $(builddir)/build-$*/$(kernel_file) \ + $(pkgdir)/boot/$(install_file)-$(abi_release)-$* +else + install -d $(pkgdir)/boot + gzip -c9v $(builddir)/build-$*/$(kernel_file) > \ + $(pkgdir)/boot/$(install_file)-$(abi_release)-$* + chmod 644 $(pkgdir)/boot/$(install_file)-$(abi_release)-$* +endif + + install -m644 $(builddir)/build-$*/.config \ + $(pkgdir)/boot/config-$(abi_release)-$* + install -m644 $(abidir)/$* \ + $(pkgdir)/boot/abi-$(abi_release)-$* + install -m644 $(builddir)/build-$*/System.map \ + $(pkgdir)/boot/System.map-$(abi_release)-$* +ifeq ($(no_dumpfile),) + makedumpfile -g $(pkgdir)/boot/vmcoreinfo-$(abi_release)-$* \ + -x $(builddir)/build-$*/vmlinux +endif + + $(build_cd) $(kmake) $(build_O) modules_install \ + INSTALL_MOD_STRIP=1 INSTALL_MOD_PATH=$(pkgdir)/ \ + INSTALL_FW_PATH=$(pkgdir)/lib/firmware/$(abi_release)-$* + + # + # Remove all modules not in the inclusion list. + # + if [ -f $(DEBIAN)/control.d/$(target_flavour).inclusion-list ] ; then \ + $(SHELL) $(DROOT)/scripts/module-inclusion $(pkgdir)/lib/modules/$(abi_release)-$*/kernel \ + $(DEBIAN)/control.d/$(target_flavour).inclusion-list 2>&1 | \ + tee $(target_flavour).inclusion-list.log; \ + /sbin/depmod -b $(pkgdir) -ea -F $(pkgdir)/boot/System.map-$(abi_release)-$* \ + $(abi_release)-$* 2>&1 |tee $(target_flavour).depmod.log; \ + fi + +ifeq ($(no_dumpfile),) + makedumpfile -g $(pkgdir)/boot/vmcoreinfo-$(abi_release)-$* \ + -x $(builddir)/build-$*/vmlinux +endif + rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/build + rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/source + + # Some initramfs-tools specific modules + install -d $(pkgdir)/lib/modules/$(abi_release)-$*/initrd + if [ -f $(pkgdir)/lib/modules/$(abi_release)-$*/kernel/drivers/video/vesafb.ko ]; then\ + ln -f $(pkgdir)/lib/modules/$(abi_release)-$*/kernel/drivers/video/vesafb.ko \ + $(pkgdir)/lib/modules/$(abi_release)-$*/initrd/; \ + fi + + # Now the image scripts + install -d $(pkgdir)/DEBIAN + for script in postinst postrm preinst prerm; do \ + sed -e 's/=V/$(abi_release)-$*/g' -e 's/=K/$(install_file)/g' \ + -e 's/=L/$(loader)/g' -e 's@=B@$(build_arch)@g' \ + $(DROOT)/control-scripts/$$script > $(pkgdir)/DEBIAN/$$script; \ + chmod 755 $(pkgdir)/DEBIAN/$$script; \ + done + + # Install the full changelog. +ifeq ($(do_doc_package),true) + install -d $(bindoc) + cat $(DEBIAN)/changelog $(DEBIAN)/changelog.historical | \ + gzip -9 >$(bindoc)/changelog.Debian.old.gz + chmod 644 $(bindoc)/changelog.Debian.old.gz +endif + +ifneq ($(skipsub),true) + for sub in $($(*)_sub); do \ + if ! (TO=$$sub FROM=$* ABI_RELEASE=$(abi_release) $(SHELL) \ + $(DROOT)/scripts/sub-flavour); then exit 1; fi; \ + /sbin/depmod -b debian/$(bin_pkg_name)-$$sub \ + -ea -F debian/$(bin_pkg_name)-$$sub/boot/System.map-$(abi_release)-$* \ + $(abi_release)-$*; \ + install -d debian/$(bin_pkg_name)-$$sub/DEBIAN; \ + for script in postinst postrm preinst prerm; do \ + sed -e 's/=V/$(abi_release)-$*/g' \ + -e 's/=K/$(install_file)/g' \ + -e 's/=L/$(loader)/g' \ + -e 's@=B@$(build_arch)@g' \ + $(DROOT)/control-scripts/$$script > \ + debian/$(bin_pkg_name)-$$sub/DEBIAN/$$script;\ + chmod 755 debian/$(bin_pkg_name)-$$sub/DEBIAN/$$script;\ + done; \ + done +endif + +ifneq ($(skipdbg),true) + # Debug image is simple + install -m644 -D $(builddir)/build-$*/vmlinux \ + $(dbgpkgdir)/usr/lib/debug/boot/vmlinux-$(abi_release)-$* + $(build_cd) $(kmake) $(build_O) modules_install \ + INSTALL_MOD_PATH=$(dbgpkgdir)/usr/lib/debug + rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/build + rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/source + rm -f $(dbgpkgdir)/usr/lib/debug/lib/modules/$(abi_release)-$*/modules.* + rm -fr $(dbgpkgdir)/usr/lib/debug/lib/firmware +endif + + # The flavour specific headers image + # TODO: Would be nice if we didn't have to dupe the original builddir + install -d -m755 $(hdrdir) + cat $(builddir)/build-$*/.config | \ + sed -e 's/.*CONFIG_DEBUG_INFO=.*/# CONFIG_DEBUG_INFO is not set/g' > \ + $(hdrdir)/.config + chmod 644 $(hdrdir)/.config + $(kmake) O=$(hdrdir) silentoldconfig prepare scripts + # We'll symlink this stuff + rm -f $(hdrdir)/Makefile + rm -rf $(hdrdir)/include2 + # powerpc seems to need some .o files for external module linking. Add them in. +ifeq ($(arch),powerpc) + mkdir -p $(hdrdir)/arch/powerpc/lib + cp $(builddir)/build-$*/arch/powerpc/lib/*.o $(hdrdir)/arch/powerpc/lib +endif + # Script to symlink everything up + $(SHELL) $(DROOT)/scripts/link-headers "$(hdrdir)" "$(basepkg)" "$*" + # Setup the proper asm symlink + rm -f $(hdrdir)/include/asm + ln -s asm-$(asm_link) $(hdrdir)/include/asm + # The build symlink + install -d debian/$(basepkg)-$*/lib/modules/$(abi_release)-$* + ln -s /usr/src/$(basepkg)-$* \ + debian/$(basepkg)-$*/lib/modules/$(abi_release)-$*/build + # And finally the symvers + install -m644 $(builddir)/build-$*/Module.symvers \ + $(hdrdir)/Module.symvers + + # Now the header scripts + install -d $(CURDIR)/debian/$(basepkg)-$*/DEBIAN + for script in postinst; do \ + sed -e 's/=V/$(abi_release)-$*/g' -e 's/=K/$(install_file)/g' \ + $(DROOT)/control-scripts/headers-$$script > \ + $(CURDIR)/debian/$(basepkg)-$*/DEBIAN/$$script; \ + chmod 755 $(CURDIR)/debian/$(basepkg)-$*/DEBIAN/$$script; \ + done + + # At the end of the package prep, call the tests + DPKG_ARCH="$(arch)" KERN_ARCH="$(build_arch)" FLAVOUR="$*" \ + VERSION="$(abi_release)" REVISION="$(revision)" \ + PREV_REVISION="$(prev_revision)" ABI_NUM="$(abinum)" \ + PREV_ABI_NUM="$(prev_abinum)" BUILD_DIR="$(builddir)/build-$*" \ + INSTALL_DIR="$(pkgdir)" SOURCE_DIR="$(CURDIR)" \ + run-parts -v $(DROOT)/tests + + # + # Remove files which are generated at installation by postinst, + # except for modules.order and modules.builtin + # + # NOTE: need to keep this list in sync with postrm + # + mkdir $(pkgdir)/lib/modules/$(abi_release)-$*/_ + mv $(pkgdir)/lib/modules/$(abi_release)-$*/modules.order \ + $(pkgdir)/lib/modules/$(abi_release)-$*/_ + if [ -f $(pkgdir)/lib/modules/$(abi_release)-$*/modules.builtin ] ; then \ + mv $(pkgdir)/lib/modules/$(abi_release)-$*/modules.builtin \ + $(pkgdir)/lib/modules/$(abi_release)-$*/_; \ + fi + rm -f $(pkgdir)/lib/modules/$(abi_release)-$*/modules.* + mv $(pkgdir)/lib/modules/$(abi_release)-$*/_/* \ + $(pkgdir)/lib/modules/$(abi_release)-$* + rmdir $(pkgdir)/lib/modules/$(abi_release)-$*/_ + +headers_tmp := $(CURDIR)/debian/tmp-headers +headers_dir := $(CURDIR)/debian/linux-libc-dev + +hmake := $(MAKE) -C $(CURDIR) O=$(headers_tmp) SUBLEVEL=$(SUBLEVEL) \ + EXTRAVERSION=-$(abinum) INSTALL_HDR_PATH=$(headers_tmp)/install \ + SHELL="$(SHELL)" ARCH=$(header_arch) + +install-arch-headers: + dh_testdir + dh_testroot + dh_clean -k -plinux-libc-dev + + rm -rf $(headers_tmp) + install -d $(headers_tmp) $(headers_dir)/usr/include/ + + $(hmake) $(defconfig) + mv $(headers_tmp)/.config $(headers_tmp)/.config.old + sed -e 's/^# \(CONFIG_MODVERSIONS\) is not set$$/\1=y/' \ + -e 's/.*CONFIG_LOCALVERSION_AUTO.*/# CONFIG_LOCALVERSION_AUTO is not set/' \ + $(headers_tmp)/.config.old > $(headers_tmp)/.config + $(hmake) silentoldconfig + $(hmake) headers_install + + ( cd $(headers_tmp)/install/include/ && \ + find . -name '.' -o -name '.*' -prune -o -print | \ + cpio -pvd --preserve-modification-time \ + $(headers_dir)/usr/include/ ) + + rm -rf $(headers_tmp) + +binary-arch-headers: install-arch-headers + dh_testdir + dh_testroot +ifeq ($(do_libc_dev_package),true) +ifneq ($(DEBIAN),debian.master) + echo "non-master branch building linux-libc-dev, aborting" + exit 1 +endif + dh_installchangelogs -plinux-libc-dev + dh_installdocs -plinux-libc-dev + dh_compress -plinux-libc-dev + dh_fixperms -plinux-libc-dev + dh_installdeb -plinux-libc-dev + dh_gencontrol -plinux-libc-dev -- $(libc_dev_version) + dh_md5sums -plinux-libc-dev + dh_builddeb -plinux-libc-dev +endif + +binary-%: pkgimg = $(bin_pkg_name)-$* +binary-%: pkghdr = $(hdrs_pkg_name)-$* +binary-%: dbgpkg = $(bin_pkg_name)-$*-dbgsym +binary-%: dbgpkgdir = $(CURDIR)/debian/$(bin_pkg_name)-$*-dbgsym +binary-%: install-% + dh_testdir + dh_testroot + + dh_installchangelogs -p$(pkgimg) + dh_installdocs -p$(pkgimg) + dh_compress -p$(pkgimg) + dh_fixperms -p$(pkgimg) + dh_installdeb -p$(pkgimg) + dh_shlibdeps -p$(pkgimg) + dh_gencontrol -p$(pkgimg) + dh_md5sums -p$(pkgimg) + dh_builddeb -p$(pkgimg) -- -Zbzip2 -z9 + + dh_installchangelogs -p$(pkghdr) + dh_installdocs -p$(pkghdr) + dh_compress -p$(pkghdr) + dh_fixperms -p$(pkghdr) + dh_shlibdeps -p$(pkghdr) + dh_installdeb -p$(pkghdr) + dh_gencontrol -p$(pkghdr) + dh_md5sums -p$(pkghdr) + dh_builddeb -p$(pkghdr) + +ifneq ($(skipsub),true) + @set -e; for sub in $($(*)_sub); do \ + pkg=$(bin_pkg_name)-$$sub; \ + dh_installchangelogs -p$$pkg; \ + dh_installdocs -p$$pkg; \ + dh_compress -p$$pkg; \ + dh_fixperms -p$$pkg; \ + dh_shlibdeps -p$$pkg; \ + dh_installdeb -p$$pkg; \ + dh_gencontrol -p$$pkg; \ + dh_md5sums -p$$pkg; \ + dh_builddeb -p$$pkg; \ + done +endif + +ifneq ($(skipdbg),true) + dh_installchangelogs -p$(dbgpkg) + dh_installdocs -p$(dbgpkg) + dh_compress -p$(dbgpkg) + dh_fixperms -p$(dbgpkg) + dh_installdeb -p$(dbgpkg) + dh_gencontrol -p$(dbgpkg) + dh_md5sums -p$(dbgpkg) + dh_builddeb -p$(dbgpkg) + + # Hokay...here's where we do a little twiddling... + # Renaming the debug package prevents it from getting into + # the primary archive, and therefore prevents this very large + # package from being mirrored. It is instead, through some + # archive admin hackery, copied to http://ddebs.ubuntu.com. + # + mv ../$(dbgpkg)_$(release)-$(revision)_$(arch).deb \ + ../$(dbgpkg)_$(release)-$(revision)_$(arch).ddeb + set -e; \ + if grep -qs '^Build-Debug-Symbols: yes$$' /CurrentlyBuilding; then \ + sed -i '/^$(dbgpkg)_/s/\.deb /.ddeb /' debian/files; \ + else \ + grep -v '^$(dbgpkg)_.*$$' debian/files > debian/files.new; \ + mv debian/files.new debian/files; \ + fi + # Now, the package wont get into the archive, but it will get put + # into the debug system. +endif +ifneq ($(full_build),false) + # Clean out this flavours build directory. + rm -rf $(builddir)/build-$* + # Clean out the debugging package source directory. + rm -rf $(dbgpkgdir) +endif + +$(stampdir)/stamp-flavours: + @echo $(flavours) > $@ + +# +# per-architecture packages +# +$(stampdir)/stamp-prepare-perarch: + @echo "Preparing perarch ..." +ifeq ($(do_tools),true) + rm -rf $(builddir)/tools-$* + install -d $(builddir)/tools-$* + for i in *; do ln -s $(CURDIR)/$$i $(builddir)/tools-$*/; done + rm $(builddir)/tools-$*/tools + rsync -a tools/ $(builddir)/tools-$*/tools/ +endif + touch $@ + +$(stampdir)/stamp-build-perarch: prepare-perarch +ifeq ($(do_tools),true) + cd $(builddir)/tools-$*/tools/perf && make $(CROSS_COMPILE) +endif + @touch $@ + +install-perarch: toolspkgdir = $(CURDIR)/debian/$(tools_pkg_name) +install-perarch: $(stampdir)/stamp-build-perarch + # Add the tools. +ifeq ($(do_tools),true) + install -d $(toolspkgdir)/usr/bin + install -s -m755 $(builddir)/tools-$*/tools/perf/perf \ + $(toolspkgdir)/usr/bin/perf_$(abi_release) +endif + +binary-perarch: toolspkg = $(tools_pkg_name) +binary-perarch: install-perarch + @# Empty for make to be happy +ifeq ($(do_tools),true) + dh_installchangelogs -p$(toolspkg) + dh_installdocs -p$(toolspkg) + dh_compress -p$(toolspkg) + dh_fixperms -p$(toolspkg) + dh_shlibdeps -p$(toolspkg) + dh_installdeb -p$(toolspkg) + dh_gencontrol -p$(toolspkg) + dh_md5sums -p$(toolspkg) + dh_builddeb -p$(toolspkg) +endif + +binary-debs: binary-perarch $(stampdir)/stamp-flavours $(addprefix binary-,$(flavours)) + +build-arch-deps-$(do_flavour_image_package) += $(addprefix build-,$(flavours)) +build-arch: $(build-arch-deps-true) + +binary-arch-deps-$(do_flavour_image_package) = binary-debs +binary-arch-deps-$(do_libc_dev_package) += binary-arch-headers +ifneq ($(do_common_headers_indep),true) +binary-arch-deps-$(do_flavour_header_package) += binary-headers +endif +binary-arch: $(binary-arch-deps-true) --- linux-2.6.37.orig/debian/rules.d/3-binary-indep.mk +++ linux-2.6.37/debian/rules.d/3-binary-indep.mk @@ -0,0 +1,125 @@ +build-indep: + +docpkg = $(doc_pkg_name) +docdir = $(CURDIR)/debian/$(docpkg)/usr/share/doc/$(docpkg) +install-doc: + dh_testdir + dh_testroot + dh_clean -k -p$(docpkg) + + install -d $(docdir) +ifeq ($(do_doc_package_content),true) + # First the html docs. We skip these for autobuilds +endif + # Copy the rest + cp -a Documentation/* $(docdir) + rm -rf $(docdir)/DocBook + find $(docdir) -name .gitignore | xargs rm -f + +indep_hdrpkg = $(hdrs_pkg_name) +indep_hdrdir = $(CURDIR)/debian/$(indep_hdrpkg)/usr/src/$(indep_hdrpkg) +install-headers: + dh_testdir + dh_testroot + dh_clean -k -p$(indep_hdrpkg) + + install -d $(indep_hdrdir) + find . -path './debian' -prune -o -path './$(DEBIAN)' -prune \ + -o -path './include/*' -prune \ + -o -path './scripts/*' -prune -o -type f \ + \( -name 'Makefile*' -o -name 'Kconfig*' -o -name 'Kbuild*' -o \ + -name '*.sh' -o -name '*.pl' -o -name '*.lds' \) \ + -print | cpio -pd --preserve-modification-time $(indep_hdrdir) + cp -a drivers/media/dvb/dvb-core/*.h $(indep_hdrdir)/drivers/media/dvb/dvb-core + cp -a drivers/media/video/*.h $(indep_hdrdir)/drivers/media/video + cp -a drivers/media/dvb/frontends/*.h $(indep_hdrdir)/drivers/media/dvb/frontends + cp -a scripts include $(indep_hdrdir) + (find arch -name include -type d -print | \ + xargs -n1 -i: find : -type f) | \ + cpio -pd --preserve-modification-time $(indep_hdrdir) + +srcpkg = $(src_pkg_name)-source-$(release) +srcdir = $(CURDIR)/debian/$(srcpkg)/usr/src/$(srcpkg) +balldir = $(CURDIR)/debian/$(srcpkg)/usr/src/$(srcpkg)/$(srcpkg) +install-source: + dh_testdir + dh_testroot + dh_clean -k -p$(srcpkg) + + install -d $(srcdir) +ifeq ($(do_source_package_content),true) + find . -path './debian' -prune -o -path './$(DEBIAN)' -prune -o \ + -path './.*' -prune -o -print | \ + cpio -pd --preserve-modification-time $(balldir) + (cd $(srcdir); tar cf - $(srcpkg)) | bzip2 -9c > \ + $(srcdir)/$(srcpkg).tar.bz2 + rm -rf $(balldir) + find './debian' './$(DEBIAN)' \ + -path './debian/linux-*' -prune -o \ + -path './debian/$(src_pkg_name)-*' -prune -o \ + -path './debian/build' -prune -o \ + -path './debian/files' -prune -o \ + -path './debian/stamps' -prune -o \ + -path './debian/tmp' -prune -o \ + -print | \ + cpio -pd --preserve-modification-time $(srcdir) + ln -s $(srcpkg)/$(srcpkg).tar.bz2 $(srcdir)/.. +endif + +install-tools: toolspkg = $(tools_common_pkg_name) +install-tools: toolsbin = $(CURDIR)/debian/$(toolspkg)/usr/bin +install-tools: toolsman = $(CURDIR)/debian/$(toolspkg)/usr/share/man +install-tools: + dh_testdir + dh_testroot + dh_clean -k -p$(toolspkg) + + install -d $(toolsbin) + install -d $(toolsman)/man1 + + install -m755 debian/tools/perf $(toolsbin)/perf + + rm -rf $(builddir)/tools + install -d $(builddir)/tools + for i in *; do ln -s $(CURDIR)/$$i $(builddir)/tools/; done + rm $(builddir)/tools/tools + rsync -a tools/ $(builddir)/tools/tools/ + + cd $(builddir)/tools/tools/perf && make man + install -m644 $(builddir)/tools/tools/perf/Documentation/*.1 \ + $(toolsman)/man1 + +ifeq ($(do_common_headers_indep),true) +install-indep-deps-$(do_flavour_header_package) += install-headers +endif +install-indep-deps-$(do_doc_package) += install-doc +install-indep-deps-$(do_source_package) += install-source +install-indep-deps-$(do_tools) += install-tools +install-indep: $(install-indep-deps-true) + +# This is just to make it easy to call manually. Normally done in +# binary-indep target during builds. +binary-headers: install-headers + dh_testdir + dh_testroot + dh_installchangelogs -p$(indep_hdrpkg) + dh_installdocs -p$(indep_hdrpkg) + dh_compress -p$(indep_hdrpkg) + dh_fixperms -p$(indep_hdrpkg) + dh_installdeb -p$(indep_hdrpkg) + dh_gencontrol -p$(indep_hdrpkg) + dh_md5sums -p$(indep_hdrpkg) + dh_builddeb -p$(indep_hdrpkg) + +binary-indep: install-indep + dh_testdir + dh_testroot + + dh_installchangelogs -i + dh_installdocs -i + dh_compress -i + dh_fixperms -i + dh_installdeb -i + dh_gencontrol -i + dh_md5sums -i + dh_builddeb -i --- linux-2.6.37.orig/debian/scripts/config-check +++ linux-2.6.37/debian/scripts/config-check @@ -0,0 +1,389 @@ +#!/usr/bin/perl +# +# check-config -- check the current config for issues +# +use strict; + +my $P = 'check-config'; + +my $test = -1; +if ($ARGV[0] eq '--test') { + $test = $ARGV[1] + 0; +} elsif ($#ARGV != 4) { + die "Usage: $P \n"; +} + +my ($config, $arch, $flavour, $commonconfig, $warn_only) = @ARGV; + +my $checks = "$commonconfig/enforce"; +my %values = (); + +# If we are in overridden then still perform the checks and emit the messages +# but do not return failure. Those items marked FATAL will alway trigger +# failure. +my $fail_exit = 1; +$fail_exit = 0 if ($warn_only eq 'true' || $warn_only eq '1'); +my $exit_val = 0; + +# Predicate execution engine. +sub pred_first { + my ($rest) = @_; + my $depth = 0; + my $off; + my $char; + my $pred; + + for ($off = 0; $off <= length($rest); $off++) { + $char = substr($rest, $off, 1); + if ($char eq '(') { + $depth++; + } elsif ($char eq ')') { + $depth--; + } elsif ($depth == 0 && $char eq '&') { + last; + } elsif ($depth == 0 && $char eq '|') { + last; + } + } + if ($depth > 0) { + die "$P: $rest: missing close parenthesis ')'\n"; + } elsif ($depth < 0) { + die "$P: $rest: missing open parenthesis '('\n"; + } + + ($pred, $rest) = (substr($rest, 0, $off), substr($rest, $off + 1)); + + $pred =~ s/^\s*//; + $pred =~ s/\s*$//; + + #print "pred<$pred> rest<$rest> char<$char>\n"; + ($pred, $rest, $char); +} + +sub pred_do { + my ($pred) = @_; + my (@a) = split(' ', $pred); + + if ($a[0] eq 'arch') { + die "$P: $pred: malformed -- $pred \n" if ($#a != 1); + #print " *** ARCH<$arch ?? $a[1]>\n"; + return ($arch eq $a[1]) + } elsif ($a[0] eq 'flavour') { + die "$P: $pred: malformed -- $pred \n" if ($#a != 1); + #print " *** FLAVOUR<$flavour ?? $a[1]>\n"; + return ($flavour eq $a[1]) + } elsif ($a[0] eq 'value') { + die "$P: $pred: malformed -- $pred \n" if ($#a != 2); + #print " *** CHECK<$a[1] $a[2] ?? " . $values{$a[1]} . ">\n"; + return ($values{$a[1]} eq $a[2]); + } elsif ($a[0] eq 'exists') { + die "$P: $pred: malformed -- $pred \n" if ($#a != 1); + return (defined $values{$a[1]}); + } else { + die "$P: $pred: unknown predicate\n"; + } + return 1; +} +sub pred_exec { + my ($rest) = @_; + my $pred; + my $res; + my $sep; + + #print "pred_exec<$rest>\n"; + + ($pred, $rest, $sep) = pred_first($rest); + + # Leading ! implies inversion. + if ($pred =~ /^\s*!\s*(.*)$/) { + #print " invert<$1>\n"; + $res = !pred_exec($1); + + # Recurse left for complex expressions. + } elsif ($pred =~ /^\s*\((.*)\)\s*$/) { + #print " left<$1>\n"; + $res = pred_exec($1); + + # Check for common syntax issues. + } elsif ($pred eq '') { + if ($sep eq '&' || $sep eq '|') { + die "$P: $pred$rest: malformed binary operator\n"; + } else { + die "$P: $pred$rest: syntax error\n"; + } + + # A predicate, execute it. + } else { + #print " DO<$pred> sep<$sep>\n"; + $res = pred_do($pred); + } + + #print " pre-return res<$res> sep<$sep>\n"; + if ($sep eq '') { + # + + # Recurse right for binary operators -- note these are lazy. + } elsif ($sep eq '&' || $sep eq '|') { + #print " right<$rest> ? sep<$sep> res<$res>\n"; + if ($rest =~ /^\s*($|\||\&)/) { + die "$P: $pred$rest: malformed binary operator\n"; + } + if (($res && $sep eq '&') || (!$res && $sep eq '|')) { + #print " right<$rest>\n"; + $res = pred_exec($rest); + } + + } else { + die "$P: $pred$rest: malformed predicate\n"; + } + #print " return res<$res> sep<$sep>\n"; + return $res; +} + +# +# PREDICATE TESTS +# +my $test_total = 1; +my $test_good = 0; +sub pred_test { + my ($pred, $eres, $eerr) = @_; + my ($res, $err, $fail); + + $test_total++; + if ($test != 0 && $test != $test_total - 1) { + return; + } + + eval { + $res = pred_exec($pred); + }; + $err = $@; + chomp($err); + + $res = !!$res; + $eres = !!$eres; + + $fail = ''; + if (defined $eres && $res != $eres) { + $fail = "result missmatch, expected $eres returned $res"; + } + if (defined $eerr && $err eq '') { + $fail = "error missmatch, expected '$eerr' returned success"; + } elsif (defined $eerr && $err !~ /$eerr/) { + $fail = "error missmatch, expected '$eerr' returned '$err'"; + } elsif (!defined $eerr && $err ne '') { + $fail = "error missmatch, expected success returned '$err'"; + } + + if ($fail eq '') { + $test_good++; + } else { + print "$pred: $test_total: FAIL: $fail\n"; + } + #print "TEST<$pred> eres<$eres> eerr<$eerr> res<$res> err<$err>\n"; +} +if ($test >= 0) { + $arch = 'MYARCH'; + $flavour = 'MYFLAVOUR'; + %values = ( 'ENABLED' => 'y', 'DISABLED' => 'n' ); + + # Errors. + my $eunkn = 'unknown predicate'; + my $epred = 'malformed'; + my $eclose = 'missing close parenthesis'; + my $eopen = 'missing open parenthesis'; + my $ebinary = 'malformed binary operator'; + + # Basic predicate tests. + print "TEST: $test_total: basic predicate tests ...\n"; + + pred_test('nosuchcommand', undef, $eunkn); + pred_test('arch', undef, $epred); + pred_test('arch MYARCH MYARCH', undef, $epred); + pred_test('arch MYARCH', 1, undef); + pred_test('arch NOTMYARCH', 0, undef); + + pred_test('flavour', undef, $epred); + pred_test('flavour MYFLAVOUR myflavour', undef, $epred); + pred_test('flavour MYFLAVOUR', 1, undef); + pred_test('flavour NOTMYFLAVOUR', 0, undef); + + pred_test('value', undef, $epred); + pred_test('value ENABLED', undef, $epred); + pred_test('value ENABLED ENABLED ENABLED', undef, $epred); + pred_test('value ENABLED y', 1, undef); + pred_test('value ENABLED n', 0, undef); + pred_test('value DISABLED n', 1, undef); + pred_test('value DISABLED y', 0, undef); + + pred_test('exists', undef, $epred); + pred_test('exists ENABLED ENABLED', undef, $epred); + pred_test('exists ENABLED', 1, undef); + pred_test('exists DISABLED', 1, undef); + pred_test('exists MISSING', 0, undef); + + print "TEST: $test_total: inversion tests ...\n"; + pred_test('!exists ENABLED', 0, undef); + pred_test('!exists MISSING', 1, undef); + pred_test('!!exists ENABLED', 1, undef); + pred_test('!!exists MISSING', 0, undef); + pred_test('!!!exists ENABLED', 0, undef); + pred_test('!!!exists MISSING', 1, undef); + + print "TEST: $test_total: parentheses tests ...\n"; + pred_test('(exists ENABLED)', 1, undef); + pred_test('((exists ENABLED))', 1, undef); + pred_test('(((exists ENABLED)))', 1, undef); + pred_test('(exists MISSING)', 0, undef); + pred_test('((exists MISSING))', 0, undef); + pred_test('(((exists MISSING)))', 0, undef); + + pred_test('(!exists ENABLED)', 0, undef); + pred_test('((!exists ENABLED))', 0, undef); + pred_test('(((!exists ENABLED)))', 0, undef); + pred_test('(!exists MISSING)', 1, undef); + pred_test('((!exists MISSING))', 1, undef); + pred_test('(((!exists MISSING)))', 1, undef); + + pred_test('((!(exists ENABLED)))', 0, undef); + pred_test('((!(exists MISSING)))', 1, undef); + pred_test('(!((exists ENABLED)))', 0, undef); + pred_test('(!((exists MISSING)))', 1, undef); + pred_test('!(((exists ENABLED)))', 0, undef); + pred_test('!(((exists MISSING)))', 1, undef); + pred_test('!((!(exists ENABLED)))', 1, undef); + pred_test('!((!(exists MISSING)))', 0, undef); + pred_test('!(!(!(exists ENABLED)))', 0, undef); + pred_test('!(!(!(exists MISSING)))', 1, undef); + + pred_test('(', undef, $eclose); + pred_test('()(', undef, $eclose); + pred_test('(())(', undef, $eclose); + pred_test('((()))(', undef, $eclose); + pred_test('(()', undef, $eclose); + pred_test('((())', undef, $eclose); + pred_test('(((()))', undef, $eclose); + pred_test('(()()', undef, $eclose); + pred_test('((())()', undef, $eclose); + + pred_test(')', undef, $eopen); + pred_test('())', undef, $eopen); + pred_test('(()))', undef, $eopen); + pred_test('((())))', undef, $eopen); + + print "TEST: $test_total: binary and tests ...\n"; + + pred_test('exists ENABLED &', undef, $ebinary); + pred_test('& exists ENABLED', undef, $ebinary); + pred_test('exists ENABLED & & exists ENABLED', undef, $ebinary); + + pred_test('exists MISSING & exists MISSING', 0, undef); + pred_test('exists MISSING & exists ENABLED', 0, undef); + pred_test('exists ENABLED & exists MISSING', 0, undef); + pred_test('exists ENABLED & exists ENABLED', 1, undef); + + pred_test('exists MISSING & exists MISSING & exists MISSING', 0, undef); + pred_test('exists MISSING & exists MISSING & exists ENABLED', 0, undef); + pred_test('exists MISSING & exists ENABLED & exists MISSING', 0, undef); + pred_test('exists MISSING & exists ENABLED & exists ENABLED', 0, undef); + pred_test('exists ENABLED & exists MISSING & exists MISSING', 0, undef); + pred_test('exists ENABLED & exists MISSING & exists ENABLED', 0, undef); + pred_test('exists ENABLED & exists ENABLED & exists MISSING', 0, undef); + pred_test('exists ENABLED & exists ENABLED & exists ENABLED', 1, undef); + + print "TEST: $test_total: binary or tests ...\n"; + + pred_test('exists ENABLED |', undef, $ebinary); + pred_test('| exists ENABLED', undef, $ebinary); + pred_test('exists ENABLED | | exists ENABLED', undef, $ebinary); + + pred_test('exists MISSING | exists MISSING', 0, undef); + pred_test('exists MISSING | exists ENABLED', 1, undef); + pred_test('exists ENABLED | exists MISSING', 1, undef); + pred_test('exists ENABLED | exists ENABLED', 1, undef); + + pred_test('exists MISSING | exists MISSING | exists MISSING', 0, undef); + pred_test('exists MISSING | exists MISSING | exists ENABLED', 1, undef); + pred_test('exists MISSING | exists ENABLED | exists MISSING', 1, undef); + pred_test('exists MISSING | exists ENABLED | exists ENABLED', 1, undef); + pred_test('exists ENABLED | exists MISSING | exists MISSING', 1, undef); + pred_test('exists ENABLED | exists MISSING | exists ENABLED', 1, undef); + pred_test('exists ENABLED | exists ENABLED | exists MISSING', 1, undef); + pred_test('exists ENABLED | exists ENABLED | exists ENABLED', 1, undef); + + print "TEST: $test_total: binary or/and combination tests ...\n"; + + pred_test('exists MISSING | exists MISSING & exists MISSING', 0, undef); + pred_test('exists MISSING | exists MISSING & exists ENABLED', 0, undef); + pred_test('exists MISSING | exists ENABLED & exists MISSING', 0, undef); + pred_test('exists MISSING | exists ENABLED & exists ENABLED', 1, undef); + pred_test('exists ENABLED | exists MISSING & exists MISSING', 1, undef); + pred_test('exists ENABLED | exists MISSING & exists ENABLED', 1, undef); + pred_test('exists ENABLED | exists ENABLED & exists MISSING', 1, undef); + pred_test('exists ENABLED | exists ENABLED & exists ENABLED', 1, undef); + + print "TEST: $test_total: binary and/or combination tests ...\n"; + + pred_test('exists MISSING & exists MISSING | exists MISSING', 0, undef); + pred_test('exists MISSING & exists MISSING | exists ENABLED', 0, undef); + pred_test('exists MISSING & exists ENABLED | exists MISSING', 0, undef); + pred_test('exists MISSING & exists ENABLED | exists ENABLED', 0, undef); + pred_test('exists ENABLED & exists MISSING | exists MISSING', 0, undef); + pred_test('exists ENABLED & exists MISSING | exists ENABLED', 1, undef); + pred_test('exists ENABLED & exists ENABLED | exists MISSING', 1, undef); + pred_test('exists ENABLED & exists ENABLED | exists ENABLED', 1, undef); + + $test_total--; + print "TEST: $test_good/$test_total succeeded\n"; + + exit $exit_val; +} + +# Load up the current configuration values -- FATAL if this fails +print "$P: $config: loading config\n"; +open(CONFIG, "<$config") || die "$P: $config: open failed -- $! -- aborting\n"; +while () { + # Pull out values. + /^#*\s*(CONFIG_\w+)[\s=](.*)$/ or next; + if ($2 eq 'is not set') { + $values{$1} = 'n'; + } else { + $values{$1} = $2; + } +} +close(CONFIG); + +# FATAL: Check if we have an enforcement list. +my $pass = 0; +my $total = 0; +my $line = ''; +print "$P: $checks: loading checks\n"; +open(CHECKS, "<$checks") || die "$P: $checks: open failed -- $! -- aborting\n"; +while () { + /^#/ && next; + chomp; + + $line .= $_; + if ($line =~ /\\$/) { + chop($line); + $line .= " "; + next; + } + $line =~ /^\s*$/ && next; + + #print "CHECK: <$line>\n"; + $total++; + my $result = pred_exec($line); + if (!$result) { + print "$P: FAIL: $line\n"; + $exit_val = $fail_exit; + } else { + $pass++; + } + + $line = ''; +} +close(CHECKS); + +print "$P: $pass/$total checks passed -- exit $exit_val\n"; +exit $exit_val; --- linux-2.6.37.orig/debian/scripts/control-create +++ linux-2.6.37/debian/scripts/control-create @@ -0,0 +1,25 @@ +#!/bin/bash + +. debian/debian.env + +vars=$1 + +. $vars + +if [ "$is_sub" = "" ]; then + flavour=$(basename $vars | sed 's/.*\.//') + stub=${DEBIAN}/control.d/flavour-control.stub +else + flavour=$(basename $vars .vars) + stub=${DEBIAN}/sub-flavours/control.stub +fi + +cat $stub | grep -v '^#' | sed \ + -e "s#FLAVOUR#$flavour#g" \ + -e "s#DESC#$desc#g" \ + -e "s#ARCH#$arch#g" \ + -e "s#SUPPORTED#$supported#g" \ + -e "s#TARGET#$target#g" \ + -e "s#BOOTLOADER#$bootloader#g" \ + -e "s#=PROVIDES=#$provides#g" \ + -e "s#=CONFLICTS=#$conflicts#g" --- linux-2.6.37.orig/debian/scripts/link-headers +++ linux-2.6.37/debian/scripts/link-headers @@ -0,0 +1,42 @@ +#!/bin/bash -e + +. debian/debian.env + +hdrdir="$1" +symdir="$2" +flavour="$3" + +echo "Symlinking and copying headers for $flavour..." + +excludes="( -path ./debian -prune -o -path ./${DEBIAN} -prune -o -path ./.git ) -prune -o" + +( +find . $excludes -type f \ + \( -name 'Makefile*' -o -name 'Kconfig*' -o -name 'Kbuild*' -o \ + -name '*.sh' -o -name '*.pl' -o -name '*.lds' \) -print +find ./include ./scripts -name .gitignore -prune -o -type f -print +find ./include -mindepth 1 -maxdepth 1 $excludes -type d -print +) | ( +while read file; do + dir=$file + lastdir=$file + + if [ -e "$hdrdir/$file" -o -L "$hdrdir/$file" ]; then + continue + fi + + while [ ! -e "$hdrdir/$dir" -a ! -L "$hdrdir/$dir" ]; do + lastdir=$dir + dir=`dirname $dir` + done + # If the last item to exist is a symlink we assume all is good + if [ ! -L "$hdrdir/$dir" ]; then + # Turns things like "./foo" into "../" + deref="`echo -n $lastdir | sed -e 's/^\.//' -e's,/[^/]*,../,g'`" + item="`echo -n $lastdir | sed -e 's/^\.\///'`" + ln -s $deref$symdir/$item $hdrdir/$item + fi +done +) + +exit --- linux-2.6.37.orig/debian/scripts/module-inclusion +++ linux-2.6.37/debian/scripts/module-inclusion @@ -0,0 +1,51 @@ +#!/bin/bash + +# +# Build a new directory of modules based on an inclusion list. +# The includsion list format must be a bash regular expression. +# +# usage: $0 ROOT INCLUSION_LIST +# example: $0 debian/build/build-virtual debian.master/control.d/virtual.inclusion-list +ROOT=$1 +ILIST=$2 + +NROOT=${ROOT}.new + +# +# Prep a destination directory. +# +mkdir -p ${NROOT} +rsync -a --exclude="*.ko" ${ROOT}/ ${NROOT} + +cat ${ILIST} |while read i +do + # + # 'find' blurts a warning if it cannot find any ko files. + # + if echo "$i" | grep '\*' > /dev/null + then + (cd ${ROOT}; eval find "${i}" -name "*.ko") |while read f + do + mkdir -p ${NROOT}/`dirname $f` + cp ${ROOT}/$f ${NROOT}/$f + done + else + if [ -f "${ROOT}/$i" ] + then + mkdir -p ${NROOT}/`dirname $i` + cp ${ROOT}/$i ${NROOT}/$i + else + echo Warning: Could not find ${ROOT}/$i + fi + fi + +done + +# +# Cleanup +# +rm -rf ${ROOT} +mv ${NROOT} ${ROOT} + +exit 0 + --- linux-2.6.37.orig/debian/scripts/sub-flavour +++ linux-2.6.37/debian/scripts/sub-flavour @@ -0,0 +1,67 @@ +#!/bin/bash + +. debian/debian.env + +echo "SUB_PROCESS $FROM => $TO" + +export from_pkg="linux-image-$ABI_RELEASE-$FROM" +export to_pkg="linux-image-$ABI_RELEASE-$TO" + +from_moddir="debian/$from_pkg/lib/modules/$ABI_RELEASE-$FROM" +to_moddir="debian/$to_pkg/lib/modules/$ABI_RELEASE-$FROM" + +install -d "debian/$to_pkg/boot" +install -m644 debian/$from_pkg/boot/{vmlinuz,System.map,config}-$ABI_RELEASE-$FROM \ + debian/$to_pkg/boot/ + +# +# Print some warnings if there are files in the sub-flavours list +# that do not actually exist. +# +cat ${DEBIAN}/sub-flavours/$TO.list | while read line +do +( + cd debian/$from_pkg/lib/modules/$ABI_RELEASE-$FROM/kernel; + # + # If its a wildcard, then check that there are files that match. + # + if echo "$line" | grep '\*' > /dev/null + then + if [ `eval find "$line" -name '*.ko' 2>/dev/null|wc -l` -lt 1 ] + then + echo SUB_INST Warning - No files in $line + fi + # + # Else it should be a single file reference. + # + elif [ ! -f "$line" ] + then + echo SUB_INST Warning - could not find "$line" + fi +) +done + +cat ${DEBIAN}/sub-flavours/$TO.list | while read line; do + ( + cd debian/$from_pkg/lib/modules/$ABI_RELEASE-$FROM/kernel; + if echo "$line" | grep '\*' > /dev/null + then + eval find "$line" -name '*.ko' 2>/dev/null || true + elif [ -f "$line" ] + then + echo "$line" + fi + ); +done | while read mod; do + echo "SUB_INST checking: $mod" + fromdir="/lib/modules/$ABI_RELEASE-$FROM/" + egrep "^($fromdir)?kernel/$mod:" \ + $from_moddir/modules.dep | sed -e "s|^$fromdir||" -e 's/://' -e 's/ /\n/g' | \ + while read m; do + m="${fromdir}$m" + test -f debian/$to_pkg/$m && continue + echo "SUB_INST installing: $m" + install -D -m644 debian/$from_pkg/$m \ + debian/$to_pkg/$m + done +done --- linux-2.6.37.orig/debian/scripts/abi-check +++ linux-2.6.37/debian/scripts/abi-check @@ -0,0 +1,212 @@ +#!/usr/bin/perl -w + +my $flavour = shift; +my $prev_abinum = shift; +my $abinum = shift; +my $prev_abidir = shift; +my $abidir = shift; +my $skipabi = shift; + +my $fail_exit = 1; +my $EE = "EE:"; +my $errors = 0; +my $abiskip = 0; + +my $count; + +exit(0); + +print "II: Checking ABI for $flavour...\n"; + +if (-f "$prev_abidir/ignore" + or -f "$prev_abidir/$flavour.ignore" or "$skipabi" eq "true") { + print "WW: Explicitly asked to ignore ABI, running in no-fail mode\n"; + $fail_exit = 0; + $abiskip = 1; + $EE = "WW:"; +} + +if ($prev_abinum != $abinum) { + print "II: Different ABI's, running in no-fail mode\n"; + $fail_exit = 0; + $EE = "WW:"; +} + +if (not -f "$abidir/$flavour" or not -f "$prev_abidir/$flavour") { + print "EE: Previous or current ABI file missing!\n"; + print " $abidir/$flavour\n" if not -f "$abidir/$flavour"; + print " $prev_abidir/$flavour\n" if not -f "$prev_abidir/$flavour"; + + # Exit if the ABI files are missing, but return status based on whether + # skip ABI was indicated. + if ("$abiskip" eq "1") { + exit(0); + } else { + exit(1); + } +} + +my %symbols; +my %symbols_ignore; +my %modules_ignore; +my %module_syms; + +# See if we have any ignores +my $ignore = 0; +print " Reading symbols/modules to ignore..."; + +for $file ("$prev_abidir/../blacklist", "$prev_abidir/../../perm-blacklist") { + if (-f $file) { + open(IGNORE, "< $file") or + die "Could not open $file"; + while () { + chomp; + if ($_ =~ m/M: (.*)/) { + $modules_ignore{$1} = 1; + } else { + $symbols_ignore{$_} = 1; + } + $ignore++; + } + close(IGNORE); + } +} +print "read $ignore symbols/modules.\n"; + +sub is_ignored($$) { + my ($mod, $sym) = @_; + + die "Missing module name in is_ignored()" if not defined($mod); + die "Missing symbol name in is_ignored()" if not defined($sym); + + if (defined($symbols_ignore{$sym}) or defined($modules_ignore{$mod})) { + return 1; + } + return 0; +} + +# Read new syms first +print " Reading new symbols ($abinum)..."; +$count = 0; +open(NEW, "< $abidir/$flavour") or + die "Could not open $abidir/$flavour"; +while () { + chomp; + m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/; + $symbols{$4}{'type'} = $1; + $symbols{$4}{'loc'} = $2; + $symbols{$4}{'hash'} = $3; + $module_syms{$2} = 0; + $count++; +} +close(NEW); +print "read $count symbols.\n"; + +# Now the old symbols, checking for missing ones +print " Reading old symbols ($prev_abinum)..."; +$count = 0; +open(OLD, "< $prev_abidir/$flavour") or + die "Could not open $prev_abidir/$flavour"; +while () { + chomp; + m/^(\S+)\s(.+)\s(0x[0-9a-f]+)\s(.+)$/; + $symbols{$4}{'old_type'} = $1; + $symbols{$4}{'old_loc'} = $2; + $symbols{$4}{'old_hash'} = $3; + $count++; +} +close(OLD); + +print "read $count symbols.\n"; + +print "II: Checking for missing symbols in new ABI..."; +$count = 0; +foreach $sym (keys(%symbols)) { + if (!defined($symbols{$sym}{'type'})) { + print "\n" if not $count; + printf(" MISS : %s%s\n", $sym, + is_ignored($symbols{$sym}{'old_loc'}, $sym) ? " (ignored)" : ""); + $count++ if !is_ignored($symbols{$sym}{'old_loc'}, $sym); + } +} +print " " if $count; +print "found $count missing symbols\n"; +if ($count) { + print "$EE Symbols gone missing (what did you do!?!)\n"; + $errors++; +} + + +print "II: Checking for new symbols in new ABI..."; +$count = 0; +foreach $sym (keys(%symbols)) { + if (!defined($symbols{$sym}{'old_type'})) { + print "\n" if not $count; + print " NEW : $sym\n"; + $count++; + } +} +print " " if $count; +print "found $count new symbols\n"; +if ($count and $prev_abinum == $abinum) { + print "WW: Found new symbols within same ABI. Not recommended\n"; +} + +print "II: Checking for changes to ABI...\n"; +$count = 0; +my $moved = 0; +my $changed_type = 0; +my $changed_hash = 0; +foreach $sym (keys(%symbols)) { + if (!defined($symbols{$sym}{'old_type'}) or + !defined($symbols{$sym}{'type'})) { + next; + } + + # Changes in location don't hurt us, but log it anyway + if ($symbols{$sym}{'loc'} ne $symbols{$sym}{'old_loc'}) { + printf(" MOVE : %-40s : %s => %s\n", $sym, $symbols{$sym}{'old_loc'}, + $symbols{$sym}{'loc'}); + $moved++; + } + + # Changes to export type are only bad if new type isn't + # EXPORT_SYMBOL. Changing things to GPL are bad. + if ($symbols{$sym}{'type'} ne $symbols{$sym}{'old_type'}) { + printf(" TYPE : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_type'}. + $symbols{$sym}{'type'}, is_ignored($symbols{$sym}{'loc'}, $sym) + ? " (ignored)" : ""); + $changed_type++ if $symbols{$sym}{'type'} ne "EXPORT_SYMBOL" + and !is_ignored($symbols{$sym}{'loc'}, $sym); + } + + # Changes to the hash are always bad + if ($symbols{$sym}{'hash'} ne $symbols{$sym}{'old_hash'}) { + printf(" HASH : %-40s : %s => %s%s\n", $sym, $symbols{$sym}{'old_hash'}, + $symbols{$sym}{'hash'}, is_ignored($symbols{$sym}{'loc'}, $sym) + ? " (ignored)" : ""); + $changed_hash++ if !is_ignored($symbols{$sym}{'loc'}, $sym); + $module_syms{$symbols{$sym}{'loc'}}++; + } +} + +print "WW: $moved symbols changed location\n" if $moved; +print "$EE $changed_type symbols changed export type and weren't ignored\n" if $changed_type; +print "$EE $changed_hash symbols changed hash and weren't ignored\n" if $changed_hash; + +$errors++ if $changed_hash or $changed_type; +if ($changed_hash) { + print "II: Module hash change summary...\n"; + foreach $mod (sort { $module_syms{$b} <=> $module_syms{$a} } keys %module_syms) { + next if ! $module_syms{$mod}; + printf(" %-40s: %d\n", $mod, $module_syms{$mod}); + } +} + +print "II: Done\n"; + +if ($errors) { + exit($fail_exit); +} else { + exit(0); +} --- linux-2.6.37.orig/debian/scripts/module-check +++ linux-2.6.37/debian/scripts/module-check @@ -0,0 +1,122 @@ +#!/usr/bin/perl -w + +$flavour = shift; +$prev_abidir = shift; +$abidir = shift; +$skipmodule = shift; + +exit(0); + +print "II: Checking modules for $flavour..."; + +if (-f "$prev_abidir/ignore.modules" + or -f "$prev_abidir/$flavour.ignore.modules") { + print "explicitly ignoring modules\n"; + exit(0); +} + +if (not -f "$abidir/$flavour.modules" or not -f + "$prev_abidir/$flavour.modules") { + print "previous or current modules file missing!\n"; + print " $abidir/$flavour.modules\n"; + print " $prev_abidir/$flavour.modules\n"; + if (defined($skipmodule)) { + exit(0); + } else { + exit(1); + } +} + +print "\n"; + +my %modules; +my %modules_ignore; +my $missing = 0; +my $new = 0; +my $errors = 0; + +# See if we have any ignores +if (-f "$prev_abidir/../modules.ignore") { + my $ignore = 0; + open(IGNORE, "< $prev_abidir/../modules.ignore") or + die "Could not open $prev_abidir/../modules.ignore"; + print " reading modules to ignore..."; + while () { + chomp; + next if /\s*#/; + $modules_ignore{$_} = 1; + $ignore++; + } + close(IGNORE); + print "read $ignore modules.\n"; +} + +# Read new modules first +print " reading new modules..."; +$new_count = 0; +open(NEW, "< $abidir/$flavour.modules") or + die "Could not open $abidir/$flavour.modules"; +while () { + chomp; + $modules{$_} = 1; + $new_count++; +} +close(NEW); +print "read $new_count modules.\n"; + +# Now the old modules, checking for missing ones +print " reading old modules..."; +$old_count = 0; +open(OLD, "< $prev_abidir/$flavour.modules") or + die "Could not open $prev_abidir/$flavour.modules"; +while () { + chomp; + if (not defined($modules{$_})) { + print "\n" if not $missing; + $missing++; + if (not defined($modules_ignore{$_})) { + print " MISS: $_\n"; + $errors++; + } else { + print " MISS: $_ (ignored)\n"; + } + } else { + $modules{$_}++; + } + $old_count++; +} +close(OLD); +# Check for new modules +foreach $mod (keys(%modules)) { + if ($modules{$mod} < 2) { + print "\n" if not $missing and not $new; + print " NEW : $mod\n"; + $new++; + } +} +if ($new or $missing) { + print " read $old_count modules : new($new) missing($missing)\n"; +} else { + print "read $old_count modules.\n"; +} + + +# Let's see where we stand... +if ($errors) { + if (defined($skipmodule)) { + print "WW: Explicitly asked to ignore failures (probably not good)\n"; + } else { + print "EE: Missing modules (start begging for mercy)\n"; + exit 1 + } +} + +if ($new) { + print "II: New modules (you've been busy, wipe the poop off your nose)\n"; +} else { + print "II: No new modules (hope you're happy, slacker)\n"; +} + +print "II: Done\n"; + +exit(0); --- linux-2.6.37.orig/debian/scripts/misc/getabis +++ linux-2.6.37/debian/scripts/misc/getabis @@ -0,0 +1,76 @@ +#!/bin/bash + +. debian/debian.env + +if [ "$#" != "2" ]; then + echo "Usage: $0 " 1>&2 + exit 1 +fi + +ver=$1 +revision=$2 +abi=$(echo $revision | awk -F. '{print $1}') + +verabi=$ver-$abi +verfull=$ver-$revision + +WGET="wget --quiet -c" + +abidir="`pwd`/$DEBIAN/abi/$verfull" +tmpdir="`pwd`/abi-tmp-$verfull" +origdir="`pwd`" + +test -d $tmpdir || mkdir $tmpdir + +getall() { + arch=$1 + shift + + mkdir -p $abidir/$arch + + for sub in $@; do + if [ -f $abidir/$arch/$sub ]; then + echo "Exists: $sub" + continue + fi + echo -n "Fetching $sub..." + filename=linux-image-${verabi}-${sub}_${verfull}_${arch}.deb + cd $tmpdir + for r in "${repo_list[@]}" + do + if ! [ -f $filename ]; then + $WGET $r/$filename + fi + done + if [ "$?" = "0" ]; then + echo -n "extracting..." + dpkg-deb --extract $filename tmp + if [ -f tmp/boot/abi-* ]; then + mv tmp/boot/abi-* $abidir/$arch/$sub + else + echo -n "NO ABI FILE..." + fi + (cd tmp; find lib/modules/$verabi-$sub/kernel -name '*.ko') | \ + sed -e 's/.*\/\([^\/]*\)\.ko/\1/' | sort > \ + $abidir/$arch/$sub.modules + rm -rf tmp $filename + echo "done." + else + echo "FAILED." + fi + cd $origdir + done +} + +# MAIN + +# Setup abi directory +mkdir -p $abidir +echo $abi > $abidir/abiname + +# NOTE: The flavours are hardcoded, because they may have changed from the +# current build. + +. $DEBIAN/etc/getabis + +rmdir $tmpdir --- linux-2.6.37.orig/debian/scripts/misc/git-ubuntu-log +++ linux-2.6.37/debian/scripts/misc/git-ubuntu-log @@ -0,0 +1,232 @@ +#!/usr/bin/perl -w + +use strict; +use Text::Wrap; + +my $kernel_auth = "Upstream Kernel Changes"; + +my (%map, @reverts); +my $pstate = 1; +my $no_kern_log = 0; +my $print_shas = 0; +my $first_print = 1; + +while (@ARGV) { + my $opt = $ARGV[0]; + shift; + if ($opt eq "--no-kern-log") { + $no_kern_log = 1; + } elsif ($opt eq "--print-shas") { + $print_shas = 1; + } else { + print STDERR "Unknown options: $opt\n"; + exit(1); + } +} + +sub check_reverts($) { + my ($entry) = @_; + my ($check); + + foreach $check (reverse @reverts) { + my $desc = "Revert \"" . $entry->{'desc'} . "\""; + if ($check->{'desc'} eq $desc) { + @reverts = grep($_->{'desc'} ne $desc, @reverts); + return 1; + } + } + + return 0; +} + +sub add_entry($) { + my ($entry) = @_; + my $key = $entry->{'author'}; + + # store description in array, in email->{desc list} map + if (exists $map{$key}) { + # grab ref + my $obj = $map{$key}; + + # add desc to array + push(@$obj, $entry); + } else { + # create new array, containing 1 item + my @arr = ($entry); + + # store ref to array + $map{$key} = \@arr; + } +} + +sub shortlog_entry($$$$$) { + my ($name, $desc, $bug, $cve, $commit) = @_; + my $entry; + + $desc =~ s#/pub/scm/linux/kernel/git/#/.../#g; + $desc =~ s#\[PATCH\] ##g; + + $desc =~ s#^\s*##g; + $desc =~ s# *UBUNTU: ##g; + + $entry->{'desc'} = $desc; + if ($bug ne '') { + $entry->{'bugno'} = $bug; + } + $entry->{'cve'} = $cve; + $entry->{'commit'} = $commit; + $entry->{'author'} = $name; + + if ($desc =~ /^Revert "/) { + push(@reverts, $entry); + return; + } + + return if check_reverts($entry); + + add_entry($entry); +} + +# sort comparison function +sub by_name($$) { + my ($a, $b) = @_; + + uc($a) cmp uc($b); +} + +sub shortlog_output { + my ($obj, $key, $entry); + + foreach $key (sort by_name keys %map) { + next if $key eq $kernel_auth and $no_kern_log; + + print "\n" unless $first_print; + $first_print = 0; + + # output author + printf " [ %s ]\n\n", $key; + + # output author's 1-line summaries + $obj = $map{$key}; + foreach $entry (reverse @$obj) { + print wrap(" * ", " ", $entry->{'desc'}) . "\n"; + # For non upstream changes, add other info. + if ($key ne $kernel_auth) { + if ($print_shas) { + print " - GIT-SHA " . $entry->{'commit'} . + "\n"; + } + } + if (defined($entry->{'bugno'})) { + print " - LP: #" . $entry->{'bugno'} . "\n"; + } + if (defined($entry->{'cve'})) { + print " - " . $entry->{'cve'} . "\n"; + } + } + } +} + +sub changelog_input { + my ($author, $desc, $commit, $entry, $cve); + + while () { + # get commit + if ($pstate == 1) { + next unless /^commit (.*)/; + + $commit = $1; + + $pstate++; + } + + # get author and email + elsif ($pstate == 2) { + my ($email); + + next unless /^[Aa]uthor:?\s*(.*?)\s*<(.*)>/; + + $author = $1; + $email = $2; + $desc = undef; + $cve = undef; + + # cset author fixups + if (!$author) { + $author = $email; + } + $pstate++; + } + + # skip to blank line + elsif ($pstate == 3) { + next unless /^\s*$/; + $pstate++; + } + + # skip to non-blank line + elsif ($pstate == 4) { + next unless /^\s*?(.*)/; + my $ignore = 0; + my $do_ignore = 0; + my $bug = undef; + my %bugz = (); + my $k; + + # skip lines that are obviously not + # a 1-line cset description + next if /^\s*From: /; + + chomp; + $desc = $1; + + if ($desc =~ /^ *(Revert "|)UBUNTU:/) { + $do_ignore = 1; + } else { + $do_ignore = 0; + $author = $kernel_auth; + $ignore = 1 if $desc =~ /Merge /; + } + while () { + $ignore = 1 if ($do_ignore && /^ *Ignore: yes/i); + if (/^ *Bug: *(#|)([0-9#,\s]*)\s*$/i) { + foreach $k (split('(,|\s)\s*(#|)', $2)) { + $bugz{$k} = 1 if (($k ne '') and ($k =~ /[0-9]+/)); + } + } + elsif (/^ *BugLink: *http.*:\/\/.*\/([0-9]+)/i) { + $bugz{$1} = 1; + } + elsif (/^ *(CVE-.*)/) { + $cve = $1 + } + last if /^commit /; + } + + $bug = join(", #", sort keys(%bugz)); + if (!$ignore) { + &shortlog_entry($author, $desc, $bug, + $cve, $commit, 0); + } + + $pstate = 1; + if ($_ && /^commit (.*)/) { + $commit = $1; + $pstate++; + } + } + + else { + die "invalid parse state $pstate"; + } + } + + foreach $entry (@reverts) { + add_entry($entry); + } +} + +&changelog_input; +&shortlog_output; + +exit(0); --- linux-2.6.37.orig/debian/scripts/misc/insert-changes.pl +++ linux-2.6.37/debian/scripts/misc/insert-changes.pl @@ -0,0 +1,36 @@ +#!/usr/bin/perl -w + +my $debian; +$droot = $ARGV[0] if (defined $ARGV[0]); +$droot = 'debian' if (!defined $droot); +$debian = $ARGV[1] if (defined $ARGV[1]); +$debian = 'debian.master' if (!defined $debian); + +system("make -s -f $droot/rules printchanges > $debian/changes"); + +open(CHANGELOG, "< $debian/changelog") or die "Cannot open changelog"; +open(CHANGES, "< $debian/changes") or die "Cannot open new changes"; +open(NEW, "> $debian/changelog.new") or die "Cannot open new changelog"; + +$printed = 0; + +while () { + if (/^ CHANGELOG: /) { + next if $printed; + + while () { + print NEW; + } + + $printed = 1; + } else { + print NEW; + } +} + +close(NEW); +close(CHANGES); +close(CHANGELOG); + +rename("$debian/changelog.new", "$debian/changelog"); +unlink("$debian/changes"); --- linux-2.6.37.orig/debian/scripts/misc/insert-ubuntu-changes +++ linux-2.6.37/debian/scripts/misc/insert-ubuntu-changes @@ -0,0 +1,58 @@ +#!/usr/bin/perl + +if ($#ARGV != 2) { + die "Usage: $0 \n"; +} +my ($changelog, $end, $start) = @ARGV; + +$end =~ s/.*\.//; +$start =~ s/.*\.//; + +my @changes = (); +my $output = 0; +open(CHG, ") { + if (/^\S+\s+\((.*\.(\d+))\)/) { + if ($2 <= $end) { + last; + } + if ($2 == $start) { + $output = 1; + } + if ($output) { + push(@changes, "\n [ Ubuntu: $1 ]\n\n"); + next; + } + } + next if ($output == 0); + + next if (/^\s*$/); + next if (/^\s--/); + next if (/^\s\s[^\*\s]/); + + push(@changes, $_); +} +close(CHG); + +open(CHANGELOG, "< $changelog") or die "Cannot open changelog"; +open(NEW, "> $changelog.new") or die "Cannot open new changelog"; + +$printed = 3; +while () { + if (/^ CHANGELOG: /) { + $printed--; + print NEW; + if ($printed == 0) { + print NEW @changes; + } + next; + } + print NEW; +} + +close(NEW); +close(CHANGELOG); + +rename("$changelog.new", "$changelog"); --- linux-2.6.37.orig/debian/scripts/misc/kernelconfig +++ linux-2.6.37/debian/scripts/misc/kernelconfig @@ -0,0 +1,171 @@ +#!/bin/bash + +. debian/debian.env + +# Script to merge all configs and run 'make silentoldconfig' on it to wade out bad juju. +# Then split the configs into distro-commmon and flavour-specific parts + +# We have to be in the top level kernel source directory +if [ ! -f MAINTAINERS ] || [ ! -f Makefile ]; then + echo "This does not appear to be the kernel source directory." 1>&2 + exit 1 +fi + +mode=${1:?"Usage: $0 [oldconfig|editconfig]"} +yes=0 +case "$mode" in + update*configs) mode='silentoldconfig' ;; + default*configs) mode='oldconfig'; yes=1 ;; + edit*configs) ;; # All is good + gen*configs) mode='genconfigs' ;; # All is good + dump*configs) mode='config'; yes=1 ;; + *) echo "$0 called with invalid mode" 1>&2 + exit 1 ;; +esac +kerneldir="`pwd`" +confdir="$kerneldir/${DEBIAN}/config" +sharedconfdir="$kerneldir/debian.master/config" +variant="$2" + +. $DEBIAN/etc/kernelconfig + +bindir="`pwd`/${DROOT}/scripts/misc" +common_conf="$confdir/config.common.$family" +tmpdir=`mktemp -d` +mkdir "$tmpdir/CONFIGS" + +if [ "$mode" = "genconfigs" ]; then + keep=1 + mode="oldconfig" + test -d CONFIGS || mkdir CONFIGS +fi + +for arch in $archs; do + rm -rf build + mkdir build + + # Map debian archs to kernel archs + case "$arch" in + amd64) kernarch="x86_64" ;; + lpia) kernarch="x86" ;; + sparc) kernarch="sparc64" ;; + armel) kernarch="arm" ;; + *) kernarch="$arch" ;; + esac + + archconfdir=$confdir/$arch + flavourconfigs=$(cd $archconfdir && ls config.flavour.*) + + # Merge configs + # We merge config.common.ubuntu + config.common. + + # config.flavour. + + for config in $flavourconfigs; do + fullconf="$tmpdir/$arch-$config-full" + case $config in + *) + : >"$fullconf" + if [ -f $common_conf ]; then + cat $common_conf >> "$fullconf" + fi + if [ -f $archconfdir/config.common.$arch ]; then + cat $archconfdir/config.common.$arch >> "$fullconf" + fi + cat "$archconfdir/$config" >>"$fullconf" + if [ -f $confdir/OVERRIDES ]; then + cat $confdir/OVERRIDES >> "$fullconf" + fi + ;; + esac + done + + for config in $flavourconfigs; do + if [ -f $archconfdir/$config ]; then + fullconf="$tmpdir/$arch-$config-full" + cat "$fullconf" > build/.config + # Call oldconfig or menuconfig + case "$mode" in + editconfigs) + # Interactively edit config parameters + while : ; do + echo -n "Do you want to edit config: $arch/$config? [Y/n] " + read choice + + case "$choice" in + y* | Y* | "" ) + make O=`pwd`/build ARCH=$kernarch menuconfig + break ;; + n* | N* ) + break ;; + *) + echo "Entry not valid" + esac + done + ;; + *) + echo "* Run $mode (yes=$yes) on $arch/$config ..." + if [ "$yes" -eq 1 ]; then + yes "" | make O=`pwd`/build ARCH=$kernarch "$mode" + else + make O=`pwd`/build ARCH=$kernarch "$mode" + fi ;; + esac + cat build/.config > $archconfdir/$config + cat build/.config > "$tmpdir/CONFIGS/$arch-$config" + if [ "$keep" = "1" ]; then + cat build/.config > CONFIGS/$arch-$config + fi + else + echo "!! Config not found $archconfdir/$config..." + fi + done + + echo "Running splitconfig.pl for $arch" + echo + + # Can we make this more robust by avoiding $tmpdir completely? + # This approach was used for now because I didn't want to change + # splitconfig.pl + (cd $archconfdir; $bindir/splitconfig.pl; mv config.common \ + config.common.$arch; cp config.common.$arch $tmpdir) +done + +rm -f $common_conf + +# Now run splitconfig.pl on all the config.common. copied to +# $tmpdir +(cd $tmpdir; $bindir/splitconfig.pl) +( + cd $confdir; + rm -f *-full + grep -v 'is UNMERGABLE' <$tmpdir/config.common >$common_conf + for arch in $archs; do + grep -v 'is UNMERGABLE' <$tmpdir/config.common.$arch \ + >$arch/config.common.$arch + done +) + +echo "" +echo "Running config-check for all configurations ..." +echo "" +fail=0 +for arch in $archs; do + archconfdir=$confdir/$arch + flavourconfigs=$(cd $archconfdir && ls config.flavour.*) + for config in $flavourconfigs; do + flavour="${config##*.}" + if [ -f $archconfdir/$config ]; then + fullconf="$tmpdir/CONFIGS/$arch-$config" + "$bindir/../config-check" "$fullconf" "$arch" "$flavour" "$sharedconfdir" "0" || let "fail=$fail+1" + fi + done +done + +if [ "$fail" != 0 ]; then + echo "" + echo "*** ERROR: $fail config-check failures detected" + echo "" +fi + +rm -rf build + --- linux-2.6.37.orig/debian/scripts/misc/retag +++ linux-2.6.37/debian/scripts/misc/retag @@ -0,0 +1,34 @@ +#!/usr/bin/perl -w + +open(TAGS, "git tag -l |") or die "Could not get list of tags"; +@tags = ; +close(TAGS); + +open(LOGS, "git log --pretty=short |") or die "ERROR: Calling git log"; +my $commit = ""; + +while () { + my $origtag; + + if (m|^commit (.*)$|) { + $commit = $1; + next; + } + + m|\s*UBUNTU: (Ubuntu-2\.6\..*)| or next; + + $tag = $1; + + ($origtag) = grep(/^$tag.orig$/, @tags); + + if (!defined($origtag)) { + print "I: Adding original tag for $tag\n"; + system("git tag -m $tag $tag.orig $tag"); + } + + print "I: Tagging $tag => $commit\n"; + + system("git tag -f -m $tag $tag $commit"); +} + +close(LOGS); --- linux-2.6.37.orig/debian/scripts/misc/splitconfig.pl +++ linux-2.6.37/debian/scripts/misc/splitconfig.pl @@ -0,0 +1,111 @@ +#!/usr/bin/perl -w + +%allconfigs = (); +%common = (); + +print "Reading config's ...\n"; + +opendir(DIR, "."); + +while (defined($config = readdir(DIR))) { + # Only config.* + next if $config !~ /^config\..*/; + # Nothing that is disabled, or remnant + next if $config =~ /.*\.(default|disabled|stub)$/; + + %{$allconfigs{$config}} = (); + + print " processing $config ... "; + + open(CONFIG, "< $config"); + + while () { + # Skip comments + /^#*\s*CONFIG_(\w+)[\s=](.*)$/ or next; + + ${$allconfigs{$config}}{$1} = $2; + + $common{$1} = $2; + } + + close(CONFIG); + + print "done.\n"; +} + +closedir(DIR); + +print "\n"; + +print "Merging lists ... \n"; + +# %options - pointer to flavour config inside the allconfigs array +for $config (keys(%allconfigs)) { + my %options = %{$allconfigs{$config}}; + + print " processing $config ... "; + + for $key (keys(%common)) { + next if not defined $common{$key}; + + # If we don't have the common option, then it isn't + # common. If we do have that option, it must have the same + # value. EXCEPT where this file does not have a value at all + # which may safely be merged with any other value; the value + # will be elided during recombination of the parts. + if (!defined($options{$key})) { + # Its ok really ... let it merge + } elsif (not defined($options{$key})) { + undef $common{$key}; + } elsif ($common{$key} ne $options{$key}) { + undef $common{$key}; + } + } + + print "done.\n"; +} + +print "\n"; + +print "Creating common config ... "; + +open(COMMON, "> config.common"); +print COMMON "#\n# Common config options automatically generated by splitconfig.pl\n#\n"; + +for $key (sort(keys(%common))) { + if (not defined $common{$key}) { + print COMMON "# CONFIG_$key is UNMERGABLE\n"; + } elsif ($common{$key} eq "is not set") { + print COMMON "# CONFIG_$key is not set\n"; + } else { + print COMMON "CONFIG_$key=$common{$key}\n"; + } +} +close(COMMON); + +print "done.\n\n"; + +print "Creating stub configs ...\n"; + +for $config (keys(%allconfigs)) { + my %options = %{$allconfigs{$config}}; + + print " processing $config ... "; + + open(STUB, "> $config"); + print STUB "#\n# Config options for $config automatically generated by splitconfig.pl\n#\n"; + + for $key (sort(keys(%options))) { + next if defined $common{$key}; + + if ($options{$key} =~ /^is /) { + print STUB "# CONFIG_$key $options{$key}\n"; + } else { + print STUB "CONFIG_$key=$options{$key}\n"; + } + } + + close(STUB); + + print "done.\n"; +} --- linux-2.6.37.orig/debian/source/format +++ linux-2.6.37/debian/source/format @@ -0,0 +1 @@ +1.0 --- linux-2.6.37.orig/debian/stamps/keep-dir +++ linux-2.6.37/debian/stamps/keep-dir @@ -0,0 +1 @@ +Place holder --- linux-2.6.37.orig/debian/tests/README +++ linux-2.6.37/debian/tests/README @@ -0,0 +1,21 @@ +Scripts placed in this directory get called one at a time by run-parts(8). +The scripts are expected to perform some sort of sanity checks on the +finished build. Scripts will be called once for each flavour. + +Some environment variables are exported to make life a little easier: + +DPKG_ARCH : The dpkg architecture (e.g. "amd64") +KERN_ARCH : The kernel architecture (e.g. "x86_64") +FLAVOUR : The specific flavour for this run (e.g. "generic") +VERSION : The full version of this build (e.g. 2.6.22-1) +REVISION : The exact revision of this build (e.g. 1.3) +PREV_REVISION : The revision prior to this one +ABI_NUM : The specific ABI number for this build (e.g. 2) +PREV_ABI_NUM : The previous ABI number. Can be the same as ABI_NUM. +BUILD_DIR : The directory where this build took place +INSTALL_DIR : The directory where the package is prepared +SOURCE_DIR : Where the main kernel source is + +Scripts are expected to have a zero exit status when no problems occur, +and non-zero when an error occurs that should stop the build. Scripts +should print whatever info they deem needed to deduce the problem. --- linux-2.6.37.orig/debian/tools/perf +++ linux-2.6.37/debian/tools/perf @@ -0,0 +1,16 @@ +#!/bin/bash +full_version=`uname -r` + +# Removing flavour from version i.e. generic or server. +flavour_abi=${full_version#*-} +flavour=${flavour_abi#*-} +version=${full_version%-$flavour} +perf="perf_$version" + +if ! which "$perf" > /dev/null; then + echo "$perf not found" >&2 + echo "You may need to install linux-tools-$version" >&2 + exit 2 +fi + +exec "$perf" "$@" --- linux-2.6.37.orig/ubuntu/Kconfig +++ linux-2.6.37/ubuntu/Kconfig @@ -0,0 +1,53 @@ +menu "Ubuntu Supplied Third-Party Device Drivers" + +# +# NOTE: to allow drivers to be added and removed without causing merge +# collisions you should add new entries in the middle of the six lines +# of ## at the bottom of the list. Always add three lines of ## above +# your new entry and maintain the six lines below. +# + +## +## +## +source "ubuntu/compcache/Kconfig" +## +## +## +source "ubuntu/dm-raid4-5/Kconfig" +## +## +## +source "ubuntu/ndiswrapper/Kconfig" +## +## +## +source "ubuntu/rfkill/Kconfig" +## +## +## +source "ubuntu/fsam7400/Kconfig" +## +## +## +source "ubuntu/omnibook/Kconfig" +## +## +## +source "ubuntu/iscsitarget/Kconfig" +## +## +## +source "ubuntu/rtl8192se/Kconfig" +## +## +## +source "ubuntu/aufs/Kconfig" +## +## +## +## +## +## + +endmenu --- linux-2.6.37.orig/ubuntu/Makefile +++ linux-2.6.37/ubuntu/Makefile @@ -0,0 +1,60 @@ +# +# Makefile for the Linux kernel ubuntu supplied third-party device drivers. +# + +# +# NOTE: to allow drivers to be added and removed without causing merge +# collisions you should add new entries in the middle of the six lines +# of ## at the bottom of the list. Always add three lines of ## above +# your new entry and maintain the six lines below. +# + +## +## +## +obj-$(CONFIG_BLK_DEV_COMPCACHE) += compcache/ +## +## +## +obj-$(CONFIG_DM_RAID45) += dm-raid4-5/ +## +## +## +obj-$(CONFIG_NDISWRAPPER) += ndiswrapper/ +## +## +## +obj-m += rfkill/ +## +## +## +obj-$(CONFIG_FSAM7400) += fsam7400/ +## +## +## +obj-$(CONFIG_OMNIBOOK) += omnibook/ +## +## +## +obj-$(CONFIG_SCSI_ISCSITARGET) += iscsitarget/ +## +## +## +obj-$(CONFIG_AUFS_FS) += aufs/ +## +## +## +obj-$(CONFIG_RTL8192SE) += rtl8192se/ +## +## +## +obj-$(CONFIG_AUFS_FS) += aufs/ +## +## +## +## +## +## + +# This is a stupid trick to get kbuild to create ubuntu/built-in.o +obj- += foo.o --- linux-2.6.37.orig/ubuntu/aufs-update +++ linux-2.6.37/ubuntu/aufs-update @@ -0,0 +1,37 @@ +#!/bin/bash + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " 1>&2 + exit 1 +fi +aufs="$1" + +# Get the current tip name +{ + read x url + read x osha1 +} comm,current->pid' + +obj-$(CONFIG_AUFS_FS) += aufs.o +aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \ + wkq.o vfsub.o dcsub.o \ + cpup.o whout.o wbr_policy.o \ + dinfo.o dentry.o \ + dynop.o \ + finfo.o file.o f_op.o \ + dir.o vdir.o \ + iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \ + ioctl.o + +# all are boolean +aufs-$(CONFIG_PROC_FS) += procfs.o plink.o +aufs-$(CONFIG_SYSFS) += sysfs.o +aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o +aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o +aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o +aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o +aufs-$(CONFIG_AUFS_EXPORT) += export.o +aufs-$(CONFIG_AUFS_POLL) += poll.o +aufs-$(CONFIG_AUFS_RDU) += rdu.o +aufs-$(CONFIG_AUFS_SP_IATTR) += f_op_sp.o +aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o +aufs-$(CONFIG_AUFS_DEBUG) += debug.o +aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o --- linux-2.6.37.orig/ubuntu/aufs/aufs.h +++ linux-2.6.37/ubuntu/aufs/aufs.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * all header files + */ + +#ifndef __AUFS_H__ +#define __AUFS_H__ + +#ifdef __KERNEL__ + +#define AuStub(type, name, body, ...) \ + static inline type name(__VA_ARGS__) { body; } + +#define AuStubVoid(name, ...) \ + AuStub(void, name, , __VA_ARGS__) +#define AuStubInt0(name, ...) \ + AuStub(int, name, return 0, __VA_ARGS__) + +#include "debug.h" + +#include "branch.h" +#include "cpup.h" +#include "dcsub.h" +#include "dbgaufs.h" +#include "dentry.h" +#include "dir.h" +#include "dynop.h" +#include "file.h" +#include "fstype.h" +#include "inode.h" +#include "loop.h" +#include "module.h" +/* never include ./mtx.h */ +#include "opts.h" +#include "rwsem.h" +#include "spl.h" +#include "super.h" +#include "sysaufs.h" +#include "vfsub.h" +#include "whout.h" +#include "wkq.h" + +#endif /* __KERNEL__ */ +#endif /* __AUFS_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/branch.c +++ linux-2.6.37/ubuntu/aufs/branch.c @@ -0,0 +1,1051 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * branch management + */ + +#include +#include +#include "aufs.h" + +/* + * free a single branch + */ +static void au_br_do_free(struct au_branch *br) +{ + int i; + struct au_wbr *wbr; + struct au_dykey **key; + + if (br->br_xino.xi_file) + fput(br->br_xino.xi_file); + mutex_destroy(&br->br_xino.xi_nondir_mtx); + + AuDebugOn(atomic_read(&br->br_count)); + + wbr = br->br_wbr; + if (wbr) { + for (i = 0; i < AuBrWh_Last; i++) + dput(wbr->wbr_wh[i]); + AuDebugOn(atomic_read(&wbr->wbr_wh_running)); + AuRwDestroy(&wbr->wbr_wh_rwsem); + } + + key = br->br_dykey; + for (i = 0; i < AuBrDynOp; i++, key++) + if (*key) + au_dy_put(*key); + else + break; + + mntput(br->br_mnt); + kfree(wbr); + kfree(br); +} + +/* + * frees all branches + */ +void au_br_free(struct au_sbinfo *sbinfo) +{ + aufs_bindex_t bmax; + struct au_branch **br; + + AuRwMustWriteLock(&sbinfo->si_rwsem); + + bmax = sbinfo->si_bend + 1; + br = sbinfo->si_branch; + while (bmax--) + au_br_do_free(*br++); +} + +/* + * find the index of a branch which is specified by @br_id. + */ +int au_br_index(struct super_block *sb, aufs_bindex_t br_id) +{ + aufs_bindex_t bindex, bend; + + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) + if (au_sbr_id(sb, bindex) == br_id) + return bindex; + return -1; +} + +/* ---------------------------------------------------------------------- */ + +/* + * add a branch + */ + +static int test_overlap(struct super_block *sb, struct dentry *h_adding, + struct dentry *h_root) +{ + if (unlikely(h_adding == h_root + || au_test_loopback_overlap(sb, h_adding))) + return 1; + if (h_adding->d_sb != h_root->d_sb) + return 0; + return au_test_subdir(h_adding, h_root) + || au_test_subdir(h_root, h_adding); +} + +/* + * returns a newly allocated branch. @new_nbranch is a number of branches + * after adding a branch. + */ +static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch, + int perm) +{ + struct au_branch *add_branch; + struct dentry *root; + int err; + + err = -ENOMEM; + root = sb->s_root; + add_branch = kmalloc(sizeof(*add_branch), GFP_NOFS); + if (unlikely(!add_branch)) + goto out; + + add_branch->br_wbr = NULL; + if (au_br_writable(perm)) { + /* may be freed separately at changing the branch permission */ + add_branch->br_wbr = kmalloc(sizeof(*add_branch->br_wbr), + GFP_NOFS); + if (unlikely(!add_branch->br_wbr)) + goto out_br; + } + + err = au_sbr_realloc(au_sbi(sb), new_nbranch); + if (!err) + err = au_di_realloc(au_di(root), new_nbranch); + if (!err) + err = au_ii_realloc(au_ii(root->d_inode), new_nbranch); + if (!err) + return add_branch; /* success */ + + kfree(add_branch->br_wbr); + +out_br: + kfree(add_branch); +out: + return ERR_PTR(err); +} + +/* + * test if the branch permission is legal or not. + */ +static int test_br(struct inode *inode, int brperm, char *path) +{ + int err; + + err = (au_br_writable(brperm) && IS_RDONLY(inode)); + if (!err) + goto out; + + err = -EINVAL; + pr_err("write permission for readonly mount or inode, %s\n", path); + +out: + return err; +} + +/* + * returns: + * 0: success, the caller will add it + * plus: success, it is already unified, the caller should ignore it + * minus: error + */ +static int test_add(struct super_block *sb, struct au_opt_add *add, int remount) +{ + int err; + aufs_bindex_t bend, bindex; + struct dentry *root; + struct inode *inode, *h_inode; + + root = sb->s_root; + bend = au_sbend(sb); + if (unlikely(bend >= 0 + && au_find_dbindex(root, add->path.dentry) >= 0)) { + err = 1; + if (!remount) { + err = -EINVAL; + pr_err("%s duplicated\n", add->pathname); + } + goto out; + } + + err = -ENOSPC; /* -E2BIG; */ + if (unlikely(AUFS_BRANCH_MAX <= add->bindex + || AUFS_BRANCH_MAX - 1 <= bend)) { + pr_err("number of branches exceeded %s\n", add->pathname); + goto out; + } + + err = -EDOM; + if (unlikely(add->bindex < 0 || bend + 1 < add->bindex)) { + pr_err("bad index %d\n", add->bindex); + goto out; + } + + inode = add->path.dentry->d_inode; + err = -ENOENT; + if (unlikely(!inode->i_nlink)) { + pr_err("no existence %s\n", add->pathname); + goto out; + } + + err = -EINVAL; + if (unlikely(inode->i_sb == sb)) { + pr_err("%s must be outside\n", add->pathname); + goto out; + } + + if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) { + pr_err("unsupported filesystem, %s (%s)\n", + add->pathname, au_sbtype(inode->i_sb)); + goto out; + } + + err = test_br(add->path.dentry->d_inode, add->perm, add->pathname); + if (unlikely(err)) + goto out; + + if (bend < 0) + return 0; /* success */ + + err = -EINVAL; + for (bindex = 0; bindex <= bend; bindex++) + if (unlikely(test_overlap(sb, add->path.dentry, + au_h_dptr(root, bindex)))) { + pr_err("%s is overlapped\n", add->pathname); + goto out; + } + + err = 0; + if (au_opt_test(au_mntflags(sb), WARN_PERM)) { + h_inode = au_h_dptr(root, 0)->d_inode; + if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO) + || h_inode->i_uid != inode->i_uid + || h_inode->i_gid != inode->i_gid) + pr_warning("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n", + add->pathname, + inode->i_uid, inode->i_gid, + (inode->i_mode & S_IALLUGO), + h_inode->i_uid, h_inode->i_gid, + (h_inode->i_mode & S_IALLUGO)); + } + +out: + return err; +} + +/* + * initialize or clean the whiteouts for an adding branch + */ +static int au_br_init_wh(struct super_block *sb, struct au_branch *br, + int new_perm, struct dentry *h_root) +{ + int err, old_perm; + aufs_bindex_t bindex; + struct mutex *h_mtx; + struct au_wbr *wbr; + struct au_hinode *hdir; + + wbr = br->br_wbr; + old_perm = br->br_perm; + br->br_perm = new_perm; + hdir = NULL; + h_mtx = NULL; + bindex = au_br_index(sb, br->br_id); + if (0 <= bindex) { + hdir = au_hi(sb->s_root->d_inode, bindex); + au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT); + } else { + h_mtx = &h_root->d_inode->i_mutex; + mutex_lock_nested(h_mtx, AuLsc_I_PARENT); + } + if (!wbr) + err = au_wh_init(h_root, br, sb); + else { + wbr_wh_write_lock(wbr); + err = au_wh_init(h_root, br, sb); + wbr_wh_write_unlock(wbr); + } + if (hdir) + au_hn_imtx_unlock(hdir); + else + mutex_unlock(h_mtx); + br->br_perm = old_perm; + + if (!err && wbr && !au_br_writable(new_perm)) { + kfree(wbr); + br->br_wbr = NULL; + } + + return err; +} + +static int au_wbr_init(struct au_branch *br, struct super_block *sb, + int perm, struct path *path) +{ + int err; + struct kstatfs kst; + struct au_wbr *wbr; + struct dentry *h_dentry; + + wbr = br->br_wbr; + au_rw_init(&wbr->wbr_wh_rwsem); + memset(wbr->wbr_wh, 0, sizeof(wbr->wbr_wh)); + atomic_set(&wbr->wbr_wh_running, 0); + wbr->wbr_bytes = 0; + + /* + * a limit for rmdir/rename a dir + * cf. AUFS_MAX_NAMELEN in include/linux/aufs_type.h + */ + err = vfs_statfs(path, &kst); + if (unlikely(err)) + goto out; + err = -EINVAL; + h_dentry = path->dentry; + if (kst.f_namelen >= NAME_MAX) + err = au_br_init_wh(sb, br, perm, h_dentry); + else + pr_err("%.*s(%s), unsupported namelen %ld\n", + AuDLNPair(h_dentry), au_sbtype(h_dentry->d_sb), + kst.f_namelen); + +out: + return err; +} + +/* intialize a new branch */ +static int au_br_init(struct au_branch *br, struct super_block *sb, + struct au_opt_add *add) +{ + int err; + + err = 0; + memset(&br->br_xino, 0, sizeof(br->br_xino)); + mutex_init(&br->br_xino.xi_nondir_mtx); + br->br_perm = add->perm; + br->br_mnt = add->path.mnt; /* set first, mntget() later */ + spin_lock_init(&br->br_dykey_lock); + memset(br->br_dykey, 0, sizeof(br->br_dykey)); + atomic_set(&br->br_count, 0); + br->br_xino_upper = AUFS_XINO_TRUNC_INIT; + atomic_set(&br->br_xino_running, 0); + br->br_id = au_new_br_id(sb); + AuDebugOn(br->br_id < 0); + + if (au_br_writable(add->perm)) { + err = au_wbr_init(br, sb, add->perm, &add->path); + if (unlikely(err)) + goto out_err; + } + + if (au_opt_test(au_mntflags(sb), XINO)) { + err = au_xino_br(sb, br, add->path.dentry->d_inode->i_ino, + au_sbr(sb, 0)->br_xino.xi_file, /*do_test*/1); + if (unlikely(err)) { + AuDebugOn(br->br_xino.xi_file); + goto out_err; + } + } + + sysaufs_br_init(br); + mntget(add->path.mnt); + goto out; /* success */ + +out_err: + br->br_mnt = NULL; +out: + return err; +} + +static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex, + struct au_branch *br, aufs_bindex_t bend, + aufs_bindex_t amount) +{ + struct au_branch **brp; + + AuRwMustWriteLock(&sbinfo->si_rwsem); + + brp = sbinfo->si_branch + bindex; + memmove(brp + 1, brp, sizeof(*brp) * amount); + *brp = br; + sbinfo->si_bend++; + if (unlikely(bend < 0)) + sbinfo->si_bend = 0; +} + +static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex, + aufs_bindex_t bend, aufs_bindex_t amount) +{ + struct au_hdentry *hdp; + + AuRwMustWriteLock(&dinfo->di_rwsem); + + hdp = dinfo->di_hdentry + bindex; + memmove(hdp + 1, hdp, sizeof(*hdp) * amount); + au_h_dentry_init(hdp); + dinfo->di_bend++; + if (unlikely(bend < 0)) + dinfo->di_bstart = 0; +} + +static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex, + aufs_bindex_t bend, aufs_bindex_t amount) +{ + struct au_hinode *hip; + + AuRwMustWriteLock(&iinfo->ii_rwsem); + + hip = iinfo->ii_hinode + bindex; + memmove(hip + 1, hip, sizeof(*hip) * amount); + hip->hi_inode = NULL; + au_hn_init(hip); + iinfo->ii_bend++; + if (unlikely(bend < 0)) + iinfo->ii_bstart = 0; +} + +static void au_br_do_add(struct super_block *sb, struct dentry *h_dentry, + struct au_branch *br, aufs_bindex_t bindex) +{ + struct dentry *root; + struct inode *root_inode; + aufs_bindex_t bend, amount; + + root = sb->s_root; + root_inode = root->d_inode; + bend = au_sbend(sb); + amount = bend + 1 - bindex; + au_br_do_add_brp(au_sbi(sb), bindex, br, bend, amount); + au_br_do_add_hdp(au_di(root), bindex, bend, amount); + au_br_do_add_hip(au_ii(root_inode), bindex, bend, amount); + au_set_h_dptr(root, bindex, dget(h_dentry)); + au_set_h_iptr(root_inode, bindex, au_igrab(h_dentry->d_inode), + /*flags*/0); +} + +int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount) +{ + int err; + aufs_bindex_t bend, add_bindex; + struct dentry *root, *h_dentry; + struct inode *root_inode; + struct au_branch *add_branch; + + root = sb->s_root; + root_inode = root->d_inode; + IMustLock(root_inode); + err = test_add(sb, add, remount); + if (unlikely(err < 0)) + goto out; + if (err) { + err = 0; + goto out; /* success */ + } + + bend = au_sbend(sb); + add_branch = au_br_alloc(sb, bend + 2, add->perm); + err = PTR_ERR(add_branch); + if (IS_ERR(add_branch)) + goto out; + + err = au_br_init(add_branch, sb, add); + if (unlikely(err)) { + au_br_do_free(add_branch); + goto out; + } + + add_bindex = add->bindex; + h_dentry = add->path.dentry; + if (!remount) + au_br_do_add(sb, h_dentry, add_branch, add_bindex); + else { + sysaufs_brs_del(sb, add_bindex); + au_br_do_add(sb, h_dentry, add_branch, add_bindex); + sysaufs_brs_add(sb, add_bindex); + } + + if (!add_bindex) { + au_cpup_attr_all(root_inode, /*force*/1); + sb->s_maxbytes = h_dentry->d_sb->s_maxbytes; + } else + au_add_nlink(root_inode, h_dentry->d_inode); + + /* + * this test/set prevents aufs from handling unnecesary notify events + * of xino files, in a case of re-adding a writable branch which was + * once detached from aufs. + */ + if (au_xino_brid(sb) < 0 + && au_br_writable(add_branch->br_perm) + && !au_test_fs_bad_xino(h_dentry->d_sb) + && add_branch->br_xino.xi_file + && add_branch->br_xino.xi_file->f_dentry->d_parent == h_dentry) + au_xino_brid_set(sb, add_branch->br_id); + +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * delete a branch + */ + +/* to show the line number, do not make it inlined function */ +#define AuVerbose(do_info, fmt, ...) do { \ + if (do_info) \ + pr_info(fmt, ##__VA_ARGS__); \ +} while (0) + +/* + * test if the branch is deletable or not. + */ +static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex, + unsigned int sigen, const unsigned int verbose) +{ + int err, i, j, ndentry; + aufs_bindex_t bstart, bend; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + struct dentry *d; + struct inode *inode; + + err = au_dpages_init(&dpages, GFP_NOFS); + if (unlikely(err)) + goto out; + err = au_dcsub_pages(&dpages, root, NULL, NULL); + if (unlikely(err)) + goto out_dpages; + + for (i = 0; !err && i < dpages.ndpage; i++) { + dpage = dpages.dpages + i; + ndentry = dpage->ndentry; + for (j = 0; !err && j < ndentry; j++) { + d = dpage->dentries[j]; + AuDebugOn(!atomic_read(&d->d_count)); + inode = d->d_inode; + if (au_digen(d) == sigen && au_iigen(inode) == sigen) + di_read_lock_child(d, AuLock_IR); + else { + di_write_lock_child(d); + err = au_reval_dpath(d, sigen); + if (!err) + di_downgrade_lock(d, AuLock_IR); + else { + di_write_unlock(d); + break; + } + } + + bstart = au_dbstart(d); + bend = au_dbend(d); + if (bstart <= bindex + && bindex <= bend + && au_h_dptr(d, bindex) + && (!S_ISDIR(inode->i_mode) || bstart == bend)) { + err = -EBUSY; + AuVerbose(verbose, "busy %.*s\n", AuDLNPair(d)); + } + di_read_unlock(d, AuLock_IR); + } + } + +out_dpages: + au_dpages_free(&dpages); +out: + return err; +} + +static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex, + unsigned int sigen, const unsigned int verbose) +{ + int err; + unsigned long long max, ull; + struct inode *i, **array; + aufs_bindex_t bstart, bend; + + array = au_iarray_alloc(sb, &max); + err = PTR_ERR(array); + if (IS_ERR(array)) + goto out; + + err = 0; + AuDbg("b%d\n", bindex); + for (ull = 0; !err && ull < max; ull++) { + i = array[ull]; + if (i->i_ino == AUFS_ROOT_INO) + continue; + + /* AuDbgInode(i); */ + if (au_iigen(i) == sigen) + ii_read_lock_child(i); + else { + ii_write_lock_child(i); + err = au_refresh_hinode_self(i, /*do_attr*/1); + if (!err) + ii_downgrade_lock(i); + else { + ii_write_unlock(i); + break; + } + } + + bstart = au_ibstart(i); + bend = au_ibend(i); + if (bstart <= bindex + && bindex <= bend + && au_h_iptr(i, bindex) + && (!S_ISDIR(i->i_mode) || bstart == bend)) { + err = -EBUSY; + AuVerbose(verbose, "busy i%lu\n", i->i_ino); + AuDbgInode(i); + } + ii_read_unlock(i); + } + au_iarray_free(array, max); + +out: + return err; +} + +static int test_children_busy(struct dentry *root, aufs_bindex_t bindex, + const unsigned int verbose) +{ + int err; + unsigned int sigen; + + sigen = au_sigen(root->d_sb); + DiMustNoWaiters(root); + IiMustNoWaiters(root->d_inode); + di_write_unlock(root); + err = test_dentry_busy(root, bindex, sigen, verbose); + if (!err) + err = test_inode_busy(root->d_sb, bindex, sigen, verbose); + di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */ + + return err; +} + +static void au_br_do_del_brp(struct au_sbinfo *sbinfo, + const aufs_bindex_t bindex, + const aufs_bindex_t bend) +{ + struct au_branch **brp, **p; + + AuRwMustWriteLock(&sbinfo->si_rwsem); + + brp = sbinfo->si_branch + bindex; + if (bindex < bend) + memmove(brp, brp + 1, sizeof(*brp) * (bend - bindex)); + sbinfo->si_branch[0 + bend] = NULL; + sbinfo->si_bend--; + + p = krealloc(sbinfo->si_branch, sizeof(*p) * bend, GFP_NOFS); + if (p) + sbinfo->si_branch = p; + /* harmless error */ +} + +static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex, + const aufs_bindex_t bend) +{ + struct au_hdentry *hdp, *p; + + AuRwMustWriteLock(&dinfo->di_rwsem); + + hdp = dinfo->di_hdentry; + if (bindex < bend) + memmove(hdp + bindex, hdp + bindex + 1, + sizeof(*hdp) * (bend - bindex)); + hdp[0 + bend].hd_dentry = NULL; + dinfo->di_bend--; + + p = krealloc(hdp, sizeof(*p) * bend, GFP_NOFS); + if (p) + dinfo->di_hdentry = p; + /* harmless error */ +} + +static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex, + const aufs_bindex_t bend) +{ + struct au_hinode *hip, *p; + + AuRwMustWriteLock(&iinfo->ii_rwsem); + + hip = iinfo->ii_hinode + bindex; + if (bindex < bend) + memmove(hip, hip + 1, sizeof(*hip) * (bend - bindex)); + iinfo->ii_hinode[0 + bend].hi_inode = NULL; + au_hn_init(iinfo->ii_hinode + bend); + iinfo->ii_bend--; + + p = krealloc(iinfo->ii_hinode, sizeof(*p) * bend, GFP_NOFS); + if (p) + iinfo->ii_hinode = p; + /* harmless error */ +} + +static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex, + struct au_branch *br) +{ + aufs_bindex_t bend; + struct au_sbinfo *sbinfo; + struct dentry *root; + struct inode *inode; + + SiMustWriteLock(sb); + + root = sb->s_root; + inode = root->d_inode; + sbinfo = au_sbi(sb); + bend = sbinfo->si_bend; + + dput(au_h_dptr(root, bindex)); + au_hiput(au_hi(inode, bindex)); + au_br_do_free(br); + + au_br_do_del_brp(sbinfo, bindex, bend); + au_br_do_del_hdp(au_di(root), bindex, bend); + au_br_do_del_hip(au_ii(inode), bindex, bend); +} + +int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount) +{ + int err, rerr, i; + unsigned int mnt_flags; + aufs_bindex_t bindex, bend, br_id; + unsigned char do_wh, verbose; + struct au_branch *br; + struct au_wbr *wbr; + + err = 0; + bindex = au_find_dbindex(sb->s_root, del->h_path.dentry); + if (bindex < 0) { + if (remount) + goto out; /* success */ + err = -ENOENT; + pr_err("%s no such branch\n", del->pathname); + goto out; + } + AuDbg("bindex b%d\n", bindex); + + err = -EBUSY; + mnt_flags = au_mntflags(sb); + verbose = !!au_opt_test(mnt_flags, VERBOSE); + bend = au_sbend(sb); + if (unlikely(!bend)) { + AuVerbose(verbose, "no more branches left\n"); + goto out; + } + br = au_sbr(sb, bindex); + i = atomic_read(&br->br_count); + if (unlikely(i)) { + AuVerbose(verbose, "%d file(s) opened\n", i); + goto out; + } + + wbr = br->br_wbr; + do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph); + if (do_wh) { + /* instead of WbrWhMustWriteLock(wbr) */ + SiMustWriteLock(sb); + for (i = 0; i < AuBrWh_Last; i++) { + dput(wbr->wbr_wh[i]); + wbr->wbr_wh[i] = NULL; + } + } + + err = test_children_busy(sb->s_root, bindex, verbose); + if (unlikely(err)) { + if (do_wh) + goto out_wh; + goto out; + } + + err = 0; + br_id = br->br_id; + if (!remount) + au_br_do_del(sb, bindex, br); + else { + sysaufs_brs_del(sb, bindex); + au_br_do_del(sb, bindex, br); + sysaufs_brs_add(sb, bindex); + } + + if (!bindex) { + au_cpup_attr_all(sb->s_root->d_inode, /*force*/1); + sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes; + } else + au_sub_nlink(sb->s_root->d_inode, del->h_path.dentry->d_inode); + if (au_opt_test(mnt_flags, PLINK)) + au_plink_half_refresh(sb, br_id); + + if (au_xino_brid(sb) == br_id) + au_xino_brid_set(sb, -1); + goto out; /* success */ + +out_wh: + /* revert */ + rerr = au_br_init_wh(sb, br, br->br_perm, del->h_path.dentry); + if (rerr) + pr_warning("failed re-creating base whiteout, %s. (%d)\n", + del->pathname, rerr); +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * change a branch permission + */ + +static void au_warn_ima(void) +{ +#ifdef CONFIG_IMA + /* since it doesn't support mark_files_ro() */ + AuWarn1("RW -> RO makes IMA to produce wrong message"); +#endif +} + +static int do_need_sigen_inc(int a, int b) +{ + return au_br_whable(a) && !au_br_whable(b); +} + +static int need_sigen_inc(int old, int new) +{ + return do_need_sigen_inc(old, new) + || do_need_sigen_inc(new, old); +} + +static unsigned long long au_farray_cb(void *a, + unsigned long long max __maybe_unused, + void *arg) +{ + unsigned long long n; + struct file **p, *f; + struct super_block *sb = arg; + + n = 0; + p = a; + lg_global_lock(files_lglock); + do_file_list_for_each_entry(sb, f) { + if (au_fi(f) + && !special_file(f->f_dentry->d_inode->i_mode)) { + get_file(f); + *p++ = f; + n++; + AuDebugOn(n > max); + } + } while_file_list_for_each_entry; + lg_global_unlock(files_lglock); + + return n; +} + +static struct file **au_farray_alloc(struct super_block *sb, + unsigned long long *max) +{ + *max = atomic_long_read(&au_sbi(sb)->si_nfiles); + return au_array_alloc(max, au_farray_cb, sb); +} + +static void au_farray_free(struct file **a, unsigned long long max) +{ + unsigned long long ull; + + for (ull = 0; ull < max; ull++) + if (a[ull]) + fput(a[ull]); + au_array_free(a); +} + +static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex) +{ + int err, do_warn; + unsigned long long ull, max; + aufs_bindex_t br_id; + struct file *file, *hf, **array; + struct dentry *dentry; + struct inode *inode; + struct au_hfile *hfile; + + array = au_farray_alloc(sb, &max); + err = PTR_ERR(array); + if (IS_ERR(array)) + goto out; + + do_warn = 0; + br_id = au_sbr_id(sb, bindex); + for (ull = 0; ull < max; ull++) { + file = array[ull]; + dentry = file->f_dentry; + inode = dentry->d_inode; + + /* AuDbg("%.*s\n", AuDLNPair(file->f_dentry)); */ + fi_read_lock(file); + if (unlikely(au_test_mmapped(file))) { + err = -EBUSY; + AuDbgFile(file); + FiMustNoWaiters(file); + fi_read_unlock(file); + goto out_array; + } + + hfile = &au_fi(file)->fi_htop; + hf = hfile->hf_file; + if (!S_ISREG(inode->i_mode) + || !(file->f_mode & FMODE_WRITE) + || hfile->hf_br->br_id != br_id + || !(hf->f_mode & FMODE_WRITE)) + array[ull] = NULL; + else { + do_warn = 1; + get_file(file); + } + + FiMustNoWaiters(file); + fi_read_unlock(file); + fput(file); + } + + err = 0; + if (do_warn) + au_warn_ima(); + + for (ull = 0; ull < max; ull++) { + file = array[ull]; + if (!file) + continue; + + /* todo: already flushed? */ + /* cf. fs/super.c:mark_files_ro() */ + /* fi_read_lock(file); */ + hfile = &au_fi(file)->fi_htop; + hf = hfile->hf_file; + /* fi_read_unlock(file); */ + hf->f_mode &= ~FMODE_WRITE; + if (!file_check_writeable(hf)) { + file_release_write(hf); + mnt_drop_write(hf->f_vfsmnt); + } + } + +out_array: + au_farray_free(array, max); +out: + AuTraceErr(err); + return err; +} + +int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, + int *do_refresh) +{ + int err, rerr; + aufs_bindex_t bindex; + struct path path; + struct dentry *root; + struct au_branch *br; + + root = sb->s_root; + bindex = au_find_dbindex(root, mod->h_root); + if (bindex < 0) { + if (remount) + return 0; /* success */ + err = -ENOENT; + pr_err("%s no such branch\n", mod->path); + goto out; + } + AuDbg("bindex b%d\n", bindex); + + err = test_br(mod->h_root->d_inode, mod->perm, mod->path); + if (unlikely(err)) + goto out; + + br = au_sbr(sb, bindex); + if (br->br_perm == mod->perm) + return 0; /* success */ + + if (au_br_writable(br->br_perm)) { + /* remove whiteout base */ + err = au_br_init_wh(sb, br, mod->perm, mod->h_root); + if (unlikely(err)) + goto out; + + if (!au_br_writable(mod->perm)) { + /* rw --> ro, file might be mmapped */ + DiMustNoWaiters(root); + IiMustNoWaiters(root->d_inode); + di_write_unlock(root); + err = au_br_mod_files_ro(sb, bindex); + /* aufs_write_lock() calls ..._child() */ + di_write_lock_child(root); + + if (unlikely(err)) { + rerr = -ENOMEM; + br->br_wbr = kmalloc(sizeof(*br->br_wbr), + GFP_NOFS); + if (br->br_wbr) { + path.mnt = br->br_mnt; + path.dentry = mod->h_root; + rerr = au_wbr_init(br, sb, br->br_perm, + &path); + } + if (unlikely(rerr)) { + AuIOErr("nested error %d (%d)\n", + rerr, err); + br->br_perm = mod->perm; + } + } + } + } else if (au_br_writable(mod->perm)) { + /* ro --> rw */ + err = -ENOMEM; + br->br_wbr = kmalloc(sizeof(*br->br_wbr), GFP_NOFS); + if (br->br_wbr) { + path.mnt = br->br_mnt; + path.dentry = mod->h_root; + err = au_wbr_init(br, sb, mod->perm, &path); + if (unlikely(err)) { + kfree(br->br_wbr); + br->br_wbr = NULL; + } + } + } + + if (!err) { + *do_refresh |= need_sigen_inc(br->br_perm, mod->perm); + br->br_perm = mod->perm; + } + +out: + AuTraceErr(err); + return err; +} --- linux-2.6.37.orig/ubuntu/aufs/branch.h +++ linux-2.6.37/ubuntu/aufs/branch.h @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * branch filesystems and xino for them + */ + +#ifndef __AUFS_BRANCH_H__ +#define __AUFS_BRANCH_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include "dynop.h" +#include "rwsem.h" +#include "super.h" + +/* ---------------------------------------------------------------------- */ + +/* a xino file */ +struct au_xino_file { + struct file *xi_file; + struct mutex xi_nondir_mtx; + + /* todo: make xino files an array to support huge inode number */ + +#ifdef CONFIG_DEBUG_FS + struct dentry *xi_dbgaufs; +#endif +}; + +/* members for writable branch only */ +enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last}; +struct au_wbr { + struct au_rwsem wbr_wh_rwsem; + struct dentry *wbr_wh[AuBrWh_Last]; + atomic_t wbr_wh_running; +#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */ +#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */ +#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */ + + /* mfs mode */ + unsigned long long wbr_bytes; +}; + +/* ext2 has 3 types of operations at least, ext3 has 4 */ +#define AuBrDynOp (AuDyLast * 4) + +/* protected by superblock rwsem */ +struct au_branch { + struct au_xino_file br_xino; + + aufs_bindex_t br_id; + + int br_perm; + struct vfsmount *br_mnt; + spinlock_t br_dykey_lock; + struct au_dykey *br_dykey[AuBrDynOp]; + atomic_t br_count; + + struct au_wbr *br_wbr; + + /* xino truncation */ + blkcnt_t br_xino_upper; /* watermark in blocks */ + atomic_t br_xino_running; + +#ifdef CONFIG_SYSFS + /* an entry under sysfs per mount-point */ + char br_name[8]; + struct attribute br_attr; +#endif +}; + +/* ---------------------------------------------------------------------- */ + +/* branch permission and attribute */ +enum { + AuBrPerm_RW, /* writable, linkable wh */ + AuBrPerm_RO, /* readonly, no wh */ + AuBrPerm_RR, /* natively readonly, no wh */ + + AuBrPerm_RWNoLinkWH, /* un-linkable whiteouts */ + + AuBrPerm_ROWH, /* whiteout-able */ + AuBrPerm_RRWH, /* whiteout-able */ + + AuBrPerm_Last +}; + +static inline int au_br_writable(int brperm) +{ + return brperm == AuBrPerm_RW || brperm == AuBrPerm_RWNoLinkWH; +} + +static inline int au_br_whable(int brperm) +{ + return brperm == AuBrPerm_RW + || brperm == AuBrPerm_ROWH + || brperm == AuBrPerm_RRWH; +} + +static inline int au_br_rdonly(struct au_branch *br) +{ + return ((br->br_mnt->mnt_sb->s_flags & MS_RDONLY) + || !au_br_writable(br->br_perm)) + ? -EROFS : 0; +} + +static inline int au_br_hnotifyable(int brperm __maybe_unused) +{ +#ifdef CONFIG_AUFS_HNOTIFY + return brperm != AuBrPerm_RR && brperm != AuBrPerm_RRWH; +#else + return 0; +#endif +} + +/* ---------------------------------------------------------------------- */ + +/* branch.c */ +struct au_sbinfo; +void au_br_free(struct au_sbinfo *sinfo); +int au_br_index(struct super_block *sb, aufs_bindex_t br_id); +struct au_opt_add; +int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount); +struct au_opt_del; +int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount); +struct au_opt_mod; +int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount, + int *do_refresh); + +/* xino.c */ +static const loff_t au_loff_max = LLONG_MAX; + +int au_xib_trunc(struct super_block *sb); +ssize_t xino_fread(au_readf_t func, struct file *file, void *buf, size_t size, + loff_t *pos); +ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size, + loff_t *pos); +struct file *au_xino_create2(struct file *base_file, struct file *copy_src); +struct file *au_xino_create(struct super_block *sb, char *fname, int silent); +ino_t au_xino_new_ino(struct super_block *sb); +void au_xino_delete_inode(struct inode *inode, const int unlinked); +int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + ino_t ino); +int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + ino_t *ino); +int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t hino, + struct file *base_file, int do_test); +int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex); + +struct au_opt_xino; +int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount); +void au_xino_clr(struct super_block *sb); +struct file *au_xino_def(struct super_block *sb); +int au_xino_path(struct seq_file *seq, struct file *file); + +/* ---------------------------------------------------------------------- */ + +/* Superblock to branch */ +static inline +aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_sbr(sb, bindex)->br_id; +} + +static inline +struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_sbr(sb, bindex)->br_mnt; +} + +static inline +struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_sbr_mnt(sb, bindex)->mnt_sb; +} + +static inline void au_sbr_put(struct super_block *sb, aufs_bindex_t bindex) +{ + atomic_dec(&au_sbr(sb, bindex)->br_count); +} + +static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_sbr(sb, bindex)->br_perm; +} + +static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_br_whable(au_sbr_perm(sb, bindex)); +} + +/* ---------------------------------------------------------------------- */ + +/* + * wbr_wh_read_lock, wbr_wh_write_lock + * wbr_wh_read_unlock, wbr_wh_write_unlock, wbr_wh_downgrade_lock + */ +AuSimpleRwsemFuncs(wbr_wh, struct au_wbr *wbr, &wbr->wbr_wh_rwsem); + +#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&wbr->wbr_wh_rwsem) +#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&wbr->wbr_wh_rwsem) +#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&wbr->wbr_wh_rwsem) + +#endif /* __KERNEL__ */ +#endif /* __AUFS_BRANCH_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/conf.mk +++ linux-2.6.37/ubuntu/aufs/conf.mk @@ -0,0 +1,37 @@ + +AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS} + +define AuConf +ifdef ${1} +AuConfStr += ${1}=${${1}} +endif +endef + +AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \ + SBILIST \ + HNOTIFY HFSNOTIFY \ + EXPORT INO_T_64 \ + RDU \ + SP_IATTR \ + SHWH \ + BR_RAMFS \ + BR_FUSE POLL \ + BR_HFSPLUS \ + BDEV_LOOP \ + DEBUG MAGIC_SYSRQ +$(foreach i, ${AuConfAll}, \ + $(eval $(call AuConf,CONFIG_AUFS_${i}))) + +AuConfName = ${obj}/conf.str +${AuConfName}.tmp: FORCE + @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@ +${AuConfName}: ${AuConfName}.tmp + @diff -q $< $@ > /dev/null 2>&1 || { \ + echo ' GEN ' $@; \ + cp -p $< $@; \ + } +FORCE: +clean-files += ${AuConfName} ${AuConfName}.tmp +${obj}/sysfs.o: ${AuConfName} + +-include ${srctree}/${src}/conf_priv.mk --- linux-2.6.37.orig/ubuntu/aufs/cpup.c +++ linux-2.6.37/ubuntu/aufs/cpup.c @@ -0,0 +1,1059 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * copy-up functions, see wbr_policy.c for copy-down + */ + +#include +#include +#include +#include +#include "aufs.h" + +void au_cpup_attr_flags(struct inode *dst, struct inode *src) +{ + const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE + | S_NOATIME | S_NOCMTIME; + + dst->i_flags |= src->i_flags & ~mask; + if (au_test_fs_notime(dst->i_sb)) + dst->i_flags |= S_NOATIME | S_NOCMTIME; +} + +void au_cpup_attr_timesizes(struct inode *inode) +{ + struct inode *h_inode; + + h_inode = au_h_iptr(inode, au_ibstart(inode)); + fsstack_copy_attr_times(inode, h_inode); + fsstack_copy_inode_size(inode, h_inode); +} + +void au_cpup_attr_nlink(struct inode *inode, int force) +{ + struct inode *h_inode; + struct super_block *sb; + aufs_bindex_t bindex, bend; + + sb = inode->i_sb; + bindex = au_ibstart(inode); + h_inode = au_h_iptr(inode, bindex); + if (!force + && !S_ISDIR(h_inode->i_mode) + && au_opt_test(au_mntflags(sb), PLINK) + && au_plink_test(inode)) + return; + + inode->i_nlink = h_inode->i_nlink; + + /* + * fewer nlink makes find(1) noisy, but larger nlink doesn't. + * it may includes whplink directory. + */ + if (S_ISDIR(h_inode->i_mode)) { + bend = au_ibend(inode); + for (bindex++; bindex <= bend; bindex++) { + h_inode = au_h_iptr(inode, bindex); + if (h_inode) + au_add_nlink(inode, h_inode); + } + } +} + +void au_cpup_attr_changeable(struct inode *inode) +{ + struct inode *h_inode; + + h_inode = au_h_iptr(inode, au_ibstart(inode)); + inode->i_mode = h_inode->i_mode; + inode->i_uid = h_inode->i_uid; + inode->i_gid = h_inode->i_gid; + au_cpup_attr_timesizes(inode); + au_cpup_attr_flags(inode, h_inode); +} + +void au_cpup_igen(struct inode *inode, struct inode *h_inode) +{ + struct au_iinfo *iinfo = au_ii(inode); + + IiMustWriteLock(inode); + + iinfo->ii_higen = h_inode->i_generation; + iinfo->ii_hsb1 = h_inode->i_sb; +} + +void au_cpup_attr_all(struct inode *inode, int force) +{ + struct inode *h_inode; + + h_inode = au_h_iptr(inode, au_ibstart(inode)); + au_cpup_attr_changeable(inode); + if (inode->i_nlink > 0) + au_cpup_attr_nlink(inode, force); + inode->i_rdev = h_inode->i_rdev; + inode->i_blkbits = h_inode->i_blkbits; + au_cpup_igen(inode, h_inode); +} + +/* ---------------------------------------------------------------------- */ + +/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */ + +/* keep the timestamps of the parent dir when cpup */ +void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, + struct path *h_path) +{ + struct inode *h_inode; + + dt->dt_dentry = dentry; + dt->dt_h_path = *h_path; + h_inode = h_path->dentry->d_inode; + dt->dt_atime = h_inode->i_atime; + dt->dt_mtime = h_inode->i_mtime; + /* smp_mb(); */ +} + +void au_dtime_revert(struct au_dtime *dt) +{ + struct iattr attr; + int err; + + attr.ia_atime = dt->dt_atime; + attr.ia_mtime = dt->dt_mtime; + attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET + | ATTR_ATIME | ATTR_ATIME_SET; + + err = vfsub_notify_change(&dt->dt_h_path, &attr); + if (unlikely(err)) + pr_warning("restoring timestamps failed(%d). ignored\n", err); +} + +/* ---------------------------------------------------------------------- */ + +static noinline_for_stack +int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src) +{ + int err, sbits; + struct iattr ia; + struct path h_path; + struct inode *h_isrc, *h_idst; + + h_path.dentry = au_h_dptr(dst, bindex); + h_idst = h_path.dentry->d_inode; + h_path.mnt = au_sbr_mnt(dst->d_sb, bindex); + h_isrc = h_src->d_inode; + ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID + | ATTR_ATIME | ATTR_MTIME + | ATTR_ATIME_SET | ATTR_MTIME_SET; + ia.ia_uid = h_isrc->i_uid; + ia.ia_gid = h_isrc->i_gid; + ia.ia_atime = h_isrc->i_atime; + ia.ia_mtime = h_isrc->i_mtime; + if (h_idst->i_mode != h_isrc->i_mode + && !S_ISLNK(h_idst->i_mode)) { + ia.ia_valid |= ATTR_MODE; + ia.ia_mode = h_isrc->i_mode; + } + sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID)); + au_cpup_attr_flags(h_idst, h_isrc); + err = vfsub_notify_change(&h_path, &ia); + + /* is this nfs only? */ + if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) { + ia.ia_valid = ATTR_FORCE | ATTR_MODE; + ia.ia_mode = h_isrc->i_mode; + err = vfsub_notify_change(&h_path, &ia); + } + + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int au_do_copy_file(struct file *dst, struct file *src, loff_t len, + char *buf, unsigned long blksize) +{ + int err; + size_t sz, rbytes, wbytes; + unsigned char all_zero; + char *p, *zp; + struct mutex *h_mtx; + /* reduce stack usage */ + struct iattr *ia; + + zp = page_address(ZERO_PAGE(0)); + if (unlikely(!zp)) + return -ENOMEM; /* possible? */ + + err = 0; + all_zero = 0; + while (len) { + AuDbg("len %lld\n", len); + sz = blksize; + if (len < blksize) + sz = len; + + rbytes = 0; + /* todo: signal_pending? */ + while (!rbytes || err == -EAGAIN || err == -EINTR) { + rbytes = vfsub_read_k(src, buf, sz, &src->f_pos); + err = rbytes; + } + if (unlikely(err < 0)) + break; + + all_zero = 0; + if (len >= rbytes && rbytes == blksize) + all_zero = !memcmp(buf, zp, rbytes); + if (!all_zero) { + wbytes = rbytes; + p = buf; + while (wbytes) { + size_t b; + + b = vfsub_write_k(dst, p, wbytes, &dst->f_pos); + err = b; + /* todo: signal_pending? */ + if (unlikely(err == -EAGAIN || err == -EINTR)) + continue; + if (unlikely(err < 0)) + break; + wbytes -= b; + p += b; + } + } else { + loff_t res; + + AuLabel(hole); + res = vfsub_llseek(dst, rbytes, SEEK_CUR); + err = res; + if (unlikely(res < 0)) + break; + } + len -= rbytes; + err = 0; + } + + /* the last block may be a hole */ + if (!err && all_zero) { + AuLabel(last hole); + + err = 1; + if (au_test_nfs(dst->f_dentry->d_sb)) { + /* nfs requires this step to make last hole */ + /* is this only nfs? */ + do { + /* todo: signal_pending? */ + err = vfsub_write_k(dst, "\0", 1, &dst->f_pos); + } while (err == -EAGAIN || err == -EINTR); + if (err == 1) + dst->f_pos--; + } + + if (err == 1) { + ia = (void *)buf; + ia->ia_size = dst->f_pos; + ia->ia_valid = ATTR_SIZE | ATTR_FILE; + ia->ia_file = dst; + h_mtx = &dst->f_dentry->d_inode->i_mutex; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD2); + err = vfsub_notify_change(&dst->f_path, ia); + mutex_unlock(h_mtx); + } + } + + return err; +} + +int au_copy_file(struct file *dst, struct file *src, loff_t len) +{ + int err; + unsigned long blksize; + unsigned char do_kfree; + char *buf; + + err = -ENOMEM; + blksize = dst->f_dentry->d_sb->s_blocksize; + if (!blksize || PAGE_SIZE < blksize) + blksize = PAGE_SIZE; + AuDbg("blksize %lu\n", blksize); + do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *)); + if (do_kfree) + buf = kmalloc(blksize, GFP_NOFS); + else + buf = (void *)__get_free_page(GFP_NOFS); + if (unlikely(!buf)) + goto out; + + if (len > (1 << 22)) + AuDbg("copying a large file %lld\n", (long long)len); + + src->f_pos = 0; + dst->f_pos = 0; + err = au_do_copy_file(dst, src, len, buf, blksize); + if (do_kfree) + kfree(buf); + else + free_page((unsigned long)buf); + +out: + return err; +} + +/* + * to support a sparse file which is opened with O_APPEND, + * we need to close the file. + */ +static int au_cp_regular(struct dentry *dentry, aufs_bindex_t bdst, + aufs_bindex_t bsrc, loff_t len) +{ + int err, i; + enum { SRC, DST }; + struct { + aufs_bindex_t bindex; + unsigned int flags; + struct dentry *dentry; + struct file *file; + void *label, *label_file; + } *f, file[] = { + { + .bindex = bsrc, + .flags = O_RDONLY | O_NOATIME | O_LARGEFILE, + .file = NULL, + .label = &&out, + .label_file = &&out_src + }, + { + .bindex = bdst, + .flags = O_WRONLY | O_NOATIME | O_LARGEFILE, + .file = NULL, + .label = &&out_src, + .label_file = &&out_dst + } + }; + struct super_block *sb; + + /* bsrc branch can be ro/rw. */ + sb = dentry->d_sb; + f = file; + for (i = 0; i < 2; i++, f++) { + f->dentry = au_h_dptr(dentry, f->bindex); + f->file = au_h_open(dentry, f->bindex, f->flags, /*file*/NULL); + err = PTR_ERR(f->file); + if (IS_ERR(f->file)) + goto *f->label; + err = -EINVAL; + if (unlikely(!f->file->f_op)) + goto *f->label_file; + } + + /* try stopping to update while we copyup */ + IMustLock(file[SRC].dentry->d_inode); + err = au_copy_file(file[DST].file, file[SRC].file, len); + +out_dst: + fput(file[DST].file); + au_sbr_put(sb, file[DST].bindex); +out_src: + fput(file[SRC].file); + au_sbr_put(sb, file[SRC].bindex); +out: + return err; +} + +static int au_do_cpup_regular(struct dentry *dentry, aufs_bindex_t bdst, + aufs_bindex_t bsrc, loff_t len, + struct inode *h_dir, struct path *h_path) +{ + int err, rerr; + loff_t l; + + err = 0; + l = i_size_read(au_h_iptr(dentry->d_inode, bsrc)); + if (len == -1 || l < len) + len = l; + if (len) + err = au_cp_regular(dentry, bdst, bsrc, len); + if (!err) + goto out; /* success */ + + rerr = vfsub_unlink(h_dir, h_path, /*force*/0); + if (rerr) { + AuIOErr("failed unlinking cpup-ed %.*s(%d, %d)\n", + AuDLNPair(h_path->dentry), err, rerr); + err = -EIO; + } + +out: + return err; +} + +static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src, + struct inode *h_dir) +{ + int err, symlen; + mm_segment_t old_fs; + union { + char *k; + char __user *u; + } sym; + + err = -ENOSYS; + if (unlikely(!h_src->d_inode->i_op->readlink)) + goto out; + + err = -ENOMEM; + sym.k = __getname_gfp(GFP_NOFS); + if (unlikely(!sym.k)) + goto out; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + symlen = h_src->d_inode->i_op->readlink(h_src, sym.u, PATH_MAX); + err = symlen; + set_fs(old_fs); + + if (symlen > 0) { + sym.k[symlen] = 0; + err = vfsub_symlink(h_dir, h_path, sym.k); + } + __putname(sym.k); + +out: + return err; +} + +/* return with the lower dst inode is locked */ +static noinline_for_stack +int cpup_entry(struct dentry *dentry, aufs_bindex_t bdst, + aufs_bindex_t bsrc, loff_t len, unsigned int flags, + struct dentry *dst_parent) +{ + int err; + umode_t mode; + unsigned int mnt_flags; + unsigned char isdir; + const unsigned char do_dt = !!au_ftest_cpup(flags, DTIME); + struct au_dtime dt; + struct path h_path; + struct dentry *h_src, *h_dst, *h_parent; + struct inode *h_inode, *h_dir; + struct super_block *sb; + + /* bsrc branch can be ro/rw. */ + h_src = au_h_dptr(dentry, bsrc); + h_inode = h_src->d_inode; + AuDebugOn(h_inode != au_h_iptr(dentry->d_inode, bsrc)); + + /* try stopping to be referenced while we are creating */ + h_dst = au_h_dptr(dentry, bdst); + h_parent = h_dst->d_parent; /* dir inode is locked */ + h_dir = h_parent->d_inode; + IMustLock(h_dir); + AuDebugOn(h_parent != h_dst->d_parent); + + sb = dentry->d_sb; + h_path.mnt = au_sbr_mnt(sb, bdst); + if (do_dt) { + h_path.dentry = h_parent; + au_dtime_store(&dt, dst_parent, &h_path); + } + h_path.dentry = h_dst; + + isdir = 0; + mode = h_inode->i_mode; + switch (mode & S_IFMT) { + case S_IFREG: + /* try stopping to update while we are referencing */ + IMustLock(h_inode); + err = vfsub_create(h_dir, &h_path, mode | S_IWUSR); + if (!err) + err = au_do_cpup_regular + (dentry, bdst, bsrc, len, + au_h_iptr(dst_parent->d_inode, bdst), &h_path); + break; + case S_IFDIR: + isdir = 1; + err = vfsub_mkdir(h_dir, &h_path, mode); + if (!err) { + /* + * strange behaviour from the users view, + * particularry setattr case + */ + if (au_ibstart(dst_parent->d_inode) == bdst) + au_cpup_attr_nlink(dst_parent->d_inode, + /*force*/1); + au_cpup_attr_nlink(dentry->d_inode, /*force*/1); + } + break; + case S_IFLNK: + err = au_do_cpup_symlink(&h_path, h_src, h_dir); + break; + case S_IFCHR: + case S_IFBLK: + AuDebugOn(!capable(CAP_MKNOD)); + /*FALLTHROUGH*/ + case S_IFIFO: + case S_IFSOCK: + err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev); + break; + default: + AuIOErr("Unknown inode type 0%o\n", mode); + err = -EIO; + } + + mnt_flags = au_mntflags(sb); + if (!au_opt_test(mnt_flags, UDBA_NONE) + && !isdir + && au_opt_test(mnt_flags, XINO) + && h_inode->i_nlink == 1 + /* todo: unnecessary? */ + /* && dentry->d_inode->i_nlink == 1 */ + && bdst < bsrc + && !au_ftest_cpup(flags, KEEPLINO)) + au_xino_write(sb, bsrc, h_inode->i_ino, /*ino*/0); + /* ignore this error */ + + if (do_dt) + au_dtime_revert(&dt); + return err; +} + +/* + * copyup the @dentry from @bsrc to @bdst. + * the caller must set the both of lower dentries. + * @len is for truncating when it is -1 copyup the entire file. + * in link/rename cases, @dst_parent may be different from the real one. + */ +static int au_cpup_single(struct dentry *dentry, aufs_bindex_t bdst, + aufs_bindex_t bsrc, loff_t len, unsigned int flags, + struct dentry *dst_parent) +{ + int err, rerr; + aufs_bindex_t old_ibstart; + unsigned char isdir, plink; + struct au_dtime dt; + struct path h_path; + struct dentry *h_src, *h_dst, *h_parent; + struct inode *dst_inode, *h_dir, *inode; + struct super_block *sb; + + AuDebugOn(bsrc <= bdst); + + sb = dentry->d_sb; + h_path.mnt = au_sbr_mnt(sb, bdst); + h_dst = au_h_dptr(dentry, bdst); + h_parent = h_dst->d_parent; /* dir inode is locked */ + h_dir = h_parent->d_inode; + IMustLock(h_dir); + + h_src = au_h_dptr(dentry, bsrc); + inode = dentry->d_inode; + + if (!dst_parent) + dst_parent = dget_parent(dentry); + else + dget(dst_parent); + + plink = !!au_opt_test(au_mntflags(sb), PLINK); + dst_inode = au_h_iptr(inode, bdst); + if (dst_inode) { + if (unlikely(!plink)) { + err = -EIO; + AuIOErr("i%lu exists on a upper branch " + "but plink is disabled\n", inode->i_ino); + goto out; + } + + if (dst_inode->i_nlink) { + const int do_dt = au_ftest_cpup(flags, DTIME); + + h_src = au_plink_lkup(inode, bdst); + err = PTR_ERR(h_src); + if (IS_ERR(h_src)) + goto out; + if (unlikely(!h_src->d_inode)) { + err = -EIO; + AuIOErr("i%lu exists on a upper branch " + "but plink is broken\n", inode->i_ino); + dput(h_src); + goto out; + } + + if (do_dt) { + h_path.dentry = h_parent; + au_dtime_store(&dt, dst_parent, &h_path); + } + h_path.dentry = h_dst; + err = vfsub_link(h_src, h_dir, &h_path); + if (do_dt) + au_dtime_revert(&dt); + dput(h_src); + goto out; + } else + /* todo: cpup_wh_file? */ + /* udba work */ + au_update_ibrange(inode, /*do_put_zero*/1); + } + + old_ibstart = au_ibstart(inode); + err = cpup_entry(dentry, bdst, bsrc, len, flags, dst_parent); + if (unlikely(err)) + goto out; + dst_inode = h_dst->d_inode; + mutex_lock_nested(&dst_inode->i_mutex, AuLsc_I_CHILD2); + + err = cpup_iattr(dentry, bdst, h_src); + isdir = S_ISDIR(dst_inode->i_mode); + if (!err) { + if (bdst < old_ibstart) { + if (S_ISREG(inode->i_mode)) { + err = au_dy_iaop(inode, bdst, dst_inode); + if (unlikely(err)) + goto out_rev; + } + au_set_ibstart(inode, bdst); + } + au_set_h_iptr(inode, bdst, au_igrab(dst_inode), + au_hi_flags(inode, isdir)); + mutex_unlock(&dst_inode->i_mutex); + if (!isdir + && h_src->d_inode->i_nlink > 1 + && plink) + au_plink_append(inode, bdst, h_dst); + goto out; /* success */ + } + + /* revert */ +out_rev: + h_path.dentry = h_parent; + mutex_unlock(&dst_inode->i_mutex); + au_dtime_store(&dt, dst_parent, &h_path); + h_path.dentry = h_dst; + if (!isdir) + rerr = vfsub_unlink(h_dir, &h_path, /*force*/0); + else + rerr = vfsub_rmdir(h_dir, &h_path); + au_dtime_revert(&dt); + if (rerr) { + AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr); + err = -EIO; + } + +out: + dput(dst_parent); + return err; +} + +struct au_cpup_single_args { + int *errp; + struct dentry *dentry; + aufs_bindex_t bdst, bsrc; + loff_t len; + unsigned int flags; + struct dentry *dst_parent; +}; + +static void au_call_cpup_single(void *args) +{ + struct au_cpup_single_args *a = args; + *a->errp = au_cpup_single(a->dentry, a->bdst, a->bsrc, a->len, + a->flags, a->dst_parent); +} + +int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst, + aufs_bindex_t bsrc, loff_t len, unsigned int flags, + struct dentry *dst_parent) +{ + int err, wkq_err; + umode_t mode; + struct dentry *h_dentry; + + h_dentry = au_h_dptr(dentry, bsrc); + mode = h_dentry->d_inode->i_mode & S_IFMT; + if ((mode != S_IFCHR && mode != S_IFBLK) + || capable(CAP_MKNOD)) + err = au_cpup_single(dentry, bdst, bsrc, len, flags, + dst_parent); + else { + struct au_cpup_single_args args = { + .errp = &err, + .dentry = dentry, + .bdst = bdst, + .bsrc = bsrc, + .len = len, + .flags = flags, + .dst_parent = dst_parent + }; + wkq_err = au_wkq_wait(au_call_cpup_single, &args); + if (unlikely(wkq_err)) + err = wkq_err; + } + + return err; +} + +/* + * copyup the @dentry from the first active lower branch to @bdst, + * using au_cpup_single(). + */ +static int au_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + unsigned int flags) +{ + int err; + aufs_bindex_t bsrc, bend; + + bend = au_dbend(dentry); + for (bsrc = bdst + 1; bsrc <= bend; bsrc++) + if (au_h_dptr(dentry, bsrc)) + break; + + err = au_lkup_neg(dentry, bdst); + if (!err) { + err = au_cpup_single(dentry, bdst, bsrc, len, flags, NULL); + if (!err) + return 0; /* success */ + + /* revert */ + au_set_h_dptr(dentry, bdst, NULL); + au_set_dbstart(dentry, bsrc); + } + + return err; +} + +struct au_cpup_simple_args { + int *errp; + struct dentry *dentry; + aufs_bindex_t bdst; + loff_t len; + unsigned int flags; +}; + +static void au_call_cpup_simple(void *args) +{ + struct au_cpup_simple_args *a = args; + *a->errp = au_cpup_simple(a->dentry, a->bdst, a->len, a->flags); +} + +int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + unsigned int flags) +{ + int err, wkq_err; + unsigned char do_sio; + struct dentry *parent; + struct inode *h_dir; + + parent = dget_parent(dentry); + h_dir = au_h_iptr(parent->d_inode, bdst); + do_sio = !!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE); + if (!do_sio) { + /* + * testing CAP_MKNOD is for generic fs, + * but CAP_FSETID is for xfs only, currently. + */ + umode_t mode = dentry->d_inode->i_mode; + do_sio = (((mode & (S_IFCHR | S_IFBLK)) + && !capable(CAP_MKNOD)) + || ((mode & (S_ISUID | S_ISGID)) + && !capable(CAP_FSETID))); + } + if (!do_sio) + err = au_cpup_simple(dentry, bdst, len, flags); + else { + struct au_cpup_simple_args args = { + .errp = &err, + .dentry = dentry, + .bdst = bdst, + .len = len, + .flags = flags + }; + wkq_err = au_wkq_wait(au_call_cpup_simple, &args); + if (unlikely(wkq_err)) + err = wkq_err; + } + + dput(parent); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * copyup the deleted file for writing. + */ +static int au_do_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, + struct dentry *wh_dentry, struct file *file, + loff_t len) +{ + int err; + aufs_bindex_t bstart; + struct au_dinfo *dinfo; + struct dentry *h_d_dst, *h_d_start; + struct au_hdentry *hdp; + + dinfo = au_di(dentry); + AuRwMustWriteLock(&dinfo->di_rwsem); + + bstart = dinfo->di_bstart; + hdp = dinfo->di_hdentry; + h_d_dst = hdp[0 + bdst].hd_dentry; + dinfo->di_bstart = bdst; + hdp[0 + bdst].hd_dentry = wh_dentry; + h_d_start = hdp[0 + bstart].hd_dentry; + if (file) + hdp[0 + bstart].hd_dentry = au_hf_top(file)->f_dentry; + err = au_cpup_single(dentry, bdst, bstart, len, !AuCpup_DTIME, + /*h_parent*/NULL); + if (!err && file) { + err = au_reopen_nondir(file); + hdp[0 + bstart].hd_dentry = h_d_start; + } + hdp[0 + bdst].hd_dentry = h_d_dst; + dinfo->di_bstart = bstart; + + return err; +} + +static int au_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + struct file *file) +{ + int err; + struct au_dtime dt; + struct dentry *parent, *h_parent, *wh_dentry; + struct au_branch *br; + struct path h_path; + + br = au_sbr(dentry->d_sb, bdst); + parent = dget_parent(dentry); + h_parent = au_h_dptr(parent, bdst); + wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out; + + h_path.dentry = h_parent; + h_path.mnt = br->br_mnt; + au_dtime_store(&dt, parent, &h_path); + err = au_do_cpup_wh(dentry, bdst, wh_dentry, file, len); + if (unlikely(err)) + goto out_wh; + + dget(wh_dentry); + h_path.dentry = wh_dentry; + if (!S_ISDIR(wh_dentry->d_inode->i_mode)) + err = vfsub_unlink(h_parent->d_inode, &h_path, /*force*/0); + else + err = vfsub_rmdir(h_parent->d_inode, &h_path); + if (unlikely(err)) { + AuIOErr("failed remove copied-up tmp file %.*s(%d)\n", + AuDLNPair(wh_dentry), err); + err = -EIO; + } + au_dtime_revert(&dt); + au_set_hi_wh(dentry->d_inode, bdst, wh_dentry); + +out_wh: + dput(wh_dentry); +out: + dput(parent); + return err; +} + +struct au_cpup_wh_args { + int *errp; + struct dentry *dentry; + aufs_bindex_t bdst; + loff_t len; + struct file *file; +}; + +static void au_call_cpup_wh(void *args) +{ + struct au_cpup_wh_args *a = args; + *a->errp = au_cpup_wh(a->dentry, a->bdst, a->len, a->file); +} + +int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + struct file *file) +{ + int err, wkq_err; + struct dentry *parent, *h_orph, *h_parent, *h_dentry; + struct inode *dir, *h_dir, *h_tmpdir, *h_inode; + struct au_wbr *wbr; + + parent = dget_parent(dentry); + dir = parent->d_inode; + h_orph = NULL; + h_parent = NULL; + h_dir = au_igrab(au_h_iptr(dir, bdst)); + h_tmpdir = h_dir; + if (!h_dir->i_nlink) { + wbr = au_sbr(dentry->d_sb, bdst)->br_wbr; + h_orph = wbr->wbr_orph; + + h_parent = dget(au_h_dptr(parent, bdst)); + au_set_h_dptr(parent, bdst, dget(h_orph)); + h_tmpdir = h_orph->d_inode; + au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0); + + /* this temporary unlock is safe */ + if (file) + h_dentry = au_hf_top(file)->f_dentry; + else + h_dentry = au_h_dptr(dentry, au_dbstart(dentry)); + h_inode = h_dentry->d_inode; + IMustLock(h_inode); + mutex_unlock(&h_inode->i_mutex); + mutex_lock_nested(&h_tmpdir->i_mutex, AuLsc_I_PARENT3); + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + /* todo: au_h_open_pre()? */ + } + + if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE)) + err = au_cpup_wh(dentry, bdst, len, file); + else { + struct au_cpup_wh_args args = { + .errp = &err, + .dentry = dentry, + .bdst = bdst, + .len = len, + .file = file + }; + wkq_err = au_wkq_wait(au_call_cpup_wh, &args); + if (unlikely(wkq_err)) + err = wkq_err; + } + + if (h_orph) { + mutex_unlock(&h_tmpdir->i_mutex); + /* todo: au_h_open_post()? */ + au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0); + au_set_h_dptr(parent, bdst, h_parent); + } + iput(h_dir); + dput(parent); + + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * generic routine for both of copy-up and copy-down. + */ +/* cf. revalidate function in file.c */ +int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, + int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, + struct dentry *h_parent, void *arg), + void *arg) +{ + int err; + struct au_pin pin; + struct dentry *d, *parent, *h_parent, *real_parent; + + err = 0; + parent = dget_parent(dentry); + if (IS_ROOT(parent)) + goto out; + + au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2, + au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE); + + /* do not use au_dpage */ + real_parent = parent; + while (1) { + dput(parent); + parent = dget_parent(dentry); + h_parent = au_h_dptr(parent, bdst); + if (h_parent) + goto out; /* success */ + + /* find top dir which is necessary to cpup */ + do { + d = parent; + dput(parent); + parent = dget_parent(d); + di_read_lock_parent3(parent, !AuLock_IR); + h_parent = au_h_dptr(parent, bdst); + di_read_unlock(parent, !AuLock_IR); + } while (!h_parent); + + if (d != real_parent) + di_write_lock_child3(d); + + /* somebody else might create while we were sleeping */ + if (!au_h_dptr(d, bdst) || !au_h_dptr(d, bdst)->d_inode) { + if (au_h_dptr(d, bdst)) + au_update_dbstart(d); + + au_pin_set_dentry(&pin, d); + err = au_do_pin(&pin); + if (!err) { + err = cp(d, bdst, h_parent, arg); + au_unpin(&pin); + } + } + + if (d != real_parent) + di_write_unlock(d); + if (unlikely(err)) + break; + } + +out: + dput(parent); + return err; +} + +static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst, + struct dentry *h_parent __maybe_unused , + void *arg __maybe_unused) +{ + return au_sio_cpup_simple(dentry, bdst, -1, AuCpup_DTIME); +} + +int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) +{ + return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL); +} + +int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst) +{ + int err; + struct dentry *parent; + struct inode *dir; + + parent = dget_parent(dentry); + dir = parent->d_inode; + err = 0; + if (au_h_iptr(dir, bdst)) + goto out; + + di_read_unlock(parent, AuLock_IR); + di_write_lock_parent(parent); + /* someone else might change our inode while we were sleeping */ + if (!au_h_iptr(dir, bdst)) + err = au_cpup_dirs(dentry, bdst); + di_downgrade_lock(parent, AuLock_IR); + +out: + dput(parent); + return err; +} --- linux-2.6.37.orig/ubuntu/aufs/cpup.h +++ linux-2.6.37/ubuntu/aufs/cpup.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * copy-up/down functions + */ + +#ifndef __AUFS_CPUP_H__ +#define __AUFS_CPUP_H__ + +#ifdef __KERNEL__ + +#include +#include +#include + +struct inode; +struct file; + +void au_cpup_attr_flags(struct inode *dst, struct inode *src); +void au_cpup_attr_timesizes(struct inode *inode); +void au_cpup_attr_nlink(struct inode *inode, int force); +void au_cpup_attr_changeable(struct inode *inode); +void au_cpup_igen(struct inode *inode, struct inode *h_inode); +void au_cpup_attr_all(struct inode *inode, int force); + +/* ---------------------------------------------------------------------- */ + +/* cpup flags */ +#define AuCpup_DTIME 1 /* do dtime_store/revert */ +#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino, + for link(2) */ +#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name) +#define au_fset_cpup(flags, name) \ + do { (flags) |= AuCpup_##name; } while (0) +#define au_fclr_cpup(flags, name) \ + do { (flags) &= ~AuCpup_##name; } while (0) + +int au_copy_file(struct file *dst, struct file *src, loff_t len); +int au_sio_cpup_single(struct dentry *dentry, aufs_bindex_t bdst, + aufs_bindex_t bsrc, loff_t len, unsigned int flags, + struct dentry *dst_parent); +int au_sio_cpup_simple(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + unsigned int flags); +int au_sio_cpup_wh(struct dentry *dentry, aufs_bindex_t bdst, loff_t len, + struct file *file); + +int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst, + int (*cp)(struct dentry *dentry, aufs_bindex_t bdst, + struct dentry *h_parent, void *arg), + void *arg); +int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); +int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst); + +/* ---------------------------------------------------------------------- */ + +/* keep timestamps when copyup */ +struct au_dtime { + struct dentry *dt_dentry; + struct path dt_h_path; + struct timespec dt_atime, dt_mtime; +}; +void au_dtime_store(struct au_dtime *dt, struct dentry *dentry, + struct path *h_path); +void au_dtime_revert(struct au_dtime *dt); + +#endif /* __KERNEL__ */ +#endif /* __AUFS_CPUP_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/dbgaufs.c +++ linux-2.6.37/ubuntu/aufs/dbgaufs.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * debugfs interface + */ + +#include +#include "aufs.h" + +#ifndef CONFIG_SYSFS +#error DEBUG_FS depends upon SYSFS +#endif + +static struct dentry *dbgaufs; +static const mode_t dbgaufs_mode = S_IRUSR | S_IRGRP | S_IROTH; + +/* 20 is max digits length of ulong 64 */ +struct dbgaufs_arg { + int n; + char a[20 * 4]; +}; + +/* + * common function for all XINO files + */ +static int dbgaufs_xi_release(struct inode *inode __maybe_unused, + struct file *file) +{ + kfree(file->private_data); + return 0; +} + +static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt) +{ + int err; + struct kstat st; + struct dbgaufs_arg *p; + + err = -ENOMEM; + p = kmalloc(sizeof(*p), GFP_NOFS); + if (unlikely(!p)) + goto out; + + err = 0; + p->n = 0; + file->private_data = p; + if (!xf) + goto out; + + err = vfs_getattr(xf->f_vfsmnt, xf->f_dentry, &st); + if (!err) { + if (do_fcnt) + p->n = snprintf + (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n", + (long)file_count(xf), st.blocks, st.blksize, + (long long)st.size); + else + p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n", + st.blocks, st.blksize, + (long long)st.size); + AuDebugOn(p->n >= sizeof(p->a)); + } else { + p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err); + err = 0; + } + +out: + return err; + +} + +static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct dbgaufs_arg *p; + + p = file->private_data; + return simple_read_from_buffer(buf, count, ppos, p->a, p->n); +} + +/* ---------------------------------------------------------------------- */ + +static int dbgaufs_xib_open(struct inode *inode, struct file *file) +{ + int err; + struct au_sbinfo *sbinfo; + struct super_block *sb; + + sbinfo = inode->i_private; + sb = sbinfo->si_sb; + si_noflush_read_lock(sb); + err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0); + si_read_unlock(sb); + return err; +} + +static const struct file_operations dbgaufs_xib_fop = { + .owner = THIS_MODULE, + .open = dbgaufs_xib_open, + .release = dbgaufs_xi_release, + .read = dbgaufs_xi_read +}; + +/* ---------------------------------------------------------------------- */ + +#define DbgaufsXi_PREFIX "xi" + +static int dbgaufs_xino_open(struct inode *inode, struct file *file) +{ + int err; + long l; + struct au_sbinfo *sbinfo; + struct super_block *sb; + struct file *xf; + struct qstr *name; + + err = -ENOENT; + xf = NULL; + name = &file->f_dentry->d_name; + if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX) + || memcmp(name->name, DbgaufsXi_PREFIX, + sizeof(DbgaufsXi_PREFIX) - 1))) + goto out; + err = strict_strtol(name->name + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l); + if (unlikely(err)) + goto out; + + sbinfo = inode->i_private; + sb = sbinfo->si_sb; + si_noflush_read_lock(sb); + if (l <= au_sbend(sb)) { + xf = au_sbr(sb, (aufs_bindex_t)l)->br_xino.xi_file; + err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1); + } else + err = -ENOENT; + si_read_unlock(sb); + +out: + return err; +} + +static const struct file_operations dbgaufs_xino_fop = { + .owner = THIS_MODULE, + .open = dbgaufs_xino_open, + .release = dbgaufs_xi_release, + .read = dbgaufs_xi_read +}; + +void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) +{ + aufs_bindex_t bend; + struct au_branch *br; + struct au_xino_file *xi; + + if (!au_sbi(sb)->si_dbgaufs) + return; + + bend = au_sbend(sb); + for (; bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + xi = &br->br_xino; + if (xi->xi_dbgaufs) { + debugfs_remove(xi->xi_dbgaufs); + xi->xi_dbgaufs = NULL; + } + } +} + +void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex) +{ + struct au_sbinfo *sbinfo; + struct dentry *parent; + struct au_branch *br; + struct au_xino_file *xi; + aufs_bindex_t bend; + char name[sizeof(DbgaufsXi_PREFIX) + 5]; /* "xi" bindex NULL */ + + sbinfo = au_sbi(sb); + parent = sbinfo->si_dbgaufs; + if (!parent) + return; + + bend = au_sbend(sb); + for (; bindex <= bend; bindex++) { + snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex); + br = au_sbr(sb, bindex); + xi = &br->br_xino; + AuDebugOn(xi->xi_dbgaufs); + xi->xi_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent, + sbinfo, &dbgaufs_xino_fop); + /* ignore an error */ + if (unlikely(!xi->xi_dbgaufs)) + AuWarn1("failed %s under debugfs\n", name); + } +} + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_EXPORT +static int dbgaufs_xigen_open(struct inode *inode, struct file *file) +{ + int err; + struct au_sbinfo *sbinfo; + struct super_block *sb; + + sbinfo = inode->i_private; + sb = sbinfo->si_sb; + si_noflush_read_lock(sb); + err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0); + si_read_unlock(sb); + return err; +} + +static const struct file_operations dbgaufs_xigen_fop = { + .owner = THIS_MODULE, + .open = dbgaufs_xigen_open, + .release = dbgaufs_xi_release, + .read = dbgaufs_xi_read +}; + +static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) +{ + int err; + + /* + * This function is a dynamic '__init' fucntion actually, + * so the tiny check for si_rwsem is unnecessary. + */ + /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ + + err = -EIO; + sbinfo->si_dbgaufs_xigen = debugfs_create_file + ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, + &dbgaufs_xigen_fop); + if (sbinfo->si_dbgaufs_xigen) + err = 0; + + return err; +} +#else +static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo) +{ + return 0; +} +#endif /* CONFIG_AUFS_EXPORT */ + +/* ---------------------------------------------------------------------- */ + +void dbgaufs_si_fin(struct au_sbinfo *sbinfo) +{ + /* + * This function is a dynamic '__init' fucntion actually, + * so the tiny check for si_rwsem is unnecessary. + */ + /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ + + debugfs_remove_recursive(sbinfo->si_dbgaufs); + sbinfo->si_dbgaufs = NULL; + kobject_put(&sbinfo->si_kobj); +} + +int dbgaufs_si_init(struct au_sbinfo *sbinfo) +{ + int err; + char name[SysaufsSiNameLen]; + + /* + * This function is a dynamic '__init' fucntion actually, + * so the tiny check for si_rwsem is unnecessary. + */ + /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ + + err = -ENOENT; + if (!dbgaufs) { + AuErr1("/debug/aufs is uninitialized\n"); + goto out; + } + + err = -EIO; + sysaufs_name(sbinfo, name); + sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs); + if (unlikely(!sbinfo->si_dbgaufs)) + goto out; + kobject_get(&sbinfo->si_kobj); + + sbinfo->si_dbgaufs_xib = debugfs_create_file + ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo, + &dbgaufs_xib_fop); + if (unlikely(!sbinfo->si_dbgaufs_xib)) + goto out_dir; + + err = dbgaufs_xigen_init(sbinfo); + if (!err) + goto out; /* success */ + +out_dir: + dbgaufs_si_fin(sbinfo); +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +void dbgaufs_fin(void) +{ + debugfs_remove(dbgaufs); +} + +int __init dbgaufs_init(void) +{ + int err; + + err = -EIO; + dbgaufs = debugfs_create_dir(AUFS_NAME, NULL); + if (dbgaufs) + err = 0; + return err; +} --- linux-2.6.37.orig/ubuntu/aufs/dbgaufs.h +++ linux-2.6.37/ubuntu/aufs/dbgaufs.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * debugfs interface + */ + +#ifndef __DBGAUFS_H__ +#define __DBGAUFS_H__ + +#ifdef __KERNEL__ + +#include +#include + +struct super_block; +struct au_sbinfo; + +#ifdef CONFIG_DEBUG_FS +/* dbgaufs.c */ +void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); +void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex); +void dbgaufs_si_fin(struct au_sbinfo *sbinfo); +int dbgaufs_si_init(struct au_sbinfo *sbinfo); +void dbgaufs_fin(void); +int __init dbgaufs_init(void); +#else +AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) +AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex) +AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo) +AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo) +AuStubVoid(dbgaufs_fin, void) +AuStubInt0(__init dbgaufs_init, void) +#endif /* CONFIG_DEBUG_FS */ + +#endif /* __KERNEL__ */ +#endif /* __DBGAUFS_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/dcsub.c +++ linux-2.6.37/ubuntu/aufs/dcsub.c @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sub-routines for dentry cache + */ + +#include "aufs.h" + +static void au_dpage_free(struct au_dpage *dpage) +{ + int i; + struct dentry **p; + + p = dpage->dentries; + for (i = 0; i < dpage->ndentry; i++) + dput(*p++); + free_page((unsigned long)dpage->dentries); +} + +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp) +{ + int err; + void *p; + + err = -ENOMEM; + dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp); + if (unlikely(!dpages->dpages)) + goto out; + + p = (void *)__get_free_page(gfp); + if (unlikely(!p)) + goto out_dpages; + + dpages->dpages[0].ndentry = 0; + dpages->dpages[0].dentries = p; + dpages->ndpage = 1; + return 0; /* success */ + +out_dpages: + kfree(dpages->dpages); +out: + return err; +} + +void au_dpages_free(struct au_dcsub_pages *dpages) +{ + int i; + struct au_dpage *p; + + p = dpages->dpages; + for (i = 0; i < dpages->ndpage; i++) + au_dpage_free(p++); + kfree(dpages->dpages); +} + +static int au_dpages_append(struct au_dcsub_pages *dpages, + struct dentry *dentry, gfp_t gfp) +{ + int err, sz; + struct au_dpage *dpage; + void *p; + + dpage = dpages->dpages + dpages->ndpage - 1; + sz = PAGE_SIZE / sizeof(dentry); + if (unlikely(dpage->ndentry >= sz)) { + AuLabel(new dpage); + err = -ENOMEM; + sz = dpages->ndpage * sizeof(*dpages->dpages); + p = au_kzrealloc(dpages->dpages, sz, + sz + sizeof(*dpages->dpages), gfp); + if (unlikely(!p)) + goto out; + + dpages->dpages = p; + dpage = dpages->dpages + dpages->ndpage; + p = (void *)__get_free_page(gfp); + if (unlikely(!p)) + goto out; + + dpage->ndentry = 0; + dpage->dentries = p; + dpages->ndpage++; + } + + dpage->dentries[dpage->ndentry++] = dget(dentry); + return 0; /* success */ + +out: + return err; +} + +int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, + au_dpages_test test, void *arg) +{ + int err; + struct dentry *this_parent = root; + struct list_head *next; + struct super_block *sb = root->d_sb; + + err = 0; + spin_lock(&dcache_lock); +repeat: + next = this_parent->d_subdirs.next; +resume: + if (this_parent->d_sb == sb + && !IS_ROOT(this_parent) + && atomic_read(&this_parent->d_count) + && this_parent->d_inode + && (!test || test(this_parent, arg))) { + err = au_dpages_append(dpages, this_parent, GFP_ATOMIC); + if (unlikely(err)) + goto out; + } + + while (next != &this_parent->d_subdirs) { + struct list_head *tmp = next; + struct dentry *dentry = list_entry(tmp, struct dentry, + d_u.d_child); + next = tmp->next; + if (/*d_unhashed(dentry) || */!dentry->d_inode) + continue; + if (!list_empty(&dentry->d_subdirs)) { + this_parent = dentry; + goto repeat; + } + if (dentry->d_sb == sb + && atomic_read(&dentry->d_count) + && (!test || test(dentry, arg))) { + err = au_dpages_append(dpages, dentry, GFP_ATOMIC); + if (unlikely(err)) + goto out; + } + } + + if (this_parent != root) { + next = this_parent->d_u.d_child.next; + this_parent = this_parent->d_parent; /* dcache_lock is locked */ + goto resume; + } +out: + spin_unlock(&dcache_lock); + return err; +} + +int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, + int do_include, au_dpages_test test, void *arg) +{ + int err; + + err = 0; + spin_lock(&dcache_lock); + if (do_include && (!test || test(dentry, arg))) { + err = au_dpages_append(dpages, dentry, GFP_ATOMIC); + if (unlikely(err)) + goto out; + } + while (!IS_ROOT(dentry)) { + dentry = dentry->d_parent; /* dcache_lock is locked */ + if (!test || test(dentry, arg)) { + err = au_dpages_append(dpages, dentry, GFP_ATOMIC); + if (unlikely(err)) + break; + } + } + +out: + spin_unlock(&dcache_lock); + + return err; +} + +int au_test_subdir(struct dentry *d1, struct dentry *d2) +{ + struct path path[2] = { + { + .dentry = d1 + }, + { + .dentry = d2 + } + }; + + return path_is_under(path + 0, path + 1); +} --- linux-2.6.37.orig/ubuntu/aufs/dcsub.h +++ linux-2.6.37/ubuntu/aufs/dcsub.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sub-routines for dentry cache + */ + +#ifndef __AUFS_DCSUB_H__ +#define __AUFS_DCSUB_H__ + +#ifdef __KERNEL__ + +#include +#include + +struct dentry; + +struct au_dpage { + int ndentry; + struct dentry **dentries; +}; + +struct au_dcsub_pages { + int ndpage; + struct au_dpage *dpages; +}; + +/* ---------------------------------------------------------------------- */ + +/* dcsub.c */ +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp); +void au_dpages_free(struct au_dcsub_pages *dpages); +typedef int (*au_dpages_test)(struct dentry *dentry, void *arg); +int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root, + au_dpages_test test, void *arg); +int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry, + int do_include, au_dpages_test test, void *arg); +int au_test_subdir(struct dentry *d1, struct dentry *d2); + +/* ---------------------------------------------------------------------- */ + +static inline int au_d_removed(struct dentry *d) +{ + return !IS_ROOT(d) && d_unhashed(d); +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_DCSUB_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/debug.c +++ linux-2.6.37/ubuntu/aufs/debug.c @@ -0,0 +1,429 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * debug print functions + */ + +#include +#include +#include "aufs.h" + +int aufs_debug; +MODULE_PARM_DESC(debug, "debug print"); +module_param_named(debug, aufs_debug, int, S_IRUGO | S_IWUSR | S_IWGRP); + +char *au_plevel = KERN_DEBUG; +#define dpri(fmt, ...) do { \ + if ((au_plevel \ + && strcmp(au_plevel, KERN_DEBUG)) \ + || au_debug_test()) \ + printk("%s" fmt, au_plevel, ##__VA_ARGS__); \ +} while (0) + +/* ---------------------------------------------------------------------- */ + +void au_dpri_whlist(struct au_nhash *whlist) +{ + unsigned long ul, n; + struct hlist_head *head; + struct au_vdir_wh *tpos; + struct hlist_node *pos; + + n = whlist->nh_num; + head = whlist->nh_head; + for (ul = 0; ul < n; ul++) { + hlist_for_each_entry(tpos, pos, head, wh_hash) + dpri("b%d, %.*s, %d\n", + tpos->wh_bindex, + tpos->wh_str.len, tpos->wh_str.name, + tpos->wh_str.len); + head++; + } +} + +void au_dpri_vdir(struct au_vdir *vdir) +{ + unsigned long ul; + union au_vdir_deblk_p p; + unsigned char *o; + + if (!vdir || IS_ERR(vdir)) { + dpri("err %ld\n", PTR_ERR(vdir)); + return; + } + + dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %lu\n", + vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk, + vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version); + for (ul = 0; ul < vdir->vd_nblk; ul++) { + p.deblk = vdir->vd_deblk[ul]; + o = p.deblk; + dpri("[%lu]: %p\n", ul, o); + } +} + +static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, + struct dentry *wh) +{ + char *n = NULL; + int l = 0; + + if (!inode || IS_ERR(inode)) { + dpri("i%d: err %ld\n", bindex, PTR_ERR(inode)); + return -1; + } + + /* the type of i_blocks depends upon CONFIG_LSF */ + BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long) + && sizeof(inode->i_blocks) != sizeof(u64)); + if (wh) { + n = (void *)wh->d_name.name; + l = wh->d_name.len; + } + + dpri("i%d: i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu," + " ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n", + bindex, + inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??", + atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode, + i_size_read(inode), (unsigned long long)inode->i_blocks, + (long long)timespec_to_ns(&inode->i_ctime) & 0x0ffff, + inode->i_mapping ? inode->i_mapping->nrpages : 0, + inode->i_state, inode->i_flags, inode->i_version, + inode->i_generation, + l ? ", wh " : "", l, n); + return 0; +} + +void au_dpri_inode(struct inode *inode) +{ + struct au_iinfo *iinfo; + aufs_bindex_t bindex; + int err; + + err = do_pri_inode(-1, inode, NULL); + if (err || !au_test_aufs(inode->i_sb)) + return; + + iinfo = au_ii(inode); + if (!iinfo) + return; + dpri("i-1: bstart %d, bend %d, gen %d\n", + iinfo->ii_bstart, iinfo->ii_bend, au_iigen(inode)); + if (iinfo->ii_bstart < 0) + return; + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; bindex++) + do_pri_inode(bindex, iinfo->ii_hinode[0 + bindex].hi_inode, + iinfo->ii_hinode[0 + bindex].hi_whdentry); +} + +static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry) +{ + struct dentry *wh = NULL; + + if (!dentry || IS_ERR(dentry)) { + dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry)); + return -1; + } + /* do not call dget_parent() here */ + dpri("d%d: %.*s?/%.*s, %s, cnt %d, flags 0x%x\n", + bindex, + AuDLNPair(dentry->d_parent), AuDLNPair(dentry), + dentry->d_sb ? au_sbtype(dentry->d_sb) : "??", + atomic_read(&dentry->d_count), dentry->d_flags); + if (bindex >= 0 && dentry->d_inode && au_test_aufs(dentry->d_sb)) { + struct au_iinfo *iinfo = au_ii(dentry->d_inode); + if (iinfo) + wh = iinfo->ii_hinode[0 + bindex].hi_whdentry; + } + do_pri_inode(bindex, dentry->d_inode, wh); + return 0; +} + +void au_dpri_dentry(struct dentry *dentry) +{ + struct au_dinfo *dinfo; + aufs_bindex_t bindex; + int err; + struct au_hdentry *hdp; + + err = do_pri_dentry(-1, dentry); + if (err || !au_test_aufs(dentry->d_sb)) + return; + + dinfo = au_di(dentry); + if (!dinfo) + return; + dpri("d-1: bstart %d, bend %d, bwh %d, bdiropq %d, gen %d\n", + dinfo->di_bstart, dinfo->di_bend, + dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry)); + if (dinfo->di_bstart < 0) + return; + hdp = dinfo->di_hdentry; + for (bindex = dinfo->di_bstart; bindex <= dinfo->di_bend; bindex++) + do_pri_dentry(bindex, hdp[0 + bindex].hd_dentry); +} + +static int do_pri_file(aufs_bindex_t bindex, struct file *file) +{ + char a[32]; + + if (!file || IS_ERR(file)) { + dpri("f%d: err %ld\n", bindex, PTR_ERR(file)); + return -1; + } + a[0] = 0; + if (bindex < 0 + && file->f_dentry + && au_test_aufs(file->f_dentry->d_sb) + && au_fi(file)) + snprintf(a, sizeof(a), ", gen %d, mmapped %d", + au_figen(file), !!au_fi(file)->fi_hvmop); + dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n", + bindex, file->f_mode, file->f_flags, (long)file_count(file), + file->f_version, file->f_pos, a); + if (file->f_dentry) + do_pri_dentry(bindex, file->f_dentry); + return 0; +} + +void au_dpri_file(struct file *file) +{ + struct au_finfo *finfo; + struct au_fidir *fidir; + struct au_hfile *hfile; + aufs_bindex_t bindex; + int err; + + err = do_pri_file(-1, file); + if (err || !file->f_dentry || !au_test_aufs(file->f_dentry->d_sb)) + return; + + finfo = au_fi(file); + if (!finfo) + return; + if (finfo->fi_btop < 0) + return; + fidir = finfo->fi_hdir; + if (!fidir) + do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file); + else + for (bindex = finfo->fi_btop; + bindex >= 0 && bindex <= fidir->fd_bbot; + bindex++) { + hfile = fidir->fd_hfile + bindex; + do_pri_file(bindex, hfile ? hfile->hf_file : NULL); + } +} + +static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br) +{ + struct vfsmount *mnt; + struct super_block *sb; + + if (!br || IS_ERR(br)) + goto out; + mnt = br->br_mnt; + if (!mnt || IS_ERR(mnt)) + goto out; + sb = mnt->mnt_sb; + if (!sb || IS_ERR(sb)) + goto out; + + dpri("s%d: {perm 0x%x, cnt %d, wbr %p}, " + "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, " + "xino %d\n", + bindex, br->br_perm, atomic_read(&br->br_count), br->br_wbr, + au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev), + sb->s_flags, sb->s_count, + atomic_read(&sb->s_active), !!br->br_xino.xi_file); + return 0; + +out: + dpri("s%d: err %ld\n", bindex, PTR_ERR(br)); + return -1; +} + +void au_dpri_sb(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + aufs_bindex_t bindex; + int err; + /* to reuduce stack size */ + struct { + struct vfsmount mnt; + struct au_branch fake; + } *a; + + /* this function can be called from magic sysrq */ + a = kzalloc(sizeof(*a), GFP_ATOMIC); + if (unlikely(!a)) { + dpri("no memory\n"); + return; + } + + a->mnt.mnt_sb = sb; + a->fake.br_perm = 0; + a->fake.br_mnt = &a->mnt; + a->fake.br_xino.xi_file = NULL; + atomic_set(&a->fake.br_count, 0); + smp_mb(); /* atomic_set */ + err = do_pri_br(-1, &a->fake); + kfree(a); + dpri("dev 0x%x\n", sb->s_dev); + if (err || !au_test_aufs(sb)) + return; + + sbinfo = au_sbi(sb); + if (!sbinfo) + return; + dpri("nw %d, gen %u, kobj %d\n", + atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation, + atomic_read(&sbinfo->si_kobj.kref.refcount)); + for (bindex = 0; bindex <= sbinfo->si_bend; bindex++) + do_pri_br(bindex, sbinfo->si_branch[0 + bindex]); +} + +/* ---------------------------------------------------------------------- */ + +void au_dbg_sleep_jiffy(int jiffy) +{ + while (jiffy) + jiffy = schedule_timeout_uninterruptible(jiffy); +} + +void au_dbg_iattr(struct iattr *ia) +{ +#define AuBit(name) if (ia->ia_valid & ATTR_ ## name) \ + dpri(#name "\n") + AuBit(MODE); + AuBit(UID); + AuBit(GID); + AuBit(SIZE); + AuBit(ATIME); + AuBit(MTIME); + AuBit(CTIME); + AuBit(ATIME_SET); + AuBit(MTIME_SET); + AuBit(FORCE); + AuBit(ATTR_FLAG); + AuBit(KILL_SUID); + AuBit(KILL_SGID); + AuBit(FILE); + AuBit(KILL_PRIV); + AuBit(OPEN); + AuBit(TIMES_SET); +#undef AuBit + dpri("ia_file %p\n", ia->ia_file); +} + +/* ---------------------------------------------------------------------- */ + +void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen) +{ + struct dentry *parent; + + parent = dget_parent(dentry); + AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode) + || IS_ROOT(dentry) + || au_digen(parent) != sigen); + dput(parent); +} + +void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen) +{ + struct dentry *parent; + + parent = dget_parent(dentry); + AuDebugOn(S_ISDIR(dentry->d_inode->i_mode) + || au_digen(parent) != sigen); + dput(parent); +} + +void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen) +{ + int err, i, j; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + struct dentry **dentries; + + err = au_dpages_init(&dpages, GFP_NOFS); + AuDebugOn(err); + err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/1, NULL, NULL); + AuDebugOn(err); + for (i = dpages.ndpage - 1; !err && i >= 0; i--) { + dpage = dpages.dpages + i; + dentries = dpage->dentries; + for (j = dpage->ndentry - 1; !err && j >= 0; j--) + AuDebugOn(au_digen(dentries[j]) != sigen); + } + au_dpages_free(&dpages); +} + +void au_dbg_verify_kthread(void) +{ + if (current->flags & PF_WQ_WORKER) { + au_dbg_blocked(); + WARN_ON(1); + } +} + +/* ---------------------------------------------------------------------- */ + +void au_debug_sbinfo_init(struct au_sbinfo *sbinfo __maybe_unused) +{ +#ifdef AuForceNoPlink + au_opt_clr(sbinfo->si_mntflags, PLINK); +#endif +#ifdef AuForceNoXino + au_opt_clr(sbinfo->si_mntflags, XINO); +#endif +#ifdef AuForceNoRefrof + au_opt_clr(sbinfo->si_mntflags, REFROF); +#endif +#ifdef AuForceHnotify + au_opt_set_udba(sbinfo->si_mntflags, UDBA_HNOTIFY); +#endif +#ifdef AuForceRd0 + sbinfo->si_rdblk = 0; + sbinfo->si_rdhash = 0; +#endif +} + +int __init au_debug_init(void) +{ + aufs_bindex_t bindex; + struct au_vdir_destr destr; + + bindex = -1; + AuDebugOn(bindex >= 0); + + destr.len = -1; + AuDebugOn(destr.len < NAME_MAX); + +#ifdef CONFIG_4KSTACKS + pr_warning("CONFIG_4KSTACKS is defined.\n"); +#endif + +#ifdef AuForceNoBrs + sysaufs_brs = 0; +#endif + + return 0; +} --- linux-2.6.37.orig/ubuntu/aufs/debug.h +++ linux-2.6.37/ubuntu/aufs/debug.h @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * debug print functions + */ + +#ifndef __AUFS_DEBUG_H__ +#define __AUFS_DEBUG_H__ + +#ifdef __KERNEL__ + +#include +#include +/* #include */ +#include +#include +#include +/* #include */ +#include +/* #include */ +#include +#include + +#include + +#ifdef CONFIG_AUFS_DEBUG +#define AuDebugOn(a) BUG_ON(a) + +/* module parameter */ +extern int aufs_debug; +static inline void au_debug(int n) +{ + aufs_debug = n; + smp_mb(); +} + +static inline int au_debug_test(void) +{ + return aufs_debug; +} +#else +#define AuDebugOn(a) do {} while (0) +AuStubVoid(au_debug, int n) +AuStubInt0(au_debug_test, void) +#endif /* CONFIG_AUFS_DEBUG */ + +/* ---------------------------------------------------------------------- */ + +/* debug print */ + +#define AuDbg(fmt, ...) do { \ + if (au_debug_test()) \ + pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \ +} while (0) +#define AuLabel(l) AuDbg(#l "\n") +#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__) +#define AuWarn1(fmt, ...) do { \ + static unsigned char _c; \ + if (!_c++) \ + pr_warning(fmt, ##__VA_ARGS__); \ +} while (0) + +#define AuErr1(fmt, ...) do { \ + static unsigned char _c; \ + if (!_c++) \ + pr_err(fmt, ##__VA_ARGS__); \ +} while (0) + +#define AuIOErr1(fmt, ...) do { \ + static unsigned char _c; \ + if (!_c++) \ + AuIOErr(fmt, ##__VA_ARGS__); \ +} while (0) + +#define AuUnsupportMsg "This operation is not supported." \ + " Please report this application to aufs-users ML." +#define AuUnsupport(fmt, ...) do { \ + pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \ + dump_stack(); \ +} while (0) + +#define AuTraceErr(e) do { \ + if (unlikely((e) < 0)) \ + AuDbg("err %d\n", (int)(e)); \ +} while (0) + +#define AuTraceErrPtr(p) do { \ + if (IS_ERR(p)) \ + AuDbg("err %ld\n", PTR_ERR(p)); \ +} while (0) + +/* dirty macros for debug print, use with "%.*s" and caution */ +#define AuLNPair(qstr) (qstr)->len, (qstr)->name +#define AuDLNPair(d) AuLNPair(&(d)->d_name) + +/* ---------------------------------------------------------------------- */ + +struct au_sbinfo; +struct au_finfo; +struct dentry; +#ifdef CONFIG_AUFS_DEBUG +extern char *au_plevel; +struct au_nhash; +void au_dpri_whlist(struct au_nhash *whlist); +struct au_vdir; +void au_dpri_vdir(struct au_vdir *vdir); +struct inode; +void au_dpri_inode(struct inode *inode); +void au_dpri_dentry(struct dentry *dentry); +struct file; +void au_dpri_file(struct file *filp); +struct super_block; +void au_dpri_sb(struct super_block *sb); + +void au_dbg_sleep_jiffy(int jiffy); +struct iattr; +void au_dbg_iattr(struct iattr *ia); + +void au_dbg_verify_dir_parent(struct dentry *dentry, unsigned int sigen); +void au_dbg_verify_nondir_parent(struct dentry *dentry, unsigned int sigen); +void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen); +void au_dbg_verify_kthread(void); + +int __init au_debug_init(void); +void au_debug_sbinfo_init(struct au_sbinfo *sbinfo); +#define AuDbgWhlist(w) do { \ + AuDbg(#w "\n"); \ + au_dpri_whlist(w); \ +} while (0) + +#define AuDbgVdir(v) do { \ + AuDbg(#v "\n"); \ + au_dpri_vdir(v); \ +} while (0) + +#define AuDbgInode(i) do { \ + AuDbg(#i "\n"); \ + au_dpri_inode(i); \ +} while (0) + +#define AuDbgDentry(d) do { \ + AuDbg(#d "\n"); \ + au_dpri_dentry(d); \ +} while (0) + +#define AuDbgFile(f) do { \ + AuDbg(#f "\n"); \ + au_dpri_file(f); \ +} while (0) + +#define AuDbgSb(sb) do { \ + AuDbg(#sb "\n"); \ + au_dpri_sb(sb); \ +} while (0) + +#define AuDbgSleep(sec) do { \ + AuDbg("sleep %d sec\n", sec); \ + ssleep(sec); \ +} while (0) + +#define AuDbgSleepJiffy(jiffy) do { \ + AuDbg("sleep %d jiffies\n", jiffy); \ + au_dbg_sleep_jiffy(jiffy); \ +} while (0) + +#define AuDbgIAttr(ia) do { \ + AuDbg("ia_valid 0x%x\n", (ia)->ia_valid); \ + au_dbg_iattr(ia); \ +} while (0) + +#define AuDbgSym(addr) do { \ + char sym[KSYM_SYMBOL_LEN]; \ + sprint_symbol(sym, (unsigned long)addr); \ + AuDbg("%s\n", sym); \ +} while (0) + +#define AuInfoSym(addr) do { \ + char sym[KSYM_SYMBOL_LEN]; \ + sprint_symbol(sym, (unsigned long)addr); \ + AuInfo("%s\n", sym); \ +} while (0) +#else +AuStubVoid(au_dbg_verify_dir_parent, struct dentry *dentry, unsigned int sigen) +AuStubVoid(au_dbg_verify_nondir_parent, struct dentry *dentry, + unsigned int sigen) +AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen) +AuStubVoid(au_dbg_verify_kthread, void) +AuStubInt0(__init au_debug_init, void) +AuStubVoid(au_debug_sbinfo_init, struct au_sbinfo *sbinfo) + +#define AuDbgWhlist(w) do {} while (0) +#define AuDbgVdir(v) do {} while (0) +#define AuDbgInode(i) do {} while (0) +#define AuDbgDentry(d) do {} while (0) +#define AuDbgFile(f) do {} while (0) +#define AuDbgSb(sb) do {} while (0) +#define AuDbgSleep(sec) do {} while (0) +#define AuDbgSleepJiffy(jiffy) do {} while (0) +#define AuDbgIAttr(ia) do {} while (0) +#define AuDbgSym(addr) do {} while (0) +#define AuInfoSym(addr) do {} while (0) +#endif /* CONFIG_AUFS_DEBUG */ + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_MAGIC_SYSRQ +int __init au_sysrq_init(void); +void au_sysrq_fin(void); + +#ifdef CONFIG_HW_CONSOLE +#define au_dbg_blocked() do { \ + WARN_ON(1); \ + handle_sysrq('w'); \ +} while (0) +#else +AuStubVoid(au_dbg_blocked, void) +#endif + +#else +AuStubInt0(__init au_sysrq_init, void) +AuStubVoid(au_sysrq_fin, void) +AuStubVoid(au_dbg_blocked, void) +#endif /* CONFIG_AUFS_MAGIC_SYSRQ */ + +#endif /* __KERNEL__ */ +#endif /* __AUFS_DEBUG_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/dentry.c +++ linux-2.6.37/ubuntu/aufs/dentry.c @@ -0,0 +1,863 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * lookup and dentry operations + */ + +#include +#include "aufs.h" + +static void au_h_nd(struct nameidata *h_nd, struct nameidata *nd) +{ + if (nd) { + *h_nd = *nd; + + /* + * gave up supporting LOOKUP_CREATE/OPEN for lower fs, + * due to whiteout and branch permission. + */ + h_nd->flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE + | LOOKUP_FOLLOW | LOOKUP_EXCL); + /* unnecessary? */ + h_nd->intent.open.file = NULL; + } else + memset(h_nd, 0, sizeof(*h_nd)); +} + +struct au_lkup_one_args { + struct dentry **errp; + struct qstr *name; + struct dentry *h_parent; + struct au_branch *br; + struct nameidata *nd; +}; + +struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent, + struct au_branch *br, struct nameidata *nd) +{ + struct dentry *h_dentry; + int err; + struct nameidata h_nd; + + if (au_test_fs_null_nd(h_parent->d_sb)) + return vfsub_lookup_one_len(name->name, h_parent, name->len); + + au_h_nd(&h_nd, nd); + h_nd.path.dentry = h_parent; + h_nd.path.mnt = br->br_mnt; + + err = __lookup_one_len(name->name, &h_nd.last, NULL, name->len); + h_dentry = ERR_PTR(err); + if (!err) { + path_get(&h_nd.path); + h_dentry = vfsub_lookup_hash(&h_nd); + path_put(&h_nd.path); + } + + AuTraceErrPtr(h_dentry); + return h_dentry; +} + +static void au_call_lkup_one(void *args) +{ + struct au_lkup_one_args *a = args; + *a->errp = au_lkup_one(a->name, a->h_parent, a->br, a->nd); +} + +#define AuLkup_ALLOW_NEG 1 +#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name) +#define au_fset_lkup(flags, name) \ + do { (flags) |= AuLkup_##name; } while (0) +#define au_fclr_lkup(flags, name) \ + do { (flags) &= ~AuLkup_##name; } while (0) + +struct au_do_lookup_args { + unsigned int flags; + mode_t type; + struct nameidata *nd; +}; + +/* + * returns positive/negative dentry, NULL or an error. + * NULL means whiteout-ed or not-found. + */ +static struct dentry* +au_do_lookup(struct dentry *h_parent, struct dentry *dentry, + aufs_bindex_t bindex, struct qstr *wh_name, + struct au_do_lookup_args *args) +{ + struct dentry *h_dentry; + struct inode *h_inode, *inode; + struct au_branch *br; + int wh_found, opq; + unsigned char wh_able; + const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG); + + wh_found = 0; + br = au_sbr(dentry->d_sb, bindex); + wh_able = !!au_br_whable(br->br_perm); + if (wh_able) + wh_found = au_wh_test(h_parent, wh_name, br, /*try_sio*/0); + h_dentry = ERR_PTR(wh_found); + if (!wh_found) + goto real_lookup; + if (unlikely(wh_found < 0)) + goto out; + + /* We found a whiteout */ + /* au_set_dbend(dentry, bindex); */ + au_set_dbwh(dentry, bindex); + if (!allow_neg) + return NULL; /* success */ + +real_lookup: + h_dentry = au_lkup_one(&dentry->d_name, h_parent, br, args->nd); + if (IS_ERR(h_dentry)) + goto out; + + h_inode = h_dentry->d_inode; + if (!h_inode) { + if (!allow_neg) + goto out_neg; + } else if (wh_found + || (args->type && args->type != (h_inode->i_mode & S_IFMT))) + goto out_neg; + + if (au_dbend(dentry) <= bindex) + au_set_dbend(dentry, bindex); + if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry)) + au_set_dbstart(dentry, bindex); + au_set_h_dptr(dentry, bindex, h_dentry); + + inode = dentry->d_inode; + if (!h_inode || !S_ISDIR(h_inode->i_mode) || !wh_able + || (inode && !S_ISDIR(inode->i_mode))) + goto out; /* success */ + + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + opq = au_diropq_test(h_dentry, br); + mutex_unlock(&h_inode->i_mutex); + if (opq > 0) + au_set_dbdiropq(dentry, bindex); + else if (unlikely(opq < 0)) { + au_set_h_dptr(dentry, bindex, NULL); + h_dentry = ERR_PTR(opq); + } + goto out; + +out_neg: + dput(h_dentry); + h_dentry = NULL; +out: + return h_dentry; +} + +static int au_test_shwh(struct super_block *sb, const struct qstr *name) +{ + if (unlikely(!au_opt_test(au_mntflags(sb), SHWH) + && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))) + return -EPERM; + return 0; +} + +/* + * returns the number of lower positive dentries, + * otherwise an error. + * can be called at unlinking with @type is zero. + */ +int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type, + struct nameidata *nd) +{ + int npositive, err; + aufs_bindex_t bindex, btail, bdiropq; + unsigned char isdir; + struct qstr whname; + struct au_do_lookup_args args = { + .flags = 0, + .type = type, + .nd = nd + }; + const struct qstr *name = &dentry->d_name; + struct dentry *parent; + struct inode *inode; + + err = au_test_shwh(dentry->d_sb, name); + if (unlikely(err)) + goto out; + + err = au_wh_name_alloc(&whname, name); + if (unlikely(err)) + goto out; + + inode = dentry->d_inode; + isdir = !!(inode && S_ISDIR(inode->i_mode)); + if (!type) + au_fset_lkup(args.flags, ALLOW_NEG); + + npositive = 0; + parent = dget_parent(dentry); + btail = au_dbtaildir(parent); + for (bindex = bstart; bindex <= btail; bindex++) { + struct dentry *h_parent, *h_dentry; + struct inode *h_inode, *h_dir; + + h_dentry = au_h_dptr(dentry, bindex); + if (h_dentry) { + if (h_dentry->d_inode) + npositive++; + if (type != S_IFDIR) + break; + continue; + } + h_parent = au_h_dptr(parent, bindex); + if (!h_parent) + continue; + h_dir = h_parent->d_inode; + if (!h_dir || !S_ISDIR(h_dir->i_mode)) + continue; + + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); + h_dentry = au_do_lookup(h_parent, dentry, bindex, &whname, + &args); + mutex_unlock(&h_dir->i_mutex); + err = PTR_ERR(h_dentry); + if (IS_ERR(h_dentry)) + goto out_parent; + au_fclr_lkup(args.flags, ALLOW_NEG); + + if (au_dbwh(dentry) >= 0) + break; + if (!h_dentry) + continue; + h_inode = h_dentry->d_inode; + if (!h_inode) + continue; + npositive++; + if (!args.type) + args.type = h_inode->i_mode & S_IFMT; + if (args.type != S_IFDIR) + break; + else if (isdir) { + /* the type of lower may be different */ + bdiropq = au_dbdiropq(dentry); + if (bdiropq >= 0 && bdiropq <= bindex) + break; + } + } + + if (npositive) { + AuLabel(positive); + au_update_dbstart(dentry); + } + err = npositive; + if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE) + && au_dbstart(dentry) < 0)) + /* both of real entry and whiteout found */ + err = -EIO; + +out_parent: + dput(parent); + kfree(whname.name); +out: + return err; +} + +struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent, + struct au_branch *br) +{ + struct dentry *dentry; + int wkq_err; + + if (!au_test_h_perm_sio(parent->d_inode, MAY_EXEC)) + dentry = au_lkup_one(name, parent, br, /*nd*/NULL); + else { + struct au_lkup_one_args args = { + .errp = &dentry, + .name = name, + .h_parent = parent, + .br = br, + .nd = NULL + }; + + wkq_err = au_wkq_wait(au_call_lkup_one, &args); + if (unlikely(wkq_err)) + dentry = ERR_PTR(wkq_err); + } + + return dentry; +} + +/* + * lookup @dentry on @bindex which should be negative. + */ +int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex) +{ + int err; + struct dentry *parent, *h_parent, *h_dentry; + + parent = dget_parent(dentry); + h_parent = au_h_dptr(parent, bindex); + h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent, + au_sbr(dentry->d_sb, bindex)); + err = PTR_ERR(h_dentry); + if (IS_ERR(h_dentry)) + goto out; + if (unlikely(h_dentry->d_inode)) { + err = -EIO; + AuIOErr("b%d %.*s should be negative.\n", + bindex, AuDLNPair(h_dentry)); + dput(h_dentry); + goto out; + } + + err = 0; + if (bindex < au_dbstart(dentry)) + au_set_dbstart(dentry, bindex); + if (au_dbend(dentry) < bindex) + au_set_dbend(dentry, bindex); + au_set_h_dptr(dentry, bindex, h_dentry); + +out: + dput(parent); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* subset of struct inode */ +struct au_iattr { + unsigned long i_ino; + /* unsigned int i_nlink; */ + uid_t i_uid; + gid_t i_gid; + u64 i_version; +/* + loff_t i_size; + blkcnt_t i_blocks; +*/ + umode_t i_mode; +}; + +static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode) +{ + ia->i_ino = h_inode->i_ino; + /* ia->i_nlink = h_inode->i_nlink; */ + ia->i_uid = h_inode->i_uid; + ia->i_gid = h_inode->i_gid; + ia->i_version = h_inode->i_version; +/* + ia->i_size = h_inode->i_size; + ia->i_blocks = h_inode->i_blocks; +*/ + ia->i_mode = (h_inode->i_mode & S_IFMT); +} + +static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode) +{ + return ia->i_ino != h_inode->i_ino + /* || ia->i_nlink != h_inode->i_nlink */ + || ia->i_uid != h_inode->i_uid + || ia->i_gid != h_inode->i_gid + || ia->i_version != h_inode->i_version +/* + || ia->i_size != h_inode->i_size + || ia->i_blocks != h_inode->i_blocks +*/ + || ia->i_mode != (h_inode->i_mode & S_IFMT); +} + +static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent, + struct au_branch *br) +{ + int err; + struct au_iattr ia; + struct inode *h_inode; + struct dentry *h_d; + struct super_block *h_sb; + + err = 0; + memset(&ia, -1, sizeof(ia)); + h_sb = h_dentry->d_sb; + h_inode = h_dentry->d_inode; + if (h_inode) + au_iattr_save(&ia, h_inode); + else if (au_test_nfs(h_sb) || au_test_fuse(h_sb)) + /* nfs d_revalidate may return 0 for negative dentry */ + /* fuse d_revalidate always return 0 for negative dentry */ + goto out; + + /* main purpose is namei.c:cached_lookup() and d_revalidate */ + h_d = au_lkup_one(&h_dentry->d_name, h_parent, br, /*nd*/NULL); + err = PTR_ERR(h_d); + if (IS_ERR(h_d)) + goto out; + + err = 0; + if (unlikely(h_d != h_dentry + || h_d->d_inode != h_inode + || (h_inode && au_iattr_test(&ia, h_inode)))) + err = au_busy_or_stale(); + dput(h_d); + +out: + AuTraceErr(err); + return err; +} + +int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, + struct dentry *h_parent, struct au_branch *br) +{ + int err; + + err = 0; + if (udba == AuOpt_UDBA_REVAL) { + IMustLock(h_dir); + err = (h_dentry->d_parent->d_inode != h_dir); + } else if (udba == AuOpt_UDBA_HNOTIFY) + err = au_h_verify_dentry(h_dentry, h_parent, br); + + return err; +} + +/* ---------------------------------------------------------------------- */ + +static void au_do_refresh_hdentry(struct au_hdentry *p, struct au_dinfo *dinfo, + struct dentry *parent) +{ + struct dentry *h_d, *h_dp; + struct au_hdentry tmp, *q; + struct super_block *sb; + aufs_bindex_t new_bindex, bindex, bend, bwh, bdiropq; + + AuRwMustWriteLock(&dinfo->di_rwsem); + + bend = dinfo->di_bend; + bwh = dinfo->di_bwh; + bdiropq = dinfo->di_bdiropq; + for (bindex = dinfo->di_bstart; bindex <= bend; bindex++, p++) { + h_d = p->hd_dentry; + if (!h_d) + continue; + + h_dp = dget_parent(h_d); + if (h_dp == au_h_dptr(parent, bindex)) { + dput(h_dp); + continue; + } + + new_bindex = au_find_dbindex(parent, h_dp); + dput(h_dp); + if (dinfo->di_bwh == bindex) + bwh = new_bindex; + if (dinfo->di_bdiropq == bindex) + bdiropq = new_bindex; + if (new_bindex < 0) { + au_hdput(p); + p->hd_dentry = NULL; + continue; + } + + /* swap two lower dentries, and loop again */ + q = dinfo->di_hdentry + new_bindex; + tmp = *q; + *q = *p; + *p = tmp; + if (tmp.hd_dentry) { + bindex--; + p--; + } + } + + sb = parent->d_sb; + dinfo->di_bwh = -1; + if (bwh >= 0 && bwh <= au_sbend(sb) && au_sbr_whable(sb, bwh)) + dinfo->di_bwh = bwh; + + dinfo->di_bdiropq = -1; + if (bdiropq >= 0 + && bdiropq <= au_sbend(sb) + && au_sbr_whable(sb, bdiropq)) + dinfo->di_bdiropq = bdiropq; + + bend = au_dbend(parent); + p = dinfo->di_hdentry; + for (bindex = 0; bindex <= bend; bindex++, p++) + if (p->hd_dentry) { + dinfo->di_bstart = bindex; + break; + } + + p = dinfo->di_hdentry + bend; + for (bindex = bend; bindex >= 0; bindex--, p--) + if (p->hd_dentry) { + dinfo->di_bend = bindex; + break; + } +} + +/* + * returns the number of found lower positive dentries, + * otherwise an error. + */ +int au_refresh_hdentry(struct dentry *dentry, mode_t type) +{ + int npositive, err; + unsigned int sigen; + aufs_bindex_t bstart; + struct au_dinfo *dinfo; + struct super_block *sb; + struct dentry *parent; + + DiMustWriteLock(dentry); + + sb = dentry->d_sb; + AuDebugOn(IS_ROOT(dentry)); + sigen = au_sigen(sb); + parent = dget_parent(dentry); + AuDebugOn(au_digen(parent) != sigen + || au_iigen(parent->d_inode) != sigen); + + dinfo = au_di(dentry); + err = au_di_realloc(dinfo, au_sbend(sb) + 1); + npositive = err; + if (unlikely(err)) + goto out; + au_do_refresh_hdentry(dinfo->di_hdentry + dinfo->di_bstart, dinfo, + parent); + + npositive = 0; + bstart = au_dbstart(parent); + if (type != S_IFDIR && dinfo->di_bstart == bstart) + goto out_dgen; /* success */ + + npositive = au_lkup_dentry(dentry, bstart, type, /*nd*/NULL); + if (npositive < 0) + goto out; + if (dinfo->di_bwh >= 0 && dinfo->di_bwh <= dinfo->di_bstart) + d_drop(dentry); + +out_dgen: + au_update_digen(dentry); +out: + dput(parent); + AuTraceErr(npositive); + return npositive; +} + +static noinline_for_stack +int au_do_h_d_reval(struct dentry *h_dentry, struct nameidata *nd, + struct dentry *dentry, aufs_bindex_t bindex) +{ + int err, valid; + int (*reval)(struct dentry *, struct nameidata *); + + err = 0; + reval = NULL; + if (h_dentry->d_op) + reval = h_dentry->d_op->d_revalidate; + if (!reval) + goto out; + + AuDbg("b%d\n", bindex); + if (au_test_fs_null_nd(h_dentry->d_sb)) + /* it may return tri-state */ + valid = reval(h_dentry, NULL); + else { + struct nameidata h_nd; + int locked; + struct dentry *parent; + + au_h_nd(&h_nd, nd); + parent = nd->path.dentry; + locked = (nd && nd->path.dentry != dentry); + if (locked) + di_read_lock_parent(parent, AuLock_IR); + BUG_ON(bindex > au_dbend(parent)); + h_nd.path.dentry = au_h_dptr(parent, bindex); + BUG_ON(!h_nd.path.dentry); + h_nd.path.mnt = au_sbr(parent->d_sb, bindex)->br_mnt; + path_get(&h_nd.path); + valid = reval(h_dentry, &h_nd); + path_put(&h_nd.path); + if (locked) + di_read_unlock(parent, AuLock_IR); + } + + if (unlikely(valid < 0)) + err = valid; + else if (!valid) + err = -EINVAL; + +out: + AuTraceErr(err); + return err; +} + +/* todo: remove this */ +static int h_d_revalidate(struct dentry *dentry, struct inode *inode, + struct nameidata *nd, int do_udba) +{ + int err; + umode_t mode, h_mode; + aufs_bindex_t bindex, btail, bstart, ibs, ibe; + unsigned char plus, unhashed, is_root, h_plus; + struct inode *h_inode, *h_cached_inode; + struct dentry *h_dentry; + struct qstr *name, *h_name; + + err = 0; + plus = 0; + mode = 0; + ibs = -1; + ibe = -1; + unhashed = !!d_unhashed(dentry); + is_root = !!IS_ROOT(dentry); + name = &dentry->d_name; + + /* + * Theoretically, REVAL test should be unnecessary in case of + * {FS,I}NOTIFY. + * But {fs,i}notify doesn't fire some necessary events, + * IN_ATTRIB for atime/nlink/pageio + * IN_DELETE for NFS dentry + * Let's do REVAL test too. + */ + if (do_udba && inode) { + mode = (inode->i_mode & S_IFMT); + plus = (inode->i_nlink > 0); + ibs = au_ibstart(inode); + ibe = au_ibend(inode); + } + + bstart = au_dbstart(dentry); + btail = bstart; + if (inode && S_ISDIR(inode->i_mode)) + btail = au_dbtaildir(dentry); + for (bindex = bstart; bindex <= btail; bindex++) { + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + + AuDbg("b%d, %.*s\n", bindex, AuDLNPair(h_dentry)); + h_name = &h_dentry->d_name; + if (unlikely(do_udba + && !is_root + && (unhashed != !!d_unhashed(h_dentry) + || name->len != h_name->len + || memcmp(name->name, h_name->name, name->len)) + )) { + AuDbg("unhash 0x%x 0x%x, %.*s %.*s\n", + unhashed, d_unhashed(h_dentry), + AuDLNPair(dentry), AuDLNPair(h_dentry)); + goto err; + } + + err = au_do_h_d_reval(h_dentry, nd, dentry, bindex); + if (unlikely(err)) + /* do not goto err, to keep the errno */ + break; + + /* todo: plink too? */ + if (!do_udba) + continue; + + /* UDBA tests */ + h_inode = h_dentry->d_inode; + if (unlikely(!!inode != !!h_inode)) + goto err; + + h_plus = plus; + h_mode = mode; + h_cached_inode = h_inode; + if (h_inode) { + h_mode = (h_inode->i_mode & S_IFMT); + h_plus = (h_inode->i_nlink > 0); + } + if (inode && ibs <= bindex && bindex <= ibe) + h_cached_inode = au_h_iptr(inode, bindex); + + if (unlikely(plus != h_plus + || mode != h_mode + || h_cached_inode != h_inode)) + goto err; + continue; + + err: + err = -EINVAL; + break; + } + + return err; +} + +static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen) +{ + int err; + struct dentry *parent; + struct inode *inode; + + inode = dentry->d_inode; + if (au_digen(dentry) == sigen && au_iigen(inode) == sigen) + return 0; + + parent = dget_parent(dentry); + di_read_lock_parent(parent, AuLock_IR); + AuDebugOn(au_digen(parent) != sigen + || au_iigen(parent->d_inode) != sigen); + au_dbg_verify_gen(parent, sigen); + + /* returns a number of positive dentries */ + err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT); + if (err >= 0) + err = au_refresh_hinode(inode, dentry); + + di_read_unlock(parent, AuLock_IR); + dput(parent); + return err; +} + +int au_reval_dpath(struct dentry *dentry, unsigned int sigen) +{ + int err; + struct dentry *d, *parent; + struct inode *inode; + + if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS)) + return simple_reval_dpath(dentry, sigen); + + /* slow loop, keep it simple and stupid */ + /* cf: au_cpup_dirs() */ + err = 0; + parent = NULL; + while (au_digen(dentry) != sigen + || au_iigen(dentry->d_inode) != sigen) { + d = dentry; + while (1) { + dput(parent); + parent = dget_parent(d); + if (au_digen(parent) == sigen + && au_iigen(parent->d_inode) == sigen) + break; + d = parent; + } + + inode = d->d_inode; + if (d != dentry) + di_write_lock_child(d); + + /* someone might update our dentry while we were sleeping */ + if (au_digen(d) != sigen || au_iigen(d->d_inode) != sigen) { + di_read_lock_parent(parent, AuLock_IR); + /* returns a number of positive dentries */ + err = au_refresh_hdentry(d, inode->i_mode & S_IFMT); + if (err >= 0) + err = au_refresh_hinode(inode, d); + di_read_unlock(parent, AuLock_IR); + } + + if (d != dentry) + di_write_unlock(d); + dput(parent); + if (unlikely(err)) + break; + } + + return err; +} + +/* + * if valid returns 1, otherwise 0. + */ +static int aufs_d_revalidate(struct dentry *dentry, struct nameidata *nd) +{ + int valid, err; + unsigned int sigen; + unsigned char do_udba; + struct super_block *sb; + struct inode *inode; + + valid = 1; + sb = dentry->d_sb; + inode = dentry->d_inode; + /* + * todo: very ugly + * i_mutex of parent dir may be held, + * but we should not return 'invalid' due to busy. + */ + err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM); + if (unlikely(err)) { + valid = err; + goto out; + } + sigen = au_sigen(sb); + if (au_digen(dentry) != sigen) { + AuDebugOn(IS_ROOT(dentry)); + if (inode) + err = au_reval_dpath(dentry, sigen); + if (unlikely(err)) + goto out_dgrade; + } + if (inode && au_iigen(inode) != sigen) { + AuDebugOn(IS_ROOT(dentry)); + err = au_refresh_hinode(inode, dentry); + if (unlikely(err)) + goto out_dgrade; + } + di_downgrade_lock(dentry, AuLock_IR); + + err = -EINVAL; + do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE); + if (do_udba && inode) { + aufs_bindex_t bstart = au_ibstart(inode); + + if (bstart >= 0 + && au_test_higen(inode, au_h_iptr(inode, bstart))) + goto out_inval; + } + + err = h_d_revalidate(dentry, inode, nd, do_udba); + if (unlikely(!err && do_udba && au_dbstart(dentry) < 0)) + /* both of real entry and whiteout found */ + err = -EIO; + goto out_inval; + +out_dgrade: + di_downgrade_lock(dentry, AuLock_IR); +out_inval: + aufs_read_unlock(dentry, AuLock_IR); + AuTraceErr(err); + valid = !err; +out: + if (!valid) + AuDbg("%.*s invalid, %d\n", AuDLNPair(dentry), valid); + return valid; +} + +static void aufs_d_release(struct dentry *dentry) +{ + if (dentry->d_fsdata) { + au_di_fin(dentry); + au_hn_di_reinit(dentry); + } +} + +const struct dentry_operations aufs_dop = { + .d_revalidate = aufs_d_revalidate, + .d_release = aufs_d_release +}; --- linux-2.6.37.orig/ubuntu/aufs/dentry.h +++ linux-2.6.37/ubuntu/aufs/dentry.h @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * lookup and dentry operations + */ + +#ifndef __AUFS_DENTRY_H__ +#define __AUFS_DENTRY_H__ + +#ifdef __KERNEL__ + +#include +#include +#include "rwsem.h" + +/* make a single member structure for future use */ +/* todo: remove this structure */ +struct au_hdentry { + struct dentry *hd_dentry; +}; + +struct au_dinfo { + atomic_t di_generation; + + struct au_rwsem di_rwsem; + aufs_bindex_t di_bstart, di_bend, di_bwh, di_bdiropq; + struct au_hdentry *di_hdentry; +} ____cacheline_aligned_in_smp; + +/* ---------------------------------------------------------------------- */ + +/* dentry.c */ +extern const struct dentry_operations aufs_dop; +struct au_branch; +struct dentry *au_lkup_one(struct qstr *name, struct dentry *h_parent, + struct au_branch *br, struct nameidata *nd); +struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent, + struct au_branch *br); +int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, + struct dentry *h_parent, struct au_branch *br); + +int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t bstart, mode_t type, + struct nameidata *nd); +int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex); +int au_refresh_hdentry(struct dentry *dentry, mode_t type); +int au_reval_dpath(struct dentry *dentry, unsigned int sigen); + +/* dinfo.c */ +void au_di_init_once(void *_di); +int au_di_init(struct dentry *dentry); +void au_di_fin(struct dentry *dentry); +int au_di_realloc(struct au_dinfo *dinfo, int nbr); + +void di_read_lock(struct dentry *d, int flags, unsigned int lsc); +void di_read_unlock(struct dentry *d, int flags); +void di_downgrade_lock(struct dentry *d, int flags); +void di_write_lock(struct dentry *d, unsigned int lsc); +void di_write_unlock(struct dentry *d); +void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir); +void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir); +void di_write_unlock2(struct dentry *d1, struct dentry *d2); + +struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex); +aufs_bindex_t au_dbtail(struct dentry *dentry); +aufs_bindex_t au_dbtaildir(struct dentry *dentry); + +void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_dentry); +void au_update_digen(struct dentry *dentry); +void au_update_dbrange(struct dentry *dentry, int do_put_zero); +void au_update_dbstart(struct dentry *dentry); +void au_update_dbend(struct dentry *dentry); +int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry); + +/* ---------------------------------------------------------------------- */ + +static inline struct au_dinfo *au_di(struct dentry *dentry) +{ + return dentry->d_fsdata; +} + +/* ---------------------------------------------------------------------- */ + +/* lock subclass for dinfo */ +enum { + AuLsc_DI_CHILD, /* child first */ + AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */ + AuLsc_DI_CHILD3, /* copyup dirs */ + AuLsc_DI_PARENT, + AuLsc_DI_PARENT2, + AuLsc_DI_PARENT3 +}; + +/* + * di_read_lock_child, di_write_lock_child, + * di_read_lock_child2, di_write_lock_child2, + * di_read_lock_child3, di_write_lock_child3, + * di_read_lock_parent, di_write_lock_parent, + * di_read_lock_parent2, di_write_lock_parent2, + * di_read_lock_parent3, di_write_lock_parent3, + */ +#define AuReadLockFunc(name, lsc) \ +static inline void di_read_lock_##name(struct dentry *d, int flags) \ +{ di_read_lock(d, flags, AuLsc_DI_##lsc); } + +#define AuWriteLockFunc(name, lsc) \ +static inline void di_write_lock_##name(struct dentry *d) \ +{ di_write_lock(d, AuLsc_DI_##lsc); } + +#define AuRWLockFuncs(name, lsc) \ + AuReadLockFunc(name, lsc) \ + AuWriteLockFunc(name, lsc) + +AuRWLockFuncs(child, CHILD); +AuRWLockFuncs(child2, CHILD2); +AuRWLockFuncs(child3, CHILD3); +AuRWLockFuncs(parent, PARENT); +AuRWLockFuncs(parent2, PARENT2); +AuRWLockFuncs(parent3, PARENT3); + +#undef AuReadLockFunc +#undef AuWriteLockFunc +#undef AuRWLockFuncs + +#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem) +#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem) +#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem) + +/* ---------------------------------------------------------------------- */ + +/* todo: memory barrier? */ +static inline unsigned int au_digen(struct dentry *d) +{ + return atomic_read(&au_di(d)->di_generation); +} + +static inline void au_h_dentry_init(struct au_hdentry *hdentry) +{ + hdentry->hd_dentry = NULL; +} + +static inline void au_hdput(struct au_hdentry *hd) +{ + if (hd) + dput(hd->hd_dentry); +} + +static inline aufs_bindex_t au_dbstart(struct dentry *dentry) +{ + DiMustAnyLock(dentry); + return au_di(dentry)->di_bstart; +} + +static inline aufs_bindex_t au_dbend(struct dentry *dentry) +{ + DiMustAnyLock(dentry); + return au_di(dentry)->di_bend; +} + +static inline aufs_bindex_t au_dbwh(struct dentry *dentry) +{ + DiMustAnyLock(dentry); + return au_di(dentry)->di_bwh; +} + +static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry) +{ + DiMustAnyLock(dentry); + return au_di(dentry)->di_bdiropq; +} + +/* todo: hard/soft set? */ +static inline void au_set_dbstart(struct dentry *dentry, aufs_bindex_t bindex) +{ + DiMustWriteLock(dentry); + au_di(dentry)->di_bstart = bindex; +} + +static inline void au_set_dbend(struct dentry *dentry, aufs_bindex_t bindex) +{ + DiMustWriteLock(dentry); + au_di(dentry)->di_bend = bindex; +} + +static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex) +{ + DiMustWriteLock(dentry); + /* dbwh can be outside of bstart - bend range */ + au_di(dentry)->di_bwh = bindex; +} + +static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex) +{ + DiMustWriteLock(dentry); + au_di(dentry)->di_bdiropq = bindex; +} + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_HNOTIFY +static inline void au_digen_dec(struct dentry *d) +{ + atomic_dec(&au_di(d)->di_generation); +} + +static inline void au_hn_di_reinit(struct dentry *dentry) +{ + dentry->d_fsdata = NULL; +} +#else +AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused) +#endif /* CONFIG_AUFS_HNOTIFY */ + +#endif /* __KERNEL__ */ +#endif /* __AUFS_DENTRY_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/dinfo.c +++ linux-2.6.37/ubuntu/aufs/dinfo.c @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * dentry private data + */ + +#include "aufs.h" + +void au_di_init_once(void *_dinfo) +{ + struct au_dinfo *dinfo = _dinfo; + static struct lock_class_key aufs_di; + + au_rw_init(&dinfo->di_rwsem); + au_rw_class(&dinfo->di_rwsem, &aufs_di); +} + +int au_di_init(struct dentry *dentry) +{ + struct au_dinfo *dinfo; + struct super_block *sb; + int nbr; + + dinfo = au_cache_alloc_dinfo(); + if (unlikely(!dinfo)) + goto out; + + sb = dentry->d_sb; + nbr = au_sbend(sb) + 1; + if (nbr <= 0) + nbr = 1; + dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS); + if (unlikely(!dinfo->di_hdentry)) + goto out_dinfo; + + atomic_set(&dinfo->di_generation, au_sigen(sb)); + /* smp_mb(); */ /* atomic_set */ + au_rw_write_lock_nested(&dinfo->di_rwsem, AuLsc_DI_CHILD); + dinfo->di_bstart = -1; + dinfo->di_bend = -1; + dinfo->di_bwh = -1; + dinfo->di_bdiropq = -1; + + dentry->d_fsdata = dinfo; + dentry->d_op = &aufs_dop; + return 0; /* success */ + +out_dinfo: + au_cache_free_dinfo(dinfo); +out: + return -ENOMEM; +} + +void au_di_fin(struct dentry *dentry) +{ + struct au_dinfo *di; + struct au_hdentry *p; + aufs_bindex_t bend, bindex; + + /* dentry may not be revalidated */ + di = dentry->d_fsdata; + bindex = di->di_bstart; + if (bindex >= 0) { + bend = di->di_bend; + p = di->di_hdentry + bindex; + while (bindex++ <= bend) + au_hdput(p++); + } + kfree(di->di_hdentry); + AuRwDestroy(&di->di_rwsem); + au_cache_free_dinfo(di); +} + +int au_di_realloc(struct au_dinfo *dinfo, int nbr) +{ + int err, sz; + struct au_hdentry *hdp; + + AuRwMustWriteLock(&dinfo->di_rwsem); + + err = -ENOMEM; + sz = sizeof(*hdp) * (dinfo->di_bend + 1); + if (!sz) + sz = sizeof(*hdp); + hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS); + if (hdp) { + dinfo->di_hdentry = hdp; + err = 0; + } + + return err; +} + +/* ---------------------------------------------------------------------- */ + +static void do_ii_write_lock(struct inode *inode, unsigned int lsc) +{ + switch (lsc) { + case AuLsc_DI_CHILD: + ii_write_lock_child(inode); + break; + case AuLsc_DI_CHILD2: + ii_write_lock_child2(inode); + break; + case AuLsc_DI_CHILD3: + ii_write_lock_child3(inode); + break; + case AuLsc_DI_PARENT: + ii_write_lock_parent(inode); + break; + case AuLsc_DI_PARENT2: + ii_write_lock_parent2(inode); + break; + case AuLsc_DI_PARENT3: + ii_write_lock_parent3(inode); + break; + default: + BUG(); + } +} + +static void do_ii_read_lock(struct inode *inode, unsigned int lsc) +{ + switch (lsc) { + case AuLsc_DI_CHILD: + ii_read_lock_child(inode); + break; + case AuLsc_DI_CHILD2: + ii_read_lock_child2(inode); + break; + case AuLsc_DI_CHILD3: + ii_read_lock_child3(inode); + break; + case AuLsc_DI_PARENT: + ii_read_lock_parent(inode); + break; + case AuLsc_DI_PARENT2: + ii_read_lock_parent2(inode); + break; + case AuLsc_DI_PARENT3: + ii_read_lock_parent3(inode); + break; + default: + BUG(); + } +} + +void di_read_lock(struct dentry *d, int flags, unsigned int lsc) +{ + au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc); + if (d->d_inode) { + if (au_ftest_lock(flags, IW)) + do_ii_write_lock(d->d_inode, lsc); + else if (au_ftest_lock(flags, IR)) + do_ii_read_lock(d->d_inode, lsc); + } +} + +void di_read_unlock(struct dentry *d, int flags) +{ + if (d->d_inode) { + if (au_ftest_lock(flags, IW)) + ii_write_unlock(d->d_inode); + else if (au_ftest_lock(flags, IR)) + ii_read_unlock(d->d_inode); + } + au_rw_read_unlock(&au_di(d)->di_rwsem); +} + +void di_downgrade_lock(struct dentry *d, int flags) +{ + if (d->d_inode && au_ftest_lock(flags, IR)) + ii_downgrade_lock(d->d_inode); + au_rw_dgrade_lock(&au_di(d)->di_rwsem); +} + +void di_write_lock(struct dentry *d, unsigned int lsc) +{ + au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc); + if (d->d_inode) + do_ii_write_lock(d->d_inode, lsc); +} + +void di_write_unlock(struct dentry *d) +{ + if (d->d_inode) + ii_write_unlock(d->d_inode); + au_rw_write_unlock(&au_di(d)->di_rwsem); +} + +void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir) +{ + AuDebugOn(d1 == d2 + || d1->d_inode == d2->d_inode + || d1->d_sb != d2->d_sb); + + if (isdir && au_test_subdir(d1, d2)) { + di_write_lock_child(d1); + di_write_lock_child2(d2); + } else { + /* there should be no races */ + di_write_lock_child(d2); + di_write_lock_child2(d1); + } +} + +void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir) +{ + AuDebugOn(d1 == d2 + || d1->d_inode == d2->d_inode + || d1->d_sb != d2->d_sb); + + if (isdir && au_test_subdir(d1, d2)) { + di_write_lock_parent(d1); + di_write_lock_parent2(d2); + } else { + /* there should be no races */ + di_write_lock_parent(d2); + di_write_lock_parent2(d1); + } +} + +void di_write_unlock2(struct dentry *d1, struct dentry *d2) +{ + di_write_unlock(d1); + if (d1->d_inode == d2->d_inode) + au_rw_write_unlock(&au_di(d2)->di_rwsem); + else + di_write_unlock(d2); +} + +/* ---------------------------------------------------------------------- */ + +struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex) +{ + struct dentry *d; + + DiMustAnyLock(dentry); + + if (au_dbstart(dentry) < 0 || bindex < au_dbstart(dentry)) + return NULL; + AuDebugOn(bindex < 0); + d = au_di(dentry)->di_hdentry[0 + bindex].hd_dentry; + AuDebugOn(d && (atomic_read(&d->d_count) <= 0)); + return d; +} + +aufs_bindex_t au_dbtail(struct dentry *dentry) +{ + aufs_bindex_t bend, bwh; + + bend = au_dbend(dentry); + if (0 <= bend) { + bwh = au_dbwh(dentry); + if (!bwh) + return bwh; + if (0 < bwh && bwh < bend) + return bwh - 1; + } + return bend; +} + +aufs_bindex_t au_dbtaildir(struct dentry *dentry) +{ + aufs_bindex_t bend, bopq; + + bend = au_dbtail(dentry); + if (0 <= bend) { + bopq = au_dbdiropq(dentry); + if (0 <= bopq && bopq < bend) + bend = bopq; + } + return bend; +} + +/* ---------------------------------------------------------------------- */ + +void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_dentry) +{ + struct au_hdentry *hd = au_di(dentry)->di_hdentry + bindex; + + DiMustWriteLock(dentry); + + au_hdput(hd); + hd->hd_dentry = h_dentry; +} + +void au_update_digen(struct dentry *dentry) +{ + atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb)); + /* smp_mb(); */ /* atomic_set */ +} + +void au_update_dbrange(struct dentry *dentry, int do_put_zero) +{ + struct au_dinfo *dinfo; + struct dentry *h_d; + struct au_hdentry *hdp; + + DiMustWriteLock(dentry); + + dinfo = au_di(dentry); + if (!dinfo || dinfo->di_bstart < 0) + return; + + hdp = dinfo->di_hdentry; + if (do_put_zero) { + aufs_bindex_t bindex, bend; + + bend = dinfo->di_bend; + for (bindex = dinfo->di_bstart; bindex <= bend; bindex++) { + h_d = hdp[0 + bindex].hd_dentry; + if (h_d && !h_d->d_inode) + au_set_h_dptr(dentry, bindex, NULL); + } + } + + dinfo->di_bstart = -1; + while (++dinfo->di_bstart <= dinfo->di_bend) + if (hdp[0 + dinfo->di_bstart].hd_dentry) + break; + if (dinfo->di_bstart > dinfo->di_bend) { + dinfo->di_bstart = -1; + dinfo->di_bend = -1; + return; + } + + dinfo->di_bend++; + while (0 <= --dinfo->di_bend) + if (hdp[0 + dinfo->di_bend].hd_dentry) + break; + AuDebugOn(dinfo->di_bstart > dinfo->di_bend || dinfo->di_bend < 0); +} + +void au_update_dbstart(struct dentry *dentry) +{ + aufs_bindex_t bindex, bend; + struct dentry *h_dentry; + + bend = au_dbend(dentry); + for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) { + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + if (h_dentry->d_inode) { + au_set_dbstart(dentry, bindex); + return; + } + au_set_h_dptr(dentry, bindex, NULL); + } +} + +void au_update_dbend(struct dentry *dentry) +{ + aufs_bindex_t bindex, bstart; + struct dentry *h_dentry; + + bstart = au_dbstart(dentry); + for (bindex = au_dbend(dentry); bindex >= bstart; bindex--) { + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + if (h_dentry->d_inode) { + au_set_dbend(dentry, bindex); + return; + } + au_set_h_dptr(dentry, bindex, NULL); + } +} + +int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry) +{ + aufs_bindex_t bindex, bend; + + bend = au_dbend(dentry); + for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) + if (au_h_dptr(dentry, bindex) == h_dentry) + return bindex; + return -1; +} --- linux-2.6.37.orig/ubuntu/aufs/dir.c +++ linux-2.6.37/ubuntu/aufs/dir.c @@ -0,0 +1,643 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * directory operations + */ + +#include +#include +#include "aufs.h" + +void au_add_nlink(struct inode *dir, struct inode *h_dir) +{ + AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); + + dir->i_nlink += h_dir->i_nlink - 2; + if (h_dir->i_nlink < 2) + dir->i_nlink += 2; +} + +void au_sub_nlink(struct inode *dir, struct inode *h_dir) +{ + AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode)); + + dir->i_nlink -= h_dir->i_nlink - 2; + if (h_dir->i_nlink < 2) + dir->i_nlink -= 2; +} + +loff_t au_dir_size(struct file *file, struct dentry *dentry) +{ + loff_t sz; + aufs_bindex_t bindex, bend; + struct file *h_file; + struct dentry *h_dentry; + + sz = 0; + if (file) { + AuDebugOn(!file->f_dentry); + AuDebugOn(!file->f_dentry->d_inode); + AuDebugOn(!S_ISDIR(file->f_dentry->d_inode->i_mode)); + + bend = au_fbend_dir(file); + for (bindex = au_fbstart(file); + bindex <= bend && sz < KMALLOC_MAX_SIZE; + bindex++) { + h_file = au_hf_dir(file, bindex); + if (h_file + && h_file->f_dentry + && h_file->f_dentry->d_inode) + sz += i_size_read(h_file->f_dentry->d_inode); + } + } else { + AuDebugOn(!dentry); + AuDebugOn(!dentry->d_inode); + AuDebugOn(!S_ISDIR(dentry->d_inode->i_mode)); + + bend = au_dbtaildir(dentry); + for (bindex = au_dbstart(dentry); + bindex <= bend && sz < KMALLOC_MAX_SIZE; + bindex++) { + h_dentry = au_h_dptr(dentry, bindex); + if (h_dentry && h_dentry->d_inode) + sz += i_size_read(h_dentry->d_inode); + } + } + if (sz < KMALLOC_MAX_SIZE) + sz = roundup_pow_of_two(sz); + if (sz > KMALLOC_MAX_SIZE) + sz = KMALLOC_MAX_SIZE; + else if (sz < NAME_MAX) { + BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX); + sz = AUFS_RDBLK_DEF; + } + return sz; +} + +/* ---------------------------------------------------------------------- */ + +static int reopen_dir(struct file *file) +{ + int err; + unsigned int flags; + aufs_bindex_t bindex, btail, bstart; + struct dentry *dentry, *h_dentry; + struct file *h_file; + + /* open all lower dirs */ + dentry = file->f_dentry; + bstart = au_dbstart(dentry); + for (bindex = au_fbstart(file); bindex < bstart; bindex++) + au_set_h_fptr(file, bindex, NULL); + au_set_fbstart(file, bstart); + + btail = au_dbtaildir(dentry); + for (bindex = au_fbend_dir(file); btail < bindex; bindex--) + au_set_h_fptr(file, bindex, NULL); + au_set_fbend_dir(file, btail); + + flags = vfsub_file_flags(file); + for (bindex = bstart; bindex <= btail; bindex++) { + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + h_file = au_hf_dir(file, bindex); + if (h_file) + continue; + + h_file = au_h_open(dentry, bindex, flags, file); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; /* close all? */ + au_set_h_fptr(file, bindex, h_file); + } + au_update_figen(file); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + err = 0; + +out: + return err; +} + +static int do_open_dir(struct file *file, int flags) +{ + int err; + aufs_bindex_t bindex, btail; + struct dentry *dentry, *h_dentry; + struct file *h_file; + + FiMustWriteLock(file); + + err = 0; + dentry = file->f_dentry; + file->f_version = dentry->d_inode->i_version; + bindex = au_dbstart(dentry); + au_set_fbstart(file, bindex); + btail = au_dbtaildir(dentry); + au_set_fbend_dir(file, btail); + for (; !err && bindex <= btail; bindex++) { + h_dentry = au_h_dptr(dentry, bindex); + if (!h_dentry) + continue; + + h_file = au_h_open(dentry, bindex, flags, file); + if (IS_ERR(h_file)) { + err = PTR_ERR(h_file); + break; + } + au_set_h_fptr(file, bindex, h_file); + } + au_update_figen(file); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + if (!err) + return 0; /* success */ + + /* close all */ + for (bindex = au_fbstart(file); bindex <= btail; bindex++) + au_set_h_fptr(file, bindex, NULL); + au_set_fbstart(file, -1); + au_set_fbend_dir(file, -1); + + return err; +} + +static int aufs_open_dir(struct inode *inode __maybe_unused, + struct file *file) +{ + int err; + struct super_block *sb; + struct au_fidir *fidir; + + err = -ENOMEM; + sb = file->f_dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + fidir = au_fidir_alloc(sb); + if (fidir) { + err = au_do_open(file, do_open_dir, fidir); + if (unlikely(err)) + kfree(fidir); + } + si_read_unlock(sb); + return err; +} + +static int aufs_release_dir(struct inode *inode __maybe_unused, + struct file *file) +{ + struct au_vdir *vdir_cache; + struct super_block *sb; + struct au_finfo *finfo; + struct au_fidir *fidir; + aufs_bindex_t bindex, bend; + + sb = file->f_dentry->d_sb; + finfo = au_fi(file); + fidir = finfo->fi_hdir; + if (fidir) { + /* remove me from sb->s_files */ + file_sb_list_del(file); + + vdir_cache = fidir->fd_vdir_cache; /* lock-free */ + if (vdir_cache) + au_vdir_free(vdir_cache); + + bindex = finfo->fi_btop; + if (bindex >= 0) { + /* + * calls fput() instead of filp_close(), + * since no dnotify or lock for the lower file. + */ + bend = fidir->fd_bbot; + for (; bindex <= bend; bindex++) + au_set_h_fptr(file, bindex, NULL); + } + kfree(fidir); + finfo->fi_hdir = NULL; + } + au_finfo_fin(file); + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int au_do_flush_dir(struct file *file, fl_owner_t id) +{ + int err; + aufs_bindex_t bindex, bend; + struct file *h_file; + + err = 0; + bend = au_fbend_dir(file); + for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) { + h_file = au_hf_dir(file, bindex); + if (h_file) + err = vfsub_flush(h_file, id); + } + return err; +} + +static int aufs_flush_dir(struct file *file, fl_owner_t id) +{ + return au_do_flush(file, id, au_do_flush_dir); +} + +/* ---------------------------------------------------------------------- */ + +static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync) +{ + int err; + aufs_bindex_t bend, bindex; + struct inode *inode; + struct super_block *sb; + + err = 0; + sb = dentry->d_sb; + inode = dentry->d_inode; + IMustLock(inode); + bend = au_dbend(dentry); + for (bindex = au_dbstart(dentry); !err && bindex <= bend; bindex++) { + struct path h_path; + struct inode *h_inode; + + if (au_test_ro(sb, bindex, inode)) + continue; + h_path.dentry = au_h_dptr(dentry, bindex); + if (!h_path.dentry) + continue; + h_inode = h_path.dentry->d_inode; + if (!h_inode) + continue; + + /* no mnt_want_write() */ + /* cf. fs/nsfd/vfs.c and fs/nfsd/nfs4recover.c */ + /* todo: inotiry fired? */ + h_path.mnt = au_sbr_mnt(sb, bindex); + mutex_lock(&h_inode->i_mutex); + err = filemap_fdatawrite(h_inode->i_mapping); + AuDebugOn(!h_inode->i_fop); + if (!err && h_inode->i_fop->fsync) + err = h_inode->i_fop->fsync(NULL, datasync); + if (!err) + err = filemap_fdatawrite(h_inode->i_mapping); + if (!err) + vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/ + mutex_unlock(&h_inode->i_mutex); + } + + return err; +} + +static int au_do_fsync_dir(struct file *file, int datasync) +{ + int err; + aufs_bindex_t bend, bindex; + struct file *h_file; + struct super_block *sb; + struct inode *inode; + struct mutex *h_mtx; + + err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1); + if (unlikely(err)) + goto out; + + sb = file->f_dentry->d_sb; + inode = file->f_dentry->d_inode; + bend = au_fbend_dir(file); + for (bindex = au_fbstart(file); !err && bindex <= bend; bindex++) { + h_file = au_hf_dir(file, bindex); + if (!h_file || au_test_ro(sb, bindex, inode)) + continue; + + err = vfs_fsync(h_file, datasync); + if (!err) { + h_mtx = &h_file->f_dentry->d_inode->i_mutex; + mutex_lock(h_mtx); + vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); + /*ignore*/ + mutex_unlock(h_mtx); + } + } + +out: + return err; +} + +/* + * @file may be NULL + */ +static int aufs_fsync_dir(struct file *file, int datasync) +{ + int err; + struct dentry *dentry; + struct super_block *sb; + + dentry = file->f_dentry; + IMustLock(dentry->d_inode); + + err = 0; + sb = dentry->d_sb; + si_noflush_read_lock(sb); + if (file) + err = au_do_fsync_dir(file, datasync); + else { + di_write_lock_child(dentry); + err = au_do_fsync_dir_no_file(dentry, datasync); + } + au_cpup_attr_timesizes(dentry->d_inode); + di_write_unlock(dentry); + if (file) + fi_write_unlock(file); + + si_read_unlock(sb); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int aufs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + int err; + struct dentry *dentry; + struct inode *inode; + struct super_block *sb; + + dentry = file->f_dentry; + inode = dentry->d_inode; + IMustLock(inode); + + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1); + if (unlikely(err)) + goto out; + err = au_vdir_init(file); + di_downgrade_lock(dentry, AuLock_IR); + if (unlikely(err)) + goto out_unlock; + + if (!au_test_nfsd()) { + err = au_vdir_fill_de(file, dirent, filldir); + fsstack_copy_attr_atime(inode, + au_h_iptr(inode, au_ibstart(inode))); + } else { + /* + * nfsd filldir may call lookup_one_len(), vfs_getattr(), + * encode_fh() and others. + */ + struct inode *h_inode = au_h_iptr(inode, au_ibstart(inode)); + + di_read_unlock(dentry, AuLock_IR); + si_read_unlock(sb); + err = au_vdir_fill_de(file, dirent, filldir); + fsstack_copy_attr_atime(inode, h_inode); + fi_write_unlock(file); + + AuTraceErr(err); + return err; + } + +out_unlock: + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); +out: + si_read_unlock(sb); + return err; +} + +/* ---------------------------------------------------------------------- */ + +#define AuTestEmpty_WHONLY 1 +#define AuTestEmpty_CALLED (1 << 1) +#define AuTestEmpty_SHWH (1 << 2) +#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name) +#define au_fset_testempty(flags, name) \ + do { (flags) |= AuTestEmpty_##name; } while (0) +#define au_fclr_testempty(flags, name) \ + do { (flags) &= ~AuTestEmpty_##name; } while (0) + +#ifndef CONFIG_AUFS_SHWH +#undef AuTestEmpty_SHWH +#define AuTestEmpty_SHWH 0 +#endif + +struct test_empty_arg { + struct au_nhash *whlist; + unsigned int flags; + int err; + aufs_bindex_t bindex; +}; + +static int test_empty_cb(void *__arg, const char *__name, int namelen, + loff_t offset __maybe_unused, u64 ino, + unsigned int d_type) +{ + struct test_empty_arg *arg = __arg; + char *name = (void *)__name; + + arg->err = 0; + au_fset_testempty(arg->flags, CALLED); + /* smp_mb(); */ + if (name[0] == '.' + && (namelen == 1 || (name[1] == '.' && namelen == 2))) + goto out; /* success */ + + if (namelen <= AUFS_WH_PFX_LEN + || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { + if (au_ftest_testempty(arg->flags, WHONLY) + && !au_nhash_test_known_wh(arg->whlist, name, namelen)) + arg->err = -ENOTEMPTY; + goto out; + } + + name += AUFS_WH_PFX_LEN; + namelen -= AUFS_WH_PFX_LEN; + if (!au_nhash_test_known_wh(arg->whlist, name, namelen)) + arg->err = au_nhash_append_wh + (arg->whlist, name, namelen, ino, d_type, arg->bindex, + au_ftest_testempty(arg->flags, SHWH)); + +out: + /* smp_mb(); */ + AuTraceErr(arg->err); + return arg->err; +} + +static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg) +{ + int err; + struct file *h_file; + + h_file = au_h_open(dentry, arg->bindex, + O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE, + /*file*/NULL); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; + + err = 0; + if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE) + && !h_file->f_dentry->d_inode->i_nlink) + goto out_put; + + do { + arg->err = 0; + au_fclr_testempty(arg->flags, CALLED); + /* smp_mb(); */ + err = vfsub_readdir(h_file, test_empty_cb, arg); + if (err >= 0) + err = arg->err; + } while (!err && au_ftest_testempty(arg->flags, CALLED)); + +out_put: + fput(h_file); + au_sbr_put(dentry->d_sb, arg->bindex); +out: + return err; +} + +struct do_test_empty_args { + int *errp; + struct dentry *dentry; + struct test_empty_arg *arg; +}; + +static void call_do_test_empty(void *args) +{ + struct do_test_empty_args *a = args; + *a->errp = do_test_empty(a->dentry, a->arg); +} + +static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg) +{ + int err, wkq_err; + struct dentry *h_dentry; + struct inode *h_inode; + + h_dentry = au_h_dptr(dentry, arg->bindex); + h_inode = h_dentry->d_inode; + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ); + mutex_unlock(&h_inode->i_mutex); + if (!err) + err = do_test_empty(dentry, arg); + else { + struct do_test_empty_args args = { + .errp = &err, + .dentry = dentry, + .arg = arg + }; + unsigned int flags = arg->flags; + + wkq_err = au_wkq_wait(call_do_test_empty, &args); + if (unlikely(wkq_err)) + err = wkq_err; + arg->flags = flags; + } + + return err; +} + +int au_test_empty_lower(struct dentry *dentry) +{ + int err; + unsigned int rdhash; + aufs_bindex_t bindex, bstart, btail; + struct au_nhash whlist; + struct test_empty_arg arg; + + SiMustAnyLock(dentry->d_sb); + + rdhash = au_sbi(dentry->d_sb)->si_rdhash; + if (!rdhash) + rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry)); + err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); + if (unlikely(err)) + goto out; + + arg.flags = 0; + arg.whlist = &whlist; + bstart = au_dbstart(dentry); + if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) + au_fset_testempty(arg.flags, SHWH); + arg.bindex = bstart; + err = do_test_empty(dentry, &arg); + if (unlikely(err)) + goto out_whlist; + + au_fset_testempty(arg.flags, WHONLY); + btail = au_dbtaildir(dentry); + for (bindex = bstart + 1; !err && bindex <= btail; bindex++) { + struct dentry *h_dentry; + + h_dentry = au_h_dptr(dentry, bindex); + if (h_dentry && h_dentry->d_inode) { + arg.bindex = bindex; + err = do_test_empty(dentry, &arg); + } + } + +out_whlist: + au_nhash_wh_free(&whlist); +out: + return err; +} + +int au_test_empty(struct dentry *dentry, struct au_nhash *whlist) +{ + int err; + struct test_empty_arg arg; + aufs_bindex_t bindex, btail; + + err = 0; + arg.whlist = whlist; + arg.flags = AuTestEmpty_WHONLY; + if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)) + au_fset_testempty(arg.flags, SHWH); + btail = au_dbtaildir(dentry); + for (bindex = au_dbstart(dentry); !err && bindex <= btail; bindex++) { + struct dentry *h_dentry; + + h_dentry = au_h_dptr(dentry, bindex); + if (h_dentry && h_dentry->d_inode) { + arg.bindex = bindex; + err = sio_test_empty(dentry, &arg); + } + } + + return err; +} + +/* ---------------------------------------------------------------------- */ + +const struct file_operations aufs_dir_fop = { + .owner = THIS_MODULE, + .llseek = default_llseek, + .read = generic_read_dir, + .readdir = aufs_readdir, + .unlocked_ioctl = aufs_ioctl_dir, +#ifdef CONFIG_COMPAT + .compat_ioctl = aufs_compat_ioctl_dir, +#endif + .open = aufs_open_dir, + .release = aufs_release_dir, + .flush = aufs_flush_dir, + .fsync = aufs_fsync_dir +}; --- linux-2.6.37.orig/ubuntu/aufs/dir.h +++ linux-2.6.37/ubuntu/aufs/dir.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * directory operations + */ + +#ifndef __AUFS_DIR_H__ +#define __AUFS_DIR_H__ + +#ifdef __KERNEL__ + +#include +#include + +/* ---------------------------------------------------------------------- */ + +/* need to be faster and smaller */ + +struct au_nhash { + unsigned int nh_num; + struct hlist_head *nh_head; +}; + +struct au_vdir_destr { + unsigned char len; + unsigned char name[0]; +} __packed; + +struct au_vdir_dehstr { + struct hlist_node hash; + struct au_vdir_destr *str; +} ____cacheline_aligned_in_smp; + +struct au_vdir_de { + ino_t de_ino; + unsigned char de_type; + /* caution: packed */ + struct au_vdir_destr de_str; +} __packed; + +struct au_vdir_wh { + struct hlist_node wh_hash; +#ifdef CONFIG_AUFS_SHWH + ino_t wh_ino; + aufs_bindex_t wh_bindex; + unsigned char wh_type; +#else + aufs_bindex_t wh_bindex; +#endif + /* caution: packed */ + struct au_vdir_destr wh_str; +} __packed; + +union au_vdir_deblk_p { + unsigned char *deblk; + struct au_vdir_de *de; +}; + +struct au_vdir { + unsigned char **vd_deblk; + unsigned long vd_nblk; + struct { + unsigned long ul; + union au_vdir_deblk_p p; + } vd_last; + + unsigned long vd_version; + unsigned int vd_deblk_sz; + unsigned long vd_jiffy; +} ____cacheline_aligned_in_smp; + +/* ---------------------------------------------------------------------- */ + +/* dir.c */ +extern const struct file_operations aufs_dir_fop; +void au_add_nlink(struct inode *dir, struct inode *h_dir); +void au_sub_nlink(struct inode *dir, struct inode *h_dir); +loff_t au_dir_size(struct file *file, struct dentry *dentry); +int au_test_empty_lower(struct dentry *dentry); +int au_test_empty(struct dentry *dentry, struct au_nhash *whlist); + +/* vdir.c */ +unsigned int au_rdhash_est(loff_t sz); +int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp); +void au_nhash_wh_free(struct au_nhash *whlist); +int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, + int limit); +int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen); +int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, + unsigned int d_type, aufs_bindex_t bindex, + unsigned char shwh); +void au_vdir_free(struct au_vdir *vdir); +int au_vdir_init(struct file *file); +int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir); + +/* ioctl.c */ +long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg); + +#ifdef CONFIG_AUFS_RDU +/* rdu.c */ +long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT +long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); +#endif +#else +static inline long au_rdu_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + return -EINVAL; +} +#ifdef CONFIG_COMPAT +static inline long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + return -EINVAL; +} +#endif +#endif + +#endif /* __KERNEL__ */ +#endif /* __AUFS_DIR_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/dynop.c +++ linux-2.6.37/ubuntu/aufs/dynop.c @@ -0,0 +1,425 @@ +/* + * Copyright (C) 2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * dynamically customizable operations for regular files + */ + +#include "aufs.h" + +#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop) + +/* + * How large will these lists be? + * Usually just a few elements, 20-30 at most for each, I guess. + */ +static struct au_splhead dynop[AuDyLast]; + +static struct au_dykey *dy_gfind_get(struct au_splhead *spl, const void *h_op) +{ + struct au_dykey *key, *tmp; + struct list_head *head; + + key = NULL; + head = &spl->head; + rcu_read_lock(); + list_for_each_entry_rcu(tmp, head, dk_list) + if (tmp->dk_op.dy_hop == h_op) { + key = tmp; + kref_get(&key->dk_kref); + break; + } + rcu_read_unlock(); + + return key; +} + +static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key) +{ + struct au_dykey **k, *found; + const void *h_op = key->dk_op.dy_hop; + int i; + + found = NULL; + k = br->br_dykey; + for (i = 0; i < AuBrDynOp; i++) + if (k[i]) { + if (k[i]->dk_op.dy_hop == h_op) { + found = k[i]; + break; + } + } else + break; + if (!found) { + spin_lock(&br->br_dykey_lock); + for (; i < AuBrDynOp; i++) + if (k[i]) { + if (k[i]->dk_op.dy_hop == h_op) { + found = k[i]; + break; + } + } else { + k[i] = key; + break; + } + spin_unlock(&br->br_dykey_lock); + BUG_ON(i == AuBrDynOp); /* expand the array */ + } + + return found; +} + +/* kref_get() if @key is already added */ +static struct au_dykey *dy_gadd(struct au_splhead *spl, struct au_dykey *key) +{ + struct au_dykey *tmp, *found; + struct list_head *head; + const void *h_op = key->dk_op.dy_hop; + + found = NULL; + head = &spl->head; + spin_lock(&spl->spin); + list_for_each_entry(tmp, head, dk_list) + if (tmp->dk_op.dy_hop == h_op) { + kref_get(&tmp->dk_kref); + found = tmp; + break; + } + if (!found) + list_add_rcu(&key->dk_list, head); + spin_unlock(&spl->spin); + + if (!found) + DyPrSym(key); + return found; +} + +static void dy_free_rcu(struct rcu_head *rcu) +{ + struct au_dykey *key; + + key = container_of(rcu, struct au_dykey, dk_rcu); + DyPrSym(key); + kfree(key); +} + +static void dy_free(struct kref *kref) +{ + struct au_dykey *key; + struct au_splhead *spl; + + key = container_of(kref, struct au_dykey, dk_kref); + spl = dynop + key->dk_op.dy_type; + au_spl_del_rcu(&key->dk_list, spl); + call_rcu(&key->dk_rcu, dy_free_rcu); +} + +void au_dy_put(struct au_dykey *key) +{ + kref_put(&key->dk_kref, dy_free); +} + +/* ---------------------------------------------------------------------- */ + +#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *)) + +#ifdef CONFIG_AUFS_DEBUG +#define DyDbgDeclare(cnt) unsigned int cnt = 0 +#define DyDbgInc(cnt) do { cnt++; } while (0) +#else +#define DyDbgDeclare(cnt) do {} while (0) +#define DyDbgInc(cnt) do {} while (0) +#endif + +#define DySet(func, dst, src, h_op, h_sb) do { \ + DyDbgInc(cnt); \ + if (h_op->func) { \ + if (src.func) \ + dst.func = src.func; \ + else \ + AuDbg("%s %s\n", au_sbtype(h_sb), #func); \ + } \ +} while (0) + +#define DySetForce(func, dst, src) do { \ + AuDebugOn(!src.func); \ + DyDbgInc(cnt); \ + dst.func = src.func; \ +} while (0) + +#define DySetAop(func) \ + DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb) +#define DySetAopForce(func) \ + DySetForce(func, dyaop->da_op, aufs_aop) + +static void dy_aop(struct au_dykey *key, const void *h_op, + struct super_block *h_sb __maybe_unused) +{ + struct au_dyaop *dyaop = (void *)key; + const struct address_space_operations *h_aop = h_op; + DyDbgDeclare(cnt); + + AuDbg("%s\n", au_sbtype(h_sb)); + + DySetAop(writepage); + DySetAopForce(readpage); /* force */ + DySetAop(sync_page); + DySetAop(writepages); + DySetAop(set_page_dirty); + DySetAop(readpages); + DySetAop(write_begin); + DySetAop(write_end); + DySetAop(bmap); + DySetAop(invalidatepage); + DySetAop(releasepage); + /* these two will be changed according to an aufs mount option */ + DySetAop(direct_IO); + DySetAop(get_xip_mem); + DySetAop(migratepage); + DySetAop(launder_page); + DySetAop(is_partially_uptodate); + DySetAop(error_remove_page); + + DyDbgSize(cnt, *h_aop); + dyaop->da_get_xip_mem = h_aop->get_xip_mem; +} + +#define DySetVmop(func) \ + DySet(func, dyvmop->dv_op, aufs_vm_ops, h_vmop, h_sb) +#define DySetVmopForce(func) \ + DySetForce(func, dyvmop->dv_op, aufs_vm_ops) + +static void dy_vmop(struct au_dykey *key, const void *h_op, + struct super_block *h_sb __maybe_unused) +{ + struct au_dyvmop *dyvmop = (void *)key; + const struct vm_operations_struct *h_vmop = h_op; + DyDbgDeclare(cnt); + + AuDbg("%s\n", au_sbtype(h_sb)); + + DySetVmop(open); + DySetVmop(close); + DySetVmop(fault); + DySetVmop(page_mkwrite); + DySetVmop(access); +#ifdef CONFIG_NUMA + DySetVmop(set_policy); + DySetVmop(get_policy); + DySetVmop(migrate); +#endif + + DyDbgSize(cnt, *h_vmop); +} + +/* ---------------------------------------------------------------------- */ + +static void dy_bug(struct kref *kref) +{ + BUG(); +} + +static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br) +{ + struct au_dykey *key, *old; + struct au_splhead *spl; + struct op { + unsigned int sz; + void (*set)(struct au_dykey *key, const void *h_op, + struct super_block *h_sb __maybe_unused); + }; + static const struct op a[] = { + [AuDy_AOP] = { + .sz = sizeof(struct au_dyaop), + .set = dy_aop + }, + [AuDy_VMOP] = { + .sz = sizeof(struct au_dyvmop), + .set = dy_vmop + } + }; + const struct op *p; + + spl = dynop + op->dy_type; + key = dy_gfind_get(spl, op->dy_hop); + if (key) + goto out_add; /* success */ + + p = a + op->dy_type; + key = kzalloc(p->sz, GFP_NOFS); + if (unlikely(!key)) { + key = ERR_PTR(-ENOMEM); + goto out; + } + + key->dk_op.dy_hop = op->dy_hop; + kref_init(&key->dk_kref); + p->set(key, op->dy_hop, br->br_mnt->mnt_sb); + old = dy_gadd(spl, key); + if (old) { + kfree(key); + key = old; + } + +out_add: + old = dy_bradd(br, key); + if (old) + /* its ref-count should never be zero here */ + kref_put(&key->dk_kref, dy_bug); +out: + return key; +} + +/* ---------------------------------------------------------------------- */ +/* + * Aufs prohibits O_DIRECT by defaut even if the branch supports it. + * This behaviour is neccessary to return an error from open(O_DIRECT) instead + * of the succeeding I/O. The dio mount option enables O_DIRECT and makes + * open(O_DIRECT) always succeed, but the succeeding I/O may return an error. + * See the aufs manual in detail. + * + * To keep this behaviour, aufs has to set NULL to ->get_xip_mem too, and the + * performance of fadvise() and madvise() may be affected. + */ +static void dy_adx(struct au_dyaop *dyaop, int do_dx) +{ + if (!do_dx) { + dyaop->da_op.direct_IO = NULL; + dyaop->da_op.get_xip_mem = NULL; + } else { + dyaop->da_op.direct_IO = aufs_aop.direct_IO; + dyaop->da_op.get_xip_mem = aufs_aop.get_xip_mem; + if (!dyaop->da_get_xip_mem) + dyaop->da_op.get_xip_mem = NULL; + } +} + +static struct au_dyaop *dy_aget(struct au_branch *br, + const struct address_space_operations *h_aop, + int do_dx) +{ + struct au_dyaop *dyaop; + struct au_dynop op; + + op.dy_type = AuDy_AOP; + op.dy_haop = h_aop; + dyaop = (void *)dy_get(&op, br); + if (IS_ERR(dyaop)) + goto out; + dy_adx(dyaop, do_dx); + +out: + return dyaop; +} + +int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, + struct inode *h_inode) +{ + int err, do_dx; + struct super_block *sb; + struct au_branch *br; + struct au_dyaop *dyaop; + + AuDebugOn(!S_ISREG(h_inode->i_mode)); + IiMustWriteLock(inode); + + sb = inode->i_sb; + br = au_sbr(sb, bindex); + do_dx = !!au_opt_test(au_mntflags(sb), DIO); + dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx); + err = PTR_ERR(dyaop); + if (IS_ERR(dyaop)) + /* unnecessary to call dy_fput() */ + goto out; + + err = 0; + inode->i_mapping->a_ops = &dyaop->da_op; + +out: + return err; +} + +/* + * Is it safe to replace a_ops during the inode/file is in operation? + * Yes, I hope so. + */ +int au_dy_irefresh(struct inode *inode) +{ + int err; + aufs_bindex_t bstart; + struct inode *h_inode; + + err = 0; + if (S_ISREG(inode->i_mode)) { + bstart = au_ibstart(inode); + h_inode = au_h_iptr(inode, bstart); + err = au_dy_iaop(inode, bstart, h_inode); + } + return err; +} + +void au_dy_arefresh(int do_dx) +{ + struct au_splhead *spl; + struct list_head *head; + struct au_dykey *key; + + spl = dynop + AuDy_AOP; + head = &spl->head; + spin_lock(&spl->spin); + list_for_each_entry(key, head, dk_list) + dy_adx((void *)key, do_dx); + spin_unlock(&spl->spin); +} + +const struct vm_operations_struct * +au_dy_vmop(struct file *file, struct au_branch *br, + const struct vm_operations_struct *h_vmop) +{ + struct au_dyvmop *dyvmop; + struct au_dynop op; + + op.dy_type = AuDy_VMOP; + op.dy_hvmop = h_vmop; + dyvmop = (void *)dy_get(&op, br); + if (IS_ERR(dyvmop)) + return (void *)dyvmop; + return &dyvmop->dv_op; +} + +/* ---------------------------------------------------------------------- */ + +void __init au_dy_init(void) +{ + int i; + + /* make sure that 'struct au_dykey *' can be any type */ + BUILD_BUG_ON(offsetof(struct au_dyaop, da_key)); + BUILD_BUG_ON(offsetof(struct au_dyvmop, dv_key)); + + for (i = 0; i < AuDyLast; i++) + au_spl_init(dynop + i); +} + +void au_dy_fin(void) +{ + int i; + + for (i = 0; i < AuDyLast; i++) + WARN_ON(!list_empty(&dynop[i].head)); +} --- linux-2.6.37.orig/ubuntu/aufs/dynop.h +++ linux-2.6.37/ubuntu/aufs/dynop.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * dynamically customizable operations (for regular files only) + */ + +#ifndef __AUFS_DYNOP_H__ +#define __AUFS_DYNOP_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include "inode.h" + +enum {AuDy_AOP, AuDy_VMOP, AuDyLast}; + +struct au_dynop { + int dy_type; + union { + const void *dy_hop; + const struct address_space_operations *dy_haop; + const struct vm_operations_struct *dy_hvmop; + }; +}; + +struct au_dykey { + union { + struct list_head dk_list; + struct rcu_head dk_rcu; + }; + struct au_dynop dk_op; + + /* + * during I am in the branch local array, kref is gotten. when the + * branch is removed, kref is put. + */ + struct kref dk_kref; +}; + +/* stop unioning since their sizes are very different from each other */ +struct au_dyaop { + struct au_dykey da_key; + struct address_space_operations da_op; /* not const */ + int (*da_get_xip_mem)(struct address_space *, pgoff_t, int, + void **, unsigned long *); +}; + +struct au_dyvmop { + struct au_dykey dv_key; + struct vm_operations_struct dv_op; /* not const */ +}; + +/* ---------------------------------------------------------------------- */ + +/* dynop.c */ +struct au_branch; +void au_dy_put(struct au_dykey *key); +int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex, + struct inode *h_inode); +int au_dy_irefresh(struct inode *inode); +void au_dy_arefresh(int do_dio); +const struct vm_operations_struct * +au_dy_vmop(struct file *file, struct au_branch *br, + const struct vm_operations_struct *h_vmop); + +void __init au_dy_init(void); +void au_dy_fin(void); + +#endif /* __KERNEL__ */ +#endif /* __AUFS_DYNOP_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/export.c +++ linux-2.6.37/ubuntu/aufs/export.c @@ -0,0 +1,790 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * export via nfs + */ + +#include +#include +#include +#include +#include +#include +#include +#include "aufs.h" + +union conv { +#ifdef CONFIG_AUFS_INO_T_64 + __u32 a[2]; +#else + __u32 a[1]; +#endif + ino_t ino; +}; + +static ino_t decode_ino(__u32 *a) +{ + union conv u; + + BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a)); + u.a[0] = a[0]; +#ifdef CONFIG_AUFS_INO_T_64 + u.a[1] = a[1]; +#endif + return u.ino; +} + +static void encode_ino(__u32 *a, ino_t ino) +{ + union conv u; + + u.ino = ino; + a[0] = u.a[0]; +#ifdef CONFIG_AUFS_INO_T_64 + a[1] = u.a[1]; +#endif +} + +/* NFS file handle */ +enum { + Fh_br_id, + Fh_sigen, +#ifdef CONFIG_AUFS_INO_T_64 + /* support 64bit inode number */ + Fh_ino1, + Fh_ino2, + Fh_dir_ino1, + Fh_dir_ino2, +#else + Fh_ino1, + Fh_dir_ino1, +#endif + Fh_igen, + Fh_h_type, + Fh_tail, + + Fh_ino = Fh_ino1, + Fh_dir_ino = Fh_dir_ino1 +}; + +static int au_test_anon(struct dentry *dentry) +{ + return !!(dentry->d_flags & DCACHE_DISCONNECTED); +} + +/* ---------------------------------------------------------------------- */ +/* inode generation external table */ + +void au_xigen_inc(struct inode *inode) +{ + loff_t pos; + ssize_t sz; + __u32 igen; + struct super_block *sb; + struct au_sbinfo *sbinfo; + + sb = inode->i_sb; + AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); + + sbinfo = au_sbi(sb); + pos = inode->i_ino; + pos *= sizeof(igen); + igen = inode->i_generation + 1; + sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen, + sizeof(igen), &pos); + if (sz == sizeof(igen)) + return; /* success */ + + if (unlikely(sz >= 0)) + AuIOErr("xigen error (%zd)\n", sz); +} + +int au_xigen_new(struct inode *inode) +{ + int err; + loff_t pos; + ssize_t sz; + struct super_block *sb; + struct au_sbinfo *sbinfo; + struct file *file; + + err = 0; + /* todo: dirty, at mount time */ + if (inode->i_ino == AUFS_ROOT_INO) + goto out; + sb = inode->i_sb; + SiMustAnyLock(sb); + if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) + goto out; + + err = -EFBIG; + pos = inode->i_ino; + if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) { + AuIOErr1("too large i%lld\n", pos); + goto out; + } + pos *= sizeof(inode->i_generation); + + err = 0; + sbinfo = au_sbi(sb); + file = sbinfo->si_xigen; + BUG_ON(!file); + + if (i_size_read(file->f_dentry->d_inode) + < pos + sizeof(inode->i_generation)) { + inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next); + sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation, + sizeof(inode->i_generation), &pos); + } else + sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation, + sizeof(inode->i_generation), &pos); + if (sz == sizeof(inode->i_generation)) + goto out; /* success */ + + err = sz; + if (unlikely(sz >= 0)) { + err = -EIO; + AuIOErr("xigen error (%zd)\n", sz); + } + +out: + return err; +} + +int au_xigen_set(struct super_block *sb, struct file *base) +{ + int err; + struct au_sbinfo *sbinfo; + struct file *file; + + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); + file = au_xino_create2(base, sbinfo->si_xigen); + err = PTR_ERR(file); + if (IS_ERR(file)) + goto out; + err = 0; + if (sbinfo->si_xigen) + fput(sbinfo->si_xigen); + sbinfo->si_xigen = file; + +out: + return err; +} + +void au_xigen_clr(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); + if (sbinfo->si_xigen) { + fput(sbinfo->si_xigen); + sbinfo->si_xigen = NULL; + } +} + +/* ---------------------------------------------------------------------- */ + +static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino, + ino_t dir_ino) +{ + struct dentry *dentry, *d; + struct inode *inode; + unsigned int sigen; + + dentry = NULL; + inode = ilookup(sb, ino); + if (!inode) + goto out; + + dentry = ERR_PTR(-ESTALE); + sigen = au_sigen(sb); + if (unlikely(is_bad_inode(inode) + || IS_DEADDIR(inode) + || sigen != au_iigen(inode))) + goto out_iput; + + dentry = NULL; + if (!dir_ino || S_ISDIR(inode->i_mode)) + dentry = d_find_alias(inode); + else { + spin_lock(&dcache_lock); + list_for_each_entry(d, &inode->i_dentry, d_alias) + if (!au_test_anon(d) + && d->d_parent->d_inode->i_ino == dir_ino) { + dentry = dget_locked(d); + break; + } + spin_unlock(&dcache_lock); + } + if (unlikely(dentry && sigen != au_digen(dentry))) { + dput(dentry); + dentry = ERR_PTR(-ESTALE); + } + +out_iput: + iput(inode); +out: + return dentry; +} + +/* ---------------------------------------------------------------------- */ + +/* todo: dirty? */ +/* if exportfs_decode_fh() passed vfsmount*, we could be happy */ + +struct au_compare_mnt_args { + /* input */ + struct super_block *sb; + + /* output */ + struct vfsmount *mnt; +}; + +static int au_compare_mnt(struct vfsmount *mnt, void *arg) +{ + struct au_compare_mnt_args *a = arg; + + if (mnt->mnt_sb != a->sb) + return 0; + a->mnt = mntget(mnt); + return 1; +} + +static struct vfsmount *au_mnt_get(struct super_block *sb) +{ + int err; + struct au_compare_mnt_args args = { + .sb = sb + }; + struct mnt_namespace *ns; + + br_read_lock(vfsmount_lock); + /* no get/put ?? */ + AuDebugOn(!current->nsproxy); + ns = current->nsproxy->mnt_ns; + AuDebugOn(!ns); + err = iterate_mounts(au_compare_mnt, &args, ns->root); + br_read_unlock(vfsmount_lock); + AuDebugOn(!err); + AuDebugOn(!args.mnt); + return args.mnt; +} + +struct au_nfsd_si_lock { + unsigned int sigen; + aufs_bindex_t br_id; + unsigned char force_lock; +}; + +static aufs_bindex_t si_nfsd_read_lock(struct super_block *sb, + struct au_nfsd_si_lock *nsi_lock) +{ + aufs_bindex_t bindex; + + si_read_lock(sb, AuLock_FLUSH); + + /* branch id may be wrapped around */ + bindex = au_br_index(sb, nsi_lock->br_id); + if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb)) + goto out; /* success */ + + if (!nsi_lock->force_lock) + si_read_unlock(sb); + bindex = -1; + +out: + return bindex; +} + +struct find_name_by_ino { + int called, found; + ino_t ino; + char *name; + int namelen; +}; + +static int +find_name_by_ino(void *arg, const char *name, int namelen, loff_t offset, + u64 ino, unsigned int d_type) +{ + struct find_name_by_ino *a = arg; + + a->called++; + if (a->ino != ino) + return 0; + + memcpy(a->name, name, namelen); + a->namelen = namelen; + a->found = 1; + return 1; +} + +static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino, + struct au_nfsd_si_lock *nsi_lock) +{ + struct dentry *dentry, *parent; + struct file *file; + struct inode *dir; + struct find_name_by_ino arg; + int err; + + parent = path->dentry; + if (nsi_lock) + si_read_unlock(parent->d_sb); + file = vfsub_dentry_open(path, au_dir_roflags); + dentry = (void *)file; + if (IS_ERR(file)) + goto out; + + dentry = ERR_PTR(-ENOMEM); + arg.name = __getname_gfp(GFP_NOFS); + if (unlikely(!arg.name)) + goto out_file; + arg.ino = ino; + arg.found = 0; + do { + arg.called = 0; + /* smp_mb(); */ + err = vfsub_readdir(file, find_name_by_ino, &arg); + } while (!err && !arg.found && arg.called); + dentry = ERR_PTR(err); + if (unlikely(err)) + goto out_name; + dentry = ERR_PTR(-ENOENT); + if (!arg.found) + goto out_name; + + /* do not call au_lkup_one() */ + dir = parent->d_inode; + mutex_lock(&dir->i_mutex); + dentry = vfsub_lookup_one_len(arg.name, parent, arg.namelen); + mutex_unlock(&dir->i_mutex); + AuTraceErrPtr(dentry); + if (IS_ERR(dentry)) + goto out_name; + AuDebugOn(au_test_anon(dentry)); + if (unlikely(!dentry->d_inode)) { + dput(dentry); + dentry = ERR_PTR(-ENOENT); + } + +out_name: + __putname(arg.name); +out_file: + fput(file); +out: + if (unlikely(nsi_lock + && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0)) + if (!IS_ERR(dentry)) { + dput(dentry); + dentry = ERR_PTR(-ESTALE); + } + AuTraceErrPtr(dentry); + return dentry; +} + +static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino, + ino_t dir_ino, + struct au_nfsd_si_lock *nsi_lock) +{ + struct dentry *dentry; + struct path path; + + if (dir_ino != AUFS_ROOT_INO) { + path.dentry = decode_by_ino(sb, dir_ino, 0); + dentry = path.dentry; + if (!path.dentry || IS_ERR(path.dentry)) + goto out; + AuDebugOn(au_test_anon(path.dentry)); + } else + path.dentry = dget(sb->s_root); + + path.mnt = au_mnt_get(sb); + dentry = au_lkup_by_ino(&path, ino, nsi_lock); + path_put(&path); + +out: + AuTraceErrPtr(dentry); + return dentry; +} + +/* ---------------------------------------------------------------------- */ + +static int h_acceptable(void *expv, struct dentry *dentry) +{ + return 1; +} + +static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath, + char *buf, int len, struct super_block *sb) +{ + char *p; + int n; + struct path path; + + p = d_path(h_rootpath, buf, len); + if (IS_ERR(p)) + goto out; + n = strlen(p); + + path.mnt = h_rootpath->mnt; + path.dentry = h_parent; + p = d_path(&path, buf, len); + if (IS_ERR(p)) + goto out; + if (n != 1) + p += n; + + path.mnt = au_mnt_get(sb); + path.dentry = sb->s_root; + p = d_path(&path, buf, len - strlen(p)); + mntput(path.mnt); + if (IS_ERR(p)) + goto out; + if (n != 1) + p[strlen(p)] = '/'; + +out: + AuTraceErrPtr(p); + return p; +} + +static +struct dentry *decode_by_path(struct super_block *sb, aufs_bindex_t bindex, + ino_t ino, __u32 *fh, int fh_len, + struct au_nfsd_si_lock *nsi_lock) +{ + struct dentry *dentry, *h_parent, *root; + struct super_block *h_sb; + char *pathname, *p; + struct vfsmount *h_mnt; + struct au_branch *br; + int err; + struct path path; + + br = au_sbr(sb, bindex); + /* au_br_get(br); */ + h_mnt = br->br_mnt; + h_sb = h_mnt->mnt_sb; + /* todo: call lower fh_to_dentry()? fh_to_parent()? */ + h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail), + fh_len - Fh_tail, fh[Fh_h_type], + h_acceptable, /*context*/NULL); + dentry = h_parent; + if (unlikely(!h_parent || IS_ERR(h_parent))) { + AuWarn1("%s decode_fh failed, %ld\n", + au_sbtype(h_sb), PTR_ERR(h_parent)); + goto out; + } + dentry = NULL; + if (unlikely(au_test_anon(h_parent))) { + AuWarn1("%s decode_fh returned a disconnected dentry\n", + au_sbtype(h_sb)); + goto out_h_parent; + } + + dentry = ERR_PTR(-ENOMEM); + pathname = (void *)__get_free_page(GFP_NOFS); + if (unlikely(!pathname)) + goto out_h_parent; + + root = sb->s_root; + path.mnt = h_mnt; + di_read_lock_parent(root, !AuLock_IR); + path.dentry = au_h_dptr(root, bindex); + di_read_unlock(root, !AuLock_IR); + p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb); + dentry = (void *)p; + if (IS_ERR(p)) + goto out_pathname; + + si_read_unlock(sb); + err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); + dentry = ERR_PTR(err); + if (unlikely(err)) + goto out_relock; + + dentry = ERR_PTR(-ENOENT); + AuDebugOn(au_test_anon(path.dentry)); + if (unlikely(!path.dentry->d_inode)) + goto out_path; + + if (ino != path.dentry->d_inode->i_ino) + dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL); + else + dentry = dget(path.dentry); + +out_path: + path_put(&path); +out_relock: + if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0)) + if (!IS_ERR(dentry)) { + dput(dentry); + dentry = ERR_PTR(-ESTALE); + } +out_pathname: + free_page((unsigned long)pathname); +out_h_parent: + dput(h_parent); +out: + /* au_br_put(br); */ + AuTraceErrPtr(dentry); + return dentry; +} + +/* ---------------------------------------------------------------------- */ + +static struct dentry * +aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, + int fh_type) +{ + struct dentry *dentry; + __u32 *fh = fid->raw; + ino_t ino, dir_ino; + aufs_bindex_t bindex; + struct au_nfsd_si_lock nsi_lock = { + .force_lock = 0 + }; + + dentry = ERR_PTR(-ESTALE); + /* it should never happen, but the file handle is unreliable */ + if (unlikely(fh_len < Fh_tail)) + goto out; + nsi_lock.sigen = fh[Fh_sigen]; + nsi_lock.br_id = fh[Fh_br_id]; + + /* branch id may be wrapped around */ + bindex = si_nfsd_read_lock(sb, &nsi_lock); + if (unlikely(bindex < 0)) + goto out; + nsi_lock.force_lock = 1; + + /* is this inode still cached? */ + ino = decode_ino(fh + Fh_ino); + /* it should never happen */ + if (unlikely(ino == AUFS_ROOT_INO)) + goto out; + + dir_ino = decode_ino(fh + Fh_dir_ino); + dentry = decode_by_ino(sb, ino, dir_ino); + if (IS_ERR(dentry)) + goto out_unlock; + if (dentry) + goto accept; + + /* is the parent dir cached? */ + dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock); + if (IS_ERR(dentry)) + goto out_unlock; + if (dentry) + goto accept; + + /* lookup path */ + dentry = decode_by_path(sb, bindex, ino, fh, fh_len, &nsi_lock); + if (IS_ERR(dentry)) + goto out_unlock; + if (unlikely(!dentry)) + /* todo?: make it ESTALE */ + goto out_unlock; + +accept: + if (dentry->d_inode->i_generation == fh[Fh_igen]) + goto out_unlock; /* success */ + + dput(dentry); + dentry = ERR_PTR(-ESTALE); +out_unlock: + si_read_unlock(sb); +out: + AuTraceErrPtr(dentry); + return dentry; +} + +#if 0 /* reserved for future use */ +/* support subtreecheck option */ +static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + struct dentry *parent; + __u32 *fh = fid->raw; + ino_t dir_ino; + + dir_ino = decode_ino(fh + Fh_dir_ino); + parent = decode_by_ino(sb, dir_ino, 0); + if (IS_ERR(parent)) + goto out; + if (!parent) + parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]), + dir_ino, fh, fh_len); + +out: + AuTraceErrPtr(parent); + return parent; +} +#endif + +/* ---------------------------------------------------------------------- */ + +static int aufs_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len, + int connectable) +{ + int err; + aufs_bindex_t bindex, bend; + struct super_block *sb, *h_sb; + struct inode *inode; + struct dentry *parent, *h_parent; + struct au_branch *br; + + AuDebugOn(au_test_anon(dentry)); + + parent = NULL; + err = -ENOSPC; + if (unlikely(*max_len <= Fh_tail)) { + AuWarn1("NFSv2 client (max_len %d)?\n", *max_len); + goto out; + } + + err = FILEID_ROOT; + if (IS_ROOT(dentry)) { + AuDebugOn(dentry->d_inode->i_ino != AUFS_ROOT_INO); + goto out; + } + + err = -EIO; + h_parent = NULL; + sb = dentry->d_sb; + aufs_read_lock(dentry, AuLock_FLUSH | AuLock_IR); + parent = dget_parent(dentry); + di_read_lock_parent(parent, !AuLock_IR); + inode = dentry->d_inode; + AuDebugOn(!inode); +#ifdef CONFIG_AUFS_DEBUG + if (unlikely(!au_opt_test(au_mntflags(sb), XINO))) + AuWarn1("NFS-exporting requires xino\n"); +#endif + + bend = au_dbtaildir(parent); + for (bindex = au_dbstart(parent); bindex <= bend; bindex++) { + h_parent = au_h_dptr(parent, bindex); + if (h_parent) { + dget(h_parent); + break; + } + } + if (unlikely(!h_parent)) + goto out_unlock; + + err = -EPERM; + br = au_sbr(sb, bindex); + h_sb = br->br_mnt->mnt_sb; + if (unlikely(!h_sb->s_export_op)) { + AuErr1("%s branch is not exportable\n", au_sbtype(h_sb)); + goto out_dput; + } + + fh[Fh_br_id] = br->br_id; + fh[Fh_sigen] = au_sigen(sb); + encode_ino(fh + Fh_ino, inode->i_ino); + encode_ino(fh + Fh_dir_ino, parent->d_inode->i_ino); + fh[Fh_igen] = inode->i_generation; + + *max_len -= Fh_tail; + fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail), + max_len, + /*connectable or subtreecheck*/0); + err = fh[Fh_h_type]; + *max_len += Fh_tail; + /* todo: macros? */ + if (err != 255) + err = 99; + else + AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb)); + +out_dput: + dput(h_parent); +out_unlock: + di_read_unlock(parent, !AuLock_IR); + dput(parent); + aufs_read_unlock(dentry, AuLock_IR); +out: + if (unlikely(err < 0)) + err = 255; + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int aufs_commit_metadata(struct inode *inode) +{ + int err; + aufs_bindex_t bindex; + struct super_block *sb; + struct inode *h_inode; + int (*f)(struct inode *inode); + + sb = inode->i_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + ii_write_lock_child(inode); + bindex = au_ibstart(inode); + AuDebugOn(bindex < 0); + h_inode = au_h_iptr(inode, bindex); + + f = h_inode->i_sb->s_export_op->commit_metadata; + if (f) + err = f(h_inode); + else { + struct writeback_control wbc = { + .sync_mode = WB_SYNC_ALL, + .nr_to_write = 0 /* metadata only */ + }; + + err = sync_inode(h_inode, &wbc); + } + + au_cpup_attr_timesizes(inode); + ii_write_unlock(inode); + si_read_unlock(sb); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static struct export_operations aufs_export_op = { + .fh_to_dentry = aufs_fh_to_dentry, + /* .fh_to_parent = aufs_fh_to_parent, */ + .encode_fh = aufs_encode_fh, + .commit_metadata = aufs_commit_metadata +}; + +void au_export_init(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + __u32 u; + + sb->s_export_op = &aufs_export_op; + sbinfo = au_sbi(sb); + sbinfo->si_xigen = NULL; + get_random_bytes(&u, sizeof(u)); + BUILD_BUG_ON(sizeof(u) != sizeof(int)); + atomic_set(&sbinfo->si_xigen_next, u); +} --- linux-2.6.37.orig/ubuntu/aufs/f_op.c +++ linux-2.6.37/ubuntu/aufs/f_op.c @@ -0,0 +1,902 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * file and vm operations + */ + +#include +#include +#include +#include +#include +#include "aufs.h" + +int au_do_open_nondir(struct file *file, int flags) +{ + int err; + aufs_bindex_t bindex; + struct file *h_file; + struct dentry *dentry; + struct au_finfo *finfo; + + FiMustWriteLock(file); + + err = 0; + dentry = file->f_dentry; + finfo = au_fi(file); + memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop)); + finfo->fi_hvmop = NULL; + bindex = au_dbstart(dentry); + h_file = au_h_open(dentry, bindex, flags, file); + if (IS_ERR(h_file)) + err = PTR_ERR(h_file); + else { + au_set_fbstart(file, bindex); + au_set_h_fptr(file, bindex, h_file); + au_update_figen(file); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + } + return err; +} + +static int aufs_open_nondir(struct inode *inode __maybe_unused, + struct file *file) +{ + int err; + struct super_block *sb; + + AuDbg("%.*s, f_ flags 0x%x, f_mode 0x%x\n", + AuDLNPair(file->f_dentry), vfsub_file_flags(file), + file->f_mode); + + sb = file->f_dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + err = au_do_open(file, au_do_open_nondir, /*fidir*/NULL); + si_read_unlock(sb); + return err; +} + +int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file) +{ + struct au_finfo *finfo; + aufs_bindex_t bindex; + + finfo = au_fi(file); + bindex = finfo->fi_btop; + if (bindex >= 0) { + /* remove me from sb->s_files */ + file_sb_list_del(file); + au_set_h_fptr(file, bindex, NULL); + } + + au_finfo_fin(file); + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int au_do_flush_nondir(struct file *file, fl_owner_t id) +{ + int err; + struct file *h_file; + + err = 0; + h_file = au_hf_top(file); + if (h_file) + err = vfsub_flush(h_file, id); + return err; +} + +static int aufs_flush_nondir(struct file *file, fl_owner_t id) +{ + return au_do_flush(file, id, au_do_flush_nondir); +} + +/* ---------------------------------------------------------------------- */ + +static ssize_t aufs_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + ssize_t err; + struct dentry *dentry; + struct file *h_file; + struct super_block *sb; + + dentry = file->f_dentry; + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0); + if (unlikely(err)) + goto out; + + h_file = au_hf_top(file); + err = vfsub_read_u(h_file, buf, count, ppos); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode); + + di_read_unlock(dentry, AuLock_IR); + fi_read_unlock(file); +out: + si_read_unlock(sb); + return err; +} + +/* + * todo: very ugly + * it locks both of i_mutex and si_rwsem for read in safe. + * if the plink maintenance mode continues forever (that is the problem), + * may loop forever. + */ +static void au_mtx_and_read_lock(struct inode *inode) +{ + int err; + struct super_block *sb = inode->i_sb; + + while (1) { + mutex_lock(&inode->i_mutex); + err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); + if (!err) + break; + mutex_unlock(&inode->i_mutex); + si_read_lock(sb, AuLock_NOPLMW); + si_read_unlock(sb); + } +} + +static ssize_t aufs_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + ssize_t err; + struct au_pin pin; + struct dentry *dentry; + struct inode *inode; + struct file *h_file; + char __user *buf = (char __user *)ubuf; + + dentry = file->f_dentry; + inode = dentry->d_inode; + au_mtx_and_read_lock(inode); + + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1); + if (unlikely(err)) + goto out; + + err = au_ready_to_write(file, -1, &pin); + di_downgrade_lock(dentry, AuLock_IR); + if (unlikely(err)) + goto out_unlock; + + h_file = au_hf_top(file); + au_unpin(&pin); + err = vfsub_write_u(h_file, buf, count, ppos); + au_cpup_attr_timesizes(inode); + inode->i_mode = h_file->f_dentry->d_inode->i_mode; + +out_unlock: + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); +out: + si_read_unlock(inode->i_sb); + mutex_unlock(&inode->i_mutex); + return err; +} + +static ssize_t au_do_aio(struct file *h_file, int rw, struct kiocb *kio, + const struct iovec *iov, unsigned long nv, loff_t pos) +{ + ssize_t err; + struct file *file; + ssize_t (*func)(struct kiocb *, const struct iovec *, unsigned long, + loff_t); + + err = security_file_permission(h_file, rw); + if (unlikely(err)) + goto out; + + err = -ENOSYS; + func = NULL; + if (rw == MAY_READ) + func = h_file->f_op->aio_read; + else if (rw == MAY_WRITE) + func = h_file->f_op->aio_write; + if (func) { + file = kio->ki_filp; + kio->ki_filp = h_file; + err = func(kio, iov, nv, pos); + kio->ki_filp = file; + } else + /* currently there is no such fs */ + WARN_ON_ONCE(1); + +out: + return err; +} + +static ssize_t aufs_aio_read(struct kiocb *kio, const struct iovec *iov, + unsigned long nv, loff_t pos) +{ + ssize_t err; + struct file *file, *h_file; + struct dentry *dentry; + struct super_block *sb; + + file = kio->ki_filp; + dentry = file->f_dentry; + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0); + if (unlikely(err)) + goto out; + + h_file = au_hf_top(file); + err = au_do_aio(h_file, MAY_READ, kio, iov, nv, pos); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode); + di_read_unlock(dentry, AuLock_IR); + fi_read_unlock(file); + +out: + si_read_unlock(sb); + return err; +} + +static ssize_t aufs_aio_write(struct kiocb *kio, const struct iovec *iov, + unsigned long nv, loff_t pos) +{ + ssize_t err; + struct au_pin pin; + struct dentry *dentry; + struct inode *inode; + struct file *file, *h_file; + + file = kio->ki_filp; + dentry = file->f_dentry; + inode = dentry->d_inode; + au_mtx_and_read_lock(inode); + + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1); + if (unlikely(err)) + goto out; + + err = au_ready_to_write(file, -1, &pin); + di_downgrade_lock(dentry, AuLock_IR); + if (unlikely(err)) + goto out_unlock; + + au_unpin(&pin); + h_file = au_hf_top(file); + err = au_do_aio(h_file, MAY_WRITE, kio, iov, nv, pos); + au_cpup_attr_timesizes(inode); + inode->i_mode = h_file->f_dentry->d_inode->i_mode; + +out_unlock: + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); +out: + si_read_unlock(inode->i_sb); + mutex_unlock(&inode->i_mutex); + return err; +} + +static ssize_t aufs_splice_read(struct file *file, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) +{ + ssize_t err; + struct file *h_file; + struct dentry *dentry; + struct super_block *sb; + + dentry = file->f_dentry; + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0); + if (unlikely(err)) + goto out; + + err = -EINVAL; + h_file = au_hf_top(file); + if (au_test_loopback_kthread()) { + file->f_mapping = h_file->f_mapping; + smp_mb(); /* unnecessary? */ + } + err = vfsub_splice_to(h_file, ppos, pipe, len, flags); + /* todo: necessasry? */ + /* file->f_ra = h_file->f_ra; */ + fsstack_copy_attr_atime(dentry->d_inode, h_file->f_dentry->d_inode); + + di_read_unlock(dentry, AuLock_IR); + fi_read_unlock(file); + +out: + si_read_unlock(sb); + return err; +} + +static ssize_t +aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos, + size_t len, unsigned int flags) +{ + ssize_t err; + struct au_pin pin; + struct dentry *dentry; + struct inode *inode; + struct file *h_file; + + dentry = file->f_dentry; + inode = dentry->d_inode; + au_mtx_and_read_lock(inode); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1); + if (unlikely(err)) + goto out; + + err = au_ready_to_write(file, -1, &pin); + di_downgrade_lock(dentry, AuLock_IR); + if (unlikely(err)) + goto out_unlock; + + h_file = au_hf_top(file); + au_unpin(&pin); + err = vfsub_splice_from(pipe, h_file, ppos, len, flags); + au_cpup_attr_timesizes(inode); + inode->i_mode = h_file->f_dentry->d_inode->i_mode; + +out_unlock: + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); +out: + si_read_unlock(inode->i_sb); + mutex_unlock(&inode->i_mutex); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static struct file *au_safe_file(struct vm_area_struct *vma) +{ + struct file *file; + + file = vma->vm_file; + if (file->private_data && au_test_aufs(file->f_dentry->d_sb)) + return file; + return NULL; +} + +static void au_reset_file(struct vm_area_struct *vma, struct file *file) +{ + vma->vm_file = file; + /* smp_mb(); */ /* flush vm_file */ +} + +static int aufs_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + int err; + static DECLARE_WAIT_QUEUE_HEAD(wq); + struct file *file, *h_file; + struct au_finfo *finfo; + + /* todo: non-robr mode, user vm_file as it is? */ + wait_event(wq, (file = au_safe_file(vma))); + + /* do not revalidate, no si lock */ + finfo = au_fi(file); + AuDebugOn(finfo->fi_hdir); + h_file = finfo->fi_htop.hf_file; + AuDebugOn(!h_file || !finfo->fi_hvmop); + + mutex_lock(&finfo->fi_vm_mtx); + vma->vm_file = h_file; + err = finfo->fi_hvmop->fault(vma, vmf); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + au_reset_file(vma, file); + mutex_unlock(&finfo->fi_vm_mtx); +#if 0 /* def CONFIG_SMP */ + /* wake_up_nr(&wq, online_cpu - 1); */ + wake_up_all(&wq); +#else + wake_up(&wq); +#endif + + return err; +} + +static int aufs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + int err; + static DECLARE_WAIT_QUEUE_HEAD(wq); + struct file *file, *h_file; + struct au_finfo *finfo; + + wait_event(wq, (file = au_safe_file(vma))); + + finfo = au_fi(file); + AuDebugOn(finfo->fi_hdir); + h_file = finfo->fi_htop.hf_file; + AuDebugOn(!h_file || !finfo->fi_hvmop); + + mutex_lock(&finfo->fi_vm_mtx); + vma->vm_file = h_file; + err = finfo->fi_hvmop->page_mkwrite(vma, vmf); + au_reset_file(vma, file); + mutex_unlock(&finfo->fi_vm_mtx); + wake_up(&wq); + + return err; +} + +static void aufs_vm_close(struct vm_area_struct *vma) +{ + static DECLARE_WAIT_QUEUE_HEAD(wq); + struct file *file, *h_file; + struct au_finfo *finfo; + + wait_event(wq, (file = au_safe_file(vma))); + + finfo = au_fi(file); + AuDebugOn(finfo->fi_hdir); + h_file = finfo->fi_htop.hf_file; + AuDebugOn(!h_file || !finfo->fi_hvmop); + + mutex_lock(&finfo->fi_vm_mtx); + vma->vm_file = h_file; + finfo->fi_hvmop->close(vma); + au_reset_file(vma, file); + mutex_unlock(&finfo->fi_vm_mtx); + wake_up(&wq); +} + +const struct vm_operations_struct aufs_vm_ops = { + .close = aufs_vm_close, + .fault = aufs_fault, + .page_mkwrite = aufs_page_mkwrite +}; + +/* ---------------------------------------------------------------------- */ + +/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */ +#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b) + +static unsigned long au_arch_prot_conv(unsigned long flags) +{ + /* currently ppc64 only */ +#ifdef CONFIG_PPC64 + /* cf. linux/arch/powerpc/include/asm/mman.h */ + AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO); + return AuConv_VM_PROT(flags, SAO); +#else + AuDebugOn(arch_calc_vm_prot_bits(-1)); + return 0; +#endif +} + +static unsigned long au_prot_conv(unsigned long flags) +{ + return AuConv_VM_PROT(flags, READ) + | AuConv_VM_PROT(flags, WRITE) + | AuConv_VM_PROT(flags, EXEC) + | au_arch_prot_conv(flags); +} + +/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */ +#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b) + +static unsigned long au_flag_conv(unsigned long flags) +{ + return AuConv_VM_MAP(flags, GROWSDOWN) + | AuConv_VM_MAP(flags, DENYWRITE) + | AuConv_VM_MAP(flags, EXECUTABLE) + | AuConv_VM_MAP(flags, LOCKED); +} + +static struct vm_operations_struct * +au_hvmop(struct file *h_file, struct vm_area_struct *vma, unsigned long *flags) +{ + struct vm_operations_struct *h_vmop; + unsigned long prot; + int err; + + h_vmop = ERR_PTR(-ENODEV); + if (!h_file->f_op || !h_file->f_op->mmap) + goto out; + + prot = au_prot_conv(vma->vm_flags); + err = security_file_mmap(h_file, /*reqprot*/prot, prot, + au_flag_conv(vma->vm_flags), vma->vm_start, 0); + h_vmop = ERR_PTR(err); + if (unlikely(err)) + goto out; + + err = h_file->f_op->mmap(h_file, vma); + h_vmop = ERR_PTR(err); + if (unlikely(err)) + goto out; + + /* oops, it became 'const' */ + h_vmop = (struct vm_operations_struct *)vma->vm_ops; + *flags = vma->vm_flags; + err = do_munmap(current->mm, vma->vm_start, + vma->vm_end - vma->vm_start); + if (unlikely(err)) { + AuIOErr("failed internal unmapping %.*s, %d\n", + AuDLNPair(h_file->f_dentry), err); + h_vmop = ERR_PTR(-EIO); + } + +out: + return h_vmop; +} + +/* + * This is another ugly approach to keep the lock order, particularly + * mm->mmap_sem and aufs rwsem. The previous approach was reverted and you can + * find it in git-log, if you want. + * + * native readdir: i_mutex, copy_to_user, mmap_sem + * aufs readdir: i_mutex, rwsem, nested-i_mutex, copy_to_user, mmap_sem + * + * Before aufs_mmap() mmap_sem is acquired already, but aufs_mmap() has to + * acquire aufs rwsem. It introduces a circular locking dependency. + * To address this problem, aufs_mmap() delegates the part which requires aufs + * rwsem to its internal workqueue. + */ + +/* very ugly approach */ +#include "mtx.h" + +struct au_mmap_pre_args { + /* input */ + struct file *file; + struct vm_area_struct *vma; + + /* output */ + int *errp; + struct file *h_file; + struct au_branch *br; + int mmapped; +}; + +static int au_mmap_pre(struct file *file, struct vm_area_struct *vma, + struct file **h_file, struct au_branch **br, + int *mmapped) +{ + int err; + aufs_bindex_t bstart; + const unsigned char wlock + = !!(file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED); + struct dentry *dentry; + struct super_block *sb; + + dentry = file->f_dentry; + sb = dentry->d_sb; + si_read_lock(sb, AuLock_NOPLMW); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1); + if (unlikely(err)) + goto out; + + *mmapped = !!au_test_mmapped(file); + if (wlock) { + struct au_pin pin; + + err = au_ready_to_write(file, -1, &pin); + di_write_unlock(dentry); + if (unlikely(err)) + goto out_unlock; + au_unpin(&pin); + } else + di_write_unlock(dentry); + bstart = au_fbstart(file); + *br = au_sbr(sb, bstart); + *h_file = au_hf_top(file); + get_file(*h_file); + au_fi_mmap_lock(file); + +out_unlock: + fi_write_unlock(file); +out: + si_read_unlock(sb); + return err; +} + +static void au_call_mmap_pre(void *args) +{ + struct au_mmap_pre_args *a = args; + *a->errp = au_mmap_pre(a->file, a->vma, &a->h_file, &a->br, + &a->mmapped); +} + +static int aufs_mmap(struct file *file, struct vm_area_struct *vma) +{ + int err, wkq_err; + unsigned long h_vmflags; + struct au_finfo *finfo; + struct dentry *h_dentry; + struct vm_operations_struct *h_vmop, *vmop; + struct au_mmap_pre_args args = { + .file = file, + .vma = vma, + .errp = &err + }; + + wkq_err = au_wkq_wait_pre(au_call_mmap_pre, &args); + if (unlikely(wkq_err)) + err = wkq_err; + if (unlikely(err)) + goto out; + finfo = au_fi(file); + mutex_set_owner(&finfo->fi_mmap); + + h_dentry = args.h_file->f_dentry; + if (!args.mmapped && au_test_fs_bad_mapping(h_dentry->d_sb)) { + /* + * by this assignment, f_mapping will differs from aufs inode + * i_mapping. + * if someone else mixes the use of f_dentry->d_inode and + * f_mapping->host, then a problem may arise. + */ + file->f_mapping = args.h_file->f_mapping; + } + + /* always try this internal mmap to get vma flags */ + h_vmflags = 0; /* gcc warning */ + h_vmop = au_hvmop(args.h_file, vma, &h_vmflags); + err = PTR_ERR(h_vmop); + if (IS_ERR(h_vmop)) + goto out_unlock; + AuDebugOn(args.mmapped && h_vmop != finfo->fi_hvmop); + + vmop = (void *)au_dy_vmop(file, args.br, h_vmop); + err = PTR_ERR(vmop); + if (IS_ERR(vmop)) + goto out_unlock; + + /* + * unnecessary to handle MAP_DENYWRITE and deny_write_access()? + * currently MAP_DENYWRITE from userspace is ignored, but elf loader + * sets it. when FMODE_EXEC is set (by open_exec() or sys_uselib()), + * both of the aufs file and the lower file is deny_write_access()-ed. + * finally I hope we can skip handlling MAP_DENYWRITE here. + */ + err = generic_file_mmap(file, vma); + if (unlikely(err)) + goto out_unlock; + + vma->vm_ops = vmop; + vma->vm_flags = h_vmflags; + if (!args.mmapped) + finfo->fi_hvmop = h_vmop; + + vfsub_file_accessed(args.h_file); + /* update without lock, I don't think it a problem */ + fsstack_copy_attr_atime(file->f_dentry->d_inode, h_dentry->d_inode); + +out_unlock: + au_fi_mmap_unlock(file); + fput(args.h_file); +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int aufs_fsync_nondir(struct file *file, int datasync) +{ + int err; + struct au_pin pin; + struct dentry *dentry; + struct inode *inode; + struct file *h_file; + struct super_block *sb; + + dentry = file->f_dentry; + inode = dentry->d_inode; + IMustLock(file->f_mapping->host); + if (inode != file->f_mapping->host) { + mutex_unlock(&file->f_mapping->host->i_mutex); + mutex_lock(&inode->i_mutex); + } + IMustLock(inode); + + sb = dentry->d_sb; + err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); + if (unlikely(err)) + goto out; + + err = 0; /* -EBADF; */ /* posix? */ + if (unlikely(!(file->f_mode & FMODE_WRITE))) + goto out_si; + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1); + if (unlikely(err)) + goto out_si; + + err = au_ready_to_write(file, -1, &pin); + di_downgrade_lock(dentry, AuLock_IR); + if (unlikely(err)) + goto out_unlock; + au_unpin(&pin); + + err = -EINVAL; + h_file = au_hf_top(file); + if (h_file->f_op && h_file->f_op->fsync) { + struct mutex *h_mtx; + + /* + * no filemap_fdatawrite() since aufs file has no its own + * mapping, but dir. + */ + h_mtx = &h_file->f_dentry->d_inode->i_mutex; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + err = h_file->f_op->fsync(h_file, datasync); + if (!err) + vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); + /*ignore*/ + au_cpup_attr_timesizes(inode); + mutex_unlock(h_mtx); + } + +out_unlock: + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); +out_si: + si_read_unlock(sb); +out: + if (inode != file->f_mapping->host) { + mutex_unlock(&inode->i_mutex); + mutex_lock(&file->f_mapping->host->i_mutex); + } + return err; +} + +/* no one supports this operation, currently */ +#if 0 +static int aufs_aio_fsync_nondir(struct kiocb *kio, int datasync) +{ + int err; + struct au_pin pin; + struct dentry *dentry; + struct inode *inode; + struct file *file, *h_file; + + file = kio->ki_filp; + dentry = file->f_dentry; + inode = dentry->d_inode; + au_mtx_and_read_lock(inode); + + err = 0; /* -EBADF; */ /* posix? */ + if (unlikely(!(file->f_mode & FMODE_WRITE))) + goto out; + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1); + if (unlikely(err)) + goto out; + + err = au_ready_to_write(file, -1, &pin); + di_downgrade_lock(dentry, AuLock_IR); + if (unlikely(err)) + goto out_unlock; + au_unpin(&pin); + + err = -ENOSYS; + h_file = au_hf_top(file); + if (h_file->f_op && h_file->f_op->aio_fsync) { + struct dentry *h_d; + struct mutex *h_mtx; + + h_d = h_file->f_dentry; + h_mtx = &h_d->d_inode->i_mutex; + if (!is_sync_kiocb(kio)) { + get_file(h_file); + fput(file); + } + kio->ki_filp = h_file; + err = h_file->f_op->aio_fsync(kio, datasync); + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + if (!err) + vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); + /*ignore*/ + au_cpup_attr_timesizes(inode); + mutex_unlock(h_mtx); + } + +out_unlock: + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); +out: + si_read_unlock(inode->sb); + mutex_unlock(&inode->i_mutex); + return err; +} +#endif + +static int aufs_fasync(int fd, struct file *file, int flag) +{ + int err; + struct file *h_file; + struct dentry *dentry; + struct super_block *sb; + + dentry = file->f_dentry; + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0); + if (unlikely(err)) + goto out; + + h_file = au_hf_top(file); + if (h_file->f_op && h_file->f_op->fasync) + err = h_file->f_op->fasync(fd, h_file, flag); + + di_read_unlock(dentry, AuLock_IR); + fi_read_unlock(file); + +out: + si_read_unlock(sb); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* no one supports this operation, currently */ +#if 0 +static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset, + size_t len, loff_t *pos , int more) +{ +} +#endif + +/* ---------------------------------------------------------------------- */ + +const struct file_operations aufs_file_fop = { + .owner = THIS_MODULE, + /* + * while generic_file_llseek/_unlocked() don't use BKL, + * don't use it since it operates file->f_mapping->host. + * in aufs, it may be a real file and may confuse users by UDBA. + */ + /* .llseek = generic_file_llseek, */ + .llseek = default_llseek, + + .read = aufs_read, + .write = aufs_write, + .aio_read = aufs_aio_read, + .aio_write = aufs_aio_write, +#ifdef CONFIG_AUFS_POLL + .poll = aufs_poll, +#endif + .unlocked_ioctl = aufs_ioctl_nondir, +#ifdef CONFIG_COMPAT + .compat_ioctl = aufs_ioctl_nondir, /* same */ +#endif + .mmap = aufs_mmap, + .open = aufs_open_nondir, + .flush = aufs_flush_nondir, + .release = aufs_release_nondir, + .fsync = aufs_fsync_nondir, + /* .aio_fsync = aufs_aio_fsync_nondir, */ + .fasync = aufs_fasync, + /* .sendpage = aufs_sendpage, */ + .splice_write = aufs_splice_write, + .splice_read = aufs_splice_read, +#if 0 + .aio_splice_write = aufs_aio_splice_write, + .aio_splice_read = aufs_aio_splice_read +#endif +}; --- linux-2.6.37.orig/ubuntu/aufs/f_op_sp.c +++ linux-2.6.37/ubuntu/aufs/f_op_sp.c @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * file operations for special files. + * while they exist in aufs virtually, + * their file I/O is handled out of aufs. + */ + +#include +#include "aufs.h" + +static ssize_t aufs_aio_read_sp(struct kiocb *kio, const struct iovec *iov, + unsigned long nv, loff_t pos) +{ + ssize_t err; + aufs_bindex_t bstart; + unsigned char wbr; + struct file *file, *h_file; + struct super_block *sb; + + file = kio->ki_filp; + sb = file->f_dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + fi_read_lock(file); + bstart = au_fbstart(file); + h_file = au_hf_top(file); + fi_read_unlock(file); + wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm); + si_read_unlock(sb); + + /* do not change the file in kio */ + AuDebugOn(!h_file->f_op || !h_file->f_op->aio_read); + err = h_file->f_op->aio_read(kio, iov, nv, pos); + if (err > 0 && wbr) + file_accessed(h_file); + + return err; +} + +static ssize_t aufs_aio_write_sp(struct kiocb *kio, const struct iovec *iov, + unsigned long nv, loff_t pos) +{ + ssize_t err; + aufs_bindex_t bstart; + unsigned char wbr; + struct super_block *sb; + struct file *file, *h_file; + + file = kio->ki_filp; + sb = file->f_dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + fi_read_lock(file); + bstart = au_fbstart(file); + h_file = au_hf_top(file); + fi_read_unlock(file); + wbr = !!au_br_writable(au_sbr(sb, bstart)->br_perm); + si_read_unlock(sb); + + /* do not change the file in kio */ + AuDebugOn(!h_file->f_op || !h_file->f_op->aio_write); + err = h_file->f_op->aio_write(kio, iov, nv, pos); + if (err > 0 && wbr) + file_update_time(h_file); + + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int aufs_release_sp(struct inode *inode, struct file *file) +{ + int err; + struct file *h_file; + + fi_read_lock(file); + h_file = au_hf_top(file); + fi_read_unlock(file); + /* close this fifo in aufs */ + err = h_file->f_op->release(inode, file); /* ignore */ + aufs_release_nondir(inode, file); /* ignore */ + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* currently, support only FIFO */ +enum { + AuSp_FIFO, AuSp_FIFO_R, AuSp_FIFO_W, AuSp_FIFO_RW, + /* AuSp_SOCK, AuSp_CHR, AuSp_BLK, */ + AuSp_Last +}; +static int aufs_open_sp(struct inode *inode, struct file *file); +static struct au_sp_fop { + int done; + struct file_operations fop; /* not 'const' */ + spinlock_t spin; +} au_sp_fop[AuSp_Last] = { + [AuSp_FIFO] = { + .fop = { + .owner = THIS_MODULE, + .open = aufs_open_sp + } + } +}; + +static void au_init_fop_sp(struct file *file) +{ + struct au_sp_fop *p; + int i; + struct file *h_file; + + p = au_sp_fop; + if (unlikely(!p->done)) { + /* initialize first time only */ + static DEFINE_SPINLOCK(spin); + + spin_lock(&spin); + if (!p->done) { + BUILD_BUG_ON(sizeof(au_sp_fop)/sizeof(*au_sp_fop) + != AuSp_Last); + for (i = 0; i < AuSp_Last; i++) + spin_lock_init(&p[i].spin); + p->done = 1; + } + spin_unlock(&spin); + } + + switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) { + case FMODE_READ: + i = AuSp_FIFO_R; + break; + case FMODE_WRITE: + i = AuSp_FIFO_W; + break; + case FMODE_READ | FMODE_WRITE: + i = AuSp_FIFO_RW; + break; + default: + BUG(); + } + + p += i; + if (unlikely(!p->done)) { + /* initialize first time only */ + h_file = au_hf_top(file); + spin_lock(&p->spin); + if (!p->done) { + p->fop = *h_file->f_op; + p->fop.owner = THIS_MODULE; + if (p->fop.aio_read) + p->fop.aio_read = aufs_aio_read_sp; + if (p->fop.aio_write) + p->fop.aio_write = aufs_aio_write_sp; + p->fop.release = aufs_release_sp; + p->done = 1; + } + spin_unlock(&p->spin); + } + file->f_op = &p->fop; +} + +static int au_cpup_sp(struct dentry *dentry) +{ + int err; + aufs_bindex_t bcpup; + struct au_pin pin; + struct au_wr_dir_args wr_dir_args = { + .force_btgt = -1, + .flags = 0 + }; + + AuDbg("%.*s\n", AuDLNPair(dentry)); + + di_read_unlock(dentry, AuLock_IR); + di_write_lock_child(dentry); + err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); + if (unlikely(err < 0)) + goto out; + bcpup = err; + err = 0; + if (bcpup == au_dbstart(dentry)) + goto out; /* success */ + + err = au_pin(&pin, dentry, bcpup, au_opt_udba(dentry->d_sb), + AuPin_MNT_WRITE); + if (!err) { + err = au_sio_cpup_simple(dentry, bcpup, -1, AuCpup_DTIME); + au_unpin(&pin); + } + +out: + di_downgrade_lock(dentry, AuLock_IR); + return err; +} + +static int au_do_open_sp(struct file *file, int flags) +{ + int err; + struct dentry *dentry; + struct super_block *sb; + struct file *h_file; + struct inode *h_inode; + + dentry = file->f_dentry; + AuDbg("%.*s\n", AuDLNPair(dentry)); + + /* + * try copying-up. + * operate on the ro branch is not an error. + */ + au_cpup_sp(dentry); /* ignore */ + + /* prepare h_file */ + err = au_do_open_nondir(file, vfsub_file_flags(file)); + if (unlikely(err)) + goto out; + + sb = dentry->d_sb; + h_file = au_hf_top(file); + h_inode = h_file->f_dentry->d_inode; + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); + si_read_unlock(sb); + /* open this fifo in aufs */ + err = h_inode->i_fop->open(file->f_dentry->d_inode, file); + si_noflush_read_lock(sb); + fi_write_lock(file); + di_read_lock_child(dentry, AuLock_IR); + if (!err) + au_init_fop_sp(file); + +out: + return err; +} + +static int aufs_open_sp(struct inode *inode, struct file *file) +{ + int err; + struct super_block *sb; + + sb = file->f_dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + err = au_do_open(file, au_do_open_sp, /*fidir*/NULL); + si_read_unlock(sb); + return err; +} + +/* ---------------------------------------------------------------------- */ + +void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev) +{ + init_special_inode(inode, mode, rdev); + + switch (mode & S_IFMT) { + case S_IFIFO: + inode->i_fop = &au_sp_fop[AuSp_FIFO].fop; + /*FALLTHROUGH*/ + case S_IFCHR: + case S_IFBLK: + case S_IFSOCK: + break; + default: + AuDebugOn(1); + } +} + +int au_special_file(umode_t mode) +{ + int ret; + + ret = 0; + switch (mode & S_IFMT) { + case S_IFIFO: +#if 0 + case S_IFCHR: + case S_IFBLK: + case S_IFSOCK: +#endif + ret = 1; + } + + return ret; +} --- linux-2.6.37.orig/ubuntu/aufs/file.c +++ linux-2.6.37/ubuntu/aufs/file.c @@ -0,0 +1,655 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * handling file/dir, and address_space operation + */ + +#include +#include +#include +#include +#include "aufs.h" + +/* drop flags for writing */ +unsigned int au_file_roflags(unsigned int flags) +{ + flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC); + flags |= O_RDONLY | O_NOATIME; + return flags; +} + +/* common functions to regular file and dir */ +struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, + struct file *file) +{ + struct file *h_file; + struct dentry *h_dentry; + struct inode *h_inode; + struct super_block *sb; + struct au_branch *br; + struct path h_path; + int err, exec_flag; + + /* a race condition can happen between open and unlink/rmdir */ + h_file = ERR_PTR(-ENOENT); + h_dentry = au_h_dptr(dentry, bindex); + if (au_test_nfsd() && !h_dentry) + goto out; + h_inode = h_dentry->d_inode; + if (au_test_nfsd() && !h_inode) + goto out; + if (unlikely((!d_unhashed(dentry) && au_d_removed(h_dentry)) + || !h_inode + /* || !dentry->d_inode->i_nlink */ + )) + goto out; + + sb = dentry->d_sb; + br = au_sbr(sb, bindex); + h_file = ERR_PTR(-EACCES); + exec_flag = flags & vfsub_fmode_to_uint(FMODE_EXEC); + if (exec_flag && (br->br_mnt->mnt_flags & MNT_NOEXEC)) + goto out; + + /* drop flags for writing */ + if (au_test_ro(sb, bindex, dentry->d_inode)) + flags = au_file_roflags(flags); + flags &= ~O_CREAT; + atomic_inc(&br->br_count); + h_path.dentry = h_dentry; + h_path.mnt = br->br_mnt; + if (!au_special_file(h_inode->i_mode)) + h_file = vfsub_dentry_open(&h_path, flags); + else { + /* this block depends upon the configuration */ + di_read_unlock(dentry, AuLock_IR); + fi_write_unlock(file); + si_read_unlock(sb); + h_file = vfsub_dentry_open(&h_path, flags); + si_noflush_read_lock(sb); + fi_write_lock(file); + di_read_lock_child(dentry, AuLock_IR); + } + if (IS_ERR(h_file)) + goto out_br; + + if (exec_flag) { + err = deny_write_access(h_file); + if (unlikely(err)) { + fput(h_file); + h_file = ERR_PTR(err); + goto out_br; + } + } + fsnotify_open(h_file); + goto out; /* success */ + +out_br: + atomic_dec(&br->br_count); +out: + return h_file; +} + +int au_do_open(struct file *file, int (*open)(struct file *file, int flags), + struct au_fidir *fidir) +{ + int err; + struct dentry *dentry; + + err = au_finfo_init(file, fidir); + if (unlikely(err)) + goto out; + + dentry = file->f_dentry; + di_read_lock_child(dentry, AuLock_IR); + err = open(file, vfsub_file_flags(file)); + di_read_unlock(dentry, AuLock_IR); + + fi_write_unlock(file); + if (unlikely(err)) { + au_fi(file)->fi_hdir = NULL; + au_finfo_fin(file); + } + +out: + return err; +} + +int au_reopen_nondir(struct file *file) +{ + int err; + aufs_bindex_t bstart; + struct dentry *dentry; + struct file *h_file, *h_file_tmp; + + dentry = file->f_dentry; + AuDebugOn(au_special_file(dentry->d_inode->i_mode)); + bstart = au_dbstart(dentry); + h_file_tmp = NULL; + if (au_fbstart(file) == bstart) { + h_file = au_hf_top(file); + if (file->f_mode == h_file->f_mode) + return 0; /* success */ + h_file_tmp = h_file; + get_file(h_file_tmp); + au_set_h_fptr(file, bstart, NULL); + } + AuDebugOn(au_fi(file)->fi_hdir); + AuDebugOn(au_fbstart(file) < bstart); + + h_file = au_h_open(dentry, bstart, vfsub_file_flags(file) & ~O_TRUNC, + file); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; /* todo: close all? */ + + err = 0; + au_set_fbstart(file, bstart); + au_set_h_fptr(file, bstart, h_file); + au_update_figen(file); + /* todo: necessary? */ + /* file->f_ra = h_file->f_ra; */ + +out: + if (h_file_tmp) + fput(h_file_tmp); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int au_reopen_wh(struct file *file, aufs_bindex_t btgt, + struct dentry *hi_wh) +{ + int err; + aufs_bindex_t bstart; + struct au_dinfo *dinfo; + struct dentry *h_dentry; + struct au_hdentry *hdp; + + dinfo = au_di(file->f_dentry); + AuRwMustWriteLock(&dinfo->di_rwsem); + + bstart = dinfo->di_bstart; + dinfo->di_bstart = btgt; + hdp = dinfo->di_hdentry; + h_dentry = hdp[0 + btgt].hd_dentry; + hdp[0 + btgt].hd_dentry = hi_wh; + err = au_reopen_nondir(file); + hdp[0 + btgt].hd_dentry = h_dentry; + dinfo->di_bstart = bstart; + + return err; +} + +static int au_ready_to_write_wh(struct file *file, loff_t len, + aufs_bindex_t bcpup) +{ + int err; + struct inode *inode; + struct dentry *dentry, *hi_wh; + + dentry = file->f_dentry; + au_update_dbstart(dentry); + inode = dentry->d_inode; + hi_wh = au_hi_wh(inode, bcpup); + if (!hi_wh) + err = au_sio_cpup_wh(dentry, bcpup, len, file); + else + /* already copied-up after unlink */ + err = au_reopen_wh(file, bcpup, hi_wh); + + if (!err + && inode->i_nlink > 1 + && au_opt_test(au_mntflags(dentry->d_sb), PLINK)) + au_plink_append(inode, bcpup, au_h_dptr(dentry, bcpup)); + + return err; +} + +/* + * prepare the @file for writing. + */ +int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin) +{ + int err; + aufs_bindex_t bstart, bcpup; + struct dentry *dentry, *parent, *h_dentry; + struct inode *h_inode, *inode; + struct super_block *sb; + struct file *h_file; + + dentry = file->f_dentry; + sb = dentry->d_sb; + inode = dentry->d_inode; + AuDebugOn(au_special_file(inode->i_mode)); + bstart = au_fbstart(file); + err = au_test_ro(sb, bstart, inode); + if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) { + err = au_pin(pin, dentry, bstart, AuOpt_UDBA_NONE, /*flags*/0); + goto out; + } + + /* need to cpup */ + parent = dget_parent(dentry); + di_write_lock_parent(parent); + err = AuWbrCopyup(au_sbi(sb), dentry); + bcpup = err; + if (unlikely(err < 0)) + goto out_dgrade; + err = 0; + + if (!au_h_dptr(parent, bcpup)) { + err = au_cpup_dirs(dentry, bcpup); + if (unlikely(err)) + goto out_dgrade; + } + + err = au_pin(pin, dentry, bcpup, AuOpt_UDBA_NONE, + AuPin_DI_LOCKED | AuPin_MNT_WRITE); + if (unlikely(err)) + goto out_dgrade; + + h_dentry = au_hf_top(file)->f_dentry; + h_inode = h_dentry->d_inode; + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + h_file = au_h_open_pre(dentry, bstart); + if (IS_ERR(h_file)) { + err = PTR_ERR(h_file); + h_file = NULL; + } else if (d_unhashed(dentry) /* || d_unhashed(h_dentry) */ + /* || !h_inode->i_nlink */) { + err = au_ready_to_write_wh(file, len, bcpup); + di_downgrade_lock(parent, AuLock_IR); + } else { + di_downgrade_lock(parent, AuLock_IR); + if (!au_h_dptr(dentry, bcpup)) + err = au_sio_cpup_simple(dentry, bcpup, len, + AuCpup_DTIME); + if (!err) + err = au_reopen_nondir(file); + } + mutex_unlock(&h_inode->i_mutex); + au_h_open_post(dentry, bstart, h_file); + + if (!err) { + au_pin_set_parent_lflag(pin, /*lflag*/0); + goto out_dput; /* success */ + } + au_unpin(pin); + goto out_unlock; + +out_dgrade: + di_downgrade_lock(parent, AuLock_IR); +out_unlock: + di_read_unlock(parent, AuLock_IR); +out_dput: + dput(parent); +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +int au_do_flush(struct file *file, fl_owner_t id, + int (*flush)(struct file *file, fl_owner_t id)) +{ + int err; + struct dentry *dentry; + struct super_block *sb; + struct inode *inode; + + dentry = file->f_dentry; + sb = dentry->d_sb; + inode = dentry->d_inode; + si_noflush_read_lock(sb); + fi_read_lock(file); + ii_read_lock_child(inode); + + err = flush(file, id); + au_cpup_attr_timesizes(inode); + + ii_read_unlock(inode); + fi_read_unlock(file); + si_read_unlock(sb); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int au_file_refresh_by_inode(struct file *file, int *need_reopen) +{ + int err; + aufs_bindex_t bstart; + struct au_pin pin; + struct au_finfo *finfo; + struct dentry *dentry, *parent, *hi_wh; + struct inode *inode; + struct super_block *sb; + + FiMustWriteLock(file); + + err = 0; + finfo = au_fi(file); + dentry = file->f_dentry; + sb = dentry->d_sb; + inode = dentry->d_inode; + bstart = au_ibstart(inode); + if (bstart == finfo->fi_btop) + goto out; + + parent = dget_parent(dentry); + if (au_test_ro(sb, bstart, inode)) { + di_read_lock_parent(parent, !AuLock_IR); + err = AuWbrCopyup(au_sbi(sb), dentry); + bstart = err; + di_read_unlock(parent, !AuLock_IR); + if (unlikely(err < 0)) + goto out_parent; + err = 0; + } + + di_read_lock_parent(parent, AuLock_IR); + hi_wh = au_hi_wh(inode, bstart); + if (!S_ISDIR(inode->i_mode) + && au_opt_test(au_mntflags(sb), PLINK) + && au_plink_test(inode) + && !d_unhashed(dentry)) { + err = au_test_and_cpup_dirs(dentry, bstart); + if (unlikely(err)) + goto out_unlock; + + /* always superio. */ + err = au_pin(&pin, dentry, bstart, AuOpt_UDBA_NONE, + AuPin_DI_LOCKED | AuPin_MNT_WRITE); + if (!err) + err = au_sio_cpup_simple(dentry, bstart, -1, + AuCpup_DTIME); + au_unpin(&pin); + } else if (hi_wh) { + /* already copied-up after unlink */ + err = au_reopen_wh(file, bstart, hi_wh); + *need_reopen = 0; + } + +out_unlock: + di_read_unlock(parent, AuLock_IR); +out_parent: + dput(parent); +out: + return err; +} + +static void au_do_refresh_dir(struct file *file) +{ + aufs_bindex_t bindex, bend, new_bindex, brid; + struct au_hfile *p, tmp, *q; + struct au_finfo *finfo; + struct super_block *sb; + struct au_fidir *fidir; + + FiMustWriteLock(file); + + sb = file->f_dentry->d_sb; + finfo = au_fi(file); + fidir = finfo->fi_hdir; + AuDebugOn(!fidir); + p = fidir->fd_hfile + finfo->fi_btop; + brid = p->hf_br->br_id; + bend = fidir->fd_bbot; + for (bindex = finfo->fi_btop; bindex <= bend; bindex++, p++) { + if (!p->hf_file) + continue; + + new_bindex = au_br_index(sb, p->hf_br->br_id); + if (new_bindex == bindex) + continue; + if (new_bindex < 0) { + au_set_h_fptr(file, bindex, NULL); + continue; + } + + /* swap two lower inode, and loop again */ + q = fidir->fd_hfile + new_bindex; + tmp = *q; + *q = *p; + *p = tmp; + if (tmp.hf_file) { + bindex--; + p--; + } + } + + p = fidir->fd_hfile; + if (!au_test_mmapped(file) && !au_d_removed(file->f_dentry)) { + bend = au_sbend(sb); + for (finfo->fi_btop = 0; finfo->fi_btop <= bend; + finfo->fi_btop++, p++) + if (p->hf_file) { + if (p->hf_file->f_dentry + && p->hf_file->f_dentry->d_inode) + break; + else + au_hfput(p, file); + } + } else { + bend = au_br_index(sb, brid); + for (finfo->fi_btop = 0; finfo->fi_btop < bend; + finfo->fi_btop++, p++) + if (p->hf_file) + au_hfput(p, file); + bend = au_sbend(sb); + } + + p = fidir->fd_hfile + bend; + for (fidir->fd_bbot = bend; fidir->fd_bbot >= finfo->fi_btop; + fidir->fd_bbot--, p--) + if (p->hf_file) { + if (p->hf_file->f_dentry + && p->hf_file->f_dentry->d_inode) + break; + else + au_hfput(p, file); + } + AuDebugOn(fidir->fd_bbot < finfo->fi_btop); +} + +/* + * after branch manipulating, refresh the file. + */ +static int refresh_file(struct file *file, int (*reopen)(struct file *file)) +{ + int err, need_reopen; + aufs_bindex_t bend, bindex; + struct dentry *dentry; + struct au_finfo *finfo; + struct au_hfile *hfile; + + dentry = file->f_dentry; + finfo = au_fi(file); + if (!finfo->fi_hdir) { + hfile = &finfo->fi_htop; + AuDebugOn(!hfile->hf_file); + bindex = au_br_index(dentry->d_sb, hfile->hf_br->br_id); + AuDebugOn(bindex < 0); + if (bindex != finfo->fi_btop) + au_set_fbstart(file, bindex); + } else { + err = au_fidir_realloc(finfo, au_sbend(dentry->d_sb) + 1); + if (unlikely(err)) + goto out; + au_do_refresh_dir(file); + } + + err = 0; + need_reopen = 1; + if (!au_test_mmapped(file)) + err = au_file_refresh_by_inode(file, &need_reopen); + if (!err && need_reopen && !au_d_removed(dentry)) + err = reopen(file); + if (!err) { + au_update_figen(file); + goto out; /* success */ + } + + /* error, close all lower files */ + if (finfo->fi_hdir) { + bend = au_fbend_dir(file); + for (bindex = au_fbstart(file); bindex <= bend; bindex++) + au_set_h_fptr(file, bindex, NULL); + } + +out: + return err; +} + +/* common function to regular file and dir */ +int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), + int wlock) +{ + int err; + unsigned int sigen, figen; + aufs_bindex_t bstart; + unsigned char pseudo_link; + struct dentry *dentry; + struct inode *inode; + + err = 0; + dentry = file->f_dentry; + inode = dentry->d_inode; + AuDebugOn(au_special_file(inode->i_mode)); + sigen = au_sigen(dentry->d_sb); + fi_write_lock(file); + figen = au_figen(file); + di_write_lock_child(dentry); + bstart = au_dbstart(dentry); + pseudo_link = (bstart != au_ibstart(inode)); + if (sigen == figen && !pseudo_link && au_fbstart(file) == bstart) { + if (!wlock) { + di_downgrade_lock(dentry, AuLock_IR); + fi_downgrade_lock(file); + } + goto out; /* success */ + } + + AuDbg("sigen %d, figen %d\n", sigen, figen); + if (sigen != au_digen(dentry) + || sigen != au_iigen(inode)) { + err = au_reval_dpath(dentry, sigen); + if (unlikely(err < 0)) + goto out; + AuDebugOn(au_digen(dentry) != sigen + || au_iigen(inode) != sigen); + } + + err = refresh_file(file, reopen); + if (!err) { + if (!wlock) { + di_downgrade_lock(dentry, AuLock_IR); + fi_downgrade_lock(file); + } + } else { + di_write_unlock(dentry); + fi_write_unlock(file); + } + +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* cf. aufs_nopage() */ +/* for madvise(2) */ +static int aufs_readpage(struct file *file __maybe_unused, struct page *page) +{ + unlock_page(page); + return 0; +} + +/* it will never be called, but necessary to support O_DIRECT */ +static ssize_t aufs_direct_IO(int rw, struct kiocb *iocb, + const struct iovec *iov, loff_t offset, + unsigned long nr_segs) +{ BUG(); return 0; } + +/* + * it will never be called, but madvise and fadvise behaves differently + * when get_xip_mem is defined + */ +static int aufs_get_xip_mem(struct address_space *mapping, pgoff_t pgoff, + int create, void **kmem, unsigned long *pfn) +{ BUG(); return 0; } + +/* they will never be called. */ +#ifdef CONFIG_AUFS_DEBUG +static int aufs_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) +{ AuUnsupport(); return 0; } +static int aufs_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, + struct page *page, void *fsdata) +{ AuUnsupport(); return 0; } +static int aufs_writepage(struct page *page, struct writeback_control *wbc) +{ AuUnsupport(); return 0; } +static void aufs_sync_page(struct page *page) +{ AuUnsupport(); } + +static int aufs_set_page_dirty(struct page *page) +{ AuUnsupport(); return 0; } +static void aufs_invalidatepage(struct page *page, unsigned long offset) +{ AuUnsupport(); } +static int aufs_releasepage(struct page *page, gfp_t gfp) +{ AuUnsupport(); return 0; } +static int aufs_migratepage(struct address_space *mapping, struct page *newpage, + struct page *page) +{ AuUnsupport(); return 0; } +static int aufs_launder_page(struct page *page) +{ AuUnsupport(); return 0; } +static int aufs_is_partially_uptodate(struct page *page, + read_descriptor_t *desc, + unsigned long from) +{ AuUnsupport(); return 0; } +static int aufs_error_remove_page(struct address_space *mapping, + struct page *page) +{ AuUnsupport(); return 0; } +#endif /* CONFIG_AUFS_DEBUG */ + +const struct address_space_operations aufs_aop = { + .readpage = aufs_readpage, + .direct_IO = aufs_direct_IO, + .get_xip_mem = aufs_get_xip_mem, +#ifdef CONFIG_AUFS_DEBUG + .writepage = aufs_writepage, + .sync_page = aufs_sync_page, + /* no writepages, because of writepage */ + .set_page_dirty = aufs_set_page_dirty, + /* no readpages, because of readpage */ + .write_begin = aufs_write_begin, + .write_end = aufs_write_end, + /* no bmap, no block device */ + .invalidatepage = aufs_invalidatepage, + .releasepage = aufs_releasepage, + .migratepage = aufs_migratepage, + .launder_page = aufs_launder_page, + .is_partially_uptodate = aufs_is_partially_uptodate, + .error_remove_page = aufs_error_remove_page +#endif /* CONFIG_AUFS_DEBUG */ +}; --- linux-2.6.37.orig/ubuntu/aufs/file.h +++ linux-2.6.37/ubuntu/aufs/file.h @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * file operations + */ + +#ifndef __AUFS_FILE_H__ +#define __AUFS_FILE_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include "rwsem.h" + +struct au_branch; +struct au_hfile { + struct file *hf_file; + struct au_branch *hf_br; +}; + +struct au_vdir; +struct au_fidir { + aufs_bindex_t fd_bbot; + aufs_bindex_t fd_nent; + struct au_vdir *fd_vdir_cache; + struct au_hfile fd_hfile[]; +}; + +static inline int au_fidir_sz(int nent) +{ + AuDebugOn(nent < 0); + return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent; +} + +struct au_finfo { + atomic_t fi_generation; + + struct au_rwsem fi_rwsem; + aufs_bindex_t fi_btop; + + /* do not union them */ + struct { /* for non-dir */ + struct au_hfile fi_htop; + struct vm_operations_struct *fi_hvmop; + struct mutex fi_vm_mtx; + struct mutex fi_mmap; + }; + struct au_fidir *fi_hdir; /* for dir only */ +} ____cacheline_aligned_in_smp; + +/* ---------------------------------------------------------------------- */ + +/* file.c */ +extern const struct address_space_operations aufs_aop; +unsigned int au_file_roflags(unsigned int flags); +struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags, + struct file *file); +int au_do_open(struct file *file, int (*open)(struct file *file, int flags), + struct au_fidir *fidir); +int au_reopen_nondir(struct file *file); +struct au_pin; +int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin); +int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), + int wlock); +int au_do_flush(struct file *file, fl_owner_t id, + int (*flush)(struct file *file, fl_owner_t id)); + +/* poll.c */ +#ifdef CONFIG_AUFS_POLL +unsigned int aufs_poll(struct file *file, poll_table *wait); +#endif + +#ifdef CONFIG_AUFS_BR_HFSPLUS +/* hfsplus.c */ +struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex); +void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, + struct file *h_file); +#else +static inline +struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex) +{ + return NULL; +} + +AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex, + struct file *h_file); +#endif + +/* f_op.c */ +extern const struct file_operations aufs_file_fop; +extern const struct vm_operations_struct aufs_vm_ops; +int au_do_open_nondir(struct file *file, int flags); +int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file); + +#ifdef CONFIG_AUFS_SP_IATTR +/* f_op_sp.c */ +int au_special_file(umode_t mode); +void au_init_special_fop(struct inode *inode, umode_t mode, dev_t rdev); +#else +AuStubInt0(au_special_file, umode_t mode) +static inline void au_init_special_fop(struct inode *inode, umode_t mode, + dev_t rdev) +{ + init_special_inode(inode, mode, rdev); +} +#endif + +/* finfo.c */ +void au_hfput(struct au_hfile *hf, struct file *file); +void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, + struct file *h_file); + +void au_update_figen(struct file *file); +void au_fi_mmap_lock(struct file *file); +void au_fi_mmap_unlock(struct file *file); +struct au_fidir *au_fidir_alloc(struct super_block *sb); +int au_fidir_realloc(struct au_finfo *finfo, int nbr); + +void au_fi_init_once(void *_fi); +void au_finfo_fin(struct file *file); +int au_finfo_init(struct file *file, struct au_fidir *fidir); + +/* ioctl.c */ +long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg); +#ifdef CONFIG_COMPAT +long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, + unsigned long arg); +#endif + +/* ---------------------------------------------------------------------- */ + +static inline struct au_finfo *au_fi(struct file *file) +{ + return file->private_data; +} + +/* ---------------------------------------------------------------------- */ + +/* + * fi_read_lock, fi_write_lock, + * fi_read_unlock, fi_write_unlock, fi_downgrade_lock + */ +AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem); + +#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem) +#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem) +#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem) + +/* ---------------------------------------------------------------------- */ + +/* todo: hard/soft set? */ +static inline aufs_bindex_t au_fbstart(struct file *file) +{ + FiMustAnyLock(file); + return au_fi(file)->fi_btop; +} + +static inline aufs_bindex_t au_fbend_dir(struct file *file) +{ + FiMustAnyLock(file); + AuDebugOn(!au_fi(file)->fi_hdir); + return au_fi(file)->fi_hdir->fd_bbot; +} + +static inline struct au_vdir *au_fvdir_cache(struct file *file) +{ + FiMustAnyLock(file); + AuDebugOn(!au_fi(file)->fi_hdir); + return au_fi(file)->fi_hdir->fd_vdir_cache; +} + +static inline void au_set_fbstart(struct file *file, aufs_bindex_t bindex) +{ + FiMustWriteLock(file); + au_fi(file)->fi_btop = bindex; +} + +static inline void au_set_fbend_dir(struct file *file, aufs_bindex_t bindex) +{ + FiMustWriteLock(file); + AuDebugOn(!au_fi(file)->fi_hdir); + au_fi(file)->fi_hdir->fd_bbot = bindex; +} + +static inline void au_set_fvdir_cache(struct file *file, + struct au_vdir *vdir_cache) +{ + FiMustWriteLock(file); + AuDebugOn(!au_fi(file)->fi_hdir); + au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache; +} + +static inline struct file *au_hf_top(struct file *file) +{ + FiMustAnyLock(file); + AuDebugOn(au_fi(file)->fi_hdir); + return au_fi(file)->fi_htop.hf_file; +} + +static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex) +{ + FiMustAnyLock(file); + AuDebugOn(!au_fi(file)->fi_hdir); + return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file; +} + +/* todo: memory barrier? */ +static inline unsigned int au_figen(struct file *f) +{ + return atomic_read(&au_fi(f)->fi_generation); +} + +static inline int au_test_mmapped(struct file *f) +{ + FiMustAnyLock(f); + return !!(au_fi(f)->fi_hvmop); +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_FILE_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/finfo.c +++ linux-2.6.37/ubuntu/aufs/finfo.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * file private data + */ + +#include +#include "aufs.h" + +void au_hfput(struct au_hfile *hf, struct file *file) +{ + /* todo: direct access f_flags */ + if (vfsub_file_flags(file) & vfsub_fmode_to_uint(FMODE_EXEC)) + allow_write_access(hf->hf_file); + fput(hf->hf_file); + hf->hf_file = NULL; + atomic_dec(&hf->hf_br->br_count); + hf->hf_br = NULL; +} + +void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val) +{ + struct au_finfo *finfo = au_fi(file); + struct au_hfile *hf; + struct au_fidir *fidir; + + fidir = finfo->fi_hdir; + if (!fidir) { + AuDebugOn(finfo->fi_btop != bindex); + hf = &finfo->fi_htop; + } else + hf = fidir->fd_hfile + bindex; + + if (hf && hf->hf_file) + au_hfput(hf, file); + if (val) { + FiMustWriteLock(file); + hf->hf_file = val; + hf->hf_br = au_sbr(file->f_dentry->d_sb, bindex); + } +} + +void au_update_figen(struct file *file) +{ + atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_dentry)); + /* smp_mb(); */ /* atomic_set */ +} + +/* ---------------------------------------------------------------------- */ + +void au_fi_mmap_lock(struct file *file) +{ + FiMustWriteLock(file); + lockdep_off(); + mutex_lock(&au_fi(file)->fi_mmap); + lockdep_on(); +} + +void au_fi_mmap_unlock(struct file *file) +{ + lockdep_off(); + mutex_unlock(&au_fi(file)->fi_mmap); + lockdep_on(); +} + +/* ---------------------------------------------------------------------- */ + +struct au_fidir *au_fidir_alloc(struct super_block *sb) +{ + struct au_fidir *fidir; + int nbr; + + nbr = au_sbend(sb) + 1; + if (nbr < 2) + nbr = 2; /* initial allocate for 2 branches */ + fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS); + if (fidir) { + fidir->fd_bbot = -1; + fidir->fd_nent = nbr; + fidir->fd_vdir_cache = NULL; + } + + return fidir; +} + +int au_fidir_realloc(struct au_finfo *finfo, int nbr) +{ + int err; + struct au_fidir *fidir, *p; + + AuRwMustWriteLock(&finfo->fi_rwsem); + fidir = finfo->fi_hdir; + AuDebugOn(!fidir); + + err = -ENOMEM; + p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr), + GFP_NOFS); + if (p) { + p->fd_nent = nbr; + finfo->fi_hdir = p; + err = 0; + } + + return err; +} + +/* ---------------------------------------------------------------------- */ + +void au_finfo_fin(struct file *file) +{ + struct au_finfo *finfo; + + au_nfiles_dec(file->f_dentry->d_sb); + + finfo = au_fi(file); + AuDebugOn(finfo->fi_hdir); + AuRwDestroy(&finfo->fi_rwsem); + au_cache_free_finfo(finfo); +} + +void au_fi_init_once(void *_finfo) +{ + struct au_finfo *finfo = _finfo; + static struct lock_class_key aufs_fi, aufs_fi_vm, aufs_fi_mmap; + + au_rw_init(&finfo->fi_rwsem); + au_rw_class(&finfo->fi_rwsem, &aufs_fi); + mutex_init(&finfo->fi_vm_mtx); + lockdep_set_class(&finfo->fi_vm_mtx, &aufs_fi_vm); + mutex_init(&finfo->fi_mmap); + lockdep_set_class(&finfo->fi_mmap, &aufs_fi_mmap); +} + +int au_finfo_init(struct file *file, struct au_fidir *fidir) +{ + int err; + struct au_finfo *finfo; + struct dentry *dentry; + + err = -ENOMEM; + dentry = file->f_dentry; + finfo = au_cache_alloc_finfo(); + if (unlikely(!finfo)) + goto out; + + err = 0; + au_nfiles_inc(dentry->d_sb); + au_rw_write_lock(&finfo->fi_rwsem); + finfo->fi_btop = -1; + finfo->fi_hdir = fidir; + atomic_set(&finfo->fi_generation, au_digen(dentry)); + /* smp_mb(); */ /* atomic_set */ + + file->private_data = finfo; + +out: + return err; +} --- linux-2.6.37.orig/ubuntu/aufs/fstype.h +++ linux-2.6.37/ubuntu/aufs/fstype.h @@ -0,0 +1,497 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * judging filesystem type + */ + +#ifndef __AUFS_FSTYPE_H__ +#define __AUFS_FSTYPE_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include + +static inline int au_test_aufs(struct super_block *sb) +{ + return sb->s_magic == AUFS_SUPER_MAGIC; +} + +static inline const char *au_sbtype(struct super_block *sb) +{ + return sb->s_type->name; +} + +static inline int au_test_iso9660(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_ROMFS_FS) || defined(CONFIG_ROMFS_FS_MODULE) + return sb->s_magic == ROMFS_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_romfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_ISO9660_FS) || defined(CONFIG_ISO9660_FS_MODULE) + return sb->s_magic == ISOFS_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_cramfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_CRAMFS) || defined(CONFIG_CRAMFS_MODULE) + return sb->s_magic == CRAMFS_MAGIC; +#endif + return 0; +} + +static inline int au_test_nfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_NFS_FS) || defined(CONFIG_NFS_FS_MODULE) + return sb->s_magic == NFS_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_fuse(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_FUSE_FS) || defined(CONFIG_FUSE_FS_MODULE) + return sb->s_magic == FUSE_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_xfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_XFS_FS) || defined(CONFIG_XFS_FS_MODULE) + return sb->s_magic == XFS_SB_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_tmpfs(struct super_block *sb __maybe_unused) +{ +#ifdef CONFIG_TMPFS + return sb->s_magic == TMPFS_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_ECRYPT_FS) || defined(CONFIG_ECRYPT_FS_MODULE) + return !strcmp(au_sbtype(sb), "ecryptfs"); +#else + return 0; +#endif +} + +static inline int au_test_smbfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_SMB_FS) || defined(CONFIG_SMB_FS_MODULE) + return sb->s_magic == SMB_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_ocfs2(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_OCFS2_FS) || defined(CONFIG_OCFS2_FS_MODULE) + return sb->s_magic == OCFS2_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_ocfs2_dlmfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_OCFS2_FS_O2CB) || defined(CONFIG_OCFS2_FS_O2CB_MODULE) + return sb->s_magic == DLMFS_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_coda(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_CODA_FS) || defined(CONFIG_CODA_FS_MODULE) + return sb->s_magic == CODA_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_v9fs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_9P_FS) || defined(CONFIG_9P_FS_MODULE) + return sb->s_magic == V9FS_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_ext4(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_EXT4DEV_FS) || defined(CONFIG_EXT4DEV_FS_MODULE) + return sb->s_magic == EXT4_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_sysv(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_SYSV_FS) || defined(CONFIG_SYSV_FS_MODULE) + return !strcmp(au_sbtype(sb), "sysv"); +#else + return 0; +#endif +} + +static inline int au_test_ramfs(struct super_block *sb) +{ + return sb->s_magic == RAMFS_MAGIC; +} + +static inline int au_test_ubifs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_UBIFS_FS) || defined(CONFIG_UBIFS_FS_MODULE) + return sb->s_magic == UBIFS_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_procfs(struct super_block *sb __maybe_unused) +{ +#ifdef CONFIG_PROC_FS + return sb->s_magic == PROC_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_sysfs(struct super_block *sb __maybe_unused) +{ +#ifdef CONFIG_SYSFS + return sb->s_magic == SYSFS_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_configfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_CONFIGFS_FS) || defined(CONFIG_CONFIGFS_FS_MODULE) + return sb->s_magic == CONFIGFS_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_minix(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_MINIX_FS) || defined(CONFIG_MINIX_FS_MODULE) + return sb->s_magic == MINIX3_SUPER_MAGIC + || sb->s_magic == MINIX2_SUPER_MAGIC + || sb->s_magic == MINIX2_SUPER_MAGIC2 + || sb->s_magic == MINIX_SUPER_MAGIC + || sb->s_magic == MINIX_SUPER_MAGIC2; +#else + return 0; +#endif +} + +static inline int au_test_cifs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_CIFS_FS) || defined(CONFIGCIFS_FS_MODULE) + return sb->s_magic == CIFS_MAGIC_NUMBER; +#else + return 0; +#endif +} + +static inline int au_test_fat(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_FAT_FS) || defined(CONFIG_FAT_FS_MODULE) + return sb->s_magic == MSDOS_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_msdos(struct super_block *sb) +{ + return au_test_fat(sb); +} + +static inline int au_test_vfat(struct super_block *sb) +{ + return au_test_fat(sb); +} + +static inline int au_test_securityfs(struct super_block *sb __maybe_unused) +{ +#ifdef CONFIG_SECURITYFS + return sb->s_magic == SECURITYFS_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_squashfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_SQUASHFS) || defined(CONFIG_SQUASHFS_MODULE) + return sb->s_magic == SQUASHFS_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_btrfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_BTRFS_FS) || defined(CONFIG_BTRFS_FS_MODULE) + return sb->s_magic == BTRFS_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_xenfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_XENFS) || defined(CONFIG_XENFS_MODULE) + return sb->s_magic == XENFS_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_debugfs(struct super_block *sb __maybe_unused) +{ +#ifdef CONFIG_DEBUG_FS + return sb->s_magic == DEBUGFS_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_nilfs(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_NILFS) || defined(CONFIG_NILFS_MODULE) + return sb->s_magic == NILFS_SUPER_MAGIC; +#else + return 0; +#endif +} + +static inline int au_test_hfsplus(struct super_block *sb __maybe_unused) +{ +#if defined(CONFIG_HFSPLUS_FS) || defined(CONFIG_HFSPLUS_FS_MODULE) + return sb->s_magic == HFSPLUS_SUPER_MAGIC; +#else + return 0; +#endif +} + +/* ---------------------------------------------------------------------- */ +/* + * they can't be an aufs branch. + */ +static inline int au_test_fs_unsuppoted(struct super_block *sb) +{ + return +#ifndef CONFIG_AUFS_BR_RAMFS + au_test_ramfs(sb) || +#endif + au_test_procfs(sb) + || au_test_sysfs(sb) + || au_test_configfs(sb) + || au_test_debugfs(sb) + || au_test_securityfs(sb) + || au_test_xenfs(sb) + || au_test_ecryptfs(sb) + /* || !strcmp(au_sbtype(sb), "unionfs") */ + || au_test_aufs(sb); /* will be supported in next version */ +} + +/* + * If the filesystem supports NFS-export, then it has to support NULL as + * a nameidata parameter for ->create(), ->lookup() and ->d_revalidate(). + * We can apply this principle when we handle a lower filesystem. + */ +static inline int au_test_fs_null_nd(struct super_block *sb) +{ + return !!sb->s_export_op; +} + +static inline int au_test_fs_remote(struct super_block *sb) +{ + return !au_test_tmpfs(sb) +#ifdef CONFIG_AUFS_BR_RAMFS + && !au_test_ramfs(sb) +#endif + && !(sb->s_type->fs_flags & FS_REQUIRES_DEV); +} + +/* ---------------------------------------------------------------------- */ + +/* + * Note: these functions (below) are created after reading ->getattr() in all + * filesystems under linux/fs. it means we have to do so in every update... + */ + +/* + * some filesystems require getattr to refresh the inode attributes before + * referencing. + * in most cases, we can rely on the inode attribute in NFS (or every remote fs) + * and leave the work for d_revalidate() + */ +static inline int au_test_fs_refresh_iattr(struct super_block *sb) +{ + return au_test_nfs(sb) + || au_test_fuse(sb) + /* || au_test_smbfs(sb) */ /* untested */ + /* || au_test_ocfs2(sb) */ /* untested */ + /* || au_test_btrfs(sb) */ /* untested */ + /* || au_test_coda(sb) */ /* untested */ + /* || au_test_v9fs(sb) */ /* untested */ + ; +} + +/* + * filesystems which don't maintain i_size or i_blocks. + */ +static inline int au_test_fs_bad_iattr_size(struct super_block *sb) +{ + return au_test_xfs(sb) + || au_test_btrfs(sb) + || au_test_ubifs(sb) + || au_test_hfsplus(sb) /* maintained, but incorrect */ + /* || au_test_ext4(sb) */ /* untested */ + /* || au_test_ocfs2(sb) */ /* untested */ + /* || au_test_ocfs2_dlmfs(sb) */ /* untested */ + /* || au_test_sysv(sb) */ /* untested */ + /* || au_test_minix(sb) */ /* untested */ + ; +} + +/* + * filesystems which don't store the correct value in some of their inode + * attributes. + */ +static inline int au_test_fs_bad_iattr(struct super_block *sb) +{ + return au_test_fs_bad_iattr_size(sb) + /* || au_test_cifs(sb) */ /* untested */ + || au_test_fat(sb) + || au_test_msdos(sb) + || au_test_vfat(sb); +} + +/* they don't check i_nlink in link(2) */ +static inline int au_test_fs_no_limit_nlink(struct super_block *sb) +{ + return au_test_tmpfs(sb) +#ifdef CONFIG_AUFS_BR_RAMFS + || au_test_ramfs(sb) +#endif + || au_test_ubifs(sb) + || au_test_btrfs(sb) + || au_test_hfsplus(sb); +} + +/* + * filesystems which sets S_NOATIME and S_NOCMTIME. + */ +static inline int au_test_fs_notime(struct super_block *sb) +{ + return au_test_nfs(sb) + || au_test_fuse(sb) + || au_test_ubifs(sb) + /* || au_test_cifs(sb) */ /* untested */ + ; +} + +/* + * filesystems which requires replacing i_mapping. + */ +static inline int au_test_fs_bad_mapping(struct super_block *sb) +{ + return au_test_fuse(sb) + || au_test_ubifs(sb); +} + +/* temporary support for i#1 in cramfs */ +static inline int au_test_fs_unique_ino(struct inode *inode) +{ + if (au_test_cramfs(inode->i_sb)) + return inode->i_ino != 1; + return 1; +} + +/* ---------------------------------------------------------------------- */ + +/* + * the filesystem where the xino files placed must support i/o after unlink and + * maintain i_size and i_blocks. + */ +static inline int au_test_fs_bad_xino(struct super_block *sb) +{ + return au_test_fs_remote(sb) + || au_test_fs_bad_iattr_size(sb) +#ifdef CONFIG_AUFS_BR_RAMFS + || !(au_test_ramfs(sb) || au_test_fs_null_nd(sb)) +#else + || !au_test_fs_null_nd(sb) /* to keep xino code simple */ +#endif + /* don't want unnecessary work for xino */ + || au_test_aufs(sb) + || au_test_ecryptfs(sb) + || au_test_nilfs(sb); +} + +static inline int au_test_fs_trunc_xino(struct super_block *sb) +{ + return au_test_tmpfs(sb) + || au_test_ramfs(sb); +} + +/* + * test if the @sb is real-readonly. + */ +static inline int au_test_fs_rr(struct super_block *sb) +{ + return au_test_squashfs(sb) + || au_test_iso9660(sb) + || au_test_cramfs(sb) + || au_test_romfs(sb); +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_FSTYPE_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/hfsnotify.c +++ linux-2.6.37/ubuntu/aufs/hfsnotify.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * fsnotify for the lower directories + */ + +#include "aufs.h" + +/* FS_IN_IGNORED is unnecessary */ +static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE + | FS_CREATE | FS_EVENT_ON_CHILD); +static struct fsnotify_group *au_hfsn_group; +static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq); + +static void au_hfsn_free_mark(struct fsnotify_mark *mark) +{ + struct au_hnotify *hn = container_of(mark, struct au_hnotify, + hn_mark); + AuDbg("here\n"); + hn->hn_mark_dead = 1; + smp_mb(); + wake_up_all(&au_hfsn_wq); +} + +static int au_hfsn_alloc(struct au_hnotify *hn, struct inode *h_inode) +{ + struct fsnotify_mark *mark; + + hn->hn_mark_dead = 0; + mark = &hn->hn_mark; + fsnotify_init_mark(mark, au_hfsn_free_mark); + mark->mask = AuHfsnMask; + /* + * by udba rename or rmdir, aufs assign a new inode to the known + * h_inode, so specify 1 to allow dups. + */ + return fsnotify_add_mark(mark, au_hfsn_group, h_inode, /*mnt*/NULL, + /*allow_dups*/1); +} + +static void au_hfsn_free(struct au_hnotify *hn) +{ + struct fsnotify_mark *mark; + + mark = &hn->hn_mark; + fsnotify_destroy_mark(mark); + fsnotify_put_mark(mark); + + /* TODO: bad approach */ + wait_event(au_hfsn_wq, hn->hn_mark_dead); +} + +/* ---------------------------------------------------------------------- */ + +static void au_hfsn_ctl(struct au_hinode *hinode, int do_set) +{ + struct fsnotify_mark *mark; + + mark = &hinode->hi_notify->hn_mark; + spin_lock(&mark->lock); + if (do_set) { + AuDebugOn(mark->mask & AuHfsnMask); + mark->mask |= AuHfsnMask; + } else { + AuDebugOn(!(mark->mask & AuHfsnMask)); + mark->mask &= ~AuHfsnMask; + } + spin_unlock(&mark->lock); + /* fsnotify_recalc_inode_mask(hinode->hi_inode); */ +} + +/* ---------------------------------------------------------------------- */ + +/* #define AuDbgHnotify */ +#ifdef AuDbgHnotify +static char *au_hfsn_name(u32 mask) +{ +#ifdef CONFIG_AUFS_DEBUG +#define test_ret(flag) if (mask & flag) \ + return #flag; + test_ret(FS_ACCESS); + test_ret(FS_MODIFY); + test_ret(FS_ATTRIB); + test_ret(FS_CLOSE_WRITE); + test_ret(FS_CLOSE_NOWRITE); + test_ret(FS_OPEN); + test_ret(FS_MOVED_FROM); + test_ret(FS_MOVED_TO); + test_ret(FS_CREATE); + test_ret(FS_DELETE); + test_ret(FS_DELETE_SELF); + test_ret(FS_MOVE_SELF); + test_ret(FS_UNMOUNT); + test_ret(FS_Q_OVERFLOW); + test_ret(FS_IN_IGNORED); + test_ret(FS_IN_ISDIR); + test_ret(FS_IN_ONESHOT); + test_ret(FS_EVENT_ON_CHILD); + return ""; +#undef test_ret +#else + return "??"; +#endif +} +#endif + +/* ---------------------------------------------------------------------- */ + +static int au_hfsn_handle_event(struct fsnotify_group *group, + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, + struct fsnotify_event *event) +{ + int err; + struct au_hnotify *hnotify; + struct inode *h_dir, *h_inode; + __u32 mask; + struct qstr h_child_qstr = { + .name = event->file_name, + .len = event->name_len + }; + + AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE); + + err = 0; + /* if FS_UNMOUNT happens, there must be another bug */ + mask = event->mask; + AuDebugOn(mask & FS_UNMOUNT); + if (mask & (FS_IN_IGNORED | FS_UNMOUNT)) + goto out; + + h_dir = event->to_tell; + h_inode = event->inode; +#ifdef AuDbgHnotify + au_debug(1); + if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1 + || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) { + AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n", + h_dir->i_ino, mask, au_hfsn_name(mask), + AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0); + /* WARN_ON(1); */ + } + au_debug(0); +#endif + + AuDebugOn(!inode_mark); + hnotify = container_of(inode_mark, struct au_hnotify, hn_mark); + err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode); + +out: + return err; +} + +/* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */ +/* it should be exported to modules */ +static bool au_hfsn_should_send_event(struct fsnotify_group *group, + struct inode *h_inode, + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, + __u32 mask, void *data, int data_type) +{ + mask = (mask & ~FS_EVENT_ON_CHILD); + return inode_mark->mask & mask; +} + +static struct fsnotify_ops au_hfsn_ops = { + .should_send_event = au_hfsn_should_send_event, + .handle_event = au_hfsn_handle_event +}; + +/* ---------------------------------------------------------------------- */ + +static int __init au_hfsn_init(void) +{ + int err; + + err = 0; + au_hfsn_group = fsnotify_alloc_group(&au_hfsn_ops); + if (IS_ERR(au_hfsn_group)) { + err = PTR_ERR(au_hfsn_group); + pr_err("fsnotify_alloc_group() failed, %d\n", err); + } + + AuTraceErr(err); + return err; +} + +static void au_hfsn_fin(void) +{ + fsnotify_put_group(au_hfsn_group); +} + +const struct au_hnotify_op au_hnotify_op = { + .ctl = au_hfsn_ctl, + .alloc = au_hfsn_alloc, + .free = au_hfsn_free, + + .fin = au_hfsn_fin, + .init = au_hfsn_init +}; --- linux-2.6.37.orig/ubuntu/aufs/hfsplus.c +++ linux-2.6.37/ubuntu/aufs/hfsplus.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * special support for filesystems which aqucires an inode mutex + * at final closing a file, eg, hfsplus. + * + * This trick is very simple and stupid, just to open the file before really + * neceeary open to tell hfsplus that this is not the final closing. + * The caller should call au_h_open_pre() after acquiring the inode mutex, + * and au_h_open_post() after releasing it. + */ + +#include +#include "aufs.h" + +struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex) +{ + struct file *h_file; + struct dentry *h_dentry; + + h_dentry = au_h_dptr(dentry, bindex); + AuDebugOn(!h_dentry); + AuDebugOn(!h_dentry->d_inode); + IMustLock(h_dentry->d_inode); + + h_file = NULL; + if (au_test_hfsplus(h_dentry->d_sb) + && S_ISREG(h_dentry->d_inode->i_mode)) + h_file = au_h_open(dentry, bindex, + O_RDONLY | O_NOATIME | O_LARGEFILE, + /*file*/NULL); + return h_file; +} + +void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex, + struct file *h_file) +{ + if (h_file) { + fput(h_file); + au_sbr_put(dentry->d_sb, bindex); + } +} --- linux-2.6.37.orig/ubuntu/aufs/hnotify.c +++ linux-2.6.37/ubuntu/aufs/hnotify.c @@ -0,0 +1,664 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * abstraction to notify the direct changes on lower directories + */ + +#include "aufs.h" + +int au_hn_alloc(struct au_hinode *hinode, struct inode *inode, + struct inode *h_inode) +{ + int err; + struct au_hnotify *hn; + + err = -ENOMEM; + hn = au_cache_alloc_hnotify(); + if (hn) { + hn->hn_aufs_inode = inode; + err = au_hnotify_op.alloc(hn, h_inode); + if (!err) + hinode->hi_notify = hn; + else { + au_cache_free_hnotify(hn); + /* + * The upper dir was removed by udba, but the same named + * dir left. In this case, aufs assignes a new inode + * number and set the monitor again. + * For the lower dir, the old monitnor is still left. + */ + if (err == -EEXIST) + err = 0; + } + } + + return err; +} + +void au_hn_free(struct au_hinode *hinode) +{ + struct au_hnotify *hn; + + hn = hinode->hi_notify; + if (hn) { + au_hnotify_op.free(hn); + au_cache_free_hnotify(hn); + hinode->hi_notify = NULL; + } +} + +/* ---------------------------------------------------------------------- */ + +void au_hn_ctl(struct au_hinode *hinode, int do_set) +{ + if (hinode->hi_notify) + au_hnotify_op.ctl(hinode, do_set); +} + +void au_hn_reset(struct inode *inode, unsigned int flags) +{ + aufs_bindex_t bindex, bend; + struct inode *hi; + struct dentry *iwhdentry; + + bend = au_ibend(inode); + for (bindex = au_ibstart(inode); bindex <= bend; bindex++) { + hi = au_h_iptr(inode, bindex); + if (!hi) + continue; + + /* mutex_lock_nested(&hi->i_mutex, AuLsc_I_CHILD); */ + iwhdentry = au_hi_wh(inode, bindex); + if (iwhdentry) + dget(iwhdentry); + au_igrab(hi); + au_set_h_iptr(inode, bindex, NULL, 0); + au_set_h_iptr(inode, bindex, au_igrab(hi), + flags & ~AuHi_XINO); + iput(hi); + dput(iwhdentry); + /* mutex_unlock(&hi->i_mutex); */ + } +} + +/* ---------------------------------------------------------------------- */ + +static int hn_xino(struct inode *inode, struct inode *h_inode) +{ + int err; + aufs_bindex_t bindex, bend, bfound, bstart; + struct inode *h_i; + + err = 0; + if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { + pr_warning("branch root dir was changed\n"); + goto out; + } + + bfound = -1; + bend = au_ibend(inode); + bstart = au_ibstart(inode); +#if 0 /* reserved for future use */ + if (bindex == bend) { + /* keep this ino in rename case */ + goto out; + } +#endif + for (bindex = bstart; bindex <= bend; bindex++) + if (au_h_iptr(inode, bindex) == h_inode) { + bfound = bindex; + break; + } + if (bfound < 0) + goto out; + + for (bindex = bstart; bindex <= bend; bindex++) { + h_i = au_h_iptr(inode, bindex); + if (!h_i) + continue; + + err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0); + /* ignore this error */ + /* bad action? */ + } + + /* children inode number will be broken */ + +out: + AuTraceErr(err); + return err; +} + +static int hn_gen_tree(struct dentry *dentry) +{ + int err, i, j, ndentry; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + struct dentry **dentries; + + err = au_dpages_init(&dpages, GFP_NOFS); + if (unlikely(err)) + goto out; + err = au_dcsub_pages(&dpages, dentry, NULL, NULL); + if (unlikely(err)) + goto out_dpages; + + for (i = 0; i < dpages.ndpage; i++) { + dpage = dpages.dpages + i; + dentries = dpage->dentries; + ndentry = dpage->ndentry; + for (j = 0; j < ndentry; j++) { + struct dentry *d; + + d = dentries[j]; + if (IS_ROOT(d)) + continue; + + d_drop(d); + au_digen_dec(d); + if (d->d_inode) + /* todo: reset children xino? + cached children only? */ + au_iigen_dec(d->d_inode); + } + } + +out_dpages: + au_dpages_free(&dpages); + + /* discard children */ + dentry_unhash(dentry); + dput(dentry); +out: + return err; +} + +/* + * return 0 if processed. + */ +static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode, + const unsigned int isdir) +{ + int err; + struct dentry *d; + struct qstr *dname; + + err = 1; + if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { + pr_warning("branch root dir was changed\n"); + err = 0; + goto out; + } + + if (!isdir) { + AuDebugOn(!name); + au_iigen_dec(inode); + spin_lock(&dcache_lock); + list_for_each_entry(d, &inode->i_dentry, d_alias) { + dname = &d->d_name; + if (dname->len != nlen + && memcmp(dname->name, name, nlen)) + continue; + err = 0; + spin_lock(&d->d_lock); + __d_drop(d); + au_digen_dec(d); + spin_unlock(&d->d_lock); + break; + } + spin_unlock(&dcache_lock); + } else { + au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIRS); + d = d_find_alias(inode); + if (!d) { + au_iigen_dec(inode); + goto out; + } + + dname = &d->d_name; + if (dname->len == nlen && !memcmp(dname->name, name, nlen)) + err = hn_gen_tree(d); + dput(d); + } + +out: + AuTraceErr(err); + return err; +} + +static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir) +{ + int err; + struct inode *inode; + + inode = dentry->d_inode; + if (IS_ROOT(dentry) + /* || (inode && inode->i_ino == AUFS_ROOT_INO) */ + ) { + pr_warning("branch root dir was changed\n"); + return 0; + } + + err = 0; + if (!isdir) { + d_drop(dentry); + au_digen_dec(dentry); + if (inode) + au_iigen_dec(inode); + } else { + au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIRS); + if (inode) + err = hn_gen_tree(dentry); + } + + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* hnotify job flags */ +#define AuHnJob_XINO0 1 +#define AuHnJob_GEN (1 << 1) +#define AuHnJob_DIRENT (1 << 2) +#define AuHnJob_ISDIR (1 << 3) +#define AuHnJob_TRYXINO0 (1 << 4) +#define AuHnJob_MNTPNT (1 << 5) +#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name) +#define au_fset_hnjob(flags, name) \ + do { (flags) |= AuHnJob_##name; } while (0) +#define au_fclr_hnjob(flags, name) \ + do { (flags) &= ~AuHnJob_##name; } while (0) + +enum { + AuHn_CHILD, + AuHn_PARENT, + AuHnLast +}; + +struct au_hnotify_args { + struct inode *h_dir, *dir, *h_child_inode; + u32 mask; + unsigned int flags[AuHnLast]; + unsigned int h_child_nlen; + char h_child_name[]; +}; + +struct hn_job_args { + unsigned int flags; + struct inode *inode, *h_inode, *dir, *h_dir; + struct dentry *dentry; + char *h_name; + int h_nlen; +}; + +static int hn_job(struct hn_job_args *a) +{ + const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR); + + /* reset xino */ + if (au_ftest_hnjob(a->flags, XINO0) && a->inode) + hn_xino(a->inode, a->h_inode); /* ignore this error */ + + if (au_ftest_hnjob(a->flags, TRYXINO0) + && a->inode + && a->h_inode) { + mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD); + if (!a->h_inode->i_nlink) + hn_xino(a->inode, a->h_inode); /* ignore this error */ + mutex_unlock(&a->h_inode->i_mutex); + } + + /* make the generation obsolete */ + if (au_ftest_hnjob(a->flags, GEN)) { + int err = -1; + if (a->inode) + err = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode, + isdir); + if (err && a->dentry) + hn_gen_by_name(a->dentry, isdir); + /* ignore this error */ + } + + /* make dir entries obsolete */ + if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) { + struct au_vdir *vdir; + + vdir = au_ivdir(a->inode); + if (vdir) + vdir->vd_jiffy = 0; + /* IMustLock(a->inode); */ + /* a->inode->i_version++; */ + } + + /* can do nothing but warn */ + if (au_ftest_hnjob(a->flags, MNTPNT) + && a->dentry + && d_mountpoint(a->dentry)) + pr_warning("mount-point %.*s is removed or renamed\n", + AuDLNPair(a->dentry)); + + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen, + struct inode *dir) +{ + struct dentry *dentry, *d, *parent; + struct qstr *dname; + + parent = d_find_alias(dir); + if (!parent) + return NULL; + + dentry = NULL; + spin_lock(&dcache_lock); + list_for_each_entry(d, &parent->d_subdirs, d_u.d_child) { + /* AuDbg("%.*s\n", AuDLNPair(d)); */ + dname = &d->d_name; + if (dname->len != nlen || memcmp(dname->name, name, nlen)) + continue; + if (!atomic_read(&d->d_count) || !d->d_fsdata) { + spin_lock(&d->d_lock); + __d_drop(d); + spin_unlock(&d->d_lock); + continue; + } + + dentry = dget(d); + break; + } + spin_unlock(&dcache_lock); + dput(parent); + + if (dentry) + di_write_lock_child(dentry); + + return dentry; +} + +static struct inode *lookup_wlock_by_ino(struct super_block *sb, + aufs_bindex_t bindex, ino_t h_ino) +{ + struct inode *inode; + ino_t ino; + int err; + + inode = NULL; + err = au_xino_read(sb, bindex, h_ino, &ino); + if (!err && ino) + inode = ilookup(sb, ino); + if (!inode) + goto out; + + if (unlikely(inode->i_ino == AUFS_ROOT_INO)) { + pr_warning("wrong root branch\n"); + iput(inode); + inode = NULL; + goto out; + } + + ii_write_lock_child(inode); + +out: + return inode; +} + +static void au_hn_bh(void *_args) +{ + struct au_hnotify_args *a = _args; + struct super_block *sb; + aufs_bindex_t bindex, bend, bfound; + unsigned char xino, try_iput; + int err; + struct inode *inode; + ino_t h_ino; + struct hn_job_args args; + struct dentry *dentry; + struct au_sbinfo *sbinfo; + + AuDebugOn(!_args); + AuDebugOn(!a->h_dir); + AuDebugOn(!a->dir); + AuDebugOn(!a->mask); + AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n", + a->mask, a->dir->i_ino, a->h_dir->i_ino, + a->h_child_inode ? a->h_child_inode->i_ino : 0); + + inode = NULL; + dentry = NULL; + /* + * do not lock a->dir->i_mutex here + * because of d_revalidate() may cause a deadlock. + */ + sb = a->dir->i_sb; + AuDebugOn(!sb); + sbinfo = au_sbi(sb); + AuDebugOn(!sbinfo); + si_write_lock(sb, AuLock_NOPLMW); + + ii_read_lock_parent(a->dir); + bfound = -1; + bend = au_ibend(a->dir); + for (bindex = au_ibstart(a->dir); bindex <= bend; bindex++) + if (au_h_iptr(a->dir, bindex) == a->h_dir) { + bfound = bindex; + break; + } + ii_read_unlock(a->dir); + if (unlikely(bfound < 0)) + goto out; + + xino = !!au_opt_test(au_mntflags(sb), XINO); + h_ino = 0; + if (a->h_child_inode) + h_ino = a->h_child_inode->i_ino; + + if (a->h_child_nlen + && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN) + || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT))) + dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen, + a->dir); + try_iput = 0; + if (dentry) + inode = dentry->d_inode; + if (xino && !inode && h_ino + && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0) + || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0) + || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) { + inode = lookup_wlock_by_ino(sb, bfound, h_ino); + try_iput = 1; + } + + args.flags = a->flags[AuHn_CHILD]; + args.dentry = dentry; + args.inode = inode; + args.h_inode = a->h_child_inode; + args.dir = a->dir; + args.h_dir = a->h_dir; + args.h_name = a->h_child_name; + args.h_nlen = a->h_child_nlen; + err = hn_job(&args); + if (dentry) { + if (dentry->d_fsdata) + di_write_unlock(dentry); + dput(dentry); + } + if (inode && try_iput) { + ii_write_unlock(inode); + iput(inode); + } + + ii_write_lock_parent(a->dir); + args.flags = a->flags[AuHn_PARENT]; + args.dentry = NULL; + args.inode = a->dir; + args.h_inode = a->h_dir; + args.dir = NULL; + args.h_dir = NULL; + args.h_name = NULL; + args.h_nlen = 0; + err = hn_job(&args); + ii_write_unlock(a->dir); + +out: + au_nwt_done(&sbinfo->si_nowait); + si_write_unlock(sb); + + iput(a->h_child_inode); + iput(a->h_dir); + iput(a->dir); + kfree(a); +} + +/* ---------------------------------------------------------------------- */ + +int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, + struct qstr *h_child_qstr, struct inode *h_child_inode) +{ + int err, len; + unsigned int flags[AuHnLast]; + unsigned char isdir, isroot, wh; + struct inode *dir; + struct au_hnotify_args *args; + char *p, *h_child_name; + + err = 0; + AuDebugOn(!hnotify || !hnotify->hn_aufs_inode); + dir = igrab(hnotify->hn_aufs_inode); + if (!dir) + goto out; + + isroot = (dir->i_ino == AUFS_ROOT_INO); + wh = 0; + h_child_name = (void *)h_child_qstr->name; + len = h_child_qstr->len; + if (h_child_name) { + if (len > AUFS_WH_PFX_LEN + && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { + h_child_name += AUFS_WH_PFX_LEN; + len -= AUFS_WH_PFX_LEN; + wh = 1; + } + } + + isdir = 0; + if (h_child_inode) + isdir = !!S_ISDIR(h_child_inode->i_mode); + flags[AuHn_PARENT] = AuHnJob_ISDIR; + flags[AuHn_CHILD] = 0; + if (isdir) + flags[AuHn_CHILD] = AuHnJob_ISDIR; + au_fset_hnjob(flags[AuHn_PARENT], DIRENT); + au_fset_hnjob(flags[AuHn_CHILD], GEN); + switch (mask & FS_EVENTS_POSS_ON_CHILD) { + case FS_MOVED_FROM: + case FS_MOVED_TO: + au_fset_hnjob(flags[AuHn_CHILD], XINO0); + au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); + /*FALLTHROUGH*/ + case FS_CREATE: + AuDebugOn(!h_child_name || !h_child_inode); + break; + + case FS_DELETE: + /* + * aufs never be able to get this child inode. + * revalidation should be in d_revalidate() + * by checking i_nlink, i_generation or d_unhashed(). + */ + AuDebugOn(!h_child_name); + au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0); + au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); + break; + + default: + AuDebugOn(1); + } + + if (wh) + h_child_inode = NULL; + + err = -ENOMEM; + /* iput() and kfree() will be called in au_hnotify() */ + args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS); + if (unlikely(!args)) { + AuErr1("no memory\n"); + iput(dir); + goto out; + } + args->flags[AuHn_PARENT] = flags[AuHn_PARENT]; + args->flags[AuHn_CHILD] = flags[AuHn_CHILD]; + args->mask = mask; + args->dir = dir; + args->h_dir = igrab(h_dir); + if (h_child_inode) + h_child_inode = igrab(h_child_inode); /* can be NULL */ + args->h_child_inode = h_child_inode; + args->h_child_nlen = len; + if (len) { + p = (void *)args; + p += sizeof(*args); + memcpy(p, h_child_name, len); + p[len] = 0; + } + + err = au_wkq_nowait(au_hn_bh, args, dir->i_sb); + if (unlikely(err)) { + pr_err("wkq %d\n", err); + iput(args->h_child_inode); + iput(args->h_dir); + iput(args->dir); + kfree(args); + } + +out: + return err; +} + +static void au_hn_destroy_cache(void) +{ + kmem_cache_destroy(au_cachep[AuCache_HNOTIFY]); + au_cachep[AuCache_HNOTIFY] = NULL; +} + +int __init au_hnotify_init(void) +{ + int err; + + err = -ENOMEM; + au_cachep[AuCache_HNOTIFY] = AuCache(au_hnotify); + if (au_cachep[AuCache_HNOTIFY]) { + err = au_hnotify_op.init(); + if (unlikely(err)) + au_hn_destroy_cache(); + } + AuTraceErr(err); + return err; +} + +void au_hnotify_fin(void) +{ + au_hnotify_op.fin(); + /* cf. au_cache_fin() */ + if (au_cachep[AuCache_HNOTIFY]) + au_hn_destroy_cache(); +} --- linux-2.6.37.orig/ubuntu/aufs/i_op.c +++ linux-2.6.37/ubuntu/aufs/i_op.c @@ -0,0 +1,931 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode operations (except add/del/rename) + */ + +#include +#include +#include +#include +#include +#include +#include "aufs.h" + +static int h_permission(struct inode *h_inode, int mask, + struct vfsmount *h_mnt, int brperm) +{ + int err; + const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); + + err = -EACCES; + if ((write_mask && IS_IMMUTABLE(h_inode)) + || ((mask & MAY_EXEC) + && S_ISREG(h_inode->i_mode) + && ((h_mnt->mnt_flags & MNT_NOEXEC) + || !(h_inode->i_mode & S_IXUGO)))) + goto out; + + /* + * - skip the lower fs test in the case of write to ro branch. + * - nfs dir permission write check is optimized, but a policy for + * link/rename requires a real check. + */ + if ((write_mask && !au_br_writable(brperm)) + || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode) + && write_mask && !(mask & MAY_READ)) + || !h_inode->i_op->permission) { + /* AuLabel(generic_permission); */ + err = generic_permission(h_inode, mask, + h_inode->i_op->check_acl); + } else { + /* AuLabel(h_inode->permission); */ + err = h_inode->i_op->permission(h_inode, mask); + AuTraceErr(err); + } + + if (!err) + err = devcgroup_inode_permission(h_inode, mask); + if (!err) + err = security_inode_permission(h_inode, mask); + +#if 0 + if (!err) { + /* todo: do we need to call ima_path_check()? */ + struct path h_path = { + .dentry = + .mnt = h_mnt + }; + err = ima_path_check(&h_path, + mask & (MAY_READ | MAY_WRITE | MAY_EXEC), + IMA_COUNT_LEAVE); + } +#endif + +out: + return err; +} + +static int aufs_permission(struct inode *inode, int mask) +{ + int err; + aufs_bindex_t bindex, bend; + const unsigned char isdir = !!S_ISDIR(inode->i_mode), + write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); + struct inode *h_inode; + struct super_block *sb; + struct au_branch *br; + + sb = inode->i_sb; + si_read_lock(sb, AuLock_FLUSH); + ii_read_lock_child(inode); + + if (!isdir || write_mask) { + err = au_busy_or_stale(); + h_inode = au_h_iptr(inode, au_ibstart(inode)); + if (unlikely(!h_inode + || (h_inode->i_mode & S_IFMT) + != (inode->i_mode & S_IFMT))) + goto out; + + err = 0; + bindex = au_ibstart(inode); + br = au_sbr(sb, bindex); + err = h_permission(h_inode, mask, br->br_mnt, br->br_perm); + if (write_mask + && !err + && !special_file(h_inode->i_mode)) { + /* test whether the upper writable branch exists */ + err = -EROFS; + for (; bindex >= 0; bindex--) + if (!au_br_rdonly(au_sbr(sb, bindex))) { + err = 0; + break; + } + } + goto out; + } + + /* non-write to dir */ + err = 0; + bend = au_ibend(inode); + for (bindex = au_ibstart(inode); !err && bindex <= bend; bindex++) { + h_inode = au_h_iptr(inode, bindex); + if (h_inode) { + err = au_busy_or_stale(); + if (unlikely(!S_ISDIR(h_inode->i_mode))) + break; + + br = au_sbr(sb, bindex); + err = h_permission(h_inode, mask, br->br_mnt, + br->br_perm); + } + } + +out: + ii_read_unlock(inode); + si_read_unlock(sb); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) +{ + struct dentry *ret, *parent; + struct inode *inode; + struct super_block *sb; + int err, npositive; + + IMustLock(dir); + + sb = dir->i_sb; + err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); + ret = ERR_PTR(err); + if (unlikely(err)) + goto out; + + ret = ERR_PTR(-ENAMETOOLONG); + if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) + goto out_si; + err = au_di_init(dentry); + ret = ERR_PTR(err); + if (unlikely(err)) + goto out_si; + + parent = dentry->d_parent; /* dir inode is locked */ + di_read_lock_parent(parent, AuLock_IR); + npositive = au_lkup_dentry(dentry, au_dbstart(parent), /*type*/0, nd); + di_read_unlock(parent, AuLock_IR); + err = npositive; + ret = ERR_PTR(err); + if (unlikely(err < 0)) + goto out_unlock; + + inode = NULL; + if (npositive) { + inode = au_new_inode(dentry, /*must_new*/0); + ret = (void *)inode; + } + if (IS_ERR(inode)) + goto out_unlock; + + ret = d_splice_alias(inode, dentry); + if (unlikely(IS_ERR(ret) && inode)) { + ii_write_unlock(inode); + iput(inode); + } + +out_unlock: + di_write_unlock(dentry); +out_si: + si_read_unlock(sb); +out: + return ret; +} + +/* ---------------------------------------------------------------------- */ + +static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent, + const unsigned char add_entry, aufs_bindex_t bcpup, + aufs_bindex_t bstart) +{ + int err; + struct dentry *h_parent; + struct inode *h_dir; + + if (add_entry) { + au_update_dbstart(dentry); + IMustLock(parent->d_inode); + } else + di_write_lock_parent(parent); + + err = 0; + if (!au_h_dptr(parent, bcpup)) { + if (bstart < bcpup) + err = au_cpdown_dirs(dentry, bcpup); + else + err = au_cpup_dirs(dentry, bcpup); + } + if (!err && add_entry) { + h_parent = au_h_dptr(parent, bcpup); + h_dir = h_parent->d_inode; + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); + err = au_lkup_neg(dentry, bcpup); + /* todo: no unlock here */ + mutex_unlock(&h_dir->i_mutex); + if (bstart < bcpup && au_dbstart(dentry) < 0) { + au_set_dbstart(dentry, 0); + au_update_dbrange(dentry, /*do_put_zero*/0); + } + } + + if (!add_entry) + di_write_unlock(parent); + if (!err) + err = bcpup; /* success */ + + return err; +} + +/* + * decide the branch and the parent dir where we will create a new entry. + * returns new bindex or an error. + * copyup the parent dir if needed. + */ +int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, + struct au_wr_dir_args *args) +{ + int err; + aufs_bindex_t bcpup, bstart, src_bstart; + const unsigned char add_entry = !!au_ftest_wrdir(args->flags, + ADD_ENTRY); + struct super_block *sb; + struct dentry *parent; + struct au_sbinfo *sbinfo; + + sb = dentry->d_sb; + sbinfo = au_sbi(sb); + parent = dget_parent(dentry); + bstart = au_dbstart(dentry); + bcpup = bstart; + if (args->force_btgt < 0) { + if (src_dentry) { + src_bstart = au_dbstart(src_dentry); + if (src_bstart < bstart) + bcpup = src_bstart; + } else if (add_entry) { + err = AuWbrCreate(sbinfo, dentry, + au_ftest_wrdir(args->flags, ISDIR)); + bcpup = err; + } + + if (bcpup < 0 || au_test_ro(sb, bcpup, dentry->d_inode)) { + if (add_entry) + err = AuWbrCopyup(sbinfo, dentry); + else { + if (!IS_ROOT(dentry)) { + di_read_lock_parent(parent, !AuLock_IR); + err = AuWbrCopyup(sbinfo, dentry); + di_read_unlock(parent, !AuLock_IR); + } else + err = AuWbrCopyup(sbinfo, dentry); + } + bcpup = err; + if (unlikely(err < 0)) + goto out; + } + } else { + bcpup = args->force_btgt; + AuDebugOn(au_test_ro(sb, bcpup, dentry->d_inode)); + } + AuDbg("bstart %d, bcpup %d\n", bstart, bcpup); + err = bcpup; + if (bcpup == bstart) + goto out; /* success */ + else if (bstart < bcpup) + au_update_dbrange(dentry, /*do_put_zero*/1); + + /* copyup the new parent into the branch we process */ + err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, bstart); + +out: + dput(parent); + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct dentry *au_pinned_h_parent(struct au_pin *pin) +{ + if (pin && pin->parent) + return au_h_dptr(pin->parent, pin->bindex); + return NULL; +} + +void au_unpin(struct au_pin *p) +{ + if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE)) + mnt_drop_write(p->h_mnt); + if (!p->hdir) + return; + + au_hn_imtx_unlock(p->hdir); + if (!au_ftest_pin(p->flags, DI_LOCKED)) + di_read_unlock(p->parent, AuLock_IR); + iput(p->hdir->hi_inode); + dput(p->parent); + p->parent = NULL; + p->hdir = NULL; + p->h_mnt = NULL; +} + +int au_do_pin(struct au_pin *p) +{ + int err; + struct super_block *sb; + struct dentry *h_dentry, *h_parent; + struct au_branch *br; + struct inode *h_dir; + + err = 0; + sb = p->dentry->d_sb; + br = au_sbr(sb, p->bindex); + if (IS_ROOT(p->dentry)) { + if (au_ftest_pin(p->flags, MNT_WRITE)) { + p->h_mnt = br->br_mnt; + err = mnt_want_write(p->h_mnt); + if (unlikely(err)) { + au_fclr_pin(p->flags, MNT_WRITE); + goto out_err; + } + } + goto out; + } + + h_dentry = NULL; + if (p->bindex <= au_dbend(p->dentry)) + h_dentry = au_h_dptr(p->dentry, p->bindex); + + p->parent = dget_parent(p->dentry); + if (!au_ftest_pin(p->flags, DI_LOCKED)) + di_read_lock(p->parent, AuLock_IR, p->lsc_di); + + h_dir = NULL; + h_parent = au_h_dptr(p->parent, p->bindex); + p->hdir = au_hi(p->parent->d_inode, p->bindex); + if (p->hdir) + h_dir = p->hdir->hi_inode; + + /* + * udba case, or + * if DI_LOCKED is not set, then p->parent may be different + * and h_parent can be NULL. + */ + if (unlikely(!p->hdir || !h_dir || !h_parent)) { + err = -EBUSY; + if (!au_ftest_pin(p->flags, DI_LOCKED)) + di_read_unlock(p->parent, AuLock_IR); + dput(p->parent); + p->parent = NULL; + goto out_err; + } + + au_igrab(h_dir); + au_hn_imtx_lock_nested(p->hdir, p->lsc_hi); + + if (unlikely(p->hdir->hi_inode != h_parent->d_inode)) { + err = -EBUSY; + goto out_unpin; + } + if (h_dentry) { + err = au_h_verify(h_dentry, p->udba, h_dir, h_parent, br); + if (unlikely(err)) { + au_fclr_pin(p->flags, MNT_WRITE); + goto out_unpin; + } + } + + if (au_ftest_pin(p->flags, MNT_WRITE)) { + p->h_mnt = br->br_mnt; + err = mnt_want_write(p->h_mnt); + if (unlikely(err)) { + au_fclr_pin(p->flags, MNT_WRITE); + goto out_unpin; + } + } + goto out; /* success */ + +out_unpin: + au_unpin(p); +out_err: + pr_err("err %d\n", err); + err = au_busy_or_stale(); +out: + return err; +} + +void au_pin_init(struct au_pin *p, struct dentry *dentry, + aufs_bindex_t bindex, int lsc_di, int lsc_hi, + unsigned int udba, unsigned char flags) +{ + p->dentry = dentry; + p->udba = udba; + p->lsc_di = lsc_di; + p->lsc_hi = lsc_hi; + p->flags = flags; + p->bindex = bindex; + + p->parent = NULL; + p->hdir = NULL; + p->h_mnt = NULL; +} + +int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, + unsigned int udba, unsigned char flags) +{ + au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2, + udba, flags); + return au_do_pin(pin); +} + +/* ---------------------------------------------------------------------- */ + +/* + * ->setattr() and ->getattr() are called in various cases. + * chmod, stat: dentry is revalidated. + * fchmod, fstat: file and dentry are not revalidated, additionally they may be + * unhashed. + * for ->setattr(), ia->ia_file is passed from ftruncate only. + */ +static int au_reval_for_attr(struct dentry *dentry, unsigned int sigen) +{ + int err; + struct inode *inode; + struct dentry *parent; + + err = 0; + inode = dentry->d_inode; + if (au_digen(dentry) != sigen || au_iigen(inode) != sigen) { + parent = dget_parent(dentry); + di_read_lock_parent(parent, AuLock_IR); + /* returns a number of positive dentries */ + err = au_refresh_hdentry(dentry, inode->i_mode & S_IFMT); + if (err >= 0) + err = au_refresh_hinode(inode, dentry); + di_read_unlock(parent, AuLock_IR); + dput(parent); + } + + AuTraceErr(err); + return err; +} + +#define AuIcpup_DID_CPUP 1 +#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name) +#define au_fset_icpup(flags, name) \ + do { (flags) |= AuIcpup_##name; } while (0) +#define au_fclr_icpup(flags, name) \ + do { (flags) &= ~AuIcpup_##name; } while (0) + +struct au_icpup_args { + unsigned char flags; + unsigned char pin_flags; + aufs_bindex_t btgt; + unsigned int udba; + struct au_pin pin; + struct path h_path; + struct inode *h_inode; +}; + +static int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, + struct au_icpup_args *a) +{ + int err; + loff_t sz; + aufs_bindex_t bstart, ibstart; + struct dentry *hi_wh, *parent; + struct inode *inode; + struct file *h_file; + struct au_wr_dir_args wr_dir_args = { + .force_btgt = -1, + .flags = 0 + }; + + bstart = au_dbstart(dentry); + inode = dentry->d_inode; + if (S_ISDIR(inode->i_mode)) + au_fset_wrdir(wr_dir_args.flags, ISDIR); + /* plink or hi_wh() case */ + ibstart = au_ibstart(inode); + if (bstart != ibstart) + wr_dir_args.force_btgt = ibstart; + err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args); + if (unlikely(err < 0)) + goto out; + a->btgt = err; + if (err != bstart) + au_fset_icpup(a->flags, DID_CPUP); + + err = 0; + a->pin_flags = AuPin_MNT_WRITE; + parent = NULL; + if (!IS_ROOT(dentry)) { + au_fset_pin(a->pin_flags, DI_LOCKED); + parent = dget_parent(dentry); + di_write_lock_parent(parent); + } + + err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags); + if (unlikely(err)) + goto out_parent; + + a->h_path.dentry = au_h_dptr(dentry, bstart); + a->h_inode = a->h_path.dentry->d_inode; + mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD); + sz = -1; + if ((ia->ia_valid & ATTR_SIZE) && ia->ia_size < i_size_read(a->h_inode)) + sz = ia->ia_size; + + h_file = NULL; + hi_wh = NULL; + if (au_ftest_icpup(a->flags, DID_CPUP) && au_d_removed(dentry)) { + hi_wh = au_hi_wh(inode, a->btgt); + if (!hi_wh) { + err = au_sio_cpup_wh(dentry, a->btgt, sz, /*file*/NULL); + if (unlikely(err)) + goto out_unlock; + hi_wh = au_hi_wh(inode, a->btgt); + /* todo: revalidate hi_wh? */ + } + } + + if (parent) { + au_pin_set_parent_lflag(&a->pin, /*lflag*/0); + di_downgrade_lock(parent, AuLock_IR); + dput(parent); + parent = NULL; + } + if (!au_ftest_icpup(a->flags, DID_CPUP)) + goto out; /* success */ + + if (!d_unhashed(dentry)) { + h_file = au_h_open_pre(dentry, bstart); + if (IS_ERR(h_file)) { + err = PTR_ERR(h_file); + h_file = NULL; + } else + err = au_sio_cpup_simple(dentry, a->btgt, sz, + AuCpup_DTIME); + if (!err) + a->h_path.dentry = au_h_dptr(dentry, a->btgt); + } else if (!hi_wh) + a->h_path.dentry = au_h_dptr(dentry, a->btgt); + else + a->h_path.dentry = hi_wh; /* do not dget here */ + +out_unlock: + mutex_unlock(&a->h_inode->i_mutex); + au_h_open_post(dentry, bstart, h_file); + a->h_inode = a->h_path.dentry->d_inode; + if (!err) { + mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD); + goto out; /* success */ + } + + au_unpin(&a->pin); +out_parent: + if (parent) { + di_write_unlock(parent); + dput(parent); + } +out: + return err; +} + +static int aufs_setattr(struct dentry *dentry, struct iattr *ia) +{ + int err; + struct inode *inode; + struct super_block *sb; + struct file *file; + struct au_icpup_args *a; + + inode = dentry->d_inode; + IMustLock(inode); + + err = -ENOMEM; + a = kzalloc(sizeof(*a), GFP_NOFS); + if (unlikely(!a)) + goto out; + + if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID)) + ia->ia_valid &= ~ATTR_MODE; + + file = NULL; + sb = dentry->d_sb; + err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); + if (unlikely(err)) + goto out_kfree; + + if (ia->ia_valid & ATTR_FILE) { + /* currently ftruncate(2) only */ + AuDebugOn(!S_ISREG(inode->i_mode)); + file = ia->ia_file; + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1); + if (unlikely(err)) + goto out_si; + ia->ia_file = au_hf_top(file); + a->udba = AuOpt_UDBA_NONE; + } else { + /* fchmod() doesn't pass ia_file */ + a->udba = au_opt_udba(sb); + /* no au_d_removed(), to set UDBA_NONE for root */ + if (d_unhashed(dentry)) + a->udba = AuOpt_UDBA_NONE; + di_write_lock_child(dentry); + if (a->udba != AuOpt_UDBA_NONE) { + AuDebugOn(IS_ROOT(dentry)); + err = au_reval_for_attr(dentry, au_sigen(sb)); + if (unlikely(err)) + goto out_dentry; + } + } + + err = au_pin_and_icpup(dentry, ia, a); + if (unlikely(err < 0)) + goto out_dentry; + if (au_ftest_icpup(a->flags, DID_CPUP)) { + ia->ia_file = NULL; + ia->ia_valid &= ~ATTR_FILE; + } + + a->h_path.mnt = au_sbr_mnt(sb, a->btgt); + if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME)) + == (ATTR_MODE | ATTR_CTIME)) { + err = security_path_chmod(a->h_path.dentry, a->h_path.mnt, + ia->ia_mode); + if (unlikely(err)) + goto out_unlock; + } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID)) + && (ia->ia_valid & ATTR_CTIME)) { + err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid); + if (unlikely(err)) + goto out_unlock; + } + + if (ia->ia_valid & ATTR_SIZE) { + struct file *f; + + if (ia->ia_size < i_size_read(inode)) + /* unmap only */ + truncate_setsize(inode, ia->ia_size); + + f = NULL; + if (ia->ia_valid & ATTR_FILE) + f = ia->ia_file; + mutex_unlock(&a->h_inode->i_mutex); + err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f); + mutex_lock_nested(&a->h_inode->i_mutex, AuLsc_I_CHILD); + } else + err = vfsub_notify_change(&a->h_path, ia); + if (!err) + au_cpup_attr_changeable(inode); + +out_unlock: + mutex_unlock(&a->h_inode->i_mutex); + au_unpin(&a->pin); +out_dentry: + di_write_unlock(dentry); + if (file) { + fi_write_unlock(file); + ia->ia_file = file; + ia->ia_valid |= ATTR_FILE; + } +out_si: + si_read_unlock(sb); +out_kfree: + kfree(a); +out: + AuTraceErr(err); + return err; +} + +static void au_refresh_iattr(struct inode *inode, struct kstat *st, + unsigned int nlink) +{ + inode->i_mode = st->mode; + inode->i_uid = st->uid; + inode->i_gid = st->gid; + inode->i_atime = st->atime; + inode->i_mtime = st->mtime; + inode->i_ctime = st->ctime; + + au_cpup_attr_nlink(inode, /*force*/0); + if (S_ISDIR(inode->i_mode)) { + inode->i_nlink -= nlink; + inode->i_nlink += st->nlink; + } + + spin_lock(&inode->i_lock); + inode->i_blocks = st->blocks; + i_size_write(inode, st->size); + spin_unlock(&inode->i_lock); +} + +static int aufs_getattr(struct vfsmount *mnt __maybe_unused, + struct dentry *dentry, struct kstat *st) +{ + int err; + unsigned int mnt_flags; + aufs_bindex_t bindex; + unsigned char udba_none, positive; + struct super_block *sb, *h_sb; + struct inode *inode; + struct vfsmount *h_mnt; + struct dentry *h_dentry; + + sb = dentry->d_sb; + inode = dentry->d_inode; + err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); + if (unlikely(err)) + goto out; + mnt_flags = au_mntflags(sb); + udba_none = !!au_opt_test(mnt_flags, UDBA_NONE); + + /* support fstat(2) */ + if (!au_d_removed(dentry) && !udba_none) { + unsigned int sigen = au_sigen(sb); + if (au_digen(dentry) == sigen && au_iigen(inode) == sigen) + di_read_lock_child(dentry, AuLock_IR); + else { + AuDebugOn(IS_ROOT(dentry)); + di_write_lock_child(dentry); + err = au_reval_for_attr(dentry, sigen); + di_downgrade_lock(dentry, AuLock_IR); + if (unlikely(err)) + goto out_unlock; + } + } else + di_read_lock_child(dentry, AuLock_IR); + + bindex = au_ibstart(inode); + h_mnt = au_sbr_mnt(sb, bindex); + h_sb = h_mnt->mnt_sb; + if (!au_test_fs_bad_iattr(h_sb) && udba_none) + goto out_fill; /* success */ + + h_dentry = NULL; + if (au_dbstart(dentry) == bindex) + h_dentry = dget(au_h_dptr(dentry, bindex)); + else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) { + h_dentry = au_plink_lkup(inode, bindex); + if (IS_ERR(h_dentry)) + goto out_fill; /* pretending success */ + } + /* illegally overlapped or something */ + if (unlikely(!h_dentry)) + goto out_fill; /* pretending success */ + + positive = !!h_dentry->d_inode; + if (positive) + err = vfs_getattr(h_mnt, h_dentry, st); + dput(h_dentry); + if (!err) { + if (positive) + au_refresh_iattr(inode, st, h_dentry->d_inode->i_nlink); + goto out_fill; /* success */ + } + AuTraceErr(err); + goto out_unlock; + +out_fill: + generic_fillattr(inode, st); +out_unlock: + di_read_unlock(dentry, AuLock_IR); + si_read_unlock(sb); +out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int h_readlink(struct dentry *dentry, int bindex, char __user *buf, + int bufsiz) +{ + int err; + struct super_block *sb; + struct dentry *h_dentry; + + err = -EINVAL; + h_dentry = au_h_dptr(dentry, bindex); + if (unlikely(!h_dentry->d_inode->i_op->readlink)) + goto out; + + err = security_inode_readlink(h_dentry); + if (unlikely(err)) + goto out; + + sb = dentry->d_sb; + if (!au_test_ro(sb, bindex, dentry->d_inode)) { + vfsub_touch_atime(au_sbr_mnt(sb, bindex), h_dentry); + fsstack_copy_attr_atime(dentry->d_inode, h_dentry->d_inode); + } + err = h_dentry->d_inode->i_op->readlink(h_dentry, buf, bufsiz); + +out: + return err; +} + +static int aufs_readlink(struct dentry *dentry, char __user *buf, int bufsiz) +{ + int err; + + aufs_read_lock(dentry, AuLock_IR); + err = h_readlink(dentry, au_dbstart(dentry), buf, bufsiz); + aufs_read_unlock(dentry, AuLock_IR); + + return err; +} + +static void *aufs_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + int err; + mm_segment_t old_fs; + union { + char *k; + char __user *u; + } buf; + + err = -ENOMEM; + buf.k = __getname_gfp(GFP_NOFS); + if (unlikely(!buf.k)) + goto out; + + aufs_read_lock(dentry, AuLock_IR); + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = h_readlink(dentry, au_dbstart(dentry), buf.u, PATH_MAX); + set_fs(old_fs); + aufs_read_unlock(dentry, AuLock_IR); + + if (err >= 0) { + buf.k[err] = 0; + /* will be freed by put_link */ + nd_set_link(nd, buf.k); + return NULL; /* success */ + } + __putname(buf.k); + +out: + path_put(&nd->path); + AuTraceErr(err); + return ERR_PTR(err); +} + +static void aufs_put_link(struct dentry *dentry __maybe_unused, + struct nameidata *nd, void *cookie __maybe_unused) +{ + __putname(nd_get_link(nd)); +} + +/* ---------------------------------------------------------------------- */ + +static void aufs_truncate_range(struct inode *inode __maybe_unused, + loff_t start __maybe_unused, + loff_t end __maybe_unused) +{ + AuUnsupport(); +} + +/* ---------------------------------------------------------------------- */ + +struct inode_operations aufs_symlink_iop = { + .permission = aufs_permission, + .setattr = aufs_setattr, + .getattr = aufs_getattr, + .readlink = aufs_readlink, + .follow_link = aufs_follow_link, + .put_link = aufs_put_link +}; + +struct inode_operations aufs_dir_iop = { + .create = aufs_create, + .lookup = aufs_lookup, + .link = aufs_link, + .unlink = aufs_unlink, + .symlink = aufs_symlink, + .mkdir = aufs_mkdir, + .rmdir = aufs_rmdir, + .mknod = aufs_mknod, + .rename = aufs_rename, + + .permission = aufs_permission, + .setattr = aufs_setattr, + .getattr = aufs_getattr +}; + +struct inode_operations aufs_iop = { + .permission = aufs_permission, + .setattr = aufs_setattr, + .getattr = aufs_getattr, + .truncate_range = aufs_truncate_range +}; --- linux-2.6.37.orig/ubuntu/aufs/i_op_add.c +++ linux-2.6.37/ubuntu/aufs/i_op_add.c @@ -0,0 +1,676 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode operations (add entry) + */ + +#include "aufs.h" + +/* + * final procedure of adding a new entry, except link(2). + * remove whiteout, instantiate, copyup the parent dir's times and size + * and update version. + * if it failed, re-create the removed whiteout. + */ +static int epilog(struct inode *dir, aufs_bindex_t bindex, + struct dentry *wh_dentry, struct dentry *dentry) +{ + int err, rerr; + aufs_bindex_t bwh; + struct path h_path; + struct inode *inode, *h_dir; + struct dentry *wh; + + bwh = -1; + if (wh_dentry) { + h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */ + IMustLock(h_dir); + AuDebugOn(au_h_iptr(dir, bindex) != h_dir); + bwh = au_dbwh(dentry); + h_path.dentry = wh_dentry; + h_path.mnt = au_sbr_mnt(dir->i_sb, bindex); + err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, + dentry); + if (unlikely(err)) + goto out; + } + + inode = au_new_inode(dentry, /*must_new*/1); + if (!IS_ERR(inode)) { + d_instantiate(dentry, inode); + dir = dentry->d_parent->d_inode; /* dir inode is locked */ + IMustLock(dir); + if (au_ibstart(dir) == au_dbstart(dentry)) + au_cpup_attr_timesizes(dir); + dir->i_version++; + return 0; /* success */ + } + + err = PTR_ERR(inode); + if (!wh_dentry) + goto out; + + /* revert */ + /* dir inode is locked */ + wh = au_wh_create(dentry, bwh, wh_dentry->d_parent); + rerr = PTR_ERR(wh); + if (IS_ERR(wh)) { + AuIOErr("%.*s reverting whiteout failed(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + err = -EIO; + } else + dput(wh); + +out: + return err; +} + +/* + * simple tests for the adding inode operations. + * following the checks in vfs, plus the parent-child relationship. + */ +int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent, int isdir) +{ + int err; + umode_t h_mode; + struct dentry *h_dentry; + struct inode *h_inode; + + err = -ENAMETOOLONG; + if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) + goto out; + + h_dentry = au_h_dptr(dentry, bindex); + h_inode = h_dentry->d_inode; + if (!dentry->d_inode) { + err = -EEXIST; + if (unlikely(h_inode)) + goto out; + } else { + /* rename(2) case */ + err = -EIO; + if (unlikely(!h_inode || !h_inode->i_nlink)) + goto out; + + h_mode = h_inode->i_mode; + if (!isdir) { + err = -EISDIR; + if (unlikely(S_ISDIR(h_mode))) + goto out; + } else if (unlikely(!S_ISDIR(h_mode))) { + err = -ENOTDIR; + goto out; + } + } + + err = 0; + /* expected parent dir is locked */ + if (unlikely(h_parent != h_dentry->d_parent)) + err = -EIO; + +out: + AuTraceErr(err); + return err; +} + +/* + * initial procedure of adding a new entry. + * prepare writable branch and the parent dir, lock it, + * and lookup whiteout for the new entry. + */ +static struct dentry* +lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt, + struct dentry *src_dentry, struct au_pin *pin, + struct au_wr_dir_args *wr_dir_args) +{ + struct dentry *wh_dentry, *h_parent; + struct super_block *sb; + struct au_branch *br; + int err; + unsigned int udba; + aufs_bindex_t bcpup; + + AuDbg("%.*s\n", AuDLNPair(dentry)); + + err = au_wr_dir(dentry, src_dentry, wr_dir_args); + bcpup = err; + wh_dentry = ERR_PTR(err); + if (unlikely(err < 0)) + goto out; + + sb = dentry->d_sb; + udba = au_opt_udba(sb); + err = au_pin(pin, dentry, bcpup, udba, + AuPin_DI_LOCKED | AuPin_MNT_WRITE); + wh_dentry = ERR_PTR(err); + if (unlikely(err)) + goto out; + + h_parent = au_pinned_h_parent(pin); + if (udba != AuOpt_UDBA_NONE + && au_dbstart(dentry) == bcpup) + err = au_may_add(dentry, bcpup, h_parent, + au_ftest_wrdir(wr_dir_args->flags, ISDIR)); + else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN)) + err = -ENAMETOOLONG; + wh_dentry = ERR_PTR(err); + if (unlikely(err)) + goto out_unpin; + + br = au_sbr(sb, bcpup); + if (dt) { + struct path tmp = { + .dentry = h_parent, + .mnt = br->br_mnt + }; + au_dtime_store(dt, au_pinned_parent(pin), &tmp); + } + + wh_dentry = NULL; + if (bcpup != au_dbwh(dentry)) + goto out; /* success */ + + wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br); + +out_unpin: + if (IS_ERR(wh_dentry)) + au_unpin(pin); +out: + return wh_dentry; +} + +/* ---------------------------------------------------------------------- */ + +enum { Mknod, Symlink, Creat }; +struct simple_arg { + int type; + union { + struct { + int mode; + struct nameidata *nd; + } c; + struct { + const char *symname; + } s; + struct { + int mode; + dev_t dev; + } m; + } u; +}; + +static int add_simple(struct inode *dir, struct dentry *dentry, + struct simple_arg *arg) +{ + int err; + aufs_bindex_t bstart; + unsigned char created; + struct au_dtime dt; + struct au_pin pin; + struct path h_path; + struct dentry *wh_dentry, *parent; + struct inode *h_dir; + struct au_wr_dir_args wr_dir_args = { + .force_btgt = -1, + .flags = AuWrDir_ADD_ENTRY + }; + + AuDbg("%.*s\n", AuDLNPair(dentry)); + IMustLock(dir); + + parent = dentry->d_parent; /* dir inode is locked */ + aufs_read_lock(dentry, AuLock_DW); + di_write_lock_parent(parent); + wh_dentry = lock_hdir_lkup_wh(dentry, &dt, /*src_dentry*/NULL, &pin, + &wr_dir_args); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out; + + bstart = au_dbstart(dentry); + h_path.dentry = au_h_dptr(dentry, bstart); + h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart); + h_dir = au_pinned_h_dir(&pin); + switch (arg->type) { + case Creat: + err = vfsub_create(h_dir, &h_path, arg->u.c.mode); + break; + case Symlink: + err = vfsub_symlink(h_dir, &h_path, arg->u.s.symname); + break; + case Mknod: + err = vfsub_mknod(h_dir, &h_path, arg->u.m.mode, arg->u.m.dev); + break; + default: + BUG(); + } + created = !err; + if (!err) + err = epilog(dir, bstart, wh_dentry, dentry); + + /* revert */ + if (unlikely(created && err && h_path.dentry->d_inode)) { + int rerr; + rerr = vfsub_unlink(h_dir, &h_path, /*force*/0); + if (rerr) { + AuIOErr("%.*s revert failure(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + err = -EIO; + } + au_dtime_revert(&dt); + d_drop(dentry); + } + + au_unpin(&pin); + dput(wh_dentry); + +out: + if (unlikely(err)) { + au_update_dbstart(dentry); + d_drop(dentry); + } + di_write_unlock(parent); + aufs_read_unlock(dentry, AuLock_DW); + return err; +} + +int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +{ + struct simple_arg arg = { + .type = Mknod, + .u.m = { + .mode = mode, + .dev = dev + } + }; + return add_simple(dir, dentry, &arg); +} + +int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) +{ + struct simple_arg arg = { + .type = Symlink, + .u.s.symname = symname + }; + return add_simple(dir, dentry, &arg); +} + +int aufs_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +{ + struct simple_arg arg = { + .type = Creat, + .u.c = { + .mode = mode, + .nd = nd + } + }; + return add_simple(dir, dentry, &arg); +} + +/* ---------------------------------------------------------------------- */ + +struct au_link_args { + aufs_bindex_t bdst, bsrc; + struct au_pin pin; + struct path h_path; + struct dentry *src_parent, *parent; +}; + +static int au_cpup_before_link(struct dentry *src_dentry, + struct au_link_args *a) +{ + int err; + struct dentry *h_src_dentry; + struct mutex *h_mtx; + struct file *h_file; + + di_read_lock_parent(a->src_parent, AuLock_IR); + err = au_test_and_cpup_dirs(src_dentry, a->bdst); + if (unlikely(err)) + goto out; + + h_src_dentry = au_h_dptr(src_dentry, a->bsrc); + h_mtx = &h_src_dentry->d_inode->i_mutex; + err = au_pin(&a->pin, src_dentry, a->bdst, + au_opt_udba(src_dentry->d_sb), + AuPin_DI_LOCKED | AuPin_MNT_WRITE); + if (unlikely(err)) + goto out; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + h_file = au_h_open_pre(src_dentry, a->bsrc); + if (IS_ERR(h_file)) { + err = PTR_ERR(h_file); + h_file = NULL; + } else + err = au_sio_cpup_simple(src_dentry, a->bdst, a->bsrc, + AuCpup_DTIME /* | AuCpup_KEEPLINO */); + mutex_unlock(h_mtx); + au_h_open_post(src_dentry, a->bsrc, h_file); + au_unpin(&a->pin); + +out: + di_read_unlock(a->src_parent, AuLock_IR); + return err; +} + +static int au_cpup_or_link(struct dentry *src_dentry, struct au_link_args *a) +{ + int err; + unsigned char plink; + struct inode *h_inode, *inode; + struct dentry *h_src_dentry; + struct super_block *sb; + struct file *h_file; + + plink = 0; + h_inode = NULL; + sb = src_dentry->d_sb; + inode = src_dentry->d_inode; + if (au_ibstart(inode) <= a->bdst) + h_inode = au_h_iptr(inode, a->bdst); + if (!h_inode || !h_inode->i_nlink) { + /* copyup src_dentry as the name of dentry. */ + au_set_dbstart(src_dentry, a->bdst); + au_set_h_dptr(src_dentry, a->bdst, dget(a->h_path.dentry)); + h_inode = au_h_dptr(src_dentry, a->bsrc)->d_inode; + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + h_file = au_h_open_pre(src_dentry, a->bsrc); + if (IS_ERR(h_file)) { + err = PTR_ERR(h_file); + h_file = NULL; + } else + err = au_sio_cpup_single(src_dentry, a->bdst, a->bsrc, + -1, AuCpup_KEEPLINO, + a->parent); + mutex_unlock(&h_inode->i_mutex); + au_h_open_post(src_dentry, a->bsrc, h_file); + au_set_h_dptr(src_dentry, a->bdst, NULL); + au_set_dbstart(src_dentry, a->bsrc); + } else { + /* the inode of src_dentry already exists on a.bdst branch */ + h_src_dentry = d_find_alias(h_inode); + if (!h_src_dentry && au_plink_test(inode)) { + plink = 1; + h_src_dentry = au_plink_lkup(inode, a->bdst); + err = PTR_ERR(h_src_dentry); + if (IS_ERR(h_src_dentry)) + goto out; + + if (unlikely(!h_src_dentry->d_inode)) { + dput(h_src_dentry); + h_src_dentry = NULL; + } + + } + if (h_src_dentry) { + err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), + &a->h_path); + dput(h_src_dentry); + } else { + AuIOErr("no dentry found for hi%lu on b%d\n", + h_inode->i_ino, a->bdst); + err = -EIO; + } + } + + if (!err && !plink) + au_plink_append(inode, a->bdst, a->h_path.dentry); + +out: + return err; +} + +int aufs_link(struct dentry *src_dentry, struct inode *dir, + struct dentry *dentry) +{ + int err, rerr; + struct au_dtime dt; + struct au_link_args *a; + struct dentry *wh_dentry, *h_src_dentry; + struct inode *inode; + struct super_block *sb; + struct au_wr_dir_args wr_dir_args = { + /* .force_btgt = -1, */ + .flags = AuWrDir_ADD_ENTRY + }; + + IMustLock(dir); + inode = src_dentry->d_inode; + IMustLock(inode); + + err = -ENOENT; + if (unlikely(!inode->i_nlink)) + goto out; + + err = -ENOMEM; + a = kzalloc(sizeof(*a), GFP_NOFS); + if (unlikely(!a)) + goto out; + + a->parent = dentry->d_parent; /* dir inode is locked */ + err = aufs_read_and_write_lock2(dentry, src_dentry, AuLock_NOPLM); + if (unlikely(err)) + goto out_kfree; + + a->src_parent = dget_parent(src_dentry); + wr_dir_args.force_btgt = au_dbstart(src_dentry); + + di_write_lock_parent(a->parent); + wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt); + wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin, + &wr_dir_args); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out_unlock; + + err = 0; + sb = dentry->d_sb; + a->bdst = au_dbstart(dentry); + a->h_path.dentry = au_h_dptr(dentry, a->bdst); + a->h_path.mnt = au_sbr_mnt(sb, a->bdst); + a->bsrc = au_dbstart(src_dentry); + if (au_opt_test(au_mntflags(sb), PLINK)) { + if (a->bdst < a->bsrc + /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) + err = au_cpup_or_link(src_dentry, a); + else { + h_src_dentry = au_h_dptr(src_dentry, a->bdst); + err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin), + &a->h_path); + } + } else { + /* + * copyup src_dentry to the branch we process, + * and then link(2) to it. + */ + if (a->bdst < a->bsrc + /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) { + au_unpin(&a->pin); + di_write_unlock(a->parent); + err = au_cpup_before_link(src_dentry, a); + di_write_lock_parent(a->parent); + if (!err) + err = au_pin(&a->pin, dentry, a->bdst, + au_opt_udba(sb), + AuPin_DI_LOCKED | AuPin_MNT_WRITE); + if (unlikely(err)) + goto out_wh; + } + if (!err) { + h_src_dentry = au_h_dptr(src_dentry, a->bdst); + err = -ENOENT; + if (h_src_dentry && h_src_dentry->d_inode) + err = vfsub_link(h_src_dentry, + au_pinned_h_dir(&a->pin), + &a->h_path); + } + } + if (unlikely(err)) + goto out_unpin; + + if (wh_dentry) { + a->h_path.dentry = wh_dentry; + err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path, + dentry); + if (unlikely(err)) + goto out_revert; + } + + dir->i_version++; + if (au_ibstart(dir) == au_dbstart(dentry)) + au_cpup_attr_timesizes(dir); + inc_nlink(inode); + inode->i_ctime = dir->i_ctime; + if (!d_unhashed(a->h_path.dentry)) + d_instantiate(dentry, au_igrab(inode)); + else + /* some filesystem calls d_drop() */ + d_drop(dentry); + goto out_unpin; /* success */ + +out_revert: + rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path, /*force*/0); + if (!rerr) + goto out_dt; + AuIOErr("%.*s reverting failed(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + err = -EIO; +out_dt: + d_drop(dentry); + au_dtime_revert(&dt); +out_unpin: + au_unpin(&a->pin); +out_wh: + dput(wh_dentry); +out_unlock: + if (unlikely(err)) { + au_update_dbstart(dentry); + d_drop(dentry); + } + di_write_unlock(a->parent); + dput(a->src_parent); + aufs_read_and_write_unlock2(dentry, src_dentry); +out_kfree: + kfree(a); +out: + return err; +} + +int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode) +{ + int err, rerr; + aufs_bindex_t bindex; + unsigned char diropq; + struct path h_path; + struct dentry *wh_dentry, *parent, *opq_dentry; + struct mutex *h_mtx; + struct super_block *sb; + struct { + struct au_pin pin; + struct au_dtime dt; + } *a; /* reduce the stack usage */ + struct au_wr_dir_args wr_dir_args = { + .force_btgt = -1, + .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR + }; + + IMustLock(dir); + + err = -ENOMEM; + a = kmalloc(sizeof(*a), GFP_NOFS); + if (unlikely(!a)) + goto out; + + aufs_read_lock(dentry, AuLock_DW); + parent = dentry->d_parent; /* dir inode is locked */ + di_write_lock_parent(parent); + wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL, + &a->pin, &wr_dir_args); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out_free; + + sb = dentry->d_sb; + bindex = au_dbstart(dentry); + h_path.dentry = au_h_dptr(dentry, bindex); + h_path.mnt = au_sbr_mnt(sb, bindex); + err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode); + if (unlikely(err)) + goto out_unlock; + + /* make the dir opaque */ + diropq = 0; + h_mtx = &h_path.dentry->d_inode->i_mutex; + if (wh_dentry + || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) { + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + opq_dentry = au_diropq_create(dentry, bindex); + mutex_unlock(h_mtx); + err = PTR_ERR(opq_dentry); + if (IS_ERR(opq_dentry)) + goto out_dir; + dput(opq_dentry); + diropq = 1; + } + + err = epilog(dir, bindex, wh_dentry, dentry); + if (!err) { + inc_nlink(dir); + goto out_unlock; /* success */ + } + + /* revert */ + if (diropq) { + AuLabel(revert opq); + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + rerr = au_diropq_remove(dentry, bindex); + mutex_unlock(h_mtx); + if (rerr) { + AuIOErr("%.*s reverting diropq failed(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + err = -EIO; + } + } + +out_dir: + AuLabel(revert dir); + rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path); + if (rerr) { + AuIOErr("%.*s reverting dir failed(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + err = -EIO; + } + d_drop(dentry); + au_dtime_revert(&a->dt); +out_unlock: + au_unpin(&a->pin); + dput(wh_dentry); +out_free: + if (unlikely(err)) { + au_update_dbstart(dentry); + d_drop(dentry); + } + di_write_unlock(parent); + aufs_read_unlock(dentry, AuLock_DW); + kfree(a); +out: + return err; +} --- linux-2.6.37.orig/ubuntu/aufs/i_op_del.c +++ linux-2.6.37/ubuntu/aufs/i_op_del.c @@ -0,0 +1,472 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode operations (del entry) + */ + +#include "aufs.h" + +/* + * decide if a new whiteout for @dentry is necessary or not. + * when it is necessary, prepare the parent dir for the upper branch whose + * branch index is @bcpup for creation. the actual creation of the whiteout will + * be done by caller. + * return value: + * 0: wh is unnecessary + * plus: wh is necessary + * minus: error + */ +int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup) +{ + int need_wh, err; + aufs_bindex_t bstart; + struct super_block *sb; + + sb = dentry->d_sb; + bstart = au_dbstart(dentry); + if (*bcpup < 0) { + *bcpup = bstart; + if (au_test_ro(sb, bstart, dentry->d_inode)) { + err = AuWbrCopyup(au_sbi(sb), dentry); + *bcpup = err; + if (unlikely(err < 0)) + goto out; + } + } else + AuDebugOn(bstart < *bcpup + || au_test_ro(sb, *bcpup, dentry->d_inode)); + AuDbg("bcpup %d, bstart %d\n", *bcpup, bstart); + + if (*bcpup != bstart) { + err = au_cpup_dirs(dentry, *bcpup); + if (unlikely(err)) + goto out; + need_wh = 1; + } else { + aufs_bindex_t old_bend, new_bend, bdiropq = -1; + + old_bend = au_dbend(dentry); + if (isdir) { + bdiropq = au_dbdiropq(dentry); + au_set_dbdiropq(dentry, -1); + } + need_wh = au_lkup_dentry(dentry, bstart + 1, /*type*/0, + /*nd*/NULL); + err = need_wh; + if (isdir) + au_set_dbdiropq(dentry, bdiropq); + if (unlikely(err < 0)) + goto out; + new_bend = au_dbend(dentry); + if (!need_wh && old_bend != new_bend) { + au_set_h_dptr(dentry, new_bend, NULL); + au_set_dbend(dentry, old_bend); + } + } + AuDbg("need_wh %d\n", need_wh); + err = need_wh; + +out: + return err; +} + +/* + * simple tests for the del-entry operations. + * following the checks in vfs, plus the parent-child relationship. + */ +int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent, int isdir) +{ + int err; + umode_t h_mode; + struct dentry *h_dentry, *h_latest; + struct inode *h_inode; + + h_dentry = au_h_dptr(dentry, bindex); + h_inode = h_dentry->d_inode; + if (dentry->d_inode) { + err = -ENOENT; + if (unlikely(!h_inode || !h_inode->i_nlink)) + goto out; + + h_mode = h_inode->i_mode; + if (!isdir) { + err = -EISDIR; + if (unlikely(S_ISDIR(h_mode))) + goto out; + } else if (unlikely(!S_ISDIR(h_mode))) { + err = -ENOTDIR; + goto out; + } + } else { + /* rename(2) case */ + err = -EIO; + if (unlikely(h_inode)) + goto out; + } + + err = -ENOENT; + /* expected parent dir is locked */ + if (unlikely(h_parent != h_dentry->d_parent)) + goto out; + err = 0; + + /* + * rmdir a dir may break the consistency on some filesystem. + * let's try heavy test. + */ + err = -EACCES; + if (unlikely(au_test_h_perm(h_parent->d_inode, MAY_EXEC | MAY_WRITE))) + goto out; + + h_latest = au_sio_lkup_one(&dentry->d_name, h_parent, + au_sbr(dentry->d_sb, bindex)); + err = -EIO; + if (IS_ERR(h_latest)) + goto out; + if (h_latest == h_dentry) + err = 0; + dput(h_latest); + +out: + return err; +} + +/* + * decide the branch where we operate for @dentry. the branch index will be set + * @rbcpup. after diciding it, 'pin' it and store the timestamps of the parent + * dir for reverting. + * when a new whiteout is necessary, create it. + */ +static struct dentry* +lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup, + struct au_dtime *dt, struct au_pin *pin) +{ + struct dentry *wh_dentry; + struct super_block *sb; + struct path h_path; + int err, need_wh; + unsigned int udba; + aufs_bindex_t bcpup; + + need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup); + wh_dentry = ERR_PTR(need_wh); + if (unlikely(need_wh < 0)) + goto out; + + sb = dentry->d_sb; + udba = au_opt_udba(sb); + bcpup = *rbcpup; + err = au_pin(pin, dentry, bcpup, udba, + AuPin_DI_LOCKED | AuPin_MNT_WRITE); + wh_dentry = ERR_PTR(err); + if (unlikely(err)) + goto out; + + h_path.dentry = au_pinned_h_parent(pin); + if (udba != AuOpt_UDBA_NONE + && au_dbstart(dentry) == bcpup) { + err = au_may_del(dentry, bcpup, h_path.dentry, isdir); + wh_dentry = ERR_PTR(err); + if (unlikely(err)) + goto out_unpin; + } + + h_path.mnt = au_sbr_mnt(sb, bcpup); + au_dtime_store(dt, au_pinned_parent(pin), &h_path); + wh_dentry = NULL; + if (!need_wh) + goto out; /* success, no need to create whiteout */ + + wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry); + if (IS_ERR(wh_dentry)) + goto out_unpin; + + /* returns with the parent is locked and wh_dentry is dget-ed */ + goto out; /* success */ + +out_unpin: + au_unpin(pin); +out: + return wh_dentry; +} + +/* + * when removing a dir, rename it to a unique temporary whiteout-ed name first + * in order to be revertible and save time for removing many child whiteouts + * under the dir. + * returns 1 when there are too many child whiteout and caller should remove + * them asynchronously. returns 0 when the number of children is enough small to + * remove now or the branch fs is a remote fs. + * otherwise return an error. + */ +static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex, + struct au_nhash *whlist, struct inode *dir) +{ + int rmdir_later, err, dirwh; + struct dentry *h_dentry; + struct super_block *sb; + + sb = dentry->d_sb; + SiMustAnyLock(sb); + h_dentry = au_h_dptr(dentry, bindex); + err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex)); + if (unlikely(err)) + goto out; + + /* stop monitoring */ + au_hn_free(au_hi(dentry->d_inode, bindex)); + + if (!au_test_fs_remote(h_dentry->d_sb)) { + dirwh = au_sbi(sb)->si_dirwh; + rmdir_later = (dirwh <= 1); + if (!rmdir_later) + rmdir_later = au_nhash_test_longer_wh(whlist, bindex, + dirwh); + if (rmdir_later) + return rmdir_later; + } + + err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist); + if (unlikely(err)) { + AuIOErr("rmdir %.*s, b%d failed, %d. ignored\n", + AuDLNPair(h_dentry), bindex, err); + err = 0; + } + +out: + AuTraceErr(err); + return err; +} + +/* + * final procedure for deleting a entry. + * maintain dentry and iattr. + */ +static void epilog(struct inode *dir, struct dentry *dentry, + aufs_bindex_t bindex) +{ + struct inode *inode; + + inode = dentry->d_inode; + d_drop(dentry); + inode->i_ctime = dir->i_ctime; + + if (atomic_read(&dentry->d_count) == 1) { + au_set_h_dptr(dentry, au_dbstart(dentry), NULL); + au_update_dbstart(dentry); + } + if (au_ibstart(dir) == bindex) + au_cpup_attr_timesizes(dir); + dir->i_version++; +} + +/* + * when an error happened, remove the created whiteout and revert everything. + */ +static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex, + aufs_bindex_t bwh, struct dentry *wh_dentry, + struct dentry *dentry, struct au_dtime *dt) +{ + int rerr; + struct path h_path = { + .dentry = wh_dentry, + .mnt = au_sbr_mnt(dir->i_sb, bindex) + }; + + rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry); + if (!rerr) { + au_set_dbwh(dentry, bwh); + au_dtime_revert(dt); + return 0; + } + + AuIOErr("%.*s reverting whiteout failed(%d, %d)\n", + AuDLNPair(dentry), err, rerr); + return -EIO; +} + +/* ---------------------------------------------------------------------- */ + +int aufs_unlink(struct inode *dir, struct dentry *dentry) +{ + int err; + aufs_bindex_t bwh, bindex, bstart; + struct au_dtime dt; + struct au_pin pin; + struct path h_path; + struct inode *inode, *h_dir; + struct dentry *parent, *wh_dentry; + + IMustLock(dir); + inode = dentry->d_inode; + if (unlikely(!inode)) + return -ENOENT; /* possible? */ + IMustLock(inode); + + aufs_read_lock(dentry, AuLock_DW); + parent = dentry->d_parent; /* dir inode is locked */ + di_write_lock_parent(parent); + + bstart = au_dbstart(dentry); + bwh = au_dbwh(dentry); + bindex = -1; + wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &dt, &pin); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out; + + h_path.mnt = au_sbr_mnt(dentry->d_sb, bstart); + h_path.dentry = au_h_dptr(dentry, bstart); + dget(h_path.dentry); + if (bindex == bstart) { + h_dir = au_pinned_h_dir(&pin); + err = vfsub_unlink(h_dir, &h_path, /*force*/0); + } else { + /* dir inode is locked */ + h_dir = wh_dentry->d_parent->d_inode; + IMustLock(h_dir); + err = 0; + } + + if (!err) { + vfsub_drop_nlink(inode); + epilog(dir, dentry, bindex); + + /* update target timestamps */ + if (bindex == bstart) { + vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/ + inode->i_ctime = h_path.dentry->d_inode->i_ctime; + } else + /* todo: this timestamp may be reverted later */ + inode->i_ctime = h_dir->i_ctime; + goto out_unlock; /* success */ + } + + /* revert */ + if (wh_dentry) { + int rerr; + + rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt); + if (rerr) + err = rerr; + } + +out_unlock: + au_unpin(&pin); + dput(wh_dentry); + dput(h_path.dentry); +out: + di_write_unlock(parent); + aufs_read_unlock(dentry, AuLock_DW); + return err; +} + +int aufs_rmdir(struct inode *dir, struct dentry *dentry) +{ + int err, rmdir_later; + aufs_bindex_t bwh, bindex, bstart; + struct au_dtime dt; + struct au_pin pin; + struct inode *inode; + struct dentry *parent, *wh_dentry, *h_dentry; + struct au_whtmp_rmdir *args; + + IMustLock(dir); + inode = dentry->d_inode; + err = -ENOENT; /* possible? */ + if (unlikely(!inode)) + goto out; + IMustLock(inode); + + aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH); + err = -ENOMEM; + args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS); + if (unlikely(!args)) + goto out_unlock; + + parent = dentry->d_parent; /* dir inode is locked */ + di_write_lock_parent(parent); + err = au_test_empty(dentry, &args->whlist); + if (unlikely(err)) + goto out_args; + + bstart = au_dbstart(dentry); + bwh = au_dbwh(dentry); + bindex = -1; + wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &dt, &pin); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out_args; + + h_dentry = au_h_dptr(dentry, bstart); + dget(h_dentry); + rmdir_later = 0; + if (bindex == bstart) { + err = renwh_and_rmdir(dentry, bstart, &args->whlist, dir); + if (err > 0) { + rmdir_later = err; + err = 0; + } + } else { + /* stop monitoring */ + au_hn_free(au_hi(inode, bstart)); + + /* dir inode is locked */ + IMustLock(wh_dentry->d_parent->d_inode); + err = 0; + } + + if (!err) { + clear_nlink(inode); + au_set_dbdiropq(dentry, -1); + epilog(dir, dentry, bindex); + + if (rmdir_later) { + au_whtmp_kick_rmdir(dir, bstart, h_dentry, args); + args = NULL; + } + + goto out_unpin; /* success */ + } + + /* revert */ + AuLabel(revert); + if (wh_dentry) { + int rerr; + + rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry, &dt); + if (rerr) + err = rerr; + } + +out_unpin: + au_unpin(&pin); + dput(wh_dentry); + dput(h_dentry); +out_args: + di_write_unlock(parent); + if (args) + au_whtmp_rmdir_free(args); +out_unlock: + aufs_read_unlock(dentry, AuLock_DW); +out: + AuTraceErr(err); + return err; +} --- linux-2.6.37.orig/ubuntu/aufs/i_op_ren.c +++ linux-2.6.37/ubuntu/aufs/i_op_ren.c @@ -0,0 +1,982 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode operation (rename entry) + * todo: this is crazy monster + */ + +#include "aufs.h" + +enum { AuSRC, AuDST, AuSrcDst }; +enum { AuPARENT, AuCHILD, AuParentChild }; + +#define AuRen_ISDIR 1 +#define AuRen_ISSAMEDIR (1 << 1) +#define AuRen_WHSRC (1 << 2) +#define AuRen_WHDST (1 << 3) +#define AuRen_MNT_WRITE (1 << 4) +#define AuRen_DT_DSTDIR (1 << 5) +#define AuRen_DIROPQ (1 << 6) +#define AuRen_CPUP (1 << 7) +#define au_ftest_ren(flags, name) ((flags) & AuRen_##name) +#define au_fset_ren(flags, name) \ + do { (flags) |= AuRen_##name; } while (0) +#define au_fclr_ren(flags, name) \ + do { (flags) &= ~AuRen_##name; } while (0) + +struct au_ren_args { + struct { + struct dentry *dentry, *h_dentry, *parent, *h_parent, + *wh_dentry; + struct inode *dir, *inode; + struct au_hinode *hdir; + struct au_dtime dt[AuParentChild]; + aufs_bindex_t bstart; + } sd[AuSrcDst]; + +#define src_dentry sd[AuSRC].dentry +#define src_dir sd[AuSRC].dir +#define src_inode sd[AuSRC].inode +#define src_h_dentry sd[AuSRC].h_dentry +#define src_parent sd[AuSRC].parent +#define src_h_parent sd[AuSRC].h_parent +#define src_wh_dentry sd[AuSRC].wh_dentry +#define src_hdir sd[AuSRC].hdir +#define src_h_dir sd[AuSRC].hdir->hi_inode +#define src_dt sd[AuSRC].dt +#define src_bstart sd[AuSRC].bstart + +#define dst_dentry sd[AuDST].dentry +#define dst_dir sd[AuDST].dir +#define dst_inode sd[AuDST].inode +#define dst_h_dentry sd[AuDST].h_dentry +#define dst_parent sd[AuDST].parent +#define dst_h_parent sd[AuDST].h_parent +#define dst_wh_dentry sd[AuDST].wh_dentry +#define dst_hdir sd[AuDST].hdir +#define dst_h_dir sd[AuDST].hdir->hi_inode +#define dst_dt sd[AuDST].dt +#define dst_bstart sd[AuDST].bstart + + struct dentry *h_trap; + struct au_branch *br; + struct au_hinode *src_hinode; + struct path h_path; + struct au_nhash whlist; + aufs_bindex_t btgt; + + unsigned int flags; + + struct au_whtmp_rmdir *thargs; + struct dentry *h_dst; +}; + +/* ---------------------------------------------------------------------- */ + +/* + * functions for reverting. + * when an error happened in a single rename systemcall, we should revert + * everything as if nothing happend. + * we don't need to revert the copied-up/down the parent dir since they are + * harmless. + */ + +#define RevertFailure(fmt, ...) do { \ + AuIOErr("revert failure: " fmt " (%d, %d)\n", \ + ##__VA_ARGS__, err, rerr); \ + err = -EIO; \ +} while (0) + +static void au_ren_rev_diropq(int err, struct au_ren_args *a) +{ + int rerr; + + au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD); + rerr = au_diropq_remove(a->src_dentry, a->btgt); + au_hn_imtx_unlock(a->src_hinode); + if (rerr) + RevertFailure("remove diropq %.*s", AuDLNPair(a->src_dentry)); +} + +static void au_ren_rev_rename(int err, struct au_ren_args *a) +{ + int rerr; + + a->h_path.dentry = au_lkup_one(&a->src_dentry->d_name, a->src_h_parent, + a->br, /*nd*/NULL); + rerr = PTR_ERR(a->h_path.dentry); + if (IS_ERR(a->h_path.dentry)) { + RevertFailure("au_lkup_one %.*s", AuDLNPair(a->src_dentry)); + return; + } + + rerr = vfsub_rename(a->dst_h_dir, + au_h_dptr(a->src_dentry, a->btgt), + a->src_h_dir, &a->h_path); + d_drop(a->h_path.dentry); + dput(a->h_path.dentry); + /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */ + if (rerr) + RevertFailure("rename %.*s", AuDLNPair(a->src_dentry)); +} + +static void au_ren_rev_cpup(int err, struct au_ren_args *a) +{ + int rerr; + + a->h_path.dentry = a->dst_h_dentry; + rerr = vfsub_unlink(a->dst_h_dir, &a->h_path, /*force*/0); + au_set_h_dptr(a->src_dentry, a->btgt, NULL); + au_set_dbstart(a->src_dentry, a->src_bstart); + if (rerr) + RevertFailure("unlink %.*s", AuDLNPair(a->dst_h_dentry)); +} + +static void au_ren_rev_whtmp(int err, struct au_ren_args *a) +{ + int rerr; + + a->h_path.dentry = au_lkup_one(&a->dst_dentry->d_name, a->dst_h_parent, + a->br, /*nd*/NULL); + rerr = PTR_ERR(a->h_path.dentry); + if (IS_ERR(a->h_path.dentry)) { + RevertFailure("lookup %.*s", AuDLNPair(a->dst_dentry)); + return; + } + if (a->h_path.dentry->d_inode) { + d_drop(a->h_path.dentry); + dput(a->h_path.dentry); + return; + } + + rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path); + d_drop(a->h_path.dentry); + dput(a->h_path.dentry); + if (!rerr) + au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst)); + else + RevertFailure("rename %.*s", AuDLNPair(a->h_dst)); +} + +static void au_ren_rev_whsrc(int err, struct au_ren_args *a) +{ + int rerr; + + a->h_path.dentry = a->src_wh_dentry; + rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry); + if (rerr) + RevertFailure("unlink %.*s", AuDLNPair(a->src_wh_dentry)); +} + +static void au_ren_rev_drop(struct au_ren_args *a) +{ + struct dentry *d, *h_d; + int i; + aufs_bindex_t bend, bindex; + + for (i = 0; i < AuSrcDst; i++) { + d = a->sd[i].dentry; + d_drop(d); + bend = au_dbend(d); + for (bindex = au_dbstart(d); bindex <= bend; bindex++) { + h_d = au_h_dptr(d, bindex); + if (h_d) + d_drop(h_d); + } + } + + au_update_dbstart(a->dst_dentry); + if (a->thargs) + d_drop(a->h_dst); +} +#undef RevertFailure + +/* ---------------------------------------------------------------------- */ + +/* + * when we have to copyup the renaming entry, do it with the rename-target name + * in order to minimize the cost (the later actual rename is unnecessary). + * otherwise rename it on the target branch. + */ +static int au_ren_or_cpup(struct au_ren_args *a) +{ + int err; + struct dentry *d; + + d = a->src_dentry; + if (au_dbstart(d) == a->btgt) { + a->h_path.dentry = a->dst_h_dentry; + if (au_ftest_ren(a->flags, DIROPQ) + && au_dbdiropq(d) == a->btgt) + au_fclr_ren(a->flags, DIROPQ); + AuDebugOn(au_dbstart(d) != a->btgt); + err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt), + a->dst_h_dir, &a->h_path); + } else { + struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex; + struct file *h_file; + + au_fset_ren(a->flags, CPUP); + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + au_set_dbstart(d, a->btgt); + au_set_h_dptr(d, a->btgt, dget(a->dst_h_dentry)); + h_file = au_h_open_pre(d, a->src_bstart); + if (IS_ERR(h_file)) { + err = PTR_ERR(h_file); + h_file = NULL; + } else + err = au_sio_cpup_single(d, a->btgt, a->src_bstart, -1, + !AuCpup_DTIME, a->dst_parent); + mutex_unlock(h_mtx); + au_h_open_post(d, a->src_bstart, h_file); + if (!err) { + d = a->dst_dentry; + au_set_h_dptr(d, a->btgt, NULL); + au_update_dbstart(d); + } else { + au_set_h_dptr(d, a->btgt, NULL); + au_set_dbstart(d, a->src_bstart); + } + } + + return err; +} + +/* cf. aufs_rmdir() */ +static int au_ren_del_whtmp(struct au_ren_args *a) +{ + int err; + struct inode *dir; + + dir = a->dst_dir; + SiMustAnyLock(dir->i_sb); + if (!au_nhash_test_longer_wh(&a->whlist, a->btgt, + au_sbi(dir->i_sb)->si_dirwh) + || au_test_fs_remote(a->h_dst->d_sb)) { + err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist); + if (unlikely(err)) + pr_warning("failed removing whtmp dir %.*s (%d), " + "ignored.\n", AuDLNPair(a->h_dst), err); + } else { + au_nhash_wh_free(&a->thargs->whlist); + a->thargs->whlist = a->whlist; + a->whlist.nh_num = 0; + au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs); + dput(a->h_dst); + a->thargs = NULL; + } + + return 0; +} + +/* make it 'opaque' dir. */ +static int au_ren_diropq(struct au_ren_args *a) +{ + int err; + struct dentry *diropq; + + err = 0; + a->src_hinode = au_hi(a->src_inode, a->btgt); + au_hn_imtx_lock_nested(a->src_hinode, AuLsc_I_CHILD); + diropq = au_diropq_create(a->src_dentry, a->btgt); + au_hn_imtx_unlock(a->src_hinode); + if (IS_ERR(diropq)) + err = PTR_ERR(diropq); + dput(diropq); + + return err; +} + +static int do_rename(struct au_ren_args *a) +{ + int err; + struct dentry *d, *h_d; + + /* prepare workqueue args for asynchronous rmdir */ + h_d = a->dst_h_dentry; + if (au_ftest_ren(a->flags, ISDIR) && h_d->d_inode) { + err = -ENOMEM; + a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb, GFP_NOFS); + if (unlikely(!a->thargs)) + goto out; + a->h_dst = dget(h_d); + } + + /* create whiteout for src_dentry */ + if (au_ftest_ren(a->flags, WHSRC)) { + a->src_wh_dentry + = au_wh_create(a->src_dentry, a->btgt, a->src_h_parent); + err = PTR_ERR(a->src_wh_dentry); + if (IS_ERR(a->src_wh_dentry)) + goto out_thargs; + } + + /* lookup whiteout for dentry */ + if (au_ftest_ren(a->flags, WHDST)) { + h_d = au_wh_lkup(a->dst_h_parent, &a->dst_dentry->d_name, + a->br); + err = PTR_ERR(h_d); + if (IS_ERR(h_d)) + goto out_whsrc; + if (!h_d->d_inode) + dput(h_d); + else + a->dst_wh_dentry = h_d; + } + + /* rename dentry to tmpwh */ + if (a->thargs) { + err = au_whtmp_ren(a->dst_h_dentry, a->br); + if (unlikely(err)) + goto out_whdst; + + d = a->dst_dentry; + au_set_h_dptr(d, a->btgt, NULL); + err = au_lkup_neg(d, a->btgt); + if (unlikely(err)) + goto out_whtmp; + a->dst_h_dentry = au_h_dptr(d, a->btgt); + } + + /* cpup src */ + if (a->dst_h_dentry->d_inode && a->src_bstart != a->btgt) { + struct mutex *h_mtx = &a->src_h_dentry->d_inode->i_mutex; + struct file *h_file; + + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + AuDebugOn(au_dbstart(a->src_dentry) != a->src_bstart); + h_file = au_h_open_pre(a->src_dentry, a->src_bstart); + if (IS_ERR(h_file)) { + err = PTR_ERR(h_file); + h_file = NULL; + } else + err = au_sio_cpup_simple(a->src_dentry, a->btgt, -1, + !AuCpup_DTIME); + mutex_unlock(h_mtx); + au_h_open_post(a->src_dentry, a->src_bstart, h_file); + if (unlikely(err)) + goto out_whtmp; + } + + /* rename by vfs_rename or cpup */ + d = a->dst_dentry; + if (au_ftest_ren(a->flags, ISDIR) + && (a->dst_wh_dentry + || au_dbdiropq(d) == a->btgt + /* hide the lower to keep xino */ + || a->btgt < au_dbend(d) + || au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ))) + au_fset_ren(a->flags, DIROPQ); + err = au_ren_or_cpup(a); + if (unlikely(err)) + /* leave the copied-up one */ + goto out_whtmp; + + /* make dir opaque */ + if (au_ftest_ren(a->flags, DIROPQ)) { + err = au_ren_diropq(a); + if (unlikely(err)) + goto out_rename; + } + + /* update target timestamps */ + AuDebugOn(au_dbstart(a->src_dentry) != a->btgt); + a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt); + vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/ + a->src_inode->i_ctime = a->h_path.dentry->d_inode->i_ctime; + + /* remove whiteout for dentry */ + if (a->dst_wh_dentry) { + a->h_path.dentry = a->dst_wh_dentry; + err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path, + a->dst_dentry); + if (unlikely(err)) + goto out_diropq; + } + + /* remove whtmp */ + if (a->thargs) + au_ren_del_whtmp(a); /* ignore this error */ + + err = 0; + goto out_success; + +out_diropq: + if (au_ftest_ren(a->flags, DIROPQ)) + au_ren_rev_diropq(err, a); +out_rename: + if (!au_ftest_ren(a->flags, CPUP)) + au_ren_rev_rename(err, a); + else + au_ren_rev_cpup(err, a); +out_whtmp: + if (a->thargs) + au_ren_rev_whtmp(err, a); +out_whdst: + dput(a->dst_wh_dentry); + a->dst_wh_dentry = NULL; +out_whsrc: + if (a->src_wh_dentry) + au_ren_rev_whsrc(err, a); + au_ren_rev_drop(a); +out_success: + dput(a->src_wh_dentry); + dput(a->dst_wh_dentry); +out_thargs: + if (a->thargs) { + dput(a->h_dst); + au_whtmp_rmdir_free(a->thargs); + a->thargs = NULL; + } +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * test if @dentry dir can be rename destination or not. + * success means, it is a logically empty dir. + */ +static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist) +{ + return au_test_empty(dentry, whlist); +} + +/* + * test if @dentry dir can be rename source or not. + * if it can, return 0 and @children is filled. + * success means, + * - it is a logically empty dir. + * - or, it exists on writable branch and has no children including whiteouts + * on the lower branch. + */ +static int may_rename_srcdir(struct dentry *dentry, aufs_bindex_t btgt) +{ + int err; + unsigned int rdhash; + aufs_bindex_t bstart; + + bstart = au_dbstart(dentry); + if (bstart != btgt) { + struct au_nhash whlist; + + SiMustAnyLock(dentry->d_sb); + rdhash = au_sbi(dentry->d_sb)->si_rdhash; + if (!rdhash) + rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, + dentry)); + err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS); + if (unlikely(err)) + goto out; + err = au_test_empty(dentry, &whlist); + au_nhash_wh_free(&whlist); + goto out; + } + + if (bstart == au_dbtaildir(dentry)) + return 0; /* success */ + + err = au_test_empty_lower(dentry); + +out: + if (err == -ENOTEMPTY) { + AuWarn1("renaming dir who has child(ren) on multiple branches," + " is not supported\n"); + err = -EXDEV; + } + return err; +} + +/* side effect: sets whlist and h_dentry */ +static int au_ren_may_dir(struct au_ren_args *a) +{ + int err; + unsigned int rdhash; + struct dentry *d; + + d = a->dst_dentry; + SiMustAnyLock(d->d_sb); + + err = 0; + if (au_ftest_ren(a->flags, ISDIR) && a->dst_inode) { + rdhash = au_sbi(d->d_sb)->si_rdhash; + if (!rdhash) + rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d)); + err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS); + if (unlikely(err)) + goto out; + + au_set_dbstart(d, a->dst_bstart); + err = may_rename_dstdir(d, &a->whlist); + au_set_dbstart(d, a->btgt); + } + a->dst_h_dentry = au_h_dptr(d, au_dbstart(d)); + if (unlikely(err)) + goto out; + + d = a->src_dentry; + a->src_h_dentry = au_h_dptr(d, au_dbstart(d)); + if (au_ftest_ren(a->flags, ISDIR)) { + err = may_rename_srcdir(d, a->btgt); + if (unlikely(err)) { + au_nhash_wh_free(&a->whlist); + a->whlist.nh_num = 0; + } + } +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * simple tests for rename. + * following the checks in vfs, plus the parent-child relationship. + */ +static int au_may_ren(struct au_ren_args *a) +{ + int err, isdir; + struct inode *h_inode; + + if (a->src_bstart == a->btgt) { + err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent, + au_ftest_ren(a->flags, ISDIR)); + if (unlikely(err)) + goto out; + err = -EINVAL; + if (unlikely(a->src_h_dentry == a->h_trap)) + goto out; + } + + err = 0; + if (a->dst_bstart != a->btgt) + goto out; + + err = -EIO; + h_inode = a->dst_h_dentry->d_inode; + isdir = !!au_ftest_ren(a->flags, ISDIR); + if (!a->dst_dentry->d_inode) { + if (unlikely(h_inode)) + goto out; + err = au_may_add(a->dst_dentry, a->btgt, a->dst_h_parent, + isdir); + } else { + if (unlikely(!h_inode || !h_inode->i_nlink)) + goto out; + err = au_may_del(a->dst_dentry, a->btgt, a->dst_h_parent, + isdir); + if (unlikely(err)) + goto out; + err = -ENOTEMPTY; + if (unlikely(a->dst_h_dentry == a->h_trap)) + goto out; + err = 0; + } + +out: + if (unlikely(err == -ENOENT || err == -EEXIST)) + err = -EIO; + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * locking order + * (VFS) + * - src_dir and dir by lock_rename() + * - inode if exitsts + * (aufs) + * - lock all + * + src_dentry and dentry by aufs_read_and_write_lock2() which calls, + * + si_read_lock + * + di_write_lock2_child() + * + di_write_lock_child() + * + ii_write_lock_child() + * + di_write_lock_child2() + * + ii_write_lock_child2() + * + src_parent and parent + * + di_write_lock_parent() + * + ii_write_lock_parent() + * + di_write_lock_parent2() + * + ii_write_lock_parent2() + * + lower src_dir and dir by vfsub_lock_rename() + * + verify the every relationships between child and parent. if any + * of them failed, unlock all and return -EBUSY. + */ +static void au_ren_unlock(struct au_ren_args *a) +{ + struct super_block *sb; + + sb = a->dst_dentry->d_sb; + if (au_ftest_ren(a->flags, MNT_WRITE)) + mnt_drop_write(a->br->br_mnt); + vfsub_unlock_rename(a->src_h_parent, a->src_hdir, + a->dst_h_parent, a->dst_hdir); +} + +static int au_ren_lock(struct au_ren_args *a) +{ + int err; + unsigned int udba; + + err = 0; + a->src_h_parent = au_h_dptr(a->src_parent, a->btgt); + a->src_hdir = au_hi(a->src_dir, a->btgt); + a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt); + a->dst_hdir = au_hi(a->dst_dir, a->btgt); + a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir, + a->dst_h_parent, a->dst_hdir); + udba = au_opt_udba(a->src_dentry->d_sb); + if (unlikely(a->src_hdir->hi_inode != a->src_h_parent->d_inode + || a->dst_hdir->hi_inode != a->dst_h_parent->d_inode)) + err = au_busy_or_stale(); + if (!err && au_dbstart(a->src_dentry) == a->btgt) + err = au_h_verify(a->src_h_dentry, udba, + a->src_h_parent->d_inode, a->src_h_parent, + a->br); + if (!err && au_dbstart(a->dst_dentry) == a->btgt) + err = au_h_verify(a->dst_h_dentry, udba, + a->dst_h_parent->d_inode, a->dst_h_parent, + a->br); + if (!err) { + err = mnt_want_write(a->br->br_mnt); + if (unlikely(err)) + goto out_unlock; + au_fset_ren(a->flags, MNT_WRITE); + goto out; /* success */ + } + + err = au_busy_or_stale(); + +out_unlock: + au_ren_unlock(a); +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +static void au_ren_refresh_dir(struct au_ren_args *a) +{ + struct inode *dir; + + dir = a->dst_dir; + dir->i_version++; + if (au_ftest_ren(a->flags, ISDIR)) { + /* is this updating defined in POSIX? */ + au_cpup_attr_timesizes(a->src_inode); + au_cpup_attr_nlink(dir, /*force*/1); + if (a->dst_inode) { + clear_nlink(a->dst_inode); + au_cpup_attr_timesizes(a->dst_inode); + } + } + if (au_ibstart(dir) == a->btgt) + au_cpup_attr_timesizes(dir); + + if (au_ftest_ren(a->flags, ISSAMEDIR)) + return; + + dir = a->src_dir; + dir->i_version++; + if (au_ftest_ren(a->flags, ISDIR)) + au_cpup_attr_nlink(dir, /*force*/1); + if (au_ibstart(dir) == a->btgt) + au_cpup_attr_timesizes(dir); +} + +static void au_ren_refresh(struct au_ren_args *a) +{ + aufs_bindex_t bend, bindex; + struct dentry *d, *h_d; + struct inode *i, *h_i; + struct super_block *sb; + + d = a->src_dentry; + au_set_dbwh(d, -1); + bend = au_dbend(d); + for (bindex = a->btgt + 1; bindex <= bend; bindex++) { + h_d = au_h_dptr(d, bindex); + if (h_d) + au_set_h_dptr(d, bindex, NULL); + } + au_set_dbend(d, a->btgt); + + sb = d->d_sb; + i = a->src_inode; + if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i)) + return; /* success */ + + bend = au_ibend(i); + for (bindex = a->btgt + 1; bindex <= bend; bindex++) { + h_i = au_h_iptr(i, bindex); + if (h_i) { + au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0); + /* ignore this error */ + au_set_h_iptr(i, bindex, NULL, 0); + } + } + au_set_ibend(i, a->btgt); +} + +/* ---------------------------------------------------------------------- */ + +/* mainly for link(2) and rename(2) */ +int au_wbr(struct dentry *dentry, aufs_bindex_t btgt) +{ + aufs_bindex_t bdiropq, bwh; + struct dentry *parent; + struct au_branch *br; + + parent = dentry->d_parent; + IMustLock(parent->d_inode); /* dir is locked */ + + bdiropq = au_dbdiropq(parent); + bwh = au_dbwh(dentry); + br = au_sbr(dentry->d_sb, btgt); + if (au_br_rdonly(br) + || (0 <= bdiropq && bdiropq < btgt) + || (0 <= bwh && bwh < btgt)) + btgt = -1; + + AuDbg("btgt %d\n", btgt); + return btgt; +} + +/* sets src_bstart, dst_bstart and btgt */ +static int au_ren_wbr(struct au_ren_args *a) +{ + int err; + struct au_wr_dir_args wr_dir_args = { + /* .force_btgt = -1, */ + .flags = AuWrDir_ADD_ENTRY + }; + + a->src_bstart = au_dbstart(a->src_dentry); + a->dst_bstart = au_dbstart(a->dst_dentry); + if (au_ftest_ren(a->flags, ISDIR)) + au_fset_wrdir(wr_dir_args.flags, ISDIR); + wr_dir_args.force_btgt = a->src_bstart; + if (a->dst_inode && a->dst_bstart < a->src_bstart) + wr_dir_args.force_btgt = a->dst_bstart; + wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt); + err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args); + a->btgt = err; + + return err; +} + +static void au_ren_dt(struct au_ren_args *a) +{ + a->h_path.dentry = a->src_h_parent; + au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path); + if (!au_ftest_ren(a->flags, ISSAMEDIR)) { + a->h_path.dentry = a->dst_h_parent; + au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path); + } + + au_fclr_ren(a->flags, DT_DSTDIR); + if (!au_ftest_ren(a->flags, ISDIR)) + return; + + a->h_path.dentry = a->src_h_dentry; + au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path); + if (a->dst_h_dentry->d_inode) { + au_fset_ren(a->flags, DT_DSTDIR); + a->h_path.dentry = a->dst_h_dentry; + au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path); + } +} + +static void au_ren_rev_dt(int err, struct au_ren_args *a) +{ + struct dentry *h_d; + struct mutex *h_mtx; + + au_dtime_revert(a->src_dt + AuPARENT); + if (!au_ftest_ren(a->flags, ISSAMEDIR)) + au_dtime_revert(a->dst_dt + AuPARENT); + + if (au_ftest_ren(a->flags, ISDIR) && err != -EIO) { + h_d = a->src_dt[AuCHILD].dt_h_path.dentry; + h_mtx = &h_d->d_inode->i_mutex; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + au_dtime_revert(a->src_dt + AuCHILD); + mutex_unlock(h_mtx); + + if (au_ftest_ren(a->flags, DT_DSTDIR)) { + h_d = a->dst_dt[AuCHILD].dt_h_path.dentry; + h_mtx = &h_d->d_inode->i_mutex; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD); + au_dtime_revert(a->dst_dt + AuCHILD); + mutex_unlock(h_mtx); + } + } +} + +/* ---------------------------------------------------------------------- */ + +int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, + struct inode *_dst_dir, struct dentry *_dst_dentry) +{ + int err, flags; + /* reduce stack space */ + struct au_ren_args *a; + + AuDbg("%.*s, %.*s\n", AuDLNPair(_src_dentry), AuDLNPair(_dst_dentry)); + IMustLock(_src_dir); + IMustLock(_dst_dir); + + err = -ENOMEM; + BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE); + a = kzalloc(sizeof(*a), GFP_NOFS); + if (unlikely(!a)) + goto out; + + a->src_dir = _src_dir; + a->src_dentry = _src_dentry; + a->src_inode = a->src_dentry->d_inode; + a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */ + a->dst_dir = _dst_dir; + a->dst_dentry = _dst_dentry; + a->dst_inode = a->dst_dentry->d_inode; + a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */ + if (a->dst_inode) { + IMustLock(a->dst_inode); + au_igrab(a->dst_inode); + } + + err = -ENOTDIR; + flags = AuLock_FLUSH | AuLock_NOPLM; + if (S_ISDIR(a->src_inode->i_mode)) { + au_fset_ren(a->flags, ISDIR); + if (unlikely(a->dst_inode && !S_ISDIR(a->dst_inode->i_mode))) + goto out_free; + err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry, + AuLock_DIR | flags); + } else + err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry, + flags); + if (unlikely(err)) + goto out_free; + + au_fset_ren(a->flags, ISSAMEDIR); /* temporary */ + di_write_lock_parent(a->dst_parent); + + /* which branch we process */ + err = au_ren_wbr(a); + if (unlikely(err < 0)) + goto out_unlock; + a->br = au_sbr(a->dst_dentry->d_sb, a->btgt); + a->h_path.mnt = a->br->br_mnt; + + /* are they available to be renamed */ + err = au_ren_may_dir(a); + if (unlikely(err)) + goto out_children; + + /* prepare the writable parent dir on the same branch */ + if (a->dst_bstart == a->btgt) { + au_fset_ren(a->flags, WHDST); + } else { + err = au_cpup_dirs(a->dst_dentry, a->btgt); + if (unlikely(err)) + goto out_children; + } + + if (a->src_dir != a->dst_dir) { + /* + * this temporary unlock is safe, + * because both dir->i_mutex are locked. + */ + di_write_unlock(a->dst_parent); + di_write_lock_parent(a->src_parent); + err = au_wr_dir_need_wh(a->src_dentry, + au_ftest_ren(a->flags, ISDIR), + &a->btgt); + di_write_unlock(a->src_parent); + di_write_lock2_parent(a->src_parent, a->dst_parent, /*isdir*/1); + au_fclr_ren(a->flags, ISSAMEDIR); + } else + err = au_wr_dir_need_wh(a->src_dentry, + au_ftest_ren(a->flags, ISDIR), + &a->btgt); + if (unlikely(err < 0)) + goto out_children; + if (err) + au_fset_ren(a->flags, WHSRC); + + /* lock them all */ + err = au_ren_lock(a); + if (unlikely(err)) + goto out_children; + + if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE)) + err = au_may_ren(a); + else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN)) + err = -ENAMETOOLONG; + if (unlikely(err)) + goto out_hdir; + + /* store timestamps to be revertible */ + au_ren_dt(a); + + /* here we go */ + err = do_rename(a); + if (unlikely(err)) + goto out_dt; + + /* update dir attributes */ + au_ren_refresh_dir(a); + + /* dput/iput all lower dentries */ + au_ren_refresh(a); + + goto out_hdir; /* success */ + +out_dt: + au_ren_rev_dt(err, a); +out_hdir: + au_ren_unlock(a); +out_children: + au_nhash_wh_free(&a->whlist); +out_unlock: + if (unlikely(err && au_ftest_ren(a->flags, ISDIR))) { + au_update_dbstart(a->dst_dentry); + d_drop(a->dst_dentry); + } + if (!err) + d_move(a->src_dentry, a->dst_dentry); + if (au_ftest_ren(a->flags, ISSAMEDIR)) + di_write_unlock(a->dst_parent); + else + di_write_unlock2(a->src_parent, a->dst_parent); + aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry); +out_free: + iput(a->dst_inode); + if (a->thargs) + au_whtmp_rmdir_free(a->thargs); + kfree(a); +out: + AuTraceErr(err); + return err; +} --- linux-2.6.37.orig/ubuntu/aufs/iinfo.c +++ linux-2.6.37/ubuntu/aufs/iinfo.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode private data + */ + +#include "aufs.h" + +struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex) +{ + struct inode *h_inode; + + IiMustAnyLock(inode); + + h_inode = au_ii(inode)->ii_hinode[0 + bindex].hi_inode; + AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); + return h_inode; +} + +/* todo: hard/soft set? */ +void au_hiput(struct au_hinode *hinode) +{ + au_hn_free(hinode); + dput(hinode->hi_whdentry); + iput(hinode->hi_inode); +} + +unsigned int au_hi_flags(struct inode *inode, int isdir) +{ + unsigned int flags; + const unsigned int mnt_flags = au_mntflags(inode->i_sb); + + flags = 0; + if (au_opt_test(mnt_flags, XINO)) + au_fset_hi(flags, XINO); + if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY)) + au_fset_hi(flags, HNOTIFY); + return flags; +} + +void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, + struct inode *h_inode, unsigned int flags) +{ + struct au_hinode *hinode; + struct inode *hi; + struct au_iinfo *iinfo = au_ii(inode); + + IiMustWriteLock(inode); + + hinode = iinfo->ii_hinode + bindex; + hi = hinode->hi_inode; + AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0); + + if (hi) + au_hiput(hinode); + hinode->hi_inode = h_inode; + if (h_inode) { + int err; + struct super_block *sb = inode->i_sb; + struct au_branch *br; + + if (bindex == iinfo->ii_bstart) + au_cpup_igen(inode, h_inode); + br = au_sbr(sb, bindex); + hinode->hi_id = br->br_id; + if (au_ftest_hi(flags, XINO)) { + err = au_xino_write(sb, bindex, h_inode->i_ino, + inode->i_ino); + if (unlikely(err)) + AuIOErr1("failed au_xino_write() %d\n", err); + } + + if (au_ftest_hi(flags, HNOTIFY) + && au_br_hnotifyable(br->br_perm)) { + err = au_hn_alloc(hinode, inode, h_inode); + if (unlikely(err)) + AuIOErr1("au_hn_alloc() %d\n", err); + } + } +} + +void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, + struct dentry *h_wh) +{ + struct au_hinode *hinode; + + IiMustWriteLock(inode); + + hinode = au_ii(inode)->ii_hinode + bindex; + AuDebugOn(hinode->hi_whdentry); + hinode->hi_whdentry = h_wh; +} + +void au_update_iigen(struct inode *inode) +{ + atomic_set(&au_ii(inode)->ii_generation, au_sigen(inode->i_sb)); + /* smp_mb(); */ /* atomic_set */ +} + +/* it may be called at remount time, too */ +void au_update_ibrange(struct inode *inode, int do_put_zero) +{ + struct au_iinfo *iinfo; + + iinfo = au_ii(inode); + if (!iinfo || iinfo->ii_bstart < 0) + return; + + IiMustWriteLock(inode); + + if (do_put_zero) { + aufs_bindex_t bindex; + + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; + bindex++) { + struct inode *h_i; + + h_i = iinfo->ii_hinode[0 + bindex].hi_inode; + if (h_i && !h_i->i_nlink) + au_set_h_iptr(inode, bindex, NULL, 0); + } + } + + iinfo->ii_bstart = -1; + while (++iinfo->ii_bstart <= iinfo->ii_bend) + if (iinfo->ii_hinode[0 + iinfo->ii_bstart].hi_inode) + break; + if (iinfo->ii_bstart > iinfo->ii_bend) { + iinfo->ii_bstart = -1; + iinfo->ii_bend = -1; + return; + } + + iinfo->ii_bend++; + while (0 <= --iinfo->ii_bend) + if (iinfo->ii_hinode[0 + iinfo->ii_bend].hi_inode) + break; + AuDebugOn(iinfo->ii_bstart > iinfo->ii_bend || iinfo->ii_bend < 0); +} + +/* ---------------------------------------------------------------------- */ + +void au_icntnr_init_once(void *_c) +{ + struct au_icntnr *c = _c; + struct au_iinfo *iinfo = &c->iinfo; + static struct lock_class_key aufs_ii; + + au_rw_init(&iinfo->ii_rwsem); + au_rw_class(&iinfo->ii_rwsem, &aufs_ii); + inode_init_once(&c->vfs_inode); +} + +int au_iinfo_init(struct inode *inode) +{ + struct au_iinfo *iinfo; + struct super_block *sb; + int nbr, i; + + sb = inode->i_sb; + iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); + nbr = au_sbend(sb) + 1; + if (unlikely(nbr <= 0)) + nbr = 1; + iinfo->ii_hinode = kcalloc(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS); + if (iinfo->ii_hinode) { + au_ninodes_inc(sb); + for (i = 0; i < nbr; i++) + iinfo->ii_hinode[i].hi_id = -1; + + atomic_set(&iinfo->ii_generation, au_sigen(sb)); + /* smp_mb(); */ /* atomic_set */ + iinfo->ii_bstart = -1; + iinfo->ii_bend = -1; + iinfo->ii_vdir = NULL; + return 0; + } + return -ENOMEM; +} + +int au_ii_realloc(struct au_iinfo *iinfo, int nbr) +{ + int err, sz; + struct au_hinode *hip; + + AuRwMustWriteLock(&iinfo->ii_rwsem); + + err = -ENOMEM; + sz = sizeof(*hip) * (iinfo->ii_bend + 1); + if (!sz) + sz = sizeof(*hip); + hip = au_kzrealloc(iinfo->ii_hinode, sz, sizeof(*hip) * nbr, GFP_NOFS); + if (hip) { + iinfo->ii_hinode = hip; + err = 0; + } + + return err; +} + +void au_iinfo_fin(struct inode *inode) +{ + struct au_iinfo *iinfo; + struct au_hinode *hi; + struct super_block *sb; + aufs_bindex_t bindex, bend; + const unsigned char unlinked = !inode->i_nlink; + + iinfo = au_ii(inode); + /* bad_inode case */ + if (!iinfo) + return; + + sb = inode->i_sb; + au_ninodes_dec(sb); + if (si_pid_test(sb)) + au_xino_delete_inode(inode, unlinked); + else { + /* + * it is safe to hide the dependency between sbinfo and + * sb->s_umount. + */ + lockdep_off(); + si_noflush_read_lock(sb); + au_xino_delete_inode(inode, unlinked); + si_read_unlock(sb); + lockdep_on(); + } + + if (iinfo->ii_vdir) + au_vdir_free(iinfo->ii_vdir); + + bindex = iinfo->ii_bstart; + if (bindex >= 0) { + hi = iinfo->ii_hinode + bindex; + bend = iinfo->ii_bend; + while (bindex++ <= bend) { + if (hi->hi_inode) + au_hiput(hi); + hi++; + } + } + kfree(iinfo->ii_hinode); + AuRwDestroy(&iinfo->ii_rwsem); +} --- linux-2.6.37.orig/ubuntu/aufs/inode.c +++ linux-2.6.37/ubuntu/aufs/inode.c @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode functions + */ + +#include "aufs.h" + +struct inode *au_igrab(struct inode *inode) +{ + if (inode) { + AuDebugOn(!atomic_read(&inode->i_count)); + ihold(inode); + } + return inode; +} + +static void au_refresh_hinode_attr(struct inode *inode, int do_version) +{ + au_cpup_attr_all(inode, /*force*/0); + au_update_iigen(inode); + if (do_version) + inode->i_version++; +} + +int au_refresh_hinode_self(struct inode *inode, int do_attr) +{ + int err, e; + aufs_bindex_t bindex, new_bindex; + unsigned char update; + struct au_hinode *p, *q, tmp; + struct super_block *sb; + struct au_iinfo *iinfo; + + IiMustWriteLock(inode); + + update = 0; + sb = inode->i_sb; + iinfo = au_ii(inode); + err = au_ii_realloc(iinfo, au_sbend(sb) + 1); + if (unlikely(err)) + goto out; + + p = iinfo->ii_hinode + iinfo->ii_bstart; + err = 0; + for (bindex = iinfo->ii_bstart; bindex <= iinfo->ii_bend; + bindex++, p++) { + if (!p->hi_inode) + continue; + + new_bindex = au_br_index(sb, p->hi_id); + if (new_bindex == bindex) + continue; + + if (new_bindex < 0) { + update = 1; + au_hiput(p); + p->hi_inode = NULL; + continue; + } + + if (new_bindex < iinfo->ii_bstart) + iinfo->ii_bstart = new_bindex; + if (iinfo->ii_bend < new_bindex) + iinfo->ii_bend = new_bindex; + /* swap two lower inode, and loop again */ + q = iinfo->ii_hinode + new_bindex; + tmp = *q; + *q = *p; + *p = tmp; + if (tmp.hi_inode) { + bindex--; + p--; + } + } + au_update_ibrange(inode, /*do_put_zero*/0); + e = au_dy_irefresh(inode); + if (unlikely(e && !err)) + err = e; + if (do_attr) + au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode)); + +out: + return err; +} + +int au_refresh_hinode(struct inode *inode, struct dentry *dentry) +{ + int err, e; + unsigned int flags; + aufs_bindex_t bindex, bend; + unsigned char isdir, update; + struct au_hinode *p; + struct au_iinfo *iinfo; + + err = au_refresh_hinode_self(inode, /*do_attr*/0); + if (unlikely(err)) + goto out; + + update = 0; + iinfo = au_ii(inode); + p = iinfo->ii_hinode + iinfo->ii_bstart; + isdir = S_ISDIR(inode->i_mode); + flags = au_hi_flags(inode, isdir); + bend = au_dbend(dentry); + for (bindex = au_dbstart(dentry); bindex <= bend; bindex++) { + struct inode *h_i; + struct dentry *h_d; + + h_d = au_h_dptr(dentry, bindex); + if (!h_d || !h_d->d_inode) + continue; + + if (iinfo->ii_bstart <= bindex && bindex <= iinfo->ii_bend) { + h_i = au_h_iptr(inode, bindex); + if (h_i) { + if (h_i == h_d->d_inode) + continue; + err = -EIO; + break; + } + } + if (bindex < iinfo->ii_bstart) + iinfo->ii_bstart = bindex; + if (iinfo->ii_bend < bindex) + iinfo->ii_bend = bindex; + au_set_h_iptr(inode, bindex, au_igrab(h_d->d_inode), flags); + update = 1; + } + au_update_ibrange(inode, /*do_put_zero*/0); + e = au_dy_irefresh(inode); + if (unlikely(e && !err)) + err = e; + au_refresh_hinode_attr(inode, update && isdir); + +out: + AuTraceErr(err); + return err; +} + +static int set_inode(struct inode *inode, struct dentry *dentry) +{ + int err; + unsigned int flags; + umode_t mode; + aufs_bindex_t bindex, bstart, btail; + unsigned char isdir; + struct dentry *h_dentry; + struct inode *h_inode; + struct au_iinfo *iinfo; + + IiMustWriteLock(inode); + + err = 0; + isdir = 0; + bstart = au_dbstart(dentry); + h_inode = au_h_dptr(dentry, bstart)->d_inode; + mode = h_inode->i_mode; + switch (mode & S_IFMT) { + case S_IFREG: + btail = au_dbtail(dentry); + inode->i_op = &aufs_iop; + inode->i_fop = &aufs_file_fop; + err = au_dy_iaop(inode, bstart, h_inode); + if (unlikely(err)) + goto out; + break; + case S_IFDIR: + isdir = 1; + btail = au_dbtaildir(dentry); + inode->i_op = &aufs_dir_iop; + inode->i_fop = &aufs_dir_fop; + break; + case S_IFLNK: + btail = au_dbtail(dentry); + inode->i_op = &aufs_symlink_iop; + break; + case S_IFBLK: + case S_IFCHR: + case S_IFIFO: + case S_IFSOCK: + btail = au_dbtail(dentry); + inode->i_op = &aufs_iop; + au_init_special_fop(inode, mode, h_inode->i_rdev); + break; + default: + AuIOErr("Unknown file type 0%o\n", mode); + err = -EIO; + goto out; + } + + /* do not set hnotify for whiteouted dirs (SHWH mode) */ + flags = au_hi_flags(inode, isdir); + if (au_opt_test(au_mntflags(dentry->d_sb), SHWH) + && au_ftest_hi(flags, HNOTIFY) + && dentry->d_name.len > AUFS_WH_PFX_LEN + && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) + au_fclr_hi(flags, HNOTIFY); + iinfo = au_ii(inode); + iinfo->ii_bstart = bstart; + iinfo->ii_bend = btail; + for (bindex = bstart; bindex <= btail; bindex++) { + h_dentry = au_h_dptr(dentry, bindex); + if (h_dentry) + au_set_h_iptr(inode, bindex, + au_igrab(h_dentry->d_inode), flags); + } + au_cpup_attr_all(inode, /*force*/1); + +out: + return err; +} + +/* successful returns with iinfo write_locked */ +static int reval_inode(struct inode *inode, struct dentry *dentry, int *matched) +{ + int err; + aufs_bindex_t bindex, bend; + struct inode *h_inode, *h_dinode; + + *matched = 0; + + /* + * before this function, if aufs got any iinfo lock, it must be only + * one, the parent dir. + * it can happen by UDBA and the obsoleted inode number. + */ + err = -EIO; + if (unlikely(inode->i_ino == parent_ino(dentry))) + goto out; + + err = 0; + ii_write_lock_new_child(inode); + h_dinode = au_h_dptr(dentry, au_dbstart(dentry))->d_inode; + bend = au_ibend(inode); + for (bindex = au_ibstart(inode); bindex <= bend; bindex++) { + h_inode = au_h_iptr(inode, bindex); + if (h_inode && h_inode == h_dinode) { + *matched = 1; + err = 0; + if (au_iigen(inode) != au_digen(dentry)) + err = au_refresh_hinode(inode, dentry); + break; + } + } + + if (unlikely(err)) + ii_write_unlock(inode); +out: + return err; +} + +int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + unsigned int d_type, ino_t *ino) +{ + int err; + struct mutex *mtx; + + /* prevent hardlinked inode number from race condition */ + mtx = NULL; + if (d_type != DT_DIR) { + mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx; + mutex_lock(mtx); + } + err = au_xino_read(sb, bindex, h_ino, ino); + if (unlikely(err)) + goto out; + + if (!*ino) { + err = -EIO; + *ino = au_xino_new_ino(sb); + if (unlikely(!*ino)) + goto out; + err = au_xino_write(sb, bindex, h_ino, *ino); + if (unlikely(err)) + goto out; + } + +out: + if (mtx) + mutex_unlock(mtx); + return err; +} + +/* successful returns with iinfo write_locked */ +/* todo: return with unlocked? */ +struct inode *au_new_inode(struct dentry *dentry, int must_new) +{ + struct inode *inode, *h_inode; + struct dentry *h_dentry; + struct super_block *sb; + struct mutex *mtx; + ino_t h_ino, ino; + int err, match; + aufs_bindex_t bstart; + + sb = dentry->d_sb; + bstart = au_dbstart(dentry); + h_dentry = au_h_dptr(dentry, bstart); + h_inode = h_dentry->d_inode; + h_ino = h_inode->i_ino; + + /* + * stop 'race'-ing between hardlinks under different + * parents. + */ + mtx = NULL; + if (!S_ISDIR(h_inode->i_mode)) + mtx = &au_sbr(sb, bstart)->br_xino.xi_nondir_mtx; + +new_ino: + if (mtx) + mutex_lock(mtx); + err = au_xino_read(sb, bstart, h_ino, &ino); + inode = ERR_PTR(err); + if (unlikely(err)) + goto out; + + if (!ino) { + ino = au_xino_new_ino(sb); + if (unlikely(!ino)) { + inode = ERR_PTR(-EIO); + goto out; + } + } + + AuDbg("i%lu\n", (unsigned long)ino); + inode = au_iget_locked(sb, ino); + err = PTR_ERR(inode); + if (IS_ERR(inode)) + goto out; + + AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); + if (inode->i_state & I_NEW) { + ii_write_lock_new_child(inode); + err = set_inode(inode, dentry); + if (!err) { + unlock_new_inode(inode); + goto out; /* success */ + } + + ii_write_unlock(inode); + iget_failed(inode); + goto out_err; + } else if (!must_new) { + /* + * horrible race condition between lookup, readdir and copyup + * (or something). + */ + if (mtx) + mutex_unlock(mtx); + err = reval_inode(inode, dentry, &match); + if (!err) { + mtx = NULL; + goto out; /* success */ + } else if (match) { + mtx = NULL; + goto out_iput; + } else if (mtx) + mutex_lock(mtx); + } + + if (unlikely(au_test_fs_unique_ino(h_dentry->d_inode))) + AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir," + " b%d, %s, %.*s, hi%lu, i%lu.\n", + bstart, au_sbtype(h_dentry->d_sb), AuDLNPair(dentry), + (unsigned long)h_ino, (unsigned long)ino); + ino = 0; + err = au_xino_write(sb, bstart, h_ino, /*ino*/0); + if (!err) { + iput(inode); + if (mtx) + mutex_unlock(mtx); + goto new_ino; + } + +out_iput: + iput(inode); +out_err: + inode = ERR_PTR(err); +out: + if (mtx) + mutex_unlock(mtx); + return inode; +} + +/* ---------------------------------------------------------------------- */ + +int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, + struct inode *inode) +{ + int err; + + err = au_br_rdonly(au_sbr(sb, bindex)); + + /* pseudo-link after flushed may happen out of bounds */ + if (!err + && inode + && au_ibstart(inode) <= bindex + && bindex <= au_ibend(inode)) { + /* + * permission check is unnecessary since vfsub routine + * will be called later + */ + struct inode *hi = au_h_iptr(inode, bindex); + if (hi) + err = IS_IMMUTABLE(hi) ? -EROFS : 0; + } + + return err; +} + +int au_test_h_perm(struct inode *h_inode, int mask) +{ + if (!current_fsuid()) + return 0; + return inode_permission(h_inode, mask); +} + +int au_test_h_perm_sio(struct inode *h_inode, int mask) +{ + if (au_test_nfs(h_inode->i_sb) + && (mask & MAY_WRITE) + && S_ISDIR(h_inode->i_mode)) + mask |= MAY_READ; /* force permission check */ + return au_test_h_perm(h_inode, mask); +} --- linux-2.6.37.orig/ubuntu/aufs/inode.h +++ linux-2.6.37/ubuntu/aufs/inode.h @@ -0,0 +1,518 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * inode operations + */ + +#ifndef __AUFS_INODE_H__ +#define __AUFS_INODE_H__ + +#ifdef __KERNEL__ + +#include +#include +#include +#include "rwsem.h" + +struct vfsmount; + +struct au_hnotify { +#ifdef CONFIG_AUFS_HNOTIFY +#ifdef CONFIG_AUFS_HFSNOTIFY + /* never use fsnotify_add_vfsmount_mark() */ + struct fsnotify_mark hn_mark; + int hn_mark_dead; +#endif + struct inode *hn_aufs_inode; /* no get/put */ +#endif +} ____cacheline_aligned_in_smp; + +struct au_hinode { + struct inode *hi_inode; + aufs_bindex_t hi_id; +#ifdef CONFIG_AUFS_HNOTIFY + struct au_hnotify *hi_notify; +#endif + + /* reference to the copied-up whiteout with get/put */ + struct dentry *hi_whdentry; +}; + +struct au_vdir; +struct au_iinfo { + atomic_t ii_generation; + struct super_block *ii_hsb1; /* no get/put */ + + struct au_rwsem ii_rwsem; + aufs_bindex_t ii_bstart, ii_bend; + __u32 ii_higen; + struct au_hinode *ii_hinode; + struct au_vdir *ii_vdir; +}; + +struct au_icntnr { + struct au_iinfo iinfo; + struct inode vfs_inode; +} ____cacheline_aligned_in_smp; + +/* au_pin flags */ +#define AuPin_DI_LOCKED 1 +#define AuPin_MNT_WRITE (1 << 1) +#define au_ftest_pin(flags, name) ((flags) & AuPin_##name) +#define au_fset_pin(flags, name) \ + do { (flags) |= AuPin_##name; } while (0) +#define au_fclr_pin(flags, name) \ + do { (flags) &= ~AuPin_##name; } while (0) + +struct au_pin { + /* input */ + struct dentry *dentry; + unsigned int udba; + unsigned char lsc_di, lsc_hi, flags; + aufs_bindex_t bindex; + + /* output */ + struct dentry *parent; + struct au_hinode *hdir; + struct vfsmount *h_mnt; +}; + +/* ---------------------------------------------------------------------- */ + +static inline struct au_iinfo *au_ii(struct inode *inode) +{ + struct au_iinfo *iinfo; + + iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo); + if (iinfo->ii_hinode) + return iinfo; + return NULL; /* debugging bad_inode case */ +} + +/* ---------------------------------------------------------------------- */ + +/* inode.c */ +struct inode *au_igrab(struct inode *inode); +int au_refresh_hinode_self(struct inode *inode, int do_attr); +int au_refresh_hinode(struct inode *inode, struct dentry *dentry); +int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + unsigned int d_type, ino_t *ino); +struct inode *au_new_inode(struct dentry *dentry, int must_new); +int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, + struct inode *inode); +int au_test_h_perm(struct inode *h_inode, int mask); +int au_test_h_perm_sio(struct inode *h_inode, int mask); + +static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, + ino_t h_ino, unsigned int d_type, ino_t *ino) +{ +#ifdef CONFIG_AUFS_SHWH + return au_ino(sb, bindex, h_ino, d_type, ino); +#else + return 0; +#endif +} + +/* i_op.c */ +extern struct inode_operations aufs_iop, aufs_symlink_iop, aufs_dir_iop; + +/* au_wr_dir flags */ +#define AuWrDir_ADD_ENTRY 1 +#define AuWrDir_ISDIR (1 << 1) +#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name) +#define au_fset_wrdir(flags, name) \ + do { (flags) |= AuWrDir_##name; } while (0) +#define au_fclr_wrdir(flags, name) \ + do { (flags) &= ~AuWrDir_##name; } while (0) + +struct au_wr_dir_args { + aufs_bindex_t force_btgt; + unsigned char flags; +}; +int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry, + struct au_wr_dir_args *args); + +struct dentry *au_pinned_h_parent(struct au_pin *pin); +void au_pin_init(struct au_pin *pin, struct dentry *dentry, + aufs_bindex_t bindex, int lsc_di, int lsc_hi, + unsigned int udba, unsigned char flags); +int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex, + unsigned int udba, unsigned char flags) __must_check; +int au_do_pin(struct au_pin *pin) __must_check; +void au_unpin(struct au_pin *pin); + +/* i_op_add.c */ +int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent, int isdir); +int aufs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev); +int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); +int aufs_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd); +int aufs_link(struct dentry *src_dentry, struct inode *dir, + struct dentry *dentry); +int aufs_mkdir(struct inode *dir, struct dentry *dentry, int mode); + +/* i_op_del.c */ +int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); +int au_may_del(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent, int isdir); +int aufs_unlink(struct inode *dir, struct dentry *dentry); +int aufs_rmdir(struct inode *dir, struct dentry *dentry); + +/* i_op_ren.c */ +int au_wbr(struct dentry *dentry, aufs_bindex_t btgt); +int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, + struct inode *dir, struct dentry *dentry); + +/* iinfo.c */ +struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex); +void au_hiput(struct au_hinode *hinode); +void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex, + struct dentry *h_wh); +unsigned int au_hi_flags(struct inode *inode, int isdir); + +/* hinode flags */ +#define AuHi_XINO 1 +#define AuHi_HNOTIFY (1 << 1) +#define au_ftest_hi(flags, name) ((flags) & AuHi_##name) +#define au_fset_hi(flags, name) \ + do { (flags) |= AuHi_##name; } while (0) +#define au_fclr_hi(flags, name) \ + do { (flags) &= ~AuHi_##name; } while (0) + +#ifndef CONFIG_AUFS_HNOTIFY +#undef AuHi_HNOTIFY +#define AuHi_HNOTIFY 0 +#endif + +void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex, + struct inode *h_inode, unsigned int flags); + +void au_update_iigen(struct inode *inode); +void au_update_ibrange(struct inode *inode, int do_put_zero); + +void au_icntnr_init_once(void *_c); +int au_iinfo_init(struct inode *inode); +void au_iinfo_fin(struct inode *inode); +int au_ii_realloc(struct au_iinfo *iinfo, int nbr); + +#ifdef CONFIG_PROC_FS +/* plink.c */ +int au_plink_maint(struct super_block *sb, int flags); +void au_plink_maint_leave(struct au_sbinfo *sbinfo); +int au_plink_maint_enter(struct super_block *sb); +#ifdef CONFIG_AUFS_DEBUG +void au_plink_list(struct super_block *sb); +#else +AuStubVoid(au_plink_list, struct super_block *sb) +#endif +int au_plink_test(struct inode *inode); +struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex); +void au_plink_append(struct inode *inode, aufs_bindex_t bindex, + struct dentry *h_dentry); +void au_plink_put(struct super_block *sb, int verbose); +void au_plink_clean(struct super_block *sb, int verbose); +void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id); +#else +AuStubInt0(au_plink_maint, struct super_block *sb, int flags); +AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo); +AuStubInt0(au_plink_maint_enter, struct super_block *sb); +AuStubVoid(au_plink_list, struct super_block *sb); +AuStubInt0(au_plink_test, struct inode *inode); +AuStub(struct dentry *, au_plink_lkup, return NULL, + struct inode *inode, aufs_bindex_t bindex); +AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex, + struct dentry *h_dentry); +AuStubVoid(au_plink_put, struct super_block *sb, int verbose); +AuStubVoid(au_plink_clean, struct super_block *sb, int verbose); +AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id); +#endif /* CONFIG_PROC_FS */ + +/* ---------------------------------------------------------------------- */ + +/* lock subclass for iinfo */ +enum { + AuLsc_II_CHILD, /* child first */ + AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */ + AuLsc_II_CHILD3, /* copyup dirs */ + AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */ + AuLsc_II_PARENT2, + AuLsc_II_PARENT3, /* copyup dirs */ + AuLsc_II_NEW_CHILD +}; + +/* + * ii_read_lock_child, ii_write_lock_child, + * ii_read_lock_child2, ii_write_lock_child2, + * ii_read_lock_child3, ii_write_lock_child3, + * ii_read_lock_parent, ii_write_lock_parent, + * ii_read_lock_parent2, ii_write_lock_parent2, + * ii_read_lock_parent3, ii_write_lock_parent3, + * ii_read_lock_new_child, ii_write_lock_new_child, + */ +#define AuReadLockFunc(name, lsc) \ +static inline void ii_read_lock_##name(struct inode *i) \ +{ \ + au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ +} + +#define AuWriteLockFunc(name, lsc) \ +static inline void ii_write_lock_##name(struct inode *i) \ +{ \ + au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \ +} + +#define AuRWLockFuncs(name, lsc) \ + AuReadLockFunc(name, lsc) \ + AuWriteLockFunc(name, lsc) + +AuRWLockFuncs(child, CHILD); +AuRWLockFuncs(child2, CHILD2); +AuRWLockFuncs(child3, CHILD3); +AuRWLockFuncs(parent, PARENT); +AuRWLockFuncs(parent2, PARENT2); +AuRWLockFuncs(parent3, PARENT3); +AuRWLockFuncs(new_child, NEW_CHILD); + +#undef AuReadLockFunc +#undef AuWriteLockFunc +#undef AuRWLockFuncs + +/* + * ii_read_unlock, ii_write_unlock, ii_downgrade_lock + */ +AuSimpleUnlockRwsemFuncs(ii, struct inode *i, &au_ii(i)->ii_rwsem); + +#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem) +#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem) +#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem) + +/* ---------------------------------------------------------------------- */ + +static inline unsigned int au_iigen(struct inode *inode) +{ + return atomic_read(&au_ii(inode)->ii_generation); +} + +/* tiny test for inode number */ +/* tmpfs generation is too rough */ +static inline int au_test_higen(struct inode *inode, struct inode *h_inode) +{ + struct au_iinfo *iinfo; + + iinfo = au_ii(inode); + AuRwMustAnyLock(&iinfo->ii_rwsem); + return !(iinfo->ii_hsb1 == h_inode->i_sb + && iinfo->ii_higen == h_inode->i_generation); +} + +static inline void au_iigen_dec(struct inode *inode) +{ +#ifdef CONFIG_AUFS_HNOTIFY + atomic_dec(&au_ii(inode)->ii_generation); +#endif +} + +/* ---------------------------------------------------------------------- */ + +static inline aufs_bindex_t au_ii_br_id(struct inode *inode, + aufs_bindex_t bindex) +{ + IiMustAnyLock(inode); + return au_ii(inode)->ii_hinode[0 + bindex].hi_id; +} + +static inline aufs_bindex_t au_ibstart(struct inode *inode) +{ + IiMustAnyLock(inode); + return au_ii(inode)->ii_bstart; +} + +static inline aufs_bindex_t au_ibend(struct inode *inode) +{ + IiMustAnyLock(inode); + return au_ii(inode)->ii_bend; +} + +static inline struct au_vdir *au_ivdir(struct inode *inode) +{ + IiMustAnyLock(inode); + return au_ii(inode)->ii_vdir; +} + +static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex) +{ + IiMustAnyLock(inode); + return au_ii(inode)->ii_hinode[0 + bindex].hi_whdentry; +} + +static inline void au_set_ibstart(struct inode *inode, aufs_bindex_t bindex) +{ + IiMustWriteLock(inode); + au_ii(inode)->ii_bstart = bindex; +} + +static inline void au_set_ibend(struct inode *inode, aufs_bindex_t bindex) +{ + IiMustWriteLock(inode); + au_ii(inode)->ii_bend = bindex; +} + +static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir) +{ + IiMustWriteLock(inode); + au_ii(inode)->ii_vdir = vdir; +} + +static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex) +{ + IiMustAnyLock(inode); + return au_ii(inode)->ii_hinode + bindex; +} + +/* ---------------------------------------------------------------------- */ + +static inline struct dentry *au_pinned_parent(struct au_pin *pin) +{ + if (pin) + return pin->parent; + return NULL; +} + +static inline struct inode *au_pinned_h_dir(struct au_pin *pin) +{ + if (pin && pin->hdir) + return pin->hdir->hi_inode; + return NULL; +} + +static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin) +{ + if (pin) + return pin->hdir; + return NULL; +} + +static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry) +{ + if (pin) + pin->dentry = dentry; +} + +static inline void au_pin_set_parent_lflag(struct au_pin *pin, + unsigned char lflag) +{ + if (pin) { + if (lflag) + au_fset_pin(pin->flags, DI_LOCKED); + else + au_fclr_pin(pin->flags, DI_LOCKED); + } +} + +static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent) +{ + if (pin) { + dput(pin->parent); + pin->parent = dget(parent); + } +} + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_HNOTIFY +struct au_hnotify_op { + void (*ctl)(struct au_hinode *hinode, int do_set); + int (*alloc)(struct au_hnotify *hn, struct inode *h_inode); + void (*free)(struct au_hnotify *hn); + + void (*fin)(void); + int (*init)(void); +}; + +/* hnotify.c */ +int au_hn_alloc(struct au_hinode *hinode, struct inode *inode, + struct inode *h_inode); +void au_hn_free(struct au_hinode *hinode); +void au_hn_ctl(struct au_hinode *hinode, int do_set); +void au_hn_reset(struct inode *inode, unsigned int flags); +int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask, + struct qstr *h_child_qstr, struct inode *h_child_inode); +int __init au_hnotify_init(void); +void au_hnotify_fin(void); + +/* hfsnotify.c */ +extern const struct au_hnotify_op au_hnotify_op; + +static inline +void au_hn_init(struct au_hinode *hinode) +{ + hinode->hi_notify = NULL; +} + +#else +static inline +int au_hn_alloc(struct au_hinode *hinode __maybe_unused, + struct inode *inode __maybe_unused, + struct inode *h_inode __maybe_unused) +{ + return -EOPNOTSUPP; +} + +AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused) +AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused, + int do_set __maybe_unused) +AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused, + unsigned int flags __maybe_unused) +AuStubInt0(__init au_hnotify_init, void) +AuStubVoid(au_hnotify_fin, void) +AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused) +#endif /* CONFIG_AUFS_HNOTIFY */ + +static inline void au_hn_suspend(struct au_hinode *hdir) +{ + au_hn_ctl(hdir, /*do_set*/0); +} + +static inline void au_hn_resume(struct au_hinode *hdir) +{ + au_hn_ctl(hdir, /*do_set*/1); +} + +static inline void au_hn_imtx_lock(struct au_hinode *hdir) +{ + mutex_lock(&hdir->hi_inode->i_mutex); + au_hn_suspend(hdir); +} + +static inline void au_hn_imtx_lock_nested(struct au_hinode *hdir, + unsigned int sc __maybe_unused) +{ + mutex_lock_nested(&hdir->hi_inode->i_mutex, sc); + au_hn_suspend(hdir); +} + +static inline void au_hn_imtx_unlock(struct au_hinode *hdir) +{ + au_hn_resume(hdir); + mutex_unlock(&hdir->hi_inode->i_mutex); +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_INODE_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/ioctl.c +++ linux-2.6.37/ubuntu/aufs/ioctl.c @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * ioctl + * plink-management and readdir in userspace. + * assist the pathconf(3) wrapper library. + */ + +#include +#include "aufs.h" + +static int au_wbr_fd(struct path *path) +{ + int err, fd; + aufs_bindex_t wbi, bindex, bend; + struct file *h_file; + struct super_block *sb; + struct dentry *root; + struct au_branch *wbr; + + err = get_unused_fd(); + if (unlikely(err < 0)) + goto out; + fd = err; + + wbi = 0; + sb = path->dentry->d_sb; + root = sb->s_root; + aufs_read_lock(root, AuLock_IR); + wbr = au_sbr(sb, wbi); + if (!(path->mnt->mnt_flags & MNT_READONLY) + && !au_br_writable(wbr->br_perm)) { + bend = au_sbend(sb); + for (bindex = 1; bindex <= bend; bindex++) { + wbr = au_sbr(sb, bindex); + if (au_br_writable(wbr->br_perm)) { + wbi = bindex; + break; + } + } + wbr = au_sbr(sb, wbi); + } + AuDbg("wbi %d\n", wbi); + h_file = au_h_open(root, wbi, O_RDONLY | O_DIRECTORY | O_LARGEFILE, + NULL); + aufs_read_unlock(root, AuLock_IR); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out_fd; + + atomic_dec(&wbr->br_count); /* cf. au_h_open() */ + fd_install(fd, h_file); + err = fd; + goto out; /* success */ + +out_fd: + put_unused_fd(fd); +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg) +{ + long err; + + switch (cmd) { + case AUFS_CTL_RDU: + case AUFS_CTL_RDU_INO: + err = au_rdu_ioctl(file, cmd, arg); + break; + + case AUFS_CTL_WBR_FD: + err = au_wbr_fd(&file->f_path); + break; + + default: + /* do not call the lower */ + AuDbg("0x%x\n", cmd); + err = -ENOTTY; + } + + AuTraceErr(err); + return err; +} + +long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg) +{ + long err; + + switch (cmd) { + case AUFS_CTL_WBR_FD: + err = au_wbr_fd(&file->f_path); + break; + + default: + /* do not call the lower */ + AuDbg("0x%x\n", cmd); + err = -ENOTTY; + } + + AuTraceErr(err); + return err; +} + +#ifdef CONFIG_COMPAT +long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd, + unsigned long arg) +{ + long err; + + switch (cmd) { + case AUFS_CTL_RDU: + case AUFS_CTL_RDU_INO: + err = au_rdu_compat_ioctl(file, cmd, arg); + break; + + default: + err = aufs_ioctl_dir(file, cmd, arg); + } + + AuTraceErr(err); + return err; +} + +#if 0 /* unused yet */ +long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd, + unsigned long arg) +{ + return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg)); +} +#endif +#endif --- linux-2.6.37.orig/ubuntu/aufs/loop.c +++ linux-2.6.37/ubuntu/aufs/loop.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * support for loopback block device as a branch + */ + +#include +#include "aufs.h" + +/* + * test if two lower dentries have overlapping branches. + */ +int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding) +{ + struct super_block *h_sb; + struct loop_device *l; + + h_sb = h_adding->d_sb; + if (MAJOR(h_sb->s_dev) != LOOP_MAJOR) + return 0; + + l = h_sb->s_bdev->bd_disk->private_data; + h_adding = l->lo_backing_file->f_dentry; + /* + * h_adding can be local NFS. + * in this case aufs cannot detect the loop. + */ + if (unlikely(h_adding->d_sb == sb)) + return 1; + return !!au_test_subdir(h_adding, sb->s_root); +} + +/* true if a kernel thread named 'loop[0-9].*' accesses a file */ +int au_test_loopback_kthread(void) +{ + int ret; + struct task_struct *tsk = current; + + ret = 0; + if (tsk->flags & PF_KTHREAD) { + const char c = tsk->comm[4]; + ret = ('0' <= c && c <= '9' + && !strncmp(tsk->comm, "loop", 4)); + } + + return ret; +} --- linux-2.6.37.orig/ubuntu/aufs/loop.h +++ linux-2.6.37/ubuntu/aufs/loop.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * support for loopback mount as a branch + */ + +#ifndef __AUFS_LOOP_H__ +#define __AUFS_LOOP_H__ + +#ifdef __KERNEL__ + +struct dentry; +struct super_block; + +#ifdef CONFIG_AUFS_BDEV_LOOP +/* loop.c */ +int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding); +int au_test_loopback_kthread(void); +#else +AuStubInt0(au_test_loopback_overlap, struct super_block *sb, + struct dentry *h_adding) +AuStubInt0(au_test_loopback_kthread, void) +#endif /* BLK_DEV_LOOP */ + +#endif /* __KERNEL__ */ +#endif /* __AUFS_LOOP_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/magic.mk +++ linux-2.6.37/ubuntu/aufs/magic.mk @@ -0,0 +1,54 @@ + +# defined in ${srctree}/fs/fuse/inode.c +# tristate +ifdef CONFIG_FUSE_FS +ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546 +endif + +# defined in ${srctree}/fs/ocfs2/ocfs2_fs.h +# tristate +ifdef CONFIG_OCFS2_FS +ccflags-y += -DOCFS2_SUPER_MAGIC=0x7461636f +endif + +# defined in ${srctree}/fs/ocfs2/dlm/userdlm.h +# tristate +ifdef CONFIG_OCFS2_FS_O2CB +ccflags-y += -DDLMFS_MAGIC=0x76a9f425 +endif + +# defined in ${srctree}/fs/cifs/cifsfs.c +# tristate +ifdef CONFIG_CIFS_FS +ccflags-y += -DCIFS_MAGIC_NUMBER=0xFF534D42 +endif + +# defined in ${srctree}/fs/xfs/xfs_sb.h +# tristate +ifdef CONFIG_XFS_FS +ccflags-y += -DXFS_SB_MAGIC=0x58465342 +endif + +# defined in ${srctree}/fs/configfs/mount.c +# tristate +ifdef CONFIG_CONFIGFS_FS +ccflags-y += -DCONFIGFS_MAGIC=0x62656570 +endif + +# defined in ${srctree}/fs/9p/v9fs.h +# tristate +ifdef CONFIG_9P_FS +ccflags-y += -DV9FS_MAGIC=0x01021997 +endif + +# defined in ${srctree}/fs/ubifs/ubifs.h +# tristate +ifdef CONFIG_UBIFS_FS +ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905 +endif + +# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h +# tristate +ifdef CONFIG_HFSPLUS_FS +ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b +endif --- linux-2.6.37.orig/ubuntu/aufs/module.c +++ linux-2.6.37/ubuntu/aufs/module.c @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * module global variables and operations + */ + +#include +#include +#include "aufs.h" + +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp) +{ + if (new_sz <= nused) + return p; + + p = krealloc(p, new_sz, gfp); + if (p) + memset(p + nused, 0, new_sz - nused); + return p; +} + +/* ---------------------------------------------------------------------- */ + +/* + * aufs caches + */ +struct kmem_cache *au_cachep[AuCache_Last]; +static int __init au_cache_init(void) +{ + au_cachep[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once); + if (au_cachep[AuCache_DINFO]) + au_cachep[AuCache_ICNTNR] = AuCacheCtor(au_icntnr, + au_icntnr_init_once); + if (au_cachep[AuCache_ICNTNR]) + au_cachep[AuCache_FINFO] = AuCacheCtor(au_finfo, + au_fi_init_once); + if (au_cachep[AuCache_FINFO]) + au_cachep[AuCache_VDIR] = AuCache(au_vdir); + if (au_cachep[AuCache_VDIR]) + au_cachep[AuCache_DEHSTR] = AuCache(au_vdir_dehstr); + if (au_cachep[AuCache_DEHSTR]) + return 0; + + return -ENOMEM; +} + +static void au_cache_fin(void) +{ + int i; + + /* including AuCache_HNOTIFY */ + for (i = 0; i < AuCache_Last; i++) + if (au_cachep[i]) { + kmem_cache_destroy(au_cachep[i]); + au_cachep[i] = NULL; + } +} + +/* ---------------------------------------------------------------------- */ + +int au_dir_roflags; + +#ifdef CONFIG_AUFS_SBILIST +struct au_splhead au_sbilist; +#endif + +/* + * functions for module interface. + */ +MODULE_LICENSE("GPL"); +/* MODULE_LICENSE("GPL v2"); */ +MODULE_AUTHOR("Junjiro R. Okajima "); +MODULE_DESCRIPTION(AUFS_NAME + " -- Advanced multi layered unification filesystem"); +MODULE_VERSION(AUFS_VERSION); + +/* this module parameter has no meaning when SYSFS is disabled */ +int sysaufs_brs = 1; +MODULE_PARM_DESC(brs, "use /fs/aufs/si_*/brN"); +module_param_named(brs, sysaufs_brs, int, S_IRUGO); + +/* ---------------------------------------------------------------------- */ + +static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */ + +int au_seq_path(struct seq_file *seq, struct path *path) +{ + return seq_path(seq, path, au_esc_chars); +} + +/* ---------------------------------------------------------------------- */ + +static int __init aufs_init(void) +{ + int err, i; + char *p; + + p = au_esc_chars; + for (i = 1; i <= ' '; i++) + *p++ = i; + *p++ = '\\'; + *p++ = '\x7f'; + *p = 0; + + au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE); + + au_sbilist_init(); + sysaufs_brs_init(); + au_debug_init(); + au_dy_init(); + err = sysaufs_init(); + if (unlikely(err)) + goto out; + err = au_procfs_init(); + if (unlikely(err)) + goto out_sysaufs; + err = au_wkq_init(); + if (unlikely(err)) + goto out_procfs; + err = au_hnotify_init(); + if (unlikely(err)) + goto out_wkq; + err = au_sysrq_init(); + if (unlikely(err)) + goto out_hin; + err = au_cache_init(); + if (unlikely(err)) + goto out_sysrq; + err = register_filesystem(&aufs_fs_type); + if (unlikely(err)) + goto out_cache; + /* since we define pr_fmt, call printk directly */ + printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n"); + goto out; /* success */ + +out_cache: + au_cache_fin(); +out_sysrq: + au_sysrq_fin(); +out_hin: + au_hnotify_fin(); +out_wkq: + au_wkq_fin(); +out_procfs: + au_procfs_fin(); +out_sysaufs: + sysaufs_fin(); + au_dy_fin(); +out: + return err; +} + +static void __exit aufs_exit(void) +{ + unregister_filesystem(&aufs_fs_type); + au_cache_fin(); + au_sysrq_fin(); + au_hnotify_fin(); + au_wkq_fin(); + au_procfs_fin(); + sysaufs_fin(); + au_dy_fin(); +} + +module_init(aufs_init); +module_exit(aufs_exit); --- linux-2.6.37.orig/ubuntu/aufs/module.h +++ linux-2.6.37/ubuntu/aufs/module.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * module initialization and module-global + */ + +#ifndef __AUFS_MODULE_H__ +#define __AUFS_MODULE_H__ + +#ifdef __KERNEL__ + +#include + +struct path; +struct seq_file; + +/* module parameters */ +extern int sysaufs_brs; + +/* ---------------------------------------------------------------------- */ + +extern int au_dir_roflags; + +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp); +int au_seq_path(struct seq_file *seq, struct path *path); + +#ifdef CONFIG_PROC_FS +/* procfs.c */ +int __init au_procfs_init(void); +void au_procfs_fin(void); +#else +AuStubInt0(au_procfs_init, void); +AuStubVoid(au_procfs_fin, void); +#endif + +/* ---------------------------------------------------------------------- */ + +/* kmem cache */ +enum { + AuCache_DINFO, + AuCache_ICNTNR, + AuCache_FINFO, + AuCache_VDIR, + AuCache_DEHSTR, +#ifdef CONFIG_AUFS_HNOTIFY + AuCache_HNOTIFY, +#endif + AuCache_Last +}; + +#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD) +#define AuCache(type) KMEM_CACHE(type, AuCacheFlags) +#define AuCacheCtor(type, ctor) \ + kmem_cache_create(#type, sizeof(struct type), \ + __alignof__(struct type), AuCacheFlags, ctor) + +extern struct kmem_cache *au_cachep[]; + +#define AuCacheFuncs(name, index) \ +static inline struct au_##name *au_cache_alloc_##name(void) \ +{ return kmem_cache_alloc(au_cachep[AuCache_##index], GFP_NOFS); } \ +static inline void au_cache_free_##name(struct au_##name *p) \ +{ kmem_cache_free(au_cachep[AuCache_##index], p); } + +AuCacheFuncs(dinfo, DINFO); +AuCacheFuncs(icntnr, ICNTNR); +AuCacheFuncs(finfo, FINFO); +AuCacheFuncs(vdir, VDIR); +AuCacheFuncs(vdir_dehstr, DEHSTR); +#ifdef CONFIG_AUFS_HNOTIFY +AuCacheFuncs(hnotify, HNOTIFY); +#endif + +#endif /* __KERNEL__ */ +#endif /* __AUFS_MODULE_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/mtx.h +++ linux-2.6.37/ubuntu/aufs/mtx.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * very ugly approach for aufs_mmap() + * never include this file from other than f_op.c. + * see f_op.c in detail. + */ + +#ifndef __AUFS_MTX_H__ +#define __AUFS_MTX_H__ + +#ifdef __KERNEL__ + +/* copied from ../kernel/mutex{,-debug}.h */ +struct mutex; +struct thread_info; +#ifdef CONFIG_DEBUG_MUTEXES +static inline void mutex_set_owner(struct mutex *lock) +{ + lock->owner = current_thread_info(); +} +#else +static inline void mutex_set_owner(struct mutex *lock) +{ +#ifdef CONFIG_SMP + lock->owner = current_thread_info(); +#endif +} +#endif + +#endif /* __KERNEL__ */ +#endif /* __AUFS_MTX_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/opts.c +++ linux-2.6.37/ubuntu/aufs/opts.c @@ -0,0 +1,1581 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * mount options/flags + */ + +#include +#include +#include +#include /* a distribution requires */ +#include +#include "aufs.h" + +/* ---------------------------------------------------------------------- */ + +enum { + Opt_br, + Opt_add, Opt_del, Opt_mod, Opt_reorder, Opt_append, Opt_prepend, + Opt_idel, Opt_imod, Opt_ireorder, + Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, Opt_rendir, + Opt_rdblk_def, Opt_rdhash_def, + Opt_xino, Opt_zxino, Opt_noxino, + Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino, + Opt_trunc_xino_path, Opt_itrunc_xino, + Opt_trunc_xib, Opt_notrunc_xib, + Opt_shwh, Opt_noshwh, + Opt_plink, Opt_noplink, Opt_list_plink, + Opt_udba, + Opt_dio, Opt_nodio, + /* Opt_lock, Opt_unlock, */ + Opt_cmd, Opt_cmd_args, + Opt_diropq_a, Opt_diropq_w, + Opt_warn_perm, Opt_nowarn_perm, + Opt_wbr_copyup, Opt_wbr_create, + Opt_refrof, Opt_norefrof, + Opt_verbose, Opt_noverbose, + Opt_sum, Opt_nosum, Opt_wsum, + Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err +}; + +static match_table_t options = { + {Opt_br, "br=%s"}, + {Opt_br, "br:%s"}, + + {Opt_add, "add=%d:%s"}, + {Opt_add, "add:%d:%s"}, + {Opt_add, "ins=%d:%s"}, + {Opt_add, "ins:%d:%s"}, + {Opt_append, "append=%s"}, + {Opt_append, "append:%s"}, + {Opt_prepend, "prepend=%s"}, + {Opt_prepend, "prepend:%s"}, + + {Opt_del, "del=%s"}, + {Opt_del, "del:%s"}, + /* {Opt_idel, "idel:%d"}, */ + {Opt_mod, "mod=%s"}, + {Opt_mod, "mod:%s"}, + /* {Opt_imod, "imod:%d:%s"}, */ + + {Opt_dirwh, "dirwh=%d"}, + + {Opt_xino, "xino=%s"}, + {Opt_noxino, "noxino"}, + {Opt_trunc_xino, "trunc_xino"}, + {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"}, + {Opt_notrunc_xino, "notrunc_xino"}, + {Opt_trunc_xino_path, "trunc_xino=%s"}, + {Opt_itrunc_xino, "itrunc_xino=%d"}, + /* {Opt_zxino, "zxino=%s"}, */ + {Opt_trunc_xib, "trunc_xib"}, + {Opt_notrunc_xib, "notrunc_xib"}, + +#ifdef CONFIG_PROC_FS + {Opt_plink, "plink"}, +#else + {Opt_ignore_silent, "plink"}, +#endif + + {Opt_noplink, "noplink"}, + +#ifdef CONFIG_AUFS_DEBUG + {Opt_list_plink, "list_plink"}, +#endif + + {Opt_udba, "udba=%s"}, + + {Opt_dio, "dio"}, + {Opt_nodio, "nodio"}, + + {Opt_diropq_a, "diropq=always"}, + {Opt_diropq_a, "diropq=a"}, + {Opt_diropq_w, "diropq=whiteouted"}, + {Opt_diropq_w, "diropq=w"}, + + {Opt_warn_perm, "warn_perm"}, + {Opt_nowarn_perm, "nowarn_perm"}, + + /* keep them temporary */ + {Opt_ignore_silent, "coo=%s"}, + {Opt_ignore_silent, "nodlgt"}, + {Opt_ignore_silent, "nodirperm1"}, + {Opt_ignore_silent, "clean_plink"}, + +#ifdef CONFIG_AUFS_SHWH + {Opt_shwh, "shwh"}, +#endif + {Opt_noshwh, "noshwh"}, + + {Opt_rendir, "rendir=%d"}, + + {Opt_refrof, "refrof"}, + {Opt_norefrof, "norefrof"}, + + {Opt_verbose, "verbose"}, + {Opt_verbose, "v"}, + {Opt_noverbose, "noverbose"}, + {Opt_noverbose, "quiet"}, + {Opt_noverbose, "q"}, + {Opt_noverbose, "silent"}, + + {Opt_sum, "sum"}, + {Opt_nosum, "nosum"}, + {Opt_wsum, "wsum"}, + + {Opt_rdcache, "rdcache=%d"}, + {Opt_rdblk, "rdblk=%d"}, + {Opt_rdblk_def, "rdblk=def"}, + {Opt_rdhash, "rdhash=%d"}, + {Opt_rdhash_def, "rdhash=def"}, + + {Opt_wbr_create, "create=%s"}, + {Opt_wbr_create, "create_policy=%s"}, + {Opt_wbr_copyup, "cpup=%s"}, + {Opt_wbr_copyup, "copyup=%s"}, + {Opt_wbr_copyup, "copyup_policy=%s"}, + + /* internal use for the scripts */ + {Opt_ignore_silent, "si=%s"}, + + {Opt_br, "dirs=%s"}, + {Opt_ignore, "debug=%d"}, + {Opt_ignore, "delete=whiteout"}, + {Opt_ignore, "delete=all"}, + {Opt_ignore, "imap=%s"}, + + /* temporary workaround, due to old mount(8)? */ + {Opt_ignore_silent, "relatime"}, + + {Opt_err, NULL} +}; + +/* ---------------------------------------------------------------------- */ + +static const char *au_parser_pattern(int val, struct match_token *token) +{ + while (token->pattern) { + if (token->token == val) + return token->pattern; + token++; + } + BUG(); + return "??"; +} + +/* ---------------------------------------------------------------------- */ + +static match_table_t brperms = { + {AuBrPerm_RO, AUFS_BRPERM_RO}, + {AuBrPerm_RR, AUFS_BRPERM_RR}, + {AuBrPerm_RW, AUFS_BRPERM_RW}, + + {AuBrPerm_ROWH, AUFS_BRPERM_ROWH}, + {AuBrPerm_RRWH, AUFS_BRPERM_RRWH}, + {AuBrPerm_RWNoLinkWH, AUFS_BRPERM_RWNLWH}, + + {AuBrPerm_ROWH, "nfsro"}, + {AuBrPerm_RO, NULL} +}; + +static int noinline_for_stack br_perm_val(char *perm) +{ + int val; + substring_t args[MAX_OPT_ARGS]; + + val = match_token(perm, brperms, args); + return val; +} + +const char *au_optstr_br_perm(int brperm) +{ + return au_parser_pattern(brperm, (void *)brperms); +} + +/* ---------------------------------------------------------------------- */ + +static match_table_t udbalevel = { + {AuOpt_UDBA_REVAL, "reval"}, + {AuOpt_UDBA_NONE, "none"}, +#ifdef CONFIG_AUFS_HNOTIFY + {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */ +#ifdef CONFIG_AUFS_HFSNOTIFY + {AuOpt_UDBA_HNOTIFY, "fsnotify"}, +#endif +#endif + {-1, NULL} +}; + +static int noinline_for_stack udba_val(char *str) +{ + substring_t args[MAX_OPT_ARGS]; + + return match_token(str, udbalevel, args); +} + +const char *au_optstr_udba(int udba) +{ + return au_parser_pattern(udba, (void *)udbalevel); +} + +/* ---------------------------------------------------------------------- */ + +static match_table_t au_wbr_create_policy = { + {AuWbrCreate_TDP, "tdp"}, + {AuWbrCreate_TDP, "top-down-parent"}, + {AuWbrCreate_RR, "rr"}, + {AuWbrCreate_RR, "round-robin"}, + {AuWbrCreate_MFS, "mfs"}, + {AuWbrCreate_MFS, "most-free-space"}, + {AuWbrCreate_MFSV, "mfs:%d"}, + {AuWbrCreate_MFSV, "most-free-space:%d"}, + + {AuWbrCreate_MFSRR, "mfsrr:%d"}, + {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"}, + {AuWbrCreate_PMFS, "pmfs"}, + {AuWbrCreate_PMFSV, "pmfs:%d"}, + + {-1, NULL} +}; + +/* + * cf. linux/lib/parser.c and cmdline.c + * gave up calling memparse() since it uses simple_strtoull() instead of + * strict_...(). + */ +static int noinline_for_stack +au_match_ull(substring_t *s, unsigned long long *result) +{ + int err; + unsigned int len; + char a[32]; + + err = -ERANGE; + len = s->to - s->from; + if (len + 1 <= sizeof(a)) { + memcpy(a, s->from, len); + a[len] = '\0'; + err = strict_strtoull(a, 0, result); + } + return err; +} + +static int au_wbr_mfs_wmark(substring_t *arg, char *str, + struct au_opt_wbr_create *create) +{ + int err; + unsigned long long ull; + + err = 0; + if (!au_match_ull(arg, &ull)) + create->mfsrr_watermark = ull; + else { + pr_err("bad integer in %s\n", str); + err = -EINVAL; + } + + return err; +} + +static int au_wbr_mfs_sec(substring_t *arg, char *str, + struct au_opt_wbr_create *create) +{ + int n, err; + + err = 0; + if (!match_int(arg, &n) && 0 <= n && n <= MAX_SEC_IN_JIFFIES) + create->mfs_second = n; + else { + pr_err("bad integer in %s\n", str); + err = -EINVAL; + } + + return err; +} + +static int noinline_for_stack +au_wbr_create_val(char *str, struct au_opt_wbr_create *create) +{ + int err, e; + substring_t args[MAX_OPT_ARGS]; + + err = match_token(str, au_wbr_create_policy, args); + create->wbr_create = err; + switch (err) { + case AuWbrCreate_MFSRRV: + e = au_wbr_mfs_wmark(&args[0], str, create); + if (!e) + e = au_wbr_mfs_sec(&args[1], str, create); + if (unlikely(e)) + err = e; + break; + case AuWbrCreate_MFSRR: + e = au_wbr_mfs_wmark(&args[0], str, create); + if (unlikely(e)) { + err = e; + break; + } + /*FALLTHROUGH*/ + case AuWbrCreate_MFS: + case AuWbrCreate_PMFS: + create->mfs_second = AUFS_MFS_SECOND_DEF; + break; + case AuWbrCreate_MFSV: + case AuWbrCreate_PMFSV: + e = au_wbr_mfs_sec(&args[0], str, create); + if (unlikely(e)) + err = e; + break; + } + + return err; +} + +const char *au_optstr_wbr_create(int wbr_create) +{ + return au_parser_pattern(wbr_create, (void *)au_wbr_create_policy); +} + +static match_table_t au_wbr_copyup_policy = { + {AuWbrCopyup_TDP, "tdp"}, + {AuWbrCopyup_TDP, "top-down-parent"}, + {AuWbrCopyup_BUP, "bup"}, + {AuWbrCopyup_BUP, "bottom-up-parent"}, + {AuWbrCopyup_BU, "bu"}, + {AuWbrCopyup_BU, "bottom-up"}, + {-1, NULL} +}; + +static int noinline_for_stack au_wbr_copyup_val(char *str) +{ + substring_t args[MAX_OPT_ARGS]; + + return match_token(str, au_wbr_copyup_policy, args); +} + +const char *au_optstr_wbr_copyup(int wbr_copyup) +{ + return au_parser_pattern(wbr_copyup, (void *)au_wbr_copyup_policy); +} + +/* ---------------------------------------------------------------------- */ + +static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; + +static void dump_opts(struct au_opts *opts) +{ +#ifdef CONFIG_AUFS_DEBUG + /* reduce stack space */ + union { + struct au_opt_add *add; + struct au_opt_del *del; + struct au_opt_mod *mod; + struct au_opt_xino *xino; + struct au_opt_xino_itrunc *xino_itrunc; + struct au_opt_wbr_create *create; + } u; + struct au_opt *opt; + + opt = opts->opt; + while (opt->type != Opt_tail) { + switch (opt->type) { + case Opt_add: + u.add = &opt->add; + AuDbg("add {b%d, %s, 0x%x, %p}\n", + u.add->bindex, u.add->pathname, u.add->perm, + u.add->path.dentry); + break; + case Opt_del: + case Opt_idel: + u.del = &opt->del; + AuDbg("del {%s, %p}\n", + u.del->pathname, u.del->h_path.dentry); + break; + case Opt_mod: + case Opt_imod: + u.mod = &opt->mod; + AuDbg("mod {%s, 0x%x, %p}\n", + u.mod->path, u.mod->perm, u.mod->h_root); + break; + case Opt_append: + u.add = &opt->add; + AuDbg("append {b%d, %s, 0x%x, %p}\n", + u.add->bindex, u.add->pathname, u.add->perm, + u.add->path.dentry); + break; + case Opt_prepend: + u.add = &opt->add; + AuDbg("prepend {b%d, %s, 0x%x, %p}\n", + u.add->bindex, u.add->pathname, u.add->perm, + u.add->path.dentry); + break; + case Opt_dirwh: + AuDbg("dirwh %d\n", opt->dirwh); + break; + case Opt_rdcache: + AuDbg("rdcache %d\n", opt->rdcache); + break; + case Opt_rdblk: + AuDbg("rdblk %u\n", opt->rdblk); + break; + case Opt_rdblk_def: + AuDbg("rdblk_def\n"); + break; + case Opt_rdhash: + AuDbg("rdhash %u\n", opt->rdhash); + break; + case Opt_rdhash_def: + AuDbg("rdhash_def\n"); + break; + case Opt_xino: + u.xino = &opt->xino; + AuDbg("xino {%s %.*s}\n", + u.xino->path, + AuDLNPair(u.xino->file->f_dentry)); + break; + case Opt_trunc_xino: + AuLabel(trunc_xino); + break; + case Opt_notrunc_xino: + AuLabel(notrunc_xino); + break; + case Opt_trunc_xino_path: + case Opt_itrunc_xino: + u.xino_itrunc = &opt->xino_itrunc; + AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex); + break; + + case Opt_noxino: + AuLabel(noxino); + break; + case Opt_trunc_xib: + AuLabel(trunc_xib); + break; + case Opt_notrunc_xib: + AuLabel(notrunc_xib); + break; + case Opt_shwh: + AuLabel(shwh); + break; + case Opt_noshwh: + AuLabel(noshwh); + break; + case Opt_plink: + AuLabel(plink); + break; + case Opt_noplink: + AuLabel(noplink); + break; + case Opt_list_plink: + AuLabel(list_plink); + break; + case Opt_udba: + AuDbg("udba %d, %s\n", + opt->udba, au_optstr_udba(opt->udba)); + break; + case Opt_dio: + AuLabel(dio); + break; + case Opt_nodio: + AuLabel(nodio); + break; + case Opt_diropq_a: + AuLabel(diropq_a); + break; + case Opt_diropq_w: + AuLabel(diropq_w); + break; + case Opt_warn_perm: + AuLabel(warn_perm); + break; + case Opt_nowarn_perm: + AuLabel(nowarn_perm); + break; + case Opt_refrof: + AuLabel(refrof); + break; + case Opt_norefrof: + AuLabel(norefrof); + break; + case Opt_verbose: + AuLabel(verbose); + break; + case Opt_noverbose: + AuLabel(noverbose); + break; + case Opt_sum: + AuLabel(sum); + break; + case Opt_nosum: + AuLabel(nosum); + break; + case Opt_wsum: + AuLabel(wsum); + break; + case Opt_wbr_create: + u.create = &opt->wbr_create; + AuDbg("create %d, %s\n", u.create->wbr_create, + au_optstr_wbr_create(u.create->wbr_create)); + switch (u.create->wbr_create) { + case AuWbrCreate_MFSV: + case AuWbrCreate_PMFSV: + AuDbg("%d sec\n", u.create->mfs_second); + break; + case AuWbrCreate_MFSRR: + AuDbg("%llu watermark\n", + u.create->mfsrr_watermark); + break; + case AuWbrCreate_MFSRRV: + AuDbg("%llu watermark, %d sec\n", + u.create->mfsrr_watermark, + u.create->mfs_second); + break; + } + break; + case Opt_wbr_copyup: + AuDbg("copyup %d, %s\n", opt->wbr_copyup, + au_optstr_wbr_copyup(opt->wbr_copyup)); + break; + default: + BUG(); + } + opt++; + } +#endif +} + +void au_opts_free(struct au_opts *opts) +{ + struct au_opt *opt; + + opt = opts->opt; + while (opt->type != Opt_tail) { + switch (opt->type) { + case Opt_add: + case Opt_append: + case Opt_prepend: + path_put(&opt->add.path); + break; + case Opt_del: + case Opt_idel: + path_put(&opt->del.h_path); + break; + case Opt_mod: + case Opt_imod: + dput(opt->mod.h_root); + break; + case Opt_xino: + fput(opt->xino.file); + break; + } + opt++; + } +} + +static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, + aufs_bindex_t bindex) +{ + int err; + struct au_opt_add *add = &opt->add; + char *p; + + add->bindex = bindex; + add->perm = AuBrPerm_Last; + add->pathname = opt_str; + p = strchr(opt_str, '='); + if (p) { + *p++ = 0; + if (*p) + add->perm = br_perm_val(p); + } + + err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path); + if (!err) { + if (!p) { + add->perm = AuBrPerm_RO; + if (au_test_fs_rr(add->path.dentry->d_sb)) + add->perm = AuBrPerm_RR; + else if (!bindex && !(sb_flags & MS_RDONLY)) + add->perm = AuBrPerm_RW; + } + opt->type = Opt_add; + goto out; + } + pr_err("lookup failed %s (%d)\n", add->pathname, err); + err = -EINVAL; + +out: + return err; +} + +static int au_opts_parse_del(struct au_opt_del *del, substring_t args[]) +{ + int err; + + del->pathname = args[0].from; + AuDbg("del path %s\n", del->pathname); + + err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path); + if (unlikely(err)) + pr_err("lookup failed %s (%d)\n", del->pathname, err); + + return err; +} + +#if 0 /* reserved for future use */ +static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex, + struct au_opt_del *del, substring_t args[]) +{ + int err; + struct dentry *root; + + err = -EINVAL; + root = sb->s_root; + aufs_read_lock(root, AuLock_FLUSH); + if (bindex < 0 || au_sbend(sb) < bindex) { + pr_err("out of bounds, %d\n", bindex); + goto out; + } + + err = 0; + del->h_path.dentry = dget(au_h_dptr(root, bindex)); + del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex)); + +out: + aufs_read_unlock(root, !AuLock_IR); + return err; +} +#endif + +static int noinline_for_stack +au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[]) +{ + int err; + struct path path; + char *p; + + err = -EINVAL; + mod->path = args[0].from; + p = strchr(mod->path, '='); + if (unlikely(!p)) { + pr_err("no permssion %s\n", args[0].from); + goto out; + } + + *p++ = 0; + err = vfsub_kern_path(mod->path, lkup_dirflags, &path); + if (unlikely(err)) { + pr_err("lookup failed %s (%d)\n", mod->path, err); + goto out; + } + + mod->perm = br_perm_val(p); + AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p); + mod->h_root = dget(path.dentry); + path_put(&path); + +out: + return err; +} + +#if 0 /* reserved for future use */ +static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex, + struct au_opt_mod *mod, substring_t args[]) +{ + int err; + struct dentry *root; + + err = -EINVAL; + root = sb->s_root; + aufs_read_lock(root, AuLock_FLUSH); + if (bindex < 0 || au_sbend(sb) < bindex) { + pr_err("out of bounds, %d\n", bindex); + goto out; + } + + err = 0; + mod->perm = br_perm_val(args[1].from); + AuDbg("mod path %s, perm 0x%x, %s\n", + mod->path, mod->perm, args[1].from); + mod->h_root = dget(au_h_dptr(root, bindex)); + +out: + aufs_read_unlock(root, !AuLock_IR); + return err; +} +#endif + +static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino, + substring_t args[]) +{ + int err; + struct file *file; + + file = au_xino_create(sb, args[0].from, /*silent*/0); + err = PTR_ERR(file); + if (IS_ERR(file)) + goto out; + + err = -EINVAL; + if (unlikely(file->f_dentry->d_sb == sb)) { + fput(file); + pr_err("%s must be outside\n", args[0].from); + goto out; + } + + err = 0; + xino->file = file; + xino->path = args[0].from; + +out: + return err; +} + +static int noinline_for_stack +au_opts_parse_xino_itrunc_path(struct super_block *sb, + struct au_opt_xino_itrunc *xino_itrunc, + substring_t args[]) +{ + int err; + aufs_bindex_t bend, bindex; + struct path path; + struct dentry *root; + + err = vfsub_kern_path(args[0].from, lkup_dirflags, &path); + if (unlikely(err)) { + pr_err("lookup failed %s (%d)\n", args[0].from, err); + goto out; + } + + xino_itrunc->bindex = -1; + root = sb->s_root; + aufs_read_lock(root, AuLock_FLUSH); + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) { + if (au_h_dptr(root, bindex) == path.dentry) { + xino_itrunc->bindex = bindex; + break; + } + } + aufs_read_unlock(root, !AuLock_IR); + path_put(&path); + + if (unlikely(xino_itrunc->bindex < 0)) { + pr_err("no such branch %s\n", args[0].from); + err = -EINVAL; + } + +out: + return err; +} + +/* called without aufs lock */ +int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts) +{ + int err, n, token; + aufs_bindex_t bindex; + unsigned char skipped; + struct dentry *root; + struct au_opt *opt, *opt_tail; + char *opt_str; + /* reduce the stack space */ + union { + struct au_opt_xino_itrunc *xino_itrunc; + struct au_opt_wbr_create *create; + } u; + struct { + substring_t args[MAX_OPT_ARGS]; + } *a; + + err = -ENOMEM; + a = kmalloc(sizeof(*a), GFP_NOFS); + if (unlikely(!a)) + goto out; + + root = sb->s_root; + err = 0; + bindex = 0; + opt = opts->opt; + opt_tail = opt + opts->max_opt - 1; + opt->type = Opt_tail; + while (!err && (opt_str = strsep(&str, ",")) && *opt_str) { + err = -EINVAL; + skipped = 0; + token = match_token(opt_str, options, a->args); + switch (token) { + case Opt_br: + err = 0; + while (!err && (opt_str = strsep(&a->args[0].from, ":")) + && *opt_str) { + err = opt_add(opt, opt_str, opts->sb_flags, + bindex++); + if (unlikely(!err && ++opt > opt_tail)) { + err = -E2BIG; + break; + } + opt->type = Opt_tail; + skipped = 1; + } + break; + case Opt_add: + if (unlikely(match_int(&a->args[0], &n))) { + pr_err("bad integer in %s\n", opt_str); + break; + } + bindex = n; + err = opt_add(opt, a->args[1].from, opts->sb_flags, + bindex); + if (!err) + opt->type = token; + break; + case Opt_append: + err = opt_add(opt, a->args[0].from, opts->sb_flags, + /*dummy bindex*/1); + if (!err) + opt->type = token; + break; + case Opt_prepend: + err = opt_add(opt, a->args[0].from, opts->sb_flags, + /*bindex*/0); + if (!err) + opt->type = token; + break; + case Opt_del: + err = au_opts_parse_del(&opt->del, a->args); + if (!err) + opt->type = token; + break; +#if 0 /* reserved for future use */ + case Opt_idel: + del->pathname = "(indexed)"; + if (unlikely(match_int(&args[0], &n))) { + pr_err("bad integer in %s\n", opt_str); + break; + } + err = au_opts_parse_idel(sb, n, &opt->del, a->args); + if (!err) + opt->type = token; + break; +#endif + case Opt_mod: + err = au_opts_parse_mod(&opt->mod, a->args); + if (!err) + opt->type = token; + break; +#ifdef IMOD /* reserved for future use */ + case Opt_imod: + u.mod->path = "(indexed)"; + if (unlikely(match_int(&a->args[0], &n))) { + pr_err("bad integer in %s\n", opt_str); + break; + } + err = au_opts_parse_imod(sb, n, &opt->mod, a->args); + if (!err) + opt->type = token; + break; +#endif + case Opt_xino: + err = au_opts_parse_xino(sb, &opt->xino, a->args); + if (!err) + opt->type = token; + break; + + case Opt_trunc_xino_path: + err = au_opts_parse_xino_itrunc_path + (sb, &opt->xino_itrunc, a->args); + if (!err) + opt->type = token; + break; + + case Opt_itrunc_xino: + u.xino_itrunc = &opt->xino_itrunc; + if (unlikely(match_int(&a->args[0], &n))) { + pr_err("bad integer in %s\n", opt_str); + break; + } + u.xino_itrunc->bindex = n; + aufs_read_lock(root, AuLock_FLUSH); + if (n < 0 || au_sbend(sb) < n) { + pr_err("out of bounds, %d\n", n); + aufs_read_unlock(root, !AuLock_IR); + break; + } + aufs_read_unlock(root, !AuLock_IR); + err = 0; + opt->type = token; + break; + + case Opt_dirwh: + if (unlikely(match_int(&a->args[0], &opt->dirwh))) + break; + err = 0; + opt->type = token; + break; + + case Opt_rdcache: + if (unlikely(match_int(&a->args[0], &opt->rdcache) + || opt->rdcache > MAX_SEC_IN_JIFFIES)) + break; + err = 0; + opt->type = token; + break; + case Opt_rdblk: + if (unlikely(match_int(&a->args[0], &n) + || n < 0 + || n > KMALLOC_MAX_SIZE)) { + pr_err("bad integer in %s\n", opt_str); + break; + } + if (unlikely(n && n < NAME_MAX)) { + pr_err("rdblk must be larger than %d\n", + NAME_MAX); + break; + } + opt->rdblk = n; + err = 0; + opt->type = token; + break; + case Opt_rdhash: + if (unlikely(match_int(&a->args[0], &n) + || n < 0 + || n * sizeof(struct hlist_head) + > KMALLOC_MAX_SIZE)) { + pr_err("bad integer in %s\n", opt_str); + break; + } + opt->rdhash = n; + err = 0; + opt->type = token; + break; + + case Opt_trunc_xino: + case Opt_notrunc_xino: + case Opt_noxino: + case Opt_trunc_xib: + case Opt_notrunc_xib: + case Opt_shwh: + case Opt_noshwh: + case Opt_plink: + case Opt_noplink: + case Opt_list_plink: + case Opt_dio: + case Opt_nodio: + case Opt_diropq_a: + case Opt_diropq_w: + case Opt_warn_perm: + case Opt_nowarn_perm: + case Opt_refrof: + case Opt_norefrof: + case Opt_verbose: + case Opt_noverbose: + case Opt_sum: + case Opt_nosum: + case Opt_wsum: + case Opt_rdblk_def: + case Opt_rdhash_def: + err = 0; + opt->type = token; + break; + + case Opt_udba: + opt->udba = udba_val(a->args[0].from); + if (opt->udba >= 0) { + err = 0; + opt->type = token; + } else + pr_err("wrong value, %s\n", opt_str); + break; + + case Opt_wbr_create: + u.create = &opt->wbr_create; + u.create->wbr_create + = au_wbr_create_val(a->args[0].from, u.create); + if (u.create->wbr_create >= 0) { + err = 0; + opt->type = token; + } else + pr_err("wrong value, %s\n", opt_str); + break; + case Opt_wbr_copyup: + opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from); + if (opt->wbr_copyup >= 0) { + err = 0; + opt->type = token; + } else + pr_err("wrong value, %s\n", opt_str); + break; + + case Opt_ignore: + pr_warning("ignored %s\n", opt_str); + /*FALLTHROUGH*/ + case Opt_ignore_silent: + skipped = 1; + err = 0; + break; + case Opt_err: + pr_err("unknown option %s\n", opt_str); + break; + } + + if (!err && !skipped) { + if (unlikely(++opt > opt_tail)) { + err = -E2BIG; + opt--; + opt->type = Opt_tail; + break; + } + opt->type = Opt_tail; + } + } + + kfree(a); + dump_opts(opts); + if (unlikely(err)) + au_opts_free(opts); + +out: + return err; +} + +static int au_opt_wbr_create(struct super_block *sb, + struct au_opt_wbr_create *create) +{ + int err; + struct au_sbinfo *sbinfo; + + SiMustWriteLock(sb); + + err = 1; /* handled */ + sbinfo = au_sbi(sb); + if (sbinfo->si_wbr_create_ops->fin) { + err = sbinfo->si_wbr_create_ops->fin(sb); + if (!err) + err = 1; + } + + sbinfo->si_wbr_create = create->wbr_create; + sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create; + switch (create->wbr_create) { + case AuWbrCreate_MFSRRV: + case AuWbrCreate_MFSRR: + sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark; + /*FALLTHROUGH*/ + case AuWbrCreate_MFS: + case AuWbrCreate_MFSV: + case AuWbrCreate_PMFS: + case AuWbrCreate_PMFSV: + sbinfo->si_wbr_mfs.mfs_expire + = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC); + break; + } + + if (sbinfo->si_wbr_create_ops->init) + sbinfo->si_wbr_create_ops->init(sb); /* ignore */ + + return err; +} + +/* + * returns, + * plus: processed without an error + * zero: unprocessed + */ +static int au_opt_simple(struct super_block *sb, struct au_opt *opt, + struct au_opts *opts) +{ + int err; + struct au_sbinfo *sbinfo; + + SiMustWriteLock(sb); + + err = 1; /* handled */ + sbinfo = au_sbi(sb); + switch (opt->type) { + case Opt_udba: + sbinfo->si_mntflags &= ~AuOptMask_UDBA; + sbinfo->si_mntflags |= opt->udba; + opts->given_udba |= opt->udba; + break; + + case Opt_plink: + au_opt_set(sbinfo->si_mntflags, PLINK); + break; + case Opt_noplink: + if (au_opt_test(sbinfo->si_mntflags, PLINK)) + au_plink_put(sb, /*verbose*/1); + au_opt_clr(sbinfo->si_mntflags, PLINK); + break; + case Opt_list_plink: + if (au_opt_test(sbinfo->si_mntflags, PLINK)) + au_plink_list(sb); + break; + + case Opt_dio: + au_opt_set(sbinfo->si_mntflags, DIO); + au_fset_opts(opts->flags, REFRESH_DYAOP); + break; + case Opt_nodio: + au_opt_clr(sbinfo->si_mntflags, DIO); + au_fset_opts(opts->flags, REFRESH_DYAOP); + break; + + case Opt_diropq_a: + au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ); + break; + case Opt_diropq_w: + au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ); + break; + + case Opt_warn_perm: + au_opt_set(sbinfo->si_mntflags, WARN_PERM); + break; + case Opt_nowarn_perm: + au_opt_clr(sbinfo->si_mntflags, WARN_PERM); + break; + + case Opt_refrof: + au_opt_set(sbinfo->si_mntflags, REFROF); + break; + case Opt_norefrof: + au_opt_clr(sbinfo->si_mntflags, REFROF); + break; + + case Opt_verbose: + au_opt_set(sbinfo->si_mntflags, VERBOSE); + break; + case Opt_noverbose: + au_opt_clr(sbinfo->si_mntflags, VERBOSE); + break; + + case Opt_sum: + au_opt_set(sbinfo->si_mntflags, SUM); + break; + case Opt_wsum: + au_opt_clr(sbinfo->si_mntflags, SUM); + au_opt_set(sbinfo->si_mntflags, SUM_W); + case Opt_nosum: + au_opt_clr(sbinfo->si_mntflags, SUM); + au_opt_clr(sbinfo->si_mntflags, SUM_W); + break; + + case Opt_wbr_create: + err = au_opt_wbr_create(sb, &opt->wbr_create); + break; + case Opt_wbr_copyup: + sbinfo->si_wbr_copyup = opt->wbr_copyup; + sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup; + break; + + case Opt_dirwh: + sbinfo->si_dirwh = opt->dirwh; + break; + + case Opt_rdcache: + sbinfo->si_rdcache + = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC); + break; + case Opt_rdblk: + sbinfo->si_rdblk = opt->rdblk; + break; + case Opt_rdblk_def: + sbinfo->si_rdblk = AUFS_RDBLK_DEF; + break; + case Opt_rdhash: + sbinfo->si_rdhash = opt->rdhash; + break; + case Opt_rdhash_def: + sbinfo->si_rdhash = AUFS_RDHASH_DEF; + break; + + case Opt_shwh: + au_opt_set(sbinfo->si_mntflags, SHWH); + break; + case Opt_noshwh: + au_opt_clr(sbinfo->si_mntflags, SHWH); + break; + + case Opt_trunc_xino: + au_opt_set(sbinfo->si_mntflags, TRUNC_XINO); + break; + case Opt_notrunc_xino: + au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO); + break; + + case Opt_trunc_xino_path: + case Opt_itrunc_xino: + err = au_xino_trunc(sb, opt->xino_itrunc.bindex); + if (!err) + err = 1; + break; + + case Opt_trunc_xib: + au_fset_opts(opts->flags, TRUNC_XIB); + break; + case Opt_notrunc_xib: + au_fclr_opts(opts->flags, TRUNC_XIB); + break; + + default: + err = 0; + break; + } + + return err; +} + +/* + * returns tri-state. + * plus: processed without an error + * zero: unprocessed + * minus: error + */ +static int au_opt_br(struct super_block *sb, struct au_opt *opt, + struct au_opts *opts) +{ + int err, do_refresh; + + err = 0; + switch (opt->type) { + case Opt_append: + opt->add.bindex = au_sbend(sb) + 1; + if (opt->add.bindex < 0) + opt->add.bindex = 0; + goto add; + case Opt_prepend: + opt->add.bindex = 0; + add: + case Opt_add: + err = au_br_add(sb, &opt->add, + au_ftest_opts(opts->flags, REMOUNT)); + if (!err) { + err = 1; + au_fset_opts(opts->flags, REFRESH_DIR); + au_fset_opts(opts->flags, REFRESH_NONDIR); + } + break; + + case Opt_del: + case Opt_idel: + err = au_br_del(sb, &opt->del, + au_ftest_opts(opts->flags, REMOUNT)); + if (!err) { + err = 1; + au_fset_opts(opts->flags, TRUNC_XIB); + au_fset_opts(opts->flags, REFRESH_DIR); + au_fset_opts(opts->flags, REFRESH_NONDIR); + } + break; + + case Opt_mod: + case Opt_imod: + err = au_br_mod(sb, &opt->mod, + au_ftest_opts(opts->flags, REMOUNT), + &do_refresh); + if (!err) { + err = 1; + if (do_refresh) { + au_fset_opts(opts->flags, REFRESH_DIR); + au_fset_opts(opts->flags, REFRESH_NONDIR); + } + } + break; + } + + return err; +} + +static int au_opt_xino(struct super_block *sb, struct au_opt *opt, + struct au_opt_xino **opt_xino, + struct au_opts *opts) +{ + int err; + aufs_bindex_t bend, bindex; + struct dentry *root, *parent, *h_root; + + err = 0; + switch (opt->type) { + case Opt_xino: + err = au_xino_set(sb, &opt->xino, + !!au_ftest_opts(opts->flags, REMOUNT)); + if (unlikely(err)) + break; + + *opt_xino = &opt->xino; + au_xino_brid_set(sb, -1); + + /* safe d_parent access */ + parent = opt->xino.file->f_dentry->d_parent; + root = sb->s_root; + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) { + h_root = au_h_dptr(root, bindex); + if (h_root == parent) { + au_xino_brid_set(sb, au_sbr_id(sb, bindex)); + break; + } + } + break; + + case Opt_noxino: + au_xino_clr(sb); + au_xino_brid_set(sb, -1); + *opt_xino = (void *)-1; + break; + } + + return err; +} + +int au_opts_verify(struct super_block *sb, unsigned long sb_flags, + unsigned int pending) +{ + int err; + aufs_bindex_t bindex, bend; + unsigned char do_plink, skip, do_free; + struct au_branch *br; + struct au_wbr *wbr; + struct dentry *root; + struct inode *dir, *h_dir; + struct au_sbinfo *sbinfo; + struct au_hinode *hdir; + + SiMustAnyLock(sb); + + sbinfo = au_sbi(sb); + AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA)); + + if (!(sb_flags & MS_RDONLY)) { + if (unlikely(!au_br_writable(au_sbr_perm(sb, 0)))) + pr_warning("first branch should be rw\n"); + if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH))) + pr_warning("shwh should be used with ro\n"); + } + + if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY) + && !au_opt_test(sbinfo->si_mntflags, XINO)) + pr_warning("udba=*notify requires xino\n"); + + err = 0; + root = sb->s_root; + dir = root->d_inode; + do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK); + bend = au_sbend(sb); + for (bindex = 0; !err && bindex <= bend; bindex++) { + skip = 0; + h_dir = au_h_iptr(dir, bindex); + br = au_sbr(sb, bindex); + do_free = 0; + + wbr = br->br_wbr; + if (wbr) + wbr_wh_read_lock(wbr); + + switch (br->br_perm) { + case AuBrPerm_RO: + case AuBrPerm_ROWH: + case AuBrPerm_RR: + case AuBrPerm_RRWH: + do_free = !!wbr; + skip = (!wbr + || (!wbr->wbr_whbase + && !wbr->wbr_plink + && !wbr->wbr_orph)); + break; + + case AuBrPerm_RWNoLinkWH: + /* skip = (!br->br_whbase && !br->br_orph); */ + skip = (!wbr || !wbr->wbr_whbase); + if (skip && wbr) { + if (do_plink) + skip = !!wbr->wbr_plink; + else + skip = !wbr->wbr_plink; + } + break; + + case AuBrPerm_RW: + /* skip = (br->br_whbase && br->br_ohph); */ + skip = (wbr && wbr->wbr_whbase); + if (skip) { + if (do_plink) + skip = !!wbr->wbr_plink; + else + skip = !wbr->wbr_plink; + } + break; + + default: + BUG(); + } + if (wbr) + wbr_wh_read_unlock(wbr); + + if (skip) + continue; + + hdir = au_hi(dir, bindex); + au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT); + if (wbr) + wbr_wh_write_lock(wbr); + err = au_wh_init(au_h_dptr(root, bindex), br, sb); + if (wbr) + wbr_wh_write_unlock(wbr); + au_hn_imtx_unlock(hdir); + + if (!err && do_free) { + kfree(wbr); + br->br_wbr = NULL; + } + } + + return err; +} + +int au_opts_mount(struct super_block *sb, struct au_opts *opts) +{ + int err; + unsigned int tmp; + aufs_bindex_t bend; + struct au_opt *opt; + struct au_opt_xino *opt_xino, xino; + struct au_sbinfo *sbinfo; + + SiMustWriteLock(sb); + + err = 0; + opt_xino = NULL; + opt = opts->opt; + while (err >= 0 && opt->type != Opt_tail) + err = au_opt_simple(sb, opt++, opts); + if (err > 0) + err = 0; + else if (unlikely(err < 0)) + goto out; + + /* disable xino and udba temporary */ + sbinfo = au_sbi(sb); + tmp = sbinfo->si_mntflags; + au_opt_clr(sbinfo->si_mntflags, XINO); + au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL); + + opt = opts->opt; + while (err >= 0 && opt->type != Opt_tail) + err = au_opt_br(sb, opt++, opts); + if (err > 0) + err = 0; + else if (unlikely(err < 0)) + goto out; + + bend = au_sbend(sb); + if (unlikely(bend < 0)) { + err = -EINVAL; + pr_err("no branches\n"); + goto out; + } + + if (au_opt_test(tmp, XINO)) + au_opt_set(sbinfo->si_mntflags, XINO); + opt = opts->opt; + while (!err && opt->type != Opt_tail) + err = au_opt_xino(sb, opt++, &opt_xino, opts); + if (unlikely(err)) + goto out; + + err = au_opts_verify(sb, sb->s_flags, tmp); + if (unlikely(err)) + goto out; + + /* restore xino */ + if (au_opt_test(tmp, XINO) && !opt_xino) { + xino.file = au_xino_def(sb); + err = PTR_ERR(xino.file); + if (IS_ERR(xino.file)) + goto out; + + err = au_xino_set(sb, &xino, /*remount*/0); + fput(xino.file); + if (unlikely(err)) + goto out; + } + + /* restore udba */ + sbinfo->si_mntflags &= ~AuOptMask_UDBA; + sbinfo->si_mntflags |= (tmp & AuOptMask_UDBA); + if (au_opt_test(tmp, UDBA_HNOTIFY)) { + struct inode *dir = sb->s_root->d_inode; + au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO); + } + +out: + return err; +} + +int au_opts_remount(struct super_block *sb, struct au_opts *opts) +{ + int err, rerr; + struct inode *dir; + struct au_opt_xino *opt_xino; + struct au_opt *opt; + struct au_sbinfo *sbinfo; + + SiMustWriteLock(sb); + + dir = sb->s_root->d_inode; + sbinfo = au_sbi(sb); + err = 0; + opt_xino = NULL; + opt = opts->opt; + while (err >= 0 && opt->type != Opt_tail) { + err = au_opt_simple(sb, opt, opts); + if (!err) + err = au_opt_br(sb, opt, opts); + if (!err) + err = au_opt_xino(sb, opt, &opt_xino, opts); + opt++; + } + if (err > 0) + err = 0; + AuTraceErr(err); + /* go on even err */ + + rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0); + if (unlikely(rerr && !err)) + err = rerr; + + if (au_ftest_opts(opts->flags, TRUNC_XIB)) { + rerr = au_xib_trunc(sb); + if (unlikely(rerr && !err)) + err = rerr; + } + + /* will be handled by the caller */ + if (!au_ftest_opts(opts->flags, REFRESH_DIR) + && (opts->given_udba || au_opt_test(sbinfo->si_mntflags, XINO))) + au_fset_opts(opts->flags, REFRESH_DIR); + + AuDbg("status 0x%x\n", opts->flags); + return err; +} + +/* ---------------------------------------------------------------------- */ + +unsigned int au_opt_udba(struct super_block *sb) +{ + return au_mntflags(sb) & AuOptMask_UDBA; +} --- linux-2.6.37.orig/ubuntu/aufs/opts.h +++ linux-2.6.37/ubuntu/aufs/opts.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * mount options/flags + */ + +#ifndef __AUFS_OPTS_H__ +#define __AUFS_OPTS_H__ + +#ifdef __KERNEL__ + +#include +#include + +struct file; +struct super_block; + +/* ---------------------------------------------------------------------- */ + +/* mount flags */ +#define AuOpt_XINO 1 /* external inode number bitmap + and translation table */ +#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */ +#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */ +#define AuOpt_UDBA_REVAL (1 << 3) +#define AuOpt_UDBA_HNOTIFY (1 << 4) +#define AuOpt_SHWH (1 << 5) /* show whiteout */ +#define AuOpt_PLINK (1 << 6) /* pseudo-link */ +#define AuOpt_DIRPERM1 (1 << 7) /* unimplemented */ +#define AuOpt_REFROF (1 << 8) /* unimplemented */ +#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */ +#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */ +#define AuOpt_SUM_W (1 << 11) /* unimplemented */ +#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */ +#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */ +#define AuOpt_DIO (1 << 14) /* direct io */ + +#ifndef CONFIG_AUFS_HNOTIFY +#undef AuOpt_UDBA_HNOTIFY +#define AuOpt_UDBA_HNOTIFY 0 +#endif +#ifndef CONFIG_AUFS_SHWH +#undef AuOpt_SHWH +#define AuOpt_SHWH 0 +#endif + +#define AuOpt_Def (AuOpt_XINO \ + | AuOpt_UDBA_REVAL \ + | AuOpt_PLINK \ + /* | AuOpt_DIRPERM1 */ \ + | AuOpt_WARN_PERM) +#define AuOptMask_UDBA (AuOpt_UDBA_NONE \ + | AuOpt_UDBA_REVAL \ + | AuOpt_UDBA_HNOTIFY) + +#define au_opt_test(flags, name) (flags & AuOpt_##name) +#define au_opt_set(flags, name) do { \ + BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \ + ((flags) |= AuOpt_##name); \ +} while (0) +#define au_opt_set_udba(flags, name) do { \ + (flags) &= ~AuOptMask_UDBA; \ + ((flags) |= AuOpt_##name); \ +} while (0) +#define au_opt_clr(flags, name) do { \ + ((flags) &= ~AuOpt_##name); \ +} while (0) + +static inline unsigned int au_opts_plink(unsigned int mntflags) +{ +#ifdef CONFIG_PROC_FS + return mntflags; +#else + return mntflags & ~AuOpt_PLINK; +#endif +} + +/* ---------------------------------------------------------------------- */ + +/* policies to select one among multiple writable branches */ +enum { + AuWbrCreate_TDP, /* top down parent */ + AuWbrCreate_RR, /* round robin */ + AuWbrCreate_MFS, /* most free space */ + AuWbrCreate_MFSV, /* mfs with seconds */ + AuWbrCreate_MFSRR, /* mfs then rr */ + AuWbrCreate_MFSRRV, /* mfs then rr with seconds */ + AuWbrCreate_PMFS, /* parent and mfs */ + AuWbrCreate_PMFSV, /* parent and mfs with seconds */ + + AuWbrCreate_Def = AuWbrCreate_TDP +}; + +enum { + AuWbrCopyup_TDP, /* top down parent */ + AuWbrCopyup_BUP, /* bottom up parent */ + AuWbrCopyup_BU, /* bottom up */ + + AuWbrCopyup_Def = AuWbrCopyup_TDP +}; + +/* ---------------------------------------------------------------------- */ + +struct au_opt_add { + aufs_bindex_t bindex; + char *pathname; + int perm; + struct path path; +}; + +struct au_opt_del { + char *pathname; + struct path h_path; +}; + +struct au_opt_mod { + char *path; + int perm; + struct dentry *h_root; +}; + +struct au_opt_xino { + char *path; + struct file *file; +}; + +struct au_opt_xino_itrunc { + aufs_bindex_t bindex; +}; + +struct au_opt_wbr_create { + int wbr_create; + int mfs_second; + unsigned long long mfsrr_watermark; +}; + +struct au_opt { + int type; + union { + struct au_opt_xino xino; + struct au_opt_xino_itrunc xino_itrunc; + struct au_opt_add add; + struct au_opt_del del; + struct au_opt_mod mod; + int dirwh; + int rdcache; + unsigned int rdblk; + unsigned int rdhash; + int udba; + struct au_opt_wbr_create wbr_create; + int wbr_copyup; + }; +}; + +/* opts flags */ +#define AuOpts_REMOUNT 1 +#define AuOpts_REFRESH_DIR (1 << 1) +#define AuOpts_REFRESH_NONDIR (1 << 2) +#define AuOpts_TRUNC_XIB (1 << 3) +#define AuOpts_REFRESH_DYAOP (1 << 4) +#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name) +#define au_fset_opts(flags, name) \ + do { (flags) |= AuOpts_##name; } while (0) +#define au_fclr_opts(flags, name) \ + do { (flags) &= ~AuOpts_##name; } while (0) + +struct au_opts { + struct au_opt *opt; + int max_opt; + + unsigned int given_udba; + unsigned int flags; + unsigned long sb_flags; +}; + +/* ---------------------------------------------------------------------- */ + +const char *au_optstr_br_perm(int brperm); +const char *au_optstr_udba(int udba); +const char *au_optstr_wbr_copyup(int wbr_copyup); +const char *au_optstr_wbr_create(int wbr_create); + +void au_opts_free(struct au_opts *opts); +int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts); +int au_opts_verify(struct super_block *sb, unsigned long sb_flags, + unsigned int pending); +int au_opts_mount(struct super_block *sb, struct au_opts *opts); +int au_opts_remount(struct super_block *sb, struct au_opts *opts); + +unsigned int au_opt_udba(struct super_block *sb); + +/* ---------------------------------------------------------------------- */ + +#endif /* __KERNEL__ */ +#endif /* __AUFS_OPTS_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/plink.c +++ linux-2.6.37/ubuntu/aufs/plink.c @@ -0,0 +1,522 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * pseudo-link + */ + +#include "aufs.h" + +/* + * the pseudo-link maintenance mode. + * during a user process maintains the pseudo-links, + * prohibit adding a new plink and branch manipulation. + * + * Flags + * NOPLM: + * For entry functions which will handle plink, and i_mutex is already held + * in VFS. + * They cannot wait and should return an error at once. + * Callers has to check the error. + * NOPLMW: + * For entry functions which will handle plink, but i_mutex is not held + * in VFS. + * They can wait the plink maintenance mode to finish. + * + * They behave like F_SETLK and F_SETLKW. + * If the caller never handle plink, then both flags are unnecessary. + */ + +int au_plink_maint(struct super_block *sb, int flags) +{ + int err; + pid_t pid, ppid; + struct au_sbinfo *sbi; + + SiMustAnyLock(sb); + + err = 0; + if (!au_opt_test(au_mntflags(sb), PLINK)) + goto out; + + sbi = au_sbi(sb); + pid = sbi->si_plink_maint_pid; + if (!pid || pid == current->pid) + goto out; + + /* todo: it highly depends upon /sbin/mount.aufs */ + rcu_read_lock(); + ppid = task_pid_vnr(rcu_dereference(current->real_parent)); + rcu_read_unlock(); + if (pid == ppid) + goto out; + + if (au_ftest_lock(flags, NOPLMW)) { + /* + * todo: debug by lockdep, if there is no i_mutex lock in VFS, + * we don't need to wait. + */ + while (sbi->si_plink_maint_pid) { + si_read_unlock(sb); + /* gave up wake_up_bit() */ + wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid); + + if (au_ftest_lock(flags, FLUSH)) + au_nwt_flush(&sbi->si_nowait); + si_noflush_read_lock(sb); + } + } else if (au_ftest_lock(flags, NOPLM)) { + AuDbg("ppid %d, pid %d\n", ppid, pid); + err = -EAGAIN; + } + +out: + return err; +} + +void au_plink_maint_leave(struct au_sbinfo *sbinfo) +{ + int iam; + + spin_lock(&sbinfo->si_plink_maint_lock); + iam = (sbinfo->si_plink_maint_pid == current->pid); + if (iam) + sbinfo->si_plink_maint_pid = 0; + spin_unlock(&sbinfo->si_plink_maint_lock); + if (iam) + wake_up_all(&sbinfo->si_plink_wq); +} + +int au_plink_maint_enter(struct super_block *sb) +{ + int err; + struct au_sbinfo *sbinfo; + + err = 0; + sbinfo = au_sbi(sb); + /* make sure i am the only one in this fs */ + si_write_lock(sb, AuLock_FLUSH); + if (au_opt_test(au_mntflags(sb), PLINK)) { + spin_lock(&sbinfo->si_plink_maint_lock); + if (!sbinfo->si_plink_maint_pid) + sbinfo->si_plink_maint_pid = current->pid; + else + err = -EBUSY; + spin_unlock(&sbinfo->si_plink_maint_lock); + } + si_write_unlock(sb); + + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct pseudo_link { + union { + struct list_head list; + struct rcu_head rcu; + }; + struct inode *inode; +}; + +#ifdef CONFIG_AUFS_DEBUG +void au_plink_list(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + struct list_head *plink_list; + struct pseudo_link *plink; + + SiMustAnyLock(sb); + + sbinfo = au_sbi(sb); + AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); + AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); + + plink_list = &sbinfo->si_plink.head; + rcu_read_lock(); + list_for_each_entry_rcu(plink, plink_list, list) + AuDbg("%lu\n", plink->inode->i_ino); + rcu_read_unlock(); +} +#endif + +/* is the inode pseudo-linked? */ +int au_plink_test(struct inode *inode) +{ + int found; + struct au_sbinfo *sbinfo; + struct list_head *plink_list; + struct pseudo_link *plink; + + sbinfo = au_sbi(inode->i_sb); + AuRwMustAnyLock(&sbinfo->si_rwsem); + AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK)); + AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); + + found = 0; + plink_list = &sbinfo->si_plink.head; + rcu_read_lock(); + list_for_each_entry_rcu(plink, plink_list, list) + if (plink->inode == inode) { + found = 1; + break; + } + rcu_read_unlock(); + return found; +} + +/* ---------------------------------------------------------------------- */ + +/* + * generate a name for plink. + * the file will be stored under AUFS_WH_PLINKDIR. + */ +/* 20 is max digits length of ulong 64 */ +#define PLINK_NAME_LEN ((20 + 1) * 2) + +static int plink_name(char *name, int len, struct inode *inode, + aufs_bindex_t bindex) +{ + int rlen; + struct inode *h_inode; + + h_inode = au_h_iptr(inode, bindex); + rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino); + return rlen; +} + +struct au_do_plink_lkup_args { + struct dentry **errp; + struct qstr *tgtname; + struct dentry *h_parent; + struct au_branch *br; +}; + +static struct dentry *au_do_plink_lkup(struct qstr *tgtname, + struct dentry *h_parent, + struct au_branch *br) +{ + struct dentry *h_dentry; + struct mutex *h_mtx; + + h_mtx = &h_parent->d_inode->i_mutex; + mutex_lock_nested(h_mtx, AuLsc_I_CHILD2); + h_dentry = au_lkup_one(tgtname, h_parent, br, /*nd*/NULL); + mutex_unlock(h_mtx); + return h_dentry; +} + +static void au_call_do_plink_lkup(void *args) +{ + struct au_do_plink_lkup_args *a = args; + *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br); +} + +/* lookup the plink-ed @inode under the branch at @bindex */ +struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex) +{ + struct dentry *h_dentry, *h_parent; + struct au_branch *br; + struct inode *h_dir; + int wkq_err; + char a[PLINK_NAME_LEN]; + struct qstr tgtname = { + .name = a + }; + + AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); + + br = au_sbr(inode->i_sb, bindex); + h_parent = br->br_wbr->wbr_plink; + h_dir = h_parent->d_inode; + tgtname.len = plink_name(a, sizeof(a), inode, bindex); + + if (current_fsuid()) { + struct au_do_plink_lkup_args args = { + .errp = &h_dentry, + .tgtname = &tgtname, + .h_parent = h_parent, + .br = br + }; + + wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args); + if (unlikely(wkq_err)) + h_dentry = ERR_PTR(wkq_err); + } else + h_dentry = au_do_plink_lkup(&tgtname, h_parent, br); + + return h_dentry; +} + +/* create a pseudo-link */ +static int do_whplink(struct qstr *tgt, struct dentry *h_parent, + struct dentry *h_dentry, struct au_branch *br) +{ + int err; + struct path h_path = { + .mnt = br->br_mnt + }; + struct inode *h_dir; + + h_dir = h_parent->d_inode; + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_CHILD2); +again: + h_path.dentry = au_lkup_one(tgt, h_parent, br, /*nd*/NULL); + err = PTR_ERR(h_path.dentry); + if (IS_ERR(h_path.dentry)) + goto out; + + err = 0; + /* wh.plink dir is not monitored */ + /* todo: is it really safe? */ + if (h_path.dentry->d_inode + && h_path.dentry->d_inode != h_dentry->d_inode) { + err = vfsub_unlink(h_dir, &h_path, /*force*/0); + dput(h_path.dentry); + h_path.dentry = NULL; + if (!err) + goto again; + } + if (!err && !h_path.dentry->d_inode) + err = vfsub_link(h_dentry, h_dir, &h_path); + dput(h_path.dentry); + +out: + mutex_unlock(&h_dir->i_mutex); + return err; +} + +struct do_whplink_args { + int *errp; + struct qstr *tgt; + struct dentry *h_parent; + struct dentry *h_dentry; + struct au_branch *br; +}; + +static void call_do_whplink(void *args) +{ + struct do_whplink_args *a = args; + *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br); +} + +static int whplink(struct dentry *h_dentry, struct inode *inode, + aufs_bindex_t bindex, struct au_branch *br) +{ + int err, wkq_err; + struct au_wbr *wbr; + struct dentry *h_parent; + struct inode *h_dir; + char a[PLINK_NAME_LEN]; + struct qstr tgtname = { + .name = a + }; + + wbr = au_sbr(inode->i_sb, bindex)->br_wbr; + h_parent = wbr->wbr_plink; + h_dir = h_parent->d_inode; + tgtname.len = plink_name(a, sizeof(a), inode, bindex); + + /* always superio. */ + if (current_fsuid()) { + struct do_whplink_args args = { + .errp = &err, + .tgt = &tgtname, + .h_parent = h_parent, + .h_dentry = h_dentry, + .br = br + }; + wkq_err = au_wkq_wait(call_do_whplink, &args); + if (unlikely(wkq_err)) + err = wkq_err; + } else + err = do_whplink(&tgtname, h_parent, h_dentry, br); + + return err; +} + +/* free a single plink */ +static void do_put_plink(struct pseudo_link *plink, int do_del) +{ + if (do_del) + list_del(&plink->list); + iput(plink->inode); + kfree(plink); +} + +static void do_put_plink_rcu(struct rcu_head *rcu) +{ + struct pseudo_link *plink; + + plink = container_of(rcu, struct pseudo_link, rcu); + iput(plink->inode); + kfree(plink); +} + +/* + * create a new pseudo-link for @h_dentry on @bindex. + * the linked inode is held in aufs @inode. + */ +void au_plink_append(struct inode *inode, aufs_bindex_t bindex, + struct dentry *h_dentry) +{ + struct super_block *sb; + struct au_sbinfo *sbinfo; + struct list_head *plink_list; + struct pseudo_link *plink, *tmp; + int found, err, cnt; + + sb = inode->i_sb; + sbinfo = au_sbi(sb); + AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); + AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); + + cnt = 0; + found = 0; + plink_list = &sbinfo->si_plink.head; + rcu_read_lock(); + list_for_each_entry_rcu(plink, plink_list, list) { + cnt++; + if (plink->inode == inode) { + found = 1; + break; + } + } + rcu_read_unlock(); + if (found) + return; + + tmp = kmalloc(sizeof(*plink), GFP_NOFS); + if (tmp) + tmp->inode = au_igrab(inode); + else { + err = -ENOMEM; + goto out; + } + + spin_lock(&sbinfo->si_plink.spin); + list_for_each_entry(plink, plink_list, list) { + if (plink->inode == inode) { + found = 1; + break; + } + } + if (!found) + list_add_rcu(&tmp->list, plink_list); + spin_unlock(&sbinfo->si_plink.spin); + if (!found) { + cnt++; + WARN_ONCE(cnt > AUFS_PLINK_WARN, + "unexpectedly many pseudo links, %d\n", cnt); + err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex)); + } else { + do_put_plink(tmp, 0); + return; + } + +out: + if (unlikely(err)) { + pr_warning("err %d, damaged pseudo link.\n", err); + if (tmp) { + au_spl_del_rcu(&tmp->list, &sbinfo->si_plink); + call_rcu(&tmp->rcu, do_put_plink_rcu); + } + } +} + +/* free all plinks */ +void au_plink_put(struct super_block *sb, int verbose) +{ + struct au_sbinfo *sbinfo; + struct list_head *plink_list; + struct pseudo_link *plink, *tmp; + + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); + AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); + AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); + + plink_list = &sbinfo->si_plink.head; + /* no spin_lock since sbinfo is write-locked */ + WARN(verbose && !list_empty(plink_list), "pseudo-link is not flushed"); + list_for_each_entry_safe(plink, tmp, plink_list, list) + do_put_plink(plink, 0); + INIT_LIST_HEAD(plink_list); +} + +void au_plink_clean(struct super_block *sb, int verbose) +{ + struct dentry *root; + + root = sb->s_root; + aufs_write_lock(root); + if (au_opt_test(au_mntflags(sb), PLINK)) + au_plink_put(sb, verbose); + aufs_write_unlock(root); +} + +/* free the plinks on a branch specified by @br_id */ +void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id) +{ + struct au_sbinfo *sbinfo; + struct list_head *plink_list; + struct pseudo_link *plink, *tmp; + struct inode *inode; + aufs_bindex_t bstart, bend, bindex; + unsigned char do_put; + + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); + AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK)); + AuDebugOn(au_plink_maint(sb, AuLock_NOPLM)); + + plink_list = &sbinfo->si_plink.head; + /* no spin_lock since sbinfo is write-locked */ + list_for_each_entry_safe(plink, tmp, plink_list, list) { + do_put = 0; + inode = au_igrab(plink->inode); + ii_write_lock_child(inode); + bstart = au_ibstart(inode); + bend = au_ibend(inode); + if (bstart >= 0) { + for (bindex = bstart; bindex <= bend; bindex++) { + if (!au_h_iptr(inode, bindex) + || au_ii_br_id(inode, bindex) != br_id) + continue; + au_set_h_iptr(inode, bindex, NULL, 0); + do_put = 1; + break; + } + } else + do_put_plink(plink, 1); + + if (do_put) { + for (bindex = bstart; bindex <= bend; bindex++) + if (au_h_iptr(inode, bindex)) { + do_put = 0; + break; + } + if (do_put) + do_put_plink(plink, 1); + } + ii_write_unlock(inode); + iput(inode); + } +} --- linux-2.6.37.orig/ubuntu/aufs/poll.c +++ linux-2.6.37/ubuntu/aufs/poll.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * poll operation + * There is only one filesystem which implements ->poll operation, currently. + */ + +#include "aufs.h" + +unsigned int aufs_poll(struct file *file, poll_table *wait) +{ + unsigned int mask; + int err; + struct file *h_file; + struct dentry *dentry; + struct super_block *sb; + + /* We should pretend an error happened. */ + mask = POLLERR /* | POLLIN | POLLOUT */; + dentry = file->f_dentry; + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0); + if (unlikely(err)) + goto out; + + /* it is not an error if h_file has no operation */ + mask = DEFAULT_POLLMASK; + h_file = au_hf_top(file); + if (h_file->f_op && h_file->f_op->poll) + mask = h_file->f_op->poll(h_file, wait); + + di_read_unlock(dentry, AuLock_IR); + fi_read_unlock(file); + +out: + si_read_unlock(sb); + AuTraceErr((int)mask); + return mask; +} --- linux-2.6.37.orig/ubuntu/aufs/procfs.c +++ linux-2.6.37/ubuntu/aufs/procfs.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * procfs interfaces + */ + +#include +#include "aufs.h" + +static int au_procfs_plm_release(struct inode *inode, struct file *file) +{ + struct au_sbinfo *sbinfo; + + sbinfo = file->private_data; + if (sbinfo) { + au_plink_maint_leave(sbinfo); + kobject_put(&sbinfo->si_kobj); + } + + return 0; +} + +static void au_procfs_plm_write_clean(struct file *file) +{ + struct au_sbinfo *sbinfo; + + sbinfo = file->private_data; + if (sbinfo) + au_plink_clean(sbinfo->si_sb, /*verbose*/0); +} + +static int au_procfs_plm_write_si(struct file *file, unsigned long id) +{ + int err; + struct super_block *sb; + struct au_sbinfo *sbinfo; + + err = -EBUSY; + if (unlikely(file->private_data)) + goto out; + + sb = NULL; + spin_lock(&au_sbilist.spin); + list_for_each_entry(sbinfo, &au_sbilist.head, si_list) + if (id == sysaufs_si_id(sbinfo)) { + kobject_get(&sbinfo->si_kobj); + sb = sbinfo->si_sb; + break; + } + spin_unlock(&au_sbilist.spin); + + err = -EINVAL; + if (unlikely(!sb)) + goto out; + + err = au_plink_maint_enter(sb); + if (!err) + /* keep kobject_get() */ + file->private_data = sbinfo; + else + kobject_put(&sbinfo->si_kobj); +out: + return err; +} + +/* + * Accept a valid "si=xxxx" only. + * Once it is accepted successfully, accept "clean" too. + */ +static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf, + size_t count, loff_t *ppos) +{ + ssize_t err; + unsigned long id; + /* last newline is allowed */ + char buf[3 + sizeof(unsigned long) * 2 + 1]; + + err = -EACCES; + if (unlikely(!capable(CAP_SYS_ADMIN))) + goto out; + + err = -EINVAL; + if (unlikely(count > sizeof(buf))) + goto out; + + err = copy_from_user(buf, ubuf, count); + if (unlikely(err)) { + err = -EFAULT; + goto out; + } + buf[count] = 0; + + err = -EINVAL; + if (!strcmp("clean", buf)) { + au_procfs_plm_write_clean(file); + goto out_success; + } else if (unlikely(strncmp("si=", buf, 3))) + goto out; + + err = strict_strtoul(buf + 3, 16, &id); + if (unlikely(err)) + goto out; + + err = au_procfs_plm_write_si(file, id); + if (unlikely(err)) + goto out; + +out_success: + err = count; /* success */ +out: + return err; +} + +static const struct file_operations au_procfs_plm_fop = { + .write = au_procfs_plm_write, + .release = au_procfs_plm_release, + .owner = THIS_MODULE +}; + +/* ---------------------------------------------------------------------- */ + +static struct proc_dir_entry *au_procfs_dir; + +void au_procfs_fin(void) +{ + remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir); + remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); +} + +int __init au_procfs_init(void) +{ + int err; + struct proc_dir_entry *entry; + + err = -ENOMEM; + au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL); + if (unlikely(!au_procfs_dir)) + goto out; + + entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | S_IWUSR, + au_procfs_dir, &au_procfs_plm_fop); + if (unlikely(!entry)) + goto out_dir; + + err = 0; + goto out; /* success */ + + +out_dir: + remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL); +out: + return err; +} --- linux-2.6.37.orig/ubuntu/aufs/rdu.c +++ linux-2.6.37/ubuntu/aufs/rdu.c @@ -0,0 +1,382 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * readdir in userspace. + */ + +#include +#include +#include +#include +#include +#include "aufs.h" + +/* bits for struct aufs_rdu.flags */ +#define AuRdu_CALLED 1 +#define AuRdu_CONT (1 << 1) +#define AuRdu_FULL (1 << 2) +#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name) +#define au_fset_rdu(flags, name) \ + do { (flags) |= AuRdu_##name; } while (0) +#define au_fclr_rdu(flags, name) \ + do { (flags) &= ~AuRdu_##name; } while (0) + +struct au_rdu_arg { + struct aufs_rdu *rdu; + union au_rdu_ent_ul ent; + unsigned long end; + + struct super_block *sb; + int err; +}; + +static int au_rdu_fill(void *__arg, const char *name, int nlen, + loff_t offset, u64 h_ino, unsigned int d_type) +{ + int err, len; + struct au_rdu_arg *arg = __arg; + struct aufs_rdu *rdu = arg->rdu; + struct au_rdu_ent ent; + + err = 0; + arg->err = 0; + au_fset_rdu(rdu->cookie.flags, CALLED); + len = au_rdu_len(nlen); + if (arg->ent.ul + len < arg->end) { + ent.ino = h_ino; + ent.bindex = rdu->cookie.bindex; + ent.type = d_type; + ent.nlen = nlen; + if (unlikely(nlen > AUFS_MAX_NAMELEN)) + ent.type = DT_UNKNOWN; + + err = -EFAULT; + if (copy_to_user(arg->ent.e, &ent, sizeof(ent))) + goto out; + if (copy_to_user(arg->ent.e->name, name, nlen)) + goto out; + /* the terminating NULL */ + if (__put_user(0, arg->ent.e->name + nlen)) + goto out; + err = 0; + /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */ + arg->ent.ul += len; + rdu->rent++; + } else { + err = -EFAULT; + au_fset_rdu(rdu->cookie.flags, FULL); + rdu->full = 1; + rdu->tail = arg->ent; + } + +out: + /* AuTraceErr(err); */ + return err; +} + +static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg) +{ + int err; + loff_t offset; + struct au_rdu_cookie *cookie = &arg->rdu->cookie; + + offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET); + err = offset; + if (unlikely(offset != cookie->h_pos)) + goto out; + + err = 0; + do { + arg->err = 0; + au_fclr_rdu(cookie->flags, CALLED); + /* smp_mb(); */ + err = vfsub_readdir(h_file, au_rdu_fill, arg); + if (err >= 0) + err = arg->err; + } while (!err + && au_ftest_rdu(cookie->flags, CALLED) + && !au_ftest_rdu(cookie->flags, FULL)); + cookie->h_pos = h_file->f_pos; + +out: + AuTraceErr(err); + return err; +} + +static int au_rdu(struct file *file, struct aufs_rdu *rdu) +{ + int err; + aufs_bindex_t bend; + struct au_rdu_arg arg; + struct dentry *dentry; + struct inode *inode; + struct file *h_file; + struct au_rdu_cookie *cookie = &rdu->cookie; + + err = !access_ok(VERIFY_WRITE, rdu->ent.e, rdu->sz); + if (unlikely(err)) { + err = -EFAULT; + AuTraceErr(err); + goto out; + } + rdu->rent = 0; + rdu->tail = rdu->ent; + rdu->full = 0; + arg.rdu = rdu; + arg.ent = rdu->ent; + arg.end = arg.ent.ul; + arg.end += rdu->sz; + + err = -ENOTDIR; + if (unlikely(!file->f_op || !file->f_op->readdir)) + goto out; + + err = security_file_permission(file, MAY_READ); + AuTraceErr(err); + if (unlikely(err)) + goto out; + + dentry = file->f_dentry; + inode = dentry->d_inode; +#if 1 + mutex_lock(&inode->i_mutex); +#else + err = mutex_lock_killable(&inode->i_mutex); + AuTraceErr(err); + if (unlikely(err)) + goto out; +#endif + err = -ENOENT; + if (unlikely(IS_DEADDIR(inode))) + goto out_mtx; + + arg.sb = inode->i_sb; + err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM); + if (unlikely(err)) + goto out_mtx; + /* todo: reval? */ + fi_read_lock(file); + + err = -EAGAIN; + if (unlikely(au_ftest_rdu(cookie->flags, CONT) + && cookie->generation != au_figen(file))) + goto out_unlock; + + err = 0; + if (!rdu->blk) { + rdu->blk = au_sbi(arg.sb)->si_rdblk; + if (!rdu->blk) + rdu->blk = au_dir_size(file, /*dentry*/NULL); + } + bend = au_fbstart(file); + if (cookie->bindex < bend) + cookie->bindex = bend; + bend = au_fbend_dir(file); + /* AuDbg("b%d, b%d\n", cookie->bindex, bend); */ + for (; !err && cookie->bindex <= bend; + cookie->bindex++, cookie->h_pos = 0) { + h_file = au_hf_dir(file, cookie->bindex); + if (!h_file) + continue; + + au_fclr_rdu(cookie->flags, FULL); + err = au_rdu_do(h_file, &arg); + AuTraceErr(err); + if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err)) + break; + } + AuDbg("rent %llu\n", rdu->rent); + + if (!err && !au_ftest_rdu(cookie->flags, CONT)) { + rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH); + au_fset_rdu(cookie->flags, CONT); + cookie->generation = au_figen(file); + } + + ii_read_lock_child(inode); + fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibstart(inode))); + ii_read_unlock(inode); + +out_unlock: + fi_read_unlock(file); + si_read_unlock(arg.sb); +out_mtx: + mutex_unlock(&inode->i_mutex); +out: + AuTraceErr(err); + return err; +} + +static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu) +{ + int err; + ino_t ino; + unsigned long long nent; + union au_rdu_ent_ul *u; + struct au_rdu_ent ent; + struct super_block *sb; + + err = 0; + nent = rdu->nent; + u = &rdu->ent; + sb = file->f_dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); + while (nent-- > 0) { + err = copy_from_user(&ent, u->e, sizeof(ent)); + if (!err) + err = !access_ok(VERIFY_WRITE, &u->e->ino, sizeof(ino)); + if (unlikely(err)) { + err = -EFAULT; + AuTraceErr(err); + break; + } + + /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */ + if (!ent.wh) + err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino); + else + err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type, + &ino); + if (unlikely(err)) { + AuTraceErr(err); + break; + } + + err = __put_user(ino, &u->e->ino); + if (unlikely(err)) { + err = -EFAULT; + AuTraceErr(err); + break; + } + u->ul += au_rdu_len(ent.nlen); + } + si_read_unlock(sb); + + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int au_rdu_verify(struct aufs_rdu *rdu) +{ + AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | " + "%llu, b%d, 0x%x, g%u}\n", + rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ], + rdu->blk, + rdu->rent, rdu->shwh, rdu->full, + rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags, + rdu->cookie.generation); + + if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu)) + return 0; + + AuDbg("%u:%u\n", + rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu)); + return -EINVAL; +} + +long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long err, e; + struct aufs_rdu rdu; + void __user *p = (void __user *)arg; + + err = copy_from_user(&rdu, p, sizeof(rdu)); + if (unlikely(err)) { + err = -EFAULT; + AuTraceErr(err); + goto out; + } + err = au_rdu_verify(&rdu); + if (unlikely(err)) + goto out; + + switch (cmd) { + case AUFS_CTL_RDU: + err = au_rdu(file, &rdu); + if (unlikely(err)) + break; + + e = copy_to_user(p, &rdu, sizeof(rdu)); + if (unlikely(e)) { + err = -EFAULT; + AuTraceErr(err); + } + break; + case AUFS_CTL_RDU_INO: + err = au_rdu_ino(file, &rdu); + break; + + default: + /* err = -ENOTTY; */ + err = -EINVAL; + } + +out: + AuTraceErr(err); + return err; +} + +#ifdef CONFIG_COMPAT +long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long err, e; + struct aufs_rdu rdu; + void __user *p = compat_ptr(arg); + + /* todo: get_user()? */ + err = copy_from_user(&rdu, p, sizeof(rdu)); + if (unlikely(err)) { + err = -EFAULT; + AuTraceErr(err); + goto out; + } + rdu.ent.e = compat_ptr(rdu.ent.ul); + err = au_rdu_verify(&rdu); + if (unlikely(err)) + goto out; + + switch (cmd) { + case AUFS_CTL_RDU: + err = au_rdu(file, &rdu); + if (unlikely(err)) + break; + + rdu.ent.ul = ptr_to_compat(rdu.ent.e); + rdu.tail.ul = ptr_to_compat(rdu.tail.e); + e = copy_to_user(p, &rdu, sizeof(rdu)); + if (unlikely(e)) { + err = -EFAULT; + AuTraceErr(err); + } + break; + case AUFS_CTL_RDU_INO: + err = au_rdu_ino(file, &rdu); + break; + + default: + /* err = -ENOTTY; */ + err = -EINVAL; + } + +out: + AuTraceErr(err); + return err; +} +#endif --- linux-2.6.37.orig/ubuntu/aufs/rwsem.h +++ linux-2.6.37/ubuntu/aufs/rwsem.h @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * simple read-write semaphore wrappers + */ + +#ifndef __AUFS_RWSEM_H__ +#define __AUFS_RWSEM_H__ + +#ifdef __KERNEL__ + +#include +#include "debug.h" + +struct au_rwsem { + struct rw_semaphore rwsem; +#ifdef CONFIG_AUFS_DEBUG + /* just for debugging, not almighty counter */ + atomic_t rcnt, wcnt; +#endif +}; + +#ifdef CONFIG_AUFS_DEBUG +#define AuDbgCntInit(rw) do { \ + atomic_set(&(rw)->rcnt, 0); \ + atomic_set(&(rw)->wcnt, 0); \ + smp_mb(); /* atomic set */ \ +} while (0) + +#define AuDbgRcntInc(rw) atomic_inc(&(rw)->rcnt) +#define AuDbgRcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->rcnt) < 0) +#define AuDbgWcntInc(rw) atomic_inc(&(rw)->wcnt) +#define AuDbgWcntDec(rw) WARN_ON(atomic_dec_return(&(rw)->wcnt) < 0) +#else +#define AuDbgCntInit(rw) do {} while (0) +#define AuDbgRcntInc(rw) do {} while (0) +#define AuDbgRcntDec(rw) do {} while (0) +#define AuDbgWcntInc(rw) do {} while (0) +#define AuDbgWcntDec(rw) do {} while (0) +#endif /* CONFIG_AUFS_DEBUG */ + +/* to debug easier, do not make them inlined functions */ +#define AuRwMustNoWaiters(rw) AuDebugOn(!list_empty(&(rw)->rwsem.wait_list)) +/* rwsem_is_locked() is unusable */ +#define AuRwMustReadLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0) +#define AuRwMustWriteLock(rw) AuDebugOn(atomic_read(&(rw)->wcnt) <= 0) +#define AuRwMustAnyLock(rw) AuDebugOn(atomic_read(&(rw)->rcnt) <= 0 \ + && atomic_read(&(rw)->wcnt) <= 0) +#define AuRwDestroy(rw) AuDebugOn(atomic_read(&(rw)->rcnt) \ + || atomic_read(&(rw)->wcnt)) + +#define au_rw_class(rw, key) lockdep_set_class(&(rw)->rwsem, key) + +static inline void au_rw_init(struct au_rwsem *rw) +{ + AuDbgCntInit(rw); + init_rwsem(&rw->rwsem); +} + +static inline void au_rw_init_wlock(struct au_rwsem *rw) +{ + au_rw_init(rw); + down_write(&rw->rwsem); + AuDbgWcntInc(rw); +} + +static inline void au_rw_init_wlock_nested(struct au_rwsem *rw, + unsigned int lsc) +{ + au_rw_init(rw); + down_write_nested(&rw->rwsem, lsc); + AuDbgWcntInc(rw); +} + +static inline void au_rw_read_lock(struct au_rwsem *rw) +{ + down_read(&rw->rwsem); + AuDbgRcntInc(rw); +} + +static inline void au_rw_read_lock_nested(struct au_rwsem *rw, unsigned int lsc) +{ + down_read_nested(&rw->rwsem, lsc); + AuDbgRcntInc(rw); +} + +static inline void au_rw_read_unlock(struct au_rwsem *rw) +{ + AuRwMustReadLock(rw); + AuDbgRcntDec(rw); + up_read(&rw->rwsem); +} + +static inline void au_rw_dgrade_lock(struct au_rwsem *rw) +{ + AuRwMustWriteLock(rw); + AuDbgRcntInc(rw); + AuDbgWcntDec(rw); + downgrade_write(&rw->rwsem); +} + +static inline void au_rw_write_lock(struct au_rwsem *rw) +{ + down_write(&rw->rwsem); + AuDbgWcntInc(rw); +} + +static inline void au_rw_write_lock_nested(struct au_rwsem *rw, + unsigned int lsc) +{ + down_write_nested(&rw->rwsem, lsc); + AuDbgWcntInc(rw); +} + +static inline void au_rw_write_unlock(struct au_rwsem *rw) +{ + AuRwMustWriteLock(rw); + AuDbgWcntDec(rw); + up_write(&rw->rwsem); +} + +/* why is not _nested version defined */ +static inline int au_rw_read_trylock(struct au_rwsem *rw) +{ + int ret = down_read_trylock(&rw->rwsem); + if (ret) + AuDbgRcntInc(rw); + return ret; +} + +static inline int au_rw_write_trylock(struct au_rwsem *rw) +{ + int ret = down_write_trylock(&rw->rwsem); + if (ret) + AuDbgWcntInc(rw); + return ret; +} + +#undef AuDbgCntInit +#undef AuDbgRcntInc +#undef AuDbgRcntDec +#undef AuDbgWcntInc +#undef AuDbgWcntDec + +#define AuSimpleLockRwsemFuncs(prefix, param, rwsem) \ +static inline void prefix##_read_lock(param) \ +{ au_rw_read_lock(rwsem); } \ +static inline void prefix##_write_lock(param) \ +{ au_rw_write_lock(rwsem); } \ +static inline int prefix##_read_trylock(param) \ +{ return au_rw_read_trylock(rwsem); } \ +static inline int prefix##_write_trylock(param) \ +{ return au_rw_write_trylock(rwsem); } +/* why is not _nested version defined */ +/* static inline void prefix##_read_trylock_nested(param, lsc) +{ au_rw_read_trylock_nested(rwsem, lsc)); } +static inline void prefix##_write_trylock_nestd(param, lsc) +{ au_rw_write_trylock_nested(rwsem, lsc); } */ + +#define AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) \ +static inline void prefix##_read_unlock(param) \ +{ au_rw_read_unlock(rwsem); } \ +static inline void prefix##_write_unlock(param) \ +{ au_rw_write_unlock(rwsem); } \ +static inline void prefix##_downgrade_lock(param) \ +{ au_rw_dgrade_lock(rwsem); } + +#define AuSimpleRwsemFuncs(prefix, param, rwsem) \ + AuSimpleLockRwsemFuncs(prefix, param, rwsem) \ + AuSimpleUnlockRwsemFuncs(prefix, param, rwsem) + +#endif /* __KERNEL__ */ +#endif /* __AUFS_RWSEM_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/sbinfo.c +++ linux-2.6.37/ubuntu/aufs/sbinfo.c @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * superblock private data + */ + +#include +#include "aufs.h" + +/* + * they are necessary regardless sysfs is disabled. + */ +void au_si_free(struct kobject *kobj) +{ + struct au_sbinfo *sbinfo; + char *locked __maybe_unused; /* debug only */ + + sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); + AuDebugOn(!list_empty(&sbinfo->si_plink.head)); + AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len)); + + au_rw_write_lock(&sbinfo->si_rwsem); + au_br_free(sbinfo); + au_rw_write_unlock(&sbinfo->si_rwsem); + + AuDebugOn(radix_tree_gang_lookup + (&sbinfo->au_si_pid.tree, (void **)&locked, + /*first_index*/PID_MAX_DEFAULT - 1, + /*max_items*/sizeof(locked)/sizeof(*locked))); + + kfree(sbinfo->si_branch); + kfree(sbinfo->au_si_pid.bitmap); + mutex_destroy(&sbinfo->si_xib_mtx); + AuRwDestroy(&sbinfo->si_rwsem); + + kfree(sbinfo); +} + +int au_si_alloc(struct super_block *sb) +{ + int err; + struct au_sbinfo *sbinfo; + static struct lock_class_key aufs_si; + + err = -ENOMEM; + sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS); + if (unlikely(!sbinfo)) + goto out; + + BUILD_BUG_ON(sizeof(unsigned long) != + sizeof(*sbinfo->au_si_pid.bitmap)); + sbinfo->au_si_pid.bitmap = kcalloc(BITS_TO_LONGS(PID_MAX_DEFAULT), + sizeof(*sbinfo->au_si_pid.bitmap), + GFP_NOFS); + if (unlikely(!sbinfo->au_si_pid.bitmap)) + goto out_sbinfo; + + /* will be reallocated separately */ + sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS); + if (unlikely(!sbinfo->si_branch)) + goto out_pidmap; + + err = sysaufs_si_init(sbinfo); + if (unlikely(err)) + goto out_br; + + au_nwt_init(&sbinfo->si_nowait); + au_rw_init_wlock(&sbinfo->si_rwsem); + au_rw_class(&sbinfo->si_rwsem, &aufs_si); + spin_lock_init(&sbinfo->au_si_pid.tree_lock); + INIT_RADIX_TREE(&sbinfo->au_si_pid.tree, GFP_ATOMIC | __GFP_NOFAIL); + + atomic_long_set(&sbinfo->si_ninodes, 0); + + atomic_long_set(&sbinfo->si_nfiles, 0); + + sbinfo->si_bend = -1; + + sbinfo->si_wbr_copyup = AuWbrCopyup_Def; + sbinfo->si_wbr_create = AuWbrCreate_Def; + sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup; + sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create; + + sbinfo->si_mntflags = au_opts_plink(AuOpt_Def); + + mutex_init(&sbinfo->si_xib_mtx); + sbinfo->si_xino_brid = -1; + /* leave si_xib_last_pindex and si_xib_next_bit */ + + sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC); + sbinfo->si_rdblk = AUFS_RDBLK_DEF; + sbinfo->si_rdhash = AUFS_RDHASH_DEF; + sbinfo->si_dirwh = AUFS_DIRWH_DEF; + + au_spl_init(&sbinfo->si_plink); + init_waitqueue_head(&sbinfo->si_plink_wq); + spin_lock_init(&sbinfo->si_plink_maint_lock); + + /* leave other members for sysaufs and si_mnt. */ + sbinfo->si_sb = sb; + sb->s_fs_info = sbinfo; + si_pid_set(sb); + au_debug_sbinfo_init(sbinfo); + return 0; /* success */ + +out_br: + kfree(sbinfo->si_branch); +out_pidmap: + kfree(sbinfo->au_si_pid.bitmap); +out_sbinfo: + kfree(sbinfo); +out: + return err; +} + +int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr) +{ + int err, sz; + struct au_branch **brp; + + AuRwMustWriteLock(&sbinfo->si_rwsem); + + err = -ENOMEM; + sz = sizeof(*brp) * (sbinfo->si_bend + 1); + if (unlikely(!sz)) + sz = sizeof(*brp); + brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS); + if (brp) { + sbinfo->si_branch = brp; + err = 0; + } + + return err; +} + +/* ---------------------------------------------------------------------- */ + +unsigned int au_sigen_inc(struct super_block *sb) +{ + unsigned int gen; + + SiMustWriteLock(sb); + + gen = ++au_sbi(sb)->si_generation; + au_update_digen(sb->s_root); + au_update_iigen(sb->s_root->d_inode); + sb->s_root->d_inode->i_version++; + return gen; +} + +aufs_bindex_t au_new_br_id(struct super_block *sb) +{ + aufs_bindex_t br_id; + int i; + struct au_sbinfo *sbinfo; + + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); + for (i = 0; i <= AUFS_BRANCH_MAX; i++) { + br_id = ++sbinfo->si_last_br_id; + AuDebugOn(br_id < 0); + if (br_id && au_br_index(sb, br_id) < 0) + return br_id; + } + + return -1; +} + +/* ---------------------------------------------------------------------- */ + +/* it is ok that new 'nwt' tasks are appended while we are sleeping */ +int si_read_lock(struct super_block *sb, int flags) +{ + int err; + + err = 0; + if (au_ftest_lock(flags, FLUSH)) + au_nwt_flush(&au_sbi(sb)->si_nowait); + + si_noflush_read_lock(sb); + err = au_plink_maint(sb, flags); + if (unlikely(err)) + si_read_unlock(sb); + + return err; +} + +int si_write_lock(struct super_block *sb, int flags) +{ + int err; + + if (au_ftest_lock(flags, FLUSH)) + au_nwt_flush(&au_sbi(sb)->si_nowait); + + si_noflush_write_lock(sb); + err = au_plink_maint(sb, flags); + if (unlikely(err)) + si_write_unlock(sb); + + return err; +} + +/* dentry and super_block lock. call at entry point */ +int aufs_read_lock(struct dentry *dentry, int flags) +{ + int err; + + err = si_read_lock(dentry->d_sb, flags); + if (!err) { + if (au_ftest_lock(flags, DW)) + di_write_lock_child(dentry); + else + di_read_lock_child(dentry, flags); + } + + return err; +} + +void aufs_read_unlock(struct dentry *dentry, int flags) +{ + if (au_ftest_lock(flags, DW)) + di_write_unlock(dentry); + else + di_read_unlock(dentry, flags); + si_read_unlock(dentry->d_sb); +} + +void aufs_write_lock(struct dentry *dentry) +{ + si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW); + di_write_lock_child(dentry); +} + +void aufs_write_unlock(struct dentry *dentry) +{ + di_write_unlock(dentry); + si_write_unlock(dentry->d_sb); +} + +int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags) +{ + int err; + + err = si_read_lock(d1->d_sb, flags); + if (!err) + di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIR)); + return err; +} + +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2) +{ + di_write_unlock2(d1, d2); + si_read_unlock(d1->d_sb); +} + +/* ---------------------------------------------------------------------- */ + +int si_pid_test_slow(struct super_block *sb) +{ + void *p; + + rcu_read_lock(); + p = radix_tree_lookup(&au_sbi(sb)->au_si_pid.tree, current->pid); + rcu_read_unlock(); + + return (long)p; +} + +void si_pid_set_slow(struct super_block *sb) +{ + int err; + struct au_sbinfo *sbinfo; + + AuDebugOn(si_pid_test_slow(sb)); + + sbinfo = au_sbi(sb); + err = radix_tree_preload(GFP_NOFS | __GFP_NOFAIL); + AuDebugOn(err); + spin_lock(&sbinfo->au_si_pid.tree_lock); + err = radix_tree_insert(&sbinfo->au_si_pid.tree, current->pid, + (void *)1); + spin_unlock(&sbinfo->au_si_pid.tree_lock); + AuDebugOn(err); + radix_tree_preload_end(); +} + +void si_pid_clr_slow(struct super_block *sb) +{ + void *p; + struct au_sbinfo *sbinfo; + + AuDebugOn(!si_pid_test_slow(sb)); + + sbinfo = au_sbi(sb); + spin_lock(&sbinfo->au_si_pid.tree_lock); + p = radix_tree_delete(&sbinfo->au_si_pid.tree, current->pid); + spin_unlock(&sbinfo->au_si_pid.tree_lock); + AuDebugOn(1 != (long)p); +} --- linux-2.6.37.orig/ubuntu/aufs/spl.h +++ linux-2.6.37/ubuntu/aufs/spl.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * simple list protected by a spinlock + */ + +#ifndef __AUFS_SPL_H__ +#define __AUFS_SPL_H__ + +#ifdef __KERNEL__ + +#include +#include +#include + +struct au_splhead { + spinlock_t spin; + struct list_head head; +}; + +static inline void au_spl_init(struct au_splhead *spl) +{ + spin_lock_init(&spl->spin); + INIT_LIST_HEAD(&spl->head); +} + +static inline void au_spl_add(struct list_head *list, struct au_splhead *spl) +{ + spin_lock(&spl->spin); + list_add(list, &spl->head); + spin_unlock(&spl->spin); +} + +static inline void au_spl_del(struct list_head *list, struct au_splhead *spl) +{ + spin_lock(&spl->spin); + list_del(list); + spin_unlock(&spl->spin); +} + +static inline void au_spl_del_rcu(struct list_head *list, + struct au_splhead *spl) +{ + spin_lock(&spl->spin); + list_del_rcu(list); + spin_unlock(&spl->spin); +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_SPL_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/super.c +++ linux-2.6.37/ubuntu/aufs/super.c @@ -0,0 +1,957 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * mount and super_block operations + */ + +#include +#include +#include +#include +#include +#include +#include +#include "aufs.h" + +/* + * super_operations + */ +static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused) +{ + struct au_icntnr *c; + + c = au_cache_alloc_icntnr(); + if (c) { + c->vfs_inode.i_version = 1; /* sigen(sb); */ + c->iinfo.ii_hinode = NULL; + return &c->vfs_inode; + } + return NULL; +} + +static void aufs_destroy_inode(struct inode *inode) +{ + au_iinfo_fin(inode); + au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode)); +} + +struct inode *au_iget_locked(struct super_block *sb, ino_t ino) +{ + struct inode *inode; + int err; + + inode = iget_locked(sb, ino); + if (unlikely(!inode)) { + inode = ERR_PTR(-ENOMEM); + goto out; + } + if (!(inode->i_state & I_NEW)) + goto out; + + err = au_xigen_new(inode); + if (!err) + err = au_iinfo_init(inode); + if (!err) + inode->i_version++; + else { + iget_failed(inode); + inode = ERR_PTR(err); + } + +out: + /* never return NULL */ + AuDebugOn(!inode); + AuTraceErrPtr(inode); + return inode; +} + +/* lock free root dinfo */ +static int au_show_brs(struct seq_file *seq, struct super_block *sb) +{ + int err; + aufs_bindex_t bindex, bend; + struct path path; + struct au_hdentry *hdp; + struct au_branch *br; + + err = 0; + bend = au_sbend(sb); + hdp = au_di(sb->s_root)->di_hdentry; + for (bindex = 0; !err && bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + path.mnt = br->br_mnt; + path.dentry = hdp[bindex].hd_dentry; + err = au_seq_path(seq, &path); + if (err > 0) + err = seq_printf(seq, "=%s", + au_optstr_br_perm(br->br_perm)); + if (!err && bindex != bend) + err = seq_putc(seq, ':'); + } + + return err; +} + +static void au_show_wbr_create(struct seq_file *m, int v, + struct au_sbinfo *sbinfo) +{ + const char *pat; + + AuRwMustAnyLock(&sbinfo->si_rwsem); + + seq_printf(m, ",create="); + pat = au_optstr_wbr_create(v); + switch (v) { + case AuWbrCreate_TDP: + case AuWbrCreate_RR: + case AuWbrCreate_MFS: + case AuWbrCreate_PMFS: + seq_printf(m, pat); + break; + case AuWbrCreate_MFSV: + seq_printf(m, /*pat*/"mfs:%lu", + jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire) + / MSEC_PER_SEC); + break; + case AuWbrCreate_PMFSV: + seq_printf(m, /*pat*/"pmfs:%lu", + jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire) + / MSEC_PER_SEC); + break; + case AuWbrCreate_MFSRR: + seq_printf(m, /*pat*/"mfsrr:%llu", + sbinfo->si_wbr_mfs.mfsrr_watermark); + break; + case AuWbrCreate_MFSRRV: + seq_printf(m, /*pat*/"mfsrr:%llu:%lu", + sbinfo->si_wbr_mfs.mfsrr_watermark, + jiffies_to_msecs(sbinfo->si_wbr_mfs.mfs_expire) + / MSEC_PER_SEC); + break; + } +} + +static int au_show_xino(struct seq_file *seq, struct vfsmount *mnt) +{ +#ifdef CONFIG_SYSFS + return 0; +#else + int err; + const int len = sizeof(AUFS_XINO_FNAME) - 1; + aufs_bindex_t bindex, brid; + struct super_block *sb; + struct qstr *name; + struct file *f; + struct dentry *d, *h_root; + struct au_hdentry *hdp; + + AuRwMustAnyLock(&sbinfo->si_rwsem); + + err = 0; + sb = mnt->mnt_sb; + f = au_sbi(sb)->si_xib; + if (!f) + goto out; + + /* stop printing the default xino path on the first writable branch */ + h_root = NULL; + brid = au_xino_brid(sb); + if (brid >= 0) { + bindex = au_br_index(sb, brid); + hdp = au_di(sb->s_root)->di_hdentry; + h_root = hdp[0 + bindex].hd_dentry; + } + d = f->f_dentry; + name = &d->d_name; + /* safe ->d_parent because the file is unlinked */ + if (d->d_parent == h_root + && name->len == len + && !memcmp(name->name, AUFS_XINO_FNAME, len)) + goto out; + + seq_puts(seq, ",xino="); + err = au_xino_path(seq, f); + +out: + return err; +#endif +} + +/* seq_file will re-call me in case of too long string */ +static int aufs_show_options(struct seq_file *m, struct vfsmount *mnt) +{ + int err, n; + unsigned int mnt_flags, v; + struct super_block *sb; + struct au_sbinfo *sbinfo; + +#define AuBool(name, str) do { \ + v = au_opt_test(mnt_flags, name); \ + if (v != au_opt_test(AuOpt_Def, name)) \ + seq_printf(m, ",%s" #str, v ? "" : "no"); \ +} while (0) + +#define AuStr(name, str) do { \ + v = mnt_flags & AuOptMask_##name; \ + if (v != (AuOpt_Def & AuOptMask_##name)) \ + seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \ +} while (0) + +#define AuUInt(name, str, val) do { \ + if (val != AUFS_##name##_DEF) \ + seq_printf(m, "," #str "=%u", val); \ +} while (0) + + /* lock free root dinfo */ + sb = mnt->mnt_sb; + si_noflush_read_lock(sb); + sbinfo = au_sbi(sb); + seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo)); + + mnt_flags = au_mntflags(sb); + if (au_opt_test(mnt_flags, XINO)) { + err = au_show_xino(m, mnt); + if (unlikely(err)) + goto out; + } else + seq_puts(m, ",noxino"); + + AuBool(TRUNC_XINO, trunc_xino); + AuStr(UDBA, udba); + AuBool(SHWH, shwh); + AuBool(PLINK, plink); + AuBool(DIO, dio); + /* AuBool(DIRPERM1, dirperm1); */ + /* AuBool(REFROF, refrof); */ + + v = sbinfo->si_wbr_create; + if (v != AuWbrCreate_Def) + au_show_wbr_create(m, v, sbinfo); + + v = sbinfo->si_wbr_copyup; + if (v != AuWbrCopyup_Def) + seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v)); + + v = au_opt_test(mnt_flags, ALWAYS_DIROPQ); + if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ)) + seq_printf(m, ",diropq=%c", v ? 'a' : 'w'); + + AuUInt(DIRWH, dirwh, sbinfo->si_dirwh); + + n = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC; + AuUInt(RDCACHE, rdcache, n); + + AuUInt(RDBLK, rdblk, sbinfo->si_rdblk); + AuUInt(RDHASH, rdhash, sbinfo->si_rdhash); + + AuBool(SUM, sum); + /* AuBool(SUM_W, wsum); */ + AuBool(WARN_PERM, warn_perm); + AuBool(VERBOSE, verbose); + +out: + /* be sure to print "br:" last */ + if (!sysaufs_brs) { + seq_puts(m, ",br:"); + au_show_brs(m, sb); + } + si_read_unlock(sb); + return 0; + +#undef AuBool +#undef AuStr +#undef AuUInt +} + +/* ---------------------------------------------------------------------- */ + +/* sum mode which returns the summation for statfs(2) */ + +static u64 au_add_till_max(u64 a, u64 b) +{ + u64 old; + + old = a; + a += b; + if (old < a) + return a; + return ULLONG_MAX; +} + +static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf) +{ + int err; + u64 blocks, bfree, bavail, files, ffree; + aufs_bindex_t bend, bindex, i; + unsigned char shared; + struct path h_path; + struct super_block *h_sb; + + blocks = 0; + bfree = 0; + bavail = 0; + files = 0; + ffree = 0; + + err = 0; + bend = au_sbend(sb); + for (bindex = bend; bindex >= 0; bindex--) { + h_path.mnt = au_sbr_mnt(sb, bindex); + h_sb = h_path.mnt->mnt_sb; + shared = 0; + for (i = bindex + 1; !shared && i <= bend; i++) + shared = (au_sbr_sb(sb, i) == h_sb); + if (shared) + continue; + + /* sb->s_root for NFS is unreliable */ + h_path.dentry = h_path.mnt->mnt_root; + err = vfs_statfs(&h_path, buf); + if (unlikely(err)) + goto out; + + blocks = au_add_till_max(blocks, buf->f_blocks); + bfree = au_add_till_max(bfree, buf->f_bfree); + bavail = au_add_till_max(bavail, buf->f_bavail); + files = au_add_till_max(files, buf->f_files); + ffree = au_add_till_max(ffree, buf->f_ffree); + } + + buf->f_blocks = blocks; + buf->f_bfree = bfree; + buf->f_bavail = bavail; + buf->f_files = files; + buf->f_ffree = ffree; + +out: + return err; +} + +static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + int err; + struct path h_path; + struct super_block *sb; + + /* lock free root dinfo */ + sb = dentry->d_sb; + si_noflush_read_lock(sb); + if (!au_opt_test(au_mntflags(sb), SUM)) { + /* sb->s_root for NFS is unreliable */ + h_path.mnt = au_sbr_mnt(sb, 0); + h_path.dentry = h_path.mnt->mnt_root; + err = vfs_statfs(&h_path, buf); + } else + err = au_statfs_sum(sb, buf); + si_read_unlock(sb); + + if (!err) { + buf->f_type = AUFS_SUPER_MAGIC; + buf->f_namelen = AUFS_MAX_NAMELEN; + memset(&buf->f_fsid, 0, sizeof(buf->f_fsid)); + } + /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */ + + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* final actions when unmounting a file system */ +static void aufs_put_super(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + + sbinfo = au_sbi(sb); + if (!sbinfo) + return; + + dbgaufs_si_fin(sbinfo); + kobject_put(&sbinfo->si_kobj); +} + +/* ---------------------------------------------------------------------- */ + +void au_array_free(void *array) +{ + if (array) { + if (!is_vmalloc_addr(array)) + kfree(array); + else + vfree(array); + } +} + +void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg) +{ + void *array; + unsigned long long n; + + array = NULL; + n = 0; + if (!*hint) + goto out; + + if (*hint > ULLONG_MAX / sizeof(array)) { + array = ERR_PTR(-EMFILE); + pr_err("hint %llu\n", *hint); + goto out; + } + + array = kmalloc(sizeof(array) * *hint, GFP_NOFS); + if (unlikely(!array)) + array = vmalloc(sizeof(array) * *hint); + if (unlikely(!array)) { + array = ERR_PTR(-ENOMEM); + goto out; + } + + n = cb(array, *hint, arg); + AuDebugOn(n > *hint); + +out: + *hint = n; + return array; +} + +static unsigned long long au_iarray_cb(void *a, + unsigned long long max __maybe_unused, + void *arg) +{ + unsigned long long n; + struct inode **p, *inode; + struct list_head *head; + + n = 0; + p = a; + head = arg; + spin_lock(&inode_lock); + list_for_each_entry(inode, head, i_sb_list) { + if (!is_bad_inode(inode) + && au_ii(inode)->ii_bstart >= 0) { + au_igrab(inode); + *p++ = inode; + n++; + AuDebugOn(n > max); + } + } + spin_unlock(&inode_lock); + + return n; +} + +struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max) +{ + *max = atomic_long_read(&au_sbi(sb)->si_ninodes); + return au_array_alloc(max, au_iarray_cb, &sb->s_inodes); +} + +void au_iarray_free(struct inode **a, unsigned long long max) +{ + unsigned long long ull; + + for (ull = 0; ull < max; ull++) + iput(a[ull]); + au_array_free(a); +} + +/* ---------------------------------------------------------------------- */ + +/* + * refresh dentry and inode at remount time. + */ +static int do_refresh(struct dentry *dentry, mode_t type, + unsigned int dir_flags) +{ + int err; + struct dentry *parent; + + di_write_lock_child(dentry); + parent = dget_parent(dentry); + di_read_lock_parent(parent, AuLock_IR); + + /* returns the number of positive dentries */ + err = au_refresh_hdentry(dentry, type); + if (err >= 0) { + struct inode *inode = dentry->d_inode; + err = au_refresh_hinode(inode, dentry); + if (!err && type == S_IFDIR) + au_hn_reset(inode, dir_flags); + } + if (unlikely(err)) + pr_err("unrecoverable error %d, %.*s\n", + err, AuDLNPair(dentry)); + + di_read_unlock(parent, AuLock_IR); + dput(parent); + di_write_unlock(dentry); + + return err; +} + +static int test_dir(struct dentry *dentry, void *arg __maybe_unused) +{ + return S_ISDIR(dentry->d_inode->i_mode); +} + +/* gave up consolidating with refresh_nondir() */ +static int refresh_dir(struct dentry *root, unsigned int sigen) +{ + int err, i, j, ndentry, e; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + struct dentry **dentries; + struct inode *inode; + const unsigned int flags = au_hi_flags(root->d_inode, /*isdir*/1); + + err = 0; + list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list) + if (S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) { + ii_write_lock_child(inode); + e = au_refresh_hinode_self(inode, /*do_attr*/1); + ii_write_unlock(inode); + if (unlikely(e)) { + AuDbg("e %d, i%lu\n", e, inode->i_ino); + if (!err) + err = e; + /* go on even if err */ + } + } + + e = au_dpages_init(&dpages, GFP_NOFS); + if (unlikely(e)) { + if (!err) + err = e; + goto out; + } + e = au_dcsub_pages(&dpages, root, test_dir, NULL); + if (unlikely(e)) { + if (!err) + err = e; + goto out_dpages; + } + + for (i = 0; !e && i < dpages.ndpage; i++) { + dpage = dpages.dpages + i; + dentries = dpage->dentries; + ndentry = dpage->ndentry; + for (j = 0; !e && j < ndentry; j++) { + struct dentry *d; + + d = dentries[j]; + au_dbg_verify_dir_parent(d, sigen); + if (au_digen(d) != sigen) { + e = do_refresh(d, S_IFDIR, flags); + if (unlikely(e && !err)) + err = e; + /* break on err */ + } + } + } + +out_dpages: + au_dpages_free(&dpages); +out: + return err; +} + +static int test_nondir(struct dentry *dentry, void *arg __maybe_unused) +{ + return !S_ISDIR(dentry->d_inode->i_mode); +} + +static int refresh_nondir(struct dentry *root, unsigned int sigen, + int do_dentry) +{ + int err, i, j, ndentry, e; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + struct dentry **dentries; + struct inode *inode; + + err = 0; + list_for_each_entry(inode, &root->d_sb->s_inodes, i_sb_list) + if (!S_ISDIR(inode->i_mode) && au_iigen(inode) != sigen) { + ii_write_lock_child(inode); + e = au_refresh_hinode_self(inode, /*do_attr*/1); + ii_write_unlock(inode); + if (unlikely(e)) { + AuDbg("e %d, i%lu\n", e, inode->i_ino); + if (!err) + err = e; + /* go on even if err */ + } + } + + if (!do_dentry) + goto out; + + e = au_dpages_init(&dpages, GFP_NOFS); + if (unlikely(e)) { + if (!err) + err = e; + goto out; + } + e = au_dcsub_pages(&dpages, root, test_nondir, NULL); + if (unlikely(e)) { + if (!err) + err = e; + goto out_dpages; + } + + for (i = 0; i < dpages.ndpage; i++) { + dpage = dpages.dpages + i; + dentries = dpage->dentries; + ndentry = dpage->ndentry; + for (j = 0; j < ndentry; j++) { + struct dentry *d; + + d = dentries[j]; + au_dbg_verify_nondir_parent(d, sigen); + inode = d->d_inode; + if (inode && au_digen(d) != sigen) { + e = do_refresh(d, inode->i_mode & S_IFMT, + /*dir_flags*/0); + if (unlikely(e && !err)) + err = e; + /* go on even err */ + } + } + } + +out_dpages: + au_dpages_free(&dpages); +out: + return err; +} + +static void au_remount_refresh(struct super_block *sb, unsigned int flags) +{ + int err; + unsigned int sigen; + struct au_sbinfo *sbinfo; + struct dentry *root; + struct inode *inode; + + au_sigen_inc(sb); + sigen = au_sigen(sb); + sbinfo = au_sbi(sb); + au_fclr_si(sbinfo, FAILED_REFRESH_DIRS); + + root = sb->s_root; + DiMustNoWaiters(root); + inode = root->d_inode; + IiMustNoWaiters(inode); + au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1)); + di_write_unlock(root); + + err = refresh_dir(root, sigen); + if (unlikely(err)) { + au_fset_si(sbinfo, FAILED_REFRESH_DIRS); + pr_warning("Refreshing directories failed, ignored (%d)\n", + err); + } + + if (au_ftest_opts(flags, REFRESH_NONDIR)) { + err = refresh_nondir(root, sigen, !err); + if (unlikely(err)) + pr_warning("Refreshing non-directories failed, ignored" + "(%d)\n", err); + } + + /* aufs_write_lock() calls ..._child() */ + di_write_lock_child(root); + au_cpup_attr_all(root->d_inode, /*force*/1); +} + +/* stop extra interpretation of errno in mount(8), and strange error messages */ +static int cvt_err(int err) +{ + AuTraceErr(err); + + switch (err) { + case -ENOENT: + case -ENOTDIR: + case -EEXIST: + case -EIO: + err = -EINVAL; + } + return err; +} + +static int aufs_remount_fs(struct super_block *sb, int *flags, char *data) +{ + int err, do_dx; + unsigned int mntflags; + struct au_opts opts; + struct dentry *root; + struct inode *inode; + struct au_sbinfo *sbinfo; + + err = 0; + root = sb->s_root; + if (!data || !*data) { + err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); + if (!err) { + di_write_lock_child(root); + err = au_opts_verify(sb, *flags, /*pending*/0); + aufs_write_unlock(root); + } + goto out; + } + + err = -ENOMEM; + memset(&opts, 0, sizeof(opts)); + opts.opt = (void *)__get_free_page(GFP_NOFS); + if (unlikely(!opts.opt)) + goto out; + opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); + opts.flags = AuOpts_REMOUNT; + opts.sb_flags = *flags; + + /* parse it before aufs lock */ + err = au_opts_parse(sb, data, &opts); + if (unlikely(err)) + goto out_opts; + + sbinfo = au_sbi(sb); + inode = root->d_inode; + mutex_lock(&inode->i_mutex); + err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); + if (unlikely(err)) + goto out_mtx; + di_write_lock_child(root); + + /* au_opts_remount() may return an error */ + err = au_opts_remount(sb, &opts); + au_opts_free(&opts); + + if (au_ftest_opts(opts.flags, REFRESH_DIR) + || au_ftest_opts(opts.flags, REFRESH_NONDIR)) + au_remount_refresh(sb, opts.flags); + + if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) { + mntflags = au_mntflags(sb); + do_dx = !!au_opt_test(mntflags, DIO); + au_dy_arefresh(do_dx); + } + + aufs_write_unlock(root); + +out_mtx: + mutex_unlock(&inode->i_mutex); +out_opts: + free_page((unsigned long)opts.opt); +out: + err = cvt_err(err); + AuTraceErr(err); + return err; +} + +static const struct super_operations aufs_sop = { + .alloc_inode = aufs_alloc_inode, + .destroy_inode = aufs_destroy_inode, + /* always deleting, no clearing */ + .drop_inode = generic_delete_inode, + .show_options = aufs_show_options, + .statfs = aufs_statfs, + .put_super = aufs_put_super, + .remount_fs = aufs_remount_fs +}; + +/* ---------------------------------------------------------------------- */ + +static int alloc_root(struct super_block *sb) +{ + int err; + struct inode *inode; + struct dentry *root; + + err = -ENOMEM; + inode = au_iget_locked(sb, AUFS_ROOT_INO); + err = PTR_ERR(inode); + if (IS_ERR(inode)) + goto out; + + inode->i_op = &aufs_dir_iop; + inode->i_fop = &aufs_dir_fop; + inode->i_mode = S_IFDIR; + inode->i_nlink = 2; + unlock_new_inode(inode); + + root = d_alloc_root(inode); + if (unlikely(!root)) + goto out_iput; + err = PTR_ERR(root); + if (IS_ERR(root)) + goto out_iput; + + err = au_di_init(root); + if (!err) { + sb->s_root = root; + return 0; /* success */ + } + dput(root); + goto out; /* do not iput */ + +out_iput: + iget_failed(inode); +out: + return err; + +} + +static int aufs_fill_super(struct super_block *sb, void *raw_data, + int silent __maybe_unused) +{ + int err; + struct au_opts opts; + struct dentry *root; + struct inode *inode; + char *arg = raw_data; + + if (unlikely(!arg || !*arg)) { + err = -EINVAL; + pr_err("no arg\n"); + goto out; + } + + err = -ENOMEM; + memset(&opts, 0, sizeof(opts)); + opts.opt = (void *)__get_free_page(GFP_NOFS); + if (unlikely(!opts.opt)) + goto out; + opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); + opts.sb_flags = sb->s_flags; + + err = au_si_alloc(sb); + if (unlikely(err)) + goto out_opts; + + /* all timestamps always follow the ones on the branch */ + sb->s_flags |= MS_NOATIME | MS_NODIRATIME; + sb->s_op = &aufs_sop; + sb->s_magic = AUFS_SUPER_MAGIC; + sb->s_maxbytes = 0; + au_export_init(sb); + + err = alloc_root(sb); + if (unlikely(err)) { + si_write_unlock(sb); + goto out_info; + } + root = sb->s_root; + inode = root->d_inode; + + /* + * actually we can parse options regardless aufs lock here. + * but at remount time, parsing must be done before aufs lock. + * so we follow the same rule. + */ + ii_write_lock_parent(inode); + aufs_write_unlock(root); + err = au_opts_parse(sb, arg, &opts); + if (unlikely(err)) + goto out_root; + + /* lock vfs_inode first, then aufs. */ + mutex_lock(&inode->i_mutex); + aufs_write_lock(root); + err = au_opts_mount(sb, &opts); + au_opts_free(&opts); + aufs_write_unlock(root); + mutex_unlock(&inode->i_mutex); + if (!err) + goto out_opts; /* success */ + +out_root: + dput(root); + sb->s_root = NULL; +out_info: + kobject_put(&au_sbi(sb)->si_kobj); + sb->s_fs_info = NULL; +out_opts: + free_page((unsigned long)opts.opt); +out: + AuTraceErr(err); + err = cvt_err(err); + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags, + const char *dev_name __maybe_unused, + void *raw_data) +{ + struct dentry *root; + struct super_block *sb; + + /* all timestamps always follow the ones on the branch */ + /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */ + root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super); + if (IS_ERR(root)) + goto out; + + sb = root->d_sb; + si_write_lock(sb, !AuLock_FLUSH); + sysaufs_brs_add(sb, 0); + si_write_unlock(sb); + au_sbilist_add(sb); + +out: + return root; +} + +static void aufs_kill_sb(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + + sbinfo = au_sbi(sb); + if (sbinfo) { + au_sbilist_del(sb); + aufs_write_lock(sb->s_root); + if (sbinfo->si_wbr_create_ops->fin) + sbinfo->si_wbr_create_ops->fin(sb); + if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) { + au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE); + au_remount_refresh(sb, /*flags*/0); + } + if (au_opt_test(sbinfo->si_mntflags, PLINK)) + au_plink_put(sb, /*verbose*/1); + au_xino_clr(sb); + aufs_write_unlock(sb->s_root); + + au_plink_maint_leave(sbinfo); + au_nwt_flush(&sbinfo->si_nowait); + } + generic_shutdown_super(sb); +} + +struct file_system_type aufs_fs_type = { + .name = AUFS_FSTYPE, + .fs_flags = + FS_RENAME_DOES_D_MOVE /* a race between rename and others */ + | FS_REVAL_DOT, /* for NFS branch and udba */ + .mount = aufs_mount, + .kill_sb = aufs_kill_sb, + /* no need to __module_get() and module_put(). */ + .owner = THIS_MODULE, +}; --- linux-2.6.37.orig/ubuntu/aufs/super.h +++ linux-2.6.37/ubuntu/aufs/super.h @@ -0,0 +1,526 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * super_block operations + */ + +#ifndef __AUFS_SUPER_H__ +#define __AUFS_SUPER_H__ + +#ifdef __KERNEL__ + +#include +#include +#include "rwsem.h" +#include "spl.h" +#include "wkq.h" + +typedef ssize_t (*au_readf_t)(struct file *, char __user *, size_t, loff_t *); +typedef ssize_t (*au_writef_t)(struct file *, const char __user *, size_t, + loff_t *); + +/* policies to select one among multiple writable branches */ +struct au_wbr_copyup_operations { + int (*copyup)(struct dentry *dentry); +}; + +struct au_wbr_create_operations { + int (*create)(struct dentry *dentry, int isdir); + int (*init)(struct super_block *sb); + int (*fin)(struct super_block *sb); +}; + +struct au_wbr_mfs { + struct mutex mfs_lock; /* protect this structure */ + unsigned long mfs_jiffy; + unsigned long mfs_expire; + aufs_bindex_t mfs_bindex; + + unsigned long long mfsrr_bytes; + unsigned long long mfsrr_watermark; +}; + +struct au_branch; +struct au_sbinfo { + /* nowait tasks in the system-wide workqueue */ + struct au_nowait_tasks si_nowait; + + /* + * tried sb->s_umount, but failed due to the dependecy between i_mutex. + * rwsem for au_sbinfo is necessary. + */ + struct au_rwsem si_rwsem; + + /* prevent recursive locking in deleting inode */ + struct { + unsigned long *bitmap; + spinlock_t tree_lock; + struct radix_tree_root tree; + } au_si_pid; + + /* + * dirty approach to protect sb->sb_inodes and ->s_files from remount. + */ + atomic_long_t si_ninodes, si_nfiles; + + /* branch management */ + unsigned int si_generation; + + /* see above flags */ + unsigned char au_si_status; + + aufs_bindex_t si_bend; + + /* dirty trick to keep br_id plus */ + unsigned int si_last_br_id : + sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1; + struct au_branch **si_branch; + + /* policy to select a writable branch */ + unsigned char si_wbr_copyup; + unsigned char si_wbr_create; + struct au_wbr_copyup_operations *si_wbr_copyup_ops; + struct au_wbr_create_operations *si_wbr_create_ops; + + /* round robin */ + atomic_t si_wbr_rr_next; + + /* most free space */ + struct au_wbr_mfs si_wbr_mfs; + + /* mount flags */ + /* include/asm-ia64/siginfo.h defines a macro named si_flags */ + unsigned int si_mntflags; + + /* external inode number (bitmap and translation table) */ + au_readf_t si_xread; + au_writef_t si_xwrite; + struct file *si_xib; + struct mutex si_xib_mtx; /* protect xib members */ + unsigned long *si_xib_buf; + unsigned long si_xib_last_pindex; + int si_xib_next_bit; + aufs_bindex_t si_xino_brid; + /* reserved for future use */ + /* unsigned long long si_xib_limit; */ /* Max xib file size */ + +#ifdef CONFIG_AUFS_EXPORT + /* i_generation */ + struct file *si_xigen; + atomic_t si_xigen_next; +#endif + + /* vdir parameters */ + unsigned long si_rdcache; /* max cache time in jiffies */ + unsigned int si_rdblk; /* deblk size */ + unsigned int si_rdhash; /* hash size */ + + /* + * If the number of whiteouts are larger than si_dirwh, leave all of + * them after au_whtmp_ren to reduce the cost of rmdir(2). + * future fsck.aufs or kernel thread will remove them later. + * Otherwise, remove all whiteouts and the dir in rmdir(2). + */ + unsigned int si_dirwh; + + /* + * rename(2) a directory with all children. + */ + /* reserved for future use */ + /* int si_rendir; */ + + /* pseudo_link list */ + struct au_splhead si_plink; + wait_queue_head_t si_plink_wq; + spinlock_t si_plink_maint_lock; + pid_t si_plink_maint_pid; + + /* + * sysfs and lifetime management. + * this is not a small structure and it may be a waste of memory in case + * of sysfs is disabled, particulary when many aufs-es are mounted. + * but using sysfs is majority. + */ + struct kobject si_kobj; +#ifdef CONFIG_DEBUG_FS + struct dentry *si_dbgaufs, *si_dbgaufs_xib; +#ifdef CONFIG_AUFS_EXPORT + struct dentry *si_dbgaufs_xigen; +#endif +#endif + +#ifdef CONFIG_AUFS_SBILIST + struct list_head si_list; +#endif + + /* dirty, necessary for unmounting, sysfs and sysrq */ + struct super_block *si_sb; +}; + +/* sbinfo status flags */ +/* + * set true when refresh_dirs() failed at remount time. + * then try refreshing dirs at access time again. + * if it is false, refreshing dirs at access time is unnecesary + */ +#define AuSi_FAILED_REFRESH_DIRS 1 +static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi, + unsigned int flag) +{ + AuRwMustAnyLock(&sbi->si_rwsem); + return sbi->au_si_status & flag; +} +#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name) +#define au_fset_si(sbinfo, name) do { \ + AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ + (sbinfo)->au_si_status |= AuSi_##name; \ +} while (0) +#define au_fclr_si(sbinfo, name) do { \ + AuRwMustWriteLock(&(sbinfo)->si_rwsem); \ + (sbinfo)->au_si_status &= ~AuSi_##name; \ +} while (0) + +/* ---------------------------------------------------------------------- */ + +/* policy to select one among writable branches */ +#define AuWbrCopyup(sbinfo, ...) \ + ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__)) +#define AuWbrCreate(sbinfo, ...) \ + ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__)) + +/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */ +#define AuLock_DW 1 /* write-lock dentry */ +#define AuLock_IR (1 << 1) /* read-lock inode */ +#define AuLock_IW (1 << 2) /* write-lock inode */ +#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */ +#define AuLock_DIR (1 << 4) /* target is a dir */ +#define AuLock_NOPLM (1 << 5) /* return err in plm mode */ +#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */ +#define au_ftest_lock(flags, name) ((flags) & AuLock_##name) +#define au_fset_lock(flags, name) \ + do { (flags) |= AuLock_##name; } while (0) +#define au_fclr_lock(flags, name) \ + do { (flags) &= ~AuLock_##name; } while (0) + +/* ---------------------------------------------------------------------- */ + +/* super.c */ +extern struct file_system_type aufs_fs_type; +struct inode *au_iget_locked(struct super_block *sb, ino_t ino); +typedef unsigned long long (*au_arraycb_t)(void *array, unsigned long long max, + void *arg); +void au_array_free(void *array); +void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, void *arg); +struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max); +void au_iarray_free(struct inode **a, unsigned long long max); + +/* sbinfo.c */ +void au_si_free(struct kobject *kobj); +int au_si_alloc(struct super_block *sb); +int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr); + +unsigned int au_sigen_inc(struct super_block *sb); +aufs_bindex_t au_new_br_id(struct super_block *sb); + +int si_read_lock(struct super_block *sb, int flags); +int si_write_lock(struct super_block *sb, int flags); +int aufs_read_lock(struct dentry *dentry, int flags); +void aufs_read_unlock(struct dentry *dentry, int flags); +void aufs_write_lock(struct dentry *dentry); +void aufs_write_unlock(struct dentry *dentry); +int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags); +void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2); + +int si_pid_test_slow(struct super_block *sb); +void si_pid_set_slow(struct super_block *sb); +void si_pid_clr_slow(struct super_block *sb); + +/* wbr_policy.c */ +extern struct au_wbr_copyup_operations au_wbr_copyup_ops[]; +extern struct au_wbr_create_operations au_wbr_create_ops[]; +int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst); + +/* ---------------------------------------------------------------------- */ + +static inline struct au_sbinfo *au_sbi(struct super_block *sb) +{ + return sb->s_fs_info; +} + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_EXPORT +void au_export_init(struct super_block *sb); + +static inline int au_test_nfsd(void) +{ + struct task_struct *tsk = current; + + return (tsk->flags & PF_KTHREAD) + && !strcmp(tsk->comm, "nfsd"); +} + +void au_xigen_inc(struct inode *inode); +int au_xigen_new(struct inode *inode); +int au_xigen_set(struct super_block *sb, struct file *base); +void au_xigen_clr(struct super_block *sb); + +static inline int au_busy_or_stale(void) +{ + if (!au_test_nfsd()) + return -EBUSY; + return -ESTALE; +} +#else +AuStubVoid(au_export_init, struct super_block *sb) +AuStubInt0(au_test_nfsd, void) +AuStubVoid(au_xigen_inc, struct inode *inode) +AuStubInt0(au_xigen_new, struct inode *inode) +AuStubInt0(au_xigen_set, struct super_block *sb, struct file *base) +AuStubVoid(au_xigen_clr, struct super_block *sb) +static inline int au_busy_or_stale(void) +{ + return -EBUSY; +} +#endif /* CONFIG_AUFS_EXPORT */ + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_SBILIST +/* module.c */ +extern struct au_splhead au_sbilist; + +static inline void au_sbilist_init(void) +{ + au_spl_init(&au_sbilist); +} + +static inline void au_sbilist_add(struct super_block *sb) +{ + au_spl_add(&au_sbi(sb)->si_list, &au_sbilist); +} + +static inline void au_sbilist_del(struct super_block *sb) +{ + au_spl_del(&au_sbi(sb)->si_list, &au_sbilist); +} +#else +AuStubVoid(au_sbilist_init, void) +AuStubVoid(au_sbilist_add, struct super_block*) +AuStubVoid(au_sbilist_del, struct super_block*) +#endif + +/* ---------------------------------------------------------------------- */ + +static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo) +{ + /* + * This function is a dynamic '__init' fucntion actually, + * so the tiny check for si_rwsem is unnecessary. + */ + /* AuRwMustWriteLock(&sbinfo->si_rwsem); */ +#ifdef CONFIG_DEBUG_FS + sbinfo->si_dbgaufs = NULL; + sbinfo->si_dbgaufs_xib = NULL; +#ifdef CONFIG_AUFS_EXPORT + sbinfo->si_dbgaufs_xigen = NULL; +#endif +#endif +} + +/* ---------------------------------------------------------------------- */ + +static inline pid_t si_pid_bit(void) +{ + /* the origin of pid is 1, but the bitmap's is 0 */ + return current->pid - 1; +} + +static inline int si_pid_test(struct super_block *sb) +{ + pid_t bit = si_pid_bit(); + if (bit < PID_MAX_DEFAULT) + return test_bit(bit, au_sbi(sb)->au_si_pid.bitmap); + else + return si_pid_test_slow(sb); +} + +static inline void si_pid_set(struct super_block *sb) +{ + pid_t bit = si_pid_bit(); + if (bit < PID_MAX_DEFAULT) { + AuDebugOn(test_bit(bit, au_sbi(sb)->au_si_pid.bitmap)); + set_bit(bit, au_sbi(sb)->au_si_pid.bitmap); + /* smp_mb(); */ + } else + si_pid_set_slow(sb); +} + +static inline void si_pid_clr(struct super_block *sb) +{ + pid_t bit = si_pid_bit(); + if (bit < PID_MAX_DEFAULT) { + AuDebugOn(!test_bit(bit, au_sbi(sb)->au_si_pid.bitmap)); + clear_bit(bit, au_sbi(sb)->au_si_pid.bitmap); + /* smp_mb(); */ + } else + si_pid_clr_slow(sb); +} + +/* ---------------------------------------------------------------------- */ + +/* lock superblock. mainly for entry point functions */ +/* + * __si_read_lock, __si_write_lock, + * __si_read_unlock, __si_write_unlock, __si_downgrade_lock + */ +AuSimpleRwsemFuncs(__si, struct super_block *sb, &au_sbi(sb)->si_rwsem); + +#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem) +#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem) +#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem) + +static inline void si_noflush_read_lock(struct super_block *sb) +{ + __si_read_lock(sb); + si_pid_set(sb); +} + +static inline int si_noflush_read_trylock(struct super_block *sb) +{ + int locked = __si_read_trylock(sb); + if (locked) + si_pid_set(sb); + return locked; +} + +static inline void si_noflush_write_lock(struct super_block *sb) +{ + __si_write_lock(sb); + si_pid_set(sb); +} + +static inline int si_noflush_write_trylock(struct super_block *sb) +{ + int locked = __si_write_trylock(sb); + if (locked) + si_pid_set(sb); + return locked; +} + +#if 0 /* unused */ +static inline int si_read_trylock(struct super_block *sb, int flags) +{ + if (au_ftest_lock(flags, FLUSH)) + au_nwt_flush(&au_sbi(sb)->si_nowait); + return si_noflush_read_trylock(sb); +} +#endif + +static inline void si_read_unlock(struct super_block *sb) +{ + si_pid_clr(sb); + __si_read_unlock(sb); +} + +#if 0 /* unused */ +static inline int si_write_trylock(struct super_block *sb, int flags) +{ + if (au_ftest_lock(flags, FLUSH)) + au_nwt_flush(&au_sbi(sb)->si_nowait); + return si_noflush_write_trylock(sb); +} +#endif + +static inline void si_write_unlock(struct super_block *sb) +{ + si_pid_clr(sb); + __si_write_unlock(sb); +} + +#if 0 /* unused */ +static inline void si_downgrade_lock(struct super_block *sb) +{ + __si_downgrade_lock(sb); +} +#endif + +/* ---------------------------------------------------------------------- */ + +static inline aufs_bindex_t au_sbend(struct super_block *sb) +{ + SiMustAnyLock(sb); + return au_sbi(sb)->si_bend; +} + +static inline unsigned int au_mntflags(struct super_block *sb) +{ + SiMustAnyLock(sb); + return au_sbi(sb)->si_mntflags; +} + +static inline unsigned int au_sigen(struct super_block *sb) +{ + SiMustAnyLock(sb); + return au_sbi(sb)->si_generation; +} + +static inline void au_ninodes_inc(struct super_block *sb) +{ + atomic_long_inc(&au_sbi(sb)->si_ninodes); +} + +static inline void au_ninodes_dec(struct super_block *sb) +{ + AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_ninodes)); + atomic_long_dec(&au_sbi(sb)->si_ninodes); +} + +static inline void au_nfiles_inc(struct super_block *sb) +{ + atomic_long_inc(&au_sbi(sb)->si_nfiles); +} + +static inline void au_nfiles_dec(struct super_block *sb) +{ + AuDebugOn(!atomic_long_read(&au_sbi(sb)->si_nfiles)); + atomic_long_dec(&au_sbi(sb)->si_nfiles); +} + +static inline struct au_branch *au_sbr(struct super_block *sb, + aufs_bindex_t bindex) +{ + SiMustAnyLock(sb); + return au_sbi(sb)->si_branch[0 + bindex]; +} + +static inline void au_xino_brid_set(struct super_block *sb, aufs_bindex_t brid) +{ + SiMustWriteLock(sb); + au_sbi(sb)->si_xino_brid = brid; +} + +static inline aufs_bindex_t au_xino_brid(struct super_block *sb) +{ + SiMustAnyLock(sb); + return au_sbi(sb)->si_xino_brid; +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_SUPER_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/sysaufs.c +++ linux-2.6.37/ubuntu/aufs/sysaufs.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sysfs interface and lifetime management + * they are necessary regardless sysfs is disabled. + */ + +#include +#include +#include +#include "aufs.h" + +unsigned long sysaufs_si_mask; +struct kset *sysaufs_kset; + +#define AuSiAttr(_name) { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = sysaufs_si_##_name, \ +} + +static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path); +struct attribute *sysaufs_si_attrs[] = { + &sysaufs_si_attr_xi_path.attr, + NULL, +}; + +static const struct sysfs_ops au_sbi_ops = { + .show = sysaufs_si_show +}; + +static struct kobj_type au_sbi_ktype = { + .release = au_si_free, + .sysfs_ops = &au_sbi_ops, + .default_attrs = sysaufs_si_attrs +}; + +/* ---------------------------------------------------------------------- */ + +int sysaufs_si_init(struct au_sbinfo *sbinfo) +{ + int err; + + sbinfo->si_kobj.kset = sysaufs_kset; + /* cf. sysaufs_name() */ + err = kobject_init_and_add + (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL, + SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo)); + + dbgaufs_si_null(sbinfo); + if (!err) { + err = dbgaufs_si_init(sbinfo); + if (unlikely(err)) + kobject_put(&sbinfo->si_kobj); + } + return err; +} + +void sysaufs_fin(void) +{ + dbgaufs_fin(); + sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group); + kset_unregister(sysaufs_kset); +} + +int __init sysaufs_init(void) +{ + int err; + + do { + get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask)); + } while (!sysaufs_si_mask); + + err = -EINVAL; + sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj); + if (unlikely(!sysaufs_kset)) + goto out; + err = PTR_ERR(sysaufs_kset); + if (IS_ERR(sysaufs_kset)) + goto out; + err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group); + if (unlikely(err)) { + kset_unregister(sysaufs_kset); + goto out; + } + + err = dbgaufs_init(); + if (unlikely(err)) + sysaufs_fin(); +out: + return err; +} --- linux-2.6.37.orig/ubuntu/aufs/sysaufs.h +++ linux-2.6.37/ubuntu/aufs/sysaufs.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sysfs interface and mount lifetime management + */ + +#ifndef __SYSAUFS_H__ +#define __SYSAUFS_H__ + +#ifdef __KERNEL__ + +#include +#include +#include "module.h" + +struct super_block; +struct au_sbinfo; + +struct sysaufs_si_attr { + struct attribute attr; + int (*show)(struct seq_file *seq, struct super_block *sb); +}; + +/* ---------------------------------------------------------------------- */ + +/* sysaufs.c */ +extern unsigned long sysaufs_si_mask; +extern struct kset *sysaufs_kset; +extern struct attribute *sysaufs_si_attrs[]; +int sysaufs_si_init(struct au_sbinfo *sbinfo); +int __init sysaufs_init(void); +void sysaufs_fin(void); + +/* ---------------------------------------------------------------------- */ + +/* some people doesn't like to show a pointer in kernel */ +static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo) +{ + return sysaufs_si_mask ^ (unsigned long)sbinfo; +} + +#define SysaufsSiNamePrefix "si_" +#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16) +static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name) +{ + snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx", + sysaufs_si_id(sbinfo)); +} + +struct au_branch; +#ifdef CONFIG_SYSFS +/* sysfs.c */ +extern struct attribute_group *sysaufs_attr_group; + +int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb); +ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, + char *buf); + +void sysaufs_br_init(struct au_branch *br); +void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex); +void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex); + +#define sysaufs_brs_init() do {} while (0) + +#else +#define sysaufs_attr_group NULL + +AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb) + +static inline +ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + return 0; +} + +AuStubVoid(sysaufs_br_init, struct au_branch *br) +AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex) +AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex) + +static inline void sysaufs_brs_init(void) +{ + sysaufs_brs = 0; +} + +#endif /* CONFIG_SYSFS */ + +#endif /* __KERNEL__ */ +#endif /* __SYSAUFS_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/sysfs.c +++ linux-2.6.37/ubuntu/aufs/sysfs.c @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sysfs interface + */ + +#include +#include +#include +#include +#include "aufs.h" + +#ifdef CONFIG_AUFS_FS_MODULE +/* this entry violates the "one line per file" policy of sysfs */ +static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + ssize_t err; + static char *conf = +/* this file is generated at compiling */ +#include "conf.str" + ; + + err = snprintf(buf, PAGE_SIZE, conf); + if (unlikely(err >= PAGE_SIZE)) + err = -EFBIG; + return err; +} + +static struct kobj_attribute au_config_attr = __ATTR_RO(config); +#endif + +static struct attribute *au_attr[] = { +#ifdef CONFIG_AUFS_FS_MODULE + &au_config_attr.attr, +#endif + NULL, /* need to NULL terminate the list of attributes */ +}; + +static struct attribute_group sysaufs_attr_group_body = { + .attrs = au_attr +}; + +struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body; + +/* ---------------------------------------------------------------------- */ + +int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb) +{ + int err; + + SiMustAnyLock(sb); + + err = 0; + if (au_opt_test(au_mntflags(sb), XINO)) { + err = au_xino_path(seq, au_sbi(sb)->si_xib); + seq_putc(seq, '\n'); + } + return err; +} + +/* + * the lifetime of branch is independent from the entry under sysfs. + * sysfs handles the lifetime of the entry, and never call ->show() after it is + * unlinked. + */ +static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb, + aufs_bindex_t bindex) +{ + struct path path; + struct dentry *root; + struct au_branch *br; + + AuDbg("b%d\n", bindex); + + root = sb->s_root; + di_read_lock_parent(root, !AuLock_IR); + br = au_sbr(sb, bindex); + path.mnt = br->br_mnt; + path.dentry = au_h_dptr(root, bindex); + au_seq_path(seq, &path); + di_read_unlock(root, !AuLock_IR); + seq_printf(seq, "=%s\n", au_optstr_br_perm(br->br_perm)); + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static struct seq_file *au_seq(char *p, ssize_t len) +{ + struct seq_file *seq; + + seq = kzalloc(sizeof(*seq), GFP_NOFS); + if (seq) { + /* mutex_init(&seq.lock); */ + seq->buf = p; + seq->size = len; + return seq; /* success */ + } + + seq = ERR_PTR(-ENOMEM); + return seq; +} + +#define SysaufsBr_PREFIX "br" + +/* todo: file size may exceed PAGE_SIZE */ +ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + ssize_t err; + long l; + aufs_bindex_t bend; + struct au_sbinfo *sbinfo; + struct super_block *sb; + struct seq_file *seq; + char *name; + struct attribute **cattr; + + sbinfo = container_of(kobj, struct au_sbinfo, si_kobj); + sb = sbinfo->si_sb; + + /* + * prevent a race condition between sysfs and aufs. + * for instance, sysfs_file_read() calls sysfs_get_active_two() which + * prohibits maintaining the sysfs entries. + * hew we acquire read lock after sysfs_get_active_two(). + * on the other hand, the remount process may maintain the sysfs/aufs + * entries after acquiring write lock. + * it can cause a deadlock. + * simply we gave up processing read here. + */ + err = -EBUSY; + if (unlikely(!si_noflush_read_trylock(sb))) + goto out; + + seq = au_seq(buf, PAGE_SIZE); + err = PTR_ERR(seq); + if (IS_ERR(seq)) + goto out_unlock; + + name = (void *)attr->name; + cattr = sysaufs_si_attrs; + while (*cattr) { + if (!strcmp(name, (*cattr)->name)) { + err = container_of(*cattr, struct sysaufs_si_attr, attr) + ->show(seq, sb); + goto out_seq; + } + cattr++; + } + + bend = au_sbend(sb); + if (!strncmp(name, SysaufsBr_PREFIX, sizeof(SysaufsBr_PREFIX) - 1)) { + name += sizeof(SysaufsBr_PREFIX) - 1; + err = strict_strtol(name, 10, &l); + if (!err) { + if (l <= bend) + err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l); + else + err = -ENOENT; + } + goto out_seq; + } + BUG(); + +out_seq: + if (!err) { + err = seq->count; + /* sysfs limit */ + if (unlikely(err == PAGE_SIZE)) + err = -EFBIG; + } + kfree(seq); +out_unlock: + si_read_unlock(sb); +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +void sysaufs_br_init(struct au_branch *br) +{ + struct attribute *attr = &br->br_attr; + + sysfs_attr_init(attr); + attr->name = br->br_name; + attr->mode = S_IRUGO; +} + +void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex) +{ + struct au_branch *br; + struct kobject *kobj; + aufs_bindex_t bend; + + dbgaufs_brs_del(sb, bindex); + + if (!sysaufs_brs) + return; + + kobj = &au_sbi(sb)->si_kobj; + bend = au_sbend(sb); + for (; bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + sysfs_remove_file(kobj, &br->br_attr); + } +} + +void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex) +{ + int err; + aufs_bindex_t bend; + struct kobject *kobj; + struct au_branch *br; + + dbgaufs_brs_add(sb, bindex); + + if (!sysaufs_brs) + return; + + kobj = &au_sbi(sb)->si_kobj; + bend = au_sbend(sb); + for (; bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + snprintf(br->br_name, sizeof(br->br_name), SysaufsBr_PREFIX + "%d", bindex); + err = sysfs_create_file(kobj, &br->br_attr); + if (unlikely(err)) + pr_warning("failed %s under sysfs(%d)\n", + br->br_name, err); + } +} --- linux-2.6.37.orig/ubuntu/aufs/sysrq.c +++ linux-2.6.37/ubuntu/aufs/sysrq.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * magic sysrq hanlder + */ + +#include +#include +#include +/* #include */ +#include "aufs.h" + +/* ---------------------------------------------------------------------- */ + +static void sysrq_sb(struct super_block *sb) +{ + char *plevel; + struct au_sbinfo *sbinfo; + struct file *file; + + plevel = au_plevel; + au_plevel = KERN_WARNING; + + sbinfo = au_sbi(sb); + /* since we define pr_fmt, call printk directly */ + printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo)); + printk(KERN_WARNING AUFS_NAME ": superblock\n"); + au_dpri_sb(sb); + printk(KERN_WARNING AUFS_NAME ": root dentry\n"); + au_dpri_dentry(sb->s_root); + printk(KERN_WARNING AUFS_NAME ": root inode\n"); + au_dpri_inode(sb->s_root->d_inode); +#if 0 + struct inode *i; + printk(KERN_WARNING AUFS_NAME ": isolated inode\n"); + spin_lock(&inode_lock); + list_for_each_entry(i, &sb->s_inodes, i_sb_list) + if (list_empty(&i->i_dentry)) + au_dpri_inode(i); + spin_unlock(&inode_lock); +#endif + printk(KERN_WARNING AUFS_NAME ": files\n"); + lg_global_lock(files_lglock); + do_file_list_for_each_entry(sb, file) { + umode_t mode; + mode = file->f_dentry->d_inode->i_mode; + if (!special_file(mode) || au_special_file(mode)) + au_dpri_file(file); + } while_file_list_for_each_entry; + lg_global_unlock(files_lglock); + printk(KERN_WARNING AUFS_NAME ": done\n"); + + au_plevel = plevel; +} + +/* ---------------------------------------------------------------------- */ + +/* module parameter */ +static char *aufs_sysrq_key = "a"; +module_param_named(sysrq, aufs_sysrq_key, charp, S_IRUGO); +MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME); + +static void au_sysrq(int key __maybe_unused) +{ + struct au_sbinfo *sbinfo; + + spin_lock(&au_sbilist.spin); + list_for_each_entry(sbinfo, &au_sbilist.head, si_list) + sysrq_sb(sbinfo->si_sb); + spin_unlock(&au_sbilist.spin); +} + +static struct sysrq_key_op au_sysrq_op = { + .handler = au_sysrq, + .help_msg = "Aufs", + .action_msg = "Aufs", + .enable_mask = SYSRQ_ENABLE_DUMP +}; + +/* ---------------------------------------------------------------------- */ + +int __init au_sysrq_init(void) +{ + int err; + char key; + + err = -1; + key = *aufs_sysrq_key; + if ('a' <= key && key <= 'z') + err = register_sysrq_key(key, &au_sysrq_op); + if (unlikely(err)) + pr_err("err %d, sysrq=%c\n", err, key); + return err; +} + +void au_sysrq_fin(void) +{ + int err; + err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op); + if (unlikely(err)) + pr_err("err %d (ignored)\n", err); +} --- linux-2.6.37.orig/ubuntu/aufs/vdir.c +++ linux-2.6.37/ubuntu/aufs/vdir.c @@ -0,0 +1,886 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * virtual or vertical directory + */ + +#include +#include "aufs.h" + +static unsigned int calc_size(int nlen) +{ + return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t)); +} + +static int set_deblk_end(union au_vdir_deblk_p *p, + union au_vdir_deblk_p *deblk_end) +{ + if (calc_size(0) <= deblk_end->deblk - p->deblk) { + p->de->de_str.len = 0; + /* smp_mb(); */ + return 0; + } + return -1; /* error */ +} + +/* returns true or false */ +static int is_deblk_end(union au_vdir_deblk_p *p, + union au_vdir_deblk_p *deblk_end) +{ + if (calc_size(0) <= deblk_end->deblk - p->deblk) + return !p->de->de_str.len; + return 1; +} + +static unsigned char *last_deblk(struct au_vdir *vdir) +{ + return vdir->vd_deblk[vdir->vd_nblk - 1]; +} + +/* ---------------------------------------------------------------------- */ + +/* estimate the apropriate size for name hash table */ +unsigned int au_rdhash_est(loff_t sz) +{ + unsigned int n; + + n = UINT_MAX; + sz >>= 10; + if (sz < n) + n = sz; + if (sz < AUFS_RDHASH_DEF) + n = AUFS_RDHASH_DEF; + /* pr_info("n %u\n", n); */ + return n; +} + +/* + * the allocated memory has to be freed by + * au_nhash_wh_free() or au_nhash_de_free(). + */ +int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp) +{ + struct hlist_head *head; + unsigned int u; + + head = kmalloc(sizeof(*nhash->nh_head) * num_hash, gfp); + if (head) { + nhash->nh_num = num_hash; + nhash->nh_head = head; + for (u = 0; u < num_hash; u++) + INIT_HLIST_HEAD(head++); + return 0; /* success */ + } + + return -ENOMEM; +} + +static void nhash_count(struct hlist_head *head) +{ +#if 0 + unsigned long n; + struct hlist_node *pos; + + n = 0; + hlist_for_each(pos, head) + n++; + pr_info("%lu\n", n); +#endif +} + +static void au_nhash_wh_do_free(struct hlist_head *head) +{ + struct au_vdir_wh *tpos; + struct hlist_node *pos, *node; + + hlist_for_each_entry_safe(tpos, pos, node, head, wh_hash) { + /* hlist_del(pos); */ + kfree(tpos); + } +} + +static void au_nhash_de_do_free(struct hlist_head *head) +{ + struct au_vdir_dehstr *tpos; + struct hlist_node *pos, *node; + + hlist_for_each_entry_safe(tpos, pos, node, head, hash) { + /* hlist_del(pos); */ + au_cache_free_vdir_dehstr(tpos); + } +} + +static void au_nhash_do_free(struct au_nhash *nhash, + void (*free)(struct hlist_head *head)) +{ + unsigned int n; + struct hlist_head *head; + + n = nhash->nh_num; + if (!n) + return; + + head = nhash->nh_head; + while (n-- > 0) { + nhash_count(head); + free(head++); + } + kfree(nhash->nh_head); +} + +void au_nhash_wh_free(struct au_nhash *whlist) +{ + au_nhash_do_free(whlist, au_nhash_wh_do_free); +} + +static void au_nhash_de_free(struct au_nhash *delist) +{ + au_nhash_do_free(delist, au_nhash_de_do_free); +} + +/* ---------------------------------------------------------------------- */ + +int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt, + int limit) +{ + int num; + unsigned int u, n; + struct hlist_head *head; + struct au_vdir_wh *tpos; + struct hlist_node *pos; + + num = 0; + n = whlist->nh_num; + head = whlist->nh_head; + for (u = 0; u < n; u++, head++) + hlist_for_each_entry(tpos, pos, head, wh_hash) + if (tpos->wh_bindex == btgt && ++num > limit) + return 1; + return 0; +} + +static struct hlist_head *au_name_hash(struct au_nhash *nhash, + unsigned char *name, + unsigned int len) +{ + unsigned int v; + /* const unsigned int magic_bit = 12; */ + + AuDebugOn(!nhash->nh_num || !nhash->nh_head); + + v = 0; + while (len--) + v += *name++; + /* v = hash_long(v, magic_bit); */ + v %= nhash->nh_num; + return nhash->nh_head + v; +} + +static int au_nhash_test_name(struct au_vdir_destr *str, const char *name, + int nlen) +{ + return str->len == nlen && !memcmp(str->name, name, nlen); +} + +/* returns found or not */ +int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen) +{ + struct hlist_head *head; + struct au_vdir_wh *tpos; + struct hlist_node *pos; + struct au_vdir_destr *str; + + head = au_name_hash(whlist, name, nlen); + hlist_for_each_entry(tpos, pos, head, wh_hash) { + str = &tpos->wh_str; + AuDbg("%.*s\n", str->len, str->name); + if (au_nhash_test_name(str, name, nlen)) + return 1; + } + return 0; +} + +/* returns found(true) or not */ +static int test_known(struct au_nhash *delist, char *name, int nlen) +{ + struct hlist_head *head; + struct au_vdir_dehstr *tpos; + struct hlist_node *pos; + struct au_vdir_destr *str; + + head = au_name_hash(delist, name, nlen); + hlist_for_each_entry(tpos, pos, head, hash) { + str = tpos->str; + AuDbg("%.*s\n", str->len, str->name); + if (au_nhash_test_name(str, name, nlen)) + return 1; + } + return 0; +} + +static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino, + unsigned char d_type) +{ +#ifdef CONFIG_AUFS_SHWH + wh->wh_ino = ino; + wh->wh_type = d_type; +#endif +} + +/* ---------------------------------------------------------------------- */ + +int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, + unsigned int d_type, aufs_bindex_t bindex, + unsigned char shwh) +{ + int err; + struct au_vdir_destr *str; + struct au_vdir_wh *wh; + + AuDbg("%.*s\n", nlen, name); + AuDebugOn(!whlist->nh_num || !whlist->nh_head); + + err = -ENOMEM; + wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS); + if (unlikely(!wh)) + goto out; + + err = 0; + wh->wh_bindex = bindex; + if (shwh) + au_shwh_init_wh(wh, ino, d_type); + str = &wh->wh_str; + str->len = nlen; + memcpy(str->name, name, nlen); + hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen)); + /* smp_mb(); */ + +out: + return err; +} + +static int append_deblk(struct au_vdir *vdir) +{ + int err; + unsigned long ul; + const unsigned int deblk_sz = vdir->vd_deblk_sz; + union au_vdir_deblk_p p, deblk_end; + unsigned char **o; + + err = -ENOMEM; + o = krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1), + GFP_NOFS); + if (unlikely(!o)) + goto out; + + vdir->vd_deblk = o; + p.deblk = kmalloc(deblk_sz, GFP_NOFS); + if (p.deblk) { + ul = vdir->vd_nblk++; + vdir->vd_deblk[ul] = p.deblk; + vdir->vd_last.ul = ul; + vdir->vd_last.p.deblk = p.deblk; + deblk_end.deblk = p.deblk + deblk_sz; + err = set_deblk_end(&p, &deblk_end); + } + +out: + return err; +} + +static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino, + unsigned int d_type, struct au_nhash *delist) +{ + int err; + unsigned int sz; + const unsigned int deblk_sz = vdir->vd_deblk_sz; + union au_vdir_deblk_p p, *room, deblk_end; + struct au_vdir_dehstr *dehstr; + + p.deblk = last_deblk(vdir); + deblk_end.deblk = p.deblk + deblk_sz; + room = &vdir->vd_last.p; + AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk + || !is_deblk_end(room, &deblk_end)); + + sz = calc_size(nlen); + if (unlikely(sz > deblk_end.deblk - room->deblk)) { + err = append_deblk(vdir); + if (unlikely(err)) + goto out; + + p.deblk = last_deblk(vdir); + deblk_end.deblk = p.deblk + deblk_sz; + /* smp_mb(); */ + AuDebugOn(room->deblk != p.deblk); + } + + err = -ENOMEM; + dehstr = au_cache_alloc_vdir_dehstr(); + if (unlikely(!dehstr)) + goto out; + + dehstr->str = &room->de->de_str; + hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen)); + room->de->de_ino = ino; + room->de->de_type = d_type; + room->de->de_str.len = nlen; + memcpy(room->de->de_str.name, name, nlen); + + err = 0; + room->deblk += sz; + if (unlikely(set_deblk_end(room, &deblk_end))) + err = append_deblk(vdir); + /* smp_mb(); */ + +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +void au_vdir_free(struct au_vdir *vdir) +{ + unsigned char **deblk; + + deblk = vdir->vd_deblk; + while (vdir->vd_nblk--) + kfree(*deblk++); + kfree(vdir->vd_deblk); + au_cache_free_vdir(vdir); +} + +static struct au_vdir *alloc_vdir(struct file *file) +{ + struct au_vdir *vdir; + struct super_block *sb; + int err; + + sb = file->f_dentry->d_sb; + SiMustAnyLock(sb); + + err = -ENOMEM; + vdir = au_cache_alloc_vdir(); + if (unlikely(!vdir)) + goto out; + + vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS); + if (unlikely(!vdir->vd_deblk)) + goto out_free; + + vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk; + if (!vdir->vd_deblk_sz) { + /* estimate the apropriate size for deblk */ + vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL); + /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */ + } + vdir->vd_nblk = 0; + vdir->vd_version = 0; + vdir->vd_jiffy = 0; + err = append_deblk(vdir); + if (!err) + return vdir; /* success */ + + kfree(vdir->vd_deblk); + +out_free: + au_cache_free_vdir(vdir); +out: + vdir = ERR_PTR(err); + return vdir; +} + +static int reinit_vdir(struct au_vdir *vdir) +{ + int err; + union au_vdir_deblk_p p, deblk_end; + + while (vdir->vd_nblk > 1) { + kfree(vdir->vd_deblk[vdir->vd_nblk - 1]); + /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */ + vdir->vd_nblk--; + } + p.deblk = vdir->vd_deblk[0]; + deblk_end.deblk = p.deblk + vdir->vd_deblk_sz; + err = set_deblk_end(&p, &deblk_end); + /* keep vd_dblk_sz */ + vdir->vd_last.ul = 0; + vdir->vd_last.p.deblk = vdir->vd_deblk[0]; + vdir->vd_version = 0; + vdir->vd_jiffy = 0; + /* smp_mb(); */ + return err; +} + +/* ---------------------------------------------------------------------- */ + +#define AuFillVdir_CALLED 1 +#define AuFillVdir_WHABLE (1 << 1) +#define AuFillVdir_SHWH (1 << 2) +#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name) +#define au_fset_fillvdir(flags, name) \ + do { (flags) |= AuFillVdir_##name; } while (0) +#define au_fclr_fillvdir(flags, name) \ + do { (flags) &= ~AuFillVdir_##name; } while (0) + +#ifndef CONFIG_AUFS_SHWH +#undef AuFillVdir_SHWH +#define AuFillVdir_SHWH 0 +#endif + +struct fillvdir_arg { + struct file *file; + struct au_vdir *vdir; + struct au_nhash delist; + struct au_nhash whlist; + aufs_bindex_t bindex; + unsigned int flags; + int err; +}; + +static int fillvdir(void *__arg, const char *__name, int nlen, + loff_t offset __maybe_unused, u64 h_ino, + unsigned int d_type) +{ + struct fillvdir_arg *arg = __arg; + char *name = (void *)__name; + struct super_block *sb; + ino_t ino; + const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH); + + arg->err = 0; + sb = arg->file->f_dentry->d_sb; + au_fset_fillvdir(arg->flags, CALLED); + /* smp_mb(); */ + if (nlen <= AUFS_WH_PFX_LEN + || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) { + if (test_known(&arg->delist, name, nlen) + || au_nhash_test_known_wh(&arg->whlist, name, nlen)) + goto out; /* already exists or whiteouted */ + + sb = arg->file->f_dentry->d_sb; + arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino); + if (!arg->err) { + if (unlikely(nlen > AUFS_MAX_NAMELEN)) + d_type = DT_UNKNOWN; + arg->err = append_de(arg->vdir, name, nlen, ino, + d_type, &arg->delist); + } + } else if (au_ftest_fillvdir(arg->flags, WHABLE)) { + name += AUFS_WH_PFX_LEN; + nlen -= AUFS_WH_PFX_LEN; + if (au_nhash_test_known_wh(&arg->whlist, name, nlen)) + goto out; /* already whiteouted */ + + if (shwh) + arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type, + &ino); + if (!arg->err) { + if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN) + d_type = DT_UNKNOWN; + arg->err = au_nhash_append_wh + (&arg->whlist, name, nlen, ino, d_type, + arg->bindex, shwh); + } + } + +out: + if (!arg->err) + arg->vdir->vd_jiffy = jiffies; + /* smp_mb(); */ + AuTraceErr(arg->err); + return arg->err; +} + +static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir, + struct au_nhash *whlist, struct au_nhash *delist) +{ +#ifdef CONFIG_AUFS_SHWH + int err; + unsigned int nh, u; + struct hlist_head *head; + struct au_vdir_wh *tpos; + struct hlist_node *pos, *n; + char *p, *o; + struct au_vdir_destr *destr; + + AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH)); + + err = -ENOMEM; + o = p = __getname_gfp(GFP_NOFS); + if (unlikely(!p)) + goto out; + + err = 0; + nh = whlist->nh_num; + memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); + p += AUFS_WH_PFX_LEN; + for (u = 0; u < nh; u++) { + head = whlist->nh_head + u; + hlist_for_each_entry_safe(tpos, pos, n, head, wh_hash) { + destr = &tpos->wh_str; + memcpy(p, destr->name, destr->len); + err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN, + tpos->wh_ino, tpos->wh_type, delist); + if (unlikely(err)) + break; + } + } + + __putname(o); + +out: + AuTraceErr(err); + return err; +#else + return 0; +#endif +} + +static int au_do_read_vdir(struct fillvdir_arg *arg) +{ + int err; + unsigned int rdhash; + loff_t offset; + aufs_bindex_t bend, bindex, bstart; + unsigned char shwh; + struct file *hf, *file; + struct super_block *sb; + + file = arg->file; + sb = file->f_dentry->d_sb; + SiMustAnyLock(sb); + + rdhash = au_sbi(sb)->si_rdhash; + if (!rdhash) + rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL)); + err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS); + if (unlikely(err)) + goto out; + err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS); + if (unlikely(err)) + goto out_delist; + + err = 0; + arg->flags = 0; + shwh = 0; + if (au_opt_test(au_mntflags(sb), SHWH)) { + shwh = 1; + au_fset_fillvdir(arg->flags, SHWH); + } + bstart = au_fbstart(file); + bend = au_fbend_dir(file); + for (bindex = bstart; !err && bindex <= bend; bindex++) { + hf = au_hf_dir(file, bindex); + if (!hf) + continue; + + offset = vfsub_llseek(hf, 0, SEEK_SET); + err = offset; + if (unlikely(offset)) + break; + + arg->bindex = bindex; + au_fclr_fillvdir(arg->flags, WHABLE); + if (shwh + || (bindex != bend + && au_br_whable(au_sbr_perm(sb, bindex)))) + au_fset_fillvdir(arg->flags, WHABLE); + do { + arg->err = 0; + au_fclr_fillvdir(arg->flags, CALLED); + /* smp_mb(); */ + err = vfsub_readdir(hf, fillvdir, arg); + if (err >= 0) + err = arg->err; + } while (!err && au_ftest_fillvdir(arg->flags, CALLED)); + } + + if (!err && shwh) + err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist); + + au_nhash_wh_free(&arg->whlist); + +out_delist: + au_nhash_de_free(&arg->delist); +out: + return err; +} + +static int read_vdir(struct file *file, int may_read) +{ + int err; + unsigned long expire; + unsigned char do_read; + struct fillvdir_arg arg; + struct inode *inode; + struct au_vdir *vdir, *allocated; + + err = 0; + inode = file->f_dentry->d_inode; + IMustLock(inode); + SiMustAnyLock(inode->i_sb); + + allocated = NULL; + do_read = 0; + expire = au_sbi(inode->i_sb)->si_rdcache; + vdir = au_ivdir(inode); + if (!vdir) { + do_read = 1; + vdir = alloc_vdir(file); + err = PTR_ERR(vdir); + if (IS_ERR(vdir)) + goto out; + err = 0; + allocated = vdir; + } else if (may_read + && (inode->i_version != vdir->vd_version + || time_after(jiffies, vdir->vd_jiffy + expire))) { + do_read = 1; + err = reinit_vdir(vdir); + if (unlikely(err)) + goto out; + } + + if (!do_read) + return 0; /* success */ + + arg.file = file; + arg.vdir = vdir; + err = au_do_read_vdir(&arg); + if (!err) { + /* file->f_pos = 0; */ + vdir->vd_version = inode->i_version; + vdir->vd_last.ul = 0; + vdir->vd_last.p.deblk = vdir->vd_deblk[0]; + if (allocated) + au_set_ivdir(inode, allocated); + } else if (allocated) + au_vdir_free(allocated); + +out: + return err; +} + +static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src) +{ + int err, rerr; + unsigned long ul, n; + const unsigned int deblk_sz = src->vd_deblk_sz; + + AuDebugOn(tgt->vd_nblk != 1); + + err = -ENOMEM; + if (tgt->vd_nblk < src->vd_nblk) { + unsigned char **p; + + p = krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk, + GFP_NOFS); + if (unlikely(!p)) + goto out; + tgt->vd_deblk = p; + } + + if (tgt->vd_deblk_sz != deblk_sz) { + unsigned char *p; + + tgt->vd_deblk_sz = deblk_sz; + p = krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS); + if (unlikely(!p)) + goto out; + tgt->vd_deblk[0] = p; + } + memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz); + tgt->vd_version = src->vd_version; + tgt->vd_jiffy = src->vd_jiffy; + + n = src->vd_nblk; + for (ul = 1; ul < n; ul++) { + tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz, + GFP_NOFS); + if (unlikely(!tgt->vd_deblk[ul])) + goto out; + tgt->vd_nblk++; + } + tgt->vd_nblk = n; + tgt->vd_last.ul = tgt->vd_last.ul; + tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul]; + tgt->vd_last.p.deblk += src->vd_last.p.deblk + - src->vd_deblk[src->vd_last.ul]; + /* smp_mb(); */ + return 0; /* success */ + +out: + rerr = reinit_vdir(tgt); + BUG_ON(rerr); + return err; +} + +int au_vdir_init(struct file *file) +{ + int err; + struct inode *inode; + struct au_vdir *vdir_cache, *allocated; + + err = read_vdir(file, !file->f_pos); + if (unlikely(err)) + goto out; + + allocated = NULL; + vdir_cache = au_fvdir_cache(file); + if (!vdir_cache) { + vdir_cache = alloc_vdir(file); + err = PTR_ERR(vdir_cache); + if (IS_ERR(vdir_cache)) + goto out; + allocated = vdir_cache; + } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) { + err = reinit_vdir(vdir_cache); + if (unlikely(err)) + goto out; + } else + return 0; /* success */ + + inode = file->f_dentry->d_inode; + err = copy_vdir(vdir_cache, au_ivdir(inode)); + if (!err) { + file->f_version = inode->i_version; + if (allocated) + au_set_fvdir_cache(file, allocated); + } else if (allocated) + au_vdir_free(allocated); + +out: + return err; +} + +static loff_t calc_offset(struct au_vdir *vdir) +{ + loff_t offset; + union au_vdir_deblk_p p; + + p.deblk = vdir->vd_deblk[vdir->vd_last.ul]; + offset = vdir->vd_last.p.deblk - p.deblk; + offset += vdir->vd_deblk_sz * vdir->vd_last.ul; + return offset; +} + +/* returns true or false */ +static int seek_vdir(struct file *file) +{ + int valid; + unsigned int deblk_sz; + unsigned long ul, n; + loff_t offset; + union au_vdir_deblk_p p, deblk_end; + struct au_vdir *vdir_cache; + + valid = 1; + vdir_cache = au_fvdir_cache(file); + offset = calc_offset(vdir_cache); + AuDbg("offset %lld\n", offset); + if (file->f_pos == offset) + goto out; + + vdir_cache->vd_last.ul = 0; + vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0]; + if (!file->f_pos) + goto out; + + valid = 0; + deblk_sz = vdir_cache->vd_deblk_sz; + ul = div64_u64(file->f_pos, deblk_sz); + AuDbg("ul %lu\n", ul); + if (ul >= vdir_cache->vd_nblk) + goto out; + + n = vdir_cache->vd_nblk; + for (; ul < n; ul++) { + p.deblk = vdir_cache->vd_deblk[ul]; + deblk_end.deblk = p.deblk + deblk_sz; + offset = ul; + offset *= deblk_sz; + while (!is_deblk_end(&p, &deblk_end) && offset < file->f_pos) { + unsigned int l; + + l = calc_size(p.de->de_str.len); + offset += l; + p.deblk += l; + } + if (!is_deblk_end(&p, &deblk_end)) { + valid = 1; + vdir_cache->vd_last.ul = ul; + vdir_cache->vd_last.p = p; + break; + } + } + +out: + /* smp_mb(); */ + AuTraceErr(!valid); + return valid; +} + +int au_vdir_fill_de(struct file *file, void *dirent, filldir_t filldir) +{ + int err; + unsigned int l, deblk_sz; + union au_vdir_deblk_p deblk_end; + struct au_vdir *vdir_cache; + struct au_vdir_de *de; + + vdir_cache = au_fvdir_cache(file); + if (!seek_vdir(file)) + return 0; + + deblk_sz = vdir_cache->vd_deblk_sz; + while (1) { + deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; + deblk_end.deblk += deblk_sz; + while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) { + de = vdir_cache->vd_last.p.de; + AuDbg("%.*s, off%lld, i%lu, dt%d\n", + de->de_str.len, de->de_str.name, file->f_pos, + (unsigned long)de->de_ino, de->de_type); + err = filldir(dirent, de->de_str.name, de->de_str.len, + file->f_pos, de->de_ino, de->de_type); + if (unlikely(err)) { + AuTraceErr(err); + /* todo: ignore the error caused by udba? */ + /* return err; */ + return 0; + } + + l = calc_size(de->de_str.len); + vdir_cache->vd_last.p.deblk += l; + file->f_pos += l; + } + if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) { + vdir_cache->vd_last.ul++; + vdir_cache->vd_last.p.deblk + = vdir_cache->vd_deblk[vdir_cache->vd_last.ul]; + file->f_pos = deblk_sz * vdir_cache->vd_last.ul; + continue; + } + break; + } + + /* smp_mb(); */ + return 0; +} --- linux-2.6.37.orig/ubuntu/aufs/vfsub.c +++ linux-2.6.37/ubuntu/aufs/vfsub.c @@ -0,0 +1,790 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sub-routines for VFS + */ + +#include +#include +#include +#include +#include +#include +#include "aufs.h" + +int vfsub_update_h_iattr(struct path *h_path, int *did) +{ + int err; + struct kstat st; + struct super_block *h_sb; + + /* for remote fs, leave work for its getattr or d_revalidate */ + /* for bad i_attr fs, handle them in aufs_getattr() */ + /* still some fs may acquire i_mutex. we need to skip them */ + err = 0; + if (!did) + did = &err; + h_sb = h_path->dentry->d_sb; + *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb)); + if (*did) + err = vfs_getattr(h_path->mnt, h_path->dentry, &st); + + return err; +} + +/* ---------------------------------------------------------------------- */ + +static int au_conv_oflags(int flags) +{ + int mask = 0; + +#ifdef CONFIG_IMA + fmode_t fmode; + + /* mask = MAY_OPEN; */ + fmode = OPEN_FMODE(flags); + if (fmode & FMODE_READ) + mask |= MAY_READ; + if ((fmode & FMODE_WRITE) + || (flags & O_TRUNC)) + mask |= MAY_WRITE; + /* + * if (flags & O_APPEND) + * mask |= MAY_APPEND; + */ + if (flags & vfsub_fmode_to_uint(FMODE_EXEC)) + mask |= MAY_EXEC; + + AuDbg("flags 0x%x, mask 0x%x\n", flags, mask); +#endif + + return mask; +} + +struct file *vfsub_dentry_open(struct path *path, int flags) +{ + struct file *file; + int err; + + path_get(path); + file = dentry_open(path->dentry, path->mnt, + flags /* | vfsub_fmode_to_uint(FMODE_NONOTIFY) */, + current_cred()); + if (IS_ERR(file)) + goto out; + + err = ima_file_check(file, au_conv_oflags(flags)); + if (unlikely(err)) { + fput(file); + file = ERR_PTR(err); + } +out: + return file; +} + +struct file *vfsub_filp_open(const char *path, int oflags, int mode) +{ + struct file *file; + + file = filp_open(path, + oflags /* | vfsub_fmode_to_uint(FMODE_NONOTIFY) */, + mode); + if (IS_ERR(file)) + goto out; + vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ + +out: + return file; +} + +int vfsub_kern_path(const char *name, unsigned int flags, struct path *path) +{ + int err; + + err = kern_path(name, flags, path); + if (!err && path->dentry->d_inode) + vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/ + return err; +} + +struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, + int len) +{ + struct path path = { + .mnt = NULL + }; + + /* VFS checks it too, but by WARN_ON_ONCE() */ + IMustLock(parent->d_inode); + + path.dentry = lookup_one_len(name, parent, len); + if (IS_ERR(path.dentry)) + goto out; + if (path.dentry->d_inode) + vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ + +out: + AuTraceErrPtr(path.dentry); + return path.dentry; +} + +struct dentry *vfsub_lookup_hash(struct nameidata *nd) +{ + struct path path = { + .mnt = nd->path.mnt + }; + + IMustLock(nd->path.dentry->d_inode); + + path.dentry = lookup_hash(nd); + if (IS_ERR(path.dentry)) + goto out; + if (path.dentry->d_inode) + vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ + +out: + AuTraceErrPtr(path.dentry); + return path.dentry; +} + +/* ---------------------------------------------------------------------- */ + +struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, + struct dentry *d2, struct au_hinode *hdir2) +{ + struct dentry *d; + + d = lock_rename(d1, d2); + au_hn_suspend(hdir1); + if (hdir1 != hdir2) + au_hn_suspend(hdir2); + + return d; +} + +void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, + struct dentry *d2, struct au_hinode *hdir2) +{ + au_hn_resume(hdir1); + if (hdir1 != hdir2) + au_hn_resume(hdir2); + unlock_rename(d1, d2); +} + +/* ---------------------------------------------------------------------- */ + +int vfsub_create(struct inode *dir, struct path *path, int mode) +{ + int err; + struct dentry *d; + + IMustLock(dir); + + d = path->dentry; + path->dentry = d->d_parent; + err = security_path_mknod(path, d, mode, 0); + path->dentry = d; + if (unlikely(err)) + goto out; + + if (au_test_fs_null_nd(dir->i_sb)) + err = vfs_create(dir, path->dentry, mode, NULL); + else { + struct nameidata h_nd; + + memset(&h_nd, 0, sizeof(h_nd)); + h_nd.flags = LOOKUP_CREATE; + h_nd.intent.open.flags = O_CREAT + | vfsub_fmode_to_uint(FMODE_READ); + h_nd.intent.open.create_mode = mode; + h_nd.path.dentry = path->dentry->d_parent; + h_nd.path.mnt = path->mnt; + path_get(&h_nd.path); + err = vfs_create(dir, path->dentry, mode, &h_nd); + path_put(&h_nd.path); + } + + if (!err) { + struct path tmp = *path; + int did; + + vfsub_update_h_iattr(&tmp, &did); + if (did) { + tmp.dentry = path->dentry->d_parent; + vfsub_update_h_iattr(&tmp, /*did*/NULL); + } + /*ignore*/ + } + +out: + return err; +} + +int vfsub_symlink(struct inode *dir, struct path *path, const char *symname) +{ + int err; + struct dentry *d; + + IMustLock(dir); + + d = path->dentry; + path->dentry = d->d_parent; + err = security_path_symlink(path, d, symname); + path->dentry = d; + if (unlikely(err)) + goto out; + + err = vfs_symlink(dir, path->dentry, symname); + if (!err) { + struct path tmp = *path; + int did; + + vfsub_update_h_iattr(&tmp, &did); + if (did) { + tmp.dentry = path->dentry->d_parent; + vfsub_update_h_iattr(&tmp, /*did*/NULL); + } + /*ignore*/ + } + +out: + return err; +} + +int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev) +{ + int err; + struct dentry *d; + + IMustLock(dir); + + d = path->dentry; + path->dentry = d->d_parent; + err = security_path_mknod(path, d, mode, dev); + path->dentry = d; + if (unlikely(err)) + goto out; + + err = vfs_mknod(dir, path->dentry, mode, dev); + if (!err) { + struct path tmp = *path; + int did; + + vfsub_update_h_iattr(&tmp, &did); + if (did) { + tmp.dentry = path->dentry->d_parent; + vfsub_update_h_iattr(&tmp, /*did*/NULL); + } + /*ignore*/ + } + +out: + return err; +} + +static int au_test_nlink(struct inode *inode) +{ + const unsigned int link_max = UINT_MAX >> 1; /* rough margin */ + + if (!au_test_fs_no_limit_nlink(inode->i_sb) + || inode->i_nlink < link_max) + return 0; + return -EMLINK; +} + +int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path) +{ + int err; + struct dentry *d; + + IMustLock(dir); + + err = au_test_nlink(src_dentry->d_inode); + if (unlikely(err)) + return err; + + d = path->dentry; + path->dentry = d->d_parent; + err = security_path_link(src_dentry, path, d); + path->dentry = d; + if (unlikely(err)) + goto out; + + err = vfs_link(src_dentry, dir, path->dentry); + if (!err) { + struct path tmp = *path; + int did; + + /* fuse has different memory inode for the same inumber */ + vfsub_update_h_iattr(&tmp, &did); + if (did) { + tmp.dentry = path->dentry->d_parent; + vfsub_update_h_iattr(&tmp, /*did*/NULL); + tmp.dentry = src_dentry; + vfsub_update_h_iattr(&tmp, /*did*/NULL); + } + /*ignore*/ + } + +out: + return err; +} + +int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry, + struct inode *dir, struct path *path) +{ + int err; + struct path tmp = { + .mnt = path->mnt + }; + struct dentry *d; + + IMustLock(dir); + IMustLock(src_dir); + + d = path->dentry; + path->dentry = d->d_parent; + tmp.dentry = src_dentry->d_parent; + err = security_path_rename(&tmp, src_dentry, path, d); + path->dentry = d; + if (unlikely(err)) + goto out; + + err = vfs_rename(src_dir, src_dentry, dir, path->dentry); + if (!err) { + int did; + + tmp.dentry = d->d_parent; + vfsub_update_h_iattr(&tmp, &did); + if (did) { + tmp.dentry = src_dentry; + vfsub_update_h_iattr(&tmp, /*did*/NULL); + tmp.dentry = src_dentry->d_parent; + vfsub_update_h_iattr(&tmp, /*did*/NULL); + } + /*ignore*/ + } + +out: + return err; +} + +int vfsub_mkdir(struct inode *dir, struct path *path, int mode) +{ + int err; + struct dentry *d; + + IMustLock(dir); + + d = path->dentry; + path->dentry = d->d_parent; + err = security_path_mkdir(path, d, mode); + path->dentry = d; + if (unlikely(err)) + goto out; + + err = vfs_mkdir(dir, path->dentry, mode); + if (!err) { + struct path tmp = *path; + int did; + + vfsub_update_h_iattr(&tmp, &did); + if (did) { + tmp.dentry = path->dentry->d_parent; + vfsub_update_h_iattr(&tmp, /*did*/NULL); + } + /*ignore*/ + } + +out: + return err; +} + +int vfsub_rmdir(struct inode *dir, struct path *path) +{ + int err; + struct dentry *d; + + IMustLock(dir); + + d = path->dentry; + path->dentry = d->d_parent; + err = security_path_rmdir(path, d); + path->dentry = d; + if (unlikely(err)) + goto out; + + err = vfs_rmdir(dir, path->dentry); + if (!err) { + struct path tmp = { + .dentry = path->dentry->d_parent, + .mnt = path->mnt + }; + + vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ + } + +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, + loff_t *ppos) +{ + ssize_t err; + + err = vfs_read(file, ubuf, count, ppos); + if (err >= 0) + vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ + return err; +} + +/* todo: kernel_read()? */ +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, + loff_t *ppos) +{ + ssize_t err; + mm_segment_t oldfs; + union { + void *k; + char __user *u; + } buf; + + buf.k = kbuf; + oldfs = get_fs(); + set_fs(KERNEL_DS); + err = vfsub_read_u(file, buf.u, count, ppos); + set_fs(oldfs); + return err; +} + +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, + loff_t *ppos) +{ + ssize_t err; + + err = vfs_write(file, ubuf, count, ppos); + if (err >= 0) + vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ + return err; +} + +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos) +{ + ssize_t err; + mm_segment_t oldfs; + union { + void *k; + const char __user *u; + } buf; + + buf.k = kbuf; + oldfs = get_fs(); + set_fs(KERNEL_DS); + err = vfsub_write_u(file, buf.u, count, ppos); + set_fs(oldfs); + return err; +} + +int vfsub_flush(struct file *file, fl_owner_t id) +{ + int err; + + err = 0; + if (file->f_op && file->f_op->flush) { + err = file->f_op->flush(file, id); + if (!err) + vfsub_update_h_iattr(&file->f_path, /*did*/NULL); + /*ignore*/ + } + return err; +} + +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg) +{ + int err; + + err = vfs_readdir(file, filldir, arg); + if (err >= 0) + vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ + return err; +} + +long vfsub_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) +{ + long err; + + err = do_splice_to(in, ppos, pipe, len, flags); + file_accessed(in); + if (err >= 0) + vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/ + return err; +} + +long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) +{ + long err; + + err = do_splice_from(pipe, out, ppos, len, flags); + if (err >= 0) + vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/ + return err; +} + +/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */ +int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, + struct file *h_file) +{ + int err; + struct inode *h_inode; + + h_inode = h_path->dentry->d_inode; + if (!h_file) { + err = mnt_want_write(h_path->mnt); + if (err) + goto out; + err = inode_permission(h_inode, MAY_WRITE); + if (err) + goto out_mnt; + err = get_write_access(h_inode); + if (err) + goto out_mnt; + err = break_lease(h_inode, O_WRONLY); + if (err) + goto out_inode; + } + + err = locks_verify_truncate(h_inode, h_file, length); + if (!err) + err = security_path_truncate(h_path); + if (!err) + err = do_truncate(h_path->dentry, length, attr, h_file); + +out_inode: + if (!h_file) + put_write_access(h_inode); +out_mnt: + if (!h_file) + mnt_drop_write(h_path->mnt); +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct au_vfsub_mkdir_args { + int *errp; + struct inode *dir; + struct path *path; + int mode; +}; + +static void au_call_vfsub_mkdir(void *args) +{ + struct au_vfsub_mkdir_args *a = args; + *a->errp = vfsub_mkdir(a->dir, a->path, a->mode); +} + +int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode) +{ + int err, do_sio, wkq_err; + + do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); + if (!do_sio) + err = vfsub_mkdir(dir, path, mode); + else { + struct au_vfsub_mkdir_args args = { + .errp = &err, + .dir = dir, + .path = path, + .mode = mode + }; + wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args); + if (unlikely(wkq_err)) + err = wkq_err; + } + + return err; +} + +struct au_vfsub_rmdir_args { + int *errp; + struct inode *dir; + struct path *path; +}; + +static void au_call_vfsub_rmdir(void *args) +{ + struct au_vfsub_rmdir_args *a = args; + *a->errp = vfsub_rmdir(a->dir, a->path); +} + +int vfsub_sio_rmdir(struct inode *dir, struct path *path) +{ + int err, do_sio, wkq_err; + + do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); + if (!do_sio) + err = vfsub_rmdir(dir, path); + else { + struct au_vfsub_rmdir_args args = { + .errp = &err, + .dir = dir, + .path = path + }; + wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args); + if (unlikely(wkq_err)) + err = wkq_err; + } + + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct notify_change_args { + int *errp; + struct path *path; + struct iattr *ia; +}; + +static void call_notify_change(void *args) +{ + struct notify_change_args *a = args; + struct inode *h_inode; + + h_inode = a->path->dentry->d_inode; + IMustLock(h_inode); + + *a->errp = -EPERM; + if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) { + *a->errp = notify_change(a->path->dentry, a->ia); + if (!*a->errp) + vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/ + } + AuTraceErr(*a->errp); +} + +int vfsub_notify_change(struct path *path, struct iattr *ia) +{ + int err; + struct notify_change_args args = { + .errp = &err, + .path = path, + .ia = ia + }; + + call_notify_change(&args); + + return err; +} + +int vfsub_sio_notify_change(struct path *path, struct iattr *ia) +{ + int err, wkq_err; + struct notify_change_args args = { + .errp = &err, + .path = path, + .ia = ia + }; + + wkq_err = au_wkq_wait(call_notify_change, &args); + if (unlikely(wkq_err)) + err = wkq_err; + + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct unlink_args { + int *errp; + struct inode *dir; + struct path *path; +}; + +static void call_unlink(void *args) +{ + struct unlink_args *a = args; + struct dentry *d = a->path->dentry; + struct inode *h_inode; + const int stop_sillyrename = (au_test_nfs(d->d_sb) + && atomic_read(&d->d_count) == 1); + + IMustLock(a->dir); + + a->path->dentry = d->d_parent; + *a->errp = security_path_unlink(a->path, d); + a->path->dentry = d; + if (unlikely(*a->errp)) + return; + + if (!stop_sillyrename) + dget(d); + h_inode = d->d_inode; + if (h_inode) + ihold(h_inode); + + *a->errp = vfs_unlink(a->dir, d); + if (!*a->errp) { + struct path tmp = { + .dentry = d->d_parent, + .mnt = a->path->mnt + }; + vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/ + } + + if (!stop_sillyrename) + dput(d); + if (h_inode) + iput(h_inode); + + AuTraceErr(*a->errp); +} + +/* + * @dir: must be locked. + * @dentry: target dentry. + */ +int vfsub_unlink(struct inode *dir, struct path *path, int force) +{ + int err; + struct unlink_args args = { + .errp = &err, + .dir = dir, + .path = path + }; + + if (!force) + call_unlink(&args); + else { + int wkq_err; + + wkq_err = au_wkq_wait(call_unlink, &args); + if (unlikely(wkq_err)) + err = wkq_err; + } + + return err; +} --- linux-2.6.37.orig/ubuntu/aufs/vfsub.h +++ linux-2.6.37/ubuntu/aufs/vfsub.h @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * sub-routines for VFS + */ + +#ifndef __AUFS_VFSUB_H__ +#define __AUFS_VFSUB_H__ + +#ifdef __KERNEL__ + +#include +#include +#include "debug.h" + +/* copied from linux/fs/internal.h */ +DECLARE_BRLOCK(vfsmount_lock); +extern void file_sb_list_del(struct file *f); + +/* copied from linux/fs/file_table.c */ +DECLARE_LGLOCK(files_lglock); +#ifdef CONFIG_SMP +/* + * These macros iterate all files on all CPUs for a given superblock. + * files_lglock must be held globally. + */ +#define do_file_list_for_each_entry(__sb, __file) \ +{ \ + int i; \ + for_each_possible_cpu(i) { \ + struct list_head *list; \ + list = per_cpu_ptr((__sb)->s_files, i); \ + list_for_each_entry((__file), list, f_u.fu_list) + +#define while_file_list_for_each_entry \ + } \ +} + +#else + +#define do_file_list_for_each_entry(__sb, __file) \ +{ \ + struct list_head *list; \ + list = &(sb)->s_files; \ + list_for_each_entry((__file), list, f_u.fu_list) + +#define while_file_list_for_each_entry \ +} +#endif + +/* ---------------------------------------------------------------------- */ + +/* lock subclass for lower inode */ +/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */ +/* reduce? gave up. */ +enum { + AuLsc_I_Begin = I_MUTEX_QUOTA, /* 4 */ + AuLsc_I_PARENT, /* lower inode, parent first */ + AuLsc_I_PARENT2, /* copyup dirs */ + AuLsc_I_PARENT3, /* copyup wh */ + AuLsc_I_CHILD, + AuLsc_I_CHILD2, + AuLsc_I_End +}; + +/* to debug easier, do not make them inlined functions */ +#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx)) +#define IMustLock(i) MtxMustLock(&(i)->i_mutex) + +/* ---------------------------------------------------------------------- */ + +static inline void vfsub_drop_nlink(struct inode *inode) +{ + AuDebugOn(!inode->i_nlink); + drop_nlink(inode); +} + +/* ---------------------------------------------------------------------- */ + +int vfsub_update_h_iattr(struct path *h_path, int *did); +struct file *vfsub_dentry_open(struct path *path, int flags); +struct file *vfsub_filp_open(const char *path, int oflags, int mode); +int vfsub_kern_path(const char *name, unsigned int flags, struct path *path); +struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, + int len); +struct dentry *vfsub_lookup_hash(struct nameidata *nd); + +/* ---------------------------------------------------------------------- */ + +struct au_hinode; +struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1, + struct dentry *d2, struct au_hinode *hdir2); +void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1, + struct dentry *d2, struct au_hinode *hdir2); + +int vfsub_create(struct inode *dir, struct path *path, int mode); +int vfsub_symlink(struct inode *dir, struct path *path, + const char *symname); +int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev); +int vfsub_link(struct dentry *src_dentry, struct inode *dir, + struct path *path); +int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry, + struct inode *hdir, struct path *path); +int vfsub_mkdir(struct inode *dir, struct path *path, int mode); +int vfsub_rmdir(struct inode *dir, struct path *path); + +/* ---------------------------------------------------------------------- */ + +ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count, + loff_t *ppos); +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, + loff_t *ppos); +ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count, + loff_t *ppos); +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, + loff_t *ppos); +int vfsub_flush(struct file *file, fl_owner_t id); +int vfsub_readdir(struct file *file, filldir_t filldir, void *arg); + +static inline unsigned int vfsub_file_flags(struct file *file) +{ + unsigned int flags; + + spin_lock(&file->f_lock); + flags = file->f_flags; + spin_unlock(&file->f_lock); + + return flags; +} + +static inline void vfsub_file_accessed(struct file *h_file) +{ + file_accessed(h_file); + vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/ +} + +static inline void vfsub_touch_atime(struct vfsmount *h_mnt, + struct dentry *h_dentry) +{ + struct path h_path = { + .dentry = h_dentry, + .mnt = h_mnt + }; + touch_atime(h_mnt, h_dentry); + vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/ +} + +long vfsub_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags); +long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags); +int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr, + struct file *h_file); + +/* ---------------------------------------------------------------------- */ + +static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin) +{ + loff_t err; + + err = vfs_llseek(file, offset, origin); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* dirty workaround for strict type of fmode_t */ +union vfsub_fmu { + fmode_t fm; + unsigned int ui; +}; + +static inline unsigned int vfsub_fmode_to_uint(fmode_t fm) +{ + union vfsub_fmu u = { + .fm = fm + }; + + BUILD_BUG_ON(sizeof(u.fm) != sizeof(u.ui)); + + return u.ui; +} + +static inline fmode_t vfsub_uint_to_fmode(unsigned int ui) +{ + union vfsub_fmu u = { + .ui = ui + }; + + return u.fm; +} + +/* ---------------------------------------------------------------------- */ + +int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode); +int vfsub_sio_rmdir(struct inode *dir, struct path *path); +int vfsub_sio_notify_change(struct path *path, struct iattr *ia); +int vfsub_notify_change(struct path *path, struct iattr *ia); +int vfsub_unlink(struct inode *dir, struct path *path, int force); + +#endif /* __KERNEL__ */ +#endif /* __AUFS_VFSUB_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/wbr_policy.c +++ linux-2.6.37/ubuntu/aufs/wbr_policy.c @@ -0,0 +1,701 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * policies for selecting one among multiple writable branches + */ + +#include +#include "aufs.h" + +/* subset of cpup_attr() */ +static noinline_for_stack +int au_cpdown_attr(struct path *h_path, struct dentry *h_src) +{ + int err, sbits; + struct iattr ia; + struct inode *h_isrc; + + h_isrc = h_src->d_inode; + ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID; + ia.ia_mode = h_isrc->i_mode; + ia.ia_uid = h_isrc->i_uid; + ia.ia_gid = h_isrc->i_gid; + sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID)); + au_cpup_attr_flags(h_path->dentry->d_inode, h_isrc); + err = vfsub_sio_notify_change(h_path, &ia); + + /* is this nfs only? */ + if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) { + ia.ia_valid = ATTR_FORCE | ATTR_MODE; + ia.ia_mode = h_isrc->i_mode; + err = vfsub_sio_notify_change(h_path, &ia); + } + + return err; +} + +#define AuCpdown_PARENT_OPQ 1 +#define AuCpdown_WHED (1 << 1) +#define AuCpdown_MADE_DIR (1 << 2) +#define AuCpdown_DIROPQ (1 << 3) +#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name) +#define au_fset_cpdown(flags, name) \ + do { (flags) |= AuCpdown_##name; } while (0) +#define au_fclr_cpdown(flags, name) \ + do { (flags) &= ~AuCpdown_##name; } while (0) + +struct au_cpdown_dir_args { + struct dentry *parent; + unsigned int flags; +}; + +static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst, + struct au_cpdown_dir_args *a) +{ + int err; + struct dentry *opq_dentry; + + opq_dentry = au_diropq_create(dentry, bdst); + err = PTR_ERR(opq_dentry); + if (IS_ERR(opq_dentry)) + goto out; + dput(opq_dentry); + au_fset_cpdown(a->flags, DIROPQ); + +out: + return err; +} + +static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent, + struct inode *dir, aufs_bindex_t bdst) +{ + int err; + struct path h_path; + struct au_branch *br; + + br = au_sbr(dentry->d_sb, bdst); + h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br); + err = PTR_ERR(h_path.dentry); + if (IS_ERR(h_path.dentry)) + goto out; + + err = 0; + if (h_path.dentry->d_inode) { + h_path.mnt = br->br_mnt; + err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path, + dentry); + } + dput(h_path.dentry); + +out: + return err; +} + +static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst, + struct dentry *h_parent, void *arg) +{ + int err, rerr; + aufs_bindex_t bopq, bstart; + struct path h_path; + struct dentry *parent; + struct inode *h_dir, *h_inode, *inode, *dir; + struct au_cpdown_dir_args *args = arg; + + bstart = au_dbstart(dentry); + /* dentry is di-locked */ + parent = dget_parent(dentry); + dir = parent->d_inode; + h_dir = h_parent->d_inode; + AuDebugOn(h_dir != au_h_iptr(dir, bdst)); + IMustLock(h_dir); + + err = au_lkup_neg(dentry, bdst); + if (unlikely(err < 0)) + goto out; + h_path.dentry = au_h_dptr(dentry, bdst); + h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst); + err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, + S_IRWXU | S_IRUGO | S_IXUGO); + if (unlikely(err)) + goto out_put; + au_fset_cpdown(args->flags, MADE_DIR); + + bopq = au_dbdiropq(dentry); + au_fclr_cpdown(args->flags, WHED); + au_fclr_cpdown(args->flags, DIROPQ); + if (au_dbwh(dentry) == bdst) + au_fset_cpdown(args->flags, WHED); + if (!au_ftest_cpdown(args->flags, PARENT_OPQ) && bopq <= bdst) + au_fset_cpdown(args->flags, PARENT_OPQ); + h_inode = h_path.dentry->d_inode; + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + if (au_ftest_cpdown(args->flags, WHED)) { + err = au_cpdown_dir_opq(dentry, bdst, args); + if (unlikely(err)) { + mutex_unlock(&h_inode->i_mutex); + goto out_dir; + } + } + + err = au_cpdown_attr(&h_path, au_h_dptr(dentry, bstart)); + mutex_unlock(&h_inode->i_mutex); + if (unlikely(err)) + goto out_opq; + + if (au_ftest_cpdown(args->flags, WHED)) { + err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst); + if (unlikely(err)) + goto out_opq; + } + + inode = dentry->d_inode; + if (au_ibend(inode) < bdst) + au_set_ibend(inode, bdst); + au_set_h_iptr(inode, bdst, au_igrab(h_inode), + au_hi_flags(inode, /*isdir*/1)); + goto out; /* success */ + + /* revert */ +out_opq: + if (au_ftest_cpdown(args->flags, DIROPQ)) { + mutex_lock_nested(&h_inode->i_mutex, AuLsc_I_CHILD); + rerr = au_diropq_remove(dentry, bdst); + mutex_unlock(&h_inode->i_mutex); + if (unlikely(rerr)) { + AuIOErr("failed removing diropq for %.*s b%d (%d)\n", + AuDLNPair(dentry), bdst, rerr); + err = -EIO; + goto out; + } + } +out_dir: + if (au_ftest_cpdown(args->flags, MADE_DIR)) { + rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path); + if (unlikely(rerr)) { + AuIOErr("failed removing %.*s b%d (%d)\n", + AuDLNPair(dentry), bdst, rerr); + err = -EIO; + } + } +out_put: + au_set_h_dptr(dentry, bdst, NULL); + if (au_dbend(dentry) == bdst) + au_update_dbend(dentry); +out: + dput(parent); + return err; +} + +int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst) +{ + int err; + struct au_cpdown_dir_args args = { + .parent = dget_parent(dentry), + .flags = 0 + }; + + err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &args); + dput(args.parent); + + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* policies for create */ + +static int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex) +{ + int err, i, j, ndentry; + aufs_bindex_t bopq; + struct au_dcsub_pages dpages; + struct au_dpage *dpage; + struct dentry **dentries, *parent, *d; + + err = au_dpages_init(&dpages, GFP_NOFS); + if (unlikely(err)) + goto out; + parent = dget_parent(dentry); + err = au_dcsub_pages_rev(&dpages, parent, /*do_include*/0, /*test*/NULL, + /*arg*/NULL); + if (unlikely(err)) + goto out_free; + + err = bindex; + for (i = 0; i < dpages.ndpage; i++) { + dpage = dpages.dpages + i; + dentries = dpage->dentries; + ndentry = dpage->ndentry; + for (j = 0; j < ndentry; j++) { + d = dentries[j]; + di_read_lock_parent2(d, !AuLock_IR); + bopq = au_dbdiropq(d); + di_read_unlock(d, !AuLock_IR); + if (bopq >= 0 && bopq < err) + err = bopq; + } + } + +out_free: + dput(parent); + au_dpages_free(&dpages); +out: + return err; +} + +static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex) +{ + for (; bindex >= 0; bindex--) + if (!au_br_rdonly(au_sbr(sb, bindex))) + return bindex; + return -EROFS; +} + +/* top down parent */ +static int au_wbr_create_tdp(struct dentry *dentry, int isdir __maybe_unused) +{ + int err; + aufs_bindex_t bstart, bindex; + struct super_block *sb; + struct dentry *parent, *h_parent; + + sb = dentry->d_sb; + bstart = au_dbstart(dentry); + err = bstart; + if (!au_br_rdonly(au_sbr(sb, bstart))) + goto out; + + err = -EROFS; + parent = dget_parent(dentry); + for (bindex = au_dbstart(parent); bindex < bstart; bindex++) { + h_parent = au_h_dptr(parent, bindex); + if (!h_parent || !h_parent->d_inode) + continue; + + if (!au_br_rdonly(au_sbr(sb, bindex))) { + err = bindex; + break; + } + } + dput(parent); + + /* bottom up here */ + if (unlikely(err < 0)) { + err = au_wbr_bu(sb, bstart - 1); + if (err >= 0) + err = au_wbr_nonopq(dentry, err); + } + +out: + AuDbg("b%d\n", err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* an exception for the policy other than tdp */ +static int au_wbr_create_exp(struct dentry *dentry) +{ + int err; + aufs_bindex_t bwh, bdiropq; + struct dentry *parent; + + err = -1; + bwh = au_dbwh(dentry); + parent = dget_parent(dentry); + bdiropq = au_dbdiropq(parent); + if (bwh >= 0) { + if (bdiropq >= 0) + err = min(bdiropq, bwh); + else + err = bwh; + AuDbg("%d\n", err); + } else if (bdiropq >= 0) { + err = bdiropq; + AuDbg("%d\n", err); + } + dput(parent); + + if (err >= 0) + err = au_wbr_nonopq(dentry, err); + + if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err))) + err = -1; + + AuDbg("%d\n", err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* round robin */ +static int au_wbr_create_init_rr(struct super_block *sb) +{ + int err; + + err = au_wbr_bu(sb, au_sbend(sb)); + atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */ + /* smp_mb(); */ + + AuDbg("b%d\n", err); + return err; +} + +static int au_wbr_create_rr(struct dentry *dentry, int isdir) +{ + int err, nbr; + unsigned int u; + aufs_bindex_t bindex, bend; + struct super_block *sb; + atomic_t *next; + + err = au_wbr_create_exp(dentry); + if (err >= 0) + goto out; + + sb = dentry->d_sb; + next = &au_sbi(sb)->si_wbr_rr_next; + bend = au_sbend(sb); + nbr = bend + 1; + for (bindex = 0; bindex <= bend; bindex++) { + if (!isdir) { + err = atomic_dec_return(next) + 1; + /* modulo for 0 is meaningless */ + if (unlikely(!err)) + err = atomic_dec_return(next) + 1; + } else + err = atomic_read(next); + AuDbg("%d\n", err); + u = err; + err = u % nbr; + AuDbg("%d\n", err); + if (!au_br_rdonly(au_sbr(sb, err))) + break; + err = -EROFS; + } + + if (err >= 0) + err = au_wbr_nonopq(dentry, err); + +out: + AuDbg("%d\n", err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* most free space */ +static void au_mfs(struct dentry *dentry) +{ + struct super_block *sb; + struct au_branch *br; + struct au_wbr_mfs *mfs; + aufs_bindex_t bindex, bend; + int err; + unsigned long long b, bavail; + struct path h_path; + /* reduce the stack usage */ + struct kstatfs *st; + + st = kmalloc(sizeof(*st), GFP_NOFS); + if (unlikely(!st)) { + AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM); + return; + } + + bavail = 0; + sb = dentry->d_sb; + mfs = &au_sbi(sb)->si_wbr_mfs; + MtxMustLock(&mfs->mfs_lock); + mfs->mfs_bindex = -EROFS; + mfs->mfsrr_bytes = 0; + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + if (au_br_rdonly(br)) + continue; + + /* sb->s_root for NFS is unreliable */ + h_path.mnt = br->br_mnt; + h_path.dentry = h_path.mnt->mnt_root; + err = vfs_statfs(&h_path, st); + if (unlikely(err)) { + AuWarn1("failed statfs, b%d, %d\n", bindex, err); + continue; + } + + /* when the available size is equal, select the lower one */ + BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail) + || sizeof(b) < sizeof(st->f_bsize)); + b = st->f_bavail * st->f_bsize; + br->br_wbr->wbr_bytes = b; + if (b >= bavail) { + bavail = b; + mfs->mfs_bindex = bindex; + mfs->mfs_jiffy = jiffies; + } + } + + mfs->mfsrr_bytes = bavail; + AuDbg("b%d\n", mfs->mfs_bindex); + kfree(st); +} + +static int au_wbr_create_mfs(struct dentry *dentry, int isdir __maybe_unused) +{ + int err; + struct super_block *sb; + struct au_wbr_mfs *mfs; + + err = au_wbr_create_exp(dentry); + if (err >= 0) + goto out; + + sb = dentry->d_sb; + mfs = &au_sbi(sb)->si_wbr_mfs; + mutex_lock(&mfs->mfs_lock); + if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire) + || mfs->mfs_bindex < 0 + || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex))) + au_mfs(dentry); + mutex_unlock(&mfs->mfs_lock); + err = mfs->mfs_bindex; + + if (err >= 0) + err = au_wbr_nonopq(dentry, err); + +out: + AuDbg("b%d\n", err); + return err; +} + +static int au_wbr_create_init_mfs(struct super_block *sb) +{ + struct au_wbr_mfs *mfs; + + mfs = &au_sbi(sb)->si_wbr_mfs; + mutex_init(&mfs->mfs_lock); + mfs->mfs_jiffy = 0; + mfs->mfs_bindex = -EROFS; + + return 0; +} + +static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused) +{ + mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock); + return 0; +} + +/* ---------------------------------------------------------------------- */ + +/* most free space and then round robin */ +static int au_wbr_create_mfsrr(struct dentry *dentry, int isdir) +{ + int err; + struct au_wbr_mfs *mfs; + + err = au_wbr_create_mfs(dentry, isdir); + if (err >= 0) { + mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs; + mutex_lock(&mfs->mfs_lock); + if (mfs->mfsrr_bytes < mfs->mfsrr_watermark) + err = au_wbr_create_rr(dentry, isdir); + mutex_unlock(&mfs->mfs_lock); + } + + AuDbg("b%d\n", err); + return err; +} + +static int au_wbr_create_init_mfsrr(struct super_block *sb) +{ + int err; + + au_wbr_create_init_mfs(sb); /* ignore */ + err = au_wbr_create_init_rr(sb); + + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* top down parent and most free space */ +static int au_wbr_create_pmfs(struct dentry *dentry, int isdir) +{ + int err, e2; + unsigned long long b; + aufs_bindex_t bindex, bstart, bend; + struct super_block *sb; + struct dentry *parent, *h_parent; + struct au_branch *br; + + err = au_wbr_create_tdp(dentry, isdir); + if (unlikely(err < 0)) + goto out; + parent = dget_parent(dentry); + bstart = au_dbstart(parent); + bend = au_dbtaildir(parent); + if (bstart == bend) + goto out_parent; /* success */ + + e2 = au_wbr_create_mfs(dentry, isdir); + if (e2 < 0) + goto out_parent; /* success */ + + /* when the available size is equal, select upper one */ + sb = dentry->d_sb; + br = au_sbr(sb, err); + b = br->br_wbr->wbr_bytes; + AuDbg("b%d, %llu\n", err, b); + + for (bindex = bstart; bindex <= bend; bindex++) { + h_parent = au_h_dptr(parent, bindex); + if (!h_parent || !h_parent->d_inode) + continue; + + br = au_sbr(sb, bindex); + if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) { + b = br->br_wbr->wbr_bytes; + err = bindex; + AuDbg("b%d, %llu\n", err, b); + } + } + + if (err >= 0) + err = au_wbr_nonopq(dentry, err); + +out_parent: + dput(parent); +out: + AuDbg("b%d\n", err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* policies for copyup */ + +/* top down parent */ +static int au_wbr_copyup_tdp(struct dentry *dentry) +{ + return au_wbr_create_tdp(dentry, /*isdir, anything is ok*/0); +} + +/* bottom up parent */ +static int au_wbr_copyup_bup(struct dentry *dentry) +{ + int err; + aufs_bindex_t bindex, bstart; + struct dentry *parent, *h_parent; + struct super_block *sb; + + err = -EROFS; + sb = dentry->d_sb; + parent = dget_parent(dentry); + bstart = au_dbstart(parent); + for (bindex = au_dbstart(dentry); bindex >= bstart; bindex--) { + h_parent = au_h_dptr(parent, bindex); + if (!h_parent || !h_parent->d_inode) + continue; + + if (!au_br_rdonly(au_sbr(sb, bindex))) { + err = bindex; + break; + } + } + dput(parent); + + /* bottom up here */ + if (unlikely(err < 0)) + err = au_wbr_bu(sb, bstart - 1); + + AuDbg("b%d\n", err); + return err; +} + +/* bottom up */ +static int au_wbr_copyup_bu(struct dentry *dentry) +{ + int err; + aufs_bindex_t bstart; + + bstart = au_dbstart(dentry); + err = au_wbr_bu(dentry->d_sb, bstart); + AuDbg("b%d\n", err); + if (err > bstart) + err = au_wbr_nonopq(dentry, err); + + AuDbg("b%d\n", err); + return err; +} + +/* ---------------------------------------------------------------------- */ + +struct au_wbr_copyup_operations au_wbr_copyup_ops[] = { + [AuWbrCopyup_TDP] = { + .copyup = au_wbr_copyup_tdp + }, + [AuWbrCopyup_BUP] = { + .copyup = au_wbr_copyup_bup + }, + [AuWbrCopyup_BU] = { + .copyup = au_wbr_copyup_bu + } +}; + +struct au_wbr_create_operations au_wbr_create_ops[] = { + [AuWbrCreate_TDP] = { + .create = au_wbr_create_tdp + }, + [AuWbrCreate_RR] = { + .create = au_wbr_create_rr, + .init = au_wbr_create_init_rr + }, + [AuWbrCreate_MFS] = { + .create = au_wbr_create_mfs, + .init = au_wbr_create_init_mfs, + .fin = au_wbr_create_fin_mfs + }, + [AuWbrCreate_MFSV] = { + .create = au_wbr_create_mfs, + .init = au_wbr_create_init_mfs, + .fin = au_wbr_create_fin_mfs + }, + [AuWbrCreate_MFSRR] = { + .create = au_wbr_create_mfsrr, + .init = au_wbr_create_init_mfsrr, + .fin = au_wbr_create_fin_mfs + }, + [AuWbrCreate_MFSRRV] = { + .create = au_wbr_create_mfsrr, + .init = au_wbr_create_init_mfsrr, + .fin = au_wbr_create_fin_mfs + }, + [AuWbrCreate_PMFS] = { + .create = au_wbr_create_pmfs, + .init = au_wbr_create_init_mfs, + .fin = au_wbr_create_fin_mfs + }, + [AuWbrCreate_PMFSV] = { + .create = au_wbr_create_pmfs, + .init = au_wbr_create_init_mfs, + .fin = au_wbr_create_fin_mfs + } +}; --- linux-2.6.37.orig/ubuntu/aufs/whout.c +++ linux-2.6.37/ubuntu/aufs/whout.c @@ -0,0 +1,1060 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * whiteout for logical deletion and opaque directory + */ + +#include +#include "aufs.h" + +#define WH_MASK S_IRUGO + +/* + * If a directory contains this file, then it is opaque. We start with the + * .wh. flag so that it is blocked by lookup. + */ +static struct qstr diropq_name = { + .name = AUFS_WH_DIROPQ, + .len = sizeof(AUFS_WH_DIROPQ) - 1 +}; + +/* + * generate whiteout name, which is NOT terminated by NULL. + * @name: original d_name.name + * @len: original d_name.len + * @wh: whiteout qstr + * returns zero when succeeds, otherwise error. + * succeeded value as wh->name should be freed by kfree(). + */ +int au_wh_name_alloc(struct qstr *wh, const struct qstr *name) +{ + char *p; + + if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN)) + return -ENAMETOOLONG; + + wh->len = name->len + AUFS_WH_PFX_LEN; + p = kmalloc(wh->len, GFP_NOFS); + wh->name = p; + if (p) { + memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); + memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len); + /* smp_mb(); */ + return 0; + } + return -ENOMEM; +} + +/* ---------------------------------------------------------------------- */ + +/* + * test if the @wh_name exists under @h_parent. + * @try_sio specifies the necessary of super-io. + */ +int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, + struct au_branch *br, int try_sio) +{ + int err; + struct dentry *wh_dentry; + + if (!try_sio) + wh_dentry = au_lkup_one(wh_name, h_parent, br, /*nd*/NULL); + else + wh_dentry = au_sio_lkup_one(wh_name, h_parent, br); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) + goto out; + + err = 0; + if (!wh_dentry->d_inode) + goto out_wh; /* success */ + + err = 1; + if (S_ISREG(wh_dentry->d_inode->i_mode)) + goto out_wh; /* success */ + + err = -EIO; + AuIOErr("%.*s Invalid whiteout entry type 0%o.\n", + AuDLNPair(wh_dentry), wh_dentry->d_inode->i_mode); + +out_wh: + dput(wh_dentry); +out: + return err; +} + +/* + * test if the @h_dentry sets opaque or not. + */ +int au_diropq_test(struct dentry *h_dentry, struct au_branch *br) +{ + int err; + struct inode *h_dir; + + h_dir = h_dentry->d_inode; + err = au_wh_test(h_dentry, &diropq_name, br, + au_test_h_perm_sio(h_dir, MAY_EXEC)); + return err; +} + +/* + * returns a negative dentry whose name is unique and temporary. + */ +struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, + struct qstr *prefix) +{ + struct dentry *dentry; + int i; + char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN_MIN + 1], + *name, *p; + static unsigned short cnt; + struct qstr qs; + + BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN); + + name = defname; + qs.len = sizeof(defname) - DNAME_INLINE_LEN_MIN + prefix->len - 1; + if (unlikely(prefix->len > DNAME_INLINE_LEN_MIN)) { + dentry = ERR_PTR(-ENAMETOOLONG); + if (unlikely(qs.len > NAME_MAX)) + goto out; + dentry = ERR_PTR(-ENOMEM); + name = kmalloc(qs.len + 1, GFP_NOFS); + if (unlikely(!name)) + goto out; + } + + /* doubly whiteout-ed */ + memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2); + p = name + AUFS_WH_PFX_LEN * 2; + memcpy(p, prefix->name, prefix->len); + p += prefix->len; + *p++ = '.'; + AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN); + + qs.name = name; + for (i = 0; i < 3; i++) { + sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++); + dentry = au_sio_lkup_one(&qs, h_parent, br); + if (IS_ERR(dentry) || !dentry->d_inode) + goto out_name; + dput(dentry); + } + /* pr_warning("could not get random name\n"); */ + dentry = ERR_PTR(-EEXIST); + AuDbg("%.*s\n", AuLNPair(&qs)); + BUG(); + +out_name: + if (name != defname) + kfree(name); +out: + AuTraceErrPtr(dentry); + return dentry; +} + +/* + * rename the @h_dentry on @br to the whiteouted temporary name. + */ +int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br) +{ + int err; + struct path h_path = { + .mnt = br->br_mnt + }; + struct inode *h_dir; + struct dentry *h_parent; + + h_parent = h_dentry->d_parent; /* dir inode is locked */ + h_dir = h_parent->d_inode; + IMustLock(h_dir); + + h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name); + err = PTR_ERR(h_path.dentry); + if (IS_ERR(h_path.dentry)) + goto out; + + /* under the same dir, no need to lock_rename() */ + err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path); + AuTraceErr(err); + dput(h_path.dentry); + +out: + AuTraceErr(err); + return err; +} + +/* ---------------------------------------------------------------------- */ +/* + * functions for removing a whiteout + */ + +static int do_unlink_wh(struct inode *h_dir, struct path *h_path) +{ + int force; + + /* + * forces superio when the dir has a sticky bit. + * this may be a violation of unix fs semantics. + */ + force = (h_dir->i_mode & S_ISVTX) + && h_path->dentry->d_inode->i_uid != current_fsuid(); + return vfsub_unlink(h_dir, h_path, force); +} + +int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, + struct dentry *dentry) +{ + int err; + + err = do_unlink_wh(h_dir, h_path); + if (!err && dentry) + au_set_dbwh(dentry, -1); + + return err; +} + +static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh, + struct au_branch *br) +{ + int err; + struct path h_path = { + .mnt = br->br_mnt + }; + + err = 0; + h_path.dentry = au_lkup_one(wh, h_parent, br, /*nd*/NULL); + if (IS_ERR(h_path.dentry)) + err = PTR_ERR(h_path.dentry); + else { + if (h_path.dentry->d_inode + && S_ISREG(h_path.dentry->d_inode->i_mode)) + err = do_unlink_wh(h_parent->d_inode, &h_path); + dput(h_path.dentry); + } + + return err; +} + +/* ---------------------------------------------------------------------- */ +/* + * initialize/clean whiteout for a branch + */ + +static void au_wh_clean(struct inode *h_dir, struct path *whpath, + const int isdir) +{ + int err; + + if (!whpath->dentry->d_inode) + return; + + err = mnt_want_write(whpath->mnt); + if (!err) { + if (isdir) + err = vfsub_rmdir(h_dir, whpath); + else + err = vfsub_unlink(h_dir, whpath, /*force*/0); + mnt_drop_write(whpath->mnt); + } + if (unlikely(err)) + pr_warning("failed removing %.*s (%d), ignored.\n", + AuDLNPair(whpath->dentry), err); +} + +static int test_linkable(struct dentry *h_root) +{ + struct inode *h_dir = h_root->d_inode; + + if (h_dir->i_op->link) + return 0; + + pr_err("%.*s (%s) doesn't support link(2), use noplink and rw+nolwh\n", + AuDLNPair(h_root), au_sbtype(h_root->d_sb)); + return -ENOSYS; +} + +/* todo: should this mkdir be done in /sbin/mount.aufs helper? */ +static int au_whdir(struct inode *h_dir, struct path *path) +{ + int err; + + err = -EEXIST; + if (!path->dentry->d_inode) { + int mode = S_IRWXU; + + if (au_test_nfs(path->dentry->d_sb)) + mode |= S_IXUGO; + err = mnt_want_write(path->mnt); + if (!err) { + err = vfsub_mkdir(h_dir, path, mode); + mnt_drop_write(path->mnt); + } + } else if (S_ISDIR(path->dentry->d_inode->i_mode)) + err = 0; + else + pr_err("unknown %.*s exists\n", AuDLNPair(path->dentry)); + + return err; +} + +struct au_wh_base { + const struct qstr *name; + struct dentry *dentry; +}; + +static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[], + struct path *h_path) +{ + h_path->dentry = base[AuBrWh_BASE].dentry; + au_wh_clean(h_dir, h_path, /*isdir*/0); + h_path->dentry = base[AuBrWh_PLINK].dentry; + au_wh_clean(h_dir, h_path, /*isdir*/1); + h_path->dentry = base[AuBrWh_ORPH].dentry; + au_wh_clean(h_dir, h_path, /*isdir*/1); +} + +/* + * returns tri-state, + * minus: error, caller should print the mesage + * zero: succuess + * plus: error, caller should NOT print the mesage + */ +static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr, + int do_plink, struct au_wh_base base[], + struct path *h_path) +{ + int err; + struct inode *h_dir; + + h_dir = h_root->d_inode; + h_path->dentry = base[AuBrWh_BASE].dentry; + au_wh_clean(h_dir, h_path, /*isdir*/0); + h_path->dentry = base[AuBrWh_PLINK].dentry; + if (do_plink) { + err = test_linkable(h_root); + if (unlikely(err)) { + err = 1; + goto out; + } + + err = au_whdir(h_dir, h_path); + if (unlikely(err)) + goto out; + wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); + } else + au_wh_clean(h_dir, h_path, /*isdir*/1); + h_path->dentry = base[AuBrWh_ORPH].dentry; + err = au_whdir(h_dir, h_path); + if (unlikely(err)) + goto out; + wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); + +out: + return err; +} + +/* + * for the moment, aufs supports the branch filesystem which does not support + * link(2). testing on FAT which does not support i_op->setattr() fully either, + * copyup failed. finally, such filesystem will not be used as the writable + * branch. + * + * returns tri-state, see above. + */ +static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr, + int do_plink, struct au_wh_base base[], + struct path *h_path) +{ + int err; + struct inode *h_dir; + + WbrWhMustWriteLock(wbr); + + err = test_linkable(h_root); + if (unlikely(err)) { + err = 1; + goto out; + } + + /* + * todo: should this create be done in /sbin/mount.aufs helper? + */ + err = -EEXIST; + h_dir = h_root->d_inode; + if (!base[AuBrWh_BASE].dentry->d_inode) { + err = mnt_want_write(h_path->mnt); + if (!err) { + h_path->dentry = base[AuBrWh_BASE].dentry; + err = vfsub_create(h_dir, h_path, WH_MASK); + mnt_drop_write(h_path->mnt); + } + } else if (S_ISREG(base[AuBrWh_BASE].dentry->d_inode->i_mode)) + err = 0; + else + pr_err("unknown %.*s/%.*s exists\n", + AuDLNPair(h_root), AuDLNPair(base[AuBrWh_BASE].dentry)); + if (unlikely(err)) + goto out; + + h_path->dentry = base[AuBrWh_PLINK].dentry; + if (do_plink) { + err = au_whdir(h_dir, h_path); + if (unlikely(err)) + goto out; + wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry); + } else + au_wh_clean(h_dir, h_path, /*isdir*/1); + wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry); + + h_path->dentry = base[AuBrWh_ORPH].dentry; + err = au_whdir(h_dir, h_path); + if (unlikely(err)) + goto out; + wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry); + +out: + return err; +} + +/* + * initialize the whiteout base file/dir for @br. + */ +int au_wh_init(struct dentry *h_root, struct au_branch *br, + struct super_block *sb) +{ + int err, i; + const unsigned char do_plink + = !!au_opt_test(au_mntflags(sb), PLINK); + struct path path = { + .mnt = br->br_mnt + }; + struct inode *h_dir; + struct au_wbr *wbr = br->br_wbr; + static const struct qstr base_name[] = { + [AuBrWh_BASE] = { + .name = AUFS_BASE_NAME, + .len = sizeof(AUFS_BASE_NAME) - 1 + }, + [AuBrWh_PLINK] = { + .name = AUFS_PLINKDIR_NAME, + .len = sizeof(AUFS_PLINKDIR_NAME) - 1 + }, + [AuBrWh_ORPH] = { + .name = AUFS_ORPHDIR_NAME, + .len = sizeof(AUFS_ORPHDIR_NAME) - 1 + } + }; + struct au_wh_base base[] = { + [AuBrWh_BASE] = { + .name = base_name + AuBrWh_BASE, + .dentry = NULL + }, + [AuBrWh_PLINK] = { + .name = base_name + AuBrWh_PLINK, + .dentry = NULL + }, + [AuBrWh_ORPH] = { + .name = base_name + AuBrWh_ORPH, + .dentry = NULL + } + }; + + if (wbr) + WbrWhMustWriteLock(wbr); + + for (i = 0; i < AuBrWh_Last; i++) { + /* doubly whiteouted */ + struct dentry *d; + + d = au_wh_lkup(h_root, (void *)base[i].name, br); + err = PTR_ERR(d); + if (IS_ERR(d)) + goto out; + + base[i].dentry = d; + AuDebugOn(wbr + && wbr->wbr_wh[i] + && wbr->wbr_wh[i] != base[i].dentry); + } + + if (wbr) + for (i = 0; i < AuBrWh_Last; i++) { + dput(wbr->wbr_wh[i]); + wbr->wbr_wh[i] = NULL; + } + + err = 0; + switch (br->br_perm) { + case AuBrPerm_RO: + case AuBrPerm_ROWH: + case AuBrPerm_RR: + case AuBrPerm_RRWH: + h_dir = h_root->d_inode; + au_wh_init_ro(h_dir, base, &path); + break; + + case AuBrPerm_RWNoLinkWH: + err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path); + if (err > 0) + goto out; + else if (err) + goto out_err; + break; + + case AuBrPerm_RW: + err = au_wh_init_rw(h_root, wbr, do_plink, base, &path); + if (err > 0) + goto out; + else if (err) + goto out_err; + break; + + default: + BUG(); + } + goto out; /* success */ + +out_err: + pr_err("an error(%d) on the writable branch %.*s(%s)\n", + err, AuDLNPair(h_root), au_sbtype(h_root->d_sb)); +out: + for (i = 0; i < AuBrWh_Last; i++) + dput(base[i].dentry); + return err; +} + +/* ---------------------------------------------------------------------- */ +/* + * whiteouts are all hard-linked usually. + * when its link count reaches a ceiling, we create a new whiteout base + * asynchronously. + */ + +struct reinit_br_wh { + struct super_block *sb; + struct au_branch *br; +}; + +static void reinit_br_wh(void *arg) +{ + int err; + aufs_bindex_t bindex; + struct path h_path; + struct reinit_br_wh *a = arg; + struct au_wbr *wbr; + struct inode *dir; + struct dentry *h_root; + struct au_hinode *hdir; + + err = 0; + wbr = a->br->br_wbr; + /* big aufs lock */ + si_noflush_write_lock(a->sb); + if (!au_br_writable(a->br->br_perm)) + goto out; + bindex = au_br_index(a->sb, a->br->br_id); + if (unlikely(bindex < 0)) + goto out; + + di_read_lock_parent(a->sb->s_root, AuLock_IR); + dir = a->sb->s_root->d_inode; + hdir = au_hi(dir, bindex); + h_root = au_h_dptr(a->sb->s_root, bindex); + + au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT); + wbr_wh_write_lock(wbr); + err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode, + h_root, a->br); + if (!err) { + err = mnt_want_write(a->br->br_mnt); + if (!err) { + h_path.dentry = wbr->wbr_whbase; + h_path.mnt = a->br->br_mnt; + err = vfsub_unlink(hdir->hi_inode, &h_path, /*force*/0); + mnt_drop_write(a->br->br_mnt); + } + } else { + pr_warning("%.*s is moved, ignored\n", + AuDLNPair(wbr->wbr_whbase)); + err = 0; + } + dput(wbr->wbr_whbase); + wbr->wbr_whbase = NULL; + if (!err) + err = au_wh_init(h_root, a->br, a->sb); + wbr_wh_write_unlock(wbr); + au_hn_imtx_unlock(hdir); + di_read_unlock(a->sb->s_root, AuLock_IR); + +out: + if (wbr) + atomic_dec(&wbr->wbr_wh_running); + atomic_dec(&a->br->br_count); + au_nwt_done(&au_sbi(a->sb)->si_nowait); + si_write_unlock(a->sb); + kfree(arg); + if (unlikely(err)) + AuIOErr("err %d\n", err); +} + +static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br) +{ + int do_dec, wkq_err; + struct reinit_br_wh *arg; + + do_dec = 1; + if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1) + goto out; + + /* ignore ENOMEM */ + arg = kmalloc(sizeof(*arg), GFP_NOFS); + if (arg) { + /* + * dec(wh_running), kfree(arg) and dec(br_count) + * in reinit function + */ + arg->sb = sb; + arg->br = br; + atomic_inc(&br->br_count); + wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb); + if (unlikely(wkq_err)) { + atomic_dec(&br->br_wbr->wbr_wh_running); + atomic_dec(&br->br_count); + kfree(arg); + } + do_dec = 0; + } + +out: + if (do_dec) + atomic_dec(&br->br_wbr->wbr_wh_running); +} + +/* ---------------------------------------------------------------------- */ + +/* + * create the whiteout @wh. + */ +static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex, + struct dentry *wh) +{ + int err; + struct path h_path = { + .dentry = wh + }; + struct au_branch *br; + struct au_wbr *wbr; + struct dentry *h_parent; + struct inode *h_dir; + + h_parent = wh->d_parent; /* dir inode is locked */ + h_dir = h_parent->d_inode; + IMustLock(h_dir); + + br = au_sbr(sb, bindex); + h_path.mnt = br->br_mnt; + wbr = br->br_wbr; + wbr_wh_read_lock(wbr); + if (wbr->wbr_whbase) { + err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path); + if (!err || err != -EMLINK) + goto out; + + /* link count full. re-initialize br_whbase. */ + kick_reinit_br_wh(sb, br); + } + + /* return this error in this context */ + err = vfsub_create(h_dir, &h_path, WH_MASK); + +out: + wbr_wh_read_unlock(wbr); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * create or remove the diropq. + */ +static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex, + unsigned int flags) +{ + struct dentry *opq_dentry, *h_dentry; + struct super_block *sb; + struct au_branch *br; + int err; + + sb = dentry->d_sb; + br = au_sbr(sb, bindex); + h_dentry = au_h_dptr(dentry, bindex); + opq_dentry = au_lkup_one(&diropq_name, h_dentry, br, /*nd*/NULL); + if (IS_ERR(opq_dentry)) + goto out; + + if (au_ftest_diropq(flags, CREATE)) { + err = link_or_create_wh(sb, bindex, opq_dentry); + if (!err) { + au_set_dbdiropq(dentry, bindex); + goto out; /* success */ + } + } else { + struct path tmp = { + .dentry = opq_dentry, + .mnt = br->br_mnt + }; + err = do_unlink_wh(au_h_iptr(dentry->d_inode, bindex), &tmp); + if (!err) + au_set_dbdiropq(dentry, -1); + } + dput(opq_dentry); + opq_dentry = ERR_PTR(err); + +out: + return opq_dentry; +} + +struct do_diropq_args { + struct dentry **errp; + struct dentry *dentry; + aufs_bindex_t bindex; + unsigned int flags; +}; + +static void call_do_diropq(void *args) +{ + struct do_diropq_args *a = args; + *a->errp = do_diropq(a->dentry, a->bindex, a->flags); +} + +struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, + unsigned int flags) +{ + struct dentry *diropq, *h_dentry; + + h_dentry = au_h_dptr(dentry, bindex); + if (!au_test_h_perm_sio(h_dentry->d_inode, MAY_EXEC | MAY_WRITE)) + diropq = do_diropq(dentry, bindex, flags); + else { + int wkq_err; + struct do_diropq_args args = { + .errp = &diropq, + .dentry = dentry, + .bindex = bindex, + .flags = flags + }; + + wkq_err = au_wkq_wait(call_do_diropq, &args); + if (unlikely(wkq_err)) + diropq = ERR_PTR(wkq_err); + } + + return diropq; +} + +/* ---------------------------------------------------------------------- */ + +/* + * lookup whiteout dentry. + * @h_parent: lower parent dentry which must exist and be locked + * @base_name: name of dentry which will be whiteouted + * returns dentry for whiteout. + */ +struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, + struct au_branch *br) +{ + int err; + struct qstr wh_name; + struct dentry *wh_dentry; + + err = au_wh_name_alloc(&wh_name, base_name); + wh_dentry = ERR_PTR(err); + if (!err) { + wh_dentry = au_lkup_one(&wh_name, h_parent, br, /*nd*/NULL); + kfree(wh_name.name); + } + return wh_dentry; +} + +/* + * link/create a whiteout for @dentry on @bindex. + */ +struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent) +{ + struct dentry *wh_dentry; + struct super_block *sb; + int err; + + sb = dentry->d_sb; + wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex)); + if (!IS_ERR(wh_dentry) && !wh_dentry->d_inode) { + err = link_or_create_wh(sb, bindex, wh_dentry); + if (!err) + au_set_dbwh(dentry, bindex); + else { + dput(wh_dentry); + wh_dentry = ERR_PTR(err); + } + } + + return wh_dentry; +} + +/* ---------------------------------------------------------------------- */ + +/* Delete all whiteouts in this directory on branch bindex. */ +static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist, + aufs_bindex_t bindex, struct au_branch *br) +{ + int err; + unsigned long ul, n; + struct qstr wh_name; + char *p; + struct hlist_head *head; + struct au_vdir_wh *tpos; + struct hlist_node *pos; + struct au_vdir_destr *str; + + err = -ENOMEM; + p = __getname_gfp(GFP_NOFS); + wh_name.name = p; + if (unlikely(!wh_name.name)) + goto out; + + err = 0; + memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN); + p += AUFS_WH_PFX_LEN; + n = whlist->nh_num; + head = whlist->nh_head; + for (ul = 0; !err && ul < n; ul++, head++) { + hlist_for_each_entry(tpos, pos, head, wh_hash) { + if (tpos->wh_bindex != bindex) + continue; + + str = &tpos->wh_str; + if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) { + memcpy(p, str->name, str->len); + wh_name.len = AUFS_WH_PFX_LEN + str->len; + err = unlink_wh_name(h_dentry, &wh_name, br); + if (!err) + continue; + break; + } + AuIOErr("whiteout name too long %.*s\n", + str->len, str->name); + err = -EIO; + break; + } + } + __putname(wh_name.name); + +out: + return err; +} + +struct del_wh_children_args { + int *errp; + struct dentry *h_dentry; + struct au_nhash *whlist; + aufs_bindex_t bindex; + struct au_branch *br; +}; + +static void call_del_wh_children(void *args) +{ + struct del_wh_children_args *a = args; + *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br); +} + +/* ---------------------------------------------------------------------- */ + +struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp) +{ + struct au_whtmp_rmdir *whtmp; + int err; + unsigned int rdhash; + + SiMustAnyLock(sb); + + whtmp = kmalloc(sizeof(*whtmp), gfp); + if (unlikely(!whtmp)) { + whtmp = ERR_PTR(-ENOMEM); + goto out; + } + + whtmp->dir = NULL; + whtmp->wh_dentry = NULL; + /* no estimation for dir size */ + rdhash = au_sbi(sb)->si_rdhash; + if (!rdhash) + rdhash = AUFS_RDHASH_DEF; + err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp); + if (unlikely(err)) { + kfree(whtmp); + whtmp = ERR_PTR(err); + } + +out: + return whtmp; +} + +void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp) +{ + dput(whtmp->wh_dentry); + iput(whtmp->dir); + au_nhash_wh_free(&whtmp->whlist); + kfree(whtmp); +} + +/* + * rmdir the whiteouted temporary named dir @h_dentry. + * @whlist: whiteouted children. + */ +int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, + struct dentry *wh_dentry, struct au_nhash *whlist) +{ + int err; + struct path h_tmp; + struct inode *wh_inode, *h_dir; + struct au_branch *br; + + h_dir = wh_dentry->d_parent->d_inode; /* dir inode is locked */ + IMustLock(h_dir); + + br = au_sbr(dir->i_sb, bindex); + wh_inode = wh_dentry->d_inode; + mutex_lock_nested(&wh_inode->i_mutex, AuLsc_I_CHILD); + + /* + * someone else might change some whiteouts while we were sleeping. + * it means this whlist may have an obsoleted entry. + */ + if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE)) + err = del_wh_children(wh_dentry, whlist, bindex, br); + else { + int wkq_err; + struct del_wh_children_args args = { + .errp = &err, + .h_dentry = wh_dentry, + .whlist = whlist, + .bindex = bindex, + .br = br + }; + + wkq_err = au_wkq_wait(call_del_wh_children, &args); + if (unlikely(wkq_err)) + err = wkq_err; + } + mutex_unlock(&wh_inode->i_mutex); + + if (!err) { + h_tmp.dentry = wh_dentry; + h_tmp.mnt = br->br_mnt; + err = vfsub_rmdir(h_dir, &h_tmp); + /* d_drop(h_dentry); */ + } + + if (!err) { + if (au_ibstart(dir) == bindex) { + /* todo: dir->i_mutex is necessary */ + au_cpup_attr_timesizes(dir); + vfsub_drop_nlink(dir); + } + return 0; /* success */ + } + + pr_warning("failed removing %.*s(%d), ignored\n", + AuDLNPair(wh_dentry), err); + return err; +} + +static void call_rmdir_whtmp(void *args) +{ + int err; + aufs_bindex_t bindex; + struct au_whtmp_rmdir *a = args; + struct super_block *sb; + struct dentry *h_parent; + struct inode *h_dir; + struct au_hinode *hdir; + + /* rmdir by nfsd may cause deadlock with this i_mutex */ + /* mutex_lock(&a->dir->i_mutex); */ + err = -EROFS; + sb = a->dir->i_sb; + si_read_lock(sb, !AuLock_FLUSH); + if (!au_br_writable(a->br->br_perm)) + goto out; + bindex = au_br_index(sb, a->br->br_id); + if (unlikely(bindex < 0)) + goto out; + + err = -EIO; + ii_write_lock_parent(a->dir); + h_parent = dget_parent(a->wh_dentry); + h_dir = h_parent->d_inode; + hdir = au_hi(a->dir, bindex); + au_hn_imtx_lock_nested(hdir, AuLsc_I_PARENT); + err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent, + a->br); + if (!err) { + err = mnt_want_write(a->br->br_mnt); + if (!err) { + err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, + &a->whlist); + mnt_drop_write(a->br->br_mnt); + } + } + au_hn_imtx_unlock(hdir); + dput(h_parent); + ii_write_unlock(a->dir); + +out: + /* mutex_unlock(&a->dir->i_mutex); */ + atomic_dec(&a->br->br_count); + au_nwt_done(&au_sbi(sb)->si_nowait); + si_read_unlock(sb); + au_whtmp_rmdir_free(a); + if (unlikely(err)) + AuIOErr("err %d\n", err); +} + +void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, + struct dentry *wh_dentry, struct au_whtmp_rmdir *args) +{ + int wkq_err; + struct super_block *sb; + + IMustLock(dir); + + /* all post-process will be done in do_rmdir_whtmp(). */ + sb = dir->i_sb; + args->dir = au_igrab(dir); + args->br = au_sbr(sb, bindex); + atomic_inc(&args->br->br_count); + args->wh_dentry = dget(wh_dentry); + wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb); + if (unlikely(wkq_err)) { + pr_warning("rmdir error %.*s (%d), ignored\n", + AuDLNPair(wh_dentry), wkq_err); + au_whtmp_rmdir_free(args); + } +} --- linux-2.6.37.orig/ubuntu/aufs/whout.h +++ linux-2.6.37/ubuntu/aufs/whout.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * whiteout for logical deletion and opaque directory + */ + +#ifndef __AUFS_WHOUT_H__ +#define __AUFS_WHOUT_H__ + +#ifdef __KERNEL__ + +#include +#include "dir.h" + +/* whout.c */ +int au_wh_name_alloc(struct qstr *wh, const struct qstr *name); +struct au_branch; +int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, + struct au_branch *br, int try_sio); +int au_diropq_test(struct dentry *h_dentry, struct au_branch *br); +struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, + struct qstr *prefix); +int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br); +int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path, + struct dentry *dentry); +int au_wh_init(struct dentry *h_parent, struct au_branch *br, + struct super_block *sb); + +/* diropq flags */ +#define AuDiropq_CREATE 1 +#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name) +#define au_fset_diropq(flags, name) \ + do { (flags) |= AuDiropq_##name; } while (0) +#define au_fclr_diropq(flags, name) \ + do { (flags) &= ~AuDiropq_##name; } while (0) + +struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex, + unsigned int flags); +struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name, + struct au_branch *br); +struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent); + +/* real rmdir for the whiteout-ed dir */ +struct au_whtmp_rmdir { + struct inode *dir; + struct au_branch *br; + struct dentry *wh_dentry; + struct au_nhash whlist; +}; + +struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp); +void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp); +int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex, + struct dentry *wh_dentry, struct au_nhash *whlist); +void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex, + struct dentry *wh_dentry, struct au_whtmp_rmdir *args); + +/* ---------------------------------------------------------------------- */ + +static inline struct dentry *au_diropq_create(struct dentry *dentry, + aufs_bindex_t bindex) +{ + return au_diropq_sio(dentry, bindex, AuDiropq_CREATE); +} + +static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex) +{ + return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE)); +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_WHOUT_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/wkq.c +++ linux-2.6.37/ubuntu/aufs/wkq.c @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * workqueue for asynchronous/super-io operations + * todo: try new dredential scheme + */ + +#include +#include "aufs.h" + +/* internal workqueue named AUFS_WKQ_NAME and AUFS_WKQ_PRE_NAME */ +enum { + AuWkq_INORMAL, + AuWkq_IPRE +}; + +static struct { + char *name; + struct workqueue_struct *wkq; +} au_wkq[] = { + [AuWkq_INORMAL] = { + .name = AUFS_WKQ_NAME + }, + [AuWkq_IPRE] = { + .name = AUFS_WKQ_PRE_NAME + } +}; + +struct au_wkinfo { + struct work_struct wk; + struct kobject *kobj; + + unsigned int flags; /* see wkq.h */ + + au_wkq_func_t func; + void *args; + + struct completion *comp; +}; + +/* ---------------------------------------------------------------------- */ + +static void wkq_func(struct work_struct *wk) +{ + struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk); + + AuDebugOn(current_fsuid()); + AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY); + + wkinfo->func(wkinfo->args); + if (au_ftest_wkq(wkinfo->flags, WAIT)) + complete(wkinfo->comp); + else { + kobject_put(wkinfo->kobj); + module_put(THIS_MODULE); + kfree(wkinfo); + } +} + +/* + * Since struct completion is large, try allocating it dynamically. + */ +#if defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS) +#define AuWkqCompDeclare(name) struct completion *comp = NULL + +static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) +{ + *comp = kmalloc(sizeof(**comp), GFP_NOFS); + if (*comp) { + init_completion(*comp); + wkinfo->comp = *comp; + return 0; + } + return -ENOMEM; +} + +static void au_wkq_comp_free(struct completion *comp) +{ + kfree(comp); +} + +#else + +/* no braces */ +#define AuWkqCompDeclare(name) \ + DECLARE_COMPLETION_ONSTACK(_ ## name); \ + struct completion *comp = &_ ## name + +static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) +{ + wkinfo->comp = *comp; + return 0; +} + +static void au_wkq_comp_free(struct completion *comp __maybe_unused) +{ + /* empty */ +} +#endif /* 4KSTACKS */ + +static void au_wkq_run(struct au_wkinfo *wkinfo, unsigned int flags) +{ + struct workqueue_struct *wkq; + + au_dbg_verify_kthread(); + if (flags & AuWkq_WAIT) { + INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func); + wkq = au_wkq[AuWkq_INORMAL].wkq; + if (flags & AuWkq_PRE) + wkq = au_wkq[AuWkq_IPRE].wkq; + queue_work(wkq, &wkinfo->wk); + } else { + INIT_WORK(&wkinfo->wk, wkq_func); + schedule_work(&wkinfo->wk); + } +} + +/* + * Be careful. It is easy to make deadlock happen. + * processA: lock, wkq and wait + * processB: wkq and wait, lock in wkq + * --> deadlock + */ +int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args) +{ + int err; + AuWkqCompDeclare(comp); + struct au_wkinfo wkinfo = { + .flags = flags, + .func = func, + .args = args + }; + + err = au_wkq_comp_alloc(&wkinfo, &comp); + if (!err) { + au_wkq_run(&wkinfo, flags); + /* no timeout, no interrupt */ + wait_for_completion(wkinfo.comp); + au_wkq_comp_free(comp); + destroy_work_on_stack(&wkinfo.wk); + } + + return err; + +} + +int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb) +{ + int err; + struct au_wkinfo *wkinfo; + + atomic_inc(&au_sbi(sb)->si_nowait.nw_len); + + /* + * wkq_func() must free this wkinfo. + * it highly depends upon the implementation of workqueue. + */ + err = 0; + wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS); + if (wkinfo) { + wkinfo->kobj = &au_sbi(sb)->si_kobj; + wkinfo->flags = !AuWkq_WAIT; + wkinfo->func = func; + wkinfo->args = args; + wkinfo->comp = NULL; + kobject_get(wkinfo->kobj); + __module_get(THIS_MODULE); + + au_wkq_run(wkinfo, !AuWkq_WAIT); + } else { + err = -ENOMEM; + au_nwt_done(&au_sbi(sb)->si_nowait); + } + + return err; +} + +/* ---------------------------------------------------------------------- */ + +void au_nwt_init(struct au_nowait_tasks *nwt) +{ + atomic_set(&nwt->nw_len, 0); + /* smp_mb(); */ /* atomic_set */ + init_waitqueue_head(&nwt->nw_wq); +} + +void au_wkq_fin(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(au_wkq); i++) + if (au_wkq[i].wkq) + destroy_workqueue(au_wkq[i].wkq); +} + +int __init au_wkq_init(void) +{ + int err, i; + + err = 0; + for (i = 0; !err && i < ARRAY_SIZE(au_wkq); i++) { + BUILD_BUG_ON(!WQ_RESCUER); + au_wkq[i].wkq = alloc_workqueue(au_wkq[i].name, !WQ_RESCUER, + WQ_DFL_ACTIVE); + if (IS_ERR(au_wkq[i].wkq)) + err = PTR_ERR(au_wkq[i].wkq); + else if (!au_wkq[i].wkq) + err = -ENOMEM; + if (unlikely(err)) + au_wkq[i].wkq = NULL; + } + if (unlikely(err)) + au_wkq_fin(); + + return err; +} --- linux-2.6.37.orig/ubuntu/aufs/wkq.h +++ linux-2.6.37/ubuntu/aufs/wkq.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * workqueue for asynchronous/super-io operations + * todo: try new credentials management scheme + */ + +#ifndef __AUFS_WKQ_H__ +#define __AUFS_WKQ_H__ + +#ifdef __KERNEL__ + +#include +#include +#include + +struct super_block; + +/* ---------------------------------------------------------------------- */ + +/* + * in the next operation, wait for the 'nowait' tasks in system-wide workqueue + */ +struct au_nowait_tasks { + atomic_t nw_len; + wait_queue_head_t nw_wq; +}; + +/* ---------------------------------------------------------------------- */ + +typedef void (*au_wkq_func_t)(void *args); + +/* wkq flags */ +#define AuWkq_WAIT 1 +#define AuWkq_PRE (1 << 1) +#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name) +#define au_fset_wkq(flags, name) \ + do { (flags) |= AuWkq_##name; } while (0) +#define au_fclr_wkq(flags, name) \ + do { (flags) &= ~AuWkq_##name; } while (0) + +/* wkq.c */ +int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args); +int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb); +void au_nwt_init(struct au_nowait_tasks *nwt); +int __init au_wkq_init(void); +void au_wkq_fin(void); + +/* ---------------------------------------------------------------------- */ + +static inline int au_wkq_wait_pre(au_wkq_func_t func, void *args) +{ + return au_wkq_do_wait(AuWkq_WAIT | AuWkq_PRE, func, args); +} + +static inline int au_wkq_wait(au_wkq_func_t func, void *args) +{ + return au_wkq_do_wait(AuWkq_WAIT, func, args); +} + +static inline void au_nwt_done(struct au_nowait_tasks *nwt) +{ + if (atomic_dec_and_test(&nwt->nw_len)) + wake_up_all(&nwt->nw_wq); +} + +static inline int au_nwt_flush(struct au_nowait_tasks *nwt) +{ + wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len)); + return 0; +} + +#endif /* __KERNEL__ */ +#endif /* __AUFS_WKQ_H__ */ --- linux-2.6.37.orig/ubuntu/aufs/xino.c +++ linux-2.6.37/ubuntu/aufs/xino.c @@ -0,0 +1,1265 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * external inode number translation table and bitmap + */ + +#include +#include +#include +#include "aufs.h" + +ssize_t xino_fread(au_readf_t func, struct file *file, void *kbuf, size_t size, + loff_t *pos) +{ + ssize_t err; + mm_segment_t oldfs; + union { + void *k; + char __user *u; + } buf; + + buf.k = kbuf; + oldfs = get_fs(); + set_fs(KERNEL_DS); + do { + /* todo: signal_pending? */ + err = func(file, buf.u, size, pos); + } while (err == -EAGAIN || err == -EINTR); + set_fs(oldfs); + +#if 0 /* reserved for future use */ + if (err > 0) + fsnotify_access(file->f_dentry); +#endif + + return err; +} + +/* ---------------------------------------------------------------------- */ + +static ssize_t do_xino_fwrite(au_writef_t func, struct file *file, void *kbuf, + size_t size, loff_t *pos) +{ + ssize_t err; + mm_segment_t oldfs; + union { + void *k; + const char __user *u; + } buf; + + buf.k = kbuf; + oldfs = get_fs(); + set_fs(KERNEL_DS); + do { + /* todo: signal_pending? */ + err = func(file, buf.u, size, pos); + } while (err == -EAGAIN || err == -EINTR); + set_fs(oldfs); + +#if 0 /* reserved for future use */ + if (err > 0) + fsnotify_modify(file->f_dentry); +#endif + + return err; +} + +struct do_xino_fwrite_args { + ssize_t *errp; + au_writef_t func; + struct file *file; + void *buf; + size_t size; + loff_t *pos; +}; + +static void call_do_xino_fwrite(void *args) +{ + struct do_xino_fwrite_args *a = args; + *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos); +} + +ssize_t xino_fwrite(au_writef_t func, struct file *file, void *buf, size_t size, + loff_t *pos) +{ + ssize_t err; + + /* todo: signal block and no wkq? */ + if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) { + lockdep_off(); + err = do_xino_fwrite(func, file, buf, size, pos); + lockdep_on(); + } else { + /* + * it breaks RLIMIT_FSIZE and normal user's limit, + * users should care about quota and real 'filesystem full.' + */ + int wkq_err; + struct do_xino_fwrite_args args = { + .errp = &err, + .func = func, + .file = file, + .buf = buf, + .size = size, + .pos = pos + }; + + wkq_err = au_wkq_wait(call_do_xino_fwrite, &args); + if (unlikely(wkq_err)) + err = wkq_err; + } + + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * create a new xinofile at the same place/path as @base_file. + */ +struct file *au_xino_create2(struct file *base_file, struct file *copy_src) +{ + struct file *file; + struct dentry *base, *parent; + struct inode *dir; + struct qstr *name; + struct path path; + int err; + + base = base_file->f_dentry; + parent = base->d_parent; /* dir inode is locked */ + dir = parent->d_inode; + IMustLock(dir); + + file = ERR_PTR(-EINVAL); + name = &base->d_name; + path.dentry = vfsub_lookup_one_len(name->name, parent, name->len); + if (IS_ERR(path.dentry)) { + file = (void *)path.dentry; + pr_err("%.*s lookup err %ld\n", + AuLNPair(name), PTR_ERR(path.dentry)); + goto out; + } + + /* no need to mnt_want_write() since we call dentry_open() later */ + err = vfs_create(dir, path.dentry, S_IRUGO | S_IWUGO, NULL); + if (unlikely(err)) { + file = ERR_PTR(err); + pr_err("%.*s create err %d\n", AuLNPair(name), err); + goto out_dput; + } + + path.mnt = base_file->f_vfsmnt; + file = vfsub_dentry_open(&path, + O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE + /* | FMODE_NONOTIFY */); + if (IS_ERR(file)) { + pr_err("%.*s open err %ld\n", AuLNPair(name), PTR_ERR(file)); + goto out_dput; + } + + err = vfsub_unlink(dir, &file->f_path, /*force*/0); + if (unlikely(err)) { + pr_err("%.*s unlink err %d\n", AuLNPair(name), err); + goto out_fput; + } + + if (copy_src) { + /* no one can touch copy_src xino */ + err = au_copy_file(file, copy_src, + i_size_read(copy_src->f_dentry->d_inode)); + if (unlikely(err)) { + pr_err("%.*s copy err %d\n", AuLNPair(name), err); + goto out_fput; + } + } + goto out_dput; /* success */ + +out_fput: + fput(file); + file = ERR_PTR(err); +out_dput: + dput(path.dentry); +out: + return file; +} + +struct au_xino_lock_dir { + struct au_hinode *hdir; + struct dentry *parent; + struct mutex *mtx; +}; + +static void au_xino_lock_dir(struct super_block *sb, struct file *xino, + struct au_xino_lock_dir *ldir) +{ + aufs_bindex_t brid, bindex; + + ldir->hdir = NULL; + bindex = -1; + brid = au_xino_brid(sb); + if (brid >= 0) + bindex = au_br_index(sb, brid); + if (bindex >= 0) { + ldir->hdir = au_hi(sb->s_root->d_inode, bindex); + au_hn_imtx_lock_nested(ldir->hdir, AuLsc_I_PARENT); + } else { + ldir->parent = dget_parent(xino->f_dentry); + ldir->mtx = &ldir->parent->d_inode->i_mutex; + mutex_lock_nested(ldir->mtx, AuLsc_I_PARENT); + } +} + +static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir) +{ + if (ldir->hdir) + au_hn_imtx_unlock(ldir->hdir); + else { + mutex_unlock(ldir->mtx); + dput(ldir->parent); + } +} + +/* ---------------------------------------------------------------------- */ + +/* trucate xino files asynchronously */ + +int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex) +{ + int err; + aufs_bindex_t bi, bend; + struct au_branch *br; + struct file *new_xino, *file; + struct super_block *h_sb; + struct au_xino_lock_dir ldir; + + err = -EINVAL; + bend = au_sbend(sb); + if (unlikely(bindex < 0 || bend < bindex)) + goto out; + br = au_sbr(sb, bindex); + file = br->br_xino.xi_file; + if (!file) + goto out; + + au_xino_lock_dir(sb, file, &ldir); + /* mnt_want_write() is unnecessary here */ + new_xino = au_xino_create2(file, file); + au_xino_unlock_dir(&ldir); + err = PTR_ERR(new_xino); + if (IS_ERR(new_xino)) + goto out; + err = 0; + fput(file); + br->br_xino.xi_file = new_xino; + + h_sb = br->br_mnt->mnt_sb; + for (bi = 0; bi <= bend; bi++) { + if (unlikely(bi == bindex)) + continue; + br = au_sbr(sb, bi); + if (br->br_mnt->mnt_sb != h_sb) + continue; + + fput(br->br_xino.xi_file); + br->br_xino.xi_file = new_xino; + get_file(new_xino); + } + +out: + return err; +} + +struct xino_do_trunc_args { + struct super_block *sb; + struct au_branch *br; +}; + +static void xino_do_trunc(void *_args) +{ + struct xino_do_trunc_args *args = _args; + struct super_block *sb; + struct au_branch *br; + struct inode *dir; + int err; + aufs_bindex_t bindex; + + err = 0; + sb = args->sb; + dir = sb->s_root->d_inode; + br = args->br; + + si_noflush_write_lock(sb); + ii_read_lock_parent(dir); + bindex = au_br_index(sb, br->br_id); + err = au_xino_trunc(sb, bindex); + if (!err + && br->br_xino.xi_file->f_dentry->d_inode->i_blocks + >= br->br_xino_upper) + br->br_xino_upper += AUFS_XINO_TRUNC_STEP; + + ii_read_unlock(dir); + if (unlikely(err)) + pr_warning("err b%d, (%d)\n", bindex, err); + atomic_dec(&br->br_xino_running); + atomic_dec(&br->br_count); + au_nwt_done(&au_sbi(sb)->si_nowait); + si_write_unlock(sb); + kfree(args); +} + +static void xino_try_trunc(struct super_block *sb, struct au_branch *br) +{ + struct xino_do_trunc_args *args; + int wkq_err; + + if (br->br_xino.xi_file->f_dentry->d_inode->i_blocks + < br->br_xino_upper) + return; + + if (atomic_inc_return(&br->br_xino_running) > 1) + goto out; + + /* lock and kfree() will be called in trunc_xino() */ + args = kmalloc(sizeof(*args), GFP_NOFS); + if (unlikely(!args)) { + AuErr1("no memory\n"); + goto out_args; + } + + atomic_inc(&br->br_count); + args->sb = sb; + args->br = br; + wkq_err = au_wkq_nowait(xino_do_trunc, args, sb); + if (!wkq_err) + return; /* success */ + + pr_err("wkq %d\n", wkq_err); + atomic_dec(&br->br_count); + +out_args: + kfree(args); +out: + atomic_dec(&br->br_xino_running); +} + +/* ---------------------------------------------------------------------- */ + +static int au_xino_do_write(au_writef_t write, struct file *file, + ino_t h_ino, ino_t ino) +{ + loff_t pos; + ssize_t sz; + + pos = h_ino; + if (unlikely(au_loff_max / sizeof(ino) - 1 < pos)) { + AuIOErr1("too large hi%lu\n", (unsigned long)h_ino); + return -EFBIG; + } + pos *= sizeof(ino); + sz = xino_fwrite(write, file, &ino, sizeof(ino), &pos); + if (sz == sizeof(ino)) + return 0; /* success */ + + AuIOErr("write failed (%zd)\n", sz); + return -EIO; +} + +/* + * write @ino to the xinofile for the specified branch{@sb, @bindex} + * at the position of @h_ino. + * even if @ino is zero, it is written to the xinofile and means no entry. + * if the size of the xino file on a specific filesystem exceeds the watermark, + * try truncating it. + */ +int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + ino_t ino) +{ + int err; + unsigned int mnt_flags; + struct au_branch *br; + + BUILD_BUG_ON(sizeof(long long) != sizeof(au_loff_max) + || ((loff_t)-1) > 0); + SiMustAnyLock(sb); + + mnt_flags = au_mntflags(sb); + if (!au_opt_test(mnt_flags, XINO)) + return 0; + + br = au_sbr(sb, bindex); + err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file, + h_ino, ino); + if (!err) { + if (au_opt_test(mnt_flags, TRUNC_XINO) + && au_test_fs_trunc_xino(br->br_mnt->mnt_sb)) + xino_try_trunc(sb, br); + return 0; /* success */ + } + + AuIOErr("write failed (%d)\n", err); + return -EIO; +} + +/* ---------------------------------------------------------------------- */ + +/* aufs inode number bitmap */ + +static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE; +static ino_t xib_calc_ino(unsigned long pindex, int bit) +{ + ino_t ino; + + AuDebugOn(bit < 0 || page_bits <= bit); + ino = AUFS_FIRST_INO + pindex * page_bits + bit; + return ino; +} + +static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit) +{ + AuDebugOn(ino < AUFS_FIRST_INO); + ino -= AUFS_FIRST_INO; + *pindex = ino / page_bits; + *bit = ino % page_bits; +} + +static int xib_pindex(struct super_block *sb, unsigned long pindex) +{ + int err; + loff_t pos; + ssize_t sz; + struct au_sbinfo *sbinfo; + struct file *xib; + unsigned long *p; + + sbinfo = au_sbi(sb); + MtxMustLock(&sbinfo->si_xib_mtx); + AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE + || !au_opt_test(sbinfo->si_mntflags, XINO)); + + if (pindex == sbinfo->si_xib_last_pindex) + return 0; + + xib = sbinfo->si_xib; + p = sbinfo->si_xib_buf; + pos = sbinfo->si_xib_last_pindex; + pos *= PAGE_SIZE; + sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); + if (unlikely(sz != PAGE_SIZE)) + goto out; + + pos = pindex; + pos *= PAGE_SIZE; + if (i_size_read(xib->f_dentry->d_inode) >= pos + PAGE_SIZE) + sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos); + else { + memset(p, 0, PAGE_SIZE); + sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); + } + if (sz == PAGE_SIZE) { + sbinfo->si_xib_last_pindex = pindex; + return 0; /* success */ + } + +out: + AuIOErr1("write failed (%zd)\n", sz); + err = sz; + if (sz >= 0) + err = -EIO; + return err; +} + +/* ---------------------------------------------------------------------- */ + +static void au_xib_clear_bit(struct inode *inode) +{ + int err, bit; + unsigned long pindex; + struct super_block *sb; + struct au_sbinfo *sbinfo; + + AuDebugOn(inode->i_nlink); + + sb = inode->i_sb; + xib_calc_bit(inode->i_ino, &pindex, &bit); + AuDebugOn(page_bits <= bit); + sbinfo = au_sbi(sb); + mutex_lock(&sbinfo->si_xib_mtx); + err = xib_pindex(sb, pindex); + if (!err) { + clear_bit(bit, sbinfo->si_xib_buf); + sbinfo->si_xib_next_bit = bit; + } + mutex_unlock(&sbinfo->si_xib_mtx); +} + +/* for s_op->delete_inode() */ +void au_xino_delete_inode(struct inode *inode, const int unlinked) +{ + int err; + unsigned int mnt_flags; + aufs_bindex_t bindex, bend, bi; + unsigned char try_trunc; + struct au_iinfo *iinfo; + struct super_block *sb; + struct au_hinode *hi; + struct inode *h_inode; + struct au_branch *br; + au_writef_t xwrite; + + sb = inode->i_sb; + mnt_flags = au_mntflags(sb); + if (!au_opt_test(mnt_flags, XINO) + || inode->i_ino == AUFS_ROOT_INO) + return; + + if (unlinked) { + au_xigen_inc(inode); + au_xib_clear_bit(inode); + } + + iinfo = au_ii(inode); + if (!iinfo) + return; + + bindex = iinfo->ii_bstart; + if (bindex < 0) + return; + + xwrite = au_sbi(sb)->si_xwrite; + try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO); + hi = iinfo->ii_hinode + bindex; + bend = iinfo->ii_bend; + for (; bindex <= bend; bindex++, hi++) { + h_inode = hi->hi_inode; + if (!h_inode + || (!unlinked && h_inode->i_nlink)) + continue; + + /* inode may not be revalidated */ + bi = au_br_index(sb, hi->hi_id); + if (bi < 0) + continue; + + br = au_sbr(sb, bi); + err = au_xino_do_write(xwrite, br->br_xino.xi_file, + h_inode->i_ino, /*ino*/0); + if (!err && try_trunc + && au_test_fs_trunc_xino(br->br_mnt->mnt_sb)) + xino_try_trunc(sb, br); + } +} + +/* get an unused inode number from bitmap */ +ino_t au_xino_new_ino(struct super_block *sb) +{ + ino_t ino; + unsigned long *p, pindex, ul, pend; + struct au_sbinfo *sbinfo; + struct file *file; + int free_bit, err; + + if (!au_opt_test(au_mntflags(sb), XINO)) + return iunique(sb, AUFS_FIRST_INO); + + sbinfo = au_sbi(sb); + mutex_lock(&sbinfo->si_xib_mtx); + p = sbinfo->si_xib_buf; + free_bit = sbinfo->si_xib_next_bit; + if (free_bit < page_bits && !test_bit(free_bit, p)) + goto out; /* success */ + free_bit = find_first_zero_bit(p, page_bits); + if (free_bit < page_bits) + goto out; /* success */ + + pindex = sbinfo->si_xib_last_pindex; + for (ul = pindex - 1; ul < ULONG_MAX; ul--) { + err = xib_pindex(sb, ul); + if (unlikely(err)) + goto out_err; + free_bit = find_first_zero_bit(p, page_bits); + if (free_bit < page_bits) + goto out; /* success */ + } + + file = sbinfo->si_xib; + pend = i_size_read(file->f_dentry->d_inode) / PAGE_SIZE; + for (ul = pindex + 1; ul <= pend; ul++) { + err = xib_pindex(sb, ul); + if (unlikely(err)) + goto out_err; + free_bit = find_first_zero_bit(p, page_bits); + if (free_bit < page_bits) + goto out; /* success */ + } + BUG(); + +out: + set_bit(free_bit, p); + sbinfo->si_xib_next_bit = free_bit + 1; + pindex = sbinfo->si_xib_last_pindex; + mutex_unlock(&sbinfo->si_xib_mtx); + ino = xib_calc_ino(pindex, free_bit); + AuDbg("i%lu\n", (unsigned long)ino); + return ino; +out_err: + mutex_unlock(&sbinfo->si_xib_mtx); + AuDbg("i0\n"); + return 0; +} + +/* + * read @ino from xinofile for the specified branch{@sb, @bindex} + * at the position of @h_ino. + * if @ino does not exist and @do_new is true, get new one. + */ +int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + ino_t *ino) +{ + int err; + ssize_t sz; + loff_t pos; + struct file *file; + struct au_sbinfo *sbinfo; + + *ino = 0; + if (!au_opt_test(au_mntflags(sb), XINO)) + return 0; /* no xino */ + + err = 0; + sbinfo = au_sbi(sb); + pos = h_ino; + if (unlikely(au_loff_max / sizeof(*ino) - 1 < pos)) { + AuIOErr1("too large hi%lu\n", (unsigned long)h_ino); + return -EFBIG; + } + pos *= sizeof(*ino); + + file = au_sbr(sb, bindex)->br_xino.xi_file; + if (i_size_read(file->f_dentry->d_inode) < pos + sizeof(*ino)) + return 0; /* no ino */ + + sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &pos); + if (sz == sizeof(*ino)) + return 0; /* success */ + + err = sz; + if (unlikely(sz >= 0)) { + err = -EIO; + AuIOErr("xino read error (%zd)\n", sz); + } + + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* create and set a new xino file */ + +struct file *au_xino_create(struct super_block *sb, char *fname, int silent) +{ + struct file *file; + struct dentry *h_parent, *d; + struct inode *h_dir; + int err; + + /* + * at mount-time, and the xino file is the default path, + * hnotify is disabled so we have no notify events to ignore. + * when a user specified the xino, we cannot get au_hdir to be ignored. + */ + file = vfsub_filp_open(fname, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE + /* | FMODE_NONOTIFY */, + S_IRUGO | S_IWUGO); + if (IS_ERR(file)) { + if (!silent) + pr_err("open %s(%ld)\n", fname, PTR_ERR(file)); + return file; + } + + /* keep file count */ + h_parent = dget_parent(file->f_dentry); + h_dir = h_parent->d_inode; + mutex_lock_nested(&h_dir->i_mutex, AuLsc_I_PARENT); + /* mnt_want_write() is unnecessary here */ + err = vfsub_unlink(h_dir, &file->f_path, /*force*/0); + mutex_unlock(&h_dir->i_mutex); + dput(h_parent); + if (unlikely(err)) { + if (!silent) + pr_err("unlink %s(%d)\n", fname, err); + goto out; + } + + err = -EINVAL; + d = file->f_dentry; + if (unlikely(sb == d->d_sb)) { + if (!silent) + pr_err("%s must be outside\n", fname); + goto out; + } + if (unlikely(au_test_fs_bad_xino(d->d_sb))) { + if (!silent) + pr_err("xino doesn't support %s(%s)\n", + fname, au_sbtype(d->d_sb)); + goto out; + } + return file; /* success */ + +out: + fput(file); + file = ERR_PTR(err); + return file; +} + +/* + * find another branch who is on the same filesystem of the specified + * branch{@btgt}. search until @bend. + */ +static int is_sb_shared(struct super_block *sb, aufs_bindex_t btgt, + aufs_bindex_t bend) +{ + aufs_bindex_t bindex; + struct super_block *tgt_sb = au_sbr_sb(sb, btgt); + + for (bindex = 0; bindex < btgt; bindex++) + if (unlikely(tgt_sb == au_sbr_sb(sb, bindex))) + return bindex; + for (bindex++; bindex <= bend; bindex++) + if (unlikely(tgt_sb == au_sbr_sb(sb, bindex))) + return bindex; + return -1; +} + +/* ---------------------------------------------------------------------- */ + +/* + * initialize the xinofile for the specified branch @br + * at the place/path where @base_file indicates. + * test whether another branch is on the same filesystem or not, + * if @do_test is true. + */ +int au_xino_br(struct super_block *sb, struct au_branch *br, ino_t h_ino, + struct file *base_file, int do_test) +{ + int err; + ino_t ino; + aufs_bindex_t bend, bindex; + struct au_branch *shared_br, *b; + struct file *file; + struct super_block *tgt_sb; + + shared_br = NULL; + bend = au_sbend(sb); + if (do_test) { + tgt_sb = br->br_mnt->mnt_sb; + for (bindex = 0; bindex <= bend; bindex++) { + b = au_sbr(sb, bindex); + if (tgt_sb == b->br_mnt->mnt_sb) { + shared_br = b; + break; + } + } + } + + if (!shared_br || !shared_br->br_xino.xi_file) { + struct au_xino_lock_dir ldir; + + au_xino_lock_dir(sb, base_file, &ldir); + /* mnt_want_write() is unnecessary here */ + file = au_xino_create2(base_file, NULL); + au_xino_unlock_dir(&ldir); + err = PTR_ERR(file); + if (IS_ERR(file)) + goto out; + br->br_xino.xi_file = file; + } else { + br->br_xino.xi_file = shared_br->br_xino.xi_file; + get_file(br->br_xino.xi_file); + } + + ino = AUFS_ROOT_INO; + err = au_xino_do_write(au_sbi(sb)->si_xwrite, br->br_xino.xi_file, + h_ino, ino); + if (unlikely(err)) { + fput(br->br_xino.xi_file); + br->br_xino.xi_file = NULL; + } + +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* trucate a xino bitmap file */ + +/* todo: slow */ +static int do_xib_restore(struct super_block *sb, struct file *file, void *page) +{ + int err, bit; + ssize_t sz; + unsigned long pindex; + loff_t pos, pend; + struct au_sbinfo *sbinfo; + au_readf_t func; + ino_t *ino; + unsigned long *p; + + err = 0; + sbinfo = au_sbi(sb); + MtxMustLock(&sbinfo->si_xib_mtx); + p = sbinfo->si_xib_buf; + func = sbinfo->si_xread; + pend = i_size_read(file->f_dentry->d_inode); + pos = 0; + while (pos < pend) { + sz = xino_fread(func, file, page, PAGE_SIZE, &pos); + err = sz; + if (unlikely(sz <= 0)) + goto out; + + err = 0; + for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) { + if (unlikely(*ino < AUFS_FIRST_INO)) + continue; + + xib_calc_bit(*ino, &pindex, &bit); + AuDebugOn(page_bits <= bit); + err = xib_pindex(sb, pindex); + if (!err) + set_bit(bit, p); + else + goto out; + } + } + +out: + return err; +} + +static int xib_restore(struct super_block *sb) +{ + int err; + aufs_bindex_t bindex, bend; + void *page; + + err = -ENOMEM; + page = (void *)__get_free_page(GFP_NOFS); + if (unlikely(!page)) + goto out; + + err = 0; + bend = au_sbend(sb); + for (bindex = 0; !err && bindex <= bend; bindex++) + if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) + err = do_xib_restore + (sb, au_sbr(sb, bindex)->br_xino.xi_file, page); + else + AuDbg("b%d\n", bindex); + free_page((unsigned long)page); + +out: + return err; +} + +int au_xib_trunc(struct super_block *sb) +{ + int err; + ssize_t sz; + loff_t pos; + struct au_xino_lock_dir ldir; + struct au_sbinfo *sbinfo; + unsigned long *p; + struct file *file; + + SiMustWriteLock(sb); + + err = 0; + sbinfo = au_sbi(sb); + if (!au_opt_test(sbinfo->si_mntflags, XINO)) + goto out; + + file = sbinfo->si_xib; + if (i_size_read(file->f_dentry->d_inode) <= PAGE_SIZE) + goto out; + + au_xino_lock_dir(sb, file, &ldir); + /* mnt_want_write() is unnecessary here */ + file = au_xino_create2(sbinfo->si_xib, NULL); + au_xino_unlock_dir(&ldir); + err = PTR_ERR(file); + if (IS_ERR(file)) + goto out; + fput(sbinfo->si_xib); + sbinfo->si_xib = file; + + p = sbinfo->si_xib_buf; + memset(p, 0, PAGE_SIZE); + pos = 0; + sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos); + if (unlikely(sz != PAGE_SIZE)) { + err = sz; + AuIOErr("err %d\n", err); + if (sz >= 0) + err = -EIO; + goto out; + } + + mutex_lock(&sbinfo->si_xib_mtx); + /* mnt_want_write() is unnecessary here */ + err = xib_restore(sb); + mutex_unlock(&sbinfo->si_xib_mtx); + +out: + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * xino mount option handlers + */ +static au_readf_t find_readf(struct file *h_file) +{ + const struct file_operations *fop = h_file->f_op; + + if (fop) { + if (fop->read) + return fop->read; + if (fop->aio_read) + return do_sync_read; + } + return ERR_PTR(-ENOSYS); +} + +static au_writef_t find_writef(struct file *h_file) +{ + const struct file_operations *fop = h_file->f_op; + + if (fop) { + if (fop->write) + return fop->write; + if (fop->aio_write) + return do_sync_write; + } + return ERR_PTR(-ENOSYS); +} + +/* xino bitmap */ +static void xino_clear_xib(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); + sbinfo->si_xread = NULL; + sbinfo->si_xwrite = NULL; + if (sbinfo->si_xib) + fput(sbinfo->si_xib); + sbinfo->si_xib = NULL; + free_page((unsigned long)sbinfo->si_xib_buf); + sbinfo->si_xib_buf = NULL; +} + +static int au_xino_set_xib(struct super_block *sb, struct file *base) +{ + int err; + loff_t pos; + struct au_sbinfo *sbinfo; + struct file *file; + + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); + file = au_xino_create2(base, sbinfo->si_xib); + err = PTR_ERR(file); + if (IS_ERR(file)) + goto out; + if (sbinfo->si_xib) + fput(sbinfo->si_xib); + sbinfo->si_xib = file; + sbinfo->si_xread = find_readf(file); + sbinfo->si_xwrite = find_writef(file); + + err = -ENOMEM; + if (!sbinfo->si_xib_buf) + sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS); + if (unlikely(!sbinfo->si_xib_buf)) + goto out_unset; + + sbinfo->si_xib_last_pindex = 0; + sbinfo->si_xib_next_bit = 0; + if (i_size_read(file->f_dentry->d_inode) < PAGE_SIZE) { + pos = 0; + err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf, + PAGE_SIZE, &pos); + if (unlikely(err != PAGE_SIZE)) + goto out_free; + } + err = 0; + goto out; /* success */ + +out_free: + free_page((unsigned long)sbinfo->si_xib_buf); + sbinfo->si_xib_buf = NULL; + if (err >= 0) + err = -EIO; +out_unset: + fput(sbinfo->si_xib); + sbinfo->si_xib = NULL; + sbinfo->si_xread = NULL; + sbinfo->si_xwrite = NULL; +out: + return err; +} + +/* xino for each branch */ +static void xino_clear_br(struct super_block *sb) +{ + aufs_bindex_t bindex, bend; + struct au_branch *br; + + bend = au_sbend(sb); + for (bindex = 0; bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + if (!br || !br->br_xino.xi_file) + continue; + + fput(br->br_xino.xi_file); + br->br_xino.xi_file = NULL; + } +} + +static int au_xino_set_br(struct super_block *sb, struct file *base) +{ + int err; + ino_t ino; + aufs_bindex_t bindex, bend, bshared; + struct { + struct file *old, *new; + } *fpair, *p; + struct au_branch *br; + struct inode *inode; + au_writef_t writef; + + SiMustWriteLock(sb); + + err = -ENOMEM; + bend = au_sbend(sb); + fpair = kcalloc(bend + 1, sizeof(*fpair), GFP_NOFS); + if (unlikely(!fpair)) + goto out; + + inode = sb->s_root->d_inode; + ino = AUFS_ROOT_INO; + writef = au_sbi(sb)->si_xwrite; + for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) { + br = au_sbr(sb, bindex); + bshared = is_sb_shared(sb, bindex, bindex - 1); + if (bshared >= 0) { + /* shared xino */ + *p = fpair[bshared]; + get_file(p->new); + } + + if (!p->new) { + /* new xino */ + p->old = br->br_xino.xi_file; + p->new = au_xino_create2(base, br->br_xino.xi_file); + err = PTR_ERR(p->new); + if (IS_ERR(p->new)) { + p->new = NULL; + goto out_pair; + } + } + + err = au_xino_do_write(writef, p->new, + au_h_iptr(inode, bindex)->i_ino, ino); + if (unlikely(err)) + goto out_pair; + } + + for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) { + br = au_sbr(sb, bindex); + if (br->br_xino.xi_file) + fput(br->br_xino.xi_file); + get_file(p->new); + br->br_xino.xi_file = p->new; + } + +out_pair: + for (bindex = 0, p = fpair; bindex <= bend; bindex++, p++) + if (p->new) + fput(p->new); + else + break; + kfree(fpair); +out: + return err; +} + +void au_xino_clr(struct super_block *sb) +{ + struct au_sbinfo *sbinfo; + + au_xigen_clr(sb); + xino_clear_xib(sb); + xino_clear_br(sb); + sbinfo = au_sbi(sb); + /* lvalue, do not call au_mntflags() */ + au_opt_clr(sbinfo->si_mntflags, XINO); +} + +int au_xino_set(struct super_block *sb, struct au_opt_xino *xino, int remount) +{ + int err, skip; + struct dentry *parent, *cur_parent; + struct qstr *dname, *cur_name; + struct file *cur_xino; + struct inode *dir; + struct au_sbinfo *sbinfo; + + SiMustWriteLock(sb); + + err = 0; + sbinfo = au_sbi(sb); + parent = dget_parent(xino->file->f_dentry); + if (remount) { + skip = 0; + dname = &xino->file->f_dentry->d_name; + cur_xino = sbinfo->si_xib; + if (cur_xino) { + cur_parent = dget_parent(cur_xino->f_dentry); + cur_name = &cur_xino->f_dentry->d_name; + skip = (cur_parent == parent + && dname->len == cur_name->len + && !memcmp(dname->name, cur_name->name, + dname->len)); + dput(cur_parent); + } + if (skip) + goto out; + } + + au_opt_set(sbinfo->si_mntflags, XINO); + dir = parent->d_inode; + mutex_lock_nested(&dir->i_mutex, AuLsc_I_PARENT); + /* mnt_want_write() is unnecessary here */ + err = au_xino_set_xib(sb, xino->file); + if (!err) + err = au_xigen_set(sb, xino->file); + if (!err) + err = au_xino_set_br(sb, xino->file); + mutex_unlock(&dir->i_mutex); + if (!err) + goto out; /* success */ + + /* reset all */ + AuIOErr("failed creating xino(%d).\n", err); + +out: + dput(parent); + return err; +} + +/* ---------------------------------------------------------------------- */ + +/* + * create a xinofile at the default place/path. + */ +struct file *au_xino_def(struct super_block *sb) +{ + struct file *file; + char *page, *p; + struct au_branch *br; + struct super_block *h_sb; + struct path path; + aufs_bindex_t bend, bindex, bwr; + + br = NULL; + bend = au_sbend(sb); + bwr = -1; + for (bindex = 0; bindex <= bend; bindex++) { + br = au_sbr(sb, bindex); + if (au_br_writable(br->br_perm) + && !au_test_fs_bad_xino(br->br_mnt->mnt_sb)) { + bwr = bindex; + break; + } + } + + if (bwr >= 0) { + file = ERR_PTR(-ENOMEM); + page = __getname_gfp(GFP_NOFS); + if (unlikely(!page)) + goto out; + path.mnt = br->br_mnt; + path.dentry = au_h_dptr(sb->s_root, bwr); + p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME)); + file = (void *)p; + if (!IS_ERR(p)) { + strcat(p, "/" AUFS_XINO_FNAME); + AuDbg("%s\n", p); + file = au_xino_create(sb, p, /*silent*/0); + if (!IS_ERR(file)) + au_xino_brid_set(sb, br->br_id); + } + __putname(page); + } else { + file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0); + if (IS_ERR(file)) + goto out; + h_sb = file->f_dentry->d_sb; + if (unlikely(au_test_fs_bad_xino(h_sb))) { + pr_err("xino doesn't support %s(%s)\n", + AUFS_XINO_DEFPATH, au_sbtype(h_sb)); + fput(file); + file = ERR_PTR(-EINVAL); + } + if (!IS_ERR(file)) + au_xino_brid_set(sb, -1); + } + +out: + return file; +} + +/* ---------------------------------------------------------------------- */ + +int au_xino_path(struct seq_file *seq, struct file *file) +{ + int err; + + err = au_seq_path(seq, &file->f_path); + if (unlikely(err < 0)) + goto out; + + err = 0; +#define Deleted "\\040(deleted)" + seq->count -= sizeof(Deleted) - 1; + AuDebugOn(memcmp(seq->buf + seq->count, Deleted, + sizeof(Deleted) - 1)); +#undef Deleted + +out: + return err; +} --- linux-2.6.37.orig/ubuntu/compcache/BOM +++ linux-2.6.37/ubuntu/compcache/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://code.google.com/p/compcache/ +Current Version: 0.5.3 --- linux-2.6.37.orig/ubuntu/compcache/Changelog +++ linux-2.6.37/ubuntu/compcache/Changelog @@ -0,0 +1,82 @@ +version 0.5.3 (8/4/2009) + - Major cleanups. + - Rename module: compcache.ko -> ramzswap.ko + - Rename params: backing_dev -> backing_swap + - Updated use_compcache.sh script with detailed + documentation on parameters. + - LZO de/compress modules are no longer packaged + with compcache. Most distros now include these. + +version 0.5.2 (11/3/2009) + - Can forward incompressible pages to physical swap disk. + - New module params: + - memlimit_kb + - disksize_kb + - backing_dev + See use_compcache.sh for documentation on these params. + - Modified use_compcache.sh script to handle new params. + - Detect zero-filled pages and don't allocate any memory + for them. + +version 0.5.1 (22/1/2009) + - Fix crash on x86 systems with higmem (mem > ~1G). + This required minor changes to atomic (un)map functions (see Issue #20). + +version 0.5 (16/1/2009) + - Fix crash in case compcache init fails. + +version 0.5pre4 (10/1/2009) + - Support discarding pages for freed swap blocks (requires 2.6.28-git14). + This feature will be disabled if compiled for older kernel. + - Mark ramzswap as "solid-state" block device (requires 2.6.26-git14). + - Fixed incorrect stats reporting in /proc/compcache (some + new stats added too). + +version 0.5pre3 (5/1/2009) + - Use kmap_atomic() in xvMalloc. This fixes issue #19 + - Remove xvMapPage() and xvUnmapMap() from xvMalloc. + +version 0.5pre2 (28/10/2008) + - Alloc full page for uncompressible pages instead + of returning I/O error. + - Warn users when using ramzswap > (2 x RAM size) + +version 0.5pre1 (15/10/2008) + - Replaced TLSF with xvMalloc memory allocator + http://code.google.com/p/compcache/wiki/xvMalloc + +version 0.4 (13/8/2008) + - Enable debug and stats option for compcache and tlsf by default + proc nodes: /proc/{tlsfinfo,compcache} + - Fix crash when reading /proc/tlsfinfo + - Lots of cleanups: clean compile on x64 + +version 0.3 (17/3/2008) + - Fix spurious swap read failures + - Better swap request filtering + - Swap device again renamed to /dev/ramzswap0 + This is to prevent Ubuntu installer from presenting + this device as possible installation target (see Issue #5) + - use_compcache.sh script now waits for disk node to be created + instead of arbitrary sleep (see Issue #6). + - Modified scripts: use_compcache.sh and unuse_compcache.sh + to now use new device name (compcache0 -> ramzswap0). + +version 0.2 (3/3/2008) + - Fixed bug on systems with highmem + - Better filtering-out of non-swap requests + - Export statistics through proc nodes: + - /proc/compcache + - /proc/tlsfinfo + - Debug and Statistics support for allocator + and compcache can now be individually turned + on/off by setting DEBUG, STATS to 0/1 in + respective header files + - Swap device now renamed to /dev/compcache0 + - Added scripts: use_compcache.sh and unuse_compcache.sh + See README for usage + - Default compcache size set to 25% of RAM + - Lots of code cleanups + - Updated README + - Created Changelog :) + --- linux-2.6.37.orig/ubuntu/compcache/GPL.txt +++ linux-2.6.37/ubuntu/compcache/GPL.txt @@ -0,0 +1,280 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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. + + GNU GENERAL PUBLIC LICENSE + 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 --- linux-2.6.37.orig/ubuntu/compcache/Kconfig +++ linux-2.6.37/ubuntu/compcache/Kconfig @@ -0,0 +1,31 @@ +menu "Compcache options" + +config BLK_DEV_COMPCACHE + tristate "Compressed RAM based swap device" + default m + select LZO_COMPRESS + select LZO_DECOMPRESS + depends on BLOCK + help + This creates RAM based block device which acts as swap disk. Pages + swapped to this disk are compressed and stored in memory itself. + Project Home: http://code.google.com/p/compcache/ + +config BLK_DEV_COMPCACHE_DEBUG + default n + depends on BLK_DEV_COMPCACHE + bool "Enable debugging" + help + This causes negligible performance loss and size increase. + If unsure, say Y. + +config BLK_DEV_COMPCACHE_STATS + default n + depends on BLK_DEV_COMPCACHE + bool "Enable statistics" + help + Creates /proc/compcache to export various statistics. + This adds about 4K to size with negligible performance loss. + If unsure, say Y. + +endmenu --- linux-2.6.37.orig/ubuntu/compcache/LGPL-2.1.txt +++ linux-2.6.37/ubuntu/compcache/LGPL-2.1.txt @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, 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. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +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 and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete 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 distribute a copy of this License along with the +Library. + + 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 Library or any portion +of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +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 Library, 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 Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be 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. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +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 with +this License. + + 11. 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 Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library 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 Library. + +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. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser 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 Library +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 Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "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 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 +LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + --- linux-2.6.37.orig/ubuntu/compcache/Makefile +++ linux-2.6.37/ubuntu/compcache/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_BLK_DEV_COMPCACHE) := ramzswap.o xvmalloc.o --- linux-2.6.37.orig/ubuntu/compcache/README +++ linux-2.6.37/ubuntu/compcache/README @@ -0,0 +1,45 @@ +ramzswap: Compressed RAM based swap device +------------------------------------------- + +Project home: http://compcache.googlecode.com + +* Introduction +This is a RAM based block device which acts as swap disk. +Pages swapped to this device are compressed and stored in +memory itself. See project home for use cases, performance +numbers and lot more. + +* Compiling + - Run 'make': this will compile all modules against your kernel. + + - Following kernel modules are created: + - xvmalloc.ko + - ramzswap.ko + +* Using + - Following scipts are included + - use_ramzswap.sh [] [] + This loads all required modules and sets up swap device. + NOTE: script contains detailed documentation on parameters. + + - unuse_ramzswap.sh + Unloads all modules and turns off ramzswap swap device. + +* Common Problems + - If you get lots of compile errors, make sure you have package for + kernel source installed. For e.g., on Fedora its 'kernel-devel' package. + + - If (un)use_ramzswap scripts fail to work, refer to wiki: + http://code.google.com/p/compcache/wiki/CompilingAndUsing + +* Notes + - Statistics are exported via /proc/ramzswap + +Please consider using Issue Tracker: +http://code.google.com/p/compcache/issues/list +for reporting any bugs/feature requests. + +Cheers! +Nitin Gupta +EMail: ngupta at vflare dot org + --- linux-2.6.37.orig/ubuntu/compcache/compat.h +++ linux-2.6.37/ubuntu/compcache/compat.h @@ -0,0 +1,34 @@ +#ifndef _CCACHE_COMPAT_H_ +#define _CCACHE_COMPAT_H_ + +#include + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) +#define BIO_IO_ERROR(bio) bio_io_error(bio, PAGE_SIZE) +#define BIO_ENDIO(bio, error) bio_endio(bio, PAGE_SIZE, error) +#else +#define BIO_IO_ERROR(bio) bio_io_error(bio) +#define BIO_ENDIO(bio, error) bio_endio(bio, error) +#endif + +#ifndef pr_err +#define pr_err(fmt, arg...) \ + printk(KERN_ERR fmt, ##arg) +#endif + +#ifndef pr_warning +#define pr_warning(fmt, arg...) \ + printk(KERN_WARNING fmt, ##arg) +#endif + +#ifndef pr_info +#define pr_info(fmt, arg...) \ + printk(KERN_ERR fmt, ##arg) +#endif + +#ifdef bio_discard +#define SWAP_DISCARD_SUPPORTED +#endif + +#endif + --- linux-2.6.37.orig/ubuntu/compcache/ramzswap.c +++ linux-2.6.37/ubuntu/compcache/ramzswap.c @@ -0,0 +1,1049 @@ +/* + * Compressed RAM based swap device + * + * Copyright (C) 2008, 2009 Nitin Gupta + * + * This RAM based block device acts as swap disk. + * Pages swapped to this device are compressed and + * stored in memory. + * + * Released under the terms of GNU General Public License Version 2.0 + * + * Project home: http://compcache.googlecode.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "compat.h" +#include "ramzswap.h" + +/* Globals */ +static struct ramzswap rzs; +static struct ramzswap_stats stats; +/* + * Pages that compress to larger than this size are + * forwarded to backing swap, if present or stored + * uncompressed in memory otherwise. + */ +static unsigned int MAX_CPAGE_SIZE; + +/* Module params (documentation at end) */ +static unsigned long disksize_kb; +static unsigned long memlimit_kb; +static char *backing_swap; + +static int __init ramzswap_init(void); +static struct block_device_operations ramzswap_devops = { + .owner = THIS_MODULE, +}; + +static int test_flag(u32 index, enum rzs_pageflags flag) +{ + return rzs.table[index].flags & BIT(flag); +} + +static void set_flag(u32 index, enum rzs_pageflags flag) +{ + rzs.table[index].flags |= BIT(flag); +} + +static void clear_flag(u32 index, enum rzs_pageflags flag) +{ + rzs.table[index].flags &= ~BIT(flag); +} + +static int page_zero_filled(void *ptr) +{ + u32 pos; + u64 *page; + + page = (u64 *)ptr; + + for (pos = 0; pos != PAGE_SIZE / sizeof(*page); pos++) { + if (page[pos]) + return 0; + } + + return 1; +} + +/* + * Given pair, provide a dereferencable pointer. + */ +static void *get_ptr_atomic(u32 pagenum, u16 offset, enum km_type type) +{ + unsigned char *page; + + page = kmap_atomic(pfn_to_page(pagenum), type); + return page + offset; +} + +static void put_ptr_atomic(void *ptr, enum km_type type) +{ + kunmap_atomic(ptr, type); +} + +#if defined(STATS) +static struct proc_dir_entry *proc; + +static int proc_ramzswap_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + size_t succ_writes, mem_used; + unsigned int good_compress_perc = 0, no_compress_perc = 0; + + mem_used = xv_get_total_size_bytes(rzs.mem_pool) + + (stats.pages_expand << PAGE_SHIFT); + + if (off > 0) { + *eof = 1; + return 0; + } + +#define K(x) ((x) >> 10) + /* Basic stats */ + len = sprintf(page, + "DiskSize: %8zu kB\n", + (size_t)(K(rzs.disksize))); + + if (rzs.backing_swap) { + /* This must always be less than ComprDataSize */ + len += sprintf(page + len, + "MemLimit: %8zu kB\n", + K(rzs.memlimit)); + } + + succ_writes = stats.num_writes - stats.failed_writes; + + if (succ_writes && stats.pages_stored) { + good_compress_perc = stats.good_compress * 100 + / stats.pages_stored; + no_compress_perc = stats.pages_expand * 100 + / stats.pages_stored; + } + + /* Extended stats */ + len += sprintf(page + len, + "NumReads: %8llu\n" + "NumWrites: %8llu\n" + "FailedReads: %8llu\n" + "FailedWrites: %8llu\n" + "InvalidIO: %8llu\n" + "PagesDiscard: %8llu\n" + "ZeroPages: %8u\n" + "GoodCompress: %8u %%\n" + "NoCompress: %8u %%\n" + "PagesStored: %8u\n" + "PagesUsed: %8zu\n" + "OrigDataSize: %8zu kB\n" + "ComprDataSize: %8zu kB\n" + "MemUsedTotal: %8zu kB\n", + stats.num_reads, + stats.num_writes, + stats.failed_reads, + stats.failed_writes, + stats.invalid_io, + stats.pages_discard, + stats.pages_zero, + good_compress_perc, + no_compress_perc, + stats.pages_stored, + mem_used >> PAGE_SHIFT, + (size_t)(K(stats.pages_stored << PAGE_SHIFT)), + (size_t)(K(stats.compr_size)), + (size_t)(K(mem_used))); + + if (rzs.backing_swap) { + /* This must always be less than ComprDataSize */ + len += sprintf(page + len, + "BDevNumReads: %8llu\n" + "BDevNumWrites: %8llu\n", + stats.bdev_num_reads, + stats.bdev_num_writes); + } + + return len; +} +#endif /* STATS */ + +/* + * Check if value of backing_swap module param is sane. + * Claim this device and set ramzswap size equal to + * size of this block device. + */ +static int setup_backing_swap(void) +{ + int error = 0; + struct inode *inode; + struct file *swap_file; + struct address_space *mapping; + struct block_device *bdev = NULL; + + if (backing_swap == NULL) { + pr_debug(C "backing_swap param not given\n"); + goto out; + } + + pr_info(C "Using backing swap device: %s\n", backing_swap); + + swap_file = filp_open(backing_swap, O_RDWR | O_LARGEFILE, 0); + if (IS_ERR(swap_file)) { + pr_err(C "Error opening backing device: %s\n", backing_swap); + error = -EINVAL; + goto out; + } + + mapping = swap_file->f_mapping; + inode = mapping->host; + + if (S_ISBLK(inode->i_mode)) { + bdev = I_BDEV(inode); + error = bd_claim(bdev, ramzswap_init); + if (error < 0) { + bdev = NULL; + goto bad_param; + } + rzs.old_block_size = block_size(bdev); + error = set_blocksize(bdev, PAGE_SIZE); + if (error < 0) + goto bad_param; + } else { + /* TODO: support for regular file as backing swap */ + pr_info(C "%s is not a block device.\n", backing_swap); + error = -EINVAL; + goto out; + } + + rzs.swap_file = swap_file; + rzs.backing_swap = bdev; + rzs.disksize = i_size_read(inode); + BUG_ON(!rzs.disksize); + + return 0; + +bad_param: + if (bdev) { + set_blocksize(bdev, rzs.old_block_size); + bd_release(bdev); + } + filp_close(swap_file, NULL); + +out: + rzs.backing_swap = NULL; + return error; +} + +/* + * Check if request is within bounds and page aligned. + */ +static inline int valid_swap_request(struct bio *bio) +{ + if (unlikely( + (bio->bi_sector >= (rzs.disksize >> SECTOR_SHIFT)) || + (bio->bi_sector & (SECTORS_PER_PAGE - 1)) || + (bio->bi_vcnt != 1) || + (bio->bi_size != PAGE_SIZE) || + (bio->bi_io_vec[0].bv_offset != 0))) { + + return 0; + } + + /* swap request is valid */ + return 1; +} + +static void ramzswap_free_page(size_t index) +{ + u32 clen; + void *obj; + + u32 pagenum = rzs.table[index].pagenum; + u32 offset = rzs.table[index].offset; + + if (unlikely(test_flag(index, RZS_UNCOMPRESSED))) { + clen = PAGE_SIZE; + __free_page(pfn_to_page(pagenum)); + clear_flag(index, RZS_UNCOMPRESSED); + stat_dec(stats.pages_expand); + goto out; + } + + obj = get_ptr_atomic(pagenum, offset, KM_USER0); + clen = xv_get_object_size(obj) - sizeof(struct zobj_header); + put_ptr_atomic(obj, KM_USER0); + + xv_free(rzs.mem_pool, pagenum, offset); + stat_dec_if_less(stats.good_compress, clen, PAGE_SIZE / 2 + 1); + +out: + stats.compr_size -= clen; + stat_dec(stats.pages_stored); + + rzs.table[index].pagenum = 0; + rzs.table[index].offset = 0; +} + +#ifdef SWAP_DISCARD_SUPPORTED +static int ramzswap_prepare_discard(struct request_queue *q, + struct request *req) +{ + return 0; +} + +/* + * Called by main I/O handler function. This helper + * function handles 'discard' I/O requests which means + * that some swap pages are no longer required, so + * swap device can take needed action -- we free memory + * allocated for these pages. + */ +static int ramzswap_discard(struct bio *bio) +{ + size_t index, start_page, num_pages; + + start_page = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; + num_pages = bio->bi_size >> (SECTOR_SHIFT + SECTORS_PER_PAGE_SHIFT); + + for (index = start_page; index < start_page + num_pages; index++) { + if (rzs.table[index].pagenum) { + ramzswap_free_page(index); + stat_inc(stats.pages_discard); + } + } + + set_bit(BIO_UPTODATE, &bio->bi_flags); + BIO_ENDIO(bio, 0); + return 0; +} +#endif + +int handle_zero_page(struct bio *bio) +{ + void *user_mem; + struct page *page = bio->bi_io_vec[0].bv_page; + + user_mem = get_ptr_atomic(page_to_pfn(page), 0, KM_USER0); + memset(user_mem, 0, PAGE_SIZE); + put_ptr_atomic(user_mem, KM_USER0); + + set_bit(BIO_UPTODATE, &bio->bi_flags); + BIO_ENDIO(bio, 0); + return 0; +} + +int handle_uncompressed_page(struct bio *bio) +{ + u32 index; + struct page *page; + unsigned char *user_mem, *cmem; + + page = bio->bi_io_vec[0].bv_page; + index = bio->bi_sector >>SECTORS_PER_PAGE_SHIFT; + + user_mem = get_ptr_atomic(page_to_pfn(page), 0, KM_USER0); + cmem = get_ptr_atomic(rzs.table[index].pagenum, + rzs.table[index].offset, KM_USER1); + + memcpy(user_mem, cmem, PAGE_SIZE); + put_ptr_atomic(user_mem, KM_USER0); + put_ptr_atomic(cmem, KM_USER1); + + set_bit(BIO_UPTODATE, &bio->bi_flags); + BIO_ENDIO(bio, 0); + return 0; +} + + +/* + * Called when request page is not present in ramzswap. + * Its either in backing swap device (if present) or + * this is an attempt to read before any previous write + * to this location - this happens due to readahead when + * swap device is read from user-space (e.g. during swapon) + */ +int handle_ramzswap_fault(struct bio *bio) +{ + void *user_mem; + struct page *page = bio->bi_io_vec[0].bv_page; + + /* + * Always forward such requests to backing swap + * device (if present) + */ + if (rzs.backing_swap) { + stat_dec(stats.num_reads); + stat_inc(stats.bdev_num_reads); + bio->bi_bdev = rzs.backing_swap; + return 1; + } + + /* + * Its unlikely event in case backing dev is + * not present + */ + pr_debug(C "Read before write on swap device: " + "sector=%lu, size=%u, offset=%u\n", + (ulong)(bio->bi_sector), bio->bi_size, + bio->bi_io_vec[0].bv_offset); + user_mem = kmap(page); + memset(user_mem, 0, PAGE_SIZE); + kunmap(page); + + set_bit(BIO_UPTODATE, &bio->bi_flags); + BIO_ENDIO(bio, 0); + return 0; +} + +int ramzswap_read(struct bio *bio) +{ + int ret; + u32 index; + size_t clen; + struct page *page; + struct zobj_header *zheader; + unsigned char *user_mem, *cmem; + + stat_inc(stats.num_reads); + + page = bio->bi_io_vec[0].bv_page; + index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; + + if (test_flag(index, RZS_ZERO)) + return handle_zero_page(bio); + + /* Requested page is not present in compressed area */ + if (!rzs.table[index].pagenum) + return handle_ramzswap_fault(bio); + + /* Page is stored uncompressed since its incompressible */ + if (unlikely(test_flag(index, RZS_UNCOMPRESSED))) + return handle_uncompressed_page(bio); + + user_mem = get_ptr_atomic(page_to_pfn(page), 0, KM_USER0); + clen = PAGE_SIZE; + + cmem = get_ptr_atomic(rzs.table[index].pagenum, + rzs.table[index].offset, KM_USER1); + + ret = lzo1x_decompress_safe( + cmem + sizeof(*zheader), + xv_get_object_size(cmem) - sizeof(*zheader), + user_mem, &clen); + + put_ptr_atomic(user_mem, KM_USER0); + put_ptr_atomic(cmem, KM_USER1); + + /* should NEVER happen */ + if (unlikely(ret != LZO_E_OK)) { + pr_err(C "Decompression failed! err=%d, page=%u\n", + ret, index); + stat_inc(stats.failed_reads); + goto out; + } + + set_bit(BIO_UPTODATE, &bio->bi_flags); + BIO_ENDIO(bio, 0); + return 0; + +out: + BIO_IO_ERROR(bio); + return 0; +} + +int ramzswap_write(struct bio *bio) +{ + int ret, fwd_write_request = 0; + u32 offset; + size_t clen, index; + struct zobj_header *zheader; + struct page *page, *page_store; + unsigned char *user_mem, *cmem, *src; + + stat_inc(stats.num_writes); + + page = bio->bi_io_vec[0].bv_page; + index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT; + + src = rzs.compress_buffer; + + /* + * System swaps to same sector again when the stored page + * is no longer referenced by any process. So, its now safe + * to free the memory that was allocated for this page. + */ + if (rzs.table[index].pagenum) + ramzswap_free_page(index); + + /* + * No memory ia allocated for zero filled pages. + * Simply clear zero page flag. + */ + if (test_flag(index, RZS_ZERO)) { + stat_dec(stats.pages_zero); + clear_flag(index, RZS_ZERO); + } + + mutex_lock(&rzs.lock); + + user_mem = get_ptr_atomic(page_to_pfn(page), 0, KM_USER0); + if (page_zero_filled(user_mem)) { + put_ptr_atomic(user_mem, KM_USER0); + mutex_unlock(&rzs.lock); + stat_inc(stats.pages_zero); + set_flag(index, RZS_ZERO); + + set_bit(BIO_UPTODATE, &bio->bi_flags); + BIO_ENDIO(bio, 0); + return 0; + } + + if (rzs.backing_swap && + (stats.compr_size > rzs.memlimit - PAGE_SIZE)) { + put_ptr_atomic(user_mem, KM_USER0); + mutex_unlock(&rzs.lock); + fwd_write_request = 1; + goto out; + } + + ret = lzo1x_1_compress(user_mem, PAGE_SIZE, src, &clen, + rzs.compress_workmem); + + put_ptr_atomic(user_mem, KM_USER0); + + if (unlikely(ret != LZO_E_OK)) { + mutex_unlock(&rzs.lock); + pr_err(C "Compression failed! err=%d\n", ret); + stat_inc(stats.failed_writes); + goto out; + } + + /* + * Page is incompressible. Forward it to backing swap + * if present. Otherwise, store it as-is (uncompressed) + * since we do not want to return too many swap write + * errors which has side effect of hanging the system. + */ + if (unlikely(clen > MAX_CPAGE_SIZE)) { + if (rzs.backing_swap) { + mutex_unlock(&rzs.lock); + fwd_write_request = 1; + goto out; + } + + clen = PAGE_SIZE; + page_store = alloc_page(GFP_NOIO | __GFP_HIGHMEM); + if (unlikely(!page_store)) { + mutex_unlock(&rzs.lock); + stat_inc(stats.failed_writes); + goto out; + } + + offset = 0; + set_flag(index, RZS_UNCOMPRESSED); + stat_inc(stats.pages_expand); + rzs.table[index].pagenum = page_to_pfn(page_store); + src = get_ptr_atomic(page_to_pfn(page), 0, KM_USER0); + goto memstore; + } + + if (xv_malloc(rzs.mem_pool, clen + sizeof(*zheader), + &rzs.table[index].pagenum, &offset, + GFP_NOIO | __GFP_HIGHMEM)) { + mutex_unlock(&rzs.lock); + pr_info(C "Error allocating memory for compressed " + "page: %zu, size=%zu\n", index, clen); + stat_inc(stats.failed_writes); + if (rzs.backing_swap) + fwd_write_request = 1; + goto out; + } + +memstore: + rzs.table[index].offset = offset; + + cmem = get_ptr_atomic(rzs.table[index].pagenum, + rzs.table[index].offset, KM_USER1); + +#if 0 + /* Back-reference needed for memory defragmentation */ + if (!test_flag(index, RZS_UNCOMPRESSED)) { + zheader = (struct zobj_header *)cmem; + zheader->table_idx = index; + cmem += sizeof(*zheader); + } +#endif + + memcpy(cmem, src, clen); + + put_ptr_atomic(cmem, KM_USER1); + if (unlikely(test_flag(index, RZS_UNCOMPRESSED))) + put_ptr_atomic(src, KM_USER0); + + /* Update stats */ + stats.compr_size += clen; + stat_inc(stats.pages_stored); + stat_inc_if_less(stats.good_compress, clen, PAGE_SIZE / 2 + 1); + + mutex_unlock(&rzs.lock); + + set_bit(BIO_UPTODATE, &bio->bi_flags); + BIO_ENDIO(bio, 0); + return 0; + +out: + if (fwd_write_request) { + stat_inc(stats.bdev_num_writes); + bio->bi_bdev = rzs.backing_swap; + return 1; + } + + BIO_IO_ERROR(bio); + return 0; +} + +/* + * Handler function for all ramzswap I/O requests. + */ +static int ramzswap_make_request(struct request_queue *queue, struct bio *bio) +{ + int ret = 0; + +#ifdef SWAP_DISCARD_SUPPORTED + if (bio_discard(bio)) + return ramzswap_discard(bio); +#endif + + if (!valid_swap_request(bio)) { + stat_inc(stats.invalid_io); + BIO_IO_ERROR(bio); + return 0; + } + + switch (bio_data_dir(bio)) { + case READ: + ret = ramzswap_read(bio); + break; + + case WRITE: + ret = ramzswap_write(bio); + break; + } + + return ret; +} + +/* + * Swap header (1st page of swap device) contains information + * to indentify it as a swap partition. Prepare such a header + * for ramzswap device (ramzswap0) so that swapon can identify + * it as swap partition. In case backing swap device is provided, + * copy its swap header. + */ +static int setup_swap_header(union swap_header *s) +{ + int ret = 0; + struct page *page; + struct address_space *mapping; + union swap_header *backing_swap_header; + + /* + * There is no backing swap device. Create a swap header + * that is acceptable by swapon. + */ + if (rzs.backing_swap == NULL) { + s->info.version = 1; + s->info.last_page = rzs.disksize >> PAGE_SHIFT; + s->info.nr_badpages = 0; + memcpy(s->magic.magic, "SWAPSPACE2", 10); + return 0; + } + + /* + * We have a backing swap device. Copy its swap header + * to ramzswap device header. If this header contains + * invalid information (backing device not a swap + * partition, etc.), swapon will fail for ramzswap + * which is correct behavior - we don't want to swap + * over filesystem partition! + */ + + /* Read the backing swap header (code from sys_swapon) */ + mapping = rzs.swap_file->f_mapping; + if (!mapping->a_ops->readpage) { + ret = -EINVAL; + goto out; + } + + page = read_mapping_page(mapping, 0, rzs.swap_file); + if (IS_ERR(page)) { + ret = PTR_ERR(page); + goto out; + } + + backing_swap_header = kmap(page); + *s = *backing_swap_header; + kunmap(page); + +out: + return ret; +} + +static void ramzswap_set_disksize(size_t totalram_bytes) +{ + rzs.disksize = disksize_kb << 10; + + if (!disksize_kb) { + pr_info(C + "disk size not provided. You can use disksize_kb module " + "param to specify size.\nUsing default: (%u%% of RAM).\n", + DEFAULT_DISKSIZE_PERC_RAM + ); + rzs.disksize = DEFAULT_DISKSIZE_PERC_RAM * + (totalram_bytes / 100); + } + + if (disksize_kb > 2 * (totalram_bytes >> 10)) { + pr_info(C + "There is little point creating a ramzswap of greater than " + "twice the size of memory since we expect a 2:1 compression " + "ratio. Note that ramzswap uses about 0.1%% of the size of " + "the swap device when not in use so a huge ramzswap is " + "wasteful.\n" + "\tMemory Size: %zu kB\n" + "\tSize you selected: %lu kB\n" + "Continuing anyway ...\n", + totalram_bytes >> 10, disksize_kb + ); + } + + rzs.disksize &= PAGE_MASK; + pr_info(C "disk size set to %zu kB\n", rzs.disksize >> 10); +} + +/* + * memlimit cannot be greater than backing disk size. + */ +static void ramzswap_set_memlimit(size_t totalram_bytes) +{ + int memlimit_valid = 1; + rzs.memlimit = memlimit_kb << 10; + + if (!rzs.memlimit) { + pr_info(C "memory limit not set. You can use " + "memlimit_kb module param to specify limit."); + memlimit_valid = 0; + } + + if (rzs.memlimit > rzs.disksize) { + pr_info(C "memory limit cannot be greater than " + "disksize: limit=%zu, disksize=%zu", + rzs.memlimit, rzs.disksize); + memlimit_valid = 0; + } + + if (!memlimit_valid) { + size_t mempart, disksize; + pr_info(C "\nUsing default: MIN[(%u%% of RAM), " + "(backing disk size)].\n", + DEFAULT_MEMLIMIT_PERC_RAM); + mempart = DEFAULT_MEMLIMIT_PERC_RAM * (totalram_bytes / 100); + disksize = rzs.disksize; + rzs.memlimit = mempart > disksize ? disksize : mempart; + } + + if (rzs.memlimit > totalram_bytes / 2) { + pr_info(C + "Its not advisable setting limit more than half of " + "size of memory since we expect a 2:1 compression ratio. " + "Limit represents amount of *compressed* data we can keep " + "in memory!\n" + "\tMemory Size: %zu kB\n" + "\tLimit you selected: %lu kB\n" + "Continuing anyway ...\n", + totalram_bytes >> 10, memlimit_kb + ); + } + + rzs.memlimit &= PAGE_MASK; + BUG_ON(!rzs.memlimit); + + pr_info(C "memory limit set to %zu kB\n", rzs.memlimit >> 10); +} + +static int __init ramzswap_init(void) +{ + int ret; + size_t num_pages, totalram_bytes; + struct sysinfo i; + struct page *page; + void *swap_header; + + mutex_init(&rzs.lock); + + ret = setup_backing_swap(); + if (ret) + goto fail; + + si_meminfo(&i); + /* Here is a trivia: guess unit used for i.totalram !! */ + totalram_bytes = i.totalram << PAGE_SHIFT; + + if (rzs.backing_swap) + ramzswap_set_memlimit(totalram_bytes); + else + ramzswap_set_disksize(totalram_bytes); + + rzs.compress_workmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL); + if (rzs.compress_workmem == NULL) { + pr_err(C "Error allocating compressor working memory\n"); + ret = -ENOMEM; + goto fail; + } + + rzs.compress_buffer = kmalloc(2 * PAGE_SIZE, GFP_KERNEL); + if (rzs.compress_buffer == NULL) { + pr_err(C "Error allocating compressor buffer space\n"); + ret = -ENOMEM; + goto fail; + } + + num_pages = rzs.disksize >> PAGE_SHIFT; + rzs.table = vmalloc(num_pages * sizeof(*rzs.table)); + if (rzs.table == NULL) { + pr_err(C "Error allocating ramzswap address table\n"); + ret = -ENOMEM; + goto fail; + } + memset(rzs.table, 0, num_pages * sizeof(*rzs.table)); + + page = alloc_page(__GFP_ZERO); + if (page == NULL) { + pr_err(C "Error allocating swap header page\n"); + ret = -ENOMEM; + goto fail; + } + rzs.table[0].pagenum = page_to_pfn(page); + set_flag(0, RZS_UNCOMPRESSED); + + swap_header = kmap(page); + ret = setup_swap_header((union swap_header *)(swap_header)); + kunmap(page); + if (ret) { + pr_err(C "Error setting swap header\n"); + goto fail; + } + + rzs.disk = alloc_disk(1); + if (rzs.disk == NULL) { + pr_err(C "Error allocating disk structure\n"); + ret = -ENOMEM; + goto fail; + } + + rzs.disk->first_minor = 0; + rzs.disk->fops = &ramzswap_devops; + /* + * It is named like this to prevent distro installers + * from offering ramzswap as installation target. They + * seem to ignore all devices beginning with 'ram' + */ + strcpy(rzs.disk->disk_name, "ramzswap0"); + + rzs.disk->major = register_blkdev(0, rzs.disk->disk_name); + if (rzs.disk->major < 0) { + pr_err(C "Cannot register block device\n"); + ret = -EFAULT; + goto fail; + } + + rzs.disk->queue = blk_alloc_queue(GFP_KERNEL); + if (rzs.disk->queue == NULL) { + pr_err(C "Cannot register disk queue\n"); + ret = -EFAULT; + goto fail; + } + + set_capacity(rzs.disk, rzs.disksize >> SECTOR_SHIFT); + blk_queue_make_request(rzs.disk->queue, ramzswap_make_request); + +#ifdef QUEUE_FLAG_NONROT + /* + * Assuming backing device is "rotational" type. + * TODO: check if its actually "non-rotational" (SSD). + * + * We have ident mapping of sectors for ramzswap and + * and the backing swap device. So, this queue flag + * should be according to backing dev. + */ + if (!rzs.backing_swap) + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, rzs.disk->queue); +#endif +#ifdef SWAP_DISCARD_SUPPORTED + blk_queue_set_discard(rzs.disk->queue, ramzswap_prepare_discard); +#endif + blk_queue_logical_block_size(rzs.disk->queue, PAGE_SIZE); + add_disk(rzs.disk); + + rzs.mem_pool = xv_create_pool(); + if (!rzs.mem_pool) { + pr_err(C "Error creating memory pool\n"); + ret = -ENOMEM; + goto fail; + } + +#if defined(STATS) + proc = create_proc_entry("ramzswap", S_IRUGO, NULL); + if (proc) + proc->read_proc = &proc_ramzswap_read; + else { + ret = -ENOMEM; + pr_warning(C "Error creating proc entry\n"); + goto fail; + } +#endif + + /* + * Pages that compress to size greater than this are forwarded + * to physical swap disk (if backing dev is provided) + */ + if (rzs.backing_swap) + MAX_CPAGE_SIZE = MAX_CPAGE_SIZE_BDEV; + else + MAX_CPAGE_SIZE = MAX_CPAGE_SIZE_NOBDEV; + + pr_debug(C "Max compressed page size: %u bytes\n", MAX_CPAGE_SIZE); + + pr_debug(C "Initialization done!\n"); + return 0; + +fail: + if (rzs.disk != NULL) { + if (rzs.disk->major > 0) + unregister_blkdev(rzs.disk->major, rzs.disk->disk_name); + del_gendisk(rzs.disk); + } + + if (rzs.table && rzs.table[0].pagenum) + __free_page(pfn_to_page(rzs.table[0].pagenum)); + kfree(rzs.compress_workmem); + kfree(rzs.compress_buffer); + vfree(rzs.table); + xv_destroy_pool(rzs.mem_pool); +#if defined(STATS) + if (proc) + remove_proc_entry("ramzswap", proc->parent); +#endif + pr_err(C "Initialization failed: err=%d\n", ret); + return ret; +} + +static void __exit ramzswap_exit(void) +{ + size_t index, num_pages; + num_pages = rzs.disksize >> PAGE_SHIFT; + + unregister_blkdev(rzs.disk->major, rzs.disk->disk_name); + del_gendisk(rzs.disk); + + /* Close backing swap device (if present) */ + if (rzs.backing_swap) { + set_blocksize(rzs.backing_swap, rzs.old_block_size); + bd_release(rzs.backing_swap); + filp_close(rzs.swap_file, NULL); + } + + __free_page(pfn_to_page(rzs.table[0].pagenum)); + kfree(rzs.compress_workmem); + kfree(rzs.compress_buffer); + + /* Free all pages that are still in ramzswap */ + for (index = 1; index < num_pages; index++) { + u32 pagenum, offset; + + pagenum = rzs.table[index].pagenum; + offset = rzs.table[index].offset; + + if (!pagenum) + continue; + + if (unlikely(test_flag(index, RZS_UNCOMPRESSED))) + __free_page(pfn_to_page(pagenum)); + else + xv_free(rzs.mem_pool, pagenum, offset); + } + + vfree(rzs.table); + xv_destroy_pool(rzs.mem_pool); + +#if defined(STATS) + remove_proc_entry("ramzswap", proc->parent); +#endif + pr_debug(C "cleanup done!\n"); +} + +/* + * This param is applicable only when there is no backing swap device. + * We ignore this param in case backing dev is provided since then its + * always equal to size of the backing swap device. + * + * This size refers to amount of (uncompressed) data it can hold. + * For e.g. disksize_kb=1024 means it can hold 1024kb worth of + * uncompressed data even if this data compresses to just, say, 100kb. + * + * Default value is used if this param is missing or 0 (if its applicable). + * Default: [DEFAULT_DISKSIZE_PERC_RAM]% of RAM + */ +module_param(disksize_kb, ulong, 0); +MODULE_PARM_DESC(disksize_kb, "ramzswap device size (kB)"); + +/* + * This param is applicable only when backing swap device is provided. + * This refers to limit on amount of (compressed) data it can hold in + * memory. Note that total amount of memory used (MemUsedTotal) can + * exceed this memlimit since that includes memory wastage due to + * fragmentation and metadata overhead. + * + * Any additional data beyond this limit is forwarded to backing + * swap device. TODO: allow changing memlimit at runtime. + * + * Default value is used if this param is missing or 0 (if its applicable). + * Default: MIN([DEFAULT_MEMLIMIT_PERC_RAM]% of RAM, Backing Device Size) + */ +module_param(memlimit_kb, ulong, 0); +MODULE_PARM_DESC(memlimit_kb, "ramzswap memory limit (kB)"); + +/* + * This is block device to be used as backing store for ramzswap. + * When pages more than memlimit_kb as swapped to ramzswap, we store + * any additional pages in this device. We may also move some pages + * from ramzswap to this device in case system is really low on + * memory (TODO). + * + * This device is not directly visible to kernel as a swap device + * (/proc/swaps will only show /dev/ramzswap0 and not this device). + * Managing this backing device is the job of ramzswap module. + */ +module_param(backing_swap, charp, 0); +MODULE_PARM_DESC(backing_swap, "Backing swap partition"); + +module_init(ramzswap_init); +module_exit(ramzswap_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nitin Gupta "); +MODULE_DESCRIPTION("Compressed RAM Based Swap Device"); --- linux-2.6.37.orig/ubuntu/compcache/ramzswap.h +++ linux-2.6.37/ubuntu/compcache/ramzswap.h @@ -0,0 +1,159 @@ +/* + * Compressed RAM based swap device + * + * Copyright (C) 2008, 2009 Nitin Gupta + * + * This RAM based block device acts as swap disk. + * Pages swapped to this device are compressed and + * stored in memory. + * + * Released under the terms of GNU General Public License Version 2.0 + * + * Project home: http://compcache.googlecode.com + */ + +#ifndef _RAMZSWAP_H_ +#define _RAMZSWAP_H_ + +#include "xvmalloc.h" + +/* + * Stored at beginning of each compressed object. + * + * It stores back-reference to table entry which points to this + * object. This is required to support memory defragmentation or + * migrating compressed pages to backing swap disk. + */ +struct zobj_header { +#if 0 + u32 table_idx; +#endif +}; + +/*-- Configurable parameters */ + +/* Default ramzswap disk size: 25% of total RAM */ +#define DEFAULT_DISKSIZE_PERC_RAM 25 +#define DEFAULT_MEMLIMIT_PERC_RAM 15 + +/* + * Max compressed page size when backing device is provided. + * Pages that compress to size greater than this are sent to + * physical swap disk. + */ +#define MAX_CPAGE_SIZE_BDEV (PAGE_SIZE / 2) + +/* + * Max compressed page size when there is no backing dev. + * Pages that compress to size greater than this are stored + * uncompressed in memory. + */ +#define MAX_CPAGE_SIZE_NOBDEV (PAGE_SIZE / 4 * 3) + +/* + * NOTE: MAX_CPAGE_SIZE_{BDEV,NOBDEV} sizes must be + * less than or equal to: + * XV_MAX_ALLOC_SIZE - sizeof(struct zobj_header) + * since otherwise xvMalloc would always return failure. + */ + +/*-- End of configurable params */ + +#define SECTOR_SHIFT 9 +#define SECTOR_SIZE (1 << SECTOR_SHIFT) +#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT) +#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT) + +/* Message prefix */ +#define C "ramzswap: " + +/* Debugging and Stats */ +#define NOP do { } while (0) + +#if defined(CONFIG_BLK_DEV_RAMZSWAP_STATS) +#define STATS +#endif + +#if defined(STATS) +#define stat_inc(stat) ((stat)++) +#define stat_dec(stat) ((stat)--) +#define stat_inc_if_less(stat, val1, val2) \ + ((stat) += ((val1) < (val2) ? 1 : 0)) +#define stat_dec_if_less(stat, val1, val2) \ + ((stat) -= ((val1) < (val2) ? 1 : 0)) +#else /* STATS */ +#define stat_inc(x) NOP +#define stat_dec(x) NOP +#define stat_inc_if_less(x, v1, v2) NOP +#define stat_dec_if_less(x, v1, v2) NOP +#endif /* STATS */ + +/* Flags for ramzswap pages (table[page_no].flags) */ +enum rzs_pageflags { + /* Page is stored uncompressed */ + RZS_UNCOMPRESSED, + + /* Page consists entirely of zeros */ + RZS_ZERO, + + __NR_RZS_PAGEFLAGS, +}; + +/*-- Data structures */ + +/* Indexed by page no. */ +struct table { + u32 pagenum; + u16 offset; + u8 count; /* object ref count (not yet used) */ + u8 flags; +}; + +struct ramzswap { + struct xv_pool *mem_pool; + void *compress_workmem; + void *compress_buffer; + struct table *table; + struct mutex lock; + struct gendisk *disk; + /* + * This is limit on compressed data size (stats.compr_size) + * Its applicable only when backing swap device is present. + */ + size_t memlimit; /* bytes */ + /* + * This is limit on amount of *uncompressed* worth of data + * we can hold. When backing swap device is provided, it is + * set equal to device size. + */ + size_t disksize; /* bytes */ + + /* backing swap device info */ + struct block_device *backing_swap; + struct file *swap_file; + int old_block_size; +}; + +struct ramzswap_stats { + /* basic stats */ + size_t compr_size; /* compressed size of pages stored - + * needed to enforce memlimit */ + /* more stats */ +#if defined(STATS) + u64 num_reads; /* failed + successful */ + u64 num_writes; /* --do-- */ + u64 failed_reads; /* can happen when memory is too low */ + u64 failed_writes; /* should NEVER! happen */ + u64 invalid_io; /* non-swap I/O requests */ + u64 pages_discard; /* no. of pages freed by discard callback */ + u32 pages_zero; /* no. of zero filled pages */ + u32 pages_stored; /* no. of pages currently stored */ + u32 good_compress; /* no. of pages with compression ratio<=50% */ + u32 pages_expand; /* no. of incompressible pages */ + u64 bdev_num_reads; /* no. of reads on backing dev */ + u64 bdev_num_writes; /* no. of writes on backing dev */ +#endif +}; +/*-- */ + +#endif --- linux-2.6.37.orig/ubuntu/compcache/xvmalloc.c +++ linux-2.6.37/ubuntu/compcache/xvmalloc.c @@ -0,0 +1,557 @@ +/* + * xvmalloc.c + * + * Copyright (C) 2008, 2009 Nitin Gupta + * + * This code is released using a dual license strategy: GPL/LGPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of GNU General Public License Version 2.0 + * Released under the terms of GNU Lesser General Public License Version 2.1 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xvmalloc.h" +#include "xvmalloc_int.h" + +static void stat_inc(u64 *value) +{ + *value = *value + 1; +} + +static void stat_dec(u64 *value) +{ + *value = *value - 1; +} + +static int test_flag(struct block_header *block, enum blockflags flag) +{ + return block->prev & BIT(flag); +} + +static void set_flag(struct block_header *block, enum blockflags flag) +{ + block->prev |= BIT(flag); +} + +static void clear_flag(struct block_header *block, enum blockflags flag) +{ + block->prev &= ~BIT(flag); +} + +/* + * Given pair, provide a derefrencable pointer. + * This is called from xv_malloc/xv_free path, so it needs to be fast. + */ +static void *get_ptr_atomic(u32 pagenum, u16 offset, enum km_type type) +{ + unsigned char *base; + + base = kmap_atomic(pfn_to_page(pagenum), type); + return base + offset; +} + +static void put_ptr_atomic(void *ptr, enum km_type type) +{ + kunmap_atomic(ptr, type); +} + +static u32 get_blockprev(struct block_header *block) +{ + return block->prev & PREV_MASK; +} + +static void set_blockprev(struct block_header *block, u16 new_offset) +{ + block->prev = new_offset | (block->prev & FLAGS_MASK); +} + +static struct block_header *BLOCK_NEXT(struct block_header *block) +{ + return (struct block_header *)((char *)block + block->size + XV_ALIGN); +} + +/* + * Get index of free list containing blocks of maximum size + * which is less than or equal to given size. + */ +static u32 get_index_for_insert(u32 size) +{ + if (unlikely(size > XV_MAX_ALLOC_SIZE)) + size = XV_MAX_ALLOC_SIZE; + size &= ~FL_DELTA_MASK; + return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; +} + +/* + * Get index of free list having blocks of size greater than + * or equal to requested size. + */ +static u32 get_index(u32 size) +{ + if (unlikely(size < XV_MIN_ALLOC_SIZE)) + size = XV_MIN_ALLOC_SIZE; + size = ALIGN(size, FL_DELTA); + return (size - XV_MIN_ALLOC_SIZE) >> FL_DELTA_SHIFT; +} + +/* + * Allocate a memory page. Called when a pool needs to grow. + */ +static u32 xv_alloc_page(gfp_t flags) +{ + struct page *page; + + //page = alloc_page(GFP_NOIO | __GFP_HIGHMEM); + page = alloc_page(flags); + if (unlikely(!page)) + return 0; + + return page_to_pfn(page); +} + +/* + * Called when all objects in a page are freed. + */ +static void xv_free_page(u32 pagenum) +{ + __free_page(pfn_to_page(pagenum)); +} + +/** + * find_block - find block of at least given size + * @pool: memory pool to search from + * @size: size of block required + * @pagenum: page no. containing required block + * @offset: offset within the page where block is located. + * + * Searches two level bitmap to locate block of at least + * the given size. If such a block is found, it provides + * to identify this block and returns index + * in freelist where we found this block. + * Otherwise, returns 0 and params are not touched. + */ +static u32 find_block(struct xv_pool *pool, u32 size, + u32 *pagenum, u32 *offset) +{ + ulong flbitmap, slbitmap; + u32 flindex, slindex, slbitstart; + + /* There are no free blocks in this pool */ + if (!pool->flbitmap) + return 0; + + /* Get freelist index correspoding to this size */ + slindex = get_index(size); + slbitmap = pool->slbitmap[slindex / BITS_PER_LONG]; + slbitstart = slindex % BITS_PER_LONG; + + /* + * If freelist is not empty at this index, we found the + * block - head of this list. This is approximate best-fit match. + */ + if (test_bit(slbitstart, &slbitmap)) { + *pagenum = pool->freelist[slindex].pagenum; + *offset = pool->freelist[slindex].offset; + return slindex; + } + + /* + * No best-fit found. Search a bit further in bitmap for a free block. + * Second level bitmap consists of series of 32-bit chunks. Search + * further in the chunk where we expected a best-fit, starting from + * index location found above. + */ + slbitstart++; + slbitmap >>= slbitstart; + + /* Skip this search if we were already at end of this bitmap chunk */ + if ((slbitstart != BITS_PER_LONG) && slbitmap) { + slindex += __ffs(slbitmap) + 1; + *pagenum = pool->freelist[slindex].pagenum; + *offset = pool->freelist[slindex].offset; + return slindex; + } + + /* Now do a full two-level bitmap search to find next nearest fit */ + flindex = slindex / BITS_PER_LONG; + + flbitmap = (pool->flbitmap) >> (flindex + 1); + if (!flbitmap) + return 0; + + flindex += __ffs(flbitmap) + 1; + slbitmap = pool->slbitmap[flindex]; + slindex = (flindex * BITS_PER_LONG) + __ffs(slbitmap); + *pagenum = pool->freelist[slindex].pagenum; + *offset = pool->freelist[slindex].offset; + + return slindex; +} + +/* + * Insert block at in freelist of given pool. + * freelist used depends on block size. + */ +static void insert_block(struct xv_pool *pool, u32 pagenum, u32 offset, + struct block_header *block) +{ + u32 flindex, slindex; + struct block_header *nextblock; + + slindex = get_index_for_insert(block->size); + flindex = slindex / BITS_PER_LONG; + + block->link.prev_pagenum = 0; + block->link.prev_offset = 0; + block->link.next_pagenum = pool->freelist[slindex].pagenum; + block->link.next_offset = pool->freelist[slindex].offset; + pool->freelist[slindex].pagenum = pagenum; + pool->freelist[slindex].offset = offset; + + if (block->link.next_pagenum) { + nextblock = get_ptr_atomic(block->link.next_pagenum, + block->link.next_offset, KM_USER1); + nextblock->link.prev_pagenum = pagenum; + nextblock->link.prev_offset = offset; + put_ptr_atomic(nextblock, KM_USER1); + } + + __set_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); + __set_bit(flindex, &pool->flbitmap); +} + +/* + * Remove block from head of freelist. Index 'slindex' identifies the freelist. + */ +static void remove_block_head(struct xv_pool *pool, + struct block_header *block, u32 slindex) +{ + struct block_header *tmpblock; + u32 flindex = slindex / BITS_PER_LONG; + + pool->freelist[slindex].pagenum = block->link.next_pagenum; + pool->freelist[slindex].offset = block->link.next_offset; + block->link.prev_pagenum = 0; + block->link.prev_offset = 0; + + if (!pool->freelist[slindex].pagenum) { + __clear_bit(slindex % BITS_PER_LONG, &pool->slbitmap[flindex]); + if (!pool->slbitmap[flindex]) + __clear_bit(flindex, &pool->flbitmap); + } else { + /* + * DEBUG ONLY: We need not reinitialize freelist head previous + * pointer to 0 - we never depend on its value. But just for + * sanity, lets do it. + */ + tmpblock = get_ptr_atomic(pool->freelist[slindex].pagenum, + pool->freelist[slindex].offset, KM_USER1); + tmpblock->link.prev_pagenum = 0; + tmpblock->link.prev_offset = 0; + put_ptr_atomic(tmpblock, KM_USER1); + } +} + +/* + * Remove block from freelist. Index 'slindex' identifies the freelist. + */ +static void remove_block(struct xv_pool *pool, u32 pagenum, u32 offset, + struct block_header *block, u32 slindex) +{ + u32 flindex; + struct block_header *tmpblock; + + if (pool->freelist[slindex].pagenum == pagenum + && pool->freelist[slindex].offset == offset) { + remove_block_head(pool, block, slindex); + return; + } + + flindex = slindex / BITS_PER_LONG; + + if (block->link.prev_pagenum) { + tmpblock = get_ptr_atomic(block->link.prev_pagenum, + block->link.prev_offset, KM_USER1); + tmpblock->link.next_pagenum = block->link.next_pagenum; + tmpblock->link.next_offset = block->link.next_offset; + put_ptr_atomic(tmpblock, KM_USER1); + } + + if (block->link.next_pagenum) { + tmpblock = get_ptr_atomic(block->link.next_pagenum, + block->link.next_offset, KM_USER1); + tmpblock->link.prev_pagenum = block->link.prev_pagenum; + tmpblock->link.prev_offset = block->link.prev_offset; + put_ptr_atomic(tmpblock, KM_USER1); + } + + return; +} + +/* + * Allocate a page and add it freelist of given pool. + */ +static int grow_pool(struct xv_pool *pool, gfp_t flags) +{ + u32 pagenum; + struct block_header *block; + + pagenum = xv_alloc_page(flags); + if (unlikely(!pagenum)) + return -ENOMEM; + + stat_inc(&pool->total_pages); + + spin_lock(&pool->lock); + block = get_ptr_atomic(pagenum, 0, KM_USER0); + + block->size = PAGE_SIZE - XV_ALIGN; + set_flag(block, BLOCK_FREE); + clear_flag(block, PREV_FREE); + set_blockprev(block, 0); + + insert_block(pool, pagenum, 0, block); + + put_ptr_atomic(block, KM_USER0); + spin_unlock(&pool->lock); + + return 0; +} + +/* + * Create a memory pool. Allocates freelist, bitmaps and other + * per-pool metadata. + */ +struct xv_pool *xv_create_pool(void) +{ + u32 ovhd_size; + struct xv_pool *pool; + + ovhd_size = roundup(sizeof(*pool), PAGE_SIZE); + pool = kzalloc(ovhd_size, GFP_KERNEL); + if (!pool) + return NULL; + + spin_lock_init(&pool->lock); + + return pool; +} +EXPORT_SYMBOL_GPL(xv_create_pool); + +void xv_destroy_pool(struct xv_pool *pool) +{ + kfree(pool); +} +EXPORT_SYMBOL_GPL(xv_destroy_pool); + +/** + * xv_malloc - Allocate block of given size from pool. + * @pool: pool to allocate from + * @size: size of block to allocate + * @pagenum: page no. that holds the object + * @offset: location of object within pagenum + * + * On success, identifies block allocated + * and 0 is returned. On failure, is set to + * 0 and -ENOMEM is returned. + * + * Allocation requests with size > XV_MAX_ALLOC_SIZE will fail. + */ +int xv_malloc(struct xv_pool *pool, u32 size, u32 *pagenum, u32 *offset, + gfp_t flags) +{ + int error; + u32 index, tmpsize, origsize, tmpoffset; + struct block_header *block, *tmpblock; + + *pagenum = 0; + *offset = 0; + origsize = size; + + if (unlikely(!size || size > XV_MAX_ALLOC_SIZE)) + return -ENOMEM; + + size = ALIGN(size, XV_ALIGN); + + spin_lock(&pool->lock); + + index = find_block(pool, size, pagenum, offset); + + if (!*pagenum) { + spin_unlock(&pool->lock); + if (flags & GFP_NOWAIT) + return -ENOMEM; + error = grow_pool(pool, flags); + if (unlikely(error)) + return -ENOMEM; + + spin_lock(&pool->lock); + index = find_block(pool, size, pagenum, offset); + } + + if (!*pagenum) { + spin_unlock(&pool->lock); + return -ENOMEM; + } + + block = get_ptr_atomic(*pagenum, *offset, KM_USER0); + + remove_block_head(pool, block, index); + + /* Split the block if required */ + tmpoffset = *offset + size + XV_ALIGN; + tmpsize = block->size - size; + tmpblock = (struct block_header *)((char *)block + size + XV_ALIGN); + if (tmpsize) { + tmpblock->size = tmpsize - XV_ALIGN; + set_flag(tmpblock, BLOCK_FREE); + clear_flag(tmpblock, PREV_FREE); + + set_blockprev(tmpblock, *offset); + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) + insert_block(pool, *pagenum, tmpoffset, tmpblock); + + if (tmpoffset + XV_ALIGN + tmpblock->size != PAGE_SIZE) { + tmpblock = BLOCK_NEXT(tmpblock); + set_blockprev(tmpblock, tmpoffset); + } + } else { + /* This block is exact fit */ + if (tmpoffset != PAGE_SIZE) + clear_flag(tmpblock, PREV_FREE); + } + + block->size = origsize; + clear_flag(block, BLOCK_FREE); + + put_ptr_atomic(block, KM_USER0); + spin_unlock(&pool->lock); + + *offset += XV_ALIGN; + + return 0; +} +EXPORT_SYMBOL_GPL(xv_malloc); + +/* + * Free block identified with + */ +void xv_free(struct xv_pool *pool, u32 pagenum, u32 offset) +{ + void *page; + struct block_header *block, *tmpblock; + + offset -= XV_ALIGN; + + spin_lock(&pool->lock); + + page = get_ptr_atomic(pagenum, 0, KM_USER0); + block = (struct block_header *)((char *)page + offset); + + /* Catch double free bugs */ + BUG_ON(test_flag(block, BLOCK_FREE)); + + block->size = ALIGN(block->size, XV_ALIGN); + + tmpblock = BLOCK_NEXT(block); + if (offset + block->size + XV_ALIGN == PAGE_SIZE) + tmpblock = NULL; + + /* Merge next block if its free */ + if (tmpblock && test_flag(tmpblock, BLOCK_FREE)) { + /* + * Blocks smaller than XV_MIN_ALLOC_SIZE + * are not inserted in any free list. + */ + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) { + remove_block(pool, pagenum, + offset + block->size + XV_ALIGN, tmpblock, + get_index_for_insert(tmpblock->size)); + } + block->size += tmpblock->size + XV_ALIGN; + } + + /* Merge previous block if its free */ + if (test_flag(block, PREV_FREE)) { + tmpblock = (struct block_header *)((char *)(page) + + get_blockprev(block)); + offset = offset - tmpblock->size - XV_ALIGN; + + if (tmpblock->size >= XV_MIN_ALLOC_SIZE) + remove_block(pool, pagenum, offset, tmpblock, + get_index_for_insert(tmpblock->size)); + + tmpblock->size += block->size + XV_ALIGN; + block = tmpblock; + } + + /* No used objects in this page. Free it. */ + if (block->size == PAGE_SIZE - XV_ALIGN) { + put_ptr_atomic(page, KM_USER0); + spin_unlock(&pool->lock); + + xv_free_page(pagenum); + stat_dec(&pool->total_pages); + return; + } + + set_flag(block, BLOCK_FREE); + if (block->size >= XV_MIN_ALLOC_SIZE) + insert_block(pool, pagenum, offset, block); + + if (offset + block->size + XV_ALIGN != PAGE_SIZE) { + tmpblock = BLOCK_NEXT(block); + set_flag(tmpblock, PREV_FREE); + set_blockprev(tmpblock, offset); + } + + put_ptr_atomic(page, KM_USER0); + spin_unlock(&pool->lock); + + return; +} +EXPORT_SYMBOL_GPL(xv_free); + +u32 xv_get_object_size(void *obj) +{ + struct block_header *blk; + + blk = (struct block_header *)((char *)(obj) - XV_ALIGN); + return blk->size; +} +EXPORT_SYMBOL_GPL(xv_get_object_size); + +/* + * Returns total memory used by allocator (userdata + metadata) + */ +u64 xv_get_total_size_bytes(struct xv_pool *pool) +{ + return pool->total_pages << PAGE_SHIFT; +} +EXPORT_SYMBOL_GPL(xv_get_total_size_bytes); + +static int __init xv_malloc_init(void) +{ + return 0; +} + +static void __exit xv_malloc_exit(void) +{ + return; +} + +module_init(xv_malloc_init); +module_exit(xv_malloc_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nitin Gupta "); +MODULE_DESCRIPTION("xvmalloc memory allocator"); --- linux-2.6.37.orig/ubuntu/compcache/xvmalloc.h +++ linux-2.6.37/ubuntu/compcache/xvmalloc.h @@ -0,0 +1,30 @@ +/* + * xvmalloc.h + * + * Copyright (C) 2008, 2009 Nitin Gupta + * + * This code is released using a dual license strategy: GPL/LGPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of GNU General Public License Version 2.0 + * Released under the terms of GNU Lesser General Public License Version 2.1 + */ + +#ifndef _XVMALLOC_H_ +#define _XVMALLOC_H_ + +#include + +struct xv_pool; + +struct xv_pool *xv_create_pool(void); +void xv_destroy_pool(struct xv_pool *pool); + +int xv_malloc(struct xv_pool *pool, u32 size, u32 *pagenum, u32 *offset, + gfp_t flags); +void xv_free(struct xv_pool *pool, u32 pagenum, u32 offset); + +u32 xv_get_object_size(void *obj); +u64 xv_get_total_size_bytes(struct xv_pool *pool); + +#endif --- linux-2.6.37.orig/ubuntu/compcache/xvmalloc_int.h +++ linux-2.6.37/ubuntu/compcache/xvmalloc_int.h @@ -0,0 +1,86 @@ +/* + * xvmalloc_int.c + * + * Copyright (C) 2008, 2009 Nitin Gupta + * + * This code is released using a dual license strategy: GPL/LGPL + * You can choose the licence that better fits your requirements. + * + * Released under the terms of GNU General Public License Version 2.0 + * Released under the terms of GNU Lesser General Public License Version 2.1 + */ + +#ifndef _XVMALLOC_INT_H_ +#define _XVMALLOC_INT_H_ + +#include +#include + +/* User configurable params */ + +/* This must be greater than sizeof(LinkFree) */ +#define XV_MIN_ALLOC_SIZE 32 +#define XV_MAX_ALLOC_SIZE (PAGE_SIZE - XV_ALIGN) + +/* Must be power of two */ +#define XV_ALIGN_SHIFT 2 +#define XV_ALIGN (1 << XV_ALIGN_SHIFT) +#define XV_ALIGN_MASK (XV_ALIGN - 1) + +/* Free lists are separated by FL_DELTA bytes */ +#define FL_DELTA_SHIFT 3 +#define FL_DELTA (1 << FL_DELTA_SHIFT) +#define FL_DELTA_MASK (FL_DELTA - 1) +#define NUM_FREE_LISTS ((XV_MAX_ALLOC_SIZE - XV_MIN_ALLOC_SIZE) \ + / FL_DELTA + 1) + +#define MAX_FLI DIV_ROUND_UP(NUM_FREE_LISTS, BITS_PER_LONG) + +/* End of user params */ + +enum blockflags { + BLOCK_FREE, + PREV_FREE, + __NR_BLOCKFLAGS, +}; + +#define FLAGS_MASK XV_ALIGN_MASK +#define PREV_MASK (~FLAGS_MASK) + +struct freelist_entry { + u32 pagenum; + u16 offset; + u16 pad; +}; + +struct link_free { + u32 prev_pagenum; + u32 next_pagenum; + u16 prev_offset; + u16 next_offset; +}; + +struct block_header { + union { + /* This common header must be ALIGN bytes */ + u8 common[XV_ALIGN]; + struct { + u16 size; + u16 prev; + }; + }; + struct link_free link; +}; + +struct xv_pool { + ulong flbitmap; + ulong slbitmap[MAX_FLI]; + spinlock_t lock; + + struct freelist_entry freelist[NUM_FREE_LISTS]; + + /* stats */ + u64 total_pages; +}; + +#endif --- linux-2.6.37.orig/ubuntu/dm-raid4-5/BOM +++ linux-2.6.37/ubuntu/dm-raid4-5/BOM @@ -0,0 +1,3 @@ +Downloaded from: http://people.redhat.com/~heinzm/sw/dm/dm-raid45/ +Current Version: 2009.04.24 (2.6.30-rc3) +Comments: All of the patches to dmraid1/dm-log, etc are upstream. --- linux-2.6.37.orig/ubuntu/dm-raid4-5/Kconfig +++ linux-2.6.37/ubuntu/dm-raid4-5/Kconfig @@ -0,0 +1,6 @@ +config DM_RAID45 + tristate "RAID 4/5 target (EXPERIMENTAL)" + depends on BLK_DEV_DM && XOR_BLOCKS && EXPERIMENTAL + default m + ---help--- + A target that supports RAID4 and RAID5 mappings. --- linux-2.6.37.orig/ubuntu/dm-raid4-5/Makefile +++ linux-2.6.37/ubuntu/dm-raid4-5/Makefile @@ -0,0 +1,4 @@ +EXTRA_CFLAGS += -I$(srctree)/drivers/md + +obj-$(CONFIG_DM_RAID45) := dm-raid45.o +dm-raid45-objs := dm-raid4-5.o dm-memcache.o dm-region-hash.o dm-message.o --- linux-2.6.37.orig/ubuntu/dm-raid4-5/dm-memcache.c +++ linux-2.6.37/ubuntu/dm-raid4-5/dm-memcache.c @@ -0,0 +1,302 @@ +/* + * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. + * + * Module Author: Heinz Mauelshagen + * + * Device-mapper memory object handling: + * + * o allocate/free total_pages in a per client page pool. + * + * o allocate/free memory objects with chunks (1..n) of + * pages_per_chunk pages hanging off. + * + * This file is released under the GPL. + */ + +#define DM_MEM_CACHE_VERSION "0.2" + +#include "dm.h" +#include "dm-memcache.h" +#include +#include + +struct dm_mem_cache_client { + spinlock_t lock; + mempool_t *objs_pool; + struct page_list *free_list; + unsigned objects; + unsigned chunks; + unsigned pages_per_chunk; + unsigned free_pages; + unsigned total_pages; +}; + +/* + * Free pages and page_list elements of client. + */ +static void free_cache_pages(struct page_list *list) +{ + while (list) { + struct page_list *pl = list; + + list = pl->next; + BUG_ON(!pl->page); + __free_page(pl->page); + kfree(pl); + } +} + +/* + * Alloc number of pages and page_list elements as required by client. + */ +static struct page_list *alloc_cache_pages(unsigned pages) +{ + struct page_list *pl, *ret = NULL; + struct page *page; + + while (pages--) { + page = alloc_page(GFP_NOIO); + if (!page) + goto err; + + pl = kmalloc(sizeof(*pl), GFP_NOIO); + if (!pl) { + __free_page(page); + goto err; + } + + pl->page = page; + pl->next = ret; + ret = pl; + } + + return ret; + +err: + free_cache_pages(ret); + return NULL; +} + +/* + * Allocate page_list elements from the pool to chunks of the memory object. + */ +static void alloc_chunks(struct dm_mem_cache_client *cl, + struct dm_mem_cache_object *obj) +{ + unsigned chunks = cl->chunks; + unsigned long flags; + + local_irq_save(flags); + local_irq_disable(); + while (chunks--) { + unsigned p = cl->pages_per_chunk; + + obj[chunks].pl = NULL; + + while (p--) { + struct page_list *pl; + + /* Take next element from free list */ + spin_lock(&cl->lock); + pl = cl->free_list; + BUG_ON(!pl); + cl->free_list = pl->next; + spin_unlock(&cl->lock); + + pl->next = obj[chunks].pl; + obj[chunks].pl = pl; + } + } + + local_irq_restore(flags); +} + +/* + * Free page_list elements putting them back onto free list + */ +static void free_chunks(struct dm_mem_cache_client *cl, + struct dm_mem_cache_object *obj) +{ + unsigned chunks = cl->chunks; + unsigned long flags; + struct page_list *next, *pl; + + local_irq_save(flags); + local_irq_disable(); + while (chunks--) { + for (pl = obj[chunks].pl; pl; pl = next) { + next = pl->next; + + spin_lock(&cl->lock); + pl->next = cl->free_list; + cl->free_list = pl; + cl->free_pages++; + spin_unlock(&cl->lock); + } + } + + local_irq_restore(flags); +} + +/* + * Create/destroy dm memory cache client resources. + */ +struct dm_mem_cache_client * +dm_mem_cache_client_create(unsigned objects, unsigned chunks, + unsigned pages_per_chunk) +{ + unsigned total_pages = objects * chunks * pages_per_chunk; + struct dm_mem_cache_client *client; + + BUG_ON(!total_pages); + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return ERR_PTR(-ENOMEM); + + client->objs_pool = mempool_create_kmalloc_pool(objects, + chunks * sizeof(struct dm_mem_cache_object)); + if (!client->objs_pool) + goto err; + + client->free_list = alloc_cache_pages(total_pages); + if (!client->free_list) + goto err1; + + spin_lock_init(&client->lock); + client->objects = objects; + client->chunks = chunks; + client->pages_per_chunk = pages_per_chunk; + client->free_pages = client->total_pages = total_pages; + return client; + +err1: + mempool_destroy(client->objs_pool); +err: + kfree(client); + return ERR_PTR(-ENOMEM); +} +EXPORT_SYMBOL(dm_mem_cache_client_create); + +void dm_mem_cache_client_destroy(struct dm_mem_cache_client *cl) +{ + BUG_ON(cl->free_pages != cl->total_pages); + free_cache_pages(cl->free_list); + mempool_destroy(cl->objs_pool); + kfree(cl); +} +EXPORT_SYMBOL(dm_mem_cache_client_destroy); + +/* + * Grow a clients cache by an amount of pages. + * + * Don't call from interrupt context! + */ +int dm_mem_cache_grow(struct dm_mem_cache_client *cl, unsigned objects) +{ + unsigned pages = objects * cl->chunks * cl->pages_per_chunk; + struct page_list *pl, *last; + + BUG_ON(!pages); + pl = alloc_cache_pages(pages); + if (!pl) + return -ENOMEM; + + last = pl; + while (last->next) + last = last->next; + + spin_lock_irq(&cl->lock); + last->next = cl->free_list; + cl->free_list = pl; + cl->free_pages += pages; + cl->total_pages += pages; + cl->objects++; + spin_unlock_irq(&cl->lock); + + mempool_resize(cl->objs_pool, cl->objects, GFP_NOIO); + return 0; +} +EXPORT_SYMBOL(dm_mem_cache_grow); + +/* Shrink a clients cache by an amount of pages */ +int dm_mem_cache_shrink(struct dm_mem_cache_client *cl, unsigned objects) +{ + int r; + unsigned pages = objects * cl->chunks * cl->pages_per_chunk, p = pages; + unsigned long flags; + struct page_list *last = NULL, *pl, *pos; + + BUG_ON(!pages); + + spin_lock_irqsave(&cl->lock, flags); + pl = pos = cl->free_list; + while (p-- && pos->next) { + last = pos; + pos = pos->next; + } + + if (++p) + r = -ENOMEM; + else { + r = 0; + cl->free_list = pos; + cl->free_pages -= pages; + cl->total_pages -= pages; + cl->objects--; + last->next = NULL; + } + spin_unlock_irqrestore(&cl->lock, flags); + + if (!r) { + free_cache_pages(pl); + mempool_resize(cl->objs_pool, cl->objects, GFP_NOIO); + } + + return r; +} +EXPORT_SYMBOL(dm_mem_cache_shrink); + +/* + * Allocate/free a memory object + * + * Can be called from interrupt context + */ +struct dm_mem_cache_object *dm_mem_cache_alloc(struct dm_mem_cache_client *cl) +{ + int r = 0; + unsigned pages = cl->chunks * cl->pages_per_chunk; + unsigned long flags; + struct dm_mem_cache_object *obj; + + obj = mempool_alloc(cl->objs_pool, GFP_NOIO); + if (!obj) + return ERR_PTR(-ENOMEM); + + spin_lock_irqsave(&cl->lock, flags); + if (pages > cl->free_pages) + r = -ENOMEM; + else + cl->free_pages -= pages; + spin_unlock_irqrestore(&cl->lock, flags); + + if (r) { + mempool_free(obj, cl->objs_pool); + return ERR_PTR(r); + } + + alloc_chunks(cl, obj); + return obj; +} +EXPORT_SYMBOL(dm_mem_cache_alloc); + +void dm_mem_cache_free(struct dm_mem_cache_client *cl, + struct dm_mem_cache_object *obj) +{ + free_chunks(cl, obj); + mempool_free(obj, cl->objs_pool); +} +EXPORT_SYMBOL(dm_mem_cache_free); + +MODULE_DESCRIPTION(DM_NAME " dm memory cache"); +MODULE_AUTHOR("Heinz Mauelshagen "); +MODULE_LICENSE("GPL"); --- linux-2.6.37.orig/ubuntu/dm-raid4-5/dm-memcache.h +++ linux-2.6.37/ubuntu/dm-raid4-5/dm-memcache.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. + * + * Module Author: Heinz Mauelshagen + * + * Device-mapper memory object handling: + * + * o allocate/free total_pages in a per client page pool. + * + * o allocate/free memory objects with chunks (1..n) of + * pages_per_chunk pages hanging off. + * + * This file is released under the GPL. + */ + +#ifndef _DM_MEM_CACHE_H +#define _DM_MEM_CACHE_H + +#define DM_MEM_CACHE_H_VERSION "0.1" + +#include "dm.h" +#include + +static inline struct page_list *pl_elem(struct page_list *pl, unsigned p) +{ + while (pl && p--) + pl = pl->next; + + return pl; +} + +struct dm_mem_cache_object { + struct page_list *pl; /* Dynamically allocated array */ + void *private; /* Caller context reference */ +}; + +struct dm_mem_cache_client; + +/* + * Create/destroy dm memory cache client resources. + * + * On creation, a number of @objects with @chunks of + * @pages_per_chunk pages will be allocated. + */ +struct dm_mem_cache_client * +dm_mem_cache_client_create(unsigned objects, unsigned chunks, + unsigned pages_per_chunk); +void dm_mem_cache_client_destroy(struct dm_mem_cache_client *client); + +/* + * Grow/shrink a dm memory cache client resources + * by @objetcs amount of objects. + */ +int dm_mem_cache_grow(struct dm_mem_cache_client *client, unsigned objects); +int dm_mem_cache_shrink(struct dm_mem_cache_client *client, unsigned objects); + +/* + * Allocate/free a memory object + * + * On allocation one object with an amount of chunks and + * an amount of pages per chunk will be returned on success. + */ +struct dm_mem_cache_object * +dm_mem_cache_alloc(struct dm_mem_cache_client *client); +void dm_mem_cache_free(struct dm_mem_cache_client *client, + struct dm_mem_cache_object *object); + +#endif --- linux-2.6.37.orig/ubuntu/dm-raid4-5/dm-message.c +++ linux-2.6.37/ubuntu/dm-raid4-5/dm-message.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2007,2008 Red Hat Inc. All rights reserved. + * + * Module Author: Heinz Mauelshagen + * + * General device-mapper message interface argument parser. + * + * This file is released under the GPL. + * + * device-mapper message parser. + * + */ + +#include "dm.h" +#include "dm-message.h" +#include + +#define DM_MSG_PREFIX "dm_message" + +/* Basename of a path. */ +static inline char * +basename(char *s) +{ + char *p = strrchr(s, '/'); + + return p ? p + 1 : s; +} + +/* Get an argument depending on type. */ +static void +message_arguments(struct dm_msg *msg, int argc, char **argv) +{ + + if (argc) { + int i; + struct dm_message_argument *args = msg->spec->args; + + for (i = 0; i < args->num_args; i++) { + int r; + unsigned long **ptr = args->ptr; + enum dm_message_argument_type type = args->types[i]; + + switch (type) { + case dm_msg_base_t: + ((char **) ptr)[i] = basename(argv[i]); + break; + + case dm_msg_str_t: + ((char **) ptr)[i] = argv[i]; + break; + + case dm_msg_int_t: + r = sscanf(argv[i], "%d", ((int **) ptr)[i]); + goto check; + + case dm_msg_uint_t: + r = sscanf(argv[i], "%u", + ((unsigned **) ptr)[i]); + goto check; + + case dm_msg_uint64_t: + r = sscanf(argv[i], "%llu", + ((unsigned long long **) ptr)[i]); + +check: + if (r != 1) { + set_bit(dm_msg_ret_undef, &msg->ret); + set_bit(dm_msg_ret_arg, &msg->ret); + } + } + } + } +} + +/* Parse message options. */ +static void +message_options_parse(struct dm_msg *msg, int argc, char **argv) +{ + int hit = 0; + unsigned long *action; + size_t l1 = strlen(*argv), l_hit = 0; + struct dm_message_option *o = msg->spec->options; + char **option, **option_end = o->options + o->num_options; + + for (option = o->options, action = o->actions; + option < option_end; option++, action++) { + size_t l2 = strlen(*option); + + if (!strnicmp(*argv, *option, min(l1, l2))) { + hit++; + l_hit = l2; + set_bit(*action, &msg->action); + } + } + + /* Assume error. */ + msg->ret = 0; + set_bit(dm_msg_ret_option, &msg->ret); + if (!hit || l1 > l_hit) + set_bit(dm_msg_ret_undef, &msg->ret); /* Undefined option. */ + else if (hit > 1) + set_bit(dm_msg_ret_ambiguous, &msg->ret); /* Ambiguous option.*/ + else { + clear_bit(dm_msg_ret_option, &msg->ret); /* Option OK. */ + message_arguments(msg, --argc, ++argv); + } +} + +static inline void +print_ret(const char *caller, unsigned long ret) +{ + struct { + unsigned long err; + const char *err_str; + } static err_msg[] = { + { dm_msg_ret_ambiguous, "message ambiguous" }, + { dm_msg_ret_inval, "message invalid" }, + { dm_msg_ret_undef, "message undefined" }, + { dm_msg_ret_arg, "message argument" }, + { dm_msg_ret_argcount, "message argument count" }, + { dm_msg_ret_option, "option" }, + }, *e = ARRAY_END(err_msg); + + while (e-- > err_msg) { + if (test_bit(e->err, &ret)) + DMERR("%s %s", caller, e->err_str); + } +} + +/* Parse a message action. */ +int +dm_message_parse(const char *caller, struct dm_msg *msg, void *context, + int argc, char **argv) +{ + int hit = 0; + size_t l1, l_hit = 0; + struct dm_msg_spec *s, *s_hit = NULL, + *s_end = msg->specs + msg->num_specs; + + if (argc < 2) + return -EINVAL; + + l1 = strlen(*argv); + for (s = msg->specs; s < s_end; s++) { + size_t l2 = strlen(s->cmd); + + if (!strnicmp(*argv, s->cmd, min(l1, l2))) { + hit++; + l_hit = l2; + s_hit = s; + } + } + + msg->ret = 0; + if (!hit || l1 > l_hit) /* No hit or message string too long. */ + set_bit(dm_msg_ret_undef, &msg->ret); + else if (hit > 1) /* Ambiguous message. */ + set_bit(dm_msg_ret_ambiguous, &msg->ret); + else if (argc - 2 != s_hit->args->num_args) { + set_bit(dm_msg_ret_undef, &msg->ret); + set_bit(dm_msg_ret_argcount, &msg->ret); + } + + if (msg->ret) + goto bad; + + msg->action = 0; + msg->spec = s_hit; + set_bit(s_hit->action, &msg->action); + message_options_parse(msg, --argc, ++argv); + + if (!msg->ret) + return msg->spec->f(msg, context); + +bad: + print_ret(caller, msg->ret); + return -EINVAL; +} +EXPORT_SYMBOL(dm_message_parse); + +MODULE_DESCRIPTION(DM_NAME " device-mapper target message parser"); +MODULE_AUTHOR("Heinz Mauelshagen "); +MODULE_LICENSE("GPL"); --- linux-2.6.37.orig/ubuntu/dm-raid4-5/dm-message.h +++ linux-2.6.37/ubuntu/dm-raid4-5/dm-message.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2007,2008 Red Hat, Inc. All rights reserved. + * + * Module Author: Heinz Mauelshagen + * + * General device-mapper message interface argument parser. + * + * This file is released under the GPL. + * + */ + +#ifndef DM_MESSAGE_H +#define DM_MESSAGE_H + +/* Factor out to dm.h. */ +/* Reference to array end. */ +#define ARRAY_END(a) ((a) + ARRAY_SIZE(a)) + +/* Message return bits. */ +enum dm_message_return { + dm_msg_ret_ambiguous, /* Action ambiguous. */ + dm_msg_ret_inval, /* Action invalid. */ + dm_msg_ret_undef, /* Action undefined. */ + + dm_msg_ret_option, /* Option error. */ + dm_msg_ret_arg, /* Argument error. */ + dm_msg_ret_argcount, /* Argument count error. */ +}; + +/* Message argument type conversions. */ +enum dm_message_argument_type { + dm_msg_base_t, /* Basename string. */ + dm_msg_str_t, /* String. */ + dm_msg_int_t, /* Signed int. */ + dm_msg_uint_t, /* Unsigned int. */ + dm_msg_uint64_t, /* Unsigned int 64. */ +}; + +/* A message option. */ +struct dm_message_option { + unsigned num_options; + char **options; + unsigned long *actions; +}; + +/* Message arguments and types. */ +struct dm_message_argument { + unsigned num_args; + unsigned long **ptr; + enum dm_message_argument_type types[]; +}; + +/* Client message. */ +struct dm_msg { + unsigned long action; /* Identified action. */ + unsigned long ret; /* Return bits. */ + unsigned num_specs; /* # of sepcifications listed. */ + struct dm_msg_spec *specs; /* Specification list. */ + struct dm_msg_spec *spec; /* Specification selected. */ +}; + +/* Secification of the message. */ +struct dm_msg_spec { + const char *cmd; /* Name of the command (i.e. 'bandwidth'). */ + unsigned long action; + struct dm_message_option *options; + struct dm_message_argument *args; + unsigned long parm; /* Parameter to pass through to callback. */ + /* Function to process for action. */ + int (*f) (struct dm_msg *msg, void *context); +}; + +/* Parameter access macros. */ +#define DM_MSG_PARM(msg) ((msg)->spec->parm) + +#define DM_MSG_STR_ARGS(msg, idx) ((char *) *(msg)->spec->args->ptr[idx]) +#define DM_MSG_INT_ARGS(msg, idx) ((int) *(msg)->spec->args->ptr[idx]) +#define DM_MSG_UINT_ARGS(msg, idx) ((unsigned) DM_MSG_INT_ARG(msg, idx)) +#define DM_MSG_UINT64_ARGS(msg, idx) ((uint64_t) *(msg)->spec->args->ptr[idx]) + +#define DM_MSG_STR_ARG(msg) DM_MSG_STR_ARGS(msg, 0) +#define DM_MSG_INT_ARG(msg) DM_MSG_INT_ARGS(msg, 0) +#define DM_MSG_UINT_ARG(msg) DM_MSG_UINT_ARGS(msg, 0) +#define DM_MSG_UINT64_ARG(msg) DM_MSG_UINT64_ARGS(msg, 0) + + +/* Parse a message and its options and optionally call a function back. */ +int dm_message_parse(const char *caller, struct dm_msg *msg, void *context, + int argc, char **argv); + +#endif --- linux-2.6.37.orig/ubuntu/dm-raid4-5/dm-raid4-5.c +++ linux-2.6.37/ubuntu/dm-raid4-5/dm-raid4-5.c @@ -0,0 +1,4546 @@ +/*[A[A + * Copyright (C) 2005-2009 Red Hat, Inc. All rights reserved. + * + * Module Author: Heinz Mauelshagen + * + * This file is released under the GPL. + * + * + * Linux 2.6 Device Mapper RAID4 and RAID5 target. + * + * Supports: + * o RAID4 with dedicated and selectable parity device + * o RAID5 with rotating parity (left+right, symmetric+asymmetric) + * o recovery of out of sync device for initial + * RAID set creation or after dead drive replacement + * o run time optimization of xor algorithm used to calculate parity + * + * + * Thanks to MD for: + * o the raid address calculation algorithm + * o the base of the biovec <-> page list copier. + * + * + * Uses region hash to keep track of how many writes are in flight to + * regions in order to use dirty log to keep state of regions to recover: + * + * o clean regions (those which are synchronized + * and don't have write io in flight) + * o dirty regions (those with write io in flight) + * + * + * On startup, any dirty regions are migrated to the + * 'nosync' state and are subject to recovery by the daemon. + * + * See raid_ctr() for table definition. + * + * FIXME: recovery bandwidth + */ + +static const char *version = "v0.2594b"; + +#include "dm.h" +#include "dm-memcache.h" +#include "dm-message.h" +#include "dm-raid45.h" + +#include +#include +#include + +#include +#include +#include +#include "dm-region-hash.h" + +#include + +/* + * Configurable parameters + */ + +/* Minimum/maximum and default # of selectable stripes. */ +#define STRIPES_MIN 8 +#define STRIPES_MAX 16384 +#define STRIPES_DEFAULT 80 + +/* Maximum and default chunk size in sectors if not set in constructor. */ +#define CHUNK_SIZE_MIN 8 +#define CHUNK_SIZE_MAX 16384 +#define CHUNK_SIZE_DEFAULT 64 + +/* Default io size in sectors if not set in constructor. */ +#define IO_SIZE_MIN CHUNK_SIZE_MIN +#define IO_SIZE_DEFAULT IO_SIZE_MIN + +/* Recover io size default in sectors. */ +#define RECOVER_IO_SIZE_MIN 64 +#define RECOVER_IO_SIZE_DEFAULT 256 + +/* Default, minimum and maximum percentage of recover io bandwidth. */ +#define BANDWIDTH_DEFAULT 10 +#define BANDWIDTH_MIN 1 +#define BANDWIDTH_MAX 100 + +/* # of parallel recovered regions */ +#define RECOVERY_STRIPES_MIN 1 +#define RECOVERY_STRIPES_MAX 64 +#define RECOVERY_STRIPES_DEFAULT RECOVERY_STRIPES_MIN +/* + * END Configurable parameters + */ + +#define TARGET "dm-raid45" +#define DAEMON "kraid45d" +#define DM_MSG_PREFIX TARGET + +#define SECTORS_PER_PAGE (PAGE_SIZE >> SECTOR_SHIFT) + +/* Amount/size for __xor(). */ +#define XOR_SIZE PAGE_SIZE + +/* Check value in range. */ +#define range_ok(i, min, max) (i >= min && i <= max) + +/* Check argument is power of 2. */ +#define POWER_OF_2(a) (!(a & (a - 1))) + +/* Structure access macros. */ +/* Derive raid_set from stripe_cache pointer. */ +#define RS(x) container_of(x, struct raid_set, sc) + +/* Page reference. */ +#define PAGE(stripe, p) ((stripe)->obj[p].pl->page) + +/* Stripe chunk reference. */ +#define CHUNK(stripe, p) ((stripe)->chunk + p) + +/* Bio list reference. */ +#define BL(stripe, p, rw) (stripe->chunk[p].bl + rw) +#define BL_CHUNK(chunk, rw) (chunk->bl + rw) + +/* Page list reference. */ +#define PL(stripe, p) (stripe->obj[p].pl) +/* END: structure access macros. */ + +/* Factor out to dm-bio-list.h */ +static inline void bio_list_push(struct bio_list *bl, struct bio *bio) +{ + bio->bi_next = bl->head; + bl->head = bio; + + if (!bl->tail) + bl->tail = bio; +} + +/* Factor out to dm.h */ +#define TI_ERR_RET(str, ret) \ + do { ti->error = str; return ret; } while (0); +#define TI_ERR(str) TI_ERR_RET(str, -EINVAL) + +/* Macro to define access IO flags access inline functions. */ +#define BITOPS(name, what, var, flag) \ +static inline int TestClear ## name ## what(struct var *v) \ +{ return test_and_clear_bit(flag, &v->io.flags); } \ +static inline int TestSet ## name ## what(struct var *v) \ +{ return test_and_set_bit(flag, &v->io.flags); } \ +static inline void Clear ## name ## what(struct var *v) \ +{ clear_bit(flag, &v->io.flags); } \ +static inline void Set ## name ## what(struct var *v) \ +{ set_bit(flag, &v->io.flags); } \ +static inline int name ## what(struct var *v) \ +{ return test_bit(flag, &v->io.flags); } + +/*----------------------------------------------------------------- + * Stripe cache + * + * Cache for all reads and writes to raid sets (operational or degraded) + * + * We need to run all data to and from a RAID set through this cache, + * because parity chunks need to get calculated from data chunks + * or, in the degraded/resynchronization case, missing chunks need + * to be reconstructed using the other chunks of the stripe. + *---------------------------------------------------------------*/ +/* A chunk within a stripe (holds bios hanging off). */ +/* IO status flags for chunks of a stripe. */ +enum chunk_flags { + CHUNK_DIRTY, /* Pages of chunk dirty; need writing. */ + CHUNK_ERROR, /* IO error on any chunk page. */ + CHUNK_IO, /* Allow/prohibit IO on chunk pages. */ + CHUNK_LOCKED, /* Chunk pages locked during IO. */ + CHUNK_MUST_IO, /* Chunk must io. */ + CHUNK_UNLOCK, /* Enforce chunk unlock. */ + CHUNK_UPTODATE, /* Chunk pages are uptodate. */ +}; + +#if READ != 0 || WRITE != 1 +#error dm-raid45: READ/WRITE != 0/1 used as index!!! +#endif + +enum bl_type { + WRITE_QUEUED = WRITE + 1, + WRITE_MERGED, + NR_BL_TYPES, /* Must be last one! */ +}; +struct stripe_chunk { + atomic_t cnt; /* Reference count. */ + struct stripe *stripe; /* Backpointer to stripe for endio(). */ + /* Bio lists for reads, writes, and writes merged. */ + struct bio_list bl[NR_BL_TYPES]; + struct { + unsigned long flags; /* IO status flags. */ + } io; +}; + +/* Define chunk bit operations. */ +BITOPS(Chunk, Dirty, stripe_chunk, CHUNK_DIRTY) +BITOPS(Chunk, Error, stripe_chunk, CHUNK_ERROR) +BITOPS(Chunk, Io, stripe_chunk, CHUNK_IO) +BITOPS(Chunk, Locked, stripe_chunk, CHUNK_LOCKED) +BITOPS(Chunk, MustIo, stripe_chunk, CHUNK_MUST_IO) +BITOPS(Chunk, Unlock, stripe_chunk, CHUNK_UNLOCK) +BITOPS(Chunk, Uptodate, stripe_chunk, CHUNK_UPTODATE) + +/* + * Stripe linked list indexes. Keep order, because the stripe + * and the stripe cache rely on the first 3! + */ +enum list_types { + LIST_FLUSH, /* Stripes to flush for io. */ + LIST_ENDIO, /* Stripes to endio. */ + LIST_LRU, /* Least recently used stripes. */ + SC_NR_LISTS, /* # of lists in stripe cache. */ + LIST_HASH = SC_NR_LISTS, /* Hashed stripes. */ + LIST_RECOVER = LIST_HASH, /* For recovery type stripes only. */ + STRIPE_NR_LISTS,/* To size array in struct stripe. */ +}; + +/* Adressing region recovery. */ +struct recover_addr { + struct dm_region *reg; /* Actual region to recover. */ + sector_t pos; /* Position within region to recover. */ + sector_t end; /* End of region to recover. */ +}; + +/* A stripe: the io object to handle all reads and writes to a RAID set. */ +struct stripe { + atomic_t cnt; /* Reference count. */ + struct stripe_cache *sc; /* Backpointer to stripe cache. */ + + /* + * 4 linked lists: + * o io list to flush io + * o endio list + * o LRU list to put stripes w/o reference count on + * o stripe cache hash + */ + struct list_head lists[STRIPE_NR_LISTS]; + + sector_t key; /* Hash key. */ + region_t region; /* Region stripe is mapped to. */ + + struct { + unsigned long flags; /* Stripe state flags (see below). */ + + /* + * Pending ios in flight: + * + * used to control move of stripe to endio list + */ + atomic_t pending; + + /* Sectors to read and write for multi page stripe sets. */ + unsigned size; + } io; + + /* Address region recovery. */ + struct recover_addr *recover; + + /* Lock on stripe (Future: for clustering). */ + void *lock; + + struct { + unsigned short parity; /* Parity chunk index. */ + short recover; /* Recovery chunk index. */ + } idx; + + /* + * This stripe's memory cache object (dm-mem-cache); + * i.e. the io chunk pages. + */ + struct dm_mem_cache_object *obj; + + /* Array of stripe sets (dynamically allocated). */ + struct stripe_chunk chunk[0]; +}; + +/* States stripes can be in (flags field). */ +enum stripe_states { + STRIPE_ERROR, /* io error on stripe. */ + STRIPE_MERGED, /* Writes got merged to be written. */ + STRIPE_RBW, /* Read-before-write stripe. */ + STRIPE_RECONSTRUCT, /* Reconstruct of a missing chunk required. */ + STRIPE_RECONSTRUCTED, /* Reconstructed of a missing chunk. */ + STRIPE_RECOVER, /* Stripe used for RAID set recovery. */ +}; + +/* Define stripe bit operations. */ +BITOPS(Stripe, Error, stripe, STRIPE_ERROR) +BITOPS(Stripe, Merged, stripe, STRIPE_MERGED) +BITOPS(Stripe, RBW, stripe, STRIPE_RBW) +BITOPS(Stripe, Reconstruct, stripe, STRIPE_RECONSTRUCT) +BITOPS(Stripe, Reconstructed, stripe, STRIPE_RECONSTRUCTED) +BITOPS(Stripe, Recover, stripe, STRIPE_RECOVER) + +/* A stripe hash. */ +struct stripe_hash { + struct list_head *hash; + unsigned buckets; + unsigned mask; + unsigned prime; + unsigned shift; +}; + +enum sc_lock_types { + LOCK_ENDIO, /* Protect endio list. */ + LOCK_LRU, /* Protect LRU list. */ + NR_LOCKS, /* To size array in struct stripe_cache. */ +}; + +/* A stripe cache. */ +struct stripe_cache { + /* Stripe hash. */ + struct stripe_hash hash; + + spinlock_t locks[NR_LOCKS]; /* Locks to protect lists. */ + + /* Stripes with io to flush, stripes to endio and LRU lists. */ + struct list_head lists[SC_NR_LISTS]; + + /* Slab cache to allocate stripes from. */ + struct { + struct kmem_cache *cache; /* Cache itself. */ + char name[32]; /* Unique name. */ + } kc; + + struct dm_io_client *dm_io_client; /* dm-io client resource context. */ + + /* dm-mem-cache client resource context. */ + struct dm_mem_cache_client *mem_cache_client; + + int stripes_parm; /* # stripes parameter from constructor. */ + atomic_t stripes; /* actual # of stripes in cache. */ + atomic_t stripes_to_set; /* # of stripes to resize cache to. */ + atomic_t stripes_last; /* last # of stripes in cache. */ + atomic_t active_stripes; /* actual # of active stripes in cache. */ + + /* REMOVEME: */ + atomic_t active_stripes_max; /* actual # of active stripes in cache. */ +}; + +/* Flag specs for raid_dev */ ; +enum raid_dev_flags { + DEV_FAILED, /* Device failed. */ + DEV_IO_QUEUED, /* Io got queued to device. */ +}; + +/* The raid device in a set. */ +struct raid_dev { + struct dm_dev *dev; + sector_t start; /* Offset to map to. */ + struct { /* Using struct to be able to BITOPS(). */ + unsigned long flags; /* raid_dev_flags. */ + } io; +}; + +BITOPS(Dev, Failed, raid_dev, DEV_FAILED) +BITOPS(Dev, IoQueued, raid_dev, DEV_IO_QUEUED) + +/* Flags spec for raid_set. */ +enum raid_set_flags { + RS_CHECK_OVERWRITE, /* Check for chunk overwrites. */ + RS_DEAD, /* RAID set inoperational. */ + RS_DEGRADED, /* Io errors on RAID device. */ + RS_DEVEL_STATS, /* REMOVEME: display status information. */ + RS_RECOVER, /* Do recovery. */ + RS_RECOVERY_BANDWIDTH, /* Allow recovery bandwidth (delayed bios). */ + RS_SC_BUSY, /* Stripe cache busy -> send an event. */ + RS_SUSPEND, /* Suspend RAID set. */ +}; + +/* REMOVEME: devel stats counters. */ +enum stats_types { + S_BIOS_READ, + S_BIOS_ADDED_READ, + S_BIOS_ENDIO_READ, + S_BIOS_WRITE, + S_BIOS_ADDED_WRITE, + S_BIOS_ENDIO_WRITE, + S_CAN_MERGE, + S_CANT_MERGE, + S_CONGESTED, + S_DM_IO_READ, + S_DM_IO_WRITE, + S_BANDWIDTH, + S_BARRIER, + S_BIO_COPY_PL_NEXT, + S_DEGRADED, + S_DELAYED_BIOS, + S_FLUSHS, + S_HITS_1ST, + S_IOS_POST, + S_INSCACHE, + S_MAX_LOOKUP, + S_CHUNK_LOCKED, + S_NO_BANDWIDTH, + S_NOT_CONGESTED, + S_NO_RW, + S_NOSYNC, + S_OVERWRITE, + S_PROHIBITCHUNKIO, + S_RECONSTRUCT_EI, + S_RECONSTRUCT_DEV, + S_RECONSTRUCT_SET, + S_RECONSTRUCTED, + S_REQUEUE, + S_STRIPE_ERROR, + S_SUM_DELAYED_BIOS, + S_XORS, + S_NR_STATS, /* # of stats counters. Must be last! */ +}; + +/* Status type -> string mappings. */ +struct stats_map { + const enum stats_types type; + const char *str; +}; + +static struct stats_map stats_map[] = { + { S_BIOS_READ, "r=" }, + { S_BIOS_ADDED_READ, "/" }, + { S_BIOS_ENDIO_READ, "/" }, + { S_BIOS_WRITE, " w=" }, + { S_BIOS_ADDED_WRITE, "/" }, + { S_BIOS_ENDIO_WRITE, "/" }, + { S_DM_IO_READ, " rc=" }, + { S_DM_IO_WRITE, " wc=" }, + { S_BANDWIDTH, "\nbw=" }, + { S_NO_BANDWIDTH, " no_bw=" }, + { S_BARRIER, "\nbarrier=" }, + { S_BIO_COPY_PL_NEXT, "\nbio_cp_next=" }, + { S_CAN_MERGE, "\nmerge=" }, + { S_CANT_MERGE, "/no_merge=" }, + { S_CHUNK_LOCKED, "\nchunk_locked=" }, + { S_CONGESTED, "\ncgst=" }, + { S_NOT_CONGESTED, "/not_cgst=" }, + { S_DEGRADED, "\ndegraded=" }, + { S_DELAYED_BIOS, "\ndel_bios=" }, + { S_SUM_DELAYED_BIOS, "/sum_del_bios=" }, + { S_FLUSHS, "\nflushs=" }, + { S_HITS_1ST, "\nhits_1st=" }, + { S_IOS_POST, " ios_post=" }, + { S_INSCACHE, " inscache=" }, + { S_MAX_LOOKUP, " maxlookup=" }, + { S_NO_RW, "\nno_rw=" }, + { S_NOSYNC, " nosync=" }, + { S_OVERWRITE, " ovr=" }, + { S_PROHIBITCHUNKIO, " prhbt_io=" }, + { S_RECONSTRUCT_EI, "\nrec_ei=" }, + { S_RECONSTRUCT_DEV, " rec_dev=" }, + { S_RECONSTRUCT_SET, " rec_set=" }, + { S_RECONSTRUCTED, " rec=" }, + { S_REQUEUE, " requeue=" }, + { S_STRIPE_ERROR, " stripe_err=" }, + { S_XORS, " xors=" }, +}; + +/* + * A RAID set. + */ +#define dm_rh_client dm_region_hash +enum count_type { IO_WORK = 0, IO_RECOVER, IO_NR_COUNT }; +typedef void (*xor_function_t)(unsigned count, unsigned long **data); +struct raid_set { + struct dm_target *ti; /* Target pointer. */ + + struct { + unsigned long flags; /* State flags. */ + struct mutex in_lock; /* Protects central input list below. */ + struct bio_list in; /* Pending ios (central input list). */ + struct bio_list work; /* ios work set. */ + wait_queue_head_t suspendq; /* suspend synchronization. */ + atomic_t in_process; /* counter of queued bios (suspendq). */ + atomic_t in_process_max;/* counter of queued bios max. */ + + /* io work. */ + struct workqueue_struct *wq; + struct delayed_work dws_do_raid; /* For main worker. */ + struct work_struct ws_do_table_event; /* For event worker. */ + } io; + + /* Stripe locking abstraction. */ + struct dm_raid45_locking_type *locking; + + struct stripe_cache sc; /* Stripe cache for this set. */ + + /* Xor optimization. */ + struct { + struct xor_func *f; + unsigned chunks; + unsigned speed; + } xor; + + /* Recovery parameters. */ + struct recover { + struct dm_dirty_log *dl; /* Dirty log. */ + struct dm_rh_client *rh; /* Region hash. */ + + struct dm_io_client *dm_io_client; /* recovery dm-io client. */ + /* dm-mem-cache client resource context for recovery stripes. */ + struct dm_mem_cache_client *mem_cache_client; + + struct list_head stripes; /* List of recovery stripes. */ + + region_t nr_regions; + region_t nr_regions_to_recover; + region_t nr_regions_recovered; + unsigned long start_jiffies; + unsigned long end_jiffies; + + unsigned bandwidth; /* Recovery bandwidth [%]. */ + unsigned bandwidth_work; /* Recovery bandwidth [factor]. */ + unsigned bandwidth_parm; /* " constructor parm. */ + unsigned io_size; /* recovery io size <= region size. */ + unsigned io_size_parm; /* recovery io size ctr parameter. */ + unsigned recovery; /* Recovery allowed/prohibited. */ + unsigned recovery_stripes; /* # of parallel recovery stripes. */ + + /* recovery io throttling. */ + atomic_t io_count[IO_NR_COUNT]; /* counter recover/regular io.*/ + unsigned long last_jiffies; + } recover; + + /* RAID set parameters. */ + struct { + struct raid_type *raid_type; /* RAID type (eg, RAID4). */ + unsigned raid_parms; /* # variable raid parameters. */ + + unsigned chunk_size; /* Sectors per chunk. */ + unsigned chunk_size_parm; + unsigned chunk_shift; /* rsector chunk size shift. */ + + unsigned io_size; /* Sectors per io. */ + unsigned io_size_parm; + unsigned io_mask; /* Mask for bio_copy_page_list(). */ + unsigned io_inv_mask; /* Mask for raid_address(). */ + + sector_t sectors_per_dev; /* Sectors per device. */ + + atomic_t failed_devs; /* Amount of devices failed. */ + + /* Index of device to initialize. */ + int dev_to_init; + int dev_to_init_parm; + + /* Raid devices dynamically allocated. */ + unsigned raid_devs; /* # of RAID devices below. */ + unsigned data_devs; /* # of RAID data devices. */ + + int ei; /* index of failed RAID device. */ + + /* Index of dedicated parity device (i.e. RAID4). */ + int pi; + int pi_parm; /* constructor parm for status output. */ + } set; + + /* REMOVEME: devel stats counters. */ + atomic_t stats[S_NR_STATS]; + + /* Dynamically allocated temporary pointers for xor(). */ + unsigned long **data; + + /* Dynamically allocated RAID devices. Alignment? */ + struct raid_dev dev[0]; +}; + +/* Define RAID set bit operations. */ +BITOPS(RS, Bandwidth, raid_set, RS_RECOVERY_BANDWIDTH) +BITOPS(RS, CheckOverwrite, raid_set, RS_CHECK_OVERWRITE) +BITOPS(RS, Dead, raid_set, RS_DEAD) +BITOPS(RS, Degraded, raid_set, RS_DEGRADED) +BITOPS(RS, DevelStats, raid_set, RS_DEVEL_STATS) +BITOPS(RS, Recover, raid_set, RS_RECOVER) +BITOPS(RS, ScBusy, raid_set, RS_SC_BUSY) +BITOPS(RS, Suspend, raid_set, RS_SUSPEND) +#undef BITOPS + +/*----------------------------------------------------------------- + * Raid-4/5 set structures. + *---------------------------------------------------------------*/ +/* RAID level definitions. */ +enum raid_level { + raid4, + raid5, +}; + +/* Symmetric/Asymmetric, Left/Right parity rotating algorithms. */ +enum raid_algorithm { + none, + left_asym, + right_asym, + left_sym, + right_sym, +}; + +struct raid_type { + const char *name; /* RAID algorithm. */ + const char *descr; /* Descriptor text for logging. */ + const unsigned parity_devs; /* # of parity devices. */ + const unsigned minimal_devs; /* minimal # of devices in set. */ + const enum raid_level level; /* RAID level. */ + const enum raid_algorithm algorithm; /* RAID algorithm. */ +}; + +/* Supported raid types and properties. */ +static struct raid_type raid_types[] = { + {"raid4", "RAID4 (dedicated parity disk)", 1, 3, raid4, none}, + {"raid5_la", "RAID5 (left asymmetric)", 1, 3, raid5, left_asym}, + {"raid5_ra", "RAID5 (right asymmetric)", 1, 3, raid5, right_asym}, + {"raid5_ls", "RAID5 (left symmetric)", 1, 3, raid5, left_sym}, + {"raid5_rs", "RAID5 (right symmetric)", 1, 3, raid5, right_sym}, +}; + +/* Address as calculated by raid_address(). */ +struct raid_address { + sector_t key; /* Hash key (address of stripe % chunk_size). */ + unsigned di, pi; /* Data and parity disks index. */ +}; + +/* REMOVEME: reset statistics counters. */ +static void stats_reset(struct raid_set *rs) +{ + unsigned s = S_NR_STATS; + + while (s--) + atomic_set(rs->stats + s, 0); +} + +/*---------------------------------------------------------------- + * RAID set management routines. + *--------------------------------------------------------------*/ +/* + * Begin small helper functions. + */ +/* No need to be called from region hash indirectly at dm_rh_dec(). */ +static void wake_dummy(void *context) {} + +/* Return # of io reference. */ +static int io_ref(struct raid_set *rs) +{ + return atomic_read(&rs->io.in_process); +} + +/* Get an io reference. */ +static void io_get(struct raid_set *rs) +{ + int p = atomic_inc_return(&rs->io.in_process); + + if (p > atomic_read(&rs->io.in_process_max)) + atomic_set(&rs->io.in_process_max, p); /* REMOVEME: max. */ +} + +/* Put the io reference and conditionally wake io waiters. */ +static void io_put(struct raid_set *rs) +{ + /* Intel: rebuild data corrupter? */ + if (atomic_dec_and_test(&rs->io.in_process)) + wake_up(&rs->io.suspendq); + else + BUG_ON(io_ref(rs) < 0); +} + +/* Wait until all io has been processed. */ +static void wait_ios(struct raid_set *rs) +{ + wait_event(rs->io.suspendq, !io_ref(rs)); +} + +/* Queue (optionally delayed) io work. */ +static void wake_do_raid_delayed(struct raid_set *rs, unsigned long delay) +{ + queue_delayed_work(rs->io.wq, &rs->io.dws_do_raid, delay); +} + +/* Queue io work immediately (called from region hash too). */ +static void wake_do_raid(void *context) +{ + struct raid_set *rs = context; + + queue_work(rs->io.wq, &rs->io.dws_do_raid.work); +} + +/* Calculate device sector offset. */ +static sector_t _sector(struct raid_set *rs, struct bio *bio) +{ + sector_t sector = bio->bi_sector; + + sector_div(sector, rs->set.data_devs); + return sector; +} + +/* Return # of active stripes in stripe cache. */ +static int sc_active(struct stripe_cache *sc) +{ + return atomic_read(&sc->active_stripes); +} + +/* Stripe cache busy indicator. */ +static int sc_busy(struct raid_set *rs) +{ + return sc_active(&rs->sc) > + atomic_read(&rs->sc.stripes) - (STRIPES_MIN / 2); +} + +/* Set chunks states. */ +enum chunk_dirty_type { CLEAN, DIRTY, ERROR }; +static void chunk_set(struct stripe_chunk *chunk, enum chunk_dirty_type type) +{ + switch (type) { + case CLEAN: + ClearChunkDirty(chunk); + break; + case DIRTY: + SetChunkDirty(chunk); + break; + case ERROR: + SetChunkError(chunk); + SetStripeError(chunk->stripe); + return; + default: + BUG(); + } + + SetChunkUptodate(chunk); + SetChunkIo(chunk); + ClearChunkError(chunk); +} + +/* Return region state for a sector. */ +static int region_state(struct raid_set *rs, sector_t sector, + enum dm_rh_region_states state) +{ + struct dm_rh_client *rh = rs->recover.rh; + region_t region = dm_rh_sector_to_region(rh, sector); + + return !!(dm_rh_get_state(rh, region, 1) & state); +} + +/* + * Return true in case a chunk should be read/written + * + * Conditions to read/write: + * o chunk not uptodate + * o chunk dirty + * + * Conditios to avoid io: + * o io already ongoing on chunk + * o io explitely prohibited + */ +static int chunk_io(struct stripe_chunk *chunk) +{ + /* 2nd run optimization (flag set below on first run). */ + if (TestClearChunkMustIo(chunk)) + return 1; + + /* Avoid io if prohibited or a locked chunk. */ + if (!ChunkIo(chunk) || ChunkLocked(chunk)) + return 0; + + if (!ChunkUptodate(chunk) || ChunkDirty(chunk)) { + SetChunkMustIo(chunk); /* 2nd run optimization. */ + return 1; + } + + return 0; +} + +/* Call a function on each chunk needing io unless device failed. */ +static unsigned for_each_io_dev(struct stripe *stripe, + void (*f_io)(struct stripe *stripe, unsigned p)) +{ + struct raid_set *rs = RS(stripe->sc); + unsigned p, r = 0; + + for (p = 0; p < rs->set.raid_devs; p++) { + if (chunk_io(CHUNK(stripe, p)) && !DevFailed(rs->dev + p)) { + f_io(stripe, p); + r++; + } + } + + return r; +} + +/* + * Index of device to calculate parity on. + * + * Either the parity device index *or* the selected + * device to init after a spare replacement. + */ +static int dev_for_parity(struct stripe *stripe, int *sync) +{ + struct raid_set *rs = RS(stripe->sc); + int r = region_state(rs, stripe->key, DM_RH_NOSYNC | DM_RH_RECOVERING); + + *sync = !r; + + /* Reconstruct a particular device ?. */ + if (r && rs->set.dev_to_init > -1) + return rs->set.dev_to_init; + else if (rs->set.raid_type->level == raid4) + return rs->set.pi; + else if (!StripeRecover(stripe)) + return stripe->idx.parity; + else + return -1; +} + +/* RAID set congested function. */ +static int rs_congested(void *congested_data, int bdi_bits) +{ + int r; + unsigned p; + struct raid_set *rs = congested_data; + + if (sc_busy(rs) || RSSuspend(rs)) + r = 1; + else for (r = 0, p = rs->set.raid_devs; !r && p--; ) { + /* If any of our component devices are overloaded. */ + struct request_queue *q = bdev_get_queue(rs->dev[p].dev->bdev); + + r |= bdi_congested(&q->backing_dev_info, bdi_bits); + } + + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + (r ? S_CONGESTED : S_NOT_CONGESTED)); + return r; +} + +/* RAID device degrade check. */ +static void rs_check_degrade_dev(struct raid_set *rs, + struct stripe *stripe, unsigned p) +{ + if (TestSetDevFailed(rs->dev + p)) + return; + + /* Through an event in case of member device errors. */ + if (atomic_inc_return(&rs->set.failed_devs) > + rs->set.raid_type->parity_devs && + !TestSetRSDead(rs)) { + /* Display RAID set dead message once. */ + unsigned p; + char buf[BDEVNAME_SIZE]; + + DMERR("FATAL: too many devices failed -> RAID set broken"); + for (p = 0; p < rs->set.raid_devs; p++) { + if (DevFailed(rs->dev + p)) + DMERR("device /dev/%s failed", + bdevname(rs->dev[p].dev->bdev, buf)); + } + } + + /* Only log the first member error. */ + if (!TestSetRSDegraded(rs)) { + char buf[BDEVNAME_SIZE]; + + /* Store index for recovery. */ + rs->set.ei = p; + DMERR("CRITICAL: %sio error on device /dev/%s " + "in region=%llu; DEGRADING RAID set\n", + stripe ? "" : "FAKED ", + bdevname(rs->dev[p].dev->bdev, buf), + (unsigned long long) (stripe ? stripe->key : 0)); + DMERR("further device error messages suppressed"); + } + + schedule_work(&rs->io.ws_do_table_event); +} + +/* RAID set degrade check. */ +static void rs_check_degrade(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + unsigned p = rs->set.raid_devs; + + while (p--) { + if (ChunkError(CHUNK(stripe, p))) + rs_check_degrade_dev(rs, stripe, p); + } +} + +/* Lookup a RAID device by name or by major:minor number. */ +static int raid_dev_lookup(struct raid_set *rs, struct raid_dev *dev_lookup) +{ + unsigned p; + struct raid_dev *dev; + + /* + * Must be an incremental loop, because the device array + * can have empty slots still on calls from raid_ctr() + */ + for (dev = rs->dev, p = 0; + dev->dev && p < rs->set.raid_devs; + dev++, p++) { + if (dev_lookup->dev->bdev->bd_dev == dev->dev->bdev->bd_dev) + return p; + } + + return -ENODEV; +} +/* + * End small helper functions. + */ + +/* + * Stripe hash functions + */ +/* Initialize/destroy stripe hash. */ +static int hash_init(struct stripe_hash *hash, unsigned stripes) +{ + unsigned buckets = 2, max_buckets = stripes >> 1; + static unsigned hash_primes[] = { + /* Table of primes for hash_fn/table size optimization. */ + 1, 2, 3, 7, 13, 27, 53, 97, 193, 389, 769, + 1543, 3079, 6151, 12289, 24593, 49157, 98317, + }; + + /* Calculate number of buckets (2^^n <= stripes / 2). */ + while (buckets < max_buckets) + buckets <<= 1; + + /* Allocate stripe hash buckets. */ + hash->hash = vmalloc(buckets * sizeof(*hash->hash)); + if (!hash->hash) + return -ENOMEM; + + hash->buckets = buckets; + hash->mask = buckets - 1; + hash->shift = ffs(buckets); + if (hash->shift > ARRAY_SIZE(hash_primes)) + hash->shift = ARRAY_SIZE(hash_primes) - 1; + + BUG_ON(hash->shift < 2); + hash->prime = hash_primes[hash->shift]; + + /* Initialize buckets. */ + while (buckets--) + INIT_LIST_HEAD(hash->hash + buckets); + return 0; +} + +static void hash_exit(struct stripe_hash *hash) +{ + if (hash->hash) { + vfree(hash->hash); + hash->hash = NULL; + } +} + +static unsigned hash_fn(struct stripe_hash *hash, sector_t key) +{ + return (unsigned) (((key * hash->prime) >> hash->shift) & hash->mask); +} + +static struct list_head *hash_bucket(struct stripe_hash *hash, sector_t key) +{ + return hash->hash + hash_fn(hash, key); +} + +/* Insert an entry into a hash. */ +static void stripe_insert(struct stripe_hash *hash, struct stripe *stripe) +{ + list_add(stripe->lists + LIST_HASH, hash_bucket(hash, stripe->key)); +} + +/* Lookup an entry in the stripe hash. */ +static struct stripe *stripe_lookup(struct stripe_cache *sc, sector_t key) +{ + unsigned look = 0; + struct stripe *stripe; + struct list_head *bucket = hash_bucket(&sc->hash, key); + + list_for_each_entry(stripe, bucket, lists[LIST_HASH]) { + look++; + + if (stripe->key == key) { + /* REMOVEME: statisics. */ + if (look > atomic_read(RS(sc)->stats + S_MAX_LOOKUP)) + atomic_set(RS(sc)->stats + S_MAX_LOOKUP, look); + return stripe; + } + } + + return NULL; +} + +/* Resize the stripe cache hash on size changes. */ +static int sc_hash_resize(struct stripe_cache *sc) +{ + /* Resize indicated ? */ + if (atomic_read(&sc->stripes) != atomic_read(&sc->stripes_last)) { + int r; + struct stripe_hash hash; + + r = hash_init(&hash, atomic_read(&sc->stripes)); + if (r) + return r; + + if (sc->hash.hash) { + unsigned b = sc->hash.buckets; + struct list_head *pos, *tmp; + + /* Walk old buckets and insert into new. */ + while (b--) { + list_for_each_safe(pos, tmp, sc->hash.hash + b) + stripe_insert(&hash, + list_entry(pos, struct stripe, + lists[LIST_HASH])); + } + + } + + hash_exit(&sc->hash); + memcpy(&sc->hash, &hash, sizeof(sc->hash)); + atomic_set(&sc->stripes_last, atomic_read(&sc->stripes)); + } + + return 0; +} +/* End hash stripe hash function. */ + +/* List add, delete, push and pop functions. */ +/* Add stripe to flush list. */ +#define DEL_LIST(lh) \ + if (!list_empty(lh)) \ + list_del_init(lh); + +/* Delete stripe from hash. */ +static void stripe_hash_del(struct stripe *stripe) +{ + DEL_LIST(stripe->lists + LIST_HASH); +} + +/* Return stripe reference count. */ +static inline int stripe_ref(struct stripe *stripe) +{ + return atomic_read(&stripe->cnt); +} + +static void stripe_flush_add(struct stripe *stripe) +{ + struct stripe_cache *sc = stripe->sc; + struct list_head *lh = stripe->lists + LIST_FLUSH; + + if (!StripeReconstruct(stripe) && list_empty(lh)) + list_add_tail(lh, sc->lists + LIST_FLUSH); +} + +/* + * Add stripe to LRU (inactive) list. + * + * Need lock, because of concurrent access from message interface. + */ +static void stripe_lru_add(struct stripe *stripe) +{ + if (!StripeRecover(stripe)) { + unsigned long flags; + struct list_head *lh = stripe->lists + LIST_LRU; + spinlock_t *lock = stripe->sc->locks + LOCK_LRU; + + spin_lock_irqsave(lock, flags); + if (list_empty(lh)) + list_add_tail(lh, stripe->sc->lists + LIST_LRU); + spin_unlock_irqrestore(lock, flags); + } +} + +#define POP_LIST(list) \ + do { \ + if (list_empty(sc->lists + (list))) \ + stripe = NULL; \ + else { \ + stripe = list_first_entry(sc->lists + (list), \ + struct stripe, \ + lists[(list)]); \ + list_del_init(stripe->lists + (list)); \ + } \ + } while (0); + +/* Pop an available stripe off the LRU list. */ +static struct stripe *stripe_lru_pop(struct stripe_cache *sc) +{ + struct stripe *stripe; + spinlock_t *lock = sc->locks + LOCK_LRU; + + spin_lock_irq(lock); + POP_LIST(LIST_LRU); + spin_unlock_irq(lock); + + return stripe; +} + +/* Pop an available stripe off the io list. */ +static struct stripe *stripe_io_pop(struct stripe_cache *sc) +{ + struct stripe *stripe; + + POP_LIST(LIST_FLUSH); + return stripe; +} + +/* Push a stripe safely onto the endio list to be handled by do_endios(). */ +static void stripe_endio_push(struct stripe *stripe) +{ + unsigned long flags; + struct stripe_cache *sc = stripe->sc; + struct list_head *stripe_list = stripe->lists + LIST_ENDIO, + *sc_list = sc->lists + LIST_ENDIO; + spinlock_t *lock = sc->locks + LOCK_ENDIO; + + /* This runs in parallel with do_endios(). */ + spin_lock_irqsave(lock, flags); + if (list_empty(stripe_list)) + list_add_tail(stripe_list, sc_list); + spin_unlock_irqrestore(lock, flags); + + wake_do_raid(RS(sc)); /* Wake myself. */ +} + +/* Pop a stripe off safely off the endio list. */ +static struct stripe *stripe_endio_pop(struct stripe_cache *sc) +{ + struct stripe *stripe; + spinlock_t *lock = sc->locks + LOCK_ENDIO; + + /* This runs in parallel with endio(). */ + spin_lock_irq(lock); + POP_LIST(LIST_ENDIO) + spin_unlock_irq(lock); + return stripe; +} +#undef POP_LIST + +/* + * Stripe cache locking functions + */ +/* Dummy lock function for single host RAID4+5. */ +static void *no_lock(sector_t key, enum dm_lock_type type) +{ + return &no_lock; +} + +/* Dummy unlock function for single host RAID4+5. */ +static void no_unlock(void *lock_handle) +{ +} + +/* No locking (for single host RAID 4+5). */ +static struct dm_raid45_locking_type locking_none = { + .lock = no_lock, + .unlock = no_unlock, +}; + +/* Lock a stripe (for clustering). */ +static int +stripe_lock(struct stripe *stripe, int rw, sector_t key) +{ + stripe->lock = RS(stripe->sc)->locking->lock(key, rw == READ ? DM_RAID45_SHARED : DM_RAID45_EX); + return stripe->lock ? 0 : -EPERM; +} + +/* Unlock a stripe (for clustering). */ +static void stripe_unlock(struct stripe *stripe) +{ + RS(stripe->sc)->locking->unlock(stripe->lock); + stripe->lock = NULL; +} + +/* Test io pending on stripe. */ +static int stripe_io_ref(struct stripe *stripe) +{ + return atomic_read(&stripe->io.pending); +} + +static void stripe_io_get(struct stripe *stripe) +{ + if (atomic_inc_return(&stripe->io.pending) == 1) + /* REMOVEME: statistics */ + atomic_inc(&stripe->sc->active_stripes); + else + BUG_ON(stripe_io_ref(stripe) < 0); +} + +static void stripe_io_put(struct stripe *stripe) +{ + if (atomic_dec_and_test(&stripe->io.pending)) { + if (unlikely(StripeRecover(stripe))) + /* Don't put recovery stripe on endio list. */ + wake_do_raid(RS(stripe->sc)); + else + /* Add regular stripe to endio list and wake daemon. */ + stripe_endio_push(stripe); + + /* REMOVEME: statistics */ + atomic_dec(&stripe->sc->active_stripes); + } else + BUG_ON(stripe_io_ref(stripe) < 0); +} + +/* Take stripe reference out. */ +static int stripe_get(struct stripe *stripe) +{ + int r; + struct list_head *lh = stripe->lists + LIST_LRU; + spinlock_t *lock = stripe->sc->locks + LOCK_LRU; + + /* Delete stripe from LRU (inactive) list if on. */ + spin_lock_irq(lock); + DEL_LIST(lh); + spin_unlock_irq(lock); + + BUG_ON(stripe_ref(stripe) < 0); + + /* Lock stripe on first reference */ + r = (atomic_inc_return(&stripe->cnt) == 1) ? + stripe_lock(stripe, WRITE, stripe->key) : 0; + + return r; +} +#undef DEL_LIST + +/* Return references on a chunk. */ +static int chunk_ref(struct stripe_chunk *chunk) +{ + return atomic_read(&chunk->cnt); +} + +/* Take out reference on a chunk. */ +static int chunk_get(struct stripe_chunk *chunk) +{ + return atomic_inc_return(&chunk->cnt); +} + +/* Drop reference on a chunk. */ +static void chunk_put(struct stripe_chunk *chunk) +{ + BUG_ON(atomic_dec_return(&chunk->cnt) < 0); +} + +/* + * Drop reference on a stripe. + * + * Move it to list of LRU stripes if zero. + */ +static void stripe_put(struct stripe *stripe) +{ + if (atomic_dec_and_test(&stripe->cnt)) { + BUG_ON(stripe_io_ref(stripe)); + stripe_unlock(stripe); + } else + BUG_ON(stripe_ref(stripe) < 0); +} + +/* Helper needed by for_each_io_dev(). */ +static void stripe_get_references(struct stripe *stripe, unsigned p) +{ + + /* + * Another one to reference the stripe in + * order to protect vs. LRU list moves. + */ + io_get(RS(stripe->sc)); /* Global io references. */ + stripe_get(stripe); + stripe_io_get(stripe); /* One for each chunk io. */ +} + +/* Helper for endio() to put all take references. */ +static void stripe_put_references(struct stripe *stripe) +{ + stripe_io_put(stripe); /* One for each chunk io. */ + stripe_put(stripe); + io_put(RS(stripe->sc)); +} + +/* + * Stripe cache functions. + */ +/* + * Invalidate all chunks (i.e. their pages) of a stripe. + * + * I only keep state for the whole chunk. + */ +static inline void stripe_chunk_invalidate(struct stripe_chunk *chunk) +{ + chunk->io.flags = 0; +} + +static void +stripe_chunks_invalidate(struct stripe *stripe) +{ + unsigned p = RS(stripe->sc)->set.raid_devs; + + while (p--) + stripe_chunk_invalidate(CHUNK(stripe, p)); +} + +/* Prepare stripe for (re)use. */ +static void stripe_invalidate(struct stripe *stripe) +{ + stripe->io.flags = 0; + stripe->idx.parity = stripe->idx.recover = -1; + stripe_chunks_invalidate(stripe); +} + +/* + * Allow io on all chunks of a stripe. + * If not set, IO will not occur; i.e. it's prohibited. + * + * Actual IO submission for allowed chunks depends + * on their !uptodate or dirty state. + */ +static void stripe_allow_io(struct stripe *stripe) +{ + unsigned p = RS(stripe->sc)->set.raid_devs; + + while (p--) + SetChunkIo(CHUNK(stripe, p)); +} + +/* Initialize a stripe. */ +static void stripe_init(struct stripe_cache *sc, struct stripe *stripe) +{ + unsigned i, p = RS(sc)->set.raid_devs; + + /* Work all io chunks. */ + while (p--) { + struct stripe_chunk *chunk = CHUNK(stripe, p); + + atomic_set(&chunk->cnt, 0); + chunk->stripe = stripe; + i = ARRAY_SIZE(chunk->bl); + while (i--) + bio_list_init(chunk->bl + i); + } + + stripe->sc = sc; + + + i = ARRAY_SIZE(stripe->lists); + while (i--) + INIT_LIST_HEAD(stripe->lists + i); + + stripe->io.size = RS(sc)->set.io_size; + atomic_set(&stripe->cnt, 0); + atomic_set(&stripe->io.pending, 0); + stripe_invalidate(stripe); +} + +/* Number of pages per chunk. */ +static inline unsigned chunk_pages(unsigned sectors) +{ + return dm_div_up(sectors, SECTORS_PER_PAGE); +} + +/* Number of pages per stripe. */ +static inline unsigned stripe_pages(struct raid_set *rs, unsigned io_size) +{ + return chunk_pages(io_size) * rs->set.raid_devs; +} + +/* Initialize part of page_list (recovery). */ +static void stripe_zero_pl_part(struct stripe *stripe, int p, + unsigned start, unsigned count) +{ + unsigned o = start / SECTORS_PER_PAGE, pages = chunk_pages(count); + /* Get offset into the page_list. */ + struct page_list *pl = pl_elem(PL(stripe, p), o); + + BUG_ON(!pl); + while (pl && pages--) { + BUG_ON(!pl->page); + memset(page_address(pl->page), 0, PAGE_SIZE); + pl = pl->next; + } +} + +/* Initialize parity chunk of stripe. */ +static void stripe_zero_chunk(struct stripe *stripe, int p) +{ + if (p > -1) + stripe_zero_pl_part(stripe, p, 0, stripe->io.size); +} + +/* Return dynamic stripe structure size. */ +static size_t stripe_size(struct raid_set *rs) +{ + return sizeof(struct stripe) + + rs->set.raid_devs * sizeof(struct stripe_chunk); +} + +/* Allocate a stripe and its memory object. */ +/* XXX adjust to cope with stripe cache and recovery stripe caches. */ +enum grow { SC_GROW, SC_KEEP }; +static struct stripe *stripe_alloc(struct stripe_cache *sc, + struct dm_mem_cache_client *mc, + enum grow grow) +{ + int r; + struct stripe *stripe; + + stripe = kmem_cache_zalloc(sc->kc.cache, GFP_KERNEL); + if (stripe) { + /* Grow the dm-mem-cache by one object. */ + if (grow == SC_GROW) { + r = dm_mem_cache_grow(mc, 1); + if (r) + goto err_free; + } + + stripe->obj = dm_mem_cache_alloc(mc); + if (!stripe->obj) + goto err_shrink; + + stripe_init(sc, stripe); + } + + return stripe; + +err_shrink: + if (grow == SC_GROW) + dm_mem_cache_shrink(mc, 1); +err_free: + kmem_cache_free(sc->kc.cache, stripe); + return NULL; +} + +/* + * Free a stripes memory object, shrink the + * memory cache and free the stripe itself. + */ +static void stripe_free(struct stripe *stripe, struct dm_mem_cache_client *mc) +{ + dm_mem_cache_free(mc, stripe->obj); + dm_mem_cache_shrink(mc, 1); + kmem_cache_free(stripe->sc->kc.cache, stripe); +} + +/* Free the recovery stripe. */ +static void stripe_recover_free(struct raid_set *rs) +{ + struct recover *rec = &rs->recover; + struct dm_mem_cache_client *mc; + + mc = rec->mem_cache_client; + rec->mem_cache_client = NULL; + if (mc) { + struct stripe *stripe; + + while (!list_empty(&rec->stripes)) { + stripe = list_first_entry(&rec->stripes, struct stripe, + lists[LIST_RECOVER]); + list_del(stripe->lists + LIST_RECOVER); + kfree(stripe->recover); + stripe_free(stripe, mc); + } + + dm_mem_cache_client_destroy(mc); + dm_io_client_destroy(rec->dm_io_client); + rec->dm_io_client = NULL; + } +} + +/* Grow stripe cache. */ +static int sc_grow(struct stripe_cache *sc, unsigned stripes, enum grow grow) +{ + int r = 0; + + /* Try to allocate this many (additional) stripes. */ + while (stripes--) { + struct stripe *stripe = + stripe_alloc(sc, sc->mem_cache_client, grow); + + if (likely(stripe)) { + stripe_lru_add(stripe); + atomic_inc(&sc->stripes); + } else { + r = -ENOMEM; + break; + } + } + + return r ? r : sc_hash_resize(sc); +} + +/* Shrink stripe cache. */ +static int sc_shrink(struct stripe_cache *sc, unsigned stripes) +{ + int r = 0; + + /* Try to get unused stripe from LRU list. */ + while (stripes--) { + struct stripe *stripe; + + stripe = stripe_lru_pop(sc); + if (stripe) { + /* An LRU stripe may never have ios pending! */ + BUG_ON(stripe_io_ref(stripe)); + BUG_ON(stripe_ref(stripe)); + atomic_dec(&sc->stripes); + /* Remove from hash if on before deletion. */ + stripe_hash_del(stripe); + stripe_free(stripe, sc->mem_cache_client); + } else { + r = -ENOENT; + break; + } + } + + /* Check if stats are still sane. */ + if (atomic_read(&sc->active_stripes_max) > + atomic_read(&sc->stripes)) + atomic_set(&sc->active_stripes_max, 0); + + if (r) + return r; + + return atomic_read(&sc->stripes) ? sc_hash_resize(sc) : 0; +} + +/* Create stripe cache and recovery. */ +static int sc_init(struct raid_set *rs, unsigned stripes) +{ + unsigned i, r, rstripes; + struct stripe_cache *sc = &rs->sc; + struct stripe *stripe; + struct recover *rec = &rs->recover; + struct mapped_device *md; + struct gendisk *disk; + + /* Initialize lists and locks. */ + i = ARRAY_SIZE(sc->lists); + while (i--) + INIT_LIST_HEAD(sc->lists + i); + + INIT_LIST_HEAD(&rec->stripes); + + /* Initialize endio and LRU list locks. */ + i = NR_LOCKS; + while (i--) + spin_lock_init(sc->locks + i); + + /* Initialize atomic variables. */ + atomic_set(&sc->stripes, 0); + atomic_set(&sc->stripes_to_set, 0); + atomic_set(&sc->active_stripes, 0); + atomic_set(&sc->active_stripes_max, 0); /* REMOVEME: statistics. */ + + /* + * We need a runtime unique # to suffix the kmem cache name + * because we'll have one for each active RAID set. + */ + md = dm_table_get_md(rs->ti->table); + disk = dm_disk(md); + sprintf(sc->kc.name, "%s-%d", TARGET, disk->first_minor); + dm_put(md); + sc->kc.cache = kmem_cache_create(sc->kc.name, stripe_size(rs), + 0, 0, NULL); + if (!sc->kc.cache) + return -ENOMEM; + + /* Create memory cache client context for RAID stripe cache. */ + sc->mem_cache_client = + dm_mem_cache_client_create(stripes, rs->set.raid_devs, + chunk_pages(rs->set.io_size)); + if (IS_ERR(sc->mem_cache_client)) + return PTR_ERR(sc->mem_cache_client); + + /* Create memory cache client context for RAID recovery stripe(s). */ + rstripes = rec->recovery_stripes; + rec->mem_cache_client = + dm_mem_cache_client_create(rstripes, rs->set.raid_devs, + chunk_pages(rec->io_size)); + if (IS_ERR(rec->mem_cache_client)) + return PTR_ERR(rec->mem_cache_client); + + /* Create dm-io client context for IO stripes. */ + sc->dm_io_client = + dm_io_client_create((stripes > 32 ? 32 : stripes) * + rs->set.raid_devs * + chunk_pages(rs->set.io_size)); + if (IS_ERR(sc->dm_io_client)) + return PTR_ERR(sc->dm_io_client); + + /* FIXME: intermingeled with stripe cache initialization. */ + /* Create dm-io client context for recovery stripes. */ + rec->dm_io_client = + dm_io_client_create(rstripes * rs->set.raid_devs * + chunk_pages(rec->io_size)); + if (IS_ERR(rec->dm_io_client)) + return PTR_ERR(rec->dm_io_client); + + /* Allocate stripes for set recovery. */ + while (rstripes--) { + stripe = stripe_alloc(sc, rec->mem_cache_client, SC_KEEP); + if (!stripe) + return -ENOMEM; + + stripe->recover = kzalloc(sizeof(*stripe->recover), GFP_KERNEL); + if (!stripe->recover) { + stripe_free(stripe, rec->mem_cache_client); + return -ENOMEM; + } + + SetStripeRecover(stripe); + stripe->io.size = rec->io_size; + list_add_tail(stripe->lists + LIST_RECOVER, &rec->stripes); + /* Don't add recovery stripes to LRU list! */ + } + + /* + * Allocate the stripe objetcs from the + * cache and add them to the LRU list. + */ + r = sc_grow(sc, stripes, SC_KEEP); + if (!r) + atomic_set(&sc->stripes_last, stripes); + + return r; +} + +/* Destroy the stripe cache. */ +static void sc_exit(struct stripe_cache *sc) +{ + struct raid_set *rs = RS(sc); + + if (sc->kc.cache) { + stripe_recover_free(rs); + BUG_ON(sc_shrink(sc, atomic_read(&sc->stripes))); + kmem_cache_destroy(sc->kc.cache); + sc->kc.cache = NULL; + + if (sc->mem_cache_client && !IS_ERR(sc->mem_cache_client)) + dm_mem_cache_client_destroy(sc->mem_cache_client); + + if (sc->dm_io_client && !IS_ERR(sc->dm_io_client)) + dm_io_client_destroy(sc->dm_io_client); + + hash_exit(&sc->hash); + } +} + +/* + * Calculate RAID address + * + * Delivers tuple with the index of the data disk holding the chunk + * in the set, the parity disks index and the start of the stripe + * within the address space of the set (used as the stripe cache hash key). + */ +/* thx MD. */ +static struct raid_address *raid_address(struct raid_set *rs, sector_t sector, + struct raid_address *addr) +{ + sector_t stripe, tmp; + + /* + * chunk_number = sector / chunk_size + * stripe_number = chunk_number / data_devs + * di = stripe % data_devs; + */ + stripe = sector >> rs->set.chunk_shift; + addr->di = sector_div(stripe, rs->set.data_devs); + + switch (rs->set.raid_type->level) { + case raid4: + addr->pi = rs->set.pi; + goto check_shift_di; + case raid5: + tmp = stripe; + addr->pi = sector_div(tmp, rs->set.raid_devs); + + switch (rs->set.raid_type->algorithm) { + case left_asym: /* Left asymmetric. */ + addr->pi = rs->set.data_devs - addr->pi; + case right_asym: /* Right asymmetric. */ +check_shift_di: + if (addr->di >= addr->pi) + addr->di++; + break; + case left_sym: /* Left symmetric. */ + addr->pi = rs->set.data_devs - addr->pi; + case right_sym: /* Right symmetric. */ + addr->di = (addr->pi + addr->di + 1) % + rs->set.raid_devs; + break; + case none: /* Ain't happen: RAID4 algorithm placeholder. */ + BUG(); + } + } + + /* + * Start offset of the stripes chunk on any single device of the RAID + * set, adjusted in case io size differs from chunk size. + */ + addr->key = (stripe << rs->set.chunk_shift) + + (sector & rs->set.io_inv_mask); + return addr; +} + +/* + * Copy data across between stripe pages and bio vectors. + * + * Pay attention to data alignment in stripe and bio pages. + */ +static void bio_copy_page_list(int rw, struct stripe *stripe, + struct page_list *pl, struct bio *bio) +{ + unsigned i, page_offset; + void *page_addr; + struct raid_set *rs = RS(stripe->sc); + struct bio_vec *bv; + + /* Get start page in page list for this sector. */ + i = (bio->bi_sector & rs->set.io_mask) / SECTORS_PER_PAGE; + pl = pl_elem(pl, i); + BUG_ON(!pl); + BUG_ON(!pl->page); + + page_addr = page_address(pl->page); + page_offset = to_bytes(bio->bi_sector & (SECTORS_PER_PAGE - 1)); + + /* Walk all segments and copy data across between bio_vecs and pages. */ + bio_for_each_segment(bv, bio, i) { + int len = bv->bv_len, size; + unsigned bio_offset = 0; + void *bio_addr = __bio_kmap_atomic(bio, i, KM_USER0); +redo: + size = (page_offset + len > PAGE_SIZE) ? + PAGE_SIZE - page_offset : len; + + if (rw == READ) + memcpy(bio_addr + bio_offset, + page_addr + page_offset, size); + else + memcpy(page_addr + page_offset, + bio_addr + bio_offset, size); + + page_offset += size; + if (page_offset == PAGE_SIZE) { + /* + * We reached the end of the chunk page -> + * need to refer to the next one to copy more data. + */ + len -= size; + if (len) { + /* Get next page. */ + pl = pl->next; + BUG_ON(!pl); + BUG_ON(!pl->page); + page_addr = page_address(pl->page); + page_offset = 0; + bio_offset += size; + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_BIO_COPY_PL_NEXT); + goto redo; + } + } + + __bio_kunmap_atomic(bio_addr, KM_USER0); + } +} + +/* + * Xor optimization macros. + */ +/* Xor data pointer declaration and initialization macros. */ +#define DECLARE_2 unsigned long *d0 = data[0], *d1 = data[1] +#define DECLARE_3 DECLARE_2, *d2 = data[2] +#define DECLARE_4 DECLARE_3, *d3 = data[3] +#define DECLARE_5 DECLARE_4, *d4 = data[4] +#define DECLARE_6 DECLARE_5, *d5 = data[5] +#define DECLARE_7 DECLARE_6, *d6 = data[6] +#define DECLARE_8 DECLARE_7, *d7 = data[7] + +/* Xor unrole macros. */ +#define D2(n) d0[n] = d0[n] ^ d1[n] +#define D3(n) D2(n) ^ d2[n] +#define D4(n) D3(n) ^ d3[n] +#define D5(n) D4(n) ^ d4[n] +#define D6(n) D5(n) ^ d5[n] +#define D7(n) D6(n) ^ d6[n] +#define D8(n) D7(n) ^ d7[n] + +#define X_2(macro, offset) macro(offset); macro(offset + 1); +#define X_4(macro, offset) X_2(macro, offset); X_2(macro, offset + 2); +#define X_8(macro, offset) X_4(macro, offset); X_4(macro, offset + 4); +#define X_16(macro, offset) X_8(macro, offset); X_8(macro, offset + 8); +#define X_32(macro, offset) X_16(macro, offset); X_16(macro, offset + 16); +#define X_64(macro, offset) X_32(macro, offset); X_32(macro, offset + 32); + +/* Define a _xor_#chunks_#xors_per_run() function. */ +#define _XOR(chunks, xors_per_run) \ +static void _xor ## chunks ## _ ## xors_per_run(unsigned long **data) \ +{ \ + unsigned end = XOR_SIZE / sizeof(data[0]), i; \ + DECLARE_ ## chunks; \ +\ + for (i = 0; i < end; i += xors_per_run) { \ + X_ ## xors_per_run(D ## chunks, i); \ + } \ +} + +/* Define xor functions for 2 - 8 chunks and xors per run. */ +#define MAKE_XOR_PER_RUN(xors_per_run) \ + _XOR(2, xors_per_run); _XOR(3, xors_per_run); \ + _XOR(4, xors_per_run); _XOR(5, xors_per_run); \ + _XOR(6, xors_per_run); _XOR(7, xors_per_run); \ + _XOR(8, xors_per_run); + +MAKE_XOR_PER_RUN(8) /* Define _xor_*_8() functions. */ +MAKE_XOR_PER_RUN(16) /* Define _xor_*_16() functions. */ +MAKE_XOR_PER_RUN(32) /* Define _xor_*_32() functions. */ +MAKE_XOR_PER_RUN(64) /* Define _xor_*_64() functions. */ + +#define MAKE_XOR(xors_per_run) \ +struct { \ + void (*f)(unsigned long **); \ +} static xor_funcs ## xors_per_run[] = { \ + { NULL }, /* NULL pointers to optimize indexing in xor(). */ \ + { NULL }, \ + { _xor2_ ## xors_per_run }, \ + { _xor3_ ## xors_per_run }, \ + { _xor4_ ## xors_per_run }, \ + { _xor5_ ## xors_per_run }, \ + { _xor6_ ## xors_per_run }, \ + { _xor7_ ## xors_per_run }, \ + { _xor8_ ## xors_per_run }, \ +}; \ +\ +static void xor_ ## xors_per_run(unsigned n, unsigned long **data) \ +{ \ + /* Call respective function for amount of chunks. */ \ + xor_funcs ## xors_per_run[n].f(data); \ +} + +/* Define xor_8() - xor_64 functions. */ +MAKE_XOR(8) +MAKE_XOR(16) +MAKE_XOR(32) +MAKE_XOR(64) + +/* Maximum number of chunks, which can be xor'ed in one go. */ +#define XOR_CHUNKS_MAX (ARRAY_SIZE(xor_funcs8) - 1) + +static void xor_blocks_wrapper(unsigned n, unsigned long **data) +{ + BUG_ON(n < 2 || n > MAX_XOR_BLOCKS + 1); + xor_blocks(n - 1, XOR_SIZE, (void *) data[0], (void **) data + 1); +} + +struct xor_func { + xor_function_t f; + const char *name; +} static xor_funcs[] = { + { xor_8, "xor_8" }, + { xor_16, "xor_16" }, + { xor_32, "xor_32" }, + { xor_64, "xor_64" }, + { xor_blocks_wrapper, "xor_blocks" }, +}; + +/* + * Check, if chunk has to be xored in/out: + * + * o if writes are queued + * o if writes are merged + * o if stripe is to be reconstructed + * o if recovery stripe + */ +static inline int chunk_must_xor(struct stripe_chunk *chunk) +{ + if (ChunkUptodate(chunk)) { + BUG_ON(!bio_list_empty(BL_CHUNK(chunk, WRITE_QUEUED)) && + !bio_list_empty(BL_CHUNK(chunk, WRITE_MERGED))); + + if (!bio_list_empty(BL_CHUNK(chunk, WRITE_QUEUED)) || + !bio_list_empty(BL_CHUNK(chunk, WRITE_MERGED))) + return 1; + + if (StripeReconstruct(chunk->stripe) || + StripeRecover(chunk->stripe)) + return 1; + } + + return 0; +} + +/* + * Calculate crc. + * + * This indexes into the chunks of a stripe and their pages. + * + * All chunks will be xored into the indexed (@pi) + * chunk in maximum groups of xor.chunks. + * + */ +static void xor(struct stripe *stripe, unsigned pi, unsigned sector) +{ + struct raid_set *rs = RS(stripe->sc); + unsigned max_chunks = rs->xor.chunks, n = 1, + o = sector / SECTORS_PER_PAGE, /* Offset into the page_list. */ + p = rs->set.raid_devs; + unsigned long **d = rs->data; + xor_function_t xor_f = rs->xor.f->f; + + BUG_ON(sector > stripe->io.size); + + /* Address of parity page to xor into. */ + d[0] = page_address(pl_elem(PL(stripe, pi), o)->page); + + while (p--) { + /* Preset pointers to data pages. */ + if (p != pi && chunk_must_xor(CHUNK(stripe, p))) + d[n++] = page_address(pl_elem(PL(stripe, p), o)->page); + + /* If max chunks -> xor. */ + if (n == max_chunks) { + xor_f(n, d); + n = 1; + } + } + + /* If chunks -> xor. */ + if (n > 1) + xor_f(n, d); +} + +/* Common xor loop through all stripe page lists. */ +static void common_xor(struct stripe *stripe, sector_t count, + unsigned off, unsigned pi) +{ + unsigned sector; + + BUG_ON(!count); + for (sector = off; sector < count; sector += SECTORS_PER_PAGE) + xor(stripe, pi, sector); + + /* Set parity page uptodate and clean. */ + chunk_set(CHUNK(stripe, pi), CLEAN); + atomic_inc(RS(stripe->sc)->stats + S_XORS); /* REMOVEME: statistics. */ +} + +/* + * Calculate parity sectors on intact stripes. + * + * Need to calculate raid address for recover stripe, because its + * chunk sizes differs and is typically larger than io chunk size. + */ +static void parity_xor(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + unsigned chunk_size = rs->set.chunk_size, io_size = stripe->io.size, + xor_size = chunk_size > io_size ? io_size : chunk_size; + sector_t off; + + /* This can be the recover stripe with a larger io size. */ + for (off = 0; off < io_size; off += xor_size) { + /* + * Recover stripe is likely bigger than regular io + * ones and has no precalculated parity disk index -> + * need to calculate RAID address. + */ + if (unlikely(StripeRecover(stripe))) { + struct raid_address addr; + + raid_address(rs, + (stripe->key + off) * rs->set.data_devs, + &addr); + stripe->idx.parity = addr.pi; + stripe_zero_pl_part(stripe, addr.pi, off, xor_size); + } + + common_xor(stripe, xor_size, off, stripe->idx.parity); + chunk_set(CHUNK(stripe, stripe->idx.parity), DIRTY); + } +} + +/* Reconstruct missing chunk. */ +static void stripe_reconstruct(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + int p = rs->set.raid_devs, pr = stripe->idx.recover; + + BUG_ON(pr < 0); + + /* Check if all but the chunk to be reconstructed are uptodate. */ + while (p--) + BUG_ON(p != pr && !ChunkUptodate(CHUNK(stripe, p))); + + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + (RSDegraded(rs) ? S_RECONSTRUCT_EI : + S_RECONSTRUCT_DEV)); + /* Zero chunk to be reconstructed. */ + stripe_zero_chunk(stripe, pr); + common_xor(stripe, stripe->io.size, 0, pr); + stripe->idx.recover = -1; +} + +/* + * Recovery io throttling + */ +/* Conditionally reset io counters. */ +static int recover_io_reset(struct raid_set *rs) +{ + unsigned long j = jiffies; + + /* Pay attention to jiffies overflows. */ + if (j > rs->recover.last_jiffies + HZ / 20 || + j < rs->recover.last_jiffies) { + atomic_set(rs->recover.io_count + IO_WORK, 0); + atomic_set(rs->recover.io_count + IO_RECOVER, 0); + rs->recover.last_jiffies = j; + return 1; + } + + return 0; +} + +/* Count ios. */ +static void recover_io_count(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + + recover_io_reset(rs); + atomic_inc(rs->recover.io_count + + (StripeRecover(stripe) ? IO_RECOVER : IO_WORK)); +} + +/* Try getting a stripe either from the hash or from the LRU list. */ +static struct stripe *stripe_find(struct raid_set *rs, + struct raid_address *addr) +{ + int r; + struct stripe_cache *sc = &rs->sc; + struct stripe *stripe; + + /* Try stripe from hash. */ + stripe = stripe_lookup(sc, addr->key); + if (stripe) { + r = stripe_get(stripe); + if (r) + goto get_lock_failed; + + atomic_inc(rs->stats + S_HITS_1ST); /* REMOVEME: statistics. */ + } else { + /* Not in hash -> try to get an LRU stripe. */ + stripe = stripe_lru_pop(sc); + if (stripe) { + /* + * An LRU stripe may not be referenced + * and may never have ios pending! + */ + BUG_ON(stripe_ref(stripe)); + BUG_ON(stripe_io_ref(stripe)); + + /* Remove from hash if on before reuse. */ + stripe_hash_del(stripe); + + /* Invalidate before reinserting with changed key. */ + stripe_invalidate(stripe); + + stripe->key = addr->key; + stripe->region = dm_rh_sector_to_region(rs->recover.rh, + addr->key); + stripe->idx.parity = addr->pi; + r = stripe_get(stripe); + if (r) + goto get_lock_failed; + + /* Insert stripe into the stripe hash. */ + stripe_insert(&sc->hash, stripe); + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_INSCACHE); + } + } + + return stripe; + +get_lock_failed: + stripe_put(stripe); + return NULL; +} + +/* + * Process end io + * + * I need to do it here because I can't in interrupt + */ +/* End io all bios on a bio list. */ +static void bio_list_endio(struct stripe *stripe, struct bio_list *bl, + int p, int error) +{ + struct raid_set *rs = RS(stripe->sc); + struct bio *bio; + struct page_list *pl = PL(stripe, p); + struct stripe_chunk *chunk = CHUNK(stripe, p); + + /* Update region counters. */ + while ((bio = bio_list_pop(bl))) { + if (bio_data_dir(bio) == WRITE) + /* Drop io pending count for any writes. */ + dm_rh_dec(rs->recover.rh, stripe->region); + else if (!error) + /* Copy data accross. */ + bio_copy_page_list(READ, stripe, pl, bio); + + bio_endio(bio, error); + + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + (bio_data_dir(bio) == READ ? + S_BIOS_ENDIO_READ : S_BIOS_ENDIO_WRITE)); + + chunk_put(chunk); + stripe_put(stripe); + io_put(rs); /* Wake any suspend waiters on last bio. */ + } +} + +/* + * End io all reads/writes on a stripe copying + * read data accross from stripe to bios and + * decrementing region counters for writes. + * + * Processing of ios depeding on state: + * o no chunk error -> endio ok + * o degraded: + * - chunk error and read -> ignore to be requeued + * - chunk error and write -> endio ok + * o dead (more than parity_devs failed) and chunk_error-> endio failed + */ +static void stripe_endio(int rw, struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + unsigned p = rs->set.raid_devs; + int write = (rw != READ); + + while (p--) { + struct stripe_chunk *chunk = CHUNK(stripe, p); + struct bio_list *bl; + + BUG_ON(ChunkLocked(chunk)); + + bl = BL_CHUNK(chunk, rw); + if (bio_list_empty(bl)) + continue; + + if (unlikely(ChunkError(chunk) || !ChunkUptodate(chunk))) { + /* RAID set dead. */ + if (unlikely(RSDead(rs))) + bio_list_endio(stripe, bl, p, -EIO); + /* RAID set degraded. */ + else if (write) + bio_list_endio(stripe, bl, p, 0); + } else { + BUG_ON(!RSDegraded(rs) && ChunkDirty(chunk)); + bio_list_endio(stripe, bl, p, 0); + } + } +} + +/* Fail all ios hanging off all bio lists of a stripe. */ +static void stripe_fail_io(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + unsigned p = rs->set.raid_devs; + + while (p--) { + struct stripe_chunk *chunk = CHUNK(stripe, p); + int i = ARRAY_SIZE(chunk->bl); + + /* Fail all bios on all bio lists of the stripe. */ + while (i--) { + struct bio_list *bl = chunk->bl + i; + + if (!bio_list_empty(bl)) + bio_list_endio(stripe, bl, p, -EIO); + } + } + + /* Put stripe on LRU list. */ + BUG_ON(stripe_io_ref(stripe)); + BUG_ON(stripe_ref(stripe)); +} + +/* Unlock all required chunks. */ +static void stripe_chunks_unlock(struct stripe *stripe) +{ + unsigned p = RS(stripe->sc)->set.raid_devs; + struct stripe_chunk *chunk; + + while (p--) { + chunk = CHUNK(stripe, p); + + if (TestClearChunkUnlock(chunk)) + ClearChunkLocked(chunk); + } +} + +/* + * Queue reads and writes to a stripe by hanging + * their bios off the stripesets read/write lists. + */ +static int stripe_queue_bio(struct raid_set *rs, struct bio *bio, + struct bio_list *reject) +{ + struct raid_address addr; + struct stripe *stripe; + + stripe = stripe_find(rs, raid_address(rs, bio->bi_sector, &addr)); + if (stripe) { + int r = 0, rw = bio_data_dir(bio); + + /* Distinguish reads and writes. */ + bio_list_add(BL(stripe, addr.di, rw), bio); + + if (rw == READ) + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_BIOS_ADDED_READ); + else { + /* Inrement pending write count on region. */ + dm_rh_inc(rs->recover.rh, stripe->region); + r = 1; + + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_BIOS_ADDED_WRITE); + } + + /* + * Put on io (flush) list in case of + * initial bio queued to chunk. + */ + if (chunk_get(CHUNK(stripe, addr.di)) == 1) + stripe_flush_add(stripe); + + return r; + } + + /* Got no stripe from cache or failed to lock it -> reject bio. */ + bio_list_add(reject, bio); + atomic_inc(rs->stats + S_IOS_POST); /* REMOVEME: statistics. */ + return 0; +} + +/* + * Handle all stripes by handing them to the daemon, because we can't + * map their chunk pages to copy the data in interrupt context. + * + * We don't want to handle them here either, while interrupts are disabled. + */ + +/* Read/write endio function for dm-io (interrupt context). */ +static void endio(unsigned long error, void *context) +{ + struct stripe_chunk *chunk = context; + + if (unlikely(error)) { + chunk_set(chunk, ERROR); + /* REMOVEME: statistics. */ + atomic_inc(RS(chunk->stripe->sc)->stats + S_STRIPE_ERROR); + } else + chunk_set(chunk, CLEAN); + + /* + * For recovery stripes, I need to reset locked locked + * here, because those aren't processed in do_endios(). + */ + if (unlikely(StripeRecover(chunk->stripe))) + ClearChunkLocked(chunk); + else + SetChunkUnlock(chunk); + + /* Indirectly puts stripe on cache's endio list via stripe_io_put(). */ + stripe_put_references(chunk->stripe); +} + +/* Read/Write a chunk asynchronously. */ +static void stripe_chunk_rw(struct stripe *stripe, unsigned p) +{ + struct stripe_cache *sc = stripe->sc; + struct raid_set *rs = RS(sc); + struct dm_mem_cache_object *obj = stripe->obj + p; + struct page_list *pl = obj->pl; + struct stripe_chunk *chunk = CHUNK(stripe, p); + struct raid_dev *dev = rs->dev + p; + struct dm_io_region io = { + .bdev = dev->dev->bdev, + .sector = stripe->key, + .count = stripe->io.size, + }; + struct dm_io_request control = { + .bi_rw = ChunkDirty(chunk) ? WRITE : READ, + .mem = { + .type = DM_IO_PAGE_LIST, + .ptr.pl = pl, + .offset = 0, + }, + .notify = { + .fn = endio, + .context = chunk, + }, + .client = StripeRecover(stripe) ? rs->recover.dm_io_client : + sc->dm_io_client, + }; + + BUG_ON(ChunkLocked(chunk)); + BUG_ON(!ChunkUptodate(chunk) && ChunkDirty(chunk)); + BUG_ON(ChunkUptodate(chunk) && !ChunkDirty(chunk)); + + /* + * Don't rw past end of device, which can happen, because + * typically sectors_per_dev isn't divisible by io_size. + */ + if (unlikely(io.sector + io.count > rs->set.sectors_per_dev)) + io.count = rs->set.sectors_per_dev - io.sector; + + BUG_ON(!io.count); + io.sector += dev->start; /* Add . */ + if (RSRecover(rs)) + recover_io_count(stripe); /* Recovery io accounting. */ + + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + (ChunkDirty(chunk) ? S_DM_IO_WRITE : + S_DM_IO_READ)); + SetChunkLocked(chunk); + SetDevIoQueued(dev); + BUG_ON(dm_io(&control, 1, &io, NULL)); +} + +/* + * Write dirty or read not uptodate page lists of a stripe. + */ +static int stripe_chunks_rw(struct stripe *stripe) +{ + int r; + struct raid_set *rs = RS(stripe->sc); + + /* + * Increment the pending count on the stripe + * first, so that we don't race in endio(). + * + * An inc (IO) is needed for any chunk unless !ChunkIo(chunk): + * + * o not uptodate + * o dirtied by writes merged + * o dirtied by parity calculations + */ + r = for_each_io_dev(stripe, stripe_get_references); + if (r) { + /* Io needed: chunks are either not uptodate or dirty. */ + int max; /* REMOVEME: */ + struct stripe_cache *sc = &rs->sc; + + /* Submit actual io. */ + for_each_io_dev(stripe, stripe_chunk_rw); + + /* REMOVEME: statistics */ + max = sc_active(sc); + if (atomic_read(&sc->active_stripes_max) < max) + atomic_set(&sc->active_stripes_max, max); + + atomic_inc(rs->stats + S_FLUSHS); + /* END REMOVEME: statistics */ + } + + return r; +} + +/* Merge in all writes hence dirtying respective chunks. */ +static void stripe_merge_writes(struct stripe *stripe) +{ + unsigned p = RS(stripe->sc)->set.raid_devs; + + while (p--) { + struct stripe_chunk *chunk = CHUNK(stripe, p); + struct bio_list *write = BL_CHUNK(chunk, WRITE_QUEUED); + + if (!bio_list_empty(write)) { + struct bio *bio; + struct page_list *pl = stripe->obj[p].pl; + + /* + * We can play with the lists without holding a lock, + * because it is just us accessing them anyway. + */ + bio_list_for_each(bio, write) + bio_copy_page_list(WRITE, stripe, pl, bio); + + bio_list_merge(BL_CHUNK(chunk, WRITE_MERGED), write); + bio_list_init(write); + chunk_set(chunk, DIRTY); + } + } +} + +/* Queue all writes to get merged. */ +static int stripe_queue_writes(struct stripe *stripe) +{ + int r = 0; + unsigned p = RS(stripe->sc)->set.raid_devs; + + while (p--) { + struct stripe_chunk *chunk = CHUNK(stripe, p); + struct bio_list *write = BL_CHUNK(chunk, WRITE); + + if (!bio_list_empty(write)) { + bio_list_merge(BL_CHUNK(chunk, WRITE_QUEUED), write); + bio_list_init(write); +SetChunkIo(chunk); + r = 1; + } + } + + return r; +} + + +/* Check, if a chunk gets completely overwritten. */ +static int stripe_check_chunk_overwrite(struct stripe *stripe, unsigned p) +{ + unsigned sectors = 0; + struct bio *bio; + struct bio_list *bl = BL(stripe, p, WRITE_QUEUED); + + bio_list_for_each(bio, bl) + sectors += bio_sectors(bio); + + BUG_ON(sectors > RS(stripe->sc)->set.io_size); + return sectors == RS(stripe->sc)->set.io_size; +} + +/* + * Avoid io on broken/reconstructed drive in order to + * reconstruct date on endio. + * + * (*1*) We set StripeReconstruct() in here, so that _do_endios() + * will trigger a reconstruct call before resetting it. + */ +static int stripe_chunk_set_io_flags(struct stripe *stripe, int pr) +{ + struct stripe_chunk *chunk = CHUNK(stripe, pr); + + /* + * Allow io on all chunks but the indexed one, + * because we're either degraded or prohibit it + * on the one for later reconstruction. + */ + /* Includes ClearChunkIo(), ClearChunkUptodate(). */ + stripe_chunk_invalidate(chunk); + stripe->idx.recover = pr; + SetStripeReconstruct(stripe); + + /* REMOVEME: statistics. */ + atomic_inc(RS(stripe->sc)->stats + S_PROHIBITCHUNKIO); + return -EPERM; +} + +/* Chunk locked/uptodate and device failed tests. */ +static struct stripe_chunk * +stripe_chunk_check(struct stripe *stripe, unsigned p, unsigned *chunks_uptodate) +{ + struct raid_set *rs = RS(stripe->sc); + struct stripe_chunk *chunk = CHUNK(stripe, p); + + /* Can't access active chunks. */ + if (ChunkLocked(chunk)) { + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_CHUNK_LOCKED); + return NULL; + } + + /* Can't access broken devive. */ + if (ChunkError(chunk) || DevFailed(rs->dev + p)) + return NULL; + + /* Can access uptodate chunks. */ + if (ChunkUptodate(chunk)) { + (*chunks_uptodate)++; + return NULL; + } + + return chunk; +} + +/* + * Degraded/reconstruction mode. + * + * Check stripe state to figure which chunks don't need IO. + * + * Returns 0 for fully operational, -EPERM for degraded/resynchronizing. + */ +static int stripe_check_reconstruct(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + + if (RSDead(rs)) { + ClearStripeReconstruct(stripe); + ClearStripeReconstructed(stripe); + stripe_allow_io(stripe); + return 0; + } + + /* Avoid further reconstruction setting, when already set. */ + if (StripeReconstruct(stripe)) { + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_RECONSTRUCT_SET); + return -EBUSY; + } + + /* Initially allow io on all chunks. */ + stripe_allow_io(stripe); + + /* Return if stripe is already reconstructed. */ + if (StripeReconstructed(stripe)) { + atomic_inc(rs->stats + S_RECONSTRUCTED); + return 0; + } + + /* + * Degraded/reconstruction mode (device failed) -> + * avoid io on the failed device. + */ + if (unlikely(RSDegraded(rs))) { + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_DEGRADED); + /* Allow IO on all devices but the dead one. */ + BUG_ON(rs->set.ei < 0); + return stripe_chunk_set_io_flags(stripe, rs->set.ei); + } else { + int sync, pi = dev_for_parity(stripe, &sync); + + /* + * Reconstruction mode (ie. a particular (replaced) device or + * some (rotating) parity chunk is being resynchronized) -> + * o make sure all needed chunks are read in + * o writes are allowed to go through + */ + if (!sync) { + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_NOSYNC); + /* Allow IO on all devs but the one to reconstruct. */ + return stripe_chunk_set_io_flags(stripe, pi); + } + } + + return 0; +} + +/* + * Check, if stripe is ready to merge writes. + * I.e. if all chunks present to allow to merge bios. + * + * We prohibit io on: + * + * o chunks without bios + * o chunks which get completely written over + */ +static int stripe_merge_possible(struct stripe *stripe, int nosync) +{ + struct raid_set *rs = RS(stripe->sc); + unsigned chunks_overwrite = 0, chunks_prohibited = 0, + chunks_uptodate = 0, p = rs->set.raid_devs; + + /* Walk all chunks. */ + while (p--) { + struct stripe_chunk *chunk; + + /* Prohibit io on broken devices. */ + if (DevFailed(rs->dev + p)) { + chunk = CHUNK(stripe, p); + goto prohibit_io; + } + + /* We can't optimize any further if no chunk. */ + chunk = stripe_chunk_check(stripe, p, &chunks_uptodate); + if (!chunk || nosync) + continue; + + /* + * We have a chunk, which is not uptodate. + * + * If this is not parity and we don't have + * reads queued, we can optimize further. + */ + if (p != stripe->idx.parity && + bio_list_empty(BL_CHUNK(chunk, READ)) && + bio_list_empty(BL_CHUNK(chunk, WRITE_MERGED))) { + if (bio_list_empty(BL_CHUNK(chunk, WRITE_QUEUED))) + goto prohibit_io; + else if (RSCheckOverwrite(rs) && + stripe_check_chunk_overwrite(stripe, p)) + /* Completely overwritten chunk. */ + chunks_overwrite++; + } + + /* Allow io for chunks with bios and overwritten ones. */ + SetChunkIo(chunk); + continue; + +prohibit_io: + /* No io for broken devices or for chunks w/o bios. */ + ClearChunkIo(chunk); + chunks_prohibited++; + /* REMOVEME: statistics. */ + atomic_inc(RS(stripe->sc)->stats + S_PROHIBITCHUNKIO); + } + + /* All data chunks will get written over. */ + if (chunks_overwrite == rs->set.data_devs) + atomic_inc(rs->stats + S_OVERWRITE); /* REMOVEME: statistics.*/ + else if (chunks_uptodate + chunks_prohibited < rs->set.raid_devs) { + /* We don't have enough chunks to merge. */ + atomic_inc(rs->stats + S_CANT_MERGE); /* REMOVEME: statistics.*/ + return -EPERM; + } + + /* + * If we have all chunks up to date or overwrite them, we + * just zero the parity chunk and let stripe_rw() recreate it. + */ + if (chunks_uptodate == rs->set.raid_devs || + chunks_overwrite == rs->set.data_devs) { + stripe_zero_chunk(stripe, stripe->idx.parity); + BUG_ON(StripeReconstruct(stripe)); + SetStripeReconstruct(stripe); /* Enforce xor in caller. */ + } else { + /* + * With less chunks, we xor parity out. + * + * (*4*) We rely on !StripeReconstruct() in chunk_must_xor(), + * so that only chunks with queued or merged writes + * are being xored. + */ + parity_xor(stripe); + } + + /* + * We do have enough chunks to merge. + * All chunks are uptodate or get written over. + */ + atomic_inc(rs->stats + S_CAN_MERGE); /* REMOVEME: statistics. */ + return 0; +} + +/* + * Avoid reading chunks in case we're fully operational. + * + * We prohibit io on any chunks without bios but the parity chunk. + */ +static void stripe_avoid_reads(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + unsigned dummy = 0, p = rs->set.raid_devs; + + /* Walk all chunks. */ + while (p--) { + struct stripe_chunk *chunk = + stripe_chunk_check(stripe, p, &dummy); + + if (!chunk) + continue; + + /* If parity or any bios pending -> allow io. */ + if (chunk_ref(chunk) || p == stripe->idx.parity) + SetChunkIo(chunk); + else { + ClearChunkIo(chunk); + /* REMOVEME: statistics. */ + atomic_inc(RS(stripe->sc)->stats + S_PROHIBITCHUNKIO); + } + } +} + +/* + * Read/write a stripe. + * + * All stripe read/write activity goes through this function + * unless recovery, which has to call stripe_chunk_rw() directly. + * + * Make sure we don't try already merged stripes in order + * to avoid data corruption. + * + * Check the state of the RAID set and if degraded (or + * resynchronizing for reads), read in all other chunks but + * the one on the dead/resynchronizing device in order to be + * able to reconstruct the missing one in _do_endios(). + * + * Can be called on active stripes in order + * to dispatch new io on inactive chunks. + * + * States to cover: + * o stripe to read and/or write + * o stripe with error to reconstruct + */ +static void stripe_rw(struct stripe *stripe) +{ + int nosync, r; + struct raid_set *rs = RS(stripe->sc); + + /* + * Check, if a chunk needs to be reconstructed + * because of a degraded set or a region out of sync. + */ + nosync = stripe_check_reconstruct(stripe); + switch (nosync) { + case -EBUSY: + return; /* Wait for stripe reconstruction to finish. */ + case -EPERM: + goto io; + } + + /* + * If we don't have merged writes pending, we can schedule + * queued writes to be merged next without corrupting data. + */ + if (!StripeMerged(stripe)) { + r = stripe_queue_writes(stripe); + if (r) + /* Writes got queued -> flag RBW. */ + SetStripeRBW(stripe); + } + + /* + * Merge all writes hanging off uptodate/overwritten + * chunks of the stripe. + */ + if (StripeRBW(stripe)) { + r = stripe_merge_possible(stripe, nosync); + if (!r) { /* Merge possible. */ + struct stripe_chunk *chunk; + + /* + * I rely on valid parity in order + * to xor a fraction of chunks out + * of parity and back in. + */ + stripe_merge_writes(stripe); /* Merge writes in. */ + parity_xor(stripe); /* Update parity. */ + ClearStripeReconstruct(stripe); /* Reset xor enforce. */ + SetStripeMerged(stripe); /* Writes merged. */ + ClearStripeRBW(stripe); /* Disable RBW. */ + + /* + * REMOVEME: sanity check on parity chunk + * states after writes got merged. + */ + chunk = CHUNK(stripe, stripe->idx.parity); + BUG_ON(ChunkLocked(chunk)); + BUG_ON(!ChunkUptodate(chunk)); + BUG_ON(!ChunkDirty(chunk)); + BUG_ON(!ChunkIo(chunk)); + } + } else if (!nosync && !StripeMerged(stripe)) + /* Read avoidance if not degraded/resynchronizing/merged. */ + stripe_avoid_reads(stripe); + +io: + /* Now submit any reads/writes for non-uptodate or dirty chunks. */ + r = stripe_chunks_rw(stripe); + if (!r) { + /* + * No io submitted because of chunk io + * prohibited or locked chunks/failed devices + * -> push to end io list for processing. + */ + stripe_endio_push(stripe); + atomic_inc(rs->stats + S_NO_RW); /* REMOVEME: statistics. */ + } +} + +/* + * Recovery functions + */ +/* Read a stripe off a raid set for recovery. */ +static int stripe_recover_read(struct stripe *stripe, int pi) +{ + BUG_ON(stripe_io_ref(stripe)); + + /* Invalidate all chunks so that they get read in. */ + stripe_chunks_invalidate(stripe); + stripe_allow_io(stripe); /* Allow io on all recovery chunks. */ + + /* + * If we are reconstructing a perticular device, we can avoid + * reading the respective chunk in, because we're going to + * reconstruct it anyway. + * + * We can't do that for resynchronization of rotating parity, + * because the recovery stripe chunk size is typically larger + * than the sets chunk size. + */ + if (pi > -1) + ClearChunkIo(CHUNK(stripe, pi)); + + return stripe_chunks_rw(stripe); +} + +/* Write a stripe to a raid set for recovery. */ +static int stripe_recover_write(struct stripe *stripe, int pi) +{ + BUG_ON(stripe_io_ref(stripe)); + + /* + * If this is a reconstruct of a particular device, then + * reconstruct the respective chunk, else create parity chunk. + */ + if (pi > -1) { + stripe_zero_chunk(stripe, pi); + common_xor(stripe, stripe->io.size, 0, pi); + chunk_set(CHUNK(stripe, pi), DIRTY); + } else + parity_xor(stripe); + + return stripe_chunks_rw(stripe); +} + +/* Read/write a recovery stripe. */ +static int stripe_recover_rw(struct stripe *stripe) +{ + int r = 0, sync = 0; + + /* Read/write flip-flop. */ + if (TestClearStripeRBW(stripe)) { + SetStripeMerged(stripe); + stripe->key = stripe->recover->pos; + r = stripe_recover_read(stripe, dev_for_parity(stripe, &sync)); + BUG_ON(!r); + } else if (TestClearStripeMerged(stripe)) { + r = stripe_recover_write(stripe, dev_for_parity(stripe, &sync)); + BUG_ON(!r); + } + + BUG_ON(sync); + return r; +} + +/* Recover bandwidth available ?. */ +static int recover_bandwidth(struct raid_set *rs) +{ + int r, work; + + /* On reset or when bios delayed -> allow recovery. */ + r = recover_io_reset(rs); + if (r || RSBandwidth(rs)) + goto out; + + work = atomic_read(rs->recover.io_count + IO_WORK); + if (work) { + /* Pay attention to larger recover stripe size. */ + int recover = atomic_read(rs->recover.io_count + IO_RECOVER) * + rs->recover.io_size / rs->set.io_size; + + /* + * Don't use more than given bandwidth + * of the work io for recovery. + */ + if (recover > work / rs->recover.bandwidth_work) { + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_NO_BANDWIDTH); + return 0; + } + } + +out: + atomic_inc(rs->stats + S_BANDWIDTH); /* REMOVEME: statistics. */ + return 1; +} + +/* Try to get a region to recover. */ +static int stripe_recover_get_region(struct stripe *stripe) +{ + struct raid_set *rs = RS(stripe->sc); + struct recover *rec = &rs->recover; + struct recover_addr *addr = stripe->recover; + struct dm_dirty_log *dl = rec->dl; + struct dm_rh_client *rh = rec->rh; + + BUG_ON(!dl); + BUG_ON(!rh); + + /* Return, that we have region first to finish it during suspension. */ + if (addr->reg) + return 1; + + if (RSSuspend(rs)) + return -EPERM; + + if (dl->type->get_sync_count(dl) >= rec->nr_regions) + return -ENOENT; + + /* If we don't have enough bandwidth, we don't proceed recovering. */ + if (!recover_bandwidth(rs)) + return -EAGAIN; + + /* Start quiescing a region. */ + dm_rh_recovery_prepare(rh); + addr->reg = dm_rh_recovery_start(rh); + if (!addr->reg) + return -EAGAIN; + + addr->pos = dm_rh_region_to_sector(rh, dm_rh_get_region_key(addr->reg)); + addr->end = addr->pos + dm_rh_get_region_size(rh); + + /* + * Take one global io reference out for the + * whole region, which is going to be released + * when the region is completely done with. + */ + io_get(rs); + return 0; +} + +/* Update region hash state. */ +enum recover_type { REC_FAILURE = 0, REC_SUCCESS = 1 }; +static void recover_rh_update(struct stripe *stripe, enum recover_type success) +{ + struct recover_addr *addr = stripe->recover; + struct raid_set *rs = RS(stripe->sc); + struct recover *rec = &rs->recover; + + if (!addr->reg) { + DMERR("%s- Called w/o region", __func__); + return; + } + + dm_rh_recovery_end(addr->reg, success); + if (success) + rec->nr_regions_recovered++; + + addr->reg = NULL; + + /* + * Completely done with this region -> + * release the 1st io reference. + */ + io_put(rs); +} + +/* Set start of recovery state. */ +static void set_start_recovery(struct raid_set *rs) +{ + /* Initialize recovery. */ + rs->recover.start_jiffies = jiffies; + rs->recover.end_jiffies = 0; +} + +/* Set end of recovery state. */ +static void set_end_recovery(struct raid_set *rs) +{ + ClearRSRecover(rs); + rs->set.dev_to_init = -1; + + /* Check for jiffies overrun. */ + rs->recover.end_jiffies = jiffies; + if (rs->recover.end_jiffies < rs->recover.start_jiffies) + rs->recover.end_jiffies = ~0; +} + +/* Handle recovery on one recovery stripe. */ +static int _do_recovery(struct stripe *stripe) +{ + int r; + struct raid_set *rs = RS(stripe->sc); + struct recover_addr *addr = stripe->recover; + + /* If recovery is active -> return. */ + if (stripe_io_ref(stripe)) + return 1; + + /* IO error is fatal for recovery -> stop it. */ + if (unlikely(StripeError(stripe))) + goto err; + + /* Recovery end required. */ + if (!RSRecover(rs)) + goto err; + + /* Get a region to recover. */ + r = stripe_recover_get_region(stripe); + switch (r) { + case 0: /* Got a new region: flag initial read before write. */ + SetStripeRBW(stripe); + case 1: /* Have a region in the works. */ + break; + case -EAGAIN: + /* No bandwidth/quiesced region yet, try later. */ + if (!io_ref(rs)) + wake_do_raid_delayed(rs, HZ / 4); + case -EPERM: + /* Suspend. */ + return 1; + case -ENOENT: /* No more regions to recover. */ + schedule_work(&rs->io.ws_do_table_event); + return 0; + default: + BUG(); + } + + /* Read/write a recover stripe. */ + r = stripe_recover_rw(stripe); + if (r) + /* IO initiated. */ + return 1; + + /* Read and write finished-> update recovery position within region. */ + addr->pos += stripe->io.size; + + /* If we're at end of region, update region hash. */ + if (addr->pos >= addr->end || + addr->pos >= rs->set.sectors_per_dev) + recover_rh_update(stripe, REC_SUCCESS); + else + /* Prepare to read next region segment. */ + SetStripeRBW(stripe); + + /* Schedule myself for another round... */ + wake_do_raid(rs); + return 1; + +err: + /* FIXME: rather try recovering other regions on error? */ + rs_check_degrade(stripe); + recover_rh_update(stripe, REC_FAILURE); + + /* Check state of partially recovered array. */ + if (RSDegraded(rs) && !RSDead(rs) && + rs->set.dev_to_init != -1 && + rs->set.ei != rs->set.dev_to_init) + /* Broken drive != drive to recover -> FATAL. */ + SetRSDead(rs); + + if (StripeError(stripe)) { + char buf[BDEVNAME_SIZE]; + + DMERR("stopping recovery due to " + "ERROR on /dev/%s, stripe at offset %llu", + bdevname(rs->dev[rs->set.ei].dev->bdev, buf), + (unsigned long long) stripe->key); + + } + + /* Make sure, that all quiesced regions get released. */ + while (addr->reg) { + dm_rh_recovery_end(addr->reg, -EIO); + addr->reg = dm_rh_recovery_start(rs->recover.rh); + } + + return 0; +} + +/* Called by main io daemon to recover regions. */ +static void do_recovery(struct raid_set *rs) +{ + if (RSRecover(rs)) { + int r = 0; + struct stripe *stripe; + + list_for_each_entry(stripe, &rs->recover.stripes, + lists[LIST_RECOVER]) + r += _do_recovery(stripe); + + if (!r) { + set_end_recovery(rs); + stripe_recover_free(rs); + } + } +} + +/* + * END recovery functions + */ + +/* End io process all stripes handed in by endio() callback. */ +static void _do_endios(struct raid_set *rs, struct stripe *stripe, + struct list_head *flush_list) +{ + /* First unlock all required chunks. */ + stripe_chunks_unlock(stripe); + + /* + * If an io error on a stripe occured, degrade the RAID set + * and try to endio as many bios as possible. If any bios can't + * be endio processed, requeue the stripe (stripe_ref() != 0). + */ + if (TestClearStripeError(stripe)) { + /* + * FIXME: if read, rewrite the failed chunk after reconstruction + * in order to trigger disk bad sector relocation. + */ + rs_check_degrade(stripe); /* Resets ChunkError(). */ + ClearStripeReconstruct(stripe); + ClearStripeReconstructed(stripe); + } + + /* Got to reconstruct a missing chunk. */ + if (StripeReconstruct(stripe)) { + /* + * (*2*) We use StripeReconstruct() to allow for + * all chunks to be xored into the reconstructed + * one (see chunk_must_xor()). + */ + stripe_reconstruct(stripe); + + /* + * (*3*) Now we reset StripeReconstruct() and flag + * StripeReconstructed() to show to stripe_rw(), + * that we have reconstructed a missing chunk. + */ + ClearStripeReconstruct(stripe); + SetStripeReconstructed(stripe); + + /* FIXME: reschedule to be written in case of read. */ + // if (!StripeRBW(stripe)) { + // chunk_set(CHUNK(stripe, pr), DIRTY); + // stripe_chunks_rw(stripe); + // } + } + + /* + * Now that we eventually got a complete stripe, we + * can process the rest of the end ios on reads. + */ + stripe_endio(READ, stripe); + + /* End io all merged writes. */ + if (TestClearStripeMerged(stripe)) + stripe_endio(WRITE_MERGED, stripe); + + /* If RAID set is dead -> fail any ios to dead drives. */ + if (RSDead(rs)) { + DMERR_LIMIT("RAID set dead: failing ios to dead devices"); + stripe_fail_io(stripe); + } + + /* + * We have stripe references still, + * beacuse of read befeore writes or IO errors -> + * got to put on flush list for processing. + */ + if (stripe_ref(stripe)) { + BUG_ON(!list_empty(stripe->lists + LIST_LRU)); + list_add_tail(stripe->lists + LIST_FLUSH, flush_list); + atomic_inc(rs->stats + S_REQUEUE); /* REMOVEME: statistics. */ + } else + stripe_lru_add(stripe); +} + +/* Pop any endio stripes off of the endio list and belabour them. */ +static void do_endios(struct raid_set *rs) +{ + struct stripe_cache *sc = &rs->sc; + struct stripe *stripe; + /* IO flush list for sorted requeued stripes. */ + struct list_head flush_list; + + INIT_LIST_HEAD(&flush_list); + + while ((stripe = stripe_endio_pop(sc))) { + /* Avoid endio on stripes with newly io'ed chunks. */ + if (!stripe_io_ref(stripe)) + _do_endios(rs, stripe, &flush_list); + } + + /* + * Insert any requeued stripes in the proper + * order at the beginning of the io (flush) list. + */ + list_splice(&flush_list, sc->lists + LIST_FLUSH); +} + +/* Flush any stripes on the io list. */ +static void do_flush(struct raid_set *rs) +{ + struct stripe *stripe; + + while ((stripe = stripe_io_pop(&rs->sc))) + stripe_rw(stripe); /* Read/write stripe. */ +} + +/* Stripe cache resizing. */ +static void do_sc_resize(struct raid_set *rs) +{ + unsigned set = atomic_read(&rs->sc.stripes_to_set); + + if (set) { + unsigned cur = atomic_read(&rs->sc.stripes); + int r = (set > cur) ? sc_grow(&rs->sc, set - cur, SC_GROW) : + sc_shrink(&rs->sc, cur - set); + + /* Flag end of resizeing if ok. */ + if (!r) + atomic_set(&rs->sc.stripes_to_set, 0); + } +} + +/* + * Process all ios + * + * We do different things with the io depending + * on the state of the region that it is in: + * + * o reads: hang off stripe cache or postpone if full + * + * o writes: + * + * CLEAN/DIRTY/NOSYNC: increment pending and hang io off stripe's stripe set. + * In case stripe cache is full or busy, postpone the io. + * + * RECOVERING: delay the io until recovery of the region completes. + * + */ +static void do_ios(struct raid_set *rs, struct bio_list *ios) +{ + int r; + unsigned flush = 0, delay = 0; + sector_t sector; + struct dm_rh_client *rh = rs->recover.rh; + struct bio *bio; + struct bio_list reject; + + bio_list_init(&reject); + + /* + * Classify each io: + * o delay writes to recovering regions (let reads go through) + * o queue io to all other regions + */ + while ((bio = bio_list_pop(ios))) { + /* + * In case we get a barrier bio, push it back onto + * the input queue unless all work queues are empty + * and the stripe cache is inactive. + */ + if (unlikely(bio->bi_rw & REQ_FLUSH)) { + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + S_BARRIER); + if (delay || + !list_empty(rs->sc.lists + LIST_FLUSH) || + !bio_list_empty(&reject) || + sc_active(&rs->sc)) { + bio_list_push(ios, bio); + break; + } + } + + /* Check for recovering regions. */ + sector = _sector(rs, bio); + r = region_state(rs, sector, DM_RH_RECOVERING); + if (unlikely(r && bio_data_dir(bio) == WRITE)) { + delay++; + /* Wait writing to recovering regions. */ + dm_rh_delay_by_region(rh, bio, + dm_rh_sector_to_region(rh, + sector)); + /* REMOVEME: statistics.*/ + atomic_inc(rs->stats + S_DELAYED_BIOS); + atomic_inc(rs->stats + S_SUM_DELAYED_BIOS); + + /* Force bandwidth tests in recovery. */ + SetRSBandwidth(rs); + } else { + /* + * Process ios to non-recovering regions by queueing + * them to stripes (does dm_rh_inc()) for writes). + */ + flush += stripe_queue_bio(rs, bio, &reject); + } + } + + if (flush) { + /* FIXME: better error handling. */ + r = dm_rh_flush(rh); /* Writes got queued -> flush dirty log. */ + if (r) + DMERR_LIMIT("dirty log flush"); + } + + /* Merge any rejected bios back to the head of the input list. */ + bio_list_merge_head(ios, &reject); +} + +/* Unplug: let any queued io role on the sets devices. */ +static void do_unplug(struct raid_set *rs) +{ + struct raid_dev *dev = rs->dev + rs->set.raid_devs; + + while (dev-- > rs->dev) { + /* Only call any device unplug function, if io got queued. */ + if (TestClearDevIoQueued(dev)) + blk_unplug(bdev_get_queue(dev->dev->bdev)); + } +} + +/* Send an event in case we're getting too busy. */ +static void do_busy_event(struct raid_set *rs) +{ + if (sc_busy(rs)) { + if (!TestSetRSScBusy(rs)) + schedule_work(&rs->io.ws_do_table_event); + } + + ClearRSScBusy(rs); +} + +/* Throw an event. */ +static void do_table_event(struct work_struct *ws) +{ + struct raid_set *rs = container_of(ws, struct raid_set, + io.ws_do_table_event); + dm_table_event(rs->ti->table); +} + + +/*----------------------------------------------------------------- + * RAID daemon + *---------------------------------------------------------------*/ +/* + * o belabour all end ios + * o update the region hash states + * o optionally shrink the stripe cache + * o optionally do recovery + * o unplug any component raid devices with queued bios + * o grab the input queue + * o work an all requeued or new ios and perform stripe cache flushs + * o unplug any component raid devices with queued bios + * o check, if the stripe cache gets too busy and throw an event if so + */ +static void do_raid(struct work_struct *ws) +{ + struct raid_set *rs = container_of(ws, struct raid_set, + io.dws_do_raid.work); + struct bio_list *ios = &rs->io.work, *ios_in = &rs->io.in; + + /* + * We always need to end io, so that ios can get errored in + * case the set failed and the region counters get decremented + * before we update region hash states and go any further. + */ + do_endios(rs); + dm_rh_update_states(rs->recover.rh, 1); + + /* + * Now that we've end io'd, which may have put stripes on the LRU list + * to allow for shrinking, we resize the stripe cache if requested. + */ + do_sc_resize(rs); + + /* Try to recover regions. */ + do_recovery(rs); + do_unplug(rs); /* Unplug the sets device queues. */ + + /* Quickly grab all new ios queued and add them to the work list. */ + mutex_lock(&rs->io.in_lock); + bio_list_merge(ios, ios_in); + bio_list_init(ios_in); + mutex_unlock(&rs->io.in_lock); + + if (!bio_list_empty(ios)) + do_ios(rs, ios); /* Got ios to work into the cache. */ + + do_flush(rs); /* Flush any stripes on io list. */ + do_unplug(rs); /* Unplug the sets device queues. */ + do_busy_event(rs); /* Check if we got too busy. */ +} + +/* + * Callback for region hash to dispatch + * delayed bios queued to recovered regions + * (gets called via dm_rh_update_states()). + */ +static void dispatch_delayed_bios(void *context, struct bio_list *bl) +{ + struct raid_set *rs = context; + struct bio *bio; + + /* REMOVEME: statistics; decrement pending delayed bios counter. */ + bio_list_for_each(bio, bl) + atomic_dec(rs->stats + S_DELAYED_BIOS); + + /* Merge region hash private list to work list. */ + bio_list_merge_head(&rs->io.work, bl); + bio_list_init(bl); + ClearRSBandwidth(rs); +} + +/************************************************************* + * Constructor helpers + *************************************************************/ +/* Calculate MB/sec. */ +static unsigned mbpers(struct raid_set *rs, unsigned speed) +{ + return to_bytes(speed * rs->set.data_devs * + rs->recover.io_size * HZ >> 10) >> 10; +} + +/* + * Discover fastest xor algorithm and # of chunks combination. + */ +/* Calculate speed for algorithm and # of chunks. */ +static unsigned xor_speed(struct stripe *stripe) +{ + unsigned r = 0; + unsigned long j; + + /* Wait for next tick. */ + for (j = jiffies; j == jiffies; ) + ; + + /* Do xors for a full tick. */ + for (j = jiffies; j == jiffies; ) { + mb(); + common_xor(stripe, stripe->io.size, 0, 0); + mb(); + r++; + } + + return r; +} + +/* Optimize xor algorithm for this RAID set. */ +static unsigned xor_optimize(struct raid_set *rs) +{ + unsigned chunks_max = 2, p = rs->set.raid_devs, speed_max = 0; + struct xor_func *f = ARRAY_END(xor_funcs), *f_max = NULL; + struct stripe *stripe; + + BUG_ON(list_empty(&rs->recover.stripes)); + stripe = list_first_entry(&rs->recover.stripes, struct stripe, + lists[LIST_RECOVER]); + + /* Must set uptodate so that xor() will belabour chunks. */ + while (p--) + SetChunkUptodate(CHUNK(stripe, p)); + + /* Try all xor functions. */ + while (f-- > xor_funcs) { + unsigned speed; + + /* Set actual xor function for common_xor(). */ + rs->xor.f = f; + rs->xor.chunks = (f->f == xor_blocks_wrapper ? + (MAX_XOR_BLOCKS + 1) : XOR_CHUNKS_MAX) + 1; + + while (rs->xor.chunks-- > 2) { + speed = xor_speed(stripe); + if (speed > speed_max) { + speed_max = speed; + chunks_max = rs->xor.chunks; + f_max = f; + } + } + } + + /* Memorize optimum parameters. */ + rs->xor.f = f_max; + rs->xor.chunks = chunks_max; + return speed_max; +} + +/* + * Allocate a RAID context (a RAID set) + */ +/* Structure for variable RAID parameters. */ +struct variable_parms { + int bandwidth; + int bandwidth_parm; + int chunk_size; + int chunk_size_parm; + int io_size; + int io_size_parm; + int stripes; + int stripes_parm; + int recover_io_size; + int recover_io_size_parm; + int raid_parms; + int recovery; + int recovery_stripes; + int recovery_stripes_parm; +}; + +static struct raid_set * +context_alloc(struct raid_type *raid_type, struct variable_parms *p, + unsigned raid_devs, sector_t sectors_per_dev, + struct dm_target *ti, unsigned dl_parms, char **argv) +{ + int r; + size_t len; + sector_t region_size, ti_len; + struct raid_set *rs = NULL; + struct dm_dirty_log *dl; + struct recover *rec; + + /* + * Create the dirty log + * + * We need to change length for the dirty log constructor, + * because we want an amount of regions for all stripes derived + * from the single device size, so that we can keep region + * size = 2^^n independant of the number of devices + */ + ti_len = ti->len; + ti->len = sectors_per_dev; + dl = dm_dirty_log_create(argv[0], ti, NULL, dl_parms, argv + 2); + ti->len = ti_len; + if (!dl) + goto bad_dirty_log; + + /* Chunk size *must* be smaller than region size. */ + region_size = dl->type->get_region_size(dl); + if (p->chunk_size > region_size) + goto bad_chunk_size; + + /* Recover io size *must* be smaller than region size as well. */ + if (p->recover_io_size > region_size) + goto bad_recover_io_size; + + /* Size and allocate the RAID set structure. */ + len = sizeof(*rs->data) + sizeof(*rs->dev); + if (dm_array_too_big(sizeof(*rs), len, raid_devs)) + goto bad_array; + + len = sizeof(*rs) + raid_devs * len; + rs = kzalloc(len, GFP_KERNEL); + if (!rs) + goto bad_alloc; + + rec = &rs->recover; + atomic_set(&rs->io.in_process, 0); + atomic_set(&rs->io.in_process_max, 0); + rec->io_size = p->recover_io_size; + + /* Pointer to data array. */ + rs->data = (unsigned long **) + ((void *) rs->dev + raid_devs * sizeof(*rs->dev)); + rec->dl = dl; + rs->set.raid_devs = raid_devs; + rs->set.data_devs = raid_devs - raid_type->parity_devs; + rs->set.raid_type = raid_type; + + rs->set.raid_parms = p->raid_parms; + rs->set.chunk_size_parm = p->chunk_size_parm; + rs->set.io_size_parm = p->io_size_parm; + rs->sc.stripes_parm = p->stripes_parm; + rec->io_size_parm = p->recover_io_size_parm; + rec->bandwidth_parm = p->bandwidth_parm; + rec->recovery = p->recovery; + rec->recovery_stripes = p->recovery_stripes; + + /* + * Set chunk and io size and respective shifts + * (used to avoid divisions) + */ + rs->set.chunk_size = p->chunk_size; + rs->set.chunk_shift = ffs(p->chunk_size) - 1; + + rs->set.io_size = p->io_size; + rs->set.io_mask = p->io_size - 1; + /* Mask to adjust address key in case io_size != chunk_size. */ + rs->set.io_inv_mask = (p->chunk_size - 1) & ~rs->set.io_mask; + + rs->set.sectors_per_dev = sectors_per_dev; + + rs->set.ei = -1; /* Indicate no failed device. */ + atomic_set(&rs->set.failed_devs, 0); + + rs->ti = ti; + + atomic_set(rec->io_count + IO_WORK, 0); + atomic_set(rec->io_count + IO_RECOVER, 0); + + /* Initialize io lock and queues. */ + mutex_init(&rs->io.in_lock); + bio_list_init(&rs->io.in); + bio_list_init(&rs->io.work); + + init_waitqueue_head(&rs->io.suspendq); /* Suspend waiters (dm-io). */ + + rec->nr_regions = dm_sector_div_up(sectors_per_dev, region_size); + rec->rh = dm_region_hash_create(rs, dispatch_delayed_bios, + wake_dummy, wake_do_raid, 0, p->recovery_stripes, + dl, region_size, rec->nr_regions); + if (IS_ERR(rec->rh)) + goto bad_rh; + + /* Initialize stripe cache. */ + r = sc_init(rs, p->stripes); + if (r) + goto bad_sc; + + /* REMOVEME: statistics. */ + stats_reset(rs); + ClearRSDevelStats(rs); /* Disnable development status. */ + return rs; + +bad_dirty_log: + TI_ERR_RET("Error creating dirty log", ERR_PTR(-ENOMEM)); + +bad_chunk_size: + dm_dirty_log_destroy(dl); + TI_ERR_RET("Chunk size larger than region size", ERR_PTR(-EINVAL)); + +bad_recover_io_size: + dm_dirty_log_destroy(dl); + TI_ERR_RET("Recover stripe io size larger than region size", + ERR_PTR(-EINVAL)); + +bad_array: + dm_dirty_log_destroy(dl); + TI_ERR_RET("Arry too big", ERR_PTR(-EINVAL)); + +bad_alloc: + dm_dirty_log_destroy(dl); + TI_ERR_RET("Cannot allocate raid context", ERR_PTR(-ENOMEM)); + +bad_rh: + dm_dirty_log_destroy(dl); + ti->error = DM_MSG_PREFIX "Error creating dirty region hash"; + goto free_rs; + +bad_sc: + dm_region_hash_destroy(rec->rh); /* Destroys dirty log too. */ + sc_exit(&rs->sc); + ti->error = DM_MSG_PREFIX "Error creating stripe cache"; +free_rs: + kfree(rs); + return ERR_PTR(-ENOMEM); +} + +/* Free a RAID context (a RAID set). */ +static void context_free(struct raid_set *rs, unsigned p) +{ + while (p--) + dm_put_device(rs->ti, rs->dev[p].dev); + + sc_exit(&rs->sc); + dm_region_hash_destroy(rs->recover.rh); /* Destroys dirty log too. */ + kfree(rs); +} + +/* Create work queue and initialize delayed work. */ +static int rs_workqueue_init(struct raid_set *rs) +{ + struct dm_target *ti = rs->ti; + + rs->io.wq = create_singlethread_workqueue(DAEMON); + if (!rs->io.wq) + TI_ERR_RET("failed to create " DAEMON, -ENOMEM); + + INIT_DELAYED_WORK(&rs->io.dws_do_raid, do_raid); + INIT_WORK(&rs->io.ws_do_table_event, do_table_event); + return 0; +} + +/* Return pointer to raid_type structure for raid name. */ +static struct raid_type *get_raid_type(char *name) +{ + struct raid_type *r = ARRAY_END(raid_types); + + while (r-- > raid_types) { + if (!strcmp(r->name, name)) + return r; + } + + return NULL; +} + +/* FIXME: factor out to dm core. */ +static int multiple(sector_t a, sector_t b, sector_t *n) +{ + sector_t r = a; + + sector_div(r, b); + *n = r; + return a == r * b; +} + +/* Log RAID set information to kernel log. */ +static void rs_log(struct raid_set *rs, unsigned speed) +{ + unsigned p; + char buf[BDEVNAME_SIZE]; + + for (p = 0; p < rs->set.raid_devs; p++) + DMINFO("/dev/%s is raid disk %u%s", + bdevname(rs->dev[p].dev->bdev, buf), p, + (p == rs->set.pi) ? " (parity)" : ""); + + DMINFO("%d/%d/%d sectors chunk/io/recovery size, %u stripes\n" + "algorithm \"%s\", %u chunks with %uMB/s\n" + "%s set with net %u/%u devices", + rs->set.chunk_size, rs->set.io_size, rs->recover.io_size, + atomic_read(&rs->sc.stripes), + rs->xor.f->name, rs->xor.chunks, mbpers(rs, speed), + rs->set.raid_type->descr, rs->set.data_devs, rs->set.raid_devs); +} + +/* Get all devices and offsets. */ +static int dev_parms(struct raid_set *rs, char **argv, int *p) +{ + struct dm_target *ti = rs->ti; + + for (*p = 0; *p < rs->set.raid_devs; (*p)++, argv += 2) { + int r; + unsigned long long tmp; + struct raid_dev *dev = rs->dev + *p; + + /* Get offset and device. */ + if (sscanf(argv[1], "%llu", &tmp) != 1 || + tmp > rs->set.sectors_per_dev) + TI_ERR("Invalid RAID device offset parameter"); + + dev->start = tmp; + r = dm_get_device(ti, *argv, dm_table_get_mode(ti->table), &dev->dev); + if (r) + TI_ERR_RET("RAID device lookup failure", r); + + r = raid_dev_lookup(rs, dev); + if (r != -ENODEV && r < *p) { + (*p)++; /* Ensure dm_put_device() on actual device. */ + TI_ERR_RET("Duplicate RAID device", -ENXIO); + } + } + + return 0; +} + +/* Set recovery bandwidth. */ +static void +recover_set_bandwidth(struct raid_set *rs, unsigned bandwidth) +{ + rs->recover.bandwidth = bandwidth; + rs->recover.bandwidth_work = 100 / bandwidth; +} + +/* Handle variable number of RAID parameters. */ +static int get_raid_variable_parms(struct dm_target *ti, char **argv, + struct variable_parms *vp) +{ + int p, value; + struct { + int action; /* -1: skip, 0: no pwer2 check, 1: power2 check */ + char *errmsg; + int min, max; + int *var, *var2, *var3; + } argctr[] = { + { 1, + "Invalid chunk size; must be -1 or 2^^n and <= 16384", + IO_SIZE_MIN, CHUNK_SIZE_MAX, + &vp->chunk_size_parm, &vp->chunk_size, &vp->io_size }, + { 0, + "Invalid number of stripes: must be -1 or >= 8 and <= 16384", + STRIPES_MIN, STRIPES_MAX, + &vp->stripes_parm, &vp->stripes, NULL }, + { 1, + "Invalid io size; must -1 or >= 8, 2^^n and less equal " + "min(BIO_MAX_SECTORS/2, chunk size)", + IO_SIZE_MIN, 0, /* Needs to be updated in loop below. */ + &vp->io_size_parm, &vp->io_size, NULL }, + { 1, + "Invalid recovery io size; must be -1 or " + "2^^n and less equal BIO_MAX_SECTORS/2", + RECOVER_IO_SIZE_MIN, BIO_MAX_SECTORS / 2, + &vp->recover_io_size_parm, &vp->recover_io_size, NULL }, + { 0, + "Invalid recovery bandwidth percentage; " + "must be -1 or > 0 and <= 100", + BANDWIDTH_MIN, BANDWIDTH_MAX, + &vp->bandwidth_parm, &vp->bandwidth, NULL }, + /* Handle sync argument seperately in loop. */ + { -1, + "Invalid recovery switch; must be \"sync\" or \"nosync\"" }, + { 0, + "Invalid number of recovery stripes;" + "must be -1, > 0 and <= 16384", + RECOVERY_STRIPES_MIN, RECOVERY_STRIPES_MAX, + &vp->recovery_stripes_parm, &vp->recovery_stripes, NULL }, + }, *varp; + + /* Fetch # of variable raid parameters. */ + if (sscanf(*(argv++), "%d", &vp->raid_parms) != 1 || + !range_ok(vp->raid_parms, 0, 7)) + TI_ERR("Bad variable raid parameters number"); + + /* Preset variable RAID parameters. */ + vp->chunk_size = CHUNK_SIZE_DEFAULT; + vp->io_size = IO_SIZE_DEFAULT; + vp->stripes = STRIPES_DEFAULT; + vp->recover_io_size = RECOVER_IO_SIZE_DEFAULT; + vp->bandwidth = BANDWIDTH_DEFAULT; + vp->recovery = 1; + vp->recovery_stripes = RECOVERY_STRIPES_DEFAULT; + + /* Walk the array of argument constraints for all given ones. */ + for (p = 0, varp = argctr; p < vp->raid_parms; p++, varp++) { + BUG_ON(varp >= ARRAY_END(argctr)); + + /* Special case for "[no]sync" string argument. */ + if (varp->action < 0) { + if (!strcmp(*argv, "sync")) + ; + else if (!strcmp(*argv, "nosync")) + vp->recovery = 0; + else + TI_ERR(varp->errmsg); + + argv++; + continue; + } + + /* + * Special case for io_size depending + * on previously set chunk size. + */ + if (p == 2) + varp->max = min(BIO_MAX_SECTORS / 2, vp->chunk_size); + + if (sscanf(*(argv++), "%d", &value) != 1 || + (value != -1 && + ((varp->action && !POWER_OF_2(value)) || + !range_ok(value, varp->min, varp->max)))) + TI_ERR(varp->errmsg); + + *varp->var = value; + if (value != -1) { + if (varp->var2) + *varp->var2 = value; + if (varp->var3) + *varp->var3 = value; + } + } + + return 0; +} + +/* Parse optional locking parameters. */ +static int get_raid_locking_parms(struct dm_target *ti, char **argv, + int *locking_parms, + struct dm_raid45_locking_type **locking_type) +{ + if (!strnicmp(argv[0], "locking", strlen(argv[0]))) { + char *lckstr = argv[1]; + size_t lcksz = strlen(lckstr); + + if (!strnicmp(lckstr, "none", lcksz)) { + *locking_type = &locking_none; + *locking_parms = 2; + } else if (!strnicmp(lckstr, "cluster", lcksz)) { + DMERR("locking type \"%s\" not yet implemented", + lckstr); + return -EINVAL; + } else { + DMERR("unknown locking type \"%s\"", lckstr); + return -EINVAL; + } + } + + *locking_parms = 0; + *locking_type = &locking_none; + return 0; +} + +/* Set backing device read ahead properties of RAID set. */ +static void rs_set_read_ahead(struct raid_set *rs, + unsigned sectors, unsigned stripes) +{ + unsigned ra_pages = dm_div_up(sectors, SECTORS_PER_PAGE); + struct mapped_device *md = dm_table_get_md(rs->ti->table); + struct backing_dev_info *bdi = &dm_disk(md)->queue->backing_dev_info; + + /* Set read-ahead for the RAID set and the component devices. */ + if (ra_pages) { + unsigned p = rs->set.raid_devs; + + bdi->ra_pages = stripes * ra_pages * rs->set.data_devs; + + while (p--) { + struct request_queue *q = + bdev_get_queue(rs->dev[p].dev->bdev); + + q->backing_dev_info.ra_pages = ra_pages; + } + } + + dm_put(md); +} + +/* Set congested function. */ +static void rs_set_congested_fn(struct raid_set *rs) +{ + struct mapped_device *md = dm_table_get_md(rs->ti->table); + struct backing_dev_info *bdi = &dm_disk(md)->queue->backing_dev_info; + + /* Set congested function and data. */ + bdi->congested_fn = rs_congested; + bdi->congested_data = rs; + dm_put(md); +} + +/* + * Construct a RAID4/5 mapping: + * + * log_type #log_params \ + * raid_type [#parity_dev] #raid_variable_params \ + * [locking "none"/"cluster"] + * #raid_devs #dev_to_initialize [ ]{3,} + * + * log_type = "core"/"disk", + * #log_params = 1-3 (1-2 for core dirty log type, 3 for disk dirty log only) + * log_params = [dirty_log_path] region_size [[no]sync]) + * + * raid_type = "raid4", "raid5_la", "raid5_ra", "raid5_ls", "raid5_rs" + * + * #parity_dev = N if raid_type = "raid4" + * o N = -1: pick default = last device + * o N >= 0 and < #raid_devs: parity device index + * + * #raid_variable_params = 0-7; raid_params (-1 = default): + * [chunk_size [#stripes [io_size [recover_io_size \ + * [%recovery_bandwidth [recovery_switch [#recovery_stripes]]]]]]] + * o chunk_size (unit to calculate drive addresses; must be 2^^n, > 8 + * and <= CHUNK_SIZE_MAX) + * o #stripes is number of stripes allocated to stripe cache + * (must be > 1 and < STRIPES_MAX) + * o io_size (io unit size per device in sectors; must be 2^^n and > 8) + * o recover_io_size (io unit size per device for recovery in sectors; + must be 2^^n, > SECTORS_PER_PAGE and <= region_size) + * o %recovery_bandwith is the maximum amount spend for recovery during + * application io (1-100%) + * o recovery switch = [sync|nosync] + * o #recovery_stripes is the number of recovery stripes used for + * parallel recovery of the RAID set + * If raid_variable_params = 0, defaults will be used. + * Any raid_variable_param can be set to -1 to apply a default + * + * #raid_devs = N (N >= 3) + * + * #dev_to_initialize = N + * -1: initialize parity on all devices + * >= 0 and < #raid_devs: initialize raid_path; used to force reconstruction + * of a failed devices content after replacement + * + * = device_path (eg, /dev/sdd1) + * = begin at offset on + * + */ +#define MIN_PARMS 13 +static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv) +{ + int dev_to_init, dl_parms, i, locking_parms, + parity_parm, pi = -1, r, raid_devs; + unsigned speed; + sector_t tmp, sectors_per_dev; + struct dm_raid45_locking_type *locking; + struct raid_set *rs; + struct raid_type *raid_type; + struct variable_parms parms; + + /* Ensure minimum number of parameters. */ + if (argc < MIN_PARMS) + TI_ERR("Not enough parameters"); + + /* Fetch # of dirty log parameters. */ + if (sscanf(argv[1], "%d", &dl_parms) != 1 || + !range_ok(dl_parms, 1, 4711)) /* ;-) */ + TI_ERR("Bad dirty log parameters number"); + + /* Check raid_type. */ + raid_type = get_raid_type(argv[dl_parms + 2]); + if (!raid_type) + TI_ERR("Bad raid type"); + + /* In case of RAID4, parity drive is selectable. */ + parity_parm = !!(raid_type->level == raid4); + + /* Handle variable number of RAID parameters. */ + r = get_raid_variable_parms(ti, argv + dl_parms + parity_parm + 3, + &parms); + if (r) + return r; + + /* Handle any locking parameters. */ + r = get_raid_locking_parms(ti, + argv + dl_parms + parity_parm + + parms.raid_parms + 4, + &locking_parms, &locking); + if (r) + return r; + + /* # of raid devices. */ + i = dl_parms + parity_parm + parms.raid_parms + locking_parms + 4; + if (sscanf(argv[i], "%d", &raid_devs) != 1 || + raid_devs < raid_type->minimal_devs) + TI_ERR("Invalid number of raid devices"); + + /* In case of RAID4, check parity drive index is in limits. */ + if (raid_type->level == raid4) { + /* Fetch index of parity device. */ + if (sscanf(argv[dl_parms + 3], "%d", &pi) != 1 || + (pi != -1 && !range_ok(pi, 0, raid_devs - 1))) + TI_ERR("Invalid RAID4 parity device index"); + } + + /* + * Index of device to initialize starts at 0 + * + * o -1 -> don't initialize a selected device; + * initialize parity conforming to algorithm + * o 0..raid_devs-1 -> initialize respective device + * (used for reconstruction of a replaced device) + */ + if (sscanf(argv[dl_parms + parity_parm + parms.raid_parms + + locking_parms + 5], "%d", &dev_to_init) != 1 || + !range_ok(dev_to_init, -1, raid_devs - 1)) + TI_ERR("Invalid number for raid device to initialize"); + + /* Check # of raid device arguments. */ + if (argc - dl_parms - parity_parm - parms.raid_parms - 6 != + 2 * raid_devs) + TI_ERR("Wrong number of raid device/offset arguments"); + + /* + * Check that the table length is devisable + * w/o rest by (raid_devs - parity_devs) + */ + if (!multiple(ti->len, raid_devs - raid_type->parity_devs, + §ors_per_dev)) + TI_ERR("Target length not divisible by number of data devices"); + + /* + * Check that the device size is + * devisable w/o rest by chunk size + */ + if (!multiple(sectors_per_dev, parms.chunk_size, &tmp)) + TI_ERR("Device length not divisible by chunk_size"); + + /**************************************************************** + * Now that we checked the constructor arguments -> + * let's allocate the RAID set + ****************************************************************/ + rs = context_alloc(raid_type, &parms, raid_devs, sectors_per_dev, + ti, dl_parms, argv); + if (IS_ERR(rs)) + return PTR_ERR(rs); + + + rs->set.dev_to_init = rs->set.dev_to_init_parm = dev_to_init; + rs->set.pi = rs->set.pi_parm = pi; + + /* Set RAID4 parity drive index. */ + if (raid_type->level == raid4) + rs->set.pi = (pi == -1) ? rs->set.data_devs : pi; + + recover_set_bandwidth(rs, parms.bandwidth); + + /* Use locking type to lock stripe access. */ + rs->locking = locking; + + /* Get the device/offset tupels. */ + argv += dl_parms + 6 + parity_parm + parms.raid_parms; + r = dev_parms(rs, argv, &i); + if (r) + goto err; + + /* Set backing device information (eg. read ahead). */ + rs_set_read_ahead(rs, 2 * rs->set.chunk_size, 4 /* stripes */); + rs_set_congested_fn(rs); /* Set congested function. */ + SetRSCheckOverwrite(rs); /* Allow chunk overwrite checks. */ + speed = xor_optimize(rs); /* Select best xor algorithm. */ + + /* Set for recovery of any nosync regions. */ + if (parms.recovery) + SetRSRecover(rs); + else { + /* + * Need to free recovery stripe(s) here in case + * of nosync, because xor_optimize uses one. + */ + set_start_recovery(rs); + set_end_recovery(rs); + stripe_recover_free(rs); + } + + /* + * Make sure that dm core only hands maximum io size + * length down and pays attention to io boundaries. + */ + ti->split_io = rs->set.io_size; + ti->private = rs; + + /* Initialize work queue to handle this RAID set's io. */ + r = rs_workqueue_init(rs); + if (r) + goto err; + + rs_log(rs, speed); /* Log information about RAID set. */ + return 0; + +err: + context_free(rs, i); + return r; +} + +/* + * Destruct a raid mapping + */ +static void raid_dtr(struct dm_target *ti) +{ + struct raid_set *rs = ti->private; + + destroy_workqueue(rs->io.wq); + context_free(rs, rs->set.raid_devs); +} + +/* Raid mapping function. */ +static int raid_map(struct dm_target *ti, struct bio *bio, + union map_info *map_context) +{ + /* I don't want to waste stripe cache capacity. */ + if (bio_rw(bio) == READA) + return -EIO; + else { + struct raid_set *rs = ti->private; + + /* + * Get io reference to be waiting for to drop + * to zero on device suspension/destruction. + */ + io_get(rs); + bio->bi_sector -= ti->begin; /* Remap sector. */ + + /* Queue io to RAID set. */ + mutex_lock(&rs->io.in_lock); + bio_list_add(&rs->io.in, bio); + mutex_unlock(&rs->io.in_lock); + + /* Wake daemon to process input list. */ + wake_do_raid(rs); + + /* REMOVEME: statistics. */ + atomic_inc(rs->stats + (bio_data_dir(bio) == READ ? + S_BIOS_READ : S_BIOS_WRITE)); + return DM_MAPIO_SUBMITTED; /* Handle later. */ + } +} + +/* Device suspend. */ +static void raid_presuspend(struct dm_target *ti) +{ + struct raid_set *rs = ti->private; + struct dm_dirty_log *dl = rs->recover.dl; + + SetRSSuspend(rs); + + if (RSRecover(rs)) + dm_rh_stop_recovery(rs->recover.rh); + + cancel_delayed_work(&rs->io.dws_do_raid); + flush_workqueue(rs->io.wq); + wait_ios(rs); /* Wait for completion of all ios being processed. */ + + if (dl->type->presuspend && dl->type->presuspend(dl)) + /* FIXME: need better error handling. */ + DMWARN("log presuspend failed"); +} + +static void raid_postsuspend(struct dm_target *ti) +{ + struct raid_set *rs = ti->private; + struct dm_dirty_log *dl = rs->recover.dl; + + if (dl->type->postsuspend && dl->type->postsuspend(dl)) + /* FIXME: need better error handling. */ + DMWARN("log postsuspend failed"); + +} + +/* Device resume. */ +static void raid_resume(struct dm_target *ti) +{ + struct raid_set *rs = ti->private; + struct recover *rec = &rs->recover; + struct dm_dirty_log *dl = rec->dl; + + if (dl->type->resume && dl->type->resume(dl)) + /* Resume dirty log. */ + /* FIXME: need better error handling. */ + DMWARN("log resume failed"); + + rec->nr_regions_to_recover = + rec->nr_regions - dl->type->get_sync_count(dl); + + /* Restart any unfinished recovery. */ + if (RSRecover(rs)) { + set_start_recovery(rs); + dm_rh_start_recovery(rec->rh); + } + + ClearRSSuspend(rs); + wake_do_raid(rs); +} + +/* Return stripe cache size. */ +static unsigned sc_size(struct raid_set *rs) +{ + return to_sector(atomic_read(&rs->sc.stripes) * + (sizeof(struct stripe) + + (sizeof(struct stripe_chunk) + + (sizeof(struct page_list) + + to_bytes(rs->set.io_size) * + rs->set.raid_devs)) + + (rs->recover.end_jiffies ? + 0 : rs->recover.recovery_stripes * + to_bytes(rs->set.raid_devs * rs->recover.io_size)))); +} + +/* REMOVEME: status output for development. */ +static void raid_devel_stats(struct dm_target *ti, char *result, + unsigned *size, unsigned maxlen) +{ + unsigned sz = *size; + unsigned long j; + char buf[BDEVNAME_SIZE], *p; + struct stats_map *sm; + struct raid_set *rs = ti->private; + struct recover *rec = &rs->recover; + struct timespec ts; + + DMEMIT("%s %s %u\n", version, rs->xor.f->name, rs->xor.chunks); + DMEMIT("act_ios=%d ", io_ref(rs)); + DMEMIT("act_ios_max=%d\n", atomic_read(&rs->io.in_process_max)); + DMEMIT("act_stripes=%d ", sc_active(&rs->sc)); + DMEMIT("act_stripes_max=%d\n", + atomic_read(&rs->sc.active_stripes_max)); + + for (sm = stats_map; sm < ARRAY_END(stats_map); sm++) + DMEMIT("%s%d", sm->str, atomic_read(rs->stats + sm->type)); + + DMEMIT(" checkovr=%s\n", RSCheckOverwrite(rs) ? "on" : "off"); + DMEMIT("sc=%u/%u/%u/%u/%u/%u/%u\n", rs->set.chunk_size, + atomic_read(&rs->sc.stripes), rs->set.io_size, + rec->recovery_stripes, rec->io_size, rs->sc.hash.buckets, + sc_size(rs)); + + j = (rec->end_jiffies ? rec->end_jiffies : jiffies) - + rec->start_jiffies; + jiffies_to_timespec(j, &ts); + sprintf(buf, "%ld.%ld", ts.tv_sec, ts.tv_nsec); + p = strchr(buf, '.'); + p[3] = 0; + + DMEMIT("rg=%llu/%llu/%llu/%u %s\n", + (unsigned long long) rec->nr_regions_recovered, + (unsigned long long) rec->nr_regions_to_recover, + (unsigned long long) rec->nr_regions, rec->bandwidth, buf); + + *size = sz; +} + +static int raid_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) +{ + unsigned p, sz = 0; + char buf[BDEVNAME_SIZE]; + struct raid_set *rs = ti->private; + int raid_parms[] = { + rs->set.chunk_size_parm, + rs->sc.stripes_parm, + rs->set.io_size_parm, + rs->recover.io_size_parm, + rs->recover.bandwidth_parm, + -2, + rs->recover.recovery_stripes, + }; + + switch (type) { + case STATUSTYPE_INFO: + /* REMOVEME: statistics. */ + if (RSDevelStats(rs)) + raid_devel_stats(ti, result, &sz, maxlen); + + DMEMIT("%u ", rs->set.raid_devs); + + for (p = 0; p < rs->set.raid_devs; p++) + DMEMIT("%s ", + format_dev_t(buf, rs->dev[p].dev->bdev->bd_dev)); + + DMEMIT("1 "); + for (p = 0; p < rs->set.raid_devs; p++) { + DMEMIT("%c", !DevFailed(rs->dev + p) ? 'A' : 'D'); + + if (p == rs->set.pi) + DMEMIT("p"); + + if (rs->set.dev_to_init == p) + DMEMIT("i"); + } + + break; + case STATUSTYPE_TABLE: + sz = rs->recover.dl->type->status(rs->recover.dl, type, + result, maxlen); + DMEMIT("%s %u ", rs->set.raid_type->name, + rs->set.raid_parms); + + for (p = 0; p < rs->set.raid_parms; p++) { + if (raid_parms[p] > -2) + DMEMIT("%d ", raid_parms[p]); + else + DMEMIT("%s ", rs->recover.recovery ? + "sync" : "nosync"); + } + + DMEMIT("%u %d ", rs->set.raid_devs, rs->set.dev_to_init); + + for (p = 0; p < rs->set.raid_devs; p++) + DMEMIT("%s %llu ", + format_dev_t(buf, rs->dev[p].dev->bdev->bd_dev), + (unsigned long long) rs->dev[p].start); + } + + return 0; +} + +/* + * Message interface + */ +enum raid_msg_actions { + act_bw, /* Recovery bandwidth switch. */ + act_dev, /* Device failure switch. */ + act_overwrite, /* Stripe overwrite check. */ + act_stats, /* Development statistics switch. */ + act_sc, /* Stripe cache switch. */ + + act_on, /* Set entity on. */ + act_off, /* Set entity off. */ + act_reset, /* Reset entity. */ + + act_set = act_on, /* Set # absolute. */ + act_grow = act_off, /* Grow # by an amount. */ + act_shrink = act_reset, /* Shrink # by an amount. */ +}; + +/* Turn a delta into an absolute value. */ +static int _absolute(unsigned long action, int act, int r) +{ + /* Make delta absolute. */ + if (test_bit(act_set, &action)) + ; + else if (test_bit(act_grow, &action)) + r += act; + else if (test_bit(act_shrink, &action)) + r = act - r; + else + r = -EINVAL; + + return r; +} + + /* Change recovery io bandwidth. */ +static int bandwidth_change(struct dm_msg *msg, void *context) +{ + struct raid_set *rs = context; + int act = rs->recover.bandwidth; + int bandwidth = DM_MSG_INT_ARG(msg); + + if (range_ok(bandwidth, BANDWIDTH_MIN, BANDWIDTH_MAX)) { + /* Make delta bandwidth absolute. */ + bandwidth = _absolute(msg->action, act, bandwidth); + + /* Check range. */ + if (range_ok(bandwidth, BANDWIDTH_MIN, BANDWIDTH_MAX)) { + recover_set_bandwidth(rs, bandwidth); + return 0; + } + } + + set_bit(dm_msg_ret_arg, &msg->ret); + set_bit(dm_msg_ret_inval, &msg->ret); + return -EINVAL; +} + +/* Set/reset development feature flags. */ +static int devel_flags(struct dm_msg *msg, void *context) +{ + struct raid_set *rs = context; + + if (test_bit(act_on, &msg->action)) + return test_and_set_bit(msg->spec->parm, + &rs->io.flags) ? -EPERM : 0; + else if (test_bit(act_off, &msg->action)) + return test_and_clear_bit(msg->spec->parm, + &rs->io.flags) ? 0 : -EPERM; + else if (test_bit(act_reset, &msg->action)) { + if (test_bit(act_stats, &msg->action)) { + stats_reset(rs); + goto on; + } else if (test_bit(act_overwrite, &msg->action)) { +on: + set_bit(msg->spec->parm, &rs->io.flags); + return 0; + } + } + + return -EINVAL; +} + +/* Resize the stripe cache. */ +static int sc_resize(struct dm_msg *msg, void *context) +{ + int act, stripes; + struct raid_set *rs = context; + + /* Deny permission in case the daemon is still resizing!. */ + if (atomic_read(&rs->sc.stripes_to_set)) + return -EPERM; + + stripes = DM_MSG_INT_ARG(msg); + if (stripes > 0) { + act = atomic_read(&rs->sc.stripes); + + /* Make delta stripes absolute. */ + stripes = _absolute(msg->action, act, stripes); + + /* + * Check range and that the # of stripes changes. + * We leave the resizing to the wroker. + */ + if (range_ok(stripes, STRIPES_MIN, STRIPES_MAX) && + stripes != atomic_read(&rs->sc.stripes)) { + atomic_set(&rs->sc.stripes_to_set, stripes); + wake_do_raid(rs); + return 0; + } + } + + set_bit(dm_msg_ret_arg, &msg->ret); + set_bit(dm_msg_ret_inval, &msg->ret); + return -EINVAL; +} + +/* Parse the RAID message action. */ +/* + * 'ba[ndwidth] {se[t],g[row],sh[rink]} #' # e.g 'ba se 50' + * "o[verwrite] {on,of[f],r[eset]}' # e.g. 'o of' + * 'sta[tistics] {on,of[f],r[eset]}' # e.g. 'stat of' + * 'str[ipecache] {se[t],g[row],sh[rink]} #' # e.g. 'stripe set 1024' + * + */ +static int raid_message(struct dm_target *ti, unsigned argc, char **argv) +{ + /* Variables to store the parsed parameters im. */ + static int i[2]; + static unsigned long *i_arg[] = { + (unsigned long *) i + 0, + (unsigned long *) i + 1, + }; + + /* Declare all message option strings. */ + static char *str_sgs[] = { "set", "grow", "shrink" }; + static char *str_oor[] = { "on", "off", "reset" }; + + /* Declare all actions. */ + static unsigned long act_sgs[] = { act_set, act_grow, act_shrink }; + static unsigned long act_oor[] = { act_on, act_off, act_reset }; + + /* Bandwidth option. */ + static struct dm_message_option bw_opt = { 3, str_sgs, act_sgs }; + static struct dm_message_argument bw_args = { + 1, i_arg, { dm_msg_int_t } + }; + + static struct dm_message_argument null_args = { + 0, NULL, { dm_msg_int_t } + }; + + /* Overwrite and statistics option. */ + static struct dm_message_option ovr_stats_opt = { 3, str_oor, act_oor }; + + /* Sripecache option. */ + static struct dm_message_option stripe_opt = { 3, str_sgs, act_sgs }; + + /* Declare messages. */ + static struct dm_msg_spec specs[] = { + { "bandwidth", act_bw, &bw_opt, &bw_args, + 0, bandwidth_change }, + { "overwrite", act_overwrite, &ovr_stats_opt, &null_args, + RS_CHECK_OVERWRITE, devel_flags }, + { "statistics", act_stats, &ovr_stats_opt, &null_args, + RS_DEVEL_STATS, devel_flags }, + { "stripecache", act_sc, &stripe_opt, &bw_args, + 0, sc_resize }, + }; + + /* The message for the parser. */ + struct dm_msg msg = { + .num_specs = ARRAY_SIZE(specs), + .specs = specs, + }; + + return dm_message_parse(TARGET, &msg, ti->private, argc, argv); +} +/* + * END message interface + */ + +static struct target_type raid_target = { + .name = "raid45", + .version = {1, 0, 0}, + .module = THIS_MODULE, + .ctr = raid_ctr, + .dtr = raid_dtr, + .map = raid_map, + .presuspend = raid_presuspend, + .postsuspend = raid_postsuspend, + .resume = raid_resume, + .status = raid_status, + .message = raid_message, +}; + +static void init_exit(const char *bad_msg, const char *good_msg, int r) +{ + if (r) + DMERR("Failed to %sregister target [%d]", bad_msg, r); + else + DMINFO("%s %s", good_msg, version); +} + +static int __init dm_raid_init(void) +{ + int r = dm_register_target(&raid_target); + + init_exit("", "initialized", r); + return r; +} + +static void __exit dm_raid_exit(void) +{ + dm_unregister_target(&raid_target); + init_exit("un", "exit", 0); +} + +/* Module hooks. */ +module_init(dm_raid_init); +module_exit(dm_raid_exit); + +MODULE_DESCRIPTION(DM_NAME " raid4/5 target"); +MODULE_AUTHOR("Heinz Mauelshagen "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("dm-raid4"); +MODULE_ALIAS("dm-raid5"); --- linux-2.6.37.orig/ubuntu/dm-raid4-5/dm-raid4-5.h +++ linux-2.6.37/ubuntu/dm-raid4-5/dm-raid4-5.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2006 Red Hat GmbH + * + * Module Author: Heinz Mauelshagen (Mauelshagen@RedHat.com) + * + * This file is released under the GPL. + * + */ + +#ifndef _DM_RAID45_H +#define _DM_RAID45_H + +/* Factor out to dm.h! */ +#define STR_LEN(ptr, str) ptr, str, strlen(ptr) + +enum lock_type { RAID45_EX, RAID45_SHARED }; + +struct dmraid45_locking_type { + /* Request a lock on a stripe. */ + void* (*lock)(sector_t key, enum lock_type type); + + /* Release a lock on a stripe. */ + void (*unlock)(void *lock_handle); + +}; + +#endif --- linux-2.6.37.orig/ubuntu/dm-raid4-5/dm-raid45.h +++ linux-2.6.37/ubuntu/dm-raid4-5/dm-raid45.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. + * + * Module Author: Heinz Mauelshagen (Mauelshagen@RedHat.com) + * + * Locking definitions for the device-mapper RAID45 target. + * + * This file is released under the GPL. + * + */ + +#ifndef _DM_RAID45_H +#define _DM_RAID45_H + +/* Factor out to dm.h! */ +#define STR_LEN(ptr, str) (ptr), (str), strlen((ptr)) + +enum dm_lock_type { DM_RAID45_EX, DM_RAID45_SHARED }; + +struct dm_raid45_locking_type { + /* Request a lock on a stripe. */ + void* (*lock)(sector_t key, enum dm_lock_type type); + + /* Release a lock on a stripe. */ + void (*unlock)(void *lock_handle); +}; + +#endif --- linux-2.6.37.orig/ubuntu/dm-raid4-5/dm-region-hash.c +++ linux-2.6.37/ubuntu/dm-raid4-5/dm-region-hash.c @@ -0,0 +1,719 @@ +/* + * Copyright (C) 2003 Sistina Software Limited. + * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. + * + * This file is released under the GPL. + */ + +#include +#include "dm-region-hash.h" + +#include +#include +#include +#include +#include + +#include "dm.h" + +#define DM_MSG_PREFIX "region hash" + +/*----------------------------------------------------------------- + * Region hash + * + * The mirror splits itself up into discrete regions. Each + * region can be in one of three states: clean, dirty, + * nosync. There is no need to put clean regions in the hash. + * + * In addition to being present in the hash table a region _may_ + * be present on one of three lists. + * + * clean_regions: Regions on this list have no io pending to + * them, they are in sync, we are no longer interested in them, + * they are dull. dm_rh_update_states() will remove them from the + * hash table. + * + * quiesced_regions: These regions have been spun down, ready + * for recovery. rh_recovery_start() will remove regions from + * this list and hand them to kmirrord, which will schedule the + * recovery io with kcopyd. + * + * recovered_regions: Regions that kcopyd has successfully + * recovered. dm_rh_update_states() will now schedule any delayed + * io, up the recovery_count, and remove the region from the + * hash. + * + * There are 2 locks: + * A rw spin lock 'hash_lock' protects just the hash table, + * this is never held in write mode from interrupt context, + * which I believe means that we only have to disable irqs when + * doing a write lock. + * + * An ordinary spin lock 'region_lock' that protects the three + * lists in the region_hash, with the 'state', 'list' and + * 'delayed_bios' fields of the regions. This is used from irq + * context, so all other uses will have to suspend local irqs. + *---------------------------------------------------------------*/ +struct dm_region_hash { + uint32_t region_size; + unsigned region_shift; + + /* holds persistent region state */ + struct dm_dirty_log *log; + + /* hash table */ + rwlock_t hash_lock; + mempool_t *region_pool; + unsigned mask; + unsigned nr_buckets; + unsigned prime; + unsigned shift; + struct list_head *buckets; + + unsigned max_recovery; /* Max # of regions to recover in parallel */ + + spinlock_t region_lock; + atomic_t recovery_in_flight; + struct semaphore recovery_count; + struct list_head clean_regions; + struct list_head quiesced_regions; + struct list_head recovered_regions; + struct list_head failed_recovered_regions; + + void *context; + sector_t target_begin; + + /* Callback function to schedule bios writes */ + void (*dispatch_bios)(void *context, struct bio_list *bios); + + /* Callback function to wakeup callers worker thread. */ + void (*wakeup_workers)(void *context); + + /* Callback function to wakeup callers recovery waiters. */ + void (*wakeup_all_recovery_waiters)(void *context); +}; + +struct dm_region { + struct dm_region_hash *rh; /* FIXME: can we get rid of this ? */ + region_t key; + int state; + + struct list_head hash_list; + struct list_head list; + + atomic_t pending; + struct bio_list delayed_bios; +}; + +/* + * Conversion fns + */ +region_t dm_rh_sector_to_region(struct dm_region_hash *rh, sector_t sector) +{ + return sector >> rh->region_shift; +} +// EXPORT_SYMBOL_GPL(dm_rh_sector_to_region); + +sector_t dm_rh_region_to_sector(struct dm_region_hash *rh, region_t region) +{ + return region << rh->region_shift; +} +// EXPORT_SYMBOL_GPL(dm_rh_region_to_sector); + +region_t dm_rh_bio_to_region(struct dm_region_hash *rh, struct bio *bio) +{ + return dm_rh_sector_to_region(rh, bio->bi_sector - rh->target_begin); +} +// EXPORT_SYMBOL_GPL(dm_rh_bio_to_region); + +void *dm_rh_region_context(struct dm_region *reg) +{ + return reg->rh->context; +} +// EXPORT_SYMBOL_GPL(dm_rh_region_context); + +region_t dm_rh_get_region_key(struct dm_region *reg) +{ + return reg->key; +} +// EXPORT_SYMBOL_GPL(dm_rh_get_region_key); + +sector_t dm_rh_get_region_size(struct dm_region_hash *rh) +{ + return rh->region_size; +} +// EXPORT_SYMBOL_GPL(dm_rh_get_region_size); + +/* + * FIXME: shall we pass in a structure instead of all these args to + * dm_region_hash_create()???? + */ +#define RH_HASH_MULT 2654435387U +#define RH_HASH_SHIFT 12 + +#define MIN_REGIONS 64 +struct dm_region_hash *dm_region_hash_create( + void *context, void (*dispatch_bios)(void *context, + struct bio_list *bios), + void (*wakeup_workers)(void *context), + void (*wakeup_all_recovery_waiters)(void *context), + sector_t target_begin, unsigned max_recovery, + struct dm_dirty_log *log, uint32_t region_size, + region_t nr_regions) +{ + struct dm_region_hash *rh; + unsigned nr_buckets, max_buckets; + size_t i; + + /* + * Calculate a suitable number of buckets for our hash + * table. + */ + max_buckets = nr_regions >> 6; + for (nr_buckets = 128u; nr_buckets < max_buckets; nr_buckets <<= 1) + ; + nr_buckets >>= 1; + + rh = kmalloc(sizeof(*rh), GFP_KERNEL); + if (!rh) { + DMERR("unable to allocate region hash memory"); + return ERR_PTR(-ENOMEM); + } + + rh->context = context; + rh->dispatch_bios = dispatch_bios; + rh->wakeup_workers = wakeup_workers; + rh->wakeup_all_recovery_waiters = wakeup_all_recovery_waiters; + rh->target_begin = target_begin; + rh->max_recovery = max_recovery; + rh->log = log; + rh->region_size = region_size; + rh->region_shift = ffs(region_size) - 1; + rwlock_init(&rh->hash_lock); + rh->mask = nr_buckets - 1; + rh->nr_buckets = nr_buckets; + + rh->shift = RH_HASH_SHIFT; + rh->prime = RH_HASH_MULT; + + rh->buckets = vmalloc(nr_buckets * sizeof(*rh->buckets)); + if (!rh->buckets) { + DMERR("unable to allocate region hash bucket memory"); + kfree(rh); + return ERR_PTR(-ENOMEM); + } + + for (i = 0; i < nr_buckets; i++) + INIT_LIST_HEAD(rh->buckets + i); + + spin_lock_init(&rh->region_lock); + sema_init(&rh->recovery_count, 0); + atomic_set(&rh->recovery_in_flight, 0); + INIT_LIST_HEAD(&rh->clean_regions); + INIT_LIST_HEAD(&rh->quiesced_regions); + INIT_LIST_HEAD(&rh->recovered_regions); + INIT_LIST_HEAD(&rh->failed_recovered_regions); + + rh->region_pool = mempool_create_kmalloc_pool(MIN_REGIONS, + sizeof(struct dm_region)); + if (!rh->region_pool) { + vfree(rh->buckets); + kfree(rh); + rh = ERR_PTR(-ENOMEM); + } + + return rh; +} +// EXPORT_SYMBOL_GPL(dm_region_hash_create); + +void dm_region_hash_destroy(struct dm_region_hash *rh) +{ + unsigned h; + struct dm_region *reg, *nreg; + + BUG_ON(!list_empty(&rh->quiesced_regions)); + for (h = 0; h < rh->nr_buckets; h++) { + list_for_each_entry_safe(reg, nreg, rh->buckets + h, + hash_list) { + BUG_ON(atomic_read(®->pending)); + mempool_free(reg, rh->region_pool); + } + } + + if (rh->log) + dm_dirty_log_destroy(rh->log); + + if (rh->region_pool) + mempool_destroy(rh->region_pool); + + vfree(rh->buckets); + kfree(rh); +} +// EXPORT_SYMBOL_GPL(dm_region_hash_destroy); + +struct dm_dirty_log *dm_rh_dirty_log(struct dm_region_hash *rh) +{ + return rh->log; +} +// EXPORT_SYMBOL_GPL(dm_rh_dirty_log); + +static unsigned rh_hash(struct dm_region_hash *rh, region_t region) +{ + return (unsigned) ((region * rh->prime) >> rh->shift) & rh->mask; +} + +static struct dm_region *__rh_lookup(struct dm_region_hash *rh, region_t region) +{ + struct dm_region *reg; + struct list_head *bucket = rh->buckets + rh_hash(rh, region); + + list_for_each_entry(reg, bucket, hash_list) + if (reg->key == region) + return reg; + + return NULL; +} + +static void __rh_insert(struct dm_region_hash *rh, struct dm_region *reg) +{ + list_add(®->hash_list, rh->buckets + rh_hash(rh, reg->key)); +} + +static struct dm_region *__rh_alloc(struct dm_region_hash *rh, region_t region) +{ + struct dm_region *reg, *nreg; + + nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC); + if (unlikely(!nreg)) + nreg = kmalloc(sizeof(*nreg), GFP_NOIO | __GFP_NOFAIL); + + nreg->state = rh->log->type->in_sync(rh->log, region, 1) ? + DM_RH_CLEAN : DM_RH_NOSYNC; + nreg->rh = rh; + nreg->key = region; + INIT_LIST_HEAD(&nreg->list); + atomic_set(&nreg->pending, 0); + bio_list_init(&nreg->delayed_bios); + + write_lock_irq(&rh->hash_lock); + reg = __rh_lookup(rh, region); + if (reg) + /* We lost the race. */ + mempool_free(nreg, rh->region_pool); + else { + __rh_insert(rh, nreg); + if (nreg->state == DM_RH_CLEAN) { + spin_lock(&rh->region_lock); + list_add(&nreg->list, &rh->clean_regions); + spin_unlock(&rh->region_lock); + } + + reg = nreg; + } + write_unlock_irq(&rh->hash_lock); + + return reg; +} + +static struct dm_region *__rh_find(struct dm_region_hash *rh, region_t region) +{ + struct dm_region *reg; + + reg = __rh_lookup(rh, region); + if (!reg) { + read_unlock(&rh->hash_lock); + reg = __rh_alloc(rh, region); + read_lock(&rh->hash_lock); + } + + return reg; +} + +int dm_rh_get_state(struct dm_region_hash *rh, region_t region, int may_block) +{ + int r; + struct dm_region *reg; + + read_lock(&rh->hash_lock); + reg = __rh_lookup(rh, region); + read_unlock(&rh->hash_lock); + + if (reg) + return reg->state; + + /* + * The region wasn't in the hash, so we fall back to the + * dirty log. + */ + r = rh->log->type->in_sync(rh->log, region, may_block); + + /* + * Any error from the dirty log (eg. -EWOULDBLOCK) gets + * taken as a DM_RH_NOSYNC + */ + return r == 1 ? DM_RH_CLEAN : DM_RH_NOSYNC; +} +// EXPORT_SYMBOL_GPL(dm_rh_get_state); + +static void complete_resync_work(struct dm_region *reg, int success) +{ + struct dm_region_hash *rh = reg->rh; + + rh->log->type->set_region_sync(rh->log, reg->key, success); + + /* + * Dispatch the bios before we call 'wake_up_all'. + * This is important because if we are suspending, + * we want to know that recovery is complete and + * the work queue is flushed. If we wake_up_all + * before we dispatch_bios (queue bios and call wake()), + * then we risk suspending before the work queue + * has been properly flushed. + */ + rh->dispatch_bios(rh->context, ®->delayed_bios); + if (atomic_dec_and_test(&rh->recovery_in_flight)) + rh->wakeup_all_recovery_waiters(rh->context); + up(&rh->recovery_count); +} + +/* dm_rh_mark_nosync + * @ms + * @bio + * @done + * @error + * + * The bio was written on some mirror(s) but failed on other mirror(s). + * We can successfully endio the bio but should avoid the region being + * marked clean by setting the state DM_RH_NOSYNC. + * + * This function is _not_ safe in interrupt context! + */ +void dm_rh_mark_nosync(struct dm_region_hash *rh, + struct bio *bio, unsigned done, int error) +{ + unsigned long flags; + struct dm_dirty_log *log = rh->log; + struct dm_region *reg; + region_t region = dm_rh_bio_to_region(rh, bio); + int recovering = 0; + + /* We must inform the log that the sync count has changed. */ + log->type->set_region_sync(log, region, 0); + + read_lock(&rh->hash_lock); + reg = __rh_find(rh, region); + read_unlock(&rh->hash_lock); + + /* region hash entry should exist because write was in-flight */ + BUG_ON(!reg); + BUG_ON(!list_empty(®->list)); + + spin_lock_irqsave(&rh->region_lock, flags); + /* + * Possible cases: + * 1) DM_RH_DIRTY + * 2) DM_RH_NOSYNC: was dirty, other preceeding writes failed + * 3) DM_RH_RECOVERING: flushing pending writes + * Either case, the region should have not been connected to list. + */ + recovering = (reg->state == DM_RH_RECOVERING); + reg->state = DM_RH_NOSYNC; + BUG_ON(!list_empty(®->list)); + spin_unlock_irqrestore(&rh->region_lock, flags); + + bio_endio(bio, error); + if (recovering) + complete_resync_work(reg, 0); +} +// EXPORT_SYMBOL_GPL(dm_rh_mark_nosync); + +void dm_rh_update_states(struct dm_region_hash *rh, int errors_handled) +{ + struct dm_region *reg, *next; + + LIST_HEAD(clean); + LIST_HEAD(recovered); + LIST_HEAD(failed_recovered); + + /* + * Quickly grab the lists. + */ + write_lock_irq(&rh->hash_lock); + spin_lock(&rh->region_lock); + if (!list_empty(&rh->clean_regions)) { + list_splice_init(&rh->clean_regions, &clean); + + list_for_each_entry(reg, &clean, list) + list_del(®->hash_list); + } + + if (!list_empty(&rh->recovered_regions)) { + list_splice_init(&rh->recovered_regions, &recovered); + + list_for_each_entry(reg, &recovered, list) + list_del(®->hash_list); + } + + if (!list_empty(&rh->failed_recovered_regions)) { + list_splice_init(&rh->failed_recovered_regions, + &failed_recovered); + + list_for_each_entry(reg, &failed_recovered, list) + list_del(®->hash_list); + } + + spin_unlock(&rh->region_lock); + write_unlock_irq(&rh->hash_lock); + + /* + * All the regions on the recovered and clean lists have + * now been pulled out of the system, so no need to do + * any more locking. + */ + list_for_each_entry_safe(reg, next, &recovered, list) { + rh->log->type->clear_region(rh->log, reg->key); + complete_resync_work(reg, 1); + mempool_free(reg, rh->region_pool); + } + + list_for_each_entry_safe(reg, next, &failed_recovered, list) { + complete_resync_work(reg, errors_handled ? 0 : 1); + mempool_free(reg, rh->region_pool); + } + + list_for_each_entry_safe(reg, next, &clean, list) { + rh->log->type->clear_region(rh->log, reg->key); + mempool_free(reg, rh->region_pool); + } + + rh->log->type->flush(rh->log); +} +// EXPORT_SYMBOL_GPL(dm_rh_update_states); + +void dm_rh_inc(struct dm_region_hash *rh, region_t region) +{ + struct dm_region *reg; + + read_lock(&rh->hash_lock); + reg = __rh_find(rh, region); + + spin_lock_irq(&rh->region_lock); + atomic_inc(®->pending); + + if (reg->state == DM_RH_CLEAN) { + reg->state = DM_RH_DIRTY; + list_del_init(®->list); /* take off the clean list */ + spin_unlock_irq(&rh->region_lock); + + rh->log->type->mark_region(rh->log, reg->key); + } else + spin_unlock_irq(&rh->region_lock); + + + read_unlock(&rh->hash_lock); +} +// EXPORT_SYMBOL_GPL(dm_rh_inc); + +void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios) +{ + struct bio *bio; + + for (bio = bios->head; bio; bio = bio->bi_next) + dm_rh_inc(rh, dm_rh_bio_to_region(rh, bio)); +} +// EXPORT_SYMBOL_GPL(dm_rh_inc_pending); + +void dm_rh_dec(struct dm_region_hash *rh, region_t region) +{ + unsigned long flags; + struct dm_region *reg; + int should_wake = 0; + + read_lock(&rh->hash_lock); + reg = __rh_lookup(rh, region); + read_unlock(&rh->hash_lock); + + spin_lock_irqsave(&rh->region_lock, flags); + if (atomic_dec_and_test(®->pending)) { + /* + * There is no pending I/O for this region. + * We can move the region to corresponding list for next action. + * At this point, the region is not yet connected to any list. + * + * If the state is DM_RH_NOSYNC, the region should be kept off + * from clean list. + * The hash entry for DM_RH_NOSYNC will remain in memory + * until the region is recovered or the map is reloaded. + */ + + /* do nothing for DM_RH_NOSYNC */ + if (reg->state == DM_RH_RECOVERING) { + list_add_tail(®->list, &rh->quiesced_regions); + } else if (reg->state == DM_RH_DIRTY) { + reg->state = DM_RH_CLEAN; + list_add(®->list, &rh->clean_regions); + } + should_wake = 1; + } + spin_unlock_irqrestore(&rh->region_lock, flags); + + if (should_wake) + rh->wakeup_workers(rh->context); +} +// EXPORT_SYMBOL_GPL(dm_rh_dec); + +/* + * Starts quiescing a region in preparation for recovery. + */ +static int __rh_recovery_prepare(struct dm_region_hash *rh) +{ + int r; + region_t region; + struct dm_region *reg; + + /* + * Ask the dirty log what's next. + */ + r = rh->log->type->get_resync_work(rh->log, ®ion); + if (r <= 0) + return r; + + /* + * Get this region, and start it quiescing by setting the + * recovering flag. + */ + read_lock(&rh->hash_lock); + reg = __rh_find(rh, region); + read_unlock(&rh->hash_lock); + + spin_lock_irq(&rh->region_lock); + reg->state = DM_RH_RECOVERING; + + /* Already quiesced ? */ + if (atomic_read(®->pending)) + list_del_init(®->list); + else + list_move(®->list, &rh->quiesced_regions); + + spin_unlock_irq(&rh->region_lock); + + return 1; +} + +void dm_rh_recovery_prepare(struct dm_region_hash *rh) +{ + /* Extra reference to avoid race with dm_rh_stop_recovery */ + atomic_inc(&rh->recovery_in_flight); + + while (!down_trylock(&rh->recovery_count)) { + atomic_inc(&rh->recovery_in_flight); + if (__rh_recovery_prepare(rh) <= 0) { + atomic_dec(&rh->recovery_in_flight); + up(&rh->recovery_count); + break; + } + } + + /* Drop the extra reference */ + if (atomic_dec_and_test(&rh->recovery_in_flight)) + rh->wakeup_all_recovery_waiters(rh->context); +} +// EXPORT_SYMBOL_GPL(dm_rh_recovery_prepare); + +/* + * Returns any quiesced regions. + */ +struct dm_region *dm_rh_recovery_start(struct dm_region_hash *rh) +{ + struct dm_region *reg = NULL; + + spin_lock_irq(&rh->region_lock); + if (!list_empty(&rh->quiesced_regions)) { + reg = list_entry(rh->quiesced_regions.next, + struct dm_region, list); + list_del_init(®->list); /* remove from the quiesced list */ + } + spin_unlock_irq(&rh->region_lock); + + return reg; +} +// EXPORT_SYMBOL_GPL(dm_rh_recovery_start); + +void dm_rh_recovery_end(struct dm_region *reg, int success) +{ + struct dm_region_hash *rh = reg->rh; + + spin_lock_irq(&rh->region_lock); + if (success) + list_add(®->list, ®->rh->recovered_regions); + else { + reg->state = DM_RH_NOSYNC; + list_add(®->list, ®->rh->failed_recovered_regions); + } + spin_unlock_irq(&rh->region_lock); + + rh->wakeup_workers(rh->context); +} +// EXPORT_SYMBOL_GPL(dm_rh_recovery_end); + +/* Return recovery in flight count. */ +int dm_rh_recovery_in_flight(struct dm_region_hash *rh) +{ + return atomic_read(&rh->recovery_in_flight); +} +// EXPORT_SYMBOL_GPL(dm_rh_recovery_in_flight); + +int dm_rh_flush(struct dm_region_hash *rh) +{ + return rh->log->type->flush(rh->log); +} +// EXPORT_SYMBOL_GPL(dm_rh_flush); + +void dm_rh_delay(struct dm_region_hash *rh, struct bio *bio) +{ + struct dm_region *reg; + + read_lock(&rh->hash_lock); + reg = __rh_find(rh, dm_rh_bio_to_region(rh, bio)); + bio_list_add(®->delayed_bios, bio); + read_unlock(&rh->hash_lock); +} +// EXPORT_SYMBOL_GPL(dm_rh_delay); + +void dm_rh_delay_by_region(struct dm_region_hash *rh, + struct bio *bio, region_t region) +{ + struct dm_region *reg; + + /* FIXME: locking. */ + read_lock(&rh->hash_lock); + reg = __rh_find(rh, region); + bio_list_add(®->delayed_bios, bio); + read_unlock(&rh->hash_lock); +} +// EXPORT_SYMBOL_GPL(dm_rh_delay_by_region); + +void dm_rh_stop_recovery(struct dm_region_hash *rh) +{ + int i; + + /* wait for any recovering regions */ + for (i = 0; i < rh->max_recovery; i++) + down(&rh->recovery_count); +} +// EXPORT_SYMBOL_GPL(dm_rh_stop_recovery); + +void dm_rh_start_recovery(struct dm_region_hash *rh) +{ + int i; + + for (i = 0; i < rh->max_recovery; i++) + up(&rh->recovery_count); + + rh->wakeup_workers(rh->context); +} +// EXPORT_SYMBOL_GPL(dm_rh_start_recovery); + +MODULE_DESCRIPTION(DM_NAME " region hash"); +MODULE_AUTHOR("Joe Thornber/Heinz Mauelshagen "); +MODULE_LICENSE("GPL"); --- linux-2.6.37.orig/ubuntu/dm-raid4-5/dm-region-hash.h +++ linux-2.6.37/ubuntu/dm-raid4-5/dm-region-hash.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2003 Sistina Software Limited. + * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved. + * + * Device-Mapper dirty region hash interface. + * + * This file is released under the GPL. + */ + +#ifndef DM_REGION_HASH_H +#define DM_REGION_HASH_H + +#include + +/*----------------------------------------------------------------- + * Region hash + *----------------------------------------------------------------*/ +struct dm_region_hash; +struct dm_region; + +/* + * States a region can have. + */ +enum dm_rh_region_states { + DM_RH_CLEAN = 0x01, /* No writes in flight. */ + DM_RH_DIRTY = 0x02, /* Writes in flight. */ + DM_RH_NOSYNC = 0x04, /* Out of sync. */ + DM_RH_RECOVERING = 0x08, /* Under resynchronization. */ +}; + +/* + * Region hash create/destroy. + */ +struct bio_list; +struct dm_region_hash *dm_region_hash_create( + void *context, void (*dispatch_bios)(void *context, + struct bio_list *bios), + void (*wakeup_workers)(void *context), + void (*wakeup_all_recovery_waiters)(void *context), + sector_t target_begin, unsigned max_recovery, + struct dm_dirty_log *log, uint32_t region_size, + region_t nr_regions); +void dm_region_hash_destroy(struct dm_region_hash *rh); + +struct dm_dirty_log *dm_rh_dirty_log(struct dm_region_hash *rh); + +/* + * Conversion functions. + */ +region_t dm_rh_bio_to_region(struct dm_region_hash *rh, struct bio *bio); +sector_t dm_rh_region_to_sector(struct dm_region_hash *rh, region_t region); +region_t dm_rh_sector_to_region(struct dm_region_hash *rh, sector_t sector); +void *dm_rh_region_context(struct dm_region *reg); + +/* + * Get region size and key (ie. number of the region). + */ +sector_t dm_rh_get_region_size(struct dm_region_hash *rh); +region_t dm_rh_get_region_key(struct dm_region *reg); + +/* + * Get/set/update region state (and dirty log). + * + */ +int dm_rh_get_state(struct dm_region_hash *rh, region_t region, int may_block); +void dm_rh_set_state(struct dm_region_hash *rh, region_t region, + enum dm_rh_region_states state, int may_block); + +/* Non-zero errors_handled leaves the state of the region NOSYNC */ +void dm_rh_update_states(struct dm_region_hash *rh, int errors_handled); + +/* Flush the region hash and dirty log. */ +int dm_rh_flush(struct dm_region_hash *rh); + +/* Inc/dec pending count on regions. */ +void dm_rh_inc(struct dm_region_hash *rh, region_t region); +void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios); +void dm_rh_dec(struct dm_region_hash *rh, region_t region); + +/* Delay bios on regions. */ +void dm_rh_delay(struct dm_region_hash *rh, struct bio *bio); +void dm_rh_delay_by_region(struct dm_region_hash *rh, struct bio *bio, + region_t region); + +void dm_rh_mark_nosync(struct dm_region_hash *rh, + struct bio *bio, unsigned done, int error); + +/* + * Region recovery control. + */ + +/* Prepare some regions for recovery by starting to quiesce them. */ +void dm_rh_recovery_prepare(struct dm_region_hash *rh); + +/* Try fetching a quiesced region for recovery. */ +struct dm_region *dm_rh_recovery_start(struct dm_region_hash *rh); + +/* Report recovery end on a region. */ +void dm_rh_recovery_end(struct dm_region *reg, int error); + +/* Returns number of regions with recovery work outstanding. */ +int dm_rh_recovery_in_flight(struct dm_region_hash *rh); + +/* Start/stop recovery. */ +void dm_rh_start_recovery(struct dm_region_hash *rh); +void dm_rh_stop_recovery(struct dm_region_hash *rh); + +#endif /* DM_REGION_HASH_H */ --- linux-2.6.37.orig/ubuntu/fsam7400/BOM +++ linux-2.6.37/ubuntu/fsam7400/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://www.iragan.com/linux/fsam7400/ +Current Version: 0.5.2 (2008 Nov 22) --- linux-2.6.37.orig/ubuntu/fsam7400/CHANGELOG +++ linux-2.6.37/ubuntu/fsam7400/CHANGELOG @@ -0,0 +1,34 @@ +Nov 22 2008 Changes in 0.5.2 by legolas558 +* fixed some missing include files + +Sep 22 2006 Changes in 0.5.1 +* Fix: possible null pointer dereference in proc code +* Fix: module exit code was mistakenly disabled + +Sep 22 2006 Changes in 0.5.0 +* fixed compilation problems with kernel 2.6.18 +* debug-output enabling via module parameter +* hibernation support: reconstruct last radio state on resume +* disabled autoload option by default + +Jul 16 2006 Changes in 0.4.1 +* new Makefile fixing problems with kernel 2.6.17 +* several bug fixes and compiler cleanups + +Aug 20 2004 Changes in 0.4.0 +* several bug fixes and compiler cleanups +* UID/GID for procfs entry selectable via module parameter +* Autoload support: fsam7400 modprobes and rmmods ipw2100 automatically + depending on radio state + +Apr 15 2004 Changes in 0.3.0 +* Fix: radio state was not displayed properly +* some proc improvements +* finished code for alternative routine address calculation +* debug-output selectable at compile-time with CONFIG_IPW2100_DEBUG define + for smaller module size if no debug is needed ;) + +Apr 9 2004 Changes in 0.2.1 +* Initial release +* Determines if wireless device is enabled by default Bios-settings +* Auto-off functionality --- linux-2.6.37.orig/ubuntu/fsam7400/FILES +++ linux-2.6.37/ubuntu/fsam7400/FILES @@ -0,0 +1,6 @@ +CHANGELOG Recently changes logged +FILES This file +fsam7400.c The source code, what else... :) +INSTALL Installation instructions +Makefile Makefile to build, install, uninstall the module +README don't forget to read it --- linux-2.6.37.orig/ubuntu/fsam7400/INSTALL +++ linux-2.6.37/ubuntu/fsam7400/INSTALL @@ -0,0 +1,110 @@ +SW RF kill switch for Fujitsu Siemens Amilo M 7400 +Copyright (C) 2006, zwobbl +For additional information, contact Marcel Naziri + +COMPILER REQUIREMENTS +--------- ------ ---- --- -- -- - - + +You need to be using GCC v3.0 or higher in order to build the fsam7400 module. +Using older versions will result in several compilation errors. + + +INSTALLING THE BITS +------------ ----- ----- ---- --- -- - + +# Unpack the source tarball + +% tar xvzf fsam7400-0.x.y.tgz +% cd fsam7400-0.x.y + +Make sure to be root when performing the following operations. Also you must +have a kernel source tree installed under /usr/src/linux + +# Build the kernel module + +% make + +Debug output is enabled by default. This is a good idea if you use the fsam module for +the first time, so you get some nice information printed on kernel log. If you don't +need the messages anymore, you have to comment out the line CONFIG_IPW2100_DEBUG=y in +the Makefile. + +# Install the kernel module + +% make install + +Now you are ready for... + + +LOADING THE DRIVER +------------ ----- ----- ---- --- -- - + +Also easy to go... :) + +% modprobe fsam7400 + +If you have set "wireless device" enabled in your "Advanced" bios settings of +your Amilo M 7400 radio should be turned on at this point. So you're done! +Watch out your kernel log if supported hardware was found. :) + + +RADIO STATE AT LOADING + +You can override the wireless bios setting with + +% modprobe fsam7400 radio=[0|1] + + +PROC FILESYSTEM + +If your hardware is supported by the driver you will get an entry in /proc +called driver/wireless/radio which will give you state information by typing + +% cat /proc/driver/wireless/radio + +You can turn the radio on and off at your will with + +% echo [1|on] > /proc/driver/wireless/radio +% echo [0|off] > /proc/driver/wireless/radio + +The module also recognizes parameters to set the user- and/or group-ID to +something other than root, so you don't have to adjust it by hand. +Just select your favourite IDs and type + +% modprobe fsam7400 uid=1000 gid=500 + +Note, that /proc/driver/wireless/radio will only be read- and writeable by +user & group and only readable by others. + +If you want to see debug output on syslog use the following parameter when +loading the module + +% modprobe fsam7400 debug=1 + + +AUTOMATION FEATURES + +By default the driver will turn off the radio automatically short before the +module is unloaded. To override this behaviour load the module adding the +following parameter + +% modprobe fsam7400 autooff=0 + +Also since 0.4.0 the driver can automatically modprobe the ipw2100 module when +radio state changes to on and rmmods it when radio is turned off by fsam7400. +To enable autoload support, use + +% modprobe fsam7400 autoload=1 + + +HIBERNATION SUPPORT + +After hibernation and boot up of the system the wireless radio might be disabled +again. To revert to the radio state before hibernation just put the following +in the wakeup script + +% echo resume > /proc/driver/wireless/radio + + + +That's all for now. Have fun with the driver! --- linux-2.6.37.orig/ubuntu/fsam7400/Kconfig +++ linux-2.6.37/ubuntu/fsam7400/Kconfig @@ -0,0 +1,5 @@ +config FSAM7400 + tristate "SW RF kill switch for Fujitsu Siemens Amilo M 7400" + depends on CHECK_SIGNATURE + default m + ---help--- --- linux-2.6.37.orig/ubuntu/fsam7400/LICENSE +++ linux-2.6.37/ubuntu/fsam7400/LICENSE @@ -0,0 +1,338 @@ +"This software program is licensed subject to the GNU General Public License +(GPL). Version 2, June 1991, available at +" + +GNU General Public License + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 Library 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 + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it free +software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey the +exclusion of warranty; and each file should have at least the "copyright" +line and a pointer to where the full notice is found. + +one line to give the program's name and an idea of what it does. +Copyright (C) yyyy name of author + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your option) +any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 +Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when +it starts in an interactive mode: + +Gnomovision version 69, Copyright (C) year name of author Gnomovision comes +with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free +software, and you are welcome to redistribute it under certain conditions; +type 'show c' for details. + +The hypothetical commands 'show w' and 'show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may be +called something other than 'show w' and 'show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + +Yoyodyne, Inc., hereby disclaims all copyright interest in the program +'Gnomovision' (which makes passes at compilers) written by James Hacker. + +signature of Ty Coon, 1 April 1989 +Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General Public +License instead of this License. --- linux-2.6.37.orig/ubuntu/fsam7400/Makefile +++ linux-2.6.37/ubuntu/fsam7400/Makefile @@ -0,0 +1,2 @@ + +obj-$(CONFIG_FSAM7400) += fsam7400.o --- linux-2.6.37.orig/ubuntu/fsam7400/README +++ linux-2.6.37/ubuntu/fsam7400/README @@ -0,0 +1,60 @@ +SW RF kill switch for Fujitsu Siemens Amilo M 7400 / Maxdata 7000DX +and compatible hardware. + +Please be sure that CONFIG_CHECK_SIGNATURE=y in your kernel configuration! +Otherwise this module will not compile. + +Nov 22, 2008 - Release 0.5.2 + +This package, with minor modifications from zwobbl's 0.5.1, was created +by legolas558. + +More information at: +http://legolas558.iragan.com/fsam7400 + +Sep 24, 2006 - Release 0.5.1 +------------ ----- ----- ---- --- -- - + +* Fix: possible null pointer dereference in proc code + +* Fix: module exit code was mistakenly disabled + + +for prior changes see CHANGELOG + + +TODO +------------ ----- ----- ---- --- -- - + +* Fix bugs (if there are any ;)) + + +------------ ----- ----- ---- --- -- - + +Have a look in INSTALL for further details to get things working! + + +License +------------ ----- ----- ---- --- -- - + + Copyright(c) 2006 zwobbl. 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. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + Marcel Naziri --- linux-2.6.37.orig/ubuntu/fsam7400/fsam7400.c +++ linux-2.6.37/ubuntu/fsam7400/fsam7400.c @@ -0,0 +1,386 @@ +/******************************************************************************* + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Author: + Marcel Naziri + + Based on: + pbe5.c by Pedro Ramalhais + + Many thanks to: + Pedro Ramalhais for spending several nights with me on IRC + +*******************************************************************************/ + +#ifdef CONFIG_X86 +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "fsam7400" +#define DRV_VERSION "0.5.2" +#define DRV_DESCRIPTION "SW RF kill switch for Fujitsu Siemens Amilo M 7400 / Maxdata 7000DX" +#define DRV_COPYRIGHT "Copyright(c) 2004 zwobbl" +#define DRV_AUTHOR "Marcel Naziri" +#define DRV_LICENSE "GPL" + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_AUTHOR); +MODULE_LICENSE(DRV_LICENSE); + +#define RADIO_NONE 0xFFFFFFFF +#define RADIO_OFF 0x00000000 +#define RADIO_ON 0x00000010 + +static int radio = RADIO_NONE; +static int autooff = 1; +static int autoload = 0; +static int uid = 0; +static int gid = 0; +static int debug = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +module_param(radio, int, 0444); +module_param(autooff, int, 0444); +module_param(autoload, int, 0444); +module_param(uid, int, 0444); +module_param(gid, int, 0444); +module_param(debug, int, 0444); +#else +MODULE_PARM(radio, "i"); +MODULE_PARM(autooff, "i"); +MODULE_PARM(autoload, "i"); +MODULE_PARM(uid, "i"); +MODULE_PARM(gid, "i"); +MODULE_PARM(debug, "i"); +#endif + +MODULE_PARM_DESC(radio, "desired radio state when loading module"); +MODULE_PARM_DESC(autooff, "turns radio off when unloading module (default)"); +MODULE_PARM_DESC(autoload, "load/unloads ipw2100 driver when toggling radio"); +MODULE_PARM_DESC(uid, "user ID for proc entry"); +MODULE_PARM_DESC(gid, "group ID for proc entry"); +MODULE_PARM_DESC(debug, "enables debug output on syslog"); + +/* some more or less useful macros */ + +#define DEBUG if (debug) +#define DEBUG_OUT0(a) DEBUG printk(KERN_INFO DRV_NAME ": " a) +#define DEBUG_OUT1(a,b) DEBUG printk(KERN_INFO DRV_NAME ": " a,b) +#define DEBUG_OUT2(a,b,c) DEBUG printk(KERN_INFO DRV_NAME ": " a,b,c) +#define DEBUG_OUT3(a,b,c,d) DEBUG printk(KERN_INFO DRV_NAME ": " a,b,c,d) + +#define ONOFF(x) (x) ? "ON" : "OFF" +#define RADIO_ONOFF(x) (x) == RADIO_ON ? "ON" : "OFF" +#define TOUL(x) (unsigned long) (x) + +/* + * NOTE: These values were obtained from disassembling the wbutton.sys driver + * installed in the Fujitsu Siemens Amilo M 7400 laptop. The names were guessed, + * so don't rely on them. + */ + +/*** hardware dependant stuff ***/ + +#define BIOS_CODE_ADDR 0x000F0000 +#define BIOS_CODE_ALT_MASK 0xFFFFC000 + +#define BIOS_CODE_MAPSIZE 0x010000 +#define BIOS_CODE_ALT_MAPSIZE 0x004000 + +#define BIOS_MAGIC_COMMAND 0x9610 +#define BIOS_MAGIC_OFF 0x0035 +#define BIOS_MAGIC_ON 0x0135 +#define BIOS_MAGIC_CHECK 0x0235 + +#define PTR_POSITION 5 +#define ALLIGNED_STEP 0x10 + +#define BIOS_SIGN_SIZE 4 +static const char bios_sign[] = { + 0x42, 0x21, 0x55, 0x30 +}; + +#define WLAN_DISABLED_IN_BIOS 0x01 +#define WLAN_ENABLED_IN_BIOS 0x03 + +static unsigned long bios_code = 0; + +static int fsam_bios_routine(int eax, int ebx) +{ + __asm__ __volatile__( + "call *%3 \t\n" + : "=a"(eax) + : "a"(eax), "b"(ebx), "c"(bios_code) + ); + return (eax & 0xFF); +} + +static int fsam_call_bios(int value) +{ + if (bios_code) { + int command = BIOS_MAGIC_COMMAND; + DEBUG_OUT2("bios routine gets parameter eax=%X and ebx=%X\n", + command, value); + value = fsam_bios_routine(command, value); + DEBUG_OUT1("bios routine results %X\n", value); + return value; + } + return ~0; +} + +/* pointer to mapped memory*/ +static void *mem_code = NULL; + +static inline void fsam_unmap_memory(void) +{ + bios_code = 0; + if (mem_code) { + iounmap(mem_code); + } +} + +static inline int fsam_map_memory(void) +{ + const unsigned long max_offset = BIOS_CODE_MAPSIZE - BIOS_SIGN_SIZE - PTR_POSITION; + unsigned long offset; + unsigned int addr; + mem_code = ioremap(BIOS_CODE_ADDR, BIOS_CODE_MAPSIZE); + if (!mem_code) + goto fail; + DEBUG_OUT3("physical memory %x-%x mapped to virtual address %p\n", + BIOS_CODE_ADDR, BIOS_CODE_ADDR+BIOS_CODE_MAPSIZE, mem_code); + for ( offset = 0; offset < max_offset; offset += ALLIGNED_STEP ) + if (check_signature((void*)TOUL(mem_code) + offset, bios_sign, BIOS_SIGN_SIZE)) + break; + if (offset >= max_offset) + goto fail; + DEBUG_OUT1("bios signature found at offset %lx\n", offset); + addr = readl((void*)TOUL(mem_code) + offset + PTR_POSITION); + if (addr < BIOS_CODE_ADDR) { + DEBUG_OUT0("bios routine out of memory range, " + "doing some new memory mapping...\n"); + iounmap(mem_code); + mem_code = NULL; + addr &= BIOS_CODE_ALT_MASK; + mem_code = ioremap(addr, BIOS_CODE_ALT_MAPSIZE); + if (!mem_code) + goto fail; + DEBUG_OUT3("physical memory %x-%x mapped to virtual address %p\n", + addr, addr+BIOS_CODE_ALT_MAPSIZE, mem_code); + addr &= 0x3FFF; + } else + addr &= 0xFFFF; + + bios_code = addr + TOUL(mem_code); + DEBUG_OUT1("supposed address of bios routine is %lx\n", bios_code); + return 1; + fail: + fsam_unmap_memory(); + return 0; +} + +/*** ipw2100 loading ***/ + +static inline void do_ipw2100_loading(int state) +{ + int status; + char *mode; + char *envp[] = { "HOME=/", + "TERM=linux", + "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; + if (state == RADIO_ON) { + char *argv[] = { "/sbin/modprobe", "-s", "-k", "ipw2100", NULL }; + mode = "loading"; + status = call_usermodehelper(argv[0], argv, envp, 1); + } else { + char *argv[] = { "/sbin/rmmod", "ipw2100", NULL }; + mode = "removing"; + status = call_usermodehelper(argv[0], argv, envp, 1); + } + DEBUG_OUT2("%s of ipw2100 module %s\n", mode, status == 0 ? "successful" : "FAILED"); +} + +/*** interface stuff ***/ + +static void rfkill_set_radio(int value) +{ + radio = value == RADIO_ON ? fsam_call_bios(BIOS_MAGIC_ON) : + fsam_call_bios(BIOS_MAGIC_OFF); + if (autoload) do_ipw2100_loading(radio); +} + +static inline int rfkill_get_radio(void) +{ + return radio; +} + +static inline int rfkill_supported(void) +{ + return bios_code != 0; +} + +static inline void rfkill_initialize(void) { + fsam_map_memory(); + if (rfkill_supported()) { + radio = radio != RADIO_NONE + ? ( radio ? RADIO_ON : RADIO_OFF ) /*module parameter*/ + : ( fsam_call_bios(BIOS_MAGIC_CHECK) == WLAN_ENABLED_IN_BIOS + ? RADIO_ON : RADIO_OFF ); + } +} + +static inline void rfkill_uninitialize(void) { + fsam_unmap_memory(); +} + +/*** proc stuff ***/ + +static inline int common_proc_set_radio(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned long len = 7; + char newstate[len]; + len = count < len ? count : len; + if ( copy_from_user(newstate, buffer, len) != 0 ) + return -EFAULT; + if ( (*newstate == '1' || *newstate == '0') && + (count == 1 || isspace(newstate[1])) ) + rfkill_set_radio(*newstate == '1' ? RADIO_ON : RADIO_OFF); + else + if ( !strncmp(newstate, "on", 2) && + (count == 2 || isspace(newstate[2])) ) + rfkill_set_radio(RADIO_ON); + else + if ( !strncmp(newstate, "off", 3) && + (count == 3 || isspace(newstate[3])) ) + rfkill_set_radio(RADIO_OFF); + else + if ( !strncmp(newstate, "resume", 6) && + (count == 6 || isspace(newstate[6])) ) + rfkill_set_radio(radio); + return count; +} + +static inline int common_proc_get_radio(char *page, char **start, off_t offset, + int count, int *eof, void *data) +{ + int len = snprintf(page, count, DRV_DESCRIPTION ", v" DRV_VERSION "\n" + " auto-off is %s, auto-load is %s\n", + ONOFF(autooff), ONOFF(autoload)); + len += snprintf(page+len, count-len, " radio state is %s\n", + RADIO_ONOFF(rfkill_get_radio())); + *eof = 1; + return len; +} + +#define PROC_DIR "driver/wireless" +#define PROC_RADIO "radio" + +static struct proc_dir_entry *dir_base = NULL; + +static inline void common_proc_cleanup(void) +{ + if (dir_base) { + remove_proc_entry(PROC_RADIO, dir_base); + remove_proc_entry(PROC_DIR, NULL); + dir_base = NULL; + } +} + +static inline int common_proc_init(void) +{ + struct proc_dir_entry *ent; + int err = 0; + dir_base = proc_mkdir(PROC_DIR, NULL); + if (dir_base == NULL) { + printk(KERN_ERR DRV_NAME ": Unable to initialize /proc/" PROC_DIR "\n"); + err = -ENOMEM; + goto fail; + } + ent = create_proc_entry(PROC_RADIO, + S_IFREG | S_IRUGO | S_IWUSR | S_IWGRP, + dir_base); + if (ent) { + ent->uid = uid; + ent->gid = gid; + ent->read_proc = common_proc_get_radio; + ent->write_proc = common_proc_set_radio; + } else { + printk(KERN_ERR DRV_NAME ": Unable to initialize /proc/" + PROC_DIR "/" PROC_RADIO "\n"); + err = -ENOMEM; + goto fail; + } + return 0; + fail: + common_proc_cleanup(); + return err; +} + +/*** module stuff ***/ + +static int __init common_init(void) +{ + printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", v" DRV_VERSION "\n"); + printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); + rfkill_initialize(); + if (rfkill_supported()) { + common_proc_init(); + if (radio != RADIO_NONE) + rfkill_set_radio(radio); + } else + printk(KERN_INFO DRV_NAME ": no supported wireless hardware found\n"); + return 0; +} + +static void __exit common_exit(void) +{ + if (rfkill_supported() && autooff) + rfkill_set_radio(RADIO_OFF); + common_proc_cleanup(); + rfkill_uninitialize(); + printk(KERN_INFO DRV_NAME ": module removed successfully\n"); +} + +module_init(common_init); +module_exit(common_exit); + +#else +#error This driver is only available for X86 architecture +#endif + +/* + 1 2 3 4 5 6 7 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +*/ --- linux-2.6.37.orig/ubuntu/include/Kbuild +++ linux-2.6.37/ubuntu/include/Kbuild @@ -0,0 +1 @@ +header-y += linux/ --- linux-2.6.37.orig/ubuntu/include/README +++ linux-2.6.37/ubuntu/include/README @@ -0,0 +1,4 @@ +Only use this directory for things which need to share their headers with +other parts of the kernel or other modules in ubuntu/ + +Otherwise, keep them local to the module directory. --- linux-2.6.37.orig/ubuntu/include/linux/Kbuild +++ linux-2.6.37/ubuntu/include/linux/Kbuild @@ -0,0 +1 @@ +header-y += aufs_type.h --- linux-2.6.37.orig/ubuntu/include/linux/aufs_type.h +++ linux-2.6.37/ubuntu/include/linux/aufs_type.h @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2005-2010 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __AUFS_TYPE_H__ +#define __AUFS_TYPE_H__ + +#include +#include +#include +#include + +#define AUFS_VERSION "2.1-standalone.tree-37-rcN-20101122" + +/* todo? move this to linux-2.6.19/include/magic.h */ +#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') + +/* ---------------------------------------------------------------------- */ + +#ifdef CONFIG_AUFS_BRANCH_MAX_127 +typedef __s8 aufs_bindex_t; +#define AUFS_BRANCH_MAX 127 +#else +typedef __s16 aufs_bindex_t; +#ifdef CONFIG_AUFS_BRANCH_MAX_511 +#define AUFS_BRANCH_MAX 511 +#elif defined(CONFIG_AUFS_BRANCH_MAX_1023) +#define AUFS_BRANCH_MAX 1023 +#elif defined(CONFIG_AUFS_BRANCH_MAX_32767) +#define AUFS_BRANCH_MAX 32767 +#endif +#endif + +#ifdef __KERNEL__ +#ifndef AUFS_BRANCH_MAX +#error unknown CONFIG_AUFS_BRANCH_MAX value +#endif +#endif /* __KERNEL__ */ + +/* ---------------------------------------------------------------------- */ + +#define AUFS_NAME "aufs" +#define AUFS_FSTYPE AUFS_NAME + +#define AUFS_ROOT_INO 2 +#define AUFS_FIRST_INO 11 + +#define AUFS_WH_PFX ".wh." +#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1) +#define AUFS_WH_TMP_LEN 4 +/* a limit for rmdir/rename a dir */ +#define AUFS_MAX_NAMELEN (NAME_MAX \ + - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\ + - 1 /* dot */\ + - AUFS_WH_TMP_LEN) /* hex */ +#define AUFS_XINO_FNAME "." AUFS_NAME ".xino" +#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME +#define AUFS_XINO_TRUNC_INIT 64 /* blocks */ +#define AUFS_XINO_TRUNC_STEP 4 /* blocks */ +#define AUFS_DIRWH_DEF 3 +#define AUFS_RDCACHE_DEF 10 /* seconds */ +#define AUFS_RDBLK_DEF 512 /* bytes */ +#define AUFS_RDHASH_DEF 32 +#define AUFS_WKQ_NAME AUFS_NAME "d" +#define AUFS_WKQ_PRE_NAME AUFS_WKQ_NAME "_pre" +#define AUFS_MFS_SECOND_DEF 30 /* seconds */ +#define AUFS_PLINK_WARN 100 /* number of plinks */ + +/* pseudo-link maintenace under /proc */ +#define AUFS_PLINK_MAINT_NAME "plink_maint" +#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME +#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME + +#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */ +#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME + +#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME +#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk" +#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph" + +/* doubly whiteouted */ +#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME +#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME +#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME + +/* branch permission */ +#define AUFS_BRPERM_RW "rw" +#define AUFS_BRPERM_RO "ro" +#define AUFS_BRPERM_RR "rr" +#define AUFS_BRPERM_WH "wh" +#define AUFS_BRPERM_NLWH "nolwh" +#define AUFS_BRPERM_ROWH AUFS_BRPERM_RO "+" AUFS_BRPERM_WH +#define AUFS_BRPERM_RRWH AUFS_BRPERM_RR "+" AUFS_BRPERM_WH +#define AUFS_BRPERM_RWNLWH AUFS_BRPERM_RW "+" AUFS_BRPERM_NLWH + +/* ---------------------------------------------------------------------- */ + +/* ioctl */ +enum { + /* readdir in userspace */ + AuCtl_RDU, + AuCtl_RDU_INO, + + /* pathconf wrapper */ + AuCtl_WBR_FD +}; + +/* borrowed from linux/include/linux/kernel.h */ +#ifndef ALIGN +#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) +#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) +#endif + +/* borrowed from linux/include/linux/compiler-gcc3.h */ +#ifndef __aligned +#define __aligned(x) __attribute__((aligned(x))) +#define __packed __attribute__((packed)) +#endif + +struct au_rdu_cookie { + __u64 h_pos; + __s16 bindex; + __u8 flags; + __u8 pad; + __u32 generation; +} __aligned(8); + +struct au_rdu_ent { + __u64 ino; + __s16 bindex; + __u8 type; + __u8 nlen; + __u8 wh; + char name[0]; +} __aligned(8); + +static inline int au_rdu_len(int nlen) +{ + /* include the terminating NULL */ + return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1, + sizeof(__u64)); +} + +union au_rdu_ent_ul { + struct au_rdu_ent __user *e; + __u64 ul; +}; + +enum { + AufsCtlRduV_SZ, + AufsCtlRduV_End +}; + +struct aufs_rdu { + /* input */ + union { + __u64 sz; /* AuCtl_RDU */ + __u64 nent; /* AuCtl_RDU_INO */ + }; + union au_rdu_ent_ul ent; + __u16 verify[AufsCtlRduV_End]; + + /* input/output */ + __u32 blk; + + /* output */ + union au_rdu_ent_ul tail; + /* number of entries which were added in a single call */ + __u64 rent; + __u8 full; + __u8 shwh; + + struct au_rdu_cookie cookie; +} __aligned(8); + +#define AuCtlType 'A' +#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu) +#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu) +#define AUFS_CTL_WBR_FD _IO(AuCtlType, AuCtl_WBR_FD) + +#endif /* __AUFS_TYPE_H__ */ --- linux-2.6.37.orig/ubuntu/iscsitarget/BOM +++ linux-2.6.37/ubuntu/iscsitarget/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://sourceforge.net/projects/iscsitarget/files/ +Current Version: 1.4.20.2 --- linux-2.6.37.orig/ubuntu/iscsitarget/Kconfig +++ linux-2.6.37/ubuntu/iscsitarget/Kconfig @@ -0,0 +1,3 @@ +config SCSI_ISCSITARGET + tristate "iSCSI Target Driver" + depends on SCSI --- linux-2.6.37.orig/ubuntu/iscsitarget/Makefile +++ linux-2.6.37/ubuntu/iscsitarget/Makefile @@ -0,0 +1,17 @@ +# +# Makefile for the Linux kernel device drivers. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile. + +EXTRA_CFLAGS += -I$(src)/include + +obj-m += iscsi_trgt.o +iscsi_trgt-objs := tio.o iscsi.o nthread.o wthread.o config.o digest.o \ + conn.o session.o target.o volume.o iotype.o \ + file-io.o null-io.o target_disk.o event.o param.o \ + block-io.o ua.o + --- linux-2.6.37.orig/ubuntu/iscsitarget/block-io.c +++ linux-2.6.37/ubuntu/iscsitarget/block-io.c @@ -0,0 +1,327 @@ +/* + * Target device block I/O. + * + * Based on file I/O driver from FUJITA Tomonori + * (C) 2004 - 2005 FUJITA Tomonori + * (C) 2006 Andre Brinkmann + * (C) 2007 Ross Walker + * (C) 2007 Ming Zhang + * This code is licenced under the GPL. + */ + +#include +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +struct blockio_data { + char *path; + struct block_device *bdev; +}; + +struct tio_work { + atomic_t error; + atomic_t bios_remaining; + struct completion tio_complete; +}; + +static void blockio_bio_endio(struct bio *bio, int error) +{ + struct tio_work *tio_work = bio->bi_private; + + error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? error : -EIO; + + if (error) + atomic_set(&tio_work->error, error); + + /* If last bio signal completion */ + if (atomic_dec_and_test(&tio_work->bios_remaining)) + complete(&tio_work->tio_complete); + + bio_put(bio); +} + +/* + * Blockio_make_request(): The function translates an iscsi-request into + * a number of requests to the corresponding block device. + */ +static int +blockio_make_request(struct iet_volume *volume, struct tio *tio, int rw) +{ + struct blockio_data *bio_data = volume->private; + struct request_queue *bdev_q = bdev_get_queue(bio_data->bdev); + struct tio_work *tio_work; + struct bio *tio_bio = NULL, *bio = NULL, *biotail = NULL; + + u32 offset = tio->offset; + u32 size = tio->size; + u32 tio_index = 0; + + int max_pages = 1; + int err = 0; + + loff_t ppos = ((loff_t) tio->idx << PAGE_SHIFT) + offset; + + /* Calculate max_pages for bio_alloc (memory saver) */ + if (bdev_q) + max_pages = bio_get_nr_vecs(bio_data->bdev); + + tio_work = kzalloc(sizeof (*tio_work), GFP_KERNEL); + if (!tio_work) + return -ENOMEM; + + atomic_set(&tio_work->error, 0); + atomic_set(&tio_work->bios_remaining, 0); + init_completion(&tio_work->tio_complete); + + /* Main processing loop, allocate and fill all bios */ + while (tio_index < tio->pg_cnt) { + bio = bio_alloc(GFP_KERNEL, min(max_pages, BIO_MAX_PAGES)); + if (!bio) { + err = -ENOMEM; + goto out; + } + + /* bi_sector is ALWAYS in units of 512 bytes */ + bio->bi_sector = ppos >> 9; + bio->bi_bdev = bio_data->bdev; + bio->bi_end_io = blockio_bio_endio; + bio->bi_private = tio_work; + + if (tio_bio) + biotail = biotail->bi_next = bio; + else + tio_bio = biotail = bio; + + atomic_inc(&tio_work->bios_remaining); + + /* Loop for filling bio */ + while (tio_index < tio->pg_cnt) { + unsigned int bytes = PAGE_SIZE - offset; + + if (bytes > size) + bytes = size; + + if (!bio_add_page(bio, tio->pvec[tio_index], bytes, offset)) + break; + + size -= bytes; + ppos += bytes; + + offset = 0; + + tio_index++; + } + } + + /* Walk the list, submitting bios 1 by 1 */ + while (tio_bio) { + bio = tio_bio; + tio_bio = tio_bio->bi_next; + bio->bi_next = NULL; + + submit_bio(rw, bio); + } + + if (bdev_q && bdev_q->unplug_fn) + bdev_q->unplug_fn(bdev_q); + + wait_for_completion(&tio_work->tio_complete); + + err = atomic_read(&tio_work->error); + + kfree(tio_work); + + return err; +out: + while (tio_bio) { + bio = tio_bio; + tio_bio = tio_bio->bi_next; + + bio_put(bio); + } + + kfree(tio_work); + + return err; +} + +static int +blockio_open_path(struct iet_volume *volume, const char *path) +{ + struct blockio_data *bio_data = volume->private; + struct block_device *bdev; + int flags = FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE); + int err = 0; + + bio_data->path = kstrdup(path, GFP_KERNEL); + if (!bio_data->path) + return -ENOMEM; + + bdev = open_bdev_exclusive(path, flags, THIS_MODULE); + if (IS_ERR(bdev)) { + err = PTR_ERR(bdev); + eprintk("Can't open device %s, error %d\n", path, err); + bio_data->bdev = NULL; + } else { + bio_data->bdev = bdev; + fsync_bdev(bio_data->bdev); + } + + return err; +} + +/* Create an enumeration of our accepted actions */ +enum +{ + opt_path, opt_ignore, opt_err, +}; + +/* Create a match table using our action enums and their matching options */ +static match_table_t tokens = { + {opt_path, "path=%s"}, + {opt_ignore, "scsiid=%s"}, + {opt_ignore, "scsisn=%s"}, + {opt_ignore, "type=%s"}, + {opt_ignore, "iomode=%s"}, + {opt_ignore, "blocksize=%s"}, + {opt_err, NULL}, +}; + +static int +parse_blockio_params(struct iet_volume *volume, char *params) +{ + struct blockio_data *info = volume->private; + int err = 0; + char *p, *q; + + /* Loop through parameters separated by commas, look up our + * parameter in match table, return enumeration and arguments + * select case based on the returned enum and run the action */ + while ((p = strsep(¶ms, ",")) != NULL) { + substring_t args[MAX_OPT_ARGS]; + int token; + if (!*p) + continue; + iet_strtolower(p); + token = match_token(p, tokens, args); + switch (token) { + case opt_path: + if (info->path) { + iprintk("Target %s, LUN %u: " + "duplicate \"Path\" param\n", + volume->target->name, volume->lun); + err = -EINVAL; + goto out; + } + if (!(q = match_strdup(&args[0]))) { + err = -ENOMEM; + goto out; + } + err = blockio_open_path(volume, q); + kfree(q); + if (err < 0) + goto out; + break; + case opt_ignore: + break; + default: + iprintk("Target %s, LUN %u: unknown param %s\n", + volume->target->name, volume->lun, p); + return -EINVAL; + } + } + + if (!info->path) { + iprintk("Target %s, LUN %u: missing \"Path\" param\n", + volume->target->name, volume->lun); + err = -EINVAL; + } + + out: + return err; +} + +static void +blockio_detach(struct iet_volume *volume) +{ + struct blockio_data *bio_data = volume->private; + int flags = FMODE_READ | (LUReadonly(volume) ? 0 : FMODE_WRITE); + + if (bio_data->bdev) + close_bdev_exclusive(bio_data->bdev, flags); + kfree(bio_data->path); + + kfree(volume->private); +} + +static int +blockio_attach(struct iet_volume *volume, char *args) +{ + struct blockio_data *bio_data; + int err = 0; + + if (volume->private) { + eprintk("Lun %u already attached on Target %s \n", + volume->lun, volume->target->name); + return -EBUSY; + } + + bio_data = kzalloc(sizeof (*bio_data), GFP_KERNEL); + if (!bio_data) + return -ENOMEM; + + volume->private = bio_data; + + err = parse_blockio_params(volume, args); + if (!err) { + /* see Documentation/ABI/testing/sysfs-block */ + unsigned bsz = bdev_logical_block_size(bio_data->bdev); + if (!volume->blk_shift) + volume->blk_shift = blksize_bits(bsz); + else if (volume->blk_shift < blksize_bits(bsz)) { + eprintk("Specified block size (%u) smaller than " + "device %s logical block size (%u)\n", + (1 << volume->blk_shift), bio_data->path, bsz); + err = -EINVAL; + } + } + if (err < 0) { + eprintk("Error attaching Lun %u to Target %s \n", + volume->lun, volume->target->name); + goto out; + } + + volume->blk_cnt = bio_data->bdev->bd_inode->i_size >> volume->blk_shift; + + /* Offer neither write nor read caching */ + ClearLURCache(volume); + ClearLUWCache(volume); + + out: + if (err < 0) + blockio_detach(volume); + + return err; +} + +static void +blockio_show(struct iet_volume *volume, struct seq_file *seq) +{ + struct blockio_data *bio_data = volume->private; + + /* Used to display blockio volume info in /proc/net/iet/volumes */ + seq_printf(seq, " path:%s\n", bio_data->path); +} + +struct iotype blockio = { + .name = "blockio", + .attach = blockio_attach, + .make_request = blockio_make_request, + .detach = blockio_detach, + .show = blockio_show, +}; --- linux-2.6.37.orig/ubuntu/iscsitarget/compat.h +++ linux-2.6.37/ubuntu/iscsitarget/compat.h @@ -0,0 +1,30 @@ +/* + * Kernel compatibility routines + * + * Copyright (C) 2008 Ross Walker + * + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef __IET_COMPAT_H__ +#define __IET_COMPAT_H__ + +#include + +#ifndef DECLARE_COMPLETION_ONSTACK +#define DECLARE_COMPLETION_ONSTACK(work) DECLARE_COMPLETION(work) +#endif + +#ifndef is_power_of_2 +#define is_power_of_2(n) (n != 0 && ((n & (n - 1)) == 0)) +#endif + +#ifndef log2 +#define log2(n) ((sizeof(n) <= 4) ? (fls(n) - 1) : (fls64(n) - 1)) +#endif + +#ifndef roundup_pow_of_two +#define roundup_pow_of_two(n) (1UL << fls_long(n - 1)) +#endif + +#endif /* __IET_COMPAT_H__ */ --- linux-2.6.37.orig/ubuntu/iscsitarget/config.c +++ linux-2.6.37/ubuntu/iscsitarget/config.c @@ -0,0 +1,362 @@ +/* + * (C) 2004 - 2005 FUJITA Tomonori + * + * This code is licenced under the GPL. + */ + +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" + +static DEFINE_SEMAPHORE(ioctl_sem); + +struct proc_entries { + const char *name; + struct file_operations *fops; +}; + +static struct proc_entries iet_proc_entries[] = +{ + {"volume", &volume_seq_fops}, + {"session", &session_seq_fops}, +}; + +static struct proc_dir_entry *proc_iet_dir; + +void iet_procfs_exit(void) +{ + int i; + + if (!proc_iet_dir) + return; + + for (i = 0; i < ARRAY_SIZE(iet_proc_entries); i++) + remove_proc_entry(iet_proc_entries[i].name, proc_iet_dir); + + remove_proc_entry(proc_iet_dir->name, proc_iet_dir->parent); +} + +int iet_procfs_init(void) +{ + int i; + struct proc_dir_entry *ent; + + if (!(proc_iet_dir = proc_mkdir("iet", init_net.proc_net))) + goto err; + + for (i = 0; i < ARRAY_SIZE(iet_proc_entries); i++) { + ent = create_proc_entry(iet_proc_entries[i].name, 0, proc_iet_dir); + if (ent) + ent->proc_fops = iet_proc_entries[i].fops; + else + goto err; + } + + return 0; + +err: + if (proc_iet_dir) + iet_procfs_exit(); + + return -ENOMEM; +} + +static int get_module_info(unsigned long ptr) +{ + struct module_info info; + int err; + + snprintf(info.version, sizeof(info.version), "%s", IET_VERSION_STRING); + + err = copy_to_user((void *) ptr, &info, sizeof(info)); + if (err) + return -EFAULT; + + return 0; +} + +static int get_conn_info(struct iscsi_target *target, unsigned long ptr) +{ + struct iscsi_session *session; + struct iscsi_conn *conn; + struct conn_info info; + int err; + + err = copy_from_user(&info, (void *) ptr, sizeof(info)); + if (err) + return -EFAULT; + + session = session_lookup(target, info.sid); + if (!session) + return -ENOENT; + + conn = conn_lookup(session, info.cid); + if (!conn) + return -ENOENT; + + info.cid = conn->cid; + info.stat_sn = conn->stat_sn; + info.exp_stat_sn = conn->exp_stat_sn; + + err = copy_to_user((void *) ptr, &info, sizeof(info)); + if (err) + return -EFAULT; + + return 0; +} + +static int add_conn(struct iscsi_target *target, unsigned long ptr) +{ + struct iscsi_session *session; + struct conn_info info; + int err; + + err = copy_from_user(&info, (void *) ptr, sizeof(info)); + if (err) + return -EFAULT; + + session = session_lookup(target, info.sid); + if (!session) + return -ENOENT; + + return conn_add(session, &info); +} + +static int del_conn(struct iscsi_target *target, unsigned long ptr) +{ + struct iscsi_session *session; + struct conn_info info; + int err; + + err = copy_from_user(&info, (void *) ptr, sizeof(info)); + if (err) + return -EFAULT; + + session = session_lookup(target, info.sid); + if (!session) + return -ENOENT; + + return conn_del(session, &info); +} + +static int get_session_info(struct iscsi_target *target, unsigned long ptr) +{ + struct iscsi_session *session; + struct session_info info; + int err; + + err = copy_from_user(&info, (void *) ptr, sizeof(info)); + if (err) + return -EFAULT; + + session = session_lookup(target, info.sid); + if (!session) + return -ENOENT; + + info.exp_cmd_sn = session->exp_cmd_sn; + info.max_cmd_sn = session->max_cmd_sn; + + err = copy_to_user((void *) ptr, &info, sizeof(info)); + if (err) + return -EFAULT; + + return 0; +} + +static int add_session(struct iscsi_target *target, unsigned long ptr) +{ + struct session_info info; + int err; + + err = copy_from_user(&info, (void *) ptr, sizeof(info)); + if (err) + return -EFAULT; + + return session_add(target, &info); +} + +static int del_session(struct iscsi_target *target, unsigned long ptr) +{ + struct session_info info; + int err; + + err = copy_from_user(&info, (void *) ptr, sizeof(info)); + if (err) + return -EFAULT; + + return session_del(target, info.sid); +} + +static int add_volume(struct iscsi_target *target, unsigned long ptr) +{ + struct volume_info info; + int err; + + err = copy_from_user(&info, (void *) ptr, sizeof(info)); + if (err) + return -EFAULT; + + return volume_add(target, &info); +} + +static int del_volume(struct iscsi_target *target, unsigned long ptr) +{ + struct volume_info info; + int err; + + err = copy_from_user(&info, (void *) ptr, sizeof(info)); + if (err) + return -EFAULT; + + return iscsi_volume_del(target, &info); +} + +static int iscsi_param_config(struct iscsi_target *target, unsigned long ptr, int set) +{ + struct iscsi_param_info info; + int err; + + err = copy_from_user(&info, (void *) ptr, sizeof(info)); + if (err) + return -EFAULT; + + err = iscsi_param_set(target, &info, set); + if (err < 0 || set) + return err; + + err = copy_to_user((void *) ptr, &info, sizeof(info)); + if (err) + return -EFAULT; + + return 0; +} + +static int add_target(unsigned long ptr) +{ + struct target_info info; + int err; + + err = copy_from_user(&info, (void *) ptr, sizeof(info)); + if (err) + return -EFAULT; + + err = target_add(&info); + if (err < 0) + return err; + + err = copy_to_user((void *) ptr, &info, sizeof(info)); + if (err) + return -EFAULT; + + return 0; +} + +static long ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct iscsi_target *target = NULL; + long err; + u32 id; + + err = down_interruptible(&ioctl_sem); + if (err < 0) + return err; + + if (cmd == GET_MODULE_INFO) { + err = get_module_info(arg); + goto done; + } + + if (cmd == ADD_TARGET) { + err = add_target(arg); + goto done; + } + + err = get_user(id, (u32 *) arg); + if (err < 0) + goto done; + + /* locking handled in target_del */ + if (cmd == DEL_TARGET) { + err = target_del(id); + goto done; + } + + target = target_lookup_by_id(id); + if (!target) { + err = -ENOENT; + goto done; + } + + err = target_lock(target, 1); + if (err < 0) + goto done; + + switch (cmd) { + case ADD_VOLUME: + err = add_volume(target, arg); + break; + + case DEL_VOLUME: + err = del_volume(target, arg); + break; + + case ADD_SESSION: + err = add_session(target, arg); + break; + + case DEL_SESSION: + err = del_session(target, arg); + break; + + case GET_SESSION_INFO: + err = get_session_info(target, arg); + break; + + case ISCSI_PARAM_SET: + err = iscsi_param_config(target, arg, 1); + break; + + case ISCSI_PARAM_GET: + err = iscsi_param_config(target, arg, 0); + break; + + case ADD_CONN: + err = add_conn(target, arg); + break; + + case DEL_CONN: + err = del_conn(target, arg); + break; + + case GET_CONN_INFO: + err = get_conn_info(target, arg); + break; + default: + eprintk("invalid ioctl cmd %x\n", cmd); + err = -EINVAL; + } + + target_unlock(target); +done: + up(&ioctl_sem); + + return err; +} + +static int release(struct inode *i __attribute__((unused)), + struct file *f __attribute__((unused))) +{ + down(&ioctl_sem); + target_del_all(); + up(&ioctl_sem); + + return 0; +} + +struct file_operations ctr_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = ioctl, + .compat_ioctl = ioctl, + .release = release +}; --- linux-2.6.37.orig/ubuntu/iscsitarget/conn.c +++ linux-2.6.37/ubuntu/iscsitarget/conn.c @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "digest.h" + +static void print_conn_state(char *p, size_t size, unsigned long state) +{ + if (test_bit(CONN_ACTIVE, &state)) + snprintf(p, size, "%s", "active"); + else if (test_bit(CONN_CLOSING, &state)) + snprintf(p, size, "%s", "closing"); + else + snprintf(p, size, "%s", "unknown"); +} + +static void print_digest_state(char *p, size_t size, unsigned long flags) +{ + if (DIGEST_NONE & flags) + snprintf(p, size, "%s", "none"); + else if (DIGEST_CRC32C & flags) + snprintf(p, size, "%s", "crc32c"); + else + snprintf(p, size, "%s", "unknown"); +} + +void conn_info_show(struct seq_file *seq, struct iscsi_session *session) +{ + struct iscsi_conn *conn; + struct sock *sk; + char buf[64]; + + list_for_each_entry(conn, &session->conn_list, list) { + sk = conn->sock->sk; + switch (sk->sk_family) { + case AF_INET: + snprintf(buf, sizeof(buf), + "%pI4", &inet_sk(sk)->inet_daddr); + break; + case AF_INET6: + snprintf(buf, sizeof(buf), "[%pI6]", + &inet6_sk(sk)->daddr); + break; + default: + break; + } + seq_printf(seq, "\t\tcid:%u ip:%s ", conn->cid, buf); + print_conn_state(buf, sizeof(buf), conn->state); + seq_printf(seq, "state:%s ", buf); + print_digest_state(buf, sizeof(buf), conn->hdigest_type); + seq_printf(seq, "hd:%s ", buf); + print_digest_state(buf, sizeof(buf), conn->ddigest_type); + seq_printf(seq, "dd:%s\n", buf); + } +} + +struct iscsi_conn *conn_lookup(struct iscsi_session *session, u16 cid) +{ + struct iscsi_conn *conn; + + list_for_each_entry(conn, &session->conn_list, list) { + if (conn->cid == cid) + return conn; + } + return NULL; +} + +static void iet_state_change(struct sock *sk) +{ + struct iscsi_conn *conn = sk->sk_user_data; + struct iscsi_target *target = conn->session->target; + + if (sk->sk_state != TCP_ESTABLISHED) + conn_close(conn); + else + nthread_wakeup(target); + + target->nthread_info.old_state_change(sk); +} + +static void iet_data_ready(struct sock *sk, int len) +{ + struct iscsi_conn *conn = sk->sk_user_data; + struct iscsi_target *target = conn->session->target; + + nthread_wakeup(target); + target->nthread_info.old_data_ready(sk, len); +} + +/* + * @locking: grabs the target's nthread_lock to protect it from races with + * set_conn_wspace_wait() + */ +static void iet_write_space(struct sock *sk) +{ + struct iscsi_conn *conn = sk->sk_user_data; + struct network_thread_info *info = &conn->session->target->nthread_info; + + spin_lock_bh(&info->nthread_lock); + + if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk) && + test_bit(CONN_WSPACE_WAIT, &conn->state)) { + clear_bit(CONN_WSPACE_WAIT, &conn->state); + __nthread_wakeup(info); + } + + spin_unlock_bh(&info->nthread_lock); + + info->old_write_space(sk); +} + +static void iet_socket_bind(struct iscsi_conn *conn) +{ + int opt = 1; + mm_segment_t oldfs; + struct iscsi_session *session = conn->session; + struct iscsi_target *target = session->target; + + dprintk(D_GENERIC, "%llu\n", (unsigned long long) session->sid); + + conn->sock = SOCKET_I(conn->file->f_dentry->d_inode); + conn->sock->sk->sk_user_data = conn; + + write_lock_bh(&conn->sock->sk->sk_callback_lock); + target->nthread_info.old_state_change = conn->sock->sk->sk_state_change; + conn->sock->sk->sk_state_change = iet_state_change; + + target->nthread_info.old_data_ready = conn->sock->sk->sk_data_ready; + conn->sock->sk->sk_data_ready = iet_data_ready; + + target->nthread_info.old_write_space = conn->sock->sk->sk_write_space; + conn->sock->sk->sk_write_space = iet_write_space; + write_unlock_bh(&conn->sock->sk->sk_callback_lock); + + oldfs = get_fs(); + set_fs(get_ds()); + conn->sock->ops->setsockopt(conn->sock, SOL_TCP, TCP_NODELAY, (void *)&opt, sizeof(opt)); + set_fs(oldfs); +} + +int conn_free(struct iscsi_conn *conn) +{ + dprintk(D_GENERIC, "%p %#Lx %u\n", conn->session, + (unsigned long long) conn->session->sid, conn->cid); + + assert(atomic_read(&conn->nr_cmnds) == 0); + assert(list_empty(&conn->pdu_list)); + assert(list_empty(&conn->write_list)); + + list_del(&conn->list); + list_del(&conn->poll_list); + + del_timer_sync(&conn->nop_timer); + digest_cleanup(conn); + kfree(conn); + + return 0; +} + +static int iet_conn_alloc(struct iscsi_session *session, struct conn_info *info) +{ + struct iscsi_conn *conn; + + dprintk(D_SETUP, "%#Lx:%u\n", (unsigned long long) session->sid, info->cid); + + conn = kzalloc(sizeof(*conn), GFP_KERNEL); + if (!conn) + return -ENOMEM; + + conn->session = session; + conn->cid = info->cid; + conn->stat_sn = info->stat_sn; + conn->exp_stat_sn = info->exp_stat_sn; + + conn->hdigest_type = info->header_digest; + conn->ddigest_type = info->data_digest; + if (digest_init(conn) < 0) { + kfree(conn); + return -ENOMEM; + } + + spin_lock_init(&conn->list_lock); + atomic_set(&conn->nr_cmnds, 0); + atomic_set(&conn->nr_busy_cmnds, 0); + INIT_LIST_HEAD(&conn->pdu_list); + INIT_LIST_HEAD(&conn->write_list); + INIT_LIST_HEAD(&conn->poll_list); + init_timer(&conn->nop_timer); + + list_add(&conn->list, &session->conn_list); + + set_bit(CONN_ACTIVE, &conn->state); + + conn->file = fget(info->fd); + iet_socket_bind(conn); + + list_add(&conn->poll_list, &session->target->nthread_info.active_conns); + + nthread_wakeup(conn->session->target); + + return 0; +} + +void conn_close(struct iscsi_conn *conn) +{ + struct iscsi_cmnd *cmnd; + struct iscsi_session *session = conn->session; + + if (test_and_clear_bit(CONN_ACTIVE, &conn->state)) + set_bit(CONN_CLOSING, &conn->state); + + spin_lock(&conn->list_lock); + list_for_each_entry(cmnd, &conn->pdu_list, conn_list) { + set_cmnd_tmfabort(cmnd); + if (cmnd->lun) { + ua_establish_for_session(session, cmnd->lun->lun, 0x47, 0x7f); + iscsi_cmnd_set_sense(cmnd, UNIT_ATTENTION, 0x6e, 0x0); + } + } + spin_unlock(&conn->list_lock); + + nthread_wakeup(conn->session->target); +} + +int conn_add(struct iscsi_session *session, struct conn_info *info) +{ + struct iscsi_conn *conn; + int err; + + conn = conn_lookup(session, info->cid); + if (conn) + conn_close(conn); + + err = iet_conn_alloc(session, info); + if (!err && conn) + err = -EEXIST; + + return err; +} + +int conn_del(struct iscsi_session *session, struct conn_info *info) +{ + struct iscsi_conn *conn; + int err = -EEXIST; + + conn = conn_lookup(session, info->cid); + if (!conn) + return err; + + conn_close(conn); + + return 0; +} --- linux-2.6.37.orig/ubuntu/iscsitarget/digest.c +++ linux-2.6.37/ubuntu/iscsitarget/digest.c @@ -0,0 +1,279 @@ +/* + * iSCSI digest handling. + * (C) 2004 - 2006 Xiranet Communications GmbH + * This code is licensed under the GPL. + */ + +#include + +#include "iscsi.h" +#include "digest.h" +#include "iscsi_dbg.h" + +void digest_alg_available(unsigned int *val) +{ + if (*val & DIGEST_CRC32C && + !crypto_has_alg("crc32c", 0, CRYPTO_ALG_ASYNC)) { + printk("CRC32C digest algorithm not available in kernel\n"); + *val |= ~DIGEST_CRC32C; + } +} + +/** + * initialize support for digest calculation. + * + * digest_init - + * @conn: ptr to connection to make use of digests + * + * @return: 0 on success, < 0 on error + */ +int digest_init(struct iscsi_conn *conn) +{ + int err = 0; + + if (!(conn->hdigest_type & DIGEST_ALL)) + conn->hdigest_type = DIGEST_NONE; + + if (!(conn->ddigest_type & DIGEST_ALL)) + conn->ddigest_type = DIGEST_NONE; + + if (conn->hdigest_type & DIGEST_CRC32C || + conn->ddigest_type & DIGEST_CRC32C) { + conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, + CRYPTO_ALG_ASYNC); + conn->rx_hash.flags = 0; + if (IS_ERR(conn->rx_hash.tfm)) { + conn->rx_hash.tfm = NULL; + err = -ENOMEM; + goto out; + } + + conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, + CRYPTO_ALG_ASYNC); + conn->tx_hash.flags = 0; + if (IS_ERR(conn->tx_hash.tfm)) { + conn->tx_hash.tfm = NULL; + err = -ENOMEM; + goto out; + } + } + +out: + if (err) + digest_cleanup(conn); + + return err; +} + +/** + * free resources used for digest calculation. + * + * digest_cleanup - + * @conn: ptr to connection that made use of digests + */ +void digest_cleanup(struct iscsi_conn *conn) +{ + if (conn->tx_hash.tfm) + crypto_free_hash(conn->tx_hash.tfm); + if (conn->rx_hash.tfm) + crypto_free_hash(conn->rx_hash.tfm); +} + +/** + * debug handling of header digest errors: + * simulates a digest error after n PDUs / every n-th PDU of type + * HDIGEST_ERR_CORRUPT_PDU_TYPE. + */ +static inline void __dbg_simulate_header_digest_error(struct iscsi_cmnd *cmnd) +{ +#define HDIGEST_ERR_AFTER_N_CMNDS 1000 +#define HDIGEST_ERR_ONLY_ONCE 1 +#define HDIGEST_ERR_CORRUPT_PDU_TYPE ISCSI_OP_SCSI_CMD +#define HDIGEST_ERR_CORRUPT_PDU_WITH_DATA_ONLY 0 + + static int num_cmnds = 0; + static int num_errs = 0; + + if (cmnd_opcode(cmnd) == HDIGEST_ERR_CORRUPT_PDU_TYPE) { + if (HDIGEST_ERR_CORRUPT_PDU_WITH_DATA_ONLY) { + if (cmnd->pdu.datasize) + num_cmnds++; + } else + num_cmnds++; + } + + if ((num_cmnds == HDIGEST_ERR_AFTER_N_CMNDS) + && (!(HDIGEST_ERR_ONLY_ONCE && num_errs))) { + printk("*** Faking header digest error ***\n"); + printk("\tcmnd: 0x%x, itt 0x%x, sn 0x%x\n", + cmnd_opcode(cmnd), + be32_to_cpu(cmnd->pdu.bhs.itt), + be32_to_cpu(cmnd->pdu.bhs.sn)); + cmnd->hdigest = ~cmnd->hdigest; + /* make things even worse by manipulating header fields */ + cmnd->pdu.datasize += 8; + num_errs++; + num_cmnds = 0; + } + return; +} + +/** + * debug handling of data digest errors: + * simulates a digest error after n PDUs / every n-th PDU of type + * DDIGEST_ERR_CORRUPT_PDU_TYPE. + */ +static inline void __dbg_simulate_data_digest_error(struct iscsi_cmnd *cmnd) +{ +#define DDIGEST_ERR_AFTER_N_CMNDS 50 +#define DDIGEST_ERR_ONLY_ONCE 1 +#define DDIGEST_ERR_CORRUPT_PDU_TYPE ISCSI_OP_SCSI_DATA_OUT +#define DDIGEST_ERR_CORRUPT_UNSOL_DATA_ONLY 0 + + static int num_cmnds = 0; + static int num_errs = 0; + + if ((cmnd->pdu.datasize) + && (cmnd_opcode(cmnd) == DDIGEST_ERR_CORRUPT_PDU_TYPE)) { + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_SCSI_DATA_OUT: + if ((DDIGEST_ERR_CORRUPT_UNSOL_DATA_ONLY) + && (cmnd->pdu.bhs.ttt != ISCSI_RESERVED_TAG)) + break; + default: + num_cmnds++; + } + } + + if ((num_cmnds == DDIGEST_ERR_AFTER_N_CMNDS) + && (!(DDIGEST_ERR_ONLY_ONCE && num_errs)) + && (cmnd->pdu.datasize) + && (!cmnd->conn->read_overflow)) { + printk("*** Faking data digest error: ***"); + printk("\tcmnd 0x%x, itt 0x%x, sn 0x%x\n", + cmnd_opcode(cmnd), + be32_to_cpu(cmnd->pdu.bhs.itt), + be32_to_cpu(cmnd->pdu.bhs.sn)); + cmnd->ddigest = ~cmnd->ddigest; + num_errs++; + num_cmnds = 0; + } +} + +static void digest_header(struct hash_desc *hash, struct iscsi_pdu *pdu, + u8 *crc) +{ + struct scatterlist sg[2]; + unsigned int nbytes = sizeof(struct iscsi_hdr); + + sg_init_table(sg, pdu->ahssize ? 2 : 1); + + sg_set_buf(&sg[0], &pdu->bhs, nbytes); + if (pdu->ahssize) { + sg_set_buf(&sg[1], pdu->ahs, pdu->ahssize); + nbytes += pdu->ahssize; + } + + crypto_hash_init(hash); + crypto_hash_update(hash, sg, nbytes); + crypto_hash_final(hash, crc); +} + +int digest_rx_header(struct iscsi_cmnd *cmnd) +{ + u32 crc; + + digest_header(&cmnd->conn->rx_hash, &cmnd->pdu, (u8 *) &crc); + if (crc != cmnd->hdigest) + return -EIO; + + return 0; +} + +void digest_tx_header(struct iscsi_cmnd *cmnd) +{ + digest_header(&cmnd->conn->tx_hash, &cmnd->pdu, (u8 *) &cmnd->hdigest); +} + +static void digest_data(struct hash_desc *hash, struct iscsi_cmnd *cmnd, + struct tio *tio, u32 offset, u8 *crc) +{ + struct scatterlist *sg = cmnd->conn->hash_sg; + u32 size, length; + int i, idx, count; + unsigned int nbytes; + + size = cmnd->pdu.datasize; + nbytes = size = (size + 3) & ~3; + + offset += tio->offset; + idx = offset >> PAGE_CACHE_SHIFT; + offset &= ~PAGE_CACHE_MASK; + count = get_pgcnt(size, offset); + assert(idx + count <= tio->pg_cnt); + + assert(count <= ISCSI_CONN_IOV_MAX); + + sg_init_table(sg, ARRAY_SIZE(cmnd->conn->hash_sg)); + crypto_hash_init(hash); + + for (i = 0; size; i++) { + if (offset + size > PAGE_CACHE_SIZE) + length = PAGE_CACHE_SIZE - offset; + else + length = size; + + sg_set_page(&sg[i], tio->pvec[idx + i], length, offset); + size -= length; + offset = 0; + } + + sg_mark_end(&sg[i - 1]); + + crypto_hash_update(hash, sg, nbytes); + crypto_hash_final(hash, crc); +} + +int digest_rx_data(struct iscsi_cmnd *cmnd) +{ + struct tio *tio; + struct iscsi_cmnd *scsi_cmnd; + struct iscsi_data_out_hdr *req; + u32 offset, crc; + + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_SCSI_REJECT: + case ISCSI_OP_PDU_REJECT: + case ISCSI_OP_DATA_REJECT: + return 0; + case ISCSI_OP_SCSI_DATA_OUT: + scsi_cmnd = cmnd->req; + req = (struct iscsi_data_out_hdr *) &cmnd->pdu.bhs; + tio = scsi_cmnd->tio; + offset = be32_to_cpu(req->buffer_offset); + break; + default: + tio = cmnd->tio; + offset = 0; + } + + digest_data(&cmnd->conn->rx_hash, cmnd, tio, offset, (u8 *) &crc); + + if (!cmnd->conn->read_overflow && + (cmnd_opcode(cmnd) != ISCSI_OP_PDU_REJECT)) { + if (crc != cmnd->ddigest) + return -EIO; + } + + return 0; +} + +void digest_tx_data(struct iscsi_cmnd *cmnd) +{ + struct tio *tio = cmnd->tio; + struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs; + + assert(tio); + digest_data(&cmnd->conn->tx_hash, cmnd, tio, + be32_to_cpu(req->buffer_offset), (u8 *) &cmnd->ddigest); +} --- linux-2.6.37.orig/ubuntu/iscsitarget/digest.h +++ linux-2.6.37/ubuntu/iscsitarget/digest.h @@ -0,0 +1,20 @@ +/* + * iSCSI digest handling. + * (C) 2004 Xiranet Communications GmbH + * This code is licensed under the GPL. + */ + +#ifndef __IET_DIGEST_H__ +#define __IET_DIGEST_H__ + +extern void digest_alg_available(unsigned int *val); +extern int digest_init(struct iscsi_conn *conn); +extern void digest_cleanup(struct iscsi_conn *conn); + +extern int digest_rx_header(struct iscsi_cmnd *cmnd); +extern int digest_rx_data(struct iscsi_cmnd *cmnd); + +extern void digest_tx_header(struct iscsi_cmnd *cmnd); +extern void digest_tx_data(struct iscsi_cmnd *cmnd); + +#endif /* __IET_DIGEST_H__ */ --- linux-2.6.37.orig/ubuntu/iscsitarget/event.c +++ linux-2.6.37/ubuntu/iscsitarget/event.c @@ -0,0 +1,96 @@ +/* + * Event notification code. + * (C) 2005 FUJITA Tomonori + * This code is licenced under the GPL. + * + * Some functions are based on audit code. + */ + +#include +#include "iet_u.h" +#include "iscsi_dbg.h" + +static struct sock *nl; +static u32 ietd_pid; + +static int event_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) +{ + u32 uid, pid, seq; + char *data; + + pid = NETLINK_CREDS(skb)->pid; + uid = NETLINK_CREDS(skb)->uid; + seq = nlh->nlmsg_seq; + data = NLMSG_DATA(nlh); + + ietd_pid = pid; + + return 0; +} + +static void event_recv_skb(struct sk_buff *skb) +{ + int err; + struct nlmsghdr *nlh; + u32 rlen; + + while (skb->len >= NLMSG_SPACE(0)) { + nlh = (struct nlmsghdr *)skb->data; + if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) + break; + rlen = NLMSG_ALIGN(nlh->nlmsg_len); + if (rlen > skb->len) + rlen = skb->len; + if ((err = event_recv_msg(skb, nlh))) { + netlink_ack(skb, nlh, -err); + } else if (nlh->nlmsg_flags & NLM_F_ACK) + netlink_ack(skb, nlh, 0); + skb_pull(skb, rlen); + } +} + +static int notify(void *data, int len, int gfp_mask) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + static u32 seq = 0; + + if (!(skb = alloc_skb(NLMSG_SPACE(len), gfp_mask))) + return -ENOMEM; + + nlh = __nlmsg_put(skb, ietd_pid, seq++, NLMSG_DONE, len - sizeof(*nlh), 0); + + memcpy(NLMSG_DATA(nlh), data, len); + + return netlink_unicast(nl, skb, ietd_pid, 0); +} + +int event_send(u32 tid, u64 sid, u32 cid, u32 state, int atomic) +{ + int err; + struct iet_event event; + + event.tid = tid; + event.sid = sid; + event.cid = cid; + event.state = state; + + err = notify(&event, NLMSG_SPACE(sizeof(struct iet_event)), 0); + + return err; +} + +int event_init(void) +{ + nl = netlink_kernel_create(&init_net, NETLINK_IET, 1, event_recv_skb, + NULL, THIS_MODULE); + if (!nl) + return -ENOMEM; + else + return 0; +} + +void event_exit(void) +{ + netlink_kernel_release(nl); +} --- linux-2.6.37.orig/ubuntu/iscsitarget/file-io.c +++ linux-2.6.37/ubuntu/iscsitarget/file-io.c @@ -0,0 +1,261 @@ +/* + * Target device file I/O. + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +struct fileio_data { + char *path; + struct file *filp; +}; + +static int fileio_make_request(struct iet_volume *lu, struct tio *tio, int rw) +{ + struct fileio_data *p = lu->private; + struct file *filp; + mm_segment_t oldfs; + struct page *page; + u32 offset, size; + loff_t ppos, count; + char *buf; + int i, err = 0; + ssize_t ret; + + assert(p); + filp = p->filp; + size = tio->size; + offset= tio->offset; + + ppos = (loff_t) tio->idx << PAGE_CACHE_SHIFT; + ppos += offset; + + for (i = 0; i < tio->pg_cnt; i++) { + page = tio->pvec[i]; + assert(page); + buf = page_address(page); + buf += offset; + + if (offset + size > PAGE_CACHE_SIZE) + count = PAGE_CACHE_SIZE - offset; + else + count = size; + + oldfs = get_fs(); + set_fs(get_ds()); + + if (rw == READ) + ret = vfs_read(filp, buf, count, &ppos); + else + ret = vfs_write(filp, buf, count, &ppos); + + set_fs(oldfs); + + if (ret != count) { + eprintk("I/O error %lld, %ld\n", count, (long) ret); + err = -EIO; + } + + size -= count; + offset = 0; + } + assert(!size); + + return err; +} + +static int fileio_sync(struct iet_volume *lu, struct tio *tio) +{ + struct fileio_data *p = lu->private; + struct inode *inode = p->filp->f_dentry->d_inode; + struct address_space *mapping = inode->i_mapping; + loff_t ppos, count; + int res; + + if (tio) { + ppos = (loff_t) tio->idx << PAGE_CACHE_SHIFT; + ppos += tio->offset; + count = tio->size; + } else { + ppos = 0; + count = lu->blk_cnt << lu->blk_shift; + } + + res = filemap_write_and_wait_range(mapping, ppos, ppos + count - 1); + if (res) { + eprintk("I/O error: syncing pages failed: %d\n", res); + return -EIO; + } else + return 0; +} + +static int open_path(struct iet_volume *volume, const char *path) +{ + int err = 0; + struct fileio_data *info = volume->private; + struct file *filp; + mm_segment_t oldfs; + int flags; + + info->path = kstrdup(path, GFP_KERNEL); + if (!info->path) + return -ENOMEM; + + oldfs = get_fs(); + set_fs(get_ds()); + flags = (LUReadonly(volume) ? O_RDONLY : O_RDWR) | O_LARGEFILE; + filp = filp_open(path, flags, 0); + set_fs(oldfs); + + if (IS_ERR(filp)) { + err = PTR_ERR(filp); + eprintk("Can't open %s %d\n", path, err); + info->filp = NULL; + } else + info->filp = filp; + + return err; +} + +enum { + opt_path, opt_ignore, opt_err, +}; + +static match_table_t tokens = { + {opt_path, "path=%s"}, + {opt_ignore, "scsiid=%s"}, + {opt_ignore, "scsisn=%s"}, + {opt_ignore, "type=%s"}, + {opt_ignore, "iomode=%s"}, + {opt_ignore, "blocksize=%s"}, + {opt_err, NULL}, +}; + +static int parse_fileio_params(struct iet_volume *volume, char *params) +{ + struct fileio_data *info = volume->private; + int err = 0; + char *p, *q; + + while ((p = strsep(¶ms, ",")) != NULL) { + substring_t args[MAX_OPT_ARGS]; + int token; + if (!*p) + continue; + iet_strtolower(p); + token = match_token(p, tokens, args); + switch (token) { + case opt_path: + if (info->path) { + iprintk("Target %s, LUN %u: " + "duplicate \"Path\" param\n", + volume->target->name, volume->lun); + err = -EINVAL; + goto out; + } + if (!(q = match_strdup(&args[0]))) { + err = -ENOMEM; + goto out; + } + err = open_path(volume, q); + kfree(q); + if (err < 0) + goto out; + break; + case opt_ignore: + break; + default: + iprintk("Target %s, LUN %u: unknown param %s\n", + volume->target->name, volume->lun, p); + return -EINVAL; + } + } + + if (!info->path) { + iprintk("Target %s, LUN %u: missing \"Path\" param\n", + volume->target->name, volume->lun); + err = -EINVAL; + } +out: + return err; +} + +static void fileio_detach(struct iet_volume *lu) +{ + struct fileio_data *p = lu->private; + + kfree(p->path); + if (p->filp) + filp_close(p->filp, NULL); + kfree(p); + lu->private = NULL; +} + +static int fileio_attach(struct iet_volume *lu, char *args) +{ + int err = 0; + struct fileio_data *p; + struct inode *inode; + + if (lu->private) { + printk("already attached ? %d\n", lu->lun); + return -EBUSY; + } + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + lu->private = p; + + if ((err = parse_fileio_params(lu, args)) < 0) { + eprintk("%d\n", err); + goto out; + } + inode = p->filp->f_dentry->d_inode; + + if (S_ISREG(inode->i_mode)) + ; + else if (S_ISBLK(inode->i_mode)) + inode = inode->i_bdev->bd_inode; + else { + err = -EINVAL; + goto out; + } + + if (!lu->blk_shift) + lu->blk_shift = blksize_bits(IET_DEF_BLOCK_SIZE); + + lu->blk_cnt = inode->i_size >> lu->blk_shift; + + /* we're using the page cache */ + SetLURCache(lu); +out: + if (err < 0) + fileio_detach(lu); + return err; +} + +static void fileio_show(struct iet_volume *lu, struct seq_file *seq) +{ + struct fileio_data *p = lu->private; + seq_printf(seq, " path:%s\n", p->path); +} + +struct iotype fileio = +{ + .name = "fileio", + .attach = fileio_attach, + .make_request = fileio_make_request, + .sync = fileio_sync, + .detach = fileio_detach, + .show = fileio_show, +}; --- linux-2.6.37.orig/ubuntu/iscsitarget/iotype.c +++ linux-2.6.37/ubuntu/iscsitarget/iotype.c @@ -0,0 +1,110 @@ +/* + * Manager for various I/O types. + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include "iscsi.h" +#include "iotype.h" +#include "iscsi_dbg.h" + +static LIST_HEAD(iotypes); +static rwlock_t iotypes_lock = RW_LOCK_UNLOCKED; + +static struct iotype *find_iotype(const char *name) +{ + struct iotype *iot = NULL; + + list_for_each_entry(iot, &iotypes, iot_list) { + if (strcmp(iot->name, name) == 0) + return iot; + } + return NULL; +} + +struct iotype *get_iotype(const char *name) +{ + struct iotype *iot; + + read_lock(&iotypes_lock); + iot = find_iotype(name); + read_unlock(&iotypes_lock); + + return iot; +} + +void put_iotype(struct iotype *iot) +{ + if (!iot) + return; + return; +} + +static int register_iotype(struct iotype *iot) +{ + int err = 0; + struct iotype *p; + + write_lock(&iotypes_lock); + + p = find_iotype(iot->name); + if (p) + err = -EBUSY; + else + list_add_tail(&iot->iot_list, &iotypes); + + write_unlock(&iotypes_lock); + + return err; +} + +static int unregister_iotype(struct iotype *iot) +{ + int err = 0; + struct iotype *p; + + write_lock(&iotypes_lock); + + p = find_iotype(iot->name); + if (p && p == iot) + list_del_init(&iot->iot_list); + else + err = -EINVAL; + + write_unlock(&iotypes_lock); + + + return err; +} + +struct iotype *iotype_array[] = { + &fileio, + &blockio, + &nullio, +}; + +int iotype_init(void) +{ + int i, err; + + for (i = 0; i < ARRAY_SIZE(iotype_array); i++) { + if (!(err = register_iotype(iotype_array[i]))) + iprintk("Registered io type %s\n", + iotype_array[i]->name); + else { + eprintk("Failed to register io type %s\n", + iotype_array[i]->name); + break; + } + } + + return err; +} + +void iotype_exit(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(iotype_array); i++) + unregister_iotype(iotype_array[i]); +} --- linux-2.6.37.orig/ubuntu/iscsitarget/iotype.h +++ linux-2.6.37/ubuntu/iscsitarget/iotype.h @@ -0,0 +1,42 @@ +/* + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include +#include "iscsi.h" + +#ifndef __IOTYPE_H__ +#define __IOTYPE_H__ + +struct iotype { + const char *name; + struct list_head iot_list; + + int (*attach)(struct iet_volume *dev, char *args); + int (*make_request)(struct iet_volume *dev, struct tio *tio, int rw); + int (*sync)(struct iet_volume *dev, struct tio *tio); + void (*detach)(struct iet_volume *dev); + void (*show)(struct iet_volume *dev, struct seq_file *seq); +}; + +extern struct iotype fileio; +extern struct iotype nullio; +extern struct iotype blockio; + +extern int iotype_init(void); +extern void iotype_exit(void); + +/* For option parameter parsing. + * This is slightly iet specific: we only tolower() up to the first '='. + * Note that this changes *c _in place_, but our parsing + * routines copy the input to a scratch page before parsing anyways. */ +static inline void iet_strtolower(char *c) +{ + if (!c) + return; + for (; *c && *c != '='; c++) + *c = tolower(*c); +} + +#endif --- linux-2.6.37.orig/ubuntu/iscsitarget/iscsi.c +++ linux-2.6.37/ubuntu/iscsitarget/iscsi.c @@ -0,0 +1,1967 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * Copyright (C) 2008 Arne Redlich + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +unsigned long debug_enable_flags; +unsigned long worker_thread_pool_size; + +static struct kmem_cache *iscsi_cmnd_cache; +static u8 dummy_data[PAGE_SIZE]; + +static int ctr_major; +static char ctr_name[] = "ietctl"; +extern struct file_operations ctr_fops; + +static u32 cmnd_write_size(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd); + + if (hdr->flags & ISCSI_CMD_WRITE) + return be32_to_cpu(hdr->data_length); + return 0; +} + +static u32 cmnd_read_size(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *hdr = cmnd_hdr(cmnd); + + if (hdr->flags & ISCSI_CMD_READ) { + struct iscsi_rlength_ahdr *ahdr = + (struct iscsi_rlength_ahdr *)cmnd->pdu.ahs; + + if (!(hdr->flags & ISCSI_CMD_WRITE)) + return be32_to_cpu(hdr->data_length); + if (ahdr && ahdr->ahstype == ISCSI_AHSTYPE_RLENGTH) + return be32_to_cpu(ahdr->read_length); + } + return 0; +} + +static void iscsi_device_queue_cmnd(struct iscsi_cmnd *cmnd) +{ + set_cmnd_waitio(cmnd); + wthread_queue(cmnd); +} + +static void iscsi_scsi_queuecmnd(struct iscsi_cmnd *cmnd) +{ + struct iscsi_queue *queue = &cmnd->lun->queue; + + dprintk(D_GENERIC, "%p\n", cmnd); + + if ((cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) != ISCSI_CMD_UNTAGGED && + (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) != ISCSI_CMD_SIMPLE) { + cmnd->pdu.bhs.flags &= ~ISCSI_CMD_ATTR_MASK; + cmnd->pdu.bhs.flags |= ISCSI_CMD_UNTAGGED; + } + + spin_lock(&queue->queue_lock); + + set_cmnd_queued(cmnd); + + switch (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) { + case ISCSI_CMD_UNTAGGED: + case ISCSI_CMD_SIMPLE: + if (!list_empty(&queue->wait_list) || queue->ordered_cmnd) + goto pending; + queue->active_cnt++; + break; + + default: + BUG(); + } + spin_unlock(&queue->queue_lock); + + iscsi_device_queue_cmnd(cmnd); + return; + pending: + assert(list_empty(&cmnd->list)); + + list_add_tail(&cmnd->list, &queue->wait_list); + spin_unlock(&queue->queue_lock); + return; +} + +static void iscsi_scsi_dequeuecmnd(struct iscsi_cmnd *cmnd) +{ + struct iscsi_queue *queue; + + if (!cmnd->lun) + return; + queue = &cmnd->lun->queue; + spin_lock(&queue->queue_lock); + switch (cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK) { + case ISCSI_CMD_UNTAGGED: + case ISCSI_CMD_SIMPLE: + --queue->active_cnt; + break; + case ISCSI_CMD_ORDERED: + case ISCSI_CMD_HEAD_OF_QUEUE: + case ISCSI_CMD_ACA: + BUG(); + default: + /* Should the iscsi_scsi_queuecmnd func reject this ? */ + break; + } + + while (!list_empty(&queue->wait_list)) { + cmnd = list_entry(queue->wait_list.next, struct iscsi_cmnd, list); + switch ((cmnd->pdu.bhs.flags & ISCSI_CMD_ATTR_MASK)) { + case ISCSI_CMD_UNTAGGED: + case ISCSI_CMD_SIMPLE: + list_del_init(&cmnd->list); + queue->active_cnt++; + iscsi_device_queue_cmnd(cmnd); + break; + case ISCSI_CMD_ORDERED: + case ISCSI_CMD_HEAD_OF_QUEUE: + case ISCSI_CMD_ACA: + BUG(); + } + } + + spin_unlock(&queue->queue_lock); + + return; +} + +/** + * create a new command. + * + * iscsi_cmnd_create - + * @conn: ptr to connection (for i/o) + * + * @return ptr to command or NULL + */ + +struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *conn, int req) +{ + struct iscsi_cmnd *cmnd; + + /* TODO: async interface is necessary ? */ + cmnd = kmem_cache_alloc(iscsi_cmnd_cache, GFP_KERNEL|__GFP_NOFAIL); + + memset(cmnd, 0, sizeof(*cmnd)); + INIT_LIST_HEAD(&cmnd->list); + INIT_LIST_HEAD(&cmnd->pdu_list); + INIT_LIST_HEAD(&cmnd->conn_list); + INIT_LIST_HEAD(&cmnd->hash_list); + cmnd->conn = conn; + spin_lock(&conn->list_lock); + atomic_inc(&conn->nr_cmnds); + if (req) + list_add_tail(&cmnd->conn_list, &conn->pdu_list); + spin_unlock(&conn->list_lock); + cmnd->tio = NULL; + + dprintk(D_GENERIC, "%p:%p\n", conn, cmnd); + + return cmnd; +} + +/** + * create a new command used as response. + * + * iscsi_cmnd_create_rsp_cmnd - + * @cmnd: ptr to request command + * + * @return ptr to response command or NULL + */ + +static struct iscsi_cmnd *iscsi_cmnd_create_rsp_cmnd(struct iscsi_cmnd *cmnd, int final) +{ + struct iscsi_cmnd *rsp = cmnd_alloc(cmnd->conn, 0); + + if (final) + set_cmnd_final(rsp); + list_add_tail(&rsp->pdu_list, &cmnd->pdu_list); + rsp->req = cmnd; + return rsp; +} + +static struct iscsi_cmnd *get_rsp_cmnd(struct iscsi_cmnd *req) +{ + return list_entry(req->pdu_list.prev, struct iscsi_cmnd, pdu_list); +} + +static void iscsi_cmnds_init_write(struct list_head *send) +{ + struct iscsi_cmnd *cmnd = list_entry(send->next, struct iscsi_cmnd, list); + struct iscsi_conn *conn = cmnd->conn; + struct list_head *pos, *next; + + spin_lock(&conn->list_lock); + + list_for_each_safe(pos, next, send) { + cmnd = list_entry(pos, struct iscsi_cmnd, list); + + dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); + + list_del_init(&cmnd->list); + assert(conn == cmnd->conn); + list_add_tail(&cmnd->list, &conn->write_list); + } + + spin_unlock(&conn->list_lock); + + nthread_wakeup(conn->session->target); +} + +static void iscsi_cmnd_init_write(struct iscsi_cmnd *cmnd) +{ + LIST_HEAD(head); + + if (!list_empty(&cmnd->list)) { + eprintk("%x %x %x %x %lx %u %u %u %u %u %u %u %d %d\n", + cmnd_itt(cmnd), cmnd_ttt(cmnd), cmnd_opcode(cmnd), + cmnd_scsicode(cmnd), cmnd->flags, cmnd->r2t_sn, + cmnd->r2t_length, cmnd->is_unsolicited_data, + cmnd->target_task_tag, cmnd->outstanding_r2t, + cmnd->hdigest, cmnd->ddigest, + list_empty(&cmnd->pdu_list), list_empty(&cmnd->hash_list)); + + assert(list_empty(&cmnd->list)); + } + list_add(&cmnd->list, &head); + iscsi_cmnds_init_write(&head); +} + +static void do_send_data_rsp(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + struct iscsi_cmnd *data_cmnd; + struct tio *tio = cmnd->tio; + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + struct iscsi_data_in_hdr *rsp; + u32 pdusize, expsize, scsisize, size, offset, sn; + LIST_HEAD(send); + + dprintk(D_GENERIC, "%p\n", cmnd); + pdusize = conn->session->param.max_xmit_data_length; + expsize = cmnd_read_size(cmnd); + size = min(expsize, tio->size); + offset = 0; + sn = 0; + + while (1) { + data_cmnd = iscsi_cmnd_create_rsp_cmnd(cmnd, size <= pdusize); + tio_get(tio); + data_cmnd->tio = tio; + rsp = (struct iscsi_data_in_hdr *)&data_cmnd->pdu.bhs; + + rsp->opcode = ISCSI_OP_SCSI_DATA_IN; + rsp->itt = req->itt; + rsp->ttt = cpu_to_be32(ISCSI_RESERVED_TAG); + rsp->buffer_offset = offset; + rsp->data_sn = cpu_to_be32(sn); + + if (size <= pdusize) { + data_cmnd->pdu.datasize = size; + rsp->flags = ISCSI_FLG_FINAL | ISCSI_FLG_STATUS; + + scsisize = tio->size; + if (scsisize < expsize) { + rsp->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; + size = expsize - scsisize; + } else if (scsisize > expsize) { + rsp->flags |= ISCSI_FLG_RESIDUAL_OVERFLOW; + size = scsisize - expsize; + } else + size = 0; + rsp->residual_count = cpu_to_be32(size); + list_add_tail(&data_cmnd->list, &send); + + break; + } + + data_cmnd->pdu.datasize = pdusize; + + size -= pdusize; + offset += pdusize; + sn++; + + list_add_tail(&data_cmnd->list, &send); + } + + iscsi_cmnds_init_write(&send); +} + +static struct iscsi_cmnd *create_scsi_rsp(struct iscsi_cmnd *req) +{ + struct iscsi_cmnd *rsp; + struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req); + struct iscsi_scsi_rsp_hdr *rsp_hdr; + struct iscsi_sense_data *sense; + + rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); + + rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs; + rsp_hdr->opcode = ISCSI_OP_SCSI_RSP; + rsp_hdr->flags = ISCSI_FLG_FINAL; + rsp_hdr->response = ISCSI_RESPONSE_COMMAND_COMPLETED; + rsp_hdr->cmd_status = req->status; + rsp_hdr->itt = req_hdr->itt; + + if (req->status == SAM_STAT_CHECK_CONDITION) { + assert(!rsp->tio); + rsp->tio = tio_alloc(1); + sense = (struct iscsi_sense_data *) + page_address(rsp->tio->pvec[0]); + + assert(sense); + clear_page(sense); + sense->length = cpu_to_be16(IET_SENSE_BUF_SIZE); + + memcpy(sense->data, req->sense_buf, IET_SENSE_BUF_SIZE); + rsp->pdu.datasize = sizeof(struct iscsi_sense_data) + + IET_SENSE_BUF_SIZE; + + rsp->tio->size = (rsp->pdu.datasize + 3) & -4; + rsp->tio->offset = 0; + } + + return rsp; +} + +void iscsi_cmnd_set_sense(struct iscsi_cmnd *cmnd, u8 sense_key, u8 asc, + u8 ascq) +{ + cmnd->status = SAM_STAT_CHECK_CONDITION; + + cmnd->sense_buf[0] = 0xf0; + cmnd->sense_buf[2] = sense_key; + cmnd->sense_buf[7] = 6; // Additional sense length + cmnd->sense_buf[12] = asc; + cmnd->sense_buf[13] = ascq; + + /* Call to ACA/UAI handler */ +} + +static struct iscsi_cmnd *create_sense_rsp(struct iscsi_cmnd *req, + u8 sense_key, u8 asc, u8 ascq) +{ + iscsi_cmnd_set_sense(req, sense_key, asc, ascq); + return create_scsi_rsp(req); +} + +void send_scsi_rsp(struct iscsi_cmnd *req, void (*func)(struct iscsi_cmnd *)) +{ + struct iscsi_cmnd *rsp; + struct iscsi_scsi_rsp_hdr *rsp_hdr; + u32 size; + + func(req); + rsp = create_scsi_rsp(req); + + switch (req->status) { + case SAM_STAT_GOOD: + case SAM_STAT_RESERVATION_CONFLICT: + rsp_hdr = (struct iscsi_scsi_rsp_hdr *) &rsp->pdu.bhs; + if ((size = cmnd_read_size(req)) != 0) { + rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; + rsp_hdr->residual_count = cpu_to_be32(size); + } + break; + default: + break; + } + + iscsi_cmnd_init_write(rsp); +} + +void send_data_rsp(struct iscsi_cmnd *req, void (*func)(struct iscsi_cmnd *)) +{ + struct iscsi_cmnd *rsp; + + func(req); + + if (req->status == SAM_STAT_GOOD) + do_send_data_rsp(req); + else { + rsp = create_scsi_rsp(req); + iscsi_cmnd_init_write(rsp); + } +} + +/** + * Free a command. + * Also frees the additional header. + * + * iscsi_cmnd_remove - + * @cmnd: ptr to command + */ + +static void iscsi_cmnd_remove(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn; + + if (!cmnd) + return; + + if (cmnd_timer_active(cmnd)) { + clear_cmnd_timer_active(cmnd); + del_timer_sync(&cmnd->timer); + } + + dprintk(D_GENERIC, "%p\n", cmnd); + conn = cmnd->conn; + kfree(cmnd->pdu.ahs); + + if (!list_empty(&cmnd->list)) { + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + + eprintk("cmnd %p still on some list?, %x, %x, %x, %x, %x, %x, %x %lx\n", + cmnd, req->opcode, req->scb[0], req->flags, req->itt, + be32_to_cpu(req->data_length), + req->cmd_sn, be32_to_cpu(cmnd->pdu.datasize), + conn->state); + + if (cmnd->req) { + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd->req); + eprintk("%p %x %u\n", req, req->opcode, req->scb[0]); + } + dump_stack(); + BUG(); + } + list_del(&cmnd->list); + spin_lock(&conn->list_lock); + atomic_dec(&conn->nr_cmnds); + list_del(&cmnd->conn_list); + spin_unlock(&conn->list_lock); + + if (cmnd->tio) + tio_put(cmnd->tio); + + kmem_cache_free(iscsi_cmnd_cache, cmnd); +} + +static void cmnd_skip_pdu(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + struct tio *tio = cmnd->tio; + char *addr; + u32 size; + int i; + + eprintk("%x %x %x %u\n", cmnd_itt(cmnd), cmnd_opcode(cmnd), + cmnd_hdr(cmnd)->scb[0], cmnd->pdu.datasize); + + if (!(size = cmnd->pdu.datasize)) + return; + + if (tio) + assert(tio->pg_cnt > 0); + else + tio = cmnd->tio = tio_alloc(1); + + addr = page_address(tio->pvec[0]); + assert(addr); + size = (size + 3) & -4; + conn->read_size = size; + for (i = 0; size > PAGE_CACHE_SIZE; i++, size -= PAGE_CACHE_SIZE) { + assert(i < ISCSI_CONN_IOV_MAX); + conn->read_iov[i].iov_base = addr; + conn->read_iov[i].iov_len = PAGE_CACHE_SIZE; + } + conn->read_iov[i].iov_base = addr; + conn->read_iov[i].iov_len = size; + conn->read_msg.msg_iov = conn->read_iov; + conn->read_msg.msg_iovlen = ++i; +} + +static void iscsi_cmnd_reject(struct iscsi_cmnd *req, int reason) +{ + struct iscsi_cmnd *rsp; + struct iscsi_reject_hdr *rsp_hdr; + struct tio *tio; + char *addr; + + rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); + rsp_hdr = (struct iscsi_reject_hdr *)&rsp->pdu.bhs; + + rsp_hdr->opcode = ISCSI_OP_REJECT; + rsp_hdr->ffffffff = ISCSI_RESERVED_TAG; + rsp_hdr->reason = reason; + + rsp->tio = tio = tio_alloc(1); + addr = page_address(tio->pvec[0]); + clear_page(addr); + memcpy(addr, &req->pdu.bhs, sizeof(struct iscsi_hdr)); + tio->size = rsp->pdu.datasize = sizeof(struct iscsi_hdr); + cmnd_skip_pdu(req); + + req->pdu.bhs.opcode = ISCSI_OP_PDU_REJECT; +} + +static void cmnd_set_sn(struct iscsi_cmnd *cmnd, int set_stat_sn) +{ + struct iscsi_conn *conn = cmnd->conn; + struct iscsi_session *sess = conn->session; + + if (set_stat_sn) + cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn++); + cmnd->pdu.bhs.exp_sn = cpu_to_be32(sess->exp_cmd_sn); + cmnd->pdu.bhs.max_sn = cpu_to_be32(sess->exp_cmd_sn + sess->max_queued_cmnds); +} + +static void update_stat_sn(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + u32 exp_stat_sn; + + cmnd->pdu.bhs.exp_sn = exp_stat_sn = be32_to_cpu(cmnd->pdu.bhs.exp_sn); + dprintk(D_GENERIC, "%x,%x\n", cmnd_opcode(cmnd), exp_stat_sn); + if ((int)(exp_stat_sn - conn->exp_stat_sn) > 0 && + (int)(exp_stat_sn - conn->stat_sn) <= 0) { + // free pdu resources + cmnd->conn->exp_stat_sn = exp_stat_sn; + } +} + +static int check_cmd_sn(struct iscsi_cmnd *cmnd) +{ + struct iscsi_session *session = cmnd->conn->session; + u32 cmd_sn; + + cmnd->pdu.bhs.sn = cmd_sn = be32_to_cpu(cmnd->pdu.bhs.sn); + + dprintk(D_GENERIC, "cmd_sn(%u) exp_cmd_sn(%u) max_cmd_sn(%u)\n", + cmd_sn, session->exp_cmd_sn, session->max_cmd_sn); + + if (between(cmd_sn, session->exp_cmd_sn, session->max_cmd_sn)) + return 0; + else if (cmnd_immediate(cmnd)) + return 0; + + eprintk("sequence error: cmd_sn(%u) exp_cmd_sn(%u) max_cmd_sn(%u)\n", + cmd_sn, session->exp_cmd_sn, session->max_cmd_sn); + + set_cmnd_tmfabort(cmnd); + + return -ISCSI_REASON_PROTOCOL_ERROR; +} + +static struct iscsi_cmnd *__cmnd_find_hash(struct iscsi_session *session, u32 itt, u32 ttt) +{ + struct list_head *head; + struct iscsi_cmnd *cmnd; + + head = &session->cmnd_hash[cmnd_hashfn(itt)]; + + list_for_each_entry(cmnd, head, hash_list) { + if (cmnd->pdu.bhs.itt == itt) { + if ((ttt != ISCSI_RESERVED_TAG) && (ttt != cmnd->target_task_tag)) + continue; + return cmnd; + } + } + + return NULL; +} + +static struct iscsi_cmnd *cmnd_find_hash(struct iscsi_session *session, u32 itt, u32 ttt) +{ + struct iscsi_cmnd *cmnd; + + spin_lock(&session->cmnd_hash_lock); + + cmnd = __cmnd_find_hash(session, itt, ttt); + + spin_unlock(&session->cmnd_hash_lock); + + return cmnd; +} + +static int cmnd_insert_hash_ttt(struct iscsi_cmnd *cmnd, u32 ttt) +{ + struct iscsi_session *session = cmnd->conn->session; + struct iscsi_cmnd *tmp; + struct list_head *head; + int err = 0; + u32 itt = cmnd->pdu.bhs.itt; + + head = &session->cmnd_hash[cmnd_hashfn(itt)]; + + spin_lock(&session->cmnd_hash_lock); + + tmp = __cmnd_find_hash(session, itt, ttt); + if (!tmp) { + list_add_tail(&cmnd->hash_list, head); + set_cmnd_hashed(cmnd); + } else + err = -ISCSI_REASON_TASK_IN_PROGRESS; + + spin_unlock(&session->cmnd_hash_lock); + + return err; +} + +static int cmnd_insert_hash(struct iscsi_cmnd *cmnd) +{ + int err; + + dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd->pdu.bhs.itt); + + if (cmnd->pdu.bhs.itt == ISCSI_RESERVED_TAG) + return -ISCSI_REASON_PROTOCOL_ERROR; + + err = cmnd_insert_hash_ttt(cmnd, ISCSI_RESERVED_TAG); + if (!err) { + update_stat_sn(cmnd); + err = check_cmd_sn(cmnd); + } else if (!cmnd_immediate(cmnd)) + set_cmnd_tmfabort(cmnd); + + return err; +} + +static void __cmnd_remove_hash(struct iscsi_cmnd *cmnd) +{ + list_del(&cmnd->hash_list); +} + +static void cmnd_remove_hash(struct iscsi_cmnd *cmnd) +{ + struct iscsi_session *session = cmnd->conn->session; + struct iscsi_cmnd *tmp; + + spin_lock(&session->cmnd_hash_lock); + + tmp = __cmnd_find_hash(session, cmnd->pdu.bhs.itt, + cmnd->target_task_tag); + if (tmp && tmp == cmnd) + __cmnd_remove_hash(tmp); + else + eprintk("%p:%x not found\n", cmnd, cmnd_itt(cmnd)); + + spin_unlock(&session->cmnd_hash_lock); +} + +static void cmnd_skip_data(struct iscsi_cmnd *req) +{ + struct iscsi_cmnd *rsp; + struct iscsi_scsi_rsp_hdr *rsp_hdr; + u32 size; + + rsp = get_rsp_cmnd(req); + rsp_hdr = (struct iscsi_scsi_rsp_hdr *)&rsp->pdu.bhs; + if (cmnd_opcode(rsp) != ISCSI_OP_SCSI_RSP) { + eprintk("unexpected response command %u\n", cmnd_opcode(rsp)); + return; + } + + size = cmnd_write_size(req); + if (size) { + rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; + rsp_hdr->residual_count = cpu_to_be32(size); + } + size = cmnd_read_size(req); + if (size) { + if (cmnd_hdr(req)->flags & ISCSI_CMD_WRITE) { + rsp_hdr->flags |= ISCSI_FLG_BIRESIDUAL_UNDERFLOW; + rsp_hdr->bi_residual_count = cpu_to_be32(size); + } else { + rsp_hdr->flags |= ISCSI_FLG_RESIDUAL_UNDERFLOW; + rsp_hdr->residual_count = cpu_to_be32(size); + } + } + req->pdu.bhs.opcode = + (req->pdu.bhs.opcode & ~ISCSI_OPCODE_MASK) | ISCSI_OP_SCSI_REJECT; + + cmnd_skip_pdu(req); +} + +static int cmnd_recv_pdu(struct iscsi_conn *conn, struct tio *tio, u32 offset, u32 size) +{ + int idx, i; + char *addr; + + dprintk(D_GENERIC, "%p %u,%u\n", tio, offset, size); + offset += tio->offset; + + if (!(offset < tio->offset + tio->size) || + !(offset + size <= tio->offset + tio->size)) { + eprintk("%u %u %u %u", offset, size, tio->offset, tio->size); + return -EIO; + } + assert(offset < tio->offset + tio->size); + assert(offset + size <= tio->offset + tio->size); + + idx = offset >> PAGE_CACHE_SHIFT; + offset &= ~PAGE_CACHE_MASK; + + conn->read_msg.msg_iov = conn->read_iov; + conn->read_size = size = (size + 3) & -4; + conn->read_overflow = 0; + + i = 0; + while (1) { + assert(tio->pvec[idx]); + addr = page_address(tio->pvec[idx]); + assert(addr); + conn->read_iov[i].iov_base = addr + offset; + if (offset + size <= PAGE_CACHE_SIZE) { + conn->read_iov[i].iov_len = size; + conn->read_msg.msg_iovlen = ++i; + break; + } + conn->read_iov[i].iov_len = PAGE_CACHE_SIZE - offset; + size -= conn->read_iov[i].iov_len; + offset = 0; + if (++i >= ISCSI_CONN_IOV_MAX) { + conn->read_msg.msg_iovlen = i; + conn->read_overflow = size; + conn->read_size -= size; + break; + } + + idx++; + } + + return 0; +} + +static void set_offset_and_length(struct iet_volume *lu, u8 *cmd, loff_t *off, u32 *len) +{ + assert(lu); + + switch (cmd[0]) { + case READ_6: + case WRITE_6: + *off = ((cmd[1] & 0x1f) << 16) + (cmd[2] << 8) + cmd[3]; + *len = cmd[4]; + if (!*len) + *len = 256; + break; + case READ_10: + case WRITE_10: + case WRITE_VERIFY: + *off = (u32)cmd[2] << 24 | (u32)cmd[3] << 16 | + (u32)cmd[4] << 8 | (u32)cmd[5]; + *len = (cmd[7] << 8) + cmd[8]; + break; + case READ_16: + case WRITE_16: + *off = (u64)cmd[2] << 56 | (u64)cmd[3] << 48 | + (u64)cmd[4] << 40 | (u64)cmd[5] << 32 | + (u64)cmd[6] << 24 | (u64)cmd[7] << 16 | + (u64)cmd[8] << 8 | (u64)cmd[9]; + *len = (u32)cmd[10] << 24 | (u32)cmd[11] << 16 | + (u32)cmd[12] << 8 | (u32)cmd[13]; + break; + default: + BUG(); + } + + *off <<= lu->blk_shift; + *len <<= lu->blk_shift; +} + +static u32 translate_lun(u16 * data) +{ + u8 *p = (u8 *) data; + u32 lun = ~0U; + + switch (*p >> 6) { + case 0: + lun = p[1]; + break; + case 1: + lun = (0x3f & p[0]) << 8 | p[1]; + break; + case 2: + case 3: + default: + eprintk("%u %u %u %u\n", data[0], data[1], data[2], data[3]); + break; + } + + return lun; +} + +static void send_r2t(struct iscsi_cmnd *req) +{ + struct iscsi_cmnd *rsp; + struct iscsi_r2t_hdr *rsp_hdr; + u32 length, offset, burst; + LIST_HEAD(send); + + length = req->r2t_length; + burst = req->conn->session->param.max_burst_length; + offset = be32_to_cpu(cmnd_hdr(req)->data_length) - length; + + do { + rsp = iscsi_cmnd_create_rsp_cmnd(req, 0); + rsp->pdu.bhs.ttt = req->target_task_tag; + + rsp_hdr = (struct iscsi_r2t_hdr *)&rsp->pdu.bhs; + rsp_hdr->opcode = ISCSI_OP_R2T; + rsp_hdr->flags = ISCSI_FLG_FINAL; + memcpy(rsp_hdr->lun, cmnd_hdr(req)->lun, 8); + rsp_hdr->itt = cmnd_hdr(req)->itt; + rsp_hdr->r2t_sn = cpu_to_be32(req->r2t_sn++); + rsp_hdr->buffer_offset = cpu_to_be32(offset); + if (length > burst) { + rsp_hdr->data_length = cpu_to_be32(burst); + length -= burst; + offset += burst; + } else { + rsp_hdr->data_length = cpu_to_be32(length); + length = 0; + } + + dprintk(D_WRITE, "%x %u %u %u %u\n", cmnd_itt(req), + be32_to_cpu(rsp_hdr->data_length), + be32_to_cpu(rsp_hdr->buffer_offset), + be32_to_cpu(rsp_hdr->r2t_sn), req->outstanding_r2t); + + list_add_tail(&rsp->list, &send); + + if (++req->outstanding_r2t >= req->conn->session->param.max_outstanding_r2t) + break; + + } while (length); + + iscsi_cmnds_init_write(&send); +} + +static void scsi_cmnd_exec(struct iscsi_cmnd *cmnd) +{ + assert(!cmnd->r2t_length); + + if (cmnd->lun) { + iscsi_scsi_queuecmnd(cmnd); + } else { + iscsi_device_queue_cmnd(cmnd); + } +} + +static int nop_out_start(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) +{ + u32 size, tmp; + int i, err = 0; + + if (cmnd_ttt(cmnd) != cpu_to_be32(ISCSI_RESERVED_TAG)) { + cmnd->req = cmnd_find_hash(conn->session, cmnd->pdu.bhs.itt, + cmnd->pdu.bhs.ttt); + if (!cmnd->req) { + /* + * We didn't request this NOP-Out (by sending a + * NOP-In, see 10.18.2 of the RFC) or our fake NOP-Out + * timed out. + */ + eprintk("initiator bug %x\n", cmnd_itt(cmnd)); + err = -ISCSI_REASON_PROTOCOL_ERROR; + goto out; + } + + del_timer_sync(&cmnd->req->timer); + clear_cmnd_timer_active(cmnd->req); + dprintk(D_GENERIC, "NOP-Out: %p, ttt %x, timer %p\n", + cmnd->req, cmnd_ttt(cmnd->req), &cmnd->req->timer); + } + + if (cmnd_itt(cmnd) == cpu_to_be32(ISCSI_RESERVED_TAG)) { + if (!cmnd_immediate(cmnd)) + eprintk("%s\n", "initiator bug!"); + update_stat_sn(cmnd); + err = check_cmd_sn(cmnd); + if (err) + goto out; + } else if ((err = cmnd_insert_hash(cmnd)) < 0) { + eprintk("ignore this request %x\n", cmnd_itt(cmnd)); + goto out; + } + + if ((size = cmnd->pdu.datasize)) { + size = (size + 3) & -4; + conn->read_msg.msg_iov = conn->read_iov; + if (cmnd->pdu.bhs.itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { + struct tio *tio; + int pg_cnt = get_pgcnt(size, 0); + + assert(pg_cnt < ISCSI_CONN_IOV_MAX); + cmnd->tio = tio = tio_alloc(pg_cnt); + tio_set(tio, size, 0); + + for (i = 0; i < pg_cnt; i++) { + conn->read_iov[i].iov_base + = page_address(tio->pvec[i]); + tmp = min_t(u32, size, PAGE_CACHE_SIZE); + conn->read_iov[i].iov_len = tmp; + conn->read_size += tmp; + size -= tmp; + } + } else { + for (i = 0; i < ISCSI_CONN_IOV_MAX; i++) { + conn->read_iov[i].iov_base = dummy_data; + tmp = min_t(u32, size, sizeof(dummy_data)); + conn->read_iov[i].iov_len = tmp; + conn->read_size += tmp; + size -= tmp; + } + } + assert(!size); + conn->read_overflow = size; + conn->read_msg.msg_iovlen = i; + } + +out: + return err; +} + +static u32 get_next_ttt(struct iscsi_session *session) +{ + u32 ttt; + + if (session->next_ttt == ISCSI_RESERVED_TAG) + session->next_ttt++; + ttt = session->next_ttt++; + + return cpu_to_be32(ttt); +} + +static void scsi_cmnd_start(struct iscsi_conn *conn, struct iscsi_cmnd *req) +{ + struct iscsi_scsi_cmd_hdr *req_hdr = cmnd_hdr(req); + + dprintk(D_GENERIC, "scsi command: %02x\n", req_hdr->scb[0]); + + req->lun = volume_get(conn->session->target, translate_lun(req_hdr->lun)); + if (!req->lun) { + switch (req_hdr->scb[0]) { + case INQUIRY: + case REPORT_LUNS: + break; + default: + eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); + create_sense_rsp(req, ILLEGAL_REQUEST, 0x25, 0x0); + cmnd_skip_data(req); + goto out; + } + } else + set_cmnd_lunit(req); + + switch (req_hdr->scb[0]) { + case SERVICE_ACTION_IN: + if ((req_hdr->scb[1] & 0x1f) != 0x10) + goto error; + case INQUIRY: + case REPORT_LUNS: + case TEST_UNIT_READY: + case SYNCHRONIZE_CACHE: + case VERIFY: + case VERIFY_16: + case START_STOP: + case READ_CAPACITY: + case MODE_SENSE: + case REQUEST_SENSE: + case RESERVE: + case RELEASE: + { + if (!(req_hdr->flags & ISCSI_CMD_FINAL) || req->pdu.datasize) { + /* unexpected unsolicited data */ + eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); + create_sense_rsp(req, ABORTED_COMMAND, 0xc, 0xc); + cmnd_skip_data(req); + } + break; + } + case READ_6: + case READ_10: + case READ_16: + { + loff_t offset; + u32 length; + + if (!(req_hdr->flags & ISCSI_CMD_FINAL) || req->pdu.datasize) { + /* unexpected unsolicited data */ + eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); + create_sense_rsp(req, ABORTED_COMMAND, 0xc, 0xc); + cmnd_skip_data(req); + break; + } + + set_offset_and_length(req->lun, req_hdr->scb, &offset, &length); + req->tio = tio_alloc(get_pgcnt(length, offset)); + tio_set(req->tio, length, offset); + break; + } + case WRITE_6: + case WRITE_10: + case WRITE_16: + case WRITE_VERIFY: + { + struct iscsi_sess_param *param = &conn->session->param; + loff_t offset; + u32 length; + + req->r2t_length = be32_to_cpu(req_hdr->data_length) - req->pdu.datasize; + req->is_unsolicited_data = !(req_hdr->flags & ISCSI_CMD_FINAL); + req->target_task_tag = get_next_ttt(conn->session); + + if (LUReadonly(req->lun)) { + create_sense_rsp(req, DATA_PROTECT, 0x27, 0x0); + cmnd_skip_data(req); + break; + } + + if (!param->immediate_data && req->pdu.datasize) + eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); + + if (param->initial_r2t && !(req_hdr->flags & ISCSI_CMD_FINAL)) + eprintk("%x %x\n", cmnd_itt(req), req_hdr->scb[0]); + + if (req_hdr->scb[0] == WRITE_VERIFY && req_hdr->scb[1] & 0x02) + eprintk("Verification is ignored %x\n", cmnd_itt(req)); + + set_offset_and_length(req->lun, req_hdr->scb, &offset, &length); + if (cmnd_write_size(req) != length) + eprintk("%x %u %u\n", cmnd_itt(req), cmnd_write_size(req), length); + + req->tio = tio_alloc(get_pgcnt(length, offset)); + tio_set(req->tio, length, offset); + + if (req->pdu.datasize) { + if (cmnd_recv_pdu(conn, req->tio, 0, req->pdu.datasize) < 0) + assert(0); + } + break; + } + error: + default: + eprintk("Unsupported %x\n", req_hdr->scb[0]); + create_sense_rsp(req, ILLEGAL_REQUEST, 0x20, 0x0); + cmnd_skip_data(req); + break; + } + +out: + return; +} + +static void data_out_start(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) +{ + struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *)&cmnd->pdu.bhs; + struct iscsi_cmnd *scsi_cmnd = NULL; + u32 offset = be32_to_cpu(req->buffer_offset); + + update_stat_sn(cmnd); + + cmnd->req = scsi_cmnd = cmnd_find_hash(conn->session, req->itt, req->ttt); + if (!scsi_cmnd) { + eprintk("unable to find scsi task %x %x\n", + cmnd_itt(cmnd), cmnd_ttt(cmnd)); + goto skip_data; + } + + if (scsi_cmnd->r2t_length < cmnd->pdu.datasize) { + eprintk("invalid data len %x %u %u\n", + cmnd_itt(scsi_cmnd), cmnd->pdu.datasize, scsi_cmnd->r2t_length); + goto skip_data; + } + + if (scsi_cmnd->r2t_length + offset != cmnd_write_size(scsi_cmnd)) { + eprintk("%x %u %u %u\n", cmnd_itt(scsi_cmnd), scsi_cmnd->r2t_length, + offset, cmnd_write_size(scsi_cmnd)); + goto skip_data; + } + + scsi_cmnd->r2t_length -= cmnd->pdu.datasize; + + if (req->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) { + /* unsolicited burst data */ + if (scsi_cmnd->pdu.bhs.flags & ISCSI_FLG_FINAL) { + eprintk("unexpected data from %x %x\n", + cmnd_itt(cmnd), cmnd_ttt(cmnd)); + goto skip_data; + } + } + + dprintk(D_WRITE, "%u %p %p %p %u %u\n", req->ttt, cmnd, scsi_cmnd, + scsi_cmnd->tio, offset, cmnd->pdu.datasize); + + if (cmnd_recv_pdu(conn, scsi_cmnd->tio, offset, cmnd->pdu.datasize) < 0) + goto skip_data; + return; + +skip_data: + cmnd->pdu.bhs.opcode = ISCSI_OP_DATA_REJECT; + cmnd_skip_pdu(cmnd); + return; +} + +static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd); + +static void data_out_end(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) +{ + struct iscsi_data_out_hdr *req = (struct iscsi_data_out_hdr *) &cmnd->pdu.bhs; + struct iscsi_cmnd *scsi_cmnd; + u32 offset; + + assert(cmnd); + scsi_cmnd = cmnd->req; + assert(scsi_cmnd); + + if (conn->read_overflow) { + eprintk("%x %u\n", cmnd_itt(cmnd), conn->read_overflow); + assert(scsi_cmnd->tio); + offset = be32_to_cpu(req->buffer_offset); + offset += cmnd->pdu.datasize - conn->read_overflow; + if (cmnd_recv_pdu(conn, scsi_cmnd->tio, offset, conn->read_overflow) < 0) + assert(0); + return; + } + + if (req->ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) { + if (req->flags & ISCSI_FLG_FINAL) { + scsi_cmnd->is_unsolicited_data = 0; + iscsi_session_push_cmnd(scsi_cmnd); + } + } else { + /* TODO : proper error handling */ + if (!(req->flags & ISCSI_FLG_FINAL) && scsi_cmnd->r2t_length == 0) + eprintk("initiator error %x\n", cmnd_itt(scsi_cmnd)); + + if (!(req->flags & ISCSI_FLG_FINAL)) + goto out; + + scsi_cmnd->outstanding_r2t--; + + if (scsi_cmnd->r2t_length == 0) + assert(list_empty(&scsi_cmnd->pdu_list)); + + iscsi_session_push_cmnd(scsi_cmnd); + } + +out: + iscsi_cmnd_remove(cmnd); + return; +} + +static void __cmnd_abort(struct iscsi_cmnd *cmnd) +{ + if (cmnd_rxstart(cmnd)) + set_cmnd_tmfabort(cmnd); + + if (cmnd_waitio(cmnd)) + return; + + if (cmnd->conn->read_cmnd != cmnd) + cmnd_release(cmnd, 1); +} + +static int cmnd_abort(struct iscsi_session *session, struct iscsi_cmnd *req) +{ + struct iscsi_task_mgt_hdr *req_hdr = + (struct iscsi_task_mgt_hdr *)&req->pdu.bhs; + struct iscsi_cmnd *cmnd; + + u32 min_cmd_sn = req_hdr->cmd_sn - session->max_queued_cmnds; + + req_hdr->ref_cmd_sn = be32_to_cpu(req_hdr->ref_cmd_sn); + + dprintk(D_GENERIC, "cmd_sn(%u) ref_cmd_sn(%u) min_cmd_sn(%u) rtt(%x)" + " lun(%d) cid(%u)\n", + req_hdr->cmd_sn, req_hdr->ref_cmd_sn, min_cmd_sn, req_hdr->rtt, + translate_lun(req_hdr->lun), req->conn->cid); + + if (after(req_hdr->ref_cmd_sn, req_hdr->cmd_sn)) + return ISCSI_RESPONSE_FUNCTION_REJECTED; + + if (!(cmnd = cmnd_find_hash(session, req_hdr->rtt, ISCSI_RESERVED_TAG))) { + if (between(req_hdr->ref_cmd_sn, min_cmd_sn, req_hdr->cmd_sn)) + return ISCSI_RESPONSE_FUNCTION_COMPLETE; + else + return ISCSI_RESPONSE_UNKNOWN_TASK; + } + + dprintk(D_GENERIC, "itt(%x) opcode(%x) scsicode(%x) lun(%d) cid(%u)\n", + cmnd_itt(cmnd), cmnd_opcode(cmnd), cmnd_scsicode(cmnd), + translate_lun(cmnd_hdr(cmnd)->lun), cmnd->conn->cid); + + if (cmnd_opcode(cmnd) == ISCSI_OP_SCSI_TASK_MGT_MSG) + return ISCSI_RESPONSE_FUNCTION_REJECTED; + + if (translate_lun(cmnd_hdr(cmnd)->lun) != + translate_lun(req_hdr->lun)) + return ISCSI_RESPONSE_FUNCTION_REJECTED; + + if (cmnd->conn && test_bit(CONN_ACTIVE, &cmnd->conn->state)) { + if (cmnd->conn->cid != req->conn->cid) + return ISCSI_RESPONSE_FUNCTION_REJECTED; + } else { + /* Switch cmnd connection allegiance */ + } + + __cmnd_abort(cmnd); + + return ISCSI_RESPONSE_FUNCTION_COMPLETE; +} + +static int target_reset(struct iscsi_cmnd *req, u32 lun, int all) +{ + struct iscsi_target *target = req->conn->session->target; + struct iscsi_session *session; + struct iscsi_conn *conn; + struct iscsi_cmnd *cmnd, *tmp; + struct iet_volume *volume; + + list_for_each_entry(session, &target->session_list, list) { + list_for_each_entry(conn, &session->conn_list, list) { + list_for_each_entry_safe(cmnd, tmp, &conn->pdu_list, conn_list) { + if (cmnd == req) + continue; + + if (all) + __cmnd_abort(cmnd); + else if (translate_lun(cmnd_hdr(cmnd)->lun) + == lun) + __cmnd_abort(cmnd); + } + } + } + + list_for_each_entry(volume, &target->volumes, list) { + if (all || volume->lun == lun) { + /* force release */ + volume_release(volume, 0, 1); + /* power-on, reset, or bus device reset occurred */ + ua_establish_for_all_sessions(target, volume->lun, + 0x29, 0x0); + } + } + + return 0; +} + +static void task_set_abort(struct iscsi_cmnd *req) +{ + struct iscsi_session *session = req->conn->session; + struct iscsi_conn *conn; + struct iscsi_cmnd *cmnd, *tmp; + + list_for_each_entry(conn, &session->conn_list, list) { + list_for_each_entry_safe(cmnd, tmp, &conn->pdu_list, conn_list) { + if (translate_lun(cmnd_hdr(cmnd)->lun) + != translate_lun(cmnd_hdr(req)->lun)) + continue; + + if (before(cmnd_hdr(cmnd)->cmd_sn, + cmnd_hdr(req)->cmd_sn)) + __cmnd_abort(cmnd); + } + } +} + +static inline char *tmf_desc(int fun) +{ + static char *tmf_desc[] = { + "Unknown Function", + "Abort Task", + "Abort Task Set", + "Clear ACA", + "Clear Task Set", + "Logical Unit Reset", + "Target Warm Reset", + "Target Cold Reset", + "Task Reassign", + }; + + if ((fun < ISCSI_FUNCTION_ABORT_TASK) || + (fun > ISCSI_FUNCTION_TASK_REASSIGN)) + fun = 0; + + return tmf_desc[fun]; +} + +static inline char *rsp_desc(int rsp) +{ + static char *rsp_desc[] = { + "Function Complete", + "Unknown Task", + "Unknown LUN", + "Task Allegiant", + "Failover Unsupported", + "Function Unsupported", + "No Authorization", + "Function Rejected", + "Unknown Response", + }; + + if (((rsp < ISCSI_RESPONSE_FUNCTION_COMPLETE) || + (rsp > ISCSI_RESPONSE_NO_AUTHORIZATION)) && + (rsp != ISCSI_RESPONSE_FUNCTION_REJECTED)) + rsp = 8; + else if (rsp == ISCSI_RESPONSE_FUNCTION_REJECTED) + rsp = 7; + + return rsp_desc[rsp]; +} + +static void execute_task_management(struct iscsi_cmnd *req) +{ + struct iscsi_conn *conn = req->conn; + struct iscsi_session *session = conn->session; + struct iscsi_target *target = session->target; + struct iscsi_cmnd *rsp; + struct iscsi_task_mgt_hdr *req_hdr = (struct iscsi_task_mgt_hdr *)&req->pdu.bhs; + struct iscsi_task_rsp_hdr *rsp_hdr; + u32 lun; + int function = req_hdr->function & ISCSI_FUNCTION_MASK; + + rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); + rsp_hdr = (struct iscsi_task_rsp_hdr *)&rsp->pdu.bhs; + + rsp_hdr->opcode = ISCSI_OP_SCSI_TASK_MGT_RSP; + rsp_hdr->flags = ISCSI_FLG_FINAL; + rsp_hdr->itt = req_hdr->itt; + rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_COMPLETE; + + switch (function) { + case ISCSI_FUNCTION_ABORT_TASK: + case ISCSI_FUNCTION_ABORT_TASK_SET: + case ISCSI_FUNCTION_CLEAR_ACA: + case ISCSI_FUNCTION_CLEAR_TASK_SET: + case ISCSI_FUNCTION_LOGICAL_UNIT_RESET: + lun = translate_lun(req_hdr->lun); + if (!volume_lookup(target, lun)) { + rsp_hdr->response = ISCSI_RESPONSE_UNKNOWN_LUN; + goto out; + } + } + + switch (function) { + case ISCSI_FUNCTION_ABORT_TASK: + rsp_hdr->response = cmnd_abort(conn->session, req); + break; + case ISCSI_FUNCTION_ABORT_TASK_SET: + task_set_abort(req); + break; + case ISCSI_FUNCTION_CLEAR_ACA: + rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED; + break; + case ISCSI_FUNCTION_CLEAR_TASK_SET: + rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED; + break; + case ISCSI_FUNCTION_LOGICAL_UNIT_RESET: + target_reset(req, translate_lun(req_hdr->lun), 0); + break; + case ISCSI_FUNCTION_TARGET_WARM_RESET: + case ISCSI_FUNCTION_TARGET_COLD_RESET: + target_reset(req, 0, 1); + if (function == ISCSI_FUNCTION_TARGET_COLD_RESET) + set_cmnd_close(rsp); + break; + case ISCSI_FUNCTION_TASK_REASSIGN: + rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_UNSUPPORTED; + break; + default: + rsp_hdr->response = ISCSI_RESPONSE_FUNCTION_REJECTED; + break; + } +out: + iprintk("%s (%02x) issued on tid:%d lun:%d by sid:%llu (%s)\n", + tmf_desc(function), function, target->tid, + translate_lun(req_hdr->lun), session->sid, + rsp_desc(rsp_hdr->response)); + + iscsi_cmnd_init_write(rsp); +} + +static void nop_hdr_setup(struct iscsi_hdr *hdr, u8 opcode, __be32 itt, + __be32 ttt) +{ + hdr->opcode = opcode; + hdr->flags = ISCSI_FLG_FINAL; + hdr->itt = itt; + hdr->ttt = ttt; +} + +static void nop_out_exec(struct iscsi_cmnd *req) +{ + struct iscsi_cmnd *rsp; + + if (cmnd_itt(req) != cpu_to_be32(ISCSI_RESERVED_TAG)) { + rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); + + nop_hdr_setup(&rsp->pdu.bhs, ISCSI_OP_NOP_IN, req->pdu.bhs.itt, + cpu_to_be32(ISCSI_RESERVED_TAG)); + + if (req->pdu.datasize) + assert(req->tio); + else + assert(!req->tio); + + if (req->tio) { + tio_get(req->tio); + rsp->tio = req->tio; + } + + assert(get_pgcnt(req->pdu.datasize, 0) < ISCSI_CONN_IOV_MAX); + rsp->pdu.datasize = req->pdu.datasize; + iscsi_cmnd_init_write(rsp); + } else { + if (req->req) { + dprintk(D_GENERIC, "releasing NOP-Out %p, ttt %x; " + "removing NOP-In %p, ttt %x\n", req->req, + cmnd_ttt(req->req), req, cmnd_ttt(req)); + cmnd_release(req->req, 0); + } + iscsi_cmnd_remove(req); + } +} + +static void nop_in_timeout(unsigned long data) +{ + struct iscsi_cmnd *req = (struct iscsi_cmnd *)data; + + printk(KERN_INFO "NOP-In ping timed out - closing sid:cid %llu:%u\n", + req->conn->session->sid, req->conn->cid); + clear_cmnd_timer_active(req); + conn_close(req->conn); +} + +/* create a fake NOP-Out req and treat the NOP-In as our rsp to it */ +void send_nop_in(struct iscsi_conn *conn) +{ + struct iscsi_cmnd *req = cmnd_alloc(conn, 1); + struct iscsi_cmnd *rsp = iscsi_cmnd_create_rsp_cmnd(req, 0); + + req->target_task_tag = get_next_ttt(conn->session); + + + nop_hdr_setup(&req->pdu.bhs, ISCSI_OP_NOP_OUT, + cpu_to_be32(ISCSI_RESERVED_TAG), req->target_task_tag); + nop_hdr_setup(&rsp->pdu.bhs, ISCSI_OP_NOP_IN, + cpu_to_be32(ISCSI_RESERVED_TAG), req->target_task_tag); + + dprintk(D_GENERIC, "NOP-Out: %p, ttt %x, timer %p; " + "NOP-In: %p, ttt %x;\n", req, cmnd_ttt(req), &req->timer, rsp, + cmnd_ttt(rsp)); + + init_timer(&req->timer); + req->timer.data = (unsigned long)req; + req->timer.function = nop_in_timeout; + + if (cmnd_insert_hash_ttt(req, req->target_task_tag)) { + eprintk("%s\n", + "failed to insert fake NOP-Out into hash table"); + cmnd_release(rsp, 0); + cmnd_release(req, 0); + } else + iscsi_cmnd_init_write(rsp); +} + +static void nop_in_tx_end(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + u32 t; + + if (cmnd->pdu.bhs.ttt == cpu_to_be32(ISCSI_RESERVED_TAG)) + return; + + /* + * NOP-In ping issued by the target. + * FIXME: Sanitize the NOP timeout earlier, during configuration + */ + t = conn->session->target->trgt_param.nop_timeout; + + if (!t || t > conn->session->target->trgt_param.nop_interval) { + eprintk("Adjusting NOPTimeout of tid %u from %u to %u " + "(== NOPInterval)\n", conn->session->target->tid, + t, + conn->session->target->trgt_param.nop_interval); + t = conn->session->target->trgt_param.nop_interval; + conn->session->target->trgt_param.nop_timeout = t; + } + + dprintk(D_GENERIC, "NOP-In %p, %x: timer %p\n", cmnd, cmnd_ttt(cmnd), + &cmnd->req->timer); + + set_cmnd_timer_active(cmnd->req); + mod_timer(&cmnd->req->timer, jiffies + HZ * t); +} + +static void logout_exec(struct iscsi_cmnd *req) +{ + struct iscsi_logout_req_hdr *req_hdr; + struct iscsi_cmnd *rsp; + struct iscsi_logout_rsp_hdr *rsp_hdr; + + req_hdr = (struct iscsi_logout_req_hdr *)&req->pdu.bhs; + rsp = iscsi_cmnd_create_rsp_cmnd(req, 1); + rsp_hdr = (struct iscsi_logout_rsp_hdr *)&rsp->pdu.bhs; + rsp_hdr->opcode = ISCSI_OP_LOGOUT_RSP; + rsp_hdr->flags = ISCSI_FLG_FINAL; + rsp_hdr->itt = req_hdr->itt; + set_cmnd_close(rsp); + iscsi_cmnd_init_write(rsp); +} + +static void iscsi_cmnd_exec(struct iscsi_cmnd *cmnd) +{ + dprintk(D_GENERIC, "%p,%x,%u\n", cmnd, cmnd_opcode(cmnd), cmnd->pdu.bhs.sn); + + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_NOP_OUT: + nop_out_exec(cmnd); + break; + case ISCSI_OP_SCSI_CMD: + scsi_cmnd_exec(cmnd); + break; + case ISCSI_OP_SCSI_TASK_MGT_MSG: + execute_task_management(cmnd); + break; + case ISCSI_OP_LOGOUT_CMD: + logout_exec(cmnd); + break; + case ISCSI_OP_SCSI_REJECT: + iscsi_cmnd_init_write(get_rsp_cmnd(cmnd)); + break; + case ISCSI_OP_TEXT_CMD: + case ISCSI_OP_SNACK_CMD: + break; + default: + eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); + break; + } +} + +static void __cmnd_send_pdu(struct iscsi_conn *conn, struct tio *tio, u32 offset, u32 size) +{ + dprintk(D_GENERIC, "%p %u,%u\n", tio, offset, size); + offset += tio->offset; + + assert(offset <= tio->offset + tio->size); + assert(offset + size <= tio->offset + tio->size); + + conn->write_tcmnd = tio; + conn->write_offset = offset; + conn->write_size += size; +} + +static void cmnd_send_pdu(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) +{ + u32 size; + struct tio *tio; + + if (!cmnd->pdu.datasize) + return; + + size = (cmnd->pdu.datasize + 3) & -4; + tio = cmnd->tio; + assert(tio); + assert(tio->size == size); + __cmnd_send_pdu(conn, tio, 0, size); +} + +static void set_cork(struct socket *sock, int on) +{ + int opt = on; + mm_segment_t oldfs; + + oldfs = get_fs(); + set_fs(get_ds()); + sock->ops->setsockopt(sock, SOL_TCP, TCP_CORK, (void *)&opt, sizeof(opt)); + set_fs(oldfs); +} + +void cmnd_release(struct iscsi_cmnd *cmnd, int force) +{ + struct iscsi_cmnd *req, *rsp; + int is_last = 0; + + if (!cmnd) + return; + +/* eprintk("%x %lx %d\n", cmnd_opcode(cmnd), cmnd->flags, force); */ + + req = cmnd->req; + is_last = cmnd_final(cmnd); + + if (force) { + while (!list_empty(&cmnd->pdu_list)) { + rsp = list_entry(cmnd->pdu_list.next, struct iscsi_cmnd, pdu_list); + list_del_init(&rsp->list); + list_del(&rsp->pdu_list); + iscsi_cmnd_remove(rsp); + } + list_del_init(&cmnd->list); + } else + if (cmnd_queued(cmnd)) + iscsi_scsi_dequeuecmnd(cmnd); + + if (cmnd_hashed(cmnd)) + cmnd_remove_hash(cmnd); + + if (cmnd_lunit(cmnd)) { + assert(cmnd->lun); + volume_put(cmnd->lun); + } + + list_del_init(&cmnd->pdu_list); + iscsi_cmnd_remove(cmnd); + + if (is_last) { + assert(!force); + assert(req); + cmnd_release(req, 0); + } + + return; +} + +void cmnd_tx_start(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + struct iovec *iop; + + dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); + assert(cmnd); + iscsi_cmnd_set_length(&cmnd->pdu); + + set_cork(conn->sock, 1); + + conn->write_iop = iop = conn->write_iov; + iop->iov_base = &cmnd->pdu.bhs; + iop->iov_len = sizeof(cmnd->pdu.bhs); + iop++; + conn->write_size = sizeof(cmnd->pdu.bhs); + + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_NOP_IN: + if (cmnd->pdu.bhs.itt == ISCSI_RESERVED_TAG) { + /* NOP-In ping generated by us. Don't advance StatSN. */ + cmnd_set_sn(cmnd, 0); + cmnd_set_sn(cmnd->req, 0); + cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn); + cmnd->req->pdu.bhs.sn = cpu_to_be32(conn->stat_sn); + } else + cmnd_set_sn(cmnd, 1); + cmnd_send_pdu(conn, cmnd); + break; + case ISCSI_OP_SCSI_RSP: + cmnd_set_sn(cmnd, 1); + cmnd_send_pdu(conn, cmnd); + break; + case ISCSI_OP_SCSI_TASK_MGT_RSP: + cmnd_set_sn(cmnd, 1); + break; + case ISCSI_OP_TEXT_RSP: + cmnd_set_sn(cmnd, 1); + break; + case ISCSI_OP_SCSI_DATA_IN: + { + struct iscsi_data_in_hdr *rsp = (struct iscsi_data_in_hdr *)&cmnd->pdu.bhs; + u32 offset; + + cmnd_set_sn(cmnd, (rsp->flags & ISCSI_FLG_FINAL) ? 1 : 0); + offset = rsp->buffer_offset; + rsp->buffer_offset = cpu_to_be32(offset); + __cmnd_send_pdu(conn, cmnd->tio, offset, cmnd->pdu.datasize); + break; + } + case ISCSI_OP_LOGOUT_RSP: + cmnd_set_sn(cmnd, 1); + break; + case ISCSI_OP_R2T: + cmnd_set_sn(cmnd, 0); + cmnd->pdu.bhs.sn = cpu_to_be32(conn->stat_sn); + break; + case ISCSI_OP_ASYNC_MSG: + cmnd_set_sn(cmnd, 1); + break; + case ISCSI_OP_REJECT: + cmnd_set_sn(cmnd, 1); + cmnd_send_pdu(conn, cmnd); + break; + default: + eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); + break; + } + + iop->iov_len = 0; + // move this? + conn->write_size = (conn->write_size + 3) & -4; + iscsi_dump_pdu(&cmnd->pdu); +} + +void cmnd_tx_end(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + + dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_NOP_IN: + nop_in_tx_end(cmnd); + break; + case ISCSI_OP_SCSI_RSP: + case ISCSI_OP_SCSI_TASK_MGT_RSP: + case ISCSI_OP_TEXT_RSP: + case ISCSI_OP_R2T: + case ISCSI_OP_ASYNC_MSG: + case ISCSI_OP_REJECT: + case ISCSI_OP_SCSI_DATA_IN: + case ISCSI_OP_LOGOUT_RSP: + break; + default: + eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); + assert(0); + break; + } + + if (cmnd_close(cmnd)) + conn_close(conn); + + list_del_init(&cmnd->list); + set_cork(cmnd->conn->sock, 0); +} + +/** + * Push the command for execution. + * This functions reorders the commands. + * Called from the read thread. + * + * iscsi_session_push_cmnd - + * @cmnd: ptr to command + */ + +static void iscsi_session_push_cmnd(struct iscsi_cmnd *cmnd) +{ + struct iscsi_session *session = cmnd->conn->session; + struct list_head *entry; + u32 cmd_sn; + + if (cmnd->r2t_length) { + if (!cmnd->is_unsolicited_data) + send_r2t(cmnd); + return; + } + + dprintk(D_GENERIC, "%p:%x %u,%u\n", + cmnd, cmnd_opcode(cmnd), cmnd->pdu.bhs.sn, session->exp_cmd_sn); + + if (cmnd_immediate(cmnd)) { + iscsi_cmnd_exec(cmnd); + return; + } + + cmd_sn = cmnd->pdu.bhs.sn; + if (cmd_sn == session->exp_cmd_sn) { + while (1) { + session->exp_cmd_sn = ++cmd_sn; + iscsi_cmnd_exec(cmnd); + + if (list_empty(&session->pending_list)) + break; + + cmnd = list_entry(session->pending_list.next, struct iscsi_cmnd, list); + if (cmnd->pdu.bhs.sn != cmd_sn) + break; + + list_del_init(&cmnd->list); + clear_cmnd_pending(cmnd); + } + } else { + set_cmnd_pending(cmnd); + + list_for_each(entry, &session->pending_list) { + struct iscsi_cmnd *tmp = list_entry(entry, struct iscsi_cmnd, list); + if (before(cmd_sn, tmp->pdu.bhs.sn)) + break; + } + + assert(list_empty(&cmnd->list)); + + list_add_tail(&cmnd->list, entry); + } +} + +static int check_segment_length(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + struct iscsi_sess_param *param = &conn->session->param; + + if (cmnd->pdu.datasize > param->max_recv_data_length) { + eprintk("data too long %x %u %u\n", cmnd_itt(cmnd), + cmnd->pdu.datasize, param->max_recv_data_length); + + if (get_pgcnt(cmnd->pdu.datasize, 0) > ISCSI_CONN_IOV_MAX) { + conn_close(conn); + return -EINVAL; + } + } + + return 0; +} + +void cmnd_rx_start(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + int err = 0; + + iscsi_dump_pdu(&cmnd->pdu); + + set_cmnd_rxstart(cmnd); + if (check_segment_length(cmnd) < 0) + return; + + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_NOP_OUT: + err = nop_out_start(conn, cmnd); + break; + case ISCSI_OP_SCSI_CMD: + if (!(err = cmnd_insert_hash(cmnd))) + scsi_cmnd_start(conn, cmnd); + break; + case ISCSI_OP_SCSI_TASK_MGT_MSG: + err = cmnd_insert_hash(cmnd); + break; + case ISCSI_OP_SCSI_DATA_OUT: + data_out_start(conn, cmnd); + break; + case ISCSI_OP_LOGOUT_CMD: + err = cmnd_insert_hash(cmnd); + break; + case ISCSI_OP_TEXT_CMD: + case ISCSI_OP_SNACK_CMD: + err = -ISCSI_REASON_UNSUPPORTED_COMMAND; + break; + default: + err = -ISCSI_REASON_UNSUPPORTED_COMMAND; + break; + } + + if (err < 0) { + eprintk("%x %x %d\n", cmnd_opcode(cmnd), cmnd_itt(cmnd), err); + iscsi_cmnd_reject(cmnd, -err); + } +} + +void cmnd_rx_end(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + + if (cmnd_tmfabort(cmnd)) { + cmnd_release(cmnd, 1); + return; + } + + dprintk(D_GENERIC, "%p:%x\n", cmnd, cmnd_opcode(cmnd)); + switch (cmnd_opcode(cmnd)) { + case ISCSI_OP_SCSI_REJECT: + case ISCSI_OP_NOP_OUT: + case ISCSI_OP_SCSI_CMD: + case ISCSI_OP_SCSI_TASK_MGT_MSG: + case ISCSI_OP_TEXT_CMD: + case ISCSI_OP_LOGOUT_CMD: + iscsi_session_push_cmnd(cmnd); + break; + case ISCSI_OP_SCSI_DATA_OUT: + data_out_end(conn, cmnd); + break; + case ISCSI_OP_SNACK_CMD: + break; + case ISCSI_OP_PDU_REJECT: + iscsi_cmnd_init_write(get_rsp_cmnd(cmnd)); + break; + case ISCSI_OP_DATA_REJECT: + cmnd_release(cmnd, 0); + break; + default: + eprintk("unexpected cmnd op %x\n", cmnd_opcode(cmnd)); + BUG(); + break; + } +} + +static void iscsi_exit(void) +{ + wthread_module_exit(); + + unregister_chrdev(ctr_major, ctr_name); + + iet_procfs_exit(); + + event_exit(); + + tio_exit(); + + iotype_exit(); + + ua_exit(); + + if (iscsi_cmnd_cache) + kmem_cache_destroy(iscsi_cmnd_cache); +} + +static int iscsi_init(void) +{ + int err = -ENOMEM; + + printk("iSCSI Enterprise Target Software - version %s\n", IET_VERSION_STRING); + + if ((ctr_major = register_chrdev(0, ctr_name, &ctr_fops)) < 0) { + eprintk("failed to register the control device %d\n", ctr_major); + return ctr_major; + } + + if ((err = iet_procfs_init()) < 0) + goto err; + + if ((err = event_init()) < 0) + goto err; + + iscsi_cmnd_cache = KMEM_CACHE(iscsi_cmnd, 0); + if (!iscsi_cmnd_cache) + goto err; + + err = ua_init(); + if (err < 0) + goto err; + + if ((err = tio_init()) < 0) + goto err; + + if ((err = iotype_init()) < 0) + goto err; + + if ((err = wthread_module_init()) < 0) + goto err; + + return 0; + +err: + iscsi_exit(); + return err; +} + +module_param(worker_thread_pool_size, ulong, S_IRUGO); +MODULE_PARM_DESC(worker_thread_pool_size, + "Size of the worker thread pool " + "(0 = dedicated threads per target (default))"); + +module_param(debug_enable_flags, ulong, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug_enable_flags, + "debug bitmask, low bits (0 ... 8) used, see iscsi_dbg.h"); + +module_init(iscsi_init); +module_exit(iscsi_exit); + +MODULE_VERSION(IET_VERSION_STRING); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("iSCSI Enterprise Target"); +MODULE_AUTHOR("IET development team "); --- linux-2.6.37.orig/ubuntu/iscsitarget/iscsi.h +++ linux-2.6.37/ubuntu/iscsitarget/iscsi.h @@ -0,0 +1,524 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * Copyright (C) 2008 Arne Redlich + * + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef __ISCSI_H__ +#define __ISCSI_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iscsi_hdr.h" +#include "iet_u.h" +#include "compat.h" + +#define IET_SENSE_BUF_SIZE 18 + +struct iscsi_sess_param { + int initial_r2t; + int immediate_data; + int max_connections; + int max_recv_data_length; + int max_xmit_data_length; + int max_burst_length; + int first_burst_length; + int default_wait_time; + int default_retain_time; + int max_outstanding_r2t; + int data_pdu_inorder; + int data_sequence_inorder; + int error_recovery_level; + int header_digest; + int data_digest; + int ofmarker; + int ifmarker; + int ofmarkint; + int ifmarkint; +}; + +struct iscsi_trgt_param { + int wthreads; + int target_type; + int queued_cmnds; + int nop_interval; + int nop_timeout; +}; + +struct tio { + u32 pg_cnt; + + pgoff_t idx; + u32 offset; + u32 size; + + struct page **pvec; + + atomic_t count; +}; + +struct network_thread_info { + struct task_struct *task; + unsigned long flags; + struct list_head active_conns; + + spinlock_t nthread_lock; + + void (*old_state_change)(struct sock *); + void (*old_data_ready)(struct sock *, int); + void (*old_write_space)(struct sock *); +}; + +struct worker_thread_info; + +struct worker_thread { + struct task_struct *w_task; + struct list_head w_list; + struct worker_thread_info *w_info; +}; + +struct worker_thread_info { + spinlock_t wthread_lock; + + u32 nr_running_wthreads; + + struct list_head wthread_list; + struct list_head work_queue; + + wait_queue_head_t wthread_sleep; + + struct io_context *wthread_ioc; +}; + +struct iscsi_cmnd; + +struct target_type { + int id; + int (*execute_cmnd) (struct iscsi_cmnd *); +}; + +enum iscsi_device_state { + IDEV_RUNNING, + IDEV_DEL, +}; + +struct iscsi_target { + struct list_head t_list; + u32 tid; + + char name[ISCSI_NAME_LEN]; + + struct iscsi_sess_param sess_param; + struct iscsi_trgt_param trgt_param; + + atomic_t nr_volumes; + struct list_head volumes; + struct list_head session_list; + + /* Prevents races between add/del session and adding UAs */ + spinlock_t session_list_lock; + + struct network_thread_info nthread_info; + /* Points either to own list or global pool */ + struct worker_thread_info * wthread_info; + + struct semaphore target_sem; +}; + +struct iscsi_queue { + spinlock_t queue_lock; + struct iscsi_cmnd *ordered_cmnd; + struct list_head wait_list; + int active_cnt; +}; + +struct iet_volume { + u32 lun; + + enum iscsi_device_state l_state; + atomic_t l_count; + + struct iscsi_target *target; + struct list_head list; + + struct iscsi_queue queue; + + u8 scsi_id[SCSI_ID_LEN]; + u8 scsi_sn[SCSI_SN_LEN + 1]; + + u32 blk_shift; + u64 blk_cnt; + + u64 reserve_sid; + spinlock_t reserve_lock; + + unsigned long flags; + + struct iotype *iotype; + void *private; +}; + +enum lu_flags { + LU_READONLY, + LU_WCACHE, + LU_RCACHE, +}; + +#define LUReadonly(lu) test_bit(LU_READONLY, &(lu)->flags) +#define SetLUReadonly(lu) set_bit(LU_READONLY, &(lu)->flags) + +#define LUWCache(lu) test_bit(LU_WCACHE, &(lu)->flags) +#define SetLUWCache(lu) set_bit(LU_WCACHE, &(lu)->flags) +#define ClearLUWCache(lu) clear_bit(LU_WCACHE, &(lu)->flags) + +#define LURCache(lu) test_bit(LU_RCACHE, &(lu)->flags) +#define SetLURCache(lu) set_bit(LU_RCACHE, &(lu)->flags) +#define ClearLURCache(lu) clear_bit(LU_RCACHE, &(lu)->flags) + +#define IET_HASH_ORDER 8 +#define cmnd_hashfn(itt) hash_long((itt), IET_HASH_ORDER) + +#define UA_HASH_LEN 8 + +struct iscsi_session { + struct list_head list; + struct iscsi_target *target; + struct completion *done; + char *initiator; + u64 sid; + + u32 exp_cmd_sn; + u32 max_cmd_sn; + + struct iscsi_sess_param param; + u32 max_queued_cmnds; + + struct list_head conn_list; + + struct list_head pending_list; + + spinlock_t cmnd_hash_lock; + struct list_head cmnd_hash[1 << IET_HASH_ORDER]; + + spinlock_t ua_hash_lock; + struct list_head ua_hash[UA_HASH_LEN]; + + u32 next_ttt; +}; + +enum connection_state_bit { + CONN_ACTIVE, + CONN_CLOSING, + CONN_WSPACE_WAIT, + CONN_NEED_NOP_IN, +}; + +#define ISCSI_CONN_IOV_MAX (((256 << 10) >> PAGE_SHIFT) + 1) + +struct iscsi_conn { + struct list_head list; /* list entry in session list */ + struct iscsi_session *session; /* owning session */ + + u16 cid; + unsigned long state; + + u32 stat_sn; + u32 exp_stat_sn; + + int hdigest_type; + int ddigest_type; + + struct list_head poll_list; + + struct file *file; + struct socket *sock; + spinlock_t list_lock; + atomic_t nr_cmnds; + atomic_t nr_busy_cmnds; + struct list_head pdu_list; /* in/outcoming pdus */ + struct list_head write_list; /* list of data pdus to be sent */ + struct timer_list nop_timer; + + struct iscsi_cmnd *read_cmnd; + struct msghdr read_msg; + struct iovec read_iov[ISCSI_CONN_IOV_MAX]; + u32 read_size; + u32 read_overflow; + int read_state; + + struct iscsi_cmnd *write_cmnd; + struct iovec write_iov[ISCSI_CONN_IOV_MAX]; + struct iovec *write_iop; + struct tio *write_tcmnd; + u32 write_size; + u32 write_offset; + int write_state; + + struct hash_desc rx_hash; + struct hash_desc tx_hash; + struct scatterlist hash_sg[ISCSI_CONN_IOV_MAX]; +}; + +struct iscsi_pdu { + struct iscsi_hdr bhs; + void *ahs; + unsigned int ahssize; + unsigned int datasize; +}; + +typedef void (iet_show_info_t)(struct seq_file *seq, struct iscsi_target *target); + +struct iscsi_cmnd { + struct list_head list; + struct list_head conn_list; + unsigned long flags; + struct iscsi_conn *conn; + struct iet_volume *lun; + + struct iscsi_pdu pdu; + struct list_head pdu_list; + + struct list_head hash_list; + + struct tio *tio; + + u8 status; + + struct timer_list timer; + + u32 r2t_sn; + u32 r2t_length; + u32 is_unsolicited_data; + u32 target_task_tag; + u32 outstanding_r2t; + + u32 hdigest; + u32 ddigest; + + struct iscsi_cmnd *req; + + unsigned char sense_buf[IET_SENSE_BUF_SIZE]; +}; + +struct ua_entry { + struct list_head entry; + struct iscsi_session *session; /* only used for debugging ATM */ + u32 lun; + u8 asc; + u8 ascq; +}; + +#define ISCSI_OP_SCSI_REJECT ISCSI_OP_VENDOR1_CMD +#define ISCSI_OP_PDU_REJECT ISCSI_OP_VENDOR2_CMD +#define ISCSI_OP_DATA_REJECT ISCSI_OP_VENDOR3_CMD +#define ISCSI_OP_SCSI_ABORT ISCSI_OP_VENDOR4_CMD + +/* iscsi.c */ +extern unsigned long worker_thread_pool_size; +extern struct iscsi_cmnd *cmnd_alloc(struct iscsi_conn *, int); +extern void cmnd_rx_start(struct iscsi_cmnd *); +extern void cmnd_rx_end(struct iscsi_cmnd *); +extern void cmnd_tx_start(struct iscsi_cmnd *); +extern void cmnd_tx_end(struct iscsi_cmnd *); +extern void cmnd_release(struct iscsi_cmnd *, int); +extern void send_data_rsp(struct iscsi_cmnd *, void (*)(struct iscsi_cmnd *)); +extern void send_scsi_rsp(struct iscsi_cmnd *, void (*)(struct iscsi_cmnd *)); +extern void iscsi_cmnd_set_sense(struct iscsi_cmnd *, u8 sense_key, u8 asc, + u8 ascq); +extern void send_nop_in(struct iscsi_conn *); + +/* conn.c */ +extern struct iscsi_conn *conn_lookup(struct iscsi_session *, u16); +extern int conn_add(struct iscsi_session *, struct conn_info *); +extern int conn_del(struct iscsi_session *, struct conn_info *); +extern int conn_free(struct iscsi_conn *); +extern void conn_close(struct iscsi_conn *); +extern void conn_info_show(struct seq_file *, struct iscsi_session *); + +/* nthread.c */ +extern int nthread_init(struct iscsi_target *); +extern int nthread_start(struct iscsi_target *); +extern int nthread_stop(struct iscsi_target *); +extern void __nthread_wakeup(struct network_thread_info *); +extern void nthread_wakeup(struct iscsi_target *); + +/* wthread.c */ +extern int wthread_init(struct worker_thread_info *info); +extern int wthread_start(struct worker_thread_info *info, int wthreads, u32 tid); +extern int wthread_stop(struct worker_thread_info *info); +extern void wthread_queue(struct iscsi_cmnd *); +extern struct target_type *target_type_array[]; +extern int wthread_module_init(void); +extern void wthread_module_exit(void); +extern struct worker_thread_info *worker_thread_pool; + +/* target.c */ +extern int target_lock(struct iscsi_target *, int); +extern void target_unlock(struct iscsi_target *); +struct iscsi_target *target_lookup_by_id(u32); +extern int target_add(struct target_info *); +extern int target_del(u32 id); +extern void target_del_all(void); +extern struct seq_operations iet_seq_op; + +/* config.c */ +extern int iet_procfs_init(void); +extern void iet_procfs_exit(void); +extern int iet_info_show(struct seq_file *, iet_show_info_t *); + +/* session.c */ +extern struct file_operations session_seq_fops; +extern struct iscsi_session *session_lookup(struct iscsi_target *, u64); +extern int session_add(struct iscsi_target *, struct session_info *); +extern int session_del(struct iscsi_target *, u64); + +/* volume.c */ +extern struct file_operations volume_seq_fops; +extern int volume_add(struct iscsi_target *, struct volume_info *); +extern int iscsi_volume_del(struct iscsi_target *, struct volume_info *); +extern void iscsi_volume_destroy(struct iet_volume *); +extern struct iet_volume *volume_lookup(struct iscsi_target *, u32); +extern struct iet_volume *volume_get(struct iscsi_target *, u32); +extern void volume_put(struct iet_volume *); +extern int volume_reserve(struct iet_volume *volume, u64 sid); +extern int volume_release(struct iet_volume *volume, u64 sid, int force); +extern int is_volume_reserved(struct iet_volume *volume, u64 sid); + +/* tio.c */ +extern int tio_init(void); +extern void tio_exit(void); +extern struct tio *tio_alloc(int); +extern void tio_get(struct tio *); +extern void tio_put(struct tio *); +extern void tio_set(struct tio *, u32, loff_t); +extern int tio_read(struct iet_volume *, struct tio *); +extern int tio_write(struct iet_volume *, struct tio *); +extern int tio_sync(struct iet_volume *, struct tio *); + +/* iotype.c */ +extern struct iotype *get_iotype(const char *name); +extern void put_iotype(struct iotype *iot); + +/* params.c */ +extern int iscsi_param_set(struct iscsi_target *, struct iscsi_param_info *, int); + +/* target_disk.c */ +extern struct target_type disk_ops; + +/* event.c */ +extern int event_send(u32, u64, u32, u32, int); +extern int event_init(void); +extern void event_exit(void); + +/* ua.c */ +int ua_init(void); +void ua_exit(void); +struct ua_entry * ua_get_first(struct iscsi_session *, u32 lun); +struct ua_entry * ua_get_match(struct iscsi_session *, u32 lun, u8 asc, + u8 ascq); +void ua_free(struct ua_entry *); +int ua_pending(struct iscsi_session *, u32 lun); +void ua_establish_for_session(struct iscsi_session *, u32 lun, u8 asc, + u8 ascq); +void ua_establish_for_other_sessions(struct iscsi_session *, u32 lun, u8 asc, + u8 ascq); +void ua_establish_for_all_sessions(struct iscsi_target *, u32 lun, u8 asc, + u8 ascq); + +#define get_pgcnt(size, offset) ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT) + +static inline void iscsi_cmnd_get_length(struct iscsi_pdu *pdu) +{ +#if defined(__BIG_ENDIAN) + pdu->ahssize = pdu->bhs.length.ahslength * 4; + pdu->datasize = pdu->bhs.length.datalength; +#elif defined(__LITTLE_ENDIAN) + pdu->ahssize = (pdu->bhs.length & 0xff) * 4; + pdu->datasize = be32_to_cpu(pdu->bhs.length & ~0xff); +#else +#error +#endif +} + +static inline void iscsi_cmnd_set_length(struct iscsi_pdu *pdu) +{ +#if defined(__BIG_ENDIAN) + pdu->bhs.length.ahslength = pdu->ahssize / 4; + pdu->bhs.length.datalength = pdu->datasize; +#elif defined(__LITTLE_ENDIAN) + pdu->bhs.length = cpu_to_be32(pdu->datasize) | (pdu->ahssize / 4); +#else +#error +#endif +} + +#define cmnd_hdr(cmnd) ((struct iscsi_scsi_cmd_hdr *) (&((cmnd)->pdu.bhs))) +#define cmnd_ttt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.ttt) +#define cmnd_itt(cmnd) cpu_to_be32((cmnd)->pdu.bhs.itt) +#define cmnd_opcode(cmnd) ((cmnd)->pdu.bhs.opcode & ISCSI_OPCODE_MASK) +#define cmnd_scsicode(cmnd) cmnd_hdr(cmnd)->scb[0] +#define cmnd_immediate(cmnd) ((cmnd)->pdu.bhs.opcode & ISCSI_OP_IMMEDIATE) + +/* default and maximum scsi level block sizes */ +#define IET_DEF_BLOCK_SIZE 512 +#define IET_MAX_BLOCK_SIZE 4096 + +enum cmnd_flags { + CMND_hashed, + CMND_queued, + CMND_final, + CMND_waitio, + CMND_close, + CMND_lunit, + CMND_pending, + CMND_tmfabort, + CMND_rxstart, + CMND_timer_active, +}; + +#define set_cmnd_hashed(cmnd) set_bit(CMND_hashed, &(cmnd)->flags) +#define cmnd_hashed(cmnd) test_bit(CMND_hashed, &(cmnd)->flags) + +#define set_cmnd_queued(cmnd) set_bit(CMND_queued, &(cmnd)->flags) +#define cmnd_queued(cmnd) test_bit(CMND_queued, &(cmnd)->flags) + +#define set_cmnd_final(cmnd) set_bit(CMND_final, &(cmnd)->flags) +#define cmnd_final(cmnd) test_bit(CMND_final, &(cmnd)->flags) + +#define set_cmnd_waitio(cmnd) set_bit(CMND_waitio, &(cmnd)->flags) +#define cmnd_waitio(cmnd) test_bit(CMND_waitio, &(cmnd)->flags) + +#define set_cmnd_close(cmnd) set_bit(CMND_close, &(cmnd)->flags) +#define cmnd_close(cmnd) test_bit(CMND_close, &(cmnd)->flags) + +#define set_cmnd_lunit(cmnd) set_bit(CMND_lunit, &(cmnd)->flags) +#define cmnd_lunit(cmnd) test_bit(CMND_lunit, &(cmnd)->flags) + +#define set_cmnd_pending(cmnd) set_bit(CMND_pending, &(cmnd)->flags) +#define clear_cmnd_pending(cmnd) clear_bit(CMND_pending, &(cmnd)->flags) +#define cmnd_pending(cmnd) test_bit(CMND_pending, &(cmnd)->flags) + +#define set_cmnd_tmfabort(cmnd) set_bit(CMND_tmfabort, &(cmnd)->flags) +#define cmnd_tmfabort(cmnd) test_bit(CMND_tmfabort, &(cmnd)->flags) + +#define set_cmnd_rxstart(cmnd) set_bit(CMND_rxstart, &(cmnd)->flags) +#define cmnd_rxstart(cmnd) test_bit(CMND_rxstart, &(cmnd)->flags) + +#define set_cmnd_timer_active(cmnd) set_bit(CMND_timer_active, &(cmnd)->flags) +#define clear_cmnd_timer_active(cmnd) \ + clear_bit(CMND_timer_active, &(cmnd)->flags) +#define cmnd_timer_active(cmnd) test_bit(CMND_timer_active, &(cmnd)->flags) + +#define VENDOR_ID "IET" +#define PRODUCT_ID "VIRTUAL-DISK" +#define PRODUCT_REV "0" + +#endif /* __ISCSI_H__ */ --- linux-2.6.37.orig/ubuntu/iscsitarget/iscsi_dbg.h +++ linux-2.6.37/ubuntu/iscsitarget/iscsi_dbg.h @@ -0,0 +1,137 @@ +#ifndef ISCSI_DBG_H +#define ISCSI_DBG_H + +#define D_SETUP (1UL << 0) +#define D_EXIT (1UL << 1) +#define D_GENERIC (1UL << 2) +#define D_READ (1UL << 3) +#define D_WRITE (1UL << 4) +#define D_IOD (1UL << 5) +#define D_THREAD (1UL << 6) +#define D_TASK_MGT (1UL << 7) +#define D_IOMODE (1UL << 8) +#define D_UAC (1UL << 9) + +#define D_DATA (D_READ | D_WRITE) + +extern unsigned long debug_enable_flags; + +#define PFX "iscsi_trgt: " + +#define dprintk(debug, fmt, args...) do { \ + if ((debug) & debug_enable_flags) { \ + printk(KERN_DEBUG PFX "%s(%d) " fmt, __FUNCTION__,\ + __LINE__, args);\ + } \ +} while (0) + +#define dprintk_ua(ua, sess, lun) \ + dprintk(D_UAC, "sess %llu, lun %u: %p %x %x\n", \ + (sess)->sid, lun, ua, \ + (ua) ? (ua)->asc : 0, \ + (ua) ? (ua)->ascq : 0) + +#define eprintk(fmt, args...) do { \ + printk(KERN_ERR PFX "%s(%d) " fmt, __FUNCTION__, \ + __LINE__, args);\ +} while (0) + +#define iprintk(X...) printk(KERN_INFO PFX X) + +#define assert(p) do { \ + if (!(p)) { \ + printk(KERN_CRIT PFX "BUG at %s:%d assert(%s)\n",\ + __FILE__, __LINE__, #p); \ + dump_stack(); \ + BUG(); \ + } \ +} while (0) + +#ifdef D_IOV +static inline void iscsi_dump_iov(struct msghdr *msg) +{ + int i; + printk(PFX "%p, %d\n", msg->msg_iov, msg->msg_iovlen); + for (i = 0; i < min_t(size_t, msg->msg_iovlen, ISCSI_CONN_IOV_MAX); i++) + printk(PFX "%d: %p,%d\n", i, msg->msg_iov[i].iov_base, + msg->msg_iov[i].iov_len); +} +#else +#define iscsi_dump_iov(x) do {} while (0) +#endif + +#ifdef D_DUMP_PDU +static void iscsi_dump_char(int ch) +{ + static unsigned char text[16]; + static int i = 0; + + if (ch < 0) { + while ((i % 16) != 0) { + printk(" "); + text[i] = ' '; + i++; + if ((i % 16) == 0) + printk(" | %.16s |\n", text); + else if ((i % 4) == 0) + printk(" |"); + } + i = 0; + return; + } + + text[i] = (ch < 0x20 || (ch >= 0x80 && ch <= 0xa0)) ? ' ' : ch; + printk(" %02x", ch); + i++; + if ((i % 16) == 0) { + printk(" | %.16s |\n", text); + i = 0; + } else if ((i % 4) == 0) + printk(" |"); +} + +static inline void iscsi_dump_pdu(struct iscsi_pdu *pdu) +{ + unsigned char *buf; + int i; + + buf = (void *)&pdu->bhs; + printk(PFX "BHS: (%p,%d)\n", buf, sizeof(pdu->bhs)); + for (i = 0; i < sizeof(pdu->bhs); i++) + iscsi_dump_char(*buf++); + iscsi_dump_char(-1); + + buf = (void *)pdu->ahs; + printk(PFX "AHS: (%p,%d)\n", buf, pdu->ahssize); + for (i = 0; i < pdu->ahssize; i++) + iscsi_dump_char(*buf++); + iscsi_dump_char(-1); + + printk(PFX "Data: (%d)\n", pdu->datasize); +} + +#else +#define iscsi_dump_pdu(x) do {} while (0) +#endif + +#define show_param(param)\ +{\ + dprintk(D_SETUP, "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",\ + (param)->initial_r2t,\ + (param)->immediate_data,\ + (param)->max_connections,\ + (param)->max_recv_data_length,\ + (param)->max_xmit_data_length,\ + (param)->max_burst_length,\ + (param)->first_burst_length,\ + (param)->default_wait_time,\ + (param)->default_retain_time,\ + (param)->max_outstanding_r2t,\ + (param)->data_pdu_inorder,\ + (param)->data_sequence_inorder,\ + (param)->error_recovery_level,\ + (param)->header_digest,\ + (param)->data_digest);\ +} + +#endif --- linux-2.6.37.orig/ubuntu/iscsitarget/iscsi_hdr.h +++ linux-2.6.37/ubuntu/iscsitarget/iscsi_hdr.h @@ -0,0 +1,509 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef __ISCSI_HDR_H__ +#define __ISCSI_HDR_H__ + +#include +#include + +#define ISCSI_VERSION 0 + +#ifndef __packed +#define __packed __attribute__ ((packed)) +#endif + +struct iscsi_hdr { + u8 opcode; /* 0 */ + u8 flags; + u8 spec1[2]; +#if defined(__BIG_ENDIAN_BITFIELD) + struct { /* 4 */ + unsigned ahslength : 8; + unsigned datalength : 24; + } length; +#elif defined(__LITTLE_ENDIAN_BITFIELD) + u32 length; /* 4 */ +#endif + u16 lun[4]; /* 8 */ + u32 itt; /* 16 */ + u32 ttt; /* 20 */ + u32 sn; /* 24 */ + u32 exp_sn; /* 28 */ + u32 max_sn; /* 32 */ + u32 spec3[3]; /* 36 */ +} __packed; /* 48 */ + +/* Opcode encoding bits */ +#define ISCSI_OP_RETRY 0x80 +#define ISCSI_OP_IMMEDIATE 0x40 +#define ISCSI_OPCODE_MASK 0x3F + +/* Client to Server Message Opcode values */ +#define ISCSI_OP_NOP_OUT 0x00 +#define ISCSI_OP_SCSI_CMD 0x01 +#define ISCSI_OP_SCSI_TASK_MGT_MSG 0x02 +#define ISCSI_OP_LOGIN_CMD 0x03 +#define ISCSI_OP_TEXT_CMD 0x04 +#define ISCSI_OP_SCSI_DATA_OUT 0x05 +#define ISCSI_OP_LOGOUT_CMD 0x06 +#define ISCSI_OP_SNACK_CMD 0x10 + +#define ISCSI_OP_VENDOR1_CMD 0x1c +#define ISCSI_OP_VENDOR2_CMD 0x1d +#define ISCSI_OP_VENDOR3_CMD 0x1e +#define ISCSI_OP_VENDOR4_CMD 0x1f + +/* Server to Client Message Opcode values */ +#define ISCSI_OP_NOP_IN 0x20 +#define ISCSI_OP_SCSI_RSP 0x21 +#define ISCSI_OP_SCSI_TASK_MGT_RSP 0x22 +#define ISCSI_OP_LOGIN_RSP 0x23 +#define ISCSI_OP_TEXT_RSP 0x24 +#define ISCSI_OP_SCSI_DATA_IN 0x25 +#define ISCSI_OP_LOGOUT_RSP 0x26 +#define ISCSI_OP_R2T 0x31 +#define ISCSI_OP_ASYNC_MSG 0x32 +#define ISCSI_OP_REJECT 0x3f + +struct iscsi_ahs_hdr { + u16 ahslength; + u8 ahstype; +} __packed; + +#define ISCSI_AHSTYPE_CDB 1 +#define ISCSI_AHSTYPE_RLENGTH 2 + +union iscsi_sid { + struct { + u8 isid[6]; /* Initiator Session ID */ + u16 tsih; /* Target Session ID */ + } id; + u64 id64; +} __packed; + +struct iscsi_scsi_cmd_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 data_length; + u32 cmd_sn; + u32 exp_stat_sn; + u8 scb[16]; +} __packed; + +#define ISCSI_CMD_FINAL 0x80 +#define ISCSI_CMD_READ 0x40 +#define ISCSI_CMD_WRITE 0x20 +#define ISCSI_CMD_ATTR_MASK 0x07 +#define ISCSI_CMD_UNTAGGED 0x00 +#define ISCSI_CMD_SIMPLE 0x01 +#define ISCSI_CMD_ORDERED 0x02 +#define ISCSI_CMD_HEAD_OF_QUEUE 0x03 +#define ISCSI_CMD_ACA 0x04 + +struct iscsi_cdb_ahdr { + u16 ahslength; + u8 ahstype; + u8 reserved; + u8 cdb[0]; +} __packed; + +struct iscsi_rlength_ahdr { + u16 ahslength; + u8 ahstype; + u8 reserved; + u32 read_length; +} __packed; + +struct iscsi_scsi_rsp_hdr { + u8 opcode; + u8 flags; + u8 response; + u8 cmd_status; + u8 ahslength; + u8 datalength[3]; + u32 rsvd1[2]; + u32 itt; + u32 snack; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 exp_data_sn; + u32 bi_residual_count; + u32 residual_count; +} __packed; + +#define ISCSI_FLG_RESIDUAL_UNDERFLOW 0x02 +#define ISCSI_FLG_RESIDUAL_OVERFLOW 0x04 +#define ISCSI_FLG_BIRESIDUAL_UNDERFLOW 0x08 +#define ISCSI_FLG_BIRESIDUAL_OVERFLOW 0x10 + +#define ISCSI_RESPONSE_COMMAND_COMPLETED 0x00 +#define ISCSI_RESPONSE_TARGET_FAILURE 0x01 + +struct iscsi_sense_data { + u16 length; + u8 data[0]; +} __packed; + +struct iscsi_task_mgt_hdr { + u8 opcode; + u8 function; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 rtt; + u32 cmd_sn; + u32 exp_stat_sn; + u32 ref_cmd_sn; + u32 exp_data_sn; + u32 rsvd2[2]; +} __packed; + +#define ISCSI_FUNCTION_MASK 0x7f + +#define ISCSI_FUNCTION_ABORT_TASK 1 +#define ISCSI_FUNCTION_ABORT_TASK_SET 2 +#define ISCSI_FUNCTION_CLEAR_ACA 3 +#define ISCSI_FUNCTION_CLEAR_TASK_SET 4 +#define ISCSI_FUNCTION_LOGICAL_UNIT_RESET 5 +#define ISCSI_FUNCTION_TARGET_WARM_RESET 6 +#define ISCSI_FUNCTION_TARGET_COLD_RESET 7 +#define ISCSI_FUNCTION_TASK_REASSIGN 8 + +struct iscsi_task_rsp_hdr { + u8 opcode; + u8 flags; + u8 response; + u8 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 rsvd3; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 rsvd4[3]; +} __packed; + +#define ISCSI_RESPONSE_FUNCTION_COMPLETE 0 +#define ISCSI_RESPONSE_UNKNOWN_TASK 1 +#define ISCSI_RESPONSE_UNKNOWN_LUN 2 +#define ISCSI_RESPONSE_TASK_ALLEGIANT 3 +#define ISCSI_RESPONSE_FAILOVER_UNSUPPORTED 4 +#define ISCSI_RESPONSE_FUNCTION_UNSUPPORTED 5 +#define ISCSI_RESPONSE_NO_AUTHORIZATION 6 +#define ISCSI_RESPONSE_FUNCTION_REJECTED 255 + +struct iscsi_data_out_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 ttt; + u32 rsvd2; + u32 exp_stat_sn; + u32 rsvd3; + u32 data_sn; + u32 buffer_offset; + u32 rsvd4; +} __packed; + +struct iscsi_data_in_hdr { + u8 opcode; + u8 flags; + u8 rsvd1; + u8 cmd_status; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 ttt; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 data_sn; + u32 buffer_offset; + u32 residual_count; +} __packed; + +#define ISCSI_FLG_STATUS 0x01 + +struct iscsi_r2t_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 ttt; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 r2t_sn; + u32 buffer_offset; + u32 data_length; +} __packed; + +struct iscsi_async_msg_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 ffffffff; + u32 rsvd2; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u8 async_event; + u8 async_vcode; + u16 param1; + u16 param2; + u16 param3; + u32 rsvd3; +} __packed; + +#define ISCSI_ASYNC_SCSI 0 +#define ISCSI_ASYNC_LOGOUT 1 +#define ISCSI_ASYNC_DROP_CONNECTION 2 +#define ISCSI_ASYNC_DROP_SESSION 3 +#define ISCSI_ASYNC_PARAM_REQUEST 4 +#define ISCSI_ASYNC_VENDOR 255 + +struct iscsi_text_req_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 ttt; + u32 cmd_sn; + u32 exp_stat_sn; + u32 rsvd3[4]; +} __packed; + +struct iscsi_text_rsp_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 ttt; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 rsvd3[3]; +} __packed; + +struct iscsi_login_req_hdr { + u8 opcode; + u8 flags; + u8 max_version; /* Max. version supported */ + u8 min_version; /* Min. version supported */ + u8 ahslength; + u8 datalength[3]; + union iscsi_sid sid; + u32 itt; /* Initiator Task Tag */ + u16 cid; /* Connection ID */ + u16 rsvd1; + u32 cmd_sn; + u32 exp_stat_sn; + u32 rsvd2[4]; +} __packed; + +struct iscsi_login_rsp_hdr { + u8 opcode; + u8 flags; + u8 max_version; /* Max. version supported */ + u8 active_version; /* Active version */ + u8 ahslength; + u8 datalength[3]; + union iscsi_sid sid; + u32 itt; /* Initiator Task Tag */ + u32 rsvd1; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u8 status_class; /* see Login RSP ststus classes below */ + u8 status_detail; /* see Login RSP Status details below */ + u8 rsvd2[10]; +} __packed; + +#define ISCSI_FLG_FINAL 0x80 +#define ISCSI_FLG_TRANSIT 0x80 +#define ISCSI_FLG_CSG_SECURITY 0x00 +#define ISCSI_FLG_CSG_LOGIN 0x04 +#define ISCSI_FLG_CSG_FULL_FEATURE 0x0c +#define ISCSI_FLG_CSG_MASK 0x0c +#define ISCSI_FLG_NSG_SECURITY 0x00 +#define ISCSI_FLG_NSG_LOGIN 0x01 +#define ISCSI_FLG_NSG_FULL_FEATURE 0x03 +#define ISCSI_FLG_NSG_MASK 0x03 + +/* Login Status response classes */ +#define ISCSI_STATUS_SUCCESS 0x00 +#define ISCSI_STATUS_REDIRECT 0x01 +#define ISCSI_STATUS_INITIATOR_ERR 0x02 +#define ISCSI_STATUS_TARGET_ERR 0x03 + +/* Login Status response detail codes */ +/* Class-0 (Success) */ +#define ISCSI_STATUS_ACCEPT 0x00 + +/* Class-1 (Redirection) */ +#define ISCSI_STATUS_TGT_MOVED_TEMP 0x01 +#define ISCSI_STATUS_TGT_MOVED_PERM 0x02 + +/* Class-2 (Initiator Error) */ +#define ISCSI_STATUS_INIT_ERR 0x00 +#define ISCSI_STATUS_AUTH_FAILED 0x01 +#define ISCSI_STATUS_TGT_FORBIDDEN 0x02 +#define ISCSI_STATUS_TGT_NOT_FOUND 0x03 +#define ISCSI_STATUS_TGT_REMOVED 0x04 +#define ISCSI_STATUS_NO_VERSION 0x05 +#define ISCSI_STATUS_TOO_MANY_CONN 0x06 +#define ISCSI_STATUS_MISSING_FIELDS 0x07 +#define ISCSI_STATUS_CONN_ADD_FAILED 0x08 +#define ISCSI_STATUS_INV_SESSION_TYPE 0x09 +#define ISCSI_STATUS_SESSION_NOT_FOUND 0x0a +#define ISCSI_STATUS_INV_REQ_TYPE 0x0b + +/* Class-3 (Target Error) */ +#define ISCSI_STATUS_TARGET_ERROR 0x00 +#define ISCSI_STATUS_SVC_UNAVAILABLE 0x01 +#define ISCSI_STATUS_NO_RESOURCES 0x02 + +struct iscsi_logout_req_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u16 cid; + u16 rsvd3; + u32 cmd_sn; + u32 exp_stat_sn; + u32 rsvd4[4]; +} __packed; + +struct iscsi_logout_rsp_hdr { + u8 opcode; + u8 flags; + u8 response; + u8 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 rsvd3; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 rsvd4; + u16 time2wait; + u16 time2retain; + u32 rsvd5; +} __packed; + +struct iscsi_snack_req_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 itt; + u32 ttt; + u32 rsvd3; + u32 exp_stat_sn; + u32 rsvd4[2]; + u32 beg_run; + u32 run_length; +} __packed; + +struct iscsi_reject_hdr { + u8 opcode; + u8 flags; + u8 reason; + u8 rsvd1; + u8 ahslength; + u8 datalength[3]; + u32 rsvd2[2]; + u32 ffffffff; + u32 rsvd3; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 data_sn; + u32 rsvd4[2]; +} __packed; + +#define ISCSI_REASON_NO_FULL_FEATURE_PHASE 0x01 +#define ISCSI_REASON_DATA_DIGEST_ERROR 0x02 +#define ISCSI_REASON_DATA_SNACK_REJECT 0x03 +#define ISCSI_REASON_PROTOCOL_ERROR 0x04 +#define ISCSI_REASON_UNSUPPORTED_COMMAND 0x05 +#define ISCSI_REASON_IMMEDIATE_COMMAND_REJECT 0x06 +#define ISCSI_REASON_TASK_IN_PROGRESS 0x07 +#define ISCSI_REASON_INVALID_SNACK 0x08 +#define ISCSI_REASON_NO_BOOKMARK 0x09 +#define ISCSI_REASON_BOOKMARK_REJECT 0x0a +#define ISCSI_REASON_NEGOTIATION_RESET 0x0b +#define ISCSI_REASON_WAITING_LOGOUT 0x0c + + +struct iscsi_nop_out_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 ttt; + u32 cmd_sn; + u32 exp_stat_sn; + u32 rsvd2[4]; +} __packed; + +struct iscsi_nop_in_hdr { + u8 opcode; + u8 flags; + u16 rsvd1; + u8 ahslength; + u8 datalength[3]; + u16 lun[4]; + u32 itt; + u32 ttt; + u32 stat_sn; + u32 exp_cmd_sn; + u32 max_cmd_sn; + u32 rsvd2[3]; +} __packed; + +#define ISCSI_RESERVED_TAG (0xffffffffU) + +#endif /* __ISCSI_HDR_H__ */ --- linux-2.6.37.orig/ubuntu/iscsitarget/nthread.c +++ linux-2.6.37/ubuntu/iscsitarget/nthread.c @@ -0,0 +1,790 @@ +/* + * Network thread. + * (C) 2004 - 2005 FUJITA Tomonori + * (C) 2008 Arne Redlich + * + * This code is licenced under the GPL. + */ + +#include +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "digest.h" + +enum daemon_state_bit { + D_ACTIVE, + D_DATA_READY, +}; + +void __nthread_wakeup(struct network_thread_info *info) +{ + set_bit(D_DATA_READY, &info->flags); + wake_up_process(info->task); +} + +void nthread_wakeup(struct iscsi_target *target) +{ + struct network_thread_info *info = &target->nthread_info; + + spin_lock_bh(&info->nthread_lock); + __nthread_wakeup(info); + spin_unlock_bh(&info->nthread_lock); +} + +static inline void iscsi_conn_init_read(struct iscsi_conn *conn, void *data, size_t len) +{ + len = (len + 3) & -4; // XXX ??? + conn->read_iov[0].iov_base = data; + conn->read_iov[0].iov_len = len; + conn->read_msg.msg_iov = conn->read_iov; + conn->read_msg.msg_iovlen = 1; + conn->read_size = (len + 3) & -4; +} + +static void iscsi_conn_read_ahs(struct iscsi_conn *conn, struct iscsi_cmnd *cmnd) +{ + cmnd->pdu.ahs = kmalloc(cmnd->pdu.ahssize, __GFP_NOFAIL|GFP_KERNEL); + assert(cmnd->pdu.ahs); + iscsi_conn_init_read(conn, cmnd->pdu.ahs, cmnd->pdu.ahssize); +} + +static struct iscsi_cmnd * iscsi_get_send_cmnd(struct iscsi_conn *conn) +{ + struct iscsi_cmnd *cmnd = NULL; + + spin_lock(&conn->list_lock); + if (!list_empty(&conn->write_list)) { + cmnd = list_entry(conn->write_list.next, struct iscsi_cmnd, list); + list_del_init(&cmnd->list); + } + spin_unlock(&conn->list_lock); + + return cmnd; +} + +static int is_data_available(struct iscsi_conn *conn) +{ + int avail, res; + mm_segment_t oldfs; + struct socket *sock = conn->sock; + + oldfs = get_fs(); + set_fs(get_ds()); + res = sock->ops->ioctl(sock, SIOCINQ, (unsigned long) &avail); + set_fs(oldfs); + return (res >= 0) ? avail : res; +} + +static void forward_iov(struct msghdr *msg, int len) +{ + while (msg->msg_iov->iov_len <= len) { + len -= msg->msg_iov->iov_len; + msg->msg_iov++; + msg->msg_iovlen--; + } + + msg->msg_iov->iov_base = (char *) msg->msg_iov->iov_base + len; + msg->msg_iov->iov_len -= len; +} + +static int do_recv(struct iscsi_conn *conn, int state) +{ + mm_segment_t oldfs; + struct msghdr msg; + struct iovec iov[ISCSI_CONN_IOV_MAX]; + int i, len, res; + + if (!test_bit(CONN_ACTIVE, &conn->state)) { + res = -EIO; + goto out; + } + + if (is_data_available(conn) <= 0) { + res = -EAGAIN; + goto out; + } + + msg.msg_iov = iov; + msg.msg_iovlen = min_t(size_t, conn->read_msg.msg_iovlen, ISCSI_CONN_IOV_MAX); + for (i = 0, len = 0; i < msg.msg_iovlen; i++) { + iov[i] = conn->read_msg.msg_iov[i]; + len += iov[i].iov_len; + } + + oldfs = get_fs(); + set_fs(get_ds()); + res = sock_recvmsg(conn->sock, &msg, len, MSG_DONTWAIT | MSG_NOSIGNAL); + set_fs(oldfs); + + if (res <= 0) { + switch (res) { + case -EAGAIN: + case -ERESTARTSYS: + break; + default: + eprintk("%d\n", res); + conn_close(conn); + break; + } + } else { + conn->read_size -= res; + if (conn->read_size) + forward_iov(&conn->read_msg, res); + else + conn->read_state = state; + } + +out: + dprintk(D_IOD, "%d\n", res); + + return res; +} + +enum rx_state { + RX_INIT_BHS, /* Must be zero. */ + RX_BHS, + + RX_INIT_AHS, + RX_AHS, + + RX_INIT_HDIGEST, + RX_HDIGEST, + RX_CHECK_HDIGEST, + + RX_INIT_DATA, + RX_DATA, + + RX_INIT_DDIGEST, + RX_DDIGEST, + RX_CHECK_DDIGEST, + + RX_END, +}; + +static void rx_ddigest(struct iscsi_conn *conn, int state) +{ + struct iscsi_cmnd *cmnd = conn->read_cmnd; + int res = digest_rx_data(cmnd); + + if (!res) + conn->read_state = state; + else + conn_close(conn); +} + +static void rx_hdigest(struct iscsi_conn *conn, int state) +{ + struct iscsi_cmnd *cmnd = conn->read_cmnd; + int res = digest_rx_header(cmnd); + + if (!res) + conn->read_state = state; + else + conn_close(conn); +} + +static struct iscsi_cmnd *create_cmnd(struct iscsi_conn *conn) +{ + struct iscsi_cmnd *cmnd; + + cmnd = cmnd_alloc(conn, 1); + iscsi_conn_init_read(cmnd->conn, &cmnd->pdu.bhs, sizeof(cmnd->pdu.bhs)); + conn->read_state = RX_BHS; + + return cmnd; +} + +static int recv(struct iscsi_conn *conn) +{ + struct iscsi_cmnd *cmnd = conn->read_cmnd; + int hdigest, ddigest, res = 1; + + if (!test_bit(CONN_ACTIVE, &conn->state)) + return -EIO; + + hdigest = conn->hdigest_type & DIGEST_NONE ? 0 : 1; + ddigest = conn->ddigest_type & DIGEST_NONE ? 0 : 1; + +next_state: + switch (conn->read_state) { + case RX_INIT_BHS: + assert(!cmnd); + cmnd = conn->read_cmnd = create_cmnd(conn); + case RX_BHS: + res = do_recv(conn, RX_INIT_AHS); + if (res <= 0 || conn->read_state != RX_INIT_AHS) + break; + case RX_INIT_AHS: + iscsi_cmnd_get_length(&cmnd->pdu); + if (cmnd->pdu.ahssize) { + iscsi_conn_read_ahs(conn, cmnd); + conn->read_state = RX_AHS; + } else + conn->read_state = hdigest ? RX_INIT_HDIGEST : RX_INIT_DATA; + + if (conn->read_state != RX_AHS) + break; + case RX_AHS: + res = do_recv(conn, hdigest ? RX_INIT_HDIGEST : RX_INIT_DATA); + if (res <= 0 || conn->read_state != RX_INIT_HDIGEST) + break; + case RX_INIT_HDIGEST: + iscsi_conn_init_read(conn, &cmnd->hdigest, sizeof(u32)); + conn->read_state = RX_HDIGEST; + case RX_HDIGEST: + res = do_recv(conn, RX_CHECK_HDIGEST); + if (res <= 0 || conn->read_state != RX_CHECK_HDIGEST) + break; + case RX_CHECK_HDIGEST: + rx_hdigest(conn, RX_INIT_DATA); + if (conn->read_state != RX_INIT_DATA) + break; + case RX_INIT_DATA: + cmnd_rx_start(cmnd); + conn->read_state = cmnd->pdu.datasize ? RX_DATA : RX_END; + if (conn->read_state != RX_DATA) + break; + case RX_DATA: + res = do_recv(conn, ddigest ? RX_INIT_DDIGEST : RX_END); + if (res <= 0 || conn->read_state != RX_INIT_DDIGEST) + break; + case RX_INIT_DDIGEST: + iscsi_conn_init_read(conn, &cmnd->ddigest, sizeof(u32)); + conn->read_state = RX_DDIGEST; + case RX_DDIGEST: + res = do_recv(conn, RX_CHECK_DDIGEST); + if (res <= 0 || conn->read_state != RX_CHECK_DDIGEST) + break; + case RX_CHECK_DDIGEST: + rx_ddigest(conn, RX_END); + break; + default: + eprintk("%d %d %x\n", res, conn->read_state, cmnd_opcode(cmnd)); + assert(0); + } + + if (res <= 0) + return res; + + if (conn->read_state != RX_END) + goto next_state; + + if (conn->read_size) { + eprintk("%d %x %d\n", res, cmnd_opcode(cmnd), conn->read_size); + assert(0); + } + + cmnd_rx_end(cmnd); + if (conn->read_size) { + eprintk("%x %d\n", cmnd_opcode(cmnd), conn->read_size); + conn->read_state = RX_DATA; + return 1; + } + + conn->read_cmnd = NULL; + conn->read_state = RX_INIT_BHS; + + return 0; +} + +/* + * @locking: grabs the target's nthread_lock to protect it from races with + * iet_write_space() + */ +static void set_conn_wspace_wait(struct iscsi_conn *conn) +{ + struct network_thread_info *info = &conn->session->target->nthread_info; + struct sock *sk = conn->sock->sk; + + spin_lock_bh(&info->nthread_lock); + + if (sk_stream_wspace(sk) < sk_stream_min_wspace(sk)) + set_bit(CONN_WSPACE_WAIT, &conn->state); + + spin_unlock_bh(&info->nthread_lock); +} + +/* This is taken from the Ardis code. */ +static int write_data(struct iscsi_conn *conn) +{ + mm_segment_t oldfs; + struct file *file; + struct socket *sock; + ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); + struct tio *tio; + struct iovec *iop; + int saved_size, size, sendsize; + int offset, idx; + int flags, res; + + file = conn->file; + saved_size = size = conn->write_size; + iop = conn->write_iop; + + if (iop) while (1) { + loff_t off = 0; + unsigned long count; + struct iovec *vec; + int rest; + + vec = iop; + for (count = 0; vec->iov_len; count++, vec++) + ; + oldfs = get_fs(); + set_fs(KERNEL_DS); + res = vfs_writev(file, (struct iovec __user *) iop, count, &off); + set_fs(oldfs); + dprintk(D_DATA, "%#Lx:%u: %d(%ld)\n", + (unsigned long long) conn->session->sid, conn->cid, + res, (long) iop->iov_len); + if (unlikely(res <= 0)) { + if (res == -EAGAIN || res == -EINTR) { + conn->write_iop = iop; + goto out_iov; + } + goto err; + } + + rest = res; + size -= res; + while (iop->iov_len <= rest && rest) { + rest -= iop->iov_len; + iop++; + } + iop->iov_base += rest; + iop->iov_len -= rest; + + if (!iop->iov_len) { + conn->write_iop = NULL; + if (size) + break; + goto out_iov; + } + } + + if (!(tio = conn->write_tcmnd)) { + eprintk("%s\n", "warning data missing!"); + return 0; + } + offset = conn->write_offset; + idx = offset >> PAGE_CACHE_SHIFT; + offset &= ~PAGE_CACHE_MASK; + + sock = conn->sock; + sendpage = sock->ops->sendpage ? : sock_no_sendpage; + flags = MSG_DONTWAIT; + + while (1) { + sendsize = PAGE_CACHE_SIZE - offset; + if (size <= sendsize) { + res = sendpage(sock, tio->pvec[idx], offset, size, flags); + dprintk(D_DATA, "%s %#Lx:%u: %d(%lu,%u,%u)\n", + sock->ops->sendpage ? "sendpage" : "writepage", + (unsigned long long ) conn->session->sid, conn->cid, + res, tio->pvec[idx]->index, offset, size); + if (unlikely(res <= 0)) { + if (res == -EAGAIN || res == -EINTR) { + goto out; + } + goto err; + } + if (res == size) { + conn->write_tcmnd = NULL; + conn->write_size = 0; + return saved_size; + } + offset += res; + size -= res; + continue; + } + + res = sendpage(sock, tio->pvec[idx], offset,sendsize, flags | MSG_MORE); + dprintk(D_DATA, "%s %#Lx:%u: %d(%lu,%u,%u)\n", + sock->ops->sendpage ? "sendpage" : "writepage", + (unsigned long long ) conn->session->sid, conn->cid, + res, tio->pvec[idx]->index, offset, sendsize); + if (unlikely(res <= 0)) { + if (res == -EAGAIN || res == -EINTR) { + goto out; + } + goto err; + } + if (res == sendsize) { + idx++; + offset = 0; + } else + offset += res; + size -= res; + } + out: + conn->write_offset = (idx << PAGE_CACHE_SHIFT) + offset; + out_iov: + conn->write_size = size; + if (res == -EAGAIN) { + set_conn_wspace_wait(conn); + if (saved_size == size) + return res; + } + + return saved_size - size; + + err: + eprintk("error %d at %#Lx:%u\n", res, + (unsigned long long) conn->session->sid, conn->cid); + return res; +} + +static void exit_tx(struct iscsi_conn *conn, int res) +{ + if (res > 0) + return; + + switch (res) { + case -EAGAIN: + case -ERESTARTSYS: + break; + default: + eprintk("%d %d %d\n", conn->write_size, conn->write_state, res); + conn_close(conn); + break; + } +} + +static int tx_ddigest(struct iscsi_cmnd *cmnd, int state) +{ + int res, rest = cmnd->conn->write_size; + struct msghdr msg = {.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT}; + struct kvec iov; + + iov.iov_base = (char *) (&cmnd->ddigest) + (sizeof(u32) - rest); + iov.iov_len = rest; + + res = kernel_sendmsg(cmnd->conn->sock, &msg, &iov, 1, rest); + + if (res > 0) { + cmnd->conn->write_size -= res; + if (!cmnd->conn->write_size) + cmnd->conn->write_state = state; + } else + exit_tx(cmnd->conn, res); + + return res; +} + +static void init_tx_hdigest(struct iscsi_cmnd *cmnd) +{ + struct iscsi_conn *conn = cmnd->conn; + struct iovec *iop; + + if (conn->hdigest_type & DIGEST_NONE) + return; + + digest_tx_header(cmnd); + + for (iop = conn->write_iop; iop->iov_len; iop++) + ; + iop->iov_base = &(cmnd->hdigest); + iop->iov_len = sizeof(u32); + conn->write_size += sizeof(u32); + iop++; + iop->iov_len = 0; + + return; +} + +enum tx_state { + TX_INIT, /* Must be zero. */ + TX_BHS_DATA, + TX_INIT_DDIGEST, + TX_DDIGEST, + TX_END, +}; + +static int do_send(struct iscsi_conn *conn, int state) +{ + int res; + + res = write_data(conn); + + if (res > 0) { + if (!conn->write_size) + conn->write_state = state; + } else + exit_tx(conn, res); + + return res; +} + +static int send(struct iscsi_conn *conn) +{ + struct iscsi_cmnd *cmnd = conn->write_cmnd; + int ddigest, res = 0; + + ddigest = conn->ddigest_type != DIGEST_NONE ? 1 : 0; + +next_state: + switch (conn->write_state) { + case TX_INIT: + assert(!cmnd); + cmnd = conn->write_cmnd = iscsi_get_send_cmnd(conn); + if (!cmnd) + return 0; + cmnd_tx_start(cmnd); + init_tx_hdigest(cmnd); + conn->write_state = TX_BHS_DATA; + case TX_BHS_DATA: + res = do_send(conn, ddigest && cmnd->pdu.datasize ? TX_INIT_DDIGEST : TX_END); + if (res <= 0 || conn->write_state != TX_INIT_DDIGEST) + break; + case TX_INIT_DDIGEST: + digest_tx_data(cmnd); + assert(!cmnd->conn->write_size); + cmnd->conn->write_size += sizeof(u32); + conn->write_state = TX_DDIGEST; + case TX_DDIGEST: + res = tx_ddigest(cmnd, TX_END); + break; + default: + eprintk("%d %d %x\n", res, conn->write_state, cmnd_opcode(cmnd)); + assert(0); + } + + if (res <= 0) + return res; + + if (conn->write_state != TX_END) + goto next_state; + + if (conn->write_size) { + eprintk("%d %x %u\n", res, cmnd_opcode(cmnd), conn->write_size); + assert(!conn->write_size); + } + cmnd_tx_end(cmnd); + cmnd_release(cmnd, 0); + conn->write_cmnd = NULL; + conn->write_state = TX_INIT; + + return 0; +} + +static void conn_nop_timeout(unsigned long data) +{ + struct iscsi_conn *conn = (struct iscsi_conn *)data; + + if (test_bit(CONN_ACTIVE, &conn->state)) + set_bit(CONN_NEED_NOP_IN, &conn->state); + + dprintk(D_THREAD, "conn %llu:%hu, NOP timer %p\n", conn->session->sid, + conn->cid, &conn->nop_timer); + + nthread_wakeup(conn->session->target); +} + +static void conn_reset_nop_timer(struct iscsi_conn *conn) +{ + struct iscsi_target *target = conn->session->target; + + if (target->trgt_param.nop_interval) + mod_timer(&conn->nop_timer, + jiffies + HZ * target->trgt_param.nop_interval); +} + +static void conn_start_nop_timer(struct iscsi_conn *conn) +{ + struct iscsi_target *target = conn->session->target; + + if (!target->trgt_param.nop_interval || timer_pending(&conn->nop_timer)) + return; + + conn->nop_timer.data = (unsigned long)conn; + conn->nop_timer.function = conn_nop_timeout; + + dprintk(D_THREAD, "conn %llu:%hu, NOP timer %p\n", conn->session->sid, + conn->cid, &conn->nop_timer); + + mod_timer(&conn->nop_timer, + jiffies + HZ * target->trgt_param.nop_interval); +} + +static void process_io(struct iscsi_conn *conn) +{ + struct iscsi_target *target = conn->session->target; + int res, wakeup = 0; + + res = recv(conn); + + if (is_data_available(conn) > 0 || res > 0) { + conn_reset_nop_timer(conn); + wakeup = 1; + } + + if (!test_bit(CONN_ACTIVE, &conn->state)) { + wakeup = 1; + goto out; + } + + if (test_bit(CONN_WSPACE_WAIT, &conn->state)) + goto out; + + res = send(conn); + + if (!list_empty(&conn->write_list) || conn->write_cmnd) { + conn_reset_nop_timer(conn); + wakeup = 1; + } + +out: + if (wakeup) + nthread_wakeup(target); + else if (test_and_clear_bit(CONN_NEED_NOP_IN, &conn->state)) { + send_nop_in(conn); + nthread_wakeup(target); + } else + conn_start_nop_timer(conn); + + return; +} + +static void close_conn(struct iscsi_conn *conn) +{ + struct iscsi_session *session = conn->session; + struct iscsi_target *target = conn->session->target; + struct iscsi_cmnd *cmnd; + + if (target->trgt_param.nop_interval) + del_timer_sync(&conn->nop_timer); + + conn->sock->ops->shutdown(conn->sock, 2); + + write_lock_bh(&conn->sock->sk->sk_callback_lock); + conn->sock->sk->sk_state_change = target->nthread_info.old_state_change; + conn->sock->sk->sk_data_ready = target->nthread_info.old_data_ready; + conn->sock->sk->sk_write_space = target->nthread_info.old_write_space; + write_unlock_bh(&conn->sock->sk->sk_callback_lock); + + fput(conn->file); + conn->file = NULL; + conn->sock = NULL; + + while (atomic_read(&conn->nr_busy_cmnds)) + yield(); + + while (!list_empty(&conn->pdu_list)) { + cmnd = list_entry(conn->pdu_list.next, struct iscsi_cmnd, conn_list); + + list_del_init(&cmnd->list); + cmnd_release(cmnd, 1); + } + + if (atomic_read(&conn->nr_cmnds)) { + eprintk("%u\n", atomic_read(&conn->nr_cmnds)); + list_for_each_entry(cmnd, &conn->pdu_list, conn_list) + eprintk("%x %x\n", cmnd_opcode(cmnd), cmnd_itt(cmnd)); + assert(0); + } + + event_send(target->tid, session->sid, conn->cid, E_CONN_CLOSE, 0); + conn_free(conn); + + if (list_empty(&session->conn_list)) { + if (session->done) + complete(session->done); + else + session_del(target, session->sid); + } +} + +static int istd(void *arg) +{ + struct iscsi_target *target = arg; + struct network_thread_info *info = &target->nthread_info; + struct iscsi_conn *conn, *tmp; + + __set_current_state(TASK_RUNNING); + do { + spin_lock_bh(&info->nthread_lock); + __set_current_state(TASK_INTERRUPTIBLE); + + if (!test_bit(D_DATA_READY, &info->flags)) { + spin_unlock_bh(&info->nthread_lock); + schedule(); + spin_lock_bh(&info->nthread_lock); + } + __set_current_state(TASK_RUNNING); + clear_bit(D_DATA_READY, &info->flags); + spin_unlock_bh(&info->nthread_lock); + + target_lock(target, 0); + list_for_each_entry_safe(conn, tmp, &info->active_conns, poll_list) { + if (test_bit(CONN_ACTIVE, &conn->state)) + process_io(conn); + else + close_conn(conn); + } + target_unlock(target); + + } while (!kthread_should_stop()); + + return 0; +} + +int nthread_init(struct iscsi_target *target) +{ + struct network_thread_info *info = &target->nthread_info; + + info->flags = 0; + info->task = NULL; + + info->old_state_change = NULL; + info->old_data_ready = NULL; + info->old_write_space = NULL; + + INIT_LIST_HEAD(&info->active_conns); + + spin_lock_init(&info->nthread_lock); + + return 0; +} + +int nthread_start(struct iscsi_target *target) +{ + int err = 0; + struct network_thread_info *info = &target->nthread_info; + struct task_struct *task; + + if (info->task) { + eprintk("Target (%u) already runs\n", target->tid); + return -EALREADY; + } + + task = kthread_run(istd, target, "istd%d", target->tid); + + if (IS_ERR(task)) + err = PTR_ERR(task); + else + info->task = task; + + return err; +} + +int nthread_stop(struct iscsi_target *target) +{ + int err; + struct network_thread_info *info = &target->nthread_info; + + if (!info->task) + return -ESRCH; + + err = kthread_stop(info->task); + + if (err < 0 && err != -EINTR) + return err; + + info->task = NULL; + + return 0; +} --- linux-2.6.37.orig/ubuntu/iscsitarget/null-io.c +++ linux-2.6.37/ubuntu/iscsitarget/null-io.c @@ -0,0 +1,98 @@ +/* + * Target device null I/O. + * (C) 2005 MING Zhang + * This code is licenced under the GPL. + * + * The nullio mode will not return any meaningful or previous written + * data. It is only for performance measurement purpose. + */ + +#include +#include +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +enum { + opt_blk_cnt, opt_ignore, opt_err, +}; + +static match_table_t tokens = { + /* alias for compatibility with existing setups and documentation */ + {opt_blk_cnt, "sectors=%u"}, + /* but actually it is the scsi block count, now that we can + * specify the block size. */ + {opt_blk_cnt, "blocks=%u"}, + {opt_ignore, "scsiid=%s"}, + {opt_ignore, "scsisn=%s"}, + {opt_ignore, "blocksize=%s"}, + {opt_ignore, "type=%s"}, + {opt_err, NULL}, +}; + +static int parse_nullio_params(struct iet_volume *volume, char *params) +{ + int err = 0; + char *p, *q; + + while ((p = strsep(¶ms, ",")) != NULL) { + substring_t args[MAX_OPT_ARGS]; + int token; + if (!*p) + continue; + iet_strtolower(p); + token = match_token(p, tokens, args); + switch (token) { + case opt_blk_cnt: + q = match_strdup(&args[0]); + if (!q) + return -ENOMEM; + volume->blk_cnt = simple_strtoull(q, NULL, 10); + kfree(q); + break; + case opt_ignore: + break; + default: + eprintk("Unknown %s\n", p); + return -EINVAL; + break; + } + } + return err; +} + +static void nullio_detach(struct iet_volume *lu) +{ +} + +static int nullio_attach(struct iet_volume *lu, char *args) +{ + int err = 0; + + if ((err = parse_nullio_params(lu, args)) < 0) { + eprintk("%d\n", err); + goto out; + } + + if (!lu->blk_shift) + lu->blk_shift = blksize_bits(IET_DEF_BLOCK_SIZE); + + /* defaults to 64 GiB */ + if (!lu->blk_cnt) + lu->blk_cnt = 1 << (36 - lu->blk_shift); + +out: + if (err < 0) + nullio_detach(lu); + return err; +} + +struct iotype nullio = +{ + .name = "nullio", + .attach = nullio_attach, + .detach = nullio_detach, +}; --- linux-2.6.37.orig/ubuntu/iscsitarget/param.c +++ linux-2.6.37/ubuntu/iscsitarget/param.c @@ -0,0 +1,205 @@ +/* + * (C) 2005 FUJITA Tomonori + * + * This code is licenced under the GPL. + */ + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "digest.h" + +struct target_type *target_type_array[] = { + &disk_ops, +}; + +#define CHECK_PARAM(info, iparam, word, min, max) \ +do { \ + if (!info->partial || (info->partial & 1 << key_##word)) \ + if (iparam[key_##word] < min || \ + iparam[key_##word] > max) { \ + eprintk("%s: %u is out of range (%u %u)\n", \ + #word, iparam[key_##word], min, max); \ + iparam[key_##word] = min; \ + } \ +} while (0) + +#define SET_PARAM(param, info, iparam, word) \ +({ \ + int changed = 0; \ + if (!info->partial || (info->partial & 1 << key_##word)) { \ + if (param->word != iparam[key_##word]) \ + changed = 1; \ + param->word = iparam[key_##word]; \ + } \ + changed; \ +}) + +#define GET_PARAM(param, info, iparam, word) \ +do { \ + iparam[key_##word] = param->word; \ +} while (0) + +static void sess_param_check(struct iscsi_param_info *info) +{ + u32 *iparam = info->session_param; + + CHECK_PARAM(info, iparam, max_connections, 1, 65535); + CHECK_PARAM(info, iparam, max_recv_data_length, 512, + (u32) ((ISCSI_CONN_IOV_MAX - 1) * PAGE_CACHE_SIZE)); + CHECK_PARAM(info, iparam, max_xmit_data_length, 512, + (u32) ((ISCSI_CONN_IOV_MAX - 1) * PAGE_CACHE_SIZE)); + CHECK_PARAM(info, iparam, error_recovery_level, 0, 0); + CHECK_PARAM(info, iparam, data_pdu_inorder, 1, 1); + CHECK_PARAM(info, iparam, data_sequence_inorder, 1, 1); + + digest_alg_available(&iparam[key_header_digest]); + digest_alg_available(&iparam[key_data_digest]); + + CHECK_PARAM(info, iparam, ofmarker, 0, 0); + CHECK_PARAM(info, iparam, ifmarker, 0, 0); +} + +static void sess_param_set(struct iscsi_sess_param *param, struct iscsi_param_info *info) +{ + u32 *iparam = info->session_param; + + SET_PARAM(param, info, iparam, initial_r2t); + SET_PARAM(param, info, iparam, immediate_data); + SET_PARAM(param, info, iparam, max_connections); + SET_PARAM(param, info, iparam, max_recv_data_length); + SET_PARAM(param, info, iparam, max_xmit_data_length); + SET_PARAM(param, info, iparam, max_burst_length); + SET_PARAM(param, info, iparam, first_burst_length); + SET_PARAM(param, info, iparam, default_wait_time); + SET_PARAM(param, info, iparam, default_retain_time); + SET_PARAM(param, info, iparam, max_outstanding_r2t); + SET_PARAM(param, info, iparam, data_pdu_inorder); + SET_PARAM(param, info, iparam, data_sequence_inorder); + SET_PARAM(param, info, iparam, error_recovery_level); + SET_PARAM(param, info, iparam, header_digest); + SET_PARAM(param, info, iparam, data_digest); + SET_PARAM(param, info, iparam, ofmarker); + SET_PARAM(param, info, iparam, ifmarker); + SET_PARAM(param, info, iparam, ofmarkint); + SET_PARAM(param, info, iparam, ifmarkint); +} + +static void sess_param_get(struct iscsi_sess_param *param, struct iscsi_param_info *info) +{ + u32 *iparam = info->session_param; + + GET_PARAM(param, info, iparam, initial_r2t); + GET_PARAM(param, info, iparam, immediate_data); + GET_PARAM(param, info, iparam, max_connections); + GET_PARAM(param, info, iparam, max_recv_data_length); + GET_PARAM(param, info, iparam, max_xmit_data_length); + GET_PARAM(param, info, iparam, max_burst_length); + GET_PARAM(param, info, iparam, first_burst_length); + GET_PARAM(param, info, iparam, default_wait_time); + GET_PARAM(param, info, iparam, default_retain_time); + GET_PARAM(param, info, iparam, max_outstanding_r2t); + GET_PARAM(param, info, iparam, data_pdu_inorder); + GET_PARAM(param, info, iparam, data_sequence_inorder); + GET_PARAM(param, info, iparam, error_recovery_level); + GET_PARAM(param, info, iparam, header_digest); + GET_PARAM(param, info, iparam, data_digest); + GET_PARAM(param, info, iparam, ofmarker); + GET_PARAM(param, info, iparam, ifmarker); + GET_PARAM(param, info, iparam, ofmarkint); + GET_PARAM(param, info, iparam, ifmarkint); +} + +static void trgt_param_check(struct iscsi_param_info *info) +{ + u32 *iparam = info->target_param; + + CHECK_PARAM(info, iparam, wthreads, MIN_NR_WTHREADS, MAX_NR_WTHREADS); + CHECK_PARAM(info, iparam, target_type, 0, + (unsigned int) ARRAY_SIZE(target_type_array) - 1); + CHECK_PARAM(info, iparam, queued_cmnds, MIN_NR_QUEUED_CMNDS, + MAX_NR_QUEUED_CMNDS); + CHECK_PARAM(info, iparam, nop_interval, MIN_NOP_INTERVAL, + MAX_NOP_INTERVAL); + CHECK_PARAM(info, iparam, nop_timeout, MIN_NOP_TIMEOUT, + MAX_NOP_TIMEOUT); +} + +static void trgt_param_set(struct iscsi_target *target, struct iscsi_param_info *info) +{ + struct iscsi_trgt_param *param = &target->trgt_param; + u32 *iparam = info->target_param; + + if (!worker_thread_pool && + SET_PARAM(param, info, iparam, wthreads)) + wthread_start(target->wthread_info, + target->trgt_param.wthreads, target->tid); + SET_PARAM(param, info, iparam, target_type); + SET_PARAM(param, info, iparam, queued_cmnds); + SET_PARAM(param, info, iparam, nop_interval); + SET_PARAM(param, info, iparam, nop_timeout); +} + +static void trgt_param_get(struct iscsi_trgt_param *param, struct iscsi_param_info *info) +{ + u32 *iparam = info->target_param; + + GET_PARAM(param, info, iparam, wthreads); + GET_PARAM(param, info, iparam, target_type); + GET_PARAM(param, info, iparam, queued_cmnds); + GET_PARAM(param, info, iparam, nop_interval); + GET_PARAM(param, info, iparam, nop_timeout); +} + +static int trgt_param(struct iscsi_target *target, struct iscsi_param_info *info, int set) +{ + + if (set) { + trgt_param_check(info); + trgt_param_set(target, info); + } else + trgt_param_get(&target->trgt_param, info); + + return 0; +} + +static int sess_param(struct iscsi_target *target, struct iscsi_param_info *info, int set) +{ + struct iscsi_session *session = NULL; + struct iscsi_sess_param *param; + int err = -ENOENT; + + if (set) + sess_param_check(info); + + if (info->sid) { + if (!(session = session_lookup(target, info->sid))) + goto out; + param = &session->param; + } else { + param = &target->sess_param; + } + + if (set) { + sess_param_set(param, info); + show_param(param); + } else + sess_param_get(param, info); + + err = 0; +out: + return err; +} + +int iscsi_param_set(struct iscsi_target *target, struct iscsi_param_info *info, int set) +{ + int err; + + if (info->param_type == key_session) + err = sess_param(target, info, set); + else if (info->param_type == key_target) + err = trgt_param(target, info, set); + else + err = -EINVAL; + + return err; +} --- linux-2.6.37.orig/ubuntu/iscsitarget/session.c +++ linux-2.6.37/ubuntu/iscsitarget/session.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include "iscsi.h" +#include "iscsi_dbg.h" + +struct iscsi_session *session_lookup(struct iscsi_target *target, u64 sid) +{ + struct iscsi_session *session; + + list_for_each_entry(session, &target->session_list, list) { + if (session->sid == sid) + return session; + } + return NULL; +} + +static struct iscsi_session * +iet_session_alloc(struct iscsi_target *target, struct session_info *info) +{ + int i; + struct iscsi_session *session; + struct iet_volume *vol; + + dprintk(D_SETUP, "%p %u %#Lx\n", target, target->tid, + (unsigned long long) info->sid); + + session = kzalloc(sizeof(*session), GFP_KERNEL); + if (!session) + return NULL; + + session->target = target; + session->sid = info->sid; + memcpy(&session->param, &target->sess_param, sizeof(session->param)); + session->max_queued_cmnds = target->trgt_param.queued_cmnds; + + session->exp_cmd_sn = info->exp_cmd_sn; + session->max_cmd_sn = info->max_cmd_sn; + + session->initiator = kstrdup(info->initiator_name, GFP_KERNEL); + if (!session->initiator) { + kfree(session); + return NULL; + } + + INIT_LIST_HEAD(&session->conn_list); + INIT_LIST_HEAD(&session->pending_list); + + spin_lock_init(&session->cmnd_hash_lock); + for (i = 0; i < ARRAY_SIZE(session->cmnd_hash); i++) + INIT_LIST_HEAD(&session->cmnd_hash[i]); + + spin_lock_init(&session->ua_hash_lock); + for (i = 0; i < ARRAY_SIZE(session->ua_hash); i++) + INIT_LIST_HEAD(&session->ua_hash[i]); + + list_for_each_entry(vol, &target->volumes, list) + /* power-on, reset, or bus device reset occurred */ + ua_establish_for_session(session, vol->lun, 0x29, 0x0); + + session->next_ttt = 1; + + spin_lock(&target->session_list_lock); + list_add(&session->list, &target->session_list); + spin_unlock(&target->session_list_lock); + + return session; +} + +static int session_free(struct iscsi_session *session) +{ + int i; + struct ua_entry *ua, *tmp; + struct list_head *l; + struct iscsi_target *target = session->target; + + dprintk(D_SETUP, "%#Lx\n", (unsigned long long) session->sid); + + spin_lock(&target->session_list_lock); + + assert(list_empty(&session->conn_list)); + + for (i = 0; i < ARRAY_SIZE(session->cmnd_hash); i++) { + if (!list_empty(&session->cmnd_hash[i])) + BUG(); + } + + for (i = 0; i < ARRAY_SIZE(session->ua_hash); i++) { + l = &session->ua_hash[i]; + list_for_each_entry_safe(ua, tmp, l, entry) { + list_del_init(&ua->entry); + ua_free(ua); + } + } + + list_del(&session->list); + + kfree(session->initiator); + kfree(session); + + spin_unlock(&target->session_list_lock); + + return 0; +} + +int session_add(struct iscsi_target *target, struct session_info *info) +{ + struct iscsi_session *session; + + session = session_lookup(target, info->sid); + if (session) + return -EEXIST; + + session = iet_session_alloc(target, info); + if (!session) + return -ENOMEM; + + return 0; +} + +int session_del(struct iscsi_target *target, u64 sid) +{ + struct iscsi_session *session; + struct iet_volume *volume; + + session = session_lookup(target, sid); + if (!session) + return -ENOENT; + + if (!list_empty(&session->conn_list)) { + DECLARE_COMPLETION_ONSTACK(done); + struct iscsi_conn *conn; + + session->done = &done; + list_for_each_entry(conn, &session->conn_list, list) + conn_close(conn); + + target_unlock(target); + wait_for_completion(&done); + target_lock(target, 0); + } + + list_for_each_entry(volume, &target->volumes, list){ + volume_release(volume, sid, 0); + } + + return session_free(session); +} + +static void iet_session_info_show(struct seq_file *seq, struct iscsi_target *target) +{ + struct iscsi_session *session; + + list_for_each_entry(session, &target->session_list, list) { + seq_printf(seq, "\tsid:%llu initiator:%s\n", + (unsigned long long) session->sid, session->initiator); + conn_info_show(seq, session); + } +} + +static int iet_session_seq_open(struct inode *inode, struct file *file) +{ + int res; + res = seq_open(file, &iet_seq_op); + if (!res) + ((struct seq_file *)file->private_data)->private = + iet_session_info_show; + return res; +} + +struct file_operations session_seq_fops = { + .owner = THIS_MODULE, + .open = iet_session_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; --- linux-2.6.37.orig/ubuntu/iscsitarget/target.c +++ linux-2.6.37/ubuntu/iscsitarget/target.c @@ -0,0 +1,374 @@ +/* + * Copyright (C) 2002-2003 Ardis Technolgies + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include "iscsi.h" +#include "digest.h" +#include "iscsi_dbg.h" + +#define MAX_NR_TARGETS (1UL << 30) + +static LIST_HEAD(target_list); +static DEFINE_SEMAPHORE(target_list_sem); +static u32 next_target_id; +static u32 nr_targets; + +static struct iscsi_sess_param default_session_param = { + .initial_r2t = 1, + .immediate_data = 1, + .max_connections = 1, + .max_recv_data_length = 8192, + .max_xmit_data_length = 8192, + .max_burst_length = 262144, + .first_burst_length = 65536, + .default_wait_time = 2, + .default_retain_time = 20, + .max_outstanding_r2t = 1, + .data_pdu_inorder = 1, + .data_sequence_inorder = 1, + .error_recovery_level = 0, + .header_digest = DIGEST_NONE, + .data_digest = DIGEST_NONE, + .ofmarker = 0, + .ifmarker = 0, + .ofmarkint = 2048, + .ifmarkint = 2048, +}; + +static struct iscsi_trgt_param default_target_param = { + .wthreads = DEFAULT_NR_WTHREADS, + .target_type = 0, + .queued_cmnds = DEFAULT_NR_QUEUED_CMNDS, +}; + +inline int target_lock(struct iscsi_target *target, int interruptible) +{ + int err = 0; + + if (interruptible) + err = down_interruptible(&target->target_sem); + else + down(&target->target_sem); + + return err; +} + +inline void target_unlock(struct iscsi_target *target) +{ + up(&target->target_sem); +} + +static struct iscsi_target *__target_lookup_by_id(u32 id) +{ + struct iscsi_target *target; + + list_for_each_entry(target, &target_list, t_list) { + if (target->tid == id) + return target; + } + return NULL; +} + +static struct iscsi_target *__target_lookup_by_name(char *name) +{ + struct iscsi_target *target; + + list_for_each_entry(target, &target_list, t_list) { + if (!strcmp(target->name, name)) + return target; + } + return NULL; +} + +struct iscsi_target *target_lookup_by_id(u32 id) +{ + struct iscsi_target *target; + + down(&target_list_sem); + target = __target_lookup_by_id(id); + up(&target_list_sem); + + return target; +} + +static int target_thread_start(struct iscsi_target *target) +{ + int err; + + if ((err = nthread_start(target)) < 0) + return err; + + if (!worker_thread_pool) { + err = wthread_start(target->wthread_info, + target->trgt_param.wthreads, target->tid); + if (err) + nthread_stop(target); + } + + return err; +} + +static void target_thread_stop(struct iscsi_target *target) +{ + if (!worker_thread_pool) + wthread_stop(target->wthread_info); + + nthread_stop(target); +} + +static int iscsi_target_create(struct target_info *info, u32 tid) +{ + int err = -EINVAL, len; + char *name = info->name; + struct iscsi_target *target; + + dprintk(D_SETUP, "%u %s\n", tid, name); + + if (!(len = strlen(name))) { + eprintk("The length of the target name is zero %u\n", tid); + return err; + } + + if (!try_module_get(THIS_MODULE)) { + eprintk("Fail to get module %u\n", tid); + return err; + } + + target = kzalloc(sizeof(*target), GFP_KERNEL); + if (!target) { + err = -ENOMEM; + goto out; + } + + if (!worker_thread_pool) { + target->wthread_info = kmalloc(sizeof(struct worker_thread_info), GFP_KERNEL); + if (!target->wthread_info) { + err = -ENOMEM; + goto out; + } + } + + target->tid = info->tid = tid; + + memcpy(&target->sess_param, &default_session_param, sizeof(default_session_param)); + memcpy(&target->trgt_param, &default_target_param, sizeof(default_target_param)); + + strncpy(target->name, name, sizeof(target->name) - 1); + + sema_init(&target->target_sem, 1); + spin_lock_init(&target->session_list_lock); + + INIT_LIST_HEAD(&target->session_list); + INIT_LIST_HEAD(&target->volumes); + + atomic_set(&target->nr_volumes, 0); + + nthread_init(target); + + if (!worker_thread_pool) + wthread_init(target->wthread_info); + else + target->wthread_info = worker_thread_pool; + + + if ((err = target_thread_start(target)) < 0) { + target_thread_stop(target); + goto out; + } + + list_add(&target->t_list, &target_list); + + return 0; +out: + if (!worker_thread_pool) + kfree(target->wthread_info); + kfree(target); + module_put(THIS_MODULE); + + return err; +} + +int target_add(struct target_info *info) +{ + u32 tid = info->tid; + int err; + + err = down_interruptible(&target_list_sem); + if (err < 0) + return err; + + if (nr_targets > MAX_NR_TARGETS) { + err = -EBUSY; + goto out; + } + + if (__target_lookup_by_name(info->name) || + (tid && __target_lookup_by_id(tid))) { + err = -EEXIST; + goto out; + } + + if (!tid) { + do { + if (!++next_target_id) + ++next_target_id; + } while (__target_lookup_by_id(next_target_id)); + + tid = next_target_id; + } + + err = iscsi_target_create(info, tid); + if (!err) + nr_targets++; +out: + up(&target_list_sem); + + return err; +} + +static void target_destroy(struct iscsi_target *target) +{ + dprintk(D_SETUP, "%u\n", target->tid); + + target_thread_stop(target); + + while (!list_empty(&target->volumes)) { + struct iet_volume *volume; + volume = list_entry(target->volumes.next, struct iet_volume, list); + volume->l_state = IDEV_DEL; + iscsi_volume_destroy(volume); + } + + if (!worker_thread_pool) + kfree(target->wthread_info); + kfree(target); + + module_put(THIS_MODULE); +} + +/* @locking: target_list_sem must be locked */ +static int __target_del(struct iscsi_target *target) +{ + int err; + + target_lock(target, 0); + + if (!list_empty(&target->session_list)) { + struct iscsi_session *session; + + do { + session = list_entry(target->session_list.next, + struct iscsi_session, list); + err = session_del(target, session->sid); + if (err < 0) { + target_unlock(target); + return err; + } + } while (!list_empty(&target->session_list)); + } + + list_del(&target->t_list); + nr_targets--; + + target_unlock(target); + target_destroy(target); + + return 0; +} + +int target_del(u32 id) +{ + struct iscsi_target *target; + int err; + + err = down_interruptible(&target_list_sem); + if (err < 0) + return err; + + target = __target_lookup_by_id(id); + if (!target) { + err = -ENOENT; + goto out; + } + + err = __target_del(target); +out: + up(&target_list_sem); + + return err; +} + +void target_del_all(void) +{ + struct iscsi_target *target, *tmp; + int err; + + down(&target_list_sem); + + if (!list_empty(&target_list)) + iprintk("Removing all connections, sessions and targets\n"); + + list_for_each_entry_safe(target, tmp, &target_list, t_list) { + u32 tid = target->tid; + err =__target_del(target); + if (err) + eprintk("Error deleteing target %u: %d\n", tid, err); + } + + next_target_id = 0; + + up(&target_list_sem); +} + +static void *iet_seq_start(struct seq_file *m, loff_t *pos) +{ + int err; + + /* are you sure this is to be interruptible? */ + err = down_interruptible(&target_list_sem); + if (err < 0) + return ERR_PTR(err); + + return seq_list_start(&target_list, *pos); +} + +static void *iet_seq_next(struct seq_file *m, void *v, loff_t *pos) +{ + return seq_list_next(v, &target_list, pos); +} + +static void iet_seq_stop(struct seq_file *m, void *v) +{ + up(&target_list_sem); +} + +static int iet_seq_show(struct seq_file *m, void *p) +{ + iet_show_info_t *func = (iet_show_info_t *)m->private; + struct iscsi_target *target = + list_entry(p, struct iscsi_target, t_list); + int err; + + /* relly, interruptible? I'd think target_lock(target, 0) + * would be more appropriate. --lge */ + err = target_lock(target, 1); + if (err < 0) + return err; + + seq_printf(m, "tid:%u name:%s\n", target->tid, target->name); + + func(m, target); + + target_unlock(target); + + return 0; +} + +struct seq_operations iet_seq_op = { + .start = iet_seq_start, + .next = iet_seq_next, + .stop = iet_seq_stop, + .show = iet_seq_show, +}; --- linux-2.6.37.orig/ubuntu/iscsitarget/target_disk.c +++ linux-2.6.37/ubuntu/iscsitarget/target_disk.c @@ -0,0 +1,589 @@ +/* + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + * + * heavily based on code from kernel/iscsi.c: + * Copyright (C) 2002-2003 Ardis Technolgies , + * licensed under the terms of the GNU GPL v2.0, + */ + +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" + +static int insert_disconnect_pg(u8 *ptr) +{ + unsigned char disconnect_pg[] = {0x02, 0x0e, 0x80, 0x80, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + memcpy(ptr, disconnect_pg, sizeof(disconnect_pg)); + return sizeof(disconnect_pg); +} + +static int insert_caching_pg(u8 *ptr, int wcache, int rcache) +{ + unsigned char caching_pg[] = {0x08, 0x12, 0x10, 0x00, 0xff, 0xff, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}; + + memcpy(ptr, caching_pg, sizeof(caching_pg)); + if (wcache) + ptr[2] |= 0x04; /* set WCE bit if we're caching writes */ + if (!rcache) + ptr[2] |= 0x01; /* Read Cache Disable */ + + return sizeof(caching_pg); +} + +static int insert_ctrl_m_pg(u8 *ptr) +{ + unsigned char ctrl_m_pg[] = {0x0a, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x4b}; + + memcpy(ptr, ctrl_m_pg, sizeof(ctrl_m_pg)); + return sizeof(ctrl_m_pg); +} + +static int insert_iec_m_pg(u8 *ptr) +{ + unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00}; + + memcpy(ptr, iec_m_pg, sizeof(iec_m_pg)); + return sizeof(iec_m_pg); +} + +static int insert_format_m_pg(u8 *ptr, u32 sector_size) +{ + unsigned char format_m_pg[] = {0x03, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00}; + + memcpy(ptr, format_m_pg, sizeof(format_m_pg)); + ptr[12] = (sector_size >> 8) & 0xff; + ptr[13] = sector_size & 0xff; + return sizeof(format_m_pg); +} + +static int insert_geo_m_pg(u8 *ptr, u64 sec) +{ + unsigned char geo_m_pg[] = {0x04, 0x16, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00}; + u32 ncyl; + u32 n; + + /* assume 0xff heads, 15krpm. */ + memcpy(ptr, geo_m_pg, sizeof(geo_m_pg)); + ncyl = sec >> 14; /* 256 * 64 */ + memcpy(&n, ptr+1, sizeof(u32)); + n = n | cpu_to_be32(ncyl); + memcpy(ptr+1, &n, sizeof(u32)); + return sizeof(geo_m_pg); +} + +static void build_mode_sense_response(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + struct tio *tio = cmnd->tio; + u8 *data, *scb = req->scb; + int len = 4, err = 0; + u8 pcode; + + /* changeable parameter mode pages are unsupported */ + if ((scb[2] & 0xc0) >> 6 == 0x1) + goto set_sense; + + pcode = req->scb[2] & 0x3f; + + assert(!tio); + tio = cmnd->tio = tio_alloc(1); + data = page_address(tio->pvec[0]); + assert(data); + clear_page(data); + + if (LUReadonly(cmnd->lun)) + data[2] = 0x80; + + if ((scb[1] & 0x8)) + data[3] = 0; + else { + data[3] = 8; + len += 8; + *(u32 *)(data + 4) = (cmnd->lun->blk_cnt >> 32) ? + cpu_to_be32(0xffffffff) : cpu_to_be32(cmnd->lun->blk_cnt); + *(u32 *)(data + 8) = cpu_to_be32(1 << cmnd->lun->blk_shift); + } + + switch (pcode) { + case 0x0: + break; + case 0x2: + len += insert_disconnect_pg(data + len); + break; + case 0x3: + len += insert_format_m_pg(data + len, 1 << cmnd->lun->blk_shift); + break; + case 0x4: + len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt); + break; + case 0x8: + len += insert_caching_pg(data + len, LUWCache(cmnd->lun), + LURCache(cmnd->lun)); + break; + case 0xa: + len += insert_ctrl_m_pg(data + len); + break; + case 0x1c: + len += insert_iec_m_pg(data + len); + break; + case 0x3f: + len += insert_disconnect_pg(data + len); + len += insert_format_m_pg(data + len, 1 << cmnd->lun->blk_shift); + len += insert_geo_m_pg(data + len, cmnd->lun->blk_cnt); + len += insert_caching_pg(data + len, LUWCache(cmnd->lun), + LURCache(cmnd->lun)); + len += insert_ctrl_m_pg(data + len); + len += insert_iec_m_pg(data + len); + break; + default: + err = -1; + } + + if (!err) { + data[0] = len - 1; + tio_set(tio, len, 0); + return; + } + + tio_put(tio); + cmnd->tio = NULL; + set_sense: + /* Invalid Field In CDB */ + iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0); +} + +static void build_inquiry_response(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + struct tio *tio = cmnd->tio; + u8 *data; + u8 *scb = req->scb; + int err = -1; + + /* + * - CmdDt and EVPD both set or EVPD and Page Code set: illegal + * - CmdDt set: not supported + */ + if ((scb[1] & 0x3) > 0x1 || (!(scb[1] & 0x3) && scb[2])) + goto set_sense; + + assert(!tio); + tio = cmnd->tio = tio_alloc(1); + data = page_address(tio->pvec[0]); + assert(data); + clear_page(data); + + if (!(scb[1] & 0x3)) { + data[2] = 4; + data[3] = 0x52; + data[4] = 59; + data[7] = 0x02; + memset(data + 8, 0x20, 28); + memcpy(data + 8, + VENDOR_ID, min_t(size_t, strlen(VENDOR_ID), 8)); + memcpy(data + 16, + PRODUCT_ID, min_t(size_t, strlen(PRODUCT_ID), 16)); + memcpy(data + 32, + PRODUCT_REV, min_t(size_t, strlen(PRODUCT_REV), 4)); + data[58] = 0x03; + data[59] = 0x20; + data[60] = 0x09; + data[61] = 0x60; + data[62] = 0x03; + data[63] = 0x00; + tio_set(tio, 64, 0); + err = 0; + } else if (scb[1] & 0x1) { + /* EVPD bit set */ + if (scb[2] == 0x0) { + data[1] = 0x0; + data[3] = 3; + data[4] = 0x0; + data[5] = 0x80; + data[6] = 0x83; + tio_set(tio, 7, 0); + err = 0; + } else if (scb[2] == 0x80) { + u32 len = 4; + + if (cmnd->lun) { + if (strlen(cmnd->lun->scsi_sn) <= 16) + len = 16; + else + len = SCSI_SN_LEN; + } + + data[1] = 0x80; + data[3] = len; + memset(data + 4, 0x20, len); + if (cmnd->lun) { + size_t offset = len - + strlen(cmnd->lun->scsi_sn); + memcpy(data + 4 + offset, cmnd->lun->scsi_sn, + strlen(cmnd->lun->scsi_sn)); + } + tio_set(tio, len + 4, 0); + err = 0; + } else if (scb[2] == 0x83) { + u32 len = SCSI_ID_LEN + 8; + + data[1] = 0x83; + data[3] = len + 4; + data[4] = 0x1; + data[5] = 0x1; + data[7] = len; + if (cmnd->lun) { /* We need this ? */ + memset(data + 8, 0x00, 8); + memcpy(data + 8, VENDOR_ID, + min_t(size_t, strlen(VENDOR_ID), 8)); + memcpy(data + 16, cmnd->lun->scsi_id, + SCSI_ID_LEN); + } + tio_set(tio, len + 8, 0); + err = 0; + } + } + + if (!err) { + tio_set(tio, min_t(u8, tio->size, scb[4]), 0); + if (!cmnd->lun) + data[0] = TYPE_NO_LUN; + return; + } + + tio_put(tio); + cmnd->tio = NULL; + set_sense: + /* Invalid Field In CDB */ + iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0); +} + +static void build_report_luns_response(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + struct tio *tio = cmnd->tio; + u32 *data, size, len; + struct iet_volume *lun; + int rest, idx = 0; + + size = (u32)req->scb[6] << 24 | (u32)req->scb[7] << 16 | + (u32)req->scb[8] << 8 | (u32)req->scb[9]; + if (size < 16) { + /* Invalid Field In CDB */ + iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0); + return; + } + + len = atomic_read(&cmnd->conn->session->target->nr_volumes) * 8; + size = min(size & ~(8 - 1), len + 8); + + assert(!tio); + tio = cmnd->tio = tio_alloc(get_pgcnt(size, 0)); + tio_set(tio, size, 0); + + data = page_address(tio->pvec[idx]); + assert(data); + *data++ = cpu_to_be32(len); + *data++ = 0; + size -= 8; + rest = PAGE_CACHE_SIZE - 8; + list_for_each_entry(lun, &cmnd->conn->session->target->volumes, list) { + if (lun->l_state != IDEV_RUNNING) + continue; + + *data++ = cpu_to_be32((0x3ff & lun->lun) << 16 | + ((lun->lun > 0xff) ? (0x1 << 30) : 0)); + *data++ = 0; + if ((size -= 8) == 0) + break; + if ((rest -= 8) == 0) { + idx++; + data = page_address(tio->pvec[idx]); + rest = PAGE_CACHE_SIZE; + } + } +} + +static void build_read_capacity_response(struct iscsi_cmnd *cmnd) +{ + struct tio *tio = cmnd->tio; + u32 *data; + + assert(!tio); + tio = cmnd->tio = tio_alloc(1); + data = page_address(tio->pvec[0]); + assert(data); + clear_page(data); + + data[0] = (cmnd->lun->blk_cnt >> 32) ? + cpu_to_be32(0xffffffff) : cpu_to_be32(cmnd->lun->blk_cnt - 1); + data[1] = cpu_to_be32(1U << cmnd->lun->blk_shift); + + tio_set(tio, 8, 0); +} + +static void build_request_sense_response(struct iscsi_cmnd *cmnd) +{ + struct tio *tio = cmnd->tio; + u8 *data; + + assert(!tio); + tio = cmnd->tio = tio_alloc(1); + data = page_address(tio->pvec[0]); + assert(data); + memset(data, 0, 18); + data[0] = 0xf0; + data[1] = 0; + data[2] = NO_SENSE; + data[7] = 10; + tio_set(tio, 18, 0); +} + +static void build_service_action_in_response(struct iscsi_cmnd *cmnd) +{ + struct tio *tio = cmnd->tio; + u32 *data; + u64 *data64; + + assert(!tio); + + /* only READ_CAPACITY_16 service action is currently supported */ + if ((cmnd_hdr(cmnd)->scb[1] & 0x1F) != 0x10) { + /* Invalid Field In CDB */ + iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x24, 0x0); + return; + } + + tio = cmnd->tio = tio_alloc(1); + data = page_address(tio->pvec[0]); + assert(data); + clear_page(data); + data64 = (u64*) data; + data64[0] = cpu_to_be64(cmnd->lun->blk_cnt - 1); + data[2] = cpu_to_be32(1UL << cmnd->lun->blk_shift); + + tio_set(tio, 12, 0); +} + +static void build_read_response(struct iscsi_cmnd *cmnd) +{ + struct tio *tio = cmnd->tio; + + assert(tio); + assert(cmnd->lun); + + if (tio_read(cmnd->lun, tio)) + /* Medium Error/Unrecovered Read Error */ + iscsi_cmnd_set_sense(cmnd, MEDIUM_ERROR, 0x11, 0x0); +} + +static void build_write_response(struct iscsi_cmnd *cmnd) +{ + int err; + struct tio *tio = cmnd->tio; + + assert(tio); + assert(cmnd->lun); + + list_del_init(&cmnd->list); + err = tio_write(cmnd->lun, tio); + if (!err && !LUWCache(cmnd->lun)) + err = tio_sync(cmnd->lun, tio); + + if (err) + /* Medium Error/Write Fault */ + iscsi_cmnd_set_sense(cmnd, MEDIUM_ERROR, 0x03, 0x0); +} + +static void build_sync_cache_response(struct iscsi_cmnd *cmnd) +{ + assert(cmnd->lun); + if (tio_sync(cmnd->lun, NULL)) + /* Medium Error/Write Fault */ + iscsi_cmnd_set_sense(cmnd, MEDIUM_ERROR, 0x03, 0x0); +} + +static void build_generic_response(struct iscsi_cmnd *cmnd) +{ + return; +} + +static void build_reserve_response(struct iscsi_cmnd *cmnd) +{ + switch (volume_reserve(cmnd->lun, cmnd->conn->session->sid)) { + case -ENOENT: + /* Logical Unit Not Supported (?) */ + iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x25, 0x0); + break; + case -EBUSY: + cmnd->status = SAM_STAT_RESERVATION_CONFLICT; + break; + default: + break; + } +} + +static void build_release_response(struct iscsi_cmnd *cmnd) +{ + int ret = volume_release(cmnd->lun, + cmnd->conn->session->sid, 0); + switch (ret) { + case -ENOENT: + /* Logical Unit Not Supported (?) */ + iscsi_cmnd_set_sense(cmnd, ILLEGAL_REQUEST, 0x25, 0x0); + break; + case -EBUSY: + cmnd->status = SAM_STAT_RESERVATION_CONFLICT; + break; + default: + break; + } +} + +static void build_reservation_conflict_response(struct iscsi_cmnd *cmnd) +{ + cmnd->status = SAM_STAT_RESERVATION_CONFLICT; +} + +static int disk_check_ua(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + struct ua_entry *ua; + + if (cmnd->lun && ua_pending(cmnd->conn->session, cmnd->lun->lun)) { + switch(req->scb[0]){ + case INQUIRY: + case REQUEST_SENSE: + break; + case REPORT_LUNS: + ua = ua_get_match(cmnd->conn->session, + cmnd->lun->lun, + /* reported luns data has changed */ + 0x3f, 0x0e); + ua_free(ua); + break; + default: + ua = ua_get_first(cmnd->conn->session, cmnd->lun->lun); + iscsi_cmnd_set_sense(cmnd, UNIT_ATTENTION, ua->asc, + ua->ascq); + ua_free(ua); + send_scsi_rsp(cmnd, build_generic_response); + return 1; + } + } + return 0; +} + +static int disk_check_reservation(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + + int ret = is_volume_reserved(cmnd->lun, + cmnd->conn->session->sid); + if (ret == -EBUSY) { + switch (req->scb[0]) { + case INQUIRY: + case RELEASE: + case REPORT_LUNS: + case REQUEST_SENSE: + case READ_CAPACITY: + /* allowed commands when reserved */ + break; + case SERVICE_ACTION_IN: + if ((cmnd_hdr(cmnd)->scb[1] & 0x1F) == 0x10) + break; + /* fall through */ + default: + /* return reservation conflict for all others */ + send_scsi_rsp(cmnd, + build_reservation_conflict_response); + return 1; + } + } + + return 0; +} + +static int disk_execute_cmnd(struct iscsi_cmnd *cmnd) +{ + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + + req->opcode &= ISCSI_OPCODE_MASK; + + if (disk_check_ua(cmnd)) + return 0; + + if (disk_check_reservation(cmnd)) + return 0; + + switch (req->scb[0]) { + case INQUIRY: + send_data_rsp(cmnd, build_inquiry_response); + break; + case REPORT_LUNS: + send_data_rsp(cmnd, build_report_luns_response); + break; + case READ_CAPACITY: + send_data_rsp(cmnd, build_read_capacity_response); + break; + case MODE_SENSE: + send_data_rsp(cmnd, build_mode_sense_response); + break; + case REQUEST_SENSE: + send_data_rsp(cmnd, build_request_sense_response); + break; + case SERVICE_ACTION_IN: + send_data_rsp(cmnd, build_service_action_in_response); + break; + case READ_6: + case READ_10: + case READ_16: + send_data_rsp(cmnd, build_read_response); + break; + case WRITE_6: + case WRITE_10: + case WRITE_16: + case WRITE_VERIFY: + send_scsi_rsp(cmnd, build_write_response); + break; + case SYNCHRONIZE_CACHE: + send_scsi_rsp(cmnd, build_sync_cache_response); + break; + case RESERVE: + send_scsi_rsp(cmnd, build_reserve_response); + break; + case RELEASE: + send_scsi_rsp(cmnd, build_release_response); + break; + case START_STOP: + case TEST_UNIT_READY: + case VERIFY: + case VERIFY_16: + send_scsi_rsp(cmnd, build_generic_response); + break; + default: + eprintk("%s\n", "we should not come here!"); + break; + } + + return 0; +} + +struct target_type disk_ops = +{ + .id = 0, + .execute_cmnd = disk_execute_cmnd, +}; --- linux-2.6.37.orig/ubuntu/iscsitarget/tio.c +++ linux-2.6.37/ubuntu/iscsitarget/tio.c @@ -0,0 +1,121 @@ +/* + * Target I/O. + * (C) 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +static int tio_add_pages(struct tio *tio, int count) +{ + int i; + struct page *page; + + dprintk(D_GENERIC, "%p %d (%d)\n", tio, count, tio->pg_cnt); + + tio->pg_cnt = count; + + count *= sizeof(struct page *); + + do { + tio->pvec = kzalloc(count, GFP_KERNEL); + if (!tio->pvec) + yield(); + } while (!tio->pvec); + + for (i = 0; i < tio->pg_cnt; i++) { + do { + if (!(page = alloc_page(GFP_KERNEL))) + yield(); + } while (!page); + tio->pvec[i] = page; + } + return 0; +} + +static struct kmem_cache *tio_cache; + +struct tio *tio_alloc(int count) +{ + struct tio *tio; + + tio = kmem_cache_alloc(tio_cache, GFP_KERNEL | __GFP_NOFAIL); + + tio->pg_cnt = 0; + tio->idx = 0; + tio->offset = 0; + tio->size = 0; + tio->pvec = NULL; + + atomic_set(&tio->count, 1); + + if (count) + tio_add_pages(tio, count); + + return tio; +} + +static void tio_free(struct tio *tio) +{ + int i; + for (i = 0; i < tio->pg_cnt; i++) { + assert(tio->pvec[i]); + __free_page(tio->pvec[i]); + } + kfree(tio->pvec); + kmem_cache_free(tio_cache, tio); +} + +void tio_put(struct tio *tio) +{ + assert(atomic_read(&tio->count)); + if (atomic_dec_and_test(&tio->count)) + tio_free(tio); +} + +void tio_get(struct tio *tio) +{ + atomic_inc(&tio->count); +} + +void tio_set(struct tio *tio, u32 size, loff_t offset) +{ + tio->idx = offset >> PAGE_CACHE_SHIFT; + tio->offset = offset & ~PAGE_CACHE_MASK; + tio->size = size; +} + +int tio_read(struct iet_volume *lu, struct tio *tio) +{ + struct iotype *iot = lu->iotype; + assert(iot); + return iot->make_request ? iot->make_request(lu, tio, READ) : 0; +} + +int tio_write(struct iet_volume *lu, struct tio *tio) +{ + struct iotype *iot = lu->iotype; + assert(iot); + return iot->make_request ? iot->make_request(lu, tio, WRITE) : 0; +} + +int tio_sync(struct iet_volume *lu, struct tio *tio) +{ + struct iotype *iot = lu->iotype; + assert(iot); + return iot->sync ? iot->sync(lu, tio) : 0; +} + +int tio_init(void) +{ + tio_cache = KMEM_CACHE(tio, 0); + return tio_cache ? 0 : -ENOMEM; +} + +void tio_exit(void) +{ + if (tio_cache) + kmem_cache_destroy(tio_cache); +} --- linux-2.6.37.orig/ubuntu/iscsitarget/ua.c +++ linux-2.6.37/ubuntu/iscsitarget/ua.c @@ -0,0 +1,176 @@ +/* + * IET Unit Attention support + * + * Copyright (C) 2009 Xie Gang + * Copyright (C) 2009 Arne Redlich + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" + +#define ua_hashfn(lun) ((lun % UA_HASH_LEN)) + +static struct kmem_cache *ua_cache; + +int ua_init(void) +{ + ua_cache = KMEM_CACHE(ua_entry, 0); + if (!ua_cache) { + eprintk("%s", "Failed to create ua cache\n"); + return -ENOMEM; + } + + return 0; +} + +void ua_exit(void) +{ + if (ua_cache) + kmem_cache_destroy(ua_cache); +} + +/* sess->ua_hash_lock needs to be held */ +static struct ua_entry * ua_find_hash(struct iscsi_session *sess, u32 lun, + u8 asc, u8 ascq, int match) +{ + struct ua_entry *ua; + struct list_head *h = &sess->ua_hash[ua_hashfn(lun)]; + + list_for_each_entry(ua, h, entry) { + if (ua->lun == lun) { + if (!match) + return ua; + if (ua->asc == asc && ua->ascq == ascq) + return ua; + } + } + + return NULL; +} + +int ua_pending(struct iscsi_session *sess, u32 lun) +{ + struct ua_entry *ua; + + spin_lock(&sess->ua_hash_lock); + ua = ua_find_hash(sess, lun, 0, 0, 0); + spin_unlock(&sess->ua_hash_lock); + + dprintk_ua(ua, sess, lun); + + return ua ? 1 : 0; +} + +/* sess->ua_hash_lock needs to be held */ +static struct ua_entry * __ua_get_hash(struct iscsi_session *sess, u32 lun, + u8 asc, u8 ascq, int match) +{ + struct ua_entry *ua = ua_find_hash(sess, lun, asc, ascq, match); + + if (ua) + list_del_init(&ua->entry); + + return ua; +} + +struct ua_entry * ua_get_first(struct iscsi_session *sess, u32 lun) +{ + struct ua_entry *ua; + + spin_lock(&sess->ua_hash_lock); + ua = __ua_get_hash(sess, lun, 0, 0, 0); + spin_unlock(&sess->ua_hash_lock); + + dprintk_ua(ua, sess, lun); + + return ua; +} + +struct ua_entry * ua_get_match(struct iscsi_session *sess, u32 lun, + u8 asc, u8 ascq) +{ + struct ua_entry *ua; + + spin_lock(&sess->ua_hash_lock); + ua = __ua_get_hash(sess, lun, asc, ascq, 1); + spin_unlock(&sess->ua_hash_lock); + + dprintk_ua(ua, sess, lun); + + return ua; +} + +void ua_establish_for_session(struct iscsi_session *sess, u32 lun, + u8 asc, u8 ascq) +{ + struct list_head *l = &sess->ua_hash[ua_hashfn(lun)]; + struct ua_entry *ua = kmem_cache_alloc(ua_cache, GFP_ATOMIC); + struct ua_entry *e; + + if (!ua) { + eprintk("%s", "Failed to alloc ua"); + return; + } + + ua->asc = asc; + ua->ascq = ascq; + ua->lun = lun; + ua->session = sess; + INIT_LIST_HEAD(&ua->entry); + + spin_lock(&sess->ua_hash_lock); + /* One UA per occurrence of an event */ + list_for_each_entry(e, l, entry) { + if (e->session == sess && e->lun == lun && + e->asc == asc && e->ascq == ascq && + e->session->exp_cmd_sn == sess->exp_cmd_sn) { + spin_unlock(&sess->ua_hash_lock); + ua_free(ua); + return; + } + } + list_add_tail(&ua->entry, l); + spin_unlock(&sess->ua_hash_lock); + + dprintk_ua(ua, sess, lun); +} + +void ua_establish_for_other_sessions(struct iscsi_session *sess, u32 lun, + u8 asc, u8 ascq) +{ + struct list_head *l = &sess->target->session_list; + struct iscsi_session *s; + + spin_lock(&sess->target->session_list_lock); + list_for_each_entry(s, l, list) + if (s->sid != sess->sid) + ua_establish_for_session(s, lun, asc, ascq); + spin_unlock(&sess->target->session_list_lock); +} + +void ua_establish_for_all_sessions(struct iscsi_target *target, u32 lun, + u8 asc, u8 ascq) +{ + struct list_head *l = &target->session_list; + struct iscsi_session *s; + + spin_lock(&target->session_list_lock); + list_for_each_entry(s, l, list) + ua_establish_for_session(s, lun, asc, ascq); + spin_unlock(&target->session_list_lock); + +} + +void ua_free(struct ua_entry *ua) +{ + if (!ua) + return; + + dprintk_ua(ua, ua->session, ua->lun); + BUG_ON(!list_empty(&ua->entry)); + kmem_cache_free(ua_cache, ua); +} --- linux-2.6.37.orig/ubuntu/iscsitarget/volume.c +++ linux-2.6.37/ubuntu/iscsitarget/volume.c @@ -0,0 +1,422 @@ +/* + * Volume manager + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" +#include "iotype.h" + +struct iet_volume *volume_lookup(struct iscsi_target *target, u32 lun) +{ + struct iet_volume *volume; + + list_for_each_entry(volume, &target->volumes, list) { + if (volume->lun == lun) + return volume; + } + return NULL; +} + +enum { + opt_type, + opt_iomode, + opt_scsiid, + opt_scsisn, + opt_blk_size, + opt_err, +}; + +static match_table_t tokens = { + {opt_type, "type=%s"}, + {opt_iomode, "iomode=%s"}, + {opt_scsiid, "scsiid=%s"}, + {opt_scsisn, "scsisn=%s"}, + {opt_blk_size, "blocksize=%u"}, + {opt_err, NULL}, +}; + +static int set_scsiid(struct iet_volume *volume, const char *id) +{ + size_t len; + + if ((len = strlen(id)) > SCSI_ID_LEN) { + eprintk("SCSI ID too long, %zd provided, %u max\n", len, + SCSI_ID_LEN); + return -EINVAL; + } + + memcpy(volume->scsi_id, id, len); + + return 0; +} + +static int set_scsisn(struct iet_volume *volume, const char *sn) +{ + size_t len; + int i; + + if ((len = strlen(sn)) > SCSI_SN_LEN) { + eprintk("SCSI SN too long, %zd provided, %u max\n", len, + SCSI_SN_LEN); + return -EINVAL; + } + + for (i = 0; i < len; i++) { + if (!isascii(*(sn + i)) || !isprint(*(sn + i))) { + eprintk("invalid characters in SCSI SN, %s\n", + "only printable ascii characters allowed!"); + return -EINVAL; + } + } + + memcpy(volume->scsi_sn, sn, len); + + return 0; +} + +/* Generate a MD5 hash of the target IQN and LUN number */ +static void gen_scsiid(struct iet_volume *volume) +{ + struct hash_desc hash; + + hash.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); + hash.flags = 0; + + if (hash.tfm) { + struct scatterlist sg[2]; + unsigned int nbytes = 0; + + sg_init_table(sg, 2); + + sg_set_buf(&sg[0], volume->target->name, + strlen(volume->target->name)); + nbytes += strlen(volume->target->name); + + sg_set_buf(&sg[1], &volume->lun, sizeof(volume->lun)); + nbytes += sizeof(volume->lun); + + crypto_hash_init(&hash); + crypto_hash_update(&hash, sg, nbytes); + crypto_hash_final(&hash, volume->scsi_id); + + crypto_free_hash(hash.tfm); + } else { + /* If no MD5 available set ID to TID and LUN */ + memcpy(volume->scsi_id, &volume->target->tid, + sizeof(volume->target->tid)); + memcpy(volume->scsi_id + sizeof(volume->target->tid), + &volume->lun, sizeof(volume->lun)); + } + +} + +static int parse_volume_params(struct iet_volume *volume, char *params) +{ + int err = 0; + unsigned blk_sz; + substring_t args[MAX_OPT_ARGS]; + char *p, *argp = NULL, *buf = (char *) get_zeroed_page(GFP_USER); + + if (!buf) + return -ENOMEM; + + strncpy(buf, params, PAGE_CACHE_SIZE); + + while ((p = strsep(&buf, ",")) != NULL) { + int token; + + if (!*p) + continue; + iet_strtolower(p); + token = match_token(p, tokens, args); + switch (token) { + case opt_type: + argp = match_strdup(&args[0]); + if (!argp) { + err = -ENOMEM; + break; + } + if (!(volume->iotype = get_iotype(argp))) + err = -ENOENT; + kfree(argp); + break; + case opt_iomode: + argp = match_strdup(&args[0]); + if (!argp) { + err = -ENOMEM; + break; + } + if (!strcmp(argp, "ro")) + SetLUReadonly(volume); + else if (!strcmp(argp, "wb")) + SetLUWCache(volume); + else if (strcmp(argp, "wt")) + err = -EINVAL; + kfree(argp); + break; + case opt_scsiid: + argp = match_strdup(&args[0]); + if (!argp) { + err = -ENOMEM; + break; + } + err = set_scsiid(volume, argp); + kfree(argp); + break; + case opt_scsisn: + argp = match_strdup(&args[0]); + if (!argp) { + err = -ENOMEM; + break; + } + err = set_scsisn(volume, argp); + kfree(argp); + break; + case opt_blk_size: + argp = match_strdup(&args[0]); + if (!argp) { + err = -ENOMEM; + break; + } + blk_sz = simple_strtoull(argp, NULL, 10); + if (is_power_of_2(blk_sz) && + 512 <= blk_sz && blk_sz <= IET_MAX_BLOCK_SIZE) + volume->blk_shift = blksize_bits(blk_sz); + else { + eprintk("invalid BlockSize=%u\n", blk_sz); + err = -EINVAL; + } + kfree(argp); + break; + default: + break; + } + } + + if (!err && !volume->iotype && !(volume->iotype = get_iotype("fileio"))) { + eprintk("%s\n", "Cannot find fileio"); + err = -EINVAL; + } + + free_page((unsigned long) buf); + + return err; +} + +int volume_add(struct iscsi_target *target, struct volume_info *info) +{ + int ret; + struct iet_volume *volume; + char *args; + + volume = volume_lookup(target, info->lun); + if (volume) + return -EEXIST; + + if (info->lun > 0x3fff) + return -EINVAL; + + volume = kzalloc(sizeof(*volume), GFP_KERNEL); + if (!volume) + return -ENOMEM; + + volume->target = target; + volume->lun = info->lun; + + args = kzalloc(info->args_len + 1, GFP_KERNEL); + if (!args) { + ret = -ENOMEM; + goto free_volume; + } + + ret = copy_from_user(args, (void *)(unsigned long)info->args_ptr, + info->args_len); + if (ret) { + ret = -EFAULT; + goto free_args; + } + + ret = parse_volume_params(volume, args); + if (ret < 0) + goto free_args; + + ret = volume->iotype->attach(volume, args); + if (ret < 0) + goto free_args; + + if (!volume->scsi_id[0]) + gen_scsiid(volume); + + if (!volume->scsi_sn[0]) { + int i; + + for (i = 0; i < SCSI_ID_LEN; i++) + snprintf(volume->scsi_sn + (i * 2), 3, "%02x", + volume->scsi_id[i]); + } + + INIT_LIST_HEAD(&volume->queue.wait_list); + spin_lock_init(&volume->queue.queue_lock); + spin_lock_init(&volume->reserve_lock); + + volume->l_state = IDEV_RUNNING; + atomic_set(&volume->l_count, 0); + + list_add_tail(&volume->list, &target->volumes); + atomic_inc(&target->nr_volumes); + + kfree(args); + + return 0; +free_args: + kfree(args); +free_volume: + put_iotype(volume->iotype); + kfree(volume); + + return ret; +} + +void iscsi_volume_destroy(struct iet_volume *volume) +{ + assert(volume->l_state == IDEV_DEL); + assert(!atomic_read(&volume->l_count)); + + volume->iotype->detach(volume); + put_iotype(volume->iotype); + list_del(&volume->list); + kfree(volume); +} + +int iscsi_volume_del(struct iscsi_target *target, struct volume_info *info) +{ + struct iet_volume *volume; + + eprintk("%x %x\n", target->tid, info->lun); + if (!(volume = volume_lookup(target, info->lun))) + return -ENOENT; + + volume->l_state = IDEV_DEL; + atomic_dec(&target->nr_volumes); + if (!atomic_read(&volume->l_count)) + iscsi_volume_destroy(volume); + + return 0; +} + +struct iet_volume *volume_get(struct iscsi_target *target, u32 lun) +{ + struct iet_volume *volume; + + if ((volume = volume_lookup(target, lun))) { + if (volume->l_state == IDEV_RUNNING) + atomic_inc(&volume->l_count); + else + volume = NULL; + } + return volume; +} + +void volume_put(struct iet_volume *volume) +{ + if (atomic_dec_and_test(&volume->l_count) && volume->l_state == IDEV_DEL) + iscsi_volume_destroy(volume); +} + +int volume_reserve(struct iet_volume *volume, u64 sid) +{ + int err = 0; + + if (!volume) + return -ENOENT; + + spin_lock(&volume->reserve_lock); + if (volume->reserve_sid && volume->reserve_sid != sid) + err = -EBUSY; + else + volume->reserve_sid = sid; + + spin_unlock(&volume->reserve_lock); + return err; +} + +int is_volume_reserved(struct iet_volume *volume, u64 sid) +{ + int err = 0; + + if (!volume) + return -ENOENT; + + spin_lock(&volume->reserve_lock); + if (!volume->reserve_sid || volume->reserve_sid == sid) + err = 0; + else + err = -EBUSY; + + spin_unlock(&volume->reserve_lock); + return err; +} + +int volume_release(struct iet_volume *volume, u64 sid, int force) +{ + int err = 0; + + if (!volume) + return -ENOENT; + + spin_lock(&volume->reserve_lock); + + if (force || volume->reserve_sid == sid) + volume->reserve_sid = 0; + else + err = -EBUSY; + + spin_unlock(&volume->reserve_lock); + return err; +} + +static void iet_volume_info_show(struct seq_file *seq, struct iscsi_target *target) +{ + struct iet_volume *volume; + + list_for_each_entry(volume, &target->volumes, list) { + seq_printf(seq, "\tlun:%u state:%x iotype:%s", + volume->lun, volume->l_state, volume->iotype->name); + if (LUReadonly(volume)) + seq_printf(seq, " iomode:ro"); + else if (LUWCache(volume)) + seq_printf(seq, " iomode:wb"); + else + seq_printf(seq, " iomode:wt"); + + seq_printf(seq, " blocks:%llu blocksize:%u", + volume->blk_cnt, 1 << volume->blk_shift); + if (volume->iotype->show) + volume->iotype->show(volume, seq); + else + seq_printf(seq, "\n"); + } +} + +static int iet_volume_seq_open(struct inode *inode, struct file *file) +{ + int res; + res = seq_open(file, &iet_seq_op); + if (!res) + ((struct seq_file *)file->private_data)->private = + iet_volume_info_show; + return res; +} + +struct file_operations volume_seq_fops = { + .owner = THIS_MODULE, + .open = iet_volume_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; --- linux-2.6.37.orig/ubuntu/iscsitarget/wthread.c +++ linux-2.6.37/ubuntu/iscsitarget/wthread.c @@ -0,0 +1,258 @@ +/* + * Worker thread. + * (C) 2004 - 2005 FUJITA Tomonori + * This code is licenced under the GPL. + */ + +#include + +#include "iscsi.h" +#include "iscsi_dbg.h" + +struct worker_thread_info *worker_thread_pool; + +void wthread_queue(struct iscsi_cmnd *cmnd) +{ + struct worker_thread_info *info = cmnd->conn->session->target->wthread_info; + + if (!list_empty(&cmnd->list)) { + struct iscsi_scsi_cmd_hdr *req = cmnd_hdr(cmnd); + eprintk("%x %p %x %x %x %x %lx %x\n", + cmnd_itt(cmnd), req, req->opcode, req->scb[0], cmnd->pdu.datasize, + be32_to_cpu(req->data_length), cmnd->flags, req->flags); + + if (cmnd->lun) + eprintk("%u\n", cmnd->lun->lun); + assert(list_empty(&cmnd->list)); + } + + spin_lock(&info->wthread_lock); + list_add_tail(&cmnd->list, &info->work_queue); + spin_unlock(&info->wthread_lock); + + atomic_inc(&cmnd->conn->nr_busy_cmnds); + + wake_up(&info->wthread_sleep); +} + +static struct iscsi_cmnd * get_ready_cmnd(struct worker_thread_info *info) +{ + struct iscsi_cmnd *cmnd = NULL; + + spin_lock(&info->wthread_lock); + if (!list_empty(&info->work_queue)) { + cmnd = list_entry(info->work_queue.next, struct iscsi_cmnd, list); + list_del_init(&cmnd->list); + + assert(cmnd->conn); + } + spin_unlock(&info->wthread_lock); + + return cmnd; +} + +static int cmnd_execute(struct iscsi_cmnd *cmnd) +{ + int type = cmnd->conn->session->target->trgt_param.target_type; + + assert(target_type_array[type]->execute_cmnd); + return target_type_array[type]->execute_cmnd(cmnd); +} + +static void copy_io_context(struct io_context **pdst, struct io_context **psrc) +{ + struct io_context *src = *psrc; + struct io_context *dst = *pdst; + + if (src) { + BUG_ON(atomic_long_read(&src->refcount) == 0); + atomic_long_inc(&src->refcount); + put_io_context(dst); + *pdst = src; + } +} + +static int worker_thread(void *arg) +{ + struct worker_thread *wt = (struct worker_thread *) arg; + struct worker_thread_info *info = wt->w_info; + struct iscsi_cmnd *cmnd; + struct iscsi_conn *conn; + DECLARE_WAITQUEUE(wait, current); + + get_io_context(GFP_KERNEL, -1); + + if (!current->io_context) + eprintk("%s\n", "Failed to get IO context"); + else if (info->wthread_ioc) + copy_io_context(¤t->io_context, &info->wthread_ioc); + else + info->wthread_ioc = current->io_context; + + add_wait_queue(&info->wthread_sleep, &wait); + + __set_current_state(TASK_RUNNING); + do { + while (!list_empty(&info->work_queue) && + (cmnd = get_ready_cmnd(info))) { + conn = cmnd->conn; + if (cmnd_tmfabort(cmnd)) + cmnd_release(cmnd, 1); + else + cmnd_execute(cmnd); + assert(conn); + atomic_dec(&conn->nr_busy_cmnds); + } + + set_current_state(TASK_INTERRUPTIBLE); + if (list_empty(&info->work_queue)) + schedule(); + + __set_current_state(TASK_RUNNING); + } while (!kthread_should_stop()); + + remove_wait_queue(&info->wthread_sleep, &wait); + + if (current->io_context) { + struct io_context *ioc = current->io_context; + + task_lock(current); + current->io_context = NULL; + task_unlock(current); + + put_io_context(ioc); + } + + return 0; +} + +static int start_one_worker_thread(struct worker_thread_info *info, u32 tid) +{ + struct worker_thread *wt; + struct task_struct *task; + + if (!(wt = kmalloc(sizeof(struct worker_thread), GFP_KERNEL))) + return -ENOMEM; + + wt->w_info = info; + task = kthread_create(worker_thread, wt, "istiod%d", tid); + if (IS_ERR(task)) { + kfree(wt); + return PTR_ERR(task); + } + + wt->w_task = task; + list_add(&wt->w_list, &info->wthread_list); + info->nr_running_wthreads++; + + wake_up_process(task); + + return 0; +} + +static int stop_one_worker_thread(struct worker_thread *wt) +{ + struct worker_thread_info *info = wt->w_info; + int err; + + assert(wt->w_task); + err = kthread_stop(wt->w_task); + + if (err < 0 && err != -EINTR) + return err; + + list_del(&wt->w_list); + kfree(wt); + info->nr_running_wthreads--; + + return 0; +} + +int wthread_init(struct worker_thread_info *info) +{ + spin_lock_init(&info->wthread_lock); + + info->nr_running_wthreads = 0; + info->wthread_ioc = NULL; + + INIT_LIST_HEAD(&info->work_queue); + INIT_LIST_HEAD(&info->wthread_list); + + init_waitqueue_head(&info->wthread_sleep); + + return 0; +} + +int wthread_start(struct worker_thread_info *info, int wthreads, u32 tid) +{ + int err = 0; + + while (info->nr_running_wthreads < wthreads) { + if ((err = start_one_worker_thread(info, tid)) < 0) { + eprintk("Fail to create a worker thread %d\n", err); + goto out; + } + } + + while (info->nr_running_wthreads > wthreads) { + struct worker_thread *wt; + wt = list_entry(info->wthread_list.next, struct worker_thread, w_list); + if ((err = stop_one_worker_thread(wt)) < 0) { + eprintk("Fail to stop a worker thread %d\n", err); + break; + } + } +out: + return err; +} + +int wthread_stop(struct worker_thread_info *info) +{ + struct worker_thread *wt, *tmp; + int err = 0; + + list_for_each_entry_safe(wt, tmp, &info->wthread_list, w_list) { + if ((err = stop_one_worker_thread(wt)) < 0) { + eprintk("Fail to stop a worker thread %d\n", err); + return err; + } + } + + return err; +} + +int wthread_module_init() +{ + int err; + + if (!worker_thread_pool_size) + return 0; + + worker_thread_pool = kmalloc(sizeof(struct worker_thread_info), + GFP_KERNEL); + if (!worker_thread_pool) + return -ENOMEM; + + wthread_init(worker_thread_pool); + + err = wthread_start(worker_thread_pool, worker_thread_pool_size, 0); + if (err) { + kfree(worker_thread_pool); + worker_thread_pool = NULL; + return err; + } + + iprintk("iscsi_trgt using worker thread pool; size = %ld\n", + worker_thread_pool_size); + + return 0; +} + +void wthread_module_exit() +{ + if (!worker_thread_pool_size) + return; + + wthread_stop(worker_thread_pool); + kfree(worker_thread_pool); +} --- linux-2.6.37.orig/ubuntu/iscsitarget/include/iet_u.h +++ linux-2.6.37/ubuntu/iscsitarget/include/iet_u.h @@ -0,0 +1,151 @@ +#ifndef _IET_U_H +#define _IET_U_H + +#define IET_VERSION_STRING "1.4.20.2" + +/* The maximum length of 223 bytes in the RFC. */ +#define ISCSI_NAME_LEN 256 +#define ISCSI_ARGS_LEN 2048 + +#define ISCSI_LISTEN_PORT 3260 + +#define SCSI_ID_LEN 16 +#define SCSI_SN_LEN (SCSI_ID_LEN * 2) + +#ifndef aligned_u64 +#define aligned_u64 unsigned long long __attribute__((aligned(8))) +#endif + +struct module_info { + char version[128]; +}; + +struct target_info { + u32 tid; + char name[ISCSI_NAME_LEN]; +}; + +struct volume_info { + u32 tid; + u32 lun; + aligned_u64 args_ptr; + u32 args_len; +}; + +struct session_info { + u32 tid; + + aligned_u64 sid; + char initiator_name[ISCSI_NAME_LEN]; + u32 exp_cmd_sn; + u32 max_cmd_sn; +}; + +#define DIGEST_ALL (DIGEST_NONE | DIGEST_CRC32C) +#define DIGEST_NONE (1 << 0) +#define DIGEST_CRC32C (1 << 1) + +struct conn_info { + u32 tid; + aligned_u64 sid; + + u32 cid; + u32 stat_sn; + u32 exp_stat_sn; + int header_digest; + int data_digest; + int fd; +}; + +enum { + key_initial_r2t, + key_immediate_data, + key_max_connections, + key_max_recv_data_length, + key_max_xmit_data_length, + key_max_burst_length, + key_first_burst_length, + key_default_wait_time, + key_default_retain_time, + key_max_outstanding_r2t, + key_data_pdu_inorder, + key_data_sequence_inorder, + key_error_recovery_level, + key_header_digest, + key_data_digest, + key_ofmarker, + key_ifmarker, + key_ofmarkint, + key_ifmarkint, + session_key_last, +}; + +enum { + key_wthreads, + key_target_type, + key_queued_cmnds, + key_nop_interval, + key_nop_timeout, + target_key_last, +}; + +enum { + key_session, + key_target, +}; + +struct iscsi_param_info { + u32 tid; + aligned_u64 sid; + + u32 param_type; + u32 partial; + + u32 session_param[session_key_last]; + u32 target_param[target_key_last]; +}; + +enum iet_event_state { + E_CONN_CLOSE, +}; + +struct iet_event { + u32 tid; + aligned_u64 sid; + u32 cid; + u32 state; +}; + +#define DEFAULT_NR_WTHREADS 8 +#define MIN_NR_WTHREADS 1 +#define MAX_NR_WTHREADS 128 + +#define DEFAULT_NR_QUEUED_CMNDS 32 +#define MIN_NR_QUEUED_CMNDS 1 +#define MAX_NR_QUEUED_CMNDS 256 + +#define DEFAULT_NOP_INTERVAL 0 +#define MIN_NOP_INTERVAL 0 +#define MAX_NOP_INTERVAL 90 + +#define DEFAULT_NOP_TIMEOUT 0 +#define MIN_NOP_TIMEOUT 0 +#define MAX_NOP_TIMEOUT 90 + +#define NETLINK_IET 21 + +#define GET_MODULE_INFO _IOW('i', 20, struct module_info) +#define ADD_TARGET _IOWR('i', 21, struct target_info) +#define DEL_TARGET _IOW('i', 22, struct target_info) +#define ADD_VOLUME _IOW('i', 24, struct volume_info) +#define DEL_VOLUME _IOW('i', 25, struct volume_info) +#define ADD_SESSION _IOW('i', 26, struct session_info) +#define DEL_SESSION _IOW('i', 27, struct session_info) +#define GET_SESSION_INFO _IOWR('i', 28, struct session_info) +#define ADD_CONN _IOW('i', 29, struct conn_info) +#define DEL_CONN _IOW('i', 30, struct conn_info) +#define GET_CONN_INFO _IOWR('i', 31, struct conn_info) +#define ISCSI_PARAM_SET _IOW('i', 32, struct iscsi_param_info) +#define ISCSI_PARAM_GET _IOWR('i', 33, struct iscsi_param_info) + +#endif --- linux-2.6.37.orig/ubuntu/ndiswrapper/BOM +++ linux-2.6.37/ubuntu/ndiswrapper/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://sourceforge.net/project/showfiles.php?group_id=93482 +Current Version: 1.56 --- linux-2.6.37.orig/ubuntu/ndiswrapper/Kconfig +++ linux-2.6.37/ubuntu/ndiswrapper/Kconfig @@ -0,0 +1,4 @@ +config NDISWRAPPER + tristate "Wrapper for Windows NDIS network drivers" + depends on NET && X86 + default m --- linux-2.6.37.orig/ubuntu/ndiswrapper/Makefile +++ linux-2.6.37/ubuntu/ndiswrapper/Makefile @@ -0,0 +1,38 @@ +ndiswrapper-objs := crt.o hal.o iw_ndis.o loader.o ndis.o ntoskernel.o ntoskernel_io.o \ + pe_linker.o pnp.o proc.o rtl.o wrapmem.o wrapndis.o wrapper.o usb.o + +EXPORTS = crt_exports.h hal_exports.h ndis_exports.h ntoskernel_exports.h \ + ntoskernel_io_exports.h rtl_exports.h usb_exports.h + +STUB_SRCS = crt.c hal.c ndis.c ntoskernel.c ntoskernel_io.c \ + pnp.c rtl.c wrapndis.c usb.c + + +EXTRA_CFLAGS += -DENABLE_USB -I$(obj) +EXTRA_AFLAGS += -I$(obj) + +# generate exports symbol table from C files +quiet_cmd_mkexport = MKEXPORT $@ +cmd_mkexport = $(SHELL) $(srctree)/$(src)/mkexport.sh $< $@ + +%_exports.h: %.c $(srctree)/$(src)/mkexport.sh FORCE + $(call if_changed,mkexport) + +$(addprefix $(obj)/,$(EXPORTS:_exports.h=.o)): %.o: %_exports.h +extra-y += $(EXPORTS) + +ifeq ($(CONFIG_X86_64),y) +quiet_cmd_mkstubs = MKSTUBS $@ +cmd_mkstubs = $(SHELL) $(srctree)/$(src)/mkstubs.sh $(addprefix $(srctree)/$(src)/,$(STUB_SRCS)) >$@ + +$(obj)/win2lin_stubs.h: $(addprefix $(srctree)/$(src)/,$(STUB_SRCS)) FORCE + $(call if_changed,mkstubs) + +$(obj)/win2lin_stubs.o: $(obj)/win2lin_stubs.h +extra-y += win2lin_stubs.h +ndiswrapper-objs += win2lin_stubs.o +else +ndiswrapper-objs += divdi3.o +endif + +obj-$(CONFIG_NDISWRAPPER) := ndiswrapper.o --- linux-2.6.37.orig/ubuntu/ndiswrapper/crt.c +++ linux-2.6.37/ubuntu/ndiswrapper/crt.c @@ -0,0 +1,578 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ + +#include "ntoskernel.h" +#include "crt_exports.h" + +#ifdef CONFIG_X86_64 +/* Windows long is 32-bit, so strip single 'l' in integer formats */ +static void strip_l_modifier(char *str) +{ + char *ptr = str; + int in_format = 0; + char *lptr = NULL; + char last = 0; + char *end_ptr; + char *wptr; + + /* Replace single 'l' inside integer formats with '\0' */ + for (ptr = str; *ptr; ptr++) { + if (!in_format) { + if (*ptr == '%') + in_format = 1; + last = *ptr; + continue; + } + switch (*ptr) { + case 'd': + case 'i': + case 'o': + case 'u': + case 'x': + case 'X': + case 'p': + case 'n': + case 'm': + if (lptr) { + *lptr = '\0'; + lptr = NULL; + } + in_format = 0; + break; + case 'c': + case 'C': + case 's': + case 'S': + case 'f': + case 'e': + case 'E': + case 'g': + case 'G': + case 'a': + case 'A': + lptr = NULL; + in_format = 0; + break; + case '%': + lptr = NULL; + if (last == '%') + in_format = 0; + else + in_format = 1; /* ignore previous junk */ + break; + case 'l': + if (last == 'l') + lptr = NULL; + else + lptr = ptr; + break; + default: + break; + } + last = *ptr; + } + + /* Purge zeroes from the resulting string */ + end_ptr = ptr; + wptr = str; + for (ptr = str; ptr < end_ptr; ptr++) + if (*ptr != 0) + *(wptr++) = *ptr; + *wptr = 0; +} + +/* + * va_list on x86_64 Linux is designed to allow passing arguments in registers + * even to variadic functions. va_list is a structure holding pointers to the + * register save area, which holds the arguments passed in registers, and to + * the stack, which may have the arguments that did not fit the registers. + * va_list also holds offsets in the register save area for the next general + * purpose and floating point registers that the next va_arg() would fetch. + * + * Unlike Linux, the Windows va_list is just a pointer to the stack. No + * arguments are passed in the registers. That's why we construct the Linux + * va_list so that the register save area is never used. For that goal, we set + * the offsets to the maximal allowed values, meaning that the arguments passed + * in the registers have been exhausted. The values are 48 for general purpose + * registers (6 registers, 8 bytes each) and 304 for floating point registers + * (16 registers, 16 bytes each, on top of general purpose register). + */ + +struct x86_64_va_list { + int gp_offset; + int fp_offset; + void *overflow_arg_area; + void *reg_save_area; +}; + +#define VA_LIST_DECL(_args) \ + va_list _args##new; \ + struct x86_64_va_list *_args##x; +#define VA_LIST_PREP(_args) \ +do { \ + _args##x = (struct x86_64_va_list *)&_args##new; \ + _args##x->gp_offset = 6 * 8; /* GP registers exhausted */ \ + _args##x->fp_offset = 6 * 8 + 16 * 16; /* FP registers exhausted */ \ + _args##x->overflow_arg_area = (void *)_args; \ + _args##x->reg_save_area = NULL; \ +} while (0) +#define VA_LIST_CONV(_args) (_args##new) +#define VA_LIST_FREE(_args) +#define FMT_DECL(_fmt) \ + char *_fmt##copy; \ + int _fmt##len; +#define FMT_PREP(_fmt) \ +do { \ + _fmt##len = strlen(format) + 1; \ + _fmt##copy = kmalloc(_fmt##len, GFP_KERNEL); \ + if (_fmt##copy) { \ + memcpy(_fmt##copy, format, _fmt##len); \ + strip_l_modifier(_fmt##copy); \ + } \ +} while (0) +#define FMT_CONV(_fmt) (_fmt##copy ? _fmt##copy : format) +#define FMT_FREE(_fmt) kfree(_fmt##copy) + +#else /* !CONFIG_X86_64 */ + +#define VA_LIST_DECL(_args) +#define VA_LIST_PREP(_args) +#define VA_LIST_CONV(_args) (_args) +#define VA_LIST_FREE(_args) +#define FMT_DECL(_fmt) +#define FMT_PREP(_fmt) +#define FMT_CONV(_fmt) (format) +#define FMT_FREE(_fmt) + +#endif /* !CONFIG_X86_64 */ + +noregparm INT WIN_FUNC(_win_sprintf,12) + (char *buf, const char *format, ...) +{ + va_list args; + int res; + FMT_DECL(format) + + FMT_PREP(format); + va_start(args, format); + res = vsprintf(buf, FMT_CONV(format), args); + va_end(args); + FMT_FREE(format); + + TRACE2("buf: %p: %s", buf, buf); + return res; +} + +noregparm INT WIN_FUNC(swprintf,12) + (wchar_t *buf, const wchar_t *format, ...) +{ + TODO(); + EXIT2(return 0); +} + +noregparm INT WIN_FUNC(_win_vsprintf,3) + (char *str, const char *format, va_list ap) +{ + INT i; + VA_LIST_DECL(ap) + FMT_DECL(format) + + VA_LIST_PREP(ap); + FMT_PREP(format); + + i = vsprintf(str, FMT_CONV(format), VA_LIST_CONV(ap)); + TRACE2("str: %p: %s", str, str); + + FMT_FREE(format); + VA_LIST_FREE(ap); + EXIT2(return i); +} + +noregparm INT WIN_FUNC(_win_snprintf,12) + (char *buf, SIZE_T count, const char *format, ...) +{ + va_list args; + int res; + FMT_DECL(format) + + FMT_PREP(format); + va_start(args, format); + res = vsnprintf(buf, count, FMT_CONV(format), args); + va_end(args); + TRACE2("buf: %p: %s", buf, buf); + + FMT_FREE(format); + return res; +} + +noregparm INT WIN_FUNC(_win__snprintf,12) + (char *buf, SIZE_T count, const char *format, ...) +{ + va_list args; + int res; + FMT_DECL(format) + + FMT_PREP(format); + va_start(args, format); + res = vsnprintf(buf, count, FMT_CONV(format), args); + va_end(args); + TRACE2("buf: %p: %s", buf, buf); + + FMT_FREE(format); + return res; +} + +noregparm INT WIN_FUNC(_win_vsnprintf,4) + (char *str, SIZE_T size, const char *format, va_list ap) +{ + INT i; + VA_LIST_DECL(ap) + FMT_DECL(format) + + VA_LIST_PREP(ap); + FMT_PREP(format); + + i = vsnprintf(str, size, FMT_CONV(format), VA_LIST_CONV(ap)); + TRACE2("str: %p: %s", str, str); + + FMT_FREE(format); + VA_LIST_FREE(ap); + EXIT2(return i); +} + +noregparm INT WIN_FUNC(_win__vsnprintf,4) + (char *str, SIZE_T size, const char *format, va_list ap) +{ + INT i; + VA_LIST_DECL(ap) + FMT_DECL(format) + + VA_LIST_PREP(ap); + FMT_PREP(format); + + i = vsnprintf(str, size, FMT_CONV(format), VA_LIST_CONV(ap)); + TRACE2("str: %p: %s", str, str); + + FMT_FREE(format); + VA_LIST_FREE(ap); + EXIT2(return i); +} + +noregparm char *WIN_FUNC(_win_strncpy,3) + (char *dst, char *src, SIZE_T n) +{ + return strncpy(dst, src, n); +} + +noregparm SIZE_T WIN_FUNC(_win_strlen,1) + (const char *s) +{ + return strlen(s); +} + +noregparm INT WIN_FUNC(_win_strncmp,3) + (const char *s1, const char *s2, SIZE_T n) +{ + return strncmp(s1, s2, n); +} + +noregparm INT WIN_FUNC(_win_strcmp,2) + (const char *s1, const char *s2) +{ + return strcmp(s1, s2); +} + +noregparm INT WIN_FUNC(_win_stricmp,2) + (const char *s1, const char *s2) +{ + return stricmp(s1, s2); +} + +noregparm char *WIN_FUNC(_win_strncat,3) + (char *dest, const char *src, SIZE_T n) +{ + return strncat(dest, src, n); +} + +noregparm INT WIN_FUNC(_win_wcscmp,2) + (const wchar_t *s1, const wchar_t *s2) +{ + while (*s1 && *s1 == *s2) { + s1++; + s2++; + } + return *s1 - *s2; +} + +noregparm INT WIN_FUNC(_win_wcsicmp,2) + (const wchar_t *s1, const wchar_t *s2) +{ + while (*s1 && tolower((char)*s1) == tolower((char)*s2)) { + s1++; + s2++; + } + return tolower((char)*s1) - tolower((char)*s2); +} + +noregparm SIZE_T WIN_FUNC(_win_wcslen,1) + (const wchar_t *s) +{ + const wchar_t *t = s; + while (*t) + t++; + return t - s; +} + +noregparm wchar_t *WIN_FUNC(_win_wcsncpy,3) + (wchar_t *dest, const wchar_t *src, SIZE_T n) +{ + const wchar_t *s; + wchar_t *d; + s = src + n; + d = dest; + while (src < s && (*d++ = *src++)) + ; + if (s > src) + memset(d, 0, (s - src) * sizeof(wchar_t)); + return dest; +} + +noregparm wchar_t *WIN_FUNC(_win_wcscpy,2) + (wchar_t *dest, const wchar_t *src) +{ + wchar_t *d = dest; + while ((*d++ = *src++)) + ; + return dest; +} + +noregparm wchar_t *WIN_FUNC(_win_wcscat,2) + (wchar_t *dest, const wchar_t *src) +{ + wchar_t *d; + d = dest; + while (*d) + d++; + while ((*d++ = *src++)) + ; + return dest; +} + +noregparm INT WIN_FUNC(_win_towupper,1) + (wchar_t c) +{ + return toupper(c); +} + +noregparm INT WIN_FUNC(_win_towlower,1) + (wchar_t c) +{ + return tolower(c); +} + +noregparm INT WIN_FUNC(_win_tolower,1) + (INT c) +{ + return tolower(c); +} + +noregparm INT WIN_FUNC(_win_toupper,1) + (INT c) +{ + return toupper(c); +} + +noregparm void *WIN_FUNC(_win_strcpy,2) + (void *to, const void *from) +{ + return strcpy(to, from); +} + +noregparm char *WIN_FUNC(_win_strstr,2) + (const char *s1, const char *s2) +{ + return strstr(s1, s2); +} + +noregparm char *WIN_FUNC(_win_strchr,2) + (const char *s, int c) +{ + return strchr(s, c); +} + +noregparm char *WIN_FUNC(_win_strrchr,2) + (const char *s, int c) +{ + return strrchr(s, c); +} + +noregparm void *WIN_FUNC(_win_memmove,3) + (void *to, void *from, SIZE_T count) +{ + return memmove(to, from, count); +} + +noregparm void *WIN_FUNC(_win_memchr,3) + (const void *s, INT c, SIZE_T n) +{ + return memchr(s, c, n); +} + +noregparm void *WIN_FUNC(_win_memcpy,3) + (void *to, const void *from, SIZE_T n) +{ + return memcpy(to, from, n); +} + +noregparm void *WIN_FUNC(_win_memset,3) + (void *s, char c, SIZE_T count) +{ + return memset(s, c, count); +} + +noregparm int WIN_FUNC(_win_memcmp,3) + (void *s1, void *s2, SIZE_T n) +{ + return memcmp(s1, s2, n); +} + +noregparm void WIN_FUNC(_win_srand,1) + (UINT seed) +{ + net_srandom(seed); +} + +noregparm int WIN_FUNC(rand,0) + (void) +{ + char buf[6]; + int i, n; + + get_random_bytes(buf, sizeof(buf)); + for (n = i = 0; i < sizeof(buf) ; i++) + n += buf[i]; + return n; +} + +noregparm int WIN_FUNC(_win_atoi,1) + (const char *ptr) +{ + int i = simple_strtol(ptr, NULL, 10); + return i; +} + +noregparm int WIN_FUNC(_win_isprint,1) + (int c) +{ + return isprint(c); +} + +wstdcall s64 WIN_FUNC(_alldiv,2) + (s64 a, s64 b) +{ + return a / b; +} + +wstdcall u64 WIN_FUNC(_aulldiv,2) + (u64 a, u64 b) +{ + return a / b; +} + +wstdcall s64 WIN_FUNC(_allmul,2) + (s64 a, s64 b) +{ + return a * b; +} + +wstdcall u64 WIN_FUNC(_aullmul,2) + (u64 a, u64 b) +{ + return a * b; +} + +wstdcall s64 WIN_FUNC(_allrem,2) + (s64 a, s64 b) +{ + return a % b; +} + +wstdcall u64 WIN_FUNC(_aullrem,2) + (u64 a, u64 b) +{ + return a % b; +} + +__attribute__((regparm(3))) s64 WIN_FUNC(_allshl,2) + (s64 a, u8 b) +{ + return a << b; +} + +__attribute__((regparm(3))) u64 WIN_FUNC(_aullshl,2) + (u64 a, u8 b) +{ + return a << b; +} + +__attribute__((regparm(3))) s64 WIN_FUNC(_allshr,2) + (s64 a, u8 b) +{ + return a >> b; +} + +__attribute__((regparm(3))) u64 WIN_FUNC(_aullshr,2) + (u64 a, u8 b) +{ + return a >> b; +} + +int stricmp(const char *s1, const char *s2) +{ + while (*s1 && tolower(*s1) == tolower(*s2)) { + s1++; + s2++; + } + return *s1 - *s2; +} + +void dump_bytes(const char *ctx, const u8 *from, int len) +{ + int i, j; + u8 *buf; + + buf = kmalloc(len * 3 + 1, irql_gfp()); + if (!buf) { + ERROR("couldn't allocate memory"); + return; + } + for (i = j = 0; i < len; i++, j += 3) { + sprintf(&buf[j], "%02x ", from[i]); + } + buf[j] = 0; + printk(KERN_DEBUG "%s: %p: %s\n", ctx, from, buf); + kfree(buf); +} + +int crt_init(void) +{ + return 0; +} + +/* called when module is being removed */ +void crt_exit(void) +{ + EXIT4(return); +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/divdi3.c +++ linux-2.6.37/ubuntu/ndiswrapper/divdi3.c @@ -0,0 +1,329 @@ +/* 64-bit multiplication and division + Copyright (C) 1989, 1992-1999, 2000, 2001, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#if BITS_PER_LONG != 32 +#error This is for 32-bit targets only +#endif + +typedef unsigned int UQItype __attribute__ ((mode (QI))); +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +#define Wtype SItype +#define HWtype SItype +#define DWtype DItype +#define UWtype USItype +#define UHWtype USItype +#define UDWtype UDItype +#define W_TYPE_SIZE 32 + +#include "longlong.h" + +#if defined(__BIG_ENDIAN) +struct DWstruct { Wtype high, low;}; +#elif defined(__LITTLE_ENDIAN) +struct DWstruct { Wtype low, high;}; +#else +#error Unhandled endianity +#endif +typedef union { struct DWstruct s; DWtype ll; } DWunion; + +/* Prototypes of exported functions. */ +extern DWtype __divdi3 (DWtype u, DWtype v); +extern DWtype __moddi3 (DWtype u, DWtype v); +extern UDWtype __udivdi3 (UDWtype u, UDWtype v); +extern UDWtype __umoddi3 (UDWtype u, UDWtype v); + +static UDWtype +__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) +{ + DWunion ww; + DWunion nn, dd; + DWunion rr; + UWtype d0, d1, n0, n1, n2; + UWtype q0, q1; + UWtype b, bm; + + nn.ll = n; + dd.ll = d; + + d0 = dd.s.low; + d1 = dd.s.high; + n0 = nn.s.low; + n1 = nn.s.high; + +#if !UDIV_NEEDS_NORMALIZATION + if (d1 == 0) + { + if (d0 > n1) + { + /* 0q = nn / 0D */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + udiv_qrnnd (q1, n1, 0, n1, d0); + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0. */ + } + + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = 0; + *rp = rr.ll; + } + } + +#else /* UDIV_NEEDS_NORMALIZATION */ + + if (d1 == 0) + { + if (d0 > n1) + { + /* 0q = nn / 0D */ + + count_leading_zeros (bm, d0); + + if (bm != 0) + { + /* Normalize, i.e. make the most significant bit of the + denominator set. */ + + d0 = d0 << bm; + n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm)); + n0 = n0 << bm; + } + + udiv_qrnnd (q0, n0, n1, n0, d0); + q1 = 0; + + /* Remainder in n0 >> bm. */ + } + else + { + /* qq = NN / 0d */ + + if (d0 == 0) + d0 = 1 / d0; /* Divide intentionally by zero. */ + + count_leading_zeros (bm, d0); + + if (bm == 0) + { + /* From (n1 >= d0) /\ (the most significant bit of d0 is set), + conclude (the most significant bit of n1 is set) /\ (the + leading quotient digit q1 = 1). + + This special case is necessary, not an optimization. + (Shifts counts of W_TYPE_SIZE are undefined.) */ + + n1 -= d0; + q1 = 1; + } + else + { + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q1, n1, n2, n1, d0); + } + + /* n1 != d0... */ + + udiv_qrnnd (q0, n0, n1, n0, d0); + + /* Remainder in n0 >> bm. */ + } + + if (rp != 0) + { + rr.s.low = n0 >> bm; + rr.s.high = 0; + *rp = rr.ll; + } + } +#endif /* UDIV_NEEDS_NORMALIZATION */ + + else + { + if (d1 > n1) + { + /* 00 = nn / DD */ + + q0 = 0; + q1 = 0; + + /* Remainder in n1n0. */ + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } + else + { + /* 0q = NN / dd */ + + count_leading_zeros (bm, d1); + if (bm == 0) + { + /* From (n1 >= d1) /\ (the most significant bit of d1 is set), + conclude (the most significant bit of n1 is set) /\ (the + quotient digit q0 = 0 or 1). + + This special case is necessary, not an optimization. */ + + /* The condition on the next line takes advantage of that + n1 >= d1 (true due to program flow). */ + if (n1 > d1 || n0 >= d0) + { + q0 = 1; + sub_ddmmss (n1, n0, n1, n0, d1, d0); + } + else + q0 = 0; + + q1 = 0; + + if (rp != 0) + { + rr.s.low = n0; + rr.s.high = n1; + *rp = rr.ll; + } + } + else + { + UWtype m1, m0; + /* Normalize. */ + + b = W_TYPE_SIZE - bm; + + d1 = (d1 << bm) | (d0 >> b); + d0 = d0 << bm; + n2 = n1 >> b; + n1 = (n1 << bm) | (n0 >> b); + n0 = n0 << bm; + + udiv_qrnnd (q0, n1, n2, n1, d1); + umul_ppmm (m1, m0, q0, d0); + + if (m1 > n1 || (m1 == n1 && m0 > n0)) + { + q0--; + sub_ddmmss (m1, m0, m1, m0, d1, d0); + } + + q1 = 0; + + /* Remainder in (n1n0 - m1m0) >> bm. */ + if (rp != 0) + { + sub_ddmmss (n1, n0, n1, n0, m1, m0); + rr.s.low = (n1 << b) | (n0 >> bm); + rr.s.high = n1 >> bm; + *rp = rr.ll; + } + } + } + } + + ww.s.low = q0; + ww.s.high = q1; + return ww.ll; +} + +DWtype +__divdi3 (DWtype u, DWtype v) +{ + Wtype c = 0; + DWtype w; + + if (u < 0) + { + c = ~c; + u = -u; + } + if (v < 0) + { + c = ~c; + v = -v; + } + w = __udivmoddi4 (u, v, NULL); + if (c) + w = -w; + return w; +} + +DWtype +__moddi3 (DWtype u, DWtype v) +{ + Wtype c = 0; + DWtype w; + + if (u < 0) + { + c = ~c; + u = -u; + } + if (v < 0) + v = -v; + __udivmoddi4 (u, v, &w); + if (c) + w = -w; + return w; +} + +UDWtype +__udivdi3 (UDWtype u, UDWtype v) +{ + return __udivmoddi4 (u, v, NULL); +} + +UDWtype +__umoddi3 (UDWtype u, UDWtype v) +{ + UDWtype w; + + __udivmoddi4 (u, v, &w); + return w; +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/hal.c +++ linux-2.6.37/ubuntu/ndiswrapper/hal.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ + +#include "ntoskernel.h" +#include "hal_exports.h" + +wstdcall void WIN_FUNC(WRITE_PORT_ULONG,2) + (ULONG_PTR port, ULONG value) +{ + outl(value, port); +} + +wstdcall ULONG WIN_FUNC(READ_PORT_ULONG,1) + (ULONG_PTR port) +{ + return inl(port); +} + +wstdcall void WIN_FUNC(WRITE_PORT_USHORT,2) + (ULONG_PTR port, USHORT value) +{ + outw(value, port); +} + +wstdcall USHORT WIN_FUNC(READ_PORT_USHORT,1) + (ULONG_PTR port) +{ + return inw(port); +} + +wstdcall void WIN_FUNC(WRITE_PORT_UCHAR,2) + (ULONG_PTR port, UCHAR value) +{ + outb(value, port); +} + +wstdcall UCHAR WIN_FUNC(READ_PORT_UCHAR,1) + (ULONG_PTR port) +{ + return inb(port); +} + +wstdcall void WIN_FUNC(WRITE_PORT_BUFFER_USHORT,3) + (ULONG_PTR port, USHORT *buf, ULONG count) +{ + outsw(port, buf, count); +} + +wstdcall void WIN_FUNC(READ_PORT_BUFFER_USHORT,3) + (ULONG_PTR port, USHORT *buf, ULONG count) +{ + insw(port, buf, count); +} + +wstdcall void WIN_FUNC(WRITE_PORT_BUFFER_ULONG,3) + (ULONG_PTR port, ULONG *buf, ULONG count) +{ + outsl(port, buf, count); +} + +wstdcall void WIN_FUNC(READ_PORT_BUFFER_ULONG,3) + (ULONG_PTR port, ULONG *buf, ULONG count) +{ + insl(port, buf, count); +} + +wstdcall USHORT WIN_FUNC(READ_REGISTER_USHORT,1) + (void __iomem *reg) +{ + return readw(reg); +} + +wstdcall void WIN_FUNC(WRITE_REGISTER_ULONG,2) + (void __iomem *reg, UINT val) +{ + writel(val, reg); +} + +wstdcall void WIN_FUNC(WRITE_REGISTER_USHORT,2) + (void __iomem *reg, USHORT val) +{ + writew(val, reg); +} + +wstdcall void WIN_FUNC(WRITE_REGISTER_UCHAR,2) + (void __iomem *reg, UCHAR val) +{ + writeb(val, reg); +} + +wstdcall void WIN_FUNC(KeStallExecutionProcessor,1) + (ULONG usecs) +{ + udelay(usecs); +} + +wstdcall KIRQL WIN_FUNC(KeGetCurrentIrql,0) + (void) +{ + return current_irql(); +} + +wfastcall KIRQL WIN_FUNC(KfRaiseIrql,1) + (KIRQL newirql) +{ + return raise_irql(newirql); +} + +wfastcall void WIN_FUNC(KfLowerIrql,1) + (KIRQL oldirql) +{ + lower_irql(oldirql); +} + +wfastcall KIRQL WIN_FUNC(KfAcquireSpinLock,1) + (NT_SPIN_LOCK *lock) +{ + return nt_spin_lock_irql(lock, DISPATCH_LEVEL); +} + +wfastcall void WIN_FUNC(KfReleaseSpinLock,2) + (NT_SPIN_LOCK *lock, KIRQL oldirql) +{ + nt_spin_unlock_irql(lock, oldirql); +} + +wfastcall void WIN_FUNC(KefAcquireSpinLockAtDpcLevel,1) + (NT_SPIN_LOCK *lock) +{ +#ifdef DEBUG_IRQL + if (current_irql() != DISPATCH_LEVEL) + ERROR("irql != DISPATCH_LEVEL"); +#endif + nt_spin_lock(lock); +} + +wfastcall void WIN_FUNC(KefReleaseSpinLockFromDpcLevel,1) + (NT_SPIN_LOCK *lock) +{ +#ifdef DEBUG_IRQL + if (current_irql() != DISPATCH_LEVEL) + ERROR("irql != DISPATCH_LEVEL"); +#endif + nt_spin_unlock(lock); +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/iw_ndis.c +++ linux-2.6.37/ubuntu/ndiswrapper/iw_ndis.c @@ -0,0 +1,1973 @@ + /* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "iw_ndis.h" +#include "wrapndis.h" + +static int freq_chan[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; + +static const char *network_names[] = {"IEEE 802.11FH", "IEEE 802.11b", + "IEEE 802.11a", "IEEE 802.11g", "Auto"}; + +int set_essid(struct ndis_device *wnd, const char *ssid, int ssid_len) +{ + NDIS_STATUS res; + struct ndis_essid req; + + if (ssid_len > NDIS_ESSID_MAX_SIZE) + return -EINVAL; + + memset(&req, 0, sizeof(req)); + req.length = ssid_len; + if (ssid_len) + memcpy(&req.essid, ssid, ssid_len); + + res = mp_set(wnd, OID_802_11_SSID, &req, sizeof(req)); + if (res) { + WARNING("setting essid failed (%08X)", res); + EXIT2(return -EINVAL); + } + memcpy(&wnd->essid, &req, sizeof(req)); + EXIT2(return 0); +} + +static int set_assoc_params(struct ndis_device *wnd) +{ + TRACE2("wpa_version=0x%x auth_alg=0x%x key_mgmt=0x%x " + "cipher_pairwise=0x%x cipher_group=0x%x", + wnd->iw_auth_wpa_version, wnd->iw_auth_80211_alg, + wnd->iw_auth_key_mgmt, wnd->iw_auth_cipher_pairwise, + wnd->iw_auth_cipher_group); + set_auth_mode(wnd); + set_priv_filter(wnd); + set_encr_mode(wnd); + return 0; +} + +static int iw_set_essid(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + char ssid[NDIS_ESSID_MAX_SIZE]; + int length; + + ENTER2(""); + memset(ssid, 0, sizeof(ssid)); + /* there is no way to turn off essid other than to set to + * random bytes; instead, we use off to mean any */ + if (wrqu->essid.flags) { + /* wireless-tools prior to version 20 add extra 1, and + * later than 20 don't! Deal with that mess */ + length = wrqu->essid.length - 1; + if (length > 0) + length--; + while (length < wrqu->essid.length && extra[length]) + length++; + TRACE2("%d", length); + if (length <= 0 || length > NDIS_ESSID_MAX_SIZE) + EXIT2(return -EINVAL); + } else + length = 0; + + set_assoc_params(wnd); + + memcpy(ssid, extra, length); + if (set_essid(wnd, ssid, length)) + EXIT2(return -EINVAL); + + EXIT2(return 0); +} + +static int iw_get_essid(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + struct ndis_essid req; + + ENTER2(""); + memset(&req, 0, sizeof(req)); + res = mp_query(wnd, OID_802_11_SSID, &req, sizeof(req)); + if (res) { + WARNING("getting essid failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } + memcpy(extra, req.essid, req.length); + if (req.length > 0) + wrqu->essid.flags = 1; + else + wrqu->essid.flags = 0; + wrqu->essid.length = req.length; + EXIT2(return 0); +} + +int set_infra_mode(struct ndis_device *wnd, + enum ndis_infrastructure_mode mode) +{ + NDIS_STATUS res; + unsigned int i; + + ENTER2("%d", mode); + res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, + &wnd->infrastructure_mode); + if (res != NDIS_STATUS_SUCCESS) { + WARNING("getting operating mode to failed (%08X)", res); + EXIT2(return -EINVAL); + } + if (wnd->infrastructure_mode == mode) + EXIT2(return 0); + res = mp_set_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, mode); + if (res) { + WARNING("setting operating mode to %d failed (%08X)", + mode, res); + EXIT2(return -EINVAL); + } + /* NDIS drivers clear keys when infrastructure mode is + * changed. But Linux tools assume otherwise. So set the + * keys */ + if (wnd->iw_auth_key_mgmt == 0 || + wnd->iw_auth_key_mgmt == IW_AUTH_KEY_MGMT_802_1X) { + for (i = 0; i < MAX_ENCR_KEYS; i++) { + if (wnd->encr_info.keys[i].length > 0) + add_wep_key(wnd, wnd->encr_info.keys[i].key, + wnd->encr_info.keys[i].length, i); + } + } + wnd->infrastructure_mode = mode; + EXIT2(return 0); +} + +static int iw_set_infra_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + enum ndis_infrastructure_mode ndis_mode; + + ENTER2("%d", wrqu->mode); + switch (wrqu->mode) { + case IW_MODE_ADHOC: + ndis_mode = Ndis802_11IBSS; + break; + case IW_MODE_INFRA: + ndis_mode = Ndis802_11Infrastructure; + break; + case IW_MODE_AUTO: + ndis_mode = Ndis802_11AutoUnknown; + break; + default: + EXIT2(return -EINVAL); + } + + if (set_infra_mode(wnd, ndis_mode)) + EXIT2(return -EINVAL); + + EXIT2(return 0); +} + +static int iw_get_infra_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + int ndis_mode, iw_mode; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, &ndis_mode); + if (res) { + WARNING("getting operating mode failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } + + switch(ndis_mode) { + case Ndis802_11IBSS: + iw_mode = IW_MODE_ADHOC; + break; + case Ndis802_11Infrastructure: + iw_mode = IW_MODE_INFRA; + break; + case Ndis802_11AutoUnknown: + iw_mode = IW_MODE_AUTO; + break; + default: + ERROR("invalid operating mode (%u)", ndis_mode); + EXIT2(return -EINVAL); + } + wrqu->mode = iw_mode; + EXIT2(return 0); +} + +static const char *network_type_to_name(int net_type) +{ + if (net_type >= 0 && + net_type < (sizeof(network_names)/sizeof(network_names[0]))) + return network_names[net_type]; + else + return network_names[sizeof(network_names) / + sizeof(network_names[0]) - 1]; +} + +static int iw_get_network_type(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + unsigned int network_type; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, + &network_type); + if (res) { + WARNING("getting network type failed: %08X", res); + network_type = -1; + } + strncpy(wrqu->name, network_type_to_name(network_type), + sizeof(wrqu->name) - 1); + wrqu->name[sizeof(wrqu->name)-1] = 0; + return 0; +} + +static int iw_get_freq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + struct ndis_configuration req; + + ENTER2(""); + memset(&req, 0, sizeof(req)); + res = mp_query(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req)); + if (res) { + WARNING("getting configuration failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } + + memset(&(wrqu->freq), 0, sizeof(struct iw_freq)); + + /* see comment in wireless.h above the "struct iw_freq" + definition for an explanation of this if + NOTE: 1000000 is due to the kHz + */ + if (req.ds_config > 1000000) { + wrqu->freq.m = req.ds_config / 10; + wrqu->freq.e = 1; + } + else + wrqu->freq.m = req.ds_config; + + /* convert from kHz to Hz */ + wrqu->freq.e += 3; + + return 0; +} + +static int iw_set_freq(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + struct ndis_configuration req; + + ENTER2(""); + /* this OID is valid only when not associated */ + if (netif_carrier_ok(wnd->net_dev)) + EXIT2(return 0); + memset(&req, 0, sizeof(req)); + res = mp_query(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req)); + if (res) { + WARNING("getting configuration failed (%08X)", res); + EXIT2(return 0); + } + + if (wrqu->freq.m < 1000 && wrqu->freq.e == 0) { + if (wrqu->freq.m >= 1 && + wrqu->freq.m <= (sizeof(freq_chan) / sizeof(freq_chan[0]))) + req.ds_config = freq_chan[wrqu->freq.m - 1] * 1000; + else + return -EINVAL; + } else { + int i; + req.ds_config = wrqu->freq.m; + for (i = wrqu->freq.e; i > 0; i--) + req.ds_config *= 10; + req.ds_config /= 1000; + } + res = mp_set(wnd, OID_802_11_CONFIGURATION, &req, sizeof(req)); + if (res) + WARNING("setting configuration failed (%08X)", res); + return 0; +} + +static int iw_get_tx_power(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_tx_power_level ndis_power; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL, + &ndis_power, sizeof(ndis_power)); + if (res) + return -EOPNOTSUPP; + wrqu->txpower.flags = IW_TXPOW_MWATT; + wrqu->txpower.disabled = 0; + wrqu->txpower.fixed = 0; + wrqu->txpower.value = ndis_power; + return 0; +} + +static int iw_set_tx_power(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_tx_power_level ndis_power; + NDIS_STATUS res; + + ENTER2(""); + if (wrqu->txpower.disabled) + ndis_power = 0; + else { + if (wrqu->txpower.flags == IW_TXPOW_MWATT) + ndis_power = wrqu->txpower.value; + else { // wrqu->txpower.flags == IW_TXPOW_DBM + if (wrqu->txpower.value > 20) + ndis_power = 128; + else if (wrqu->txpower.value < -43) + ndis_power = 127; + else { + signed char tmp; + tmp = wrqu->txpower.value; + tmp = -12 - tmp; + tmp <<= 2; + ndis_power = (unsigned char)tmp; + } + } + } + TRACE2("%d", ndis_power); + res = mp_set(wnd, OID_802_11_TX_POWER_LEVEL, + &ndis_power, sizeof(ndis_power)); + if (res) + EXIT2(return -EOPNOTSUPP); + if (ndis_power == 0) + res = disassociate(wnd, 0); + EXIT2(return 0); +} + +static int iw_get_bitrate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ULONG ndis_rate; + int res; + + ENTER2(""); + res = mp_query(wnd, OID_GEN_LINK_SPEED, &ndis_rate, sizeof(ndis_rate)); + if (res) { + WARNING("getting bitrate failed (%08X)", res); + ndis_rate = 0; + } + + wrqu->bitrate.value = ndis_rate * 100; + return 0; +} + +static int iw_set_bitrate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + int i, n; + NDIS_STATUS res; + ndis_rates_ex rates; + + ENTER2(""); + if (wrqu->bitrate.fixed == 0) + EXIT2(return 0); + + res = mp_query_info(wnd, OID_802_11_SUPPORTED_RATES, &rates, + sizeof(rates), &n, NULL); + if (res) { + WARNING("getting bit rate failed (%08X)", res); + EXIT2(return 0); + } + for (i = 0; i < n; i++) { + if (rates[i] & 0x80) + continue; + if ((rates[i] & 0x7f) * 500000 > wrqu->bitrate.value) { + TRACE2("setting rate %d to 0", + (rates[i] & 0x7f) * 500000); + rates[i] = 0; + } + } + + res = mp_set(wnd, OID_802_11_DESIRED_RATES, &rates, n); + if (res) { + WARNING("setting bit rate failed (%08X)", res); + EXIT2(return 0); + } + + return 0; +} + +static int iw_set_dummy(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + /* Do nothing. Used for ioctls that are not implemented. */ + return 0; +} + +static int iw_get_rts_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_rts_threshold threshold; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query(wnd, OID_802_11_RTS_THRESHOLD, + &threshold, sizeof(threshold)); + if (res) + return -EOPNOTSUPP; + + wrqu->rts.value = threshold; + return 0; +} + +static int iw_set_rts_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_rts_threshold threshold; + NDIS_STATUS res; + + ENTER2(""); + threshold = wrqu->rts.value; + res = mp_set(wnd, OID_802_11_RTS_THRESHOLD, + &threshold, sizeof(threshold)); + if (res == NDIS_STATUS_INVALID_DATA) + return -EINVAL; + if (res) + return -EOPNOTSUPP; + + return 0; +} + +static int iw_get_frag_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_fragmentation_threshold frag_threshold; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query(wnd, OID_802_11_FRAGMENTATION_THRESHOLD, + &frag_threshold, sizeof(frag_threshold)); + if (res) + return -ENOTSUPP; + + wrqu->frag.value = frag_threshold; + return 0; +} + +static int iw_set_frag_threshold(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + ndis_rts_threshold threshold; + NDIS_STATUS res; + + ENTER2(""); + threshold = wrqu->frag.value; + res = mp_set(wnd, OID_802_11_FRAGMENTATION_THRESHOLD, + &threshold, sizeof(threshold)); + if (res == NDIS_STATUS_INVALID_DATA) + return -EINVAL; + if (res) + return -EOPNOTSUPP; + return 0; +} + +int get_ap_address(struct ndis_device *wnd, mac_address ap_addr) +{ + NDIS_STATUS res; + + res = mp_query(wnd, OID_802_11_BSSID, ap_addr, ETH_ALEN); + TRACE2(MACSTRSEP, MAC2STR(ap_addr)); + if (res) { + TRACE2("res: %08X", res); + memset(ap_addr, 0x0, ETH_ALEN); + EXIT2(return -EOPNOTSUPP); + } + EXIT2(return 0); +} + +static int iw_get_ap_address(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + mac_address ap_addr; + + ENTER2(""); + get_ap_address(wnd, ap_addr); + memcpy(wrqu->ap_addr.sa_data, ap_addr, ETH_ALEN); + wrqu->ap_addr.sa_family = ARPHRD_ETHER; + EXIT2(return 0); +} + +static int iw_set_ap_address(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + mac_address ap_addr; + + ENTER2(""); + memcpy(ap_addr, wrqu->ap_addr.sa_data, ETH_ALEN); + TRACE2(MACSTRSEP, MAC2STR(ap_addr)); + res = mp_set(wnd, OID_802_11_BSSID, ap_addr, ETH_ALEN); + /* user apps may set ap's mac address, which is not required; + * they may fail to work if this function fails, so return + * success */ + if (res) + WARNING("setting AP mac address failed (%08X)", res); + + EXIT2(return 0); +} + +int set_iw_auth_mode(struct ndis_device *wnd, int wpa_version, + int auth_80211_alg) +{ + NDIS_STATUS res; + ULONG auth_mode; + + ENTER2("%d, %d", wpa_version, auth_80211_alg); + if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) { + if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_802_1X) + auth_mode = Ndis802_11AuthModeWPA2; + else + auth_mode = Ndis802_11AuthModeWPA2PSK; + } else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) { + if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_802_1X) + auth_mode = Ndis802_11AuthModeWPA; + else if (wnd->iw_auth_key_mgmt & IW_AUTH_KEY_MGMT_PSK) + auth_mode = Ndis802_11AuthModeWPAPSK; + else + auth_mode = Ndis802_11AuthModeWPANone; + } else if (auth_80211_alg & IW_AUTH_ALG_SHARED_KEY) { + if (auth_80211_alg & IW_AUTH_ALG_OPEN_SYSTEM) + auth_mode = Ndis802_11AuthModeAutoSwitch; + else + auth_mode = Ndis802_11AuthModeShared; + } else + auth_mode = Ndis802_11AuthModeOpen; + + res = mp_set_int(wnd, OID_802_11_AUTHENTICATION_MODE, auth_mode); + if (res) { + WARNING("setting auth mode to %u failed (%08X)", + auth_mode, res); + if (res == NDIS_STATUS_INVALID_DATA) + EXIT2(return -EINVAL); + return -EOPNOTSUPP; + } + wnd->iw_auth_wpa_version = wpa_version; + wnd->iw_auth_80211_alg = auth_80211_alg; + EXIT2(return 0); +} + +int set_ndis_auth_mode(struct ndis_device *wnd, ULONG auth_mode) +{ + NDIS_STATUS res; + + ENTER2("%d", auth_mode); + res = mp_set_int(wnd, OID_802_11_AUTHENTICATION_MODE, auth_mode); + if (res) { + WARNING("setting auth mode to %u failed (%08X)", + auth_mode, res); + if (res == NDIS_STATUS_INVALID_DATA) + EXIT2(return -EINVAL); + return -EOPNOTSUPP; + } + switch (auth_mode) { + case Ndis802_11AuthModeWPA: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA; + wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_802_1X; + break; + case Ndis802_11AuthModeWPAPSK: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA; + wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK; + case Ndis802_11AuthModeWPANone: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; + wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK; + break; + case Ndis802_11AuthModeWPA2: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA2; + wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_802_1X; + break; + case Ndis802_11AuthModeWPA2PSK: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_WPA2; + wnd->iw_auth_key_mgmt = IW_AUTH_KEY_MGMT_PSK; + break; + case Ndis802_11AuthModeOpen: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; + wnd->iw_auth_80211_alg = IW_AUTH_ALG_OPEN_SYSTEM; + break; + case Ndis802_11AuthModeShared: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; + wnd->iw_auth_80211_alg = IW_AUTH_ALG_SHARED_KEY; + break; + case Ndis802_11AuthModeAutoSwitch: + wnd->iw_auth_wpa_version = IW_AUTH_WPA_VERSION_DISABLED; + wnd->iw_auth_80211_alg = IW_AUTH_ALG_SHARED_KEY; + wnd->iw_auth_80211_alg |= IW_AUTH_ALG_OPEN_SYSTEM; + break; + default: + WARNING("invalid authentication algorithm: %d", auth_mode); + break; + } + EXIT2(return 0); +} + +int set_auth_mode(struct ndis_device *wnd) +{ + return set_iw_auth_mode(wnd, wnd->iw_auth_wpa_version, + wnd->iw_auth_80211_alg); +} + +int get_ndis_auth_mode(struct ndis_device *wnd) +{ + ULONG mode; + NDIS_STATUS res; + + res = mp_query_int(wnd, OID_802_11_AUTHENTICATION_MODE, &mode); + if (res) { + WARNING("getting authentication mode failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } + TRACE2("%d", mode); + return mode; +} + +int set_iw_encr_mode(struct ndis_device *wnd, int cipher_pairwise, + int cipher_groupwise) +{ + NDIS_STATUS res; + ULONG ndis_mode; + + ENTER2("%d, %d", cipher_pairwise, cipher_groupwise); + if (cipher_pairwise & IW_AUTH_CIPHER_CCMP) + ndis_mode = Ndis802_11Encryption3Enabled; + else if (cipher_pairwise & IW_AUTH_CIPHER_TKIP) + ndis_mode = Ndis802_11Encryption2Enabled; + else if (cipher_pairwise & + (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104)) + ndis_mode = Ndis802_11Encryption1Enabled; + else if (cipher_groupwise & IW_AUTH_CIPHER_CCMP) + ndis_mode = Ndis802_11Encryption3Enabled; + else if (cipher_groupwise & IW_AUTH_CIPHER_TKIP) + ndis_mode = Ndis802_11Encryption2Enabled; + else + ndis_mode = Ndis802_11EncryptionDisabled; + + res = mp_set_int(wnd, OID_802_11_ENCRYPTION_STATUS, ndis_mode); + if (res) { + WARNING("setting encryption mode to %u failed (%08X)", + ndis_mode, res); + if (res == NDIS_STATUS_INVALID_DATA) + EXIT2(return -EINVAL); + return -EOPNOTSUPP; + } + wnd->iw_auth_cipher_pairwise = cipher_pairwise; + wnd->iw_auth_cipher_group = cipher_groupwise; + EXIT2(return 0); +} + +int set_encr_mode(struct ndis_device *wnd) +{ + return set_iw_encr_mode(wnd, wnd->iw_auth_cipher_pairwise, + wnd->iw_auth_cipher_group); +} + +int get_ndis_encr_mode(struct ndis_device *wnd) +{ + ULONG mode; + NDIS_STATUS res; + + ENTER2(""); + res = mp_query_int(wnd, OID_802_11_ENCRYPTION_STATUS, &mode); + if (res) { + WARNING("getting encryption status failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } else + EXIT2(return mode); +} + +static int iw_get_encr(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + int index, mode; + struct encr_info *encr_info = &wnd->encr_info; + + ENTER2("wnd = %p", wnd); + wrqu->data.length = 0; + extra[0] = 0; + + index = (wrqu->encoding.flags & IW_ENCODE_INDEX); + TRACE2("index = %u", index); + if (index > 0) + index--; + else + index = encr_info->tx_key_index; + + if (index < 0 || index >= MAX_ENCR_KEYS) { + WARNING("encryption index out of range (%u)", index); + EXIT2(return -EINVAL); + } + + if (index != encr_info->tx_key_index) { + if (encr_info->keys[index].length > 0) { + wrqu->data.flags |= IW_ENCODE_ENABLED; + wrqu->data.length = encr_info->keys[index].length; + memcpy(extra, encr_info->keys[index].key, + encr_info->keys[index].length); + } + else + wrqu->data.flags |= IW_ENCODE_DISABLED; + + EXIT2(return 0); + } + + /* transmit key */ + mode = get_ndis_encr_mode(wnd); + if (mode < 0) + EXIT2(return -EOPNOTSUPP); + + if (mode == Ndis802_11EncryptionDisabled || + mode == Ndis802_11EncryptionNotSupported) + wrqu->data.flags |= IW_ENCODE_DISABLED; + else { + if (mode == Ndis802_11Encryption1KeyAbsent || + mode == Ndis802_11Encryption2KeyAbsent || + mode == Ndis802_11Encryption3KeyAbsent) + wrqu->data.flags |= IW_ENCODE_NOKEY; + else { + wrqu->data.flags |= IW_ENCODE_ENABLED; + wrqu->encoding.flags |= index+1; + wrqu->data.length = encr_info->keys[index].length; + memcpy(extra, encr_info->keys[index].key, + encr_info->keys[index].length); + } + } + mode = get_ndis_auth_mode(wnd); + if (mode < 0) + EXIT2(return -EOPNOTSUPP); + + if (mode == Ndis802_11AuthModeOpen) + wrqu->data.flags |= IW_ENCODE_OPEN; + else if (mode == Ndis802_11AuthModeAutoSwitch) + wrqu->data.flags |= IW_ENCODE_RESTRICTED; + else // Ndis802_11AuthModeAutoSwitch, Ndis802_11AuthModeWPA etc. + wrqu->data.flags |= IW_ENCODE_RESTRICTED; + + EXIT2(return 0); +} + +/* index must be 0 - N, as per NDIS */ +int add_wep_key(struct ndis_device *wnd, char *key, int key_len, + int index) +{ + struct ndis_encr_key ndis_key; + NDIS_STATUS res; + + ENTER2("key index: %d, length: %d", index, key_len); + if (key_len <= 0 || key_len > NDIS_ENCODING_TOKEN_MAX) { + WARNING("invalid key length (%d)", key_len); + EXIT2(return -EINVAL); + } + if (index < 0 || index >= MAX_ENCR_KEYS) { + WARNING("invalid key index (%d)", index); + EXIT2(return -EINVAL); + } + ndis_key.struct_size = sizeof(ndis_key); + ndis_key.length = key_len; + memcpy(&ndis_key.key, key, key_len); + ndis_key.index = index; + + if (index == wnd->encr_info.tx_key_index) { + ndis_key.index |= (1 << 31); + res = set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104, + IW_AUTH_CIPHER_NONE); + if (res) + WARNING("encryption couldn't be enabled (%08X)", res); + } + TRACE2("key %d: " MACSTRSEP, index, MAC2STR(key)); + res = mp_set(wnd, OID_802_11_ADD_WEP, &ndis_key, sizeof(ndis_key)); + if (res) { + WARNING("adding encryption key %d failed (%08X)", + index+1, res); + EXIT2(return -EINVAL); + } + + /* Atheros driver messes up ndis_key during ADD_WEP, so + * don't rely on that; instead use info in key and key_len */ + wnd->encr_info.keys[index].length = key_len; + memcpy(&wnd->encr_info.keys[index].key, key, key_len); + + EXIT2(return 0); +} + +/* remove_key is for both wep and wpa */ +static int remove_key(struct ndis_device *wnd, int index, + mac_address bssid) +{ + NDIS_STATUS res; + if (wnd->encr_info.keys[index].length == 0) + EXIT2(return 0); + wnd->encr_info.keys[index].length = 0; + memset(&wnd->encr_info.keys[index].key, 0, + sizeof(wnd->encr_info.keys[index].length)); + if (wnd->iw_auth_cipher_pairwise == IW_AUTH_CIPHER_TKIP || + wnd->iw_auth_cipher_pairwise == IW_AUTH_CIPHER_CCMP || + wnd->iw_auth_cipher_group == IW_AUTH_CIPHER_TKIP || + wnd->iw_auth_cipher_group == IW_AUTH_CIPHER_CCMP) { + struct ndis_remove_key remove_key; + remove_key.struct_size = sizeof(remove_key); + remove_key.index = index; + if (bssid) { + /* pairwise key */ + if (memcmp(bssid, "\xff\xff\xff\xff\xff\xff", + ETH_ALEN) != 0) + remove_key.index |= (1 << 30); + memcpy(remove_key.bssid, bssid, + sizeof(remove_key.bssid)); + } else + memset(remove_key.bssid, 0xff, + sizeof(remove_key.bssid)); + if (mp_set(wnd, OID_802_11_REMOVE_KEY, + &remove_key, sizeof(remove_key))) + EXIT2(return -EINVAL); + } else { + ndis_key_index keyindex = index; + res = mp_set_int(wnd, OID_802_11_REMOVE_WEP, keyindex); + if (res) { + WARNING("removing encryption key %d failed (%08X)", + keyindex, res); + EXIT2(return -EINVAL); + } + } + /* if it is transmit key, disable encryption */ + if (index == wnd->encr_info.tx_key_index) { + res = set_iw_encr_mode(wnd, IW_AUTH_CIPHER_NONE, + IW_AUTH_CIPHER_NONE); + if (res) + WARNING("changing encr status failed (%08X)", res); + } + TRACE2("key %d removed", index); + EXIT2(return 0); +} + +static int iw_set_wep(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + unsigned int index, key_len; + struct encr_info *encr_info = &wnd->encr_info; + unsigned char *key; + + ENTER2(""); + index = (wrqu->encoding.flags & IW_ENCODE_INDEX); + TRACE2("index = %u", index); + + /* iwconfig gives index as 1 - N */ + if (index > 0) + index--; + else + index = encr_info->tx_key_index; + + if (index < 0 || index >= MAX_ENCR_KEYS) { + WARNING("encryption index out of range (%u)", index); + EXIT2(return -EINVAL); + } + + /* remove key if disabled */ + if (wrqu->data.flags & IW_ENCODE_DISABLED) { + if (remove_key(wnd, index, NULL)) + EXIT2(return -EINVAL); + else + EXIT2(return 0); + } + + /* global encryption state (for all keys) */ + if (wrqu->data.flags & IW_ENCODE_OPEN) + res = set_ndis_auth_mode(wnd, Ndis802_11AuthModeOpen); + else // if (wrqu->data.flags & IW_ENCODE_RESTRICTED) + res = set_ndis_auth_mode(wnd, Ndis802_11AuthModeShared); + if (res) { + WARNING("setting authentication mode failed (%08X)", res); + EXIT2(return -EINVAL); + } + + TRACE2("key length: %d", wrqu->data.length); + + if (wrqu->data.length > 0) { + key_len = wrqu->data.length; + key = extra; + } else { // must be set as tx key + if (encr_info->keys[index].length == 0) { + WARNING("key %d is not set", index+1); + EXIT2(return -EINVAL); + } + key_len = encr_info->keys[index].length; + key = encr_info->keys[index].key; + encr_info->tx_key_index = index; + } + + if (add_wep_key(wnd, key, key_len, index)) + EXIT2(return -EINVAL); + + if (index == encr_info->tx_key_index) { + /* if transmit key is at index other than 0, some + * drivers, at least Atheros and TI, want another + * (global) non-transmit key to be set; don't know why */ + if (index != 0) { + int i; + for (i = 0; i < MAX_ENCR_KEYS; i++) + if (i != index && + encr_info->keys[i].length != 0) + break; + if (i == MAX_ENCR_KEYS) { + if (index == 0) + i = index + 1; + else + i = index - 1; + if (add_wep_key(wnd, key, key_len, i)) + WARNING("couldn't add broadcast key" + " at %d", i); + } + } + /* ndis drivers want essid to be set after setting encr */ + set_essid(wnd, wnd->essid.essid, wnd->essid.length); + } + EXIT2(return 0); +} + +static int iw_set_nick(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + + if (wrqu->data.length >= IW_ESSID_MAX_SIZE || wrqu->data.length <= 0) + return -EINVAL; + memcpy(wnd->nick, extra, wrqu->data.length); + wnd->nick[wrqu->data.length] = 0; + return 0; +} + +static int iw_get_nick(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + + wrqu->data.length = strlen(wnd->nick); + memcpy(extra, wnd->nick, wrqu->data.length); + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) && !defined(IW_REQUEST_FLAG_COMPAT) +#define iwe_stream_add_event(a, b, c, d, e) iwe_stream_add_event(b, c, d, e) +#define iwe_stream_add_point(a, b, c, d, e) iwe_stream_add_point(b, c, d, e) +#define iwe_stream_add_value(a, b, c, d, e, f) \ + iwe_stream_add_value(b, c, d, e, f) +#define iwe_stream_lcp_len(a) IW_EV_LCP_LEN +#endif + +static char *ndis_translate_scan(struct net_device *dev, + struct iw_request_info *info, char *event, + char *end_buf, void *item) +{ + struct iw_event iwe; + char *current_val; + int i, nrates; + unsigned char buf[MAX_WPA_IE_LEN * 2 + 30]; + struct ndis_wlan_bssid *bssid; + struct ndis_wlan_bssid_ex *bssid_ex; + + ENTER2("%p, %p", event, item); + bssid = item; + bssid_ex = item; + /* add mac address */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + iwe.len = IW_EV_ADDR_LEN; + memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN); + event = iwe_stream_add_event(info, event, end_buf, &iwe, + IW_EV_ADDR_LEN); + + /* add essid */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWESSID; + iwe.u.data.length = bssid->ssid.length; + if (iwe.u.data.length > IW_ESSID_MAX_SIZE) + iwe.u.data.length = IW_ESSID_MAX_SIZE; + iwe.u.data.flags = 1; + iwe.len = IW_EV_POINT_LEN + iwe.u.data.length; + event = iwe_stream_add_point(info, event, end_buf, &iwe, + bssid->ssid.essid); + + /* add protocol name */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWNAME; + strncpy(iwe.u.name, network_type_to_name(bssid->net_type), IFNAMSIZ); + event = iwe_stream_add_event(info, event, end_buf, &iwe, + IW_EV_CHAR_LEN); + + /* add mode */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWMODE; + if (bssid->mode == Ndis802_11IBSS) + iwe.u.mode = IW_MODE_ADHOC; + else if (bssid->mode == Ndis802_11Infrastructure) + iwe.u.mode = IW_MODE_INFRA; + else // if (bssid->mode == Ndis802_11AutoUnknown) + iwe.u.mode = IW_MODE_AUTO; + event = iwe_stream_add_event(info, event, end_buf, &iwe, + IW_EV_UINT_LEN); + + /* add freq */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = bssid->config.ds_config; + if (bssid->config.ds_config > 1000000) { + iwe.u.freq.m = bssid->config.ds_config / 10; + iwe.u.freq.e = 1; + } + else + iwe.u.freq.m = bssid->config.ds_config; + /* convert from kHz to Hz */ + iwe.u.freq.e += 3; + iwe.len = IW_EV_FREQ_LEN; + event = iwe_stream_add_event(info, event, end_buf, &iwe, + IW_EV_FREQ_LEN); + + /* add qual */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVQUAL; + i = 100 * (bssid->rssi - WL_NOISE) / (WL_SIGMAX - WL_NOISE); + if (i < 0) + i = 0; + else if (i > 100) + i = 100; + iwe.u.qual.level = bssid->rssi; + iwe.u.qual.noise = WL_NOISE; + iwe.u.qual.qual = i; + iwe.len = IW_EV_QUAL_LEN; + event = iwe_stream_add_event(info, event, end_buf, &iwe, + IW_EV_QUAL_LEN); + + /* add key info */ + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = SIOCGIWENCODE; + if (bssid->privacy == Ndis802_11PrivFilterAcceptAll) + iwe.u.data.flags = IW_ENCODE_DISABLED; + else + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + iwe.u.data.length = 0; + iwe.len = IW_EV_POINT_LEN; + event = iwe_stream_add_point(info, event, end_buf, &iwe, + bssid->ssid.essid); + + /* add rate */ + memset(&iwe, 0, sizeof(iwe)); + current_val = event + iwe_stream_lcp_len(info); + iwe.cmd = SIOCGIWRATE; + if (bssid->length > sizeof(*bssid)) + nrates = NDIS_MAX_RATES_EX; + else + nrates = NDIS_MAX_RATES; + for (i = 0 ; i < nrates ; i++) { + if (bssid->rates[i] & 0x7f) { + iwe.u.bitrate.value = ((bssid->rates[i] & 0x7f) * + 500000); + current_val = iwe_stream_add_value(info, event, + current_val, + end_buf, &iwe, + IW_EV_PARAM_LEN); + } + } + + if ((current_val - event) > iwe_stream_lcp_len(info)) + event = current_val; + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + sprintf(buf, "bcn_int=%d", bssid->config.beacon_period); + iwe.u.data.length = strlen(buf); + event = iwe_stream_add_point(info, event, end_buf, &iwe, buf); + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + sprintf(buf, "atim=%u", bssid->config.atim_window); + iwe.u.data.length = strlen(buf); + event = iwe_stream_add_point(info, event, end_buf, &iwe, buf); + + TRACE2("%d, %u", bssid->length, (unsigned int)sizeof(*bssid)); + if (bssid->length > sizeof(*bssid)) { + unsigned char *iep = (unsigned char *)bssid_ex->ies + + sizeof(struct ndis_fixed_ies); + no_warn_unused unsigned char *end = iep + bssid_ex->ie_length; + + while (iep + 1 < end && iep + 2 + iep[1] <= end) { + unsigned char ielen = 2 + iep[1]; + + if (ielen > SSID_MAX_WPA_IE_LEN) { + iep += ielen; + continue; + } + if ((iep[0] == WLAN_EID_GENERIC && iep[1] >= 4 && + memcmp(iep + 2, "\x00\x50\xf2\x01", 4) == 0) || + iep[0] == RSN_INFO_ELEM) { + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = ielen; + event = iwe_stream_add_point(info, event, + end_buf, &iwe, + iep); + } + iep += ielen; + } + } + TRACE2("event = %p, current_val = %p", event, current_val); + EXIT2(return event); +} + +int set_scan(struct ndis_device *wnd) +{ + NDIS_STATUS res; + + ENTER2(""); + res = mp_set(wnd, OID_802_11_BSSID_LIST_SCAN, NULL, 0); + if (res) { + WARNING("scanning failed (%08X)", res); + EXIT2(return -EOPNOTSUPP); + } + wnd->scan_timestamp = jiffies; + EXIT2(return 0); +} + +static int iw_set_scan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + return set_scan(wnd); +} + +static int iw_get_scan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + unsigned int i, list_len, needed; + NDIS_STATUS res; + struct ndis_bssid_list *bssid_list = NULL; + char *event = extra; + struct ndis_wlan_bssid *cur_item ; + + ENTER2(""); + if (time_before(jiffies, wnd->scan_timestamp + 3 * HZ)) + return -EAGAIN; + /* try with space for a few scan items */ + list_len = sizeof(ULONG) + sizeof(struct ndis_wlan_bssid_ex) * 8; + bssid_list = kmalloc(list_len, GFP_KERNEL); + if (!bssid_list) { + ERROR("couldn't allocate memory"); + return -ENOMEM; + } + /* some drivers don't set bssid_list->num_items to 0 if + OID_802_11_BSSID_LIST returns no items (prism54 driver, e.g.,) */ + memset(bssid_list, 0, list_len); + + needed = 0; + res = mp_query_info(wnd, OID_802_11_BSSID_LIST, + bssid_list, list_len, NULL, &needed); + if (res == NDIS_STATUS_INVALID_LENGTH || + res == NDIS_STATUS_BUFFER_TOO_SHORT) { + /* now try with required space */ + kfree(bssid_list); + list_len = needed; + bssid_list = kmalloc(list_len, GFP_KERNEL); + if (!bssid_list) { + ERROR("couldn't allocate memory"); + return -ENOMEM; + } + memset(bssid_list, 0, list_len); + + res = mp_query(wnd, OID_802_11_BSSID_LIST, + bssid_list, list_len); + } + if (res) { + WARNING("getting BSSID list failed (%08X)", res); + kfree(bssid_list); + EXIT2(return -EOPNOTSUPP); + } + TRACE2("%d", bssid_list->num_items); + cur_item = &bssid_list->bssid[0]; + for (i = 0; i < bssid_list->num_items; i++) { + event = ndis_translate_scan(dev, info, event, + extra + IW_SCAN_MAX_DATA, cur_item); + cur_item = (struct ndis_wlan_bssid *)((char *)cur_item + + cur_item->length); + } + wrqu->data.length = event - extra; + wrqu->data.flags = 0; + kfree(bssid_list); + EXIT2(return 0); +} + +static int iw_set_power_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + ULONG power_mode; + + if (wrqu->power.disabled == 1) + power_mode = NDIS_POWER_OFF; + else if (wrqu->power.flags & IW_POWER_MIN) + power_mode = NDIS_POWER_MIN; + else // if (wrqu->power.flags & IW_POWER_MAX) + power_mode = NDIS_POWER_MAX; + + TRACE2("%d", power_mode); + res = mp_set(wnd, OID_802_11_POWER_MODE, + &power_mode, sizeof(power_mode)); + if (res) + WARNING("setting power mode failed (%08X)", res); + return 0; +} + +static int iw_get_power_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + ULONG power_mode; + + ENTER2(""); + res = mp_query(wnd, OID_802_11_POWER_MODE, + &power_mode, sizeof(power_mode)); + if (res) + return -ENOTSUPP; + + if (power_mode == NDIS_POWER_OFF) + wrqu->power.disabled = 1; + else { + if (wrqu->power.flags != 0) + return 0; + wrqu->power.flags |= IW_POWER_ALL_R; + wrqu->power.flags |= IW_POWER_TIMEOUT; + wrqu->power.value = 0; + wrqu->power.disabled = 0; + + if (power_mode == NDIS_POWER_MIN) + wrqu->power.flags |= IW_POWER_MIN; + else // if (power_mode == NDIS_POWER_MAX) + wrqu->power.flags |= IW_POWER_MAX; + } + return 0; +} + +static int iw_get_sensitivity(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + ndis_rssi rssi_trigger; + + ENTER2(""); + res = mp_query(wnd, OID_802_11_RSSI_TRIGGER, + &rssi_trigger, sizeof(rssi_trigger)); + if (res) + return -EOPNOTSUPP; + wrqu->param.value = rssi_trigger; + wrqu->param.disabled = (rssi_trigger == 0); + wrqu->param.fixed = 1; + return 0; +} + +static int iw_set_sensitivity(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + ndis_rssi rssi_trigger; + + ENTER2(""); + if (wrqu->param.disabled) + rssi_trigger = 0; + else + rssi_trigger = wrqu->param.value; + res = mp_set(wnd, OID_802_11_RSSI_TRIGGER, + &rssi_trigger, sizeof(rssi_trigger)); + if (res == NDIS_STATUS_INVALID_DATA) + return -EINVAL; + if (res) + return -EOPNOTSUPP; + return 0; +} + +static int iw_get_ndis_stats(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + struct iw_statistics *stats = &wnd->iw_stats; + memcpy(&wrqu->qual, &stats->qual, sizeof(stats->qual)); + return 0; +} + +static int iw_get_range(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_range *range = (struct iw_range *)extra; + struct iw_point *data = &wrqu->data; + struct ndis_device *wnd = netdev_priv(dev); + unsigned int i, n; + NDIS_STATUS res; + ndis_rates_ex rates; + ndis_tx_power_level tx_power; + + ENTER2(""); + data->length = sizeof(struct iw_range); + memset(range, 0, sizeof(struct iw_range)); + + range->txpower_capa = IW_TXPOW_MWATT; + range->num_txpower = 0; + + res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL, + &tx_power, sizeof(tx_power)); + if (!res) { + range->num_txpower = 1; + range->txpower[0] = tx_power; + } + + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 18; + + range->retry_capa = IW_RETRY_LIMIT; + range->retry_flags = IW_RETRY_LIMIT; + range->min_retry = 0; + range->max_retry = 255; + + range->num_channels = 1; + + range->max_qual.qual = 100; + range->max_qual.level = 154; + range->max_qual.noise = 154; + range->sensitivity = 3; + + range->max_encoding_tokens = 4; + range->num_encoding_sizes = 2; + range->encoding_size[0] = 5; + range->encoding_size[1] = 13; + + range->num_bitrates = 0; + memset(&rates, 0, sizeof(rates)); + res = mp_query_info(wnd, OID_802_11_SUPPORTED_RATES, + &rates, sizeof(rates), &n, NULL); + if (res) + WARNING("getting bit rates failed: %08X", res); + else { + for (i = 0; i < n && range->num_bitrates < IW_MAX_BITRATES; i++) + if (rates[i] & 0x80) + continue; + else if (rates[i] & 0x7f) { + range->bitrate[range->num_bitrates] = + (rates[i] & 0x7f) * 500000; + range->num_bitrates++; + } + } + + range->num_channels = (sizeof(freq_chan)/sizeof(freq_chan[0])); + + for (i = 0; i < (sizeof(freq_chan)/sizeof(freq_chan[0])) && + i < IW_MAX_FREQUENCIES; i++) { + range->freq[i].i = i + 1; + range->freq[i].m = freq_chan[i] * 100000; + range->freq[i].e = 1; + } + range->num_frequency = i; + + range->min_rts = 0; + range->max_rts = 2347; + range->min_frag = 256; + range->max_frag = 2346; + + /* Event capability (kernel + driver) */ + range->event_capa[0] = (IW_EVENT_CAPA_K_0 | + IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | + IW_EVENT_CAPA_MASK(SIOCGIWAP) | + IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); + range->event_capa[1] = IW_EVENT_CAPA_K_1; + range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) | + IW_EVENT_CAPA_MASK(IWEVCUSTOM) | + IW_EVENT_CAPA_MASK(IWEVREGISTERED) | + IW_EVENT_CAPA_MASK(IWEVEXPIRED)); + + range->enc_capa = 0; + + if (test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr)) + range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP; + if (test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr)) + range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP; + + if (test_bit(Ndis802_11AuthModeWPA, &wnd->capa.auth) || + test_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth)) + range->enc_capa |= IW_ENC_CAPA_WPA; + if (test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) || + test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth)) + range->enc_capa |= IW_ENC_CAPA_WPA2; + + return 0; +} + +void set_default_iw_params(struct ndis_device *wnd) +{ + wnd->iw_auth_key_mgmt = 0; + wnd->iw_auth_wpa_version = 0; + set_infra_mode(wnd, Ndis802_11Infrastructure); + set_ndis_auth_mode(wnd, Ndis802_11AuthModeOpen); + set_priv_filter(wnd); + set_iw_encr_mode(wnd, IW_AUTH_CIPHER_NONE, IW_AUTH_CIPHER_NONE); +} + +static int deauthenticate(struct ndis_device *wnd) +{ + int ret; + + ENTER2(""); + ret = disassociate(wnd, 1); + set_default_iw_params(wnd); + EXIT2(return ret); +} + +NDIS_STATUS disassociate(struct ndis_device *wnd, int reset_ssid) +{ + NDIS_STATUS res; + u8 buf[NDIS_ESSID_MAX_SIZE]; + int i; + + TRACE2(""); + res = mp_set(wnd, OID_802_11_DISASSOCIATE, NULL, 0); + /* disassociate causes radio to be turned off; if reset_ssid + * is given, set ssid to random to enable radio */ + if (reset_ssid) { + get_random_bytes(buf, sizeof(buf)); + for (i = 0; i < sizeof(buf); i++) + buf[i] = 'a' + (buf[i] % 26); + set_essid(wnd, buf, sizeof(buf)); + } + return res; +} + +static ULONG ndis_priv_mode(struct ndis_device *wnd) +{ + if (wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA2 || + wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA) + return Ndis802_11PrivFilter8021xWEP; + else + return Ndis802_11PrivFilterAcceptAll; +} + +int set_priv_filter(struct ndis_device *wnd) +{ + NDIS_STATUS res; + ULONG flags; + + flags = ndis_priv_mode(wnd); + ENTER2("filter: %d", flags); + res = mp_set_int(wnd, OID_802_11_PRIVACY_FILTER, flags); + if (res) + TRACE2("setting privacy filter to %d failed (%08X)", + flags, res); + EXIT2(return 0); +} + +static int iw_set_mlme(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + struct iw_mlme *mlme = (struct iw_mlme *)extra; + + ENTER2(""); + switch (mlme->cmd) { + case IW_MLME_DEAUTH: + return deauthenticate(wnd); + case IW_MLME_DISASSOC: + TRACE2("cmd=%d reason_code=%d", mlme->cmd, mlme->reason_code); + return disassociate(wnd, 1); + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int iw_set_genie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + /* + * NDIS drivers do not allow IEs to be configured; this is + * done by the driver based on other configuration. Return 0 + * to avoid causing issues with user space programs that + * expect this function to succeed. + */ + return 0; +} + +static int iw_set_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + TRACE2("index=%d value=%d", wrqu->param.flags & IW_AUTH_INDEX, + wrqu->param.value); + switch (wrqu->param.flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + wnd->iw_auth_wpa_version = wrqu->param.value; + break; + case IW_AUTH_CIPHER_PAIRWISE: + wnd->iw_auth_cipher_pairwise = wrqu->param.value; + break; + case IW_AUTH_CIPHER_GROUP: + wnd->iw_auth_cipher_group = wrqu->param.value; + break; + case IW_AUTH_KEY_MGMT: + wnd->iw_auth_key_mgmt = wrqu->param.value; + break; + case IW_AUTH_80211_AUTH_ALG: + wnd->iw_auth_80211_alg = wrqu->param.value; + break; + case IW_AUTH_WPA_ENABLED: + if (wrqu->param.value) + deauthenticate(wnd); + break; + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_PRIVACY_INVOKED: + TRACE2("%d not implemented: %d", + wrqu->param.flags & IW_AUTH_INDEX, wrqu->param.value); + break; + default: + WARNING("invalid cmd %d", wrqu->param.flags & IW_AUTH_INDEX); + return -EOPNOTSUPP; + } + return 0; +} + +static int iw_get_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + + ENTER2("index=%d", wrqu->param.flags & IW_AUTH_INDEX); + switch (wrqu->param.flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + wrqu->param.value = wnd->iw_auth_wpa_version; + break; + case IW_AUTH_CIPHER_PAIRWISE: + wrqu->param.value = wnd->iw_auth_cipher_pairwise; + break; + case IW_AUTH_CIPHER_GROUP: + wrqu->param.value = wnd->iw_auth_cipher_group; + break; + case IW_AUTH_KEY_MGMT: + wrqu->param.value = wnd->iw_auth_key_mgmt; + break; + case IW_AUTH_80211_AUTH_ALG: + wrqu->param.value = wnd->iw_auth_80211_alg; + break; + default: + WARNING("invalid cmd %d", wrqu->param.flags & IW_AUTH_INDEX); + return -EOPNOTSUPP; + } + return 0; +} + +static int iw_set_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + struct ndis_device *wnd = netdev_priv(dev); + struct ndis_add_key ndis_key; + int i, keyidx; + NDIS_STATUS res; + u8 *addr; + + keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; + ENTER2("%d", keyidx); + if (keyidx) + keyidx--; + else + keyidx = wnd->encr_info.tx_key_index; + + if (keyidx < 0 || keyidx >= MAX_ENCR_KEYS) + return -EINVAL; + + if (ext->alg == WPA_ALG_WEP) { + if (!test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr)) + EXIT2(return -1); + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + wnd->encr_info.tx_key_index = keyidx; + if (add_wep_key(wnd, ext->key, ext->key_len, keyidx)) + EXIT2(return -1); + else + EXIT2(return 0); + } + if ((wrqu->encoding.flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0) + EXIT2(return remove_key(wnd, keyidx, ndis_key.bssid)); + + if (ext->key_len > sizeof(ndis_key.key)) { + TRACE2("incorrect key length (%u)", ext->key_len); + EXIT2(return -1); + } + + memset(&ndis_key, 0, sizeof(ndis_key)); + + ndis_key.struct_size = + sizeof(ndis_key) - sizeof(ndis_key.key) + ext->key_len; + ndis_key.length = ext->key_len; + ndis_key.index = keyidx; + + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + for (i = 0; i < 6 ; i++) + ndis_key.rsc |= (((u64)ext->rx_seq[i]) << (i * 8)); + TRACE2("0x%Lx", ndis_key.rsc); + ndis_key.index |= 1 << 29; + } + + addr = ext->addr.sa_data; + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /* group key */ + if (wnd->infrastructure_mode == Ndis802_11IBSS) + memset(ndis_key.bssid, 0xff, ETH_ALEN); + else + get_ap_address(wnd, ndis_key.bssid); + } else { + /* pairwise key */ + ndis_key.index |= (1 << 30); + memcpy(ndis_key.bssid, addr, ETH_ALEN); + } + TRACE2(MACSTRSEP, MAC2STR(ndis_key.bssid)); + + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + ndis_key.index |= (1 << 31); + + if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) { + /* wpa_supplicant gives us the Michael MIC RX/TX keys in + * different order than NDIS spec, so swap the order here. */ + memcpy(ndis_key.key, ext->key, 16); + memcpy(ndis_key.key + 16, ext->key + 24, 8); + memcpy(ndis_key.key + 24, ext->key + 16, 8); + } else + memcpy(ndis_key.key, ext->key, ext->key_len); + + res = mp_set(wnd, OID_802_11_ADD_KEY, &ndis_key, ndis_key.struct_size); + if (res) { + TRACE2("adding key failed (%08X), %u", + res, ndis_key.struct_size); + EXIT2(return -1); + } + wnd->encr_info.keys[keyidx].length = ext->key_len; + memcpy(&wnd->encr_info.keys[keyidx].key, ndis_key.key, ext->key_len); + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + wnd->encr_info.tx_key_index = keyidx; + TRACE2("key %d added", keyidx); + + EXIT2(return 0); +} + +static int iw_get_encodeext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + /* struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; */ + /* TODO */ + ENTER2(""); + return 0; +} + +static int iw_set_pmksa(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_pmksa *pmksa = (struct iw_pmksa *)extra; + struct ndis_pmkid pmkid; + NDIS_STATUS res; + struct ndis_device *wnd = netdev_priv(dev); + + /* TODO: must keep local list of PMKIDs since NDIS drivers + * expect that all PMKID entries are included whenever a new + * one is added. */ + + ENTER2("%d", pmksa->cmd); + if ((pmksa->cmd == IW_PMKSA_ADD || pmksa->cmd == IW_PMKSA_REMOVE) && + (!(wnd->iw_auth_wpa_version & IW_AUTH_WPA_VERSION_WPA2))) + EXIT2(return -EOPNOTSUPP); + + memset(&pmkid, 0, sizeof(pmkid)); + if (pmksa->cmd == IW_PMKSA_ADD) { + pmkid.bssid_info_count = 1; + memcpy(pmkid.bssid_info[0].bssid, pmksa->bssid.sa_data, + ETH_ALEN); + memcpy(pmkid.bssid_info[0].pmkid, pmksa->pmkid, IW_PMKID_LEN); + } + pmkid.length = sizeof(pmkid); + + res = mp_set(wnd, OID_802_11_PMKID, &pmkid, pmkid.length); + if (res == NDIS_STATUS_FAILURE) + EXIT2(return -EOPNOTSUPP); + TRACE2("OID_802_11_PMKID -> %d", res); + if (res) + return -EINVAL; + + return 0; +} + +#define WEXT(id) [id - SIOCIWFIRST] + +static const iw_handler ndis_handler[] = { + WEXT(SIOCGIWNAME) = iw_get_network_type, + WEXT(SIOCSIWESSID) = iw_set_essid, + WEXT(SIOCGIWESSID) = iw_get_essid, + WEXT(SIOCSIWMODE) = iw_set_infra_mode, + WEXT(SIOCGIWMODE) = iw_get_infra_mode, + WEXT(SIOCGIWFREQ) = iw_get_freq, + WEXT(SIOCSIWFREQ) = iw_set_freq, + WEXT(SIOCGIWTXPOW) = iw_get_tx_power, + WEXT(SIOCSIWTXPOW) = iw_set_tx_power, + WEXT(SIOCGIWRATE) = iw_get_bitrate, + WEXT(SIOCSIWRATE) = iw_set_bitrate, + WEXT(SIOCGIWRTS) = iw_get_rts_threshold, + WEXT(SIOCSIWRTS) = iw_set_rts_threshold, + WEXT(SIOCGIWFRAG) = iw_get_frag_threshold, + WEXT(SIOCSIWFRAG) = iw_set_frag_threshold, + WEXT(SIOCGIWAP) = iw_get_ap_address, + WEXT(SIOCSIWAP) = iw_set_ap_address, + WEXT(SIOCSIWENCODE) = iw_set_wep, + WEXT(SIOCGIWENCODE) = iw_get_encr, + WEXT(SIOCSIWSCAN) = iw_set_scan, + WEXT(SIOCGIWSCAN) = iw_get_scan, + WEXT(SIOCGIWPOWER) = iw_get_power_mode, + WEXT(SIOCSIWPOWER) = iw_set_power_mode, + WEXT(SIOCGIWRANGE) = iw_get_range, + WEXT(SIOCGIWSTATS) = iw_get_ndis_stats, + WEXT(SIOCGIWSENS) = iw_get_sensitivity, + WEXT(SIOCSIWSENS) = iw_set_sensitivity, + WEXT(SIOCGIWNICKN) = iw_get_nick, + WEXT(SIOCSIWNICKN) = iw_set_nick, + WEXT(SIOCSIWCOMMIT) = iw_set_dummy, + WEXT(SIOCSIWMLME) = iw_set_mlme, + WEXT(SIOCSIWGENIE) = iw_set_genie, + WEXT(SIOCSIWAUTH) = iw_set_auth, + WEXT(SIOCGIWAUTH) = iw_get_auth, + WEXT(SIOCSIWENCODEEXT) = iw_set_encodeext, + WEXT(SIOCGIWENCODEEXT) = iw_get_encodeext, + WEXT(SIOCSIWPMKSA) = iw_set_pmksa, +}; + +/* private ioctl's */ + +static int priv_reset(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int res; + ENTER2(""); + res = mp_reset(netdev_priv(dev)); + if (res) { + WARNING("reset failed: %08X", res); + return -EOPNOTSUPP; + } + return 0; +} + +static int priv_deauthenticate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int res; + ENTER2(""); + res = deauthenticate(netdev_priv(dev)); + return res; +} + +static int priv_power_profile(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + struct miniport *mp; + ULONG profile_inf; + + ENTER2(""); + mp = &wnd->wd->driver->ndis_driver->mp; + if (!mp->pnp_event_notify) + EXIT2(return -EOPNOTSUPP); + + /* 1 for AC and 0 for Battery */ + if (wrqu->param.value) + profile_inf = NdisPowerProfileAcOnLine; + else + profile_inf = NdisPowerProfileBattery; + + LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx, + NdisDevicePnPEventPowerProfileChanged, + &profile_inf, sizeof(profile_inf)); + EXIT2(return 0); +} + +static int priv_network_type(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + enum network_type network_type; + NDIS_STATUS res; + char type; + + ENTER2(""); + type = wrqu->param.value; + if (type == 'f') + network_type = Ndis802_11FH; + else if (type == 'b') + network_type = Ndis802_11DS; + else if (type == 'a') + network_type = Ndis802_11OFDM5; + else if (type == 'g' || type == 'n') + network_type = Ndis802_11OFDM24; + else + network_type = Ndis802_11Automode; + + res = mp_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, network_type); + if (res) { + WARNING("setting network type to %d failed (%08X)", + network_type, res); + EXIT2(return -EINVAL); + } + + EXIT2(return 0); +} + +static int priv_media_stream_mode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + NDIS_STATUS res; + int mode; + + ENTER2(""); + if (wrqu->param.value > 0) + mode = Ndis802_11MediaStreamOn; + else + mode = Ndis802_11MediaStreamOff; + res = mp_set_int(wnd, OID_802_11_MEDIA_STREAM_MODE, mode); + if (res) { + WARNING("oid failed (%08X)", res); + EXIT2(return -EINVAL); + } + EXIT2(return 0); +} + +static int priv_reload_defaults(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct ndis_device *wnd = netdev_priv(dev); + int res; + ENTER2(""); + res = mp_set_int(wnd, OID_802_11_RELOAD_DEFAULTS, + Ndis802_11ReloadWEPKeys); + if (res) { + WARNING("reloading defaults failed: %08X", res); + return -EOPNOTSUPP; + } + return 0; +} + +static const struct iw_priv_args priv_args[] = { + {PRIV_RESET, 0, 0, "ndis_reset"}, + {PRIV_POWER_PROFILE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "power_profile"}, + {PRIV_DEAUTHENTICATE, 0, 0, "deauthenticate"}, + {PRIV_NETWORK_TYPE, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, + "network_type"}, + {PRIV_MEDIA_STREAM_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "media_stream"}, + + {PRIV_RELOAD_DEFAULTS, 0, 0, "reload_defaults"}, +}; + +#define WEPRIV(id) [id - SIOCIWFIRSTPRIV] + +static const iw_handler priv_handler[] = { + WEPRIV(PRIV_RESET) = priv_reset, + WEPRIV(PRIV_POWER_PROFILE) = priv_power_profile, + WEPRIV(PRIV_DEAUTHENTICATE) = priv_deauthenticate, + WEPRIV(PRIV_NETWORK_TYPE) = priv_network_type, + WEPRIV(PRIV_MEDIA_STREAM_MODE) = priv_media_stream_mode, + WEPRIV(PRIV_RELOAD_DEFAULTS) = priv_reload_defaults, +}; + +const struct iw_handler_def ndis_handler_def = { + .num_standard = sizeof(ndis_handler) / sizeof(ndis_handler[0]), + .num_private = sizeof(priv_handler) / sizeof(priv_handler[0]), + .num_private_args = sizeof(priv_args) / sizeof(priv_args[0]), + + .standard = (iw_handler *)ndis_handler, + .private = (iw_handler *)priv_handler, + .private_args = (struct iw_priv_args *)priv_args, + .get_wireless_stats = get_iw_stats, +}; --- linux-2.6.37.orig/ubuntu/ndiswrapper/iw_ndis.h +++ linux-2.6.37/ubuntu/ndiswrapper/iw_ndis.h @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _IW_NDIS_H_ +#define _IW_NDIS_H_ + +#include "ndis.h" + +#define WL_NOISE -96 /* typical noise level in dBm */ +#define WL_SIGMAX -32 /* typical maximum signal level in dBm */ + +struct ndis_encr_key { + ULONG struct_size; + ULONG index; + ULONG length; + UCHAR key[NDIS_ENCODING_TOKEN_MAX]; +}; + +struct ndis_add_key { + ULONG struct_size; + ndis_key_index index; + ULONG length; + mac_address bssid; + UCHAR pad[6]; + ndis_key_rsc rsc; + UCHAR key[NDIS_ENCODING_TOKEN_MAX]; +}; + +struct ndis_remove_key { + ULONG struct_size; + ndis_key_index index; + mac_address bssid; +}; + +struct ndis_fixed_ies { + UCHAR time_stamp[8]; + USHORT beacon_interval; + USHORT capa; +}; + +struct ndis_variable_ies { + ULONG elem_id; + UCHAR length; + UCHAR data[1]; +}; + +enum ndis_reload_defaults { Ndis802_11ReloadWEPKeys }; + +struct ndis_assoc_info { + ULONG length; + USHORT req_ies; + struct req_ie { + USHORT capa; + USHORT listen_interval; + mac_address cur_ap_address; + } req_ie; + ULONG req_ie_length; + ULONG offset_req_ies; + USHORT resp_ies; + struct resp_ie { + USHORT capa; + USHORT status_code; + USHORT assoc_id; + } resp_ie; + ULONG resp_ie_length; + ULONG offset_resp_ies; +}; + +struct ndis_configuration_fh { + ULONG length; + ULONG hop_pattern; + ULONG hop_set; + ULONG dwell_time; +}; + +struct ndis_configuration { + ULONG length; + ULONG beacon_period; + ULONG atim_window; + ULONG ds_config; + struct ndis_configuration_fh fh_config; +}; + +struct ndis_wlan_bssid { + ULONG length; + mac_address mac; + UCHAR reserved[2]; + struct ndis_essid ssid; + ULONG privacy; + ndis_rssi rssi; + UINT net_type; + struct ndis_configuration config; + UINT mode; + ndis_rates rates; +}; + +struct ndis_wlan_bssid_ex { + ULONG length; + mac_address mac; + UCHAR reserved[2]; + struct ndis_essid ssid; + ULONG privacy; + ndis_rssi rssi; + UINT net_type; + struct ndis_configuration config; + UINT mode; + ndis_rates_ex rates_ex; + ULONG ie_length; + UCHAR ies[1]; +}; + +/* we use bssid_list as bssid_list_ex also */ +struct ndis_bssid_list { + ULONG num_items; + struct ndis_wlan_bssid bssid[1]; +}; + +enum ndis_priv_filter { + Ndis802_11PrivFilterAcceptAll, Ndis802_11PrivFilter8021xWEP +}; + +enum network_type { + Ndis802_11FH, Ndis802_11DS, Ndis802_11OFDM5, Ndis802_11OFDM24, + /* MSDN site uses Ndis802_11Automode, which is not mentioned + * in DDK, so add one and assign it to + * Ndis802_11NetworkTypeMax */ + Ndis802_11Automode, Ndis802_11NetworkTypeMax = Ndis802_11Automode +}; + +struct network_type_list { + ULONG num; + enum network_type types[1]; +}; + +enum ndis_power { + NDIS_POWER_OFF = 0, NDIS_POWER_MAX, NDIS_POWER_MIN, +}; + +struct ndis_auth_req { + ULONG length; + mac_address bssid; + ULONG flags; +}; + +struct ndis_bssid_info { + mac_address bssid; + ndis_pmkid_vavlue pmkid; +}; + +struct ndis_pmkid { + ULONG length; + ULONG bssid_info_count; + struct ndis_bssid_info bssid_info[1]; +}; + +int add_wep_key(struct ndis_device *wnd, char *key, int key_len, + int index); +int set_essid(struct ndis_device *wnd, const char *ssid, int ssid_len); +int set_infra_mode(struct ndis_device *wnd, + enum ndis_infrastructure_mode mode); +int get_ap_address(struct ndis_device *wnd, mac_address mac); +int set_ndis_auth_mode(struct ndis_device *wnd, ULONG auth_mode); +int set_iw_auth_mode(struct ndis_device *wnd, int wpa_version, + int auth_80211_alg); +int set_auth_mode(struct ndis_device *wnd); +int set_ndis_encr_mode(struct ndis_device *wnd, int cipher_pairwise, + int cipher_groupwise); +int get_ndis_encr_mode(struct ndis_device *wnd); +int set_encr_mode(struct ndis_device *wnd); +int set_iw_encr_mode(struct ndis_device *wnd, int cipher_pairwise, + int cipher_groupwise); +int get_ndis_auth_mode(struct ndis_device *wnd); +int set_priv_filter(struct ndis_device *wnd); +int set_scan(struct ndis_device *wnd); +NDIS_STATUS disassociate(struct ndis_device *wnd, int reset_ssid); +void set_default_iw_params(struct ndis_device *wnd); +extern const struct iw_handler_def ndis_handler_def; + +#define PRIV_RESET SIOCIWFIRSTPRIV+16 +#define PRIV_POWER_PROFILE SIOCIWFIRSTPRIV+17 +#define PRIV_NETWORK_TYPE SIOCIWFIRSTPRIV+18 +#define PRIV_DEAUTHENTICATE SIOCIWFIRSTPRIV+19 +#define PRIV_MEDIA_STREAM_MODE SIOCIWFIRSTPRIV+20 +#define PRIV_RELOAD_DEFAULTS SIOCIWFIRSTPRIV+23 + +#define RSN_INFO_ELEM 0x30 + +/* these have to match what is in wpa_supplicant */ + +typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP } wpa_alg; +typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, + CIPHER_WEP104 } wpa_cipher; +typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, + KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE } wpa_key_mgmt; + +#endif // IW_NDIS_H --- linux-2.6.37.orig/ubuntu/ndiswrapper/lin2win.h +++ linux-2.6.37/ubuntu/ndiswrapper/lin2win.h @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2006 Giridhar Pemmasani + * + * 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. + * + */ + +#ifdef CONFIG_X86_64 + +/* Windows functions must have 32 bytes of shadow space for arguments + * above return address, irrespective of number of args. So argc >= 4 + */ + +#define alloc_win_stack_frame(argc) \ + "sub $(" #argc "+1)*8, %%rsp\n\t" +#define free_win_stack_frame(argc) \ + "add $(" #argc "+1)*8, %%rsp\n\t" + +/* m is index of Windows arg required; Windows arg 1 should be at + * 0(%rsp), arg 2 at 8(%rsp) and so on after the frame is allocated. +*/ + +#define lin2win_win_arg(m) "(" #m "-1)*8(%%rsp)" + +/* args for Windows function must be in clobber / output list */ + +#define outputs() \ + "=a" (_ret), "=c" (_dummy), "=d" (_dummy), \ + "=r" (r8), "=r" (r9), "=r" (r10), "=r" (r11) + +#define clobbers() "cc" + +#define LIN2WIN0(func) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8"); \ + register u64 r9 __asm__("r9"); \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(4) \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(4) \ + : outputs() \ + : [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN1(func, arg1) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8"); \ + register u64 r9 __asm__("r9"); \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(4) \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(4) \ + : outputs() \ + : "c" (arg1), [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN2(func, arg1, arg2) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8"); \ + register u64 r9 __asm__("r9"); \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(4) \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(4) \ + : outputs() \ + : "c" (arg1), "d" (arg2), [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN3(func, arg1, arg2, arg3) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8") = (u64)arg3; \ + register u64 r9 __asm__("r9"); \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(4) \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(4) \ + : outputs() \ + : "c" (arg1), "d" (arg2), "r" (r8), \ + [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN4(func, arg1, arg2, arg3, arg4) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8") = (u64)arg3; \ + register u64 r9 __asm__("r9") = (u64)arg4; \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(4) \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(4) \ + : outputs() \ + : "c" (arg1), "d" (arg2), "r" (r8), "r" (r9), \ + [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN5(func, arg1, arg2, arg3, arg4, arg5) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8") = (u64)arg3; \ + register u64 r9 __asm__("r9") = (u64)arg4; \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(5) \ + "movq %[rarg5], " lin2win_win_arg(5) "\n\t" \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(5) \ + : outputs() \ + : "c" (arg1), "d" (arg2), "r" (r8), "r" (r9), \ + [rarg5] "ri" ((u64)arg5), \ + [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#define LIN2WIN6(func, arg1, arg2, arg3, arg4, arg5, arg6) \ +({ \ + u64 _ret, _dummy; \ + register u64 r8 __asm__("r8") = (u64)arg3; \ + register u64 r9 __asm__("r9") = (u64)arg4; \ + register u64 r10 __asm__("r10"); \ + register u64 r11 __asm__("r11"); \ + __asm__ __volatile__( \ + alloc_win_stack_frame(6) \ + "movq %[rarg5], " lin2win_win_arg(5) "\n\t" \ + "movq %[rarg6], " lin2win_win_arg(6) "\n\t" \ + "callq *%[fptr]\n\t" \ + free_win_stack_frame(6) \ + : outputs() \ + : "c" (arg1), "d" (arg2), "r" (r8), "r" (r9), \ + [rarg5] "ri" ((u64)arg5), [rarg6] "ri" ((u64)arg6), \ + [fptr] "r" (func) \ + : clobbers()); \ + _ret; \ +}) + +#else // CONFIG_X86_64 + +#define LIN2WIN1(func, arg1) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1); \ +}) +#define LIN2WIN2(func, arg1, arg2) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1, arg2); \ +}) +#define LIN2WIN3(func, arg1, arg2, arg3) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1, arg2, arg3); \ +}) +#define LIN2WIN4(func, arg1, arg2, arg3, arg4) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1, arg2, arg3, arg4); \ +}) +#define LIN2WIN5(func, arg1, arg2, arg3, arg4, arg5) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1, arg2, arg3, arg4, arg5); \ +}) +#define LIN2WIN6(func, arg1, arg2, arg3, arg4, arg5, arg6) \ +({ \ + TRACE6("calling %p", func); \ + func(arg1, arg2, arg3, arg4, arg5, arg6); \ +}) + +#endif // CONFIG_X86_64 --- linux-2.6.37.orig/ubuntu/ndiswrapper/loader.c +++ linux-2.6.37/ubuntu/ndiswrapper/loader.c @@ -0,0 +1,884 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ + +#include "ndis.h" +#include "loader.h" +#include "wrapndis.h" +#include "pnp.h" + +#include +#include +#include +#include + +/* + Network adapter: ClassGuid = {4d36e972-e325-11ce-bfc1-08002be10318} + Network client: ClassGuid = {4d36e973-e325-11ce-bfc1-08002be10318} + PCMCIA adapter: ClassGuid = {4d36e977-e325-11ce-bfc1-08002be10318} + USB: ClassGuid = {36fc9e60-c465-11cf-8056-444553540000} +*/ + +/* the indices used here must match macros WRAP_NDIS_DEVICE etc. */ +static struct guid class_guids[] = { + /* Network */ + {0x4d36e972, 0xe325, 0x11ce, }, + /* USB WDM */ + {0x36fc9e60, 0xc465, 0x11cf, }, + /* Bluetooth */ + {0xe0cbf06c, 0xcd8b, 0x4647, }, + /* ivtcorporatino.com's bluetooth device claims this is + * bluetooth guid */ + {0xf12d3cf8, 0xb11d, 0x457e, }, +}; + +struct semaphore loader_mutex; +static struct completion loader_complete; + +static struct nt_list wrap_devices; +static struct nt_list wrap_drivers; + +static int wrap_device_type(int data1) +{ + int i; + for (i = 0; i < sizeof(class_guids) / sizeof(class_guids[0]); i++) + if (data1 == class_guids[i].data1) + return i; + ERROR("unknown device: 0x%x\n", data1); + return -1; +} + +/* load driver for given device, if not already loaded */ +struct wrap_driver *load_wrap_driver(struct wrap_device *wd) +{ + int ret; + struct nt_list *cur; + struct wrap_driver *wrap_driver; + + ENTER1("device: %04X:%04X:%04X:%04X", wd->vendor, wd->device, + wd->subvendor, wd->subdevice); + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + EXIT1(return NULL); + } + wrap_driver = NULL; + nt_list_for_each(cur, &wrap_drivers) { + wrap_driver = container_of(cur, struct wrap_driver, list); + if (!stricmp(wrap_driver->name, wd->driver_name)) { + TRACE1("driver %s already loaded", wrap_driver->name); + break; + } else + wrap_driver = NULL; + } + up(&loader_mutex); + + if (!wrap_driver) { + char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DRIVER, +#if defined(DEBUG) && DEBUG >= 1 + "1", +#else + "0", +#endif + UTILS_VERSION, wd->driver_name, + wd->conf_file_name, NULL}; + char *env[] = {NULL}; + + TRACE1("loading driver %s", wd->driver_name); + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + EXIT1(return NULL); + } + INIT_COMPLETION(loader_complete); + ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1); + if (ret) { + up(&loader_mutex); + ERROR("couldn't load driver %s; check system log " + "for messages from 'loadndisdriver'", + wd->driver_name); + EXIT1(return NULL); + } + wait_for_completion(&loader_complete); + TRACE1("%s", wd->driver_name); + wrap_driver = NULL; + nt_list_for_each(cur, &wrap_drivers) { + wrap_driver = container_of(cur, struct wrap_driver, + list); + if (!stricmp(wrap_driver->name, wd->driver_name)) { + wd->driver = wrap_driver; + break; + } else + wrap_driver = NULL; + } + up(&loader_mutex); + if (wrap_driver) + TRACE1("driver %s is loaded", wrap_driver->name); + else + ERROR("couldn't load driver '%s'", wd->driver_name); + } + EXIT1(return wrap_driver); +} + +/* load the driver files from userspace. */ +static int load_sys_files(struct wrap_driver *driver, + struct load_driver *load_driver) +{ + int i, err; + + TRACE1("num_pe_images = %d", load_driver->num_sys_files); + TRACE1("loading driver: %s", load_driver->name); + strncpy(driver->name, load_driver->name, sizeof(driver->name)); + driver->name[sizeof(driver->name)-1] = 0; + TRACE1("driver: %s", driver->name); + err = 0; + driver->num_pe_images = 0; + for (i = 0; i < load_driver->num_sys_files; i++) { + struct pe_image *pe_image; + pe_image = &driver->pe_images[driver->num_pe_images]; + + strncpy(pe_image->name, load_driver->sys_files[i].name, + sizeof(pe_image->name)); + pe_image->name[sizeof(pe_image->name)-1] = 0; + TRACE1("image size: %lu bytes", + (unsigned long)load_driver->sys_files[i].size); + +#ifdef CONFIG_X86_64 +#ifdef PAGE_KERNEL_EXECUTABLE + pe_image->image = + __vmalloc(load_driver->sys_files[i].size, + GFP_KERNEL | __GFP_HIGHMEM, + PAGE_KERNEL_EXECUTABLE); +#elif defined PAGE_KERNEL_EXEC + pe_image->image = + __vmalloc(load_driver->sys_files[i].size, + GFP_KERNEL | __GFP_HIGHMEM, + PAGE_KERNEL_EXEC); +#else +#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC +#endif +#else + /* hate to play with kernel macros, but PAGE_KERNEL_EXEC is + * not available to modules! */ +#ifdef cpu_has_nx + if (cpu_has_nx) + pe_image->image = + __vmalloc(load_driver->sys_files[i].size, + GFP_KERNEL | __GFP_HIGHMEM, + __pgprot(__PAGE_KERNEL & ~_PAGE_NX)); + else + pe_image->image = + vmalloc(load_driver->sys_files[i].size); +#else + pe_image->image = + vmalloc(load_driver->sys_files[i].size); +#endif +#endif + if (!pe_image->image) { + ERROR("couldn't allocate memory"); + err = -ENOMEM; + break; + } + TRACE1("image is at %p", pe_image->image); + + if (copy_from_user(pe_image->image, + load_driver->sys_files[i].data, + load_driver->sys_files[i].size)) { + ERROR("couldn't load file %s", + load_driver->sys_files[i].name); + err = -EFAULT; + break; + } + pe_image->size = load_driver->sys_files[i].size; + driver->num_pe_images++; + } + + if (!err && link_pe_images(driver->pe_images, driver->num_pe_images)) { + ERROR("couldn't prepare driver '%s'", load_driver->name); + err = -EINVAL; + } + + if (driver->num_pe_images < load_driver->num_sys_files || err) { + for (i = 0; i < driver->num_pe_images; i++) + if (driver->pe_images[i].image) + vfree(driver->pe_images[i].image); + driver->num_pe_images = 0; + EXIT1(return err); + } else + EXIT1(return 0); +} + +struct wrap_bin_file *get_bin_file(char *bin_file_name) +{ + int i = 0; + struct wrap_driver *driver, *cur; + + ENTER1("%s", bin_file_name); + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + EXIT1(return NULL); + } + driver = NULL; + nt_list_for_each_entry(cur, &wrap_drivers, list) { + for (i = 0; i < cur->num_bin_files; i++) + if (!stricmp(cur->bin_files[i].name, bin_file_name)) { + driver = cur; + break; + } + if (driver) + break; + } + up(&loader_mutex); + if (!driver) { + TRACE1("coudln't find bin file '%s'", bin_file_name); + return NULL; + } + + if (!driver->bin_files[i].data) { + char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_BIN_FILE, +#if defined(DEBUG) && DEBUG >= 1 + "1", +#else + "0", +#endif + UTILS_VERSION, driver->name, + driver->bin_files[i].name, NULL}; + char *env[] = {NULL}; + int ret; + + TRACE1("loading bin file %s/%s", driver->name, + driver->bin_files[i].name); + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + EXIT1(return NULL); + } + INIT_COMPLETION(loader_complete); + ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1); + if (ret) { + up(&loader_mutex); + ERROR("couldn't load file %s/%s; check system log " + "for messages from 'loadndisdriver' (%d)", + driver->name, driver->bin_files[i].name, ret); + EXIT1(return NULL); + } + wait_for_completion(&loader_complete); + up(&loader_mutex); + if (!driver->bin_files[i].data) { + WARNING("couldn't load binary file %s", + driver->bin_files[i].name); + EXIT1(return NULL); + } + } + EXIT2(return &(driver->bin_files[i])); +} + +/* called with loader_mutex down */ +static int add_bin_file(struct load_driver_file *driver_file) +{ + struct wrap_driver *driver, *cur; + struct wrap_bin_file *bin_file; + int i = 0; + + driver = NULL; + nt_list_for_each_entry(cur, &wrap_drivers, list) { + for (i = 0; i < cur->num_bin_files; i++) + if (!stricmp(cur->bin_files[i].name, + driver_file->name)) { + driver = cur; + break; + } + if (driver) + break; + } + if (!driver) { + ERROR("couldn't find %s", driver_file->name); + return -EINVAL; + } + bin_file = &driver->bin_files[i]; + strncpy(bin_file->name, driver_file->name, sizeof(bin_file->name)); + bin_file->name[sizeof(bin_file->name)-1] = 0; + bin_file->data = vmalloc(driver_file->size); + if (!bin_file->data) { + ERROR("couldn't allocate memory"); + return -ENOMEM; + } + bin_file->size = driver_file->size; + if (copy_from_user(bin_file->data, driver_file->data, bin_file->size)) { + ERROR("couldn't copy data"); + free_bin_file(bin_file); + return -EFAULT; + } + return 0; +} + +void free_bin_file(struct wrap_bin_file *bin_file) +{ + TRACE2("unloading %s", bin_file->name); + if (bin_file->data) + vfree(bin_file->data); + bin_file->data = NULL; + bin_file->size = 0; + EXIT2(return); +} + +/* load firmware files from userspace */ +static int load_bin_files_info(struct wrap_driver *driver, + struct load_driver *load_driver) +{ + struct wrap_bin_file *bin_files; + int i; + + ENTER1("%s, %d", load_driver->name, load_driver->num_bin_files); + driver->num_bin_files = 0; + driver->bin_files = NULL; + if (load_driver->num_bin_files == 0) + EXIT1(return 0); + bin_files = kzalloc(load_driver->num_bin_files * sizeof(*bin_files), + GFP_KERNEL); + if (!bin_files) { + ERROR("couldn't allocate memory"); + EXIT1(return -ENOMEM); + } + + for (i = 0; i < load_driver->num_bin_files; i++) { + strncpy(bin_files[i].name, load_driver->bin_files[i].name, + sizeof(bin_files[i].name)); + bin_files[i].name[sizeof(bin_files[i].name)-1] = 0; + TRACE2("loaded bin file %s", bin_files[i].name); + } + driver->num_bin_files = load_driver->num_bin_files; + driver->bin_files = bin_files; + EXIT1(return 0); +} + +/* load settnigs for a device. called with loader_mutex down */ +static int load_settings(struct wrap_driver *wrap_driver, + struct load_driver *load_driver) +{ + int i, num_settings; + + ENTER1("%p, %p", wrap_driver, load_driver); + + num_settings = 0; + for (i = 0; i < load_driver->num_settings; i++) { + struct load_device_setting *load_setting = + &load_driver->settings[i]; + struct wrap_device_setting *setting; + ULONG data1; + + setting = kzalloc(sizeof(*setting), GFP_KERNEL); + if (!setting) { + ERROR("couldn't allocate memory"); + break; + } + strncpy(setting->name, load_setting->name, + sizeof(setting->name)); + setting->name[sizeof(setting->name)-1] = 0; + strncpy(setting->value, load_setting->value, + sizeof(setting->value)); + setting->value[sizeof(setting->value)-1] = 0; + TRACE2("%p: %s=%s", setting, setting->name, setting->value); + + if (strcmp(setting->name, "driver_version") == 0) { + strncpy(wrap_driver->version, setting->value, + sizeof(wrap_driver->version)); + wrap_driver->version[sizeof(wrap_driver->version)-1] = 0; + } else if (strcmp(setting->name, "class_guid") == 0 && + sscanf(setting->value, "%x", &data1) == 1) { + wrap_driver->dev_type = wrap_device_type(data1); + if (wrap_driver->dev_type < 0) { + WARNING("unknown guid: %x", data1); + wrap_driver->dev_type = 0; + } + } + InsertTailList(&wrap_driver->settings, &setting->list); + num_settings++; + } + /* it is not a fatal error if some settings couldn't be loaded */ + if (num_settings > 0) + EXIT1(return 0); + else + EXIT1(return -EINVAL); +} + +void unload_wrap_device(struct wrap_device *wd) +{ + struct nt_list *cur; + ENTER1("unloading device %p (%04X:%04X:%04X:%04X), driver %s", wd, + wd->vendor, wd->device, wd->subvendor, wd->subdevice, + wd->driver_name); + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + while ((cur = RemoveHeadList(&wd->settings))) { + struct wrap_device_setting *setting; + setting = container_of(cur, struct wrap_device_setting, list); + kfree(setting); + } + RemoveEntryList(&wd->list); + up(&loader_mutex); + kfree(wd); + EXIT1(return); +} + +/* should be called with loader_mutex down */ +void unload_wrap_driver(struct wrap_driver *driver) +{ + int i; + struct driver_object *drv_obj; + struct nt_list *cur, *next; + + ENTER1("unloading driver: %s (%p)", driver->name, driver); + TRACE1("freeing %d images", driver->num_pe_images); + drv_obj = driver->drv_obj; + for (i = 0; i < driver->num_pe_images; i++) + if (driver->pe_images[i].image) { + TRACE1("freeing image at %p", + driver->pe_images[i].image); + vfree(driver->pe_images[i].image); + } + + TRACE1("freeing %d bin files", driver->num_bin_files); + for (i = 0; i < driver->num_bin_files; i++) { + TRACE1("freeing image at %p", driver->bin_files[i].data); + if (driver->bin_files[i].data) + vfree(driver->bin_files[i].data); + } + if (driver->bin_files) + kfree(driver->bin_files); + RtlFreeUnicodeString(&drv_obj->name); + RemoveEntryList(&driver->list); + nt_list_for_each_safe(cur, next, &driver->settings) { + struct wrap_device_setting *setting; + struct ndis_configuration_parameter *param; + + setting = container_of(cur, struct wrap_device_setting, list); + TRACE2("%p", setting); + param = setting->encoded; + if (param) { + TRACE2("%p", param); + if (param->type == NdisParameterString) + RtlFreeUnicodeString(¶m->data.string); + ExFreePool(param); + } + kfree(setting); + } + /* this frees driver */ + free_custom_extensions(drv_obj->drv_ext); + kfree(drv_obj->drv_ext); + TRACE1("drv_obj: %p", drv_obj); + + EXIT1(return); +} + +/* call the entry point of the driver */ +static int start_wrap_driver(struct wrap_driver *driver) +{ + int i; + NTSTATUS ret, res; + struct driver_object *drv_obj; + typeof(driver->pe_images[0].entry) entry; + + ENTER1("%s", driver->name); + drv_obj = driver->drv_obj; + for (ret = res = 0, i = 0; i < driver->num_pe_images; i++) + /* dlls are already started by loader */ + if (driver->pe_images[i].type == IMAGE_FILE_EXECUTABLE_IMAGE) { + entry = driver->pe_images[i].entry; + drv_obj->start = driver->pe_images[i].entry; + drv_obj->driver_size = driver->pe_images[i].size; + TRACE1("entry: %p, %p, drv_obj: %p", + entry, *entry, drv_obj); + res = LIN2WIN2(entry, drv_obj, &drv_obj->name); + ret |= res; + TRACE1("entry returns %08X", res); + break; + } + if (ret) { + ERROR("driver initialization failed: %08X", ret); + RtlFreeUnicodeString(&drv_obj->name); + /* this frees ndis_driver */ + free_custom_extensions(drv_obj->drv_ext); + kfree(drv_obj->drv_ext); + TRACE1("drv_obj: %p", drv_obj); + ObDereferenceObject(drv_obj); + EXIT1(return -EINVAL); + } + EXIT1(return 0); +} + +/* + * add driver to list of loaded driver but make sure this driver is + * not loaded before. called with loader_mutex down + */ +static int add_wrap_driver(struct wrap_driver *driver) +{ + struct wrap_driver *tmp; + + ENTER1("name: %s", driver->name); + nt_list_for_each_entry(tmp, &wrap_drivers, list) { + if (stricmp(tmp->name, driver->name) == 0) { + ERROR("cannot add duplicate driver"); + EXIT1(return -EBUSY); + } + } + InsertHeadList(&wrap_drivers, &driver->list); + EXIT1(return 0); +} + +/* load a driver from userspace and initialize it. called with + * loader_mutex down */ +static int load_user_space_driver(struct load_driver *load_driver) +{ + struct driver_object *drv_obj; + struct ansi_string ansi_reg; + struct wrap_driver *wrap_driver = NULL; + + ENTER1("%p", load_driver); + drv_obj = allocate_object(sizeof(*drv_obj), OBJECT_TYPE_DRIVER, NULL); + if (!drv_obj) { + ERROR("couldn't allocate memory"); + EXIT1(return -ENOMEM); + } + TRACE1("drv_obj: %p", drv_obj); + drv_obj->drv_ext = kzalloc(sizeof(*(drv_obj->drv_ext)), GFP_KERNEL); + if (!drv_obj->drv_ext) { + ERROR("couldn't allocate memory"); + ObDereferenceObject(drv_obj); + EXIT1(return -ENOMEM); + } + InitializeListHead(&drv_obj->drv_ext->custom_ext); + if (IoAllocateDriverObjectExtension(drv_obj, + (void *)WRAP_DRIVER_CLIENT_ID, + sizeof(*wrap_driver), + (void **)&wrap_driver) != + STATUS_SUCCESS) + EXIT1(return -ENOMEM); + TRACE1("driver: %p", wrap_driver); + memset(wrap_driver, 0, sizeof(*wrap_driver)); + InitializeListHead(&wrap_driver->list); + InitializeListHead(&wrap_driver->settings); + InitializeListHead(&wrap_driver->wrap_devices); + wrap_driver->drv_obj = drv_obj; + RtlInitAnsiString(&ansi_reg, "/tmp"); + if (RtlAnsiStringToUnicodeString(&drv_obj->name, &ansi_reg, TRUE) != + STATUS_SUCCESS) { + ERROR("couldn't initialize registry path"); + free_custom_extensions(drv_obj->drv_ext); + kfree(drv_obj->drv_ext); + TRACE1("drv_obj: %p", drv_obj); + ObDereferenceObject(drv_obj); + EXIT1(return -EINVAL); + } + strncpy(wrap_driver->name, load_driver->name, sizeof(wrap_driver->name)); + wrap_driver->name[sizeof(wrap_driver->name)-1] = 0; + if (load_sys_files(wrap_driver, load_driver) || + load_bin_files_info(wrap_driver, load_driver) || + load_settings(wrap_driver, load_driver) || + start_wrap_driver(wrap_driver) || + add_wrap_driver(wrap_driver)) { + unload_wrap_driver(wrap_driver); + EXIT1(return -EINVAL); + } else { + printk(KERN_INFO "%s: driver %s (%s) loaded\n", + DRIVER_NAME, wrap_driver->name, wrap_driver->version); + add_taint(TAINT_PROPRIETARY_MODULE); + EXIT1(return 0); + } +} + +static struct pci_device_id wrap_pci_id_table[] = { + {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID}, +}; + +static struct pci_driver wrap_pci_driver = { + .name = DRIVER_NAME, + .id_table = wrap_pci_id_table, + .probe = wrap_pnp_start_pci_device, + .remove = __devexit_p(wrap_pnp_remove_pci_device), + .suspend = wrap_pnp_suspend_pci_device, + .resume = wrap_pnp_resume_pci_device, +}; + +#ifdef ENABLE_USB +static struct usb_device_id wrap_usb_id_table[] = { + { + .driver_info = 1 + }, +}; + +static struct usb_driver wrap_usb_driver = { + .name = DRIVER_NAME, + .id_table = wrap_usb_id_table, + .probe = wrap_pnp_start_usb_device, + .disconnect = __devexit_p(wrap_pnp_remove_usb_device), + .suspend = wrap_pnp_suspend_usb_device, + .resume = wrap_pnp_resume_usb_device, +}; +#endif + +/* register drivers for pci and usb */ +static void register_devices(void) +{ + int res; + + res = pci_register_driver(&wrap_pci_driver); + if (res < 0) { + ERROR("couldn't register pci driver: %d", res); + wrap_pci_driver.name = NULL; + } + +#ifdef ENABLE_USB + res = usb_register(&wrap_usb_driver); + if (res < 0) { + ERROR("couldn't register usb driver: %d", res); + wrap_usb_driver.name = NULL; + } +#endif + EXIT1(return); +} + +static void unregister_devices(void) +{ + struct nt_list *cur, *next; + + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + nt_list_for_each_safe(cur, next, &wrap_devices) { + struct wrap_device *wd; + wd = container_of(cur, struct wrap_device, list); + set_bit(HW_PRESENT, &wd->hw_status); + } + up(&loader_mutex); + + if (wrap_pci_driver.name) + pci_unregister_driver(&wrap_pci_driver); +#ifdef ENABLE_USB + if (wrap_usb_driver.name) + usb_deregister(&wrap_usb_driver); +#endif +} + +struct wrap_device *load_wrap_device(struct load_device *load_device) +{ + int ret; + struct nt_list *cur; + struct wrap_device *wd = NULL; + char vendor[5], device[5], subvendor[5], subdevice[5], bus[5]; + + ENTER1("%04x, %04x, %04x, %04x", load_device->vendor, + load_device->device, load_device->subvendor, + load_device->subdevice); + if (sprintf(vendor, "%04x", load_device->vendor) == 4 && + sprintf(device, "%04x", load_device->device) == 4 && + sprintf(subvendor, "%04x", load_device->subvendor) == 4 && + sprintf(subdevice, "%04x", load_device->subdevice) == 4 && + sprintf(bus, "%04x", load_device->bus) == 4) { + char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DEVICE, +#if defined(DEBUG) && DEBUG >= 1 + "1", +#else + "0", +#endif + UTILS_VERSION, vendor, device, + subvendor, subdevice, bus, NULL}; + char *env[] = {NULL}; + TRACE2("%s, %s, %s, %s, %s", vendor, device, + subvendor, subdevice, bus); + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + EXIT1(return NULL); + } + INIT_COMPLETION(loader_complete); + ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1); + if (ret) { + up(&loader_mutex); + TRACE1("couldn't load device %04x:%04x; check system " + "log for messages from 'loadndisdriver'", + load_device->vendor, load_device->device); + EXIT1(return NULL); + } + wait_for_completion(&loader_complete); + wd = NULL; + nt_list_for_each(cur, &wrap_devices) { + wd = container_of(cur, struct wrap_device, list); + TRACE2("%p, %04x, %04x, %04x, %04x", wd, wd->vendor, + wd->device, wd->subvendor, wd->subdevice); + if (wd->vendor == load_device->vendor && + wd->device == load_device->device) + break; + else + wd = NULL; + } + up(&loader_mutex); + } else + wd = NULL; + EXIT1(return wd); +} + +struct wrap_device *get_wrap_device(void *dev, int bus) +{ + struct nt_list *cur; + struct wrap_device *wd; + + if (down_interruptible(&loader_mutex)) { + WARNING("couldn't obtain loader_mutex"); + return NULL; + } + wd = NULL; + nt_list_for_each(cur, &wrap_devices) { + wd = container_of(cur, struct wrap_device, list); + if (bus == WRAP_PCI_BUS && + wrap_is_pci_bus(wd->dev_bus) && wd->pci.pdev == dev) + break; + else if (bus == WRAP_USB_BUS && + wrap_is_usb_bus(wd->dev_bus) && wd->usb.udev == dev) + break; + else + wd = NULL; + } + up(&loader_mutex); + return wd; +} + +static DEFINE_MUTEX(ndiswrapper_ioctl_mutex); + +/* called with loader_mutex is down */ +static long wrapper_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct load_driver *load_driver; + struct load_device load_device; + struct load_driver_file load_bin_file; + int ret; + void __user *addr = (void __user *)arg; + + mutex_lock(&ndiswrapper_ioctl_mutex); + + ENTER1("cmd: %u", cmd); + + ret = 0; + switch (cmd) { + case WRAP_IOCTL_LOAD_DEVICE: + if (copy_from_user(&load_device, addr, sizeof(load_device))) { + ret = -EFAULT; + break; + } + TRACE2("%04x, %04x, %04x, %04x", load_device.vendor, + load_device.device, load_device.subvendor, + load_device.subdevice); + if (load_device.vendor) { + struct wrap_device *wd; + wd = kzalloc(sizeof(*wd), GFP_KERNEL); + if (!wd) { + ret = -ENOMEM; + break; + } + InitializeListHead(&wd->settings); + wd->dev_bus = WRAP_BUS(load_device.bus); + wd->vendor = load_device.vendor; + wd->device = load_device.device; + wd->subvendor = load_device.subvendor; + wd->subdevice = load_device.subdevice; + strncpy(wd->conf_file_name, load_device.conf_file_name, + sizeof(wd->conf_file_name)); + wd->conf_file_name[sizeof(wd->conf_file_name)-1] = 0; + strncpy(wd->driver_name, load_device.driver_name, + sizeof(wd->driver_name)); + wd->driver_name[sizeof(wd->driver_name)-1] = 0; + InsertHeadList(&wrap_devices, &wd->list); + ret = 0; + } else + ret = -EINVAL; + break; + case WRAP_IOCTL_LOAD_DRIVER: + TRACE1("loading driver at %p", addr); + load_driver = vmalloc(sizeof(*load_driver)); + if (!load_driver) { + ret = -ENOMEM; + break; + } + if (copy_from_user(load_driver, addr, sizeof(*load_driver))) + ret = -EFAULT; + else + ret = load_user_space_driver(load_driver); + vfree(load_driver); + break; + case WRAP_IOCTL_LOAD_BIN_FILE: + if (copy_from_user(&load_bin_file, addr, sizeof(load_bin_file))) + ret = -EFAULT; + else + ret = add_bin_file(&load_bin_file); + break; + default: + ERROR("unknown ioctl %u", cmd); + ret = -EINVAL; + break; + } + complete(&loader_complete); + + mutex_unlock(&ndiswrapper_ioctl_mutex); + + EXIT1(return ret); +} + +static int wrapper_ioctl_release(struct inode *inode, struct file *file) +{ + ENTER1(""); + return 0; +} + +static struct file_operations wrapper_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = wrapper_ioctl, + .release = wrapper_ioctl_release, +}; + +static struct miscdevice wrapper_misc = { + .name = DRIVER_NAME, + .minor = MISC_DYNAMIC_MINOR, + .fops = &wrapper_fops +}; + +int loader_init(void) +{ + int err; + + InitializeListHead(&wrap_drivers); + InitializeListHead(&wrap_devices); + sema_init(&loader_mutex, 1); + init_completion(&loader_complete); + if ((err = misc_register(&wrapper_misc)) < 0 ) { + ERROR("couldn't register module (%d)", err); + unregister_devices(); + EXIT1(return err); + } + register_devices(); + EXIT1(return 0); +} + +void loader_exit(void) +{ + struct nt_list *cur, *next; + + ENTER1(""); + misc_deregister(&wrapper_misc); + unregister_devices(); + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + nt_list_for_each_safe(cur, next, &wrap_drivers) { + struct wrap_driver *driver; + driver = container_of(cur, struct wrap_driver, list); + unload_wrap_driver(driver); + } + up(&loader_mutex); + EXIT1(return); +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/loader.h +++ linux-2.6.37/ubuntu/ndiswrapper/loader.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _LOADER_H_ +#define _LOADER_H_ + +#include "ndiswrapper.h" + +#ifndef __KERNEL__ +#define __user +#endif + +struct load_driver_file { + char driver_name[MAX_DRIVER_NAME_LEN]; + char name[MAX_DRIVER_NAME_LEN]; + size_t size; + void __user *data; +}; + +struct load_device_setting { + char name[MAX_SETTING_NAME_LEN]; + char value[MAX_SETTING_VALUE_LEN]; +}; + +struct load_device { + int bus; + int vendor; + int device; + int subvendor; + int subdevice; + char conf_file_name[MAX_DRIVER_NAME_LEN]; + char driver_name[MAX_DRIVER_NAME_LEN]; +}; + +struct load_devices { + int count; + struct load_device *devices; +}; + +struct load_driver { + char name[MAX_DRIVER_NAME_LEN]; + char conf_file_name[MAX_DRIVER_NAME_LEN]; + unsigned int num_sys_files; + struct load_driver_file sys_files[MAX_DRIVER_PE_IMAGES]; + unsigned int num_settings; + struct load_device_setting settings[MAX_DEVICE_SETTINGS]; + unsigned int num_bin_files; + struct load_driver_file bin_files[MAX_DRIVER_BIN_FILES]; +}; + +#define WRAP_IOCTL_LOAD_DEVICE _IOW(('N' + 'd' + 'i' + 'S'), 0, \ + struct load_device *) +#define WRAP_IOCTL_LOAD_DRIVER _IOW(('N' + 'd' + 'i' + 'S'), 1, \ + struct load_driver *) +#define WRAP_IOCTL_LOAD_BIN_FILE _IOW(('N' + 'd' + 'i' + 'S'), 2, \ + struct load_driver_file *) + +#define WRAP_CMD_LOAD_DEVICE "load_device" +#define WRAP_CMD_LOAD_DRIVER "load_driver" +#define WRAP_CMD_LOAD_BIN_FILE "load_bin_file" + +int loader_init(void); +void loader_exit(void); + +#ifdef __KERNEL__ +struct wrap_device *load_wrap_device(struct load_device *load_device); +struct wrap_driver *load_wrap_driver(struct wrap_device *device); +struct wrap_bin_file *get_bin_file(char *bin_file_name); +void free_bin_file(struct wrap_bin_file *bin_file); +void unload_wrap_driver(struct wrap_driver *driver); +void unload_wrap_device(struct wrap_device *wd); +struct wrap_device *get_wrap_device(void *dev, int bus_type); + +extern struct semaphore loader_mutex; +#endif + +#endif /* LOADER_H */ + --- linux-2.6.37.orig/ubuntu/ndiswrapper/longlong.h +++ linux-2.6.37/ubuntu/ndiswrapper/longlong.h @@ -0,0 +1,1333 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000 + Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + UQItype -- Unsigned 8 bit type. + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. +*/ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +#ifndef W_TYPE_SIZE +#define W_TYPE_SIZE 32 +#define UWtype USItype +#define UHWtype USItype +#define UDWtype UDItype +#endif + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two + UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first nonzero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! + (E.g. WE32100, IBM360.) */ + +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + +#if defined (__alpha) && W_TYPE_SIZE == 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("umulh %r1,%2,%0" \ + : "=r" ((UDItype) ph) \ + : "%rJ" (__m0), \ + "rI" (__m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 46 +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UDItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ +#ifdef __alpha_cix__ +#define count_leading_zeros(COUNT,X) \ + __asm__("ctlz %1,%0" : "=r"(COUNT) : "r"(X)) +#define count_trailing_zeros(COUNT,X) \ + __asm__("cttz %1,%0" : "=r"(COUNT) : "r"(X)) +#define COUNT_LEADING_ZEROS_0 64 +#else +extern const UQItype __clz_tab[]; +#define count_leading_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr)); \ + __a = __clz_tab[__t ^ 0xff] - 1; \ + __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \ + (COUNT) = 64 - (__clz_tab[__t] + __a*8); \ + } while (0) +#define count_trailing_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __asm__("cmpbge $31,%1,%0" : "=r"(__t) : "r"(__xr)); \ + __t = ~__t & -~__t; \ + __a = ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + __asm__("extbl %1,%2,%0" : "=r"(__t) : "r"(__xr), "r"(__a)); \ + __a <<= 3; \ + __t &= -__t; \ + __a += ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + (COUNT) = __a; \ + } while (0) +#endif /* __alpha_cix__ */ +#endif /* __alpha */ + +#if defined (__arc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.f %1, %4, %5\n\tsbc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) +/* Call libgcc routine. */ +#define umul_ppmm(w1, w0, u, v) \ +do { \ + DWunion __w; \ + __w.ll = __umulsidi3 (u, v); \ + w1 = __w.s.high; \ + w0 = __w.s.low; \ +} while (0) +#define __umulsidi3 __umulsidi3 +UDItype __umulsidi3 (USItype, USItype); +#endif + +#if defined (__arm__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds %1, %4, %5\n\tadc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%r" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rI" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs %1, %4, %5\n\tsbc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "r" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rI" ((USItype) (bl))) +#define umul_ppmm(xh, xl, a, b) \ +{register USItype __t0, __t1, __t2; \ + __asm__ ("%@ Inlined umul_ppmm\n" \ + " mov %2, %5, lsr #16\n" \ + " mov %0, %6, lsr #16\n" \ + " bic %3, %5, %2, lsl #16\n" \ + " bic %4, %6, %0, lsl #16\n" \ + " mul %1, %3, %4\n" \ + " mul %4, %2, %4\n" \ + " mul %3, %0, %3\n" \ + " mul %0, %2, %0\n" \ + " adds %3, %4, %3\n" \ + " addcs %0, %0, #65536\n" \ + " adds %1, %1, %3, lsl #16\n" \ + " adc %0, %0, %3, lsr #16" \ + : "=&r" ((USItype) (xh)), \ + "=r" ((USItype) (xl)), \ + "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ + : "r" ((USItype) (a)), \ + "r" ((USItype) (b)));} +#define UMUL_TIME 20 +#define UDIV_TIME 100 +#endif /* __arm__ */ + +#if defined (__hppa) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rM" ((USItype) (ah)), \ + "rM" ((USItype) (bh)), \ + "%rM" ((USItype) (al)), \ + "rM" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rM" ((USItype) (ah)), \ + "rM" ((USItype) (bh)), \ + "rM" ((USItype) (al)), \ + "rM" ((USItype) (bl))) +#if defined (_PA_RISC1_1) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + union \ + { \ + UDItype __f; \ + struct {USItype __w1, __w0;} __w1w0; \ + } __t; \ + __asm__ ("xmpyu %1,%2,%0" \ + : "=x" (__t.__f) \ + : "x" ((USItype) (u)), \ + "x" ((USItype) (v))); \ + (w1) = __t.__w1w0.__w1; \ + (w0) = __t.__w1w0.__w0; \ + } while (0) +#define UMUL_TIME 8 +#else +#define UMUL_TIME 30 +#endif +#define UDIV_TIME 40 +#define count_leading_zeros(count, x) \ + do { \ + USItype __tmp; \ + __asm__ ( \ + "ldi 1,%0\n" \ +" extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ +" extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n"\ +" ldo 16(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ +" extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n"\ +" ldo 8(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ +" extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n"\ +" ldo 4(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ +" extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n"\ +" ldo 2(%0),%0 ; Yes. Perform add.\n" \ +" extru %1,30,1,%1 ; Extract bit 1.\n" \ +" sub %0,%1,%0 ; Subtract it.\n" \ + : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif + +#if (defined (__i370__) || defined (__mvs__)) && W_TYPE_SIZE == 32 +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "r" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mr %0,%3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (m0), \ + "r" (m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("dr %0,%2" \ + : "=r" (__xx.__ll) \ + : "0" (__xx.__ll), "r" (d)); \ + (q) = __xx.__i.__l; (r) = __xx.__i.__h; \ + } while (0) +#endif + +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl %5,%1\n\tadcl %3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl %5,%1\n\tsbbl %3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mull %3" \ + : "=a" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "rm" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, dv) \ + __asm__ ("divl %4" \ + : "=a" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "rm" ((USItype) (dv))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("bsrl %1,%0" \ + : "=r" (__cbtmp) : "rm" ((USItype) (x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define count_trailing_zeros(count, x) \ + __asm__ ("bsfl %1,%0" : "=r" (count) : "rm" ((USItype)(x))) +#define UMUL_TIME 40 +#define UDIV_TIME 40 +#endif /* 80x86 */ + +#if defined (__i960__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__xx.__ll) \ + : "%dI" ((USItype) (u)), \ + "dI" ((USItype) (v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__w) \ + : "%dI" ((USItype) (u)), \ + "dI" ((USItype) (v))); \ + __w; }) +#endif /* __i960__ */ + +#if defined (__M32R__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + /* The cmp clears the condition bit. */ \ + __asm__ ("cmp %0,%0\n\taddx %%5,%1\n\taddx %%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "r" ((USItype) (bl)) \ + : "cbit") +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + /* The cmp clears the condition bit. */ \ + __asm__ ("cmp %0,%0\n\tsubx %5,%1\n\tsubx %3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl)) \ + : "cbit") +#endif /* __M32R__ */ + +#if defined (__mc68000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \ + : "=d" ((USItype) (sh)), \ + "=&d" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "d" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0" \ + : "=d" ((USItype) (sh)), \ + "=&d" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "d" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) + +/* The '020, '030, '040 and CPU32 have 32x32->64 and 64/32->32q-32r. */ +#if defined (__mc68020__) || defined(mc68020) \ + || defined(__mc68030__) || defined(mc68030) \ + || defined(__mc68040__) || defined(mc68040) \ + || defined(__mcpu32__) || defined(mcpu32) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "dmi" ((USItype) (v))) +#define UMUL_TIME 45 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divu%.l %4,%1:%0" \ + : "=d" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "dmi" ((USItype) (d))) +#define UDIV_TIME 90 +#define sdiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divs%.l %4,%1:%0" \ + : "=d" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "dmi" ((USItype) (d))) + +#else /* not mc68020 */ +#if !defined(__mcf5200__) +/* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX. */ +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("| Inlined umul_ppmm\n" \ + " move%.l %2,%/d0\n" \ + " move%.l %3,%/d1\n" \ + " move%.l %/d0,%/d2\n" \ + " swap %/d0\n" \ + " move%.l %/d1,%/d3\n" \ + " swap %/d1\n" \ + " move%.w %/d2,%/d4\n" \ + " mulu %/d3,%/d4\n" \ + " mulu %/d1,%/d2\n" \ + " mulu %/d0,%/d3\n" \ + " mulu %/d0,%/d1\n" \ + " move%.l %/d4,%/d0\n" \ + " eor%.w %/d0,%/d0\n" \ + " swap %/d0\n" \ + " add%.l %/d0,%/d2\n" \ + " add%.l %/d3,%/d2\n" \ + " jcc 1f\n" \ + " add%.l %#65536,%/d1\n" \ + "1: swap %/d2\n" \ + " moveq %#0,%/d0\n" \ + " move%.w %/d2,%/d0\n" \ + " move%.w %/d4,%/d2\n" \ + " move%.l %/d2,%1\n" \ + " add%.l %/d1,%/d0\n" \ + " move%.l %/d0,%0" \ + : "=g" ((USItype) (xh)), \ + "=g" ((USItype) (xl)) \ + : "g" ((USItype) (a)), \ + "g" ((USItype) (b)) \ + : "d0", "d1", "d2", "d3", "d4") +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#endif /* not mcf5200 */ +#endif /* not mc68020 */ + +/* The '020, '030, '040 and '060 have bitfield insns. */ +#if defined (__mc68020__) || defined(mc68020) \ + || defined(__mc68030__) || defined(mc68030) \ + || defined(__mc68040__) || defined(mc68040) \ + || defined(__mc68060__) || defined(mc68060) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" ((USItype) (count)) \ + : "od" ((USItype) (x)), "n" (0)) +#endif +#endif /* mc68000 */ + +#if defined (__m88000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rJ" ((USItype) (ah)), \ + "rJ" ((USItype) (bh)), \ + "%rJ" ((USItype) (al)), \ + "rJ" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rJ" ((USItype) (ah)), \ + "rJ" ((USItype) (bh)), \ + "rJ" ((USItype) (al)), \ + "rJ" ((USItype) (bl))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("ff1 %0,%1" \ + : "=r" (__cbtmp) \ + : "r" ((USItype) (x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__mc88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mulu.d %0,%1,%2" \ + : "=r" (__xx.__ll) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __q; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("divu.d %0,%1,%2" \ + : "=r" (__q) \ + : "r" (__xx.__ll), \ + "r" ((USItype) (d))); \ + (r) = (n0) - __q * (d); (q) = __q; }) +#define UMUL_TIME 5 +#define UDIV_TIME 25 +#else +#define UMUL_TIME 17 +#define UDIV_TIME 150 +#endif /* __mc88110__ */ +#endif /* __m88000__ */ + +#if defined (__mips__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("multu %2,%3" \ + : "=l" ((USItype) (w0)), \ + "=h" ((USItype) (w1)) \ + : "d" ((USItype) (u)), \ + "d" ((USItype) (v))) +#define UMUL_TIME 10 +#define UDIV_TIME 100 +#endif /* __mips__ */ + +#if defined (__ns32000__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("meid %2,%0" \ + : "=g" (__xx.__ll) \ + : "%0" ((USItype) (u)), \ + "g" ((USItype) (v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((USItype) (u)), \ + "g" ((USItype) (v))); \ + __w; }) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("deid %2,%0" \ + : "=g" (__xx.__ll) \ + : "0" (__xx.__ll), \ + "g" ((USItype) (d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +#define count_trailing_zeros(count,x) \ + do { \ + __asm__ ("ffsd %2,%0" \ + : "=r" ((USItype) (count)) \ + : "0" ((USItype) 0), \ + "r" ((USItype) (x))); \ + } while (0) +#endif /* __ns32000__ */ + +/* FIXME: We should test _IBMR2 here when we add assembly support for the + system vendor compilers. + FIXME: What's needed for gcc PowerPC VxWorks? __vxworks__ is not good + enough, since that hits ARM and m68k too. */ +#if (defined (_ARCH_PPC) /* AIX */ \ + || defined (_ARCH_PWR) /* AIX */ \ + || defined (_ARCH_COM) /* AIX */ \ + || defined (__powerpc__) /* gcc */ \ + || defined (__POWERPC__) /* BEOS */ \ + || defined (__ppc__) /* Darwin */ \ + || defined (PPC) /* GNU/Linux, SysV */ \ + ) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("{cntlz|cntlzw} %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 32 +#if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \ + || defined (__ppc__) || defined (PPC) || defined (__vxworks__) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + SItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 +#define UDIV_TIME 120 +#elif defined (_ARCH_PWR) +#define UMUL_TIME 8 +#define smul_ppmm(xh, xl, m0, m1) \ + __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (xl) : "r" (m0), "r" (m1)) +#define SMUL_TIME 4 +#define sdiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d)) +#define UDIV_TIME 100 +#endif +#endif /* 32-bit POWER architecture variants. */ + +/* We should test _IBMR2 here when we add assembly support for the system + vendor compilers. */ +#if (defined (_ARCH_PPC64) || defined (__powerpc64__)) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + DItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 /* ??? */ +#define UDIV_TIME 120 /* ??? */ +#endif /* 64-bit PowerPC. */ + +#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("a %1,%5\n\tae %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "r" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("s %1,%5\n\tse %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ( \ + "s r2,r2\n" \ +" mts r10,%2\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" cas %0,r2,r0\n" \ +" mfs r10,%1" \ + : "=r" ((USItype) (ph)), \ + "=r" ((USItype) (pl)) \ + : "%r" (__m0), \ + "r" (__m1) \ + : "r2"); \ + (ph) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x))); \ + (count) += 16; \ + } \ + } while (0) +#endif + +#if defined (__sh2__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ( \ + "dmulu.l %2,%3\n\tsts macl,%1\n\tsts mach,%0" \ + : "=r" ((USItype)(w1)), \ + "=r" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "macl", "mach") +#define UMUL_TIME 5 +#endif + +#if defined (__SH5__) && __SHMEDIA__ && W_TYPE_SIZE == 32 +#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v) +#define count_leading_zeros(count, x) \ + do \ + { \ + UDItype x_ = (USItype)(x); \ + SItype c_; \ + \ + __asm__ ("nsb %1, %0" : "=r" (c_) : "r" (x_)); \ + (count) = c_ - 31; \ + } \ + while (0) +#define COUNT_LEADING_ZEROS_0 32 +#endif + +#if defined (__sparc__) && !defined (__arch64__) && !defined (__sparcv9) \ + && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rJ" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "%rJ" ((USItype) (al)), \ + "rI" ((USItype) (bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rJ" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "rJ" ((USItype) (al)), \ + "rI" ((USItype) (bl)) \ + __CLOBBER_CC) +#if defined (__sparc_v8__) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))) +#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \ + __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\ + : "=&r" ((USItype) (__q)), \ + "=&r" ((USItype) (__r)) \ + : "r" ((USItype) (__n1)), \ + "r" ((USItype) (__n0)), \ + "r" ((USItype) (__d))) +#else +#if defined (__sparclite__) +/* This has hardware multiply but not divide. It also has two additional + instructions scan (ffs from high bit) and divscc. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("! Inlined udiv_qrnnd\n" \ +" wr %%g0,%2,%%y ! Not a delayed write for sparclite\n" \ +" tst %%g0\n" \ +" divscc %3,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%0\n" \ +" rd %%y,%1\n" \ +" bl,a 1f\n" \ +" add %1,%4,%1\n" \ +"1: ! End of inline udiv_qrnnd" \ + : "=r" ((USItype) (q)), \ + "=r" ((USItype) (r)) \ + : "r" ((USItype) (n1)), \ + "r" ((USItype) (n0)), \ + "rI" ((USItype) (d)) \ + : "g1" __AND_CLOBBER_CC) +#define UDIV_TIME 37 +#define count_leading_zeros(count, x) \ + do { \ + __asm__ ("scan %1,1,%0" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x))); \ + } while (0) +/* Early sparclites return 63 for an argument of 0, but they warn that future + implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 + undefined. */ +#else +/* SPARC without integer multiplication and divide instructions. + (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm\n" \ +" wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n"\ +" sra %3,31,%%o5 ! Don't move this insn\n" \ +" and %2,%%o5,%%o5 ! Don't move this insn\n" \ +" andcc %%g0,0,%%g1 ! Don't move this insn\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,0,%%g1\n" \ +" add %%g1,%%o5,%0\n" \ +" rd %%y,%1" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "%rI" ((USItype) (u)), \ + "r" ((USItype) (v)) \ + : "g1", "o5" __AND_CLOBBER_CC) +#define UMUL_TIME 39 /* 39 instructions */ +/* It's quite necessary to add this much assembler for the sparc. + The default udiv_qrnnd (in C) is more than 10 times slower! */ +#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \ + __asm__ ("! Inlined udiv_qrnnd\n" \ +" mov 32,%%g1\n" \ +" subcc %1,%2,%%g0\n" \ +"1: bcs 5f\n" \ +" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \ +" sub %1,%2,%1 ! this kills msb of n\n" \ +" addx %1,%1,%1 ! so this can't give carry\n" \ +" subcc %%g1,1,%%g1\n" \ +"2: bne 1b\n" \ +" subcc %1,%2,%%g0\n" \ +" bcs 3f\n" \ +" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \ +" b 3f\n" \ +" sub %1,%2,%1 ! this kills msb of n\n" \ +"4: sub %1,%2,%1\n" \ +"5: addxcc %1,%1,%1\n" \ +" bcc 2b\n" \ +" subcc %%g1,1,%%g1\n" \ +"! Got carry from n. Subtract next step to cancel this carry.\n" \ +" bne 4b\n" \ +" addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n" \ +" sub %1,%2,%1\n" \ +"3: xnor %0,0,%0\n" \ +" ! End of inline udiv_qrnnd" \ + : "=&r" ((USItype) (__q)), \ + "=&r" ((USItype) (__r)) \ + : "r" ((USItype) (__d)), \ + "1" ((USItype) (__n1)), \ + "0" ((USItype) (__n0)) : "g1" __AND_CLOBBER_CC) +#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */ +#endif /* __sparclite__ */ +#endif /* __sparc_v8__ */ +#endif /* sparc32 */ + +#if ((defined (__sparc__) && defined (__arch64__)) || defined (__sparcv9)) \ + && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n\t" \ + "add %r2,%3,%0\n\t" \ + "bcs,a,pn %%xcc, 1f\n\t" \ + "add %0, 1, %0\n" \ + "1:" \ + : "=r" ((UDItype)(sh)), \ + "=&r" ((UDItype)(sl)) \ + : "%rJ" ((UDItype)(ah)), \ + "rI" ((UDItype)(bh)), \ + "%rJ" ((UDItype)(al)), \ + "rI" ((UDItype)(bl)) \ + __CLOBBER_CC) + +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n\t" \ + "sub %r2,%3,%0\n\t" \ + "bcs,a,pn %%xcc, 1f\n\t" \ + "sub %0, 1, %0\n\t" \ + "1:" \ + : "=r" ((UDItype)(sh)), \ + "=&r" ((UDItype)(sl)) \ + : "rJ" ((UDItype)(ah)), \ + "rI" ((UDItype)(bh)), \ + "rJ" ((UDItype)(al)), \ + "rI" ((UDItype)(bl)) \ + __CLOBBER_CC) + +#define umul_ppmm(wh, wl, u, v) \ + do { \ + UDItype tmp1, tmp2, tmp3, tmp4; \ + __asm__ __volatile__ ( \ + "srl %7,0,%3\n\t" \ + "mulx %3,%6,%1\n\t" \ + "srlx %6,32,%2\n\t" \ + "mulx %2,%3,%4\n\t" \ + "sllx %4,32,%5\n\t" \ + "srl %6,0,%3\n\t" \ + "sub %1,%5,%5\n\t" \ + "srlx %5,32,%5\n\t" \ + "addcc %4,%5,%4\n\t" \ + "srlx %7,32,%5\n\t" \ + "mulx %3,%5,%3\n\t" \ + "mulx %2,%5,%5\n\t" \ + "sethi %%hi(0x80000000),%2\n\t" \ + "addcc %4,%3,%4\n\t" \ + "srlx %4,32,%4\n\t" \ + "add %2,%2,%2\n\t" \ + "movcc %%xcc,%%g0,%2\n\t" \ + "addcc %5,%4,%5\n\t" \ + "sllx %3,32,%3\n\t" \ + "add %1,%3,%1\n\t" \ + "add %5,%2,%0" \ + : "=r" ((UDItype)(wh)), \ + "=&r" ((UDItype)(wl)), \ + "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \ + : "r" ((UDItype)(u)), \ + "r" ((UDItype)(v)) \ + __CLOBBER_CC); \ + } while (0) +#define UMUL_TIME 96 +#define UDIV_TIME 230 +#endif /* sparc64 */ + +#if defined (__vax__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl2 %5,%1\n\tadwc %3,%0" \ + : "=g" ((USItype) (sh)), \ + "=&g" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl2 %5,%1\n\tsbwc %3,%0" \ + : "=g" ((USItype) (sh)), \ + "=&g" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union { \ + UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("emul %1,%2,$0,%0" \ + : "=r" (__xx.__ll) \ + : "g" (__m0), \ + "g" (__m1)); \ + (xh) = __xx.__i.__h; \ + (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("ediv %3,%2,%0,%1" \ + : "=g" (q), "=g" (r) \ + : "g" (__xx.__ll), "g" (d)); \ + } while (0) +#endif /* __vax__ */ + +#if defined (__z8000__) && W_TYPE_SIZE == 16 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "%0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "%1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long int __ll; \ + struct {unsigned int __h, __l;} __i; \ + } __xx; \ + unsigned int __m0 = (m0), __m1 = (m1); \ + __asm__ ("mult %S0,%H3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "rQR" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((signed int) __m0 >> 15) & __m1) \ + + (((signed int) __m1 >> 15) & __m0)); \ + } while (0) +#endif /* __z8000__ */ + +#endif /* __GNUC__ */ + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } while (0) +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({DWunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0; \ + UWtype __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + USItype __r; \ + (q) = __udiv_w_sdiv (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +extern const UQItype __clz_tab[]; +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype)1<<2*__BITS4) \ + ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + } while (0) +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif --- linux-2.6.37.orig/ubuntu/ndiswrapper/mkexport.sh +++ linux-2.6.37/ubuntu/ndiswrapper/mkexport.sh @@ -0,0 +1,42 @@ +#! /bin/sh + +# Generate exports symbol table from C files + +input="$1" +output="$2" +exports=$(basename "$output" .h) +exec >"$output" + +echo "/* automatically generated from src */"; + +sed -n -e '/^\(wstdcall\|wfastcall\|noregparm\|__attribute__\)/{ +:more +N +s/\([^{]\)$/\1/ +t more +s/\n{$/;/ +p +}' $input + +echo "#ifdef CONFIG_X86_64"; + +sed -n \ + -e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\ +'WIN_FUNC_DECL(\1, \2)/p' \ + -e 's/.*WIN_FUNC_PTR(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\ +'WIN_FUNC_DECL(\1, \2)/p' $input | sort -u + +echo "#endif" +echo "extern struct wrap_export $exports[];" +echo "struct wrap_export $exports[] = {" + +sed -n \ + -e 's/.*WIN_FUNC(_win_\([^\,]\+\) *\, *\([0-9]\+\)).*/'\ +' WIN_WIN_SYMBOL(\1, \2),/p' \ + -e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/'\ +' WIN_SYMBOL(\1, \2),/p' \ + -e 's/.*WIN_SYMBOL_MAP(\("[^"]\+"\)[ ,\n]\+\([^)]\+\)).*/'\ +' {\1, (generic_func)\2},/p' $input | sort -u + +echo " {NULL, NULL}" +echo "};" --- linux-2.6.37.orig/ubuntu/ndiswrapper/mkstubs.sh +++ linux-2.6.37/ubuntu/ndiswrapper/mkstubs.sh @@ -0,0 +1,12 @@ +#! /bin/sh + +for file in "$@"; do + echo + echo "# automatically generated from $file" + sed -n \ + -e 's/.*WIN_FUNC(\([^\,]\+\) *\, *\([0-9]\+\)).*/\ + win2lin(\1, \2)/p' \ + -e 's/.*WIN_FUNC_PTR(\([^\,]\+\) *\, *\([0-9]\+\)).*/\ + win2lin(\1, \2)/p' \ + $file | sed -e 's/[ \t ]\+//' | sort -u; \ +done --- linux-2.6.37.orig/ubuntu/ndiswrapper/ndis.c +++ linux-2.6.37/ubuntu/ndiswrapper/ndis.c @@ -0,0 +1,2974 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ + +#include "ndis.h" +#include "iw_ndis.h" +#include "wrapndis.h" +#include "pnp.h" +#include "loader.h" +#include +#include +#include "ndis_exports.h" + +#define MAX_ALLOCATED_NDIS_PACKETS TX_RING_SIZE +#define MAX_ALLOCATED_NDIS_BUFFERS TX_RING_SIZE + +static void ndis_worker(worker_param_t dummy); +static work_struct_t ndis_work; +static struct nt_list ndis_work_list; +static spinlock_t ndis_work_list_lock; + +workqueue_struct_t *ndis_wq; +static struct nt_thread *ndis_worker_thread; + +static void *ndis_get_routine_address(char *name); + +wstdcall void WIN_FUNC(NdisInitializeWrapper,4) + (void **driver_handle, struct driver_object *driver, + struct unicode_string *reg_path, void *unused) +{ + ENTER1("handle: %p, driver: %p", driver_handle, driver); + *driver_handle = driver; + EXIT1(return); +} + +wstdcall void WIN_FUNC(NdisTerminateWrapper,2) + (struct device_object *dev_obj, void *system_specific) +{ + EXIT1(return); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterMiniport,3) + (struct driver_object *drv_obj, struct miniport *mp, UINT length) +{ + int min_length; + struct wrap_driver *wrap_driver; + struct ndis_driver *ndis_driver; + + min_length = ((char *)&mp->co_create_vc) - ((char *)mp); + + ENTER1("%p %p %d", drv_obj, mp, length); + + if (mp->major_version < 4) { + ERROR("Driver is using ndis version %d which is too old.", + mp->major_version); + EXIT1(return NDIS_STATUS_BAD_VERSION); + } + + if (length < min_length) { + ERROR("Characteristics length %d is too small", length); + EXIT1(return NDIS_STATUS_BAD_CHARACTERISTICS); + } + + TRACE1("%d.%d, %d, %u", mp->major_version, mp->minor_version, length, + (u32)sizeof(struct miniport)); + wrap_driver = IoGetDriverObjectExtension(drv_obj, + (void *)WRAP_DRIVER_CLIENT_ID); + if (!wrap_driver) { + ERROR("couldn't get wrap_driver"); + EXIT1(return NDIS_STATUS_RESOURCES); + } + if (IoAllocateDriverObjectExtension( + drv_obj, (void *)NDIS_DRIVER_CLIENT_ID, + sizeof(*ndis_driver), (void **)&ndis_driver) != + STATUS_SUCCESS) + EXIT1(return NDIS_STATUS_RESOURCES); + wrap_driver->ndis_driver = ndis_driver; + TRACE1("driver: %p", ndis_driver); + memcpy(&ndis_driver->mp, mp, min_t(int, sizeof(*mp), length)); + + DBG_BLOCK(2) { + int i; + void **func; + char *mp_funcs[] = { + "queryinfo", "reconfig", "reset", "send", "setinfo", + "tx_data", "return_packet", "send_packets", + "alloc_complete", "co_create_vc", "co_delete_vc", + "co_activate_vc", "co_deactivate_vc", + "co_send_packets", "co_request", "cancel_send_packets", + "pnp_event_notify", "shutdown", + }; + func = (void **)&ndis_driver->mp.queryinfo; + for (i = 0; i < (sizeof(mp_funcs) / sizeof(mp_funcs[0])); i++) + TRACE2("function '%s' is at %p", mp_funcs[i], func[i]); + } + EXIT1(return NDIS_STATUS_SUCCESS); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterDevice,6) + (struct driver_object *drv_obj, struct unicode_string *dev_name, + struct unicode_string *link, void **funcs, + struct device_object **dev_obj, void **dev_obj_handle) +{ + NTSTATUS status; + struct device_object *tmp; + int i; + + ENTER1("%p, %p, %p", drv_obj, dev_name, link); + status = IoCreateDevice(drv_obj, 0, dev_name, FILE_DEVICE_NETWORK, 0, + FALSE, &tmp); + + if (status != STATUS_SUCCESS) + EXIT1(return NDIS_STATUS_RESOURCES); + if (link) + status = IoCreateSymbolicLink(link, dev_name); + if (status != STATUS_SUCCESS) { + IoDeleteDevice(tmp); + EXIT1(return NDIS_STATUS_RESOURCES); + } + + *dev_obj = tmp; + *dev_obj_handle = *dev_obj; + for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) + if (funcs[i] && i != IRP_MJ_PNP && i != IRP_MJ_POWER) { + drv_obj->major_func[i] = funcs[i]; + TRACE1("mj_fn for 0x%x is at %p", i, funcs[i]); + } + EXIT1(return NDIS_STATUS_SUCCESS); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMDeregisterDevice,1) + (struct device_object *dev_obj) +{ + ENTER2("%p", dev_obj); + IoDeleteDevice(dev_obj); + return NDIS_STATUS_SUCCESS; +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemoryWithTag,3) + (void **dest, UINT length, ULONG tag) +{ + void *addr; + + assert_irql(_irql_ <= DISPATCH_LEVEL); + addr = ExAllocatePoolWithTag(NonPagedPool, length, tag); + TRACE4("%p", addr); + if (addr) { + *dest = addr; + EXIT4(return NDIS_STATUS_SUCCESS); + } else + EXIT4(return NDIS_STATUS_FAILURE); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemory,4) + (void **dest, UINT length, UINT flags, NDIS_PHY_ADDRESS highest_address) +{ + return NdisAllocateMemoryWithTag(dest, length, 0); +} + +/* length_tag is either length or tag, depending on if + * NdisAllocateMemory or NdisAllocateMemoryTag is used to allocate + * memory */ +wstdcall void WIN_FUNC(NdisFreeMemory,3) + (void *addr, UINT length_tag, UINT flags) +{ + TRACE4("%p", addr); + ExFreePool(addr); +} + +noregparm void WIN_FUNC(NdisWriteErrorLogEntry,12) + (struct driver_object *drv_obj, ULONG error, ULONG count, ...) +{ + va_list args; + int i; + ULONG code; + + va_start(args, count); + ERROR("log: %08X, count: %d, return_address: %p", + error, count, __builtin_return_address(0)); + for (i = 0; i < count; i++) { + code = va_arg(args, ULONG); + ERROR("code: 0x%x", code); + } + va_end(args); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisOpenConfiguration,3) + (NDIS_STATUS *status, struct ndis_mp_block **conf_handle, + struct ndis_mp_block *handle) +{ + ENTER2("%p", conf_handle); + *conf_handle = handle; + *status = NDIS_STATUS_SUCCESS; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisOpenProtocolConfiguration,3) + (NDIS_STATUS *status, void **confhandle, + struct unicode_string *section) +{ + ENTER2("%p", confhandle); + *status = NDIS_STATUS_SUCCESS; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByName,4) + (NDIS_STATUS *status, void *handle, + struct unicode_string *key, void **subkeyhandle) +{ + struct ansi_string ansi; + ENTER2(""); + if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE) == STATUS_SUCCESS) { + TRACE2("%s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + *subkeyhandle = handle; + *status = NDIS_STATUS_SUCCESS; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByIndex,5) + (NDIS_STATUS *status, void *handle, ULONG index, + struct unicode_string *key, void **subkeyhandle) +{ + ENTER2("%u", index); +// *subkeyhandle = handle; + *status = NDIS_STATUS_FAILURE; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisCloseConfiguration,1) + (void *handle) +{ + /* instead of freeing all configuration parameters as we are + * supposed to do here, we free them when the device is + * removed */ + ENTER2("%p", handle); + return; +} + +wstdcall void WIN_FUNC(NdisOpenFile,5) + (NDIS_STATUS *status, struct wrap_bin_file **file, + UINT *filelength, struct unicode_string *filename, + NDIS_PHY_ADDRESS highest_address) +{ + struct ansi_string ansi; + struct wrap_bin_file *bin_file; + + ENTER2("%p, %d, %llx, %p", status, *filelength, highest_address, *file); + if (RtlUnicodeStringToAnsiString(&ansi, filename, TRUE) != + STATUS_SUCCESS) { + *status = NDIS_STATUS_RESOURCES; + EXIT2(return); + } + TRACE2("%s", ansi.buf); + bin_file = get_bin_file(ansi.buf); + if (bin_file) { + *file = bin_file; + *filelength = bin_file->size; + *status = NDIS_STATUS_SUCCESS; + } else + *status = NDIS_STATUS_FILE_NOT_FOUND; + + RtlFreeAnsiString(&ansi); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisMapFile,3) + (NDIS_STATUS *status, void **mappedbuffer, struct wrap_bin_file *file) +{ + ENTER2("%p", file); + + if (!file) { + *status = NDIS_STATUS_ALREADY_MAPPED; + EXIT2(return); + } + + *status = NDIS_STATUS_SUCCESS; + *mappedbuffer = file->data; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisUnmapFile,1) + (struct wrap_bin_file *file) +{ + ENTER2("%p", file); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisCloseFile,1) + (struct wrap_bin_file *file) +{ + ENTER2("%p", file); + free_bin_file(file); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisGetSystemUpTime,1) + (ULONG *ms) +{ + *ms = 1000 * jiffies / HZ; + EXIT5(return); +} + +wstdcall ULONG WIN_FUNC(NDIS_BUFFER_TO_SPAN_PAGES,1) + (ndis_buffer *buffer) +{ + ULONG n, length; + + if (buffer == NULL) + EXIT2(return 0); + if (MmGetMdlByteCount(buffer) == 0) + EXIT2(return 1); + + length = MmGetMdlByteCount(buffer); + n = SPAN_PAGES(MmGetMdlVirtualAddress(buffer), length); + TRACE4("%p, %p, %d, %d", buffer->startva, buffer->mappedsystemva, + length, n); + EXIT3(return n); +} + +wstdcall void WIN_FUNC(NdisGetBufferPhysicalArraySize,2) + (ndis_buffer *buffer, UINT *arraysize) +{ + ENTER3("%p", buffer); + *arraysize = NDIS_BUFFER_TO_SPAN_PAGES(buffer); + EXIT3(return); +} + +static struct ndis_configuration_parameter * +ndis_encode_setting(struct wrap_device_setting *setting, + enum ndis_parameter_type type) +{ + struct ansi_string ansi; + struct ndis_configuration_parameter *param; + + param = setting->encoded; + if (param) { + if (param->type == type) + EXIT2(return param); + if (param->type == NdisParameterString) + RtlFreeUnicodeString(¶m->data.string); + setting->encoded = NULL; + } else + param = ExAllocatePoolWithTag(NonPagedPool, sizeof(*param), 0); + if (!param) { + ERROR("couldn't allocate memory"); + return NULL; + } + switch(type) { + case NdisParameterInteger: + param->data.integer = simple_strtol(setting->value, NULL, 0); + TRACE2("0x%x", (ULONG)param->data.integer); + break; + case NdisParameterHexInteger: + param->data.integer = simple_strtol(setting->value, NULL, 16); + TRACE2("0x%x", (ULONG)param->data.integer); + break; + case NdisParameterString: + RtlInitAnsiString(&ansi, setting->value); + TRACE2("'%s'", ansi.buf); + if (RtlAnsiStringToUnicodeString(¶m->data.string, + &ansi, TRUE)) { + ExFreePool(param); + EXIT2(return NULL); + } + break; + case NdisParameterBinary: + param->data.integer = simple_strtol(setting->value, NULL, 2); + TRACE2("0x%x", (ULONG)param->data.integer); + break; + default: + ERROR("unknown type: %d", type); + ExFreePool(param); + return NULL; + } + param->type = type; + setting->encoded = param; + EXIT2(return param); +} + +static int ndis_decode_setting(struct wrap_device_setting *setting, + struct ndis_configuration_parameter *param) +{ + struct ansi_string ansi; + struct ndis_configuration_parameter *prev; + + ENTER2("%p, %p", setting, param); + prev = setting->encoded; + if (prev && prev->type == NdisParameterString) { + RtlFreeUnicodeString(&prev->data.string); + setting->encoded = NULL; + } + switch(param->type) { + case NdisParameterInteger: + snprintf(setting->value, sizeof(u32), "%u", + param->data.integer); + setting->value[sizeof(ULONG)] = 0; + break; + case NdisParameterHexInteger: + snprintf(setting->value, sizeof(u32), "%x", + param->data.integer); + setting->value[sizeof(ULONG)] = 0; + break; + case NdisParameterString: + ansi.buf = setting->value; + ansi.max_length = MAX_SETTING_VALUE_LEN; + if ((RtlUnicodeStringToAnsiString(&ansi, ¶m->data.string, + FALSE) != STATUS_SUCCESS) + || ansi.length >= MAX_SETTING_VALUE_LEN) { + EXIT1(return -1); + } + if (ansi.length == ansi.max_length) + ansi.length--; + setting->value[ansi.length] = 0; + break; + case NdisParameterBinary: + snprintf(setting->value, sizeof(u32), "%u", + param->data.integer); + setting->value[sizeof(ULONG)] = 0; + break; + default: + TRACE2("unknown setting type: %d", param->type); + return -1; + } + TRACE2("setting changed %s='%s', %d", setting->name, setting->value, + ansi.length); + return 0; +} + +static int read_setting(struct nt_list *setting_list, char *keyname, int length, + struct ndis_configuration_parameter **param, + enum ndis_parameter_type type) +{ + struct wrap_device_setting *setting; + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + nt_list_for_each_entry(setting, setting_list, list) { + if (strnicmp(keyname, setting->name, length) == 0) { + TRACE2("setting %s='%s'", keyname, setting->value); + up(&loader_mutex); + *param = ndis_encode_setting(setting, type); + if (*param) + EXIT2(return 0); + else + EXIT2(return -1); + } + } + up(&loader_mutex); + EXIT2(return -1); +} + +wstdcall void WIN_FUNC(NdisReadConfiguration,5) + (NDIS_STATUS *status, struct ndis_configuration_parameter **param, + struct ndis_mp_block *nmb, struct unicode_string *key, + enum ndis_parameter_type type) +{ + struct ansi_string ansi; + int ret; + + ENTER2("nmb: %p", nmb); + ret = RtlUnicodeStringToAnsiString(&ansi, key, TRUE); + if (ret != STATUS_SUCCESS || ansi.buf == NULL) { + *param = NULL; + *status = NDIS_STATUS_FAILURE; + RtlFreeAnsiString(&ansi); + EXIT2(return); + } + TRACE2("%d, %s", type, ansi.buf); + + if (read_setting(&nmb->wnd->wd->settings, ansi.buf, + ansi.length, param, type) == 0 || + read_setting(&nmb->wnd->wd->driver->settings, ansi.buf, + ansi.length, param, type) == 0) + *status = NDIS_STATUS_SUCCESS; + else { + TRACE2("setting %s not found (type:%d)", ansi.buf, type); + *status = NDIS_STATUS_FAILURE; + } + RtlFreeAnsiString(&ansi); + EXIT2(return); + +} + +wstdcall void WIN_FUNC(NdisWriteConfiguration,4) + (NDIS_STATUS *status, struct ndis_mp_block *nmb, + struct unicode_string *key, struct ndis_configuration_parameter *param) +{ + struct ansi_string ansi; + char *keyname; + struct wrap_device_setting *setting; + + ENTER2("nmb: %p", nmb); + if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE)) { + *status = NDIS_STATUS_FAILURE; + EXIT2(return); + } + keyname = ansi.buf; + TRACE2("%s", keyname); + + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + nt_list_for_each_entry(setting, &nmb->wnd->wd->settings, list) { + if (strnicmp(keyname, setting->name, ansi.length) == 0) { + up(&loader_mutex); + if (ndis_decode_setting(setting, param)) + *status = NDIS_STATUS_FAILURE; + else + *status = NDIS_STATUS_SUCCESS; + RtlFreeAnsiString(&ansi); + EXIT2(return); + } + } + up(&loader_mutex); + setting = kzalloc(sizeof(*setting), GFP_KERNEL); + if (setting) { + if (ansi.length == ansi.max_length) + ansi.length--; + memcpy(setting->name, keyname, ansi.length); + setting->name[ansi.length] = 0; + if (ndis_decode_setting(setting, param)) + *status = NDIS_STATUS_FAILURE; + else { + *status = NDIS_STATUS_SUCCESS; + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + InsertTailList(&nmb->wnd->wd->settings, &setting->list); + up(&loader_mutex); + } + } else + *status = NDIS_STATUS_RESOURCES; + + RtlFreeAnsiString(&ansi); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisReadNetworkAddress,4) + (NDIS_STATUS *status, void **addr, UINT *len, + struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + struct ndis_configuration_parameter *param; + struct unicode_string key; + struct ansi_string ansi; + typeof(wnd->mac) mac; + int i, ret; + + ENTER2("%p", nmb); + RtlInitAnsiString(&ansi, "NetworkAddress"); + *status = NDIS_STATUS_FAILURE; + if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE) != STATUS_SUCCESS) + EXIT1(return); + + NdisReadConfiguration(&ret, ¶m, nmb, &key, NdisParameterString); + RtlFreeUnicodeString(&key); + if (ret != NDIS_STATUS_SUCCESS) + EXIT1(return); + ret = RtlUnicodeStringToAnsiString(&ansi, ¶m->data.string, TRUE); + if (ret != STATUS_SUCCESS) + EXIT1(return); + + i = 0; + if (ansi.length >= 2 * sizeof(mac)) { + for (i = 0; i < sizeof(mac); i++) { + char c[3]; + int x; + c[0] = ansi.buf[i*2]; + c[1] = ansi.buf[i*2+1]; + c[2] = 0; + ret = sscanf(c, "%x", &x); + if (ret != 1) + break; + mac[i] = x; + } + } + TRACE2("%s, %d, " MACSTR, ansi.buf, i, MAC2STR(mac)); + RtlFreeAnsiString(&ansi); + if (i == sizeof(mac)) { + memcpy(wnd->mac, mac, sizeof(wnd->mac)); + *len = sizeof(mac); + *addr = wnd->mac; + *status = NDIS_STATUS_SUCCESS; + } + EXIT1(return); +} + +wstdcall void WIN_FUNC(NdisInitializeString,2) + (struct unicode_string *dest, UCHAR *src) +{ + struct ansi_string ansi; + + ENTER2(""); + if (src == NULL) { + dest->length = dest->max_length = 0; + dest->buf = NULL; + } else { + RtlInitAnsiString(&ansi, src); + /* the string is freed with NdisFreeMemory */ + RtlAnsiStringToUnicodeString(dest, &ansi, TRUE); + } + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisInitAnsiString,2) + (struct ansi_string *dst, CHAR *src) +{ + RtlInitAnsiString(dst, src); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisInitUnicodeString,2) + (struct unicode_string *dest, const wchar_t *src) +{ + RtlInitUnicodeString(dest, src); + return; +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisAnsiStringToUnicodeString,2) + (struct unicode_string *dst, struct ansi_string *src) +{ + ENTER2(""); + if (dst == NULL || src == NULL) + EXIT2(return NDIS_STATUS_FAILURE); + if (RtlAnsiStringToUnicodeString(dst, src, FALSE) == STATUS_SUCCESS) + return NDIS_STATUS_SUCCESS; + else + return NDIS_STATUS_FAILURE; +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisUnicodeStringToAnsiString,2) + (struct ansi_string *dst, struct unicode_string *src) +{ + ENTER2(""); + if (dst == NULL || src == NULL) + EXIT2(return NDIS_STATUS_FAILURE); + if (RtlUnicodeStringToAnsiString(dst, src, FALSE) == STATUS_SUCCESS) + return NDIS_STATUS_SUCCESS; + else + return NDIS_STATUS_FAILURE; +} + +wstdcall NTSTATUS WIN_FUNC(NdisUpcaseUnicodeString,2) + (struct unicode_string *dst, struct unicode_string *src) +{ + EXIT2(return RtlUpcaseUnicodeString(dst, src, FALSE)); +} + +wstdcall void WIN_FUNC(NdisMSetAttributesEx,5) + (struct ndis_mp_block *nmb, void *mp_ctx, + UINT hangcheck_interval, UINT attributes, ULONG adaptertype) +{ + struct ndis_device *wnd; + + ENTER1("%p, %p, %d, %08x, %d", nmb, mp_ctx, hangcheck_interval, + attributes, adaptertype); + wnd = nmb->wnd; + nmb->mp_ctx = mp_ctx; + wnd->attributes = attributes; + + if ((attributes & NDIS_ATTRIBUTE_BUS_MASTER) && + wrap_is_pci_bus(wnd->wd->dev_bus)) + pci_set_master(wnd->wd->pci.pdev); + + if (hangcheck_interval > 0) + wnd->hangcheck_interval = 2 * hangcheck_interval * HZ; + else + wnd->hangcheck_interval = 2 * HZ; + + EXIT1(return); +} + +wstdcall ULONG WIN_FUNC(NdisReadPciSlotInformation,5) + (struct ndis_mp_block *nmb, ULONG slot, + ULONG offset, char *buf, ULONG len) +{ + struct wrap_device *wd = nmb->wnd->wd; + ULONG i; + for (i = 0; i < len; i++) + if (pci_read_config_byte(wd->pci.pdev, offset + i, &buf[i]) != + PCIBIOS_SUCCESSFUL) + break; + DBG_BLOCK(2) { + if (i != len) + WARNING("%u, %u", i, len); + } + return i; +} + +wstdcall ULONG WIN_FUNC(NdisImmediateReadPciSlotInformation,5) + (struct ndis_mp_block *nmb, ULONG slot, + ULONG offset, char *buf, ULONG len) +{ + return NdisReadPciSlotInformation(nmb, slot, offset, buf, len); +} + +wstdcall ULONG WIN_FUNC(NdisWritePciSlotInformation,5) + (struct ndis_mp_block *nmb, ULONG slot, + ULONG offset, char *buf, ULONG len) +{ + struct wrap_device *wd = nmb->wnd->wd; + ULONG i; + for (i = 0; i < len; i++) + if (pci_write_config_byte(wd->pci.pdev, offset + i, buf[i]) != + PCIBIOS_SUCCESSFUL) + break; + DBG_BLOCK(2) { + if (i != len) + WARNING("%u, %u", i, len); + } + return i; +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterIoPortRange,4) + (void **virt, struct ndis_mp_block *nmb, UINT start, UINT len) +{ + ENTER3("%08x %08x", start, len); + *virt = (void *)(ULONG_PTR)start; + return NDIS_STATUS_SUCCESS; +} + +wstdcall void WIN_FUNC(NdisMDeregisterIoPortRange,4) + (struct ndis_mp_block *nmb, UINT start, UINT len, void* virt) +{ + ENTER1("%08x %08x", start, len); +} + +wstdcall void WIN_FUNC(NdisReadPortUchar,3) + (struct ndis_mp_block *nmb, ULONG port, char *data) +{ + *data = inb(port); +} + +wstdcall void WIN_FUNC(NdisImmediateReadPortUchar,3) + (struct ndis_mp_block *nmb, ULONG port, char *data) +{ + *data = inb(port); +} + +wstdcall void WIN_FUNC(NdisWritePortUchar,3) + (struct ndis_mp_block *nmb, ULONG port, char data) +{ + outb(data, port); +} + +wstdcall void WIN_FUNC(NdisImmediateWritePortUchar,3) + (struct ndis_mp_block *nmb, ULONG port, char data) +{ + outb(data, port); +} + +wstdcall void WIN_FUNC(NdisMQueryAdapterResources,4) + (NDIS_STATUS *status, struct ndis_mp_block *nmb, + NDIS_RESOURCE_LIST *resource_list, UINT *size) +{ + struct ndis_device *wnd = nmb->wnd; + NDIS_RESOURCE_LIST *list; + UINT resource_length; + + list = &wnd->wd->resource_list->list->partial_resource_list; + resource_length = sizeof(struct cm_partial_resource_list) + + sizeof(struct cm_partial_resource_descriptor) * + (list->count - 1); + TRACE2("%p, %p,%d (%d), %p %d %d", wnd, resource_list, *size, + resource_length, &list->partial_descriptors[list->count-1], + list->partial_descriptors[list->count-1].u.interrupt.level, + list->partial_descriptors[list->count-1].u.interrupt.vector); + if (*size < sizeof(*list)) { + *size = resource_length; + *status = NDIS_STATUS_BUFFER_TOO_SHORT; + } else { + ULONG count; + if (*size >= resource_length) { + *size = resource_length; + count = list->count; + } else { + UINT n = sizeof(*list); + count = 1; + while (count++ < list->count && n < *size) + n += sizeof(list->partial_descriptors); + *size = n; + } + memcpy(resource_list, list, *size); + resource_list->count = count; + *status = NDIS_STATUS_SUCCESS; + } + EXIT2(return); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMPciAssignResources,3) + (struct ndis_mp_block *nmb, ULONG slot_number, + NDIS_RESOURCE_LIST **resources) +{ + struct ndis_device *wnd = nmb->wnd; + + ENTER2("%p, %p", wnd, wnd->wd->resource_list); + *resources = &wnd->wd->resource_list->list->partial_resource_list; + EXIT2(return NDIS_STATUS_SUCCESS); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMMapIoSpace,4) + (void __iomem **virt, struct ndis_mp_block *nmb, + NDIS_PHY_ADDRESS phy_addr, UINT len) +{ + struct ndis_device *wnd = nmb->wnd; + + ENTER2("%Lx, %d", phy_addr, len); + *virt = MmMapIoSpace(phy_addr, len, MmCached); + if (*virt == NULL) { + ERROR("ioremap failed"); + EXIT2(return NDIS_STATUS_FAILURE); + } + wnd->mem_start = phy_addr; + wnd->mem_end = phy_addr + len; + TRACE2("%p", *virt); + EXIT2(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisMUnmapIoSpace,3) + (struct ndis_mp_block *nmb, void __iomem *virt, UINT len) +{ + ENTER2("%p, %d", virt, len); + MmUnmapIoSpace(virt, len); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisAllocateSpinLock,1) + (struct ndis_spinlock *lock) +{ + TRACE4("lock %p, %p", lock, &lock->klock); + KeInitializeSpinLock(&lock->klock); + lock->irql = PASSIVE_LEVEL; + return; +} + +wstdcall void WIN_FUNC(NdisFreeSpinLock,1) + (struct ndis_spinlock *lock) +{ + TRACE4("lock %p, %p", lock, &lock->klock); + return; +} + +wstdcall void WIN_FUNC(NdisAcquireSpinLock,1) + (struct ndis_spinlock *lock) +{ + ENTER6("lock %p, %p", lock, &lock->klock); +// assert_irql(_irql_ <= DISPATCH_LEVEL); + lock->irql = nt_spin_lock_irql(&lock->klock, DISPATCH_LEVEL); + return; +} + +wstdcall void WIN_FUNC(NdisReleaseSpinLock,1) + (struct ndis_spinlock *lock) +{ + ENTER6("lock %p, %p", lock, &lock->klock); +// assert_irql(_irql_ == DISPATCH_LEVEL); + nt_spin_unlock_irql(&lock->klock, lock->irql); + return; +} + +wstdcall void WIN_FUNC(NdisDprAcquireSpinLock,1) + (struct ndis_spinlock *lock) +{ + ENTER6("lock %p", &lock->klock); +// assert_irql(_irql_ == DISPATCH_LEVEL); + nt_spin_lock(&lock->klock); + return; +} + +wstdcall void WIN_FUNC(NdisDprReleaseSpinLock,1) + (struct ndis_spinlock *lock) +{ + ENTER6("lock %p", &lock->klock); +// assert_irql(_irql_ == DISPATCH_LEVEL); + nt_spin_unlock(&lock->klock); + return; +} + +wstdcall void WIN_FUNC(NdisInitializeReadWriteLock,1) + (struct ndis_rw_lock *rw_lock) +{ + ENTER3("%p", rw_lock); + memset(rw_lock, 0, sizeof(*rw_lock)); + KeInitializeSpinLock(&rw_lock->klock); + return; +} + +/* read/write locks are implemented in a rather simplisitic way - we + * should probably use Linux's rw_lock implementation */ + +wstdcall void WIN_FUNC(NdisAcquireReadWriteLock,3) + (struct ndis_rw_lock *rw_lock, BOOLEAN write, + struct lock_state *lock_state) +{ + if (write) { + while (1) { + if (cmpxchg(&rw_lock->count, 0, -1) == 0) + return; + while (rw_lock->count) + cpu_relax(); + } + return; + } + while (1) { + typeof(rw_lock->count) count; + while ((count = rw_lock->count) < 0) + cpu_relax(); + if (cmpxchg(&rw_lock->count, count, count + 1) == count) + return; + } +} + +wstdcall void WIN_FUNC(NdisReleaseReadWriteLock,2) + (struct ndis_rw_lock *rw_lock, struct lock_state *lock_state) +{ + if (rw_lock->count > 0) + pre_atomic_add(rw_lock->count, -1); + else if (rw_lock->count == -1) + rw_lock->count = 0; + else + WARNING("invalid state: %d", rw_lock->count); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMAllocateMapRegisters,5) + (struct ndis_mp_block *nmb, UINT dmachan, + NDIS_DMA_SIZE dmasize, ULONG basemap, ULONG max_buf_size) +{ + struct ndis_device *wnd = nmb->wnd; + + ENTER2("%p, %d %d %d %d", wnd, dmachan, dmasize, basemap, max_buf_size); + if (wnd->dma_map_count > 0) { + WARNING("%s: map registers already allocated: %u", + wnd->net_dev->name, wnd->dma_map_count); + EXIT2(return NDIS_STATUS_RESOURCES); + } + if (dmasize == NDIS_DMA_24BITS) { + if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(24)) || + pci_set_consistent_dma_mask(wnd->wd->pci.pdev, + DMA_BIT_MASK(24))) + WARNING("setting dma mask failed"); + } else if (dmasize == NDIS_DMA_32BITS) { + /* consistent dma is in low 32-bits by default */ + if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(32))) + WARNING("setting dma mask failed"); +#ifdef CONFIG_X86_64 + } else if (dmasize == NDIS_DMA_64BITS) { + if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(64)) || + pci_set_consistent_dma_mask(wnd->wd->pci.pdev, + DMA_BIT_MASK(64))) + WARNING("setting dma mask failed"); + else + wnd->net_dev->features |= NETIF_F_HIGHDMA; +#endif + } + /* since memory for buffer is allocated with kmalloc, buffer + * is physically contiguous, so entire map will fit in one + * register */ + if (basemap > 64) { + WARNING("Windows driver %s requesting too many (%u) " + "map registers", wnd->wd->driver->name, basemap); + /* As per NDIS, NDIS_STATUS_RESOURCES should be + * returned, but with that Atheros PCI driver fails - + * for now tolerate it */ +// EXIT2(return NDIS_STATUS_RESOURCES); + } + + wnd->dma_map_addr = kmalloc(basemap * sizeof(*(wnd->dma_map_addr)), + GFP_KERNEL); + if (!wnd->dma_map_addr) + EXIT2(return NDIS_STATUS_RESOURCES); + memset(wnd->dma_map_addr, 0, basemap * sizeof(*(wnd->dma_map_addr))); + wnd->dma_map_count = basemap; + TRACE2("%u", wnd->dma_map_count); + EXIT2(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisMFreeMapRegisters,1) + (struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + int i; + + ENTER2("wnd: %p", wnd); + if (wnd->dma_map_addr) { + for (i = 0; i < wnd->dma_map_count; i++) { + if (wnd->dma_map_addr[i]) + WARNING("%s: dma addr %p not freed by " + "Windows driver", wnd->net_dev->name, + (void *)wnd->dma_map_addr[i]); + } + kfree(wnd->dma_map_addr); + wnd->dma_map_addr = NULL; + } else + WARNING("map registers already freed?"); + wnd->dma_map_count = 0; + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisMStartBufferPhysicalMapping,6) + (struct ndis_mp_block *nmb, ndis_buffer *buf, + ULONG index, BOOLEAN write_to_dev, + struct ndis_phy_addr_unit *phy_addr_array, UINT *array_size) +{ + struct ndis_device *wnd = nmb->wnd; + + ENTER3("%p, %p, %u, %u", wnd, buf, index, wnd->dma_map_count); + if (unlikely(wnd->sg_dma_size || !write_to_dev || + index >= wnd->dma_map_count)) { + WARNING("invalid request: %d, %d, %d, %d", wnd->sg_dma_size, + write_to_dev, index, wnd->dma_map_count); + phy_addr_array[0].phy_addr = 0; + phy_addr_array[0].length = 0; + *array_size = 0; + return; + } + if (wnd->dma_map_addr[index]) { + TRACE2("buffer %p at %d is already mapped: %lx", buf, index, + (unsigned long)wnd->dma_map_addr[index]); +// *array_size = 1; + return; + } + TRACE3("%p, %p, %u", buf, MmGetSystemAddressForMdl(buf), + MmGetMdlByteCount(buf)); + DBG_BLOCK(4) { + dump_bytes(__func__, MmGetSystemAddressForMdl(buf), + MmGetMdlByteCount(buf)); + } + wnd->dma_map_addr[index] = + PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, + MmGetSystemAddressForMdl(buf), + MmGetMdlByteCount(buf), PCI_DMA_TODEVICE); + phy_addr_array[0].phy_addr = wnd->dma_map_addr[index]; + phy_addr_array[0].length = MmGetMdlByteCount(buf); + TRACE4("%Lx, %d, %d", phy_addr_array[0].phy_addr, + phy_addr_array[0].length, index); + *array_size = 1; +} + +wstdcall void WIN_FUNC(NdisMCompleteBufferPhysicalMapping,3) + (struct ndis_mp_block *nmb, ndis_buffer *buf, ULONG index) +{ + struct ndis_device *wnd = nmb->wnd; + + ENTER3("%p, %p %u (%u)", wnd, buf, index, wnd->dma_map_count); + + if (unlikely(wnd->sg_dma_size)) + WARNING("buffer %p may have been unmapped already", buf); + if (index >= wnd->dma_map_count) { + ERROR("invalid map register (%u >= %u)", + index, wnd->dma_map_count); + return; + } + TRACE4("%lx", (unsigned long)wnd->dma_map_addr[index]); + if (wnd->dma_map_addr[index]) { + PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev, wnd->dma_map_addr[index], + MmGetMdlByteCount(buf), PCI_DMA_TODEVICE); + wnd->dma_map_addr[index] = 0; + } else + WARNING("map registers at %u not used", index); +} + +wstdcall void WIN_FUNC(NdisMAllocateSharedMemory,5) + (struct ndis_mp_block *nmb, ULONG size, + BOOLEAN cached, void **virt, NDIS_PHY_ADDRESS *phys) +{ + dma_addr_t dma_addr; + struct wrap_device *wd = nmb->wnd->wd; + + ENTER3("size: %u, cached: %d", size, cached); + *virt = PCI_DMA_ALLOC_COHERENT(wd->pci.pdev, size, &dma_addr); + if (*virt) + *phys = dma_addr; + else + WARNING("couldn't allocate %d bytes of %scached DMA memory", + size, cached ? "" : "un-"); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisMFreeSharedMemory,5) + (struct ndis_mp_block *nmb, ULONG size, BOOLEAN cached, + void *virt, NDIS_PHY_ADDRESS addr) +{ + struct wrap_device *wd = nmb->wnd->wd; + ENTER3("%p, %Lx, %u", virt, addr, size); + PCI_DMA_FREE_COHERENT(wd->pci.pdev, size, virt, addr); + EXIT3(return); +} + +wstdcall void alloc_shared_memory_async(void *arg1, void *arg2) +{ + struct ndis_device *wnd; + struct alloc_shared_mem *alloc_shared_mem; + struct miniport *mp; + void *virt; + NDIS_PHY_ADDRESS phys; + KIRQL irql; + + wnd = arg1; + alloc_shared_mem = arg2; + mp = &wnd->wd->driver->ndis_driver->mp; + NdisMAllocateSharedMemory(wnd->nmb, alloc_shared_mem->size, + alloc_shared_mem->cached, &virt, &phys); + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + LIN2WIN5(mp->alloc_complete, wnd->nmb, virt, + &phys, alloc_shared_mem->size, alloc_shared_mem->ctx); + serialize_unlock_irql(wnd, irql); + kfree(alloc_shared_mem); +} +WIN_FUNC_DECL(alloc_shared_memory_async,2) + +wstdcall NDIS_STATUS WIN_FUNC(NdisMAllocateSharedMemoryAsync,4) + (struct ndis_mp_block *nmb, ULONG size, BOOLEAN cached, void *ctx) +{ + struct ndis_device *wnd = nmb->wnd; + struct alloc_shared_mem *alloc_shared_mem; + + ENTER3("wnd: %p", wnd); + alloc_shared_mem = kmalloc(sizeof(*alloc_shared_mem), irql_gfp()); + if (!alloc_shared_mem) { + WARNING("couldn't allocate memory"); + return NDIS_STATUS_FAILURE; + } + + alloc_shared_mem->size = size; + alloc_shared_mem->cached = cached; + alloc_shared_mem->ctx = ctx; + if (schedule_ntos_work_item(WIN_FUNC_PTR(alloc_shared_memory_async,2), + wnd, alloc_shared_mem)) + EXIT3(return NDIS_STATUS_FAILURE); + EXIT3(return NDIS_STATUS_PENDING); +} + +/* Some drivers allocate NDIS_BUFFER (aka MDL) very often; instead of + * allocating and freeing with kernel functions, we chain them into + * ndis_buffer_pool. When an MDL is freed, it is added to the list of + * free MDLs. When allocated, we first check if there is one in free + * list and if so just return it; otherwise, we allocate a new one and + * return that. This reduces memory fragmentation. Windows DDK says + * that the driver itself shouldn't check what is returned in + * pool_handle, presumably because buffer pools are not used in + * XP. However, as long as driver follows rest of the semantics - that + * it should indicate maximum number of MDLs used with num_descr and + * pass the same pool_handle in other buffer functions, this should + * work. Sadly, though, NdisFreeBuffer doesn't pass the pool_handle, + * so we use 'process' field of MDL to store pool_handle. */ + +wstdcall void WIN_FUNC(NdisAllocateBufferPool,3) + (NDIS_STATUS *status, struct ndis_buffer_pool **pool_handle, + UINT num_descr) +{ + struct ndis_buffer_pool *pool; + + ENTER1("buffers: %d", num_descr); + pool = kmalloc(sizeof(*pool), irql_gfp()); + if (!pool) { + *status = NDIS_STATUS_RESOURCES; + EXIT3(return); + } + spin_lock_init(&pool->lock); + pool->max_descr = num_descr; + pool->num_allocated_descr = 0; + pool->free_descr = NULL; + *pool_handle = pool; + *status = NDIS_STATUS_SUCCESS; + TRACE1("pool: %p, num_descr: %d", pool, num_descr); + EXIT1(return); +} + +wstdcall void WIN_FUNC(NdisAllocateBuffer,5) + (NDIS_STATUS *status, ndis_buffer **buffer, + struct ndis_buffer_pool *pool, void *virt, UINT length) +{ + ndis_buffer *descr; + + ENTER4("pool: %p (%d)", pool, pool->num_allocated_descr); + /* NDIS drivers should call this at DISPATCH_LEVEL, but + * alloc_tx_packet calls at SOFT_IRQL */ + assert_irql(_irql_ <= SOFT_LEVEL); + if (!pool) { + *status = NDIS_STATUS_FAILURE; + *buffer = NULL; + EXIT4(return); + } + spin_lock_bh(&pool->lock); + if ((descr = pool->free_descr)) + pool->free_descr = descr->next; + spin_unlock_bh(&pool->lock); + if (descr) { + typeof(descr->flags) flags; + flags = descr->flags; + memset(descr, 0, sizeof(*descr)); + MmInitializeMdl(descr, virt, length); + if (flags & MDL_CACHE_ALLOCATED) + descr->flags |= MDL_CACHE_ALLOCATED; + } else { + if (pool->num_allocated_descr > pool->max_descr) { + TRACE2("pool %p is full: %d(%d)", pool, + pool->num_allocated_descr, pool->max_descr); +#ifndef ALLOW_POOL_OVERFLOW + *status = NDIS_STATUS_FAILURE; + *buffer = NULL; + return; +#endif + } + descr = allocate_init_mdl(virt, length); + if (!descr) { + WARNING("couldn't allocate buffer"); + *status = NDIS_STATUS_FAILURE; + *buffer = NULL; + EXIT4(return); + } + TRACE4("buffer %p for %p, %d", descr, virt, length); + atomic_inc_var(pool->num_allocated_descr); + } + /* TODO: make sure this mdl can map given buffer */ + MmBuildMdlForNonPagedPool(descr); +// descr->flags |= MDL_ALLOCATED_FIXED_SIZE | +// MDL_MAPPED_TO_SYSTEM_VA | MDL_PAGES_LOCKED; + descr->pool = pool; + *buffer = descr; + *status = NDIS_STATUS_SUCCESS; + TRACE4("buffer: %p", descr); + EXIT4(return); +} + +wstdcall void WIN_FUNC(NdisFreeBuffer,1) + (ndis_buffer *buffer) +{ + struct ndis_buffer_pool *pool; + + ENTER4("%p", buffer); + if (!buffer || !buffer->pool) { + ERROR("invalid buffer"); + EXIT4(return); + } + pool = buffer->pool; + if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_BUFFERS) { + /* NB NB NB: set mdl's 'pool' field to NULL before + * calling free_mdl; otherwise free_mdl calls + * NdisFreeBuffer back */ + atomic_dec_var(pool->num_allocated_descr); + buffer->pool = NULL; + free_mdl(buffer); + } else { + spin_lock_bh(&pool->lock); + buffer->next = pool->free_descr; + pool->free_descr = buffer; + spin_unlock_bh(&pool->lock); + } + EXIT4(return); +} + +wstdcall void WIN_FUNC(NdisFreeBufferPool,1) + (struct ndis_buffer_pool *pool) +{ + ndis_buffer *cur, *next; + + TRACE3("pool: %p", pool); + if (!pool) { + WARNING("invalid pool"); + EXIT3(return); + } + spin_lock_bh(&pool->lock); + cur = pool->free_descr; + while (cur) { + next = cur->next; + cur->pool = NULL; + free_mdl(cur); + cur = next; + } + spin_unlock_bh(&pool->lock); + kfree(pool); + pool = NULL; + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisAdjustBufferLength,2) + (ndis_buffer *buffer, UINT length) +{ + ENTER4("%p, %d", buffer, length); + buffer->bytecount = length; +} + +wstdcall void WIN_FUNC(NdisQueryBuffer,3) + (ndis_buffer *buffer, void **virt, UINT *length) +{ + ENTER4("buffer: %p", buffer); + if (virt) + *virt = MmGetSystemAddressForMdl(buffer); + *length = MmGetMdlByteCount(buffer); + TRACE4("%p, %u", virt? *virt : NULL, *length); + return; +} + +wstdcall void WIN_FUNC(NdisQueryBufferSafe,4) + (ndis_buffer *buffer, void **virt, UINT *length, + enum mm_page_priority priority) +{ + ENTER4("%p, %p, %p, %d", buffer, virt, length, priority); + if (virt) + *virt = MmGetSystemAddressForMdlSafe(buffer, priority); + *length = MmGetMdlByteCount(buffer); + TRACE4("%p, %u", virt? *virt : NULL, *length); +} + +wstdcall void *WIN_FUNC(NdisBufferVirtualAddress,1) + (ndis_buffer *buffer) +{ + ENTER3("%p", buffer); + return MmGetSystemAddressForMdl(buffer); +} + +wstdcall ULONG WIN_FUNC(NdisBufferLength,1) + (ndis_buffer *buffer) +{ + ENTER3("%p", buffer); + return MmGetMdlByteCount(buffer); +} + +wstdcall void WIN_FUNC(NdisQueryBufferOffset,3) + (ndis_buffer *buffer, UINT *offset, UINT *length) +{ + ENTER3("%p", buffer); + *offset = MmGetMdlByteOffset(buffer); + *length = MmGetMdlByteCount(buffer); + TRACE3("%d, %d", *offset, *length); +} + +wstdcall void WIN_FUNC(NdisUnchainBufferAtBack,2) + (struct ndis_packet *packet, ndis_buffer **buffer) +{ + ndis_buffer *b, *btail; + + ENTER3("%p", packet); + b = packet->private.buffer_head; + if (!b) { + /* no buffer in packet */ + *buffer = NULL; + EXIT3(return); + } + btail = packet->private.buffer_tail; + *buffer = btail; + if (b == btail) { + /* one buffer in packet */ + packet->private.buffer_head = NULL; + packet->private.buffer_tail = NULL; + } else { + while (b->next != btail) + b = b->next; + packet->private.buffer_tail = b; + b->next = NULL; + } + packet->private.valid_counts = FALSE; + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisUnchainBufferAtFront,2) + (struct ndis_packet *packet, ndis_buffer **buffer) +{ + ENTER3("%p", packet); + if (packet->private.buffer_head == NULL) { + /* no buffer in packet */ + *buffer = NULL; + EXIT3(return); + } + + *buffer = packet->private.buffer_head; + if (packet->private.buffer_head == packet->private.buffer_tail) { + /* one buffer in packet */ + packet->private.buffer_head = NULL; + packet->private.buffer_tail = NULL; + } else + packet->private.buffer_head = (*buffer)->next; + + packet->private.valid_counts = FALSE; + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacketSafe,6) + (struct ndis_packet *packet, ndis_buffer **first_buffer, + void **first_buffer_va, UINT *first_buffer_length, + UINT *total_buffer_length, enum mm_page_priority priority) +{ + ndis_buffer *b = packet->private.buffer_head; + + ENTER3("%p(%p)", packet, b); + *first_buffer = b; + if (b) { + *first_buffer_va = MmGetSystemAddressForMdlSafe(b, priority); + *first_buffer_length = *total_buffer_length = + MmGetMdlByteCount(b); + for (b = b->next; b; b = b->next) + *total_buffer_length += MmGetMdlByteCount(b); + } else { + *first_buffer_va = NULL; + *first_buffer_length = 0; + *total_buffer_length = 0; + } + TRACE3("%p, %d, %d", *first_buffer_va, *first_buffer_length, + *total_buffer_length); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisGetFirstBufferFromPacket,6) + (struct ndis_packet *packet, ndis_buffer **first_buffer, + void **first_buffer_va, UINT *first_buffer_length, + UINT *total_buffer_length, enum mm_page_priority priority) +{ + NdisGetFirstBufferFromPacketSafe(packet, first_buffer, + first_buffer_va, first_buffer_length, + total_buffer_length, + NormalPagePriority); +} + +wstdcall void WIN_FUNC(NdisAllocatePacketPoolEx,5) + (NDIS_STATUS *status, struct ndis_packet_pool **pool_handle, + UINT num_descr, UINT overflowsize, UINT proto_rsvd_length) +{ + struct ndis_packet_pool *pool; + + ENTER3("buffers: %d, length: %d", num_descr, proto_rsvd_length); + pool = kzalloc(sizeof(*pool), irql_gfp()); + if (!pool) { + *status = NDIS_STATUS_RESOURCES; + EXIT3(return); + } + spin_lock_init(&pool->lock); + pool->max_descr = num_descr; + pool->num_allocated_descr = 0; + pool->num_used_descr = 0; + pool->free_descr = NULL; + pool->proto_rsvd_length = proto_rsvd_length; + *pool_handle = pool; + *status = NDIS_STATUS_SUCCESS; + TRACE3("pool: %p", pool); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisAllocatePacketPool,4) + (NDIS_STATUS *status, struct ndis_packet_pool **pool_handle, + UINT num_descr, UINT proto_rsvd_length) +{ + NdisAllocatePacketPoolEx(status, pool_handle, num_descr, 0, + proto_rsvd_length); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisFreePacketPool,1) + (struct ndis_packet_pool *pool) +{ + struct ndis_packet *packet, *next; + + ENTER3("pool: %p", pool); + if (!pool) { + WARNING("invalid pool"); + EXIT3(return); + } + spin_lock_bh(&pool->lock); + packet = pool->free_descr; + while (packet) { + next = (struct ndis_packet *)packet->reserved[0]; + kfree(packet); + packet = next; + } + pool->num_allocated_descr = 0; + pool->num_used_descr = 0; + pool->free_descr = NULL; + spin_unlock_bh(&pool->lock); + kfree(pool); + EXIT3(return); +} + +wstdcall UINT WIN_FUNC(NdisPacketPoolUsage,1) + (struct ndis_packet_pool *pool) +{ + EXIT4(return pool->num_used_descr); +} + +wstdcall void WIN_FUNC(NdisAllocatePacket,3) + (NDIS_STATUS *status, struct ndis_packet **ndis_packet, + struct ndis_packet_pool *pool) +{ + struct ndis_packet *packet; + int packet_length; + + ENTER4("pool: %p", pool); + if (!pool) { + *status = NDIS_STATUS_RESOURCES; + *ndis_packet = NULL; + EXIT4(return); + } + assert_irql(_irql_ <= SOFT_LEVEL); + if (pool->num_used_descr > pool->max_descr) { + TRACE3("pool %p is full: %d(%d)", pool, + pool->num_used_descr, pool->max_descr); +#ifndef ALLOW_POOL_OVERFLOW + *status = NDIS_STATUS_RESOURCES; + *ndis_packet = NULL; + return; +#endif + } + /* packet has space for 1 byte in protocol_reserved field */ + packet_length = sizeof(*packet) - 1 + pool->proto_rsvd_length + + sizeof(struct ndis_packet_oob_data); + spin_lock_bh(&pool->lock); + if ((packet = pool->free_descr)) + pool->free_descr = (void *)packet->reserved[0]; + spin_unlock_bh(&pool->lock); + if (!packet) { + packet = kmalloc(packet_length, irql_gfp()); + if (!packet) { + WARNING("couldn't allocate packet"); + *status = NDIS_STATUS_RESOURCES; + *ndis_packet = NULL; + return; + } + atomic_inc_var(pool->num_allocated_descr); + } + TRACE4("%p, %p", pool, packet); + atomic_inc_var(pool->num_used_descr); + memset(packet, 0, packet_length); + packet->private.oob_offset = + packet_length - sizeof(struct ndis_packet_oob_data); + packet->private.packet_flags = fPACKET_ALLOCATED_BY_NDIS; + packet->private.pool = pool; + *ndis_packet = packet; + *status = NDIS_STATUS_SUCCESS; + EXIT4(return); +} + +wstdcall void WIN_FUNC(NdisDprAllocatePacket,3) + (NDIS_STATUS *status, struct ndis_packet **packet, + struct ndis_packet_pool *pool) +{ + NdisAllocatePacket(status, packet, pool); +} + +wstdcall void WIN_FUNC(NdisFreePacket,1) + (struct ndis_packet *packet) +{ + struct ndis_packet_pool *pool; + + ENTER4("%p, %p", packet, packet->private.pool); + pool = packet->private.pool; + if (!pool) { + ERROR("invalid pool %p", packet); + EXIT4(return); + } + assert((int)pool->num_used_descr > 0); + atomic_dec_var(pool->num_used_descr); + if (packet->reserved[1]) { + TRACE3("%p, %p", packet, (void *)packet->reserved[1]); + kfree((void *)packet->reserved[1]); + packet->reserved[1] = 0; + } + if (pool->num_allocated_descr > MAX_ALLOCATED_NDIS_PACKETS) { + TRACE3("%p", pool); + atomic_dec_var(pool->num_allocated_descr); + kfree(packet); + } else { + TRACE4("%p, %p, %p", pool, packet, pool->free_descr); + spin_lock_bh(&pool->lock); + packet->reserved[0] = + (typeof(packet->reserved[0]))pool->free_descr; + pool->free_descr = packet; + spin_unlock_bh(&pool->lock); + } + EXIT4(return); +} + +wstdcall struct ndis_packet_stack *WIN_FUNC(NdisIMGetCurrentPacketStack,2) + (struct ndis_packet *packet, BOOLEAN *stacks_remain) +{ + struct ndis_packet_stack *stack; + + if (!packet->reserved[1]) { + stack = kzalloc(2 * sizeof(*stack), irql_gfp()); + TRACE3("%p, %p", packet, stack); + packet->reserved[1] = (typeof(packet->reserved[1]))stack; + } else { + stack = (void *)packet->reserved[1];; + if (xchg(&stack->ndis_reserved[0], 1)) { + stack++; + if (xchg(&stack->ndis_reserved[0], 1)) + stack = NULL; + } + TRACE3("%p", stack); + } + if (stack) + *stacks_remain = TRUE; + else + *stacks_remain = FALSE; + + EXIT3(return stack); +} + +wstdcall void WIN_FUNC(NdisCopyFromPacketToPacketSafe,7) + (struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy, + struct ndis_packet *src, UINT src_offset, UINT *num_copied, + enum mm_page_priority priority) +{ + UINT dst_n, src_n, n, left; + ndis_buffer *dst_buf; + ndis_buffer *src_buf; + + ENTER4(""); + if (!dst || !src) { + *num_copied = 0; + EXIT4(return); + } + + dst_buf = dst->private.buffer_head; + src_buf = src->private.buffer_head; + + if (!dst_buf || !src_buf) { + *num_copied = 0; + EXIT4(return); + } + dst_n = MmGetMdlByteCount(dst_buf) - dst_offset; + src_n = MmGetMdlByteCount(src_buf) - src_offset; + + n = min(src_n, dst_n); + n = min(n, num_to_copy); + memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset, + MmGetSystemAddressForMdl(src_buf) + src_offset, n); + + left = num_to_copy - n; + while (left > 0) { + src_offset += n; + dst_offset += n; + dst_n -= n; + src_n -= n; + if (dst_n == 0) { + dst_buf = dst_buf->next; + if (!dst_buf) + break; + dst_n = MmGetMdlByteCount(dst_buf); + dst_offset = 0; + } + if (src_n == 0) { + src_buf = src_buf->next; + if (!src_buf) + break; + src_n = MmGetMdlByteCount(src_buf); + src_offset = 0; + } + + n = min(src_n, dst_n); + n = min(n, left); + memcpy(MmGetSystemAddressForMdl(dst_buf) + dst_offset, + MmGetSystemAddressForMdl(src_buf) + src_offset, n); + left -= n; + } + *num_copied = num_to_copy - left; + EXIT4(return); +} + +wstdcall void WIN_FUNC(NdisCopyFromPacketToPacket,6) + (struct ndis_packet *dst, UINT dst_offset, UINT num_to_copy, + struct ndis_packet *src, UINT src_offset, UINT *num_copied) +{ + NdisCopyFromPacketToPacketSafe(dst, dst_offset, num_to_copy, + src, src_offset, num_copied, + NormalPagePriority); + return; +} + +wstdcall void WIN_FUNC(NdisIMCopySendPerPacketInfo,2) + (struct ndis_packet *dst, struct ndis_packet *src) +{ + struct ndis_packet_oob_data *dst_oob, *src_oob; + dst_oob = NDIS_PACKET_OOB_DATA(dst); + src_oob = NDIS_PACKET_OOB_DATA(src); + memcpy(&dst_oob->ext, &src_oob->ext, sizeof(dst_oob->ext)); + return; +} + +wstdcall void WIN_FUNC(NdisSend,3) + (NDIS_STATUS *status, struct ndis_mp_block *nmb, + struct ndis_packet *packet) +{ + struct ndis_device *wnd = nmb->wnd; + struct miniport *mp; + KIRQL irql; + + mp = &wnd->wd->driver->ndis_driver->mp; + if (mp->send_packets) { + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx, &packet, 1); + serialize_unlock_irql(wnd, irql); + if (deserialized_driver(wnd)) + *status = NDIS_STATUS_PENDING; + else { + struct ndis_packet_oob_data *oob_data; + oob_data = NDIS_PACKET_OOB_DATA(packet); + *status = oob_data->status; + switch (*status) { + case NDIS_STATUS_SUCCESS: + free_tx_packet(wnd, packet, *status); + break; + case NDIS_STATUS_PENDING: + break; + case NDIS_STATUS_RESOURCES: + wnd->tx_ok = 0; + break; + case NDIS_STATUS_FAILURE: + default: + free_tx_packet(wnd, packet, *status); + break; + } + } + } else { + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + *status = LIN2WIN3(mp->send, wnd->nmb->mp_ctx, packet, 0); + serialize_unlock_irql(wnd, irql); + switch (*status) { + case NDIS_STATUS_SUCCESS: + free_tx_packet(wnd, packet, *status); + break; + case NDIS_STATUS_PENDING: + break; + case NDIS_STATUS_RESOURCES: + wnd->tx_ok = 0; + break; + case NDIS_STATUS_FAILURE: + default: + free_tx_packet(wnd, packet, *status); + break; + } + } + EXIT3(return); +} + +/* called for serialized drivers only */ +wstdcall void mp_timer_dpc(struct kdpc *kdpc, void *ctx, void *arg1, void *arg2) +{ + struct ndis_mp_timer *timer; + struct ndis_mp_block *nmb; + + timer = ctx; + TIMERENTER("%p, %p, %p, %p", timer, timer->func, timer->ctx, timer->nmb); + assert_irql(_irql_ == DISPATCH_LEVEL); + nmb = timer->nmb; + serialize_lock(nmb->wnd); + LIN2WIN4(timer->func, NULL, timer->ctx, NULL, NULL); + serialize_unlock(nmb->wnd); + TIMEREXIT(return); +} +WIN_FUNC_DECL(mp_timer_dpc,4) + +wstdcall void WIN_FUNC(NdisMInitializeTimer,4) + (struct ndis_mp_timer *timer, struct ndis_mp_block *nmb, + DPC func, void *ctx) +{ + TIMERENTER("%p, %p, %p, %p", timer, func, ctx, nmb); + assert_irql(_irql_ == PASSIVE_LEVEL); + timer->func = func; + timer->ctx = ctx; + timer->nmb = nmb; + if (deserialized_driver(nmb->wnd)) + KeInitializeDpc(&timer->kdpc, func, ctx); + else + KeInitializeDpc(&timer->kdpc, WIN_FUNC_PTR(mp_timer_dpc,4), + timer); + wrap_init_timer(&timer->nt_timer, NotificationTimer, nmb); + TIMEREXIT(return); +} + +wstdcall void WIN_FUNC(NdisMSetPeriodicTimer,2) + (struct ndis_mp_timer *timer, UINT period_ms) +{ + unsigned long expires = MSEC_TO_HZ(period_ms); + + TIMERENTER("%p, %u, %ld", timer, period_ms, expires); + assert_irql(_irql_ <= DISPATCH_LEVEL); + wrap_set_timer(&timer->nt_timer, expires, expires, &timer->kdpc); + TIMEREXIT(return); +} + +wstdcall void WIN_FUNC(NdisMCancelTimer,2) + (struct ndis_mp_timer *timer, BOOLEAN *canceled) +{ + TIMERENTER("%p", timer); + assert_irql(_irql_ <= DISPATCH_LEVEL); + *canceled = KeCancelTimer(&timer->nt_timer); + TIMERTRACE("%d", *canceled); + return; +} + +wstdcall void WIN_FUNC(NdisInitializeTimer,3) + (struct ndis_timer *timer, void *func, void *ctx) +{ + TIMERENTER("%p, %p, %p", timer, func, ctx); + assert_irql(_irql_ == PASSIVE_LEVEL); + KeInitializeDpc(&timer->kdpc, func, ctx); + wrap_init_timer(&timer->nt_timer, NotificationTimer, NULL); + TIMEREXIT(return); +} + +/* NdisMSetTimer is a macro that calls NdisSetTimer with + * ndis_mp_timer typecast to ndis_timer */ + +wstdcall void WIN_FUNC(NdisSetTimer,2) + (struct ndis_timer *timer, UINT duetime_ms) +{ + unsigned long expires = MSEC_TO_HZ(duetime_ms); + + TIMERENTER("%p, %p, %u, %ld", timer, timer->nt_timer.wrap_timer, + duetime_ms, expires); + assert_irql(_irql_ <= DISPATCH_LEVEL); + wrap_set_timer(&timer->nt_timer, expires, 0, &timer->kdpc); + TIMEREXIT(return); +} + +wstdcall void WIN_FUNC(NdisCancelTimer,2) + (struct ndis_timer *timer, BOOLEAN *canceled) +{ + TIMERENTER("%p", timer); + assert_irql(_irql_ <= DISPATCH_LEVEL); + *canceled = KeCancelTimer(&timer->nt_timer); + TIMEREXIT(return); +} + +wstdcall void WIN_FUNC(NdisMRegisterAdapterShutdownHandler,3) + (struct ndis_mp_block *nmb, void *ctx, void *func) +{ + struct ndis_device *wnd = nmb->wnd; + ENTER1("%p", func); + wnd->wd->driver->ndis_driver->mp.shutdown = func; + wnd->shutdown_ctx = ctx; +} + +wstdcall void WIN_FUNC(NdisMDeregisterAdapterShutdownHandler,1) + (struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + wnd->wd->driver->ndis_driver->mp.shutdown = NULL; + wnd->shutdown_ctx = NULL; +} + +/* TODO: rt61 (serialized) driver doesn't want MiniportEnableInterrupt + * to be called in irq handler, but mrv800c (deserialized) driver + * wants. NDIS is confusing about when to call MiniportEnableInterrupt + * For now, handle these cases with two separate irq handlers based on + * observation of these two drivers. However, it is likely not + * correct. */ +wstdcall void deserialized_irq_handler(struct kdpc *kdpc, void *ctx, + void *arg1, void *arg2) +{ + struct ndis_device *wnd = ctx; + ndis_interrupt_handler irq_handler = arg1; + struct miniport *mp = arg2; + + TRACE6("%p", irq_handler); + assert_irql(_irql_ == DISPATCH_LEVEL); + LIN2WIN1(irq_handler, wnd->nmb->mp_ctx); + if (mp->enable_interrupt) + LIN2WIN1(mp->enable_interrupt, wnd->nmb->mp_ctx); + EXIT6(return); +} +WIN_FUNC_DECL(deserialized_irq_handler,4) + +wstdcall void serialized_irq_handler(struct kdpc *kdpc, void *ctx, + void *arg1, void *arg2) +{ + struct ndis_device *wnd = ctx; + ndis_interrupt_handler irq_handler = arg1; + + TRACE6("%p, %p, %p", wnd, irq_handler, arg2); + assert_irql(_irql_ == DISPATCH_LEVEL); + serialize_lock(wnd); + LIN2WIN1(irq_handler, arg2); + serialize_unlock(wnd); + EXIT6(return); +} +WIN_FUNC_DECL(serialized_irq_handler,4) + +wstdcall BOOLEAN ndis_isr(struct kinterrupt *kinterrupt, void *ctx) +{ + struct ndis_mp_interrupt *mp_interrupt = ctx; + struct ndis_device *wnd = mp_interrupt->nmb->wnd; + BOOLEAN recognized = TRUE, queue_handler = TRUE; + + TRACE6("%p", wnd); + /* kernel may call ISR when registering interrupt, in + * the same context if DEBUG_SHIRQ is enabled */ + assert_irql(_irql_ == DIRQL || _irql_ == PASSIVE_LEVEL); + if (mp_interrupt->shared) + LIN2WIN3(mp_interrupt->isr, &recognized, &queue_handler, + wnd->nmb->mp_ctx); + else { + struct miniport *mp; + mp = &wnd->wd->driver->ndis_driver->mp; + LIN2WIN1(mp->disable_interrupt, wnd->nmb->mp_ctx); + /* it is not shared interrupt, so handler must be called */ + recognized = queue_handler = TRUE; + } + if (recognized) { + if (queue_handler) { + TRACE5("%p", &wnd->irq_kdpc); + queue_kdpc(&wnd->irq_kdpc); + } + EXIT6(return TRUE); + } + EXIT6(return FALSE); +} +WIN_FUNC_DECL(ndis_isr,2) + +wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterInterrupt,7) + (struct ndis_mp_interrupt *mp_interrupt, + struct ndis_mp_block *nmb, UINT vector, UINT level, + BOOLEAN req_isr, BOOLEAN shared, enum kinterrupt_mode mode) +{ + struct ndis_device *wnd = nmb->wnd; + struct miniport *mp; + + ENTER1("%p, vector:%d, level:%d, req_isr:%d, shared:%d, mode:%d", + mp_interrupt, vector, level, req_isr, shared, mode); + + mp = &wnd->wd->driver->ndis_driver->mp; + nt_spin_lock_init(&mp_interrupt->lock); + mp_interrupt->irq = vector; + mp_interrupt->isr = mp->isr; + mp_interrupt->mp_dpc = mp->handle_interrupt; + mp_interrupt->nmb = nmb; + mp_interrupt->req_isr = req_isr; + if (shared && !req_isr) + WARNING("shared but dynamic interrupt!"); + mp_interrupt->shared = shared; + wnd->mp_interrupt = mp_interrupt; + if (mp->enable_interrupt) + mp_interrupt->enable = TRUE; + else + mp_interrupt->enable = FALSE; + + if (deserialized_driver(wnd)) { + KeInitializeDpc(&wnd->irq_kdpc, + WIN_FUNC_PTR(deserialized_irq_handler,4), + nmb->wnd); + wnd->irq_kdpc.arg1 = mp->handle_interrupt; + wnd->irq_kdpc.arg2 = mp; + TRACE2("%p, %p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2, + nmb->wnd, nmb->mp_ctx); + } else { + KeInitializeDpc(&wnd->irq_kdpc, + WIN_FUNC_PTR(serialized_irq_handler,4), + nmb->wnd); + wnd->irq_kdpc.arg1 = mp->handle_interrupt; + wnd->irq_kdpc.arg2 = nmb->mp_ctx; + TRACE2("%p, %p, %p", wnd->irq_kdpc.arg1, wnd->irq_kdpc.arg2, + nmb->wnd); + } + + if (IoConnectInterrupt(&mp_interrupt->kinterrupt, + WIN_FUNC_PTR(ndis_isr,2), mp_interrupt, NULL, + vector, DIRQL, DIRQL, mode, shared, 0, FALSE) != + STATUS_SUCCESS) { + printk(KERN_WARNING "%s: request for IRQ %d failed\n", + DRIVER_NAME, vector); + return NDIS_STATUS_RESOURCES; + } + printk(KERN_INFO "%s: using IRQ %d\n", DRIVER_NAME, vector); + EXIT1(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisMDeregisterInterrupt,1) + (struct ndis_mp_interrupt *mp_interrupt) +{ + struct ndis_mp_block *nmb; + + ENTER1("%p", mp_interrupt); + nmb = xchg(&mp_interrupt->nmb, NULL); + TRACE1("%p", nmb); + if (!nmb) { + WARNING("interrupt already freed?"); + return; + } + nmb->wnd->mp_interrupt = NULL; + if (dequeue_kdpc(&nmb->wnd->irq_kdpc)) + TRACE2("interrupt kdpc was pending"); + flush_workqueue(wrapndis_wq); + IoDisconnectInterrupt(mp_interrupt->kinterrupt); + EXIT1(return); +} + +wstdcall BOOLEAN WIN_FUNC(NdisMSynchronizeWithInterrupt,3) + (struct ndis_mp_interrupt *mp_interrupt, + PKSYNCHRONIZE_ROUTINE sync_func, void *ctx) +{ + return KeSynchronizeExecution(mp_interrupt->kinterrupt, sync_func, ctx); +} + +/* called via function pointer; but 64-bit RNDIS driver calls directly */ +wstdcall void WIN_FUNC(NdisMIndicateStatus,4) + (struct ndis_mp_block *nmb, NDIS_STATUS status, void *buf, UINT len) +{ + struct ndis_device *wnd = nmb->wnd; + struct ndis_status_indication *si; + + ENTER2("status=0x%x len=%d", status, len); + switch (status) { + case NDIS_STATUS_MEDIA_CONNECT: + set_media_state(wnd, NdisMediaStateConnected); + break; + case NDIS_STATUS_MEDIA_DISCONNECT: + set_media_state(wnd, NdisMediaStateDisconnected); + break; + case NDIS_STATUS_MEDIA_SPECIFIC_INDICATION: + if (!buf) + break; + si = buf; + TRACE2("status_type=%d", si->status_type); + switch (si->status_type) { + case Ndis802_11StatusType_MediaStreamMode: + break; +#ifdef CONFIG_WIRELESS_EXT + case Ndis802_11StatusType_Authentication: + buf = (char *)buf + sizeof(*si); + len -= sizeof(*si); + while (len > 0) { + int pairwise_error = 0, group_error = 0; + struct ndis_auth_req *auth_req = + (struct ndis_auth_req *)buf; + TRACE1(MACSTRSEP, MAC2STR(auth_req->bssid)); + if (auth_req->flags & 0x01) + TRACE2("reauth request"); + if (auth_req->flags & 0x02) + TRACE2("key update request"); + if (auth_req->flags & 0x06) { + pairwise_error = 1; + TRACE2("pairwise_error"); + } + if (auth_req->flags & 0x0E) { + group_error = 1; + TRACE2("group_error"); + } + if (pairwise_error || group_error) { + union iwreq_data wrqu; + struct iw_michaelmicfailure micfailure; + + memset(&micfailure, 0, sizeof(micfailure)); + if (pairwise_error) + micfailure.flags |= + IW_MICFAILURE_PAIRWISE; + if (group_error) + micfailure.flags |= + IW_MICFAILURE_GROUP; + memcpy(micfailure.src_addr.sa_data, + auth_req->bssid, ETH_ALEN); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = sizeof(micfailure); + wireless_send_event(wnd->net_dev, + IWEVMICHAELMICFAILURE, + &wrqu, (u8 *)&micfailure); + } + len -= auth_req->length; + buf = (char *)buf + auth_req->length; + } + break; + case Ndis802_11StatusType_PMKID_CandidateList: + { + u8 *end; + unsigned long i; + struct ndis_pmkid_candidate_list *cand; + + cand = buf + sizeof(struct ndis_status_indication); + if (len < sizeof(struct ndis_status_indication) + + sizeof(struct ndis_pmkid_candidate_list) || + cand->version != 1) { + WARNING("unrecognized PMKID ignored"); + EXIT1(return); + } + + end = (u8 *)buf + len; + TRACE2("PMKID ver %d num_cand %d", + cand->version, cand->num_candidates); + for (i = 0; i < cand->num_candidates; i++) { + struct iw_pmkid_cand pcand; + union iwreq_data wrqu; + struct ndis_pmkid_candidate *c = + &cand->candidates[i]; + if ((u8 *)(c + 1) > end) { + TRACE2("truncated PMKID"); + break; + } + TRACE2("%ld: " MACSTRSEP " 0x%x", + i, MAC2STR(c->bssid), c->flags); + memset(&pcand, 0, sizeof(pcand)); + if (c->flags & 0x01) + pcand.flags |= IW_PMKID_CAND_PREAUTH; + pcand.index = i; + memcpy(pcand.bssid.sa_data, c->bssid, ETH_ALEN); + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = sizeof(pcand); + wireless_send_event(wnd->net_dev, IWEVPMKIDCAND, + &wrqu, (u8 *)&pcand); + } + break; + } + case Ndis802_11StatusType_RadioState: + { + struct ndis_radio_status_indication *radio_status = buf; + if (radio_status->radio_state == + Ndis802_11RadioStatusOn) + INFO("radio is turned on"); + else if (radio_status->radio_state == + Ndis802_11RadioStatusHardwareOff) + INFO("radio is turned off by hardware"); + else if (radio_status->radio_state == + Ndis802_11RadioStatusSoftwareOff) + INFO("radio is turned off by software"); + break; + } +#endif + default: + /* is this RSSI indication? */ + TRACE2("unknown indication: %x", si->status_type); + break; + } + break; + default: + TRACE2("unknown status: %08X", status); + break; + } + + EXIT2(return); +} + +/* called via function pointer; but 64-bit RNDIS driver calls directly */ +wstdcall void WIN_FUNC(NdisMIndicateStatusComplete,1) + (struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + ENTER2("%p", wnd); + if (wnd->tx_ok) + schedule_wrapndis_work(&wnd->tx_work); +} + +/* called via function pointer */ +wstdcall void NdisMSendComplete(struct ndis_mp_block *nmb, + struct ndis_packet *packet, NDIS_STATUS status) +{ + struct ndis_device *wnd = nmb->wnd; + ENTER4("%p, %08X", packet, status); + assert_irql(_irql_ <= DISPATCH_LEVEL); + if (deserialized_driver(wnd)) + free_tx_packet(wnd, packet, status); + else { + struct ndis_packet_oob_data *oob_data; + NDIS_STATUS pkt_status; + TRACE3("%p, %08x", packet, status); + oob_data = NDIS_PACKET_OOB_DATA(packet); + switch ((pkt_status = xchg(&oob_data->status, status))) { + case NDIS_STATUS_NOT_RECOGNIZED: + free_tx_packet(wnd, packet, status); + break; + case NDIS_STATUS_PENDING: + case 0: + break; + default: + WARNING("%p: invalid status: %08X", packet, pkt_status); + break; + } + /* In case a serialized driver has earlier requested a + * pause by returning NDIS_STATUS_RESOURCES during + * MiniportSend(Packets), wakeup tx worker now. + */ + if (xchg(&wnd->tx_ok, 1) == 0) { + TRACE3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end); + schedule_wrapndis_work(&wnd->tx_work); + } + } + EXIT3(return); +} + +/* called via function pointer */ +wstdcall void NdisMSendResourcesAvailable(struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + ENTER3("%d, %d", wnd->tx_ring_start, wnd->tx_ring_end); + wnd->tx_ok = 1; + schedule_wrapndis_work(&wnd->tx_work); + EXIT3(return); +} + +wstdcall void return_packet(void *arg1, void *arg2) +{ + struct ndis_device *wnd; + struct ndis_packet *packet; + struct miniport *mp; + KIRQL irql; + + wnd = arg1; + packet = arg2; + ENTER4("%p, %p", wnd, packet); + mp = &wnd->wd->driver->ndis_driver->mp; + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + LIN2WIN2(mp->return_packet, wnd->nmb->mp_ctx, packet); + serialize_unlock_irql(wnd, irql); + EXIT4(return); +} +WIN_FUNC_DECL(return_packet,2) + +/* called via function pointer */ +wstdcall void NdisMIndicateReceivePacket(struct ndis_mp_block *nmb, + struct ndis_packet **packets, + UINT nr_packets) +{ + struct ndis_device *wnd; + ndis_buffer *buffer; + struct ndis_packet *packet; + struct sk_buff *skb; + ULONG i, length, total_length; + struct ndis_packet_oob_data *oob_data; + void *virt; + struct ndis_tcp_ip_checksum_packet_info csum; + + ENTER3("%p, %d", nmb, nr_packets); + assert_irql(_irql_ <= DISPATCH_LEVEL); + wnd = nmb->wnd; + for (i = 0; i < nr_packets; i++) { + packet = packets[i]; + if (!packet) { + WARNING("empty packet ignored"); + continue; + } + wnd->net_dev->last_rx = jiffies; + /* get total number of bytes in packet */ + NdisGetFirstBufferFromPacketSafe(packet, &buffer, &virt, + &length, &total_length, + NormalPagePriority); + TRACE3("%d, %d", length, total_length); + oob_data = NDIS_PACKET_OOB_DATA(packet); + TRACE3("0x%x, 0x%x, %Lu", packet->private.flags, + packet->private.packet_flags, oob_data->time_rxed); + skb = dev_alloc_skb(total_length); + if (skb) { + while (buffer) { + memcpy_skb(skb, MmGetSystemAddressForMdl(buffer), + MmGetMdlByteCount(buffer)); + buffer = buffer->next; + } + skb->dev = wnd->net_dev; + skb->protocol = eth_type_trans(skb, wnd->net_dev); + pre_atomic_add(wnd->net_stats.rx_bytes, total_length); + atomic_inc_var(wnd->net_stats.rx_packets); + csum.value = (typeof(csum.value))(ULONG_PTR) + oob_data->ext.info[TcpIpChecksumPacketInfo]; + TRACE3("0x%05x", csum.value); + if (wnd->rx_csum.value && + (csum.rx.tcp_succeeded || csum.rx.udp_succeeded || + csum.rx.ip_succeeded)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + + if (in_interrupt()) + netif_rx(skb); + else + netif_rx_ni(skb); + } else { + WARNING("couldn't allocate skb; packet dropped"); + atomic_inc_var(wnd->net_stats.rx_dropped); + } + + /* serialized drivers check the status upon return + * from this function */ + if (!deserialized_driver(wnd)) { + oob_data->status = NDIS_STATUS_SUCCESS; + continue; + } + + /* if a deserialized driver sets + * NDIS_STATUS_RESOURCES, then it reclaims the packet + * upon return from this function */ + if (oob_data->status == NDIS_STATUS_RESOURCES) + continue; + + assert(oob_data->status == NDIS_STATUS_SUCCESS); + /* deserialized driver doesn't check the status upon + * return from this function; we need to call + * MiniportReturnPacket later for this packet. Calling + * MiniportReturnPacket from here is not correct - the + * driver doesn't expect it (at least Centrino driver + * crashes) */ + schedule_ntos_work_item(WIN_FUNC_PTR(return_packet,2), + wnd, packet); + } + EXIT3(return); +} + +/* called via function pointer (by NdisMEthIndicateReceive macro); the + * first argument is nmb->eth_db */ +wstdcall void EthRxIndicateHandler(struct ndis_mp_block *nmb, void *rx_ctx, + char *header1, char *header, UINT header_size, + void *look_ahead, UINT look_ahead_size, + UINT packet_size) +{ + struct sk_buff *skb = NULL; + struct ndis_device *wnd; + unsigned int skb_size = 0; + KIRQL irql; + struct ndis_packet_oob_data *oob_data; + + ENTER3("nmb = %p, rx_ctx = %p, buf = %p, size = %d, buf = %p, " + "size = %d, packet = %d", nmb, rx_ctx, header, header_size, + look_ahead, look_ahead_size, packet_size); + + wnd = nmb->wnd; + TRACE3("wnd = %p", wnd); + if (!wnd) { + ERROR("nmb is NULL"); + EXIT3(return); + } + wnd->net_dev->last_rx = jiffies; + + if (look_ahead_size < packet_size) { + struct ndis_packet *packet; + struct miniport *mp; + unsigned int bytes_txed; + NDIS_STATUS res; + + NdisAllocatePacket(&res, &packet, wnd->tx_packet_pool); + if (res != NDIS_STATUS_SUCCESS) { + atomic_inc_var(wnd->net_stats.rx_dropped); + EXIT3(return); + } + oob_data = NDIS_PACKET_OOB_DATA(packet); + mp = &wnd->wd->driver->ndis_driver->mp; + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + res = LIN2WIN6(mp->tx_data, packet, &bytes_txed, nmb, + rx_ctx, look_ahead_size, packet_size); + serialize_unlock_irql(wnd, irql); + TRACE3("%d, %d, %d", header_size, look_ahead_size, bytes_txed); + if (res == NDIS_STATUS_SUCCESS) { + ndis_buffer *buffer; + struct ndis_tcp_ip_checksum_packet_info csum; + skb = dev_alloc_skb(header_size + look_ahead_size + + bytes_txed); + if (!skb) { + ERROR("couldn't allocate skb; packet dropped"); + atomic_inc_var(wnd->net_stats.rx_dropped); + NdisFreePacket(packet); + return; + } + memcpy_skb(skb, header, header_size); + memcpy_skb(skb, look_ahead, look_ahead_size); + buffer = packet->private.buffer_head; + while (buffer) { + memcpy_skb(skb, + MmGetSystemAddressForMdl(buffer), + MmGetMdlByteCount(buffer)); + buffer = buffer->next; + } + skb_size = header_size + look_ahead_size + bytes_txed; + csum.value = (typeof(csum.value))(ULONG_PTR) + oob_data->ext.info[TcpIpChecksumPacketInfo]; + TRACE3("0x%05x", csum.value); + if (wnd->rx_csum.value && + (csum.rx.tcp_succeeded || csum.rx.udp_succeeded)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + NdisFreePacket(packet); + } else if (res == NDIS_STATUS_PENDING) { + /* driver will call td_complete */ + oob_data->look_ahead = kmalloc(look_ahead_size, + GFP_ATOMIC); + if (!oob_data->look_ahead) { + NdisFreePacket(packet); + ERROR("packet dropped"); + atomic_inc_var(wnd->net_stats.rx_dropped); + EXIT3(return); + } + assert(sizeof(oob_data->header) == header_size); + memcpy(oob_data->header, header, + sizeof(oob_data->header)); + memcpy(oob_data->look_ahead, look_ahead, + look_ahead_size); + oob_data->look_ahead_size = look_ahead_size; + EXIT3(return); + } else { + WARNING("packet dropped: %08X", res); + atomic_inc_var(wnd->net_stats.rx_dropped); + NdisFreePacket(packet); + EXIT3(return); + } + } else { + skb_size = header_size + packet_size; + skb = dev_alloc_skb(skb_size); + if (skb) { + memcpy_skb(skb, header, header_size); + memcpy_skb(skb, look_ahead, packet_size); + } + } + + if (skb) { + skb->dev = wnd->net_dev; + skb->protocol = eth_type_trans(skb, wnd->net_dev); + pre_atomic_add(wnd->net_stats.rx_bytes, skb_size); + atomic_inc_var(wnd->net_stats.rx_packets); + if (in_interrupt()) + netif_rx(skb); + else + netif_rx_ni(skb); + } + + EXIT3(return); +} + +/* called via function pointer */ +wstdcall void NdisMTransferDataComplete(struct ndis_mp_block *nmb, + struct ndis_packet *packet, + NDIS_STATUS status, UINT bytes_txed) +{ + struct ndis_device *wnd = nmb->wnd; + struct sk_buff *skb; + unsigned int skb_size; + struct ndis_packet_oob_data *oob_data; + ndis_buffer *buffer; + struct ndis_tcp_ip_checksum_packet_info csum; + + ENTER3("wnd = %p, packet = %p, bytes_txed = %d", + wnd, packet, bytes_txed); + if (!packet) { + WARNING("illegal packet"); + EXIT3(return); + } + wnd->net_dev->last_rx = jiffies; + oob_data = NDIS_PACKET_OOB_DATA(packet); + skb_size = sizeof(oob_data->header) + oob_data->look_ahead_size + + bytes_txed; + skb = dev_alloc_skb(skb_size); + if (!skb) { + kfree(oob_data->look_ahead); + NdisFreePacket(packet); + ERROR("couldn't allocate skb; packet dropped"); + atomic_inc_var(wnd->net_stats.rx_dropped); + EXIT3(return); + } + memcpy_skb(skb, oob_data->header, sizeof(oob_data->header)); + memcpy_skb(skb, oob_data->look_ahead, oob_data->look_ahead_size); + buffer = packet->private.buffer_head; + while (buffer) { + memcpy_skb(skb, MmGetSystemAddressForMdl(buffer), + MmGetMdlByteCount(buffer)); + buffer = buffer->next; + } + kfree(oob_data->look_ahead); + NdisFreePacket(packet); + skb->dev = wnd->net_dev; + skb->protocol = eth_type_trans(skb, wnd->net_dev); + pre_atomic_add(wnd->net_stats.rx_bytes, skb_size); + atomic_inc_var(wnd->net_stats.rx_packets); + + csum.value = (typeof(csum.value))(ULONG_PTR) + oob_data->ext.info[TcpIpChecksumPacketInfo]; + TRACE3("0x%05x", csum.value); + if (wnd->rx_csum.value && + (csum.rx.tcp_succeeded || csum.rx.udp_succeeded)) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + + if (in_interrupt()) + netif_rx(skb); + else + netif_rx_ni(skb); +} + +/* called via function pointer */ +wstdcall void EthRxComplete(struct ndis_mp_block *nmb) +{ + TRACE3(""); +} + +/* called via function pointer */ +wstdcall void NdisMQueryInformationComplete(struct ndis_mp_block *nmb, + NDIS_STATUS status) +{ + struct ndis_device *wnd = nmb->wnd; + typeof(wnd->ndis_req_task) task; + + ENTER2("nmb: %p, wnd: %p, %08X", nmb, wnd, status); + wnd->ndis_req_status = status; + wnd->ndis_req_done = 1; + if ((task = xchg(&wnd->ndis_req_task, NULL))) + wake_up_process(task); + else + WARNING("invalid task"); + EXIT2(return); +} + +/* called via function pointer */ +wstdcall void NdisMSetInformationComplete(struct ndis_mp_block *nmb, + NDIS_STATUS status) +{ + struct ndis_device *wnd = nmb->wnd; + typeof(wnd->ndis_req_task) task; + + ENTER2("status = %08X", status); + wnd->ndis_req_status = status; + wnd->ndis_req_done = 1; + if ((task = xchg(&wnd->ndis_req_task, NULL))) + wake_up_process(task); + else + WARNING("invalid task"); + EXIT2(return); +} + +/* called via function pointer */ +wstdcall void NdisMResetComplete(struct ndis_mp_block *nmb, + NDIS_STATUS status, BOOLEAN address_reset) +{ + struct ndis_device *wnd = nmb->wnd; + typeof(wnd->ndis_req_task) task; + + ENTER2("status: %08X, %u", status, address_reset); + wnd->ndis_req_status = status; + wnd->ndis_req_done = address_reset + 1; + if ((task = xchg(&wnd->ndis_req_task, NULL))) + wake_up_process(task); + else + WARNING("invalid task"); + EXIT2(return); +} + +wstdcall void WIN_FUNC(NdisMSleep,1) + (ULONG us) +{ + unsigned long delay; + + ENTER4("%p: us: %u", current, us); + delay = USEC_TO_HZ(us); + sleep_hz(delay); + TRACE4("%p: done", current); +} + +wstdcall void WIN_FUNC(NdisGetCurrentSystemTime,1) + (LARGE_INTEGER *time) +{ + *time = ticks_1601(); + TRACE5("%Lu, %lu", *time, jiffies); +} + +wstdcall LONG WIN_FUNC(NdisInterlockedDecrement,1) + (LONG *val) +{ + return InterlockedDecrement(val); +} + +wstdcall LONG WIN_FUNC(NdisInterlockedIncrement,1) + (LONG *val) +{ + return InterlockedIncrement(val); +} + +wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertHeadList,3) + (struct nt_list *head, struct nt_list *entry, + struct ndis_spinlock *lock) +{ + return ExInterlockedInsertHeadList(head, entry, &lock->klock); +} + +wstdcall struct nt_list *WIN_FUNC(NdisInterlockedInsertTailList,3) + (struct nt_list *head, struct nt_list *entry, + struct ndis_spinlock *lock) +{ + return ExInterlockedInsertTailList(head, entry, &lock->klock); +} + +wstdcall struct nt_list *WIN_FUNC(NdisInterlockedRemoveHeadList,2) + (struct nt_list *head, struct ndis_spinlock *lock) +{ + return ExInterlockedRemoveHeadList(head, &lock->klock); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMInitializeScatterGatherDma,3) + (struct ndis_mp_block *nmb, BOOLEAN dma_size, ULONG max_phy_map) +{ + struct ndis_device *wnd = nmb->wnd; + ENTER2("dma_size=%d, maxtransfer=%u", dma_size, max_phy_map); +#ifdef CONFIG_X86_64 + if (dma_size != NDIS_DMA_64BITS) { + TRACE1("DMA size is not 64-bits"); + if (pci_set_dma_mask(wnd->wd->pci.pdev, DMA_BIT_MASK(32)) || + pci_set_consistent_dma_mask(wnd->wd->pci.pdev, + DMA_BIT_MASK(32))) + WARNING("setting dma mask failed"); + } +#endif + if ((wnd->attributes & NDIS_ATTRIBUTE_BUS_MASTER) && + wrap_is_pci_bus(wnd->wd->dev_bus)) { + wnd->sg_dma_size = max_phy_map; + return NDIS_STATUS_SUCCESS; + } else + EXIT1(return NDIS_STATUS_NOT_SUPPORTED); +} + +wstdcall ULONG WIN_FUNC(NdisMGetDmaAlignment,1) + (struct ndis_mp_block *nmb) +{ + ENTER3(""); + return dma_get_cache_alignment(); +} + +wstdcall CHAR WIN_FUNC(NdisSystemProcessorCount,0) + (void) +{ + return (CHAR)NR_CPUS; +} + +wstdcall void WIN_FUNC(NdisGetCurrentProcessorCounts,3) + (ULONG *idle, ULONG *kernel_user, ULONG *index) +{ + int cpu = smp_processor_id(); + *idle = kstat_cpu(cpu).cpustat.idle; + *kernel_user = kstat_cpu(cpu).cpustat.system + + kstat_cpu(cpu).cpustat.user; + *index = cpu; +} + +wstdcall void WIN_FUNC(NdisInitializeEvent,1) + (struct ndis_event *ndis_event) +{ + EVENTENTER("%p", ndis_event); + KeInitializeEvent(&ndis_event->nt_event, NotificationEvent, 0); +} + +wstdcall BOOLEAN WIN_FUNC(NdisWaitEvent,2) + (struct ndis_event *ndis_event, UINT ms) +{ + LARGE_INTEGER ticks; + NTSTATUS res; + + EVENTENTER("%p %u", ndis_event, ms); + ticks = -((LARGE_INTEGER)ms * TICKSPERMSEC); + res = KeWaitForSingleObject(&ndis_event->nt_event, 0, 0, TRUE, + ms == 0 ? NULL : &ticks); + if (res == STATUS_SUCCESS) + EXIT3(return TRUE); + else + EXIT3(return FALSE); +} + +wstdcall void WIN_FUNC(NdisSetEvent,1) + (struct ndis_event *ndis_event) +{ + EVENTENTER("%p", ndis_event); + KeSetEvent(&ndis_event->nt_event, 0, 0); +} + +wstdcall void WIN_FUNC(NdisResetEvent,1) + (struct ndis_event *ndis_event) +{ + EVENTENTER("%p", ndis_event); + KeResetEvent(&ndis_event->nt_event); +} + +static void ndis_worker(worker_param_t dummy) +{ + struct nt_list *ent; + struct ndis_work_item *ndis_work_item; + + WORKENTER(""); + while (1) { + spin_lock_bh(&ndis_work_list_lock); + ent = RemoveHeadList(&ndis_work_list); + spin_unlock_bh(&ndis_work_list_lock); + if (!ent) + break; + ndis_work_item = container_of(ent, struct ndis_work_item, list); + WORKTRACE("%p: %p, %p", ndis_work_item, + ndis_work_item->func, ndis_work_item->ctx); + LIN2WIN2(ndis_work_item->func, ndis_work_item, + ndis_work_item->ctx); + WORKTRACE("%p done", ndis_work_item); + } + WORKEXIT(return); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisScheduleWorkItem,1) + (struct ndis_work_item *ndis_work_item) +{ + ENTER3("%p", ndis_work_item); + spin_lock_bh(&ndis_work_list_lock); + InsertTailList(&ndis_work_list, &ndis_work_item->list); + spin_unlock_bh(&ndis_work_list_lock); + WORKTRACE("scheduling %p", ndis_work_item); + schedule_ndis_work(&ndis_work); + EXIT3(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisMGetDeviceProperty,6) + (struct ndis_mp_block *nmb, void **phy_dev, void **func_dev, + void **next_dev, void **alloc_res, void**trans_res) +{ + ENTER2("nmb: %p, phy_dev = %p, func_dev = %p, next_dev = %p, " + "alloc_res = %p, trans_res = %p", nmb, phy_dev, func_dev, + next_dev, alloc_res, trans_res); + if (phy_dev) + *phy_dev = nmb->pdo; + if (func_dev) + *func_dev = nmb->fdo; + if (next_dev) + *next_dev = nmb->next_device; +} + +wstdcall void WIN_FUNC(NdisMRegisterUnloadHandler,2) + (struct driver_object *drv_obj, void *unload) +{ + if (drv_obj) + drv_obj->unload = unload; + return; +} + +wstdcall UINT WIN_FUNC(NdisGetVersion,0) + (void) +{ + return 0x00050001; +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMQueryAdapterInstanceName,2) + (struct unicode_string *name, struct ndis_mp_block *nmb) +{ + struct ndis_device *wnd = nmb->wnd; + struct ansi_string ansi; + + if (wrap_is_pci_bus(wnd->wd->dev_bus)) + RtlInitAnsiString(&ansi, "PCI Ethernet Adapter"); + else + RtlInitAnsiString(&ansi, "USB Ethernet Adapter"); + + if (RtlAnsiStringToUnicodeString(name, &ansi, TRUE)) + EXIT2(return NDIS_STATUS_RESOURCES); + else + EXIT2(return NDIS_STATUS_SUCCESS); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisWriteEventLogEntry,7) + (void *handle, NDIS_STATUS code, ULONG value, USHORT n, + void *strings, ULONG datasize, void *data) +{ + TRACE1("0x%x, 0x%x, %u, %u", code, value, n, datasize); + return NDIS_STATUS_SUCCESS; +} + +wstdcall void *WIN_FUNC(NdisGetRoutineAddress,1) + (struct unicode_string *unicode_string) +{ + struct ansi_string ansi_string; + void *address; + + if (RtlUnicodeStringToAnsiString(&ansi_string, unicode_string, TRUE) != + STATUS_SUCCESS) + EXIT1(return NULL); + INFO("%s", ansi_string.buf); + address = ndis_get_routine_address(ansi_string.buf); + RtlFreeAnsiString(&ansi_string); + return address; +} + +wstdcall ULONG WIN_FUNC(NdisReadPcmciaAttributeMemory,4) + (struct ndis_mp_block *nmb, ULONG offset, void *buffer, + ULONG length) +{ + TODO(); + return 0; +} + +wstdcall ULONG WIN_FUNC(NdisWritePcmciaAttributeMemory,4) + (struct ndis_mp_block *nmb, ULONG offset, void *buffer, + ULONG length) +{ + TODO(); + return 0; +} + +wstdcall void WIN_FUNC(NdisMCoIndicateReceivePacket,3) + (struct ndis_mp_block *nmb, struct ndis_packet **packets, + UINT nr_packets) +{ + ENTER3("nmb = %p", nmb); + NdisMIndicateReceivePacket(nmb, packets, nr_packets); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisMCoSendComplete,3) + (NDIS_STATUS status, struct ndis_mp_block *nmb, + struct ndis_packet *packet) +{ + ENTER3("%08x", status); + NdisMSendComplete(nmb, packet, status); + EXIT3(return); +} + +wstdcall void WIN_FUNC(NdisMCoRequestComplete,3) + (NDIS_STATUS status, struct ndis_mp_block *nmb, + struct ndis_request *ndis_request) +{ + struct ndis_device *wnd = nmb->wnd; + typeof(wnd->ndis_req_task) task; + + ENTER3("%08X", status); + wnd->ndis_req_status = status; + wnd->ndis_req_done = 1; + if ((task = xchg(&wnd->ndis_req_task, NULL))) + wake_up_process(task); + else + WARNING("invalid task"); + EXIT3(return); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisIMNotifiyPnPEvent,2) + (struct ndis_mp_block *nmb, struct net_pnp_event *event) +{ + ENTER2("%p, %d", nmb, event->code); + /* NdisWrapper never calls protocol's pnp event notifier, so + * nothing to do here */ + EXIT2(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisCompletePnPEvent,2) + (NDIS_STATUS status, void *handle, struct net_pnp_event *event) +{ + ENTER2("%d, %p, %d", status, handle, event->code); + /* NdisWrapper never calls protocol's pnp event notifier, so + * nothing to do here */ + EXIT2(return); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMSetMiniportSecondary,2) + (struct ndis_mp_block *nmb2, struct ndis_mp_block *nmb1) +{ + ENTER3("%p, %p", nmb1, nmb2); + TODO(); + EXIT3(return NDIS_STATUS_SUCCESS); +} + +wstdcall NDIS_STATUS WIN_FUNC(NdisMPromoteMiniport,1) + (struct ndis_mp_block *nmb) +{ + ENTER3("%p", nmb); + TODO(); + EXIT3(return NDIS_STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(NdisMCoActivateVcComplete,3) + (NDIS_STATUS status, void *handle, void *params) +{ + TODO(); +} + +wstdcall void WIN_FUNC(NdisMCoDeactivateVcComplete,2) + (NDIS_STATUS status, void *handle) +{ + TODO(); +} + +wstdcall void WIN_FUNC(NdisMRemoveMiniport,1) + (void *handle) +{ + TODO(); +} + +static void *ndis_get_routine_address(char *name) +{ + int i; + ENTER2("%p", name); + for (i = 0; i < sizeof(ndis_exports) / sizeof(ndis_exports[0]); i++) { + if (strcmp(name, ndis_exports[i].name) == 0) { + TRACE2("%p", ndis_exports[i].func); + return ndis_exports[i].func; + } + } + EXIT2(return NULL); +} + +/* ndis_init_device is called for each device */ +int ndis_init_device(struct ndis_device *wnd) +{ + struct ndis_mp_block *nmb = wnd->nmb; + + KeInitializeSpinLock(&nmb->lock); + wnd->mp_interrupt = NULL; + wnd->wrap_timer_slist.next = NULL; + if (wnd->wd->driver->ndis_driver) + wnd->wd->driver->ndis_driver->mp.shutdown = NULL; + + nmb->filterdbs.eth_db = nmb; + nmb->filterdbs.tr_db = nmb; + nmb->filterdbs.fddi_db = nmb; + nmb->filterdbs.arc_db = nmb; + + nmb->rx_packet = WIN_FUNC_PTR(NdisMIndicateReceivePacket,3); + nmb->send_complete = WIN_FUNC_PTR(NdisMSendComplete,3); + nmb->send_resource_avail = WIN_FUNC_PTR(NdisMSendResourcesAvailable,1); + nmb->status = WIN_FUNC_PTR(NdisMIndicateStatus,4); + nmb->status_complete = WIN_FUNC_PTR(NdisMIndicateStatusComplete,1); + nmb->queryinfo_complete = WIN_FUNC_PTR(NdisMQueryInformationComplete,2); + nmb->setinfo_complete = WIN_FUNC_PTR(NdisMSetInformationComplete,2); + nmb->reset_complete = WIN_FUNC_PTR(NdisMResetComplete,3); + nmb->eth_rx_indicate = WIN_FUNC_PTR(EthRxIndicateHandler,8); + nmb->eth_rx_complete = WIN_FUNC_PTR(EthRxComplete,1); + nmb->td_complete = WIN_FUNC_PTR(NdisMTransferDataComplete,4); + return 0; +} + +/* ndis_exit_device is called for each device */ +void ndis_exit_device(struct ndis_device *wnd) +{ + struct wrap_device_setting *setting; + ENTER2("%p", wnd); + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + nt_list_for_each_entry(setting, &wnd->wd->settings, list) { + struct ndis_configuration_parameter *param; + param = setting->encoded; + if (param) { + if (param->type == NdisParameterString) + RtlFreeUnicodeString(¶m->data.string); + ExFreePool(param); + setting->encoded = NULL; + } + } + up(&loader_mutex); +} + +/* ndis_init is called once when module is loaded */ +int ndis_init(void) +{ + InitializeListHead(&ndis_work_list); + spin_lock_init(&ndis_work_list_lock); + initialize_work(&ndis_work, ndis_worker, NULL); + + ndis_wq = create_singlethread_workqueue("ndis_wq"); + if (!ndis_wq) { + WARNING("couldn't create worker thread"); + EXIT1(return -ENOMEM); + } + + ndis_worker_thread = wrap_worker_init(ndis_wq); + TRACE1("%p", ndis_worker_thread); + return 0; +} + +/* ndis_exit is called once when module is removed */ +void ndis_exit(void) +{ + ENTER1(""); + if (ndis_wq) + destroy_workqueue(ndis_wq); + TRACE1("%p", ndis_worker_thread); + if (ndis_worker_thread) + ObDereferenceObject(ndis_worker_thread); + EXIT1(return); +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/ndis.h +++ linux-2.6.37/ubuntu/ndiswrapper/ndis.h @@ -0,0 +1,1314 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _NDIS_H_ +#define _NDIS_H_ + +#include "ntoskernel.h" + +//#define ALLOW_POOL_OVERFLOW 1 + +#define NDIS_DMA_24BITS 0 +#define NDIS_DMA_32BITS 1 +#define NDIS_DMA_64BITS 2 + +#ifdef CONFIG_X86_64 +#define MAXIMUM_PROCESSORS 64 +#else +#define MAXIMUM_PROCESSORS 32 +#endif + +typedef UINT NDIS_STATUS; +typedef UCHAR NDIS_DMA_SIZE; +typedef LONG ndis_rssi; +typedef ULONG ndis_key_index; +typedef ULONG ndis_tx_power_level; +typedef ULONGULONG ndis_key_rsc; +typedef UCHAR ndis_rates[NDIS_MAX_RATES]; +typedef UCHAR ndis_rates_ex[NDIS_MAX_RATES_EX]; +typedef UCHAR mac_address[ETH_ALEN]; +typedef ULONG ndis_fragmentation_threshold; +typedef ULONG ndis_rts_threshold; +typedef ULONG ndis_antenna; +typedef ULONG ndis_oid; + +typedef UCHAR ndis_pmkid_vavlue[16]; + +typedef uint64_t NDIS_PHY_ADDRESS; + +struct ndis_sg_element { + PHYSICAL_ADDRESS address; + ULONG length; + ULONG_PTR reserved; +}; + +struct ndis_sg_list { + ULONG nent; + ULONG_PTR reserved; + struct ndis_sg_element elements[]; +}; + +/* when sending packets, ndiswrapper associates exactly one sg element + * in sg list */ +struct wrap_tx_sg_list { + ULONG nent; + ULONG_PTR reserved; + struct ndis_sg_element elements[1]; +}; + +struct ndis_phy_addr_unit { + NDIS_PHY_ADDRESS phy_addr; + UINT length; +}; + +typedef struct mdl ndis_buffer; + +struct ndis_buffer_pool { + ndis_buffer *free_descr; +// NT_SPIN_LOCK lock; + spinlock_t lock; + UINT max_descr; + UINT num_allocated_descr; +}; + +#define NDIS_PROTOCOL_ID_DEFAULT 0x00 +#define NDIS_PROTOCOL_ID_TCP_IP 0x02 +#define NDIS_PROTOCOL_ID_IPX 0x06 +#define NDIS_PROTOCOL_ID_NBF 0x07 +#define NDIS_PROTOCOL_ID_MAX 0x0F +#define NDIS_PROTOCOL_ID_MASK 0x0F + +#define fPACKET_WRAPPER_RESERVED 0x3F +#define fPACKET_CONTAINS_MEDIA_SPECIFIC_INFO 0x40 +#define fPACKET_ALLOCATED_BY_NDIS 0x80 + +#define PROTOCOL_RESERVED_SIZE_IN_PACKET (4 * sizeof(void *)) + +struct transport_header_offset { + USHORT protocol_type; + USHORT header_offset; +}; + +struct ndis_network_address { + USHORT length; + USHORT type; + UCHAR address[1]; +}; + +struct ndis_network_address_list { + LONG count; + USHORT type; + struct ndis_network_address address[1]; +}; + +struct ndis_tcp_ip_checksum_packet_info { + union { + struct { + ULONG v4:1; + ULONG v6:1; + ULONG tcp:1; + ULONG udp:1; + ULONG ip:1; + } tx; + struct { + ULONG tcp_failed:1; + ULONG udp_failed:1; + ULONG ip_failed:1; + ULONG tcp_succeeded:1; + ULONG udp_succeeded:1; + ULONG ip_succeeded:1; + ULONG loopback:1; + } rx; + ULONG value; + }; +}; + +enum ndis_task { + TcpIpChecksumNdisTask, IpSecNdisTask, TcpLargeSendNdisTask, MaxNdisTask +}; + +enum ndis_encapsulation { + UNSPECIFIED_Encapsulation, NULL_Encapsulation, + IEEE_802_3_Encapsulation, IEEE_802_5_Encapsulation, + LLC_SNAP_ROUTED_Encapsulation, LLC_SNAP_BRIDGED_Encapsulation +}; + +#define NDIS_TASK_OFFLOAD_VERSION 1 + +struct ndis_encapsulation_format { + enum ndis_encapsulation encap; + struct { + ULONG fixed_header_size:1; + ULONG reserved:31; + } flags; + ULONG header_size; +}; + +struct ndis_task_offload_header { + ULONG version; + ULONG size; + ULONG reserved; + ULONG offset_first_task; + struct ndis_encapsulation_format encap_format; +}; + +struct ndis_task_offload { + ULONG version; + ULONG size; + enum ndis_task task; + ULONG offset_next_task; + ULONG task_buf_length; + UCHAR task_buf[1]; +}; + +struct v4_checksum { + union { + struct { + ULONG ip_opts:1; + ULONG tcp_opts:1; + ULONG tcp_csum:1; + ULONG udp_csum:1; + ULONG ip_csum:1; + }; + ULONG value; + }; +}; + +struct v6_checksum { + ULONG ip_supported:1; + ULONG tcp_supported:1; + ULONG tcp_csum:1; + ULONG udp_csum:1; +}; + +struct ndis_task_tcp_ip_checksum { + struct v4_checksum v4_tx; + struct v4_checksum v4_rx; + struct v6_checksum v6_tx; + struct v6_checksum v6_rx; +}; + +struct ndis_task_tcp_large_send { + ULONG version; + ULONG max_size; + ULONG min_seg_count; + BOOLEAN tcp_opts; + BOOLEAN ip_opts; +}; + +struct ndis_packet; + +struct ndis_packet_pool { + struct ndis_packet *free_descr; +// NT_SPIN_LOCK lock; + spinlock_t lock; + UINT max_descr; + UINT num_allocated_descr; + UINT num_used_descr; + UINT proto_rsvd_length; +}; + +struct ndis_packet_stack { + ULONG_PTR IM_reserved[2]; + ULONG_PTR ndis_reserved[4]; +}; + +enum ndis_per_packet_info { + TcpIpChecksumPacketInfo, IpSecPacketInfo, TcpLargeSendPacketInfo, + ClassificationHandlePacketInfo, NdisReserved, + ScatterGatherListPacketInfo, Ieee8021QInfo, OriginalPacketInfo, + PacketCancelId, MaxPerPacketInfo +}; + +struct ndis_packet_extension { + void *info[MaxPerPacketInfo]; +}; + +struct ndis_packet_private { + UINT nr_pages; + UINT len; + ndis_buffer *buffer_head; + ndis_buffer *buffer_tail; + struct ndis_packet_pool *pool; + UINT count; + ULONG flags; + BOOLEAN valid_counts; + UCHAR packet_flags; + USHORT oob_offset; +}; + +struct ndis_packet { + struct ndis_packet_private private; + /* for use by miniport */ + union { + /* for connectionless mininports */ + struct { + UCHAR miniport_reserved[2 * sizeof(void *)]; + UCHAR wrapper_reserved[2 * sizeof(void *)]; + } cl_reserved; + /* for deserialized miniports */ + struct { + UCHAR miniport_reserved_ex[3 * sizeof(void *)]; + UCHAR wrapper_reserved_ex[sizeof(void *)]; + } deserailized_reserved; + struct { + UCHAR mac_reserved[4 * sizeof(void *)]; + } mac_reserved; + }; + ULONG_PTR reserved[2]; + UCHAR protocol_reserved[1]; +}; + +/* OOB data */ +struct ndis_packet_oob_data { + union { + ULONGLONG time_to_tx; + ULONGLONG time_txed; + }; + ULONGLONG time_rxed; + UINT header_size; + UINT media_size; + void *media; + NDIS_STATUS status; + + /* ndiswrapper specific info; extension should be right after + * ndis's oob_data */ + struct ndis_packet_extension ext; + union { + /* used for tx only */ + struct { + struct sk_buff *tx_skb; + union { + struct wrap_tx_sg_list wrap_tx_sg_list; + struct ndis_sg_list *tx_sg_list; + }; + }; + /* used for rx only */ + struct { + unsigned char header[ETH_HLEN]; + unsigned char *look_ahead; + UINT look_ahead_size; + }; + }; +}; + +#define NDIS_PACKET_OOB_DATA(packet) \ + (struct ndis_packet_oob_data *)(((void *)(packet)) + \ + (packet)->private.oob_offset) + +enum ndis_device_pnp_event { + NdisDevicePnPEventQueryRemoved, NdisDevicePnPEventRemoved, + NdisDevicePnPEventSurpriseRemoved, NdisDevicePnPEventQueryStopped, + NdisDevicePnPEventStopped, NdisDevicePnPEventPowerProfileChanged, + NdisDevicePnPEventMaximum +}; + +enum ndis_request_type { + NdisRequestQueryInformation, NdisRequestSetInformation, + NdisRequestQueryStatistics, NdisRequestOpen, NdisRequestClose, + NdisRequestSend, NdisRequestTransferData, NdisRequestReset, + NdisRequestGeneric1, NdisRequestGeneric2, NdisRequestGeneric3, + NdisRequestGeneric4 +}; + +struct ndis_request { + mac_address mac; + enum ndis_request_type request_type; + union data { + struct query_info { + UINT oid; + void *buf; + UINT buf_len; + UINT written; + UINT needed; + } query_info; + struct set_info { + UINT oid; + void *buf; + UINT buf_len; + UINT written; + UINT needed; + } set_info; + } data; +}; + +enum ndis_medium { + NdisMedium802_3, NdisMedium802_5, NdisMediumFddi, NdisMediumWan, + NdisMediumLocalTalk, NdisMediumDix, NdisMediumArcnetRaw, + NdisMediumArcnet878_2, NdisMediumAtm, NdisMediumWirelessWan, + NdisMediumIrda, NdisMediumBpc, NdisMediumCoWan, + NdisMedium1394, NdisMediumMax +}; + +enum ndis_physical_medium { + NdisPhysicalMediumUnspecified, NdisPhysicalMediumWirelessLan, + NdisPhysicalMediumCableModem, NdisPhysicalMediumPhoneLine, + NdisPhysicalMediumPowerLine, NdisPhysicalMediumDSL, + NdisPhysicalMediumFibreChannel, NdisPhysicalMedium1394, + NdisPhysicalMediumWirelessWan, NdisPhysicalMediumMax +}; + +enum ndis_power_state { + NdisDeviceStateUnspecified = 0, + NdisDeviceStateD0, NdisDeviceStateD1, NdisDeviceStateD2, + NdisDeviceStateD3, NdisDeviceStateMaximum +}; + +enum ndis_power_profile { + NdisPowerProfileBattery, NdisPowerProfileAcOnLine +}; + +struct ndis_pm_wakeup_capabilities { + enum ndis_power_state min_magic_packet_wakeup; + enum ndis_power_state min_pattern_wakeup; + enum ndis_power_state min_link_change_wakeup; +}; + +#define NDIS_PNP_WAKE_UP_MAGIC_PACKET 0x00000001 +#define NDIS_PNP_WAKE_UP_PATTERN_MATCH 0x00000002 +#define NDIS_PNP_WAKE_UP_LINK_CHANGE 0x00000004 + +enum net_pnp_event_code { + NetEventSetPower, NetEventQueryPower, NetEventQueryRemoveDevice, + NetEventCancelRemoveDevice, NetEventReconfigure, NetEventBindList, + NetEventBindsComplete, NetEventPnPCapabilities, NetEventMaximum +}; + +struct net_pnp_event { + enum net_pnp_event_code code; + void *buf; + ULONG buf_length; + ULONG_PTR ndis_reserved[4]; + ULONG_PTR transport_reserved[4]; + ULONG_PTR tdi_reserved[4]; + ULONG_PTR tdi_client_reserved[4]; +}; + +struct ndis_pnp_capabilities { + ULONG flags; + struct ndis_pm_wakeup_capabilities wakeup; +}; + +typedef void (*ndis_isr_handler)(BOOLEAN *recognized, BOOLEAN *queue_handler, + void *handle) wstdcall; +typedef void (*ndis_interrupt_handler)(void *ctx) wstdcall; + +struct miniport { + /* NDIS 3.0 */ + UCHAR major_version; + UCHAR minor_version; + USHORT filler; + UINT reserved; + BOOLEAN (*hangcheck)(void *ctx) wstdcall; + void (*disable_interrupt)(void *ctx) wstdcall; + void (*enable_interrupt)(void *ctx) wstdcall; + void (*mp_halt)(void *ctx) wstdcall; + ndis_interrupt_handler handle_interrupt; + NDIS_STATUS (*init)(NDIS_STATUS *error_status, UINT *medium_index, + enum ndis_medium medium[], UINT medium_array_size, + void *handle, void *conf_handle) wstdcall; + ndis_isr_handler isr; + NDIS_STATUS (*queryinfo)(void *ctx, ndis_oid oid, void *buffer, + ULONG buflen, ULONG *written, + ULONG *needed) wstdcall; + void *reconfig; + NDIS_STATUS (*reset)(BOOLEAN *reset_address, void *ctx) wstdcall; + NDIS_STATUS (*send)(void *ctx, struct ndis_packet *packet, + UINT flags) wstdcall; + NDIS_STATUS (*setinfo)(void *ctx, ndis_oid oid, void *buffer, + ULONG buflen, ULONG *written, + ULONG *needed) wstdcall; + NDIS_STATUS (*tx_data)(struct ndis_packet *ndis_packet, + UINT *bytes_txed, void *mp_ctx, void *rx_ctx, + UINT offset, UINT bytes_to_tx) wstdcall; + /* NDIS 4.0 extensions */ + void (*return_packet)(void *ctx, void *packet) wstdcall; + void (*send_packets)(void *ctx, struct ndis_packet **packets, + INT nr_of_packets) wstdcall; + void (*alloc_complete)(void *handle, void *virt, + NDIS_PHY_ADDRESS *phys, + ULONG size, void *ctx) wstdcall; + /* NDIS 5.0 extensions */ + NDIS_STATUS (*co_create_vc)(void *ctx, void *vc_handle, + void *vc_ctx) wstdcall; + NDIS_STATUS (*co_delete_vc)(void *vc_ctx) wstdcall; + NDIS_STATUS (*co_activate_vc)(void *vc_ctx, void *call_params) wstdcall; + NDIS_STATUS (*co_deactivate_vc)(void *vc_ctx) wstdcall; + NDIS_STATUS (*co_send_packets)(void *vc_ctx, void **packets, + UINT nr_of_packets) wstdcall; + NDIS_STATUS (*co_request)(void *ctx, void *vc_ctx, UINT *req) wstdcall; + /* NDIS 5.1 extensions */ + void (*cancel_send_packets)(void *ctx, void *id) wstdcall; + void (*pnp_event_notify)(void *ctx, enum ndis_device_pnp_event event, + void *inf_buf, ULONG inf_buf_len) wstdcall; + void (*shutdown)(void *ctx) wstdcall; + void *reserved1; + void *reserved2; + void *reserved3; + void *reserved4; +}; + +struct ndis_spinlock { + NT_SPIN_LOCK klock; + KIRQL irql; +}; + +union ndis_rw_lock_refcount { + UCHAR cache_line[16]; +}; + +struct ndis_rw_lock { + union { + struct { + NT_SPIN_LOCK klock; + void *context; + }; + UCHAR reserved[16]; + }; + union { + union ndis_rw_lock_refcount ref_count[MAXIMUM_PROCESSORS]; + /* ndiswrapper specific */ + volatile int count; + }; +}; + +struct lock_state { + USHORT state; + KIRQL irql; +}; + +struct ndis_work_item; +typedef void (*NDIS_PROC)(struct ndis_work_item *, void *) wstdcall; + +struct ndis_work_item { + void *ctx; + NDIS_PROC func; + union { + UCHAR reserved[8 * sizeof(void *)]; + /* ndiswrapper specific */ + struct nt_list list; + }; +}; + +struct alloc_shared_mem { + void *ctx; + ULONG size; + BOOLEAN cached; +}; + +struct ndis_mp_block; + +/* this is opaque to drivers, so we can use it as we please */ +struct ndis_mp_interrupt { + struct kinterrupt *kinterrupt; + NT_SPIN_LOCK lock; + union { + void *reserved; + unsigned int irq; + }; + ndis_isr_handler isr; + ndis_interrupt_handler mp_dpc; + struct kdpc intr_dpc; + struct ndis_mp_block *nmb; + UCHAR dpc_count; + BOOLEAN enable; + struct nt_event dpc_completed_event; + BOOLEAN shared; + BOOLEAN req_isr; +}; + +struct ndis_binary_data { + USHORT len; + void *buf; +}; + +enum ndis_parameter_type { + NdisParameterInteger, NdisParameterHexInteger, + NdisParameterString, NdisParameterMultiString, NdisParameterBinary, +}; + +typedef struct unicode_string NDIS_STRING; + +struct ndis_configuration_parameter { + enum ndis_parameter_type type; + union { + ULONG integer; + NDIS_STRING string; + } data; +}; + +struct ndis_driver { + struct miniport mp; +}; + +/* IDs used to store extensions in driver_object's custom extension */ +#define NDIS_DRIVER_CLIENT_ID 10 + +struct ndis_wireless_stats { + ULONG length; + LARGE_INTEGER tx_frag; + LARGE_INTEGER tx_multi_frag; + LARGE_INTEGER failed; + LARGE_INTEGER retry; + LARGE_INTEGER multi_retry; + LARGE_INTEGER rtss_succ; + LARGE_INTEGER rtss_fail; + LARGE_INTEGER ack_fail; + LARGE_INTEGER frame_dup; + LARGE_INTEGER rx_frag; + LARGE_INTEGER rx_multi_frag; + LARGE_INTEGER fcs_err; + LARGE_INTEGER tkip_local_mic_failures; + LARGE_INTEGER tkip_icv_errors; + LARGE_INTEGER tkip_counter_measures_invoked; + LARGE_INTEGER tkip_replays; + LARGE_INTEGER ccmp_format_errors; + LARGE_INTEGER ccmp_replays; + LARGE_INTEGER ccmp_decrypt_errors; + LARGE_INTEGER fourway_handshake_failures; + LARGE_INTEGER wep_undecryptable_count; + LARGE_INTEGER wep_icv_errorcount; + LARGE_INTEGER decrypt_success_count; + LARGE_INTEGER decrypt_failure_count; +}; + +enum ndis_status_type { + Ndis802_11StatusType_Authentication, + Ndis802_11StatusType_MediaStreamMode, + Ndis802_11StatusType_PMKID_CandidateList, + Ndis802_11StatusType_RadioState, +}; + +struct ndis_status_indication { + enum ndis_status_type status_type; +}; + +enum ndis_radio_status { + Ndis802_11RadioStatusOn, Ndis802_11RadioStatusHardwareOff, + Ndis802_11RadioStatusSoftwareOff, +}; + +struct ndis_radio_status_indication +{ + enum ndis_status_type status_type; + enum ndis_radio_status radio_state; +}; + +enum ndis_media_state { + NdisMediaStateConnected, + NdisMediaStateDisconnected, +}; + +enum ndis_media_stream_mode { + Ndis802_11MediaStreamOff, Ndis802_11MediaStreamOn +}; + +enum wrapper_work { + LINK_STATUS_OFF, LINK_STATUS_ON, SET_MULTICAST_LIST, COLLECT_IW_STATS, + HANGCHECK, NETIF_WAKEQ, +}; + +struct encr_info { + struct encr_key { + ULONG length; + UCHAR key[NDIS_ENCODING_TOKEN_MAX]; + } keys[MAX_ENCR_KEYS]; + unsigned short tx_key_index; +}; + +struct ndis_essid { + ULONG length; + UCHAR essid[NDIS_ESSID_MAX_SIZE]; +}; + +enum ndis_infrastructure_mode { + Ndis802_11IBSS, Ndis802_11Infrastructure, Ndis802_11AutoUnknown, + Ndis802_11InfrastructureMax +}; + +enum authentication_mode { + Ndis802_11AuthModeOpen, Ndis802_11AuthModeShared, + Ndis802_11AuthModeAutoSwitch, Ndis802_11AuthModeWPA, + Ndis802_11AuthModeWPAPSK, Ndis802_11AuthModeWPANone, + Ndis802_11AuthModeWPA2, Ndis802_11AuthModeWPA2PSK, + Ndis802_11AuthModeMax +}; + +enum encryption_status { + Ndis802_11WEPEnabled, + Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, + Ndis802_11WEPDisabled, + Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, + Ndis802_11WEPKeyAbsent, + Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, + Ndis802_11WEPNotSupported, + Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, + Ndis802_11Encryption2Enabled, Ndis802_11Encryption2KeyAbsent, + Ndis802_11Encryption3Enabled, Ndis802_11Encryption3KeyAbsent +}; + +struct ndis_auth_encr_pair { + enum authentication_mode auth_mode; + enum encryption_status encr_mode; +}; + +struct ndis_capability { + ULONG length; + ULONG version; + ULONG num_PMKIDs; + ULONG num_auth_encr_pair; + struct ndis_auth_encr_pair auth_encr_pair[1]; +}; + +struct ndis_guid { + struct guid guid; + union { + ndis_oid oid; + NDIS_STATUS status; + }; + ULONG size; + ULONG flags; +}; + +struct ndis_timer { + struct nt_timer nt_timer; + struct kdpc kdpc; +}; + +struct ndis_mp_timer { + struct nt_timer nt_timer; + struct kdpc kdpc; + DPC func; + void *ctx; + struct ndis_mp_block *nmb; + struct ndis_mp_timer *next; +}; + +typedef struct cm_partial_resource_list NDIS_RESOURCE_LIST; + +struct ndis_event { + struct nt_event nt_event; +}; + +struct ndis_bind_paths { + UINT number; + struct unicode_string paths[1]; +}; + +struct ndis_reference { + NT_SPIN_LOCK lock; + USHORT ref_count; + BOOLEAN closing; +}; + +struct ndis_filterdbs { + union { + void *eth_db; + void *null_db; + }; + void *tr_db; + void *fddi_db; + void *arc_db; +}; + +enum ndis_interface_type { + NdisInterfaceInternal, NdisInterfaceIsa, NdisInterfaceEisa, + NdisInterfaceMca, NdisInterfaceTurboChannel, NdisInterfacePci, + NdisInterfacePcMcia, +}; + +struct auth_encr_capa { + unsigned long auth; + unsigned long encr; +}; + +struct ndis_pmkid_candidate { + mac_address bssid; + DWORD flags; +}; + +struct ndis_pmkid_candidate_list { + ULONG version; + ULONG num_candidates; + struct ndis_pmkid_candidate candidates[1]; +}; + +/* + * This struct contains function pointers that the drivers references + * directly via macros, so it's important that they are at the correct + * position. + */ +struct ndis_mp_block { + void *signature; + struct ndis_mp_block *next; + struct driver_object *drv_obj; + void *mp_ctx; + struct unicode_string name; + struct ndis_bind_paths *bindpaths; + void *openqueue; + struct ndis_reference reference; + void *device_ctx; + UCHAR padding; + UCHAR lock_acquired; + UCHAR pmode_opens; + UCHAR assigned_cpu; + NT_SPIN_LOCK lock; + enum ndis_request_type *mediarequest; + struct ndis_mp_interrupt *interrupt; + ULONG flags; + ULONG pnp_flags; + struct nt_list packet_list; + struct ndis_packet *first_pending_tx_packet; + struct ndis_packet *return_packet_queue; + ULONG request_buffer; + void *set_mcast_buffer; + struct ndis_mp_block *primary_mp; + void *wrapper_ctx; + void *bus_data_ctx; + ULONG pnp_capa; + void *resources; + struct ndis_timer wakeup_dpc_timer; + struct unicode_string basename; + struct unicode_string symlink_name; + ULONG ndis_hangcheck_interval; + USHORT hanghcheck_ticks; + USHORT hangcheck_tick; + NDIS_STATUS ndis_reset_status; + void *resetopen; + struct ndis_filterdbs filterdbs; + void *rx_packet; + void *send_complete; + void *send_resource_avail; + void *reset_complete; + + enum ndis_medium media_type; + ULONG bus_number; + enum ndis_interface_type bus_type; + enum ndis_interface_type adapter_type; + struct device_object *fdo; + struct device_object *pdo; + struct device_object *next_device; + void *mapreg; + void *call_mgraflist; + void *mp_thread; + void *setinfobuf; + USHORT setinfo_buf_len; + USHORT max_send_pkts; + NDIS_STATUS fake_status; + void *lock_handler; + struct unicode_string *adapter_instance_name; + void *timer_queue; + UINT mac_options; + void *pending_req; + UINT max_long_addrs; + UINT max_short_addrs; + UINT cur_lookahead; + UINT max_lookahead; + + ndis_interrupt_handler irq_bh; + void *disable_intr; + void *enable_intr; + void *send_pkts; + void *deferred_send; + void *eth_rx_indicate; + void *tr_rx_indicate; + void *fddi_rx_indicate; + void *eth_rx_complete; + void *tr_rx_complete; + void *fddi_rx_complete; + + void *status; + void *status_complete; + void *td_complete; + + void *queryinfo_complete; + void *setinfo_complete; + void *wan_tx_complete; + void *wan_rx; + void *wan_rx_complete; + /* ndiswrapper specific */ + struct ndis_device *wnd; +}; + +struct ndis_device { + struct ndis_mp_block *nmb; + struct wrap_device *wd; + struct net_device *net_dev; + void *shutdown_ctx; + struct ndis_mp_interrupt *mp_interrupt; + struct kdpc irq_kdpc; + unsigned long mem_start; + unsigned long mem_end; + + struct net_device_stats net_stats; + struct iw_statistics iw_stats; + BOOLEAN iw_stats_enabled; + struct ndis_wireless_stats ndis_stats; + + work_struct_t tx_work; + struct ndis_packet *tx_ring[TX_RING_SIZE]; + u8 tx_ring_start; + u8 tx_ring_end; + u8 is_tx_ring_full; + u8 tx_ok; + spinlock_t tx_ring_lock; + struct semaphore tx_ring_mutex; + unsigned int max_tx_packets; + struct semaphore ndis_req_mutex; + struct task_struct *ndis_req_task; + int ndis_req_done; + NDIS_STATUS ndis_req_status; + ULONG packet_filter; + + ULONG sg_dma_size; + ULONG dma_map_count; + dma_addr_t *dma_map_addr; + + int hangcheck_interval; + struct timer_list hangcheck_timer; + int iw_stats_interval; + struct timer_list iw_stats_timer; + unsigned long scan_timestamp; + struct encr_info encr_info; + char nick[IW_ESSID_MAX_SIZE + 1]; + struct ndis_essid essid; + struct auth_encr_capa capa; + enum ndis_infrastructure_mode infrastructure_mode; + int max_pmkids; + int num_pmkids; + struct ndis_pmkid *pmkids; + mac_address mac; + struct proc_dir_entry *procfs_iface; + + work_struct_t ndis_work; + unsigned long ndis_pending_work; + UINT attributes; + int iw_auth_wpa_version; + int iw_auth_cipher_pairwise; + int iw_auth_cipher_group; + int iw_auth_key_mgmt; + int iw_auth_80211_alg; + struct ndis_packet_pool *tx_packet_pool; + struct ndis_buffer_pool *tx_buffer_pool; + int multicast_size; + struct v4_checksum rx_csum; + struct v4_checksum tx_csum; + enum ndis_physical_medium physical_medium; + ULONG ndis_wolopts; + struct nt_slist wrap_timer_slist; + int drv_ndis_version; + struct ndis_pnp_capabilities pnp_capa; + char netdev_name[IFNAMSIZ]; +}; + +BOOLEAN ndis_isr(struct kinterrupt *kinterrupt, void *ctx) wstdcall; + +int ndis_init(void); +void ndis_exit(void); +int ndis_init_device(struct ndis_device *wnd); +void ndis_exit_device(struct ndis_device *wnd); + +int wrap_procfs_add_ndis_device(struct ndis_device *wnd); +void wrap_procfs_remove_ndis_device(struct ndis_device *wnd); + +void NdisAllocatePacketPoolEx(NDIS_STATUS *status, + struct ndis_packet_pool **pool_handle, + UINT num_descr, UINT overflowsize, + UINT proto_rsvd_length) wstdcall; +void NdisFreePacketPool(struct ndis_packet_pool *pool) wstdcall; +void NdisAllocatePacket(NDIS_STATUS *status, struct ndis_packet **packet, + struct ndis_packet_pool *pool) wstdcall; +void NdisFreePacket(struct ndis_packet *descr) wstdcall; +void NdisAllocateBufferPool(NDIS_STATUS *status, + struct ndis_buffer_pool **pool_handle, + UINT num_descr) wstdcall; +void NdisFreeBufferPool(struct ndis_buffer_pool *pool) wstdcall; +void NdisAllocateBuffer(NDIS_STATUS *status, ndis_buffer **buffer, + struct ndis_buffer_pool *pool, void *virt, + UINT length) wstdcall; +void NdisFreeBuffer(ndis_buffer *descr) wstdcall; +void NdisMIndicateReceivePacket(struct ndis_mp_block *nmb, + struct ndis_packet **packets, + UINT nr_packets) wstdcall; +void NdisMSendComplete(struct ndis_mp_block *nmb, struct ndis_packet *packet, + NDIS_STATUS status) wstdcall; +void NdisMSendResourcesAvailable(struct ndis_mp_block *nmb) wstdcall; +void NdisMIndicateStatus(struct ndis_mp_block *nmb, + NDIS_STATUS status, void *buf, UINT len) wstdcall; +void NdisMIndicateStatusComplete(struct ndis_mp_block *nmb) wstdcall; +void NdisMQueryInformationComplete(struct ndis_mp_block *nmb, + NDIS_STATUS status) wstdcall; +void NdisMSetInformationComplete(struct ndis_mp_block *nmb, + NDIS_STATUS status) wstdcall; +void NdisMResetComplete(struct ndis_mp_block *nmb, NDIS_STATUS status, + BOOLEAN address_reset) wstdcall; +ULONG NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *buffer) wstdcall; +BOOLEAN NdisWaitEvent(struct ndis_event *event, UINT timeout) wstdcall; +void NdisSetEvent(struct ndis_event *event) wstdcall; +void NdisMDeregisterInterrupt(struct ndis_mp_interrupt *mp_interrupt) wstdcall; +void EthRxIndicateHandler(struct ndis_mp_block *nmb, void *rx_ctx, + char *header1, char *header, UINT header_size, + void *look_ahead, UINT look_ahead_size, + UINT packet_size) wstdcall; +void EthRxComplete(struct ndis_mp_block *nmb) wstdcall; +void NdisMTransferDataComplete(struct ndis_mp_block *nmb, + struct ndis_packet *packet, NDIS_STATUS status, + UINT bytes_txed) wstdcall; +void NdisWriteConfiguration(NDIS_STATUS *status, struct ndis_mp_block *nmb, + struct unicode_string *key, + struct ndis_configuration_parameter *param) wstdcall; +void NdisReadConfiguration(NDIS_STATUS *status, + struct ndis_configuration_parameter **param, + struct ndis_mp_block *nmb, + struct unicode_string *key, + enum ndis_parameter_type type) wstdcall; + +/* Required OIDs */ +#define OID_GEN_SUPPORTED_LIST 0x00010101 +#define OID_GEN_HARDWARE_STATUS 0x00010102 +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_MEDIA_IN_USE 0x00010104 +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define OID_GEN_LINK_SPEED 0x00010107 +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define OID_GEN_VENDOR_ID 0x0001010C +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define OID_GEN_DRIVER_VERSION 0x00010110 +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define OID_GEN_MAC_OPTIONS 0x00010113 +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +#define OID_GEN_SUPPORTED_GUIDS 0x00010117 +#define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 /* Set only */ +#define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 /* Set only */ +#define OID_GEN_MACHINE_NAME 0x0001021A +#define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B /* Set only */ +#define OID_GEN_VLAN_ID 0x0001021C + +/* Optional OIDs. */ +#define OID_GEN_MEDIA_CAPABILITIES 0x00010201 +#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 + +/* Required statistics OIDs. */ +#define OID_GEN_XMIT_OK 0x00020101 +#define OID_GEN_RCV_OK 0x00020102 +#define OID_GEN_XMIT_ERROR 0x00020103 +#define OID_GEN_RCV_ERROR 0x00020104 +#define OID_GEN_RCV_NO_BUFFER 0x00020105 + +/* Optional OID statistics */ +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define OID_GEN_RCV_CRC_ERROR 0x0002020D +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +#define OID_GEN_GET_TIME_CAPS 0x0002020F +#define OID_GEN_GET_NETCARD_TIME 0x00020210 +#define OID_GEN_NETCARD_LOAD 0x00020211 +#define OID_GEN_DEVICE_PROFILE 0x00020212 + +/* 802.3 (ethernet) OIDs */ +#define OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define OID_802_3_CURRENT_ADDRESS 0x01010102 +#define OID_802_3_MULTICAST_LIST 0x01010103 +#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +#define OID_802_3_MAC_OPTIONS 0x01010105 +#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 +#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define OID_802_3_XMIT_DEFERRED 0x01020201 +#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define OID_802_3_RCV_OVERRUN 0x01020203 +#define OID_802_3_XMIT_UNDERRUN 0x01020204 +#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + +/* PnP and power management OIDs */ +#define OID_PNP_CAPABILITIES 0xFD010100 +#define OID_PNP_SET_POWER 0xFD010101 +#define OID_PNP_QUERY_POWER 0xFD010102 +#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 +#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 +#define OID_PNP_WAKE_UP_PATTERN_LIST 0xFD010105 +#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 + +/* PnP/PM Statistics (Optional). */ +#define OID_PNP_WAKE_UP_OK 0xFD020200 +#define OID_PNP_WAKE_UP_ERROR 0xFD020201 + +/* The following bits are defined for OID_PNP_ENABLE_WAKE_UP */ +#define NDIS_PNP_WAKE_UP_MAGIC_PACKET 0x00000001 +#define NDIS_PNP_WAKE_UP_PATTERN_MATCH 0x00000002 +#define NDIS_PNP_WAKE_UP_LINK_CHANGE 0x00000004 + +/* 802.11 OIDs */ +#define OID_802_11_BSSID 0x0D010101 +#define OID_802_11_SSID 0x0D010102 +#define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0D010203 +#define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 +#define OID_802_11_TX_POWER_LEVEL 0x0D010205 +#define OID_802_11_RSSI 0x0D010206 +#define OID_802_11_RSSI_TRIGGER 0x0D010207 +#define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 +#define OID_802_11_FRAGMENTATION_THRESHOLD 0x0D010209 +#define OID_802_11_RTS_THRESHOLD 0x0D01020A +#define OID_802_11_NUMBER_OF_ANTENNAS 0x0D01020B +#define OID_802_11_RX_ANTENNA_SELECTED 0x0D01020C +#define OID_802_11_TX_ANTENNA_SELECTED 0x0D01020D +#define OID_802_11_SUPPORTED_RATES 0x0D01020E +#define OID_802_11_DESIRED_RATES 0x0D010210 +#define OID_802_11_CONFIGURATION 0x0D010211 +#define OID_802_11_STATISTICS 0x0D020212 +#define OID_802_11_ADD_WEP 0x0D010113 +#define OID_802_11_REMOVE_WEP 0x0D010114 +#define OID_802_11_DISASSOCIATE 0x0D010115 +#define OID_802_11_POWER_MODE 0x0D010216 +#define OID_802_11_BSSID_LIST 0x0D010217 +#define OID_802_11_AUTHENTICATION_MODE 0x0D010118 +#define OID_802_11_PRIVACY_FILTER 0x0D010119 +#define OID_802_11_BSSID_LIST_SCAN 0x0D01011A +#define OID_802_11_WEP_STATUS 0x0D01011B +#define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS +#define OID_802_11_RELOAD_DEFAULTS 0x0D01011C +#define OID_802_11_ADD_KEY 0x0D01011D +#define OID_802_11_REMOVE_KEY 0x0D01011E +#define OID_802_11_ASSOCIATION_INFORMATION 0x0D01011F +#define OID_802_11_TEST 0x0D010120 +#define OID_802_11_MEDIA_STREAM_MODE 0x0D010121 +#define OID_802_11_CAPABILITY 0x0D010122 +#define OID_802_11_PMKID 0x0D010123 + +#define NDIS_STATUS_SUCCESS 0 +#define NDIS_STATUS_PENDING 0x00000103 +#define NDIS_STATUS_NOT_RECOGNIZED 0x00010001 +#define NDIS_STATUS_NOT_COPIED 0x00010002 +#define NDIS_STATUS_NOT_ACCEPTED 0x00010003 +#define NDIS_STATUS_CALL_ACTIVE 0x00010007 +#define NDIS_STATUS_ONLINE 0x40010003 +#define NDIS_STATUS_RESET_START 0x40010004 +#define NDIS_STATUS_RESET_END 0x40010005 +#define NDIS_STATUS_RING_STATUS 0x40010006 +#define NDIS_STATUS_CLOSED 0x40010007 +#define NDIS_STATUS_WAN_LINE_UP 0x40010008 +#define NDIS_STATUS_WAN_LINE_DOWN 0x40010009 +#define NDIS_STATUS_WAN_FRAGMENT 0x4001000A +#define NDIS_STATUS_MEDIA_CONNECT 0x4001000B +#define NDIS_STATUS_MEDIA_DISCONNECT 0x4001000C +#define NDIS_STATUS_HARDWARE_LINE_UP 0x4001000D +#define NDIS_STATUS_HARDWARE_LINE_DOWN 0x4001000E +#define NDIS_STATUS_INTERFACE_UP 0x4001000F +#define NDIS_STATUS_INTERFACE_DOWN 0x40010010 +#define NDIS_STATUS_MEDIA_BUSY 0x40010011 +#define NDIS_STATUS_MEDIA_SPECIFIC_INDICATION 0x40010012 +#define NDIS_STATUS_WW_INDICATION NDIS_STATUS_MEDIA_SPECIFIC_INDICATION +#define NDIS_STATUS_LINK_SPEED_CHANGE 0x40010013 +#define NDIS_STATUS_WAN_GET_STATS 0x40010014 +#define NDIS_STATUS_WAN_CO_FRAGMENT 0x40010015 +#define NDIS_STATUS_WAN_CO_LINKPARAMS 0x40010016 +#define NDIS_STATUS_NOT_RESETTABLE 0x80010001 +#define NDIS_STATUS_SOFT_ERRORS 0x80010003 +#define NDIS_STATUS_HARD_ERRORS 0x80010004 +#define NDIS_STATUS_BUFFER_OVERFLOW 0x80000005 +#define NDIS_STATUS_FAILURE 0xC0000001 +#define NDIS_STATUS_INVALID_PARAMETER 0xC000000D +#define NDIS_STATUS_RESOURCES 0xC000009A +#define NDIS_STATUS_CLOSING 0xC0010002 +#define NDIS_STATUS_BAD_VERSION 0xC0010004 +#define NDIS_STATUS_BAD_CHARACTERISTICS 0xC0010005 +#define NDIS_STATUS_ADAPTER_NOT_FOUND 0xC0010006 +#define NDIS_STATUS_OPEN_FAILED 0xC0010007 +#define NDIS_STATUS_DEVICE_FAILED 0xC0010008 +#define NDIS_STATUS_MULTICAST_FULL 0xC0010009 +#define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A +#define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B +#define NDIS_STATUS_REQUEST_ABORTED 0xC001000C +#define NDIS_STATUS_RESET_IN_PROGRESS 0xC001000D +#define NDIS_STATUS_CLOSING_INDICATING 0xC001000E +#define NDIS_STATUS_BAD_VERSION 0xC0010004 +#define NDIS_STATUS_NOT_SUPPORTED 0xC00000BB +#define NDIS_STATUS_INVALID_PACKET 0xC001000F +#define NDIS_STATUS_OPEN_LIST_FULL 0xC0010010 +#define NDIS_STATUS_ADAPTER_NOT_READY 0xC0010011 +#define NDIS_STATUS_ADAPTER_NOT_OPEN 0xC0010012 +#define NDIS_STATUS_NOT_INDICATING 0xC0010013 +#define NDIS_STATUS_INVALID_LENGTH 0xC0010014 +#define NDIS_STATUS_INVALID_DATA 0xC0010015 +#define NDIS_STATUS_BUFFER_TOO_SHORT 0xC0010016 +#define NDIS_STATUS_INVALID_OID 0xC0010017 +#define NDIS_STATUS_ADAPTER_REMOVED 0xC0010018 +#define NDIS_STATUS_UNSUPPORTED_MEDIA 0xC0010019 +#define NDIS_STATUS_GROUP_ADDRESS_IN_USE 0xC001001A +#define NDIS_STATUS_FILE_NOT_FOUND 0xC001001B +#define NDIS_STATUS_ERROR_READING_FILE 0xC001001C +#define NDIS_STATUS_ALREADY_MAPPED 0xC001001D +#define NDIS_STATUS_RESOURCE_CONFLICT 0xC001001E +#define NDIS_STATUS_NO_CABLE 0xC001001F +#define NDIS_STATUS_INVALID_SAP 0xC0010020 +#define NDIS_STATUS_SAP_IN_USE 0xC0010021 +#define NDIS_STATUS_INVALID_ADDRESS 0xC0010022 +#define NDIS_STATUS_VC_NOT_ACTIVATED 0xC0010023 +#define NDIS_STATUS_DEST_OUT_OF_ORDER 0xC0010024 +#define NDIS_STATUS_VC_NOT_AVAILABLE 0xC0010025 +#define NDIS_STATUS_CELLRATE_NOT_AVAILABLE 0xC0010026 +#define NDIS_STATUS_INCOMPATABLE_QOS 0xC0010027 +#define NDIS_STATUS_AAL_PARAMS_UNSUPPORTED 0xC0010028 +#define NDIS_STATUS_NO_ROUTE_TO_DESTINATION 0xC0010029 +#define NDIS_STATUS_TOKEN_RING_OPEN_ERROR 0xC0011000 +#define NDIS_STATUS_INVALID_DEVICE_REQUEST 0xC0000010 +#define NDIS_STATUS_NETWORK_UNREACHABLE 0xC000023C + +/* Event codes */ + +#define EVENT_NDIS_RESOURCE_CONFLICT 0xC0001388 +#define EVENT_NDIS_OUT_OF_RESOURCE 0xC0001389 +#define EVENT_NDIS_HARDWARE_FAILURE 0xC000138A +#define EVENT_NDIS_ADAPTER_NOT_FOUND 0xC000138B +#define EVENT_NDIS_INTERRUPT_CONNECT 0xC000138C +#define EVENT_NDIS_DRIVER_FAILURE 0xC000138D +#define EVENT_NDIS_BAD_VERSION 0xC000138E +#define EVENT_NDIS_TIMEOUT 0x8000138F +#define EVENT_NDIS_NETWORK_ADDRESS 0xC0001390 +#define EVENT_NDIS_UNSUPPORTED_CONFIGURATION 0xC0001391 +#define EVENT_NDIS_INVALID_VALUE_FROM_ADAPTER 0xC0001392 +#define EVENT_NDIS_MISSING_CONFIGURATION_PARAMETER 0xC0001393 +#define EVENT_NDIS_BAD_IO_BASE_ADDRESS 0xC0001394 +#define EVENT_NDIS_RECEIVE_SPACE_SMALL 0x40001395 +#define EVENT_NDIS_ADAPTER_DISABLED 0x80001396 +#define EVENT_NDIS_IO_PORT_CONFLICT 0x80001397 +#define EVENT_NDIS_PORT_OR_DMA_CONFLICT 0x80001398 +#define EVENT_NDIS_MEMORY_CONFLICT 0x80001399 +#define EVENT_NDIS_INTERRUPT_CONFLICT 0x8000139A +#define EVENT_NDIS_DMA_CONFLICT 0x8000139B +#define EVENT_NDIS_INVALID_DOWNLOAD_FILE_ERROR 0xC000139C +#define EVENT_NDIS_MAXRECEIVES_ERROR 0x8000139D +#define EVENT_NDIS_MAXTRANSMITS_ERROR 0x8000139E +#define EVENT_NDIS_MAXFRAMESIZE_ERROR 0x8000139F +#define EVENT_NDIS_MAXINTERNALBUFS_ERROR 0x800013A0 +#define EVENT_NDIS_MAXMULTICAST_ERROR 0x800013A1 +#define EVENT_NDIS_PRODUCTID_ERROR 0x800013A2 +#define EVENT_NDIS_LOBE_FAILUE_ERROR 0x800013A3 +#define EVENT_NDIS_SIGNAL_LOSS_ERROR 0x800013A4 +#define EVENT_NDIS_REMOVE_RECEIVED_ERROR 0x800013A5 +#define EVENT_NDIS_TOKEN_RING_CORRECTION 0x400013A6 +#define EVENT_NDIS_ADAPTER_CHECK_ERROR 0xC00013A7 +#define EVENT_NDIS_RESET_FAILURE_ERROR 0x800013A8 +#define EVENT_NDIS_CABLE_DISCONNECTED_ERROR 0x800013A9 +#define EVENT_NDIS_RESET_FAILURE_CORRECTION 0x800013AA + +/* packet filter bits used by NDIS_OID_PACKET_FILTER */ +#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 +#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 +#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 +#define NDIS_PACKET_TYPE_SMT 0x00000040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 +#define NDIS_PACKET_TYPE_GROUP 0x00001000 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00002000 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00004000 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x00008000 + +/* memory allocation flags */ +#define NDIS_MEMORY_CONTIGUOUS 0x00000001 +#define NDIS_MEMORY_NONCACHED 0x00000002 + +/* Atrribute flags to NdisMSetAtrributesEx */ +#define NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT 0x00000001 +#define NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT 0x00000002 +#define NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS 0x00000004 +#define NDIS_ATTRIBUTE_BUS_MASTER 0x00000008 +#define NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER 0x00000010 +#define NDIS_ATTRIBUTE_DESERIALIZE 0x00000020 +#define NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND 0x00000040 +#define NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK 0x00000080 +#define NDIS_ATTRIBUTE_NOT_CO_NDIS 0x00000100 +#define NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS 0x00000200 + +#define OID_TCP_TASK_OFFLOAD 0xFC010201 + +#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 +#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 +#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 +#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 +#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 +#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 +#define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 +#define NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00000080 +#define NDIS_MAC_OPTION_RECEIVE_AT_DPC 0x00000100 +#define NDIS_MAC_OPTION_8021Q_VLAN 0x00000200 +#define NDIS_MAC_OPTION_RESERVED 0x80000000 + +#define deserialized_driver(wnd) (wnd->attributes & NDIS_ATTRIBUTE_DESERIALIZE) + +static inline void serialize_lock(struct ndis_device *wnd) +{ + nt_spin_lock(&wnd->nmb->lock); +} + +static inline void serialize_unlock(struct ndis_device *wnd) +{ + nt_spin_unlock(&wnd->nmb->lock); +} + +static inline KIRQL serialize_lock_irql(struct ndis_device *wnd) +{ + if (deserialized_driver(wnd)) + return raise_irql(DISPATCH_LEVEL); + else + return nt_spin_lock_irql(&wnd->nmb->lock, DISPATCH_LEVEL); +} + +static inline void serialize_unlock_irql(struct ndis_device *wnd, + KIRQL irql) +{ + if (deserialized_driver(wnd)) + lower_irql(irql); + else + nt_spin_unlock_irql(&wnd->nmb->lock, irql); +} + +static inline void if_serialize_lock(struct ndis_device *wnd) +{ + if (!deserialized_driver(wnd)) + nt_spin_lock(&wnd->nmb->lock); +} + +static inline void if_serialize_unlock(struct ndis_device *wnd) +{ + if (!deserialized_driver(wnd)) + nt_spin_unlock(&wnd->nmb->lock); +} + +#endif /* NDIS_H */ --- linux-2.6.37.orig/ubuntu/ndiswrapper/ndiswrapper.h +++ linux-2.6.37/ubuntu/ndiswrapper/ndiswrapper.h @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _NDISWRAPPER_H_ +#define _NDISWRAPPER_H_ + +#define DRIVER_VERSION "1.56" +#define UTILS_VERSION "1.9" + +#define DRIVER_NAME "ndiswrapper" +#define DRIVER_CONFIG_DIR "/etc/ndiswrapper" + +#define SSID_MAX_WPA_IE_LEN 40 +#define NDIS_ESSID_MAX_SIZE 32 +#define NDIS_ENCODING_TOKEN_MAX 32 +#define MAX_ENCR_KEYS 4 +#define TX_RING_SIZE 16 +#define NDIS_MAX_RATES 8 +#define NDIS_MAX_RATES_EX 16 +#define WLAN_EID_GENERIC 221 +#define MAX_WPA_IE_LEN 64 +#define MAX_STR_LEN 512 + +#define WRAP_PCI_BUS 5 +#define WRAP_PCMCIA_BUS 8 +/* some USB devices, e.g., DWL-G120 have BusType as 0 */ +#define WRAP_INTERNAL_BUS 0 +/* documentation at msdn says 15 is PNP bus, but inf files from all + * vendors say 15 is USB; which is correct? */ +#define WRAP_USB_BUS 15 + +/* NDIS device must be 0, for compatability with old versions of + * ndiswrapper where device type for NDIS drivers is 0 */ +#define WRAP_NDIS_DEVICE 0 +#define WRAP_USB_DEVICE 1 +#define WRAP_BLUETOOTH_DEVICE1 2 +#define WRAP_BLUETOOTH_DEVICE2 3 + +#define WRAP_DEVICE_BUS(dev, bus) ((dev) << 8 | (bus)) +#define WRAP_BUS(dev_bus) ((dev_bus) & 0x000FF) +#define WRAP_DEVICE(dev_bus) ((dev_bus) >> 8) + +#define MAX_DRIVER_NAME_LEN 32 +#define MAX_VERSION_STRING_LEN 64 +#define MAX_SETTING_NAME_LEN 128 +#define MAX_SETTING_VALUE_LEN 256 + +#define MAX_DRIVER_PE_IMAGES 4 +#define MAX_DRIVER_BIN_FILES 5 +#define MAX_DEVICE_SETTINGS 512 + +#define MAX_ALLOCATED_URBS 15 + +#define DEV_ANY_ID -1 + +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTRSEP "%02x:%02x:%02x:%02x:%02x:%02x" +#define MACSTR "%02x%02x%02x%02x%02x%02x" +#define MACINTADR(a) (int*)&((a)[0]), (int*)&((a)[1]), (int*)&((a)[2]), \ + (int*)&((a)[3]), (int*)&((a)[4]), (int*)&((a)[5]) + +#ifdef __KERNEL__ +/* DEBUG macros */ + +#define MSG(level, fmt, ...) \ + printk(level "ndiswrapper (%s:%d): " fmt "\n", \ + __func__, __LINE__ , ## __VA_ARGS__) + +#define WARNING(fmt, ...) MSG(KERN_WARNING, fmt, ## __VA_ARGS__) +#define ERROR(fmt, ...) MSG(KERN_ERR, fmt , ## __VA_ARGS__) +#define INFO(fmt, ...) MSG(KERN_INFO, fmt , ## __VA_ARGS__) +#define TODO() WARNING("not fully implemented (yet)") + +#define TRACE(fmt, ...) do { } while (0) +#define TRACE1(fmt, ...) do { } while (0) +#define TRACE2(fmt, ...) do { } while (0) +#define TRACE3(fmt, ...) do { } while (0) +#define TRACE4(fmt, ...) do { } while (0) +#define TRACE5(fmt, ...) do { } while (0) +#define TRACE6(fmt, ...) do { } while (0) + +/* for a block of code */ +#define DBG_BLOCK(level) while (0) + +extern int debug; + +#if defined DEBUG +#undef TRACE +#define TRACE(level, fmt, ...) \ +do { \ + if (debug >= level) \ + printk(KERN_INFO "%s (%s:%d): " fmt "\n", DRIVER_NAME, \ + __func__, __LINE__ , ## __VA_ARGS__); \ +} while (0) +#undef DBG_BLOCK +#define DBG_BLOCK(level) if (debug >= level) +#endif + +#if defined(DEBUG) && DEBUG >= 1 +#undef TRACE1 +#define TRACE1(fmt, ...) TRACE(1, fmt , ## __VA_ARGS__) +#endif + +#if defined(DEBUG) && DEBUG >= 2 +#undef TRACE2 +#define TRACE2(fmt, ...) TRACE(2, fmt , ## __VA_ARGS__) +#endif + +#if defined(DEBUG) && DEBUG >= 3 +#undef TRACE3 +#define TRACE3(fmt, ...) TRACE(3, fmt , ## __VA_ARGS__) +#endif + +#if defined(DEBUG) && DEBUG >= 4 +#undef TRACE4 +#define TRACE4(fmt, ...) TRACE(4, fmt , ## __VA_ARGS__) +#endif + +#if defined(DEBUG) && DEBUG >= 5 +#undef TRACE5 +#define TRACE5(fmt, ...) TRACE(5, fmt , ## __VA_ARGS__) +#endif + +#if defined(DEBUG) && DEBUG >= 6 +#undef TRACE6 +#define TRACE6(fmt, ...) TRACE(6, fmt , ## __VA_ARGS__) +#endif + +#define ENTER1(fmt, ...) TRACE1("Enter " fmt , ## __VA_ARGS__) +#define ENTER2(fmt, ...) TRACE2("Enter " fmt , ## __VA_ARGS__) +#define ENTER3(fmt, ...) TRACE3("Enter " fmt , ## __VA_ARGS__) +#define ENTER4(fmt, ...) TRACE4("Enter " fmt , ## __VA_ARGS__) +#define ENTER5(fmt, ...) TRACE5("Enter " fmt , ## __VA_ARGS__) +#define ENTER6(fmt, ...) TRACE6("Enter " fmt , ## __VA_ARGS__) + +#define EXIT1(stmt) do { TRACE1("Exit"); stmt; } while(0) +#define EXIT2(stmt) do { TRACE2("Exit"); stmt; } while(0) +#define EXIT3(stmt) do { TRACE3("Exit"); stmt; } while(0) +#define EXIT4(stmt) do { TRACE4("Exit"); stmt; } while(0) +#define EXIT5(stmt) do { TRACE5("Exit"); stmt; } while(0) +#define EXIT6(stmt) do { TRACE6("Exit"); stmt; } while(0) + +#if defined(USB_DEBUG) +#define USBTRACE TRACE1 +#define USBENTER ENTER1 +#define USBEXIT EXIT1 +#else +#define USBTRACE(fmt, ...) +#define USBENTER(fmt, ...) +#define USBEXIT(stmt) stmt +#endif + +#if defined(EVENT_DEBUG) +#define EVENTTRACE TRACE1 +#define EVENTENTER ENTER1 +#define EVENTEXIT EXIT1 +#else +#define EVENTTRACE(fmt, ...) +#define EVENTENTER(fmt, ...) +#define EVENTEXIT(stmt) stmt +#endif + +#if defined(TIMER_DEBUG) +#define TIMERTRACE TRACE1 +#define TIMERENTER ENTER1 +#define TIMEREXIT EXIT1 +#else +#define TIMERTRACE(fmt, ...) +#define TIMERENTER(fmt, ...) +#define TIMEREXIT(stmt) stmt +#endif + +#if defined(IO_DEBUG) +#define IOTRACE TRACE1 +#define IOENTER ENTER1 +#define IOEXIT EXIT1 +#else +#define IOTRACE(fmt, ...) +#define IOENTER(fmt, ...) +#define IOEXIT(stmt) stmt +#endif + +#if defined(WORK_DEBUG) +#define WORKTRACE TRACE1 +#define WORKENTER ENTER1 +#define WORKEXIT EXIT1 +#else +#define WORKTRACE(fmt, ...) +#define WORKENTER(fmt, ...) +#define WORKEXIT(stmt) stmt +#endif + +#ifdef DEBUG +#define assert(expr) \ +do { \ + if (!(expr)) { \ + ERROR("assertion '%s' failed", #expr); \ + dump_stack(); \ + } \ +} while (0) +#else +#define assert(expr) do { } while (0) +#endif + +#endif // __KERNEL__ + +#endif // NDISWRAPPER_H --- linux-2.6.37.orig/ubuntu/ndiswrapper/ntoskernel.c +++ linux-2.6.37/ubuntu/ndiswrapper/ntoskernel.c @@ -0,0 +1,2683 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ + +#include "ntoskernel.h" +#include "ndis.h" +#include "usb.h" +#include "pnp.h" +#include "loader.h" +#include "ntoskernel_exports.h" + +/* MDLs describe a range of virtual address with an array of physical + * pages right after the header. For different ranges of virtual + * addresses, the number of entries of physical pages may be different + * (depending on number of entries required). If we want to allocate + * MDLs from a pool, the size has to be constant. So we assume that + * maximum range used by a driver is MDL_CACHE_PAGES; if a driver + * requests an MDL for a bigger region, we allocate it with kmalloc; + * otherwise, we allocate from the pool */ + +#define MDL_CACHE_PAGES 3 +#define MDL_CACHE_SIZE (sizeof(struct mdl) + \ + (sizeof(PFN_NUMBER) * MDL_CACHE_PAGES)) +struct wrap_mdl { + struct nt_list list; + struct mdl mdl[0]; +}; + +/* everything here is for all drivers/devices - not per driver/device */ +static spinlock_t dispatcher_lock; +spinlock_t ntoskernel_lock; +static void *mdl_cache; +static struct nt_list wrap_mdl_list; + +static work_struct_t kdpc_work; +static void kdpc_worker(worker_param_t dummy); + +static struct nt_list kdpc_list; +static spinlock_t kdpc_list_lock; + +static struct nt_list callback_objects; + +struct nt_list object_list; + +struct bus_driver { + struct nt_list list; + char name[MAX_DRIVER_NAME_LEN]; + struct driver_object drv_obj; +}; + +static struct nt_list bus_driver_list; + +static work_struct_t ntos_work; +static struct nt_list ntos_work_list; +static spinlock_t ntos_work_lock; +static void ntos_work_worker(worker_param_t dummy); +static struct nt_thread *ntos_worker_thread; +spinlock_t irp_cancel_lock; +static NT_SPIN_LOCK nt_list_lock; +static struct nt_slist wrap_timer_slist; + +/* compute ticks (100ns) since 1601 until when system booted into + * wrap_ticks_to_boot */ +u64 wrap_ticks_to_boot; + +#if defined(CONFIG_X86_64) +static struct timer_list shared_data_timer; +struct kuser_shared_data kuser_shared_data; +static void update_user_shared_data_proc(unsigned long data); +#endif + +WIN_SYMBOL_MAP("KeTickCount", &jiffies) + +WIN_SYMBOL_MAP("NlsMbCodePageTag", FALSE) + +workqueue_struct_t *ntos_wq; + +#ifdef WRAP_PREEMPT +DEFINE_PER_CPU(irql_info_t, irql_info); +#endif + +#if defined(CONFIG_X86_64) +static void update_user_shared_data_proc(unsigned long data) +{ + /* timer is supposed to be scheduled every 10ms, but bigger + * intervals seem to work (tried upto 50ms) */ + *((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601(); + *((ULONG64 *)&kuser_shared_data.interrupt_time) = + jiffies * TICKSPERSEC / HZ; + *((ULONG64 *)&kuser_shared_data.tick) = jiffies; + + mod_timer(&shared_data_timer, jiffies + MSEC_TO_HZ(30)); +} +#endif + +void *allocate_object(ULONG size, enum common_object_type type, + struct unicode_string *name) +{ + struct common_object_header *hdr; + void *body; + + /* we pad header as prefix to body */ + hdr = ExAllocatePoolWithTag(NonPagedPool, OBJECT_SIZE(size), 0); + if (!hdr) { + WARNING("couldn't allocate memory"); + return NULL; + } + memset(hdr, 0, OBJECT_SIZE(size)); + if (name) { + hdr->name.buf = ExAllocatePoolWithTag(NonPagedPool, + name->max_length, 0); + if (!hdr->name.buf) { + ExFreePool(hdr); + return NULL; + } + memcpy(hdr->name.buf, name->buf, name->max_length); + hdr->name.length = name->length; + hdr->name.max_length = name->max_length; + } + hdr->type = type; + hdr->ref_count = 1; + spin_lock_bh(&ntoskernel_lock); + /* threads are looked up often (in KeWaitForXXX), so optimize + * for fast lookups of threads */ + if (type == OBJECT_TYPE_NT_THREAD) + InsertHeadList(&object_list, &hdr->list); + else + InsertTailList(&object_list, &hdr->list); + spin_unlock_bh(&ntoskernel_lock); + body = HEADER_TO_OBJECT(hdr); + TRACE3("allocated hdr: %p, body: %p", hdr, body); + return body; +} + +void free_object(void *object) +{ + struct common_object_header *hdr; + + hdr = OBJECT_TO_HEADER(object); + spin_lock_bh(&ntoskernel_lock); + RemoveEntryList(&hdr->list); + spin_unlock_bh(&ntoskernel_lock); + TRACE3("freed hdr: %p, body: %p", hdr, object); + if (hdr->name.buf) + ExFreePool(hdr->name.buf); + ExFreePool(hdr); +} + +static int add_bus_driver(const char *name) +{ + struct bus_driver *bus_driver; + + bus_driver = kzalloc(sizeof(*bus_driver), GFP_KERNEL); + if (!bus_driver) { + ERROR("couldn't allocate memory"); + return -ENOMEM; + } + strncpy(bus_driver->name, name, sizeof(bus_driver->name)); + bus_driver->name[sizeof(bus_driver->name)-1] = 0; + spin_lock_bh(&ntoskernel_lock); + InsertTailList(&bus_driver_list, &bus_driver->list); + spin_unlock_bh(&ntoskernel_lock); + TRACE1("bus driver %s is at %p", name, &bus_driver->drv_obj); + return STATUS_SUCCESS; +} + +struct driver_object *find_bus_driver(const char *name) +{ + struct bus_driver *bus_driver; + struct driver_object *drv_obj; + + spin_lock_bh(&ntoskernel_lock); + drv_obj = NULL; + nt_list_for_each_entry(bus_driver, &bus_driver_list, list) { + if (strcmp(bus_driver->name, name) == 0) { + drv_obj = &bus_driver->drv_obj; + break; + } + } + spin_unlock_bh(&ntoskernel_lock); + return drv_obj; +} + +wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertHeadList,3) + (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock) +{ + struct nt_list *first; + unsigned long flags; + + ENTER5("head = %p, entry = %p", head, entry); + nt_spin_lock_irqsave(lock, flags); + first = InsertHeadList(head, entry); + nt_spin_unlock_irqrestore(lock, flags); + TRACE5("head = %p, old = %p", head, first); + return first; +} + +wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertHeadList,3) + (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock) +{ + ENTER5("%p", head); + return ExfInterlockedInsertHeadList(head, entry, lock); +} + +wfastcall struct nt_list *WIN_FUNC(ExfInterlockedInsertTailList,3) + (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock) +{ + struct nt_list *last; + unsigned long flags; + + ENTER5("head = %p, entry = %p", head, entry); + nt_spin_lock_irqsave(lock, flags); + last = InsertTailList(head, entry); + nt_spin_unlock_irqrestore(lock, flags); + TRACE5("head = %p, old = %p", head, last); + return last; +} + +wfastcall struct nt_list *WIN_FUNC(ExInterlockedInsertTailList,3) + (struct nt_list *head, struct nt_list *entry, NT_SPIN_LOCK *lock) +{ + ENTER5("%p", head); + return ExfInterlockedInsertTailList(head, entry, lock); +} + +wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveHeadList,2) + (struct nt_list *head, NT_SPIN_LOCK *lock) +{ + struct nt_list *ret; + unsigned long flags; + + ENTER5("head = %p", head); + nt_spin_lock_irqsave(lock, flags); + ret = RemoveHeadList(head); + nt_spin_unlock_irqrestore(lock, flags); + TRACE5("head = %p, ret = %p", head, ret); + return ret; +} + +wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveHeadList,2) + (struct nt_list *head, NT_SPIN_LOCK *lock) +{ + ENTER5("%p", head); + return ExfInterlockedRemoveHeadList(head, lock); +} + +wfastcall struct nt_list *WIN_FUNC(ExfInterlockedRemoveTailList,2) + (struct nt_list *head, NT_SPIN_LOCK *lock) +{ + struct nt_list *ret; + unsigned long flags; + + ENTER5("head = %p", head); + nt_spin_lock_irqsave(lock, flags); + ret = RemoveTailList(head); + nt_spin_unlock_irqrestore(lock, flags); + TRACE5("head = %p, ret = %p", head, ret); + return ret; +} + +wfastcall struct nt_list *WIN_FUNC(ExInterlockedRemoveTailList,2) + (struct nt_list *head, NT_SPIN_LOCK *lock) +{ + ENTER5("%p", head); + return ExfInterlockedRemoveTailList(head, lock); +} + +wfastcall void WIN_FUNC(InitializeSListHead,1) + (nt_slist_header *head) +{ + memset(head, 0, sizeof(*head)); +} + +wfastcall struct nt_slist *WIN_FUNC(ExInterlockedPushEntrySList,3) + (nt_slist_header *head, struct nt_slist *entry, NT_SPIN_LOCK *lock) +{ + struct nt_slist *ret; + + ret = PushEntrySList(head, entry, lock); + return ret; +} + +wstdcall struct nt_slist *WIN_FUNC(ExpInterlockedPushEntrySList,2) + (nt_slist_header *head, struct nt_slist *entry) +{ + struct nt_slist *ret; + + ret = PushEntrySList(head, entry, &nt_list_lock); + return ret; +} + +wfastcall struct nt_slist *WIN_FUNC(InterlockedPushEntrySList,2) + (nt_slist_header *head, struct nt_slist *entry) +{ + struct nt_slist *ret; + + ret = PushEntrySList(head, entry, &nt_list_lock); + return ret; +} + +wfastcall struct nt_slist *WIN_FUNC(ExInterlockedPopEntrySList,2) + (nt_slist_header *head, NT_SPIN_LOCK *lock) +{ + struct nt_slist *ret; + + ret = PopEntrySList(head, lock); + return ret; +} + +wstdcall struct nt_slist *WIN_FUNC(ExpInterlockedPopEntrySList,1) + (nt_slist_header *head) +{ + struct nt_slist *ret; + + ret = PopEntrySList(head, &nt_list_lock); + return ret; +} + +wfastcall struct nt_slist *WIN_FUNC(InterlockedPopEntrySList,1) + (nt_slist_header *head) +{ + struct nt_slist *ret; + + ret = PopEntrySList(head, &nt_list_lock); + return ret; +} + +wstdcall USHORT WIN_FUNC(ExQueryDepthSList,1) + (nt_slist_header *head) +{ + USHORT depth; + ENTER5("%p", head); + depth = head->depth; + TRACE5("%d, %p", depth, head->next); + return depth; +} + +wfastcall LONG WIN_FUNC(InterlockedIncrement,1) + (LONG volatile *val) +{ + return post_atomic_add(*val, 1); +} + +wfastcall LONG WIN_FUNC(InterlockedDecrement,1) + (LONG volatile *val) +{ + return post_atomic_add(*val, -1); +} + +wfastcall LONG WIN_FUNC(InterlockedExchange,2) + (LONG volatile *target, LONG val) +{ + return xchg(target, val); +} + +wfastcall LONG WIN_FUNC(InterlockedCompareExchange,3) + (LONG volatile *dest, LONG new, LONG old) +{ + return cmpxchg(dest, old, new); +} + +wfastcall void WIN_FUNC(ExInterlockedAddLargeStatistic,2) + (LARGE_INTEGER volatile *plint, ULONG n) +{ + unsigned long flags; + + local_irq_save(flags); +#ifdef CONFIG_X86_64 + __asm__ __volatile__( + "\n" + LOCK_PREFIX "add %1, %0\n\t" + : "+m" (*plint) + : "r" (n)); +#else + __asm__ __volatile__( + "1:\t" + " movl %1, %%ebx\n\t" + " movl %%edx, %%ecx\n\t" + " addl %%eax, %%ebx\n\t" + " adcl $0, %%ecx\n\t" + LOCK_PREFIX "cmpxchg8b %0\n\t" + " jnz 1b\n\t" + : "+m" (*plint) + : "m" (n), "A" (*plint) + : "ebx", "ecx"); +#endif + local_irq_restore(flags); +} + +static void initialize_object(struct dispatcher_header *dh, enum dh_type type, + int state) +{ + memset(dh, 0, sizeof(*dh)); + set_object_type(dh, type); + dh->signal_state = state; + InitializeListHead(&dh->wait_blocks); +} + +static void timer_proc(unsigned long data) +{ + struct wrap_timer *wrap_timer = (struct wrap_timer *)data; + struct nt_timer *nt_timer; + struct kdpc *kdpc; + + nt_timer = wrap_timer->nt_timer; + TIMERENTER("%p(%p), %lu", wrap_timer, nt_timer, jiffies); +#ifdef TIMER_DEBUG + BUG_ON(wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC); + BUG_ON(nt_timer->wrap_timer_magic != WRAP_TIMER_MAGIC); +#endif + KeSetEvent((struct nt_event *)nt_timer, 0, FALSE); + if (wrap_timer->repeat) + mod_timer(&wrap_timer->timer, jiffies + wrap_timer->repeat); + kdpc = nt_timer->kdpc; + if (kdpc) + queue_kdpc(kdpc); + TIMEREXIT(return); +} + +void wrap_init_timer(struct nt_timer *nt_timer, enum timer_type type, + struct ndis_mp_block *nmb) +{ + struct wrap_timer *wrap_timer; + + /* TODO: if a timer is initialized more than once, we allocate + * memory for wrap_timer more than once for the same nt_timer, + * wasting memory. We can check if nt_timer->wrap_timer_magic is + * set and not allocate, but it is not guaranteed always to be + * safe */ + TIMERENTER("%p", nt_timer); + /* we allocate memory for wrap_timer behind driver's back and + * there is no NDIS/DDK function where this memory can be + * freed, so we use slack_kmalloc so it gets freed when driver + * is unloaded */ + if (nmb) + wrap_timer = kmalloc(sizeof(*wrap_timer), irql_gfp()); + else + wrap_timer = slack_kmalloc(sizeof(*wrap_timer)); + if (!wrap_timer) { + ERROR("couldn't allocate memory for timer"); + return; + } + + memset(wrap_timer, 0, sizeof(*wrap_timer)); + init_timer(&wrap_timer->timer); + wrap_timer->timer.data = (unsigned long)wrap_timer; + wrap_timer->timer.function = timer_proc; + wrap_timer->nt_timer = nt_timer; +#ifdef TIMER_DEBUG + wrap_timer->wrap_timer_magic = WRAP_TIMER_MAGIC; +#endif + nt_timer->wrap_timer = wrap_timer; + nt_timer->kdpc = NULL; + initialize_object(&nt_timer->dh, type, 0); + nt_timer->wrap_timer_magic = WRAP_TIMER_MAGIC; + TIMERTRACE("timer %p (%p)", wrap_timer, nt_timer); + spin_lock_bh(&ntoskernel_lock); + if (nmb) { + wrap_timer->slist.next = nmb->wnd->wrap_timer_slist.next; + nmb->wnd->wrap_timer_slist.next = &wrap_timer->slist; + } else { + wrap_timer->slist.next = wrap_timer_slist.next; + wrap_timer_slist.next = &wrap_timer->slist; + } + spin_unlock_bh(&ntoskernel_lock); + TIMEREXIT(return); +} + +wstdcall void WIN_FUNC(KeInitializeTimerEx,2) + (struct nt_timer *nt_timer, enum timer_type type) +{ + TIMERENTER("%p", nt_timer); + wrap_init_timer(nt_timer, type, NULL); +} + +wstdcall void WIN_FUNC(KeInitializeTimer,1) + (struct nt_timer *nt_timer) +{ + TIMERENTER("%p", nt_timer); + wrap_init_timer(nt_timer, NotificationTimer, NULL); +} + +/* expires and repeat are in HZ */ +BOOLEAN wrap_set_timer(struct nt_timer *nt_timer, unsigned long expires_hz, + unsigned long repeat_hz, struct kdpc *kdpc) +{ + struct wrap_timer *wrap_timer; + + TIMERENTER("%p, %lu, %lu, %p, %lu", + nt_timer, expires_hz, repeat_hz, kdpc, jiffies); + + wrap_timer = nt_timer->wrap_timer; + TIMERTRACE("%p", wrap_timer); +#ifdef TIMER_DEBUG + if (wrap_timer->nt_timer != nt_timer) + WARNING("bad timers: %p, %p, %p", wrap_timer, nt_timer, + wrap_timer->nt_timer); + if (nt_timer->wrap_timer_magic != WRAP_TIMER_MAGIC) { + WARNING("buggy Windows timer didn't initialize timer %p", + nt_timer); + return FALSE; + } + if (wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC) { + WARNING("timer %p is not initialized (%lx)?", + wrap_timer, wrap_timer->wrap_timer_magic); + wrap_timer->wrap_timer_magic = WRAP_TIMER_MAGIC; + } +#endif + KeClearEvent((struct nt_event *)nt_timer); + nt_timer->kdpc = kdpc; + wrap_timer->repeat = repeat_hz; + if (mod_timer(&wrap_timer->timer, jiffies + expires_hz)) + TIMEREXIT(return TRUE); + else + TIMEREXIT(return FALSE); +} + +wstdcall BOOLEAN WIN_FUNC(KeSetTimerEx,4) + (struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks, + LONG period_ms, struct kdpc *kdpc) +{ + unsigned long expires_hz, repeat_hz; + + TIMERENTER("%p, %Ld, %d", nt_timer, duetime_ticks, period_ms); + expires_hz = SYSTEM_TIME_TO_HZ(duetime_ticks); + repeat_hz = MSEC_TO_HZ(period_ms); + return wrap_set_timer(nt_timer, expires_hz, repeat_hz, kdpc); +} + +wstdcall BOOLEAN WIN_FUNC(KeSetTimer,3) + (struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks, + struct kdpc *kdpc) +{ + TIMERENTER("%p, %Ld, %p", nt_timer, duetime_ticks, kdpc); + return KeSetTimerEx(nt_timer, duetime_ticks, 0, kdpc); +} + +wstdcall BOOLEAN WIN_FUNC(KeCancelTimer,1) + (struct nt_timer *nt_timer) +{ + struct wrap_timer *wrap_timer; + int ret; + + TIMERENTER("%p", nt_timer); + wrap_timer = nt_timer->wrap_timer; + if (!wrap_timer) { + ERROR("invalid wrap_timer"); + return TRUE; + } +#ifdef TIMER_DEBUG + BUG_ON(wrap_timer->wrap_timer_magic != WRAP_TIMER_MAGIC); +#endif + /* disable timer before deleting so if it is periodic timer, it + * won't be re-armed after deleting */ + wrap_timer->repeat = 0; + ret = del_timer_sync(&wrap_timer->timer); + /* the documentation for KeCancelTimer suggests the DPC is + * deqeued, but actually DPC is left to run */ + if (ret) + TIMEREXIT(return TRUE); + else + TIMEREXIT(return FALSE); +} + +wstdcall BOOLEAN WIN_FUNC(KeReadStateTimer,1) + (struct nt_timer *nt_timer) +{ + if (nt_timer->dh.signal_state) + return TRUE; + else + return FALSE; +} + +wstdcall void WIN_FUNC(KeInitializeDpc,3) + (struct kdpc *kdpc, void *func, void *ctx) +{ + ENTER3("%p, %p, %p", kdpc, func, ctx); + memset(kdpc, 0, sizeof(*kdpc)); + kdpc->func = func; + kdpc->ctx = ctx; + InitializeListHead(&kdpc->list); +} + +static void kdpc_worker(worker_param_t dummy) +{ + struct nt_list *entry; + struct kdpc *kdpc; + unsigned long flags; + KIRQL irql; + + WORKENTER(""); + irql = raise_irql(DISPATCH_LEVEL); + while (1) { + spin_lock_irqsave(&kdpc_list_lock, flags); + entry = RemoveHeadList(&kdpc_list); + if (entry) { + kdpc = container_of(entry, struct kdpc, list); + assert(kdpc->queued); + kdpc->queued = 0; + } else + kdpc = NULL; + spin_unlock_irqrestore(&kdpc_list_lock, flags); + if (!kdpc) + break; + WORKTRACE("%p, %p, %p, %p, %p", kdpc, kdpc->func, kdpc->ctx, + kdpc->arg1, kdpc->arg2); + assert_irql(_irql_ == DISPATCH_LEVEL); + LIN2WIN4(kdpc->func, kdpc, kdpc->ctx, kdpc->arg1, kdpc->arg2); + assert_irql(_irql_ == DISPATCH_LEVEL); + } + lower_irql(irql); + WORKEXIT(return); +} + +wstdcall void WIN_FUNC(KeFlushQueuedDpcs,0) + (void) +{ + kdpc_worker(NULL); +} + +BOOLEAN queue_kdpc(struct kdpc *kdpc) +{ + BOOLEAN ret; + unsigned long flags; + + WORKENTER("%p", kdpc); + spin_lock_irqsave(&kdpc_list_lock, flags); + if (kdpc->queued) + ret = FALSE; + else { + if (unlikely(kdpc->importance == HighImportance)) + InsertHeadList(&kdpc_list, &kdpc->list); + else + InsertTailList(&kdpc_list, &kdpc->list); + kdpc->queued = 1; + ret = TRUE; + } + spin_unlock_irqrestore(&kdpc_list_lock, flags); + if (ret == TRUE) + schedule_ntos_work(&kdpc_work); + WORKTRACE("%d", ret); + return ret; +} + +BOOLEAN dequeue_kdpc(struct kdpc *kdpc) +{ + BOOLEAN ret; + unsigned long flags; + + WORKENTER("%p", kdpc); + spin_lock_irqsave(&kdpc_list_lock, flags); + if (kdpc->queued) { + RemoveEntryList(&kdpc->list); + kdpc->queued = 0; + ret = TRUE; + } else + ret = FALSE; + spin_unlock_irqrestore(&kdpc_list_lock, flags); + WORKTRACE("%d", ret); + return ret; +} + +wstdcall BOOLEAN WIN_FUNC(KeInsertQueueDpc,3) + (struct kdpc *kdpc, void *arg1, void *arg2) +{ + WORKENTER("%p, %p, %p", kdpc, arg1, arg2); + kdpc->arg1 = arg1; + kdpc->arg2 = arg2; + return queue_kdpc(kdpc); +} + +wstdcall BOOLEAN WIN_FUNC(KeRemoveQueueDpc,1) + (struct kdpc *kdpc) +{ + return dequeue_kdpc(kdpc); +} + +wstdcall void WIN_FUNC(KeSetImportanceDpc,2) + (struct kdpc *kdpc, enum kdpc_importance importance) +{ + kdpc->importance = importance; +} + +static void ntos_work_worker(worker_param_t dummy) +{ + struct ntos_work_item *ntos_work_item; + struct nt_list *cur; + + while (1) { + spin_lock_bh(&ntos_work_lock); + cur = RemoveHeadList(&ntos_work_list); + spin_unlock_bh(&ntos_work_lock); + if (!cur) + break; + ntos_work_item = container_of(cur, struct ntos_work_item, list); + WORKTRACE("%p: executing %p, %p, %p", current, + ntos_work_item->func, ntos_work_item->arg1, + ntos_work_item->arg2); + LIN2WIN2(ntos_work_item->func, ntos_work_item->arg1, + ntos_work_item->arg2); + kfree(ntos_work_item); + } + WORKEXIT(return); +} + +int schedule_ntos_work_item(NTOS_WORK_FUNC func, void *arg1, void *arg2) +{ + struct ntos_work_item *ntos_work_item; + + WORKENTER("adding work: %p, %p, %p", func, arg1, arg2); + ntos_work_item = kmalloc(sizeof(*ntos_work_item), irql_gfp()); + if (!ntos_work_item) { + ERROR("couldn't allocate memory"); + return -ENOMEM; + } + ntos_work_item->func = func; + ntos_work_item->arg1 = arg1; + ntos_work_item->arg2 = arg2; + spin_lock_bh(&ntos_work_lock); + InsertTailList(&ntos_work_list, &ntos_work_item->list); + spin_unlock_bh(&ntos_work_lock); + schedule_ntos_work(&ntos_work); + WORKEXIT(return 0); +} + +wstdcall void WIN_FUNC(KeInitializeSpinLock,1) + (NT_SPIN_LOCK *lock) +{ + ENTER6("%p", lock); + nt_spin_lock_init(lock); +} + +wstdcall void WIN_FUNC(KeAcquireSpinLock,2) + (NT_SPIN_LOCK *lock, KIRQL *irql) +{ + ENTER6("%p", lock); + *irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL); +} + +wstdcall void WIN_FUNC(KeReleaseSpinLock,2) + (NT_SPIN_LOCK *lock, KIRQL oldirql) +{ + ENTER6("%p", lock); + nt_spin_unlock_irql(lock, oldirql); +} + +wstdcall void WIN_FUNC(KeAcquireSpinLockAtDpcLevel,1) + (NT_SPIN_LOCK *lock) +{ + ENTER6("%p", lock); + nt_spin_lock(lock); +} + +wstdcall void WIN_FUNC(KeReleaseSpinLockFromDpcLevel,1) + (NT_SPIN_LOCK *lock) +{ + ENTER6("%p", lock); + nt_spin_unlock(lock); +} + +wstdcall void WIN_FUNC(KeRaiseIrql,2) + (KIRQL newirql, KIRQL *oldirql) +{ + ENTER6("%d", newirql); + *oldirql = raise_irql(newirql); +} + +wstdcall KIRQL WIN_FUNC(KeRaiseIrqlToDpcLevel,0) + (void) +{ + return raise_irql(DISPATCH_LEVEL); +} + +wstdcall void WIN_FUNC(KeLowerIrql,1) + (KIRQL irql) +{ + ENTER6("%d", irql); + lower_irql(irql); +} + +wstdcall KIRQL WIN_FUNC(KeAcquireSpinLockRaiseToDpc,1) + (NT_SPIN_LOCK *lock) +{ + ENTER6("%p", lock); + return nt_spin_lock_irql(lock, DISPATCH_LEVEL); +} + +#undef ExAllocatePoolWithTag + +wstdcall void *WIN_FUNC(ExAllocatePoolWithTag,3) + (enum pool_type pool_type, SIZE_T size, ULONG tag) +{ + void *addr; + + ENTER4("pool_type: %d, size: %lu, tag: 0x%x", pool_type, size, tag); + assert_irql(_irql_ <= DISPATCH_LEVEL); + if (size < PAGE_SIZE) + addr = kmalloc(size, irql_gfp()); + else { + if (irql_gfp() & GFP_ATOMIC) { + addr = __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, + PAGE_KERNEL); + TRACE1("%p, %lu", addr, size); + } else { + addr = vmalloc(size); + TRACE1("%p, %lu", addr, size); + } + } + DBG_BLOCK(1) { + if (addr) + TRACE4("addr: %p, %lu", addr, size); + else + TRACE1("failed: %lu", size); + } + return addr; +} +WIN_FUNC_DECL(ExAllocatePoolWithTag,3) + +wstdcall void WIN_FUNC(ExFreePoolWithTag,2) + (void *addr, ULONG tag) +{ + TRACE4("%p", addr); + if ((unsigned long)addr < VMALLOC_START || + (unsigned long)addr >= VMALLOC_END) + kfree(addr); + else + vfree(addr); + + EXIT4(return); +} + +wstdcall void WIN_FUNC(ExFreePool,1) + (void *addr) +{ + ExFreePoolWithTag(addr, 0); +} +WIN_FUNC_DECL(ExFreePool,1) + +wstdcall void WIN_FUNC(ExInitializeNPagedLookasideList,7) + (struct npaged_lookaside_list *lookaside, + LOOKASIDE_ALLOC_FUNC *alloc_func, LOOKASIDE_FREE_FUNC *free_func, + ULONG flags, SIZE_T size, ULONG tag, USHORT depth) +{ + ENTER3("lookaside: %p, size: %lu, flags: %u, head: %p, " + "alloc: %p, free: %p", lookaside, size, flags, + lookaside, alloc_func, free_func); + + memset(lookaside, 0, sizeof(*lookaside)); + + lookaside->size = size; + lookaside->tag = tag; + lookaside->depth = 4; + lookaside->maxdepth = 256; + lookaside->pool_type = NonPagedPool; + + if (alloc_func) + lookaside->alloc_func = alloc_func; + else + lookaside->alloc_func = WIN_FUNC_PTR(ExAllocatePoolWithTag,3); + if (free_func) + lookaside->free_func = free_func; + else + lookaside->free_func = WIN_FUNC_PTR(ExFreePool,1); + +#ifndef CONFIG_X86_64 + nt_spin_lock_init(&lookaside->obsolete); +#endif + EXIT3(return); +} + +wstdcall void WIN_FUNC(ExDeleteNPagedLookasideList,1) + (struct npaged_lookaside_list *lookaside) +{ + struct nt_slist *entry; + + ENTER3("lookaside = %p", lookaside); + while ((entry = ExpInterlockedPopEntrySList(&lookaside->head))) + LIN2WIN1(lookaside->free_func, entry); + EXIT3(return); +} + +#if defined(ALLOC_DEBUG) && ALLOC_DEBUG > 1 +#define ExAllocatePoolWithTag(pool_type, size, tag) \ + wrap_ExAllocatePoolWithTag(pool_type, size, tag, __FILE__, __LINE__) +#endif + +wstdcall NTSTATUS WIN_FUNC(ExCreateCallback,4) + (struct callback_object **object, struct object_attributes *attributes, + BOOLEAN create, BOOLEAN allow_multiple_callbacks) +{ + struct callback_object *obj; + + ENTER2(""); + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(obj, &callback_objects, callback_funcs) { + if (obj->attributes == attributes) { + spin_unlock_bh(&ntoskernel_lock); + *object = obj; + return STATUS_SUCCESS; + } + } + spin_unlock_bh(&ntoskernel_lock); + obj = allocate_object(sizeof(struct callback_object), + OBJECT_TYPE_CALLBACK, NULL); + if (!obj) + EXIT2(return STATUS_INSUFFICIENT_RESOURCES); + InitializeListHead(&obj->callback_funcs); + nt_spin_lock_init(&obj->lock); + obj->allow_multiple_callbacks = allow_multiple_callbacks; + obj->attributes = attributes; + *object = obj; + EXIT2(return STATUS_SUCCESS); +} + +wstdcall void *WIN_FUNC(ExRegisterCallback,3) + (struct callback_object *object, PCALLBACK_FUNCTION func, void *context) +{ + struct callback_func *callback; + KIRQL irql; + + ENTER2(""); + irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL); + if (object->allow_multiple_callbacks == FALSE && + !IsListEmpty(&object->callback_funcs)) { + nt_spin_unlock_irql(&object->lock, irql); + EXIT2(return NULL); + } + nt_spin_unlock_irql(&object->lock, irql); + callback = kmalloc(sizeof(*callback), GFP_KERNEL); + if (!callback) { + ERROR("couldn't allocate memory"); + return NULL; + } + callback->func = func; + callback->context = context; + callback->object = object; + irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL); + InsertTailList(&object->callback_funcs, &callback->list); + nt_spin_unlock_irql(&object->lock, irql); + EXIT2(return callback); +} + +wstdcall void WIN_FUNC(ExUnregisterCallback,1) + (struct callback_func *callback) +{ + struct callback_object *object; + KIRQL irql; + + ENTER3("%p", callback); + if (!callback) + return; + object = callback->object; + irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL); + RemoveEntryList(&callback->list); + nt_spin_unlock_irql(&object->lock, irql); + kfree(callback); + return; +} + +wstdcall void WIN_FUNC(ExNotifyCallback,3) + (struct callback_object *object, void *arg1, void *arg2) +{ + struct callback_func *callback; + KIRQL irql; + + ENTER3("%p", object); + irql = nt_spin_lock_irql(&object->lock, DISPATCH_LEVEL); + nt_list_for_each_entry(callback, &object->callback_funcs, list) { + LIN2WIN3(callback->func, callback->context, arg1, arg2); + } + nt_spin_unlock_irql(&object->lock, irql); + return; +} + +/* check and set signaled state; should be called with dispatcher_lock held */ +/* @grab indicates if the event should be grabbed or checked + * - note that a semaphore may stay in signaled state for multiple + * 'grabs' if the count is > 1 */ +static int grab_object(struct dispatcher_header *dh, + struct task_struct *thread, int grab) +{ + EVENTTRACE("%p, %p, %d, %d", dh, thread, grab, dh->signal_state); + if (unlikely(is_mutex_object(dh))) { + struct nt_mutex *nt_mutex; + nt_mutex = container_of(dh, struct nt_mutex, dh); + EVENTTRACE("%p, %p, %d, %p, %d", nt_mutex, + nt_mutex->owner_thread, dh->signal_state, + thread, grab); + /* either no thread owns the mutex or this thread owns + * it */ + assert(dh->signal_state == 1 && nt_mutex->owner_thread == NULL); + assert(dh->signal_state < 1 && nt_mutex->owner_thread != NULL); + if ((dh->signal_state == 1 && nt_mutex->owner_thread == NULL) || + nt_mutex->owner_thread == thread) { + if (grab) { + dh->signal_state--; + nt_mutex->owner_thread = thread; + } + EVENTEXIT(return 1); + } + } else if (dh->signal_state > 0) { + /* to grab, decrement signal_state for synchronization + * or semaphore objects */ + if (grab && (is_synch_object(dh) || is_semaphore_object(dh))) + dh->signal_state--; + EVENTEXIT(return 1); + } + EVENTEXIT(return 0); +} + +/* this function should be called holding dispatcher_lock */ +static void object_signalled(struct dispatcher_header *dh) +{ + struct nt_list *cur, *next; + struct wait_block *wb; + + EVENTENTER("%p", dh); + nt_list_for_each_safe(cur, next, &dh->wait_blocks) { + wb = container_of(cur, struct wait_block, list); + assert(wb->thread != NULL); + assert(wb->object == NULL); + if (!grab_object(dh, wb->thread, 1)) + continue; + EVENTTRACE("%p (%p): waking %p", dh, wb, wb->thread); + RemoveEntryList(cur); + wb->object = dh; + *(wb->wait_done) = 1; + wake_up_process(wb->thread); + } + EVENTEXIT(return); +} + +wstdcall NTSTATUS WIN_FUNC(KeWaitForMultipleObjects,8) + (ULONG count, void *object[], enum wait_type wait_type, + KWAIT_REASON wait_reason, KPROCESSOR_MODE wait_mode, + BOOLEAN alertable, LARGE_INTEGER *timeout, + struct wait_block *wait_block_array) +{ + int i, res = 0, wait_count, wait_done; + typeof(jiffies) wait_hz = 0; + struct wait_block *wb, wb_array[THREAD_WAIT_OBJECTS]; + struct dispatcher_header *dh; + + EVENTENTER("%p, %d, %u, %p", current, count, wait_type, timeout); + + if (count > MAX_WAIT_OBJECTS || + (count > THREAD_WAIT_OBJECTS && wait_block_array == NULL)) + EVENTEXIT(return STATUS_INVALID_PARAMETER); + + if (wait_block_array == NULL) + wb = wb_array; + else + wb = wait_block_array; + + /* If *timeout == 0: In the case of WaitAny, if an object can + * be grabbed (object is in signaled state), grab and + * return. In the case of WaitAll, we have to first make sure + * all objects can be grabbed. If any/some of them can't be + * grabbed, either we return STATUS_TIMEOUT or wait for them, + * depending on how to satisfy wait. If all of them can be + * grabbed, we will grab them in the next loop below */ + + spin_lock_bh(&dispatcher_lock); + for (i = wait_count = 0; i < count; i++) { + dh = object[i]; + EVENTTRACE("%p: event %p (%d)", current, dh, dh->signal_state); + /* wait_type == 1 for WaitAny, 0 for WaitAll */ + if (grab_object(dh, current, wait_type)) { + if (wait_type == WaitAny) { + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return STATUS_WAIT_0 + i); + } + } else { + EVENTTRACE("%p: wait for %p", current, dh); + wait_count++; + } + } + + if (timeout && *timeout == 0 && wait_count) { + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return STATUS_TIMEOUT); + } + + /* get the list of objects the thread needs to wait on and add + * the thread on the wait list for each such object */ + /* if *timeout == 0, this step will grab all the objects */ + wait_done = 0; + for (i = 0; i < count; i++) { + dh = object[i]; + EVENTTRACE("%p: event %p (%d)", current, dh, dh->signal_state); + wb[i].object = NULL; + if (grab_object(dh, current, 1)) { + EVENTTRACE("%p: no wait for %p (%d)", + current, dh, dh->signal_state); + /* mark that we are not waiting on this object */ + wb[i].thread = NULL; + } else { + wb[i].wait_done = &wait_done; + wb[i].thread = current; + EVENTTRACE("%p: wait for %p", current, dh); + InsertTailList(&dh->wait_blocks, &wb[i].list); + } + } + spin_unlock_bh(&dispatcher_lock); + if (wait_count == 0) + EVENTEXIT(return STATUS_SUCCESS); + + assert(timeout == NULL || *timeout != 0); + if (timeout == NULL) + wait_hz = 0; + else + wait_hz = SYSTEM_TIME_TO_HZ(*timeout); + + DBG_BLOCK(2) { + KIRQL irql = current_irql(); + if (irql >= DISPATCH_LEVEL) { + TRACE2("wait in atomic context: %lu, %d, %ld", + wait_hz, in_atomic(), in_interrupt()); + } + } + assert_irql(_irql_ < DISPATCH_LEVEL); + EVENTTRACE("%p: sleep for %ld on %p", current, wait_hz, &wait_done); + /* we don't honor 'alertable' - according to decription for + * this, even if waiting in non-alertable state, thread may be + * alerted in some circumstances */ + while (wait_count) { + res = wait_condition(wait_done, wait_hz, TASK_INTERRUPTIBLE); + spin_lock_bh(&dispatcher_lock); + EVENTTRACE("%p woke up: %d, %d", current, res, wait_done); + /* the event may have been set by the time + * wrap_wait_event returned and spinlock obtained, so + * don't rely on value of 'res' - check event status */ + if (!wait_done) { + assert(res <= 0); + /* timed out or interrupted; remove from wait list */ + for (i = 0; i < count; i++) { + if (!wb[i].thread) + continue; + EVENTTRACE("%p: timedout, dequeue %p (%p)", + current, object[i], wb[i].object); + assert(wb[i].object == NULL); + RemoveEntryList(&wb[i].list); + } + spin_unlock_bh(&dispatcher_lock); + if (res < 0) + EVENTEXIT(return STATUS_ALERTED); + else + EVENTEXIT(return STATUS_TIMEOUT); + } + assert(res > 0); + /* woken because object(s) signalled */ + for (i = 0; wait_count && i < count; i++) { + if (!wb[i].thread || !wb[i].object) + continue; + DBG_BLOCK(1) { + if (wb[i].object != object[i]) { + EVENTTRACE("oops %p != %p", + wb[i].object, object[i]); + continue; + } + } + wait_count--; + if (wait_type == WaitAny) { + int j; + /* done; remove from rest of wait list */ + for (j = i + 1; j < count; j++) { + if (wb[j].thread && !wb[j].object) + RemoveEntryList(&wb[j].list); + } + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return STATUS_WAIT_0 + i); + } + } + wait_done = 0; + spin_unlock_bh(&dispatcher_lock); + if (wait_count == 0) + EVENTEXIT(return STATUS_SUCCESS); + + /* this thread is still waiting for more objects, so + * let it wait for remaining time and those objects */ + if (timeout) + wait_hz = res; + else + wait_hz = 0; + } + /* should never reach here, but compiler wants return value */ + ERROR("%p: wait_hz: %ld", current, wait_hz); + EVENTEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(KeWaitForSingleObject,5) + (void *object, KWAIT_REASON wait_reason, KPROCESSOR_MODE wait_mode, + BOOLEAN alertable, LARGE_INTEGER *timeout) +{ + return KeWaitForMultipleObjects(1, &object, WaitAny, wait_reason, + wait_mode, alertable, timeout, NULL); +} + +wstdcall void WIN_FUNC(KeInitializeEvent,3) + (struct nt_event *nt_event, enum event_type type, BOOLEAN state) +{ + EVENTENTER("event = %p, type = %d, state = %d", nt_event, type, state); + initialize_object(&nt_event->dh, type, state); + EVENTEXIT(return); +} + +wstdcall LONG WIN_FUNC(KeSetEvent,3) + (struct nt_event *nt_event, KPRIORITY incr, BOOLEAN wait) +{ + LONG old_state; + + EVENTENTER("%p, %d", nt_event, nt_event->dh.type); + if (wait == TRUE) + WARNING("wait = %d, not yet implemented", wait); + spin_lock_bh(&dispatcher_lock); + old_state = nt_event->dh.signal_state; + nt_event->dh.signal_state = 1; + if (old_state == 0) + object_signalled(&nt_event->dh); + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return old_state); +} + +wstdcall void WIN_FUNC(KeClearEvent,1) + (struct nt_event *nt_event) +{ + EVENTENTER("%p", nt_event); + nt_event->dh.signal_state = 0; + EVENTEXIT(return); +} + +wstdcall LONG WIN_FUNC(KeResetEvent,1) + (struct nt_event *nt_event) +{ + LONG old_state; + + EVENTENTER("%p", nt_event); + old_state = xchg(&nt_event->dh.signal_state, 0); + EVENTEXIT(return old_state); +} + +wstdcall LONG WIN_FUNC(KeReadStateEvent,1) + (struct nt_event *nt_event) +{ + LONG state; + + state = nt_event->dh.signal_state; + EVENTTRACE("%d", state); + return state; +} + +wstdcall void WIN_FUNC(KeInitializeMutex,2) + (struct nt_mutex *mutex, ULONG level) +{ + EVENTENTER("%p", mutex); + initialize_object(&mutex->dh, MutexObject, 1); + mutex->dh.size = sizeof(*mutex); + InitializeListHead(&mutex->list); + mutex->abandoned = FALSE; + mutex->apc_disable = 1; + mutex->owner_thread = NULL; + EVENTEXIT(return); +} + +wstdcall LONG WIN_FUNC(KeReleaseMutex,2) + (struct nt_mutex *mutex, BOOLEAN wait) +{ + LONG ret; + struct task_struct *thread; + + EVENTENTER("%p, %d, %p", mutex, wait, current); + if (wait == TRUE) + WARNING("wait: %d", wait); + thread = current; + spin_lock_bh(&dispatcher_lock); + EVENTTRACE("%p, %p, %p, %d", mutex, thread, mutex->owner_thread, + mutex->dh.signal_state); + if ((mutex->owner_thread == thread) && (mutex->dh.signal_state <= 0)) { + ret = mutex->dh.signal_state++; + if (ret == 0) { + mutex->owner_thread = NULL; + object_signalled(&mutex->dh); + } + } else { + ret = STATUS_MUTANT_NOT_OWNED; + WARNING("invalid mutex: %p, %p, %p", mutex, mutex->owner_thread, + thread); + } + EVENTTRACE("%p, %p, %p, %d", mutex, thread, mutex->owner_thread, + mutex->dh.signal_state); + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return ret); +} + +wstdcall void WIN_FUNC(KeInitializeSemaphore,3) + (struct nt_semaphore *semaphore, LONG count, LONG limit) +{ + EVENTENTER("%p: %d", semaphore, count); + /* if limit > 1, we need to satisfy as many waits (until count + * becomes 0); so we keep decrementing count everytime a wait + * is satisified */ + initialize_object(&semaphore->dh, SemaphoreObject, count); + semaphore->dh.size = sizeof(*semaphore); + semaphore->limit = limit; + EVENTEXIT(return); +} + +wstdcall LONG WIN_FUNC(KeReleaseSemaphore,4) + (struct nt_semaphore *semaphore, KPRIORITY incr, LONG adjustment, + BOOLEAN wait) +{ + LONG ret; + + EVENTENTER("%p", semaphore); + spin_lock_bh(&dispatcher_lock); + ret = semaphore->dh.signal_state; + assert(ret >= 0); + if (semaphore->dh.signal_state + adjustment <= semaphore->limit) + semaphore->dh.signal_state += adjustment; + else { + WARNING("releasing %d over limit %d", adjustment, + semaphore->limit); + semaphore->dh.signal_state = semaphore->limit; + } + if (semaphore->dh.signal_state > 0) + object_signalled(&semaphore->dh); + spin_unlock_bh(&dispatcher_lock); + EVENTEXIT(return ret); +} + +wstdcall NTSTATUS WIN_FUNC(KeDelayExecutionThread,3) + (KPROCESSOR_MODE wait_mode, BOOLEAN alertable, LARGE_INTEGER *interval) +{ + int res; + long timeout; + + if (wait_mode != 0) + ERROR("invalid wait_mode %d", wait_mode); + + timeout = SYSTEM_TIME_TO_HZ(*interval); + EVENTTRACE("%p, %Ld, %ld", current, *interval, timeout); + if (timeout <= 0) + EVENTEXIT(return STATUS_SUCCESS); + + if (alertable) + set_current_state(TASK_INTERRUPTIBLE); + else + set_current_state(TASK_UNINTERRUPTIBLE); + + res = schedule_timeout(timeout); + EVENTTRACE("%p, %d", current, res); + if (res == 0) + EVENTEXIT(return STATUS_SUCCESS); + else + EVENTEXIT(return STATUS_ALERTED); +} + +wstdcall ULONGLONG WIN_FUNC(KeQueryInterruptTime,0) + (void) +{ + EXIT5(return jiffies * TICKSPERJIFFY); +} + +wstdcall ULONG WIN_FUNC(KeQueryTimeIncrement,0) + (void) +{ + EXIT5(return TICKSPERSEC / HZ); +} + +wstdcall void WIN_FUNC(KeQuerySystemTime,1) + (LARGE_INTEGER *time) +{ + *time = ticks_1601(); + TRACE5("%Lu, %lu", *time, jiffies); +} + +wstdcall void WIN_FUNC(KeQueryTickCount,1) + (LARGE_INTEGER *count) +{ + *count = jiffies; +} + +wstdcall LARGE_INTEGER WIN_FUNC(KeQueryPerformanceCounter,1) + (LARGE_INTEGER *counter) +{ + if (counter) + *counter = HZ; + return jiffies; +} + +wstdcall KAFFINITY WIN_FUNC(KeQueryActiveProcessors,0) + (void) +{ + int i, n; + KAFFINITY bits = 0; +#ifdef num_online_cpus + n = num_online_cpus(); +#else + n = NR_CPUS; +#endif + for (i = 0; i < n; i++) + bits = (bits << 1) | 1; + return bits; +} + +struct nt_thread *get_current_nt_thread(void) +{ + struct task_struct *task = current; + struct nt_thread *thread; + struct common_object_header *header; + + TRACE6("task: %p", task); + thread = NULL; + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(header, &object_list, list) { + TRACE6("%p, %d", header, header->type); + if (header->type != OBJECT_TYPE_NT_THREAD) + break; + thread = HEADER_TO_OBJECT(header); + TRACE6("%p, %p", thread, thread->task); + if (thread->task == task) + break; + else + thread = NULL; + } + spin_unlock_bh(&ntoskernel_lock); + if (thread == NULL) + TRACE4("couldn't find thread for task %p, %d", task, task->pid); + TRACE6("%p", thread); + return thread; +} + +static struct task_struct *get_nt_thread_task(struct nt_thread *thread) +{ + struct task_struct *task; + struct common_object_header *header; + + TRACE6("%p", thread); + task = NULL; + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(header, &object_list, list) { + TRACE6("%p, %d", header, header->type); + if (header->type != OBJECT_TYPE_NT_THREAD) + break; + if (thread == HEADER_TO_OBJECT(header)) { + task = thread->task; + break; + } + } + spin_unlock_bh(&ntoskernel_lock); + if (task == NULL) + TRACE2("%p: couldn't find task for %p", current, thread); + return task; +} + +static struct nt_thread *create_nt_thread(struct task_struct *task) +{ + struct nt_thread *thread; + thread = allocate_object(sizeof(*thread), OBJECT_TYPE_NT_THREAD, NULL); + if (!thread) { + ERROR("couldn't allocate thread object"); + EXIT2(return NULL); + } + thread->task = task; + if (task) + thread->pid = task->pid; + else + thread->pid = 0; + nt_spin_lock_init(&thread->lock); + InitializeListHead(&thread->irps); + initialize_object(&thread->dh, ThreadObject, 0); + thread->dh.size = sizeof(*thread); + thread->prio = LOW_PRIORITY; + return thread; +} + +wstdcall struct nt_thread *WIN_FUNC(KeGetCurrentThread,0) + (void) +{ + struct nt_thread *thread = get_current_nt_thread(); + TRACE2("%p, %p", thread, current); + return thread; +} + +wstdcall KPRIORITY WIN_FUNC(KeQueryPriorityThread,1) + (struct nt_thread *thread) +{ + KPRIORITY prio; + struct task_struct *task; + + TRACE2("%p", thread); +#ifdef CONFIG_X86_64 + /* sis163u driver for amd64 passes 0x1f from thread created by + * PsCreateSystemThread - no idea what is 0x1f */ + if (thread == (void *)0x1f) + thread = get_current_nt_thread(); +#endif + if (!thread) { + TRACE2("invalid thread"); + EXIT2(return LOW_REALTIME_PRIORITY); + } + task = get_nt_thread_task(thread); + if (!task) { + TRACE2("couldn't find task for thread: %p", thread); + EXIT2(return LOW_REALTIME_PRIORITY); + } + + prio = thread->prio; + + TRACE2("%d", prio); + return prio; +} + +wstdcall KPRIORITY WIN_FUNC(KeSetPriorityThread,2) + (struct nt_thread *thread, KPRIORITY prio) +{ + KPRIORITY old_prio; + struct task_struct *task; + + TRACE2("thread: %p, priority = %u", thread, prio); +#ifdef CONFIG_X86_64 + if (thread == (void *)0x1f) + thread = get_current_nt_thread(); +#endif + if (!thread) { + TRACE2("invalid thread"); + EXIT2(return LOW_REALTIME_PRIORITY); + } + task = get_nt_thread_task(thread); + if (!task) { + TRACE2("couldn't find task for thread: %p", thread); + EXIT2(return LOW_REALTIME_PRIORITY); + } + + old_prio = thread->prio; + thread->prio = prio; + + TRACE2("%d, %d", old_prio, thread->prio); + return old_prio; +} + +struct thread_trampoline { + void (*func)(void *) wstdcall; + void *ctx; + struct nt_thread *thread; + struct completion started; +}; + +static int ntdriver_thread(void *data) +{ + struct thread_trampoline *thread_tramp = data; + /* yes, a tramp! */ + typeof(thread_tramp->func) func = thread_tramp->func; + typeof(thread_tramp->ctx) ctx = thread_tramp->ctx; + + thread_tramp->thread->task = current; + thread_tramp->thread->pid = current->pid; + TRACE2("thread: %p, task: %p (%d)", thread_tramp->thread, + current, current->pid); + complete(&thread_tramp->started); + +#ifdef PF_NOFREEZE + current->flags |= PF_NOFREEZE; +#endif + strncpy(current->comm, "ntdriver", sizeof(current->comm)); + current->comm[sizeof(current->comm)-1] = 0; + LIN2WIN1(func, ctx); + ERROR("task: %p", current); + return 0; +} + +wstdcall NTSTATUS WIN_FUNC(PsCreateSystemThread,7) + (void **handle, ULONG access, void *obj_attr, void *process, + void *client_id, void (*func)(void *) wstdcall, void *ctx) +{ + struct thread_trampoline thread_tramp; + + ENTER2("handle = %p, access = %u, obj_attr = %p, process = %p, " + "client_id = %p, func = %p, context = %p", handle, access, + obj_attr, process, client_id, func, ctx); + + thread_tramp.thread = create_nt_thread(NULL); + if (!thread_tramp.thread) { + ERROR("couldn't allocate thread object"); + EXIT2(return STATUS_RESOURCES); + } + TRACE2("thread: %p", thread_tramp.thread); + thread_tramp.func = func; + thread_tramp.ctx = ctx; + init_completion(&thread_tramp.started); + + thread_tramp.thread->task = kthread_run(ntdriver_thread, + &thread_tramp, "ntdriver"); + if (IS_ERR(thread_tramp.thread->task)) { + free_object(thread_tramp.thread); + EXIT2(return STATUS_FAILURE); + } + TRACE2("created task: %p", thread_tramp.thread->task); + + wait_for_completion(&thread_tramp.started); + *handle = OBJECT_TO_HEADER(thread_tramp.thread); + TRACE2("created thread: %p, %p", thread_tramp.thread, *handle); + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(PsTerminateSystemThread,1) + (NTSTATUS status) +{ + struct nt_thread *thread; + + TRACE2("%p, %08X", current, status); + thread = get_current_nt_thread(); + TRACE2("%p", thread); + if (thread) { + KeSetEvent((struct nt_event *)&thread->dh, 0, FALSE); + while (1) { + struct nt_list *ent; + struct irp *irp; + KIRQL irql; + irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL); + ent = RemoveHeadList(&thread->irps); + nt_spin_unlock_irql(&thread->lock, irql); + if (!ent) + break; + irp = container_of(ent, struct irp, thread_list); + IOTRACE("%p", irp); + IoCancelIrp(irp); + } + /* the driver may later query this status with + * ZwQueryInformationThread */ + thread->status = status; + } else + ERROR("couldn't find thread for task: %p", current); + + complete_and_exit(NULL, status); + ERROR("oops: %p, %d", thread->task, thread->pid); + return STATUS_FAILURE; +} + +wstdcall BOOLEAN WIN_FUNC(KeRemoveEntryDeviceQueue,2) + (struct kdevice_queue *dev_queue, struct kdevice_queue_entry *entry) +{ + struct kdevice_queue_entry *e; + KIRQL irql; + + irql = nt_spin_lock_irql(&dev_queue->lock, DISPATCH_LEVEL); + nt_list_for_each_entry(e, &dev_queue->list, list) { + if (e == entry) { + RemoveEntryList(&e->list); + nt_spin_unlock_irql(&dev_queue->lock, irql); + return TRUE; + } + } + nt_spin_unlock_irql(&dev_queue->lock, irql); + return FALSE; +} + +wstdcall BOOLEAN WIN_FUNC(KeSynchronizeExecution,3) + (struct kinterrupt *interrupt, PKSYNCHRONIZE_ROUTINE synch_routine, + void *ctx) +{ + BOOLEAN ret; + unsigned long flags; + + nt_spin_lock_irqsave(interrupt->actual_lock, flags); + ret = LIN2WIN1(synch_routine, ctx); + nt_spin_unlock_irqrestore(interrupt->actual_lock, flags); + TRACE6("%d", ret); + return ret; +} + +wstdcall void *WIN_FUNC(MmAllocateContiguousMemorySpecifyCache,5) + (SIZE_T size, PHYSICAL_ADDRESS lowest, PHYSICAL_ADDRESS highest, + PHYSICAL_ADDRESS boundary, enum memory_caching_type cache_type) +{ + void *addr; + gfp_t flags; + + ENTER2("%lu, 0x%lx, 0x%lx, 0x%lx, %d", size, (long)lowest, + (long)highest, (long)boundary, cache_type); + flags = irql_gfp(); + addr = wrap_get_free_pages(flags, size); + TRACE2("%p, %lu, 0x%x", addr, size, flags); + if (addr && ((virt_to_phys(addr) + size) <= highest)) + EXIT2(return addr); +#ifdef CONFIG_X86_64 + /* GFP_DMA is really only 16MB even on x86-64, but there is no + * other zone available */ + if (highest <= DMA_BIT_MASK(31)) + flags |= __GFP_DMA; + else if (highest <= DMA_BIT_MASK(32)) + flags |= __GFP_DMA32; +#else + if (highest <= DMA_BIT_MASK(24)) + flags |= __GFP_DMA; + else if (highest > DMA_BIT_MASK(30)) + flags |= __GFP_HIGHMEM; +#endif + addr = wrap_get_free_pages(flags, size); + TRACE2("%p, %lu, 0x%x", addr, size, flags); + return addr; +} + +wstdcall void WIN_FUNC(MmFreeContiguousMemorySpecifyCache,3) + (void *base, SIZE_T size, enum memory_caching_type cache_type) +{ + TRACE2("%p, %lu", base, size); + free_pages((unsigned long)base, get_order(size)); +} + +wstdcall PHYSICAL_ADDRESS WIN_FUNC(MmGetPhysicalAddress,1) + (void *base) +{ + unsigned long phy = virt_to_phys(base); + TRACE2("%p, %p", base, (void *)phy); + return phy; +} + +/* Atheros card with pciid 168C:0014 calls this function with 0xf0000 + * and 0xf6ef0 address, and then check for things that seem to be + * related to ACPI: "_SM_" and "_DMI_". This may be the hack they do + * to check if this card is installed in IBM thinkpads; we can + * probably get this device to work if we create a buffer with the + * strings as required by the driver and return virtual address for + * that address instead */ +wstdcall void __iomem *WIN_FUNC(MmMapIoSpace,3) + (PHYSICAL_ADDRESS phys_addr, SIZE_T size, + enum memory_caching_type cache) +{ + void __iomem *virt; + ENTER1("cache type: %d", cache); + if (cache == MmCached) + virt = ioremap(phys_addr, size); + else + virt = ioremap_nocache(phys_addr, size); + TRACE1("%Lx, %lu, %p", phys_addr, size, virt); + return virt; +} + +wstdcall void WIN_FUNC(MmUnmapIoSpace,2) + (void __iomem *addr, SIZE_T size) +{ + ENTER1("%p, %lu", addr, size); + iounmap(addr); + return; +} + +wstdcall ULONG WIN_FUNC(MmSizeOfMdl,2) + (void *base, ULONG length) +{ + return sizeof(struct mdl) + + (sizeof(PFN_NUMBER) * SPAN_PAGES(base, length)); +} + +struct mdl *allocate_init_mdl(void *virt, ULONG length) +{ + struct wrap_mdl *wrap_mdl; + struct mdl *mdl; + int mdl_size = MmSizeOfMdl(virt, length); + + if (mdl_size <= MDL_CACHE_SIZE) { + wrap_mdl = kmem_cache_alloc(mdl_cache, irql_gfp()); + if (!wrap_mdl) + return NULL; + spin_lock_bh(&dispatcher_lock); + InsertHeadList(&wrap_mdl_list, &wrap_mdl->list); + spin_unlock_bh(&dispatcher_lock); + mdl = wrap_mdl->mdl; + TRACE3("allocated mdl from cache: %p(%p), %p(%d)", + wrap_mdl, mdl, virt, length); + memset(mdl, 0, MDL_CACHE_SIZE); + MmInitializeMdl(mdl, virt, length); + /* mark the MDL as allocated from cache pool so when + * it is freed, we free it back to the pool */ + mdl->flags = MDL_ALLOCATED_FIXED_SIZE | MDL_CACHE_ALLOCATED; + } else { + wrap_mdl = + kmalloc(sizeof(*wrap_mdl) + mdl_size, irql_gfp()); + if (!wrap_mdl) + return NULL; + mdl = wrap_mdl->mdl; + TRACE3("allocated mdl from memory: %p(%p), %p(%d)", + wrap_mdl, mdl, virt, length); + spin_lock_bh(&dispatcher_lock); + InsertHeadList(&wrap_mdl_list, &wrap_mdl->list); + spin_unlock_bh(&dispatcher_lock); + memset(mdl, 0, mdl_size); + MmInitializeMdl(mdl, virt, length); + mdl->flags = MDL_ALLOCATED_FIXED_SIZE; + } + return mdl; +} + +void free_mdl(struct mdl *mdl) +{ + /* A driver may allocate Mdl with NdisAllocateBuffer and free + * with IoFreeMdl (e.g., 64-bit Broadcom). Since we need to + * treat buffers allocated with Ndis calls differently, we + * must call NdisFreeBuffer if it is allocated with Ndis + * function. We set 'pool' field in Ndis functions. */ + if (!mdl) + return; + if (mdl->pool) + NdisFreeBuffer(mdl); + else { + struct wrap_mdl *wrap_mdl = (struct wrap_mdl *) + ((char *)mdl - offsetof(struct wrap_mdl, mdl)); + spin_lock_bh(&dispatcher_lock); + RemoveEntryList(&wrap_mdl->list); + spin_unlock_bh(&dispatcher_lock); + + if (mdl->flags & MDL_CACHE_ALLOCATED) { + TRACE3("freeing mdl cache: %p, %p, %p", + wrap_mdl, mdl, mdl->mappedsystemva); + kmem_cache_free(mdl_cache, wrap_mdl); + } else { + TRACE3("freeing mdl: %p, %p, %p", + wrap_mdl, mdl, mdl->mappedsystemva); + kfree(wrap_mdl); + } + } + return; +} + +wstdcall void WIN_FUNC(IoBuildPartialMdl,4) + (struct mdl *source, struct mdl *target, void *virt, ULONG length) +{ + MmInitializeMdl(target, virt, length); + target->flags |= MDL_PARTIAL; +} + +wstdcall void WIN_FUNC(MmBuildMdlForNonPagedPool,1) + (struct mdl *mdl) +{ + PFN_NUMBER *mdl_pages; + int i, n; + + ENTER4("%p", mdl); + /* already mapped */ +// mdl->mappedsystemva = MmGetMdlVirtualAddress(mdl); + mdl->flags |= MDL_SOURCE_IS_NONPAGED_POOL; + TRACE4("%p, %p, %p, %d, %d", mdl, mdl->mappedsystemva, mdl->startva, + mdl->byteoffset, mdl->bytecount); + n = SPAN_PAGES(MmGetSystemAddressForMdl(mdl), MmGetMdlByteCount(mdl)); + if (n > MDL_CACHE_PAGES) + WARNING("%p, %d, %d", MmGetSystemAddressForMdl(mdl), + MmGetMdlByteCount(mdl), n); + mdl_pages = MmGetMdlPfnArray(mdl); + for (i = 0; i < n; i++) + mdl_pages[i] = (ULONG_PTR)mdl->startva + (i * PAGE_SIZE); + EXIT4(return); +} + +wstdcall void *WIN_FUNC(MmMapLockedPages,2) + (struct mdl *mdl, KPROCESSOR_MODE access_mode) +{ + /* already mapped */ +// mdl->mappedsystemva = MmGetMdlVirtualAddress(mdl); + mdl->flags |= MDL_MAPPED_TO_SYSTEM_VA; + /* what is the need for MDL_PARTIAL_HAS_BEEN_MAPPED? */ + if (mdl->flags & MDL_PARTIAL) + mdl->flags |= MDL_PARTIAL_HAS_BEEN_MAPPED; + return mdl->mappedsystemva; +} + +wstdcall void *WIN_FUNC(MmMapLockedPagesSpecifyCache,6) + (struct mdl *mdl, KPROCESSOR_MODE access_mode, + enum memory_caching_type cache_type, void *base_address, + ULONG bug_check, enum mm_page_priority priority) +{ + return MmMapLockedPages(mdl, access_mode); +} + +wstdcall void WIN_FUNC(MmUnmapLockedPages,2) + (void *base, struct mdl *mdl) +{ + mdl->flags &= ~MDL_MAPPED_TO_SYSTEM_VA; + return; +} + +wstdcall void WIN_FUNC(MmProbeAndLockPages,3) + (struct mdl *mdl, KPROCESSOR_MODE access_mode, + enum lock_operation operation) +{ + /* already locked */ + mdl->flags |= MDL_PAGES_LOCKED; + return; +} + +wstdcall void WIN_FUNC(MmUnlockPages,1) + (struct mdl *mdl) +{ + mdl->flags &= ~MDL_PAGES_LOCKED; + return; +} + +wstdcall BOOLEAN WIN_FUNC(MmIsAddressValid,1) + (void *virt_addr) +{ + if (virt_addr_valid(virt_addr)) + return TRUE; + else + return FALSE; +} + +wstdcall void *WIN_FUNC(MmLockPagableDataSection,1) + (void *address) +{ + return address; +} + +wstdcall void WIN_FUNC(MmUnlockPagableImageSection,1) + (void *handle) +{ + return; +} + +wstdcall NTSTATUS WIN_FUNC(ObReferenceObjectByHandle,6) + (void *handle, ACCESS_MASK desired_access, void *obj_type, + KPROCESSOR_MODE access_mode, void **object, void *handle_info) +{ + struct common_object_header *hdr; + + TRACE2("%p", handle); + hdr = HANDLE_TO_HEADER(handle); + atomic_inc_var(hdr->ref_count); + *object = HEADER_TO_OBJECT(hdr); + TRACE2("%p, %p, %d, %p", hdr, object, hdr->ref_count, *object); + return STATUS_SUCCESS; +} + +/* DDK doesn't say if return value should be before incrementing or + * after incrementing reference count, but according to #reactos + * devels, it should be return value after incrementing */ +wfastcall LONG WIN_FUNC(ObfReferenceObject,1) + (void *object) +{ + struct common_object_header *hdr; + LONG ret; + + hdr = OBJECT_TO_HEADER(object); + ret = post_atomic_add(hdr->ref_count, 1); + TRACE2("%p, %d, %p", hdr, hdr->ref_count, object); + return ret; +} + +static int dereference_object(void *object) +{ + struct common_object_header *hdr; + int ref_count; + + ENTER2("object: %p", object); + hdr = OBJECT_TO_HEADER(object); + TRACE2("hdr: %p", hdr); + ref_count = post_atomic_add(hdr->ref_count, -1); + TRACE2("object: %p, %d", object, ref_count); + if (ref_count < 0) + ERROR("invalid object: %p (%d)", object, ref_count); + if (ref_count <= 0) { + free_object(object); + return 1; + } else + return 0; +} + +wfastcall void WIN_FUNC(ObfDereferenceObject,1) + (void *object) +{ + TRACE2("%p", object); + dereference_object(object); +} + +wstdcall NTSTATUS WIN_FUNC(ZwCreateFile,11) + (void **handle, ACCESS_MASK access_mask, + struct object_attributes *obj_attr, struct io_status_block *iosb, + LARGE_INTEGER *size, ULONG file_attr, ULONG share_access, + ULONG create_disposition, ULONG create_options, void *ea_buffer, + ULONG ea_length) +{ + struct common_object_header *coh; + struct file_object *fo; + struct ansi_string ansi; + struct wrap_bin_file *bin_file; + char *file_basename; + NTSTATUS status; + + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(coh, &object_list, list) { + if (coh->type != OBJECT_TYPE_FILE) + continue; + /* TODO: check if file is opened in shared mode */ + if (!RtlCompareUnicodeString(&coh->name, obj_attr->name, TRUE)) { + fo = HEADER_TO_OBJECT(coh); + bin_file = fo->wrap_bin_file; + *handle = coh; + spin_unlock_bh(&ntoskernel_lock); + ObReferenceObject(fo); + iosb->status = FILE_OPENED; + iosb->info = bin_file->size; + EXIT2(return STATUS_SUCCESS); + } + } + spin_unlock_bh(&ntoskernel_lock); + + if (RtlUnicodeStringToAnsiString(&ansi, obj_attr->name, TRUE) != + STATUS_SUCCESS) + EXIT2(return STATUS_INSUFFICIENT_RESOURCES); + + file_basename = strrchr(ansi.buf, '\\'); + if (file_basename) + file_basename++; + else + file_basename = ansi.buf; + TRACE2("file: '%s', '%s'", ansi.buf, file_basename); + + fo = allocate_object(sizeof(struct file_object), OBJECT_TYPE_FILE, + obj_attr->name); + if (!fo) { + RtlFreeAnsiString(&ansi); + iosb->status = STATUS_INSUFFICIENT_RESOURCES; + iosb->info = 0; + EXIT2(return STATUS_FAILURE); + } + coh = OBJECT_TO_HEADER(fo); + bin_file = get_bin_file(file_basename); + if (bin_file) { + TRACE2("%s, %s", bin_file->name, file_basename); + fo->flags = FILE_OPENED; + } else if (access_mask & FILE_WRITE_DATA) { + bin_file = kzalloc(sizeof(*bin_file), GFP_KERNEL); + if (bin_file) { + strncpy(bin_file->name, file_basename, + sizeof(bin_file->name)); + bin_file->name[sizeof(bin_file->name)-1] = 0; + bin_file->data = vmalloc(*size); + if (bin_file->data) { + memset(bin_file->data, 0, *size); + bin_file->size = *size; + fo->flags = FILE_CREATED; + } else { + kfree(bin_file); + bin_file = NULL; + } + } + } else + bin_file = NULL; + + RtlFreeAnsiString(&ansi); + if (!bin_file) { + iosb->status = FILE_DOES_NOT_EXIST; + iosb->info = 0; + free_object(fo); + EXIT2(return STATUS_FAILURE); + } + + fo->wrap_bin_file = bin_file; + fo->current_byte_offset = 0; + if (access_mask & FILE_READ_DATA) + fo->read_access = TRUE; + if (access_mask & FILE_WRITE_DATA) + fo->write_access = TRUE; + iosb->status = FILE_OPENED; + iosb->info = bin_file->size; + *handle = coh; + TRACE2("handle: %p", *handle); + status = STATUS_SUCCESS; + EXIT2(return status); +} + +wstdcall NTSTATUS WIN_FUNC(ZwOpenFile,6) + (void **handle, ACCESS_MASK access_mask, + struct object_attributes *obj_attr, struct io_status_block *iosb, + ULONG share_access, ULONG open_options) +{ + LARGE_INTEGER size; + return ZwCreateFile(handle, access_mask, obj_attr, iosb, &size, 0, + share_access, 0, open_options, NULL, 0); +} + +wstdcall NTSTATUS WIN_FUNC(ZwReadFile,9) + (void *handle, struct nt_event *event, void *apc_routine, + void *apc_context, struct io_status_block *iosb, void *buffer, + ULONG length, LARGE_INTEGER *byte_offset, ULONG *key) +{ + struct file_object *fo; + struct common_object_header *coh; + ULONG count; + size_t offset; + struct wrap_bin_file *file; + + TRACE2("%p", handle); + coh = handle; + if (coh->type != OBJECT_TYPE_FILE) { + ERROR("handle %p is invalid: %d", handle, coh->type); + EXIT2(return STATUS_FAILURE); + } + fo = HANDLE_TO_OBJECT(coh); + file = fo->wrap_bin_file; + TRACE2("file: %s (%zu)", file->name, file->size); + spin_lock_bh(&ntoskernel_lock); + if (byte_offset) + offset = *byte_offset; + else + offset = fo->current_byte_offset; + count = min((size_t)length, file->size - offset); + TRACE2("count: %u, offset: %zu, length: %u", count, offset, length); + memcpy(buffer, ((void *)file->data) + offset, count); + fo->current_byte_offset = offset + count; + spin_unlock_bh(&ntoskernel_lock); + iosb->status = STATUS_SUCCESS; + iosb->info = count; + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(ZwWriteFile,9) + (void *handle, struct nt_event *event, void *apc_routine, + void *apc_context, struct io_status_block *iosb, void *buffer, + ULONG length, LARGE_INTEGER *byte_offset, ULONG *key) +{ + struct file_object *fo; + struct common_object_header *coh; + struct wrap_bin_file *file; + unsigned long offset; + + TRACE2("%p", handle); + coh = handle; + if (coh->type != OBJECT_TYPE_FILE) { + ERROR("handle %p is invalid: %d", handle, coh->type); + EXIT2(return STATUS_FAILURE); + } + fo = HANDLE_TO_OBJECT(coh); + file = fo->wrap_bin_file; + TRACE2("file: %zu, %u", file->size, length); + spin_lock_bh(&ntoskernel_lock); + if (byte_offset) + offset = *byte_offset; + else + offset = fo->current_byte_offset; + if (length + offset > file->size) { + WARNING("%lu, %u", length + offset, (unsigned int)file->size); + /* TODO: implement writing past end of current size */ + iosb->status = STATUS_FAILURE; + iosb->info = 0; + } else { + memcpy(file->data + offset, buffer, length); + iosb->status = STATUS_SUCCESS; + iosb->info = length; + fo->current_byte_offset = offset + length; + } + spin_unlock_bh(&ntoskernel_lock); + EXIT2(return iosb->status); +} + +wstdcall NTSTATUS WIN_FUNC(ZwClose,1) + (void *handle) +{ + struct common_object_header *coh; + + TRACE2("%p", handle); + if (handle == NULL) { + TRACE1(""); + EXIT2(return STATUS_SUCCESS); + } + coh = handle; + if (coh->type == OBJECT_TYPE_FILE) { + struct file_object *fo; + struct wrap_bin_file *bin_file; + typeof(fo->flags) flags; + + fo = HANDLE_TO_OBJECT(handle); + flags = fo->flags; + bin_file = fo->wrap_bin_file; + if (dereference_object(fo)) { + if (flags == FILE_CREATED) { + vfree(bin_file->data); + kfree(bin_file); + } else + free_bin_file(bin_file); + } + } else if (coh->type == OBJECT_TYPE_NT_THREAD) { + struct nt_thread *thread = HANDLE_TO_OBJECT(handle); + TRACE2("thread: %p (%p)", thread, handle); + ObDereferenceObject(thread); + } else { + /* TODO: can we just dereference object here? */ + WARNING("closing handle 0x%x not implemented", coh->type); + } + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(ZwQueryInformationFile,5) + (void *handle, struct io_status_block *iosb, void *info, + ULONG length, enum file_info_class class) +{ + struct file_object *fo; + struct file_name_info *fni; + struct file_std_info *fsi; + struct wrap_bin_file *file; + struct common_object_header *coh; + + ENTER2("%p", handle); + coh = handle; + if (coh->type != OBJECT_TYPE_FILE) { + ERROR("handle %p is invalid: %d", coh, coh->type); + EXIT2(return STATUS_FAILURE); + } + fo = HANDLE_TO_OBJECT(handle); + TRACE2("fo: %p, %d", fo, class); + switch (class) { + case FileNameInformation: + fni = info; + fni->length = min(length, (typeof(length))coh->name.length); + memcpy(fni->name, coh->name.buf, fni->length); + iosb->status = STATUS_SUCCESS; + iosb->info = fni->length; + break; + case FileStandardInformation: + fsi = info; + file = fo->wrap_bin_file; + fsi->alloc_size = file->size; + fsi->eof = file->size; + fsi->num_links = 1; + fsi->delete_pending = FALSE; + fsi->dir = FALSE; + iosb->status = STATUS_SUCCESS; + iosb->info = 0; + break; + default: + WARNING("type %d not implemented yet", class); + iosb->status = STATUS_FAILURE; + iosb->info = 0; + break; + } + EXIT2(return iosb->status); +} + +wstdcall NTSTATUS WIN_FUNC(ZwOpenSection,3) + (void **handle, ACCESS_MASK access, struct object_attributes *obj_attrs) +{ + INFO("%p, 0x%x, %d", obj_attrs, obj_attrs->attributes, access); + TODO(); + *handle = obj_attrs; + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwMapViewOfSection,10) + (void *secn_handle, void *process_handle, void **base_address, + ULONG zero_bits, LARGE_INTEGER *secn_offset, SIZE_T *view_size, + enum section_inherit inherit, ULONG alloc_type, ULONG protect) +{ + INFO("%p, %p, %p", secn_handle, process_handle, base_address); + TODO(); + *base_address = (void *)0xdeadbeef; + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwUnmapViewOfSection,2) + (void *process_handle, void *base_address) +{ + INFO("%p, %p", process_handle, base_address); + TODO(); + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwCreateKey,7) + (void **handle, ACCESS_MASK desired_access, + struct object_attributes *attr, ULONG title_index, + struct unicode_string *class, ULONG create_options, + ULONG *disposition) +{ + struct ansi_string ansi; + if (RtlUnicodeStringToAnsiString(&ansi, attr->name, TRUE) == + STATUS_SUCCESS) { + TRACE1("key: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + *handle = NULL; + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwOpenKey,3) + (void **handle, ACCESS_MASK desired_access, + struct object_attributes *attr) +{ + struct ansi_string ansi; + if (RtlUnicodeStringToAnsiString(&ansi, attr->name, TRUE) == + STATUS_SUCCESS) { + TRACE1("key: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + *handle = NULL; + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwSetValueKey,6) + (void *handle, struct unicode_string *name, ULONG title_index, + ULONG type, void *data, ULONG data_size) +{ + struct ansi_string ansi; + if (RtlUnicodeStringToAnsiString(&ansi, name, TRUE) == + STATUS_SUCCESS) { + TRACE1("key: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwQueryValueKey,6) + (void *handle, struct unicode_string *name, + enum key_value_information_class class, void *info, + ULONG length, ULONG *res_length) +{ + struct ansi_string ansi; + if (RtlUnicodeStringToAnsiString(&ansi, name, TRUE) == STATUS_SUCCESS) { + TRACE1("key: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + TODO(); + return STATUS_INVALID_PARAMETER; +} + +wstdcall NTSTATUS WIN_FUNC(ZwDeleteKey,1) + (void *handle) +{ + ENTER2("%p", handle); + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(ZwPowerInformation,4) + (INT info_level, void *in_buf, ULONG in_buf_len, void *out_buf, + ULONG out_buf_len) +{ + INFO("%d, %u, %u", info_level, in_buf_len, out_buf_len); + TODO(); + return STATUS_ACCESS_DENIED; +} + +wstdcall NTSTATUS WIN_FUNC(WmiSystemControl,4) + (struct wmilib_context *info, struct device_object *dev_obj, + struct irp *irp, void *irp_disposition) +{ + TODO(); + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(WmiCompleteRequest,5) + (struct device_object *dev_obj, struct irp *irp, NTSTATUS status, + ULONG buffer_used, CCHAR priority_boost) +{ + TODO(); + return STATUS_SUCCESS; +} + +noregparm NTSTATUS WIN_FUNC(WmiTraceMessage,12) + (void *tracehandle, ULONG message_flags, + void *message_guid, USHORT message_no, ...) +{ + TODO(); + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(WmiQueryTraceInformation,4) + (enum trace_information_class trace_info_class, void *trace_info, + ULONG *req_length, void *buf) +{ + TODO(); + EXIT2(return STATUS_SUCCESS); +} + +/* this function can't be wstdcall as it takes variable number of args */ +noregparm ULONG WIN_FUNC(DbgPrint,12) + (char *format, ...) +{ +#ifdef DEBUG + va_list args; + static char buf[100]; + + va_start(args, format); + vsnprintf(buf, sizeof(buf), format, args); + printk(KERN_DEBUG "%s (%s): %s", DRIVER_NAME, __func__, buf); + va_end(args); +#endif + return STATUS_SUCCESS; +} + +wstdcall void WIN_FUNC(KeBugCheck,1) + (ULONG code) +{ + TODO(); + return; +} + +wstdcall void WIN_FUNC(KeBugCheckEx,5) + (ULONG code, ULONG_PTR param1, ULONG_PTR param2, + ULONG_PTR param3, ULONG_PTR param4) +{ + TODO(); + return; +} + +wstdcall void WIN_FUNC(ExSystemTimeToLocalTime,2) + (LARGE_INTEGER *system_time, LARGE_INTEGER *local_time) +{ + *local_time = *system_time; +} + +wstdcall ULONG WIN_FUNC(ExSetTimerResolution,2) + (ULONG time, BOOLEAN set) +{ + /* why a driver should change system wide timer resolution is + * beyond me */ + return time; +} + +wstdcall void WIN_FUNC(DbgBreakPoint,0) + (void) +{ + TODO(); +} + +wstdcall void WIN_FUNC(_except_handler3,0) + (void) +{ + TODO(); +} + +wstdcall void WIN_FUNC(__C_specific_handler,0) + (void) +{ + TODO(); +} + +wstdcall void WIN_FUNC(_purecall,0) + (void) +{ + TODO(); +} + +wstdcall void WIN_FUNC(__chkstk,0) + (void) +{ + TODO(); +} + +struct worker_init_struct { + work_struct_t work; + struct completion completion; + struct nt_thread *nt_thread; +}; + +static void wrap_worker_init_func(worker_param_t param) +{ + struct worker_init_struct *worker_init_struct; + + worker_init_struct = + worker_param_data(param, struct worker_init_struct, work); + TRACE1("%p", worker_init_struct); + worker_init_struct->nt_thread = create_nt_thread(current); + if (!worker_init_struct->nt_thread) + WARNING("couldn't create worker thread"); + complete(&worker_init_struct->completion); +} + +struct nt_thread *wrap_worker_init(workqueue_struct_t *wq) +{ + struct worker_init_struct worker_init_struct; + + TRACE1("%p", &worker_init_struct); + init_completion(&worker_init_struct.completion); + initialize_work(&worker_init_struct.work, wrap_worker_init_func, + &worker_init_struct); + worker_init_struct.nt_thread = NULL; + if (wq) + queue_work(wq, &worker_init_struct.work); + else + schedule_work(&worker_init_struct.work); + wait_for_completion(&worker_init_struct.completion); + TRACE1("%p", worker_init_struct.nt_thread); + return worker_init_struct.nt_thread; +} + +int ntoskernel_init(void) +{ + struct timeval now; + + spin_lock_init(&dispatcher_lock); + spin_lock_init(&ntoskernel_lock); + spin_lock_init(&ntos_work_lock); + spin_lock_init(&kdpc_list_lock); + spin_lock_init(&irp_cancel_lock); + InitializeListHead(&wrap_mdl_list); + InitializeListHead(&kdpc_list); + InitializeListHead(&callback_objects); + InitializeListHead(&bus_driver_list); + InitializeListHead(&object_list); + InitializeListHead(&ntos_work_list); + + nt_spin_lock_init(&nt_list_lock); + + initialize_work(&kdpc_work, kdpc_worker, NULL); + initialize_work(&ntos_work, ntos_work_worker, NULL); + wrap_timer_slist.next = NULL; + + do_gettimeofday(&now); + wrap_ticks_to_boot = TICKS_1601_TO_1970; + wrap_ticks_to_boot += (u64)now.tv_sec * TICKSPERSEC; + wrap_ticks_to_boot += now.tv_usec * 10; + wrap_ticks_to_boot -= jiffies * TICKSPERJIFFY; + TRACE2("%Lu", wrap_ticks_to_boot); + +#ifdef WRAP_PREEMPT + do { + int cpu; + for_each_possible_cpu(cpu) { + irql_info_t *info; + info = &per_cpu(irql_info, cpu); + mutex_init(&(info->lock)); + info->task = NULL; + info->count = 0; + } + } while (0); +#endif + + ntos_wq = create_singlethread_workqueue("ntos_wq"); + if (!ntos_wq) { + WARNING("couldn't create ntos_wq thread"); + return -ENOMEM; + } + ntos_worker_thread = wrap_worker_init(ntos_wq); + TRACE1("%p", ntos_worker_thread); + + if (add_bus_driver("PCI") +#ifdef ENABLE_USB + || add_bus_driver("USB") +#endif + ) { + ntoskernel_exit(); + return -ENOMEM; + } + mdl_cache = + wrap_kmem_cache_create("wrap_mdl", + sizeof(struct wrap_mdl) + MDL_CACHE_SIZE, + 0, 0); + TRACE2("%p", mdl_cache); + if (!mdl_cache) { + ERROR("couldn't allocate MDL cache"); + ntoskernel_exit(); + return -ENOMEM; + } + +#if defined(CONFIG_X86_64) + memset(&kuser_shared_data, 0, sizeof(kuser_shared_data)); + *((ULONG64 *)&kuser_shared_data.system_time) = ticks_1601(); + init_timer(&shared_data_timer); + shared_data_timer.function = update_user_shared_data_proc; + shared_data_timer.data = (unsigned long)0; +#endif + return 0; +} + +int ntoskernel_init_device(struct wrap_device *wd) +{ +#if defined(CONFIG_X86_64) + if (kuser_shared_data.reserved1) + mod_timer(&shared_data_timer, jiffies + MSEC_TO_HZ(30)); +#endif + return 0; +} + +void ntoskernel_exit_device(struct wrap_device *wd) +{ + ENTER2(""); + + KeFlushQueuedDpcs(); + EXIT2(return); +} + +void ntoskernel_exit(void) +{ + struct nt_list *cur; + + ENTER2(""); + + /* free kernel (Ke) timers */ + TRACE2("freeing timers"); + while (1) { + struct wrap_timer *wrap_timer; + struct nt_slist *slist; + + spin_lock_bh(&ntoskernel_lock); + if ((slist = wrap_timer_slist.next)) + wrap_timer_slist.next = slist->next; + spin_unlock_bh(&ntoskernel_lock); + TIMERTRACE("%p", slist); + if (!slist) + break; + wrap_timer = container_of(slist, struct wrap_timer, slist); + if (del_timer_sync(&wrap_timer->timer)) + WARNING("Buggy Windows driver left timer %p running", + wrap_timer->nt_timer); + memset(wrap_timer, 0, sizeof(*wrap_timer)); + slack_kfree(wrap_timer); + } + + TRACE2("freeing MDLs"); + if (mdl_cache) { + spin_lock_bh(&ntoskernel_lock); + if (!IsListEmpty(&wrap_mdl_list)) + ERROR("Windows driver didn't free all MDLs; " + "freeing them now"); + while ((cur = RemoveHeadList(&wrap_mdl_list))) { + struct wrap_mdl *wrap_mdl; + wrap_mdl = container_of(cur, struct wrap_mdl, list); + if (wrap_mdl->mdl->flags & MDL_CACHE_ALLOCATED) + kmem_cache_free(mdl_cache, wrap_mdl); + else + kfree(wrap_mdl); + } + spin_unlock_bh(&ntoskernel_lock); + kmem_cache_destroy(mdl_cache); + mdl_cache = NULL; + } + + TRACE2("freeing callbacks"); + spin_lock_bh(&ntoskernel_lock); + while ((cur = RemoveHeadList(&callback_objects))) { + struct callback_object *object; + struct nt_list *ent; + object = container_of(cur, struct callback_object, list); + while ((ent = RemoveHeadList(&object->callback_funcs))) { + struct callback_func *f; + f = container_of(ent, struct callback_func, list); + kfree(f); + } + kfree(object); + } + spin_unlock_bh(&ntoskernel_lock); + + spin_lock_bh(&ntoskernel_lock); + while ((cur = RemoveHeadList(&bus_driver_list))) { + struct bus_driver *bus_driver; + bus_driver = container_of(cur, struct bus_driver, list); + /* TODO: make sure all all drivers are shutdown/removed */ + kfree(bus_driver); + } + spin_unlock_bh(&ntoskernel_lock); + +#if defined(CONFIG_X86_64) + del_timer_sync(&shared_data_timer); +#endif + if (ntos_wq) + destroy_workqueue(ntos_wq); + TRACE1("%p", ntos_worker_thread); + if (ntos_worker_thread) + ObDereferenceObject(ntos_worker_thread); + ENTER2("freeing objects"); + spin_lock_bh(&ntoskernel_lock); + while ((cur = RemoveHeadList(&object_list))) { + struct common_object_header *hdr; + hdr = container_of(cur, struct common_object_header, list); + if (hdr->type == OBJECT_TYPE_NT_THREAD) + TRACE1("object %p(%d) was not freed, freeing it now", + HEADER_TO_OBJECT(hdr), hdr->type); + else + WARNING("object %p(%d) was not freed, freeing it now", + HEADER_TO_OBJECT(hdr), hdr->type); + ExFreePool(hdr); + } + spin_unlock_bh(&ntoskernel_lock); + + EXIT2(return); +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/ntoskernel.h +++ linux-2.6.37/ubuntu/ndiswrapper/ntoskernel.h @@ -0,0 +1,1157 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _NTOSKERNEL_H_ +#define _NTOSKERNEL_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(CONFIG_X86) && !defined(CONFIG_X86_64) +#error "this module is for x86 or x86_64 architectures only" +#endif + +/* Interrupt backwards compatibility stuff */ +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) +#ifndef IRQ_HANDLED +#define IRQ_HANDLED +#define IRQ_NONE +#define irqreturn_t void +#endif +#endif /* Linux < 2.6.29 */ + +/* pci functions in 2.6 kernels have problems allocating dma buffers, + * but seem to work fine with dma functions + */ +#include + +#define PCI_DMA_ALLOC_COHERENT(pci_dev,size,dma_handle) \ + dma_alloc_coherent(&pci_dev->dev,size,dma_handle, \ + GFP_KERNEL | __GFP_REPEAT) +#define PCI_DMA_FREE_COHERENT(pci_dev,size,cpu_addr,dma_handle) \ + dma_free_coherent(&pci_dev->dev,size,cpu_addr,dma_handle) +#define PCI_DMA_MAP_SINGLE(pci_dev,addr,size,direction) \ + dma_map_single(&pci_dev->dev,addr,size,direction) +#define PCI_DMA_UNMAP_SINGLE(pci_dev,dma_handle,size,direction) \ + dma_unmap_single(&pci_dev->dev,dma_handle,size,direction) +#define MAP_SG(pci_dev, sglist, nents, direction) \ + dma_map_sg(&pci_dev->dev, sglist, nents, direction) +#define UNMAP_SG(pci_dev, sglist, nents, direction) \ + dma_unmap_sg(&pci_dev->dev, sglist, nents, direction) +#define PCI_DMA_MAP_ERROR(dma_addr) dma_mapping_error(dma_addr) + + +#if defined(CONFIG_NET_RADIO) && !defined(CONFIG_WIRELESS_EXT) +#define CONFIG_WIRELESS_EXT +#endif + +#define prepare_wait_condition(task, var, value) \ +do { \ + var = value; \ + task = current; \ + barrier(); \ +} while (0) + +/* Wait in wait_state (e.g., TASK_INTERRUPTIBLE) for condition to + * become true; timeout is either jiffies (> 0) to wait or 0 to wait + * forever. + * When timeout == 0, return value is + * > 0 if condition becomes true, or + * < 0 if signal is pending on the thread. + * When timeout > 0, return value is + * > 0 if condition becomes true before timeout, + * < 0 if signal is pending on the thread before timeout, or + * 0 if timedout (condition may have become true at the same time) + */ + +#define wait_condition(condition, timeout, wait_state) \ +({ \ + long ret = timeout ? timeout : 1; \ + while (1) { \ + if (signal_pending(current)) { \ + ret = -ERESTARTSYS; \ + break; \ + } \ + set_current_state(wait_state); \ + if (condition) { \ + __set_current_state(TASK_RUNNING); \ + break; \ + } \ + if (timeout) { \ + ret = schedule_timeout(ret); \ + if (!ret) \ + break; \ + } else \ + schedule(); \ + } \ + ret; \ +}) + +#ifdef WRAP_WQ + +struct workqueue_struct; + +struct workqueue_thread { + spinlock_t lock; + struct task_struct *task; + struct completion *completion; + char name[16]; + int pid; + /* whether any work_structs pending? <0 implies quit */ + s8 pending; + /* list of work_structs pending */ + struct list_head work_list; +}; + +typedef struct workqueue_struct { + u8 singlethread; + u8 qon; + int num_cpus; + struct workqueue_thread threads[0]; +} workqueue_struct_t; + +typedef struct { + struct list_head list; + void (*func)(void *data); + void *data; + /* whether/on which thread scheduled */ + struct workqueue_thread *thread; +} work_struct_t; + +#define initialize_work(work, pfunc, pdata) \ + do { \ + (work)->func = (pfunc); \ + (work)->data = (pdata); \ + (work)->thread = NULL; \ + } while (0) + +#undef create_singlethread_workqueue +#define create_singlethread_workqueue(name) wrap_create_wq(name, 1, 0) +#undef create_workqueue +#define create_workqueue(name) wrap_create_wq(name, 0, 0) +#undef destroy_workqueue +#define destroy_workqueue wrap_destroy_wq +#undef queue_work +#define queue_work wrap_queue_work +#undef flush_workqueue +#define flush_workqueue wrap_flush_wq + +workqueue_struct_t *wrap_create_wq(const char *name, u8 singlethread, u8 freeze); +void wrap_destroy_wq_on(workqueue_struct_t *workq, int cpu); +void wrap_destroy_wq(workqueue_struct_t *workq); +int wrap_queue_work_on(workqueue_struct_t *workq, work_struct_t *work, + int cpu); +int wrap_queue_work(workqueue_struct_t *workq, work_struct_t *work); +void wrap_cancel_work(work_struct_t *work); +void wrap_flush_wq_on(workqueue_struct_t *workq, int cpu); +void wrap_flush_wq(workqueue_struct_t *workq); +typedef void *worker_param_t; +#define worker_param_data(param, type, member) param + +#else // WRAP_WQ + +typedef struct workqueue_struct workqueue_struct_t; +typedef struct work_struct work_struct_t; + +#if defined(INIT_WORK_NAR) || defined(INIT_DELAYED_WORK_DEFERRABLE) +#define initialize_work(work, func, data) INIT_WORK(work, func) +typedef struct work_struct *worker_param_t; +#define worker_param_data(param, type, member) \ + container_of(param, type, member) +#else +#define initialize_work(work, func, data) INIT_WORK(work, func, data) +typedef void *worker_param_t; +#define worker_param_data(param, type, member) param +#endif // INIT_WORK_NAR + +#endif // WRAP_WQ + +struct nt_thread *wrap_worker_init(workqueue_struct_t *wq); + +#ifdef module_param +#define WRAP_MODULE_PARM_INT(name, perm) module_param(name, int, perm) +#define WRAP_MODULE_PARM_STRING(name, perm) module_param(name, charp, perm) +#else +#define WRAP_MODULE_PARM_INT(name, perm) MODULE_PARM(name, "i") +#define WRAP_MODULE_PARM_STRING(name, perm) MODULE_PARM(name, "s") +#endif + +#ifndef LOCK_PREFIX +#ifdef LOCK +#define LOCK_PREFIX LOCK +#else +#ifdef CONFIG_SMP +#define LOCK_PREFIX "lock ; " +#else +#define LOCK_PREFIX "" +#endif +#endif +#endif + +#ifndef NETDEV_TX_OK +#define NETDEV_TX_OK 0 +#endif + +#ifndef NETDEV_TX_BUSY +#define NETDEV_TX_BUSY 1 +#endif + +#ifndef CHECKSUM_HW +#define CHECKSUM_HW CHECKSUM_PARTIAL +#endif + +#ifndef offset_in_page +#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) +#endif + +#ifndef PMSG_SUSPEND +#ifdef PM_SUSPEND +/* this is not correct - the value of PM_SUSPEND is different from + * PMSG_SUSPEND, but ndiswrapper doesn't care about the value when + * suspending */ +#define PMSG_SUSPEND PM_SUSPEND +#define PSMG_ON PM_ON +#else +typedef u32 pm_message_t; +#define PMSG_SUSPEND 2 +#define PMSG_ON 0 +#endif +#endif + +#ifndef PCI_D0 +#define PCI_D0 0 +#endif + +#ifndef PCI_D3hot +#define PCI_D3hot 3 +#endif + +#ifndef PCI_D3cold +#define PCI_D3cold 3 +#endif + +#ifndef PM_EVENT_SUSPEND +#define PM_EVENT_SUSPEND 2 +#endif + +#if !defined(HAVE_NETDEV_PRIV) +#define netdev_priv(dev) ((dev)->priv) +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18) +#define ISR_PT_REGS_PARAM_DECL +#define ISR_PT_REGS_ARG +#else +#define ISR_PT_REGS_PARAM_DECL , struct pt_regs *regs +#define ISR_PT_REGS_ARG , NULL +#endif + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) +#define for_each_possible_cpu(_cpu) for_each_cpu(_cpu) +#endif + +#ifndef flush_icache_range +#define flush_icache_range(start, end) do { } while (0) +#endif + +#ifndef CHECKSUM_PARTIAL +#define CHECKSUM_PARTIAL CHECKSUM_HW +#endif + +#ifndef IRQF_SHARED +#define IRQF_SHARED SA_SHIRQ +#endif + +#define memcpy_skb(skb, from, length) \ + memcpy(skb_put(skb, length), from, length) + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) +#ifndef DMA_BIT_MASK +#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) +#endif +#endif + +#ifndef __GFP_DMA32 +#define __GFP_DMA32 GFP_DMA +#endif + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) +#define wrap_kmem_cache_create(name, size, align, flags) \ + kmem_cache_create(name, size, align, flags, NULL, NULL) +#else +#define wrap_kmem_cache_create(name, size, align, flags) \ + kmem_cache_create(name, size, align, flags, NULL) +#endif + +#include "winnt_types.h" +#include "ndiswrapper.h" +#include "pe_linker.h" +#include "wrapmem.h" +#include "lin2win.h" +#include "loader.h" + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +static inline void netif_tx_lock(struct net_device *dev) +{ + spin_lock(&dev->xmit_lock); +} +static inline void netif_tx_unlock(struct net_device *dev) +{ + spin_unlock(&dev->xmit_lock); +} +static inline void netif_tx_lock_bh(struct net_device *dev) +{ + spin_lock_bh(&dev->xmit_lock); +} +static inline void netif_tx_unlock_bh(struct net_device *dev) +{ + spin_unlock_bh(&dev->xmit_lock); +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +static inline void netif_poll_enable(struct net_device *dev) +{ +} +static inline void netif_poll_disable(struct net_device *dev) +{ +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) +#define proc_net_root init_net.proc_net +#else +#define proc_net_root proc_net +#endif + +/* TICK is 100ns */ +#define TICKSPERSEC 10000000 +#define TICKSPERMSEC 10000 +#define SECSPERDAY 86400 +#define TICKSPERJIFFY ((TICKSPERSEC + HZ - 1) / HZ) + +#define int_div_round(x, y) (((x) + (y - 1)) / (y)) + +/* 1601 to 1970 is 369 years plus 89 leap days */ +#define SECS_1601_TO_1970 ((369 * 365 + 89) * (u64)SECSPERDAY) +#define TICKS_1601_TO_1970 (SECS_1601_TO_1970 * TICKSPERSEC) + +/* 100ns units to HZ; if sys_time is negative, relative to current + * clock, otherwise from year 1601 */ +#define SYSTEM_TIME_TO_HZ(sys_time) \ + (((sys_time) <= 0) ? \ + int_div_round(((u64)HZ * (-(sys_time))), TICKSPERSEC) : \ + int_div_round(((s64)HZ * ((sys_time) - ticks_1601())), TICKSPERSEC)) + +#define MSEC_TO_HZ(ms) int_div_round((ms * HZ), 1000) +#define USEC_TO_HZ(us) int_div_round((us * HZ), 1000000) + +extern u64 wrap_ticks_to_boot; + +static inline u64 ticks_1601(void) +{ + return wrap_ticks_to_boot + (u64)jiffies * TICKSPERJIFFY; +} + +typedef void (*generic_func)(void); + +struct wrap_export { + const char *name; + generic_func func; +}; + +#ifdef CONFIG_X86_64 + +#define WIN_SYMBOL(name, argc) \ + {#name, (generic_func) win2lin_ ## name ## _ ## argc} +#define WIN_WIN_SYMBOL(name, argc) \ + {#name, (generic_func) win2lin__win_ ## name ## _ ## argc} +#define WIN_FUNC_DECL(name, argc) \ + extern typeof(name) win2lin_ ## name ## _ ## argc; +#define WIN_FUNC_PTR(name, argc) win2lin_ ## name ## _ ## argc + +#else + +#define WIN_SYMBOL(name, argc) {#name, (generic_func)name} +#define WIN_WIN_SYMBOL(name, argc) {#name, (generic_func)_win_ ## name} +#define WIN_FUNC_DECL(name, argc) +#define WIN_FUNC_PTR(name, argc) name + +#endif + +#define WIN_FUNC(name, argc) name +/* map name s to f - if f is different from s */ +#define WIN_SYMBOL_MAP(s, f) + +#define POOL_TAG(A, B, C, D) \ + ((ULONG)((A) + ((B) << 8) + ((C) << 16) + ((D) << 24))) + +struct pe_image { + char name[MAX_DRIVER_NAME_LEN]; + UINT (*entry)(struct driver_object *, struct unicode_string *) wstdcall; + void *image; + int size; + int type; + + IMAGE_NT_HEADERS *nt_hdr; + IMAGE_OPTIONAL_HEADER *opt_hdr; +}; + +struct ndis_mp_block; + +struct wrap_timer { + struct nt_slist slist; + struct timer_list timer; + struct nt_timer *nt_timer; + long repeat; +#ifdef TIMER_DEBUG + unsigned long wrap_timer_magic; +#endif +}; + +struct ntos_work_item { + struct nt_list list; + void *arg1; + void *arg2; + NTOS_WORK_FUNC func; +}; + +struct wrap_device_setting { + struct nt_list list; + char name[MAX_SETTING_NAME_LEN]; + char value[MAX_SETTING_VALUE_LEN]; + void *encoded; +}; + +struct wrap_bin_file { + char name[MAX_DRIVER_NAME_LEN]; + size_t size; + void *data; +}; + +#define WRAP_DRIVER_CLIENT_ID 1 + +struct wrap_driver { + struct nt_list list; + struct driver_object *drv_obj; + char name[MAX_DRIVER_NAME_LEN]; + char version[MAX_SETTING_VALUE_LEN]; + unsigned short num_pe_images; + struct pe_image pe_images[MAX_DRIVER_PE_IMAGES]; + unsigned short num_bin_files; + struct wrap_bin_file *bin_files; + struct nt_list wrap_devices; + struct nt_list settings; + int dev_type; + struct ndis_driver *ndis_driver; +}; + +enum hw_status { + HW_INITIALIZED = 1, HW_SUSPENDED, HW_HALTED, HW_PRESENT, +}; + +struct wrap_device { + /* first part is (de)initialized once by loader */ + struct nt_list list; + int dev_bus; + int vendor; + int device; + int subvendor; + int subdevice; + char conf_file_name[MAX_DRIVER_NAME_LEN]; + char driver_name[MAX_DRIVER_NAME_LEN]; + struct wrap_driver *driver; + struct nt_list settings; + + /* rest should be (de)initialized when a device is + * (un)plugged */ + struct cm_resource_list *resource_list; + unsigned long hw_status; + struct device_object *pdo; + union { + struct { + struct pci_dev *pdev; + enum device_power_state wake_state; + } pci; + struct { + struct usb_device *udev; + struct usb_interface *intf; + int num_alloc_urbs; + struct nt_list wrap_urb_list; + } usb; + }; + union { + struct ndis_device *wnd; + }; +}; + +#define wrap_is_pci_bus(dev_bus) \ + (WRAP_BUS(dev_bus) == WRAP_PCI_BUS || \ + WRAP_BUS(dev_bus) == WRAP_PCMCIA_BUS) +#ifdef ENABLE_USB +/* earlier versions of ndiswrapper used 0 as USB_BUS */ +#define wrap_is_usb_bus(dev_bus) \ + (WRAP_BUS(dev_bus) == WRAP_USB_BUS || \ + WRAP_BUS(dev_bus) == WRAP_INTERNAL_BUS) +#else +#define wrap_is_usb_bus(dev_bus) 0 +#endif +#define wrap_is_bluetooth_device(dev_bus) \ + (WRAP_DEVICE(dev_bus) == WRAP_BLUETOOTH_DEVICE1 || \ + WRAP_DEVICE(dev_bus) == WRAP_BLUETOOTH_DEVICE2) + +extern workqueue_struct_t *ntos_wq; +#define schedule_ntos_work(work_struct) queue_work(ntos_wq, work_struct) +#define schedule_work(work_struct) queue_work(ntos_wq, work_struct) + +extern workqueue_struct_t *ndis_wq; +#define schedule_ndis_work(work_struct) queue_work(ndis_wq, work_struct) + +extern workqueue_struct_t *wrapndis_wq; +#define schedule_wrapndis_work(work_struct) queue_work(wrapndis_wq, work_struct) + +#define atomic_unary_op(var, size, oper) \ +do { \ + if (size == 1) \ + __asm__ __volatile__( \ + LOCK_PREFIX oper "b %b0\n\t" : "+m" (var)); \ + else if (size == 2) \ + __asm__ __volatile__( \ + LOCK_PREFIX oper "w %w0\n\t" : "+m" (var)); \ + else if (size == 4) \ + __asm__ __volatile__( \ + LOCK_PREFIX oper "l %0\n\t" : "+m" (var)); \ + else if (size == 8) \ + __asm__ __volatile__( \ + LOCK_PREFIX oper "q %q0\n\t" : "+m" (var)); \ + else { \ + extern void _invalid_op_size_(void); \ + _invalid_op_size_(); \ + } \ +} while (0) + +#define atomic_inc_var_size(var, size) atomic_unary_op(var, size, "inc") + +#define atomic_inc_var(var) atomic_inc_var_size(var, sizeof(var)) + +#define atomic_dec_var_size(var, size) atomic_unary_op(var, size, "dec") + +#define atomic_dec_var(var) atomic_dec_var_size(var, sizeof(var)) + +#define pre_atomic_add(var, i) \ +({ \ + typeof(var) pre; \ + __asm__ __volatile__( \ + LOCK_PREFIX "xadd %0, %1\n\t" \ + : "=r"(pre), "+m"(var) \ + : "0"(i)); \ + pre; \ +}) + +#define post_atomic_add(var, i) (pre_atomic_add(var, i) + i) + +#ifndef in_atomic +#define in_atomic() in_interrupt() +#endif + +#ifndef preempt_enable_no_resched +#define preempt_enable_no_resched() preempt_enable() +#endif + +//#define DEBUG_IRQL 1 + +#ifdef DEBUG_IRQL +#define assert_irql(cond) \ +do { \ + KIRQL _irql_ = current_irql(); \ + if (!(cond)) { \ + WARNING("assertion '%s' failed: %d", #cond, _irql_); \ + DBG_BLOCK(4) { \ + dump_stack(); \ + } \ + } \ +} while (0) +#else +#define assert_irql(cond) do { } while (0) +#endif + +/* When preempt is enabled, we should preempt_disable to raise IRQL to + * DISPATCH_LEVEL, to be consistent with the semantics. However, using + * a mutex instead, so that only ndiswrapper threads run one at a time + * on a processor when at DISPATCH_LEVEL seems to be enough. So that + * is what we will use until we learn otherwise. If + * preempt_(en|dis)able is required for some reason, comment out + * following #define. */ + +#define WRAP_PREEMPT 1 + +#if !defined(CONFIG_PREEMPT) || defined(CONFIG_PREEMPT_RT) +#ifndef WRAP_PREEMPT +#define WRAP_PREEMPT 1 +#endif +#endif + +//#undef WRAP_PREEMPT + +#ifdef WRAP_PREEMPT + +typedef struct { + int count; + struct mutex lock; +#ifdef CONFIG_SMP + typeof(current->cpus_allowed) cpus_allowed; +#endif + struct task_struct *task; +} irql_info_t; + +DECLARE_PER_CPU(irql_info_t, irql_info); + +static inline KIRQL raise_irql(KIRQL newirql) +{ + irql_info_t *info; + + assert(newirql == DISPATCH_LEVEL); + info = &get_cpu_var(irql_info); + if (info->task == current) { + assert(info->count > 0); + assert(mutex_is_locked(&info->lock)); +#if defined(CONFIG_SMP) && defined(DEBUG) + do { + cpumask_t cpumask; + cpumask = cpumask_of_cpu(smp_processor_id()); + cpus_xor(cpumask, cpumask, current->cpus_allowed); + assert(cpus_empty(cpumask)); + } while (0); +#endif + info->count++; + put_cpu_var(irql_info); + return DISPATCH_LEVEL; + } + /* TODO: is this enough to pin down to current cpu? */ +#ifdef CONFIG_SMP + assert(task_cpu(current) == smp_processor_id()); + info->cpus_allowed = current->cpus_allowed; + current->cpus_allowed = cpumask_of_cpu(smp_processor_id()); +#endif + put_cpu_var(irql_info); + mutex_lock(&info->lock); + assert(info->count == 0); + assert(info->task == NULL); + info->count = 1; + info->task = current; + return PASSIVE_LEVEL; +} + +static inline void lower_irql(KIRQL oldirql) +{ + irql_info_t *info; + + assert(oldirql <= DISPATCH_LEVEL); + info = &get_cpu_var(irql_info); + assert(info->task == current); + assert(mutex_is_locked(&info->lock)); + assert(info->count > 0); + if (--info->count == 0) { + info->task = NULL; +#ifdef CONFIG_SMP + current->cpus_allowed = info->cpus_allowed; +#endif + mutex_unlock(&info->lock); + } + put_cpu_var(irql_info); +} + +static inline KIRQL current_irql(void) +{ + int count; + if (in_irq() || irqs_disabled()) + EXIT4(return DIRQL); + if (in_atomic() || in_interrupt()) + EXIT4(return SOFT_IRQL); + count = get_cpu_var(irql_info).count; + put_cpu_var(irql_info); + if (count) + EXIT6(return DISPATCH_LEVEL); + else + EXIT6(return PASSIVE_LEVEL); +} + +#else + +static inline KIRQL current_irql(void) +{ + if (in_irq() || irqs_disabled()) + EXIT4(return DIRQL); + if (in_interrupt()) + EXIT4(return SOFT_IRQL); + if (in_atomic()) + EXIT6(return DISPATCH_LEVEL); + else + EXIT6(return PASSIVE_LEVEL); +} + +static inline KIRQL raise_irql(KIRQL newirql) +{ + KIRQL ret = in_atomic() ? DISPATCH_LEVEL : PASSIVE_LEVEL; + assert(newirql == DISPATCH_LEVEL); + assert(current_irql() <= DISPATCH_LEVEL); + preempt_disable(); + return ret; +} + +static inline void lower_irql(KIRQL oldirql) +{ + assert(current_irql() == DISPATCH_LEVEL); + preempt_enable(); +} + +#endif + +#define irql_gfp() (in_atomic() ? GFP_ATOMIC : GFP_KERNEL) + +/* Windows spinlocks are of type ULONG_PTR which is not big enough to + * store Linux spinlocks; so we implement Windows spinlocks using + * ULONG_PTR space with our own functions/macros */ + +/* Windows seems to use 0 for unlocked state of spinlock - if Linux + * convention of 1 for unlocked state is used, at least prism54 driver + * crashes */ + +#define NT_SPIN_LOCK_UNLOCKED 0 +#define NT_SPIN_LOCK_LOCKED 1 + +static inline void nt_spin_lock_init(NT_SPIN_LOCK *lock) +{ + *lock = NT_SPIN_LOCK_UNLOCKED; +} + +#ifdef CONFIG_SMP + +static inline void nt_spin_lock(NT_SPIN_LOCK *lock) +{ + __asm__ __volatile__( + "1:\t" + " xchgl %1, %0\n\t" + " testl %1, %1\n\t" + " jz 3f\n" + "2:\t" + " rep; nop\n\t" + " cmpl %2, %0\n\t" + " je 1b\n\t" + " jmp 2b\n" + "3:\n\t" + : "+m" (*lock) + : "r" (NT_SPIN_LOCK_LOCKED), "i" (NT_SPIN_LOCK_UNLOCKED)); +} + +static inline void nt_spin_unlock(NT_SPIN_LOCK *lock) +{ + *lock = NT_SPIN_LOCK_UNLOCKED; +} + +#else // CONFIG_SMP + +#define nt_spin_lock(lock) do { } while (0) + +#define nt_spin_unlock(lock) do { } while (0) + +#endif // CONFIG_SMP + +/* When kernel would've disabled preempt (e.g., in interrupt + * handlers), we need to fake preempt so driver thinks it is running + * at right IRQL */ + +/* raise IRQL to given (higher) IRQL if necessary before locking */ +static inline KIRQL nt_spin_lock_irql(NT_SPIN_LOCK *lock, KIRQL newirql) +{ + KIRQL oldirql = raise_irql(newirql); + nt_spin_lock(lock); + return oldirql; +} + +/* lower IRQL to given (lower) IRQL if necessary after unlocking */ +static inline void nt_spin_unlock_irql(NT_SPIN_LOCK *lock, KIRQL oldirql) +{ + nt_spin_unlock(lock); + lower_irql(oldirql); +} + +#define nt_spin_lock_irqsave(lock, flags) \ +do { \ + local_irq_save(flags); \ + preempt_disable(); \ + nt_spin_lock(lock); \ +} while (0) + +#define nt_spin_unlock_irqrestore(lock, flags) \ +do { \ + nt_spin_unlock(lock); \ + preempt_enable_no_resched(); \ + local_irq_restore(flags); \ + preempt_check_resched(); \ +} while (0) + +static inline ULONG SPAN_PAGES(void *ptr, SIZE_T length) +{ + return PAGE_ALIGN(((unsigned long)ptr & (PAGE_SIZE - 1)) + length) + >> PAGE_SHIFT; +} + +#ifdef CONFIG_X86_64 + +/* TODO: can these be implemented without using spinlock? */ + +static inline struct nt_slist *PushEntrySList(nt_slist_header *head, + struct nt_slist *entry, + NT_SPIN_LOCK *lock) +{ + KIRQL irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL); + entry->next = head->next; + head->next = entry; + head->depth++; + nt_spin_unlock_irql(lock, irql); + TRACE4("%p, %p, %p", head, entry, entry->next); + return entry->next; +} + +static inline struct nt_slist *PopEntrySList(nt_slist_header *head, + NT_SPIN_LOCK *lock) +{ + struct nt_slist *entry; + KIRQL irql = nt_spin_lock_irql(lock, DISPATCH_LEVEL); + entry = head->next; + if (entry) { + head->next = entry->next; + head->depth--; + } + nt_spin_unlock_irql(lock, irql); + TRACE4("%p, %p", head, entry); + return entry; +} + +#else + +#define u64_low_32(x) ((u32)x) +#define u64_high_32(x) ((u32)(x >> 32)) + +static inline u64 nt_cmpxchg8b(volatile u64 *ptr, u64 old, u64 new) +{ + u64 prev; + + __asm__ __volatile__( + "\n" + LOCK_PREFIX "cmpxchg8b %0\n" + : "+m" (*ptr), "=A" (prev) + : "A" (old), "b" (u64_low_32(new)), "c" (u64_high_32(new))); + return prev; +} + +/* slist routines below update slist atomically - no need for + * spinlocks */ + +static inline struct nt_slist *PushEntrySList(nt_slist_header *head, + struct nt_slist *entry, + NT_SPIN_LOCK *lock) +{ + nt_slist_header old, new; + do { + old.align = head->align; + entry->next = old.next; + new.next = entry; + new.depth = old.depth + 1; + } while (nt_cmpxchg8b(&head->align, old.align, new.align) != old.align); + TRACE4("%p, %p, %p", head, entry, old.next); + return old.next; +} + +static inline struct nt_slist *PopEntrySList(nt_slist_header *head, + NT_SPIN_LOCK *lock) +{ + struct nt_slist *entry; + nt_slist_header old, new; + do { + old.align = head->align; + entry = old.next; + if (!entry) + break; + new.next = entry->next; + new.depth = old.depth - 1; + } while (nt_cmpxchg8b(&head->align, old.align, new.align) != old.align); + TRACE4("%p, %p", head, entry); + return entry; +} + +#endif + +#define sleep_hz(n) \ +do { \ + set_current_state(TASK_INTERRUPTIBLE); \ + schedule_timeout(n); \ +} while (0) + +int ntoskernel_init(void); +void ntoskernel_exit(void); +int ntoskernel_init_device(struct wrap_device *wd); +void ntoskernel_exit_device(struct wrap_device *wd); +void *allocate_object(ULONG size, enum common_object_type type, + struct unicode_string *name); +void free_object(void *object); + +int usb_init(void); +void usb_exit(void); +int usb_init_device(struct wrap_device *wd); +void usb_exit_device(struct wrap_device *wd); +void usb_cancel_pending_urbs(void); + +int crt_init(void); +void crt_exit(void); +int rtl_init(void); +void rtl_exit(void); +int wrap_procfs_init(void); +void wrap_procfs_remove(void); + +int link_pe_images(struct pe_image *pe_image, unsigned short n); + +int stricmp(const char *s1, const char *s2); +void dump_bytes(const char *name, const u8 *from, int len); +struct mdl *allocate_init_mdl(void *virt, ULONG length); +void free_mdl(struct mdl *mdl); +struct driver_object *find_bus_driver(const char *name); +void free_custom_extensions(struct driver_extension *drv_obj_ext); +struct nt_thread *get_current_nt_thread(void); +u64 ticks_1601(void); +int schedule_ntos_work_item(NTOS_WORK_FUNC func, void *arg1, void *arg2); +void wrap_init_timer(struct nt_timer *nt_timer, enum timer_type type, + struct ndis_mp_block *nmb); +BOOLEAN wrap_set_timer(struct nt_timer *nt_timer, unsigned long expires_hz, + unsigned long repeat_hz, struct kdpc *kdpc); + +LONG InterlockedDecrement(LONG volatile *val) wfastcall; +LONG InterlockedIncrement(LONG volatile *val) wfastcall; +struct nt_list *ExInterlockedInsertHeadList + (struct nt_list *head, struct nt_list *entry, + NT_SPIN_LOCK *lock) wfastcall; +struct nt_list *ExInterlockedInsertTailList + (struct nt_list *head, struct nt_list *entry, + NT_SPIN_LOCK *lock) wfastcall; +struct nt_list *ExInterlockedRemoveHeadList + (struct nt_list *head, NT_SPIN_LOCK *lock) wfastcall; +NTSTATUS IofCallDriver(struct device_object *dev_obj, struct irp *irp) wfastcall; +KIRQL KfRaiseIrql(KIRQL newirql) wfastcall; +void KfLowerIrql(KIRQL oldirql) wfastcall; +KIRQL KfAcquireSpinLock(NT_SPIN_LOCK *lock) wfastcall; +void KfReleaseSpinLock(NT_SPIN_LOCK *lock, KIRQL oldirql) wfastcall; +void IofCompleteRequest(struct irp *irp, CHAR prio_boost) wfastcall; +void KefReleaseSpinLockFromDpcLevel(NT_SPIN_LOCK *lock) wfastcall; + +LONG ObfReferenceObject(void *object) wfastcall; +void ObfDereferenceObject(void *object) wfastcall; + +#define ObReferenceObject(object) ObfReferenceObject(object) +#define ObDereferenceObject(object) ObfDereferenceObject(object) + +void WRITE_PORT_UCHAR(ULONG_PTR port, UCHAR value) wstdcall; +UCHAR READ_PORT_UCHAR(ULONG_PTR port) wstdcall; + +#undef ExAllocatePoolWithTag +void *ExAllocatePoolWithTag(enum pool_type pool_type, SIZE_T size, + ULONG tag) wstdcall; +#if defined(ALLOC_DEBUG) && ALLOC_DEBUG > 1 +#define ExAllocatePoolWithTag(pool_type, size, tag) \ + wrap_ExAllocatePoolWithTag(pool_type, size, tag, __FILE__, __LINE__) +#endif + +void ExFreePool(void *p) wstdcall; +ULONG MmSizeOfMdl(void *base, ULONG length) wstdcall; +void __iomem *MmMapIoSpace(PHYSICAL_ADDRESS phys_addr, SIZE_T size, + enum memory_caching_type cache) wstdcall; +void MmUnmapIoSpace(void __iomem *addr, SIZE_T size) wstdcall; +void MmProbeAndLockPages(struct mdl *mdl, KPROCESSOR_MODE access_mode, + enum lock_operation operation) wstdcall; +void MmUnlockPages(struct mdl *mdl) wstdcall; +void KeInitializeEvent(struct nt_event *nt_event, + enum event_type type, BOOLEAN state) wstdcall; +LONG KeSetEvent(struct nt_event *nt_event, KPRIORITY incr, + BOOLEAN wait) wstdcall; +LONG KeResetEvent(struct nt_event *nt_event) wstdcall; +void KeClearEvent(struct nt_event *nt_event) wstdcall; +void KeInitializeDpc(struct kdpc *kdpc, void *func, void *ctx) wstdcall; +BOOLEAN queue_kdpc(struct kdpc *kdpc); +BOOLEAN dequeue_kdpc(struct kdpc *kdpc); + +void KeFlushQueuedDpcs(void) wstdcall; +NTSTATUS IoConnectInterrupt(struct kinterrupt **kinterrupt, + PKSERVICE_ROUTINE service_routine, + void *service_context, NT_SPIN_LOCK *lock, + ULONG vector, KIRQL irql, KIRQL synch_irql, + enum kinterrupt_mode interrupt_mode, + BOOLEAN shareable, KAFFINITY processor_enable_mask, + BOOLEAN floating_save) wstdcall; +void IoDisconnectInterrupt(struct kinterrupt *interrupt) wstdcall; +BOOLEAN KeSynchronizeExecution(struct kinterrupt *interrupt, + PKSYNCHRONIZE_ROUTINE synch_routine, + void *ctx) wstdcall; + +NTSTATUS KeWaitForSingleObject(void *object, KWAIT_REASON reason, + KPROCESSOR_MODE waitmode, BOOLEAN alertable, + LARGE_INTEGER *timeout) wstdcall; +struct mdl *IoAllocateMdl(void *virt, ULONG length, BOOLEAN second_buf, + BOOLEAN charge_quota, struct irp *irp) wstdcall; +void MmBuildMdlForNonPagedPool(struct mdl *mdl) wstdcall; +void IoFreeMdl(struct mdl *mdl) wstdcall; +NTSTATUS IoCreateDevice(struct driver_object *driver, ULONG dev_ext_length, + struct unicode_string *dev_name, DEVICE_TYPE dev_type, + ULONG dev_chars, BOOLEAN exclusive, + struct device_object **dev_obj) wstdcall; +NTSTATUS IoCreateSymbolicLink(struct unicode_string *link, + struct unicode_string *dev_name) wstdcall; +void IoDeleteDevice(struct device_object *dev) wstdcall; +void IoDetachDevice(struct device_object *topdev) wstdcall; +struct device_object *IoGetAttachedDevice(struct device_object *dev) wstdcall; +struct device_object *IoGetAttachedDeviceReference + (struct device_object *dev) wstdcall; +NTSTATUS IoAllocateDriverObjectExtension + (struct driver_object *drv_obj, void *client_id, ULONG extlen, + void **ext) wstdcall; +void *IoGetDriverObjectExtension(struct driver_object *drv, + void *client_id) wstdcall; +struct device_object *IoAttachDeviceToDeviceStack + (struct device_object *src, struct device_object *dst) wstdcall; +void KeInitializeEvent(struct nt_event *nt_event, enum event_type type, + BOOLEAN state) wstdcall; +struct irp *IoAllocateIrp(char stack_count, BOOLEAN charge_quota) wstdcall; +void IoFreeIrp(struct irp *irp) wstdcall; +BOOLEAN IoCancelIrp(struct irp *irp) wstdcall; +struct irp *IoBuildSynchronousFsdRequest + (ULONG major_func, struct device_object *dev_obj, void *buf, + ULONG length, LARGE_INTEGER *offset, struct nt_event *event, + struct io_status_block *status) wstdcall; +struct irp *IoBuildAsynchronousFsdRequest + (ULONG major_func, struct device_object *dev_obj, void *buf, + ULONG length, LARGE_INTEGER *offset, + struct io_status_block *status) wstdcall; +NTSTATUS PoCallDriver(struct device_object *dev_obj, struct irp *irp) wstdcall; + +NTSTATUS IoPassIrpDown(struct device_object *dev_obj, struct irp *irp) wstdcall; +WIN_FUNC_DECL(IoPassIrpDown,2); +NTSTATUS IoSyncForwardIrp(struct device_object *dev_obj, + struct irp *irp) wstdcall; +NTSTATUS IoAsyncForwardIrp(struct device_object *dev_obj, + struct irp *irp) wstdcall; +NTSTATUS IoInvalidDeviceRequest(struct device_object *dev_obj, + struct irp *irp) wstdcall; + +KIRQL KeGetCurrentIrql(void) wstdcall; +void KeInitializeSpinLock(NT_SPIN_LOCK *lock) wstdcall; +void KeAcquireSpinLock(NT_SPIN_LOCK *lock, KIRQL *irql) wstdcall; +void KeReleaseSpinLock(NT_SPIN_LOCK *lock, KIRQL oldirql) wstdcall; +KIRQL KeAcquireSpinLockRaiseToDpc(NT_SPIN_LOCK *lock) wstdcall; + +void IoAcquireCancelSpinLock(KIRQL *irql) wstdcall; +void IoReleaseCancelSpinLock(KIRQL irql) wstdcall; + +void RtlCopyMemory(void *dst, const void *src, SIZE_T length) wstdcall; +NTSTATUS RtlUnicodeStringToAnsiString + (struct ansi_string *dst, const struct unicode_string *src, + BOOLEAN dup) wstdcall; +NTSTATUS RtlAnsiStringToUnicodeString + (struct unicode_string *dst, const struct ansi_string *src, + BOOLEAN dup) wstdcall; +void RtlInitAnsiString(struct ansi_string *dst, const char *src) wstdcall; +void RtlInitString(struct ansi_string *dst, const char *src) wstdcall; +void RtlInitUnicodeString(struct unicode_string *dest, + const wchar_t *src) wstdcall; +void RtlFreeUnicodeString(struct unicode_string *string) wstdcall; +void RtlFreeAnsiString(struct ansi_string *string) wstdcall; +LONG RtlCompareUnicodeString(const struct unicode_string *s1, + const struct unicode_string *s2, + BOOLEAN case_insensitive) wstdcall; +void RtlCopyUnicodeString(struct unicode_string *dst, + struct unicode_string *src) wstdcall; +NTSTATUS RtlUpcaseUnicodeString(struct unicode_string *dst, + struct unicode_string *src, + BOOLEAN alloc) wstdcall; +void KeInitializeTimer(struct nt_timer *nt_timer) wstdcall; +void KeInitializeTimerEx(struct nt_timer *nt_timer, + enum timer_type type) wstdcall; +BOOLEAN KeSetTimerEx(struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks, + LONG period_ms, struct kdpc *kdpc) wstdcall; +BOOLEAN KeSetTimer(struct nt_timer *nt_timer, LARGE_INTEGER duetime_ticks, + struct kdpc *kdpc) wstdcall; +BOOLEAN KeCancelTimer(struct nt_timer *nt_timer) wstdcall; +void KeInitializeDpc(struct kdpc *kdpc, void *func, void *ctx) wstdcall; +struct nt_thread *KeGetCurrentThread(void) wstdcall; +NTSTATUS ObReferenceObjectByHandle(void *handle, ACCESS_MASK desired_access, + void *obj_type, KPROCESSOR_MODE access_mode, + void **object, void *handle_info) wstdcall; + +void adjust_user_shared_data_addr(char *driver, unsigned long length); + +extern spinlock_t ntoskernel_lock; +extern spinlock_t irp_cancel_lock; +extern struct nt_list object_list; +#ifdef CONFIG_X86_64 +extern struct kuser_shared_data kuser_shared_data; +#endif + +#define IoCompleteRequest(irp, prio) IofCompleteRequest(irp, prio) +#define IoCallDriver(dev, irp) IofCallDriver(dev, irp) + +#if defined(IO_DEBUG) +#define DUMP_IRP(_irp) \ +do { \ + struct io_stack_location *_irp_sl; \ + _irp_sl = IoGetCurrentIrpStackLocation(_irp); \ + IOTRACE("irp: %p, stack size: %d, cl: %d, sl: %p, dev_obj: %p, " \ + "mj_fn: %d, minor_fn: %d, nt_urb: %p, event: %p", \ + _irp, _irp->stack_count, (_irp)->current_location, \ + _irp_sl, _irp_sl->dev_obj, _irp_sl->major_fn, \ + _irp_sl->minor_fn, IRP_URB(_irp), \ + (_irp)->user_event); \ +} while (0) +#else +#define DUMP_IRP(_irp) do { } while (0) +#endif + +#endif // _NTOSKERNEL_H_ --- linux-2.6.37.orig/ubuntu/ndiswrapper/ntoskernel_io.c +++ linux-2.6.37/ubuntu/ndiswrapper/ntoskernel_io.c @@ -0,0 +1,1106 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ + +#include "ntoskernel.h" +#include "ndis.h" +#include "wrapndis.h" +#include "usb.h" +#include "loader.h" +#include "ntoskernel_io_exports.h" + +wstdcall void WIN_FUNC(IoAcquireCancelSpinLock,1) + (KIRQL *irql) __acquires(irql) +{ + spin_lock_bh(&irp_cancel_lock); + *irql = 0; +} + +wstdcall void WIN_FUNC(IoReleaseCancelSpinLock,1) + (KIRQL irql) __releases(irql) +{ + spin_unlock_bh(&irp_cancel_lock); +} + +wstdcall int WIN_FUNC(IoIsWdmVersionAvailable,2) + (UCHAR major, UCHAR minor) +{ + IOENTER("%d, %x", major, minor); + if (major == 1 && + (minor == 0x30 || // Windows 2003 + minor == 0x20 || // Windows XP + minor == 0x10)) // Windows 2000 + IOEXIT(return TRUE); + IOEXIT(return FALSE); +} + +wstdcall BOOLEAN WIN_FUNC(IoIs32bitProcess,1) + (struct irp *irp) +{ +#ifdef CONFIG_X86_64 + return FALSE; +#else + return TRUE; +#endif +} + +wstdcall void WIN_FUNC(IoInitializeIrp,3) + (struct irp *irp, USHORT size, CCHAR stack_count) +{ + IOENTER("irp: %p, %d, %d", irp, size, stack_count); + + memset(irp, 0, size); + irp->size = size; + irp->stack_count = stack_count; + irp->current_location = stack_count; + IoGetCurrentIrpStackLocation(irp) = IRP_SL(irp, stack_count); + IOEXIT(return); +} + +wstdcall void WIN_FUNC(IoReuseIrp,2) + (struct irp *irp, NTSTATUS status) +{ + IOENTER("%p, %d", irp, status); + if (irp) { + UCHAR alloc_flags; + + alloc_flags = irp->alloc_flags; + IoInitializeIrp(irp, irp->size, irp->stack_count); + irp->alloc_flags = alloc_flags; + irp->io_status.status = status; + } + IOEXIT(return); +} + +wstdcall struct irp *WIN_FUNC(IoAllocateIrp,2) + (char stack_count, BOOLEAN charge_quota) +{ + struct irp *irp; + int irp_size; + + IOENTER("count: %d", stack_count); + stack_count++; + irp_size = IoSizeOfIrp(stack_count); + irp = kmalloc(irp_size, irql_gfp()); + if (irp) + IoInitializeIrp(irp, irp_size, stack_count); + IOTRACE("irp %p", irp); + IOEXIT(return irp); +} + +wstdcall BOOLEAN WIN_FUNC(IoCancelIrp,1) + (struct irp *irp) +{ + typeof(irp->cancel_routine) cancel_routine; + + /* NB: this function may be called at DISPATCH_LEVEL */ + IOTRACE("irp: %p", irp); + if (!irp) + return FALSE; + DUMP_IRP(irp); + IoAcquireCancelSpinLock(&irp->cancel_irql); + cancel_routine = xchg(&irp->cancel_routine, NULL); + IOTRACE("%p", cancel_routine); + irp->cancel = TRUE; + if (cancel_routine) { + struct io_stack_location *irp_sl; + irp_sl = IoGetCurrentIrpStackLocation(irp); + IOTRACE("%p, %p", irp_sl, irp_sl->dev_obj); + /* cancel_routine will release the spin lock */ + __release(irp->cancel_irql); + LIN2WIN2(cancel_routine, irp_sl->dev_obj, irp); + /* in usb's cancel, irp->cancel is set to indicate + * status of cancel */ + IOEXIT(return xchg(&irp->cancel, TRUE)); + } else { + IOTRACE("irp %p already canceled", irp); + IoReleaseCancelSpinLock(irp->cancel_irql); + IOEXIT(return FALSE); + } +} + +wstdcall void IoQueueThreadIrp(struct irp *irp) +{ + struct nt_thread *thread; + KIRQL irql; + + thread = get_current_nt_thread(); + if (thread) { + IOTRACE("thread: %p, task: %p", thread, thread->task); + irp->flags |= IRP_SYNCHRONOUS_API; + irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL); + InsertTailList(&thread->irps, &irp->thread_list); + IoIrpThread(irp) = thread; + nt_spin_unlock_irql(&thread->lock, irql); + } else + IoIrpThread(irp) = NULL; +} + +wstdcall void IoDequeueThreadIrp(struct irp *irp) +{ + struct nt_thread *thread; + KIRQL irql; + + thread = IoIrpThread(irp); + if (thread) { + irql = nt_spin_lock_irql(&thread->lock, DISPATCH_LEVEL); + RemoveEntryList(&irp->thread_list); + nt_spin_unlock_irql(&thread->lock, irql); + } +} + +wstdcall void WIN_FUNC(IoFreeIrp,1) + (struct irp *irp) +{ + IOENTER("irp = %p", irp); + if (irp->flags & IRP_SYNCHRONOUS_API) + IoDequeueThreadIrp(irp); + kfree(irp); + + IOEXIT(return); +} + +wstdcall struct irp *WIN_FUNC(IoBuildAsynchronousFsdRequest,6) + (ULONG major_fn, struct device_object *dev_obj, void *buffer, + ULONG length, LARGE_INTEGER *offset, + struct io_status_block *user_status) +{ + struct irp *irp; + struct io_stack_location *irp_sl; + + IOENTER("%p", dev_obj); + if (!dev_obj) + IOEXIT(return NULL); + irp = IoAllocateIrp(dev_obj->stack_count, FALSE); + if (irp == NULL) { + WARNING("couldn't allocate irp"); + IOEXIT(return NULL); + } + + irp_sl = IoGetNextIrpStackLocation(irp); + irp_sl->major_fn = major_fn; + IOTRACE("major_fn: %d", major_fn); + irp_sl->minor_fn = 0; + irp_sl->flags = 0; + irp_sl->control = 0; + irp_sl->dev_obj = dev_obj; + irp_sl->file_obj = NULL; + irp_sl->completion_routine = NULL; + + if (dev_obj->flags & DO_DIRECT_IO) { + irp->mdl = IoAllocateMdl(buffer, length, FALSE, FALSE, irp); + if (irp->mdl == NULL) { + IoFreeIrp(irp); + return NULL; + } + MmProbeAndLockPages(irp->mdl, KernelMode, + major_fn == IRP_MJ_WRITE ? + IoReadAccess : IoWriteAccess); + IOTRACE("mdl: %p", irp->mdl); + } else if (dev_obj->flags & DO_BUFFERED_IO) { + irp->associated_irp.system_buffer = buffer; + irp->flags = IRP_BUFFERED_IO; + irp->mdl = NULL; + IOTRACE("buffer: %p", buffer); + } + if (major_fn == IRP_MJ_READ) { + irp_sl->params.read.length = length; + irp_sl->params.read.byte_offset = *offset; + } else if (major_fn == IRP_MJ_WRITE) { + irp_sl->params.write.length = length; + irp_sl->params.write.byte_offset = *offset; + } + irp->user_status = user_status; + IOTRACE("irp: %p", irp); + return irp; +} + +wstdcall struct irp *WIN_FUNC(IoBuildSynchronousFsdRequest,7) + (ULONG major_fn, struct device_object *dev_obj, void *buf, + ULONG length, LARGE_INTEGER *offset, struct nt_event *event, + struct io_status_block *user_status) +{ + struct irp *irp; + + irp = IoBuildAsynchronousFsdRequest(major_fn, dev_obj, buf, length, + offset, user_status); + if (irp == NULL) + return NULL; + irp->user_event = event; + IoQueueThreadIrp(irp); + return irp; +} + +wstdcall struct irp *WIN_FUNC(IoBuildDeviceIoControlRequest,9) + (ULONG ioctl, struct device_object *dev_obj, + void *input_buf, ULONG input_buf_len, void *output_buf, + ULONG output_buf_len, BOOLEAN internal_ioctl, + struct nt_event *event, struct io_status_block *io_status) +{ + struct irp *irp; + struct io_stack_location *irp_sl; + ULONG buf_len; + + IOENTER("%p, 0x%08x, %d", dev_obj, ioctl, internal_ioctl); + if (!dev_obj) + IOEXIT(return NULL); + irp = IoAllocateIrp(dev_obj->stack_count, FALSE); + if (irp == NULL) { + WARNING("couldn't allocate irp"); + return NULL; + } + irp_sl = IoGetNextIrpStackLocation(irp); + irp_sl->params.dev_ioctl.code = ioctl; + irp_sl->params.dev_ioctl.input_buf_len = input_buf_len; + irp_sl->params.dev_ioctl.output_buf_len = output_buf_len; + irp_sl->major_fn = (internal_ioctl) ? + IRP_MJ_INTERNAL_DEVICE_CONTROL : IRP_MJ_DEVICE_CONTROL; + IOTRACE("%d", IO_METHOD_FROM_CTL_CODE(ioctl)); + + switch (IO_METHOD_FROM_CTL_CODE(ioctl)) { + case METHOD_BUFFERED: + buf_len = max(input_buf_len, output_buf_len); + if (buf_len) { + irp->associated_irp.system_buffer = + ExAllocatePoolWithTag(NonPagedPool, buf_len, 0); + if (!irp->associated_irp.system_buffer) { + IoFreeIrp(irp); + IOEXIT(return NULL); + } + irp->associated_irp.system_buffer = input_buf; + if (input_buf) + memcpy(irp->associated_irp.system_buffer, + input_buf, input_buf_len); + irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; + if (output_buf) + irp->flags = IRP_INPUT_OPERATION; + irp->user_buf = output_buf; + } else + irp->user_buf = NULL; + break; + case METHOD_IN_DIRECT: + case METHOD_OUT_DIRECT: + if (input_buf) { + irp->associated_irp.system_buffer = + ExAllocatePoolWithTag(NonPagedPool, + input_buf_len, 0); + if (!irp->associated_irp.system_buffer) { + IoFreeIrp(irp); + IOEXIT(return NULL); + } + memcpy(irp->associated_irp.system_buffer, + input_buf, input_buf_len); + irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; + } + /* TODO: we are supposed to setup MDL, but USB layer + * doesn't use MDLs. Moreover, USB layer mirrors + * non-DMAable buffers, so no need to allocate + * DMAable buffer here */ + if (output_buf) { + irp->associated_irp.system_buffer = + ExAllocatePoolWithTag(NonPagedPool, + output_buf_len, 0); + if (!irp->associated_irp.system_buffer) { + IoFreeIrp(irp); + IOEXIT(return NULL); + } + irp->flags = IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER; + } + break; + case METHOD_NEITHER: + irp->user_buf = output_buf; + irp_sl->params.dev_ioctl.type3_input_buf = input_buf; + break; + } + + irp->user_status = io_status; + irp->user_event = event; + IoQueueThreadIrp(irp); + + IOTRACE("irp: %p", irp); + IOEXIT(return irp); +} + +wfastcall NTSTATUS WIN_FUNC(IofCallDriver,2) + (struct device_object *dev_obj, struct irp *irp) +{ + struct io_stack_location *irp_sl; + NTSTATUS status; + driver_dispatch_t *major_func; + struct driver_object *drv_obj; + + if (irp->current_location <= 0) { + ERROR("invalid irp: %p, %d", irp, irp->current_location); + return STATUS_INVALID_PARAMETER; + } + IOTRACE("%p, %p, %p, %d, %d, %p", dev_obj, irp, dev_obj->drv_obj, + irp->current_location, irp->stack_count, + IoGetCurrentIrpStackLocation(irp)); + IoSetNextIrpStackLocation(irp); + DUMP_IRP(irp); + irp_sl = IoGetCurrentIrpStackLocation(irp); + drv_obj = dev_obj->drv_obj; + irp_sl->dev_obj = dev_obj; + major_func = drv_obj->major_func[irp_sl->major_fn]; + IOTRACE("major_func: %p, dev_obj: %p", major_func, dev_obj); + if (major_func) + status = LIN2WIN2(major_func, dev_obj, irp); + else { + ERROR("major_function %d is not implemented", + irp_sl->major_fn); + status = STATUS_NOT_SUPPORTED; + } + IOEXIT(return status); +} + +wfastcall void WIN_FUNC(IofCompleteRequest,2) + (struct irp *irp, CHAR prio_boost) +{ + struct io_stack_location *irp_sl; + +#ifdef IO_DEBUG + DUMP_IRP(irp); + if (irp->io_status.status == STATUS_PENDING) { + ERROR("invalid irp: %p, STATUS_PENDING", irp); + return; + } + if (irp->current_location < 0 || + irp->current_location >= irp->stack_count) { + ERROR("invalid irp: %p, %d", irp, irp->current_location); + return; + } +#endif + for (irp_sl = IoGetCurrentIrpStackLocation(irp); + irp->current_location < irp->stack_count; irp_sl++) { + struct device_object *dev_obj; + NTSTATUS status; + + DUMP_IRP(irp); + if (irp_sl->control & SL_PENDING_RETURNED) + irp->pending_returned = TRUE; + + /* current_location and dev_obj must be same as when + * driver called IoSetCompletionRoutine, which sets + * completion routine at next (lower) location, which + * is what we are going to call below; so we set + * current_location and dev_obj for the previous + * (higher) location */ + IoSkipCurrentIrpStackLocation(irp); + if (irp->current_location < irp->stack_count) + dev_obj = IoGetCurrentIrpStackLocation(irp)->dev_obj; + else + dev_obj = NULL; + + IOTRACE("%d, %d, %p", irp->current_location, irp->stack_count, + dev_obj); + if (irp_sl->completion_routine && + ((irp->io_status.status == STATUS_SUCCESS && + irp_sl->control & SL_INVOKE_ON_SUCCESS) || + (irp->io_status.status != STATUS_SUCCESS && + irp_sl->control & SL_INVOKE_ON_ERROR) || + (irp->cancel == TRUE && + irp_sl->control & SL_INVOKE_ON_CANCEL))) { + IOTRACE("calling completion_routine at: %p, %p", + irp_sl->completion_routine, irp_sl->context); + status = LIN2WIN3(irp_sl->completion_routine, + dev_obj, irp, irp_sl->context); + IOTRACE("status: %08X", status); + if (status == STATUS_MORE_PROCESSING_REQUIRED) + IOEXIT(return); + } else { + /* propagate pending status to next irp_sl */ + if (irp->pending_returned && + irp->current_location < irp->stack_count) + IoMarkIrpPending(irp); + } + } + + if (irp->user_status) { + irp->user_status->status = irp->io_status.status; + irp->user_status->info = irp->io_status.info; + } + + if (irp->user_event) { + IOTRACE("setting event %p", irp->user_event); + KeSetEvent(irp->user_event, prio_boost, FALSE); + } + + if (irp->associated_irp.system_buffer && + (irp->flags & IRP_DEALLOCATE_BUFFER)) + ExFreePool(irp->associated_irp.system_buffer); + else { + struct mdl *mdl; + while ((mdl = irp->mdl)) { + irp->mdl = mdl->next; + MmUnlockPages(mdl); + IoFreeMdl(mdl); + } + } + IOTRACE("freeing irp %p", irp); + IoFreeIrp(irp); + IOEXIT(return); +} + +wstdcall NTSTATUS IoPassIrpDown(struct device_object *dev_obj, struct irp *irp) +{ + IoSkipCurrentIrpStackLocation(irp); + IOEXIT(return IoCallDriver(dev_obj, irp)); +} + +wstdcall NTSTATUS IoIrpSyncComplete(struct device_object *dev_obj, + struct irp *irp, void *context) +{ + if (irp->pending_returned == TRUE) + KeSetEvent(context, IO_NO_INCREMENT, FALSE); + IOEXIT(return STATUS_MORE_PROCESSING_REQUIRED); +} +WIN_FUNC_DECL(IoIrpSyncComplete,3) + +wstdcall NTSTATUS IoSyncForwardIrp(struct device_object *dev_obj, + struct irp *irp) +{ + struct nt_event event; + NTSTATUS status; + + IoCopyCurrentIrpStackLocationToNext(irp); + KeInitializeEvent(&event, SynchronizationEvent, FALSE); + /* completion function is called as Windows function */ + IoSetCompletionRoutine(irp, WIN_FUNC_PTR(IoIrpSyncComplete,3), &event, + TRUE, TRUE, TRUE); + status = IoCallDriver(dev_obj, irp); + IOTRACE("%08X", status); + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, + NULL); + status = irp->io_status.status; + } + IOTRACE("%08X", status); + IOEXIT(return status); +} +WIN_FUNC_DECL(IoSyncForwardIrp,2) + +wstdcall NTSTATUS IoAsyncForwardIrp(struct device_object *dev_obj, + struct irp *irp) +{ + NTSTATUS status; + + IoCopyCurrentIrpStackLocationToNext(irp); + status = IoCallDriver(dev_obj, irp); + IOEXIT(return status); +} +WIN_FUNC_DECL(IoAsyncForwardIrp,2) + +wstdcall NTSTATUS IoInvalidDeviceRequest(struct device_object *dev_obj, + struct irp *irp) +{ + struct io_stack_location *irp_sl; + NTSTATUS status; + + irp_sl = IoGetCurrentIrpStackLocation(irp); + WARNING("%d:%d not implemented", irp_sl->major_fn, irp_sl->minor_fn); + irp->io_status.status = STATUS_SUCCESS; + irp->io_status.info = 0; + status = irp->io_status.status; + IoCompleteRequest(irp, IO_NO_INCREMENT); + IOEXIT(return status); +} +WIN_FUNC_DECL(IoInvalidDeviceRequest,2) + +static irqreturn_t io_irq_isr(int irq, void *data ISR_PT_REGS_PARAM_DECL) +{ + struct kinterrupt *interrupt = data; + BOOLEAN ret; + +#ifdef CONFIG_DEBUG_SHIRQ + if (!interrupt->u.enabled) + EXIT1(return IRQ_NONE); +#endif + TRACE6("%p", interrupt); + nt_spin_lock(interrupt->actual_lock); + ret = LIN2WIN2(interrupt->isr, interrupt, interrupt->isr_ctx); + nt_spin_unlock(interrupt->actual_lock); + if (ret == TRUE) + EXIT6(return IRQ_HANDLED); + else + EXIT6(return IRQ_NONE); +} + +wstdcall NTSTATUS WIN_FUNC(IoConnectInterrupt,11) + (struct kinterrupt **kinterrupt, PKSERVICE_ROUTINE isr, void *isr_ctx, + NT_SPIN_LOCK *lock, ULONG vector, KIRQL irql, KIRQL synch_irql, + enum kinterrupt_mode mode, BOOLEAN shared, KAFFINITY cpu_mask, + BOOLEAN save_fp) +{ + struct kinterrupt *interrupt; + IOENTER(""); + interrupt = kzalloc(sizeof(*interrupt), GFP_KERNEL); + if (!interrupt) + IOEXIT(return STATUS_INSUFFICIENT_RESOURCES); + interrupt->vector = vector; + interrupt->cpu_mask = cpu_mask; + nt_spin_lock_init(&interrupt->lock); + if (lock) + interrupt->actual_lock = lock; + else + interrupt->actual_lock = &interrupt->lock; + interrupt->shared = shared; + interrupt->save_fp = save_fp; + interrupt->isr = isr; + interrupt->isr_ctx = isr_ctx; + InitializeListHead(&interrupt->list); + interrupt->irql = irql; + interrupt->synch_irql = synch_irql; + interrupt->mode = mode; + if (request_irq(vector, io_irq_isr, shared ? IRQF_SHARED : 0, + "ndiswrapper", interrupt)) { + WARNING("request for irq %d failed", vector); + kfree(interrupt); + IOEXIT(return STATUS_INSUFFICIENT_RESOURCES); + } + *kinterrupt = interrupt; +#ifdef CONFIG_DEBUG_SHIRQ + interrupt->u.enabled = 1; +#endif + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(IoDisconnectInterrupt,1) + (struct kinterrupt *interrupt) +{ +#ifdef CONFIG_DEBUG_SHIRQ + interrupt->u.enabled = 0; +#endif + free_irq(interrupt->vector, interrupt); + kfree(interrupt); +} + +wstdcall struct mdl *WIN_FUNC(IoAllocateMdl,5) + (void *virt, ULONG length, BOOLEAN second_buf, BOOLEAN charge_quota, + struct irp *irp) +{ + struct mdl *mdl; + mdl = allocate_init_mdl(virt, length); + if (!mdl) + return NULL; + if (irp) { + if (second_buf == TRUE) { + struct mdl *last; + + last = irp->mdl; + while (last->next) + last = last->next; + last->next = mdl; + } else + irp->mdl = mdl; + } + IOTRACE("%p", mdl); + return mdl; +} + +wstdcall void WIN_FUNC(IoFreeMdl,1) + (struct mdl *mdl) +{ + IOTRACE("%p", mdl); + free_mdl(mdl); +} + +wstdcall struct io_workitem *WIN_FUNC(IoAllocateWorkItem,1) + (struct device_object *dev_obj) +{ + struct io_workitem *io_workitem; + + IOENTER("%p", dev_obj); + io_workitem = kmalloc(sizeof(*io_workitem), irql_gfp()); + if (!io_workitem) + IOEXIT(return NULL); + io_workitem->dev_obj = dev_obj; + IOEXIT(return io_workitem); +} + +wstdcall void WIN_FUNC(IoFreeWorkItem,1) + (struct io_workitem *io_workitem) +{ + kfree(io_workitem); + IOEXIT(return); +} + +wstdcall void WIN_FUNC(IoQueueWorkItem,4) + (struct io_workitem *io_workitem, void *func, + enum work_queue_type queue_type, void *context) +{ + IOENTER("%p, %p", io_workitem, io_workitem->dev_obj); + io_workitem->worker_routine = func; + io_workitem->context = context; + schedule_ntos_work_item(func, io_workitem->dev_obj, context); + IOEXIT(return); +} + +wstdcall void WIN_FUNC(ExQueueWorkItem,2) + (struct io_workitem *io_workitem, enum work_queue_type queue_type) +{ + IOENTER("%p", io_workitem); + schedule_ntos_work_item(io_workitem->worker_routine, + io_workitem->dev_obj, io_workitem->context); +} + +wstdcall NTSTATUS WIN_FUNC(IoAllocateDriverObjectExtension,4) + (struct driver_object *drv_obj, void *client_id, ULONG extlen, + void **ext) +{ + struct custom_ext *ce; + + IOENTER("%p, %p", drv_obj, client_id); + ce = kmalloc(sizeof(*ce) + extlen, irql_gfp()); + if (ce == NULL) + return STATUS_INSUFFICIENT_RESOURCES; + + IOTRACE("custom_ext: %p", ce); + ce->client_id = client_id; + spin_lock_bh(&ntoskernel_lock); + InsertTailList(&drv_obj->drv_ext->custom_ext, &ce->list); + spin_unlock_bh(&ntoskernel_lock); + + *ext = (void *)ce + sizeof(*ce); + IOTRACE("ext: %p", *ext); + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall void *WIN_FUNC(IoGetDriverObjectExtension,2) + (struct driver_object *drv_obj, void *client_id) +{ + struct custom_ext *ce; + void *ret; + + IOENTER("drv_obj: %p, client_id: %p", drv_obj, client_id); + ret = NULL; + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(ce, &drv_obj->drv_ext->custom_ext, list) { + if (ce->client_id == client_id) { + ret = (void *)ce + sizeof(*ce); + break; + } + } + spin_unlock_bh(&ntoskernel_lock); + IOTRACE("ret: %p", ret); + return ret; +} + +void free_custom_extensions(struct driver_extension *drv_ext) +{ + struct nt_list *ent; + + IOENTER("%p", drv_ext); + spin_lock_bh(&ntoskernel_lock); + while ((ent = RemoveHeadList(&drv_ext->custom_ext))) + kfree(ent); + spin_unlock_bh(&ntoskernel_lock); + IOEXIT(return); +} + +wstdcall NTSTATUS WIN_FUNC(IoCreateDevice,7) + (struct driver_object *drv_obj, ULONG dev_ext_length, + struct unicode_string *dev_name, DEVICE_TYPE dev_type, + ULONG dev_chars, BOOLEAN exclusive, struct device_object **newdev) +{ + struct device_object *dev; + struct dev_obj_ext *dev_obj_ext; + int size; + + IOENTER("%p, %u, %p", drv_obj, dev_ext_length, dev_name); + + size = sizeof(*dev) + dev_ext_length + sizeof(*dev_obj_ext); + dev = allocate_object(size, OBJECT_TYPE_DEVICE, dev_name); + if (!dev) + IOEXIT(return STATUS_INSUFFICIENT_RESOURCES); + if (dev_ext_length) + dev->dev_ext = dev + 1; + else + dev->dev_ext = NULL; + + dev_obj_ext = ((void *)(dev + 1)) + dev_ext_length; + dev_obj_ext->dev_obj = dev; + dev_obj_ext->size = 0; + dev_obj_ext->type = IO_TYPE_DEVICE; + dev->dev_obj_ext = dev_obj_ext; + + dev->type = dev_type; + dev->flags = 0; + dev->size = sizeof(*dev) + dev_ext_length; + dev->ref_count = 1; + dev->attached = NULL; + dev->stack_count = 1; + + dev->drv_obj = drv_obj; + dev->next = drv_obj->dev_obj; + drv_obj->dev_obj = dev; + + dev->align_req = 1; + dev->characteristics = dev_chars; + dev->io_timer = NULL; + KeInitializeEvent(&dev->lock, SynchronizationEvent, TRUE); + dev->vpb = NULL; + + IOTRACE("dev: %p, ext: %p", dev, dev->dev_ext); + *newdev = dev; + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(IoCreateUnprotectedSymbolicLink,2) + (struct unicode_string *link, struct unicode_string *dev_name) +{ + struct ansi_string ansi; + + IOENTER("%p, %p", dev_name, link); + if (dev_name && (RtlUnicodeStringToAnsiString(&ansi, dev_name, TRUE) == + STATUS_SUCCESS)) { + IOTRACE("dev_name: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) == + STATUS_SUCCESS)) { + IOTRACE("link: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } +// TODO(); + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(IoCreateSymbolicLink,2) + (struct unicode_string *link, struct unicode_string *dev_name) +{ + IOEXIT(return IoCreateUnprotectedSymbolicLink(link, dev_name)); +} + +wstdcall NTSTATUS WIN_FUNC(IoDeleteSymbolicLink,1) + (struct unicode_string *link) +{ + struct ansi_string ansi; + + IOENTER("%p", link); + if (link && (RtlUnicodeStringToAnsiString(&ansi, link, TRUE) == + STATUS_SUCCESS)) { + IOTRACE("dev_name: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(IoDeleteDevice,1) + (struct device_object *dev) +{ + IOENTER("%p", dev); + if (dev == NULL) + IOEXIT(return); + IOTRACE("drv_obj: %p", dev->drv_obj); + if (dev->drv_obj) { + struct device_object *prev; + + prev = dev->drv_obj->dev_obj; + IOTRACE("dev_obj: %p", prev); + if (prev == dev) + dev->drv_obj->dev_obj = dev->next; + else if (prev) { + while (prev->next != dev) + prev = prev->next; + prev->next = dev->next; + } + } + ObDereferenceObject(dev); + IOEXIT(return); +} + +wstdcall void WIN_FUNC(IoDetachDevice,1) + (struct device_object *tgt) +{ + struct device_object *tail; + + IOENTER("%p", tgt); + if (!tgt) + IOEXIT(return); + tail = tgt->attached; + if (!tail) + IOEXIT(return); + IOTRACE("tail: %p", tail); + + spin_lock_bh(&ntoskernel_lock); + tgt->attached = tail->attached; + IOTRACE("attached:%p", tgt->attached); + for ( ; tail; tail = tail->attached) { + IOTRACE("tail:%p", tail); + tail->stack_count--; + } + spin_unlock_bh(&ntoskernel_lock); + IOEXIT(return); +} + +wstdcall struct device_object *WIN_FUNC(IoGetAttachedDevice,1) + (struct device_object *dev) +{ + IOENTER("%p", dev); + if (!dev) + IOEXIT(return NULL); + spin_lock_bh(&ntoskernel_lock); + while (dev->attached) + dev = dev->attached; + spin_unlock_bh(&ntoskernel_lock); + IOEXIT(return dev); +} + +wstdcall struct device_object *WIN_FUNC(IoGetAttachedDeviceReference,1) + (struct device_object *dev) +{ + IOENTER("%p", dev); + if (!dev) + IOEXIT(return NULL); + dev = IoGetAttachedDevice(dev); + ObReferenceObject(dev); + IOEXIT(return dev); +} + +wstdcall struct device_object *WIN_FUNC(IoAttachDeviceToDeviceStack,2) + (struct device_object *src, struct device_object *tgt) +{ + struct device_object *attached; + struct dev_obj_ext *src_dev_ext; + + IOENTER("%p, %p", src, tgt); + attached = IoGetAttachedDevice(tgt); + IOTRACE("%p", attached); + src_dev_ext = src->dev_obj_ext; + spin_lock_bh(&ntoskernel_lock); + if (attached) + attached->attached = src; + src->attached = NULL; + src->stack_count = attached->stack_count + 1; + src_dev_ext->attached_to = attached; + spin_unlock_bh(&ntoskernel_lock); + IOTRACE("stack_count: %d -> %d", attached->stack_count, + src->stack_count); + IOEXIT(return attached); +} + +wstdcall NTSTATUS WIN_FUNC(IoGetDeviceProperty,5) + (struct device_object *pdo, enum device_registry_property dev_property, + ULONG buffer_len, void *buffer, ULONG *result_len) +{ + struct ansi_string ansi; + struct unicode_string unicode; + struct wrap_device *wd; + ULONG need; + + IOENTER("dev_obj = %p, dev_property = %d, buffer_len = %u, " + "buffer = %p, result_len = %p", pdo, dev_property, + buffer_len, buffer, result_len); + + wd = pdo->reserved; + switch (dev_property) { + case DevicePropertyDeviceDescription: + case DevicePropertyFriendlyName: + case DevicePropertyDriverKeyName: + if (wrap_is_pci_bus(wd->dev_bus)) + RtlInitAnsiString(&ansi, "PCI"); + else // if (wrap_is_usb_bus(wd->dev_bus)) + RtlInitAnsiString(&ansi, "USB"); + need = sizeof(wchar_t) * (ansi.max_length + 1); + if (buffer_len < need) { + *result_len = need; + IOEXIT(return STATUS_BUFFER_TOO_SMALL); + } + unicode.max_length = buffer_len; + unicode.buf = buffer; + if (RtlAnsiStringToUnicodeString(&unicode, &ansi, + FALSE) != STATUS_SUCCESS) { + *result_len = unicode.length; + IOEXIT(return STATUS_BUFFER_TOO_SMALL); + } + IOEXIT(return STATUS_SUCCESS); + default: + WARNING("%d not implemented", dev_property); + IOEXIT(return STATUS_INVALID_PARAMETER_2); + } +} + +wstdcall NTSTATUS WIN_FUNC(IoGetDeviceObjectPointer,4) + (struct unicode_string *name, ACCESS_MASK desired_access, + void *file_obj, struct device_object *dev_obj) +{ + struct common_object_header *coh; + + dev_obj = NULL; + /* TODO: access is not checked and file_obj is set to NULL */ + file_obj = NULL; + spin_lock_bh(&ntoskernel_lock); + nt_list_for_each_entry(coh, &object_list, list) { + TRACE5("header: %p, type: %d", coh, coh->type); + if (coh->type != OBJECT_TYPE_DEVICE) + continue; + if (!RtlCompareUnicodeString(&coh->name, name, TRUE)) { + dev_obj = HEADER_TO_OBJECT(coh); + TRACE5("dev_obj: %p", dev_obj); + break; + } + } + spin_unlock_bh(&ntoskernel_lock); + if (dev_obj) + IOEXIT(return STATUS_SUCCESS); + else + IOEXIT(return STATUS_OBJECT_NAME_INVALID); +} + +/* NOTE: Make sure to compile with -freg-struct-return, so gcc will + * return union in register, like Windows */ +wstdcall union power_state WIN_FUNC(PoSetPowerState,3) + (struct device_object *dev_obj, enum power_state_type type, + union power_state state) +{ + IOEXIT(return state); +} + +wstdcall NTSTATUS WIN_FUNC(PoCallDriver,2) + (struct device_object *dev_obj, struct irp *irp) +{ + return IoCallDriver(dev_obj, irp); +} + +wstdcall NTSTATUS WIN_FUNC(PoRequestPowerIrp,6) + (struct device_object *dev_obj, UCHAR minor_fn, + union power_state power_state, void *completion_func, + void *context, struct irp **pirp) +{ + struct irp *irp; + struct io_stack_location *irp_sl; + + TRACE1("%p, %d, %p", dev_obj, dev_obj->stack_count, dev_obj->drv_obj); + irp = IoAllocateIrp(dev_obj->stack_count, FALSE); + if (!irp) + return STATUS_INSUFFICIENT_RESOURCES; + irp_sl = IoGetNextIrpStackLocation(irp); + irp_sl->major_fn = IRP_MJ_POWER; + irp_sl->minor_fn = minor_fn; + if (minor_fn == IRP_MN_WAIT_WAKE) + irp_sl->params.power.type = SystemPowerState; + else + irp_sl->params.power.type = DevicePowerState; + irp_sl->params.power.state = power_state; + irp_sl->completion_routine = completion_func; + irp->io_status.status = STATUS_NOT_SUPPORTED; + *pirp = irp; + return PoCallDriver(dev_obj, irp); +} + +wstdcall void WIN_FUNC(PoStartNextPowerIrp,1) + (struct irp *irp) +{ + IOENTER("irp = %p", irp); + IOEXIT(return); +} + +wstdcall void WIN_FUNC(IoInitializeRemoveLockEx,5) + (struct io_remove_lock *lock, ULONG alloc_tag, ULONG max_locked_min, + ULONG high_mark, ULONG lock_size) +{ + TODO(); +} + +wstdcall void *WIN_FUNC(IoAllocateErrorLogEntry,2) + (void *io_object, UCHAR entry_size) +{ + /* not implemented fully */ + void *ret = kmalloc(sizeof(struct io_error_log_packet) + entry_size, + irql_gfp()); + TRACE2("%p", ret); + if (ret) + return ret + sizeof(struct io_error_log_packet); + else + return NULL; +} + +wstdcall void WIN_FUNC(IoWriteErrorLogEntry,1) + (void *entry) +{ + /* TODO: log error with codes and message */ + ERROR(""); +} + +wstdcall void WIN_FUNC(IoFreeErrorLogEntry,1) + (void *entry) +{ + TRACE2("%p", entry); + kfree(entry - sizeof(struct io_error_log_packet)); +} + +wstdcall NTSTATUS WIN_FUNC(IoAcquireRemoveLockEx,5) + (struct io_remove_lock lock, void *tag, char *file, ULONG line, + ULONG lock_size) +{ + TODO(); + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(IoReleaseRemoveLockEx,3) + (struct io_remove_lock lock, void *tag, ULONG lock_size) +{ + TODO(); + IOEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(IoRegisterDeviceInterface,4) + (struct device_object *pdo, struct guid *guid_class, + struct unicode_string *reference, struct unicode_string *link) +{ + struct ansi_string ansi; + + /* TODO: check if pdo is valid */ + RtlInitAnsiString(&ansi, "ndis"); + ENTER1("pdo: %p, ref: %p, link: %p, %x, %x, %x", pdo, reference, link, + guid_class->data1, guid_class->data2, guid_class->data3); + return RtlAnsiStringToUnicodeString(link, &ansi, TRUE); +} + +wstdcall NTSTATUS WIN_FUNC(IoSetDeviceInterfaceState,2) + (struct unicode_string *link, BOOLEAN enable) +{ + ENTER1("link: %p, enable: %d", link, enable); + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(IoOpenDeviceRegistryKey,4) + (struct device_object *dev_obj, ULONG type, ACCESS_MASK mask, + void **handle) +{ + ENTER1("dev_obj: %p", dev_obj); + *handle = dev_obj; + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(IoWMIRegistrationControl,2) + (struct device_object *dev_obj, ULONG action) +{ + ENTER2("%p, %d", dev_obj, action); + EXIT2(return STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(IoInvalidateDeviceRelations,2) + (struct device_object *dev_obj, enum device_relation_type type) +{ + INFO("%p, %d", dev_obj, type); + TODO(); +} + +wstdcall void WIN_FUNC(IoInvalidateDeviceState,1) + (struct device_object *pdo) +{ + INFO("%p", pdo); + TODO(); +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/pe_linker.c +++ linux-2.6.37/ubuntu/ndiswrapper/pe_linker.c @@ -0,0 +1,599 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ + +#ifdef TEST_LOADER + +#include "usr_linker.h" + +#else + +#include +#include + +//#define DEBUGLINKER 2 + +#include "ntoskernel.h" + +#endif + +struct pe_exports { + char *dll; + char *name; + generic_func addr; +}; + +static struct pe_exports pe_exports[40]; +static int num_pe_exports; + +#define RVA2VA(image, rva, type) (type)(ULONG_PTR)((void *)image + rva) +#define CHECK_SZ(a,b) { if (sizeof(a) != b) { \ + ERROR("%s is bad, got %zd, expected %d", \ + #a , sizeof(a), (b)); return -EINVAL; } } + +#if defined(DEBUGLINKER) && DEBUGLINKER > 0 +#define DBGLINKER(fmt, ...) printk(KERN_INFO "%s (%s:%d): " fmt "\n", \ + DRIVER_NAME, __func__, \ + __LINE__ , ## __VA_ARGS__); +static const char *image_directory_name[] = { + "EXPORT", + "IMPORT", + "RESOURCE", + "EXCEPTION", + "SECURITY", + "BASERELOC", + "DEBUG", + "COPYRIGHT", + "GLOBALPTR", + "TLS", + "LOAD_CONFIG", + "BOUND_IMPORT", + "IAT", + "DELAY_IMPORT", + "COM_DESCRIPTOR" }; +#else +#define DBGLINKER(fmt, ...) do { } while (0) +#endif + +#ifndef TEST_LOADER +extern struct wrap_export ntoskernel_exports[], ntoskernel_io_exports[], + ndis_exports[], crt_exports[], hal_exports[], rtl_exports[]; +#ifdef ENABLE_USB +extern struct wrap_export usb_exports[]; +#endif + +static int get_export(char *name, generic_func *func) +{ + int i, j; + + struct wrap_export *exports[] = { + ntoskernel_exports, + ntoskernel_io_exports, + ndis_exports, + crt_exports, + hal_exports, + rtl_exports, +#ifdef ENABLE_USB + usb_exports, +#endif + }; + + for (j = 0; j < ARRAY_SIZE(exports); j++) + for (i = 0; exports[j][i].name != NULL; i++) + if (strcmp(exports[j][i].name, name) == 0) { + *func = exports[j][i].func; + return 0; + } + + for (i = 0; i < num_pe_exports; i++) + if (strcmp(pe_exports[i].name, name) == 0) { + *func = pe_exports[i].addr; + return 0; + } + + return -1; +} +#endif // TEST_LOADER + +static void *get_dll_init(char *name) +{ + int i; + for (i = 0; i < num_pe_exports; i++) + if ((strcmp(pe_exports[i].dll, name) == 0) && + (strcmp(pe_exports[i].name, "DllInitialize") == 0)) + return (void *)pe_exports[i].addr; + return NULL; +} + +/* + * Find and validate the coff header + * + */ +static int check_nt_hdr(IMAGE_NT_HEADERS *nt_hdr) +{ + int i; + WORD attr; + PIMAGE_OPTIONAL_HEADER opt_hdr; + + /* Validate the "PE\0\0" signature */ + if (nt_hdr->Signature != IMAGE_NT_SIGNATURE) { + ERROR("is this driver file? bad signature %08x", + nt_hdr->Signature); + return -EINVAL; + } + + opt_hdr = &nt_hdr->OptionalHeader; + /* Make sure Image is PE32 or PE32+ */ +#ifdef CONFIG_X86_64 + if (opt_hdr->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + ERROR("kernel is 64-bit, but Windows driver is not 64-bit;" + "bad magic: %04X", opt_hdr->Magic); + return -EINVAL; + } +#else + if (opt_hdr->Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ERROR("kernel is 32-bit, but Windows driver is not 32-bit;" + "bad magic: %04X", opt_hdr->Magic); + return -EINVAL; + } +#endif + + /* Validate the image for the current architecture. */ +#ifdef CONFIG_X86_64 + if (nt_hdr->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) { + ERROR("kernel is 64-bit, but Windows driver is not 64-bit;" + " (PE signature is %04X)", nt_hdr->FileHeader.Machine); + return -EINVAL; + } +#else + if (nt_hdr->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) { + ERROR("kernel is 32-bit, but Windows driver is not 32-bit;" + " (PE signature is %04X)", nt_hdr->FileHeader.Machine); + return -EINVAL; + } +#endif + + /* Must have attributes */ +#ifdef CONFIG_X86_64 + attr = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE; +#else + attr = IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_32BIT_MACHINE; +#endif + if ((nt_hdr->FileHeader.Characteristics & attr) != attr) + return -EINVAL; + + /* Must be relocatable */ + attr = IMAGE_FILE_RELOCS_STRIPPED; + if ((nt_hdr->FileHeader.Characteristics & attr)) + return -EINVAL; + + /* Make sure we have at least one section */ + if (nt_hdr->FileHeader.NumberOfSections == 0) + return -EINVAL; + + if (opt_hdr->SectionAlignment < opt_hdr->FileAlignment) { + ERROR("alignment mismatch: secion: 0x%x, file: 0x%x", + opt_hdr->SectionAlignment, opt_hdr->FileAlignment); + return -EINVAL; + } + + DBGLINKER("number of datadictionary entries %d", + opt_hdr->NumberOfRvaAndSizes); + for (i = 0; i < opt_hdr->NumberOfRvaAndSizes; i++) { + DBGLINKER("datadirectory %s RVA:%X Size:%d", + (i<=IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR)? + image_directory_name[i] : "unknown", + opt_hdr->DataDirectory[i].VirtualAddress, + opt_hdr->DataDirectory[i].Size); + } + + if ((nt_hdr->FileHeader.Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) + return IMAGE_FILE_EXECUTABLE_IMAGE; + if ((nt_hdr->FileHeader.Characteristics & IMAGE_FILE_DLL)) + return IMAGE_FILE_DLL; + return -EINVAL; +} + +static int import(void *image, IMAGE_IMPORT_DESCRIPTOR *dirent, char *dll) +{ + ULONG_PTR *lookup_tbl, *address_tbl; + char *symname = NULL; + int i; + int ret = 0; + generic_func adr; + + lookup_tbl = RVA2VA(image, dirent->u.OriginalFirstThunk, ULONG_PTR *); + address_tbl = RVA2VA(image, dirent->FirstThunk, ULONG_PTR *); + + for (i = 0; lookup_tbl[i]; i++) { + if (IMAGE_SNAP_BY_ORDINAL(lookup_tbl[i])) { + ERROR("ordinal import not supported: %Lu", + (uint64_t)lookup_tbl[i]); + return -1; + } + else { + symname = RVA2VA(image, + ((lookup_tbl[i] & + ~IMAGE_ORDINAL_FLAG) + 2), char *); + } + + ret = get_export(symname, &adr); + if (ret < 0) { + ERROR("unknown symbol: %s:'%s'", dll, symname); + } else { + DBGLINKER("found symbol: %s:%s: addr: %p, rva = %Lu", + dll, symname, adr, (uint64_t)address_tbl[i]); + address_tbl[i] = (ULONG_PTR)adr; + } + } + return ret; +} + +static int read_exports(struct pe_image *pe) +{ + IMAGE_EXPORT_DIRECTORY *export_dir_table; + uint32_t *export_addr_table; + int i; + uint32_t *name_table; + PIMAGE_OPTIONAL_HEADER opt_hdr; + IMAGE_DATA_DIRECTORY *export_data_dir; + + opt_hdr = &pe->nt_hdr->OptionalHeader; + export_data_dir = + &opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + + if (export_data_dir->Size == 0) { + DBGLINKER("no exports"); + return 0; + } + + export_dir_table = + RVA2VA(pe->image, export_data_dir->VirtualAddress, + IMAGE_EXPORT_DIRECTORY *); + + name_table = (unsigned int *)(pe->image + + export_dir_table->AddressOfNames); + export_addr_table = (uint32_t *) + (pe->image + export_dir_table->AddressOfFunctions); + + for (i = 0; i < export_dir_table->NumberOfNames; i++) { + + if (export_data_dir->VirtualAddress <= *export_addr_table || + *export_addr_table >= (export_data_dir->VirtualAddress + + export_data_dir->Size)) + DBGLINKER("forwarder rva"); + + DBGLINKER("export symbol: %s, at %p", + (char *)(pe->image + *name_table), + pe->image + *export_addr_table); + + pe_exports[num_pe_exports].dll = pe->name; + pe_exports[num_pe_exports].name = pe->image + *name_table; + pe_exports[num_pe_exports].addr = + pe->image + *export_addr_table; + + num_pe_exports++; + name_table++; + export_addr_table++; + } + return 0; +} + +static int fixup_imports(void *image, IMAGE_NT_HEADERS *nt_hdr) +{ + int i; + char *name; + int ret = 0; + IMAGE_IMPORT_DESCRIPTOR *dirent; + IMAGE_DATA_DIRECTORY *import_data_dir; + PIMAGE_OPTIONAL_HEADER opt_hdr; + + opt_hdr = &nt_hdr->OptionalHeader; + import_data_dir = + &opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; + dirent = RVA2VA(image, import_data_dir->VirtualAddress, + IMAGE_IMPORT_DESCRIPTOR *); + + for (i = 0; dirent[i].Name; i++) { + name = RVA2VA(image, dirent[i].Name, char*); + + DBGLINKER("imports from dll: %s", name); + ret += import(image, &dirent[i], name); + } + return ret; +} + +static int fixup_reloc(void *image, IMAGE_NT_HEADERS *nt_hdr) +{ + ULONG_PTR base; + ULONG_PTR size; + IMAGE_BASE_RELOCATION *fixup_block; + IMAGE_DATA_DIRECTORY *base_reloc_data_dir; + PIMAGE_OPTIONAL_HEADER opt_hdr; + + opt_hdr = &nt_hdr->OptionalHeader; + base = opt_hdr->ImageBase; + base_reloc_data_dir = + &opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; + if (base_reloc_data_dir->Size == 0) + return 0; + + fixup_block = RVA2VA(image, base_reloc_data_dir->VirtualAddress, + IMAGE_BASE_RELOCATION *); + DBGLINKER("fixup_block=%p, image=%p", fixup_block, image); + DBGLINKER("fixup_block info: %x %d", + fixup_block->VirtualAddress, fixup_block->SizeOfBlock); + + while (fixup_block->SizeOfBlock) { + int i; + WORD fixup, offset; + + size = (fixup_block->SizeOfBlock - + sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD); + DBGLINKER("found %Lu relocations in this block", + (uint64_t)size); + + for (i = 0; i < size; i++) { + fixup = fixup_block->TypeOffset[i]; + offset = fixup & 0xfff; + switch ((fixup >> 12) & 0x0f) { + case IMAGE_REL_BASED_ABSOLUTE: + break; + + case IMAGE_REL_BASED_HIGHLOW: { + uint32_t addr; + uint32_t *loc = + RVA2VA(image, + fixup_block->VirtualAddress + + offset, uint32_t *); + addr = RVA2VA(image, (*loc - base), uint32_t); + DBGLINKER("relocation: *%p (Val:%X)= %X", + loc, *loc, addr); + *loc = addr; + } + break; + + case IMAGE_REL_BASED_DIR64: { + uint64_t addr; + uint64_t *loc = + RVA2VA(image, + fixup_block->VirtualAddress + + offset, uint64_t *); + addr = RVA2VA(image, (*loc - base), uint64_t); + DBGLINKER("relocation: *%p (Val:%llX)= %llx", + loc, *loc, addr); + *loc = addr; + } + break; + + default: + ERROR("unknown fixup: %08X", + (fixup >> 12) & 0x0f); + return -EOPNOTSUPP; + break; + } + } + DBGLINKER("finished relocating block"); + + fixup_block = (IMAGE_BASE_RELOCATION *) + ((void *)fixup_block + fixup_block->SizeOfBlock); + }; + DBGLINKER("done relocating all"); + + return 0; +} + +/* Expand the image in memroy if necessary. The image on disk does not + * necessarily maps the image of the driver in memory, so we have to + * re-write it in order to fullfill the sections alignements. The + * advantage to do that is that rva_to_va becomes a simple + * addition. */ +static int fix_pe_image(struct pe_image *pe) +{ + void *image; + IMAGE_SECTION_HEADER *sect_hdr; + int i, sections; + int image_size; + + if (pe->size == pe->opt_hdr->SizeOfImage) { + /* Nothing to do */ + return 0; + } + + image_size = pe->opt_hdr->SizeOfImage; +#ifdef CONFIG_X86_64 +#ifdef PAGE_KERNEL_EXECUTABLE + image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM, + PAGE_KERNEL_EXECUTABLE); +#elif defined PAGE_KERNEL_EXEC + image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM, + PAGE_KERNEL_EXEC); +#else +#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC +#endif +#else +#ifdef cpu_has_nx + /* hate to play with kernel macros, but PAGE_KERNEL_EXEC is + * not available to modules! */ + if (cpu_has_nx) + image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM, + __pgprot(__PAGE_KERNEL & ~_PAGE_NX)); + else + image = vmalloc(image_size); +#else + image = vmalloc(image_size); +#endif +#endif + if (image == NULL) { + ERROR("failed to allocate enough space for new image:" + " %d bytes", image_size); + return -ENOMEM; + } + + /* Copy all the headers, ie everything before the first section. */ + + sections = pe->nt_hdr->FileHeader.NumberOfSections; + sect_hdr = IMAGE_FIRST_SECTION(pe->nt_hdr); + + DBGLINKER("copying headers: %u bytes", sect_hdr->PointerToRawData); + + memcpy(image, pe->image, sect_hdr->PointerToRawData); + + /* Copy all the sections */ + for (i = 0; i < sections; i++) { + DBGLINKER("Copy section %s from %x to %x", + sect_hdr->Name, sect_hdr->PointerToRawData, + sect_hdr->VirtualAddress); + if (sect_hdr->VirtualAddress+sect_hdr->SizeOfRawData > + image_size) { + ERROR("Invalid section %s in driver", sect_hdr->Name); + vfree(image); + return -EINVAL; + } + + memcpy(image+sect_hdr->VirtualAddress, + pe->image + sect_hdr->PointerToRawData, + sect_hdr->SizeOfRawData); + sect_hdr++; + } + + vfree(pe->image); + pe->image = image; + pe->size = image_size; + + /* Update our internal pointers */ + pe->nt_hdr = (IMAGE_NT_HEADERS *) + (pe->image + ((IMAGE_DOS_HEADER *)pe->image)->e_lfanew); + pe->opt_hdr = &pe->nt_hdr->OptionalHeader; + + DBGLINKER("set nt headers: nt_hdr=%p, opt_hdr=%p, image=%p", + pe->nt_hdr, pe->opt_hdr, pe->image); + + return 0; +} + +#if defined(CONFIG_X86_64) +static void fix_user_shared_data_addr(char *driver, unsigned long length) +{ + unsigned long i, n, max_addr, *addr; + + n = length - sizeof(unsigned long); + max_addr = KI_USER_SHARED_DATA + sizeof(kuser_shared_data); + for (i = 0; i < n; i++) { + addr = (unsigned long *)(driver + i); + if (*addr >= KI_USER_SHARED_DATA && *addr < max_addr) { + *addr -= KI_USER_SHARED_DATA; + *addr += (unsigned long)&kuser_shared_data; + kuser_shared_data.reserved1 = 1; + } + } +} +#endif + +int link_pe_images(struct pe_image *pe_image, unsigned short n) +{ + int i; + struct pe_image *pe; + +#ifdef DEBUG + /* Sanity checkings */ + CHECK_SZ(IMAGE_SECTION_HEADER, IMAGE_SIZEOF_SECTION_HEADER); + CHECK_SZ(IMAGE_FILE_HEADER, IMAGE_SIZEOF_FILE_HEADER); + CHECK_SZ(IMAGE_OPTIONAL_HEADER, IMAGE_SIZEOF_NT_OPTIONAL_HEADER); + CHECK_SZ(IMAGE_NT_HEADERS, 4 + IMAGE_SIZEOF_FILE_HEADER + + IMAGE_SIZEOF_NT_OPTIONAL_HEADER); + CHECK_SZ(IMAGE_DOS_HEADER, 0x40); + CHECK_SZ(IMAGE_EXPORT_DIRECTORY, 40); + CHECK_SZ(IMAGE_BASE_RELOCATION, 8); + CHECK_SZ(IMAGE_IMPORT_DESCRIPTOR, 20); +#endif + + for (i = 0; i < n; i++) { + IMAGE_DOS_HEADER *dos_hdr; + pe = &pe_image[i]; + dos_hdr = pe->image; + + if (pe->size < sizeof(IMAGE_DOS_HEADER)) { + TRACE1("image too small: %d", pe->size); + return -EINVAL; + } + + pe->nt_hdr = + (IMAGE_NT_HEADERS *)(pe->image + dos_hdr->e_lfanew); + pe->opt_hdr = &pe->nt_hdr->OptionalHeader; + + pe->type = check_nt_hdr(pe->nt_hdr); + if (pe->type <= 0) { + TRACE1("type <= 0"); + return -EINVAL; + } + + if (fix_pe_image(pe)) { + TRACE1("bad PE image"); + return -EINVAL; + } + + if (read_exports(pe)) { + TRACE1("read exports failed"); + return -EINVAL; + } + } + + for (i = 0; i < n; i++) { + pe = &pe_image[i]; + + if (fixup_reloc(pe->image, pe->nt_hdr)) { + TRACE1("fixup reloc failed"); + return -EINVAL; + } + if (fixup_imports(pe->image, pe->nt_hdr)) { + TRACE1("fixup imports failed"); + return -EINVAL; + } +#if defined(CONFIG_X86_64) + INFO("fixing KI_USER_SHARED_DATA address in the driver"); + fix_user_shared_data_addr(pe_image[i].image, pe_image[i].size); +#endif + flush_icache_range(pe->image, pe->size); + + pe->entry = + RVA2VA(pe->image, + pe->opt_hdr->AddressOfEntryPoint, void *); + TRACE1("entry is at %p, rva at %08X", pe->entry, + pe->opt_hdr->AddressOfEntryPoint); + } + + for (i = 0; i < n; i++) { + pe = &pe_image[i]; + + if (pe->type == IMAGE_FILE_DLL) { + struct unicode_string ustring; + char *buf = "0/0t0m0p00"; + int (*dll_entry)(struct unicode_string *ustring) + wstdcall; + + memset(&ustring, 0, sizeof(ustring)); + ustring.buf = (wchar_t *)buf; + dll_entry = (void *)get_dll_init(pe->name); + + TRACE1("calling dll_init at %p", dll_entry); + if (!dll_entry || dll_entry(&ustring)) + ERROR("DLL initialize failed for %s", + pe->name); + } + else if (pe->type != IMAGE_FILE_EXECUTABLE_IMAGE) + ERROR("illegal image type: %d", pe->type); + } + return 0; +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/pe_linker.h +++ linux-2.6.37/ubuntu/ndiswrapper/pe_linker.h @@ -0,0 +1,993 @@ +/* + * This file is an excerpt of winnt.h from WINE, which bears the + * following copyright: + * + * Win32 definitions for Windows NT + * + * Copyright 1996 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * File formats definitions + */ +typedef struct _IMAGE_DOS_HEADER { + WORD e_magic; /* 00: MZ Header signature */ + WORD e_cblp; /* 02: Bytes on last page of file */ + WORD e_cp; /* 04: Pages in file */ + WORD e_crlc; /* 06: Relocations */ + WORD e_cparhdr; /* 08: Size of header in paragraphs */ + WORD e_minalloc; /* 0a: Minimum extra paragraphs needed */ + WORD e_maxalloc; /* 0c: Maximum extra paragraphs needed */ + WORD e_ss; /* 0e: Initial (relative) SS value */ + WORD e_sp; /* 10: Initial SP value */ + WORD e_csum; /* 12: Checksum */ + WORD e_ip; /* 14: Initial IP value */ + WORD e_cs; /* 16: Initial (relative) CS value */ + WORD e_lfarlc; /* 18: File address of relocation table */ + WORD e_ovno; /* 1a: Overlay number */ + WORD e_res[4]; /* 1c: Reserved words */ + WORD e_oemid; /* 24: OEM identifier (for e_oeminfo) */ + WORD e_oeminfo; /* 26: OEM information; e_oemid specific */ + WORD e_res2[10]; /* 28: Reserved words */ + DWORD e_lfanew; /* 3c: Offset to extended header */ +} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */ +#define IMAGE_OS2_SIGNATURE 0x454E /* NE */ +#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */ +#define IMAGE_OS2_SIGNATURE_LX 0x584C /* LX */ +#define IMAGE_VXD_SIGNATURE 0x454C /* LE */ +#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */ + +/* + * This is the Windows executable (NE) header. + * the name IMAGE_OS2_HEADER is misleading, but in the SDK this way. + */ +typedef struct +{ + WORD ne_magic; /* 00 NE signature 'NE' */ + BYTE ne_ver; /* 02 Linker version number */ + BYTE ne_rev; /* 03 Linker revision number */ + WORD ne_enttab; /* 04 Offset to entry table relative to NE */ + WORD ne_cbenttab; /* 06 Length of entry table in bytes */ + LONG ne_crc; /* 08 Checksum */ + WORD ne_flags; /* 0c Flags about segments in this file */ + WORD ne_autodata; /* 0e Automatic data segment number */ + WORD ne_heap; /* 10 Initial size of local heap */ + WORD ne_stack; /* 12 Initial size of stack */ + DWORD ne_csip; /* 14 Initial CS:IP */ + DWORD ne_sssp; /* 18 Initial SS:SP */ + WORD ne_cseg; /* 1c # of entries in segment table */ + WORD ne_cmod; /* 1e # of entries in module reference tab. */ + WORD ne_cbnrestab; /* 20 Length of nonresident-name table */ + WORD ne_segtab; /* 22 Offset to segment table */ + WORD ne_rsrctab; /* 24 Offset to resource table */ + WORD ne_restab; /* 26 Offset to resident-name table */ + WORD ne_modtab; /* 28 Offset to module reference table */ + WORD ne_imptab; /* 2a Offset to imported name table */ + DWORD ne_nrestab; /* 2c Offset to nonresident-name table */ + WORD ne_cmovent; /* 30 # of movable entry points */ + WORD ne_align; /* 32 Logical sector alignment shift count */ + WORD ne_cres; /* 34 # of resource segments */ + BYTE ne_exetyp; /* 36 Flags indicating target OS */ + BYTE ne_flagsothers; /* 37 Additional information flags */ + WORD ne_pretthunks; /* 38 Offset to return thunks */ + WORD ne_psegrefbytes; /* 3a Offset to segment ref. bytes */ + WORD ne_swaparea; /* 3c Reserved by Microsoft */ + WORD ne_expver; /* 3e Expected Windows version number */ +} IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +typedef struct _IMAGE_VXD_HEADER { + WORD e32_magic; + BYTE e32_border; + BYTE e32_worder; + DWORD e32_level; + WORD e32_cpu; + WORD e32_os; + DWORD e32_ver; + DWORD e32_mflags; + DWORD e32_mpages; + DWORD e32_startobj; + DWORD e32_eip; + DWORD e32_stackobj; + DWORD e32_esp; + DWORD e32_pagesize; + DWORD e32_lastpagesize; + DWORD e32_fixupsize; + DWORD e32_fixupsum; + DWORD e32_ldrsize; + DWORD e32_ldrsum; + DWORD e32_objtab; + DWORD e32_objcnt; + DWORD e32_objmap; + DWORD e32_itermap; + DWORD e32_rsrctab; + DWORD e32_rsrccnt; + DWORD e32_restab; + DWORD e32_enttab; + DWORD e32_dirtab; + DWORD e32_dircnt; + DWORD e32_fpagetab; + DWORD e32_frectab; + DWORD e32_impmod; + DWORD e32_impmodcnt; + DWORD e32_impproc; + DWORD e32_pagesum; + DWORD e32_datapage; + DWORD e32_preload; + DWORD e32_nrestab; + DWORD e32_cbnrestab; + DWORD e32_nressum; + DWORD e32_autodata; + DWORD e32_debuginfo; + DWORD e32_debuglen; + DWORD e32_instpreload; + DWORD e32_instdemand; + DWORD e32_heapsize; + BYTE e32_res3[12]; + DWORD e32_winresoff; + DWORD e32_winreslen; + WORD e32_devid; + WORD e32_ddkver; +} IMAGE_VXD_HEADER, *PIMAGE_VXD_HEADER; + +/* These defines describe the meanings of the bits in the + Characteristics field */ + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 /* No relocation info */ +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 +#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 +#define IMAGE_FILE_16BIT_MACHINE 0x0040 +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 +#define IMAGE_FILE_32BIT_MACHINE 0x0100 +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 +#define IMAGE_FILE_SYSTEM 0x1000 +#define IMAGE_FILE_DLL 0x2000 +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 + +/* These are the settings of the Machine field. */ +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I860 0x014d +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_R3000 0x0162 +#define IMAGE_FILE_MACHINE_R4000 0x0166 +#define IMAGE_FILE_MACHINE_R10000 0x0168 +#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 +#define IMAGE_FILE_MACHINE_ALPHA 0x0184 +#define IMAGE_FILE_MACHINE_SH3 0x01a2 +#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 +#define IMAGE_FILE_MACHINE_SH3E 0x01a4 +#define IMAGE_FILE_MACHINE_SH4 0x01a6 +#define IMAGE_FILE_MACHINE_SH5 0x01a8 +#define IMAGE_FILE_MACHINE_ARM 0x01c0 +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 +#define IMAGE_FILE_MACHINE_AM33 0x01d3 +#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 +#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 +#define IMAGE_FILE_MACHINE_IA64 0x0200 +#define IMAGE_FILE_MACHINE_MIPS16 0x0266 +#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 +#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 +#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 +#define IMAGE_FILE_MACHINE_TRICORE 0x0520 +#define IMAGE_FILE_MACHINE_CEF 0x0cef +#define IMAGE_FILE_MACHINE_EBC 0x0ebc +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_M32R 0x9041 +#define IMAGE_FILE_MACHINE_CEE 0xc0ee + +#define IMAGE_SIZEOF_FILE_HEADER 20 +#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 +#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER32 224 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER64 240 +#define IMAGE_SIZEOF_SHORT_NAME 8 +#define IMAGE_SIZEOF_SECTION_HEADER 40 +#define IMAGE_SIZEOF_SYMBOL 18 +#define IMAGE_SIZEOF_AUX_SYMBOL 18 +#define IMAGE_SIZEOF_RELOCATION 10 +#define IMAGE_SIZEOF_BASE_RELOCATION 8 +#define IMAGE_SIZEOF_LINENUMBER 6 +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +/* Possible Magic values */ +#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x010b +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x020b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x0107 + +#ifdef CONFIG_X86_64 +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL_HEADER64 +#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC +#else +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL_HEADER32 +#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC +#endif + +/* These are indexes into the DataDirectory array */ +#define IMAGE_FILE_EXPORT_DIRECTORY 0 +#define IMAGE_FILE_IMPORT_DIRECTORY 1 +#define IMAGE_FILE_RESOURCE_DIRECTORY 2 +#define IMAGE_FILE_EXCEPTION_DIRECTORY 3 +#define IMAGE_FILE_SECURITY_DIRECTORY 4 +#define IMAGE_FILE_BASE_RELOCATION_TABLE 5 +#define IMAGE_FILE_DEBUG_DIRECTORY 6 +#define IMAGE_FILE_DESCRIPTION_STRING 7 +#define IMAGE_FILE_MACHINE_VALUE 8 /* Mips */ +#define IMAGE_FILE_THREAD_LOCAL_STORAGE 9 +#define IMAGE_FILE_CALLBACK_DIRECTORY 10 + +/* Directory Entries, indices into the DataDirectory array */ + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 +#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* (MIPS GP) */ +#define IMAGE_DIRECTORY_ENTRY_TLS 9 +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 +#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */ +#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 +#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 + +/* Subsystem Values */ + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 +#define IMAGE_SUBSYSTEM_NATIVE 1 +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 /* Windows GUI subsystem */ +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 /* Windows character subsystem */ +#define IMAGE_SUBSYSTEM_OS2_CUI 5 +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 +#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 /* native Win9x driver */ +#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 /* Windows CE subsystem */ +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#define IMAGE_SUBSYSTEM_EFI_ROM 13 +#define IMAGE_SUBSYSTEM_XBOX 14 + +typedef struct _IMAGE_FILE_HEADER { + WORD Machine; + WORD NumberOfSections; + DWORD TimeDateStamp; + DWORD PointerToSymbolTable; + DWORD NumberOfSymbols; + WORD SizeOfOptionalHeader; + WORD Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +typedef struct _IMAGE_DATA_DIRECTORY { + DWORD VirtualAddress; + DWORD Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +typedef struct _IMAGE_OPTIONAL_HEADER32 { + + /* Standard fields */ + + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + DWORD BaseOfData; + + /* NT additional fields */ + DWORD ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + DWORD SizeOfStackReserve; + DWORD SizeOfStackCommit; + DWORD SizeOfHeapReserve; + DWORD SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; + +typedef struct _IMAGE_OPTIONAL_HEADER64 { + + /* Standard fields */ + + WORD Magic; + BYTE MajorLinkerVersion; + BYTE MinorLinkerVersion; + DWORD SizeOfCode; + DWORD SizeOfInitializedData; + DWORD SizeOfUninitializedData; + DWORD AddressOfEntryPoint; + DWORD BaseOfCode; + + /* NT additional fields */ + ULONGLONG ImageBase; + DWORD SectionAlignment; + DWORD FileAlignment; + WORD MajorOperatingSystemVersion; + WORD MinorOperatingSystemVersion; + WORD MajorImageVersion; + WORD MinorImageVersion; + WORD MajorSubsystemVersion; + WORD MinorSubsystemVersion; + DWORD Win32VersionValue; + DWORD SizeOfImage; + DWORD SizeOfHeaders; + DWORD CheckSum; + WORD Subsystem; + WORD DllCharacteristics; + ULONGLONG SizeOfStackReserve; + ULONGLONG SizeOfStackCommit; + ULONGLONG SizeOfHeapReserve; + ULONGLONG SizeOfHeapCommit; + DWORD LoaderFlags; + DWORD NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; + +#ifdef CONFIG_X86_64 +typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER; +typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER; +#else +typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER; +typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER; +#endif + +typedef struct _IMAGE_NT_HEADERS32 { + DWORD Signature; /* "PE"\0\0 */ /* 0x00 */ + IMAGE_FILE_HEADER FileHeader; /* 0x04 */ + IMAGE_OPTIONAL_HEADER32 OptionalHeader; /* 0x18 */ +} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; + +typedef struct _IMAGE_NT_HEADERS64 { + DWORD Signature; /* "PE"\0\0 */ /* 0x00 */ + IMAGE_FILE_HEADER FileHeader; /* 0x04 */ + IMAGE_OPTIONAL_HEADER64 OptionalHeader; /* 0x18 */ +} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; + +#ifdef CONFIG_X86_64 +typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS; +typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS; +#else +typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS; +typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS; +#endif + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + DWORD PhysicalAddress; + DWORD VirtualSize; + } Misc; + DWORD VirtualAddress; + DWORD SizeOfRawData; + DWORD PointerToRawData; + DWORD PointerToRelocations; + DWORD PointerToLinenumbers; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +#define IMAGE_FIRST_SECTION(ntheader) \ +((PIMAGE_SECTION_HEADER)((LPBYTE)&((PIMAGE_NT_HEADERS)(ntheader))->OptionalHeader + \ +((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader)) + +/* These defines are for the Characteristics bitfield. */ +/* #define IMAGE_SCN_TYPE_REG 0x00000000 - Reserved */ +/* #define IMAGE_SCN_TYPE_DSECT 0x00000001 - Reserved */ +/* #define IMAGE_SCN_TYPE_NOLOAD 0x00000002 - Reserved */ +/* #define IMAGE_SCN_TYPE_GROUP 0x00000004 - Reserved */ +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved */ +/* #define IMAGE_SCN_TYPE_COPY 0x00000010 - Reserved */ + +#define IMAGE_SCN_CNT_CODE 0x00000020 +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 + +#define IMAGE_SCN_LNK_OTHER 0x00000100 +#define IMAGE_SCN_LNK_INFO 0x00000200 +/* #define IMAGE_SCN_TYPE_OVER 0x00000400 - Reserved */ +#define IMAGE_SCN_LNK_REMOVE 0x00000800 +#define IMAGE_SCN_LNK_COMDAT 0x00001000 + +/* 0x00002000 - Reserved */ +/* #define IMAGE_SCN_MEM_PROTECTED 0x00004000 - Obsolete */ +#define IMAGE_SCN_MEM_FARDATA 0x00008000 + +/* #define IMAGE_SCN_MEM_SYSHEAP 0x00010000 - Obsolete */ +#define IMAGE_SCN_MEM_PURGEABLE 0x00020000 +#define IMAGE_SCN_MEM_16BIT 0x00020000 +#define IMAGE_SCN_MEM_LOCKED 0x00040000 +#define IMAGE_SCN_MEM_PRELOAD 0x00080000 + +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default */ +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 +#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 +#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 +#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 +#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 +#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 +#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 +#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 +/* 0x00F00000 - Unused */ +#define IMAGE_SCN_ALIGN_MASK 0x00F00000 + +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 + + +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 +#define IMAGE_SCN_MEM_SHARED 0x10000000 +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define IMAGE_SCN_MEM_READ 0x40000000 +#define IMAGE_SCN_MEM_WRITE 0x80000000 + +typedef struct _IMAGE_SYMBOL { + union { + BYTE ShortName[8]; + struct { + DWORD Short; + DWORD Long; + } Name; + DWORD LongName[2]; + } N; + DWORD Value; + SHORT SectionNumber; + WORD Type; + BYTE StorageClass; + BYTE NumberOfAuxSymbols; +} IMAGE_SYMBOL; +typedef IMAGE_SYMBOL *PIMAGE_SYMBOL; + +#define IMAGE_SIZEOF_SYMBOL 18 + +typedef struct _IMAGE_LINENUMBER { + union { + DWORD SymbolTableIndex; + DWORD VirtualAddress; + } Type; + WORD Linenumber; +} IMAGE_LINENUMBER; +typedef IMAGE_LINENUMBER *PIMAGE_LINENUMBER; + +#define IMAGE_SIZEOF_LINENUMBER 6 + +typedef union _IMAGE_AUX_SYMBOL { + struct { + DWORD TagIndex; + union { + struct { + WORD Linenumber; + WORD Size; + } LnSz; + DWORD TotalSize; + } Misc; + union { + struct { + DWORD PointerToLinenumber; + DWORD PointerToNextFunction; + } Function; + struct { + WORD Dimension[4]; + } Array; + } FcnAry; + WORD TvIndex; + } Sym; + struct { + BYTE Name[IMAGE_SIZEOF_SYMBOL]; + } File; + struct { + DWORD Length; + WORD NumberOfRelocations; + WORD NumberOfLinenumbers; + DWORD CheckSum; + SHORT Number; + BYTE Selection; + } Section; +} IMAGE_AUX_SYMBOL; +typedef IMAGE_AUX_SYMBOL *PIMAGE_AUX_SYMBOL; + +#define IMAGE_SIZEOF_AUX_SYMBOL 18 + +#define IMAGE_SYM_UNDEFINED (SHORT)0 +#define IMAGE_SYM_ABSOLUTE (SHORT)-1 +#define IMAGE_SYM_DEBUG (SHORT)-2 + +#define IMAGE_SYM_TYPE_NULL 0x0000 +#define IMAGE_SYM_TYPE_VOID 0x0001 +#define IMAGE_SYM_TYPE_CHAR 0x0002 +#define IMAGE_SYM_TYPE_SHORT 0x0003 +#define IMAGE_SYM_TYPE_INT 0x0004 +#define IMAGE_SYM_TYPE_LONG 0x0005 +#define IMAGE_SYM_TYPE_FLOAT 0x0006 +#define IMAGE_SYM_TYPE_DOUBLE 0x0007 +#define IMAGE_SYM_TYPE_STRUCT 0x0008 +#define IMAGE_SYM_TYPE_UNION 0x0009 +#define IMAGE_SYM_TYPE_ENUM 0x000A +#define IMAGE_SYM_TYPE_MOE 0x000B +#define IMAGE_SYM_TYPE_BYTE 0x000C +#define IMAGE_SYM_TYPE_WORD 0x000D +#define IMAGE_SYM_TYPE_UINT 0x000E +#define IMAGE_SYM_TYPE_DWORD 0x000F +#define IMAGE_SYM_TYPE_PCODE 0x8000 + +#define IMAGE_SYM_DTYPE_NULL 0 +#define IMAGE_SYM_DTYPE_POINTER 1 +#define IMAGE_SYM_DTYPE_FUNCTION 2 +#define IMAGE_SYM_DTYPE_ARRAY 3 + +#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE )-1 +#define IMAGE_SYM_CLASS_NULL 0x0000 +#define IMAGE_SYM_CLASS_AUTOMATIC 0x0001 +#define IMAGE_SYM_CLASS_EXTERNAL 0x0002 +#define IMAGE_SYM_CLASS_STATIC 0x0003 +#define IMAGE_SYM_CLASS_REGISTER 0x0004 +#define IMAGE_SYM_CLASS_EXTERNAL_DEF 0x0005 +#define IMAGE_SYM_CLASS_LABEL 0x0006 +#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 0x0007 +#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 0x0008 +#define IMAGE_SYM_CLASS_ARGUMENT 0x0009 +#define IMAGE_SYM_CLASS_STRUCT_TAG 0x000A +#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 0x000B +#define IMAGE_SYM_CLASS_UNION_TAG 0x000C +#define IMAGE_SYM_CLASS_TYPE_DEFINITION 0x000D +#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 0x000E +#define IMAGE_SYM_CLASS_ENUM_TAG 0x000F +#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 0x0010 +#define IMAGE_SYM_CLASS_REGISTER_PARAM 0x0011 +#define IMAGE_SYM_CLASS_BIT_FIELD 0x0012 + +#define IMAGE_SYM_CLASS_FAR_EXTERNAL 0x0044 +#define IMAGE_SYM_CLASS_BLOCK 0x0064 +#define IMAGE_SYM_CLASS_FUNCTION 0x0065 +#define IMAGE_SYM_CLASS_END_OF_STRUCT 0x0066 +#define IMAGE_SYM_CLASS_FILE 0x0067 +#define IMAGE_SYM_CLASS_SECTION 0x0068 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 0x0069 + +#define N_BTMASK 0x000F +#define N_TMASK 0x0030 +#define N_TMASK1 0x00C0 +#define N_TMASK2 0x00F0 +#define N_BTSHFT 4 +#define N_TSHIFT 2 + +#define BTYPE(x) ((x) & N_BTMASK) + +#ifndef ISPTR +#define ISPTR(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT)) +#endif + +#ifndef ISFCN +#define ISFCN(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT)) +#endif + +#ifndef ISARY +#define ISARY(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT)) +#endif + +#ifndef ISTAG +#define ISTAG(x) ((x)==IMAGE_SYM_CLASS_STRUCT_TAG || (x)==IMAGE_SYM_CLASS_UNION_TAG || (x)==IMAGE_SYM_CLASS_ENUM_TAG) +#endif + +#ifndef INCREF +#define INCREF(x) ((((x)&~N_BTMASK)<>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK)) +#endif + +#define IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define IMAGE_COMDAT_SELECT_ANY 2 +#define IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 +#define IMAGE_COMDAT_SELECT_LARGEST 6 +#define IMAGE_COMDAT_SELECT_NEWEST 7 + +#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + +/* Export module directory */ + +typedef struct _IMAGE_EXPORT_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + DWORD Name; + DWORD Base; + DWORD NumberOfFunctions; + DWORD NumberOfNames; + DWORD AddressOfFunctions; + DWORD AddressOfNames; + DWORD AddressOfNameOrdinals; +} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY; + +/* Import name entry */ +typedef struct _IMAGE_IMPORT_BY_NAME { + WORD Hint; + BYTE Name[1]; +} IMAGE_IMPORT_BY_NAME,*PIMAGE_IMPORT_BY_NAME; + +/* Import thunk */ +typedef struct _IMAGE_THUNK_DATA32 { + union { + DWORD ForwarderString; + DWORD Function; + DWORD Ordinal; + DWORD AddressOfData; + } u1; +} IMAGE_THUNK_DATA32,*PIMAGE_THUNK_DATA32; + +typedef struct _IMAGE_THUNK_DATA64 { + union { + ULONGLONG ForwarderString; + ULONGLONG Function; + ULONGLONG Ordinal; + ULONGLONG AddressOfData; + } u1; +} IMAGE_THUNK_DATA64,*PIMAGE_THUNK_DATA64; + +#ifdef CONFIG_X86_64 +typedef IMAGE_THUNK_DATA32 IMAGE_THUNK_DATA; +typedef PIMAGE_THUNK_DATA32 PIMAGE_THUNK_DATA; +#else +typedef IMAGE_THUNK_DATA64 IMAGE_THUNK_DATA; +typedef PIMAGE_THUNK_DATA64 PIMAGE_THUNK_DATA; +#endif + +/* Import module directory */ + +typedef struct packed _IMAGE_IMPORT_DESCRIPTOR { + union { + DWORD Characteristics; /* 0 for terminating null + * import descriptor */ + DWORD OriginalFirstThunk; /* RVA to original unbound + * IAT */ + } u; + DWORD TimeDateStamp; /* 0 if not bound, + * -1 if bound, and real date\time stamp + * in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT + * (new BIND) + * otherwise date/time stamp of DLL bound to + * (Old BIND) + */ + DWORD ForwarderChain; /* -1 if no forwarders */ + DWORD Name; + /* RVA to IAT (if bound this IAT has actual addresses) */ + DWORD FirstThunk; +} IMAGE_IMPORT_DESCRIPTOR,*PIMAGE_IMPORT_DESCRIPTOR; + +#define IMAGE_ORDINAL_FLAG32 0x80000000 +#define IMAGE_ORDINAL_FLAG64 0x8000000000000000UL +#define IMAGE_SNAP_BY_ORDINAL32(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG32) != 0) +#define IMAGE_SNAP_BY_ORDINAL64(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG64) != 0) +#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +#ifdef CONFIG_X86_64 +#define IMAGE_ORDINAL_FLAG IMAGE_ORDINAL_FLAG64 +#define IMAGE_SNAP_BY_ORDINAL IMAGE_SNAP_BY_ORDINAL64 +#else +#define IMAGE_ORDINAL_FLAG IMAGE_ORDINAL_FLAG32 +#define IMAGE_SNAP_BY_ORDINAL IMAGE_SNAP_BY_ORDINAL32 +#endif + +typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR +{ + DWORD TimeDateStamp; + WORD OffsetModuleName; + WORD NumberOfModuleForwarderRefs; +/* Array of zero or more IMAGE_BOUND_FORWARDER_REF follows */ +} IMAGE_BOUND_IMPORT_DESCRIPTOR, *PIMAGE_BOUND_IMPORT_DESCRIPTOR; + +typedef struct _IMAGE_BOUND_FORWARDER_REF +{ + DWORD TimeDateStamp; + WORD OffsetModuleName; + WORD Reserved; +} IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF; + +typedef struct _IMAGE_BASE_RELOCATION +{ + DWORD VirtualAddress; + DWORD SizeOfBlock; + WORD TypeOffset[0]; +} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION; + +typedef struct _IMAGE_RELOCATION +{ + union { + DWORD VirtualAddress; + DWORD RelocCount; + } DUMMYUNIONNAME; + DWORD SymbolTableIndex; + WORD Type; +} IMAGE_RELOCATION, *PIMAGE_RELOCATION; + +#define IMAGE_SIZEOF_RELOCATION 10 + +/* generic relocation types */ +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_SECTION 6 +#define IMAGE_REL_BASED_REL 7 +#define IMAGE_REL_BASED_MIPS_JMPADDR16 9 +#define IMAGE_REL_BASED_IA64_IMM64 9 /* yes, 9 too */ +#define IMAGE_REL_BASED_DIR64 10 +#define IMAGE_REL_BASED_HIGH3ADJ 11 + +/* I386 relocation types */ +#define IMAGE_REL_I386_ABSOLUTE 0 +#define IMAGE_REL_I386_DIR16 1 +#define IMAGE_REL_I386_REL16 2 +#define IMAGE_REL_I386_DIR32 6 +#define IMAGE_REL_I386_DIR32NB 7 +#define IMAGE_REL_I386_SEG12 9 +#define IMAGE_REL_I386_SECTION 10 +#define IMAGE_REL_I386_SECREL 11 +#define IMAGE_REL_I386_REL32 20 + +/* MIPS relocation types */ +#define IMAGE_REL_MIPS_ABSOLUTE 0x0000 +#define IMAGE_REL_MIPS_REFHALF 0x0001 +#define IMAGE_REL_MIPS_REFWORD 0x0002 +#define IMAGE_REL_MIPS_JMPADDR 0x0003 +#define IMAGE_REL_MIPS_REFHI 0x0004 +#define IMAGE_REL_MIPS_REFLO 0x0005 +#define IMAGE_REL_MIPS_GPREL 0x0006 +#define IMAGE_REL_MIPS_LITERAL 0x0007 +#define IMAGE_REL_MIPS_SECTION 0x000A +#define IMAGE_REL_MIPS_SECREL 0x000B +#define IMAGE_REL_MIPS_SECRELLO 0x000C +#define IMAGE_REL_MIPS_SECRELHI 0x000D +#define IMAGE_REL_MIPS_JMPADDR16 0x0010 +#define IMAGE_REL_MIPS_REFWORDNB 0x0022 +#define IMAGE_REL_MIPS_PAIR 0x0025 + +/* ALPHA relocation types */ +#define IMAGE_REL_ALPHA_ABSOLUTE 0x0000 +#define IMAGE_REL_ALPHA_REFLONG 0x0001 +#define IMAGE_REL_ALPHA_REFQUAD 0x0002 +#define IMAGE_REL_ALPHA_GPREL 0x0003 +#define IMAGE_REL_ALPHA_LITERAL 0x0004 +#define IMAGE_REL_ALPHA_LITUSE 0x0005 +#define IMAGE_REL_ALPHA_GPDISP 0x0006 +#define IMAGE_REL_ALPHA_BRADDR 0x0007 +#define IMAGE_REL_ALPHA_HINT 0x0008 +#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x0009 +#define IMAGE_REL_ALPHA_REFHI 0x000A +#define IMAGE_REL_ALPHA_REFLO 0x000B +#define IMAGE_REL_ALPHA_PAIR 0x000C +#define IMAGE_REL_ALPHA_MATCH 0x000D +#define IMAGE_REL_ALPHA_SECTION 0x000E +#define IMAGE_REL_ALPHA_SECREL 0x000F +#define IMAGE_REL_ALPHA_REFLONGNB 0x0010 +#define IMAGE_REL_ALPHA_SECRELLO 0x0011 +#define IMAGE_REL_ALPHA_SECRELHI 0x0012 +#define IMAGE_REL_ALPHA_REFQ3 0x0013 +#define IMAGE_REL_ALPHA_REFQ2 0x0014 +#define IMAGE_REL_ALPHA_REFQ1 0x0015 +#define IMAGE_REL_ALPHA_GPRELLO 0x0016 +#define IMAGE_REL_ALPHA_GPRELHI 0x0017 + +/* PowerPC relocation types */ +#define IMAGE_REL_PPC_ABSOLUTE 0x0000 +#define IMAGE_REL_PPC_ADDR64 0x0001 +#define IMAGE_REL_PPC_ADDR 0x0002 +#define IMAGE_REL_PPC_ADDR24 0x0003 +#define IMAGE_REL_PPC_ADDR16 0x0004 +#define IMAGE_REL_PPC_ADDR14 0x0005 +#define IMAGE_REL_PPC_REL24 0x0006 +#define IMAGE_REL_PPC_REL14 0x0007 +#define IMAGE_REL_PPC_TOCREL16 0x0008 +#define IMAGE_REL_PPC_TOCREL14 0x0009 +#define IMAGE_REL_PPC_ADDR32NB 0x000A +#define IMAGE_REL_PPC_SECREL 0x000B +#define IMAGE_REL_PPC_SECTION 0x000C +#define IMAGE_REL_PPC_IFGLUE 0x000D +#define IMAGE_REL_PPC_IMGLUE 0x000E +#define IMAGE_REL_PPC_SECREL16 0x000F +#define IMAGE_REL_PPC_REFHI 0x0010 +#define IMAGE_REL_PPC_REFLO 0x0011 +#define IMAGE_REL_PPC_PAIR 0x0012 +#define IMAGE_REL_PPC_SECRELLO 0x0013 +#define IMAGE_REL_PPC_SECRELHI 0x0014 +#define IMAGE_REL_PPC_GPREL 0x0015 +#define IMAGE_REL_PPC_TYPEMASK 0x00FF +/* modifier bits */ +#define IMAGE_REL_PPC_NEG 0x0100 +#define IMAGE_REL_PPC_BRTAKEN 0x0200 +#define IMAGE_REL_PPC_BRNTAKEN 0x0400 +#define IMAGE_REL_PPC_TOCDEFN 0x0800 + +/* SH3 ? relocation type */ +#define IMAGE_REL_SH3_ABSOLUTE 0x0000 +#define IMAGE_REL_SH3_DIRECT16 0x0001 +#define IMAGE_REL_SH3_DIRECT 0x0002 +#define IMAGE_REL_SH3_DIRECT8 0x0003 +#define IMAGE_REL_SH3_DIRECT8_WORD 0x0004 +#define IMAGE_REL_SH3_DIRECT8_LONG 0x0005 +#define IMAGE_REL_SH3_DIRECT4 0x0006 +#define IMAGE_REL_SH3_DIRECT4_WORD 0x0007 +#define IMAGE_REL_SH3_DIRECT4_LONG 0x0008 +#define IMAGE_REL_SH3_PCREL8_WORD 0x0009 +#define IMAGE_REL_SH3_PCREL8_LONG 0x000A +#define IMAGE_REL_SH3_PCREL12_WORD 0x000B +#define IMAGE_REL_SH3_STARTOF_SECTION 0x000C +#define IMAGE_REL_SH3_SIZEOF_SECTION 0x000D +#define IMAGE_REL_SH3_SECTION 0x000E +#define IMAGE_REL_SH3_SECREL 0x000F +#define IMAGE_REL_SH3_DIRECT32_NB 0x0010 + +/* ARM (Archimedes?) relocation types */ +#define IMAGE_REL_ARM_ABSOLUTE 0x0000 +#define IMAGE_REL_ARM_ADDR 0x0001 +#define IMAGE_REL_ARM_ADDR32NB 0x0002 +#define IMAGE_REL_ARM_BRANCH24 0x0003 +#define IMAGE_REL_ARM_BRANCH11 0x0004 +#define IMAGE_REL_ARM_SECTION 0x000E +#define IMAGE_REL_ARM_SECREL 0x000F + +/* IA64 relocation types */ +#define IMAGE_REL_IA64_ABSOLUTE 0x0000 +#define IMAGE_REL_IA64_IMM14 0x0001 +#define IMAGE_REL_IA64_IMM22 0x0002 +#define IMAGE_REL_IA64_IMM64 0x0003 +#define IMAGE_REL_IA64_DIR 0x0004 +#define IMAGE_REL_IA64_DIR64 0x0005 +#define IMAGE_REL_IA64_PCREL21B 0x0006 +#define IMAGE_REL_IA64_PCREL21M 0x0007 +#define IMAGE_REL_IA64_PCREL21F 0x0008 +#define IMAGE_REL_IA64_GPREL22 0x0009 +#define IMAGE_REL_IA64_LTOFF22 0x000A +#define IMAGE_REL_IA64_SECTION 0x000B +#define IMAGE_REL_IA64_SECREL22 0x000C +#define IMAGE_REL_IA64_SECREL64I 0x000D +#define IMAGE_REL_IA64_SECREL 0x000E +#define IMAGE_REL_IA64_LTOFF64 0x000F +#define IMAGE_REL_IA64_DIR32NB 0x0010 +#define IMAGE_REL_IA64_RESERVED_11 0x0011 +#define IMAGE_REL_IA64_RESERVED_12 0x0012 +#define IMAGE_REL_IA64_RESERVED_13 0x0013 +#define IMAGE_REL_IA64_RESERVED_14 0x0014 +#define IMAGE_REL_IA64_RESERVED_15 0x0015 +#define IMAGE_REL_IA64_RESERVED_16 0x0016 +#define IMAGE_REL_IA64_ADDEND 0x001F + +/* archive format */ + +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START "!\n" +#define IMAGE_ARCHIVE_END "`\n" +#define IMAGE_ARCHIVE_PAD "\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER +{ + BYTE Name[16]; + BYTE Date[12]; + BYTE UserID[6]; + BYTE GroupID[6]; + BYTE Mode[8]; + BYTE Size[10]; + BYTE EndHeader[2]; +} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER; + +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +/* + * Resource directory stuff + */ +typedef struct _IMAGE_RESOURCE_DIRECTORY { + DWORD Characteristics; + DWORD TimeDateStamp; + WORD MajorVersion; + WORD MinorVersion; + WORD NumberOfNamedEntries; + WORD NumberOfIdEntries; + /* IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; */ +} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY; + +#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000 +#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000 + +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + union { + struct { +#ifdef BITFIELDS_BIGENDIAN + unsigned NameIsString:1; + unsigned NameOffset:31; +#else + unsigned NameOffset:31; + unsigned NameIsString:1; +#endif + } DUMMYSTRUCTNAME1; + DWORD Name; + struct { +#ifdef WORDS_BIGENDIAN + WORD __pad; + WORD Id; +#else + WORD Id; + WORD __pad; +#endif + } DUMMYSTRUCTNAME2; + } DUMMYUNIONNAME1; + union { + DWORD OffsetToData; + struct { +#ifdef BITFIELDS_BIGENDIAN + unsigned DataIsDirectory:1; + unsigned OffsetToDirectory:31; +#else + unsigned OffsetToDirectory:31; + unsigned DataIsDirectory:1; +#endif + } DUMMYSTRUCTNAME3; + } DUMMYUNIONNAME2; +} IMAGE_RESOURCE_DIRECTORY_ENTRY,*PIMAGE_RESOURCE_DIRECTORY_ENTRY; + + +typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING { + WORD Length; + CHAR NameString[ 1 ]; +} IMAGE_RESOURCE_DIRECTORY_STRING,*PIMAGE_RESOURCE_DIRECTORY_STRING; + --- linux-2.6.37.orig/ubuntu/ndiswrapper/pnp.c +++ linux-2.6.37/ubuntu/ndiswrapper/pnp.c @@ -0,0 +1,742 @@ +/* + * Copyright (C) 2005 Giridhar Pemmasani + * + * 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. + * + */ + +#include "usb.h" +#include "pnp.h" +#include "wrapndis.h" +#include "loader.h" + +/* Functions callable from the NDIS driver */ +wstdcall NTSTATUS pdoDispatchDeviceControl(struct device_object *pdo, + struct irp *irp); +wstdcall NTSTATUS pdoDispatchPnp(struct device_object *pdo, struct irp *irp); +wstdcall NTSTATUS pdoDispatchPower(struct device_object *pdo, struct irp *irp); + +static NTSTATUS start_pdo(struct device_object *pdo) +{ + int i, ret, count, resources_size; + struct wrap_device *wd; + struct pci_dev *pdev; + struct cm_partial_resource_descriptor *entry; + struct cm_partial_resource_list *partial_resource_list; + + ENTER1("%p, %p", pdo, pdo->reserved); + wd = pdo->reserved; + if (ntoskernel_init_device(wd)) + EXIT1(return STATUS_FAILURE); + if (wrap_is_usb_bus(wd->dev_bus)) { +#ifdef ENABLE_USB + if (usb_init_device(wd)) { + ntoskernel_exit_device(wd); + EXIT1(return STATUS_FAILURE); + } +#endif + EXIT1(return STATUS_SUCCESS); + } + if (!wrap_is_pci_bus(wd->dev_bus)) + EXIT1(return STATUS_SUCCESS); + pdev = wd->pci.pdev; + ret = pci_enable_device(pdev); + if (ret) { + ERROR("couldn't enable PCI device: %x", ret); + return STATUS_FAILURE; + } + ret = pci_request_regions(pdev, DRIVER_NAME); + if (ret) { + ERROR("couldn't request PCI regions: %x", ret); + goto err_enable; + } + pci_set_power_state(pdev, PCI_D0); +#ifdef CONFIG_X86_64 + /* 64-bit broadcom driver doesn't work if DMA is allocated + * from over 1GB */ + if (wd->vendor == 0x14e4) { + if (pci_set_dma_mask(pdev, DMA_BIT_MASK(30)) || + pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(30))) + WARNING("couldn't set DMA mask; this driver " + "may not work with more than 1GB RAM"); + } +#endif + /* IRQ resource entry is filled in from pdev, instead of + * pci_resource macros */ + for (i = count = 0; pci_resource_start(pdev, i); i++) + if ((pci_resource_flags(pdev, i) & IORESOURCE_MEM) || + (pci_resource_flags(pdev, i) & IORESOURCE_IO)) + count++; + /* space for entry for IRQ is already in + * cm_partial_resource_list */ + resources_size = sizeof(struct cm_resource_list) + + sizeof(struct cm_partial_resource_descriptor) * count; + TRACE2("resources: %d, %d", count, resources_size); + wd->resource_list = kzalloc(resources_size, GFP_KERNEL); + if (!wd->resource_list) { + WARNING("couldn't allocate memory"); + goto err_regions; + } + wd->resource_list->count = 1; + wd->resource_list->list[0].interface_type = PCIBus; + /* bus_number is not used by WDM drivers */ + wd->resource_list->list[0].bus_number = pdev->bus->number; + + partial_resource_list = + &wd->resource_list->list->partial_resource_list; + partial_resource_list->version = 1; + partial_resource_list->revision = 1; + partial_resource_list->count = count + 1; + + for (i = count = 0; pci_resource_start(pdev, i); i++) { + entry = &partial_resource_list->partial_descriptors[count]; + TRACE2("%d", count); + if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) { + entry->type = CmResourceTypeMemory; + entry->flags = CM_RESOURCE_MEMORY_READ_WRITE; + entry->share = CmResourceShareDeviceExclusive; + } else if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { + entry->type = CmResourceTypePort; + entry->flags = CM_RESOURCE_PORT_IO; + entry->share = CmResourceShareDeviceExclusive; +#if 0 + } else if (pci_resource_flags(pdev, i) & IORESOURCE_DMA) { + /* it looks like no driver uses this resource */ + typeof(pci_resource_flags(pdev, 0)) flags; + entry->type = CmResourceTypeDma; + flags = pci_resource_flags(pdev, i); + if (flags & IORESOURCE_DMA_TYPEA) + entry->flags |= CM_RESOURCE_DMA_TYPE_A; + else if (flags & IORESOURCE_DMA_TYPEB) + entry->flags |= CM_RESOURCE_DMA_TYPE_B; + else if (flags & IORESOURCE_DMA_TYPEF) + entry->flags |= CM_RESOURCE_DMA_TYPE_F; + if (flags & IORESOURCE_DMA_8BIT) + entry->flags |= CM_RESOURCE_DMA_8; + else if (flags & IORESOURCE_DMA_16BIT) + entry->flags |= CM_RESOURCE_DMA_16; + /* what about 32bit DMA? */ + else if (flags & IORESOURCE_DMA_8AND16BIT) + entry->flags |= CM_RESOURCE_DMA_8_AND_16; + if (flags & IORESOURCE_DMA_MASTER) + entry->flags |= CM_RESOURCE_DMA_BUS_MASTER; + entry->u.dma.channel = pci_resource_start(pdev, i); + /* what should this be? */ + entry->u.dma.port = 1; +#endif + } else + continue; + /* TODO: Add other resource types? */ + entry->u.generic.start = + (ULONG_PTR)pci_resource_start(pdev, i); + entry->u.generic.length = pci_resource_len(pdev, i); + count++; + } + + /* put IRQ resource at the end */ + entry = &partial_resource_list->partial_descriptors[count++]; + entry->type = CmResourceTypeInterrupt; + entry->flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + /* we assume all devices use shared IRQ */ + entry->share = CmResourceShareShared; + /* as per documentation, interrupt level should be DIRQL, but + * examples from DDK as well some drivers, such as AR5211, + * RT8180L use interrupt level as interrupt vector also in + * NdisMRegisterInterrupt */ + entry->u.interrupt.level = pdev->irq; + entry->u.interrupt.vector = pdev->irq; + entry->u.interrupt.affinity = -1; + + TRACE2("resource list count %d, irq: %d", + partial_resource_list->count, pdev->irq); + pci_set_drvdata(pdev, wd); + EXIT1(return STATUS_SUCCESS); +err_regions: + pci_release_regions(pdev); +err_enable: + pci_disable_device(pdev); + wd->pci.pdev = NULL; + wd->pdo = NULL; + EXIT1(return STATUS_FAILURE); +} + +static void remove_pdo(struct device_object *pdo) +{ + struct wrap_device *wd = pdo->reserved; + + ntoskernel_exit_device(wd); + if (wrap_is_pci_bus(wd->dev_bus)) { + struct pci_dev *pdev = wd->pci.pdev; + pci_release_regions(pdev); + pci_disable_device(pdev); + wd->pci.pdev = NULL; + pci_set_drvdata(pdev, NULL); + } else if (wrap_is_usb_bus(wd->dev_bus)) { +#ifdef ENABLE_USB + usb_exit_device(wd); +#endif + } + if (wd->resource_list) + kfree(wd->resource_list); + wd->resource_list = NULL; + return; +} + +static NTSTATUS IoSendIrpTopDev(struct device_object *dev_obj, ULONG major_fn, + ULONG minor_fn, struct io_stack_location *sl) +{ + NTSTATUS status; + struct nt_event event; + struct irp *irp; + struct io_stack_location *irp_sl; + struct device_object *top_dev = IoGetAttachedDeviceReference(dev_obj); + + KeInitializeEvent(&event, NotificationEvent, FALSE); + irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, top_dev, NULL, 0, NULL, + &event, NULL); + irp->io_status.status = STATUS_NOT_IMPLEMENTED; + irp->io_status.info = 0; + irp_sl = IoGetNextIrpStackLocation(irp); + if (sl) + memcpy(irp_sl, sl, sizeof(*irp_sl)); + irp_sl->major_fn = major_fn; + irp_sl->minor_fn = minor_fn; + status = IoCallDriver(top_dev, irp); + if (status == STATUS_PENDING) { + KeWaitForSingleObject(&event, Executive, KernelMode, + FALSE, NULL); + status = irp->io_status.status; + } + ObDereferenceObject(top_dev); + return status; +} + +wstdcall NTSTATUS pdoDispatchDeviceControl(struct device_object *pdo, + struct irp *irp) +{ + struct io_stack_location *irp_sl; + NTSTATUS status; + + DUMP_IRP(irp); + irp_sl = IoGetCurrentIrpStackLocation(irp); +#ifdef ENABLE_USB + status = wrap_submit_irp(pdo, irp); + IOTRACE("status: %08X", status); + if (status != STATUS_PENDING) + IoCompleteRequest(irp, IO_NO_INCREMENT); +#else + status = irp->io_status.status = STATUS_NOT_IMPLEMENTED; + IoCompleteRequest(irp, IO_NO_INCREMENT); +#endif + IOEXIT(return status); +} +WIN_FUNC_DECL(pdoDispatchDeviceControl,2) + +wstdcall NTSTATUS pdoDispatchPnp(struct device_object *pdo, struct irp *irp) +{ + struct io_stack_location *irp_sl; + struct wrap_device *wd; + NTSTATUS status; +#ifdef ENABLE_USB + struct usbd_bus_interface_usbdi *usb_intf; +#endif + + irp_sl = IoGetCurrentIrpStackLocation(irp); + TRACE2("%p %d:%d", pdo, irp_sl->major_fn, irp_sl->minor_fn); + wd = pdo->reserved; + switch (irp_sl->minor_fn) { + case IRP_MN_START_DEVICE: + status = start_pdo(pdo); + break; + case IRP_MN_QUERY_STOP_DEVICE: + case IRP_MN_STOP_DEVICE: + case IRP_MN_QUERY_REMOVE_DEVICE: + status = STATUS_SUCCESS; + break; + case IRP_MN_REMOVE_DEVICE: + remove_pdo(pdo); + status = STATUS_SUCCESS; + break; + case IRP_MN_QUERY_INTERFACE: +#ifdef ENABLE_USB + if (!wrap_is_usb_bus(wd->dev_bus)) { + status = STATUS_NOT_IMPLEMENTED; + break; + } + TRACE2("type: %x, size: %d, version: %d", + irp_sl->params.query_intf.type->data1, + irp_sl->params.query_intf.size, + irp_sl->params.query_intf.version); + usb_intf = (struct usbd_bus_interface_usbdi *) + irp_sl->params.query_intf.intf; + usb_intf->Context = wd; + usb_intf->InterfaceReference = USBD_InterfaceReference; + usb_intf->InterfaceDereference = USBD_InterfaceDereference; + usb_intf->GetUSBDIVersion = USBD_InterfaceGetUSBDIVersion; + usb_intf->QueryBusTime = USBD_InterfaceQueryBusTime; + usb_intf->SubmitIsoOutUrb = USBD_InterfaceSubmitIsoOutUrb; + usb_intf->QueryBusInformation = + USBD_InterfaceQueryBusInformation; + if (irp_sl->params.query_intf.version >= + USB_BUSIF_USBDI_VERSION_1) + usb_intf->IsDeviceHighSpeed = + USBD_InterfaceIsDeviceHighSpeed; + if (irp_sl->params.query_intf.version >= + USB_BUSIF_USBDI_VERSION_2) + usb_intf->LogEntry = USBD_InterfaceLogEntry; + status = STATUS_SUCCESS; +#else + status = STATUS_NOT_IMPLEMENTED; +#endif + break; + default: + TRACE2("fn %d not implemented", irp_sl->minor_fn); + status = STATUS_SUCCESS; + break; + } + irp->io_status.status = status; + TRACE2("status: %08X", status); + IoCompleteRequest(irp, IO_NO_INCREMENT); + IOEXIT(return status); +} +WIN_FUNC_DECL(pdoDispatchPnp,2) + +wstdcall NTSTATUS pdoDispatchPower(struct device_object *pdo, struct irp *irp) +{ + struct io_stack_location *irp_sl; + struct wrap_device *wd; + union power_state power_state; + struct pci_dev *pdev; + NTSTATUS status; + + irp_sl = IoGetCurrentIrpStackLocation(irp); + wd = pdo->reserved; + TRACE2("pdo: %p, fn: %d:%d, wd: %p", + pdo, irp_sl->major_fn, irp_sl->minor_fn, wd); + switch (irp_sl->minor_fn) { + case IRP_MN_WAIT_WAKE: + /* TODO: this is not complete/correct */ + TRACE2("state: %d, completion: %p", + irp_sl->params.power.state.system_state, + irp_sl->completion_routine); + IoMarkIrpPending(irp); + status = STATUS_PENDING; + break; + case IRP_MN_SET_POWER: + power_state = irp_sl->params.power.state; + if (power_state.device_state == PowerDeviceD0) { + TRACE2("resuming %p", wd); + if (wrap_is_pci_bus(wd->dev_bus)) { + pdev = wd->pci.pdev; + pci_restore_state(pdev); + if (wd->pci.wake_state == PowerDeviceD3) { + pci_enable_wake(wd->pci.pdev, + PCI_D3hot, 0); + pci_enable_wake(wd->pci.pdev, + PCI_D3cold, 0); + } + pci_set_power_state(pdev, PCI_D0); + } else { // usb device +#ifdef ENABLE_USB + wrap_resume_urbs(wd); +#endif + } + } else { + TRACE2("suspending device %p", wd); + if (wrap_is_pci_bus(wd->dev_bus)) { + pdev = wd->pci.pdev; + pci_save_state(pdev); + TRACE2("%d", wd->pci.wake_state); + if (wd->pci.wake_state == PowerDeviceD3) { + pci_enable_wake(wd->pci.pdev, + PCI_D3hot, 1); + pci_enable_wake(wd->pci.pdev, + PCI_D3cold, 1); + } + pci_set_power_state(pdev, PCI_D3hot); + } else { // usb device +#ifdef ENABLE_USB + wrap_suspend_urbs(wd); +#endif + } + } + status = STATUS_SUCCESS; + break; + case IRP_MN_QUERY_POWER: + status = STATUS_SUCCESS; + break; + default: + TRACE2("fn %d not implemented", irp_sl->minor_fn); + status = STATUS_SUCCESS; + break; + } + irp->io_status.status = status; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return status; +} +WIN_FUNC_DECL(pdoDispatchPower,2) + +static NTSTATUS pnp_set_device_power_state(struct wrap_device *wd, + enum device_power_state state) +{ + NTSTATUS status; + struct device_object *pdo; + struct io_stack_location irp_sl; + + pdo = wd->pdo; + IOTRACE("%p, %p", pdo, IoGetAttachedDevice(pdo)); + memset(&irp_sl, 0, sizeof(irp_sl)); + irp_sl.params.power.state.device_state = state; + irp_sl.params.power.type = DevicePowerState; + if (state > PowerDeviceD0) { + status = IoSendIrpTopDev(pdo, IRP_MJ_POWER, IRP_MN_QUERY_POWER, + &irp_sl); + if (status != STATUS_SUCCESS) { + TRACE1("query of power to %d returns %08X", + state, status); + EXIT1(return status); + } + } + status = IoSendIrpTopDev(pdo, IRP_MJ_POWER, IRP_MN_SET_POWER, &irp_sl); + if (status != STATUS_SUCCESS) + WARNING("setting power to %d failed: %08X", state, status); + EXIT1(return status); +} + +NTSTATUS pnp_start_device(struct wrap_device *wd) +{ + struct device_object *fdo; + struct device_object *pdo; + struct io_stack_location irp_sl; + NTSTATUS status; + + pdo = wd->pdo; + /* TODO: for now we use same resources for both translated + * resources and raw resources */ + memset(&irp_sl, 0, sizeof(irp_sl)); + irp_sl.params.start_device.allocated_resources = + wd->resource_list; + irp_sl.params.start_device.allocated_resources_translated = + wd->resource_list; + status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_START_DEVICE, &irp_sl); + fdo = IoGetAttachedDevice(pdo); + if (status == STATUS_SUCCESS) + fdo->drv_obj->drv_ext->count++; + else + WARNING("Windows driver couldn't initialize the device (%08X)", + status); + EXIT1(return status); +} + +NTSTATUS pnp_stop_device(struct wrap_device *wd) +{ + struct device_object *pdo; + NTSTATUS status; + + pdo = wd->pdo; + status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_QUERY_STOP_DEVICE, + NULL); + if (status != STATUS_SUCCESS) + WARNING("status: %08X", status); + /* for now we ignore query status */ + status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_STOP_DEVICE, NULL); + if (status != STATUS_SUCCESS) + WARNING("status: %08X", status); + if (status != STATUS_SUCCESS) + WARNING("status: %08X", status); + EXIT2(return status); +} + +NTSTATUS pnp_remove_device(struct wrap_device *wd) +{ + struct device_object *pdo, *fdo; + struct driver_object *fdo_drv_obj; + NTSTATUS status; + + pdo = wd->pdo; + fdo = IoGetAttachedDevice(pdo); + fdo_drv_obj = fdo->drv_obj; + TRACE2("%p, %p, %p", pdo, fdo, fdo_drv_obj); + status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_QUERY_REMOVE_DEVICE, + NULL); + if (status != STATUS_SUCCESS) + WARNING("status: %08X", status); + + status = IoSendIrpTopDev(pdo, IRP_MJ_PNP, IRP_MN_REMOVE_DEVICE, NULL); + if (status != STATUS_SUCCESS) + WARNING("status: %08X", status); + /* TODO: should we use count in drv_ext or driver's Object + * header reference count to keep count of devices associated + * with a driver? */ + if (status == STATUS_SUCCESS) + fdo_drv_obj->drv_ext->count--; + TRACE1("count: %d", fdo_drv_obj->drv_ext->count); + if (fdo_drv_obj->drv_ext->count < 0) + WARNING("wrong count: %d", fdo_drv_obj->drv_ext->count); + if (fdo_drv_obj->drv_ext->count == 0) { + struct wrap_driver *wrap_driver; + TRACE1("unloading driver: %p", fdo_drv_obj); + wrap_driver = + IoGetDriverObjectExtension(fdo_drv_obj, + (void *)WRAP_DRIVER_CLIENT_ID); + if (fdo_drv_obj->unload) + LIN2WIN1(fdo_drv_obj->unload, fdo_drv_obj); + if (wrap_driver) { + if (down_interruptible(&loader_mutex)) + WARNING("couldn't obtain loader_mutex"); + unload_wrap_driver(wrap_driver); + up(&loader_mutex); + } else + ERROR("couldn't get wrap_driver"); + ObDereferenceObject(fdo_drv_obj); + } + IoDeleteDevice(pdo); + unload_wrap_device(wd); + EXIT1(return status); +} + +WIN_FUNC_DECL(IoInvalidDeviceRequest,2) + +static struct device_object *alloc_pdo(struct driver_object *drv_obj) +{ + struct device_object *pdo; + NTSTATUS status ; + int i; + struct ansi_string ansi_name; + struct unicode_string unicode_name; + + RtlInitAnsiString(&ansi_name, "NDISpdo"); + if (RtlAnsiStringToUnicodeString(&unicode_name, &ansi_name, TRUE) == + STATUS_SUCCESS) { + status = IoCreateDevice(drv_obj, 0, &unicode_name, + FILE_DEVICE_UNKNOWN, + FILE_AUTOGENERATED_DEVICE_NAME, + FALSE, &pdo); + RtlFreeUnicodeString(&unicode_name); + } else { + status = IoCreateDevice(drv_obj, 0, NULL, + FILE_DEVICE_UNKNOWN, + FILE_AUTOGENERATED_DEVICE_NAME, + FALSE, &pdo); + } + TRACE1("%p, %d, %p", drv_obj, status, pdo); + if (status != STATUS_SUCCESS) + return NULL; + /* dispatch routines are called as Windows functions */ + for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) + drv_obj->major_func[i] = WIN_FUNC_PTR(IoInvalidDeviceRequest,2); + drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] = + WIN_FUNC_PTR(pdoDispatchDeviceControl,2); + drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] = + WIN_FUNC_PTR(pdoDispatchDeviceControl,2); + drv_obj->major_func[IRP_MJ_POWER] = WIN_FUNC_PTR(pdoDispatchPower,2); + drv_obj->major_func[IRP_MJ_PNP] = WIN_FUNC_PTR(pdoDispatchPnp,2); + return pdo; +} + +static int wrap_pnp_start_device(struct wrap_device *wd) +{ + struct wrap_driver *driver; + struct device_object *pdo; + struct driver_object *pdo_drv_obj; + + ENTER1("wd: %p", wd); + + if (!((wrap_is_pci_bus(wd->dev_bus)) || + (wrap_is_usb_bus(wd->dev_bus)))) { + ERROR("bus type %d (%d) not supported", + WRAP_BUS(wd->dev_bus), wd->dev_bus); + EXIT1(return -EINVAL); + } + driver = load_wrap_driver(wd); + if (!driver) + return -ENODEV; + + wd->driver = driver; + wd->dev_bus = WRAP_DEVICE_BUS(driver->dev_type, WRAP_BUS(wd->dev_bus)); + TRACE1("dev type: %d, bus type: %d, %d", WRAP_DEVICE(wd->dev_bus), + WRAP_BUS(wd->dev_bus), wd->dev_bus); + TRACE1("%d, %d", driver->dev_type, wrap_is_usb_bus(wd->dev_bus)); + /* first create pdo */ + if (wrap_is_pci_bus(wd->dev_bus)) + pdo_drv_obj = find_bus_driver("PCI"); + else // if (wrap_is_usb_bus(wd->dev_bus)) + pdo_drv_obj = find_bus_driver("USB"); + if (!pdo_drv_obj) + return -EINVAL; + pdo = alloc_pdo(pdo_drv_obj); + if (!pdo) + return -ENOMEM; + wd->pdo = pdo; + pdo->reserved = wd; + if (WRAP_DEVICE(wd->dev_bus) == WRAP_NDIS_DEVICE) { + if (init_ndis_driver(driver->drv_obj)) { + IoDeleteDevice(pdo); + return -EINVAL; + } + } + TRACE1("%p", driver->drv_obj->drv_ext->add_device); + if (driver->drv_obj->drv_ext->add_device(driver->drv_obj, pdo) != + STATUS_SUCCESS) { + IoDeleteDevice(pdo); + return -ENOMEM; + } + if (pnp_start_device(wd) != STATUS_SUCCESS) { + /* TODO: we need proper cleanup, to deallocate memory, + * for example */ + pnp_remove_device(wd); + return -EINVAL; + } + return 0; +} + +/* + * This function should not be marked __devinit because PCI IDs are + * added dynamically. + */ +int wrap_pnp_start_pci_device(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct load_device load_device; + struct wrap_device *wd; + + ENTER1("called for %04x:%04x:%04x:%04x", pdev->vendor, pdev->device, + pdev->subsystem_vendor, pdev->subsystem_device); + + load_device.bus = WRAP_PCI_BUS; + load_device.vendor = pdev->vendor; + load_device.device = pdev->device; + load_device.subvendor = pdev->subsystem_vendor; + load_device.subdevice = pdev->subsystem_device; + wd = load_wrap_device(&load_device); + if (!wd) + EXIT1(return -ENODEV); + wd->pci.pdev = pdev; + return wrap_pnp_start_device(wd); +} + +void wrap_pnp_remove_pci_device(struct pci_dev *pdev) +{ + struct wrap_device *wd; + + wd = (struct wrap_device *)pci_get_drvdata(pdev); + ENTER1("%p, %p", pdev, wd); + if (!wd) + EXIT1(return); + pnp_remove_device(wd); +} + +int wrap_pnp_suspend_pci_device(struct pci_dev *pdev, pm_message_t state) +{ + struct wrap_device *wd; + + wd = (struct wrap_device *)pci_get_drvdata(pdev); + return pnp_set_device_power_state(wd, PowerDeviceD3); +} + +int wrap_pnp_resume_pci_device(struct pci_dev *pdev) +{ + struct wrap_device *wd; + + wd = (struct wrap_device *)pci_get_drvdata(pdev); + return pnp_set_device_power_state(wd, PowerDeviceD0); +} + +#ifdef ENABLE_USB +int wrap_pnp_start_usb_device(struct usb_interface *intf, + const struct usb_device_id *usb_id) +{ + struct wrap_device *wd; + int ret; + struct usb_device *udev = interface_to_usbdev(intf); + ENTER1("%04x, %04x, %04x", udev->descriptor.idVendor, + udev->descriptor.idProduct, udev->descriptor.bDeviceClass); + + /* USB device (e.g., RNDIS) may have multiple interfaces; + initialize one interface only (is there a way to know which + of these interfaces is for network?) */ + + if ((wd = get_wrap_device(udev, WRAP_USB_BUS))) { + TRACE1("device already initialized: %p", wd); + usb_set_intfdata(intf, NULL); + ret = 0; + } else { + struct load_device load_device; + + load_device.bus = WRAP_USB_BUS; + load_device.vendor = le16_to_cpu(udev->descriptor.idVendor); + load_device.device = le16_to_cpu(udev->descriptor.idProduct); + load_device.subvendor = 0; + load_device.subdevice = 0; + wd = load_wrap_device(&load_device); + TRACE2("%p", wd); + if (wd) { + /* some devices (e.g., TI 4150, RNDIS) need + * full reset */ + ret = usb_reset_device(udev); + if (ret) + WARNING("reset failed: %d", ret); + usb_set_intfdata(intf, wd); + wd->usb.intf = intf; + wd->usb.udev = udev; + ret = wrap_pnp_start_device(wd); + } else + ret = -ENODEV; + } + + TRACE2("ret: %d", ret); + if (ret) + EXIT1(return ret); + else + return 0; +} + +void __devexit wrap_pnp_remove_usb_device(struct usb_interface *intf) +{ + struct wrap_device *wd; + + wd = (struct wrap_device *)usb_get_intfdata(intf); + TRACE1("%p, %p", intf, wd); + if (wd == NULL) + EXIT1(return); + usb_set_intfdata(intf, NULL); + wd->usb.intf = NULL; + pnp_remove_device(wd); +} + +int wrap_pnp_suspend_usb_device(struct usb_interface *intf, pm_message_t state) +{ + struct wrap_device *wd; + struct device_object *pdo; + + wd = usb_get_intfdata(intf); + ENTER1("%p, %p", intf, wd); + if (!wd) + EXIT1(return 0); + pdo = wd->pdo; + if (pnp_set_device_power_state(wd, PowerDeviceD3)) + return -1; + return 0; +} + +int wrap_pnp_resume_usb_device(struct usb_interface *intf) +{ + struct wrap_device *wd; + wd = usb_get_intfdata(intf); + ENTER1("%p, %p", intf, wd); + if (!wd) + EXIT1(return 0); + if (pnp_set_device_power_state(wd, PowerDeviceD0)) + return -1; + return 0; +} + +#endif // USB --- linux-2.6.37.orig/ubuntu/ndiswrapper/pnp.h +++ linux-2.6.37/ubuntu/ndiswrapper/pnp.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2005 Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _PNP_H_ +#define _PNP_H_ + +#include "ntoskernel.h" +#include "ndis.h" +#include "wrapndis.h" + +NTSTATUS pnp_start_device(struct wrap_device *wd); +NTSTATUS pnp_stop_device(struct wrap_device *wd); +NTSTATUS pnp_remove_device(struct wrap_device *wd); + +int wrap_pnp_start_pci_device(struct pci_dev *pdev, + const struct pci_device_id *ent); +void __devexit wrap_pnp_remove_pci_device(struct pci_dev *pdev); +int wrap_pnp_suspend_pci_device(struct pci_dev *pdev, pm_message_t state); +int wrap_pnp_resume_pci_device(struct pci_dev *pdev); + +#ifdef ENABLE_USB +int wrap_pnp_start_usb_device(struct usb_interface *intf, + const struct usb_device_id *usb_id); +void wrap_pnp_remove_usb_device(struct usb_interface *intf); +int wrap_pnp_suspend_usb_device(struct usb_interface *intf, + pm_message_t state); +int wrap_pnp_resume_usb_device(struct usb_interface *intf); +#endif + +#endif --- linux-2.6.37.orig/ubuntu/ndiswrapper/proc.c +++ linux-2.6.37/ubuntu/ndiswrapper/proc.c @@ -0,0 +1,565 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ +#include +#include +#include + +#include "ndis.h" +#include "iw_ndis.h" +#include "wrapndis.h" +#include "pnp.h" +#include "wrapper.h" + +#define MAX_PROC_STR_LEN 32 + +static struct proc_dir_entry *wrap_procfs_entry; + +static int procfs_read_ndis_stats(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + struct ndis_device *wnd = (struct ndis_device *)data; + struct ndis_wireless_stats stats; + NDIS_STATUS res; + ndis_rssi rssi; + + if (off != 0) { + *eof = 1; + return 0; + } + + res = mp_query(wnd, OID_802_11_RSSI, &rssi, sizeof(rssi)); + if (!res) + p += sprintf(p, "signal_level=%d dBm\n", (s32)rssi); + + res = mp_query(wnd, OID_802_11_STATISTICS, &stats, sizeof(stats)); + if (!res) { + + p += sprintf(p, "tx_frames=%Lu\n", stats.tx_frag); + p += sprintf(p, "tx_multicast_frames=%Lu\n", + stats.tx_multi_frag); + p += sprintf(p, "tx_failed=%Lu\n", stats.failed); + p += sprintf(p, "tx_retry=%Lu\n", stats.retry); + p += sprintf(p, "tx_multi_rerty=%Lu\n", stats.multi_retry); + p += sprintf(p, "tx_rtss_success=%Lu\n", stats.rtss_succ); + p += sprintf(p, "tx_rtss_fail=%Lu\n", stats.rtss_fail); + p += sprintf(p, "ack_fail=%Lu\n", stats.ack_fail); + p += sprintf(p, "frame_duplicates=%Lu\n", stats.frame_dup); + p += sprintf(p, "rx_frames=%Lu\n", stats.rx_frag); + p += sprintf(p, "rx_multicast_frames=%Lu\n", + stats.rx_multi_frag); + p += sprintf(p, "fcs_errors=%Lu\n", stats.fcs_err); + } + + if (p - page > count) { + ERROR("wrote %lu bytes (limit is %u)\n", + (unsigned long)(p - page), count); + *eof = 1; + } + + return p - page; +} + +static int procfs_read_ndis_encr(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + struct ndis_device *wnd = (struct ndis_device *)data; + int i, encr_status, auth_mode, infra_mode; + NDIS_STATUS res; + struct ndis_essid essid; + mac_address ap_address; + + if (off != 0) { + *eof = 1; + return 0; + } + + res = mp_query(wnd, OID_802_11_BSSID, + &ap_address, sizeof(ap_address)); + if (res) + memset(ap_address, 0, ETH_ALEN); + p += sprintf(p, "ap_address=%2.2X", ap_address[0]); + for (i = 1 ; i < ETH_ALEN ; i++) + p += sprintf(p, ":%2.2X", ap_address[i]); + p += sprintf(p, "\n"); + + res = mp_query(wnd, OID_802_11_SSID, &essid, sizeof(essid)); + if (!res) + p += sprintf(p, "essid=%.*s\n", essid.length, essid.essid); + + res = mp_query_int(wnd, OID_802_11_ENCRYPTION_STATUS, &encr_status); + if (!res) { + typeof(&wnd->encr_info.keys[0]) tx_key; + p += sprintf(p, "tx_key=%u\n", wnd->encr_info.tx_key_index); + p += sprintf(p, "key="); + tx_key = &wnd->encr_info.keys[wnd->encr_info.tx_key_index]; + if (tx_key->length > 0) + for (i = 0; i < tx_key->length; i++) + p += sprintf(p, "%2.2X", tx_key->key[i]); + else + p += sprintf(p, "off"); + p += sprintf(p, "\n"); + p += sprintf(p, "encr_mode=%d\n", encr_status); + } + res = mp_query_int(wnd, OID_802_11_AUTHENTICATION_MODE, &auth_mode); + if (!res) + p += sprintf(p, "auth_mode=%d\n", auth_mode); + res = mp_query_int(wnd, OID_802_11_INFRASTRUCTURE_MODE, &infra_mode); + p += sprintf(p, "mode=%s\n", (infra_mode == Ndis802_11IBSS) ? + "adhoc" : (infra_mode == Ndis802_11Infrastructure) ? + "managed" : "auto"); + if (p - page > count) { + WARNING("wrote %lu bytes (limit is %u)", + (unsigned long)(p - page), count); + *eof = 1; + } + + return p - page; +} + +static int procfs_read_ndis_hw(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + struct ndis_device *wnd = (struct ndis_device *)data; + struct ndis_configuration config; + unsigned int power_mode; + NDIS_STATUS res; + ndis_tx_power_level tx_power; + ULONG bit_rate; + ndis_rts_threshold rts_threshold; + ndis_fragmentation_threshold frag_threshold; + ndis_antenna antenna; + ULONG packet_filter; + int n; + mac_address mac; + char *hw_status[] = {"ready", "initializing", "resetting", "closing", + "not ready"}; + + if (off != 0) { + *eof = 1; + return 0; + } + + res = mp_query_int(wnd, OID_GEN_HARDWARE_STATUS, &n); + if (res == NDIS_STATUS_SUCCESS && + n >= 0 && n < sizeof(hw_status) / sizeof(hw_status[0])) + p += sprintf(p, "status=%s\n", hw_status[n]); + + res = mp_query(wnd, OID_802_3_CURRENT_ADDRESS, mac, sizeof(mac)); + if (!res) + p += sprintf(p, "mac: " MACSTRSEP "\n", MAC2STR(mac)); + res = mp_query(wnd, OID_802_11_CONFIGURATION, &config, sizeof(config)); + if (!res) { + p += sprintf(p, "beacon_period=%u msec\n", + config.beacon_period); + p += sprintf(p, "atim_window=%u msec\n", config.atim_window); + p += sprintf(p, "frequency=%u kHZ\n", config.ds_config); + p += sprintf(p, "hop_pattern=%u\n", + config.fh_config.hop_pattern); + p += sprintf(p, "hop_set=%u\n", + config.fh_config.hop_set); + p += sprintf(p, "dwell_time=%u msec\n", + config.fh_config.dwell_time); + } + + res = mp_query(wnd, OID_802_11_TX_POWER_LEVEL, + &tx_power, sizeof(tx_power)); + if (!res) + p += sprintf(p, "tx_power=%u mW\n", tx_power); + + res = mp_query(wnd, OID_GEN_LINK_SPEED, &bit_rate, sizeof(bit_rate)); + if (!res) + p += sprintf(p, "bit_rate=%u kBps\n", (u32)bit_rate / 10); + + res = mp_query(wnd, OID_802_11_RTS_THRESHOLD, + &rts_threshold, sizeof(rts_threshold)); + if (!res) + p += sprintf(p, "rts_threshold=%u bytes\n", rts_threshold); + + res = mp_query(wnd, OID_802_11_FRAGMENTATION_THRESHOLD, + &frag_threshold, sizeof(frag_threshold)); + if (!res) + p += sprintf(p, "frag_threshold=%u bytes\n", frag_threshold); + + res = mp_query_int(wnd, OID_802_11_POWER_MODE, &power_mode); + if (!res) + p += sprintf(p, "power_mode=%s\n", + (power_mode == NDIS_POWER_OFF) ? "always_on" : + (power_mode == NDIS_POWER_MAX) ? + "max_savings" : "min_savings"); + + res = mp_query(wnd, OID_802_11_NUMBER_OF_ANTENNAS, + &antenna, sizeof(antenna)); + if (!res) + p += sprintf(p, "num_antennas=%u\n", antenna); + + res = mp_query(wnd, OID_802_11_TX_ANTENNA_SELECTED, + &antenna, sizeof(antenna)); + if (!res) + p += sprintf(p, "tx_antenna=%u\n", antenna); + + res = mp_query(wnd, OID_802_11_RX_ANTENNA_SELECTED, + &antenna, sizeof(antenna)); + if (!res) + p += sprintf(p, "rx_antenna=%u\n", antenna); + + p += sprintf(p, "encryption_modes=%s%s%s%s%s%s%s\n", + test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ? + "WEP" : "none", + + test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ? + "; TKIP with WPA" : "", + test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ? + ", WPA2" : "", + test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ? + ", WPA2PSK" : "", + + test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ? + "; AES/CCMP with WPA" : "", + test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ? + ", WPA2" : "", + test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ? + ", WPA2PSK" : ""); + + res = mp_query_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, &packet_filter); + if (!res) { + if (packet_filter != wnd->packet_filter) + WARNING("wrong packet_filter? 0x%08x, 0x%08x\n", + packet_filter, wnd->packet_filter); + p += sprintf(p, "packet_filter: 0x%08x\n", packet_filter); + } + if (p - page > count) { + WARNING("wrote %lu bytes (limit is %u)", + (unsigned long)(p - page), count); + *eof = 1; + } + + return p - page; +} + +static int procfs_read_ndis_settings(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + struct ndis_device *wnd = (struct ndis_device *)data; + struct wrap_device_setting *setting; + + if (off != 0) { + *eof = 1; + return 0; + } + + p += sprintf(p, "hangcheck_interval=%d\n", + hangcheck_interval == 0 ? + (int)(wnd->hangcheck_interval / HZ) : -1); + + list_for_each_entry(setting, &wnd->wd->settings, list) { + p += sprintf(p, "%s=%s\n", setting->name, setting->value); + } + + list_for_each_entry(setting, &wnd->wd->driver->settings, list) { + p += sprintf(p, "%s=%s\n", setting->name, setting->value); + } + + return p - page; +} + +static int procfs_write_ndis_settings(struct file *file, const char __user *buf, + unsigned long count, void *data) +{ + struct ndis_device *wnd = (struct ndis_device *)data; + char setting[MAX_PROC_STR_LEN], *p; + unsigned int i; + NDIS_STATUS res; + + if (count > MAX_PROC_STR_LEN) + return -EINVAL; + + memset(setting, 0, sizeof(setting)); + if (copy_from_user(setting, buf, count)) + return -EFAULT; + + if ((p = strchr(setting, '\n'))) + *p = 0; + + if ((p = strchr(setting, '='))) + *p = 0; + + if (!strcmp(setting, "hangcheck_interval")) { + if (!p) + return -EINVAL; + p++; + i = simple_strtol(p, NULL, 10); + hangcheck_del(wnd); + if (i > 0) { + wnd->hangcheck_interval = i * HZ; + hangcheck_add(wnd); + } + } else if (!strcmp(setting, "suspend")) { + if (!p) + return -EINVAL; + p++; + i = simple_strtol(p, NULL, 10); + if (i <= 0 || i > 3) + return -EINVAL; + if (wrap_is_pci_bus(wnd->wd->dev_bus)) + i = wrap_pnp_suspend_pci_device(wnd->wd->pci.pdev, + PMSG_SUSPEND); + else +#ifdef ENABLE_USB + i = wrap_pnp_suspend_usb_device(wnd->wd->usb.intf, + PMSG_SUSPEND); +#else + i = -1; +#endif + if (i) + return -EINVAL; + } else if (!strcmp(setting, "resume")) { + if (wrap_is_pci_bus(wnd->wd->dev_bus)) + i = wrap_pnp_resume_pci_device(wnd->wd->pci.pdev); + else +#ifdef ENABLE_USB + i = wrap_pnp_resume_usb_device(wnd->wd->usb.intf); +#else + i = -1; +#endif + if (i) + return -EINVAL; + } else if (!strcmp(setting, "stats_enabled")) { + if (!p) + return -EINVAL; + p++; + i = simple_strtol(p, NULL, 10); + if (i > 0) + wnd->iw_stats_enabled = TRUE; + else + wnd->iw_stats_enabled = FALSE; + } else if (!strcmp(setting, "packet_filter")) { + if (!p) + return -EINVAL; + p++; + i = simple_strtol(p, NULL, 10); + res = mp_set_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, i); + if (res) + WARNING("setting packet_filter failed: %08X", res); + } else if (!strcmp(setting, "reinit")) { + if (ndis_reinit(wnd) != NDIS_STATUS_SUCCESS) + return -EFAULT; + } else { + struct ndis_configuration_parameter param; + struct unicode_string key; + struct ansi_string ansi; + + if (!p) + return -EINVAL; + p++; + RtlInitAnsiString(&ansi, p); + if (RtlAnsiStringToUnicodeString(¶m.data.string, &ansi, + TRUE) != STATUS_SUCCESS) + EXIT1(return -EFAULT); + param.type = NdisParameterString; + RtlInitAnsiString(&ansi, setting); + if (RtlAnsiStringToUnicodeString(&key, &ansi, + TRUE) != STATUS_SUCCESS) { + RtlFreeUnicodeString(¶m.data.string); + EXIT1(return -EINVAL); + } + NdisWriteConfiguration(&res, wnd->nmb, &key, ¶m); + RtlFreeUnicodeString(&key); + RtlFreeUnicodeString(¶m.data.string); + if (res != NDIS_STATUS_SUCCESS) + return -EFAULT; + } + return count; +} + +int wrap_procfs_add_ndis_device(struct ndis_device *wnd) +{ + struct proc_dir_entry *procfs_entry; + + if (wrap_procfs_entry == NULL) + return -ENOMEM; + + if (wnd->procfs_iface) { + ERROR("%s already registered?", wnd->netdev_name); + return -EINVAL; + } + wnd->procfs_iface = proc_mkdir(wnd->netdev_name, wrap_procfs_entry); + if (wnd->procfs_iface == NULL) { + ERROR("couldn't create proc directory"); + return -ENOMEM; + } + wnd->procfs_iface->uid = proc_uid; + wnd->procfs_iface->gid = proc_gid; + + procfs_entry = create_proc_entry("hw", S_IFREG | S_IRUSR | S_IRGRP, + wnd->procfs_iface); + if (procfs_entry == NULL) { + ERROR("couldn't create proc entry for 'hw'"); + goto err_hw; + } else { + procfs_entry->uid = proc_uid; + procfs_entry->gid = proc_gid; + procfs_entry->data = wnd; + procfs_entry->read_proc = procfs_read_ndis_hw; + } + + procfs_entry = create_proc_entry("stats", S_IFREG | S_IRUSR | S_IRGRP, + wnd->procfs_iface); + if (procfs_entry == NULL) { + ERROR("couldn't create proc entry for 'stats'"); + goto err_stats; + } else { + procfs_entry->uid = proc_uid; + procfs_entry->gid = proc_gid; + procfs_entry->data = wnd; + procfs_entry->read_proc = procfs_read_ndis_stats; + } + + procfs_entry = create_proc_entry("encr", S_IFREG | S_IRUSR | S_IRGRP, + wnd->procfs_iface); + if (procfs_entry == NULL) { + ERROR("couldn't create proc entry for 'encr'"); + goto err_encr; + } else { + procfs_entry->uid = proc_uid; + procfs_entry->gid = proc_gid; + procfs_entry->data = wnd; + procfs_entry->read_proc = procfs_read_ndis_encr; + } + + procfs_entry = create_proc_entry("settings", S_IFREG | + S_IRUSR | S_IRGRP | + S_IWUSR | S_IWGRP, wnd->procfs_iface); + if (procfs_entry == NULL) { + ERROR("couldn't create proc entry for 'settings'"); + goto err_settings; + } else { + procfs_entry->uid = proc_uid; + procfs_entry->gid = proc_gid; + procfs_entry->data = wnd; + procfs_entry->read_proc = procfs_read_ndis_settings; + procfs_entry->write_proc = procfs_write_ndis_settings; + } + return 0; + +err_settings: + remove_proc_entry("encr", wnd->procfs_iface); +err_encr: + remove_proc_entry("stats", wnd->procfs_iface); +err_stats: + remove_proc_entry("hw", wnd->procfs_iface); +err_hw: + remove_proc_entry(wnd->netdev_name, wrap_procfs_entry); + wnd->procfs_iface = NULL; + return -ENOMEM; +} + +void wrap_procfs_remove_ndis_device(struct ndis_device *wnd) +{ + struct proc_dir_entry *procfs_iface = xchg(&wnd->procfs_iface, NULL); + + if (procfs_iface == NULL) + return; + remove_proc_entry("hw", procfs_iface); + remove_proc_entry("stats", procfs_iface); + remove_proc_entry("encr", procfs_iface); + remove_proc_entry("settings", procfs_iface); + if (wrap_procfs_entry) + remove_proc_entry(wnd->netdev_name, wrap_procfs_entry); +} + +static int procfs_read_debug(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + enum alloc_type type; + + if (off != 0) { + *eof = 1; + return 0; + } + p += sprintf(p, "%d\n", debug); + type = 0; +#ifdef ALLOC_DEBUG + for (type = 0; type < ALLOC_TYPE_MAX; type++) + p += sprintf(p, "total size of allocations in %d: %d\n", + type, alloc_size(type)); +#endif + return p - page; +} + +static int procfs_write_debug(struct file *file, const char __user *buf, + unsigned long count, void *data) +{ + int i; + char setting[MAX_PROC_STR_LEN], *p; + + if (count > MAX_PROC_STR_LEN) + return -EINVAL; + + memset(setting, 0, sizeof(setting)); + if (copy_from_user(setting, buf, count)) + return -EFAULT; + + if ((p = strchr(setting, '\n'))) + *p = 0; + + if ((p = strchr(setting, '='))) + *p = 0; + + i = simple_strtol(setting, NULL, 10); + if (i >= 0 && i < 10) + debug = i; + else + return -EINVAL; + return count; +} + +int wrap_procfs_init(void) +{ + struct proc_dir_entry *procfs_entry; + + wrap_procfs_entry = proc_mkdir(DRIVER_NAME, proc_net_root); + if (wrap_procfs_entry == NULL) { + ERROR("couldn't create procfs directory"); + return -ENOMEM; + } + wrap_procfs_entry->uid = proc_uid; + wrap_procfs_entry->gid = proc_gid; + + procfs_entry = create_proc_entry("debug", S_IFREG | S_IRUSR | S_IRGRP, + wrap_procfs_entry); + if (procfs_entry == NULL) { + ERROR("couldn't create proc entry for 'debug'"); + return -ENOMEM; + } else { + procfs_entry->uid = proc_uid; + procfs_entry->gid = proc_gid; + procfs_entry->read_proc = procfs_read_debug; + procfs_entry->write_proc = procfs_write_debug; + } + return 0; +} + +void wrap_procfs_remove(void) +{ + if (wrap_procfs_entry == NULL) + return; + remove_proc_entry("debug", wrap_procfs_entry); + remove_proc_entry(DRIVER_NAME, proc_net_root); +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/rtl.c +++ linux-2.6.37/ubuntu/ndiswrapper/rtl.c @@ -0,0 +1,716 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ + +#include "ntoskernel.h" +#include "rtl_exports.h" + +wstdcall SIZE_T WIN_FUNC(RtlCompareMemory,3) + (const void *a, const void *b, SIZE_T len) +{ + size_t i; + char *x, *y; + + x = (char *)a; + y = (char *)b; + /* MSDN says this should return number of bytes that compare as + * equal. This can be interpretted as either all bytes that are + * equal in 'len' bytes or that only until the bytes compare as + * not equal. Initially we had it the former way, but Realtek driver + * doesn't like it that way - it takes many attempts to associate + * with WPA. ReactOS returns the number of bytes that are equal + * upto when they compare as not equal. + * According to lords at #reactos, that is the way it should be + * and that msdn is wrong about it! + */ + for (i = 0; i < len && x[i] == y[i]; i++) + ; + return i; +} + +wstdcall void WIN_FUNC(RtlCopyMemory,3) + (void *dst, const void *src, SIZE_T length) +{ + memcpy(dst, src, length); +} + +wstdcall void WIN_FUNC(RtlZeroMemory,2) + (void *dst, SIZE_T length) +{ + memset(dst, 0, length); +} + +wstdcall void WIN_FUNC(RtlSecureZeroMemory,2) + (void *dst, SIZE_T length) +{ + memset(dst, 0, length); +} + +wstdcall void WIN_FUNC(RtlFillMemory,3) + (void *dest, SIZE_T length, UCHAR fill) +{ + memset(dest, fill, length); +} + +wstdcall void WIN_FUNC(RtlMoveMemory,3) + (void *dest, const void *src, SIZE_T length) +{ + memmove(dest, src, length); +} + +wstdcall LONG WIN_FUNC(RtlCompareString,3) + (const struct ansi_string *s1, const struct ansi_string *s2, + BOOLEAN case_insensitive) +{ + unsigned int len; + LONG ret = 0; + const char *p1, *p2; + + ENTER2(""); + len = min(s1->length, s2->length); + p1 = s1->buf; + p2 = s2->buf; + if (case_insensitive) + while (!ret && len--) + ret = toupper(*p1++) - toupper(*p2++); + else + while (!ret && len--) + ret = *p1++ - *p2++; + if (!ret) + ret = s1->length - s2->length; + EXIT2(return ret); +} + +wstdcall LONG WIN_FUNC(RtlCompareUnicodeString,3) + (const struct unicode_string *s1, const struct unicode_string *s2, + BOOLEAN case_insensitive) +{ + unsigned int len; + LONG ret = 0; + const wchar_t *p1, *p2; + + ENTER2(""); + + len = min(s1->length, s2->length) / sizeof(wchar_t); + p1 = s1->buf; + p2 = s2->buf; + if (case_insensitive) + while (!ret && len--) + ret = toupper((u8)*p1++) - toupper((u8)*p2++); + else + while (!ret && len--) + ret = (u8)*p1++ - (u8)*p2++; + if (!ret) + ret = s1->length - s2->length; + TRACE2("len: %d, ret: %d", len, ret); + EXIT2(return ret); +} + +wstdcall BOOLEAN WIN_FUNC(RtlEqualString,3) + (const struct ansi_string *s1, const struct ansi_string *s2, + BOOLEAN case_insensitive) +{ + ENTER1(""); + if (s1->length != s2->length) + return FALSE; + return !RtlCompareString(s1, s2, case_insensitive); +} + +wstdcall BOOLEAN WIN_FUNC(RtlEqualUnicodeString,3) + (const struct unicode_string *s1, const struct unicode_string *s2, + BOOLEAN case_insensitive) +{ + if (s1->length != s2->length) + return FALSE; + return !RtlCompareUnicodeString(s1, s2, case_insensitive); +} + +wstdcall void WIN_FUNC(RtlCopyUnicodeString,2) + (struct unicode_string *dst, struct unicode_string *src) +{ + ENTER1("%p, %p", dst, src); + if (src && src->buf && dst->buf) { + dst->length = min(src->length, dst->max_length); + memcpy(dst->buf, src->buf, dst->length); + if (dst->length < dst->max_length) + dst->buf[dst->length / sizeof(dst->buf[0])] = 0; + } else + dst->length = 0; + EXIT1(return); +} + +wstdcall void WIN_FUNC(RtlCopyString,2) + (struct ansi_string *dst, struct ansi_string *src) +{ + ENTER1("%p, %p", dst, src); + if (src && src->buf && dst->buf) { + dst->length = min(src->length, dst->max_length); + memcpy(dst->buf, src->buf, dst->length); + if (dst->length < dst->max_length) + dst->buf[dst->length] = 0; + } else + dst->length = 0; + EXIT1(return); +} + +wstdcall NTSTATUS WIN_FUNC(RtlAppendUnicodeToString,2) + (struct unicode_string *dst, wchar_t *src) +{ + if (src) { + int len; + for (len = 0; src[len]; len++) + ; + if (dst->length + (len * sizeof(dst->buf[0])) > dst->max_length) + return STATUS_BUFFER_TOO_SMALL; + memcpy(&dst->buf[dst->length], src, len * sizeof(dst->buf[0])); + dst->length += len * sizeof(dst->buf[0]); + if (dst->max_length > dst->length) + dst->buf[dst->length / sizeof(dst->buf[0])] = 0; + } + return STATUS_SUCCESS; +} + +wstdcall NTSTATUS WIN_FUNC(RtlAppendUnicodeStringToString,2) + (struct unicode_string *dst, struct unicode_string *src) +{ + if (dst->max_length < src->length + dst->length) + return STATUS_BUFFER_TOO_SMALL; + if (src->length) { + memcpy(&dst->buf[dst->length], src->buf, src->length); + dst->length += src->length; + if (dst->max_length > dst->length) + dst->buf[dst->length / sizeof(dst->buf[0])] = 0; + } + EXIT2(return STATUS_SUCCESS); +} + +wstdcall ULONG WIN_FUNC(RtlxAnsiStringToUnicodeSize,1) + (const struct ansi_string *string) +{ + int i; + + for (i = 0; i < string->max_length && string->buf[i]; i++) + ; + return i * sizeof(wchar_t); +} + +wstdcall ULONG WIN_FUNC(RtlxUnicodeStringToAnsiSize,1) + (const struct unicode_string *string) +{ + int i; + + for (i = 0; i < string->max_length && string->buf[i]; i++) + ; + return i; +} + +wstdcall NTSTATUS WIN_FUNC(RtlAnsiStringToUnicodeString,3) + (struct unicode_string *dst, const struct ansi_string *src, + BOOLEAN alloc) +{ + int i, n; + + n = RtlxAnsiStringToUnicodeSize(src); + TRACE2("%d, %d, %d, %d, %p", n, dst->max_length, src->length, + src->max_length, src->buf); + if (alloc == TRUE) { +#if 0 + if (n == 0) { + dst->length = dst->max_length = 0; + dst->buf = NULL; + EXIT2(return STATUS_SUCCESS); + } +#endif + dst->max_length = n + sizeof(dst->buf[0]); + dst->buf = ExAllocatePoolWithTag(NonPagedPool, + dst->max_length, 0); + if (!dst->buf) { + dst->max_length = dst->length = 0; + EXIT2(return STATUS_NO_MEMORY); + } + } else if (dst->max_length < n) + EXIT2(return STATUS_BUFFER_TOO_SMALL); + + dst->length = n; + n /= sizeof(dst->buf[0]); + for (i = 0; i < n; i++) + dst->buf[i] = src->buf[i]; + if (i * sizeof(dst->buf[0]) < dst->max_length) + dst->buf[i] = 0; + TRACE2("dst: length: %d, max_length: %d, string: %p", + dst->length, dst->max_length, src->buf); + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(RtlUnicodeStringToAnsiString,3) + (struct ansi_string *dst, const struct unicode_string *src, + BOOLEAN alloc) +{ + int i, n; + + n = RtlxUnicodeStringToAnsiSize(src); + TRACE2("%d, %d, %d, %d, %p", n, dst->max_length, src->length, + src->max_length, src->buf); + if (alloc == TRUE) { +#if 0 + if (n == 0) { + dst->length = dst->max_length = 0; + dst->buf = NULL; + EXIT2(return STATUS_SUCCESS); + } +#endif + dst->max_length = n + sizeof(dst->buf[0]); + dst->buf = ExAllocatePoolWithTag(NonPagedPool, + dst->max_length, 0); + if (!dst->buf) { + dst->max_length = dst->length = 0; + EXIT1(return STATUS_NO_MEMORY); + } + } else if (dst->max_length < n) + EXIT2(return STATUS_BUFFER_TOO_SMALL); + + dst->length = n; + for (i = 0; i < n; i++) + dst->buf[i] = src->buf[i]; + if (i < dst->max_length) + dst->buf[i] = 0; + TRACE2("string: %p, len: %d(%d)", dst->buf, dst->length, + dst->max_length); + EXIT2(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(RtlUnicodeStringToInteger,3) + (struct unicode_string *ustring, ULONG base, ULONG *value) +{ + int i, sign = 1; + ULONG res; + typeof(ustring->buf) string; + + if (ustring->length == 0) { + *value = 0; + return STATUS_SUCCESS; + } + + string = ustring->buf; + i = 0; + while (i < (ustring->length / sizeof(*string)) && string[i] == ' ') + i++; + if (string[i] == '+') + i++; + else if (string[i] == '-') { + i++; + sign = -1; + } + if (base == 0) { + base = 10; + if (i <= ((ustring->length / sizeof(*string)) - 2) && + string[i] == '0') { + i++; + if (string[i] == 'b') { + base = 2; + i++; + } else if (string[i] == 'o') { + base = 8; + i++; + } else if (string[i] == 'x') { + base = 16; + i++; + } + } + } + if (!(base == 2 || base == 8 || base == 10 || base == 16)) + EXIT2(return STATUS_INVALID_PARAMETER); + + for (res = 0; i < (ustring->length / sizeof(*string)); i++) { + int v; + if (isdigit((char)string[i])) + v = string[i] - '0'; + else if (isxdigit((char)string[i])) + v = tolower((char)string[i]) - 'a' + 10; + else + v = base; + if (v >= base) + EXIT2(return STATUS_INVALID_PARAMETER); + res = res * base + v; + } + *value = sign * res; + EXIT3(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(RtlCharToInteger,3) + (const char *string, ULONG base, ULONG *value) +{ + int sign = 1; + ULONG res; + + if (!string || !value) + EXIT2(return STATUS_INVALID_PARAMETER); + while (*string == ' ') + string++; + if (*string == '+') + string++; + else if (*string == '-') { + string++; + sign = -1; + } + if (base == 0) { + base = 10; + if (*string == '0') { + string++; + if (*string == 'b') { + base = 2; + string++; + } else if (*string == 'o') { + base = 8; + string++; + } else if (*string == 'x') { + base = 16; + string++; + } + } + } + if (!(base == 2 || base == 8 || base == 10 || base == 16)) + EXIT2(return STATUS_INVALID_PARAMETER); + + for (res = 0; *string; string++) { + int v; + if (isdigit(*string)) + v = *string - '0'; + else if (isxdigit(*string)) + v = tolower(*string) - 'a' + 10; + else + v = base; + if (v >= base) + EXIT2(return STATUS_INVALID_PARAMETER); + res = res * base + v; + } + *value = sign * res; + EXIT3(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(RtlIntegerToUnicodeString,3) + (ULONG value, ULONG base, struct unicode_string *ustring) +{ + typeof(ustring->buf) buf = ustring->buf; + int i; + + if (base == 0) + base = 10; + if (!(base == 2 || base == 8 || base == 10 || base == 16)) + return STATUS_INVALID_PARAMETER; + for (i = 0; value && i < ustring->max_length / sizeof(*buf); i++) { + int r; + r = value % base; + value /= base; + if (r < 10) + buf[i] = r + '0'; + else + buf[i] = r + 'a' - 10; + } + if (value) + return STATUS_BUFFER_OVERFLOW; + ustring->length = i * sizeof(*buf); + return STATUS_SUCCESS; +} + +wstdcall LARGE_INTEGER WIN_FUNC(RtlConvertUlongToLargeInteger,1) + (ULONG ul) +{ + LARGE_INTEGER li = ul; + return li; +} + +wfastcall USHORT WIN_FUNC(RtlUshortByteSwap,1) + (USHORT src) +{ + return __swab16(src); +} + +wfastcall ULONG WIN_FUNC(RtlUlongByteSwap,1) + (ULONG src) +{ + /* ULONG is 32 bits for both 32-bit and 64-bit architectures */ + return __swab32(src); +} + +wstdcall NTSTATUS WIN_FUNC(RtlUpcaseUnicodeString,3) + (struct unicode_string *dst, struct unicode_string *src, BOOLEAN alloc) +{ + USHORT i, n; + + if (alloc) { + dst->buf = ExAllocatePoolWithTag(NonPagedPool, src->length, 0); + if (dst->buf) + dst->max_length = src->length; + else + EXIT2(return STATUS_NO_MEMORY); + } else { + if (dst->max_length < src->length) + EXIT2(return STATUS_BUFFER_OVERFLOW); + } + + n = src->length / sizeof(src->buf[0]); + for (i = 0; i < n; i++) + dst->buf[i] = toupper(src->buf[i]); + + dst->length = src->length; + EXIT3(return STATUS_SUCCESS); +} + +wstdcall void WIN_FUNC(RtlInitUnicodeString,2) + (struct unicode_string *dst, const wchar_t *src) +{ + ENTER2("%p", dst); + if (dst == NULL) + EXIT1(return); + if (src == NULL) { + dst->max_length = dst->length = 0; + dst->buf = NULL; + } else { + int i; + for (i = 0; (char)src[i]; i++) + ; + dst->buf = (typeof(dst->buf))src; + dst->length = i * sizeof(dst->buf[0]); + dst->max_length = (i + 1) * sizeof(dst->buf[0]); + } + EXIT1(return); +} + +wstdcall void WIN_FUNC(RtlInitAnsiString,2) + (struct ansi_string *dst, const char *src) +{ + ENTER2("%p", dst); + if (dst == NULL) + EXIT2(return); + if (src == NULL) { + dst->max_length = dst->length = 0; + dst->buf = NULL; + } else { + int i; + for (i = 0; src[i]; i++) + ; + dst->buf = (typeof(dst->buf))src; + dst->length = i; + dst->max_length = i + 1; + } + TRACE2("%p", dst->buf); + EXIT2(return); +} + +wstdcall void WIN_FUNC(RtlInitString,2) + (struct ansi_string *dst, const char *src) +{ + ENTER2("%p", dst); + RtlInitAnsiString(dst, src); + EXIT2(return); +} + +wstdcall void WIN_FUNC(RtlFreeUnicodeString,1) + (struct unicode_string *string) +{ + ENTER2("%p", string); + if (string == NULL) + return; + if (string->buf) + ExFreePool(string->buf); + string->length = string->max_length = 0; + string->buf = NULL; + return; +} + +wstdcall void WIN_FUNC(RtlFreeAnsiString,1) + (struct ansi_string *string) +{ + ENTER2("%p", string); + if (string == NULL) + return; + if (string->buf) + ExFreePool(string->buf); + string->length = string->max_length = 0; + string->buf = NULL; + return; +} + +/* guid string is of the form: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */ +wstdcall NTSTATUS WIN_FUNC(RtlGUIDFromString,2) + (struct unicode_string *guid_string, struct guid *guid) +{ + struct ansi_string ansi; + NTSTATUS ret; + int i, j, k, l, m; + + ret = RtlUnicodeStringToAnsiString(&ansi, guid_string, TRUE); + if (ret != STATUS_SUCCESS) + return ret; + if (ansi.length != 37 || ansi.buf[0] != '{' || + ansi.buf[36] != '}' || ansi.buf[9] != '-' || + ansi.buf[14] != '-' || ansi.buf[19] != '-' || + ansi.buf[24] != '-') { + RtlFreeAnsiString(&ansi); + EXIT2(return STATUS_INVALID_PARAMETER); + } + memcpy(&guid->data4, &ansi.buf[29], sizeof(guid->data3)); + /* set end of data3 for scanf */ + ansi.buf[29] = 0; + if (sscanf(&ansi.buf[1], "%x", &i) == 1 && + sscanf(&ansi.buf[10], "%x", &j) == 1 && + sscanf(&ansi.buf[15], "%x", &k) == 1 && + sscanf(&ansi.buf[20], "%x", &l) == 1 && + sscanf(&ansi.buf[25], "%x", &m) == 1) { + guid->data1 = (i << 16) | (j < 8) | k; + guid->data2 = l; + guid->data3 = m; + ret = STATUS_SUCCESS; + } else + ret = STATUS_INVALID_PARAMETER; + RtlFreeAnsiString(&ansi); + return ret; +} + +wstdcall NTSTATUS WIN_FUNC(RtlQueryRegistryValues,5) + (ULONG relative, wchar_t *path, struct rtl_query_registry_table *tbl, + void *context, void *env) +{ + struct ansi_string ansi; + struct unicode_string unicode; + NTSTATUS status, ret; + static int i = 0; + + ENTER3("%x, %p", relative, tbl); +// TODO(); + + RtlInitUnicodeString(&unicode, path); + if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) == + STATUS_SUCCESS) { + TRACE2("%s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + ret = STATUS_SUCCESS; + for (; tbl->name; tbl++) { + RtlInitUnicodeString(&unicode, tbl->name); + if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) == + STATUS_SUCCESS) { + TRACE2("name: %s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + TRACE2("flags: %08X", tbl->flags); + if (tbl->flags == RTL_QUERY_REGISTRY_DIRECT) { + TRACE2("type: %08X", tbl->def_type); + if (tbl->def_type == REG_DWORD) { + /* Atheros USB driver needs this, but + * don't know where and how to get its + * value */ + if (tbl->def_data) { + TRACE2("def_data: %x", + *(int *)tbl->def_data); + *(DWORD *)tbl->context = 0x5f292a + i++; +// *(DWORD *)tbl->def_data; + } else + *(DWORD *)tbl->context = 0x2345dbe; + } + } else { + void *data; + ULONG type, length; + + if (!tbl->query_func) { + ERROR("oops: no query_func"); + ret = STATUS_INVALID_PARAMETER; + break; + } + if (tbl->flags & RTL_QUERY_REGISTRY_NOVALUE) { + data = NULL; + type = REG_NONE; + length = 0; + } else { + data = tbl->def_data; + type = tbl->def_type; + length = tbl->def_length;; + } + TRACE2("calling query_func: %p", tbl->query_func); + status = LIN2WIN6(tbl->query_func, tbl->name, type, + data, length, context, env); + TRACE2("status: %08X", status); + if (status) { + if (status == STATUS_BUFFER_TOO_SMALL) + ret = STATUS_BUFFER_TOO_SMALL; + else + EXIT2(return STATUS_INVALID_PARAMETER); + } + } + } + EXIT3(return ret); +} + +wstdcall NTSTATUS WIN_FUNC(RtlWriteRegistryValue,6) + (ULONG relative, wchar_t *path, wchar_t *name, ULONG type, + void *data, ULONG length) +{ + struct ansi_string ansi; + struct unicode_string unicode; + + ENTER3("%d", relative); + TODO(); + + RtlInitUnicodeString(&unicode, path); + if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) == + STATUS_SUCCESS) { + TRACE2("%s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + RtlInitUnicodeString(&unicode, name); + if (RtlUnicodeStringToAnsiString(&ansi, &unicode, TRUE) == + STATUS_SUCCESS) { + TRACE2("%s", ansi.buf); + RtlFreeAnsiString(&ansi); + } + EXIT5(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS WIN_FUNC(RtlDeleteRegistryValue,3) + (ULONG relative, wchar_t *path, wchar_t *name) +{ + return STATUS_SUCCESS; +} + +wstdcall void WIN_FUNC(RtlAssert,4) + (char *failed_assertion, char *file_name, ULONG line_num, char *message) +{ + ERROR("assertion '%s' failed at %s line %d%s", + failed_assertion, file_name, line_num, message ? message : ""); + return; +} + +wstdcall void WIN_FUNC(RtlUnwind,0) + (void) +{ + TODO(); +} + +wstdcall void WIN_FUNC(RtlRaiseException,1) + (void *exception_record) +{ + TODO(); +} + +int rtl_init(void) +{ + return 0; +} + +/* called when module is being removed */ +void rtl_exit(void) +{ + EXIT4(return); +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/usb.c +++ linux-2.6.37/ubuntu/ndiswrapper/usb.c @@ -0,0 +1,1457 @@ +/* + * Copyright (C) 2004 Jan Kiszka + * Copyright (C) 2005 Giridhar Pemmasani + * + * 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. + * + */ + +#include "ndis.h" +#include "usb.h" +#include "usb_exports.h" + +#ifdef USB_DEBUG +static unsigned int urb_id = 0; + +#define DUMP_WRAP_URB(wrap_urb, dir) \ + USBTRACE("urb %p (%d) %s: buf: %p, len: %d, pipe: 0x%x, %d", \ + (wrap_urb)->urb, (wrap_urb)->id, \ + (dir == USB_DIR_OUT) ? "going down" : "coming back", \ + (wrap_urb)->urb->transfer_buffer, \ + (wrap_urb)->urb->transfer_buffer_length, \ + (wrap_urb)->urb->pipe, (wrap_urb)->urb->status) + +#define DUMP_URB_BUFFER(urb, dir) \ + while (debug >= 2) { \ + int i; \ + char msg[20], *t; \ + if (!urb->transfer_buffer) \ + break; \ + if (!((usb_pipein(urb->pipe) && dir == USB_DIR_IN) || \ + (usb_pipeout(urb->pipe) && dir == USB_DIR_OUT))) \ + break; \ + t = msg; \ + t += sprintf(t, "%d: ", (urb)->actual_length); \ + for (i = 0; i < urb->actual_length && \ + t < &msg[sizeof(msg) - 4]; i++) \ + t += sprintf(t, "%02X ", \ + ((char *)urb->transfer_buffer)[i]); \ + *t = 0; \ + USBTRACE("%s", msg); \ + break; \ + } + +#else + +#define DUMP_WRAP_URB(wrap_urb, dir) (void)0 +#define DUMP_URB_BUFFER(urb, dir) (void)0 + +#endif + +#define CUR_ALT_SETTING(intf) (intf)->cur_altsetting + +#ifndef USB_CTRL_SET_TIMEOUT +#define USB_CTRL_SET_TIMEOUT 5000 +#endif + +#ifndef USB_CTRL_GET_TIMEOUT +#define USB_CTRL_GET_TIMEOUT 5000 +#endif + +#ifndef URB_NO_TRANSFER_DMA_MAP +#define URB_NO_TRANSFER_DMA_MAP 0 +#endif + +/* wrap_urb->flags */ +/* transfer_buffer for urb is allocated; free it in wrap_free_urb */ +#define WRAP_URB_COPY_BUFFER 0x01 + +static int inline wrap_cancel_urb(struct wrap_urb *wrap_urb) +{ + int ret; + USBTRACE("%p, %p, %d", wrap_urb, wrap_urb->urb, wrap_urb->state); + if (wrap_urb->state != URB_SUBMITTED) + USBEXIT(return -1); + ret = usb_unlink_urb(wrap_urb->urb); + USBTRACE("ret: %d", ret); + if (ret == -EINPROGRESS) + return 0; + else { + WARNING("unlink failed: %d", ret); + return ret; + } +} + +#define URB_STATUS(wrap_urb) (wrap_urb->urb->status) + +static struct nt_list wrap_urb_complete_list; +static spinlock_t wrap_urb_complete_list_lock; + +static work_struct_t wrap_urb_complete_work; +static void wrap_urb_complete_worker(worker_param_t dummy); + +static void kill_all_urbs(struct wrap_device *wd, int complete) +{ + struct nt_list *ent; + struct wrap_urb *wrap_urb; + KIRQL irql; + + USBTRACE("%d", wd->usb.num_alloc_urbs); + while (1) { + IoAcquireCancelSpinLock(&irql); + ent = RemoveHeadList(&wd->usb.wrap_urb_list); + IoReleaseCancelSpinLock(irql); + if (!ent) + break; + wrap_urb = container_of(ent, struct wrap_urb, list); + if (wrap_urb->state == URB_SUBMITTED) { + WARNING("Windows driver %s didn't free urb: %p", + wd->driver->name, wrap_urb->urb); + if (!complete) + wrap_urb->urb->complete = NULL; + usb_kill_urb(wrap_urb->urb); + } + USBTRACE("%p, %p", wrap_urb, wrap_urb->urb); + usb_free_urb(wrap_urb->urb); + kfree(wrap_urb); + } + wd->usb.num_alloc_urbs = 0; +} + +/* for a given Linux urb status code, return corresponding NT urb status */ +static USBD_STATUS wrap_urb_status(int urb_status) +{ + switch (urb_status) { + case 0: + return USBD_STATUS_SUCCESS; + case -EPROTO: + return USBD_STATUS_TIMEOUT; + case -EILSEQ: + return USBD_STATUS_CRC; + case -EPIPE: + return USBD_STATUS_INVALID_PIPE_HANDLE; + case -ECOMM: + return USBD_STATUS_DATA_OVERRUN; + case -ENOSR: + return USBD_STATUS_DATA_UNDERRUN; + case -EOVERFLOW: + return USBD_STATUS_BABBLE_DETECTED; + case -EREMOTEIO: + return USBD_STATUS_ERROR_SHORT_TRANSFER;; + case -ENODEV: + case -ESHUTDOWN: + case -ENOENT: + return USBD_STATUS_DEVICE_GONE; + case -ENOMEM: + return USBD_STATUS_NO_MEMORY; + case -EINVAL: + return USBD_STATUS_REQUEST_FAILED; + default: + return USBD_STATUS_NOT_SUPPORTED; + } +} + +/* for a given USBD_STATUS, return its corresponding NTSTATUS (for irp) */ +static NTSTATUS nt_urb_irp_status(USBD_STATUS nt_urb_status) +{ + switch (nt_urb_status) { + case USBD_STATUS_SUCCESS: + return STATUS_SUCCESS; + case USBD_STATUS_DEVICE_GONE: + return STATUS_DEVICE_REMOVED; + case USBD_STATUS_PENDING: + return STATUS_PENDING; + case USBD_STATUS_NOT_SUPPORTED: + return STATUS_NOT_IMPLEMENTED; + case USBD_STATUS_NO_MEMORY: + return STATUS_NO_MEMORY; + case USBD_STATUS_REQUEST_FAILED: + return STATUS_NOT_SUPPORTED; + default: + return STATUS_FAILURE; + } +} + +static void wrap_free_urb(struct urb *urb) +{ + struct irp *irp; + struct wrap_urb *wrap_urb; + + USBTRACE("freeing urb: %p", urb); + wrap_urb = urb->context; + irp = wrap_urb->irp; + if (wrap_urb->flags & WRAP_URB_COPY_BUFFER) { + USBTRACE("freeing DMA buffer for URB: %p %p", + urb, urb->transfer_buffer); + usb_free_coherent(IRP_WRAP_DEVICE(irp)->usb.udev, + urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); + } + if (urb->setup_packet) + kfree(urb->setup_packet); + if (IRP_WRAP_DEVICE(irp)->usb.num_alloc_urbs > MAX_ALLOCATED_URBS) { + IoAcquireCancelSpinLock(&irp->cancel_irql); + RemoveEntryList(&wrap_urb->list); + IRP_WRAP_DEVICE(irp)->usb.num_alloc_urbs--; + IoReleaseCancelSpinLock(irp->cancel_irql); + usb_free_urb(urb); + kfree(wrap_urb); + } else { + wrap_urb->state = URB_FREE; + wrap_urb->flags = 0; + wrap_urb->irp = NULL; + } + return; +} + +void wrap_suspend_urbs(struct wrap_device *wd) +{ + /* TODO: do we need to cancel urbs? */ + USBTRACE("%p, %d", wd, wd->usb.num_alloc_urbs); +} + +void wrap_resume_urbs(struct wrap_device *wd) +{ + /* TODO: do we need to resubmit urbs? */ + USBTRACE("%p, %d", wd, wd->usb.num_alloc_urbs); +} + +wstdcall void wrap_cancel_irp(struct device_object *dev_obj, struct irp *irp) +{ + struct urb *urb; + + /* NB: this function is called holding Cancel spinlock */ + USBENTER("irp: %p", irp); + urb = IRP_WRAP_URB(irp)->urb; + USBTRACE("canceling urb %p", urb); + if (wrap_cancel_urb(IRP_WRAP_URB(irp))) { + irp->cancel = FALSE; + ERROR("urb %p can't be canceled: %d", urb, + IRP_WRAP_URB(irp)->state); + } else + USBTRACE("urb %p canceled", urb); + IoReleaseCancelSpinLock(irp->cancel_irql); + return; +} +WIN_FUNC_DECL(wrap_cancel_irp,2) + +static struct urb *wrap_alloc_urb(struct irp *irp, unsigned int pipe, + void *buf, unsigned int buf_len) +{ + struct urb *urb; + gfp_t alloc_flags; + struct wrap_urb *wrap_urb; + struct wrap_device *wd; + + USBENTER("irp: %p", irp); + wd = IRP_WRAP_DEVICE(irp); + alloc_flags = irql_gfp(); + IoAcquireCancelSpinLock(&irp->cancel_irql); + urb = NULL; + nt_list_for_each_entry(wrap_urb, &wd->usb.wrap_urb_list, list) { + if (cmpxchg(&wrap_urb->state, URB_FREE, + URB_ALLOCATED) == URB_FREE) { + urb = wrap_urb->urb; + usb_init_urb(urb); + break; + } + } + if (!urb) { + IoReleaseCancelSpinLock(irp->cancel_irql); + wrap_urb = kzalloc(sizeof(*wrap_urb), alloc_flags); + if (!wrap_urb) { + WARNING("couldn't allocate memory"); + return NULL; + } + urb = usb_alloc_urb(0, alloc_flags); + if (!urb) { + WARNING("couldn't allocate urb"); + kfree(wrap_urb); + return NULL; + } + IoAcquireCancelSpinLock(&irp->cancel_irql); + wrap_urb->urb = urb; + wrap_urb->state = URB_ALLOCATED; + InsertTailList(&wd->usb.wrap_urb_list, &wrap_urb->list); + wd->usb.num_alloc_urbs++; + } + +#ifdef URB_ASYNC_UNLINK + urb->transfer_flags |= URB_ASYNC_UNLINK; +#elif defined(USB_ASYNC_UNLINK) + urb->transfer_flags |= USB_ASYNC_UNLINK; +#endif + urb->context = wrap_urb; + wrap_urb->irp = irp; + IRP_WRAP_URB(irp) = wrap_urb; + /* called as Windows function */ + irp->cancel_routine = WIN_FUNC_PTR(wrap_cancel_irp,2); + IoReleaseCancelSpinLock(irp->cancel_irql); + USBTRACE("urb: %p", urb); + + urb->transfer_buffer_length = buf_len; + if (buf_len && buf && (!virt_addr_valid(buf) +#if defined(CONFIG_HIGHMEM) || defined(CONFIG_HIGHMEM4G) + || PageHighMem(virt_to_page(buf)) +#endif + )) { + urb->transfer_buffer = + usb_alloc_coherent(wd->usb.udev, buf_len, alloc_flags, + &urb->transfer_dma); + if (!urb->transfer_buffer) { + WARNING("couldn't allocate dma buf"); + IoAcquireCancelSpinLock(&irp->cancel_irql); + wrap_urb->state = URB_FREE; + wrap_urb->irp = NULL; + IRP_WRAP_URB(irp) = NULL; + IoReleaseCancelSpinLock(irp->cancel_irql); + return NULL; + } + if (urb->transfer_dma) + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + wrap_urb->flags |= WRAP_URB_COPY_BUFFER; + if (usb_pipeout(pipe)) + memcpy(urb->transfer_buffer, buf, buf_len); + USBTRACE("DMA buf for urb %p: %p", urb, urb->transfer_buffer); + } else + urb->transfer_buffer = buf; + return urb; +} + +static USBD_STATUS wrap_submit_urb(struct irp *irp) +{ + int ret; + struct urb *urb; + union nt_urb *nt_urb; + + urb = IRP_WRAP_URB(irp)->urb; + nt_urb = IRP_URB(irp); +#ifdef USB_DEBUG + if (IRP_WRAP_URB(irp)->state != URB_ALLOCATED) { + ERROR("urb %p is in wrong state: %d", + urb, IRP_WRAP_URB(irp)->state); + NT_URB_STATUS(nt_urb) = USBD_STATUS_REQUEST_FAILED; + return NT_URB_STATUS(nt_urb); + } + IRP_WRAP_URB(irp)->id = pre_atomic_add(urb_id, 1); +#endif + DUMP_WRAP_URB(IRP_WRAP_URB(irp), USB_DIR_OUT); + irp->io_status.status = STATUS_PENDING; + irp->io_status.info = 0; + NT_URB_STATUS(nt_urb) = USBD_STATUS_PENDING; + IoMarkIrpPending(irp); + DUMP_URB_BUFFER(urb, USB_DIR_OUT); + USBTRACE("%p", urb); + IRP_WRAP_URB(irp)->state = URB_SUBMITTED; + ret = usb_submit_urb(urb, irql_gfp()); + if (ret) { + USBTRACE("ret: %d", ret); + wrap_free_urb(urb); + /* we assume that IRP was not in pending state before */ + IoUnmarkIrpPending(irp); + NT_URB_STATUS(nt_urb) = wrap_urb_status(ret); + USBEXIT(return NT_URB_STATUS(nt_urb)); + } else + USBEXIT(return USBD_STATUS_PENDING); +} + +static void wrap_urb_complete(struct urb *urb ISR_PT_REGS_PARAM_DECL) +{ + struct irp *irp; + struct wrap_urb *wrap_urb; + + wrap_urb = urb->context; + USBTRACE("%p (%p) completed", wrap_urb, urb); + irp = wrap_urb->irp; + DUMP_WRAP_URB(wrap_urb, USB_DIR_IN); + irp->cancel_routine = NULL; +#ifdef USB_DEBUG + if (wrap_urb->state != URB_SUBMITTED) { + WARNING("urb %p in wrong state: %d (%d)", urb, wrap_urb->state, + urb->status); + return; + } +#endif + wrap_urb->state = URB_COMPLETED; + spin_lock(&wrap_urb_complete_list_lock); + InsertTailList(&wrap_urb_complete_list, &wrap_urb->complete_list); + spin_unlock(&wrap_urb_complete_list_lock); + schedule_ntos_work(&wrap_urb_complete_work); +} + +/* one worker for all devices */ +static void wrap_urb_complete_worker(worker_param_t dummy) +{ + struct irp *irp; + struct urb *urb; + struct usbd_bulk_or_intr_transfer *bulk_int_tx; + struct usbd_vendor_or_class_request *vc_req; + union nt_urb *nt_urb; + struct wrap_urb *wrap_urb; + struct nt_list *ent; + unsigned long flags; + + USBENTER(""); + while (1) { + spin_lock_irqsave(&wrap_urb_complete_list_lock, flags); + ent = RemoveHeadList(&wrap_urb_complete_list); + spin_unlock_irqrestore(&wrap_urb_complete_list_lock, flags); + if (!ent) + break; + wrap_urb = container_of(ent, struct wrap_urb, complete_list); + urb = wrap_urb->urb; +#ifdef USB_DEBUG + if (wrap_urb->state != URB_COMPLETED && + wrap_urb->state != URB_INT_UNLINKED) + WARNING("urb %p in wrong state: %d", + urb, wrap_urb->state); +#endif + irp = wrap_urb->irp; + DUMP_IRP(irp); + nt_urb = IRP_URB(irp); + USBTRACE("urb: %p, nt_urb: %p, status: %d", + urb, nt_urb, urb->status); + switch (urb->status) { + case 0: + /* succesfully transferred */ + irp->io_status.info = urb->actual_length; + if (nt_urb->header.function == + URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) { + bulk_int_tx = &nt_urb->bulk_int_transfer; + bulk_int_tx->transfer_buffer_length = + urb->actual_length; + DUMP_URB_BUFFER(urb, USB_DIR_IN); + if ((wrap_urb->flags & WRAP_URB_COPY_BUFFER) && + usb_pipein(urb->pipe)) + memcpy(bulk_int_tx->transfer_buffer, + urb->transfer_buffer, + urb->actual_length); + } else { // vendor or class request + vc_req = &nt_urb->vendor_class_request; + vc_req->transfer_buffer_length = + urb->actual_length; + DUMP_URB_BUFFER(urb, USB_DIR_IN); + if ((wrap_urb->flags & WRAP_URB_COPY_BUFFER) && + usb_pipein(urb->pipe)) + memcpy(vc_req->transfer_buffer, + urb->transfer_buffer, + urb->actual_length); + } + NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS; + irp->io_status.status = STATUS_SUCCESS; + break; + case -ENOENT: + case -ECONNRESET: + /* urb canceled */ + irp->io_status.info = 0; + TRACE2("urb %p canceled", urb); + NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS; + irp->io_status.status = STATUS_CANCELLED; + break; + default: + TRACE2("irp: %p, urb: %p, status: %d/%d", + irp, urb, urb->status, wrap_urb->state); + irp->io_status.info = 0; + NT_URB_STATUS(nt_urb) = wrap_urb_status(urb->status); + irp->io_status.status = + nt_urb_irp_status(NT_URB_STATUS(nt_urb)); + break; + } + wrap_free_urb(urb); + IoCompleteRequest(irp, IO_NO_INCREMENT); + } + USBEXIT(return); +} + +static USBD_STATUS wrap_bulk_or_intr_trans(struct irp *irp) +{ + usbd_pipe_handle pipe_handle; + struct urb *urb; + unsigned int pipe; + struct usbd_bulk_or_intr_transfer *bulk_int_tx; + USBD_STATUS status; + struct usb_device *udev; + union nt_urb *nt_urb; + + nt_urb = IRP_URB(irp); + udev = IRP_WRAP_DEVICE(irp)->usb.udev; + bulk_int_tx = &nt_urb->bulk_int_transfer; + pipe_handle = bulk_int_tx->pipe_handle; + USBTRACE("flags: 0x%x, length: %u, buffer: %p, handle: %p", + bulk_int_tx->transfer_flags, + bulk_int_tx->transfer_buffer_length, + bulk_int_tx->transfer_buffer, pipe_handle); + + if (USBD_IS_BULK_PIPE(pipe_handle)) { + if (bulk_int_tx->transfer_flags & USBD_TRANSFER_DIRECTION_IN) + pipe = usb_rcvbulkpipe(udev, + pipe_handle->bEndpointAddress); + else + pipe = usb_sndbulkpipe(udev, + pipe_handle->bEndpointAddress); + } else { + if (bulk_int_tx->transfer_flags & USBD_TRANSFER_DIRECTION_IN) + pipe = usb_rcvintpipe(udev, + pipe_handle->bEndpointAddress); + else + pipe = usb_sndintpipe(udev, + pipe_handle->bEndpointAddress); + } + + DUMP_IRP(irp); + urb = wrap_alloc_urb(irp, pipe, bulk_int_tx->transfer_buffer, + bulk_int_tx->transfer_buffer_length); + if (!urb) { + ERROR("couldn't allocate urb"); + return USBD_STATUS_NO_MEMORY; + } + if (usb_pipein(pipe) && + (!(bulk_int_tx->transfer_flags & USBD_SHORT_TRANSFER_OK))) { + USBTRACE("short not ok"); + urb->transfer_flags |= URB_SHORT_NOT_OK; + } + if (usb_pipebulk(pipe)) { + usb_fill_bulk_urb(urb, udev, pipe, urb->transfer_buffer, + bulk_int_tx->transfer_buffer_length, + wrap_urb_complete, urb->context); + USBTRACE("submitting bulk urb %p on pipe 0x%x (ep 0x%x)", + urb, urb->pipe, pipe_handle->bEndpointAddress); + } else { + usb_fill_int_urb(urb, udev, pipe, urb->transfer_buffer, + bulk_int_tx->transfer_buffer_length, + wrap_urb_complete, urb->context, + pipe_handle->bInterval); + USBTRACE("submitting interrupt urb %p on pipe 0x%x (ep 0x%x), " + "intvl: %d", urb, urb->pipe, + pipe_handle->bEndpointAddress, pipe_handle->bInterval); + } + status = wrap_submit_urb(irp); + USBTRACE("status: %08X", status); + USBEXIT(return status); +} + +static USBD_STATUS wrap_vendor_or_class_req(struct irp *irp) +{ + u8 req_type; + unsigned int pipe; + struct usbd_vendor_or_class_request *vc_req; + struct usb_device *udev; + union nt_urb *nt_urb; + USBD_STATUS status; + struct urb *urb; + struct usb_ctrlrequest *dr; + + nt_urb = IRP_URB(irp); + udev = IRP_WRAP_DEVICE(irp)->usb.udev; + vc_req = &nt_urb->vendor_class_request; + USBTRACE("bits: %x, req: %x, val: %08x, index: %08x, flags: %x," + "buf: %p, len: %d", vc_req->reserved_bits, vc_req->request, + vc_req->value, vc_req->index, vc_req->transfer_flags, + vc_req->transfer_buffer, vc_req->transfer_buffer_length); + + USBTRACE("%x", nt_urb->header.function); + switch (nt_urb->header.function) { + case URB_FUNCTION_VENDOR_DEVICE: + req_type = USB_TYPE_VENDOR | USB_RECIP_DEVICE; + break; + case URB_FUNCTION_VENDOR_INTERFACE: + req_type = USB_TYPE_VENDOR | USB_RECIP_INTERFACE; + break; + case URB_FUNCTION_VENDOR_ENDPOINT: + req_type = USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; + break; + case URB_FUNCTION_VENDOR_OTHER: + req_type = USB_TYPE_VENDOR | USB_RECIP_OTHER; + break; + case URB_FUNCTION_CLASS_DEVICE: + req_type = USB_TYPE_CLASS | USB_RECIP_DEVICE; + break; + case URB_FUNCTION_CLASS_INTERFACE: + req_type = USB_TYPE_CLASS | USB_RECIP_INTERFACE; + break; + case URB_FUNCTION_CLASS_ENDPOINT: + req_type = USB_TYPE_CLASS | USB_RECIP_ENDPOINT; + break; + case URB_FUNCTION_CLASS_OTHER: + req_type = USB_TYPE_CLASS | USB_RECIP_OTHER; + break; + default: + ERROR("unknown request type: %x", nt_urb->header.function); + req_type = 0; + break; + } + + req_type |= vc_req->reserved_bits; + USBTRACE("req type: %08x", req_type); + + if (vc_req->transfer_flags & USBD_TRANSFER_DIRECTION_IN) { + pipe = usb_rcvctrlpipe(udev, 0); + req_type |= USB_DIR_IN; + USBTRACE("pipe: %x, dir in", pipe); + } else { + pipe = usb_sndctrlpipe(udev, 0); + req_type |= USB_DIR_OUT; + USBTRACE("pipe: %x, dir out", pipe); + } + urb = wrap_alloc_urb(irp, pipe, vc_req->transfer_buffer, + vc_req->transfer_buffer_length); + if (!urb) { + ERROR("couldn't allocate urb"); + return USBD_STATUS_NO_MEMORY; + } + + if (usb_pipein(pipe) && + (!(vc_req->transfer_flags & USBD_SHORT_TRANSFER_OK))) { + USBTRACE("short not ok"); + urb->transfer_flags |= URB_SHORT_NOT_OK; + } + + dr = kzalloc(sizeof(*dr), GFP_ATOMIC); + if (!dr) { + ERROR("couldn't allocate memory"); + wrap_free_urb(urb); + return USBD_STATUS_NO_MEMORY; + } + dr->bRequestType = req_type; + dr->bRequest = vc_req->request; + dr->wValue = cpu_to_le16(vc_req->value); + dr->wIndex = cpu_to_le16((u16)vc_req->index); + dr->wLength = cpu_to_le16((u16)urb->transfer_buffer_length); + + usb_fill_control_urb(urb, udev, pipe, (unsigned char *)dr, + urb->transfer_buffer, urb->transfer_buffer_length, + wrap_urb_complete, urb->context); + status = wrap_submit_urb(irp); + USBTRACE("status: %08X", status); + USBEXIT(return status); +} + +static USBD_STATUS wrap_reset_pipe(struct usb_device *udev, struct irp *irp) +{ + int ret; + union nt_urb *nt_urb; + usbd_pipe_handle pipe_handle; + unsigned int pipe1, pipe2; + + nt_urb = IRP_URB(irp); + pipe_handle = nt_urb->pipe_req.pipe_handle; + /* TODO: not clear if both directions should be cleared? */ + if (USBD_IS_BULK_PIPE(pipe_handle)) { + pipe1 = usb_rcvbulkpipe(udev, pipe_handle->bEndpointAddress); + pipe2 = usb_sndbulkpipe(udev, pipe_handle->bEndpointAddress); + } else if (USBD_IS_INT_PIPE(pipe_handle)) { + pipe1 = usb_rcvintpipe(udev, pipe_handle->bEndpointAddress); + pipe2 = pipe1; + } else { + WARNING("invalid pipe %d", pipe_handle->bEndpointAddress); + return USBD_STATUS_INVALID_PIPE_HANDLE; + } + USBTRACE("ep: %d, pipe: 0x%x", pipe_handle->bEndpointAddress, pipe1); + ret = usb_clear_halt(udev, pipe1); + if (ret) + USBTRACE("resetting pipe %d failed: %d", pipe1, ret); + if (pipe2 != pipe1) { + ret = usb_clear_halt(udev, pipe2); + if (ret) + USBTRACE("resetting pipe %d failed: %d", pipe2, ret); + } +// return wrap_urb_status(ret); + return USBD_STATUS_SUCCESS; +} + +static USBD_STATUS wrap_abort_pipe(struct usb_device *udev, struct irp *irp) +{ + union nt_urb *nt_urb; + usbd_pipe_handle pipe_handle; + struct wrap_urb *wrap_urb; + struct wrap_device *wd; + KIRQL irql; + + wd = IRP_WRAP_DEVICE(irp); + nt_urb = IRP_URB(irp); + pipe_handle = nt_urb->pipe_req.pipe_handle; + USBENTER("%p, %x", irp, pipe_handle->bEndpointAddress); + IoAcquireCancelSpinLock(&irql); + nt_list_for_each_entry(wrap_urb, &wd->usb.wrap_urb_list, list) { + USBTRACE("%p, %p, %d, %x, %x", wrap_urb, wrap_urb->urb, + wrap_urb->state, wrap_urb->urb->pipe, + usb_pipeendpoint(wrap_urb->urb->pipe)); + /* for WG111T driver, urbs for endpoint 0 should also + * be canceled */ + if ((usb_pipeendpoint(wrap_urb->urb->pipe) == + pipe_handle->bEndpointAddress) || + (usb_pipeendpoint(wrap_urb->urb->pipe) == 0)) { + if (wrap_cancel_urb(wrap_urb) == 0) + USBTRACE("canceled wrap_urb: %p", wrap_urb); + } + } + IoReleaseCancelSpinLock(irql); + NT_URB_STATUS(nt_urb) = USBD_STATUS_CANCELED; + USBEXIT(return USBD_STATUS_SUCCESS); +} + +static USBD_STATUS wrap_set_clear_feature(struct usb_device *udev, + struct irp *irp) +{ + union nt_urb *nt_urb; + struct urb_control_feature_request *feat_req; + int ret = 0; + __u8 request, type; + __u16 feature; + + nt_urb = IRP_URB(irp); + feat_req = &nt_urb->feat_req; + feature = feat_req->feature_selector; + switch (nt_urb->header.function) { + case URB_FUNCTION_SET_FEATURE_TO_DEVICE: + request = USB_REQ_SET_FEATURE; + type = USB_DT_DEVICE; + break; + case URB_FUNCTION_SET_FEATURE_TO_INTERFACE: + request = USB_REQ_SET_FEATURE; + type = USB_DT_INTERFACE; + break; + case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT: + request = USB_REQ_SET_FEATURE; + type = USB_DT_ENDPOINT; + break; + case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE: + request = USB_REQ_CLEAR_FEATURE; + type = USB_DT_DEVICE; + break; + case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE: + request = USB_REQ_CLEAR_FEATURE; + type = USB_DT_INTERFACE; + break; + case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT: + request = USB_REQ_CLEAR_FEATURE; + type = USB_DT_ENDPOINT; + break; + default: + WARNING("invalid function: %x", nt_urb->header.function); + NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED; + return NT_URB_STATUS(nt_urb); + } + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request, type, + feature, feat_req->index, NULL, 0, 1000); + NT_URB_STATUS(nt_urb) = wrap_urb_status(ret); + USBEXIT(return NT_URB_STATUS(nt_urb)); +} + +static USBD_STATUS wrap_get_status_request(struct usb_device *udev, + struct irp *irp) +{ + union nt_urb *nt_urb; + struct urb_control_get_status_request *status_req; + int ret = 0; + __u8 type; + + nt_urb = IRP_URB(irp); + status_req = &nt_urb->status_req; + switch (nt_urb->header.function) { + case URB_FUNCTION_GET_STATUS_FROM_DEVICE: + type = USB_RECIP_DEVICE; + break; + case URB_FUNCTION_GET_STATUS_FROM_INTERFACE: + type = USB_RECIP_INTERFACE; + break; + case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT: + type = USB_RECIP_ENDPOINT; + break; + default: + WARNING("invalid function: %x", nt_urb->header.function); + NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED; + return NT_URB_STATUS(nt_urb); + } + assert(status_req->transfer_buffer_length == sizeof(u16)); + ret = usb_get_status(udev, type, status_req->index, + status_req->transfer_buffer); + if (ret >= 0) { + assert(ret <= status_req->transfer_buffer_length); + status_req->transfer_buffer_length = ret; + NT_URB_STATUS(nt_urb) = USBD_STATUS_SUCCESS; + } else + NT_URB_STATUS(nt_urb) = wrap_urb_status(ret); + USBEXIT(return NT_URB_STATUS(nt_urb)); +} + +static void set_intf_pipe_info(struct wrap_device *wd, + struct usb_interface *usb_intf, + struct usbd_interface_information *intf) +{ + int i; + struct usb_endpoint_descriptor *ep; + struct usbd_pipe_information *pipe; + + for (i = 0; i < CUR_ALT_SETTING(usb_intf)->desc.bNumEndpoints; i++) { + ep = &(CUR_ALT_SETTING(usb_intf)->endpoint[i]).desc; + if (i >= intf->bNumEndpoints) { + ERROR("intf %p has only %d endpoints, " + "ignoring endpoints above %d", + intf, intf->bNumEndpoints, i); + break; + } + pipe = &intf->pipes[i]; + + if (pipe->flags & USBD_PF_CHANGE_MAX_PACKET) + USBTRACE("pkt_sz: %d: %d", pipe->wMaxPacketSize, + pipe->max_tx_size); + USBTRACE("driver wants max_tx_size to %d", + pipe->max_tx_size); + + pipe->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize); + pipe->bEndpointAddress = ep->bEndpointAddress; + pipe->type = ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (pipe->type == UsbdPipeTypeInterrupt) { + /* Windows and Linux differ in how the + * bInterval is interpretted */ + /* for low speed: + interval (Windows) -> frames per ms (Linux) + 0 to 15 -> 8 + 16 to 35 -> 16 + 36 to 255 -> 32 + + for full speed: interval -> frames per ms + 1 -> 1 + 2 to 3 -> 2 + 4 to 7 -> 4 + 8 to 15 -> 8 + 16 to 31 -> 16 + 32 to 255 -> 32 + + for high speed: interval -> microframes + 1 -> 1 + 2 -> 2 + 3 -> 4 + 4 -> 8 + 5 -> 16 + 6 -> 32 + 7 to 255 -> 32 + */ + if (wd->usb.udev->speed == USB_SPEED_LOW) + pipe->bInterval = ep->bInterval + 5; + else if (wd->usb.udev->speed == USB_SPEED_FULL) + pipe->bInterval = ep->bInterval; + else { + int j, k; + for (j = k = 1; j < ep->bInterval; k++) + j *= 2; + pipe->bInterval = k; + } + } + pipe->handle = ep; + USBTRACE("%d: ep 0x%x, type %d, pkt_sz %d, intv %d (%d)," + "type: %d, handle %p", i, ep->bEndpointAddress, + ep->bmAttributes, pipe->wMaxPacketSize, ep->bInterval, + pipe->bInterval, pipe->type, pipe->handle); + } +} + +static USBD_STATUS wrap_select_configuration(struct wrap_device *wd, + union nt_urb *nt_urb, + struct irp *irp) +{ + int i, ret; + struct usbd_select_configuration *sel_conf; + struct usb_device *udev; + struct usbd_interface_information *intf; + struct usb_config_descriptor *config; + struct usb_interface *usb_intf; + + udev = wd->usb.udev; + sel_conf = &nt_urb->select_conf; + config = sel_conf->config; + USBTRACE("%p", config); + if (config == NULL) { + kill_all_urbs(wd, 1); + ret = usb_reset_configuration(udev); + return wrap_urb_status(ret); + } + + USBTRACE("conf: %d, type: %d, length: %d, numif: %d, attr: %08x", + config->bConfigurationValue, config->bDescriptorType, + config->wTotalLength, config->bNumInterfaces, + config->bmAttributes); + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_CONFIGURATION, 0, + config->bConfigurationValue, 0, + NULL, 0, USB_CTRL_SET_TIMEOUT); + if (ret < 0) { + ERROR("ret: %d", ret); + return wrap_urb_status(ret); + } + sel_conf->handle = udev->actconfig; + intf = &sel_conf->intf; + for (i = 0; i < config->bNumInterfaces && intf->bLength > 0; + i++, intf = (((void *)intf) + intf->bLength)) { + + USBTRACE("intf: %d, alt setting: %d", + intf->bInterfaceNumber, intf->bAlternateSetting); + ret = usb_set_interface(udev, intf->bInterfaceNumber, + intf->bAlternateSetting); + if (ret < 0) { + ERROR("failed with %d", ret); + return wrap_urb_status(ret); + } + usb_intf = usb_ifnum_to_if(udev, intf->bInterfaceNumber); + if (!usb_intf) { + ERROR("couldn't obtain ifnum"); + return USBD_STATUS_REQUEST_FAILED; + } + USBTRACE("intf: %p, num ep: %d", intf, intf->bNumEndpoints); + set_intf_pipe_info(wd, usb_intf, intf); + } + return USBD_STATUS_SUCCESS; +} + +static USBD_STATUS wrap_select_interface(struct wrap_device *wd, + union nt_urb *nt_urb, + struct irp *irp) +{ + int ret; + struct usbd_select_interface *sel_intf; + struct usb_device *udev; + struct usbd_interface_information *intf; + struct usb_interface *usb_intf; + + udev = wd->usb.udev; + sel_intf = &nt_urb->select_intf; + intf = &sel_intf->intf; + + ret = usb_set_interface(udev, intf->bInterfaceNumber, + intf->bAlternateSetting); + if (ret < 0) { + ERROR("failed with %d", ret); + return wrap_urb_status(ret); + } + usb_intf = usb_ifnum_to_if(udev, intf->bInterfaceNumber); + if (!usb_intf) { + ERROR("couldn't get interface information"); + return USBD_STATUS_REQUEST_FAILED; + } + USBTRACE("intf: %p, num ep: %d", usb_intf, intf->bNumEndpoints); + set_intf_pipe_info(wd, usb_intf, intf); + return USBD_STATUS_SUCCESS; +} + +static int wrap_usb_get_string(struct usb_device *udev, unsigned short langid, + unsigned char index, void *buf, int size) +{ + int i, ret; + /* if langid is 0, return array of langauges supported in + * buf */ + for (i = 0; i < 3; i++) { + ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (USB_DT_STRING << 8) + index, langid, + buf, size, USB_CTRL_GET_TIMEOUT); + if (ret > 0 || ret == -EPIPE) + break; + } + return ret; +} + +static USBD_STATUS wrap_get_descriptor(struct wrap_device *wd, + union nt_urb *nt_urb, struct irp *irp) +{ + struct usbd_control_descriptor_request *control_desc; + int ret = 0; + struct usb_device *udev; + + udev = wd->usb.udev; + control_desc = &nt_urb->control_desc; + USBTRACE("desctype = %d, descindex = %d, transfer_buffer = %p," + "transfer_buffer_length = %d", control_desc->desc_type, + control_desc->index, control_desc->transfer_buffer, + control_desc->transfer_buffer_length); + + if (control_desc->desc_type == USB_DT_STRING) { + USBTRACE("langid: %x", control_desc->language_id); + ret = wrap_usb_get_string(udev, control_desc->language_id, + control_desc->index, + control_desc->transfer_buffer, + control_desc->transfer_buffer_length); + } else { + ret = usb_get_descriptor(udev, control_desc->desc_type, + control_desc->index, + control_desc->transfer_buffer, + control_desc->transfer_buffer_length); + } + if (ret < 0) { + USBTRACE("request %d failed: %d", control_desc->desc_type, ret); + control_desc->transfer_buffer_length = 0; + return wrap_urb_status(ret); + } else { + USBTRACE("ret: %08x", ret); + control_desc->transfer_buffer_length = ret; + irp->io_status.info = ret; + return USBD_STATUS_SUCCESS; + } +} + +static USBD_STATUS wrap_process_nt_urb(struct irp *irp) +{ + union nt_urb *nt_urb; + struct usb_device *udev; + USBD_STATUS status; + struct wrap_device *wd; + + wd = IRP_WRAP_DEVICE(irp); + udev = wd->usb.udev; + nt_urb = IRP_URB(irp); + USBENTER("nt_urb = %p, irp = %p, length = %d, function = %x", + nt_urb, irp, nt_urb->header.length, nt_urb->header.function); + + DUMP_IRP(irp); + switch (nt_urb->header.function) { + /* bulk/int and vendor/class urbs are submitted to + * Linux USB core; if the call is sucessful, urb's + * completion worker will return IRP later */ + case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: + USBTRACE("submitting bulk/int irp: %p", irp); + status = wrap_bulk_or_intr_trans(irp); + break; + + case URB_FUNCTION_VENDOR_DEVICE: + case URB_FUNCTION_VENDOR_INTERFACE: + case URB_FUNCTION_VENDOR_ENDPOINT: + case URB_FUNCTION_VENDOR_OTHER: + case URB_FUNCTION_CLASS_DEVICE: + case URB_FUNCTION_CLASS_INTERFACE: + case URB_FUNCTION_CLASS_ENDPOINT: + case URB_FUNCTION_CLASS_OTHER: + USBTRACE("submitting vendor/class irp: %p", irp); + status = wrap_vendor_or_class_req(irp); + break; + + /* rest are synchronous */ + case URB_FUNCTION_SELECT_CONFIGURATION: + status = wrap_select_configuration(wd, nt_urb, irp); + NT_URB_STATUS(nt_urb) = status; + break; + + case URB_FUNCTION_SELECT_INTERFACE: + status = wrap_select_interface(wd, nt_urb, irp); + NT_URB_STATUS(nt_urb) = status; + break; + + case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: + status = wrap_get_descriptor(wd, nt_urb, irp); + NT_URB_STATUS(nt_urb) = status; + break; + + case URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL: + status = wrap_reset_pipe(udev, irp); + NT_URB_STATUS(nt_urb) = status; + break; + + case URB_FUNCTION_ABORT_PIPE: + status = wrap_abort_pipe(udev, irp); + break; + + case URB_FUNCTION_SET_FEATURE_TO_DEVICE: + case URB_FUNCTION_SET_FEATURE_TO_INTERFACE: + case URB_FUNCTION_SET_FEATURE_TO_ENDPOINT: + case URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE: + case URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE: + case URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT: + status = wrap_set_clear_feature(udev, irp); + break; + + case URB_FUNCTION_GET_STATUS_FROM_DEVICE: + case URB_FUNCTION_GET_STATUS_FROM_INTERFACE: + case URB_FUNCTION_GET_STATUS_FROM_ENDPOINT: + status = wrap_get_status_request(udev, irp); + break; + + default: + ERROR("function %x not implemented", nt_urb->header.function); + status = NT_URB_STATUS(nt_urb) = USBD_STATUS_NOT_SUPPORTED; + break; + } + USBTRACE("status: %08X", status); + return status; +} + +static USBD_STATUS wrap_reset_port(struct irp *irp) +{ + no_warn_unused int ret, lock = 0; + struct wrap_device *wd; + + wd = IRP_WRAP_DEVICE(irp); + USBENTER("%p, %p", wd, wd->usb.udev); + lock = usb_lock_device_for_reset(wd->usb.udev, wd->usb.intf); + if (lock < 0) { + WARNING("locking failed: %d", lock); +// return wrap_urb_status(lock); + return USBD_STATUS_SUCCESS; + } + ret = usb_reset_device(wd->usb.udev); + if (ret < 0) + USBTRACE("reset failed: %d", ret); + /* TODO: should reconfigure? */ + if (lock) + usb_unlock_device(wd->usb.udev); +// return wrap_urb_status(ret); + return USBD_STATUS_SUCCESS; +} + +static USBD_STATUS wrap_get_port_status(struct irp *irp) +{ + struct wrap_device *wd; + ULONG *status; + enum usb_device_state state; + + wd = IRP_WRAP_DEVICE(irp); + USBENTER("%p, %p", wd, wd->usb.udev); + status = IoGetCurrentIrpStackLocation(irp)->params.others.arg1; + state = wd->usb.udev->state; + if (state != USB_STATE_NOTATTACHED && + state != USB_STATE_SUSPENDED) { + *status |= USBD_PORT_CONNECTED; + if (state == USB_STATE_CONFIGURED) + *status |= USBD_PORT_ENABLED; + } + USBTRACE("state: %d, *status: %08X", state, *status); + return USBD_STATUS_SUCCESS; +} + +NTSTATUS wrap_submit_irp(struct device_object *pdo, struct irp *irp) +{ + struct io_stack_location *irp_sl; + struct wrap_device *wd; + USBD_STATUS status; + struct usbd_idle_callback *idle_callback; + + USBENTER("%p, %p", pdo, irp); + wd = pdo->reserved; + if (wd->usb.intf == NULL) { + USBTRACE("%p", irp); + irp->io_status.status = STATUS_DEVICE_REMOVED; + irp->io_status.info = 0; + USBEXIT(return STATUS_DEVICE_REMOVED); + } + IRP_WRAP_DEVICE(irp) = wd; + irp_sl = IoGetCurrentIrpStackLocation(irp); + switch (irp_sl->params.dev_ioctl.code) { + case IOCTL_INTERNAL_USB_SUBMIT_URB: + status = wrap_process_nt_urb(irp); + break; + case IOCTL_INTERNAL_USB_RESET_PORT: + status = wrap_reset_port(irp); + break; + case IOCTL_INTERNAL_USB_GET_PORT_STATUS: + status = wrap_get_port_status(irp); + break; + case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: + idle_callback = irp_sl->params.dev_ioctl.type3_input_buf; + USBTRACE("suspend function: %p", idle_callback->callback); + status = USBD_STATUS_NOT_SUPPORTED; + break; + default: + ERROR("ioctl %08X NOT IMPLEMENTED", + irp_sl->params.dev_ioctl.code); + status = USBD_STATUS_NOT_SUPPORTED; + break; + } + + USBTRACE("status: %08X", status); + if (status == USBD_STATUS_PENDING) { + /* don't touch this IRP - it may have been already + * completed/returned */ + return STATUS_PENDING; + } else { + irp->io_status.status = nt_urb_irp_status(status); + if (status != USBD_STATUS_SUCCESS) + irp->io_status.info = 0; + USBEXIT(return irp->io_status.status); + } +} + +/* TODO: The example on msdn in reference section suggests that second + * argument should be an array of usbd_interface_information, but + * description and examples elsewhere suggest that it should be + * usbd_interface_list_entry structre. Which is correct? */ + +wstdcall union nt_urb *WIN_FUNC(USBD_CreateConfigurationRequestEx,2) + (struct usb_config_descriptor *config, + struct usbd_interface_list_entry *intf_list) +{ + int size, i, n; + struct usbd_interface_information *intf; + struct usbd_pipe_information *pipe; + struct usb_interface_descriptor *intf_desc; + struct usbd_select_configuration *select_conf; + + USBENTER("config = %p, intf_list = %p", config, intf_list); + + /* calculate size required; select_conf already has space for + * one intf structure */ + size = sizeof(*select_conf) - sizeof(*intf); + for (n = 0; n < config->bNumInterfaces; n++) { + i = intf_list[n].intf_desc->bNumEndpoints; + /* intf already has space for one pipe */ + size += sizeof(*intf) + (i - 1) * sizeof(*pipe); + } + /* don't use kmalloc - driver frees it with ExFreePool */ + select_conf = ExAllocatePoolWithTag(NonPagedPool, size, + POOL_TAG('L', 'U', 'S', 'B')); + if (!select_conf) { + WARNING("couldn't allocate memory"); + return NULL; + } + memset(select_conf, 0, size); + intf = &select_conf->intf; + select_conf->handle = config; + for (n = 0; n < config->bNumInterfaces && intf_list[n].intf_desc; n++) { + /* initialize 'intf' fields in intf_list so they point + * to appropriate entry; these may be read/written by + * driver after this function returns */ + intf_list[n].intf = intf; + intf_desc = intf_list[n].intf_desc; + + i = intf_desc->bNumEndpoints; + intf->bLength = sizeof(*intf) + (i - 1) * sizeof(*pipe); + + intf->bInterfaceNumber = intf_desc->bInterfaceNumber; + intf->bAlternateSetting = intf_desc->bAlternateSetting; + intf->bInterfaceClass = intf_desc->bInterfaceClass; + intf->bInterfaceSubClass = intf_desc->bInterfaceSubClass; + intf->bInterfaceProtocol = intf_desc->bInterfaceProtocol; + intf->bNumEndpoints = intf_desc->bNumEndpoints; + + pipe = &intf->pipes[0]; + for (i = 0; i < intf->bNumEndpoints; i++) { + memset(&pipe[i], 0, sizeof(*pipe)); + pipe[i].max_tx_size = + USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE; + } + intf->handle = intf_desc; + intf = (((void *)intf) + intf->bLength); + } + select_conf->header.function = URB_FUNCTION_SELECT_CONFIGURATION; + select_conf->header.length = size; + select_conf->config = config; + USBEXIT(return (union nt_urb *)select_conf); +} + +WIN_SYMBOL_MAP("_USBD_CreateConfigurationRequestEx@8", USBD_CreateConfigurationRequestEx) + +wstdcall struct usb_interface_descriptor * +WIN_FUNC(USBD_ParseConfigurationDescriptorEx,7) + (struct usb_config_descriptor *config, void *start, + LONG bInterfaceNumber, LONG bAlternateSetting, LONG bInterfaceClass, + LONG bInterfaceSubClass, LONG bInterfaceProtocol) +{ + void *pos; + struct usb_interface_descriptor *intf; + + USBENTER("config = %p, start = %p, ifnum = %d, alt_setting = %d," + " class = %d, subclass = %d, proto = %d", config, start, + bInterfaceNumber, bAlternateSetting, bInterfaceClass, + bInterfaceSubClass, bInterfaceProtocol); + + for (pos = start; + pos < ((void *)config + le16_to_cpu(config->wTotalLength)); + pos += intf->bLength) { + + intf = pos; + + if ((intf->bDescriptorType == USB_DT_INTERFACE) && + ((bInterfaceNumber == -1) || + (intf->bInterfaceNumber == bInterfaceNumber)) && + ((bAlternateSetting == -1) || + (intf->bAlternateSetting == bAlternateSetting)) && + ((bInterfaceClass == -1) || + (intf->bInterfaceClass == bInterfaceClass)) && + ((bInterfaceSubClass == -1) || + (intf->bInterfaceSubClass == bInterfaceSubClass)) && + ((bInterfaceProtocol == -1) || + (intf->bInterfaceProtocol == bInterfaceProtocol))) { + USBTRACE("selected interface = %p", intf); + USBEXIT(return intf); + } + } + USBEXIT(return NULL); +} + +WIN_SYMBOL_MAP("_USBD_ParseConfigurationDescriptorEx@28", USBD_ParseConfigurationDescriptorEx) + +wstdcall union nt_urb *WIN_FUNC(USBD_CreateConfigurationRequest,2) + (struct usb_config_descriptor *config, USHORT *size) +{ + union nt_urb *nt_urb; + struct usbd_interface_list_entry intf_list[2]; + struct usb_interface_descriptor *intf_desc; + + USBENTER("config = %p, urb_size = %p", config, size); + + intf_desc = USBD_ParseConfigurationDescriptorEx(config, config, -1, -1, + -1, -1, -1); + intf_list[0].intf_desc = intf_desc; + intf_list[0].intf = NULL; + intf_list[1].intf_desc = NULL; + intf_list[1].intf = NULL; + nt_urb = USBD_CreateConfigurationRequestEx(config, intf_list); + if (!nt_urb) + return NULL; + + *size = nt_urb->select_conf.header.length; + USBEXIT(return nt_urb); +} + +wstdcall struct usb_interface_descriptor * +WIN_FUNC(USBD_ParseConfigurationDescriptor,3) + (struct usb_config_descriptor *config, UCHAR bInterfaceNumber, + UCHAR bAlternateSetting) +{ + return USBD_ParseConfigurationDescriptorEx(config, config, + bInterfaceNumber, + bAlternateSetting, + -1, -1, -1); +} + +wstdcall usb_common_descriptor_t *WIN_FUNC(USBD_ParseDescriptors,4) + (void *buf, ULONG length, void *start, LONG type) +{ + usb_common_descriptor_t *descr = start; + + while ((void *)descr < buf + length) { + if (descr->bDescriptorType == type) + return descr; + if (descr->bLength == 0) + break; + descr = (void *)descr + descr->bLength; + } + USBEXIT(return NULL); +} + +WIN_SYMBOL_MAP("_USBD_ParseDescriptors@16", USBD_ParseDescriptors) + +wstdcall void WIN_FUNC(USBD_GetUSBDIVersion,1) + (struct usbd_version_info *version_info) +{ + /* this function is obsolete in Windows XP */ + if (version_info) { + version_info->usbdi_version = USBDI_VERSION_XP; + /* TODO: how do we get this correctly? */ + version_info->supported_usb_version = 0x110; + } + USBEXIT(return); +} + +wstdcall void +USBD_InterfaceGetUSBDIVersion(void *context, + struct usbd_version_info *version_info, + ULONG *hcd_capa) +{ + struct wrap_device *wd = context; + + if (version_info) { + version_info->usbdi_version = USBDI_VERSION_XP; + if (wd->usb.udev->speed == USB_SPEED_HIGH) + version_info->supported_usb_version = 0x200; + else + version_info->supported_usb_version = 0x110; + } + *hcd_capa = USB_HCD_CAPS_SUPPORTS_RT_THREADS; + USBEXIT(return); +} + +wstdcall BOOLEAN USBD_InterfaceIsDeviceHighSpeed(void *context) +{ + struct wrap_device *wd = context; + + USBTRACE("wd: %p", wd); + if (wd->usb.udev->speed == USB_SPEED_HIGH) + USBEXIT(return TRUE); + else + USBEXIT(return FALSE); +} + +wstdcall void USBD_InterfaceReference(void *context) +{ + USBTRACE("%p", context); + TODO(); +} + +wstdcall void USBD_InterfaceDereference(void *context) +{ + USBTRACE("%p", context); + TODO(); +} + +wstdcall NTSTATUS USBD_InterfaceQueryBusTime(void *context, ULONG *frame) +{ + struct wrap_device *wd = context; + + *frame = usb_get_current_frame_number(wd->usb.udev); + USBEXIT(return STATUS_SUCCESS); +} + +wstdcall NTSTATUS USBD_InterfaceSubmitIsoOutUrb(void *context, + union nt_urb *nt_urb) +{ + /* TODO: implement this */ + TODO(); + USBEXIT(return STATUS_NOT_IMPLEMENTED); +} + +wstdcall NTSTATUS +USBD_InterfaceQueryBusInformation(void *context, ULONG level, void *buf, + ULONG *buf_length, ULONG *buf_actual_length) +{ + struct wrap_device *wd = context; + struct usb_bus_information_level *bus_info; + struct usb_bus *bus; + + bus = wd->usb.udev->bus; + bus_info = buf; + TODO(); + USBEXIT(return STATUS_NOT_IMPLEMENTED); +} + +wstdcall NTSTATUS +USBD_InterfaceLogEntry(void *context, ULONG driver_tag, ULONG enum_tag, + ULONG p1, ULONG p2) +{ + ERROR("%p, %x, %x, %x, %x", context, driver_tag, enum_tag, p1, p2); + USBEXIT(return STATUS_SUCCESS); +} + +int usb_init(void) +{ + InitializeListHead(&wrap_urb_complete_list); + spin_lock_init(&wrap_urb_complete_list_lock); + initialize_work(&wrap_urb_complete_work, wrap_urb_complete_worker, NULL); +#ifdef USB_DEBUG + urb_id = 0; +#endif + return 0; +} + +void usb_exit(void) +{ + USBEXIT(return); +} + +int usb_init_device(struct wrap_device *wd) +{ + InitializeListHead(&wd->usb.wrap_urb_list); + wd->usb.num_alloc_urbs = 0; + USBEXIT(return 0); +} + +void usb_exit_device(struct wrap_device *wd) +{ + kill_all_urbs(wd, 0); + USBEXIT(return); +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/usb.h +++ linux-2.6.37/ubuntu/ndiswrapper/usb.h @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2004 Jan Kiszka + * Copyright (C) 2005 Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _USB_H_ +#define _USB_H_ + +#include "ntoskernel.h" + +#define IOCTL_INTERNAL_USB_SUBMIT_URB 0x00220003 +#define IOCTL_INTERNAL_USB_RESET_PORT 0x00220007 +#define IOCTL_INTERNAL_USB_GET_PORT_STATUS 0x00220013 +#define IOCTL_INTERNAL_USB_CYCLE_PORT 0x0022001F +#define IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION 0x00220027 + +#define URB_FUNCTION_SELECT_CONFIGURATION 0x0000 +#define URB_FUNCTION_SELECT_INTERFACE 0x0001 +#define URB_FUNCTION_ABORT_PIPE 0x0002 +#define URB_FUNCTION_TAKE_FRAME_LENGTH_CONTROL 0x0003 +#define URB_FUNCTION_RELEASE_FRAME_LENGTH_CONTROL 0x0004 +#define URB_FUNCTION_GET_FRAME_LENGTH 0x0005 +#define URB_FUNCTION_SET_FRAME_LENGTH 0x0006 +#define URB_FUNCTION_GET_CURRENT_FRAME_NUMBER 0x0007 +#define URB_FUNCTION_CONTROL_TRANSFER 0x0008 +#define URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER 0x0009 +#define URB_FUNCTION_ISOCH_TRANSFER 0x000A +#define URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE 0x000B +#define URB_FUNCTION_SET_DESCRIPTOR_TO_DEVICE 0x000C +#define URB_FUNCTION_SET_FEATURE_TO_DEVICE 0x000D +#define URB_FUNCTION_SET_FEATURE_TO_INTERFACE 0x000E +#define URB_FUNCTION_SET_FEATURE_TO_ENDPOINT 0x000F +#define URB_FUNCTION_CLEAR_FEATURE_TO_DEVICE 0x0010 +#define URB_FUNCTION_CLEAR_FEATURE_TO_INTERFACE 0x0011 +#define URB_FUNCTION_CLEAR_FEATURE_TO_ENDPOINT 0x0012 +#define URB_FUNCTION_GET_STATUS_FROM_DEVICE 0x0013 +#define URB_FUNCTION_GET_STATUS_FROM_INTERFACE 0x0014 +#define URB_FUNCTION_GET_STATUS_FROM_ENDPOINT 0x0015 +#define URB_FUNCTION_RESERVED_0X0016 0x0016 +#define URB_FUNCTION_VENDOR_DEVICE 0x0017 +#define URB_FUNCTION_VENDOR_INTERFACE 0x0018 +#define URB_FUNCTION_VENDOR_ENDPOINT 0x0019 +#define URB_FUNCTION_CLASS_DEVICE 0x001A +#define URB_FUNCTION_CLASS_INTERFACE 0x001B +#define URB_FUNCTION_CLASS_ENDPOINT 0x001C +#define URB_FUNCTION_RESERVE_0X001D 0x001D +#define URB_FUNCTION_SYNC_RESET_PIPE_AND_CLEAR_STALL 0x001E +#define URB_FUNCTION_CLASS_OTHER 0x001F +#define URB_FUNCTION_VENDOR_OTHER 0x0020 +#define URB_FUNCTION_GET_STATUS_FROM_OTHER 0x0021 +#define URB_FUNCTION_CLEAR_FEATURE_TO_OTHER 0x0022 +#define URB_FUNCTION_SET_FEATURE_TO_OTHER 0x0023 +#define URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT 0x0024 +#define URB_FUNCTION_SET_DESCRIPTOR_TO_ENDPOINT 0x0025 +#define URB_FUNCTION_GET_CONFIGURATION 0x0026 +#define URB_FUNCTION_GET_INTERFACE 0x0027 +#define URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE 0x0028 +#define URB_FUNCTION_SET_DESCRIPTOR_TO_INTERFACE 0x0029 +#define URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR 0x002A +#define URB_FUNCTION_RESERVE_0X002B 0x002B +#define URB_FUNCTION_RESERVE_0X002C 0x002C +#define URB_FUNCTION_RESERVE_0X002D 0x002D +#define URB_FUNCTION_RESERVE_0X002E 0x002E +#define URB_FUNCTION_RESERVE_0X002F 0x002F +// USB 2.0 calls start at 0x0030 +#define URB_FUNCTION_SYNC_RESET_PIPE 0x0030 +#define URB_FUNCTION_SYNC_CLEAR_STALL 0x0031 +#define URB_FUNCTION_CONTROL_TRANSFER_EX 0x0032 + +#define USBD_PF_CHANGE_MAX_PACKET 0x00000001 + +#define USBD_TRANSFER_DIRECTION_OUT 0 +#define USBD_TRANSFER_DIRECTION_IN 1 + +#define USBD_SHORT_TRANSFER_OK 0x00000002 +#define USBD_START_ISO_TRANSFER_ASAP 0x00000004 +#define USBD_DEFAULT_PIPE_TRANSFER 0x00000008 + +#define USBD_TRANSFER_DIRECTION(flags) \ + ((flags) & USBD_TRANSFER_DIRECTION_IN) + +enum pipe_type {UsbdPipeTypeControl = USB_ENDPOINT_XFER_CONTROL, + UsbdPipeTypeIsochronous = USB_ENDPOINT_XFER_ISOC, + UsbdPipeTypeBulk = USB_ENDPOINT_XFER_BULK, + UsbdPipeTypeInterrupt = USB_ENDPOINT_XFER_INT}; + +#define USBD_IS_BULK_PIPE(pipe_handle) \ + (((pipe_handle)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) \ + == USB_ENDPOINT_XFER_BULK) + +#define USBD_IS_INT_PIPE(pipe_handle) \ + (((pipe_handle)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) \ + == USB_ENDPOINT_XFER_INT) + +#define USBD_PORT_ENABLED 0x00000001 +#define USBD_PORT_CONNECTED 0x00000002 + +typedef LONG USBD_STATUS; + +#define USBD_STATUS_SUCCESS 0x0 +#define USBD_STATUS_PENDING 0x40000000 +#define USBD_STATUS_CANCELED 0x00010000 + +#define USBD_STATUS_CRC 0xC0000001 +#define USBD_STATUS_BTSTUFF 0xC0000002 +#define USBD_STATUS_DATA_TOGGLE_MISMATCH 0xC0000003 +#define USBD_STATUS_STALL_PID 0xC0000004 +#define USBD_STATUS_DEV_NOT_RESPONDING 0xC0000005 +#define USBD_STATUS_PID_CHECK_FAILURE 0xC0000006 +#define USBD_STATUS_UNEXPECTED_PID 0xC0000007 +#define USBD_STATUS_DATA_OVERRUN 0xC0000008 +#define USBD_STATUS_DATA_UNDERRUN 0xC0000009 +#define USBD_STATUS_RESERVED1 0xC000000A +#define USBD_STATUS_RESERVED2 0xC000000B +#define USBD_STATUS_BUFFER_OVERRUN 0xC000000C +#define USBD_STATUS_BUFFER_UNDERRUN 0xC000000D +#define USBD_STATUS_NOT_ACCESSED 0xC000000F +#define USBD_STATUS_FIFO 0xC0000010 +#define USBD_STATUS_XACT_ERROR 0xC0000011 +#define USBD_STATUS_BABBLE_DETECTED 0xC0000012 +#define USBD_STATUS_DATA_BUFFER_ERROR 0xC0000013 + +#define USBD_STATUS_NOT_SUPPORTED 0xC0000E00 +#define USBD_STATUS_BUFFER_TOO_SMALL 0xC0003000 +#define USBD_STATUS_TIMEOUT 0xC0006000 +#define USBD_STATUS_DEVICE_GONE 0xC0007000 + +#define USBD_STATUS_NO_MEMORY 0x80000100 +#define USBD_STATUS_INVALID_URB_FUNCTION 0x80000200 +#define USBD_STATUS_INVALID_PARAMETER 0x80000300 +#define USBD_STATUS_REQUEST_FAILED 0x80000500 +#define USBD_STATUS_INVALID_PIPE_HANDLE 0x80000600 +#define USBD_STATUS_ERROR_SHORT_TRANSFER 0x80000900 + +#define USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE PAGE_SIZE + +struct urb_hcd_area { + void *reserved8[8]; +}; + +typedef struct usb_endpoint_descriptor *usbd_pipe_handle; +typedef struct usb_descriptor_header usb_common_descriptor_t; + +struct usbd_pipe_information { + USHORT wMaxPacketSize; + UCHAR bEndpointAddress; + UCHAR bInterval; + enum pipe_type type; + usbd_pipe_handle handle; + ULONG max_tx_size; + ULONG flags; +}; + +struct usbd_interface_information { + USHORT bLength; + UCHAR bInterfaceNumber; + UCHAR bAlternateSetting; + UCHAR bInterfaceClass; + UCHAR bInterfaceSubClass; + UCHAR bInterfaceProtocol; + UCHAR reserved; + void *handle; + ULONG bNumEndpoints; + struct usbd_pipe_information pipes[1]; +}; + +struct usbd_interface_list_entry { + struct usb_interface_descriptor *intf_desc; + struct usbd_interface_information *intf; +}; + +struct nt_urb_header { + USHORT length; + USHORT function; + USBD_STATUS status; + void *usbd_dev_handle; + ULONG usbd_flags; +}; + +struct usbd_select_interface { + struct nt_urb_header header; + void *handle; + struct usbd_interface_information intf; +}; + +struct usbd_select_configuration { + struct nt_urb_header header; + struct usb_config_descriptor *config; + void *handle; + struct usbd_interface_information intf; +}; + +struct usbd_control_descriptor_request { + struct nt_urb_header header; + void *reserved; + ULONG reserved0; + ULONG transfer_buffer_length; + void *transfer_buffer; + struct mdl *mdl; + union nt_urb *urb_link; + struct urb_hcd_area hca; + USHORT reserved1; + UCHAR index; + UCHAR desc_type; + USHORT language_id; + USHORT reserved2; +}; + +struct usbd_bulk_or_intr_transfer { + struct nt_urb_header header; + usbd_pipe_handle pipe_handle; + ULONG transfer_flags; + ULONG transfer_buffer_length; + void *transfer_buffer; + struct mdl *mdl; + union nt_urb *urb_link; + struct urb_hcd_area hca; +}; + +struct usbd_pipe_request { + struct nt_urb_header header; + usbd_pipe_handle pipe_handle; +}; + +struct usbd_vendor_or_class_request { + struct nt_urb_header header; + void *reserved; + ULONG transfer_flags; + ULONG transfer_buffer_length; + void *transfer_buffer; + struct mdl *mdl; + union nt_urb *link; + struct urb_hcd_area hca; + UCHAR reserved_bits; + UCHAR request; + USHORT value; + USHORT index; + USHORT reserved1; +}; + +struct urb_control_feature_request { + struct nt_urb_header header; + void *reserved; + ULONG reserved2; + ULONG reserved3; + void *reserved4; + struct mdl *reserved5; + union nt_urb *link; + struct urb_hcd_area hca; + USHORT reserved0; + USHORT feature_selector; + USHORT index; + USHORT reserved1; +}; + +struct urb_control_get_status_request { + struct nt_urb_header header; + void *reserved; + ULONG reserved0; + ULONG transfer_buffer_length; + void *transfer_buffer; + struct mdl *mdl; + union nt_urb *link; + struct urb_hcd_area hca; + UCHAR reserved1[4]; + USHORT index; + USHORT reserved2; +}; + +struct usbd_iso_packet_desc { + ULONG offset; + ULONG length; + USBD_STATUS status; +}; + +struct usbd_isochronous_transfer { + struct nt_urb_header header; + usbd_pipe_handle pipe_handle; + ULONG transfer_flags; + ULONG transfer_buffer_length; + void *transfer_buffer; + struct mdl *mdl; + union nt_urb *urb_link; + struct urb_hcd_area hca; + ULONG start_frame; + ULONG number_of_packets; + ULONG error_count; + struct usbd_iso_packet_desc iso_packet[1]; +}; + +union nt_urb { + struct nt_urb_header header; + struct usbd_select_interface select_intf; + struct usbd_select_configuration select_conf; + struct usbd_bulk_or_intr_transfer bulk_int_transfer; + struct usbd_control_descriptor_request control_desc; + struct usbd_vendor_or_class_request vendor_class_request; + struct usbd_isochronous_transfer isochronous; + struct usbd_pipe_request pipe_req; + struct urb_control_feature_request feat_req; + struct urb_control_get_status_request status_req; +}; + +struct usbd_bus_interface_usbdi { + USHORT Size; + USHORT Version; + void *Context; + void *InterfaceReference; + void *InterfaceDereference; + void *GetUSBDIVersion; + void *QueryBusTime; + void *SubmitIsoOutUrb; + void *QueryBusInformation; + /* version 1 and above have following field */ + void *IsDeviceHighSpeed; + /* version 2 (and above) have following field */ + void *LogEntry; +}; + +struct usbd_bus_information_level { + ULONG TotalBandwidth; + ULONG ConsumedBandwidth; + /* level 1 and above have following fields */ + ULONG ControllerNameLength; + wchar_t ControllerName[1]; +}; + +#define USBDI_VERSION_XP 0x00000500 // Windows XP +#define USB_HCD_CAPS_SUPPORTS_RT_THREADS 0x00000001 +#define USB_BUSIF_USBDI_VERSION_0 0x0000 +#define USB_BUSIF_USBDI_VERSION_1 0x0001 +#define USB_BUSIF_USBDI_VERSION_2 0x0002 + +struct usbd_version_info { + ULONG usbdi_version; + ULONG supported_usb_version; +}; + +struct usbd_idle_callback { + void *callback; + void *context; +}; + +#define NT_URB_STATUS(nt_urb) ((nt_urb)->header.status) + +NTSTATUS wrap_submit_irp(struct device_object *pdo, struct irp *irp); +void wrap_suspend_urbs(struct wrap_device *wd); +void wrap_resume_urbs(struct wrap_device *wd); + +void USBD_InterfaceGetUSBDIVersion(void *context, + struct usbd_version_info *version_info, + ULONG *hcd_capa) wstdcall; +BOOLEAN USBD_InterfaceIsDeviceHighSpeed(void *context) wstdcall; +void USBD_InterfaceReference(void *context) wstdcall; +void USBD_InterfaceDereference(void *context) wstdcall; +NTSTATUS USBD_InterfaceQueryBusTime(void *context, ULONG *frame) wstdcall; +NTSTATUS USBD_InterfaceSubmitIsoOutUrb(void *context, + union nt_urb *nt_urb) wstdcall; +NTSTATUS USBD_InterfaceQueryBusInformation(void *context, ULONG level, void *buf, + ULONG *buf_length, + ULONG *buf_actual_length) wstdcall; +NTSTATUS USBD_InterfaceLogEntry(void *context, ULONG driver_tag, ULONG enum_tag, + ULONG p1, ULONG p2) wstdcall; + +#endif /* USB_H */ --- linux-2.6.37.orig/ubuntu/ndiswrapper/win2lin_stubs.S +++ linux-2.6.37/ubuntu/ndiswrapper/win2lin_stubs.S @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2005 Karl Vogel, Giridhar Pemmasani + * + * 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. + * + */ + +#include + +#ifdef CONFIG_X86_64 + +/* +# Windows <---> Linux register usage conversion when calling functions +# V = Volatile +# NV = Non Volatile (needs to be saved) +# +# Win Lin +# --------------------------------------- +# Rax Return V Return V +# Rbx NV NV +# Rcx Arg1 V Arg4 V +# Rdx Arg2 V Arg3 V +# Rsi NV Arg2 V +# Rdi NV Arg1 V +# Rsp NV NV +# Rbp NV NV +# R8 Arg3 V Arg5 V +# R9 Arg4 V Arg6 V +# R10 V V +# R11 V V +# R12 NV NV +# R13 NV NV +# R14 NV NV +# R15 NV NV +# +# In addition, Linux uses %rax to indicate number of SSE registers used +# when variadic functions are called. Since there is no way to obtain this +# from Windows, for now, we just assume this is 0 (hence %rax is cleared). +# +# Windows pushes arguments 5 and higher onto stack in case of integer +# variables and 4 and higher in case of floating point variabes (passed +# in SSE registers). + +In a windows function, the stackframe/registers look like this: + +# 0x0048 .... +# 0x0040 arg8 +# 0x0038 arg7 +# 0x0030 arg6 +# 0x0028 arg5 +# 0x0020 shadow/spill space for arg4 +# 0x0018 shadow/spill space for arg3 +# 0x0010 shadow/spill space for arg2 +# 0x0008 shadow/spill space for arg1 +# 0x0000 ret + +# register spill space is same irrespective of number of arguments - even +# if Windows function takes less than 4 arguments, 32 bytes above return +# address is reserved for the function + +In Linux it should look like: + +# 0x0018 .... +# 0x0010 arg8 +# 0x0008 arg7 +# 0x0000 ret + +*/ + +# +# setup for Windows to Linux function call +# + + .text + +.macro win2lin_prolog + push %rsi + push %rdi +.endm + +.macro win2lin_epilog + pop %rdi + pop %rsi +.endm + +# when Windows function calls Linux function, the function address is in %r10 + +.macro call_lin_func + xor %rax, %rax # rax indicates number of SSE regs + call *%r10 +.endm + +# before prolog, 0(%rsp) is return address, 8(%rsp) would be arg1 +# (but it is in register) and so on, so n'th arg would be at n*8(%rsp) +# for n > 4. But in prolog, we push 2 registers that are non-volaile in +# Windows, but volatile in Linux. So after prolog, args are at (n+2)*8(%rsp) + +#define win2lin_win_arg(n) (n+2)*8(%rsp) + +#define win2lin_arg1 mov %rcx, %rdi +#define win2lin_arg2 mov %rdx, %rsi +#define win2lin_arg3 mov %r8, %rdx +#define win2lin_arg4 mov %r9, %rcx +#define win2lin_arg5 mov win2lin_win_arg(5), %r8 +#define win2lin_arg6 mov win2lin_win_arg(6), %r9 + + .type win2lin0, @function +win2lin0: + win2lin_prolog + call_lin_func + win2lin_epilog + ret + .size win2lin0, .-win2lin0 + + .type win2lin1, @function +win2lin1: + win2lin_prolog + win2lin_arg1 + call_lin_func + win2lin_epilog + ret + .size win2lin1, .-win2lin1 + + .type win2lin2, @function +win2lin2: + win2lin_prolog + win2lin_arg1 + win2lin_arg2 + call_lin_func + win2lin_epilog + ret + .size win2lin2, .-win2lin2 + + .type win2lin3, @function +win2lin3: + win2lin_prolog + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + call_lin_func + win2lin_epilog + ret + .size win2lin3, .-win2lin3 + + .type win2lin4, @function +win2lin4: + win2lin_prolog + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + call_lin_func + win2lin_epilog + ret + .size win2lin4, .-win2lin4 + + .type win2lin5, @function +win2lin5: + win2lin_prolog + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + win2lin_arg5 + call_lin_func + win2lin_epilog + ret + .size win2lin5, .-win2lin5 + + .type win2lin6, @function +win2lin6: + win2lin_prolog + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + win2lin_arg5 + win2lin_arg6 + call_lin_func + win2lin_epilog + ret + .size win2lin6, .-win2lin6 + +# Allocate stack frame for Linux arguments before calling function. +# First 6 args are passed through registers, so we need space for 7 and above. +# The arguments should have been copied onto stack already. + +.macro call_lin_func_args n + sub $(\n-6)*8, %rsp + call_lin_func + add $(\n-6)*8, %rsp + .endm + +# m is index of Linux arg required, n is total number of args to function +# After stack frame is allocated, Linux arg 7 should be at 0(%rsp), +# arg 8 should be at 1*8(%rsp) and so on. So Linux arg m should be at (m-7)*8 +# Stack frame starts at -(n-6)*8(%rsp), so before stack frame is allocated +# Linux arg m should be at (6-n+m-7)*8(%rsp) + +#define win2lin_lin_arg(m,n) (m-1-n)*8(%rsp) + + .type win2lin7, @function +win2lin7: + win2lin_prolog + + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + win2lin_arg5 + win2lin_arg6 + + # copy windows argument 7 onto stack for Linux function + mov win2lin_win_arg(7), %r11 + mov %r11, win2lin_lin_arg(7,7) + + call_lin_func_args(7) + win2lin_epilog + ret + .size win2lin7, .-win2lin7 + + .type win2lin8, @function +win2lin8: + win2lin_prolog + + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + win2lin_arg5 + win2lin_arg6 + + # copy windows arguments 7 and 8 onto stack for Linux function + mov win2lin_win_arg(7), %r11 + mov %r11, win2lin_lin_arg(7,8) + mov win2lin_win_arg(8), %r11 + mov %r11, win2lin_lin_arg(8,8) + + call_lin_func_args(8) + win2lin_epilog + ret + .size win2lin8, .-win2lin8 + + .type win2lin9, @function +win2lin9: +win2lin10: +win2lin11: +win2lin12: + win2lin_prolog + + # since we destroy rsi and rdi here, first copy windows + # arguments 7 through 12 onto stack for Linux function + mov %rcx, %r11 # save rcx + lea win2lin_win_arg(7), %rsi # source (windows arg 7 and up) + lea win2lin_lin_arg(7,12), %rdi # = destination + mov $6, %rcx # 6 arguments + rep + movsq + mov %r11, %rcx # restore rcx + + win2lin_arg1 + win2lin_arg2 + win2lin_arg3 + win2lin_arg4 + win2lin_arg5 + win2lin_arg6 + + call_lin_func_args(12) + win2lin_epilog + ret + .size win2lin9, .-win2lin9 + +#define win2lin(name, argc) \ +ENTRY(win2lin_ ## name ## _ ## argc) \ + lea name(%rip), %r10 ; \ + jmp win2lin ## argc + +#include "win2lin_stubs.h" + +#endif // CONFIG_X86_64 --- linux-2.6.37.orig/ubuntu/ndiswrapper/winnt_types.h +++ linux-2.6.37/ubuntu/ndiswrapper/winnt_types.h @@ -0,0 +1,1702 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _WINNT_TYPES_H_ +#define _WINNT_TYPES_H_ + +#define TRUE 1 +#define FALSE 0 + +#define PASSIVE_LEVEL 0 +#define APC_LEVEL 1 +#define DISPATCH_LEVEL 2 +#define DEVICE_LEVEL_BASE 4 + +/* soft interrupts / bottom-half's are disabled at SOFT_IRQL */ +#define SOFT_IRQL (DEVICE_LEVEL_BASE + 1) +#define DIRQL (DEVICE_LEVEL_BASE + 2) + +#define STATUS_WAIT_0 0 +#define STATUS_SUCCESS 0 +#define STATUS_ALERTED 0x00000101 +#define STATUS_TIMEOUT 0x00000102 +#define STATUS_PENDING 0x00000103 +#define STATUS_FAILURE 0xC0000001 +#define STATUS_NOT_IMPLEMENTED 0xC0000002 +#define STATUS_INVALID_PARAMETER 0xC000000D +#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010 +#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016 +#define STATUS_ACCESS_DENIED 0xC0000022 +#define STATUS_BUFFER_TOO_SMALL 0xC0000023 +#define STATUS_OBJECT_NAME_INVALID 0xC0000023 +#define STATUS_MUTANT_NOT_OWNED 0xC0000046 +#define STATUS_RESOURCES 0xC000009A +#define STATUS_DELETE_PENDING 0xC0000056 +#define STATUS_INSUFFICIENT_RESOURCES 0xC000009A +#define STATUS_NOT_SUPPORTED 0xC00000BB +#define STATUS_INVALID_PARAMETER_2 0xC00000F0 +#define STATUS_NO_MEMORY 0xC0000017 +#define STATUS_CANCELLED 0xC0000120 +#define STATUS_DEVICE_REMOVED 0xC00002B6 +#define STATUS_DEVICE_NOT_CONNECTED 0xC000009D + +#define STATUS_BUFFER_OVERFLOW 0x80000005 + +#define SL_PENDING_RETURNED 0x01 +#define SL_INVOKE_ON_CANCEL 0x20 +#define SL_INVOKE_ON_SUCCESS 0x40 +#define SL_INVOKE_ON_ERROR 0x80 + +#define IRP_MJ_CREATE 0x00 +#define IRP_MJ_CREATE_NAMED_PIPE 0x01 +#define IRP_MJ_CLOSE 0x02 +#define IRP_MJ_READ 0x03 +#define IRP_MJ_WRITE 0x04 + +#define IRP_MJ_DEVICE_CONTROL 0x0E +#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0F +#define IRP_MJ_POWER 0x16 +#define IRP_MJ_SYSTEM_CONTROL 0x0E +#define IRP_MJ_PNP 0x1b +#define IRP_MJ_MAXIMUM_FUNCTION 0x1b + +#define IRP_MN_WAIT_WAKE 0x00 +#define IRP_MN_POWER_SEQUENCE 0x01 +#define IRP_MN_SET_POWER 0x02 +#define IRP_MN_QUERY_POWER 0x03 + +#define IRP_MN_REGINFO 0x08 +#define IRP_MN_REGINFO_EX 0x0b + +#define IRP_MN_START_DEVICE 0x00 +#define IRP_MN_QUERY_REMOVE_DEVICE 0x01 +#define IRP_MN_REMOVE_DEVICE 0x02 +#define IRP_MN_CANCEL_REMOVE_DEVICE 0x03 +#define IRP_MN_STOP_DEVICE 0x04 +#define IRP_MN_QUERY_STOP_DEVICE 0x05 +#define IRP_MN_CANCEL_STOP_DEVICE 0x06 +#define IRP_MN_QUERY_DEVICE_RELATIONS 0x07 +#define IRP_MN_QUERY_INTERFACE 0x08 + +#define IRP_BUFFERED_IO 0x00000010 +#define IRP_DEALLOCATE_BUFFER 0x00000020 +#define IRP_INPUT_OPERATION 0x00000040 + +#define IRP_DEFFER_IO_COMPLETION 0x00000800 + +#define THREAD_WAIT_OBJECTS 3 +#define MAX_WAIT_OBJECTS 64 + +#define LOW_PRIORITY 0 +#define LOW_REALTIME_PRIORITY 16 +#define HIGH_PRIORITY 31 +#define MAXIMUM_PRIORITY 32 + +#define PROCESSOR_FEATURE_MAX 64 + +#define IO_NO_INCREMENT 0 + +#define WMIREG_ACTION_REGISTER 1 +#define WMIREG_ACTION_DEREGISTER 2 +#define WMIREG_ACTION_REREGISTER 3 +#define WMIREG_ACTION_UPDATE_GUIDS 4 + +#define WMIREGISTER 0 +#define WMIUPDATE 1 + +#ifdef CONFIG_X86_64 +#define wstdcall +#define wfastcall +#define noregparm + +#define KI_USER_SHARED_DATA 0xfffff78000000000UL + +#else + +#define noregparm __attribute__((regparm(0))) +#define wstdcall __attribute__((__stdcall__, regparm(0))) +#if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ > 3) || __GNUC__ > 3) +#undef fastcall +#define wfastcall __attribute__((fastcall)) +#else +#error "gcc 3.4 or newer should be used for compiling this module" +#endif + +#define KI_USER_SHARED_DATA 0xffdf0000 + +#endif + +#define packed __attribute__((packed)) +#define no_warn_unused __attribute__((unused)) + +typedef u8 BOOLEAN; +typedef u8 BYTE; +typedef u8 *LPBYTE; +typedef s8 CHAR; +typedef u8 UCHAR; +typedef s16 SHORT; +typedef u16 USHORT; +typedef u16 WORD; +typedef s32 INT; +typedef u32 UINT; +typedef u32 DWORD; +typedef s32 LONG; +typedef u32 ULONG; +typedef s64 LONGLONG; +typedef u64 ULONGLONG; +typedef u64 ULONGULONG; +typedef u64 ULONG64; + +typedef CHAR CCHAR; +typedef USHORT wchar_t; +typedef SHORT CSHORT; +typedef LONGLONG LARGE_INTEGER; + +typedef LONG NTSTATUS; + +typedef LONG KPRIORITY; +typedef LARGE_INTEGER PHYSICAL_ADDRESS; +typedef UCHAR KIRQL; +typedef CHAR KPROCESSOR_MODE; + +/* ULONG_PTR is 32 bits on 32-bit platforms and 64 bits on 64-bit + * platform, which is same as 'unsigned long' in Linux */ +typedef unsigned long ULONG_PTR; + +typedef ULONG_PTR SIZE_T; +typedef ULONG_PTR KAFFINITY; +typedef ULONG ACCESS_MASK; + +typedef ULONG_PTR PFN_NUMBER; +typedef ULONG SECURITY_INFORMATION; + +/* non-negative numbers indicate success */ +#define NT_SUCCESS(status) ((NTSTATUS)(status) >= 0) + +struct ansi_string { + USHORT length; + USHORT max_length; + char *buf; +}; + +struct unicode_string { + USHORT length; + USHORT max_length; + wchar_t *buf; +}; + +struct nt_slist { + struct nt_slist *next; +}; + +#ifdef CONFIG_X86_64 +/* it is not clear how nt_slist_head is used to store pointer to + * slists and depth; here we assume 'align' field is used to store + * depth and 'region' field is used to store slist pointers */ +struct nt_slist_head { + union { + USHORT depth; + ULONGLONG align; + }; + union { + ULONGLONG region; + struct nt_slist *next; + }; +} __attribute__((aligned(16))); +typedef struct nt_slist_head nt_slist_header; +#else +union nt_slist_head { + ULONGLONG align; + struct { + struct nt_slist *next; + USHORT depth; + USHORT sequence; + }; +}; +typedef union nt_slist_head nt_slist_header; +#endif + +struct nt_list { + struct nt_list *next; + struct nt_list *prev; +}; + +typedef ULONG_PTR NT_SPIN_LOCK; + +enum kdpc_importance {LowImportance, MediumImportance, HighImportance}; + +struct kdpc; +typedef void (*DPC)(struct kdpc *kdpc, void *ctx, void *arg1, + void *arg2) wstdcall; +struct kdpc { + SHORT type; + UCHAR nr_cpu; + UCHAR importance; + struct nt_list list; + DPC func; + void *ctx; + void *arg1; + void *arg2; + union { + NT_SPIN_LOCK *lock; + /* 'lock' is not used; 'queued' represents whether + * kdpc is queued or not */ + int queued; + }; +}; + +enum pool_type { + NonPagedPool, PagedPool, NonPagedPoolMustSucceed, DontUseThisType, + NonPagedPoolCacheAligned, PagedPoolCacheAligned, + NonPagedPoolCacheAlignedMustS, MaxPoolType, + NonPagedPoolSession = 32, + PagedPoolSession = NonPagedPoolSession + 1, + NonPagedPoolMustSucceedSession = PagedPoolSession + 1, + DontUseThisTypeSession = NonPagedPoolMustSucceedSession + 1, + NonPagedPoolCacheAlignedSession = DontUseThisTypeSession + 1, + PagedPoolCacheAlignedSession = NonPagedPoolCacheAlignedSession + 1, + NonPagedPoolCacheAlignedMustSSession = PagedPoolCacheAlignedSession + 1 +}; + +enum memory_caching_type_orig { + MmFrameBufferCached = 2 +}; + +enum memory_caching_type { + MmNonCached = FALSE, MmCached = TRUE, + MmWriteCombined = MmFrameBufferCached, MmHardwareCoherentCached, + MmNonCachedUnordered, MmUSWCCached, MmMaximumCacheType +}; + +enum lock_operation { + IoReadAccess, IoWriteAccess, IoModifyAccess +}; + +enum mode { + KernelMode, UserMode, MaximumMode +}; + +struct mdl { + struct mdl *next; + CSHORT size; + CSHORT flags; + /* NdisFreeBuffer doesn't pass pool, so we store pool in + * unused field 'process' */ + union { + void *process; + void *pool; + }; + void *mappedsystemva; + void *startva; + ULONG bytecount; + ULONG byteoffset; +}; + +#define MDL_MAPPED_TO_SYSTEM_VA 0x0001 +#define MDL_PAGES_LOCKED 0x0002 +#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004 +#define MDL_ALLOCATED_FIXED_SIZE 0x0008 +#define MDL_PARTIAL 0x0010 +#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020 +#define MDL_IO_PAGE_READ 0x0040 +#define MDL_WRITE_OPERATION 0x0080 +#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100 +#define MDL_FREE_EXTRA_PTES 0x0200 +#define MDL_IO_SPACE 0x0800 +#define MDL_NETWORK_HEADER 0x1000 +#define MDL_MAPPING_CAN_FAIL 0x2000 +#define MDL_ALLOCATED_MUST_SUCCEED 0x4000 + +#define MDL_POOL_ALLOCATED 0x0400 +#define MDL_CACHE_ALLOCATED 0x8000 + +#define PAGE_START(ptr) ((void *)((ULONG_PTR)(ptr) & ~(PAGE_SIZE - 1))) +#define BYTE_OFFSET(ptr) ((ULONG)((ULONG_PTR)(ptr) & (PAGE_SIZE - 1))) + +#define MmGetMdlByteCount(mdl) ((mdl)->bytecount) +#define MmGetMdlVirtualAddress(mdl) ((mdl)->startva + (mdl)->byteoffset) +#define MmGetMdlByteOffset(mdl) ((mdl)->byteoffset) +#define MmGetSystemAddressForMdl(mdl) ((mdl)->mappedsystemva) +#define MmGetSystemAddressForMdlSafe(mdl, priority) ((mdl)->mappedsystemva) +#define MmGetMdlPfnArray(mdl) ((PFN_NUMBER *)(mdl + 1)) +#define MmInitializeMdl(mdl, baseva, length) \ +do { \ + (mdl)->next = NULL; \ + (mdl)->size = MmSizeOfMdl(baseva, length); \ + (mdl)->flags = 0; \ + (mdl)->startva = PAGE_START(baseva); \ + (mdl)->byteoffset = BYTE_OFFSET(baseva); \ + (mdl)->bytecount = length; \ + (mdl)->mappedsystemva = baseva; \ + TRACE4("%p %p %p %d %d", (mdl), baseva, (mdl)->startva, \ + (mdl)->byteoffset, length); \ +} while (0) + +struct kdevice_queue_entry { + struct nt_list list; + ULONG sort_key; + BOOLEAN inserted; +}; + +struct kdevice_queue { + USHORT type; + USHORT size; + struct nt_list list; + NT_SPIN_LOCK lock; + BOOLEAN busy; +}; + +struct wait_context_block { + struct kdevice_queue_entry wait_queue_entry; + void *device_routine; + void *device_context; + ULONG num_regs; + void *device_object; + void *current_irp; + void *buffer_chaining_dpc; +}; + +struct wait_block { + struct nt_list list; + struct task_struct *thread; + void *object; + int *wait_done; + USHORT wait_key; + USHORT wait_type; +}; + +struct dispatcher_header { + UCHAR type; + UCHAR absolute; + UCHAR size; + UCHAR inserted; + LONG signal_state; + struct nt_list wait_blocks; +}; + +enum event_type { + NotificationEvent, + SynchronizationEvent, +}; + +enum timer_type { + NotificationTimer = NotificationEvent, + SynchronizationTimer = SynchronizationEvent, +}; + +enum dh_type { + NotificationObject = NotificationEvent, + SynchronizationObject = SynchronizationEvent, + MutexObject, + SemaphoreObject, + ThreadObject, +}; + +enum wait_type { + WaitAll, WaitAny +}; + +/* objects that use dispatcher_header have it as the first field, so + * whenever we need to initialize dispatcher_header, we can convert + * that object into a nt_event and access dispatcher_header */ +struct nt_event { + struct dispatcher_header dh; +}; + +struct wrap_timer; + +#define WRAP_TIMER_MAGIC 47697249 + +struct nt_timer { + struct dispatcher_header dh; + /* We can't fit Linux timer in this structure. Instead of + * padding the nt_timer structure, we replace due_time field + * with *wrap_timer and allocate memory for it when nt_timer is + * initialized */ + union { + ULONGLONG due_time; + struct wrap_timer *wrap_timer; + }; + struct nt_list nt_timer_list; + struct kdpc *kdpc; + union { + LONG period; + LONG wrap_timer_magic; + }; +}; + +struct nt_mutex { + struct dispatcher_header dh; + struct nt_list list; + struct task_struct *owner_thread; + BOOLEAN abandoned; + BOOLEAN apc_disable; +}; + +struct nt_semaphore { + struct dispatcher_header dh; + LONG limit; +}; + +struct nt_thread { + struct dispatcher_header dh; + /* the rest in Windows is a long structure; since this + * structure is opaque to drivers, we just define what we + * need */ + int pid; + NTSTATUS status; + struct task_struct *task; + struct nt_list irps; + NT_SPIN_LOCK lock; + KPRIORITY prio; +}; + +#define set_object_type(dh, type) ((dh)->type = (type)) +#define is_notify_object(dh) ((dh)->type == NotificationObject) +#define is_synch_object(dh) ((dh)->type == SynchronizationObject) +#define is_mutex_object(dh) ((dh)->type == MutexObject) +#define is_semaphore_object(dh) ((dh)->type == SemaphoreObject) +#define is_nt_thread_object(dh) ((dh)->type == ThreadObject) + +#define IO_TYPE_ADAPTER 1 +#define IO_TYPE_CONTROLLER 2 +#define IO_TYPE_DEVICE 3 +#define IO_TYPE_DRIVER 4 +#define IO_TYPE_FILE 5 +#define IO_TYPE_IRP 6 +#define IO_TYPE_DEVICE_OBJECT_EXTENSION 13 + +struct irp; +struct dev_obj_ext; +struct driver_object; + +struct device_object { + CSHORT type; + USHORT size; + LONG ref_count; + struct driver_object *drv_obj; + struct device_object *next; + struct device_object *attached; + struct irp *current_irp; + void *io_timer; + ULONG flags; + ULONG characteristics; + void *vpb; + void *dev_ext; + CCHAR stack_count; + union { + struct nt_list queue_list; + struct wait_context_block wcb; + } queue; + ULONG align_req; + struct kdevice_queue dev_queue; + struct kdpc dpc; + ULONG active_threads; + void *security_desc; + struct nt_event lock; + USHORT sector_size; + USHORT spare1; + struct dev_obj_ext *dev_obj_ext; + void *reserved; +}; + +struct dev_obj_ext { + CSHORT type; + CSHORT size; + struct device_object *dev_obj; + struct device_object *attached_to; +}; + +struct io_status_block { + union { + NTSTATUS status; + void *pointer; + }; + ULONG_PTR info; +}; + +#ifdef CONFIG_X86_64 +struct io_status_block32 { + NTSTATUS status; + ULONG info; +}; +#endif + +#define DEVICE_TYPE ULONG + +struct driver_extension; + +typedef NTSTATUS driver_dispatch_t(struct device_object *dev_obj, + struct irp *irp) wstdcall; + +struct driver_object { + CSHORT type; + CSHORT size; + struct device_object *dev_obj; + ULONG flags; + void *start; + ULONG driver_size; + void *section; + struct driver_extension *drv_ext; + struct unicode_string name; + struct unicode_string *hardware_database; + void *fast_io_dispatch; + void *init; + void *start_io; + void (*unload)(struct driver_object *driver) wstdcall; + driver_dispatch_t *major_func[IRP_MJ_MAXIMUM_FUNCTION + 1]; +}; + +struct driver_extension { + struct driver_object *drv_obj; + NTSTATUS (*add_device)(struct driver_object *drv_obj, + struct device_object *dev_obj) wstdcall; + ULONG count; + struct unicode_string service_key_name; + struct nt_list custom_ext; +}; + +struct custom_ext { + struct nt_list list; + void *client_id; +}; + +struct wrap_bin_file; + +struct file_object { + CSHORT type; + CSHORT size; + struct device_object *dev_obj; + void *volume_parameter_block; + void *fs_context; + void *fs_context2; + void *section_object_pointer; + void *private_cache_map; + NTSTATUS final_status; + union { + struct file_object *related_file_object; + struct wrap_bin_file *wrap_bin_file; + }; + BOOLEAN lock_operation; + BOOLEAN delete_pending; + BOOLEAN read_access; + BOOLEAN write_access; + BOOLEAN delete_access; + BOOLEAN shared_read; + BOOLEAN shared_write; + BOOLEAN shared_delete; + ULONG flags; + struct unicode_string _name_; + LARGE_INTEGER current_byte_offset; + ULONG waiters; + ULONG busy; + void *last_lock; + struct nt_event lock; + struct nt_event event; + void *completion_context; +}; + +#ifdef CONFIG_X86_64 +#define POINTER_ALIGN __attribute__((aligned(8))) +#else +#define POINTER_ALIGN +#endif + +#define CACHE_ALIGN __attribute__((aligned(128))) + +enum system_power_state { + PowerSystemUnspecified = 0, + PowerSystemWorking, PowerSystemSleeping1, PowerSystemSleeping2, + PowerSystemSleeping3, PowerSystemHibernate, PowerSystemShutdown, + PowerSystemMaximum, +}; + +enum device_power_state { + PowerDeviceUnspecified = 0, + PowerDeviceD0, PowerDeviceD1, PowerDeviceD2, PowerDeviceD3, + PowerDeviceMaximum, +}; + +union power_state { + enum system_power_state system_state; + enum device_power_state device_state; +}; + +enum power_state_type { + SystemPowerState = 0, DevicePowerState, +}; + +enum power_action { + PowerActionNone = 0, + PowerActionReserved, PowerActionSleep, PowerActionHibernate, + PowerActionShutdown, PowerActionShutdownReset, PowerActionShutdownOff, + PowerActionWarmEject, +}; + +struct guid { + ULONG data1; + USHORT data2; + USHORT data3; + UCHAR data4[8]; +}; + +struct nt_interface { + USHORT size; + USHORT version; + void *context; + void (*reference)(void *context) wstdcall; + void (*dereference)(void *context) wstdcall; +}; + +enum interface_type { + InterfaceTypeUndefined = -1, Internal, Isa, Eisa, MicroChannel, + TurboChannel, PCIBus, VMEBus, NuBus, PCMCIABus, CBus, MPIBus, + MPSABus, ProcessorInternal, InternalPowerBus, PNPISABus, + PNPBus, MaximumInterfaceType, +}; + +#define CmResourceTypeNull 0 +#define CmResourceTypePort 1 +#define CmResourceTypeInterrupt 2 +#define CmResourceTypeMemory 3 +#define CmResourceTypeDma 4 +#define CmResourceTypeDeviceSpecific 5 +#define CmResourceTypeBusNumber 6 +#define CmResourceTypeMaximum 7 + +#define CmResourceTypeNonArbitrated 128 +#define CmResourceTypeConfigData 128 +#define CmResourceTypeDevicePrivate 129 +#define CmResourceTypePcCardConfig 130 +#define CmResourceTypeMfCardConfig 131 + +enum cm_share_disposition { + CmResourceShareUndetermined = 0, CmResourceShareDeviceExclusive, + CmResourceShareDriverExclusive, CmResourceShareShared +}; + +#define CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE 0 +#define CM_RESOURCE_INTERRUPT_LATCHED 1 +#define CM_RESOURCE_MEMORY_READ_WRITE 0x0000 +#define CM_RESOURCE_MEMORY_READ_ONLY 0x0001 +#define CM_RESOURCE_MEMORY_WRITE_ONLY 0x0002 +#define CM_RESOURCE_MEMORY_PREFETCHABLE 0x0004 + +#define CM_RESOURCE_MEMORY_COMBINEDWRITE 0x0008 +#define CM_RESOURCE_MEMORY_24 0x0010 +#define CM_RESOURCE_MEMORY_CACHEABLE 0x0020 + +#define CM_RESOURCE_PORT_MEMORY 0x0000 +#define CM_RESOURCE_PORT_IO 0x0001 +#define CM_RESOURCE_PORT_10_BIT_DECODE 0x0004 +#define CM_RESOURCE_PORT_12_BIT_DECODE 0x0008 +#define CM_RESOURCE_PORT_16_BIT_DECODE 0x0010 +#define CM_RESOURCE_PORT_POSITIVE_DECODE 0x0020 +#define CM_RESOURCE_PORT_PASSIVE_DECODE 0x0040 +#define CM_RESOURCE_PORT_WINDOW_DECODE 0x0080 + +#define CM_RESOURCE_DMA_8 0x0000 +#define CM_RESOURCE_DMA_16 0x0001 +#define CM_RESOURCE_DMA_32 0x0002 +#define CM_RESOURCE_DMA_8_AND_16 0x0004 +#define CM_RESOURCE_DMA_BUS_MASTER 0x0008 +#define CM_RESOURCE_DMA_TYPE_A 0x0010 +#define CM_RESOURCE_DMA_TYPE_B 0x0020 +#define CM_RESOURCE_DMA_TYPE_F 0x0040 + +#define MAX_RESOURCES 20 + +#pragma pack(push,4) +struct cm_partial_resource_descriptor { + UCHAR type; + UCHAR share; + USHORT flags; + union { + struct { + PHYSICAL_ADDRESS start; + ULONG length; + } generic; + struct { + PHYSICAL_ADDRESS start; + ULONG length; + } port; + struct { + ULONG level; + ULONG vector; + KAFFINITY affinity; + } interrupt; + struct { + PHYSICAL_ADDRESS start; + ULONG length; + } memory; + struct { + ULONG channel; + ULONG port; + ULONG reserved1; + } dma; + struct { + ULONG data[3]; + } device_private; + struct { + ULONG start; + ULONG length; + ULONG reserved; + } bus_number; + struct { + ULONG data_size; + ULONG reserved1; + ULONG reserved2; + } device_specific_data; + } u; +}; +#pragma pack(pop) + +struct cm_partial_resource_list { + USHORT version; + USHORT revision; + ULONG count; + struct cm_partial_resource_descriptor partial_descriptors[1]; +}; + +struct cm_full_resource_descriptor { + enum interface_type interface_type; + ULONG bus_number; + struct cm_partial_resource_list partial_resource_list; +}; + +struct cm_resource_list { + ULONG count; + struct cm_full_resource_descriptor list[1]; +}; + +enum file_info_class { + FileDirectoryInformation = 1, + FileBasicInformation = 4, + FileStandardInformation = 5, + FileNameInformation = 9, + FilePositionInformation = 14, + FileAlignmentInformation = 17, + FileNetworkOpenInformation = 34, + FileAttributeTagInformation = 35, + FileMaximumInformation = 41, +}; + +enum fs_info_class { + FileFsVolumeInformation = 1, + /* ... */ + FileFsMaximumInformation = 9, +}; + +enum device_relation_type { + BusRelations, EjectionRelations, PowerRelations, RemovalRelations, + TargetDeviceRelation, SingleBusRelations, +}; + +enum bus_query_id_type { + BusQueryDeviceID = 0, BusQueryHardwareIDs = 1, + BusQueryCompatibleIDs = 2, BusQueryInstanceID = 3, + BusQueryDeviceSerialNumber = 4, +}; + +enum device_text_type { + DeviceTextDescription = 0, DeviceTextLocationInformation = 1, +}; + +enum device_usage_notification_type { + DeviceUsageTypeUndefined, DeviceUsageTypePaging, + DeviceUsageTypeHibernation, DevbiceUsageTypeDumpFile, +}; + +#define METHOD_BUFFERED 0 +#define METHOD_IN_DIRECT 1 +#define METHOD_OUT_DIRECT 2 +#define METHOD_NEITHER 3 + +#define CTL_CODE(dev_type, func, method, access) \ + (((dev_type) << 16) | ((access) << 14) | ((func) << 2) | (method)) + +#define IO_METHOD_FROM_CTL_CODE(code) (code & 0x3) + +#ifndef CONFIG_X86_64 +#pragma pack(push,4) +#endif +struct io_stack_location { + UCHAR major_fn; + UCHAR minor_fn; + UCHAR flags; + UCHAR control; + union { + struct { + void *security_context; + ULONG options; + USHORT POINTER_ALIGN file_attributes; + USHORT share_access; + ULONG POINTER_ALIGN ea_length; + } create; + struct { + ULONG length; + ULONG POINTER_ALIGN key; + LARGE_INTEGER byte_offset; + } read; + struct { + ULONG length; + ULONG POINTER_ALIGN key; + LARGE_INTEGER byte_offset; + } write; + struct { + ULONG length; + enum file_info_class POINTER_ALIGN file_info_class; + } query_file; + struct { + ULONG length; + enum file_info_class POINTER_ALIGN file_info_class; + struct file_object *file_object; + union { + struct { + BOOLEAN replace_if_exists; + BOOLEAN advance_only; + }; + ULONG cluster_count; + void *delete_handle; + }; + } set_file; + struct { + ULONG length; + enum fs_info_class POINTER_ALIGN fs_info_class; + } query_volume; + struct { + ULONG output_buf_len; + ULONG POINTER_ALIGN input_buf_len; + ULONG POINTER_ALIGN code; + void *type3_input_buf; + } dev_ioctl; + struct { + SECURITY_INFORMATION security_info; + ULONG POINTER_ALIGN length; + } query_security; + struct { + SECURITY_INFORMATION security_info; + void *security_descriptor; + } set_security; + struct { + void *vpb; + struct device_object *device_object; + } mount_volume; + struct { + void *vpb; + struct device_object *device_object; + } verify_volume; + struct { + void *srb; + } scsi; + struct { + enum device_relation_type type; + } query_device_relations; + struct { + const struct guid *type; + USHORT size; + USHORT version; + struct nt_interface *intf; + void *intf_data; + } query_intf; + struct { + void *capabilities; + } device_capabilities; + struct { + void *io_resource_requirement_list; + } filter_resource_requirements; + struct { + ULONG which_space; + void *buffer; + ULONG offset; + ULONG POINTER_ALIGN length; + } read_write_config; + struct { + BOOLEAN lock; + } set_lock; + struct { + enum bus_query_id_type id_type; + } query_id; + struct { + enum device_text_type device_text_type; + ULONG POINTER_ALIGN locale_id; + } query_device_text; + struct { + BOOLEAN in_path; + BOOLEAN reserved[3]; + enum device_usage_notification_type POINTER_ALIGN type; + } usage_notification; + struct { + enum system_power_state power_state; + } wait_wake; + struct { + void *power_sequence; + } power_sequence; + struct { + ULONG sys_context; + enum power_state_type POINTER_ALIGN type; + union power_state POINTER_ALIGN state; + enum power_action POINTER_ALIGN shutdown_type; + } power; + struct { + struct cm_resource_list *allocated_resources; + struct cm_resource_list *allocated_resources_translated; + } start_device; + struct { + ULONG_PTR provider_id; + void *data_path; + ULONG buf_len; + void *buf; + } wmi; + struct { + void *arg1; + void *arg2; + void *arg3; + void *arg4; + } others; + } params; + struct device_object *dev_obj; + struct file_object *file_obj; + NTSTATUS (*completion_routine)(struct device_object *, + struct irp *, void *) wstdcall; + void *context; +}; +#ifndef CONFIG_X86_64 +#pragma pack(pop) +#endif + +struct kapc { + CSHORT type; + CSHORT size; + ULONG spare0; + struct nt_thread *thread; + struct nt_list list; + void *kernele_routine; + void *rundown_routine; + void *normal_routine; + void *normal_context; + void *sys_arg1; + void *sys_arg2; + CCHAR apc_state_index; + KPROCESSOR_MODE apc_mode; + BOOLEAN inserted; +}; + +#define IRP_NOCACHE 0x00000001 +#define IRP_SYNCHRONOUS_API 0x00000004 +#define IRP_ASSOCIATED_IRP 0x00000008 + +enum urb_state { + URB_INVALID = 1, URB_ALLOCATED, URB_SUBMITTED, + URB_COMPLETED, URB_FREE, URB_SUSPEND, URB_INT_UNLINKED }; + +struct wrap_urb { + struct nt_list list; + enum urb_state state; + struct nt_list complete_list; + unsigned int flags; + struct urb *urb; + struct irp *irp; +#ifdef USB_DEBUG + unsigned int id; +#endif +}; + +struct irp { + SHORT type; + USHORT size; + struct mdl *mdl; + ULONG flags; + union { + struct irp *master_irp; + LONG irp_count; + void *system_buffer; + } associated_irp; + struct nt_list thread_list; + struct io_status_block io_status; + KPROCESSOR_MODE requestor_mode; + BOOLEAN pending_returned; + CHAR stack_count; + CHAR current_location; + BOOLEAN cancel; + KIRQL cancel_irql; + CCHAR apc_env; + UCHAR alloc_flags; + struct io_status_block *user_status; + struct nt_event *user_event; + union { + struct { + void *user_apc_routine; + void *user_apc_context; + } async_params; + LARGE_INTEGER alloc_size; + } overlay; + void (*cancel_routine)(struct device_object *, struct irp *) wstdcall; + void *user_buf; + union { + struct { + union { + struct kdevice_queue_entry dev_q_entry; + struct { + void *driver_context[4]; + }; + }; + void *thread; + char *aux_buf; + struct { + struct nt_list list; + union { + struct io_stack_location *csl; + ULONG packet_type; + }; + }; + struct file_object *file_object; + } overlay; + union { + struct kapc apc; + /* space for apc is used for ndiswrapper + * specific fields */ + struct { + struct wrap_urb *wrap_urb; + struct wrap_device *wrap_device; + }; + }; + void *completion_key; + } tail; +}; + +#define IoSizeOfIrp(stack_count) \ + ((USHORT)(sizeof(struct irp) + \ + ((stack_count) * sizeof(struct io_stack_location)))) +#define IoGetCurrentIrpStackLocation(irp) \ + (irp)->tail.overlay.csl +#define IoGetNextIrpStackLocation(irp) \ + (IoGetCurrentIrpStackLocation(irp) - 1) +#define IoGetPreviousIrpStackLocation(irp) \ + (IoGetCurrentIrpStackLocation(irp) + 1) + +#define IoSetNextIrpStackLocation(irp) \ +do { \ + KIRQL _irql_; \ + IoAcquireCancelSpinLock(&_irql_); \ + (irp)->current_location--; \ + IoGetCurrentIrpStackLocation(irp)--; \ + IoReleaseCancelSpinLock(_irql_); \ +} while (0) + +#define IoSkipCurrentIrpStackLocation(irp) \ +do { \ + KIRQL _irql_; \ + IoAcquireCancelSpinLock(&_irql_); \ + (irp)->current_location++; \ + IoGetCurrentIrpStackLocation(irp)++; \ + IoReleaseCancelSpinLock(_irql_); \ +} while (0) + +static inline void +IoCopyCurrentIrpStackLocationToNext(struct irp *irp) +{ + struct io_stack_location *next; + next = IoGetNextIrpStackLocation(irp); + memcpy(next, IoGetCurrentIrpStackLocation(irp), + offsetof(struct io_stack_location, completion_routine)); + next->control = 0; +} + +static inline void +IoSetCompletionRoutine(struct irp *irp, void *routine, void *context, + BOOLEAN success, BOOLEAN error, BOOLEAN cancel) +{ + struct io_stack_location *irp_sl = IoGetNextIrpStackLocation(irp); + irp_sl->completion_routine = routine; + irp_sl->context = context; + irp_sl->control = 0; + if (success) + irp_sl->control |= SL_INVOKE_ON_SUCCESS; + if (error) + irp_sl->control |= SL_INVOKE_ON_ERROR; + if (cancel) + irp_sl->control |= SL_INVOKE_ON_CANCEL; +} + +#define IoMarkIrpPending(irp) \ + (IoGetCurrentIrpStackLocation((irp))->control |= SL_PENDING_RETURNED) +#define IoUnmarkIrpPending(irp) \ + (IoGetCurrentIrpStackLocation((irp))->control &= ~SL_PENDING_RETURNED) + +#define IRP_SL(irp, n) (((struct io_stack_location *)((irp) + 1)) + (n)) +#define IRP_DRIVER_CONTEXT(irp) (irp)->tail.overlay.driver_context +#define IoIrpThread(irp) ((irp)->tail.overlay.thread) + +#define IRP_URB(irp) \ + (union nt_urb *)(IoGetCurrentIrpStackLocation(irp)->params.others.arg1) + +#define IRP_WRAP_DEVICE(irp) (irp)->tail.wrap_device +#define IRP_WRAP_URB(irp) (irp)->tail.wrap_urb + +struct wmi_guid_reg_info { + struct guid *guid; + ULONG instance_count; + ULONG flags; +}; + +struct wmilib_context { + ULONG guid_count; + struct wmi_guid_reg_info *guid_list; + void *query_wmi_reg_info; + void *query_wmi_data_block; + void *set_wmi_data_block; + void *set_wmi_data_item; + void *execute_wmi_method; + void *wmi_function_control; +}; + +enum key_value_information_class { + KeyValueBasicInformation, KeyValueFullInformation, + KeyValuePartialInformation, KeyValueFullInformationAlign64, + KeyValuePartialInformationAlign64 +}; + +struct file_name_info { + ULONG length; + wchar_t *name; +}; + +struct file_std_info { + LARGE_INTEGER alloc_size; + LARGE_INTEGER eof; + ULONG num_links; + BOOLEAN delete_pending; + BOOLEAN dir; +}; + +enum nt_obj_type { + NT_OBJ_EVENT = 10, NT_OBJ_MUTEX, NT_OBJ_THREAD, NT_OBJ_TIMER, + NT_OBJ_SEMAPHORE, +}; + +enum common_object_type { + OBJECT_TYPE_NONE, OBJECT_TYPE_DEVICE, OBJECT_TYPE_DRIVER, + OBJECT_TYPE_NT_THREAD, OBJECT_TYPE_FILE, OBJECT_TYPE_CALLBACK, +}; + +struct common_object_header { + struct nt_list list; + enum common_object_type type; + UINT size; + UINT ref_count; + BOOLEAN close_in_process; + BOOLEAN permanent; + struct unicode_string name; +}; + +#define OBJECT_TO_HEADER(object) \ + (struct common_object_header *)((void *)(object) - \ + sizeof(struct common_object_header)) +#define OBJECT_SIZE(size) \ + ((size) + sizeof(struct common_object_header)) +#define HEADER_TO_OBJECT(hdr) \ + ((void *)(hdr) + sizeof(struct common_object_header)) +#define HANDLE_TO_OBJECT(handle) HEADER_TO_OBJECT(handle) +#define HANDLE_TO_HEADER(handle) (handle) + +enum work_queue_type { + CriticalWorkQueue, DelayedWorkQueue, HyperCriticalWorkQueue, + MaximumWorkQueue +}; + +typedef void (*NTOS_WORK_FUNC)(void *arg1, void *arg2) wstdcall; + +struct io_workitem { + enum work_queue_type type; + struct device_object *dev_obj; + NTOS_WORK_FUNC worker_routine; + void *context; +}; + +struct io_workitem_entry { + struct nt_list list; + struct io_workitem *io_workitem; +}; + +enum mm_page_priority { + LowPagePriority, NormalPagePriority = 16, HighPagePriority = 32 +}; + +enum kinterrupt_mode { + LevelSensitive, Latched +}; + +enum ntos_wait_reason { + Executive, FreePage, PageIn, PoolAllocation, DelayExecution, + Suspended, UserRequest, WrExecutive, WrFreePage, WrPageIn, + WrPoolAllocation, WrDelayExecution, WrSuspended, WrUserRequest, + WrEventPair, WrQueue, WrLpcReceive, WrLpcReply, WrVirtualMemory, + WrPageOut, WrRendezvous, Spare2, Spare3, Spare4, Spare5, Spare6, + WrKernel, MaximumWaitReason +}; + +typedef enum ntos_wait_reason KWAIT_REASON; + +typedef void *LOOKASIDE_ALLOC_FUNC(enum pool_type pool_type, + SIZE_T size, ULONG tag) wstdcall; +typedef void LOOKASIDE_FREE_FUNC(void *) wstdcall; + +struct npaged_lookaside_list { + nt_slist_header head; + USHORT depth; + USHORT maxdepth; + ULONG totalallocs; + union { + ULONG allocmisses; + ULONG allochits; + } u1; + ULONG totalfrees; + union { + ULONG freemisses; + ULONG freehits; + } u2; + enum pool_type pool_type; + ULONG tag; + ULONG size; + LOOKASIDE_ALLOC_FUNC *alloc_func; + LOOKASIDE_FREE_FUNC *free_func; + struct nt_list list; + ULONG lasttotallocs; + union { + ULONG lastallocmisses; + ULONG lastallochits; + } u3; + ULONG pad[2]; +#ifndef CONFIG_X86_64 + NT_SPIN_LOCK obsolete; +#endif +} +#ifdef CONFIG_X86_64 +CACHE_ALIGN +#endif +; + +enum device_registry_property { + DevicePropertyDeviceDescription, DevicePropertyHardwareID, + DevicePropertyCompatibleIDs, DevicePropertyBootConfiguration, + DevicePropertyBootConfigurationTranslated, + DevicePropertyClassName, DevicePropertyClassGuid, + DevicePropertyDriverKeyName, DevicePropertyManufacturer, + DevicePropertyFriendlyName, DevicePropertyLocationInformation, + DevicePropertyPhysicalDeviceObjectName, DevicePropertyBusTypeGuid, + DevicePropertyLegacyBusType, DevicePropertyBusNumber, + DevicePropertyEnumeratorName, DevicePropertyAddress, + DevicePropertyUINumber, DevicePropertyInstallState, + DevicePropertyRemovalPolicy +}; + +enum trace_information_class { + TraceIdClass, TraceHandleClass, TraceEnableFlagsClass, + TraceEnableLevelClass, GlobalLoggerHandleClass, EventLoggerHandleClass, + AllLoggerHandlesClass, TraceHandleByNameClass +}; + +struct kinterrupt; +typedef BOOLEAN (*PKSERVICE_ROUTINE)(struct kinterrupt *interrupt, + void *context) wstdcall; +typedef BOOLEAN (*PKSYNCHRONIZE_ROUTINE)(void *context) wstdcall; + +struct kinterrupt { + ULONG vector; + KAFFINITY cpu_mask; + NT_SPIN_LOCK lock; + NT_SPIN_LOCK *actual_lock; + BOOLEAN shared; + BOOLEAN save_fp; + union { + CHAR processor_number; +#ifdef CONFIG_DEBUG_SHIRQ + CHAR enabled; +#endif + } u; + PKSERVICE_ROUTINE isr; + void *isr_ctx; + struct nt_list list; + KIRQL irql; + KIRQL synch_irql; + enum kinterrupt_mode mode; +}; + +struct time_fields { + CSHORT year; + CSHORT month; + CSHORT day; + CSHORT hour; + CSHORT minute; + CSHORT second; + CSHORT milliseconds; + CSHORT weekday; +}; + +struct object_attributes { + ULONG length; + void *root_dir; + struct unicode_string *name; + ULONG attributes; + void *security_descr; + void *security_qos; +}; + +typedef void (*PCALLBACK_FUNCTION)(void *context, void *arg1, + void *arg2) wstdcall; + +struct callback_object; +struct callback_func { + PCALLBACK_FUNCTION func; + void *context; + struct nt_list list; + struct callback_object *object; +}; + +struct callback_object { + NT_SPIN_LOCK lock; + struct nt_list list; + struct nt_list callback_funcs; + BOOLEAN allow_multiple_callbacks; + struct object_attributes *attributes; +}; + +enum section_inherit { + ViewShare = 1, ViewUnmap = 2 +}; + +struct ksystem_time { + ULONG low_part; + LONG high1_time; + LONG high2_time; +}; + +enum nt_product_type { + nt_product_win_nt = 1, nt_product_lan_man_nt, nt_product_server +}; + +enum alt_arch_type { + arch_type_standard, arch_type_nex98x86, end_alternatives +}; + +struct kuser_shared_data { + ULONG tick_count; + ULONG tick_count_multiplier; + volatile struct ksystem_time interrupt_time; + volatile struct ksystem_time system_time; + volatile struct ksystem_time time_zone_bias; + USHORT image_number_low; + USHORT image_number_high; + wchar_t nt_system_root[260]; + ULONG max_stack_trace_depth; + ULONG crypto_exponent; + ULONG time_zone_id; + ULONG large_page_min; + ULONG reserved2[7]; + enum nt_product_type nt_product_type; + BOOLEAN product_type_is_valid; + ULONG nt_major_version; + ULONG nt_minor_version; + BOOLEAN processor_features[PROCESSOR_FEATURE_MAX]; + ULONG reserved1; + ULONG reserved3; + volatile LONG time_slip; + enum alt_arch_type alt_arch_type; + LARGE_INTEGER system_expiration_date; + ULONG suite_mask; + BOOLEAN kdbg_enabled; + volatile ULONG active_console; + volatile ULONG dismount_count; + ULONG com_plus_package; + ULONG last_system_rite_event_tick_count; + ULONG num_phys_pages; + BOOLEAN safe_boot_mode; + ULONG trace_log; + ULONGLONG fill0; + ULONGLONG sys_call[4]; + union { + volatile struct ksystem_time tick_count; + volatile ULONG64 tick_count_quad; + } tick; +}; + +#define REG_NONE (0) +#define REG_SZ (1) +#define REG_EXPAND_SZ (2) +#define REG_BINARY (3) +#define REG_DWORD (4) + +#define RTL_REGISTRY_ABSOLUTE 0 +#define RTL_REGISTRY_SERVICES 1 +#define RTL_REGISTRY_CONTROL 2 +#define RTL_REGISTRY_WINDOWS_NT 3 +#define RTL_REGISTRY_DEVICEMAP 4 +#define RTL_REGISTRY_USER 5 +#define RTL_REGISTRY_MAXIMUM 6 +#define RTL_REGISTRY_HANDLE 0x40000000 +#define RTL_REGISTRY_OPTIONAL 0x80000000 + +#define RTL_QUERY_REGISTRY_SUBKEY 0x00000001 +#define RTL_QUERY_REGISTRY_TOPKEY 0x00000002 +#define RTL_QUERY_REGISTRY_REQUIRED 0x00000004 +#define RTL_QUERY_REGISTRY_NOVALUE 0x00000008 +#define RTL_QUERY_REGISTRY_NOEXPAND 0x00000010 +#define RTL_QUERY_REGISTRY_DIRECT 0x00000020 +#define RTL_QUERY_REGISTRY_DELETE 0x00000040 + +typedef NTSTATUS (*PRTL_QUERY_REGISTRY_ROUTINE)(wchar_t *name, ULONG type, + void *data, ULONG length, + void *context, + void *entry) wstdcall; + +struct rtl_query_registry_table { + PRTL_QUERY_REGISTRY_ROUTINE query_func; + ULONG flags; + wchar_t *name; + void *context; + ULONG def_type; + void *def_data; + ULONG def_length; +}; + +struct io_remove_lock { + BOOLEAN removed; + BOOLEAN reserved[3]; + LONG io_count; + struct nt_event remove_event; +}; + +struct io_error_log_packet { + UCHAR major_fn_code; + UCHAR retry_count; + USHORT dump_data_size; + USHORT nr_of_strings; + USHORT string_offset; + USHORT event_category; + NTSTATUS error_code; + ULONG unique_error_value; + NTSTATUS final_status; + ULONG sequence_number; + ULONG io_control_code; + LARGE_INTEGER device_offset; + ULONG dump_data[1]; +}; + +/* some of the functions below are slightly different from DDK's + * implementation; e.g., Insert functions return appropriate + * pointer */ + +/* instead of using Linux's lists, we implement list manipulation + * functions because nt_list is used by drivers and we don't want to + * worry about Linux's list being different from nt_list (right now + * they are same, but in future they could be different) */ + +static inline void InitializeListHead(struct nt_list *head) +{ + head->next = head->prev = head; +} + +static inline BOOLEAN IsListEmpty(struct nt_list *head) +{ + if (head == head->next) + return TRUE; + else + return FALSE; +} + +static inline void RemoveEntryList(struct nt_list *entry) +{ + entry->prev->next = entry->next; + entry->next->prev = entry->prev; +} + +static inline struct nt_list *RemoveHeadList(struct nt_list *head) +{ + struct nt_list *entry; + + entry = head->next; + if (entry == head) + return NULL; + else { + RemoveEntryList(entry); + return entry; + } +} + +static inline struct nt_list *RemoveTailList(struct nt_list *head) +{ + struct nt_list *entry; + + entry = head->prev; + if (entry == head) + return NULL; + else { + RemoveEntryList(entry); + return entry; + } +} + +static inline void InsertListEntry(struct nt_list *entry, struct nt_list *prev, + struct nt_list *next) +{ + next->prev = entry; + entry->next = next; + entry->prev = prev; + prev->next = entry; +} + +static inline struct nt_list *InsertHeadList(struct nt_list *head, + struct nt_list *entry) +{ + struct nt_list *ret; + + if (IsListEmpty(head)) + ret = NULL; + else + ret = head->next; + + InsertListEntry(entry, head, head->next); + return ret; +} + +static inline struct nt_list *InsertTailList(struct nt_list *head, + struct nt_list *entry) +{ + struct nt_list *ret; + + if (IsListEmpty(head)) + ret = NULL; + else + ret = head->prev; + + InsertListEntry(entry, head->prev, head); + return ret; +} + +#define nt_list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +#define nt_list_for_each_entry(pos, head, member) \ + for (pos = container_of((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = container_of(pos->member.next, typeof(*pos), member)) + +#define nt_list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/* device object flags */ +#define DO_VERIFY_VOLUME 0x00000002 +#define DO_BUFFERED_IO 0x00000004 +#define DO_EXCLUSIVE 0x00000008 +#define DO_DIRECT_IO 0x00000010 +#define DO_MAP_IO_BUFFER 0x00000020 +#define DO_DEVICE_HAS_NAME 0x00000040 +#define DO_DEVICE_INITIALIZING 0x00000080 +#define DO_SYSTEM_BOOT_PARTITION 0x00000100 +#define DO_LONG_TERM_REQUESTS 0x00000200 +#define DO_NEVER_LAST_DEVICE 0x00000400 +#define DO_SHUTDOWN_REGISTERED 0x00000800 +#define DO_BUS_ENUMERATED_DEVICE 0x00001000 +#define DO_POWER_PAGABLE 0x00002000 +#define DO_POWER_INRUSH 0x00004000 +#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000 + +/* Various supported device types (used with IoCreateDevice()) */ + +#define FILE_DEVICE_BEEP 0x00000001 +#define FILE_DEVICE_CD_ROM 0x00000002 +#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 +#define FILE_DEVICE_CONTROLLER 0x00000004 +#define FILE_DEVICE_DATALINK 0x00000005 +#define FILE_DEVICE_DFS 0x00000006 +#define FILE_DEVICE_DISK 0x00000007 +#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 +#define FILE_DEVICE_FILE_SYSTEM 0x00000009 +#define FILE_DEVICE_INPORT_PORT 0x0000000A +#define FILE_DEVICE_KEYBOARD 0x0000000B +#define FILE_DEVICE_MAILSLOT 0x0000000C +#define FILE_DEVICE_MIDI_IN 0x0000000D +#define FILE_DEVICE_MIDI_OUT 0x0000000E +#define FILE_DEVICE_MOUSE 0x0000000F +#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 +#define FILE_DEVICE_NAMED_PIPE 0x00000011 +#define FILE_DEVICE_NETWORK 0x00000012 +#define FILE_DEVICE_NETWORK_BROWSER 0x00000013 +#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 +#define FILE_DEVICE_NULL 0x00000015 +#define FILE_DEVICE_PARALLEL_PORT 0x00000016 +#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 +#define FILE_DEVICE_PRINTER 0x00000018 +#define FILE_DEVICE_SCANNER 0x00000019 +#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001A +#define FILE_DEVICE_SERIAL_PORT 0x0000001B +#define FILE_DEVICE_SCREEN 0x0000001C +#define FILE_DEVICE_SOUND 0x0000001D +#define FILE_DEVICE_STREAMS 0x0000001E +#define FILE_DEVICE_TAPE 0x0000001F +#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 +#define FILE_DEVICE_TRANSPORT 0x00000021 +#define FILE_DEVICE_UNKNOWN 0x00000022 +#define FILE_DEVICE_VIDEO 0x00000023 +#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 +#define FILE_DEVICE_WAVE_IN 0x00000025 +#define FILE_DEVICE_WAVE_OUT 0x00000026 +#define FILE_DEVICE_8042_PORT 0x00000027 +#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 +#define FILE_DEVICE_BATTERY 0x00000029 +#define FILE_DEVICE_BUS_EXTENDER 0x0000002A +#define FILE_DEVICE_MODEM 0x0000002B +#define FILE_DEVICE_VDM 0x0000002C +#define FILE_DEVICE_MASS_STORAGE 0x0000002D +#define FILE_DEVICE_SMB 0x0000002E +#define FILE_DEVICE_KS 0x0000002F +#define FILE_DEVICE_CHANGER 0x00000030 +#define FILE_DEVICE_SMARTCARD 0x00000031 +#define FILE_DEVICE_ACPI 0x00000032 +#define FILE_DEVICE_DVD 0x00000033 +#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034 +#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035 +#define FILE_DEVICE_DFS_VOLUME 0x00000036 +#define FILE_DEVICE_SERENUM 0x00000037 +#define FILE_DEVICE_TERMSRV 0x00000038 +#define FILE_DEVICE_KSEC 0x00000039 +#define FILE_DEVICE_FIPS 0x0000003A + +/* Device characteristics */ + +#define FILE_REMOVABLE_MEDIA 0x00000001 +#define FILE_READ_ONLY_DEVICE 0x00000002 +#define FILE_FLOPPY_DISKETTE 0x00000004 +#define FILE_WRITE_ONCE_MEDIA 0x00000008 +#define FILE_REMOTE_DEVICE 0x00000010 +#define FILE_DEVICE_IS_MOUNTED 0x00000020 +#define FILE_VIRTUAL_VOLUME 0x00000040 +#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080 +#define FILE_DEVICE_SECURE_OPEN 0x00000100 + +#define FILE_READ_DATA 0x0001 +#define FILE_WRITE_DATA 0x0002 + +#define FILE_SUPERSEDED 0x00000000 +#define FILE_OPENED 0x00000001 +#define FILE_CREATED 0x00000002 +#define FILE_OVERWRITTEN 0x00000003 +#define FILE_EXISTS 0x00000004 +#define FILE_DOES_NOT_EXIST 0x00000005 + + +#endif /* WINNT_TYPES_H */ --- linux-2.6.37.orig/ubuntu/ndiswrapper/wrapmem.c +++ linux-2.6.37/ubuntu/ndiswrapper/wrapmem.c @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2006 Giridhar Pemmasani + * + * 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. + * + */ + +#define _WRAPMEM_C_ + +#include "ntoskernel.h" + +struct slack_alloc_info { + struct nt_list list; + size_t size; +}; + +static struct nt_list allocs; +static struct nt_list slack_allocs; +static spinlock_t alloc_lock; + +struct vmem_block { + struct nt_list list; + int size; +}; + +static struct nt_list vmem_list; + +#if defined(ALLOC_DEBUG) +struct alloc_info { + enum alloc_type type; + size_t size; +#if ALLOC_DEBUG > 1 + struct nt_list list; + const char *file; + int line; + ULONG tag; +#endif +}; + +static atomic_t alloc_sizes[ALLOC_TYPE_MAX]; +#endif + +void wrapmem_info(void) +{ +#ifdef ALLOC_DEBUG + enum alloc_type type; + for (type = 0; type < ALLOC_TYPE_MAX; type++) + INFO("total size of allocations in %d: %d", + type, atomic_read(&alloc_sizes[type])); +#endif +} + +/* allocate memory and add it to list of allocated pointers; if a + * driver doesn't free this memory for any reason (buggy driver or we + * allocate space behind driver's back since we need more space than + * corresponding Windows structure provides etc.), this gets freed + * automatically when module is unloaded + */ +void *slack_kmalloc(size_t size) +{ + struct slack_alloc_info *info; + gfp_t flags; + + ENTER4("size = %lu", (unsigned long)size); + + if (irql_gfp() & GFP_ATOMIC) + flags = GFP_ATOMIC; + else + flags = GFP_KERNEL; + info = kmalloc(size + sizeof(*info), flags); + if (!info) + return NULL; + info->size = size; + spin_lock_bh(&alloc_lock); + InsertTailList(&slack_allocs, &info->list); + spin_unlock_bh(&alloc_lock); +#ifdef ALLOC_DEBUG + atomic_add(size, &alloc_sizes[ALLOC_TYPE_SLACK]); +#endif + TRACE4("%p, %p", info, info + 1); + EXIT4(return info + 1); +} + +/* free pointer and remove from list of allocated pointers */ +void slack_kfree(void *ptr) +{ + struct slack_alloc_info *info; + + ENTER4("%p", ptr); + info = ptr - sizeof(*info); + spin_lock_bh(&alloc_lock); + RemoveEntryList(&info->list); + spin_unlock_bh(&alloc_lock); +#ifdef ALLOC_DEBUG + atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]); +#endif + kfree(info); + EXIT4(return); +} + +#if defined(ALLOC_DEBUG) +void *wrap_kmalloc(size_t size, gfp_t flags, const char *file, int line) +{ + struct alloc_info *info; + + info = kmalloc(size + sizeof(*info), flags); + if (!info) + return NULL; + if (flags & GFP_ATOMIC) + info->type = ALLOC_TYPE_KMALLOC_ATOMIC; + else + info->type = ALLOC_TYPE_KMALLOC_NON_ATOMIC; + info->size = size; + atomic_add(size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + info->file = file; + info->line = line; + info->tag = 0; + spin_lock_bh(&alloc_lock); + InsertTailList(&allocs, &info->list); + spin_unlock_bh(&alloc_lock); +#endif + TRACE4("%p", info + 1); + return info + 1; +} + +void *wrap_kzalloc(size_t size, gfp_t flags, const char *file, int line) +{ + void *ptr = wrap_kmalloc(size, flags, file, line); + if (ptr) + memset(ptr, 0, size); + return ptr; +} + +void wrap_kfree(void *ptr) +{ + struct alloc_info *info; + + TRACE4("%p", ptr); + if (!ptr) + return; + info = ptr - sizeof(*info); + atomic_sub(info->size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + spin_lock_bh(&alloc_lock); + RemoveEntryList(&info->list); + spin_unlock_bh(&alloc_lock); + if (!(info->type == ALLOC_TYPE_KMALLOC_ATOMIC || + info->type == ALLOC_TYPE_KMALLOC_NON_ATOMIC)) + WARNING("invliad type: %d", info->type); +#endif + kfree(info); +} + +void *wrap_vmalloc(unsigned long size, const char *file, int line) +{ + struct alloc_info *info; + + info = vmalloc(size + sizeof(*info)); + if (!info) + return NULL; + info->type = ALLOC_TYPE_VMALLOC_NON_ATOMIC; + info->size = size; + atomic_add(size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + info->file = file; + info->line = line; + info->tag = 0; + spin_lock_bh(&alloc_lock); + InsertTailList(&allocs, &info->list); + spin_unlock_bh(&alloc_lock); +#endif + return info + 1; +} + +void *wrap__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot, + const char *file, int line) +{ + struct alloc_info *info; + + info = __vmalloc(size + sizeof(*info), gfp_mask, prot); + if (!info) + return NULL; + if (gfp_mask & GFP_ATOMIC) + info->type = ALLOC_TYPE_VMALLOC_ATOMIC; + else + info->type = ALLOC_TYPE_VMALLOC_NON_ATOMIC; + info->size = size; + atomic_add(size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + info->file = file; + info->line = line; + info->tag = 0; + spin_lock_bh(&alloc_lock); + InsertTailList(&allocs, &info->list); + spin_unlock_bh(&alloc_lock); +#endif + return info + 1; +} + +void wrap_vfree(void *ptr) +{ + struct alloc_info *info; + + info = ptr - sizeof(*info); + atomic_sub(info->size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + spin_lock_bh(&alloc_lock); + RemoveEntryList(&info->list); + spin_unlock_bh(&alloc_lock); + if (!(info->type == ALLOC_TYPE_VMALLOC_ATOMIC || + info->type == ALLOC_TYPE_VMALLOC_NON_ATOMIC)) + WARNING("invliad type: %d", info->type); +#endif + vfree(info); +} + +void *wrap_alloc_pages(gfp_t flags, unsigned int size, + const char *file, int line) +{ + struct alloc_info *info; + + size += sizeof(*info); + info = (struct alloc_info *)__get_free_pages(flags, get_order(size)); + if (!info) + return NULL; + info->type = ALLOC_TYPE_PAGES; + info->size = size; + atomic_add(size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + info->file = file; + info->line = line; + info->tag = 0; + spin_lock_bh(&alloc_lock); + InsertTailList(&allocs, &info->list); + spin_unlock_bh(&alloc_lock); +#endif + return info + 1; +} + +void wrap_free_pages(unsigned long ptr, int order) +{ + struct alloc_info *info; + + info = (void *)ptr - sizeof(*info); + atomic_sub(info->size, &alloc_sizes[info->type]); +#if ALLOC_DEBUG > 1 + spin_lock_bh(&alloc_lock); + RemoveEntryList(&info->list); + spin_unlock_bh(&alloc_lock); + if (info->type != ALLOC_TYPE_PAGES) + WARNING("invliad type: %d", info->type); +#endif + free_pages((unsigned long)info, get_order(info->size)); +} + +#if ALLOC_DEBUG > 1 +#undef ExAllocatePoolWithTag +void *wrap_ExAllocatePoolWithTag(enum pool_type pool_type, SIZE_T size, + ULONG tag, const char *file, int line) +{ + void *addr; + struct alloc_info *info; + + ENTER4("pool_type: %d, size: %lu, tag: %u", pool_type, size, tag); + addr = ExAllocatePoolWithTag(pool_type, size, tag); + if (!addr) + return NULL; + info = addr - sizeof(*info); + info->file = file; + info->line = line; + info->tag = tag; + EXIT4(return addr); +} +#endif + +int alloc_size(enum alloc_type type) +{ + if (type >= 0 && type < ALLOC_TYPE_MAX) + return atomic_read(&alloc_sizes[type]); + else + return -EINVAL; +} + +#endif // ALLOC_DEBUG + +int wrapmem_init(void) +{ + InitializeListHead(&allocs); + InitializeListHead(&slack_allocs); + InitializeListHead(&vmem_list); + spin_lock_init(&alloc_lock); + return 0; +} + +void wrapmem_exit(void) +{ + enum alloc_type type; + struct nt_list *ent; + + /* free all pointers on the slack list */ + while (1) { + struct slack_alloc_info *info; + spin_lock_bh(&alloc_lock); + ent = RemoveHeadList(&slack_allocs); + spin_unlock_bh(&alloc_lock); + if (!ent) + break; + info = container_of(ent, struct slack_alloc_info, list); +#ifdef ALLOC_DEBUG + atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]); +#endif + kfree(info); + } + type = 0; +#ifdef ALLOC_DEBUG + for (type = 0; type < ALLOC_TYPE_MAX; type++) { + int n = atomic_read(&alloc_sizes[type]); + if (n) + WARNING("%d bytes of memory in %d leaking", n, type); + } + +#if ALLOC_DEBUG > 1 + while (1) { + struct alloc_info *info; + + spin_lock_bh(&alloc_lock); + ent = RemoveHeadList(&allocs); + spin_unlock_bh(&alloc_lock); + if (!ent) + break; + info = container_of(ent, struct alloc_info, list); + atomic_sub(info->size, &alloc_sizes[ALLOC_TYPE_SLACK]); + WARNING("%p in %d of size %zu allocated at %s(%d) " + "with tag 0x%08X leaking; freeing it now", + info + 1, info->type, info->size, info->file, + info->line, info->tag); + if (info->type == ALLOC_TYPE_KMALLOC_ATOMIC || + info->type == ALLOC_TYPE_KMALLOC_NON_ATOMIC) + kfree(info); + else if (info->type == ALLOC_TYPE_VMALLOC_ATOMIC || + info->type == ALLOC_TYPE_VMALLOC_NON_ATOMIC) + vfree(info); + else if (info->type == ALLOC_TYPE_PAGES) + free_pages((unsigned long)info, get_order(info->size)); + else + WARNING("invalid type: %d; not freed", info->type); + } +#endif +#endif + return; +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/wrapmem.h +++ linux-2.6.37/ubuntu/ndiswrapper/wrapmem.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2006 Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _WRAPMEM_H_ + +/* set ALLOC_DEBUG to 1 to get information about memory used by both + * ndiswrapper and Windows driver by reading + * /proc/net/ndiswrapper/debug; this will also show memory leaks + * (memory allocated but not freed) when ndiswrapper module is + * unloaded. + + * ALLOC_DEBUG=2: details about individual allocations leaking is printed + * ALLOC_DEBUG=3: tags in ExAllocatePoolWithTag leaking printed +*/ + +//#ifndef ALLOC_DEBUG +//#define ALLOC_DEBUG 1 +//#endif + +enum alloc_type { ALLOC_TYPE_KMALLOC_ATOMIC, ALLOC_TYPE_KMALLOC_NON_ATOMIC, + ALLOC_TYPE_VMALLOC_ATOMIC, ALLOC_TYPE_VMALLOC_NON_ATOMIC, + ALLOC_TYPE_SLACK, ALLOC_TYPE_PAGES, ALLOC_TYPE_MAX }; + +int wrapmem_init(void); +void wrapmem_exit(void); +void *slack_kmalloc(size_t size); +void slack_kfree(void *ptr); +void wrapmem_info(void); + +#ifdef ALLOC_DEBUG +void *wrap_kmalloc(size_t size, gfp_t flags, const char *file, int line); +void *wrap_kzalloc(size_t size, gfp_t flags, const char *file, int line); +void wrap_kfree(void *ptr); +void *wrap_vmalloc(unsigned long size, const char *file, int line); +void *wrap__vmalloc(unsigned long size, gfp_t flags, pgprot_t prot, + const char *file, int line); +void wrap_vfree(void *ptr); +void *wrap_alloc_pages(gfp_t flags, unsigned int size, + const char *file, int line); +void wrap_free_pages(unsigned long ptr, int order); +int alloc_size(enum alloc_type type); + +#ifndef _WRAPMEM_C_ +#undef kmalloc +#undef kzalloc +#undef kfree +#undef vmalloc +#undef __vmalloc +#undef vfree +#define kmalloc(size, flags) \ + wrap_kmalloc(size, flags, __FILE__, __LINE__) +#define kzalloc(size, flags) \ + wrap_kzalloc(size, flags, __FILE__, __LINE__) +#define vmalloc(size) \ + wrap_vmalloc(size, __FILE__, __LINE__) +#define __vmalloc(size, flags, prot) \ + wrap__vmalloc(size, flags, prot, __FILE__, __LINE__) +#define kfree(ptr) wrap_kfree(ptr) +#define vfree(ptr) wrap_vfree(ptr) + +#define wrap_get_free_pages(flags, size) \ + wrap_alloc_pages(flags, size, __FILE__, __LINE__) +#undef free_pages +#define free_pages(ptr, order) wrap_free_pages(ptr, order) + +#if ALLOC_DEBUG > 1 +void *wrap_ExAllocatePoolWithTag(enum pool_type pool_type, SIZE_T size, + ULONG tag, const char *file, int line); +#define ExAllocatePoolWithTag(pool_type, size, tag) \ + wrap_ExAllocatePoolWithTag(pool_type, size, tag, __FILE__, __LINE__) +#endif + +#endif // _WRAPMEM_C_ + +#else + +#define wrap_get_free_pages(flags, size) \ + (void *)__get_free_pages(flags, get_order(size)) + +#endif // ALLOC_DEBUG + +#endif --- linux-2.6.37.orig/ubuntu/ndiswrapper/wrapndis.c +++ linux-2.6.37/ubuntu/ndiswrapper/wrapndis.c @@ -0,0 +1,2137 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ + +#include "ndis.h" +#include "iw_ndis.h" +#include "pnp.h" +#include "loader.h" +#include "wrapndis.h" +#include +#include +#include +#include +#include +#include "wrapper.h" + +/* Functions callable from the NDIS driver */ +wstdcall NTSTATUS NdisDispatchDeviceControl(struct device_object *fdo, + struct irp *irp); +wstdcall NTSTATUS NdisDispatchPnp(struct device_object *fdo, struct irp *irp); +wstdcall NTSTATUS NdisDispatchPower(struct device_object *fdo, struct irp *irp); + +workqueue_struct_t *wrapndis_wq; +static struct nt_thread *wrapndis_worker_thread; + +static int set_packet_filter(struct ndis_device *wnd, + ULONG packet_filter); +static void add_iw_stats_timer(struct ndis_device *wnd); +static void del_iw_stats_timer(struct ndis_device *wnd); +static NDIS_STATUS ndis_start_device(struct ndis_device *wnd); +static int ndis_remove_device(struct ndis_device *wnd); +static void set_multicast_list(struct ndis_device *wnd); +static int ndis_net_dev_open(struct net_device *net_dev); +static int ndis_net_dev_close(struct net_device *net_dev); + +/* MiniportReset */ +NDIS_STATUS mp_reset(struct ndis_device *wnd) +{ + NDIS_STATUS res; + struct miniport *mp; + BOOLEAN reset_address; + KIRQL irql; + + ENTER2("wnd: %p", wnd); + if (down_interruptible(&wnd->tx_ring_mutex)) + EXIT3(return NDIS_STATUS_FAILURE); + if (down_interruptible(&wnd->ndis_req_mutex)) { + up(&wnd->tx_ring_mutex); + EXIT3(return NDIS_STATUS_FAILURE); + } + mp = &wnd->wd->driver->ndis_driver->mp; + prepare_wait_condition(wnd->ndis_req_task, wnd->ndis_req_done, 0); + WARNING("%s is being reset", wnd->net_dev->name); + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + res = LIN2WIN2(mp->reset, &reset_address, wnd->nmb->mp_ctx); + serialize_unlock_irql(wnd, irql); + + TRACE2("%08X, %08X", res, reset_address); + if (res == NDIS_STATUS_PENDING) { + /* wait for NdisMResetComplete */ + if (wait_condition((wnd->ndis_req_done > 0), 0, + TASK_INTERRUPTIBLE) < 0) + res = NDIS_STATUS_FAILURE; + else { + res = wnd->ndis_req_status; + reset_address = wnd->ndis_req_done - 1; + } + TRACE2("%08X, %08X", res, reset_address); + } + up(&wnd->ndis_req_mutex); + if (res == NDIS_STATUS_SUCCESS && reset_address) { + set_packet_filter(wnd, wnd->packet_filter); + set_multicast_list(wnd); + } + up(&wnd->tx_ring_mutex); + EXIT3(return res); +} + +/* MiniportRequest(Query/Set)Information */ +NDIS_STATUS mp_request(enum ndis_request_type request, + struct ndis_device *wnd, ndis_oid oid, + void *buf, ULONG buflen, ULONG *written, ULONG *needed) +{ + NDIS_STATUS res; + ULONG w, n; + struct miniport *mp; + KIRQL irql; + + if (down_interruptible(&wnd->ndis_req_mutex)) + EXIT3(return NDIS_STATUS_FAILURE); + if (!written) + written = &w; + if (!needed) + needed = &n; + mp = &wnd->wd->driver->ndis_driver->mp; + prepare_wait_condition(wnd->ndis_req_task, wnd->ndis_req_done, 0); + irql = serialize_lock_irql(wnd); + assert_irql(_irql_ == DISPATCH_LEVEL); + switch (request) { + case NdisRequestQueryInformation: + TRACE2("%p, %08X, %p", mp->queryinfo, oid, wnd->nmb->mp_ctx); + res = LIN2WIN6(mp->queryinfo, wnd->nmb->mp_ctx, oid, buf, + buflen, written, needed); + break; + case NdisRequestSetInformation: + TRACE2("%p, %08X, %p", mp->setinfo, oid, wnd->nmb->mp_ctx); + res = LIN2WIN6(mp->setinfo, wnd->nmb->mp_ctx, oid, buf, + buflen, written, needed); + break; + default: + WARNING("invalid request %d, %08X", request, oid); + res = NDIS_STATUS_NOT_SUPPORTED; + break; + } + serialize_unlock_irql(wnd, irql); + TRACE2("%08X, %08X", res, oid); + if (res == NDIS_STATUS_PENDING) { + /* wait for NdisMQueryInformationComplete */ + if (wait_condition((wnd->ndis_req_done > 0), 0, + TASK_INTERRUPTIBLE) < 0) + res = NDIS_STATUS_FAILURE; + else + res = wnd->ndis_req_status; + TRACE2("%08X, %08X", res, oid); + } + up(&wnd->ndis_req_mutex); + DBG_BLOCK(2) { + if (res || needed) + TRACE2("%08X, %d, %d, %d", res, buflen, *written, + *needed); + } + EXIT3(return res); +} + +/* MiniportPnPEventNotify */ +static NDIS_STATUS mp_pnp_event(struct ndis_device *wnd, + enum ndis_device_pnp_event event, + ULONG power_profile) +{ + struct miniport *mp; + + ENTER1("%p, %d", wnd, event); + mp = &wnd->wd->driver->ndis_driver->mp; + if (!mp->pnp_event_notify) { + TRACE1("Windows driver %s doesn't support " + "MiniportPnpEventNotify", wnd->wd->driver->name); + return NDIS_STATUS_FAILURE; + } + /* RNDIS driver doesn't like to be notified if device is + * already halted */ + if (!test_bit(HW_INITIALIZED, &wnd->wd->hw_status)) + EXIT1(return NDIS_STATUS_SUCCESS); + switch (event) { + case NdisDevicePnPEventSurpriseRemoved: + TRACE1("%u, %p", + (wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK), + mp->pnp_event_notify); + if ((wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK) && + !test_bit(HW_PRESENT, &wnd->wd->hw_status) && + mp->pnp_event_notify) { + TRACE1("calling surprise_removed"); + LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx, + NdisDevicePnPEventSurpriseRemoved, NULL, 0); + } else + TRACE1("Windows driver %s doesn't support " + "MiniportPnpEventNotify for safe unplugging", + wnd->wd->driver->name); + return NDIS_STATUS_SUCCESS; + case NdisDevicePnPEventPowerProfileChanged: + if (power_profile) + power_profile = NdisPowerProfileAcOnLine; + LIN2WIN4(mp->pnp_event_notify, wnd->nmb->mp_ctx, + NdisDevicePnPEventPowerProfileChanged, + &power_profile, (ULONG)sizeof(power_profile)); + return NDIS_STATUS_SUCCESS; + default: + WARNING("event %d not yet implemented", event); + return NDIS_STATUS_SUCCESS; + } +} + +/* MiniportInitialize */ +static NDIS_STATUS mp_init(struct ndis_device *wnd) +{ + NDIS_STATUS error_status, status; + UINT medium_index; + enum ndis_medium medium_array[] = {NdisMedium802_3}; + struct miniport *mp; + + ENTER1("irql: %d", current_irql()); + if (test_bit(HW_INITIALIZED, &wnd->wd->hw_status)) { + WARNING("device %p already initialized!", wnd); + return NDIS_STATUS_FAILURE; + } + + if (!wnd->wd->driver->ndis_driver || + !wnd->wd->driver->ndis_driver->mp.init) { + WARNING("assuming WDM (non-NDIS) driver"); + EXIT1(return NDIS_STATUS_NOT_RECOGNIZED); + } + mp = &wnd->wd->driver->ndis_driver->mp; + status = LIN2WIN6(mp->init, &error_status, &medium_index, medium_array, + sizeof(medium_array) / sizeof(medium_array[0]), + wnd->nmb, wnd->nmb); + TRACE1("init returns: %08X, irql: %d", status, current_irql()); + if (status != NDIS_STATUS_SUCCESS) { + WARNING("couldn't initialize device: %08X", status); + EXIT1(return NDIS_STATUS_FAILURE); + } + + /* Wait a little to let card power up otherwise ifup might + * fail after boot */ + sleep_hz(HZ / 5); + status = mp_pnp_event(wnd, NdisDevicePnPEventPowerProfileChanged, + NdisPowerProfileAcOnLine); + if (status != NDIS_STATUS_SUCCESS) + TRACE1("setting power failed: %08X", status); + set_bit(HW_INITIALIZED, &wnd->wd->hw_status); + /* the description about NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND is + * misleading/confusing */ + status = mp_query(wnd, OID_PNP_CAPABILITIES, + &wnd->pnp_capa, sizeof(wnd->pnp_capa)); + if (status == NDIS_STATUS_SUCCESS) { + TRACE1("%d, %d", wnd->pnp_capa.wakeup.min_magic_packet_wakeup, + wnd->pnp_capa.wakeup.min_pattern_wakeup); + wnd->attributes |= NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND; + status = mp_query_int(wnd, OID_PNP_ENABLE_WAKE_UP, + &wnd->ndis_wolopts); + TRACE1("%08X, %x", status, wnd->ndis_wolopts); + } else if (status == NDIS_STATUS_NOT_SUPPORTED) + wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND; + TRACE1("%d", wnd->pnp_capa.wakeup.min_magic_packet_wakeup); + /* although some NDIS drivers support suspend, Linux kernel + * has issues with suspending USB devices */ + if (wrap_is_usb_bus(wnd->wd->dev_bus)) { + wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND; + wnd->ndis_wolopts = 0; + } + mp_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF); + EXIT1(return NDIS_STATUS_SUCCESS); +} + +/* MiniportHalt */ +static void mp_halt(struct ndis_device *wnd) +{ + struct miniport *mp; + + ENTER1("%p", wnd); + if (!test_and_clear_bit(HW_INITIALIZED, &wnd->wd->hw_status)) { + WARNING("device %p is not initialized - not halting", wnd); + return; + } + hangcheck_del(wnd); + del_iw_stats_timer(wnd); + if (wnd->physical_medium == NdisPhysicalMediumWirelessLan && + wrap_is_pci_bus(wnd->wd->dev_bus)) { + up(&wnd->ndis_req_mutex); + disassociate(wnd, 0); + if (down_interruptible(&wnd->ndis_req_mutex)) + WARNING("couldn't obtain ndis_req_mutex"); + } + mp = &wnd->wd->driver->ndis_driver->mp; + TRACE1("halt: %p", mp->mp_halt); + LIN2WIN1(mp->mp_halt, wnd->nmb->mp_ctx); + /* if a driver doesn't call NdisMDeregisterInterrupt during + * halt, deregister it now */ + if (wnd->mp_interrupt) + NdisMDeregisterInterrupt(wnd->mp_interrupt); + /* cancel any timers left by bugyy windows driver; also free + * the memory for timers */ + while (1) { + struct nt_slist *slist; + struct wrap_timer *wrap_timer; + + spin_lock_bh(&ntoskernel_lock); + if ((slist = wnd->wrap_timer_slist.next)) + wnd->wrap_timer_slist.next = slist->next; + spin_unlock_bh(&ntoskernel_lock); + TIMERTRACE("%p", slist); + if (!slist) + break; + wrap_timer = container_of(slist, struct wrap_timer, slist); + wrap_timer->repeat = 0; + /* ktimer that this wrap_timer is associated to can't + * be touched, as it may have been freed by the driver + * already */ + if (del_timer_sync(&wrap_timer->timer)) + WARNING("Buggy Windows driver left timer %p " + "running", wrap_timer->nt_timer); + memset(wrap_timer, 0, sizeof(*wrap_timer)); + kfree(wrap_timer); + } + EXIT1(return); +} + +static NDIS_STATUS mp_set_power_state(struct ndis_device *wnd, + enum ndis_power_state state) +{ + NDIS_STATUS status; + + TRACE1("%d", state); + if (state == NdisDeviceStateD0) { + status = NDIS_STATUS_SUCCESS; + up(&wnd->ndis_req_mutex); + if (test_and_clear_bit(HW_HALTED, &wnd->wd->hw_status)) { + status = mp_init(wnd); + if (status == NDIS_STATUS_SUCCESS) { + set_packet_filter(wnd, wnd->packet_filter); + set_multicast_list(wnd); + } + } else if (test_and_clear_bit(HW_SUSPENDED, + &wnd->wd->hw_status)) { + status = mp_set_int(wnd, OID_PNP_SET_POWER, state); + if (status != NDIS_STATUS_SUCCESS) + WARNING("%s: setting power to state %d failed? " + "%08X", wnd->net_dev->name, state, + status); + } else + return NDIS_STATUS_FAILURE; + + if (wrap_is_pci_bus(wnd->wd->dev_bus)) { + pci_enable_wake(wnd->wd->pci.pdev, PCI_D3hot, 0); + pci_enable_wake(wnd->wd->pci.pdev, PCI_D3cold, 0); + } + if (status == NDIS_STATUS_SUCCESS) { + up(&wnd->tx_ring_mutex); + netif_device_attach(wnd->net_dev); + hangcheck_add(wnd); + add_iw_stats_timer(wnd); + } else + WARNING("%s: couldn't set power to state %d; device not" + " resumed", wnd->net_dev->name, state); + EXIT1(return status); + } else { + if (down_interruptible(&wnd->tx_ring_mutex)) + EXIT1(return NDIS_STATUS_FAILURE); + netif_device_detach(wnd->net_dev); + hangcheck_del(wnd); + del_iw_stats_timer(wnd); + status = NDIS_STATUS_NOT_SUPPORTED; + if (wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND) { + status = mp_set_int(wnd, OID_PNP_ENABLE_WAKE_UP, + wnd->ndis_wolopts); + TRACE2("0x%x, 0x%x", status, wnd->ndis_wolopts); + if (status == NDIS_STATUS_SUCCESS) { + if (wnd->ndis_wolopts) + wnd->wd->pci.wake_state = + PowerDeviceD3; + else + wnd->wd->pci.wake_state = + PowerDeviceUnspecified; + } else + WARNING("couldn't set wake-on-lan options: " + "0x%x, %08X", wnd->ndis_wolopts, status); + status = mp_set_int(wnd, OID_PNP_SET_POWER, state); + if (status == NDIS_STATUS_SUCCESS) + set_bit(HW_SUSPENDED, &wnd->wd->hw_status); + else + WARNING("suspend failed: %08X", status); + } + if (status != NDIS_STATUS_SUCCESS) { + WARNING("%s does not support power management; " + "halting the device", wnd->net_dev->name); + mp_halt(wnd); + set_bit(HW_HALTED, &wnd->wd->hw_status); + status = STATUS_SUCCESS; + } + if (down_interruptible(&wnd->ndis_req_mutex)) + WARNING("couldn't lock ndis_req_mutex"); + EXIT1(return status); + } +} + +static int ndis_set_mac_address(struct net_device *dev, void *p) +{ + struct ndis_device *wnd = netdev_priv(dev); + struct sockaddr *addr = p; + struct ndis_configuration_parameter param; + struct unicode_string key; + struct ansi_string ansi; + NDIS_STATUS res; + unsigned char mac_string[2 * ETH_ALEN + 1]; + mac_address mac; + + memcpy(mac, addr->sa_data, sizeof(mac)); + memset(mac_string, 0, sizeof(mac_string)); + res = snprintf(mac_string, sizeof(mac_string), MACSTR, MAC2STR(mac)); + if (res != (sizeof(mac_string) - 1)) + EXIT1(return -EINVAL); + TRACE1("new mac: %s", mac_string); + + RtlInitAnsiString(&ansi, mac_string); + if (RtlAnsiStringToUnicodeString(¶m.data.string, &ansi, + TRUE) != STATUS_SUCCESS) + EXIT1(return -EINVAL); + + param.type = NdisParameterString; + RtlInitAnsiString(&ansi, "NetworkAddress"); + if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE) != STATUS_SUCCESS) { + RtlFreeUnicodeString(¶m.data.string); + EXIT1(return -EINVAL); + } + NdisWriteConfiguration(&res, wnd->nmb, &key, ¶m); + RtlFreeUnicodeString(&key); + RtlFreeUnicodeString(¶m.data.string); + + if (res != NDIS_STATUS_SUCCESS) + EXIT1(return -EFAULT); + if (ndis_reinit(wnd) == NDIS_STATUS_SUCCESS) { + res = mp_query(wnd, OID_802_3_CURRENT_ADDRESS, + mac, sizeof(mac)); + if (res == NDIS_STATUS_SUCCESS) { + TRACE1("mac:" MACSTRSEP, MAC2STR(mac)); + memcpy(dev->dev_addr, mac, sizeof(mac)); + } else + ERROR("couldn't get mac address: %08X", res); + } + EXIT1(return 0); +} + +static int setup_tx_sg_list(struct ndis_device *wnd, struct sk_buff *skb, + struct ndis_packet_oob_data *oob_data) +{ + struct ndis_sg_element *sg_element; + struct ndis_sg_list *sg_list; + int i; + + ENTER3("%p, %d", skb, skb_shinfo(skb)->nr_frags); + if (skb_shinfo(skb)->nr_frags <= 1) { + sg_element = &oob_data->wrap_tx_sg_list.elements[0]; + sg_element->address = + PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, skb->data, + skb->len, PCI_DMA_TODEVICE); + sg_element->length = skb->len; + oob_data->wrap_tx_sg_list.nent = 1; + oob_data->ext.info[ScatterGatherListPacketInfo] = + &oob_data->wrap_tx_sg_list; + TRACE3("%Lx, %u", sg_element->address, sg_element->length); + return 0; + } + sg_list = kmalloc(sizeof(*sg_list) + + (skb_shinfo(skb)->nr_frags + 1) * sizeof(*sg_element), + GFP_ATOMIC); + if (!sg_list) + return -ENOMEM; + sg_list->nent = skb_shinfo(skb)->nr_frags + 1; + TRACE3("%p, %d", sg_list, sg_list->nent); + sg_element = sg_list->elements; + sg_element->length = skb_headlen(skb); + sg_element->address = + PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, skb->data, + skb_headlen(skb), PCI_DMA_TODEVICE); + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + sg_element++; + sg_element->length = frag->size; + sg_element->address = + pci_map_page(wnd->wd->pci.pdev, frag->page, + frag->page_offset, frag->size, + PCI_DMA_TODEVICE); + TRACE3("%Lx, %u", sg_element->address, sg_element->length); + } + oob_data->ext.info[ScatterGatherListPacketInfo] = sg_list; + return 0; +} + +static void free_tx_sg_list(struct ndis_device *wnd, + struct ndis_packet_oob_data *oob_data) +{ + int i; + struct ndis_sg_element *sg_element; + struct ndis_sg_list *sg_list = + oob_data->ext.info[ScatterGatherListPacketInfo]; + sg_element = sg_list->elements; + TRACE3("%p, %d", sg_list, sg_list->nent); + PCI_DMA_UNMAP_SINGLE(wnd->wd->pci.pdev, sg_element->address, + sg_element->length, PCI_DMA_TODEVICE); + if (sg_list->nent == 1) + EXIT3(return); + for (i = 1; i < sg_list->nent; i++, sg_element++) { + TRACE3("%Lx, %u", sg_element->address, sg_element->length); + pci_unmap_page(wnd->wd->pci.pdev, sg_element->address, + sg_element->length, PCI_DMA_TODEVICE); + } + TRACE3("%p", sg_list); + kfree(sg_list); +} + +static struct ndis_packet *alloc_tx_packet(struct ndis_device *wnd, + struct sk_buff *skb) +{ + struct ndis_packet *packet; + ndis_buffer *buffer; + struct ndis_packet_oob_data *oob_data; + NDIS_STATUS status; + + NdisAllocatePacket(&status, &packet, wnd->tx_packet_pool); + if (status != NDIS_STATUS_SUCCESS) + return NULL; + NdisAllocateBuffer(&status, &buffer, wnd->tx_buffer_pool, + skb->data, skb->len); + if (status != NDIS_STATUS_SUCCESS) { + NdisFreePacket(packet); + return NULL; + } + packet->private.buffer_head = buffer; + packet->private.buffer_tail = buffer; + + oob_data = NDIS_PACKET_OOB_DATA(packet); + oob_data->tx_skb = skb; + if (wnd->sg_dma_size) { + if (setup_tx_sg_list(wnd, skb, oob_data)) { + NdisFreeBuffer(buffer); + NdisFreePacket(packet); + return NULL; + } + } + if (skb->ip_summed == CHECKSUM_PARTIAL) { + struct ndis_tcp_ip_checksum_packet_info csum; + int protocol; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) + protocol = ntohs(skb->protocol); +#else + protocol = skb->nh.iph->protocol; +#endif + csum.value = 0; + csum.tx.v4 = 1; + if (protocol == IPPROTO_TCP) + csum.tx.tcp = 1; + else if (protocol == IPPROTO_UDP) + csum.tx.udp = 1; +// csum->tx.ip = 1; + packet->private.flags |= NDIS_PROTOCOL_ID_TCP_IP; + oob_data->ext.info[TcpIpChecksumPacketInfo] = + (void *)(ULONG_PTR)csum.value; + } + DBG_BLOCK(4) { + dump_bytes(__func__, skb->data, skb->len); + } + TRACE4("%p, %p, %p", packet, buffer, skb); + return packet; +} + +void free_tx_packet(struct ndis_device *wnd, struct ndis_packet *packet, + NDIS_STATUS status) +{ + ndis_buffer *buffer; + struct ndis_packet_oob_data *oob_data; + struct sk_buff *skb; + struct ndis_packet_pool *pool; + + assert_irql(_irql_ <= DISPATCH_LEVEL); + assert(packet->private.packet_flags); + oob_data = NDIS_PACKET_OOB_DATA(packet); + skb = oob_data->tx_skb; + buffer = packet->private.buffer_head; + TRACE4("%p, %p, %p, %08X", packet, buffer, skb, status); + if (status == NDIS_STATUS_SUCCESS) { + pre_atomic_add(wnd->net_stats.tx_bytes, packet->private.len); + atomic_inc_var(wnd->net_stats.tx_packets); + } else { + TRACE1("packet dropped: %08X", status); + atomic_inc_var(wnd->net_stats.tx_dropped); + } + if (wnd->sg_dma_size) + free_tx_sg_list(wnd, oob_data); + NdisFreeBuffer(buffer); + dev_kfree_skb_any(skb); + pool = packet->private.pool; + NdisFreePacket(packet); + if (netif_queue_stopped(wnd->net_dev) && + ((pool->max_descr - pool->num_used_descr) >= + (wnd->max_tx_packets / 4))) { + set_bit(NETIF_WAKEQ, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); + } + EXIT4(return); +} + +/* MiniportSend and MiniportSendPackets */ +/* this function is called holding tx_ring_mutex. start and n are such + * that start + n < TX_RING_SIZE; i.e., packets don't wrap around + * ring */ +static u8 mp_tx_packets(struct ndis_device *wnd, u8 start, u8 n) +{ + NDIS_STATUS res; + struct miniport *mp; + struct ndis_packet *packet; + u8 sent; + KIRQL irql; + + ENTER3("%d, %d", start, n); + mp = &wnd->wd->driver->ndis_driver->mp; + if (mp->send_packets) { + if (deserialized_driver(wnd)) { + LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx, + &wnd->tx_ring[start], n); + sent = n; + } else { + irql = serialize_lock_irql(wnd); + LIN2WIN3(mp->send_packets, wnd->nmb->mp_ctx, + &wnd->tx_ring[start], n); + serialize_unlock_irql(wnd, irql); + for (sent = 0; sent < n && wnd->tx_ok; sent++) { + struct ndis_packet_oob_data *oob_data; + packet = wnd->tx_ring[start + sent]; + oob_data = NDIS_PACKET_OOB_DATA(packet); + switch ((res = + xchg(&oob_data->status, + NDIS_STATUS_NOT_RECOGNIZED))) { + case NDIS_STATUS_SUCCESS: + free_tx_packet(wnd, packet, + NDIS_STATUS_SUCCESS); + break; + case NDIS_STATUS_PENDING: + break; + case NDIS_STATUS_RESOURCES: + wnd->tx_ok = 0; + /* resubmit this packet and + * the rest when resources + * become available */ + sent--; + break; + case NDIS_STATUS_FAILURE: + free_tx_packet(wnd, packet, + NDIS_STATUS_FAILURE); + break; + default: + ERROR("%p: invalid status: %08X", + packet, res); + free_tx_packet(wnd, packet, + oob_data->status); + break; + } + TRACE3("%p, %d", packet, res); + } + } + TRACE3("sent: %d(%d)", sent, n); + } else { + for (sent = 0; sent < n && wnd->tx_ok; sent++) { + struct ndis_packet_oob_data *oob_data; + packet = wnd->tx_ring[start + sent]; + oob_data = NDIS_PACKET_OOB_DATA(packet); + oob_data->status = NDIS_STATUS_NOT_RECOGNIZED; + irql = serialize_lock_irql(wnd); + res = LIN2WIN3(mp->send, wnd->nmb->mp_ctx, + packet, packet->private.flags); + serialize_unlock_irql(wnd, irql); + switch (res) { + case NDIS_STATUS_SUCCESS: + free_tx_packet(wnd, packet, res); + break; + case NDIS_STATUS_PENDING: + break; + case NDIS_STATUS_RESOURCES: + wnd->tx_ok = 0; + /* resend this packet when resources + * become available */ + sent--; + break; + case NDIS_STATUS_FAILURE: + free_tx_packet(wnd, packet, res); + break; + default: + ERROR("packet %p: invalid status: %08X", + packet, res); + break; + } + } + } + EXIT3(return sent); +} + +static void tx_worker(worker_param_t param) +{ + struct ndis_device *wnd; + s8 n; + + wnd = worker_param_data(param, struct ndis_device, tx_work); + ENTER3("tx_ok %d", wnd->tx_ok); + while (wnd->tx_ok) { + if (down_interruptible(&wnd->tx_ring_mutex)) + break; + spin_lock_bh(&wnd->tx_ring_lock); + n = wnd->tx_ring_end - wnd->tx_ring_start; + TRACE3("%d, %d, %d", wnd->tx_ring_start, wnd->tx_ring_end, n); + /* end == start if either ring is empty or full; in + * the latter case is_tx_ring_full is set */ + if (n == 0) { + if (wnd->is_tx_ring_full) + n = TX_RING_SIZE - wnd->tx_ring_start; + else { + spin_unlock_bh(&wnd->tx_ring_lock); + up(&wnd->tx_ring_mutex); + break; + } + } else if (n < 0) + n = TX_RING_SIZE - wnd->tx_ring_start; + spin_unlock_bh(&wnd->tx_ring_lock); + if (unlikely(n > wnd->max_tx_packets)) + n = wnd->max_tx_packets; + n = mp_tx_packets(wnd, wnd->tx_ring_start, n); + if (n) { + wnd->net_dev->trans_start = jiffies; + wnd->tx_ring_start = + (wnd->tx_ring_start + n) % TX_RING_SIZE; + wnd->is_tx_ring_full = 0; + } + up(&wnd->tx_ring_mutex); + TRACE3("%d, %d, %d", wnd->tx_ring_start, wnd->tx_ring_end, n); + } + EXIT3(return); +} + +static int tx_skbuff(struct sk_buff *skb, struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + struct ndis_packet *packet; + + packet = alloc_tx_packet(wnd, skb); + if (!packet) { + TRACE2("couldn't allocate packet"); + netif_tx_lock(dev); + netif_stop_queue(dev); + netif_tx_unlock(dev); + return NETDEV_TX_BUSY; + } + spin_lock(&wnd->tx_ring_lock); + wnd->tx_ring[wnd->tx_ring_end++] = packet; + if (wnd->tx_ring_end == TX_RING_SIZE) + wnd->tx_ring_end = 0; + if (wnd->tx_ring_end == wnd->tx_ring_start) { + netif_tx_lock(dev); + wnd->is_tx_ring_full = 1; + netif_stop_queue(dev); + netif_tx_unlock(dev); + } + spin_unlock(&wnd->tx_ring_lock); + TRACE4("ring: %d, %d", wnd->tx_ring_start, wnd->tx_ring_end); + schedule_wrapndis_work(&wnd->tx_work); + return NETDEV_TX_OK; +} + +static int set_packet_filter(struct ndis_device *wnd, ULONG packet_filter) +{ + NDIS_STATUS res; + + while (1) { + res = mp_set_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, + packet_filter); + if (res == NDIS_STATUS_SUCCESS) + break; + TRACE2("couldn't set filter 0x%08x", packet_filter); + /* NDIS_PACKET_TYPE_PROMISCUOUS may not work with 802.11 */ + if (packet_filter & NDIS_PACKET_TYPE_PROMISCUOUS) { + packet_filter &= ~NDIS_PACKET_TYPE_PROMISCUOUS; + continue; + } + if (packet_filter & NDIS_PACKET_TYPE_ALL_LOCAL) { + packet_filter &= ~NDIS_PACKET_TYPE_ALL_LOCAL; + continue; + } + if (packet_filter & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) { + packet_filter &= ~NDIS_PACKET_TYPE_ALL_FUNCTIONAL; + continue; + } + if (packet_filter & NDIS_PACKET_TYPE_MULTICAST) { + packet_filter &= ~NDIS_PACKET_TYPE_MULTICAST; + packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; + continue; + } + if (packet_filter & NDIS_PACKET_TYPE_ALL_MULTICAST) { + packet_filter &= ~NDIS_PACKET_TYPE_ALL_MULTICAST; + continue; + } + break; + } + + wnd->packet_filter = packet_filter; + res = mp_query_int(wnd, OID_GEN_CURRENT_PACKET_FILTER, &packet_filter); + if (packet_filter != wnd->packet_filter) { + WARNING("filter not set: 0x%08x, 0x%08x", + packet_filter, wnd->packet_filter); + wnd->packet_filter = packet_filter; + } + if (wnd->packet_filter) + EXIT3(return 0); + else + EXIT3(return -1); +} + +void set_media_state(struct ndis_device *wnd, enum ndis_media_state state) +{ + ENTER2("state: 0x%x", state); + if (state == NdisMediaStateConnected) { + netif_carrier_on(wnd->net_dev); + wnd->tx_ok = 1; + if (netif_queue_stopped(wnd->net_dev)) + netif_wake_queue(wnd->net_dev); + if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) { + set_bit(LINK_STATUS_ON, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); + } + } else if (state == NdisMediaStateDisconnected) { + netif_carrier_off(wnd->net_dev); + netif_stop_queue(wnd->net_dev); + wnd->tx_ok = 0; + if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) { + memset(&wnd->essid, 0, sizeof(wnd->essid)); + set_bit(LINK_STATUS_OFF, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); + } + } else { + WARNING("invalid media state: 0x%x", state); + } +} + +static int ndis_net_dev_open(struct net_device *net_dev) +{ + ENTER1("%p", netdev_priv(net_dev)); + netif_start_queue(net_dev); + netif_poll_enable(net_dev); + EXIT1(return 0); +} + +static int ndis_net_dev_close(struct net_device *net_dev) +{ + ENTER1("%p", netdev_priv(net_dev)); + netif_poll_disable(net_dev); + netif_tx_disable(net_dev); + EXIT1(return 0); +} + +static int ndis_change_mtu(struct net_device *net_dev, int mtu) +{ + struct ndis_device *wnd = netdev_priv(net_dev); + int max; + + if (mtu < ETH_ZLEN) + return -EINVAL; + if (mp_query_int(wnd, OID_GEN_MAXIMUM_TOTAL_SIZE, &max) != + NDIS_STATUS_SUCCESS) + return -EOPNOTSUPP; + TRACE1("%d", max); + max -= ETH_HLEN; + if (max <= ETH_ZLEN) + return -EINVAL; + if (mtu + ETH_HLEN > max) + return -EINVAL; + net_dev->mtu = mtu; + return 0; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void ndis_poll_controller(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + + disable_irq(dev->irq); + ndis_isr(wnd->mp_interrupt->kinterrupt, wnd->mp_interrupt); + enable_irq(dev->irq); +} +#endif + +/* called from BH context */ +static struct net_device_stats *ndis_get_stats(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + return &wnd->net_stats; +} + +/* called from BH context */ +static void ndis_set_multicast_list(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + set_bit(SET_MULTICAST_LIST, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); +} + +/* called from BH context */ +struct iw_statistics *get_iw_stats(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + return &wnd->iw_stats; +} + +static void update_iw_stats(struct ndis_device *wnd) +{ + struct iw_statistics *iw_stats = &wnd->iw_stats; + struct ndis_wireless_stats ndis_stats; + NDIS_STATUS res; + ndis_rssi rssi; + int qual; + + ENTER2("%p", wnd); + if (wnd->iw_stats_enabled == FALSE || !netif_carrier_ok(wnd->net_dev)) { + memset(iw_stats, 0, sizeof(*iw_stats)); + EXIT2(return); + } + res = mp_query(wnd, OID_802_11_RSSI, &rssi, sizeof(rssi)); + if (res == NDIS_STATUS_SUCCESS) + iw_stats->qual.level = rssi; + + qual = 100 * (rssi - WL_NOISE) / (WL_SIGMAX - WL_NOISE); + if (qual < 0) + qual = 0; + else if (qual > 100) + qual = 100; + + iw_stats->qual.noise = WL_NOISE; + iw_stats->qual.qual = qual; + + res = mp_query(wnd, OID_802_11_STATISTICS, + &ndis_stats, sizeof(ndis_stats)); + if (res != NDIS_STATUS_SUCCESS) + EXIT2(return); + iw_stats->discard.retries = (unsigned long)ndis_stats.retry + + (unsigned long)ndis_stats.multi_retry; + iw_stats->discard.misc = (unsigned long)ndis_stats.fcs_err + + (unsigned long)ndis_stats.rtss_fail + + (unsigned long)ndis_stats.ack_fail + + (unsigned long)ndis_stats.frame_dup; + + EXIT2(return); +} + +static void set_multicast_list(struct ndis_device *wnd) +{ + struct net_device *net_dev; + int mc_count; + ULONG packet_filter; + NDIS_STATUS res; + + net_dev = wnd->net_dev; + packet_filter = wnd->packet_filter; + mc_count = netdev_mc_count(net_dev); + + TRACE2("0x%08x", packet_filter); + if (net_dev->flags & IFF_PROMISC) { + packet_filter |= NDIS_PACKET_TYPE_PROMISCUOUS | + NDIS_PACKET_TYPE_ALL_LOCAL; + } else if (net_dev->flags & IFF_ALLMULTI || + mc_count > wnd->multicast_size) { + packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; + TRACE2("0x%08x", packet_filter); + } else if (mc_count > 0) { + int i, size; + char *buf; + struct netdev_hw_addr *ha; + size = min(wnd->multicast_size, mc_count); + TRACE2("%d, %d", wnd->multicast_size, mc_count); + buf = kmalloc(size * ETH_ALEN, GFP_KERNEL); + if (!buf) { + WARNING("couldn't allocate memory"); + EXIT2(return); + } + i = 0; + netdev_for_each_mc_addr(ha, net_dev) { + if (i >= size) + break; + if (net_dev->addr_len != ETH_ALEN) + continue; + memcpy(buf + i * ETH_ALEN, ha->addr, ETH_ALEN); + TRACE2(MACSTRSEP, MAC2STR(ha->addr)); + i++; + } + res = mp_set(wnd, OID_802_3_MULTICAST_LIST, buf, i * ETH_ALEN); + if (res == NDIS_STATUS_SUCCESS && i > 0) + packet_filter |= NDIS_PACKET_TYPE_MULTICAST; + else + packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; + kfree(buf); + } + TRACE2("0x%08x", packet_filter); + res = set_packet_filter(wnd, packet_filter); + if (res) + TRACE1("couldn't set packet filter (%08X)", res); + EXIT2(return); +} + +static void link_status_off(struct ndis_device *wnd) +{ +#ifdef CONFIG_WIRELESS_EXT + union iwreq_data wrqu; + + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL); +#endif + EXIT2(return); +} + +static void link_status_on(struct ndis_device *wnd) +{ +#ifdef CONFIG_WIRELESS_EXT + struct ndis_assoc_info *ndis_assoc_info; + union iwreq_data wrqu; + NDIS_STATUS res; + const int assoc_size = sizeof(*ndis_assoc_info) + IW_CUSTOM_MAX + 32; +#endif + + ENTER2(""); +#ifdef CONFIG_WIRELESS_EXT + memset(&wrqu, 0, sizeof(wrqu)); + ndis_assoc_info = kzalloc(assoc_size, GFP_KERNEL); + if (!ndis_assoc_info) { + ERROR("couldn't allocate memory"); + goto send_assoc_event; + } + res = mp_query(wnd, OID_802_11_ASSOCIATION_INFORMATION, + ndis_assoc_info, assoc_size); + if (res) { + TRACE2("query assoc_info failed (%08X)", res); + kfree(ndis_assoc_info); + goto send_assoc_event; + } + TRACE2("%u, 0x%x, %u, 0x%x, %u", ndis_assoc_info->length, + ndis_assoc_info->req_ies, ndis_assoc_info->req_ie_length, + ndis_assoc_info->resp_ies, ndis_assoc_info->resp_ie_length); + if (ndis_assoc_info->req_ie_length > 0) { + wrqu.data.length = ndis_assoc_info->req_ie_length; + wireless_send_event(wnd->net_dev, IWEVASSOCREQIE, &wrqu, + ((char *)ndis_assoc_info) + + ndis_assoc_info->offset_req_ies); + } + if (ndis_assoc_info->resp_ie_length > 0) { + wrqu.data.length = ndis_assoc_info->resp_ie_length; + wireless_send_event(wnd->net_dev, IWEVASSOCRESPIE, &wrqu, + ((char *)ndis_assoc_info) + + ndis_assoc_info->offset_resp_ies); + } + kfree(ndis_assoc_info); + +send_assoc_event: + get_ap_address(wnd, wrqu.ap_addr.sa_data); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + TRACE2(MACSTRSEP, MAC2STR(wrqu.ap_addr.sa_data)); + wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL); +#endif + EXIT2(return); +} + +static void iw_stats_timer_proc(unsigned long data) +{ + struct ndis_device *wnd = (struct ndis_device *)data; + + ENTER2("%d", wnd->iw_stats_interval); + if (wnd->iw_stats_interval > 0) { + set_bit(COLLECT_IW_STATS, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); + } + mod_timer(&wnd->iw_stats_timer, jiffies + wnd->iw_stats_interval); +} + +static void add_iw_stats_timer(struct ndis_device *wnd) +{ + if (wnd->physical_medium != NdisPhysicalMediumWirelessLan) + return; + if (wnd->iw_stats_interval < 0) + wnd->iw_stats_interval *= -1; + wnd->iw_stats_timer.data = (unsigned long)wnd; + wnd->iw_stats_timer.function = iw_stats_timer_proc; + mod_timer(&wnd->iw_stats_timer, jiffies + wnd->iw_stats_interval); +} + +static void del_iw_stats_timer(struct ndis_device *wnd) +{ + ENTER2("%d", wnd->iw_stats_interval); + wnd->iw_stats_interval *= -1; + del_timer_sync(&wnd->iw_stats_timer); + EXIT2(return); +} + +static void hangcheck_proc(unsigned long data) +{ + struct ndis_device *wnd = (struct ndis_device *)data; + + ENTER3("%d", wnd->hangcheck_interval); + if (wnd->hangcheck_interval > 0) { + set_bit(HANGCHECK, &wnd->ndis_pending_work); + schedule_wrapndis_work(&wnd->ndis_work); + } + mod_timer(&wnd->hangcheck_timer, jiffies + wnd->hangcheck_interval); + EXIT3(return); +} + +void hangcheck_add(struct ndis_device *wnd) +{ + if (!wnd->wd->driver->ndis_driver->mp.hangcheck || + hangcheck_interval < 0) + EXIT2(return); + + if (hangcheck_interval > 0) + wnd->hangcheck_interval = hangcheck_interval * HZ; + if (wnd->hangcheck_interval < 0) + wnd->hangcheck_interval *= -1; + wnd->hangcheck_timer.data = (unsigned long)wnd; + wnd->hangcheck_timer.function = hangcheck_proc; + mod_timer(&wnd->hangcheck_timer, jiffies + wnd->hangcheck_interval); + EXIT2(return); +} + +void hangcheck_del(struct ndis_device *wnd) +{ + ENTER2("%d", wnd->hangcheck_interval); + if (wnd->hangcheck_interval > 0) + wnd->hangcheck_interval *= -1; + del_timer_sync(&wnd->hangcheck_timer); + EXIT2(return); +} + +/* worker procedure to take care of setting/checking various states */ +static void ndis_worker(worker_param_t param) +{ + struct ndis_device *wnd; + + wnd = worker_param_data(param, struct ndis_device, ndis_work); + WORKTRACE("0x%lx", wnd->ndis_pending_work); + + if (test_and_clear_bit(NETIF_WAKEQ, &wnd->ndis_pending_work)) { + netif_tx_lock_bh(wnd->net_dev); + netif_wake_queue(wnd->net_dev); + netif_tx_unlock_bh(wnd->net_dev); + } + + if (test_and_clear_bit(LINK_STATUS_OFF, &wnd->ndis_pending_work)) + link_status_off(wnd); + + if (test_and_clear_bit(LINK_STATUS_ON, &wnd->ndis_pending_work)) + link_status_on(wnd); + + if (test_and_clear_bit(COLLECT_IW_STATS, &wnd->ndis_pending_work)) + update_iw_stats(wnd); + + if (test_and_clear_bit(SET_MULTICAST_LIST, + &wnd->ndis_pending_work)) + set_multicast_list(wnd); + + if (test_and_clear_bit(HANGCHECK, &wnd->ndis_pending_work)) { + struct miniport *mp; + BOOLEAN reset; + KIRQL irql; + + mp = &wnd->wd->driver->ndis_driver->mp; + irql = serialize_lock_irql(wnd); + reset = LIN2WIN1(mp->hangcheck, wnd->nmb->mp_ctx); + serialize_unlock_irql(wnd, irql); + if (reset) { + TRACE2("%s needs reset", wnd->net_dev->name); + mp_reset(wnd); + } + } + WORKEXIT(return); +} + +NDIS_STATUS ndis_reinit(struct ndis_device *wnd) +{ + NDIS_STATUS status; + + wnd->attributes &= ~NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND; + status = mp_set_power_state(wnd, NdisDeviceStateD3); + if (status != NDIS_STATUS_SUCCESS) { + ERROR("halting device %s failed: %08X", wnd->net_dev->name, + status); + return status; + } + status = mp_set_power_state(wnd, NdisDeviceStateD0); + if (status != NDIS_STATUS_SUCCESS) + ERROR("starting device %s failed: %08X", wnd->net_dev->name, + status); + return status; +} + +static void get_encryption_capa(struct ndis_device *wnd, char *buf, + const int buf_len) +{ + int i, mode; + NDIS_STATUS res; + struct ndis_assoc_info ndis_assoc_info; + struct ndis_add_key ndis_key; + struct ndis_capability *c; + + ENTER1("%p", wnd); + /* set network type to g, b, or a, in that order */ + res = mp_query(wnd, OID_802_11_NETWORK_TYPES_SUPPORTED, buf, buf_len); + if (res == NDIS_STATUS_SUCCESS) { + struct network_type_list *net_types; + unsigned long types = 0; + net_types = (typeof(net_types))buf; + for (i = 0; i < net_types->num; i++) { + TRACE2("%d", net_types->types[i]); + set_bit(net_types->types[i], &types); + } + if (types & Ndis802_11OFDM24) + mode = Ndis802_11OFDM24; + else if (types & Ndis802_11DS) + mode = Ndis802_11DS; + else if (types & Ndis802_11OFDM5) + mode = Ndis802_11OFDM5; + else + mode = Ndis802_11DS; + mp_set_int(wnd, OID_802_11_NETWORK_TYPE_IN_USE, mode); + } + /* check if WEP is supported */ + if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104, + IW_AUTH_CIPHER_NONE) == 0 && + get_ndis_encr_mode(wnd) == Ndis802_11Encryption1KeyAbsent) + set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr); + + /* check if WPA is supported */ + if (set_ndis_auth_mode(wnd, Ndis802_11AuthModeWPA) == 0 && + get_ndis_auth_mode(wnd) == Ndis802_11AuthModeWPA) + set_bit(Ndis802_11AuthModeWPA, &wnd->capa.encr); + else + EXIT1(return); + + if (set_ndis_auth_mode(wnd, Ndis802_11AuthModeWPAPSK) == 0 && + get_ndis_auth_mode(wnd) == Ndis802_11AuthModeWPAPSK) + set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.encr); + + /* check for highest encryption */ + mode = 0; + if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_CCMP, + IW_AUTH_CIPHER_NONE) == 0 && + (i = get_ndis_encr_mode(wnd)) > 0 && + (i == Ndis802_11Encryption3KeyAbsent || + i == Ndis802_11Encryption3Enabled)) + mode = Ndis802_11Encryption3Enabled; + else if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_TKIP, + IW_AUTH_CIPHER_NONE) == 0 && + (i = get_ndis_encr_mode(wnd)) > 0 && + (i == Ndis802_11Encryption2KeyAbsent || + i == Ndis802_11Encryption2Enabled)) + mode = Ndis802_11Encryption2Enabled; + else if (set_iw_encr_mode(wnd, IW_AUTH_CIPHER_WEP104, + IW_AUTH_CIPHER_NONE) == 0 && + (i = get_ndis_encr_mode(wnd)) > 0 && + (i == Ndis802_11Encryption1KeyAbsent || + i == Ndis802_11Encryption1Enabled)) + mode = Ndis802_11Encryption1Enabled; + + TRACE1("mode: %d", mode); + if (mode == 0) + EXIT1(return); + set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr); + if (mode == Ndis802_11Encryption1Enabled) + EXIT1(return); + + ndis_key.length = 32; + ndis_key.index = 0xC0000001; + ndis_key.struct_size = sizeof(ndis_key); + res = mp_set(wnd, OID_802_11_ADD_KEY, &ndis_key, ndis_key.struct_size); + TRACE2("%08X, %lu", res, (unsigned long)sizeof(ndis_key)); + if (res && res != NDIS_STATUS_INVALID_DATA) + EXIT1(return); + res = mp_query(wnd, OID_802_11_ASSOCIATION_INFORMATION, + &ndis_assoc_info, sizeof(ndis_assoc_info)); + TRACE1("%08X", res); + if (res == NDIS_STATUS_NOT_SUPPORTED) + EXIT1(return); + + set_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr); + if (mode == Ndis802_11Encryption3Enabled) + set_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr); + /* not all drivers support OID_802_11_CAPABILITY, so we don't + * know for sure if driver support WPA or WPAPSK; assume + * WPAPSK */ + set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth); + wnd->max_pmkids = 1; + + memset(buf, 0, buf_len); + c = (struct ndis_capability *)buf; + res = mp_query(wnd, OID_802_11_CAPABILITY, buf, buf_len); + if (!(res == NDIS_STATUS_SUCCESS && c->version == 2)) + EXIT1(return); + wnd->max_pmkids = c->num_PMKIDs; + + for (i = 0; i < c->num_auth_encr_pair; i++) { + struct ndis_auth_encr_pair *ae; + + ae = &c->auth_encr_pair[i]; + if ((char *)(ae + 1) > buf + buf_len) + break; + switch (ae->auth_mode) { + case Ndis802_11AuthModeOpen: + case Ndis802_11AuthModeShared: + case Ndis802_11AuthModeWPA: + case Ndis802_11AuthModeWPAPSK: + case Ndis802_11AuthModeWPANone: + case Ndis802_11AuthModeWPA2: + case Ndis802_11AuthModeWPA2PSK: + set_bit(ae->auth_mode, &wnd->capa.auth); + break; + default: + WARNING("unknown auth_mode: %d", ae->auth_mode); + break; + } + switch (ae->encr_mode) { + case Ndis802_11EncryptionDisabled: + case Ndis802_11Encryption1Enabled: + case Ndis802_11Encryption2Enabled: + case Ndis802_11Encryption3Enabled: + set_bit(ae->encr_mode, &wnd->capa.encr); + break; + default: + WARNING("unknown encr_mode: %d", ae->encr_mode); + break; + } + } + EXIT1(return); +} + +wstdcall NTSTATUS NdisDispatchDeviceControl(struct device_object *fdo, + struct irp *irp) +{ + struct ndis_device *wnd; + + TRACE3("fdo: %p", fdo); + /* for now, we don't have anything intresting here, so pass it + * down to bus driver */ + wnd = fdo->reserved; + return IoPassIrpDown(wnd->nmb->pdo, irp); +} +WIN_FUNC_DECL(NdisDispatchDeviceControl,2) + +wstdcall NTSTATUS NdisDispatchPower(struct device_object *fdo, struct irp *irp) +{ + struct io_stack_location *irp_sl; + struct ndis_device *wnd; + enum ndis_power_state state; + NTSTATUS status; + NDIS_STATUS ndis_status; + + irp_sl = IoGetCurrentIrpStackLocation(irp); + wnd = fdo->reserved; + IOTRACE("fdo: %p, fn: %d:%d, wnd: %p", fdo, irp_sl->major_fn, + irp_sl->minor_fn, wnd); + if ((irp_sl->params.power.type == SystemPowerState && + irp_sl->params.power.state.system_state > PowerSystemWorking) || + (irp_sl->params.power.type == DevicePowerState && + irp_sl->params.power.state.device_state > PowerDeviceD0)) + state = NdisDeviceStateD3; + else + state = NdisDeviceStateD0; + switch (irp_sl->minor_fn) { + case IRP_MN_SET_POWER: + if (state == NdisDeviceStateD0) { + status = IoSyncForwardIrp(wnd->nmb->pdo, irp); + if (status != STATUS_SUCCESS) + break; + ndis_status = mp_set_power_state(wnd, state); + if (ndis_status != NDIS_STATUS_SUCCESS) + WARNING("couldn't set power to %d: %08X", + state, ndis_status); + TRACE2("%s: device resumed", wnd->net_dev->name); + irp->io_status.status = status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + break; + } else { + ndis_status = mp_set_power_state(wnd, state); + /* TODO: handle error case */ + if (ndis_status != NDIS_STATUS_SUCCESS) + WARNING("setting power to %d failed: %08X", + state, ndis_status); + status = IoAsyncForwardIrp(wnd->nmb->pdo, irp); + } + break; + case IRP_MN_QUERY_POWER: + if (wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND) { + ndis_status = mp_query(wnd, OID_PNP_QUERY_POWER, + &state, sizeof(state)); + TRACE2("%d, %08X", state, ndis_status); + /* this OID must always succeed */ + if (ndis_status != NDIS_STATUS_SUCCESS) + TRACE1("query power returns %08X", ndis_status); + irp->io_status.status = STATUS_SUCCESS; + } else + irp->io_status.status = STATUS_SUCCESS; + status = IoPassIrpDown(wnd->nmb->pdo, irp); + break; + case IRP_MN_WAIT_WAKE: + case IRP_MN_POWER_SEQUENCE: + /* TODO: implement WAIT_WAKE */ + status = IoPassIrpDown(wnd->nmb->pdo, irp); + break; + default: + status = IoPassIrpDown(wnd->nmb->pdo, irp); + break; + } + IOEXIT(return status); +} +WIN_FUNC_DECL(NdisDispatchPower,2) + +wstdcall NTSTATUS NdisDispatchPnp(struct device_object *fdo, struct irp *irp) +{ + struct io_stack_location *irp_sl; + struct ndis_device *wnd; + struct device_object *pdo; + NTSTATUS status; + + IOTRACE("fdo: %p, irp: %p", fdo, irp); + irp_sl = IoGetCurrentIrpStackLocation(irp); + wnd = fdo->reserved; + pdo = wnd->nmb->pdo; + switch (irp_sl->minor_fn) { + case IRP_MN_START_DEVICE: + status = IoSyncForwardIrp(pdo, irp); + if (status != STATUS_SUCCESS) + break; + if (ndis_start_device(wnd) == NDIS_STATUS_SUCCESS) + status = STATUS_SUCCESS; + else + status = STATUS_FAILURE; + irp->io_status.status = status; + IoCompleteRequest(irp, IO_NO_INCREMENT); + break; + case IRP_MN_QUERY_STOP_DEVICE: + /* TODO: implement in NDIS */ + status = IoPassIrpDown(wnd->nmb->pdo, irp); + break; + case IRP_MN_STOP_DEVICE: + mp_halt(wnd); + irp->io_status.status = STATUS_SUCCESS; + status = IoAsyncForwardIrp(pdo, irp); + break; + case IRP_MN_REMOVE_DEVICE: + TRACE1("%s", wnd->net_dev->name); + mp_pnp_event(wnd, NdisDevicePnPEventSurpriseRemoved, 0); + if (ndis_remove_device(wnd)) { + status = STATUS_FAILURE; + break; + } + /* wnd is already freed */ + status = IoAsyncForwardIrp(pdo, irp); + IoDetachDevice(fdo); + IoDeleteDevice(fdo); + break; + default: + status = IoAsyncForwardIrp(pdo, irp); + break; + } + IOTRACE("status: %08X", status); + IOEXIT(return status); +} +WIN_FUNC_DECL(NdisDispatchPnp,2) + +static void set_task_offload(struct ndis_device *wnd, void *buf, + const int buf_size) +{ + struct ndis_task_offload_header *task_offload_header; + struct ndis_task_offload *task_offload; + struct ndis_task_tcp_ip_checksum *csum = NULL; + struct ndis_task_tcp_large_send *tso = NULL; + NDIS_STATUS status; + + memset(buf, 0, buf_size); + task_offload_header = buf; + task_offload_header->version = NDIS_TASK_OFFLOAD_VERSION; + task_offload_header->size = sizeof(*task_offload_header); + task_offload_header->encap_format.flags.fixed_header_size = 1; + task_offload_header->encap_format.header_size = sizeof(struct ethhdr); + task_offload_header->encap_format.encap = IEEE_802_3_Encapsulation; + status = mp_query(wnd, OID_TCP_TASK_OFFLOAD, buf, buf_size); + TRACE1("%08X", status); + if (status != NDIS_STATUS_SUCCESS) + EXIT1(return); + if (task_offload_header->offset_first_task == 0) + EXIT1(return); + task_offload = ((void *)task_offload_header + + task_offload_header->offset_first_task); + while (1) { + TRACE1("%d, %d", task_offload->version, task_offload->task); + switch(task_offload->task) { + case TcpIpChecksumNdisTask: + csum = (void *)task_offload->task_buf; + break; + case TcpLargeSendNdisTask: + tso = (void *)task_offload->task_buf; + break; + default: + TRACE1("%d", task_offload->task); + break; + } + if (task_offload->offset_next_task == 0) + break; + task_offload = (void *)task_offload + + task_offload->offset_next_task; + } + if (tso) + TRACE1("%u, %u, %d, %d", tso->max_size, tso->min_seg_count, + tso->tcp_opts, tso->ip_opts); + if (!csum) + EXIT1(return); + TRACE1("%08x, %08x", csum->v4_tx.value, csum->v4_rx.value); + task_offload_header->encap_format.flags.fixed_header_size = 1; + task_offload_header->encap_format.header_size = sizeof(struct ethhdr); + task_offload_header->offset_first_task = sizeof(*task_offload_header); + task_offload = ((void *)task_offload_header + + task_offload_header->offset_first_task); + task_offload->offset_next_task = 0; + task_offload->size = sizeof(*task_offload); + task_offload->task = TcpIpChecksumNdisTask; + memcpy(task_offload->task_buf, csum, sizeof(*csum)); + task_offload->task_buf_length = sizeof(*csum); + status = mp_set(wnd, OID_TCP_TASK_OFFLOAD, task_offload_header, + sizeof(*task_offload_header) + + sizeof(*task_offload) + sizeof(*csum)); + TRACE1("%08X", status); + if (status != NDIS_STATUS_SUCCESS) + EXIT2(return); + wnd->tx_csum = csum->v4_tx; + if (csum->v4_tx.tcp_csum && csum->v4_tx.udp_csum) { + if (csum->v4_tx.ip_csum) { + wnd->net_dev->features |= NETIF_F_HW_CSUM; + TRACE1("hw checksum enabled"); + } else { + wnd->net_dev->features |= NETIF_F_IP_CSUM; + TRACE1("IP checksum enabled"); + } + if (wnd->sg_dma_size) + wnd->net_dev->features |= NETIF_F_SG; + } + wnd->rx_csum = csum->v4_rx; + EXIT1(return); +} + +static void get_supported_oids(struct ndis_device *wnd) +{ + NDIS_STATUS res; + int i, n, needed; + ndis_oid *oids; + + res = mp_query_info(wnd, OID_GEN_SUPPORTED_LIST, NULL, 0, NULL, + &needed); + if (!(res == NDIS_STATUS_BUFFER_TOO_SHORT || + res == NDIS_STATUS_INVALID_LENGTH)) + EXIT1(return); + oids = kmalloc(needed, GFP_KERNEL); + if (!oids) { + TRACE1("couldn't allocate memory"); + EXIT1(return); + } + res = mp_query(wnd, OID_GEN_SUPPORTED_LIST, oids, needed); + if (res) { + TRACE1("failed: %08X", res); + kfree(oids); + EXIT1(return); + } + for (i = 0, n = needed / sizeof(*oids); i < n; i++) { + TRACE1("oid: %08X", oids[i]); + /* if a wireless device didn't say so for + * OID_GEN_PHYSICAL_MEDIUM (they should, but in case) */ + if (wnd->physical_medium != NdisPhysicalMediumWirelessLan && + oids[i] == OID_802_11_SSID) + wnd->physical_medium = NdisPhysicalMediumWirelessLan; + } + kfree(oids); + EXIT1(return); +} + +static void ndis_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct ndis_device *wnd = netdev_priv(dev); + strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 2); + strcat(info->driver, "+"); + strncat(info->driver, wnd->wd->driver->name, + sizeof(info->driver) - strlen(DRIVER_NAME) - 1); + strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 2); + strcat(info->version, "+"); + strncat(info->version, wnd->wd->driver->version, + sizeof(info->version) - strlen(DRIVER_VERSION) - 1); + if (wrap_is_pci_bus(wnd->wd->dev_bus)) + strncpy(info->bus_info, pci_name(wnd->wd->pci.pdev), + sizeof(info->bus_info) - 1); +#ifdef ENABLE_USB + else + usb_make_path(wnd->wd->usb.udev, info->bus_info, + sizeof(info->bus_info) - 1); +#endif + return; +} + +static u32 ndis_get_link(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + return netif_carrier_ok(wnd->net_dev); +} + +static void ndis_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct ndis_device *wnd = netdev_priv(dev); + + wol->supported = 0; + wol->wolopts = 0; + if (!(wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND)) + EXIT2(return); + if (!wrap_is_pci_bus(wnd->wd->dev_bus)) + EXIT2(return); + /* we always suspend to D3 */ + if (wnd->pnp_capa.wakeup.min_magic_packet_wakeup < NdisDeviceStateD3) + return; + wol->supported |= WAKE_MAGIC; + if (wnd->ndis_wolopts & NDIS_PNP_WAKE_UP_MAGIC_PACKET) + wol->wolopts |= WAKE_MAGIC; + return; +} + +static int ndis_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + struct ndis_device *wnd = netdev_priv(dev); + + if (!(wnd->attributes & NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND)) + return -EOPNOTSUPP; + if (wnd->pnp_capa.wakeup.min_magic_packet_wakeup < NdisDeviceStateD3) + EXIT2(return -EOPNOTSUPP); + TRACE2("0x%x", wol->wolopts); + if (wol->wolopts & WAKE_MAGIC) { + wnd->ndis_wolopts |= NDIS_PNP_WAKE_UP_MAGIC_PACKET; + if (wol->wolopts != WAKE_MAGIC) + WARNING("ignored wake-on-lan options: 0x%x", + wol->wolopts & ~WAKE_MAGIC); + } else if (!wol->wolopts) + wnd->ndis_wolopts = 0; + else + return -EOPNOTSUPP; + TRACE2("0x%x", wnd->ndis_wolopts); + return 0; +} + +static u32 ndis_get_tx_csum(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + if (wnd->tx_csum.tcp_csum && wnd->tx_csum.udp_csum) + return 1; + else + return 0; +} + +static u32 ndis_get_rx_csum(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + if (wnd->rx_csum.value) + return 1; + else + return 0; +} + +static int ndis_set_tx_csum(struct net_device *dev, u32 data) +{ + struct ndis_device *wnd = netdev_priv(dev); + + if (data && (wnd->tx_csum.value == 0)) + return -EOPNOTSUPP; + + if (wnd->tx_csum.ip_csum) + ethtool_op_set_tx_hw_csum(dev, data); + else + ethtool_op_set_tx_csum(dev, data); + return 0; +} + +static int ndis_set_rx_csum(struct net_device *dev, u32 data) +{ + struct ndis_device *wnd = netdev_priv(dev); + + if (data && (wnd->tx_csum.value == 0)) + return -EOPNOTSUPP; + + /* TODO: enable/disable rx csum through NDIS */ + return 0; +} + +static u32 ndis_get_sg(struct net_device *dev) +{ + struct ndis_device *wnd = netdev_priv(dev); + if (wnd->sg_dma_size) + return ethtool_op_get_sg(dev); + else + return 0; +} + +static int ndis_set_sg(struct net_device *dev, u32 data) +{ + struct ndis_device *wnd = netdev_priv(dev); + if (wnd->sg_dma_size) + return ethtool_op_set_sg(dev, data); + else + return -EOPNOTSUPP; +} + +static struct ethtool_ops ndis_ethtool_ops = { + .get_drvinfo = ndis_get_drvinfo, + .get_link = ndis_get_link, + .get_wol = ndis_get_wol, + .set_wol = ndis_set_wol, + .get_tx_csum = ndis_get_tx_csum, + .get_rx_csum = ndis_get_rx_csum, + .set_tx_csum = ndis_set_tx_csum, + .set_rx_csum = ndis_set_rx_csum, + .get_sg = ndis_get_sg, + .set_sg = ndis_set_sg, +}; + +static int notifier_event(struct notifier_block *notifier, unsigned long event, + void *ptr) +{ + struct net_device *net_dev = ptr; + + ENTER2("0x%lx", event); + if (net_dev->ethtool_ops == &ndis_ethtool_ops + && event == NETDEV_CHANGENAME) { + struct ndis_device *wnd = netdev_priv(net_dev); + /* called with rtnl lock held, so no need to lock */ + wrap_procfs_remove_ndis_device(wnd); + printk(KERN_INFO "%s: changing interface name from '%s' to " + "'%s'\n", DRIVER_NAME, wnd->netdev_name, net_dev->name); + memcpy(wnd->netdev_name, net_dev->name, + sizeof(wnd->netdev_name)); + wrap_procfs_add_ndis_device(wnd); + } + return NOTIFY_DONE; +} + +static struct notifier_block netdev_notifier = { + .notifier_call = notifier_event, +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) +static const struct net_device_ops ndis_netdev_ops = { + .ndo_open = ndis_net_dev_open, + .ndo_stop = ndis_net_dev_close, + .ndo_start_xmit = tx_skbuff, + .ndo_change_mtu = ndis_change_mtu, + .ndo_set_multicast_list = ndis_set_multicast_list, + .ndo_set_mac_address = ndis_set_mac_address, + .ndo_get_stats = ndis_get_stats, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = ndis_poll_controller, +#endif +}; +#endif + +static NDIS_STATUS ndis_start_device(struct ndis_device *wnd) +{ + struct wrap_device *wd; + struct net_device *net_dev; + NDIS_STATUS status; + char *buf; + const int buf_len = 256; + mac_address mac; + struct transport_header_offset *tx_header_offset; + int n; + + ENTER2("%d", in_atomic()); + status = mp_init(wnd); + if (status == NDIS_STATUS_NOT_RECOGNIZED) + EXIT1(return NDIS_STATUS_SUCCESS); + if (status != NDIS_STATUS_SUCCESS) + EXIT1(return status); + wd = wnd->wd; + net_dev = wnd->net_dev; + + get_supported_oids(wnd); + memset(mac, 0, sizeof(mac)); + status = mp_query(wnd, OID_802_3_CURRENT_ADDRESS, mac, sizeof(mac)); + if (memcmp(mac, "\x00\x00\x00\x00\x00\x00", sizeof(mac)) == 0) { + status = mp_query(wnd, OID_802_3_PERMANENT_ADDRESS, mac, + sizeof(mac)); + if (status != NDIS_STATUS_SUCCESS) { + ERROR("couldn't get mac address: %08X", status); + goto err_start; + } + } + TRACE1("mac:" MACSTRSEP, MAC2STR(mac)); + memcpy(net_dev->dev_addr, mac, ETH_ALEN); + + strncpy(net_dev->name, if_name, IFNAMSIZ - 1); + net_dev->name[IFNAMSIZ - 1] = 0; + + wnd->packet_filter = NDIS_PACKET_TYPE_DIRECTED | + NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_MULTICAST; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) + net_dev->netdev_ops = &ndis_netdev_ops; +#else + net_dev->open = ndis_net_dev_open; + net_dev->hard_start_xmit = tx_skbuff; + net_dev->stop = ndis_net_dev_close; + net_dev->get_stats = ndis_get_stats; + net_dev->change_mtu = ndis_change_mtu; + net_dev->set_multicast_list = ndis_set_multicast_list; + net_dev->set_mac_address = ndis_set_mac_address; +#ifdef CONFIG_NET_POLL_CONTROLLER + net_dev->poll_controller = ndis_poll_controller; +#endif +#endif + if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) { + net_dev->wireless_handlers = &ndis_handler_def; + } + net_dev->ethtool_ops = &ndis_ethtool_ops; + if (wnd->mp_interrupt) + net_dev->irq = wnd->mp_interrupt->irq; + net_dev->mem_start = wnd->mem_start; + net_dev->mem_end = wnd->mem_end; + status = mp_query_int(wnd, OID_802_3_MAXIMUM_LIST_SIZE, + &wnd->multicast_size); + if (status != NDIS_STATUS_SUCCESS || wnd->multicast_size < 0) + wnd->multicast_size = 0; + if (wnd->multicast_size > 0) + net_dev->flags |= IFF_MULTICAST; + else + net_dev->flags &= ~IFF_MULTICAST; + + buf = kmalloc(buf_len, GFP_KERNEL); + if (!buf) { + WARNING("couldn't allocate memory"); + goto err_start; + } + + set_task_offload(wnd, buf, buf_len); +#ifdef NETIF_F_LLTX + net_dev->features |= NETIF_F_LLTX; +#endif + + if (register_netdev(net_dev)) { + ERROR("cannot register net device %s", net_dev->name); + goto err_register; + } + memcpy(wnd->netdev_name, net_dev->name, sizeof(wnd->netdev_name)); + memset(buf, 0, buf_len); + status = mp_query(wnd, OID_GEN_VENDOR_DESCRIPTION, buf, buf_len); + if (status != NDIS_STATUS_SUCCESS) { + WARNING("couldn't get vendor information: 0x%x", status); + buf[0] = 0; + } + wnd->drv_ndis_version = n = 0; + mp_query_int(wnd, OID_GEN_DRIVER_VERSION, &wnd->drv_ndis_version); + mp_query_int(wnd, OID_GEN_VENDOR_DRIVER_VERSION, &n); + + printk(KERN_INFO "%s: ethernet device " MACSTRSEP " using %sNDIS " + "driver: %s, version: 0x%x, NDIS version: 0x%x, vendor: '%s', " + "%s\n", net_dev->name, MAC2STR(net_dev->dev_addr), + deserialized_driver(wnd) ? "" : "serialized ", + wnd->wd->driver->name, n, wnd->drv_ndis_version, buf, + wnd->wd->conf_file_name); + + if (deserialized_driver(wnd)) { + /* deserialized drivers don't have a limit, but we + * keep max at TX_RING_SIZE */ + wnd->max_tx_packets = TX_RING_SIZE; + } else { + status = mp_query_int(wnd, OID_GEN_MAXIMUM_SEND_PACKETS, + &wnd->max_tx_packets); + if (status != NDIS_STATUS_SUCCESS) + wnd->max_tx_packets = 1; + if (wnd->max_tx_packets > TX_RING_SIZE) + wnd->max_tx_packets = TX_RING_SIZE; + } + TRACE2("maximum send packets: %d", wnd->max_tx_packets); + NdisAllocatePacketPoolEx(&status, &wnd->tx_packet_pool, + wnd->max_tx_packets, 0, + PROTOCOL_RESERVED_SIZE_IN_PACKET); + if (status != NDIS_STATUS_SUCCESS) { + ERROR("couldn't allocate packet pool"); + goto packet_pool_err; + } + NdisAllocateBufferPool(&status, &wnd->tx_buffer_pool, + wnd->max_tx_packets + 4); + if (status != NDIS_STATUS_SUCCESS) { + ERROR("couldn't allocate buffer pool"); + goto buffer_pool_err; + } + TRACE1("pool: %p", wnd->tx_buffer_pool); + + if (mp_query_int(wnd, OID_GEN_MAXIMUM_TOTAL_SIZE, &n) == + NDIS_STATUS_SUCCESS && n > ETH_HLEN) + ndis_change_mtu(wnd->net_dev, n - ETH_HLEN); + + if (mp_query_int(wnd, OID_GEN_MAC_OPTIONS, &n) == NDIS_STATUS_SUCCESS) + TRACE2("mac options supported: 0x%x", n); + + tx_header_offset = (typeof(tx_header_offset))buf; + tx_header_offset->protocol_type = NDIS_PROTOCOL_ID_TCP_IP; + tx_header_offset->header_offset = sizeof(ETH_HLEN); + status = mp_set(wnd, OID_GEN_TRANSPORT_HEADER_OFFSET, + tx_header_offset, sizeof(*tx_header_offset)); + TRACE2("%08X", status); + + status = mp_query_int(wnd, OID_GEN_PHYSICAL_MEDIUM, + &wnd->physical_medium); + if (status != NDIS_STATUS_SUCCESS) + wnd->physical_medium = NdisPhysicalMediumUnspecified; + + if (wnd->physical_medium == NdisPhysicalMediumWirelessLan) { + mp_set_int(wnd, OID_802_11_POWER_MODE, NDIS_POWER_OFF); + get_encryption_capa(wnd, buf, buf_len); + TRACE1("capbilities = %ld", wnd->capa.encr); + printk(KERN_INFO "%s: encryption modes supported: " + "%s%s%s%s%s%s%s\n", net_dev->name, + test_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr) ? + "WEP" : "none", + + test_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr) ? + "; TKIP with WPA" : "", + test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ? + ", WPA2" : "", + test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ? + ", WPA2PSK" : "", + + test_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr) ? + "; AES/CCMP with WPA" : "", + test_bit(Ndis802_11AuthModeWPA2, &wnd->capa.auth) ? + ", WPA2" : "", + test_bit(Ndis802_11AuthModeWPA2PSK, &wnd->capa.auth) ? + ", WPA2PSK" : ""); + + set_default_iw_params(wnd); + } + status = mp_query_int(wnd, OID_GEN_MEDIA_CONNECT_STATUS, (int *)buf); + if (status == NDIS_STATUS_SUCCESS) + set_media_state(wnd, *((int *)buf)); + kfree(buf); + wrap_procfs_add_ndis_device(wnd); + hangcheck_add(wnd); + add_iw_stats_timer(wnd); + EXIT1(return NDIS_STATUS_SUCCESS); + +buffer_pool_err: + wnd->tx_buffer_pool = NULL; + if (wnd->tx_packet_pool) { + NdisFreePacketPool(wnd->tx_packet_pool); + wnd->tx_packet_pool = NULL; + } +packet_pool_err: +err_register: + kfree(buf); +err_start: + ndis_remove_device(wnd); + EXIT1(return NDIS_STATUS_FAILURE); +} + +static int ndis_remove_device(struct ndis_device *wnd) +{ + s8 tx_pending; + + /* prevent setting essid during disassociation */ + memset(&wnd->essid, 0, sizeof(wnd->essid)); + wnd->tx_ok = 0; + if (wnd->max_tx_packets) + unregister_netdev(wnd->net_dev); + netif_carrier_off(wnd->net_dev); + /* if device is suspended, but resume failed, tx_ring_mutex + * may already be locked */ + if (down_trylock(&wnd->tx_ring_mutex)) + WARNING("couldn't obtain tx_ring_mutex"); + spin_lock_bh(&wnd->tx_ring_lock); + tx_pending = wnd->tx_ring_end - wnd->tx_ring_start; + if (tx_pending < 0) + tx_pending += TX_RING_SIZE; + else if (tx_pending == 0 && wnd->is_tx_ring_full) + tx_pending = TX_RING_SIZE - 1; + wnd->is_tx_ring_full = 0; + /* throw away pending packets */ + while (tx_pending-- > 0) { + struct ndis_packet *packet; + + packet = wnd->tx_ring[wnd->tx_ring_start]; + free_tx_packet(wnd, packet, NDIS_STATUS_CLOSING); + wnd->tx_ring_start = (wnd->tx_ring_start + 1) % TX_RING_SIZE; + } + spin_unlock_bh(&wnd->tx_ring_lock); + up(&wnd->tx_ring_mutex); + wrap_procfs_remove_ndis_device(wnd); + mp_halt(wnd); + ndis_exit_device(wnd); + + if (wnd->tx_packet_pool) { + NdisFreePacketPool(wnd->tx_packet_pool); + wnd->tx_packet_pool = NULL; + } + if (wnd->tx_buffer_pool) { + NdisFreeBufferPool(wnd->tx_buffer_pool); + wnd->tx_buffer_pool = NULL; + } + if (wnd->pmkids) + kfree(wnd->pmkids); + printk(KERN_INFO "%s: device %s removed\n", DRIVER_NAME, + wnd->net_dev->name); + kfree(wnd->nmb); + free_netdev(wnd->net_dev); + EXIT2(return 0); +} + +static wstdcall NTSTATUS NdisAddDevice(struct driver_object *drv_obj, + struct device_object *pdo) +{ + struct device_object *fdo; + struct ndis_mp_block *nmb; + NTSTATUS status; + struct ndis_device *wnd; + struct net_device *net_dev; + struct wrap_device *wd; + unsigned long i; + + ENTER2("%p, %p", drv_obj, pdo); + if (strlen(if_name) >= IFNAMSIZ) { + ERROR("interface name '%s' is too long", if_name); + return STATUS_INVALID_PARAMETER; + } + net_dev = alloc_etherdev(sizeof(*wnd)); + if (!net_dev) { + ERROR("couldn't allocate device"); + return STATUS_RESOURCES; + } + wd = pdo->reserved; + if (wrap_is_pci_bus(wd->dev_bus)) + SET_NETDEV_DEV(net_dev, &wd->pci.pdev->dev); + if (wrap_is_usb_bus(wd->dev_bus)) + SET_NETDEV_DEV(net_dev, &wd->usb.intf->dev); + status = IoCreateDevice(drv_obj, 0, NULL, FILE_DEVICE_UNKNOWN, 0, + FALSE, &fdo); + if (status != STATUS_SUCCESS) { + free_netdev(net_dev); + EXIT2(return status); + } + wnd = netdev_priv(net_dev); + TRACE1("wnd: %p", wnd); + + nmb = kmalloc(sizeof(*nmb), GFP_KERNEL); + if (!nmb) { + WARNING("couldn't allocate memory"); + IoDeleteDevice(fdo); + free_netdev(net_dev); + return STATUS_RESOURCES; + } +#if defined(DEBUG) && DEBUG >= 6 + /* poison nmb so if a driver accesses uninitialized pointers, we + * know what it is */ + for (i = 0; i < sizeof(*nmb) / sizeof(unsigned long); i++) + ((unsigned long *)nmb)[i] = i + 0x8a3fc1; +#endif + + wnd->nmb = nmb; + nmb->wnd = wnd; + nmb->pdo = pdo; + wd->wnd = wnd; + wnd->wd = wd; + wnd->net_dev = net_dev; + fdo->reserved = wnd; + nmb->fdo = fdo; + if (ndis_init_device(wnd)) { + IoDeleteDevice(fdo); + kfree(nmb); + free_netdev(net_dev); + EXIT1(return STATUS_RESOURCES); + } + nmb->next_device = IoAttachDeviceToDeviceStack(fdo, pdo); + spin_lock_init(&wnd->tx_ring_lock); + sema_init(&wnd->tx_ring_mutex, 1); + sema_init(&wnd->ndis_req_mutex, 1); + wnd->ndis_req_done = 0; + initialize_work(&wnd->tx_work, tx_worker, wnd); + wnd->tx_ring_start = 0; + wnd->tx_ring_end = 0; + wnd->is_tx_ring_full = 0; + wnd->capa.encr = 0; + wnd->capa.auth = 0; + wnd->attributes = 0; + wnd->dma_map_count = 0; + wnd->dma_map_addr = NULL; + wnd->nick[0] = 0; + init_timer(&wnd->hangcheck_timer); + wnd->scan_timestamp = 0; + init_timer(&wnd->iw_stats_timer); + wnd->iw_stats_interval = 10 * HZ; + wnd->ndis_pending_work = 0; + memset(&wnd->essid, 0, sizeof(wnd->essid)); + memset(&wnd->encr_info, 0, sizeof(wnd->encr_info)); + wnd->infrastructure_mode = Ndis802_11Infrastructure; + initialize_work(&wnd->ndis_work, ndis_worker, wnd); + wnd->iw_stats_enabled = TRUE; + + TRACE1("nmb: %p, pdo: %p, fdo: %p, attached: %p, next: %p", + nmb, pdo, fdo, fdo->attached, nmb->next_device); + + /* dispatch routines are called as Windows functions */ + for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) + drv_obj->major_func[i] = WIN_FUNC_PTR(IoPassIrpDown,2); + + drv_obj->major_func[IRP_MJ_PNP] = WIN_FUNC_PTR(NdisDispatchPnp,2); + drv_obj->major_func[IRP_MJ_POWER] = WIN_FUNC_PTR(NdisDispatchPower,2); + drv_obj->major_func[IRP_MJ_INTERNAL_DEVICE_CONTROL] = + WIN_FUNC_PTR(NdisDispatchDeviceControl,2); +// drv_obj->major_func[IRP_MJ_DEVICE_CONTROL] = +// WIN_FUNC_PTR(NdisDispatchDeviceControl,2); + EXIT2(return STATUS_SUCCESS); +} + +int init_ndis_driver(struct driver_object *drv_obj) +{ + ENTER1("%p", drv_obj); + drv_obj->drv_ext->add_device = NdisAddDevice; + return 0; +} + +int wrapndis_init(void) +{ + wrapndis_wq = create_singlethread_workqueue("wrapndis_wq"); + if (!wrapndis_wq) + EXIT1(return -ENOMEM); + wrapndis_worker_thread = wrap_worker_init(wrapndis_wq); + TRACE1("%p", wrapndis_worker_thread); + register_netdevice_notifier(&netdev_notifier); + return 0; +} + +void wrapndis_exit(void) +{ + unregister_netdevice_notifier(&netdev_notifier); + if (wrapndis_wq) + destroy_workqueue(wrapndis_wq); + TRACE1("%p", wrapndis_worker_thread); + if (wrapndis_worker_thread) + ObDereferenceObject(wrapndis_worker_thread); +} --- linux-2.6.37.orig/ubuntu/ndiswrapper/wrapndis.h +++ linux-2.6.37/ubuntu/ndiswrapper/wrapndis.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _WRAPNDIS_H_ +#define _WRAPNDIS_H_ + +#include "ndis.h" +#include "pnp.h" + +int wrapndis_init(void); +void wrapndis_exit(void); + +NDIS_STATUS mp_reset(struct ndis_device *wnd); + +NDIS_STATUS mp_request(enum ndis_request_type request, + struct ndis_device *wnd, ndis_oid oid, + void *buf, ULONG buflen, ULONG *written, ULONG *needed); + +static inline NDIS_STATUS mp_query_info(struct ndis_device *wnd, + ndis_oid oid, void *buf, ULONG buflen, + ULONG *written, ULONG *needed) +{ + return mp_request(NdisRequestQueryInformation, wnd, oid, + buf, buflen, written, needed); +} + +static inline NDIS_STATUS mp_set_info(struct ndis_device *wnd, + ndis_oid oid, void *buf, ULONG buflen, + ULONG *written, ULONG *needed) +{ + return mp_request(NdisRequestSetInformation, wnd, oid, + buf, buflen, written, needed); +} + +static inline NDIS_STATUS mp_query(struct ndis_device *wnd, ndis_oid oid, + void *buf, ULONG buflen) +{ + return mp_request(NdisRequestQueryInformation, wnd, oid, + buf, buflen, NULL, NULL); +} + +static inline NDIS_STATUS mp_query_int(struct ndis_device *wnd, + ndis_oid oid, ULONG *data) +{ + return mp_request(NdisRequestQueryInformation, wnd, oid, + data, sizeof(ULONG), NULL, NULL); +} + +static inline NDIS_STATUS mp_set(struct ndis_device *wnd, ndis_oid oid, + void *buf, ULONG buflen) +{ + return mp_request(NdisRequestSetInformation, wnd, oid, + buf, buflen, NULL, NULL); +} + +static inline NDIS_STATUS mp_set_int(struct ndis_device *wnd, + ndis_oid oid, ULONG data) +{ + return mp_request(NdisRequestSetInformation, wnd, oid, + &data, sizeof(ULONG), NULL, NULL); +} + +void free_tx_packet(struct ndis_device *wnd, struct ndis_packet *packet, + NDIS_STATUS status); +int init_ndis_driver(struct driver_object *drv_obj); +NDIS_STATUS ndis_reinit(struct ndis_device *wnd); +void set_media_state(struct ndis_device *wnd, enum ndis_media_state state); + +void hangcheck_add(struct ndis_device *wnd); +void hangcheck_del(struct ndis_device *wnd); + +driver_dispatch_t winNdisDispatchPnp; +driver_dispatch_t winNdisDispatchPower; +driver_dispatch_t winNdisDispatchDeviceControl; + +struct iw_statistics *get_iw_stats(struct net_device *dev); + +#endif --- linux-2.6.37.orig/ubuntu/ndiswrapper/wrapper.c +++ linux-2.6.37/ubuntu/ndiswrapper/wrapper.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * 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. + * + */ + +#include "ndis.h" +#include "iw_ndis.h" +#include "loader.h" +#include "pnp.h" +#include "wrapper.h" + +char *if_name = "wlan%d"; +int proc_uid, proc_gid; +int hangcheck_interval; +static char *utils_version = UTILS_VERSION; + +#if defined(DEBUG) && (DEBUG > 0) +int debug = DEBUG; +#else +int debug = 0; +#endif + +WRAP_MODULE_PARM_STRING(if_name, 0400); +MODULE_PARM_DESC(if_name, "Network interface name or template " + "(default: wlan%d)"); +WRAP_MODULE_PARM_INT(proc_uid, 0600); +MODULE_PARM_DESC(proc_uid, "The uid of the files created in /proc " + "(default: 0)."); +WRAP_MODULE_PARM_INT(proc_gid, 0600); +MODULE_PARM_DESC(proc_gid, "The gid of the files created in /proc " + "(default: 0)."); +WRAP_MODULE_PARM_INT(debug, 0600); +MODULE_PARM_DESC(debug, "debug level"); + +/* 0 - default value provided by NDIS driver, + * positive value - force hangcheck interval to that many seconds + * negative value - disable hangcheck + */ +WRAP_MODULE_PARM_INT(hangcheck_interval, 0600); +MODULE_PARM_DESC(hangcheck_interval, "The interval, in seconds, for checking" + " if driver is hung. (default: 0)"); + +WRAP_MODULE_PARM_STRING(utils_version, 0400); +MODULE_PARM_DESC(utils_version, "Compatible version of utils " + "(read only: " UTILS_VERSION ")"); + +MODULE_AUTHOR("ndiswrapper team "); +#ifdef MODULE_DESCRIPTION +MODULE_DESCRIPTION("NDIS wrapper driver"); +#endif +#ifdef MODULE_VERSION +MODULE_VERSION(DRIVER_VERSION); +#endif +MODULE_LICENSE("GPL"); + +static void module_cleanup(void) +{ + loader_exit(); +#ifdef ENABLE_USB + usb_exit(); +#endif + + wrap_procfs_remove(); + wrapndis_exit(); + ndis_exit(); + rtl_exit(); + crt_exit(); + ntoskernel_exit(); + wrapmem_exit(); +} + +static int __init wrapper_init(void) +{ + printk(KERN_INFO "%s version %s loaded (smp=%s, preempt=%s)\n", + DRIVER_NAME, DRIVER_VERSION, +#ifdef CONFIG_SMP + "yes" +#else + "no" +#endif + , +#ifdef CONFIG_PREEMPT_RT + "rt" +#elif defined(CONFIG_PREEMPT) + "yes" +#else + "no" +#endif + ); + + if (wrapmem_init() || ntoskernel_init() || crt_init() || + rtl_init() || ndis_init() || wrapndis_init() || +#ifdef ENABLE_USB + usb_init() || +#endif + wrap_procfs_init() || loader_init()) { + module_cleanup(); + ERROR("%s: initialization failed", DRIVER_NAME); + return -EINVAL; + } + EXIT1(return 0); +} + +static void __exit wrapper_exit(void) +{ + ENTER1(""); + module_cleanup(); +} + +module_init(wrapper_init); +module_exit(wrapper_exit); --- linux-2.6.37.orig/ubuntu/ndiswrapper/wrapper.h +++ linux-2.6.37/ubuntu/ndiswrapper/wrapper.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef WRAPPER_H +#define WRAPPER_H + +extern char *if_name; +extern int proc_uid; +extern int proc_gid; +extern int hangcheck_interval; + +#endif /* WRAPPER_H */ --- linux-2.6.37.orig/ubuntu/omnibook/BOM +++ linux-2.6.37/ubuntu/omnibook/BOM @@ -0,0 +1,3 @@ +Downloaded from: git://omnibook.git.sourceforge.net/gitroot/omnibook/omnibook +Current Version: 2.20070211 +Documentation: http://sourceforge.net/apps/mediawiki/omnibook/ --- linux-2.6.37.orig/ubuntu/omnibook/Kconfig +++ linux-2.6.37/ubuntu/omnibook/Kconfig @@ -0,0 +1,5 @@ +config OMNIBOOK + tristate "Kernel module for HP and Toshiba laptops" + depends on X86 + default m + ---help--- --- linux-2.6.37.orig/ubuntu/omnibook/Makefile +++ linux-2.6.37/ubuntu/omnibook/Makefile @@ -0,0 +1,171 @@ +# +# Makefile -- makefile for the HP OmniBook support module +# +# 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, 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. +# +# Written by Soós Péter , 2002-2004 +# Modified by Mathieu Bérard , 2006-2007 +# + +#Module informations + +MODULE_NAME = omnibook +MODULE_VERSION = 2.20090707 +MODULE_BRANCH = trunk + +# Out-of-tree configuration +ifndef CONFIG_OMNIBOOK +OMNIBOOK_STANDALONE=y +CONFIG_OMNIBOOK=m + +#Uncomment and set to force debug behavior +#NOTE: Default (commented) behavior is to enable debug in trunk or branch svn +# snapshot and to disable it for release +#OMNIBOOK_WANT_DEBUG=n + +#comment to disable backlight device support +OMNIBOOK_WANT_BACKLIGHT=y + +#Uncomment to force legacy (pre-ACPI system) features support +#OMNIBOOK_WANT_LEGACY=y + +endif + +ifeq ($(KERNELRELEASE),) +# Support for direct Makefile invocation + +DESTDIR = +MODDIR = $(DESTDIR)/lib/modules +KVERS = $(shell uname -r) +KVER = $(KVERS) +VMODDIR = $(MODDIR)/$(KVER) +INSTDIR = extra +#KSRC = /usr/src/linux +KSRC = $(VMODDIR)/build +KMODDIR = $(KSRC)/drivers/misc/omnibook +KDOCDIR = $(KSRC)/Documentation/omnibook +PWD = $(shell pwd) +TODAY = $(shell date +%Y%m%d) +DEPMOD = /sbin/depmod -aq +RMMOD = /sbin/modprobe -r +INSMOD = /sbin/modprobe +INSTALL = install -m 644 +MKDIR = mkdir -p +RM = rm -f +FIND = find + +all: $(MODULE_NAME).ko + +clean: + make -C $(KSRC) M=$(PWD) clean + $(RM) -r *~ "#*#" .swp + $(RM) -r debian/omnibook-source *-stamp + $(RM) -r Module.symvers Modules.symvers + +install: all + # Removing module from locations used by previous versions + $(RM) $(VMODDIR)/kernel/drivers/char/$(MODULE_NAME).ko + $(RM) $(VMODDIR)/kernel/drivers/misc/$(MODULE_NAME).ko + make INSTALL_MOD_PATH=$(DESTDIR) INSTALL_MOD_DIR=$(INSTDIR) -C $(KSRC) M=$(PWD) modules_install + +unload: + $(RMMOD) $(MODULE_NAME) || : + +load: install unload + $(DEPMOD) + $(INSMOD) $(MODULE_NAME) + +uninstall: unload + $(FIND) $(VMODDIR) -name "$(MODULE_NAME).ko" -exec $(RM) {} \; + $(DEPMOD) + +$(MODULE_NAME).ko: + $(MAKE) -C $(KSRC) SUBDIRS=$(PWD) modules + +kinstall: + $(RM) -r $(KMODDIR) + $(MKDIR) $(KMODDIR) + $(INSTALL) *.h *.c sections.lds $(KMODDIR) + $(MKDIR) $(KDOCDIR) + $(INSTALL) doc/README $(KDOCDIR) + +kpatch: kinstall + (cd $(KSRC); patch -p1 < $(PWD)/misc/omnibook-integration.patch) + +version: + sed -i "s|^\(MODULE_VERSION = \).*|\1 2.$(TODAY)|" Makefile + sed -i "s|^\(MODULE_BRANCH = \).*|\1 release|" Makefile + sed -i "s|^\(2\.\)X\{8\}|\1$(TODAY)|" doc/ChangeLog + + +release: clean version + mkdir -p ../$(MODULE_NAME)-2.$(TODAY) + cp -a *.h *.c *.lds Makefile doc misc ../$(MODULE_NAME)-2.$(TODAY) + rm -f ../$(MODULE_NAME)-2.$(TODAY).tar ../$(MODULE_NAME)-2.$(TODAY).tar.gz + (cd ..; tar cvf $(MODULE_NAME)-2.$(TODAY).tar $(MODULE_NAME)-2.$(TODAY); gzip -9 $(MODULE_NAME)-2.$(TODAY).tar) + +else +# Support for kernel build system invocation + +ifneq ($(MODULE_BRANCH), release) +EXTRA_CFLAGS += -DOMNIBOOK_MODULE_VERSION='"$(MODULE_VERSION)-$(MODULE_BRANCH)"' +else +EXTRA_CFLAGS += -DOMNIBOOK_MODULE_VERSION='"$(MODULE_VERSION)"' +endif + +ifeq ($(OMNIBOOK_STANDALONE),y) + +ifeq ($(OMNIBOOK_WANT_BACKLIGHT),y) +ifdef CONFIG_BACKLIGHT_CLASS_DEVICE +# we support backlight interface only after 2.6.16 +ifeq ($(shell if [ $(SUBLEVEL) -gt 16 ] ; then echo -n 'y'; fi),y) +EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_BACKLIGHT +else +$(warning "Backlight support in only supported for kernel version newer than 2.6.16") +$(warning "Disabling backlight sysfs interface") +endif +endif +endif + +ifeq ($(OMNIBOOK_WANT_LEGACY),y) +EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_LEGACY +endif + +ifndef CONFIG_ACPI_EC +EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_LEGACY +endif + +ifneq ($(MODULE_BRANCH), release) +ifneq ($(OMNIBOOK_WANT_DEBUG),n) +EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_DEBUG # -Wa -g0 +endif +else +ifeq ($(OMNIBOOK_WANT_DEBUG),y) +EXTRA_CFLAGS += -DCONFIG_OMNIBOOK_DEBUG # -Wa -g0 +endif + +endif + +endif + +EXTRA_CFLAGS += -DOMNIBOOK_MODULE_NAME='"$(MODULE_NAME)"' +#EXTRA_LDFLAGS += $(src)/sections.lds +EXTRA_LDFLAGS += $(PWD)/ubuntu/omnibook/sections.lds + +obj-$(CONFIG_OMNIBOOK) += $(MODULE_NAME).o +omnibook-objs := init.o lib.o ec.o kbc.o pio.o compal.o acpi.o nbsmi.o \ + ac.o battery.o blank.o bluetooth.o cooling.o display.o dock.o \ + dump.o fan.o fan_policy.o hotkeys.o info.o lcd.o muteled.o \ + polling.o temperature.o touchpad.o wireless.o throttling.o + +endif # End of kernel build system part + +# End of file --- linux-2.6.37.orig/ubuntu/omnibook/ac.c +++ linux-2.6.37/ubuntu/omnibook/ac.c @@ -0,0 +1,60 @@ +/* + * ac.c -- AC adapter related functions + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" +#include "hardware.h" + +static int omnibook_ac_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + u8 ac; + int retval; + + retval = backend_byte_read(io_op, &ac); + if (retval < 0) + return retval; + + len += sprintf(buffer + len, "AC %s\n", (!!ac) ? "on-line" : "off-line"); + + return len; +} + +static struct omnibook_tbl ac_table[] __initdata = { + {XE3GF | TSP10 | TSM30X | TSM70, SIMPLE_BYTE(EC, XE3GF_ADP, XE3GF_ADP_MASK)}, + {XE3GC | AMILOD, SIMPLE_BYTE(EC, XE3GC_STA1, XE3GC_ADP_MASK)}, + {OB500 | OB510 | OB6000 | OB6100 | XE4500, SIMPLE_BYTE(EC, OB500_STA2, OB500_ADP_MASK)}, + {OB4150, SIMPLE_BYTE(EC, OB4150_ADP, OB4150_ADP_MASK)}, + {XE2, SIMPLE_BYTE(EC, XE2_STA1, XE2_ADP_MASK)}, + {0,} +}; + +struct omnibook_feature __declared_feature ac_driver = { + .name = "ac", +#ifdef CONFIG_OMNIBOOK_LEGACY + .enabled = 1, +#else + .enabled = 0, +#endif + .read = omnibook_ac_read, + .ectypes = XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | OB4150 | XE2 | AMILOD | TSP10 | TSM70 | TSM30X, + .tbl = ac_table, +}; + +module_param_named(ac, ac_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(ac, "Use 0 to disable, 1 to enable AC adapter status monitoring"); + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/acpi.c +++ linux-2.6.37/ubuntu/omnibook/acpi.c @@ -0,0 +1,1158 @@ +/* + * acpi.c -- ACPI methods low-level access code for TSM70 class laptops + * + * 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, 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. + * + * Written by Mathieu Bérard , 2006 + * + */ + +#include "omnibook.h" +#include "hardware.h" + +#ifdef CONFIG_ACPI + +#include +#include + +/* copied from drivers/input/serio/i8042-io.h */ +#define I8042_KBD_PHYS_DESC "isa0060/serio0" + +/* + * ACPI backend masks and strings + */ + +#define GET_WIRELESS_METHOD "ANTR" +#define SET_WIRELESS_METHOD "ANTW" +#define WLEX_MASK 0x4 +#define WLAT_MASK 0x1 +#define BTEX_MASK 0x8 +#define BTAT_MASK 0x2 +#define KLSW_MASK 0x10 + +#define GET_DISPLAY_METHOD "DOSS" +#define SET_DISPLAY_METHOD "DOSW" +/* Display reading masks CADL = detected, CSTE = enabled */ +#define LCD_CADL 0x10 +#define CRT_CADL 0x20 +#define TVO_CADL 0x40 +#define DVI_CADL 0x80 +#define LCD_CSTE 0x1 +#define CRT_CSTE 0x2 +#define TVO_CSTE 0x4 +#define DVI_CSTE 0x8 + +/* TSX205 Video-Out methods and return values */ +#define TSX205_SET_DISPLAY_METHOD "STBL" +#define TSX205_SLI_DISPLAY_METHOD "SL01.VGA1.STBL" +/* NOTE: Method DSSW seems to be some sort of auto-detect method */ +#define TSX205_AUTO_DISPLAY_METHOD "DSSW" +#define TSX205_DSPY_DE 0x1F /* DE - Detected and Enabled */ +#define TSX205_DSPY_DN 0x1D /* DN - Detected and Not enabled */ +#define TSX205_DSPY_NE 0x0F /* NE - Not detected and Enabled */ +#define TSX205_DSPY_NN 0x0D /* NN - Not detected and Not enabled */ + +#define GET_THROTTLE_METHOD "THRO" +#define SET_THROTTLE_METHOD "CLCK" + +static char ec_dev_list[][20] = { + "\\_SB.PCI0.LPCB.EC0", + "\\_SB.PCI0.LPC0.EC0", +}; + +/* TSX205 HCI and display handles */ +static char tsx205_dev_list[][20] = { + "\\_SB.VALZ", + "\\_SB.PCI0.PEGP.VGA" +}; + +/* TSX205 GET video-out methods */ +static char tsx205_video_list[][20] = { + "LCD._DCS", + "CRT._DCS", + "TV._DCS", + "DVI._DCS", + "SL01.VGA1.LCD._DCS", + "SL01.VGA1.CRT._DCS", + "SL01.VGA1.TV._DCS", + "SL01.VGA1.DVI._DCS", +}; + +#define TOSHIBA_ACPI_BT_CLASS "bluetooth" +#define TOSHIBA_ACPI_DEVICE_NAME "bluetooth adapter" + +#define TOSH_BT_ACTIVATE_USB "AUSB" +#define TOSH_BT_DISABLE_USB "DUSB" +#define TOSH_BT_POWER_ON "BTPO" +#define TOSH_BT_POWER_OFF "BTPF" +#define TOSH_BT_STATUS "BTST" +#define TOSH_BT_KSST_MASK 0x1 +#define TOSH_BT_USB_MASK 0x40 +#define TOSH_BT_POWER_MASK 0x80 + +/* + * ACPI driver for Toshiba Bluetooth device + */ +static int omnibook_acpi_bt_add(struct acpi_device *device); +static int omnibook_acpi_bt_remove(struct acpi_device *device, int type); + + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) +static const struct acpi_device_id omnibook_bt_ids[] = { + {"TOS6205", 0}, + {"", 0}, +}; + +static struct acpi_driver omnibook_bt_driver = { + .name = OMNIBOOK_MODULE_NAME, + .class = TOSHIBA_ACPI_BT_CLASS, + .ids = omnibook_bt_ids, + .ops = { + .add = omnibook_acpi_bt_add, + .remove = omnibook_acpi_bt_remove, + }, +}; +#else /* 2.6.23 */ +static struct acpi_driver omnibook_bt_driver = { + .name = OMNIBOOK_MODULE_NAME, + .class = TOSHIBA_ACPI_BT_CLASS, + .ids = "TOS6205", + .ops = { + .add = omnibook_acpi_bt_add, + .remove = omnibook_acpi_bt_remove, + }, +}; +#endif /* 2.6.23 */ + + +/* + * ACPI backend private data structure + */ +struct acpi_backend_data { + acpi_handle ec_handle; /* Handle on ACPI EC device */ + acpi_handle bt_handle; /* Handle on ACPI BT device */ + acpi_handle hci_handle; /* Handle on ACPI HCI device */ + acpi_handle dis_handle; /* Handle on ACPI Display device */ + unsigned has_antr_antw:1; /* Are there ANTR/ANTW methods in the EC device ? */ + unsigned has_doss_dosw:1; /* Are there DOSS/DOSW methods in the EC device ? */ + unsigned has_sli:1; /* Does the laptop has SLI enabled ? */ + struct input_dev *acpi_input_dev; + struct work_struct fnkey_work; +}; + +/* + * Hotkeys workflow: + * 1. Fn+Foo pressed + * 2. Scancode 0x6e generated by kbd controller + * 3. Scancode 0x6e caught by omnibook input handler + * 4. INFO method has keycode of last actually pressed Fn key + * 5. acpi_scan_table used to associate a detected keycode with a generated one + * 6. Generated keycode issued using the omnibook input device + */ + +/* + * The input handler should only bind with the standard AT keyboard. + * XXX: Scancode 0x6e won't be detected if the keyboard has already been + * grabbed (the Xorg event input driver do that) + */ +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) +static int hook_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) +static struct input_handle *hook_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +#else +static struct input_handle *hook_connect(struct input_handler *handler, + struct input_dev *dev, + struct input_device_id *id) +#endif +{ + struct input_handle *handle; + int error; + + /* the 0x0001 vendor magic number is found in atkbd.c */ + if(!(dev->id.bustype == BUS_I8042 && dev->id.vendor == 0x0001)) + goto out_nobind; + + if(!strstr(dev->phys, I8042_KBD_PHYS_DESC)) + goto out_nobind; + + dprintk("hook_connect for device %s.\n", dev->name); + + if(dev->grab) + printk(O_WARN "Input device is grabbed by %s, Fn hotkeys won't work.\n", + dev->grab->name); + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) + return -ENOMEM; +#else + return NULL; +#endif + + handle->dev = dev; + handle->handler = handler; + handle->name = "omnibook_scancode_hook"; + handle->private = handler->private; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) + error = input_register_handle(handle); + if (error) { + dprintk("register_handle failed\n"); + goto out_nobind_free; + } + error = input_open_device(handle); + if (error) { + dprintk("register_handle failed\n"); + input_unregister_handle(handle); + goto out_nobind_free; + } + +#else + status=input_open_device(handle); + if (error==0) dprintk("Input device opened\n"); + else { + dprintk("opening input device failed\n"); + goto out_nobind_free; + } +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) + return 0; +out_nobind_free: + kfree(handle); +out_nobind: + return -ENODEV; +#else + return handle; +out_nobind_free: + kfree(handle); +out_nobind: + return NULL; +#endif +} + +static void hook_disconnect(struct input_handle *handle) +{ + dprintk("hook_disconnect.\n"); + input_close_device(handle); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) + input_unregister_handle(handle); +#endif + kfree(handle); +} + +/* + * Hook for scancode 0x6e. Actual handling is done in a workqueue. + */ +static void hook_event(struct input_handle *handle, unsigned int event_type, + unsigned int event_code, int value) +{ + if (event_type == EV_MSC && event_code == MSC_SCAN && value == ACPI_FN_SCAN) + schedule_work(&((struct acpi_backend_data *)handle->private)->fnkey_work); +} + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) +static const struct input_device_id hook_ids[] = { +#else +static struct input_device_id hook_ids[] = { +#endif + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT(EV_KEY) }, + }, + { }, /* Terminating entry */ +}; + +static struct input_handler hook_handler = { + .event = hook_event, + .connect = hook_connect, + .disconnect = hook_disconnect, + .name = OMNIBOOK_MODULE_NAME, + .id_table = hook_ids, +}; + +/* + * Detected scancode to keycode table + */ +static const struct { + unsigned int scancode; + unsigned int keycode; +} acpi_scan_table[] = { + { HCI_FN_RELEASED, KEY_FN}, + { HCI_MUTE, KEY_MUTE}, + { HCI_BREAK, KEY_COFFEE}, + { HCI_1, KEY_ZOOMOUT}, + { HCI_2, KEY_ZOOMIN}, + { HCI_SPACE, KEY_ZOOMRESET}, + { HCI_BSM, KEY_BATTERY}, + { HCI_SUSPEND, KEY_SLEEP}, + { HCI_HIBERNATE, KEY_SUSPEND}, + { HCI_VIDEOOUT, KEY_SWITCHVIDEOMODE}, + { HCI_BRIGHTNESSDOWN, KEY_BRIGHTNESSDOWN}, + { HCI_BRIGHTNESSUP, KEY_BRIGHTNESSUP}, + { HCI_WLAN, KEY_WLAN}, + { HCI_TOUCHPAD, KEY_PROG1}, + { HCI_FN_PRESSED, KEY_FN}, + { 0, 0}, +}; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)) +static void omnibook_handle_fnkey(struct work_struct *work); +#else +static void omnibook_handle_fnkey(void* data); +#endif + +/* + * Register the input handler and the input device in the input subsystem + */ +static int register_input_subsystem(struct acpi_backend_data *priv_data) +{ + int i, retval = 0; + struct input_dev *acpi_input_dev; + + acpi_input_dev = input_allocate_device(); + if (!acpi_input_dev) { + retval = -ENOMEM; + goto out; + } + + acpi_input_dev->name = "Omnibook ACPI scancode generator"; + acpi_input_dev->phys = "omnibook/input0"; + acpi_input_dev->id.bustype = BUS_HOST; + + set_bit(EV_KEY, acpi_input_dev->evbit); + + for(i=0 ; i < ARRAY_SIZE(acpi_scan_table); i++) + set_bit(acpi_scan_table[i].keycode, acpi_input_dev->keybit); + + retval = input_register_device(acpi_input_dev); + if (retval) { + input_free_device(acpi_input_dev); + goto out; + } + + priv_data->acpi_input_dev = acpi_input_dev; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)) + INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey); +#else + INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey, priv_data); +#endif + + + hook_handler.private = priv_data; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) + retval = input_register_handler(&hook_handler); +#else + input_register_handler(&hook_handler); +#endif + + out: + return retval; +} + +/* + * Execute an ACPI method which return either an integer or nothing + * and that require 0 or 1 numerical argument + * (acpi_evaluate_object wrapper) + */ +static int omnibook_acpi_execute(acpi_handle dev_handle, char *method, const int *param, int *result) +{ + + struct acpi_object_list args_list; + struct acpi_buffer buff; + union acpi_object arg, out_objs[1]; + + if (param) { + args_list.count = 1; + args_list.pointer = &arg; + arg.type = ACPI_TYPE_INTEGER; + arg.integer.value = *param; + } else + args_list.count = 0; + + buff.length = sizeof(out_objs); + buff.pointer = out_objs; + + if (acpi_evaluate_object(dev_handle, method, &args_list, &buff) != AE_OK) { + printk(O_ERR "ACPI method execution failed\n"); + return -EIO; + } + + if (!result) /* We don't care what the method returned here */ + return 0; + + if (out_objs[0].type != ACPI_TYPE_INTEGER) { + printk(O_ERR "ACPI method result is not a number\n"); + return -EINVAL; + } + + *result = out_objs[0].integer.value; + return 0; +} + +/* + * Probe for expected ACPI devices + */ +static int omnibook_acpi_init(const struct omnibook_operation *io_op) +{ + int retval = 0; + acpi_handle dev_handle, method_handle, hci_handle, dis_handle; + int i; + int has_sli = 0; + struct acpi_backend_data *priv_data; + + if (unlikely(acpi_disabled)) { + printk(O_ERR "ACPI is disabled: feature unavailable.\n"); + return -ENODEV; + } + + if (!io_op->backend->data) { + dprintk("Try to init ACPI backend\n"); + mutex_init(&io_op->backend->mutex); + mutex_lock(&io_op->backend->mutex); + kref_init(&io_op->backend->kref); + priv_data = kzalloc(sizeof(struct acpi_backend_data), GFP_KERNEL); + if (!priv_data) { + retval = -ENOMEM; + goto error0; + } + + /* Locate ACPI EC device, acpi_get_handle set dev_handle to NULL if not found */ + for (i = 0; i < ARRAY_SIZE(ec_dev_list); i++) { + if (acpi_get_handle(NULL, ec_dev_list[i], &dev_handle) == AE_OK) { + dprintk("ACPI EC device found\n"); + priv_data->ec_handle = dev_handle; + break; + } + } + + if (!dev_handle) { + printk(O_ERR "Can't get handle on ACPI EC device.\n"); + retval = -ENODEV; + goto error1; + } + + /* Probe for HCI and Display devices only on TSX205 models */ + if (omnibook_ectype & TSX205) { + if (acpi_get_handle(NULL, tsx205_dev_list[0], &hci_handle) == AE_OK) { + dprintk("Toshiba X205 HCI device found\n"); + priv_data->hci_handle = hci_handle; + } + + if (!hci_handle) { + printk(O_ERR "Couldn't get HCI handle.\n"); + retval = -ENODEV; + goto error1; + } + + if (acpi_get_handle(NULL, tsx205_dev_list[1], &dis_handle) == AE_OK) + priv_data->dis_handle = dis_handle; + + if (!dis_handle) { + printk(O_ERR "Couldn't get X205 Display handle.\n"); + retval = -ENODEV; + goto error1; + } + + /* Does the laptop has SLI enabled? */ + omnibook_acpi_execute(dis_handle, (char *)TSX205_SLIVDO_METHOD, NULL, &has_sli); + if (has_sli) + dprintk("Toshiba X205 Display device found (SLI).\n"); + else + dprintk("Toshiba X205 Display device found.\n"); + + priv_data->has_sli = has_sli; + } + + if ((acpi_get_handle( dev_handle, GET_WIRELESS_METHOD, &method_handle) == AE_OK) && + (acpi_get_handle( dev_handle, SET_WIRELESS_METHOD, &method_handle) == AE_OK)) + priv_data->has_antr_antw = 1; + + if (omnibook_ectype & TSX205) { + if ((acpi_get_handle(dis_handle, TSX205_AUTO_DISPLAY_METHOD, &method_handle) == AE_OK) && + (acpi_get_handle(dis_handle, TSX205_AUTO_DISPLAY_METHOD, &method_handle) == AE_OK)) + priv_data->has_doss_dosw = 1; + } else { + if ((acpi_get_handle( dev_handle, GET_DISPLAY_METHOD, &method_handle) == AE_OK) && + (acpi_get_handle( dev_handle, SET_DISPLAY_METHOD, &method_handle) == AE_OK)) + priv_data->has_doss_dosw = 1; + } + + retval = register_input_subsystem(priv_data); + if(retval) + goto error1; + + io_op->backend->data = (void *) priv_data; + + mutex_unlock(&io_op->backend->mutex); + + /* attempt to register Toshiba bluetooth ACPI driver */ + acpi_bus_register_driver(&omnibook_bt_driver); + + dprintk("ACPI backend init OK\n"); + + return 0; + + } else { + dprintk("ACPI backend has already been initialized\n"); + kref_get(&io_op->backend->kref); + return 0; + } + + error1: + kfree(priv_data); + io_op->backend->data = NULL; + error0: + mutex_unlock(&io_op->backend->mutex); + mutex_destroy(&io_op->backend->mutex); + return retval; +} + +static void omnibook_acpi_free(struct kref *ref) +{ + struct omnibook_backend *backend; + struct acpi_backend_data *priv_data; + + backend = container_of(ref, struct omnibook_backend, kref); + priv_data = backend->data; + + dprintk("ACPI backend not used anymore: disposing\n"); + + + dprintk("ptr addr: %p driver name: %s\n",&omnibook_bt_driver, omnibook_bt_driver.name); + acpi_bus_unregister_driver(&omnibook_bt_driver); + + flush_scheduled_work(); + input_unregister_handler(&hook_handler); + input_unregister_device(priv_data->acpi_input_dev); + + mutex_lock(&backend->mutex); + kfree(backend->data); + backend->data = NULL; + mutex_unlock(&backend->mutex); + mutex_destroy(&backend->mutex); +} + +static void omnibook_acpi_exit(const struct omnibook_operation *io_op) +{ + dprintk("Trying to dispose ACPI backend\n"); + kref_put(&io_op->backend->kref, omnibook_acpi_free); +} + +/* forward declaration */ +struct omnibook_backend acpi_backend; + +/* Function taken from toshiba_acpi */ +static acpi_status hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS]) +{ + struct acpi_backend_data *priv_data = acpi_backend.data; + struct acpi_object_list params; + union acpi_object in_objs[HCI_WORDS]; + struct acpi_buffer results; + union acpi_object out_objs[HCI_WORDS + 1]; + acpi_status status; + int i; + + params.count = HCI_WORDS; + params.pointer = in_objs; + for (i = 0; i < HCI_WORDS; ++i) { + in_objs[i].type = ACPI_TYPE_INTEGER; + in_objs[i].integer.value = in[i]; + } + + results.length = sizeof(out_objs); + results.pointer = out_objs; + + status = acpi_evaluate_object(priv_data->hci_handle, (char *)HCI_METHOD, ¶ms, + &results); + if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) { + for (i = 0; i < out_objs->package.count; ++i) { + out[i] = out_objs->package.elements[i].integer.value; + } + } + + return status; +} + +/* + * Set Bluetooth device state using the Toshiba BT device + */ +static int set_bt_status(const struct acpi_backend_data *priv_data, unsigned int state) +{ + int retval = 0; + + if (state) { + retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_ACTIVATE_USB, NULL, NULL); + if (retval) + goto out; + retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_POWER_ON, NULL, NULL); + if (retval) + goto out; + } else { + retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_DISABLE_USB, NULL, NULL); + if (retval) + goto out; + retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_POWER_OFF, NULL, NULL); + if (retval) + goto out; + } + out: + return retval; +} + +static int omnibook_acpi_bt_add(struct acpi_device *device) +{ + int retval; + struct acpi_backend_data *priv_data = acpi_backend.data; + + dprintk("Enabling Toshiba Bluetooth ACPI device.\n"); + strcpy(acpi_device_name(device), TOSHIBA_ACPI_DEVICE_NAME); + strcpy(acpi_device_class(device), TOSHIBA_ACPI_BT_CLASS); + + /* Save handle in backend private data structure. ugly. */ + + mutex_lock(&acpi_backend.mutex); + priv_data->bt_handle = device->handle; + retval = set_bt_status(priv_data, 1); + mutex_unlock(&acpi_backend.mutex); + + return retval; +} + +static int omnibook_acpi_bt_remove(struct acpi_device *device, int type) +{ + int retval; + struct acpi_backend_data *priv_data = acpi_backend.data; + + mutex_lock(&acpi_backend.mutex); + dprintk("Disabling Toshiba Bluetooth ACPI device.\n"); + retval = set_bt_status(priv_data, 0); + priv_data->bt_handle = NULL; + mutex_unlock(&acpi_backend.mutex); + + return retval; +} + +/* + * Get Bluetooth status using the BTST method + */ +static int get_bt_status(const struct acpi_backend_data *priv_data, unsigned int *state) +{ + int retval = 0; + int raw_state; + + if ((retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_STATUS, NULL, &raw_state))) + return retval; + + dprintk("BTST raw_state: %x\n", raw_state); + + *state = BT_EX; + *state |= ((raw_state & TOSH_BT_USB_MASK) && (raw_state & TOSH_BT_POWER_MASK)) ? BT_STA : 0; + + return retval; +} + +/* + * Get the Bluetooth + Wireless status using the ANTR method + * FIXME: what if ANTR and BTST disagree ? we thrust ANTR for now + */ +static int get_wireless_status(const struct acpi_backend_data *priv_data, unsigned int *state) +{ + int retval = 0; + int raw_state; + + if ((retval = omnibook_acpi_execute(priv_data->ec_handle, GET_WIRELESS_METHOD, NULL, &raw_state))) + return retval; + + dprintk("get_wireless raw_state: %x\n", raw_state); + + *state = (raw_state & WLEX_MASK) ? WIFI_EX : 0; + *state |= (raw_state & WLAT_MASK) ? WIFI_STA : 0; + *state |= (raw_state & KLSW_MASK) ? KILLSWITCH : 0; + *state |= (raw_state & BTEX_MASK) ? BT_EX : 0; + *state |= (raw_state & BTAT_MASK) ? BT_STA : 0; + + return retval; +} + +static int get_tsx205_wireless_status(const struct acpi_backend_data *priv_data, unsigned int *state) +{ + int retval = 0; + int raw_state; + u32 in[HCI_WORDS] = { HCI_GET, HCI_RF_CONTROL, 0, HCI_WIRELESS_CHECK, 0, 0 }; + u32 out[HCI_WORDS]; + + hci_raw(in, out); + + /* Now let's check the killswitch */ + if ((retval = omnibook_acpi_execute(priv_data->ec_handle, TSX205_KILLSW_METHOD, NULL, &raw_state))) + return retval; + + dprintk("get_wireless raw_state: %x\n", out[2]); + + *state = ((out[2] & 0xff)) ? WIFI_EX : 0; + *state |= (raw_state) ? WIFI_STA : 0; + *state |= (!raw_state) ? KILLSWITCH : 0; + + /* And finally BT */ + if ((retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_STATUS, NULL, &raw_state))) + return retval; + + *state |= BT_EX; + *state |= ((raw_state & TOSH_BT_USB_MASK) && (raw_state & TOSH_BT_POWER_MASK)) ? BT_STA : 0; + + return retval; +} + +static int omnibook_acpi_get_wireless(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval; + struct acpi_backend_data *priv_data = io_op->backend->data; + + /* use BTST (BT device) if we don't have ANTR/ANTW (EC device) */ + if (omnibook_ectype & TSX205) + retval = get_tsx205_wireless_status(priv_data, state); + else if (priv_data->has_antr_antw) + retval = get_wireless_status(priv_data, state); + else if(priv_data->bt_handle) + retval = get_bt_status(priv_data, state); + else + retval = -ENODEV; + + return retval; +} + +/* + * Set the Bluetooth + Wireless status using the ANTW method + */ +static int set_wireless_status(const struct acpi_backend_data *priv_data, unsigned int state) +{ + int retval; + int raw_state; + + raw_state = !!(state & WIFI_STA); /* bit 0 */ + raw_state |= !!(state & BT_STA) << 0x1; /* bit 1 */ + + dprintk("set_wireless raw_state: %x\n", raw_state); + + retval = omnibook_acpi_execute(priv_data->ec_handle, SET_WIRELESS_METHOD, &raw_state, NULL); + + return retval; +} + +static int set_tsx205_wireless_status(const struct acpi_backend_data *priv_data, unsigned int state) +{ + int retval; + int raw_state = !!(state & WIFI_STA); + + dprintk("set_wireless raw_state: %x\n", raw_state); + + u32 in[HCI_WORDS] = { HCI_SET, HCI_RF_CONTROL, raw_state, HCI_WIRELESS_POWER, 0, 0 }; + u32 out[HCI_WORDS]; + hci_raw(in, out); + + raw_state |= !!(state & BT_STA) << 0x1; /* bit 1 */ + + /* BT status */ + retval = set_bt_status(priv_data->bt_handle, state); + + return retval; +} + +static int omnibook_acpi_set_wireless(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval = -ENODEV; + struct acpi_backend_data *priv_data = io_op->backend->data; + + /* First try the TSX205 methods */ + if(omnibook_ectype & TSX205) + retval = set_tsx205_wireless_status(priv_data, state); + + /* Then try the ANTR/ANTW methods */ + if(priv_data->has_antr_antw) + retval = set_wireless_status(priv_data, state); + + /* Then try the bluetooth ACPI device if present */ + if(priv_data->bt_handle) + retval = set_bt_status(priv_data, (state & BT_STA)); + + return retval; +} + +static int tsx205_get_display(const struct acpi_backend_data *priv_data, unsigned int *state, unsigned int device) +{ + int retval = 0; + int raw_state = 0; + + retval = omnibook_acpi_execute(priv_data->dis_handle, tsx205_video_list[device], NULL, &raw_state); + if (retval < 0) { + dprintk(O_ERR "Failed to get video device (%d) state.\n", device); + return retval; + } + + /* Ugly, but better than nothing... */ + switch (device) { + case 0: + case 4: /* LCD device */ + dprintk("get_display LCD (%d) raw_state: %x\n", device, raw_state); + if (raw_state == TSX205_DSPY_DE) { + *state |= DISPLAY_LCD_DET; + *state |= DISPLAY_LCD_ON; + } else + if (raw_state == TSX205_DSPY_DN) + *state |= DISPLAY_LCD_DET; + else if (raw_state == TSX205_DSPY_NE) + *state |= DISPLAY_LCD_ON; + break; + case 1: + case 5: /* CRT device */ + dprintk("get_display CRT (%d) raw_state: %x\n", device, raw_state); + if (raw_state == TSX205_DSPY_DE) { + *state |= DISPLAY_CRT_DET; + *state |= DISPLAY_CRT_ON; + } else + if (raw_state == TSX205_DSPY_DN) + *state |= DISPLAY_CRT_DET; + else if (raw_state == TSX205_DSPY_NE) + *state |= DISPLAY_CRT_ON; + break; + case 2: + case 6: /* TV-OUT device */ + dprintk("get_display TV-OUT (%d) raw_state: %x\n", device, raw_state); + if (raw_state == TSX205_DSPY_DE) { + *state |= DISPLAY_TVO_DET; + *state |= DISPLAY_TVO_ON; + } else + if (raw_state == TSX205_DSPY_DN) + *state |= DISPLAY_TVO_DET; + else if (raw_state == TSX205_DSPY_NE) + *state |= DISPLAY_TVO_ON; + break; + case 3: + case 7: /* DVI device */ + dprintk("get_display DVI (%d) raw_state: %x\n", device, raw_state); + if (raw_state == TSX205_DSPY_DE) { + *state |= DISPLAY_DVI_DET; + *state |= DISPLAY_DVI_ON; + } else + if (raw_state == TSX205_DSPY_DN) + *state |= DISPLAY_DVI_DET; + else if (raw_state == TSX205_DSPY_NE) + *state |= DISPLAY_DVI_ON; + break; + } + + return retval; +} + +static int omnibook_acpi_get_display(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval = 0; + int raw_state = 0; + struct acpi_backend_data *priv_data = io_op->backend->data; + + if(!priv_data->has_doss_dosw) + return -ENODEV; + + if (omnibook_ectype & TSX205) { + int i; + + /* Loop 'tru the different Video-Out devices */ + if (priv_data->has_sli) + for (i = 4; i < ARRAY_SIZE(tsx205_video_list); i++) + retval = tsx205_get_display(priv_data, state, i); + else + for (i = 0; i < 4; i++) + retval = tsx205_get_display(priv_data, state, i); + + if (retval < 0) + return -EIO; + + goto vidout; + } + + retval = omnibook_acpi_execute(priv_data->ec_handle, GET_DISPLAY_METHOD, NULL, &raw_state); + if (retval < 0) + return retval; + + dprintk("get_display raw_state: %x\n", raw_state); + + /* Backend specific to backend-neutral conversion */ + *state = (raw_state & LCD_CSTE) ? DISPLAY_LCD_ON : 0; + *state |= (raw_state & CRT_CSTE) ? DISPLAY_CRT_ON : 0; + *state |= (raw_state & TVO_CSTE) ? DISPLAY_TVO_ON : 0; + *state |= (raw_state & DVI_CSTE) ? DISPLAY_DVI_ON : 0; + + *state |= (raw_state & LCD_CADL) ? DISPLAY_LCD_DET : 0; + *state |= (raw_state & CRT_CADL) ? DISPLAY_CRT_DET : 0; + *state |= (raw_state & TVO_CADL) ? DISPLAY_TVO_DET : 0; + *state |= (raw_state & DVI_CADL) ? DISPLAY_DVI_DET : 0; + +vidout: + return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON | DISPLAY_DVI_ON + | DISPLAY_LCD_DET | DISPLAY_CRT_DET | DISPLAY_TVO_DET | DISPLAY_DVI_DET; +} + +static const unsigned int acpi_display_mode_list[] = { + DISPLAY_LCD_ON, + DISPLAY_CRT_ON, + DISPLAY_LCD_ON | DISPLAY_CRT_ON, + DISPLAY_TVO_ON, + DISPLAY_LCD_ON | DISPLAY_TVO_ON, + DISPLAY_CRT_ON | DISPLAY_TVO_ON, + DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON, + DISPLAY_DVI_ON, + DISPLAY_LCD_ON | DISPLAY_DVI_ON, +}; + +static int omnibook_acpi_set_display(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval = 0; + int i; + int matched = -1; + struct acpi_backend_data *priv_data = io_op->backend->data; + + if(!priv_data->has_doss_dosw) + return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(acpi_display_mode_list); i++) { + if (acpi_display_mode_list[i] == state) { + matched = i + 1; /* raw state is array row number + 1 */ + break; + } + } + if (matched == -1) { + printk("Display mode %x is unsupported.\n", state); + return -EINVAL; + } + + dprintk("set_display raw_state: %x\n", matched); + + if (omnibook_ectype & TSX205) { + if (priv_data->has_sli) + retval = omnibook_acpi_execute(priv_data->dis_handle, TSX205_SLI_DISPLAY_METHOD, &matched, NULL); + else + retval = omnibook_acpi_execute(priv_data->dis_handle, TSX205_SET_DISPLAY_METHOD, &matched, NULL); + } else + retval = omnibook_acpi_execute(priv_data->ec_handle, SET_DISPLAY_METHOD, &matched, NULL); + if (retval < 0) + return retval; + + return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON | DISPLAY_DVI_ON; +} + +static int omnibook_acpi_get_throttle(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval; + int thtl_en = 0, thtl_dty = 0; + int param; + struct acpi_backend_data *priv_data = io_op->backend->data; + + param = 0; + /* Read THEN aka THTL_EN in ICH6M datasheets */ + retval = omnibook_acpi_execute(priv_data->ec_handle, GET_THROTTLE_METHOD, ¶m, &thtl_en); + if ( thtl_en == 0 ) { + *state = 0; + return retval; + } + param = 1; + /* Read DUTY aka THTL_DTY in ICH6M datasheets */ + retval = omnibook_acpi_execute(priv_data->ec_handle, GET_THROTTLE_METHOD, ¶m, &thtl_dty); + WARN_ON(thtl_dty > 7); /* We shouldn't encounter more than 7 throttling level */ + *state = 8 - thtl_dty; /* THTL_DTY and ACPI T-state are reverse mapped */ + return retval; +} + +static int omnibook_acpi_set_throttle(const struct omnibook_operation *io_op, unsigned int state) +{ + struct acpi_backend_data *priv_data = io_op->backend->data; + /* THTL_DTY and ACPI T-state are reverse mapped */ + /* throttling.c already clamped state between 0 and 7 */ + if (state) + state = 8 - state; + + return omnibook_acpi_execute(priv_data->ec_handle, SET_THROTTLE_METHOD, &state, NULL); +} + +/* + * Fn+foo hotkeys handling + */ +static int omnibook_hci_get_hotkeys(const struct omnibook_operation *io_op, unsigned int *state) +{ + u32 in[HCI_WORDS] = { HCI_GET, HCI_HOTKEY_EVENT, 0, 0, 0, 0 }; + u32 out[HCI_WORDS]; + acpi_status status = hci_raw(in, out); + + if (status != AE_OK) + return HCI_FAILURE; + + dprintk("get_hotkeys raw_state: %x\n", out[2]); + + *state = (out[2] & ACPI_FN_MASK) ? HKEY_FN : 0; + + return 0; +} + +static int omnibook_hci_set_hotkeys(const struct omnibook_operation *io_op, unsigned int state) +{ + u32 in[HCI_WORDS] = { 0, 0, 0, 0, 0, 0 }; + u32 out[HCI_WORDS]; + in[0] = HCI_SET; + in[1] = HCI_HOTKEY_EVENT; + in[2] = (state & HKEY_FN) ? 1 : 0; + acpi_status status = hci_raw(in, out); + + dprintk("set_hotkeys (Fn interface) raw_state: %x\n", in[2]); + + return (status == AE_OK) ? out[0] : HCI_FAILURE; +} + +static int omnibook_acpi_get_events(unsigned int *state) +{ + acpi_status status; + struct acpi_backend_data *priv_data = acpi_backend.data; + + /* We need to call the NTFY method first so it can activate the TECF variable */ + status = omnibook_acpi_execute(priv_data->ec_handle, TSX205_NOTIFY_METHOD, NULL, NULL); + if (status != AE_OK) { + dprintk(O_ERR "Failed to activate NTFY method.\n"); + return -EIO; + } + + /* Now we can poll the INFO method to get last pressed hotkey */ + status = omnibook_acpi_execute(priv_data->hci_handle, TSX205_EVENTS_METHOD, NULL, state); + if (status != AE_OK) { + dprintk(O_ERR "Failed to get Hotkey event.\n"); + return -EIO; + } + + /* We only care about a key press, so just report the Fn key Press/Release */ + if ( ((*state & ~0x80) == 0x100) || ((*state & ~0x80) == 0x17f) ) + *state &= ~0x80; + + return status; +} + +/* + * Adjust the lcd backlight level by delta. + * Used for Fn+F6/F7 keypress + */ +static int adjust_brighness(int delta) +{ + struct omnibook_feature *lcd_feature = omnibook_find_feature("lcd"); + struct omnibook_operation *io_op; + int retval = 0; + u8 brgt; + + if(!lcd_feature) + return -ENODEV; + + io_op = lcd_feature->io_op; + + mutex_lock(&io_op->backend->mutex); + + if(( retval = __backend_byte_read(io_op, &brgt))) + goto out; + + dprintk("Fn-F6/F7 pressed: adjusting brightness.\n"); + + if (((int) brgt + delta) < 0) + brgt = 0; + else if ((brgt + delta) > omnibook_max_brightness) + brgt = omnibook_max_brightness; + else + brgt += delta; + + retval = __backend_byte_write(io_op, brgt); + + out: + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +/* + * Workqueue handler for Fn hotkeys + */ +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)) +static void omnibook_handle_fnkey(struct work_struct *work) +#else +static void omnibook_handle_fnkey(void* data) +#endif +{ + int i; + u32 gen_scan; + struct input_dev *input_dev; + acpi_status status; + + status = omnibook_acpi_get_events(&gen_scan); + if (status != AE_OK) + return; + + dprintk("detected scancode 0x%x.\n", gen_scan); + switch(gen_scan) { + case HCI_BRIGHTNESSDOWN: + adjust_brighness(-1); + break; + case HCI_BRIGHTNESSUP: + adjust_brighness(+1); + break; + } + + for (i = 0 ; i < ARRAY_SIZE(acpi_scan_table); i++) { + if (gen_scan == acpi_scan_table[i].scancode) { + dprintk("generating keycode %i.\n", acpi_scan_table[i].keycode); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)) + input_dev = container_of(work, struct acpi_backend_data, fnkey_work)->acpi_input_dev; +#else + input_dev = ((struct acpi_backend_data *) data)->acpi_input_dev; +#endif + omnibook_report_key(input_dev, acpi_scan_table[i].keycode); + break; + } + } +} + +struct omnibook_backend acpi_backend = { + .name = "acpi", + .hotkeys_read_cap = HKEY_FN, + .hotkeys_write_cap = HKEY_FN, + .init = omnibook_acpi_init, + .exit = omnibook_acpi_exit, + .aerial_get = omnibook_acpi_get_wireless, + .aerial_set = omnibook_acpi_set_wireless, + .display_get = omnibook_acpi_get_display, + .display_set = omnibook_acpi_set_display, + .throttle_get = omnibook_acpi_get_throttle, + .throttle_set = omnibook_acpi_set_throttle, + .hotkeys_get = omnibook_hci_get_hotkeys, + .hotkeys_set = omnibook_hci_set_hotkeys, +}; + +#else /* CONFIG_ACPI */ + +/* dummy backend for non-ACPI systems */ +static int _fail_probe(const struct omnibook_operation *io_op) +{ + return -ENODEV; +} + +struct omnibook_backend acpi_backend = { + .name = "acpi", + .init = _fail_probe, +}; + +#endif /* CONFIG_ACPI */ --- linux-2.6.37.orig/ubuntu/omnibook/battery.c +++ linux-2.6.37/ubuntu/omnibook/battery.c @@ -0,0 +1,557 @@ +/* + * battery.c -- battery related functions + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" +#include "hardware.h" + +struct omnibook_battery_info { + u8 type; /* 1 - Li-Ion, 2 NiMH */ + u16 sn; /* Serial number */ + u16 dv; /* Design Voltage */ + u16 dc; /* Design Capacity */ +}; + +struct omnibook_battery_state { + u16 pv; /* Present Voltage */ + u16 rc; /* Remaining Capacity */ + u16 lc; /* Last Full Capacity */ + u8 gauge; /* Gauge in % */ + u8 status; /* 0 - unknown, 1 - charged, 2 - discharging, 3 - charging, 4 - critical) */ +}; + +enum { + OMNIBOOK_BATTSTAT_UNKNOWN, + OMNIBOOK_BATTSTAT_CHARGED, + OMNIBOOK_BATTSTAT_DISCHARGING, + OMNIBOOK_BATTSTAT_CHARGING, + OMNIBOOK_BATTSTAT_CRITICAL +}; + +#define BAT_OFFSET 0x10 + +static int __backend_u16_read(struct omnibook_operation *io_op, u16 *data) +{ + int retval; + u8 byte; + + retval = __backend_byte_read(io_op, &byte); + if (retval) + return retval; + *data = byte; + io_op->read_addr += 1; + retval = __backend_byte_read(io_op, &byte); + *data += (byte << 8); + return retval; +} + +static int omnibook_battery_present(struct omnibook_operation *io_op, int num) +{ + int retval; + u8 bat; + int i; + + /* + * XE3GF + * TSP10 + * TSM30X + * TSM70 + */ + if (omnibook_ectype & (XE3GF | TSP10 | TSM70 | TSM30X)) { + io_op->read_addr = XE3GF_BAL; + io_op->read_mask = XE3GF_BAL0_MASK; + for (i = 0; i < num; i++) + io_op->read_mask = io_op->read_mask << 1; + retval = __backend_byte_read(io_op, &bat); + /* + * XE3GC + * AMILOD + */ + } else if (omnibook_ectype & (XE3GC | AMILOD)) { + io_op->read_addr = XE3GC_BAT; + io_op->read_mask = XE3GC_BAT0_MASK; + for (i = 0; i < num; i++) + io_op->read_mask = io_op->read_mask << 1; + retval = __backend_byte_read(io_op, &bat); + } else + retval = -ENODEV; + + /* restore default read_mask */ + io_op->read_mask = 0; + + return !!bat; +} + +/* + * Get static battery information + * All info have to be reread every time because battery sould be cahnged + * when laptop is on AC power + * return values: + * < 0 - ERROR + * 0 - OK + * 1 - Battery is not present + * 2 - Not supported + */ +static int omnibook_get_battery_info(struct omnibook_operation *io_op, + int num, + struct omnibook_battery_info *battinfo) +{ + int retval; + /* + * XE3GF + * TSP10 + * TSM70 + * TSM30X + */ + if (omnibook_ectype & (XE3GF | TSP10 | TSM70 | TSM30X)) { + retval = omnibook_battery_present(io_op, num); + if (retval < 0) + return retval; + if (retval) { + io_op->read_addr = XE3GF_BTY0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &(*battinfo).type))) + return retval; + io_op->read_addr = XE3GF_BSN0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).sn))) + return retval; + io_op->read_addr = XE3GF_BDV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dv))) + return retval; + io_op->read_addr = XE3GF_BDC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dc))) + return retval; + + (*battinfo).type = ((*battinfo).type & XE3GF_BTY_MASK) ? 1 : 0; + } else + return 1; + /* + * XE3GC + */ + } else if (omnibook_ectype & (XE3GC)) { + retval = omnibook_battery_present(io_op, num); + if (retval < 0) + return retval; + if (retval) { + io_op->read_addr = XE3GC_BDV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dv))) + return retval; + io_op->read_addr = XE3GC_BDC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dc))) + return retval; + io_op->read_addr = XE3GC_BTY0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &(*battinfo).type))) + return retval; + + (*battinfo).type = ((*battinfo).type & XE3GC_BTY_MASK) ? 1 : 0; + (*battinfo).sn = 0; /* Unknown */ + } else + return 1; + /* + * AMILOD + */ + } else if (omnibook_ectype & (AMILOD)) { + retval = omnibook_battery_present(io_op, num); + if (retval < 0) + return retval; + if (retval) { + io_op->read_addr = AMILOD_BDV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dv))) + return retval; + io_op->read_addr = AMILOD_BDC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dc))) + return retval; + io_op->read_addr = AMILOD_BTY0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &(*battinfo).type))) + return retval; + + (*battinfo).type = ((*battinfo).type & AMILOD_BTY_MASK) ? 1 : 0; + (*battinfo).sn = 0; /* Unknown */ + } else + return 1; + /* + * FIXME + * OB500 + * OB510 + */ + } else if (omnibook_ectype & (OB500 | OB510)) { + switch (num) { + case 0: + case 1: + case 2: + break; + default: + return -EINVAL; + } + /* + * OB6000 + * OB6100 + * XE4500 + */ + } else if (omnibook_ectype & (OB6000 | OB6100 | XE4500)) { + switch (num) { + case 0: + case 1: + break; + default: + return -EINVAL; + } + } else + return 2; + + return 0; +} + +/* + * Get battery status + * return values: + * < 0 - ERROR + * 0 - OK + * 1 - Battery is not present + * 2 - Not supported + */ +static int omnibook_get_battery_status(struct omnibook_operation *io_op, + int num, + struct omnibook_battery_state *battstat) +{ + int retval; + u8 status; + u16 dc; + int gauge; + + /* + * XE3GF + * TSP10 + * TSM70 + */ + if (omnibook_ectype & (XE3GF | TSP10 | TSM70 | TSM30X)) { + retval = omnibook_battery_present(io_op, num); + if (retval < 0) + return retval; + if (retval) { + io_op->read_addr = XE3GF_BST0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &status))) + return retval; + io_op->read_addr = XE3GF_BRC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) + return retval; + io_op->read_addr = XE3GF_BPV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) + return retval; + io_op->read_addr = XE3GF_BFC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).lc))) + return retval; + io_op->read_addr = XE3GF_GAU0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &(*battstat).gauge))) + return retval; + + if (status & XE3GF_BST_MASK_CRT) + (*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL; + else if (status & XE3GF_BST_MASK_CHR) + (*battstat).status = OMNIBOOK_BATTSTAT_CHARGING; + else if (status & XE3GF_BST_MASK_DSC) + (*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING; + else if (status & (XE3GF_BST_MASK_CHR | XE3GF_BST_MASK_DSC)) + (*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN; + else { + (*battstat).status = OMNIBOOK_BATTSTAT_CHARGED; + } + } else + return 1; + /* + * XE3GC + */ + } else if (omnibook_ectype & (XE3GC)) { + retval = omnibook_battery_present(io_op, num); + if (retval < 0) + return retval; + if (retval) { + io_op->read_addr = XE3GC_BST0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &status))) + return retval; + io_op->read_addr = XE3GC_BRC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) + return retval; + io_op->read_addr = XE3GC_BPV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) + return retval; + io_op->read_addr = XE3GC_BDC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &dc))) + return retval; + + if (status & XE3GC_BST_MASK_CRT) + (*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL; + else if (status & XE3GC_BST_MASK_CHR) + (*battstat).status = OMNIBOOK_BATTSTAT_CHARGING; + else if (status & XE3GC_BST_MASK_DSC) + (*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING; + else if (status & (XE3GC_BST_MASK_CHR | XE3GC_BST_MASK_DSC)) + (*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN; + else { + (*battstat).status = OMNIBOOK_BATTSTAT_CHARGED; + } + gauge = ((*battstat).rc * 100) / dc; + (*battstat).gauge = gauge; + (*battstat).lc = 0; /* Unknown */ + } else + return 1; + /* + * AMILOD + */ + } else if (omnibook_ectype & (AMILOD)) { + retval = omnibook_battery_present(io_op, num); + if (retval < 0) + return retval; + if (retval) { + io_op->read_addr = AMILOD_BST0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &status))) + return retval; + io_op->read_addr = AMILOD_BRC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) + return retval; + io_op->read_addr = AMILOD_BPV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) + return retval; + io_op->read_addr = AMILOD_BDC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &dc))) + return retval; + + if (status & AMILOD_BST_MASK_CRT) + (*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL; + else if (status & AMILOD_BST_MASK_CHR) + (*battstat).status = OMNIBOOK_BATTSTAT_CHARGING; + else if (status & AMILOD_BST_MASK_DSC) + (*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING; + else if (status & (AMILOD_BST_MASK_CHR | AMILOD_BST_MASK_DSC)) + (*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN; + else { + (*battstat).status = OMNIBOOK_BATTSTAT_CHARGED; + } + gauge = ((*battstat).rc * 100) / dc; + (*battstat).gauge = gauge; + (*battstat).lc = 0; /* Unknown */ + } else + return 1; + /* + * OB500 + * OB510 + */ + } else if (omnibook_ectype & (OB500 | OB510)) { + switch (num) { + case 0: + io_op->read_addr = OB500_BT1S; + if ((retval = __backend_byte_read(io_op, &status))) + return retval; + io_op->read_addr = OB500_BT1C; + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) + return retval; + io_op->read_addr = OB500_BT1V; + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) + return retval; + break; + case 1: + io_op->read_addr = OB500_BT2S; + if ((retval = __backend_byte_read(io_op, &status))) + return retval; + io_op->read_addr = OB500_BT2C; + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) + return retval; + io_op->read_addr = OB500_BT2V; + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) + return retval; + break; + case 2: + io_op->read_addr = OB500_BT3S; + if ((retval = __backend_byte_read(io_op, &status))) + return retval; + io_op->read_addr = OB500_BT3C; + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) + return retval; + io_op->read_addr = OB500_BT3V; + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) + return retval; + break; + default: + return -EINVAL; + } + if (status & OB500_BST_MASK_CRT) + (*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL; + else if (status & OB500_BST_MASK_CHR) + (*battstat).status = OMNIBOOK_BATTSTAT_CHARGING; + else if (status & OB500_BST_MASK_DSC) + (*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING; + else if (status & (OB500_BST_MASK_CHR | OB500_BST_MASK_DSC)) + (*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN; + else { + (*battstat).status = OMNIBOOK_BATTSTAT_CHARGED; + } + /* + * OB6000 + * OB6100 + * XE4500 + */ + } else if (omnibook_ectype & (OB6000 | OB6100 | XE4500)) { + switch (num) { + case 0: + io_op->read_addr = OB500_BT1S; + if ((retval = __backend_byte_read(io_op, &status))) + return retval; + io_op->read_addr = OB500_BT1C; + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) + return retval; + io_op->read_addr = OB500_BT1V; + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) + return retval; + break; + case 1: + io_op->read_addr = OB500_BT3S; + if ((retval = __backend_byte_read(io_op, &status))) + return retval; + io_op->read_addr = OB500_BT3C; + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) + return retval; + io_op->read_addr = OB500_BT3V; + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) + return retval; + break; + default: + return -EINVAL; + } + if (status & OB500_BST_MASK_CRT) + (*battstat).status = OMNIBOOK_BATTSTAT_CRITICAL; + else if (status & OB500_BST_MASK_CHR) + (*battstat).status = OMNIBOOK_BATTSTAT_CHARGING; + else if (status & OB500_BST_MASK_DSC) + (*battstat).status = OMNIBOOK_BATTSTAT_DISCHARGING; + else if (status & (OB500_BST_MASK_CHR | OB500_BST_MASK_DSC)) + (*battstat).status = OMNIBOOK_BATTSTAT_UNKNOWN; + else { + (*battstat).status = OMNIBOOK_BATTSTAT_CHARGED; + } + } else { + return 2; + } + return 0; +} + +static int omnibook_battery_read(char *buffer, struct omnibook_operation *io_op) +{ + char *statustr; + char *typestr; + int max = 0; + int num = 0; + int len = 0; + int retval; + int i; + struct omnibook_battery_info battinfo; + struct omnibook_battery_state battstat; + /* + * XE3GF + * XE3GC + * 0B6000 + * 0B6100 + * XE4500 + * AMILOD + * TSP10 + */ + if (omnibook_ectype & (XE3GF | XE3GC | OB6000 | OB6100 | XE4500 | AMILOD | TSP10)) + max = 2; + /* + * OB500 + * 0B510 + */ + else if (omnibook_ectype & (OB500 | OB510)) + max = 3; + /* + * TSM30X + * TSM70 + */ + else if (omnibook_ectype & (TSM70 | TSM30X)) + max = 1; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + for (i = 0; i < max; i++) { + retval = omnibook_get_battery_info(io_op, i, &battinfo); + if (retval == 0) { + num++; + omnibook_get_battery_status(io_op, i, &battstat); + typestr = (battinfo.type) ? "Li-Ion" : "NiMH"; + switch (battstat.status) { + case OMNIBOOK_BATTSTAT_CHARGED: + statustr = "charged"; + break; + case OMNIBOOK_BATTSTAT_DISCHARGING: + statustr = "discharging"; + break; + case OMNIBOOK_BATTSTAT_CHARGING: + statustr = "charging"; + break; + case OMNIBOOK_BATTSTAT_CRITICAL: + statustr = "critical"; + break; + default: + statustr = "unknown"; + } + + len += sprintf(buffer + len, "Battery: %11d\n", i); + len += sprintf(buffer + len, "Type: %11s\n", typestr); + if (battinfo.sn) + len += + sprintf(buffer + len, "Serial Number: %11d\n", + battinfo.sn); + len += sprintf(buffer + len, "Present Voltage: %11d mV\n", battstat.pv); + len += sprintf(buffer + len, "Design Voltage: %11d mV\n", battinfo.dv); + len += sprintf(buffer + len, "Remaining Capacity: %11d mAh\n", battstat.rc); + if (battstat.lc) + len += + sprintf(buffer + len, "Last Full Capacity: %11d mAh\n", + battstat.lc); + len += sprintf(buffer + len, "Design Capacity: %11d mAh\n", battinfo.dc); + len += + sprintf(buffer + len, "Gauge: %11d %%\n", battstat.gauge); + len += sprintf(buffer + len, "Status: %11s\n", statustr); + len += sprintf(buffer + len, "\n"); + } + } + if (num == 0) + len += sprintf(buffer + len, "No battery present\n"); + + mutex_unlock(&io_op->backend->mutex); + + return len; +} + +static struct omnibook_tbl battery_table[] __initdata = { + {XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X, {EC,}}, + {0,} +}; + +static struct omnibook_feature __declared_feature battery_driver = { + .name = "battery", +#ifdef CONFIG_OMNIBOOK_LEGACY + .enabled = 1, +#else + .enabled = 0, +#endif + .read = omnibook_battery_read, + .ectypes = XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X, /* FIXME: OB500|OB6000|OB6100|XE4500 */ + .tbl = battery_table, +}; + +module_param_named(battery, battery_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(battery, "Use 0 to disable, 1 to enable battery status monitoring"); +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/blank.c +++ linux-2.6.37/ubuntu/omnibook/blank.c @@ -0,0 +1,138 @@ +/* + * blank.c -- blanking lcd console + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" + +#include +#include "hardware.h" + +static struct omnibook_feature blank_driver; + +/* + * console_blank_hook pointer manipulation is lock protected + */ +extern int (*console_blank_hook) (int); +static DEFINE_SPINLOCK(blank_spinlock); + + +int omnibook_lcd_blank(int blank) +{ + struct omnibook_feature *blank_feature = omnibook_find_feature("blank"); + + if(!blank_feature) + return -ENODEV; + + return omnibook_apply_write_mask(blank_feature->io_op, blank); +} + +static int console_blank_register_hook(void) +{ + spin_lock(&blank_spinlock); + if (console_blank_hook != omnibook_lcd_blank) { + if (console_blank_hook == NULL) { + console_blank_hook = omnibook_lcd_blank; + printk(O_INFO "LCD backlight turn off at console blanking is enabled.\n"); + } else + printk(O_INFO "There is a console blanking solution already registered.\n"); + } + spin_unlock(&blank_spinlock); + return 0; +} + +static int console_blank_unregister_hook(void) +{ + int retval; + spin_lock(&blank_spinlock); + if (console_blank_hook == omnibook_lcd_blank) { + console_blank_hook = NULL; + printk(O_INFO "LCD backlight turn off at console blanking is disabled.\n"); + } else if (console_blank_hook) { + printk(O_WARN "You can not disable another console blanking solution.\n"); + retval = -EBUSY; + } else { + printk(O_INFO "Console blanking already disabled.\n"); + } + spin_unlock(&blank_spinlock); + return retval; +} + +static int omnibook_console_blank_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + + spin_lock(&blank_spinlock); + + len += + sprintf(buffer + len, "LCD console blanking hook is %s\n", + (console_blank_hook == omnibook_lcd_blank) ? "enabled" : "disabled"); + + spin_unlock(&blank_spinlock); + + return len; +} + +static int omnibook_console_blank_write(char *buffer, struct omnibook_operation *io_op) +{ + int retval; + + switch (*buffer) { + case '0': + retval = console_blank_unregister_hook(); + break; + case '1': + retval = console_blank_register_hook(); + break; + default: + retval = -EINVAL; + } + return retval; +} + +static int __init omnibook_console_blank_init(struct omnibook_operation *io_op) +{ + return console_blank_register_hook(); +} + +static void __exit omnibook_console_blank_cleanup(struct omnibook_operation *io_op) +{ + console_blank_unregister_hook(); +} + +static struct omnibook_tbl blank_table[] __initdata = { + {TSM70 | TSX205, {CDI, 0, TSM100_BLANK_INDEX, 0, TSM100_LCD_OFF, TSM100_LCD_ON}}, + {XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X, + COMMAND(KBC, OMNIBOOK_KBC_CMD_LCD_OFF, OMNIBOOK_KBC_CMD_LCD_ON)}, + {OB500 | OB6000 | XE2, {PIO, OB500_GPO1, OB500_GPO1, 0, -OB500_BKLT_MASK, OB500_BKLT_MASK}}, + {OB510 | OB6100, {PIO, OB510_GPO2, OB510_GPO2, 0, -OB510_BKLT_MASK, OB510_BKLT_MASK}}, + {0,} +}; + +static struct omnibook_feature __declared_feature blank_driver = { + .name = "blank", + .enabled = 1, + .read = omnibook_console_blank_read, + .write = omnibook_console_blank_write, + .init = omnibook_console_blank_init, + .exit = omnibook_console_blank_cleanup, + .ectypes = + XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE2 | AMILOD | TSP10 | TSM70 | TSM30X | TSX205, + .tbl = blank_table, +}; + +module_param_named(blank, blank_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(blank, "Use 0 to disable, 1 to enable lcd console blanking"); +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/bluetooth.c +++ linux-2.6.37/ubuntu/omnibook/bluetooth.c @@ -0,0 +1,104 @@ +/* + * wireless.c Bluetooth feature + * + * 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, 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. + * + * Written by Mathieu Bérard , 2006 + * + */ + +#include "omnibook.h" +#include "hardware.h" + +static int omnibook_bt_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + int retval; + unsigned int state; + + if ((retval = backend_aerial_get(io_op, &state))) + return retval; + + len += + sprintf(buffer + len, "Bluetooth adapter is %s", + (state & BT_EX) ? "present" : "absent"); + if (state & BT_EX) + len += sprintf(buffer + len, " and %s", (state & BT_STA) ? "enabled" : "disabled"); + len += sprintf(buffer + len, ".\n"); + return len; + +} + +static int omnibook_bt_write(char *buffer, struct omnibook_operation *io_op) +{ + int retval = 0; + unsigned int state; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + if ((retval = __backend_aerial_get(io_op, &state))) + goto out; + + if (*buffer == '0') + state &= ~BT_STA; + else if (*buffer == '1') + state |= BT_STA; + else { + retval = -EINVAL; + goto out; + } + + retval = __backend_aerial_set(io_op, state); + + out: + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +static struct omnibook_feature bt_driver; + +static int __init omnibook_bt_init(struct omnibook_operation *io_op) +{ + int retval = 0; + unsigned int state; + +/* + * Refuse enabling/disabling a non-existent device + */ + + if ((retval = backend_aerial_get(io_op, &state))) + return retval; + + if (!(state & BT_EX)) + bt_driver.write = NULL; + + return retval; +} + +static struct omnibook_tbl wireless_table[] __initdata = { + {TSM70 | TSA105 | TSX205, {ACPI,}}, /* stubs to select backend */ + {TSM40, {SMI,}}, /* stubs to select backend */ + {0,} +}; + +static struct omnibook_feature __declared_feature bt_driver = { + .name = "bluetooth", + .enabled = 1, + .read = omnibook_bt_read, + .write = omnibook_bt_write, + .init = omnibook_bt_init, + .ectypes = TSM70 | TSM40 | TSA105 | TSX205, + .tbl = wireless_table, +}; + +module_param_named(bluetooth, bt_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(bluetooth, "Use 0 to disable, 1 to enable bluetooth adapter control"); --- linux-2.6.37.orig/ubuntu/omnibook/compal.c +++ linux-2.6.37/ubuntu/omnibook/compal.c @@ -0,0 +1,526 @@ +/* + * compal.c -- EC PIO Command/Data/Index mode low-level access code + * + * 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, 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. + * + * Written by Mathieu Bérard , 2006 + * + */ + +#include "omnibook.h" + +#include +#include +#include +#include + +#include +#include "hardware.h" + +/* + * ATI's IXP PCI-LPC bridge + */ +#define PCI_DEVICE_ID_ATI_SB400 0x4377 + +/* + * PCI Config space regiser + * Laptop with Intel ICH Chipset + * See ICH6M and ICH7M spec + */ +#define INTEL_LPC_GEN1_DEC 0x84 +#define INTEL_LPC_GEN4_DEC 0x90 +#define INTEL_IOPORT_BASE 0xff2c + +/* + * PCI Config space regiser + * Laptop with ATI Chipset + * FIXME Untested, name unknown + */ +#define ATI_LPC_REG 0x4a +#define ATI_IOPORT_BASE 0xfd60 + +/* + *This interface uses 2 ports for command and 1 port for data + *These are relative to the ioport_base address + */ + +#define PIO_PORT_COMMAND1 0x1 +#define PIO_PORT_COMMAND2 0x2 +#define PIO_PORT_DATA 0x3 + +/* + * Private data of this backend + */ +static struct pci_dev *lpc_bridge; /* Southbridge chip ISA bridge/LPC interface PCI device */ +static u32 ioport_base; /* PIO base adress */ +static union { + u16 word; + u32 dword; +} pci_reg_state; /* Saved state of register in PCI config spave */ + +/* + * Possible list of supported southbridges + * Here mostly to implement a more or less clean PCI probing + * Works only because of previous DMI probing. + * Shared with nbsmi backend + */ +const struct pci_device_id lpc_bridge_table[] = { + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_30, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SB400, PCI_ANY_ID, PCI_ANY_ID, 0, 0,}, + {0,}, /* End of list */ +}; + +/* + * Low-level Read function: + * Write a 2-bytes wide command to the COMMAND ports + * Read the result in the DATA port + */ +static unsigned char lowlevel_read(u16 command) +{ + unsigned char data; + outb((command & 0xff00) >> 8, ioport_base + PIO_PORT_COMMAND1); + outb(command & 0x00ff, ioport_base + PIO_PORT_COMMAND2); + data = inb(ioport_base + PIO_PORT_DATA); + return data; +} + +/* + * Low-level Write function: + * Write a 2-bytes wide command to the COMMAND ports + * Write the result in the DATA port + */ +static void lowlevel_write(u16 command, u8 data) +{ + outb((command & 0xff00) >> 8, ioport_base + PIO_PORT_COMMAND1); + outb(command & 0x00ff, ioport_base + PIO_PORT_COMMAND2); + outb(data, ioport_base + PIO_PORT_DATA); +} + +/* + * Probe for a state of the PIO Command/Data/Index interface + * Give some time for the controler to settle in the desired state + * mode significance: + * 0: Waiting for command + * 1,2,3: I am confused FIXME + */ +static int check_cdimode_flag(unsigned int mode) +{ + int i; + int retval; + + /*dprintk("Index mode:");*/ + for (i = 1; i <= 250; i++) { + retval = lowlevel_read(0xfbfc); + /*dprintk_simple(" [%i]", retval);*/ + if (retval == mode) { + /*dprintk_simple(".\n"); + dprintk("Index Mode Ok (%i) after %i iter\n", mode, i);*/ + return 0; + } + udelay(100); + } + printk(O_ERR "check_cdimode_flag timeout.\n"); + return -ETIME; +} + +/* + * Check for conventional default (0xf432) state in Commad ports + */ +static int check_default_state(void) +{ + int i; + + for (i = 1; i <= 250; i++) { + if ((inb(ioport_base + PIO_PORT_COMMAND1) == 0xf4) + && (inb(ioport_base + PIO_PORT_COMMAND2) == 0x32)) + return 0; + udelay(100); + } + printk(O_ERR "check_default_state timeout.\n"); + return -ETIME; +} + +/* + * Enable EC Command/Data/Index PIO Access and then check EC state. + * Enabling is done in PCI config space of the LPC bridge. + * + * Just after Enabling, the EC should be in a precisly defined state: + * - PIO should be in a conventional default state (0xf432 in the Command ports) + * - Command/Data/Index interface waiting for command + * The EC is expected to be in that state prior to any attempt to use the interface. + * + */ +static int enable_cdimode(void) +{ + union { + u16 word; + u32 dword; + } value; + + switch (lpc_bridge->vendor) { + case PCI_VENDOR_ID_INTEL: + switch (lpc_bridge->device) { + case PCI_DEVICE_ID_INTEL_ICH7_0: /* ICH7 */ + case PCI_DEVICE_ID_INTEL_ICH7_1: + case PCI_DEVICE_ID_INTEL_ICH7_30: + case PCI_DEVICE_ID_INTEL_ICH7_31: + case PCI_DEVICE_ID_INTEL_ICH8_4: /* ICH8 */ + pci_read_config_dword(lpc_bridge, INTEL_LPC_GEN4_DEC, &(value.dword)); + pci_reg_state.dword = value.dword; + value.dword = 0x3CFF21; + pci_write_config_dword(lpc_bridge, INTEL_LPC_GEN4_DEC, value.dword); + break; + default: /* All other Intel chipset */ + pci_read_config_word(lpc_bridge, INTEL_LPC_GEN1_DEC, &(value.word)); + pci_reg_state.word = value.word; + value.word = (INTEL_IOPORT_BASE & 0xfff1) | 0x1; + pci_write_config_word(lpc_bridge, INTEL_LPC_GEN1_DEC, value.word); + } + break; + case PCI_VENDOR_ID_ATI: + pci_read_config_dword(lpc_bridge, ATI_LPC_REG, &(value.dword)); + pci_reg_state.dword = value.dword; + value.dword = ((pci_reg_state.dword & 0x7f) | 0x80) << 0x10; + pci_write_config_dword(lpc_bridge, ATI_LPC_REG, value.dword); + break; + default: + BUG(); + } + dprintk("Saved state of PCI register: [%x].\n", pci_reg_state.dword); + + if (check_default_state() || check_cdimode_flag(0)) { + printk(O_ERR "EC state check failure, please report.\n"); + return -EIO; + } + + return 0; + +} + +/* + * Send a write command and associated data code to be written + * Known commands an associated code significance: + * 0xfbfd: Select Index with 'code' ordinal + * 0xfbfe: Set to 'code' a previously selected Index + * 0xfbfc: Set CDI mode flag + */ +static int send_ec_cmd(unsigned int command, u8 code) +{ + lowlevel_write(0xfbfc, 0x2); + lowlevel_write(command, code); + lowlevel_write(0xfbfc, 0x1); + if (check_cdimode_flag(2)) + return -ETIME; + return 0; +} + +/* + * Send a read command + * Known commands an associated code significance: + * 0xfbfe: Read a previously selected Index + * 0xfbfc: Set CDI mode flag + */ +static int read_ec_cmd(unsigned int command, u8 * value) +{ + *value = lowlevel_read(command); + lowlevel_write(0xfbfc, 0x1); + if (check_cdimode_flag(2)) + return -ETIME; + return 0; +} + +/* + * Disable EC Command/Data/Index PIO Access + * Step 1: clear_cdimode + * Send Disable command + * Revert PIO interface to conventional default state (0xf432 in the Command ports) + * Step 2: clear_cdimode_pci + * Disable the interface in the PCI config space of the Southbridge + * These steps are separated due to constrains in error path treatement + */ +static void clear_cdimode(void) +{ + lowlevel_write(0xfbfc, 0x0); + outb(0xf4, ioport_base + PIO_PORT_COMMAND1); + outb(0x32, ioport_base + PIO_PORT_COMMAND2); +} + +static void clear_cdimode_pci(void) +{ + switch (lpc_bridge->vendor) { + case PCI_VENDOR_ID_INTEL: + switch (lpc_bridge->device) { + case PCI_DEVICE_ID_INTEL_ICH7_0: /* ICH7 */ + case PCI_DEVICE_ID_INTEL_ICH7_1: + case PCI_DEVICE_ID_INTEL_ICH7_30: + case PCI_DEVICE_ID_INTEL_ICH7_31: + case PCI_DEVICE_ID_INTEL_ICH8_4: /* ICH8 */ + pci_write_config_dword(lpc_bridge, INTEL_LPC_GEN4_DEC, pci_reg_state.dword); + break; + default: /* All other Intel chipset */ + pci_write_config_word(lpc_bridge, INTEL_LPC_GEN1_DEC, pci_reg_state.word); + } + break; + case PCI_VENDOR_ID_ATI: + pci_write_config_dword(lpc_bridge, ATI_LPC_REG, pci_reg_state.dword); + break; + default: + BUG(); + } +} + +/* + * Try to init the backend + * This function can be called blindly as it use a kref + * to check if the init sequence was already done. + */ +static int omnibook_cdimode_init(const struct omnibook_operation *io_op) +{ + int retval = 0; + int i; + + /* ectypes other than TSM70 have no business with this backend */ + if (!(omnibook_ectype & (TSM70 | TSX205))) + return -ENODEV; + + if (io_op->backend->already_failed) { + dprintk("CDI backend init already failed, skipping.\n"); + return -ENODEV; + } + + if (!lpc_bridge) { + /* Fist use of the backend */ + dprintk("Try to init cdimode\n"); + mutex_init(&io_op->backend->mutex); + mutex_lock(&io_op->backend->mutex); + kref_init(&io_op->backend->kref); + + /* PCI probing: find the LPC Super I/O bridge PCI device */ + for (i = 0; !lpc_bridge && lpc_bridge_table[i].vendor; ++i) + lpc_bridge = + pci_get_device(lpc_bridge_table[i].vendor, lpc_bridge_table[i].device, + NULL); + + if (!lpc_bridge) { + printk(O_ERR "Fail to find a supported LPC I/O bridge, please report\n"); + retval = -ENODEV; + goto error1; + } + + if ((retval = pci_enable_device(lpc_bridge))) { + printk(O_ERR "Unable to enable PCI device.\n"); + goto error2; + } + + switch (lpc_bridge->vendor) { + case PCI_VENDOR_ID_INTEL: + ioport_base = INTEL_IOPORT_BASE; + break; + case PCI_VENDOR_ID_ATI: + ioport_base = ATI_IOPORT_BASE; + break; + default: + BUG(); + } + + if (!request_region(ioport_base, 4, OMNIBOOK_MODULE_NAME)) { + printk(O_ERR "Request I/O region error\n"); + retval = -ENODEV; + goto error2; + } + + /* + * Make an enable-check disable cycle for testing purpose + */ + + retval = enable_cdimode(); + if (retval) + goto error3; + + clear_cdimode(); + clear_cdimode_pci(); + + dprintk("Cdimode init ok\n"); + mutex_unlock(&io_op->backend->mutex); + return 0; + } else { + dprintk("Cdimode has already been initialized\n"); + kref_get(&io_op->backend->kref); + return 0; + } + + error3: + clear_cdimode_pci(); + release_region(ioport_base, 4); + error2: + pci_dev_put(lpc_bridge); + lpc_bridge = NULL; + error1: + io_op->backend->already_failed = 1; + mutex_unlock(&io_op->backend->mutex); + mutex_destroy(&io_op->backend->mutex); + return retval; +} + +static void cdimode_free(struct kref *ref) +{ + struct omnibook_backend *backend; + + dprintk("Cdimode not used anymore: disposing\n"); + + backend = container_of(ref, struct omnibook_backend, kref); + + mutex_lock(&backend->mutex); + pci_dev_put(lpc_bridge); + release_region(ioport_base, 4); + lpc_bridge = NULL; + mutex_unlock(&backend->mutex); + mutex_destroy(&backend->mutex); +} + +static void omnibook_cdimode_exit(const struct omnibook_operation *io_op) +{ + /* ectypes other than TSM70 have no business with this backend */ + BUG_ON(!(omnibook_ectype & (TSM70 | TSX205))); + dprintk("Trying to dispose cdimode\n"); + kref_put(&io_op->backend->kref, cdimode_free); +} + +/* + * Read EC index and write result to value + * 'EC index' here is unrelated to an index in the EC registers + */ +static int omnibook_cdimode_read(const struct omnibook_operation *io_op, u8 * value) +{ + int retval = 0; + + if (!lpc_bridge) + return -ENODEV; + + retval = enable_cdimode(); + if (retval) + goto out; + retval = send_ec_cmd(0xfbfd, (unsigned int)io_op->read_addr); + if (retval) + goto error; + retval = read_ec_cmd(0xfbfe, value); + + if (io_op->read_mask) + *value &= io_op->read_mask; + + error: + clear_cdimode(); + out: + clear_cdimode_pci(); + return retval; +} + +/* + * Write value + * 'EC index' here is unrelated to an index in the EC registers + */ +static int omnibook_cdimode_write(const struct omnibook_operation *io_op, u8 value) +{ + int retval = 0; + + if (!lpc_bridge) + return -ENODEV; + + retval = enable_cdimode(); + if (retval) + goto out; + retval = send_ec_cmd(0xfbfd, (unsigned int)io_op->write_addr); + if (retval) + goto error; + retval = send_ec_cmd(0xfbfe, value); + error: + clear_cdimode(); + out: + clear_cdimode_pci(); + return retval; + +} + +/* + * Fn+foo and multimedia hotkeys handling + */ +static int omnibook_cdimode_hotkeys(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval; + + struct omnibook_operation hotkeys_op = + { CDI, 0, TSM70_FN_INDEX, 0, TSM70_FN_ENABLE, TSM70_FN_DISABLE}; + + /* Fn+foo handling */ + retval = __omnibook_toggle(&hotkeys_op, !!(state & HKEY_FN)); + if (retval < 0) + return retval; + + /* Multimedia keys handling */ + hotkeys_op.write_addr = TSM70_HOTKEYS_INDEX; + hotkeys_op.on_mask = TSM70_HOTKEYS_ENABLE; + hotkeys_op.off_mask = TSM70_HOTKEYS_DISABLE; + retval = __omnibook_toggle(&hotkeys_op, !!(state & HKEY_MULTIMEDIA)); + + return retval; +} + +/* Scan index space, this hard locks my machine */ +#if 0 +static int compal_scan(char *buffer) +{ + int len = 0; + int i, j; + u8 v; + + for (i = 0; i < 255; i += 16) { + for (j = 0; j < 16; j++) { + omnibook_compal_read(i + j, &v); + len += sprintf(buffer + len, "Read index %02x: %02x\n", i + j, v); + mdelay(500); + } + if (j != 16) + break; + } + + return len; +} +#endif + +struct omnibook_backend compal_backend = { + .name = "compal", + .hotkeys_write_cap = HKEY_MULTIMEDIA | HKEY_FN, + .init = omnibook_cdimode_init, + .exit = omnibook_cdimode_exit, + .byte_read = omnibook_cdimode_read, + .byte_write = omnibook_cdimode_write, + .hotkeys_set = omnibook_cdimode_hotkeys, +}; + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/compat.h +++ linux-2.6.37/ubuntu/omnibook/compat.h @@ -0,0 +1,71 @@ +/* + * compat.h -- Older kernel (=> 2.6.11) support + * + * 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, 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. + * + * Written by Mathieu Bérard , 2006 + */ + +#include + +/* + * For compatibility with kernel older than 2.6.16 + * Mutex to Semaphore fallback + */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) +#include +#define DEFINE_MUTEX(lock) DECLARE_MUTEX(lock) +#define mutex_init(lock) init_MUTEX(lock) +#define mutex_lock(lock) down(lock) +#define mutex_lock_interruptible(lock) down_interruptible(lock) +#define mutex_unlock(lock) up(lock) +#define mutex_destroy(lock) do { } while(0) +#else +#include +#endif + +/* + * For compatibility with kernel older than 2.6.14 + */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)) +static void inline *kzalloc(size_t size, int flags) +{ + void *ret = kmalloc(size, flags); + if (ret) + memset(ret, 0, size); + return ret; +} +#endif + +/* + * For compatibility with kernel older than 2.6.11 + */ + +#ifndef DEFINE_SPINLOCK +#define DEFINE_SPINLOCK(s) spinlock_t s = SPIN_LOCK_UNLOCKED +#endif + +/* + * Those kernel don't have ICH7 southbridge pcids + */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)) +#define PCI_DEVICE_ID_INTEL_ICH7_0 0x27b8 +#define PCI_DEVICE_ID_INTEL_ICH7_1 0x27b9 +#define PCI_DEVICE_ID_INTEL_ICH7_30 0x27b0 +#define PCI_DEVICE_ID_INTEL_ICH7_31 0x27bd +#endif + + + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/cooling.c +++ linux-2.6.37/ubuntu/omnibook/cooling.c @@ -0,0 +1,97 @@ +/* + * colling.c -- cooling methods feature + * + * 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, 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. + * + * Written by Mathieu Bérard , 2007 + */ + +#include "omnibook.h" +#include "hardware.h" + +static int omnibook_cooling_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + len += sprintf(buffer + len, "Cooling method : %s\n", + io_op->backend->cooling_state ? "Performance" : "Powersave" ); + + mutex_unlock(&io_op->backend->mutex); + return len; +} + +static int omnibook_cooling_write(char *buffer, struct omnibook_operation *io_op) +{ + int retval = 0; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + + if (*buffer == '0') { + retval = __backend_byte_write(io_op, + TSM70_COOLING_OFFSET + TSM70_COOLING_POWERSAVE); + } else if (*buffer == '1') { + retval = __backend_byte_write(io_op, + TSM70_COOLING_OFFSET + TSM70_COOLING_PERF); + } else { + retval = -EINVAL; + goto out; + } + + /* *buffer is either '0' or '1' here */ + if (!retval) + io_op->backend->cooling_state = *buffer - '0' ; + + mutex_unlock(&io_op->backend->mutex); + + out: + return retval; +} + +static int __init omnibook_cooling_init(struct omnibook_operation *io_op) +{ + mutex_lock(&io_op->backend->mutex); + /* XXX: Assumed default cooling method: performance */ + io_op->backend->cooling_state = TSM70_COOLING_PERF; + mutex_unlock(&io_op->backend->mutex); + return 0; +} + +static void __exit omnibook_cooling_exit(struct omnibook_operation *io_op) +{ + /* Set back cooling method to performance */ + backend_byte_write(io_op, TSM70_COOLING_OFFSET + TSM70_COOLING_PERF); +} + +static struct omnibook_tbl cooling_table[] __initdata = { + {TSM70 | TSX205, {CDI, 0, TSM70_FN_INDEX, 0, 0, 0 }}, + {0,} +}; + +struct omnibook_feature __declared_feature cooling_driver = { + .name = "cooling", + .enabled = 1, + .read = omnibook_cooling_read, + .write = omnibook_cooling_write, + .init = omnibook_cooling_init, + .exit = omnibook_cooling_exit, + .ectypes = TSM70 | TSX205, + .tbl = cooling_table, +}; + +module_param_named(cooling, cooling_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(cooling, "Use 0 to disable, 1 to enable CPU cooling method control"); + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/display.c +++ linux-2.6.37/ubuntu/omnibook/display.c @@ -0,0 +1,114 @@ +/* + * display.c -- External display (LCD,VGA,TV-OUT) feature + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" +#include "hardware.h" + +static const char display_name[][16] = { + "Internal LCD", + "External VGA", + "External TV-OUT", + "External DVI", +}; + +static int omnibook_display_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + int retval; + unsigned int sta, en_mask, det_mask; + + retval = backend_display_get(io_op, &sta); + if (retval < 0) + return retval; + + for (en_mask = DISPLAY_LCD_ON; en_mask <= DISPLAY_DVI_ON; en_mask = en_mask << 1) { + det_mask = en_mask << 4; /* see display masks in omnibook.h */ + if (!(retval & en_mask) && !(retval & det_mask)) + continue; /* not supported */ + len += sprintf(buffer + len, "%s:", display_name[ffs(en_mask) - 1]); + if (retval & det_mask) + len += + sprintf(buffer + len, " display %s", + (sta & det_mask) ? "present" : "absent"); + if (retval & en_mask) + len += + sprintf(buffer + len, " port %s", + (sta & en_mask) ? "enabled" : "disabled"); + len += sprintf(buffer + len, "\n"); + } + + return len; +} + +static int omnibook_display_write(char *buffer, struct omnibook_operation *io_op) +{ + int retval; + unsigned int state; + char *endp; + + state = simple_strtoul(buffer, &endp, 16); + if (endp == buffer) + return -EINVAL; + else + retval = backend_display_set(io_op, state); + + return retval; +} + +static struct omnibook_feature display_driver; + +static int __init omnibook_display_init(struct omnibook_operation *io_op) +{ + int retval; + unsigned int state; + + /* Disable file writing if unsuported by backend */ + if (!io_op->backend->display_set) + display_driver.write = NULL; + + retval = backend_display_get(io_op, &state); + if (retval < 0) + return retval; + else + return 0; +} + +static struct omnibook_tbl display_table[] __initdata = { + {TSM70 | TSX205, {ACPI,}}, + {TSM40, {SMI, SMI_GET_DISPLAY_STATE, SMI_SET_DISPLAY_STATE, 0, 0, 0}}, + {XE3GF | TSP10 | TSM70 | TSM30X | TSM40, SIMPLE_BYTE(EC, XE3GF_STA1, XE3GF_SHDD_MASK)}, + {XE3GC, SIMPLE_BYTE(EC, XE3GC_STA1, XE3GC_CRTI_MASK)}, + {OB500 | OB510 | OB6000 | OB6100 | XE4500, SIMPLE_BYTE(EC, OB500_STA1, OB500_CRTS_MASK)}, + {OB4150, SIMPLE_BYTE(EC, OB4150_STA2, OB4150_CRST_MASK)}, + {0,} +}; + +static struct omnibook_feature __declared_feature display_driver = { + .name = "display", + .enabled = 1, + .init = omnibook_display_init, + .read = omnibook_display_read, + .write = omnibook_display_write, + .ectypes = + XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | OB4150 | TSP10 | TSM70 | TSM30X | + TSM40 | TSX205, + .tbl = display_table, +}; + +module_param_named(display, display_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(display, "Use 0 to disable, 1 to enable display status handling"); +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/dock.c +++ linux-2.6.37/ubuntu/omnibook/dock.c @@ -0,0 +1,84 @@ +/* + * dock.c -- docking station/port replicator support + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" +#include "hardware.h" + +static int omnibook_dock_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + u8 dock; + int retval; + + if ((retval = backend_byte_read(io_op, &dock))) + return retval; + + len += sprintf(buffer + len, "Laptop is %s\n", (dock) ? "docked" : "undocked"); + + return len; +} + +static int omnibook_dock_write(char *buffer, struct omnibook_operation *io_op) +{ + int retval; + + switch (*buffer) { + case '0': + retval = backend_byte_write(io_op, 0); + break; + case '1': + retval = backend_byte_write(io_op, 1); + break; + default: + retval = -EINVAL; + } + + return retval; +} + +static struct omnibook_feature dock_driver; + +static int __init omnibook_dock_init(struct omnibook_operation *io_op) +{ + /* writing is only supported on ectype 13 */ + if(!(omnibook_ectype & TSM40)) + dock_driver.write = NULL; + + return 0; +} + +static struct omnibook_tbl dock_table[] __initdata = { + {XE3GF, SIMPLE_BYTE(EC, XE3GF_CSPR, XE3GF_CSPR_MASK)}, + {OB500 | OB510 | OB6000 | OB6100, SIMPLE_BYTE(EC, OB500_STA1, OB500_DCKS_MASK)}, + {OB4150, SIMPLE_BYTE(EC, OB4150_DCID, 0)}, + {TSM40, {SMI, SMI_GET_DOCK, SMI_SET_DOCK, 0, 0, 0}}, + {0,} +}; + +static struct omnibook_feature __declared_feature dock_driver = { + .name = "dock", + .enabled = 0, + .init = omnibook_dock_init, + .read = omnibook_dock_read, + .write = omnibook_dock_write, + .ectypes = XE3GF | OB500 | OB510 | OB6000 | OB6100 | OB4150 | TSM40, + .tbl = dock_table, +}; + +module_param_named(dock, dock_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(dock, "Use 0 to disable, 1 to enable docking station support"); +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/dump.c +++ linux-2.6.37/ubuntu/omnibook/dump.c @@ -0,0 +1,107 @@ +/* + * dump.c - Raw dump of EC register, stolen from ibm_acpi.c + * + * + * Copyright (C) 2004-2005 Borislav Deianov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "omnibook.h" +#include "hardware.h" + +static u8 ecdump_regs[256]; + +static int ecdump_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + int i, j; + u8 v; + + len += + sprintf(buffer + len, + "EC " " +00 +01 +02 +03 +04 +05 +06 +07" + " +08 +09 +0a +0b +0c +0d +0e +0f\n"); + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + for (i = 0; i < 255; i += 16) { + len += sprintf(buffer + len, "EC 0x%02x:", i); + for (j = 0; j < 16; j++) { + io_op->read_addr = i +j; + if (__backend_byte_read(io_op, &v)) + break; + if (v != ecdump_regs[i + j]) + len += sprintf(buffer + len, " *%02x", v); + else + len += sprintf(buffer + len, " %02x", v); + ecdump_regs[i + j] = v; + } + len += sprintf(buffer + len, "\n"); + if (j != 16) + break; + } + + mutex_unlock(&io_op->backend->mutex); + + /* These are way too dangerous to advertise openly... */ +#if 0 + len += + sprintf(buffer + len, + "commands:\t0x 0x" " ( is 00-ff, is 00-ff)\n"); + len += + sprintf(buffer + len, + "commands:\t0x " " ( is 00-ff, is 0-255)\n"); +#endif + return len; +} + +static int ecdump_write(char *buffer, struct omnibook_operation *io_op) +{ + + int i, v; + + if (sscanf(buffer, "0x%x 0x%x", &i, &v) == 2) { + /* i and v set */ + } else if (sscanf(buffer, "0x%x %u", &i, &v) == 2) { + /* i and v set */ + } else + return -EINVAL; + if (i >= 0 && i < 256 && v >= 0 && v < 256) { + io_op->write_addr = i; + return backend_byte_write(io_op, v); + } else + return -EINVAL; + + return 0; +} + +static struct omnibook_tbl dump_table[] __initdata = { + {ALL_ECTYPES, {EC,}}, + {0,} +}; + +static struct omnibook_feature __declared_feature dump_driver = { + .name = "dump", + .enabled = 0, + .read = ecdump_read, + .write = ecdump_write, + .tbl = dump_table, +}; + +module_param_named(dump, dump_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(dump, "Use 0 to disable, 1 to enable embedded controller register dump support"); +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/ec.c +++ linux-2.6.37/ubuntu/omnibook/ec.c @@ -0,0 +1,188 @@ +/* + * ec.c -- low level functions to access Embedded Controller, + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" + +#include +#include +#include +#include +#include + +#include +#include "hardware.h" + +/* + * Interrupt control + */ + +static DEFINE_SPINLOCK(omnibook_ec_lock); + +/* + * Registers of the embedded controller + */ + +#define OMNIBOOK_EC_DATA 0x62 +#define OMNIBOOK_EC_SC 0x66 + +/* + * Embedded controller status register bits + */ + +#define OMNIBOOK_EC_STAT_OBF 0x01 /* Output buffer full */ +#define OMNIBOOK_EC_STAT_IBF 0x02 /* Input buffer full */ + + +/* + * Embedded controller commands + */ + +#define OMNIBOOK_EC_CMD_READ 0x80 +#define OMNIBOOK_EC_CMD_WRITE 0x81 + +/* + * Wait for embedded controller buffer + */ + +static int omnibook_ec_wait(u8 event) +{ + int timeout = OMNIBOOK_TIMEOUT; + + switch (event) { + case OMNIBOOK_EC_STAT_OBF: + while (!(inb(OMNIBOOK_EC_SC) & event) && timeout--) + mdelay(1); + break; + case OMNIBOOK_EC_STAT_IBF: + while ((inb(OMNIBOOK_EC_SC) & event) && timeout--) + mdelay(1); + break; + default: + return -EINVAL; + } + if (timeout > 0) + return 0; + return -ETIME; +} + +/* + * Read from the embedded controller + * Decide at run-time if we can use the much cleaner ACPI EC driver instead of + * this implementation, this is the case if ACPI has been compiled and is not + * disabled. + */ + +static int omnibook_ec_read(const struct omnibook_operation *io_op, u8 * data) +{ + int retval; + +#ifdef CONFIG_ACPI_EC + if (likely(!acpi_disabled)) { + retval = ec_read((u8) io_op->read_addr, data); + if (io_op->read_mask) + *data &= io_op->read_mask; +// dprintk("ACPI EC read at %lx success %i.\n", io_op->read_addr, retval); + return retval; + } +#endif + spin_lock_irq(&omnibook_ec_lock); + retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF); + if (retval) + goto end; + outb(OMNIBOOK_EC_CMD_READ, OMNIBOOK_EC_SC); + retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF); + if (retval) + goto end; + outb((u8) io_op->read_addr, OMNIBOOK_EC_DATA); + retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_OBF); + if (retval) + goto end; + *data = inb(OMNIBOOK_EC_DATA); + if (io_op->read_mask) + *data &= io_op->read_mask; + end: + spin_unlock_irq(&omnibook_ec_lock); +// dprintk("Custom EC read at %lx success %i.\n", io_op->read_addr, retval); + return retval; +} + +/* + * Write to the embedded controller: + * If OMNIBOOK_LEGACY is set, decide at run-time if we can use the much cleaner + * ACPI EC driver instead of this legacy implementation. + * This is the case if ACPI has been compiled and is not + * disabled. + * If OMNIBOOK_LEGACY is unset, we drop our custoim implementation + */ + +static int omnibook_ec_write(const struct omnibook_operation *io_op, u8 data) +{ + int retval; + +#ifdef CONFIG_ACPI_EC + if (likely(!acpi_disabled)) { + retval = ec_write((u8) io_op->write_addr, data); +// dprintk("ACPI EC write at %lx success %i.\n", io_op->write_addr, retval); + return retval; + } +#endif + + spin_lock_irq(&omnibook_ec_lock); + retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF); + if (retval) + goto end; + outb(OMNIBOOK_EC_CMD_WRITE, OMNIBOOK_EC_SC); + retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF); + if (retval) + goto end; + outb((u8) io_op->write_addr, OMNIBOOK_EC_DATA); + retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF); + if (retval) + goto end; + outb(data, OMNIBOOK_EC_DATA); + end: + spin_unlock_irq(&omnibook_ec_lock); +// dprintk("Custom EC write at %lx success %i.\n", io_op->write_addr, retval); + return retval; +} + +static int omnibook_ec_display(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval; + u8 raw_state; + + retval = __backend_byte_read(io_op, &raw_state); + if (retval < 0) + return retval; + + *state = !!(raw_state) & DISPLAY_CRT_DET; + + return DISPLAY_CRT_DET; +} + +/* + * Backend interface declarations + */ + +struct omnibook_backend ec_backend = { + .name = "ec", + .byte_read = omnibook_ec_read, + .byte_write = omnibook_ec_write, + .display_get = omnibook_ec_display, +}; + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/fan.c +++ linux-2.6.37/ubuntu/omnibook/fan.c @@ -0,0 +1,183 @@ +/* + * fan.c -- fan status/control + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" + +#include +#include +#include "hardware.h" + +static const struct omnibook_operation ctmp_io_op = { EC, XE3GF_CTMP, 0, 0, 0, 0 }; +static const struct omnibook_operation fot_io_op = { EC, XE3GF_FOT, XE3GF_FOT, 0, 0, 0 }; + +static int omnibook_get_fan(struct omnibook_operation *io_op) +{ + u8 fan; + int retval; + + if ((retval = backend_byte_read(io_op, &fan))) + return retval; + + /* + * For most models the reading is a bool + * It as to be inverted on all but OB6000|OB6100|OB4150|AMILOD + * TSP10|XE3GF|TSX205 return an integer + */ + + if (omnibook_ectype & (TSP10 | XE3GF | TSX205)) + retval = fan; + else if (omnibook_ectype & (OB6000 | OB6100 | OB4150 | AMILOD)) + retval = !!fan; + else + retval = !fan; + + return retval; +} + +static int omnibook_fan_on(struct omnibook_operation *io_op) +{ + return omnibook_apply_write_mask(io_op, 1); +} + +static int omnibook_fan_off(struct omnibook_operation *io_op) +{ + int i, retval = 0; + + if (!(omnibook_ectype & (XE3GF | TSP10 | TSX205))) { + retval = omnibook_apply_write_mask(io_op, 0); + return retval; + } else { + /* + * Special handling for XE3GF & TSP10 + */ + u8 fot, temp, fan; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + retval = __backend_byte_read(io_op, &fan); + + /* error or fan is already off */ + if (retval || !fan) + goto out; + + /* now we set FOT to current temp, then reset to initial value */ + if ((retval = __backend_byte_read(&fot_io_op, &fot))) + goto out; + if ((retval = __backend_byte_read(&ctmp_io_op, &temp))) + goto out; + + /* Wait for no longer than 250ms (this is arbitrary). */ + for (i = 0; i < 250; i++) { + __backend_byte_write(&fot_io_op, temp); + mdelay(1); + __backend_byte_read(io_op, &fan); + if (!fan) /* Fan is off */ + break; + } + __backend_byte_write(&fot_io_op, fot); + + if(i == 250 ) { + printk(O_ERR "Attempt to switch off the fan failed.\n"); + retval = -EIO; + } + + out: + mutex_unlock(&io_op->backend->mutex); + } + + + return retval; +} + +static int omnibook_fan_read(char *buffer, struct omnibook_operation *io_op) +{ + int fan; + int len = 0; + char *str; + + fan = omnibook_get_fan(io_op); + if (fan < 0) + return fan; + str = (fan) ? "on" : "off"; + + if (fan > 1) + len += sprintf(buffer + len, "Fan is %s (level %d)\n", str, fan); + else + len += sprintf(buffer + len, "Fan is %s\n", str); + + return len; +} + +static int omnibook_fan_write(char *buffer, struct omnibook_operation *io_op) +{ + int retval; + + switch (*buffer) { + case '0': + retval = omnibook_fan_off(io_op); + break; + case '1': + retval = omnibook_fan_on(io_op); + break; + default: + retval = -EINVAL; + } + return retval; +} + +static struct omnibook_feature fan_driver; + +static int __init omnibook_fan_init(struct omnibook_operation *io_op) +{ + /* + * OB4150 + * XE2 + * AMILOD + * They only support fan reading + */ + if (omnibook_ectype & (OB4150 | XE2 | AMILOD)) + fan_driver.write = NULL; + return 0; +} + +static struct omnibook_tbl fan_table[] __initdata = { + {XE3GF | TSP10 | TSM70 | TSX205, {EC, XE3GF_FSRD, XE3GF_FSRD, 0, XE3GF_FAN_ON_MASK, 0}}, + {OB500, + {PIO, OB500_GPO1, OB500_GPO1, OB500_FAN_OFF_MASK, -OB500_FAN_ON_MASK, OB500_FAN_OFF_MASK}}, + {OB510, + {PIO, OB510_GPIO, OB510_GPIO, OB510_FAN_OFF_MASK, -OB510_FAN_ON_MASK, OB510_FAN_OFF_MASK}}, + {OB6000 | OB6100, + {EC, OB6000_STA1, OB6000_STA1, OB6000_FAN_MASK, OB6000_FAN_MASK, -OB6000_FAN_MASK}}, + {OB4150 | AMILOD, {EC, OB4150_STA1, 0, OB4150_FAN_MASK, 0, 0}}, + {XE2, {PIO, OB500_GPO1, 0, XE2_FAN_MASK, 0, 0}}, + {0,} +}; + +static struct omnibook_feature __declared_feature fan_driver = { + .name = "fan", + .enabled = 1, + .read = omnibook_fan_read, + .write = omnibook_fan_write, + .init = omnibook_fan_init, + .ectypes = XE3GF | OB500 | OB510 | OB6000 | OB6100 | OB4150 | XE2 | AMILOD | TSP10 | TSX205, + .tbl = fan_table, +}; + +module_param_named(fan, fan_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(fan, "Use 0 to disable, 1 to enable fan status monitor and control"); +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/fan_policy.c +++ linux-2.6.37/ubuntu/omnibook/fan_policy.c @@ -0,0 +1,188 @@ +/* + * fan_policy.c -- fan policy support + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" + +#include +#include "hardware.h" + +/* + * Default temperature limits. + * Danger! You may overheat your CPU! + * Do not change these values unless you exactly know what you do. + */ + +#define OMNIBOOK_FAN_LEVELS 8 +#define OMNIBOOK_FAN_MIN 25 /* Minimal value of fan off temperature */ +#define OMNIBOOK_FOT_MAX 75 /* Maximal value of fan off temperature */ +#define OMNIBOOK_FAN_MAX 95 /* Maximal value of fan on temperature */ +#define OMNIBOOK_FOT_DEFAULT 60 /* Default value of fan off temperature */ +#define OMNIBOOK_FAN1_DEFAULT 75 /* Default value of fan on temperature */ +#define OMNIBOOK_FAN2_DEFAULT 85 /* Default value of fan level 2 temperature */ +#define OMNIBOOK_FAN3_DEFAULT 90 /* Default value of fan level 3 temperature */ +#define OMNIBOOK_FAN4_DEFAULT 95 /* Default value of fan level 4 temperature */ +#define OMNIBOOK_FAN5_DEFAULT 95 /* Default value of fan level 5 temperature */ +#define OMNIBOOK_FAN6_DEFAULT 95 /* Default value of fan level 6 temperature */ +#define OMNIBOOK_FAN7_DEFAULT 95 /* Default value of fan level 7 temperature */ + +static const u8 fan_defaults[] = { + OMNIBOOK_FOT_DEFAULT, + OMNIBOOK_FAN1_DEFAULT, + OMNIBOOK_FAN2_DEFAULT, + OMNIBOOK_FAN3_DEFAULT, + OMNIBOOK_FAN4_DEFAULT, + OMNIBOOK_FAN5_DEFAULT, + OMNIBOOK_FAN6_DEFAULT, + OMNIBOOK_FAN7_DEFAULT, +}; + +static int omnibook_get_fan_policy(struct omnibook_operation *io_op, u8 *fan_policy) +{ + int retval ; + int i; + + for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) { + io_op->read_addr = XE3GF_FOT + i; + if ((retval = __backend_byte_read(io_op, &fan_policy[i]))) + return retval; + } + + return 0; +} + +static int omnibook_set_fan_policy(struct omnibook_operation *io_op, const u8 *fan_policy) +{ + int retval; + int i; + + if (fan_policy[0] > OMNIBOOK_FOT_MAX) + return -EINVAL; + + for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) { + if ((fan_policy[i] > fan_policy[i + 1]) + || (fan_policy[i] < OMNIBOOK_FAN_MIN) + || (fan_policy[i] > OMNIBOOK_FAN_MAX)) + return -EINVAL; + } + for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) { + io_op->write_addr = XE3GF_FOT + i; + if ((retval = __backend_byte_write(io_op, fan_policy[i]))) + return retval; + } + + return 0; +} + +static int omnibook_fan_policy_read(char *buffer, struct omnibook_operation *io_op) +{ + int retval; + int len = 0; + u8 i; + u8 fan_policy[OMNIBOOK_FAN_LEVELS]; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + retval = omnibook_get_fan_policy(io_op, &fan_policy[0]); + + mutex_unlock(&io_op->backend->mutex); + + if(retval) + return retval; + + len += sprintf(buffer + len, "Fan off temperature: %2d C\n", fan_policy[0]); + len += sprintf(buffer + len, "Fan on temperature: %2d C\n", fan_policy[1]); + for (i = 2; i < OMNIBOOK_FAN_LEVELS; i++) { + len += + sprintf(buffer + len, "Fan level %1d temperature: %2d C\n", i, + fan_policy[i]); + } + len += sprintf(buffer + len, "Minimal temperature to set: %2d C\n", OMNIBOOK_FAN_MIN); + len += sprintf(buffer + len, "Maximal temperature to set: %2d C\n", OMNIBOOK_FAN_MAX); + + return len; +} + +static int omnibook_fan_policy_write(char *buffer, struct omnibook_operation *io_op) +{ + int n = 0; + char *b; + char *endp; + int retval; + int temp; + u8 fan_policy[OMNIBOOK_FAN_LEVELS]; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + if ((retval = omnibook_get_fan_policy(io_op, &fan_policy[0]))) + goto out; + + /* + * Could also be done much simpler using sscanf(,"%u %u ... + * but this would hardcode OMNIBOOK_FAN_LEVELS. + * The parsed format is "%u " repeated OMNIBOOK_FAN_LEVELS+1 times + */ + + b = buffer; + do { + dprintk("n=[%i] b=[%s]\n", n, b); + if (n > OMNIBOOK_FAN_LEVELS) { + retval = -EINVAL; + goto out; + } + if (!isspace(*b)) { + temp = simple_strtoul(b, &endp, 10); + if (endp != b) { /* there was a match */ + fan_policy[n++] = temp; + b = endp; + } else { + retval = -EINVAL; + goto out; + } + } else + b++; + } while ((*b != '\0') && (*b != '\n')); + + /* A zero value set the defaults */ + if ((fan_policy[0] == 0) && (n == 1)) + retval = omnibook_set_fan_policy(io_op, &fan_defaults[0]); + else + retval = omnibook_set_fan_policy(io_op, &fan_policy[0]); + + out: + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +static struct omnibook_tbl fan_policy_table[] __initdata = { + {XE3GF, {EC,}}, + {0,} +}; + +static struct omnibook_feature __declared_feature fan_policy_driver = { + .name = "fan_policy", + .enabled = 1, + .read = omnibook_fan_policy_read, + .write = omnibook_fan_policy_write, + .ectypes = XE3GF, + .tbl = fan_policy_table, +}; + +module_param_named(fan_policy, fan_policy_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(fan_policy, "Use 0 to disable, 1 to enable fan control policy support"); +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/hardware.h +++ linux-2.6.37/ubuntu/omnibook/hardware.h @@ -0,0 +1,582 @@ +/* + * hardware.h -- low level definitions to access Embedded Controller and co. + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006-2007 + */ + +#include +#include "compat.h" + +/* + * Quite ugly: + * on_mask and off_maks are also used to store the i8042 data for kbc backend. + * an union seemed overkilled + */ + +struct omnibook_backend; + +struct omnibook_operation { + struct omnibook_backend *backend; + unsigned long read_addr; /* address for data reading */ + unsigned long write_addr; /* address for data writing */ + u8 read_mask; /* read mask */ + int on_mask; /* mask to set (pos value) or unset (neg value) to put feature in on state */ + int off_mask; /* mask to set (pos value) or unset (neg value) to put feature in off state */ +}; + +#define COMMAND(backend,data_on,data_off) { backend, 0, 0, 0, data_on, data_off } +#define SIMPLE_BYTE(backend,addr,mask) { backend, addr, addr, mask, 0, 0 } + +struct omnibook_tbl { + enum omnibook_ectype_t ectypes; + struct omnibook_operation io_op; +}; + +/* + * Backend interface definition + */ + +struct omnibook_backend { + const char *name; /* backend name */ + struct mutex mutex; /* serializes all access to backend functions */ + const unsigned int hotkeys_read_cap; /* hotkey probing mask */ + const unsigned int hotkeys_write_cap; /* hotkey setting mask */ + + /* Public data fields, access with mutex held */ + unsigned int hotkeys_state; /* saved hotkeys state */ + unsigned int touchpad_state; /* saved touchpad state */ + unsigned int muteled_state; /* saved muteled state */ + unsigned int cooling_state; /* saved cooling method state */ + + /* Public function pointers */ + int (*init) (const struct omnibook_operation *); + void (*exit) (const struct omnibook_operation *); + int (*byte_read) (const struct omnibook_operation *, u8 *); + int (*byte_write) (const struct omnibook_operation *, u8); + int (*aerial_get) (const struct omnibook_operation *, unsigned int *); + int (*aerial_set) (const struct omnibook_operation *, unsigned int); + int (*hotkeys_get) (const struct omnibook_operation *, unsigned int *); + int (*hotkeys_set) (const struct omnibook_operation *, unsigned int); + int (*display_get) (const struct omnibook_operation *, unsigned int *); + int (*display_set) (const struct omnibook_operation *, unsigned int); + int (*throttle_get) (const struct omnibook_operation *, unsigned int *); + int (*throttle_set) (const struct omnibook_operation *, unsigned int); + + /* Private fields, never to be accessed outside backend code */ + struct kref kref; /* Reference counter of this backend */ + void *data; /* private data pointer */ + int already_failed; /* Backend init already failed at least once */ +}; + +extern struct omnibook_backend kbc_backend; +extern struct omnibook_backend pio_backend; +extern struct omnibook_backend ec_backend; +extern struct omnibook_backend acpi_backend; +extern struct omnibook_backend nbsmi_backend; +extern struct omnibook_backend compal_backend; + +#define KBC &kbc_backend +#define PIO &pio_backend +#define EC &ec_backend +#define ACPI &acpi_backend +#define SMI &nbsmi_backend +#define CDI &compal_backend + +int __omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle); +int __omnibook_toggle(const struct omnibook_operation *io_op, int toggle); + +/* + * Lock helper functions. Defines locking and __prefixed non locking variants. + */ + +#define helper_func(func) \ +static inline int backend_##func##_get(const struct omnibook_operation *io_op, unsigned int *data) \ +{ \ + int retval; \ + if(mutex_lock_interruptible(&io_op->backend->mutex)) \ + return -ERESTARTSYS; \ + retval = io_op->backend->func##_get(io_op, data); \ + mutex_unlock(&io_op->backend->mutex); \ + return retval; \ +} \ +static inline int backend_##func##_set(const struct omnibook_operation *io_op, unsigned int data) \ +{ \ + int retval; \ + if(mutex_lock_interruptible(&io_op->backend->mutex)) \ + return -ERESTARTSYS; \ + retval = io_op->backend->func##_set(io_op, data); \ + mutex_unlock(&io_op->backend->mutex); \ + return retval; \ +}\ +static inline int __backend_##func##_get(const struct omnibook_operation *io_op, unsigned int *data) \ +{ \ + int retval; \ + WARN_ON(!mutex_is_locked(&io_op->backend->mutex)); \ + retval = io_op->backend->func##_get(io_op, data); \ + return retval; \ +} \ +static inline int __backend_##func##_set(const struct omnibook_operation *io_op, unsigned int data) \ +{ \ + int retval; \ + WARN_ON(!mutex_is_locked(&io_op->backend->mutex)); \ + retval = io_op->backend->func##_set(io_op, data); \ + return retval; \ +} + +helper_func(aerial) +helper_func(hotkeys) +helper_func(display) +helper_func(throttle) + +static inline int backend_byte_read(const struct omnibook_operation *io_op, u8 *data) +{ + int retval; + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + retval = io_op->backend->byte_read(io_op, data); + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +static inline int backend_byte_write(const struct omnibook_operation *io_op, u8 data) +{ + int retval; + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + retval = io_op->backend->byte_write(io_op, data); + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +static inline int __backend_byte_read(const struct omnibook_operation *io_op, u8 *data) +{ + int retval; + WARN_ON(!mutex_is_locked(&io_op->backend->mutex)); + retval = io_op->backend->byte_read(io_op, data); + return retval; +} + +static inline int __backend_byte_write(const struct omnibook_operation *io_op, u8 data) +{ + int retval; + WARN_ON(!mutex_is_locked(&io_op->backend->mutex)); + retval = io_op->backend->byte_write(io_op, data); + return retval; +} + +static inline int omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle) +{ + int retval; + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + retval = __omnibook_apply_write_mask(io_op, toggle); + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +static inline int omnibook_toggle(const struct omnibook_operation *io_op, int toggle) +{ + int retval; + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + retval = __omnibook_toggle(io_op, toggle); + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +/* + * Timeout in ms for sending to controller + */ + +#define OMNIBOOK_TIMEOUT 250 + + +/* + * Embedded controller adresses + */ + +#define XE3GF_CHGM 0x90 /* , 16 bit */ +#define XE3GF_CHGS 0x92 /* , 16 bit */ +#define XE3GF_CHGC 0x94 /* Current charge of board, 16 bit */ +#define XE3GF_CHGV 0x96 /* Current voltage, 16 bit */ +#define XE3GF_CHGA 0x98 /* Current intensity, 16 bit */ +#define XE3GF_BAL 0x9A /* Battery present status */ +#define XE3GF_STA1 0x9C /* Various status bits */ +#define XE3GF_CSPR 0xA1 /* Port replicator status, 1 bit */ +#define XE3GF_ADP 0xA3 /* AC acapter status, 1 bit */ +#define XE3GF_FOT 0xA5 /* Fan off temperature, 8 bit */ +#define XE3GF_FSD1 0xA6 /* Fan on temperature, 8 bit */ +#define XE3GF_FSD2 0xA7 /* Fan level 2 temperature, 8 bit */ +#define XE3GF_FSD3 0xA8 /* Fan level 3 temperature, 8 bit */ +#define XE3GF_FSD4 0xA9 /* Fan level 4 temperature, 8 bit */ +#define XE3GF_FSD5 0xAA /* Fan level 5 temperature, 8 bit */ +#define XE3GF_FSD6 0xAB /* Fan level 6 temperature, 8 bit */ +#define XE3GF_FSD7 0xAC /* Fan level 7 temperature, 8 bit */ +#define XE3GF_FSRD 0xAD /* Fan status, 8 bit */ +#define XE3GF_CTMP 0xB0 /* CPU tempetature, 8 bit */ +#define XE3GF_BRTS 0xB9 /* LCD brightness, 4 bit */ +#define XE3GF_BTY0 0xC0 /* Battery 0 type, 1 bit */ +#define XE3GF_BST0 0xC1 /* Battery 0 status, 3 bit */ +#define XE3GF_BRC0 0xC2 /* Battery 0 remaining capacity, 16 bit */ +#define XE3GF_BSN0 0xC4 /* Battery 0 serial number 16 bit */ +#define XE3GF_BPV0 0xC6 /* Battery 0 present voltage, 16 bit */ +#define XE3GF_BDV0 0xC8 /* Battery 0 design voltage 16 bit */ +#define XE3GF_BDC0 0xCA /* Battery 0 design capacity 16 bit */ +#define XE3GF_BFC0 0xCC /* Battery 0 last full capacity 16 bit */ +#define XE3GF_GAU0 0xCE /* Battery 0 gauge, 8 bit */ +#define XE3GF_BTY1 0xD0 /* Battery 1 type, 1 bit */ +#define XE3GF_BST1 0xD1 /* Battery 1 status, 3 bit */ +#define XE3GF_BRC1 0xD2 /* Battery 1 remaining capacity, 16 bit */ +#define XE3GF_BSN1 0xD4 /* Battery 1 serial number, 16 bit */ +#define XE3GF_BPV1 0xD6 /* Battery 1 present voltage, 16 bit */ +#define XE3GF_BDV1 0xD8 /* Battery 1 design voltage 16 bit */ +#define XE3GF_BDC1 0xDA /* Battery 1 design capacity 16 bit */ +#define XE3GF_BFC1 0xDC /* Battery 1 last full capacity 16 bit */ +#define XE3GF_GAU1 0xDE /* Battery 1 gauge, 8 bit */ + +/* + * Bitmasks for sub byte values + */ + +#define XE3GF_SHDD_MASK 0x40 /* External display status */ +#define XE3GF_CSPR_MASK 0x01 /* Port replicator status */ +#define XE3GF_ADP_MASK 0x20 /* AC acapter status */ +#define XE3GF_BAL0_MASK 0x01 /* Battery 0 present */ +#define XE3GF_BAL1_MASK 0x02 /* Battery 1 present */ +#define XE3GF_BMF_MASK 0x70 /* Model code */ +#define XE3GF_BTY_MASK 0x80 /* Type: Ni-MH or Li-Ion */ +#define XE3GF_BST_MASK_DSC 0x01 /* Discarging */ +#define XE3GF_BST_MASK_CHR 0x02 /* Charging */ +#define XE3GF_BST_MASK_CRT 0x04 /* Critical */ +#define XE3GF_FSRD_MASK_S1 0x01 /* Fan level 1 */ +#define XE3GF_FSRD_MASK_S2 0x02 /* Fan level 2 */ +#define XE3GF_FSRD_MASK_S3 0x04 /* Fan level 3 */ +#define XE3GF_FSRD_MASK_S4 0x08 /* Fan level 4 */ +#define XE3GF_FSRD_MASK_S5 0x10 /* Fan level 5 */ +#define XE3GF_FSRD_MASK_S6 0x20 /* Fan level 6 */ +#define XE3GF_FSRD_MASK_S7 0x40 /* Fan level 7 */ +#define XE3GF_BRTS_MASK 0x0F /* LCD brightness */ +#define XE3GF_FAN_ON_MASK 0x02 /* Fan on */ + +/* + * OmniBook XE3 GC values + */ + +#define XE3GC_CTMP 0x28 /* CPU tempetature, 8 bit */ +#define XE3GC_STA1 0x30 /* Various status bits */ +#define XE3GC_Q0A 0x31 /* Various status bits */ +#define XE3GC_CCUR 0x38 /* Current charge of board, 16 bit ? */ +#define XE3GC_CVOL 0x3A /* Current voltage, 16 bit ? */ +#define XE3GC_CARM 0x3C /* Current intensity, 16 bit ? */ +#define XE3GC_BAT 0x3E /* Battery present status */ +#define XE3GC_BST0 0x40 /* Battery 0 status, 3 bit */ +#define XE3GC_BPR0 0x41 /* Battery 0 present rate, 16 bit ? */ +#define XE3GC_BRC0 0x43 /* Battery 0 remaining capacity, 16 bit */ +#define XE3GC_BPV0 0x45 /* Battery 0 present voltage, 16 bit */ +#define XE3GC_BDV0 0x47 /* Battery 0 design voltage 16 bit */ +#define XE3GC_BDC0 0x49 /* Battery 0 design capacity 16 bit */ +#define XE3GC_BTY0 0x4A /* Battery 0 type, 1 bit ? */ +#define XE3GC_BTP0 0x4B /* Battery 0 ?, 1 bit */ +#define XE3GC_BSN0 0x4C /* Battery 0 serial number, 8 bit ? */ +#define XE3GC_BMF0 0x4D /* Battery 0 ?,8 bit */ +#define XE3GC_BST1 0x50 /* Battery 1 status, 3 bit */ +#define XE3GC_BPR1 0x51 /* Battery 1 present rate, 16 bit ? */ +#define XE3GC_BRC1 0x53 /* Battery 1 remaining capacity, 16 bit */ +#define XE3GC_BPV1 0x55 /* Battery 1 present voltage, 16 bit */ +#define XE3GC_BDV1 0x57 /* Battery 1 design voltage 16 bit */ +#define XE3GC_BDC1 0x59 /* Battery 1 design capacity 16 bit */ +#define XE3GC_BTY1 0x5A /* Battery 1 type, 1 bit ? */ +#define XE3GC_BTP1 0x5B /* Battery 1 ?, 1 bit */ +#define XE3GC_BSN1 0x5C /* Battery 1 serial number, 8 bit ? */ +#define XE3GC_BMF1 0x5D /* Battery 1 ?,8 bit */ +#define XE3GC_STA2 0x61 /* Various status bits */ +#define XE3GC_BTVL 0x6A /* LCD brightness, 4 bit */ + +/* + * Bitmasks for sub byte values + */ + +#define XE3GC_ADP_MASK 0x40 /* AC acapter status */ +#define XE3GC_BAT0_MASK 0x01 /* Battery 0 present */ +#define XE3GC_BAT1_MASK 0x02 /* Battery 1 present */ +#define XE3GC_BTY_MASK 0x01 /* Type: Ni-MH or Li-Ion */ +#define XE3GC_BST_MASK_DSC 0x01 /* Discarging */ +#define XE3GC_BST_MASK_CHR 0x02 /* Charging */ +#define XE3GC_BST_MASK_CRT 0x04 /* Critical */ +#define XE3GC_CRTI_MASK 0x04 /* External display status */ +#define XE3GC_SLPB_MASK 0x01 /* Sleep button pressed */ +#define XE3GC_F5_MASK 0x02 /* Fn-F5 - LCD/CRT switch pressed */ +#define XE3GC_VOLD_MASK 0x04 /* Fn-down arrow or Volume down pressed */ +#define XE3GC_VOLU_MASK 0x08 /* Fn-up arrow or Volume up pressed */ +#define XE3GC_MUTE_MASK 0x10 /* Fn+F7 - Volume mute pressed */ +#define XE3GC_CNTR_MASK 0x20 /* Fn+F3/Fn+F4 - Contrast up or down pressed */ +#define XE3GC_BRGT_MASK 0x40 /* Fn+F1/Fn+F2 - Brightness up or down pressed */ +#define XE3GC_BTVL_MASK 0x0F /* LCD brightness */ + +/* + * Toshiba Satellite A105 values and mask + */ + +#define A105_BNDT 0xA3 /* LCD brightness */ +#define A105_BNDT_MASK 0x0F + +/* + * Fujitsu Amilo D values + */ + +#define AMILOD_TMP 0x28 /* CPU tempetature, 8 bit */ +#define AMILOD_STA1 0x30 /* Various status bits */ +#define AMILOD_BAT 0x3E /* Battery present status */ +#define AMILOD_BDC0 0x40 /* Battery 0 design capacity 16 bit */ +#define AMILOD_BDV0 0x42 /* Battery 0 design voltage 16 bit */ +#define AMILOD_BTY0 0x44 /* Battery 0 type, 1 bit ? */ +#define AMILOD_BST0 0x45 /* Battery 0 status, 3 bit */ +#define AMILOD_BPR0 0x46 /* Battery 0 present rate, 16 bit ? */ +#define AMILOD_BRC0 0x48 /* Battery 0 remaining capacity, 16 bit */ +#define AMILOD_BPV0 0x4A /* Battery 0 present voltage, 16 bit */ +#define AMILOD_BTP0 0x4C /* Battery 0 ?, 1 bit */ +#define AMILOD_BDC1 0x50 /* Battery 1 design capacity 16 bit */ +#define AMILOD_BDV1 0x52 /* Battery 1 design voltage 16 bit */ +#define AMILOD_BTY1 0x54 /* Battery 1 type, 1 bit ? */ +#define AMILOD_BST1 0x55 /* Battery 1 status, 3 bit */ +#define AMILOD_BPR1 0x56 /* Battery 1 present rate, 16 bit ? */ +#define AMILOD_BRC1 0x58 /* Battery 1 remaining capacity, 16 bit */ +#define AMILOD_BPV1 0x5A /* Battery 1 present voltage, 16 bit */ +#define AMILOD_BTP1 0x5C /* Battery 1 ?, 1 bit */ +#define AMILOD_CBRG 0x6F /* LCD brightness, 4 bit */ + +/* + * Bitmasks for sub byte values + */ + +#define AMILOD_ADP_MASK 0x40 /* AC acapter status */ +#define AMILOD_BAT0_MASK 0x01 /* Battery 0 present */ +#define AMILOD_BAT1_MASK 0x02 /* Battery 1 present */ +#define AMILOD_BTY_MASK 0x01 /* Type: Ni-MH or Li-Ion */ +#define AMILOD_BST_MASK_DSC 0x01 /* Discarging */ +#define AMILOD_BST_MASK_CHR 0x02 /* Charging */ +#define AMILOD_BST_MASK_CRT 0x04 /* Critical */ +#define AMILOD_CBRG_MASK 0x0F /* LCD brightness */ + +/* + * OmniBook 500, 510, 6000, 6100, XE2 values + */ + +#define OB500_STA1 0x44 /* Various status bits */ +#define OB500_STA2 0x50 /* Various status bits */ +#define OB500_CTMP 0x55 /* CPU tempetature, 8 bit */ +#define OB500_BT1I 0x58 /* Battery 1 ? 16 bit */ +#define OB500_BT1C 0x5A /* Battery 1 remaining capacity 16 bit ? */ +#define OB500_BT1V 0x5C /* Battery 1 present voltage 16 bit ? */ +#define OB500_BT1S 0x5E /* Battery 1 status 3 bit ? */ +#define OB500_BT2I 0x6A /* Battery 2 ? 16 bit */ +#define OB500_BT2C 0x6C /* Battery 2 remaining capacity 16 bit ? */ +#define OB500_BT2V 0x6E /* Battery 2 present voltage 16 bit ? */ +#define OB500_BT2S 0x70 /* Battery 2 status 3 bit ? */ +#define OB500_BT3I 0x5F /* Battery 3 ? 16 bit */ +#define OB500_BT3C 0x61 /* Battery 3 remaining capacity 16 bit ? */ +#define OB500_BT3V 0x63 /* Battery 3 present voltage 16 bit ? */ +#define OB500_BT3S 0x65 /* Battery 3 status 3 bit ? */ + +#define OB6000_STA1 0x77 /* Various status bits */ + +#define XE2_STA1 0x50 /* Various status bits */ + +/* + * Bitmasks for sub byte values + */ + +#define OB500_LIDS_MASK 0x01 /* LID status */ +#define OB500_CRTS_MASK 0x20 /* External display status */ +#define OB500_SLPS_MASK 0x40 /* Sleep button status */ +#define OB500_DCKS_MASK 0x80 /* Docking status */ +#define OB500_ADP_MASK 0x02 /* AC acapter status */ +#define OB500_BST_MASK_DSC 0x01 /* Discarging */ +#define OB500_BST_MASK_CHR 0x02 /* Charging */ +#define OB500_BST_MASK_CRT 0x04 /* Critical */ + +#define OB6000_FAN_MASK 0x10 /* Fan status */ + +#define XE2_ADP_MASK 0x02 /* AC acapter status */ + +/* + * OmniBook 4150 + */ + +#define OB4150_TMP 0x28 /* CPU tempetature, 8 bit */ +#define OB4150_STA1 0x2E /* Various status bits */ +#define OB4150_STA2 0x2F /* Various status bits */ +#define OB4150_ADP 0x30 /* AC acapter status, 1 bit */ +#define OB4150_DCID 0x2C /* Port replicator */ + +/* + * Bitmasks for sub byte values + */ + +#define OB4150_FAN_MASK 0x01 /* Fan status */ +#define OB4150_ADP_MASK 0x40 /* AC acapter status */ +#define OB4150_CRST_MASK 0x20 /* External display status */ + +/* + * Keyboard controller command for some laptop functions + */ + +#define OMNIBOOK_KBC_CONTROL_CMD 0x59 + +/* + * Keyboard controller command parameters for functions available via kbc + */ + +#define OMNIBOOK_KBC_CMD_ONETOUCH_ENABLE 0x90 /* Enables OneTouch buttons */ +#define OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE 0x91 /* Disables OneTouch buttons */ +#define OMNIBOOK_KBC_CMD_TOUCHPAD_ENABLE 0xAA /* Enables touchpad */ +#define OMNIBOOK_KBC_CMD_TOUCHPAD_DISABLE 0xA9 /* Disables touchpad */ +#define OMNIBOOK_KBC_CMD_LCD_ON 0xE1 /* Turns LCD display on */ +#define OMNIBOOK_KBC_CMD_LCD_OFF 0xE2 /* Turns LCD display off */ +#define OMNIBOOK_KBC_CMD_MUTELED_ON 0x94 /* Turns (xe4500) Mute LED on */ +#define OMNIBOOK_KBC_CMD_MUTELED_OFF 0x95 /* Turns (xe4500) Mute LED off */ +#define OMNIBOOK_KBC_CMD_AC_POWER_ENABLE 0xC2 /* Enable AC power */ +#define OMNIBOOK_KBC_CMD_AC_POWER_DISABLE 0xC1 /* Disable AC power */ + +/* + * Other I/O ports + */ + +#define ACL00_AC_STAT 0x11B9 /* AC adapter status on ACL00 */ +#define ACL00_AC_MASK 0x04 /* Bitmask for AC adapter status on ACL00 */ +#define TOSH3K_AC_STAT 0x102D /* AC adapter status on Toshiba 3000 */ +#define TOSH3K_AC_MASK 0x08 /* Bitmask for AC adapter status on Toshiba 3000 */ +#define XE3GF_AC_STAT 0x11B9 /* AC adapter status on XE3 GF */ +#define XE3GF_AC_MASK 0x04 /* Bitmask for AC adapter status on XE3 GF */ +#define XE3GF_LID_STAT 0x11AD /* LID switch status on XE3 GF */ +#define XE3GF_LID_MASK 0x20 /* Bitmask for LID switch status on XE3 GF */ +#define XE3GC_SMIC 0xFE00 + +#define OB500_GPO1 0x8034 /* Fan control */ +#define OB510_GPO2 0x11B9 /* LCD backlight */ +#define OB510_GPIO 0x118F /* Fan control */ + +#define OB500_FAN_ON_MASK 0x0A /* Turn fan on with zero bits */ +#define OB500_FAN_OFF_MASK 0x08 /* Fan status/off */ +#define OB500_BKLT_MASK 0x40 /* LCD backlight */ +#define OB510_FAN_ON_MASK 0x18 /* Turn fan on with zero bits */ +#define OB510_FAN_OFF_MASK 0x10 /* Turn fan on */ +#define OB510_BKLT_MASK 0x01 /* LCD backlight */ + +#define XE2_FAN_MASK 0x02 /* Turn fan on with zero bit */ + +/* + * Memory adresses + */ + +#define XE3GC_BCMD 0xFFFFEBC + +/* + * Toshiba Satellite A105 values and mask + */ + +#define A105_BNDT 0xA3 /* LCD brightness */ +#define A105_BNDT_MASK 0x0F + +/* + * Index and values for Command/Data/Index interface + * Notice similitudes with commands code for kbc + */ + +#define TSM70_FN_INDEX 0x45 +#define TSM70_FN_ENABLE 0x75 +#define TSM70_FN_DISABLE 0x74 +#define TSM70_HOTKEYS_INDEX 0x59 +#define TSM70_HOTKEYS_ENABLE 0x90 +#define TSM70_HOTKEYS_DISABLE 0x91 +#define TSM70_LCD_READ 0x5C +#define TSM70_LCD_WRITE 0x5D +#define TSM70_TOUCHPAD_ON 0x80 +#define TSM70_TOUCHPAD_OFF 0x81 +#define TSM100_BLANK_INDEX 0x59 +#define TSM100_LCD_ON 0xe1 +#define TSM100_LCD_OFF 0xe2 +#define TSM70_COOLING_OFFSET 0xb0 +#define TSM70_COOLING_POWERSAVE 0x0 +#define TSM70_COOLING_PERF 0x2 + +/* Toshiba SMI funtions and constants*/ +#define SMI_FN_PRESSED 0x8f +#define SMI_SET_LCD_BRIGHTNESS 0xa2 +#define SMI_GET_LCD_BRIGHTNESS 0xa3 +#define SMI_GET_KILL_SWITCH 0xa4 +#define SMI_SET_AERIAL 0xa5 +#define SMI_GET_AERIAL 0xa6 +#define SMI_SET_DISPLAY_STATE 0xa7 +#define SMI_GET_DISPLAY_STATE 0xa8 +#define SMI_SET_FN_INTERFACE 0xa9 +#define SMI_GET_FN_INTERFACE 0xaa +#define SMI_GET_FN_LAST_SCAN 0xab +#define SMI_SET_DOCK 0xac /* Undocumented */ +#define SMI_GET_DOCK 0xad /* Undocumented */ +#define SMI_SET_FN_F5_INTERFACE 0xc2 + +#define SMI_FN_KEYS_MASK 0x01 +#define SMI_STICK_KEYS_MASK 0x02 +#define SMI_FN_TWICE_LOCK_MASK 0x04 +#define SMI_FN_DOCK_MASK 0x08 + +#define SMI_FN_SCAN 0x6d /* Fn key scancode */ +#define SMI_DOCK_SCAN 0x6e /* Dock scancode */ + +/* Toshiba HCI method and constants */ +#define HCI_METHOD "SPFC" +#define HCI_WORDS 6 + +#define HCI_GET 0xfe00 +#define HCI_SET 0xff00 + +#define HCI_HOTKEY_EVENT 0x001e +#define HCI_RF_CONTROL 0x0056 + +#define HCI_ENABLE 0x0001 +#define HCI_DISABLE 0x0000 + +#define HCI_WIRELESS_CHECK 0x0001 +#define HCI_WIRELESS_POWER 0x0200 + +#define HCI_SUCCESS 0x0000 +#define HCI_FAILURE 0x1000 +#define HCI_NOT_SUPPORTED 0x8000 + +/* Toshiba Satellite X205 methods */ +#define TSX205_EVENTS_METHOD "INFO" +#define TSX205_NOTIFY_METHOD "NTFY" +#define TSX205_KILLSW_METHOD "KLSW" +#define TSX205_SLIVDO_METHOD "CSLI" + +#define ACPI_FN_MASK 0x01 +#define ACPI_FN_SCAN 0x6e /* Fn key scancode */ + +/* HCI key definitions */ +#define HCI_FN_RELEASED 0x100 +#define HCI_MUTE 0x101 +#define HCI_1 0x102 +#define HCI_2 0x103 +#define HCI_SPACE 0x139 +#define HCI_BREAK 0x13b +#define HCI_BSM 0x13c +#define HCI_SUSPEND 0x13d +#define HCI_HIBERNATE 0x13e +#define HCI_VIDEOOUT 0x13f +#define HCI_BRIGHTNESSDOWN 0x140 +#define HCI_BRIGHTNESSUP 0x141 +#define HCI_WLAN 0x142 +#define HCI_TOUCHPAD 0x143 +#define HCI_FN_PRESSED 0x17f --- linux-2.6.37.orig/ubuntu/omnibook/hotkeys.c +++ linux-2.6.37/ubuntu/omnibook/hotkeys.c @@ -0,0 +1,193 @@ +/* + * hotkeys.c -- code to handling Hotkey/E-Key/EasyAccess buttons + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" +#include "hardware.h" + +/* Predefined convinient on/off states */ +#define HKEY_ON HKEY_ONETOUCH|HKEY_MULTIMEDIA|HKEY_FN|HKEY_DOCK|HKEY_FNF5 +#define HKEY_OFF 0 + +/* + * Set hotkeys status and update recorded saved state + */ +static int hotkeys_set_save(struct omnibook_operation *io_op, unsigned int state) +{ + int retval; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + retval = __backend_hotkeys_set(io_op, state); + if (retval < 0) + goto out; + + /* Update saved state */ + io_op->backend->hotkeys_state = state & io_op->backend->hotkeys_write_cap; + + out: + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +/* + * Read hotkeys status, fallback to reading saved state if real probing is not + * supported. + */ +static int hotkeys_get_save(struct omnibook_operation *io_op, unsigned int *state) +{ + unsigned int read_state = 0; + int retval = 0; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + if (io_op->backend->hotkeys_get) + retval = __backend_hotkeys_get(io_op, &read_state); + if (retval < 0) + goto out; + + /* Return previously set state for the fields that are write only */ + *state = (read_state & io_op->backend->hotkeys_read_cap) + + (io_op->backend->hotkeys_state & ~io_op->backend->hotkeys_read_cap); + + out: + mutex_unlock(&io_op->backend->mutex); + return 0; +} + +/* + * Power management handlers + */ + +/* + * Restore previously saved state + */ +static int omnibook_hotkeys_resume(struct omnibook_operation *io_op) +{ + int retval; + mutex_lock(&io_op->backend->mutex); + retval = __backend_hotkeys_set(io_op, io_op->backend->hotkeys_state); + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +/* + * Disable hotkeys upon suspend (FIXME is the disabling required ?) + */ +static int omnibook_hotkeys_suspend(struct omnibook_operation *io_op) +{ + int retval = 0; + retval = backend_hotkeys_set(io_op, HKEY_OFF); + return retval; +} + +static const char pretty_name[][27] = { + "Onetouch buttons are", + "Multimedia hotkeys are", + "Fn hotkeys are", + "Stick key is", + "Press Fn twice to lock is", + "Dock events are", + "Fn + F5 hotkey is", +}; + +static int omnibook_hotkeys_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + int retval; + unsigned int read_state = 0; /* buggy gcc 4.1 warning fix */ + unsigned int shift, mask; + + retval = hotkeys_get_save(io_op, &read_state); + + if (retval < 0) + return retval; + + for (shift = 0; shift <= HKEY_LAST_SHIFT ; shift++) { + mask = 1 << shift; + /* we assume write capability or read capability imply support */ + if ((io_op->backend->hotkeys_read_cap | io_op->backend->hotkeys_write_cap) & mask) + len += + sprintf(buffer + len, "%s %s.\n", pretty_name[shift], + (read_state & mask) ? "enabled" : "disabled"); + } + + return len; +} + +static int omnibook_hotkeys_write(char *buffer, struct omnibook_operation *io_op) +{ + unsigned int state; + char *endp; + + if (strncmp(buffer, "off", 3) == 0) + hotkeys_set_save(io_op, HKEY_OFF); + else if (strncmp(buffer, "on", 2) == 0) + hotkeys_set_save(io_op, HKEY_ON); + else { + state = simple_strtoul(buffer, &endp, 16); + if (endp == buffer) + return -EINVAL; + else + hotkeys_set_save(io_op, state); + } + return 0; +} + +static int __init omnibook_hotkeys_init(struct omnibook_operation *io_op) +{ + int retval; + + printk(O_INFO "Enabling all hotkeys.\n"); + retval = hotkeys_set_save(io_op, HKEY_ON); + return retval < 0 ? retval : 0; +} + +static void __exit omnibook_hotkeys_cleanup(struct omnibook_operation *io_op) +{ + printk(O_INFO "Disabling all hotkeys.\n"); + hotkeys_set_save(io_op, HKEY_OFF); +} + +static struct omnibook_tbl hotkeys_table[] __initdata = { + {XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | AMILOD | TSP10 | TSM30X, + COMMAND(KBC,OMNIBOOK_KBC_CMD_ONETOUCH_ENABLE,OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE)}, + {TSM70, {CDI,}}, + {TSM40, {SMI,}}, + {TSX205, {ACPI,}}, + {0,} +}; + +static struct omnibook_feature __declared_feature hotkeys_driver = { + .name = "hotkeys", + .enabled = 1, + .read = omnibook_hotkeys_read, + .write = omnibook_hotkeys_write, + .init = omnibook_hotkeys_init, + .exit = omnibook_hotkeys_cleanup, + .suspend = omnibook_hotkeys_suspend, + .resume = omnibook_hotkeys_resume, + .ectypes = + XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | AMILOD | TSP10 | TSM70 | TSM30X | + TSM40 | TSX205, + .tbl = hotkeys_table, +}; + +module_param_named(hotkeys, hotkeys_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(hotkeys, "Use 0 to disable, 1 to enable hotkeys handling"); +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/info.c +++ linux-2.6.37/ubuntu/omnibook/info.c @@ -0,0 +1,68 @@ +/* + * info.c -- trivial informational features + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" + +#include +#include + +static int omnibook_version_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + + len += sprintf(buffer + len, "%s\n", OMNIBOOK_MODULE_VERSION); + + return len; +} + +static int omnibook_dmi_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + + len += sprintf(buffer + len, "BIOS Vendor: %s\n", dmi_get_system_info(DMI_BIOS_VENDOR)); + len += sprintf(buffer + len, "BIOS Version: %s\n", dmi_get_system_info(DMI_BIOS_VERSION)); + len += sprintf(buffer + len, "BIOS Release: %s\n", dmi_get_system_info(DMI_BIOS_DATE)); + len += sprintf(buffer + len, "System Vendor: %s\n", dmi_get_system_info(DMI_SYS_VENDOR)); + len += sprintf(buffer + len, "Product Name: %s\n", dmi_get_system_info(DMI_PRODUCT_NAME)); + len += + sprintf(buffer + len, "Version: %s\n", dmi_get_system_info(DMI_PRODUCT_VERSION)); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + len += + sprintf(buffer + len, "Serial Number: %s\n", dmi_get_system_info(DMI_PRODUCT_SERIAL)); +#endif + len += sprintf(buffer + len, "Board Vendor: %s\n", dmi_get_system_info(DMI_BOARD_VENDOR)); + len += sprintf(buffer + len, "Board Name: %s\n", dmi_get_system_info(DMI_BOARD_VERSION)); + + return len; +} + +static struct omnibook_feature __declared_feature version_driver = { + .name = "version", + .enabled = 1, + .read = omnibook_version_read, +}; + +static struct omnibook_feature __declared_feature dmi_driver = { + .name = "dmi", + .enabled = 1, + .read = omnibook_dmi_read, +}; + +module_param_named(dmi, dmi_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(dmi, "Use 0 to disable, 1 to enable DMI informations display support"); + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/init.c +++ linux-2.6.37/ubuntu/omnibook/init.c @@ -0,0 +1,535 @@ +/* + * init.c -- module initialization code + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" + +#include +#include +#include +#include + +#include "hardware.h" +#include "laptop.h" + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) +#include +#else +#include +#endif + +/* + * For compatibility with kernel older than 2.6.11 + */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)) +typedef u32 pm_message_t; +#endif + +static int __init omnibook_probe(struct platform_device *dev); +static int __exit omnibook_remove(struct platform_device *dev); +static int omnibook_suspend(struct platform_device *dev, pm_message_t state); +static int omnibook_resume(struct platform_device *dev); + +/* + * For compatibility with kernel older than 2.6.15 + */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) + +#define to_platform_device(x) container_of((x), struct platform_device, dev) + +static int __init compat_omnibook_probe(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + return omnibook_probe(pdev); +} + +static int __exit compat_omnibook_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + return omnibook_remove(pdev); +} + +static int compat_omnibook_suspend(struct device *dev, pm_message_t state, u32 level) +{ + struct platform_device *pdev = to_platform_device(dev); + return omnibook_suspend(pdev, state); +} + +static int compat_omnibook_resume(struct device *dev, u32 level) +{ + struct platform_device *pdev = to_platform_device(dev); + return omnibook_resume(pdev); +} + +#endif + +static struct proc_dir_entry *omnibook_proc_root = NULL; + +enum omnibook_ectype_t omnibook_ectype = NONE; + +static const char *laptop_model __initdata; + +static int omnibook_userset = 0; + +/* + * The platform_driver interface was added in linux 2.6.15 + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + +static struct platform_device *omnibook_device; + +static struct platform_driver omnibook_driver = { + .probe = omnibook_probe, + .remove = omnibook_remove, +#ifdef CONFIG_PM + .suspend = omnibook_suspend, + .resume = omnibook_resume, +#endif + .driver = { + .name = OMNIBOOK_MODULE_NAME, + .owner = THIS_MODULE, + }, +}; + +#else /* 2.6.15 */ + +static struct device_driver omnibook_driver = { + .name = OMNIBOOK_MODULE_NAME, + .bus = &platform_bus_type, + .probe = compat_omnibook_probe, + .remove = compat_omnibook_remove, +#ifdef CONFIG_PM + .suspend = compat_omnibook_suspend, + .resume = compat_omnibook_resume, +#endif +}; + +static struct platform_device omnibook_device = { + .name = OMNIBOOK_MODULE_NAME, +}; + +#endif /* 2.6.15 */ + +/* Linked list of all enabled features */ +static struct omnibook_feature *omnibook_available_feature; + +/* Delimiters of the .features section wich holds all the omnibook_feature structs */ +extern struct omnibook_feature _start_features_driver[]; +extern struct omnibook_feature _end_features_driver[]; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) +static int __init dmi_matched(struct dmi_system_id *dmi) +#else +static int __init dmi_matched(const struct dmi_system_id *dmi) +#endif +{ + omnibook_ectype = (enum omnibook_ectype_t)dmi->driver_data; + if (dmi->ident) + laptop_model = (char *)dmi->ident; + else + laptop_model = dmi_get_system_info(DMI_PRODUCT_VERSION); + return 1; /* return non zero means we stop the parsing selecting this entry */ +} + +/* + * Callback function for procfs file reading: the name of the file read was stored in *data + */ +static int procfile_read_dispatch(char *page, char **start, off_t off, int count, int *eof, + void *data) +{ + struct omnibook_feature *feature = (struct omnibook_feature *)data; + int len = 0; + + if (!feature || !feature->read) + return -EINVAL; + + if(off) + goto out; + + len = feature->read(page, feature->io_op); + if (len < 0) + return len; + + out: + *eof = 1; + return len; +} + +/* + * Callback function for procfs file writing: the name of the file written was stored in *data + */ +static int procfile_write_dispatch(struct file *file, const char __user * userbuf, + unsigned long count, void *data) +{ + struct omnibook_feature *feature = (struct omnibook_feature *)data; + char *kernbuf; + int retval; + + if (!feature || !feature->write) + return -EINVAL; + + kernbuf = kmalloc(count + 1, GFP_KERNEL); + if (!kernbuf) + return -ENOMEM; + + if (copy_from_user(kernbuf, userbuf, count)) { + kfree(kernbuf); + return -EFAULT; + } + + /* Make sure the string is \0 terminated */ + kernbuf[count] = '\0'; + + retval = feature->write(kernbuf, feature->io_op); + if (retval == 0) + retval = count; + + kfree(kernbuf); + + return retval; +} + +/* + * Match an ectype and return pointer to corresponding omnibook_operation. + * Also make corresponding backend initialisation if necessary, and skip + * to the next entry if it fails. + */ +static struct omnibook_operation *omnibook_backend_match(struct omnibook_tbl *tbl) +{ + int i; + struct omnibook_operation *matched = NULL; + + for (i = 0; tbl[i].ectypes; i++) { + if (omnibook_ectype & tbl[i].ectypes) { + if (tbl[i].io_op.backend->init && tbl[i].io_op.backend->init(&tbl[i].io_op)) { + dprintk("Backend %s init failed, skipping entry.\n", + tbl[i].io_op.backend->name); + continue; + } + matched = &tbl[i].io_op; + dprintk("Returning table entry nr %i.\n", i); + break; + } + } + return matched; +} + +/* + * Initialise a feature and add it to the linked list of active features + */ +static int __init omnibook_init(struct omnibook_feature *feature) +{ + int retval = 0; + mode_t pmode; + struct proc_dir_entry *proc_entry; + struct omnibook_operation *op; + + if (!feature) + return -EINVAL; + +/* + * Select appropriate backend for feature operations + * We copy the io_op field so the tbl can be initdata + */ + if (feature->tbl) { + dprintk("Begin table match of %s feature.\n", feature->name); + op = omnibook_backend_match(feature->tbl); + if (!op) { + dprintk("Match failed: disabling %s.\n", feature->name); + return -ENODEV; + } + feature->io_op = kmalloc(sizeof(struct omnibook_operation), GFP_KERNEL); + if (!feature->io_op) + return -ENOMEM; + memcpy(feature->io_op, op, sizeof(struct omnibook_operation)); + } else + dprintk("%s feature has no backend table, io_op not initialized.\n", feature->name); + +/* + * Specific feature init code + */ + if (feature->init && (retval = feature->init(feature->io_op))) { + printk(O_ERR "Init function of %s failed with error %i.\n", feature->name, retval); + goto err; + } +/* + * procfs file setup + */ + if (feature->name && feature->read) { + pmode = S_IFREG | S_IRUGO; + if (feature->write) { + pmode |= S_IWUSR; + if (omnibook_userset) + pmode |= S_IWUGO; + } + + proc_entry = create_proc_entry(feature->name, pmode, omnibook_proc_root); + + if (!proc_entry) { + printk(O_ERR "Unable to create proc entry %s\n", feature->name); + if (feature->exit) + feature->exit(feature->io_op); + retval = -ENOENT; + goto err; + } + proc_entry->data = feature; + proc_entry->read_proc = &procfile_read_dispatch; + if (feature->write) + proc_entry->write_proc = &procfile_write_dispatch; + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) + proc_entry->owner = THIS_MODULE; + #endif + } + list_add_tail(&feature->list, &omnibook_available_feature->list); + return 0; + err: + if (feature->io_op && feature->io_op->backend->exit) + feature->io_op->backend->exit(feature->io_op); + kfree(feature->io_op); + return retval; +} + +/* + * Callback function for driver registering : + * Initialize the linked list of enabled features and call omnibook_init to populate it + */ +static int __init omnibook_probe(struct platform_device *dev) +{ + int i; + struct omnibook_feature *feature; + + /* temporary hack */ + mutex_init(&kbc_backend.mutex); + mutex_init(&pio_backend.mutex); + mutex_init(&ec_backend.mutex); + + omnibook_available_feature = kzalloc(sizeof(struct omnibook_feature), GFP_KERNEL); + if (!omnibook_available_feature) + return -ENOMEM; + INIT_LIST_HEAD(&omnibook_available_feature->list); + + for (i = 0; i < _end_features_driver - _start_features_driver; i++) { + + feature = &_start_features_driver[i]; + + if (!feature->enabled) + continue; + + if ((omnibook_ectype & feature->ectypes) || (!feature->ectypes)) + omnibook_init(feature); + } + + printk(O_INFO "Enabled features:"); + list_for_each_entry(feature, &omnibook_available_feature->list, list) { + if (feature->name) + printk(" %s", feature->name); + } + printk(".\n"); + + return 0; +} + +/* + * Callback function for driver removal + */ +static int __exit omnibook_remove(struct platform_device *dev) +{ + struct omnibook_feature *feature, *temp; + + list_for_each_entry_safe(feature, temp, &omnibook_available_feature->list, list) { + list_del(&feature->list); + /* Feature specific cleanup */ + if (feature->exit) + feature->exit(feature->io_op); + /* Generic backend cleanup */ + if (feature->io_op && feature->io_op->backend->exit) + feature->io_op->backend->exit(feature->io_op); + if (feature->name) + remove_proc_entry(feature->name, omnibook_proc_root); + kfree(feature->io_op); + } + kfree(omnibook_available_feature); + + return 0; +} + +/* + * Callback function for system suspend + */ +static int omnibook_suspend(struct platform_device *dev, pm_message_t state) +{ + int retval; + struct omnibook_feature *feature; + + list_for_each_entry(feature, &omnibook_available_feature->list, list) { + if (feature->suspend) { + retval = feature->suspend(feature->io_op); + if (retval) + printk(O_ERR "Unable to suspend the %s feature (error %i).\n", feature->name, retval); + } + } + return 0; +} + +/* + * Callback function for system resume + */ +static int omnibook_resume(struct platform_device *dev) +{ + int retval; + struct omnibook_feature *feature; + + list_for_each_entry(feature, &omnibook_available_feature->list, list) { + if (feature->resume) { + retval = feature->resume(feature->io_op); + if (retval) + printk(O_ERR "Unable to resume the %s feature (error %i).\n", feature->name, retval); + } + } + return 0; +} + +/* + * Find a given available feature by its name + */ +struct omnibook_feature *omnibook_find_feature(char *name) +{ + struct omnibook_feature *feature; + + list_for_each_entry(feature, &omnibook_available_feature->list, list) { + if (!strcmp(feature->name, name)) + return feature; + } + return NULL; +} + +/* + * Maintain compatibility with the old ectype numbers: + * ex: The user set/get ectype=12 for TSM70=2^(12-1) + */ +static int __init set_ectype_param(const char *val, struct kernel_param *kp) +{ + char *endp; + int value; + + if (!val) + return -EINVAL; + + value = simple_strtol(val, &endp, 10); + if (endp == val) /* No match */ + return -EINVAL; + omnibook_ectype = 1 << (value - 1); + return 0; +} + +static int get_ectype_param(char *buffer, struct kernel_param *kp) +{ + return sprintf(buffer, "%i", ffs(omnibook_ectype)); +} + +static int __init omnibook_module_init(void) +{ + int retval; + + printk(O_INFO "Driver version %s.\n", OMNIBOOK_MODULE_VERSION); + + if (omnibook_ectype != NONE) + printk(O_WARN "Forced load with EC type %i.\n", ffs(omnibook_ectype)); + else if (dmi_check_system(omnibook_ids)) + printk(O_INFO "%s detected.\n", laptop_model); + else + printk(O_INFO "Unknown model.\n"); + + omnibook_proc_root = proc_mkdir(OMNIBOOK_MODULE_NAME, NULL); + if (!omnibook_proc_root) { + printk(O_ERR "Unable to create /proc/%s.\n", OMNIBOOK_MODULE_NAME); + return -ENOENT; + } + +/* + * The platform_driver interface was added in linux 2.6.15 + */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + + retval = platform_driver_register(&omnibook_driver); + if (retval < 0) + return retval; + + omnibook_device = platform_device_alloc(OMNIBOOK_MODULE_NAME, -1); + if (!omnibook_device) { + platform_driver_unregister(&omnibook_driver); + return -ENOMEM; + } + + retval = platform_device_add(omnibook_device); + if (retval) { + platform_device_put(omnibook_device); + platform_driver_unregister(&omnibook_driver); + return retval; + } +#else /* 2.6.15 */ + + retval = driver_register(&omnibook_driver); + if (retval < 0) + return retval; + + retval = platform_device_register(&omnibook_device); + + if (retval) { + driver_unregister(&omnibook_driver); + return retval; + } +#endif + return 0; +} + +static void __exit omnibook_module_cleanup(void) +{ + +/* + * The platform_driver interface was added in linux 2.6.15 + */ + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) + platform_device_unregister(omnibook_device); + platform_driver_unregister(&omnibook_driver); +#else + platform_device_unregister(&omnibook_device); + driver_unregister(&omnibook_driver); +#endif + + if (omnibook_proc_root) + remove_proc_entry("omnibook", NULL); + printk(O_INFO "Module is unloaded.\n"); +} + +module_init(omnibook_module_init); +module_exit(omnibook_module_cleanup); + +MODULE_AUTHOR("Soós Péter, Mathieu Bérard"); +MODULE_VERSION(OMNIBOOK_MODULE_VERSION); +MODULE_DESCRIPTION + ("Kernel interface for HP OmniBook, HP Pavilion, Toshiba Satellite and Compal ACL00 laptops"); +MODULE_LICENSE("GPL"); +module_param_call(ectype, set_ectype_param, get_ectype_param, NULL, S_IRUGO); +module_param_named(userset, omnibook_userset, int, S_IRUGO); +MODULE_PARM_DESC(ectype, "Type of embedded controller firmware"); +MODULE_PARM_DESC(userset, "Use 0 to disable, 1 to enable users to set parameters"); + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/kbc.c +++ linux-2.6.37/ubuntu/omnibook/kbc.c @@ -0,0 +1,152 @@ +/* + * kbc.c -- low level functions to access Keyboard Controller + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" + +#include +#include +#include +#include +#include + +#include +#include "hardware.h" + +extern int omnibook_key_polling_enable(void); +extern int omnibook_key_polling_disable(void); + +/* + * Registers of the keyboard controller + */ + +#define OMNIBOOK_KBC_DATA 0x60 +#define OMNIBOOK_KBC_SC 0x64 + +/* + * Keyboard controller status register bits + */ + +#define OMNIBOOK_KBC_STAT_OBF 0x01 /* Output buffer full */ +#define OMNIBOOK_KBC_STAT_IBF 0x02 /* Input buffer full */ + + +/* + * Interrupt control + */ + +static DEFINE_SPINLOCK(omnibook_kbc_lock); + +/* + * Wait for keyboard buffer + */ + +static int omnibook_kbc_wait(u8 event) +{ + int timeout = OMNIBOOK_TIMEOUT; + + switch (event) { + case OMNIBOOK_KBC_STAT_OBF: + while (!(inb(OMNIBOOK_KBC_SC) & event) && timeout--) + mdelay(1); + break; + case OMNIBOOK_KBC_STAT_IBF: + while ((inb(OMNIBOOK_KBC_SC) & event) && timeout--) + mdelay(1); + break; + default: + return -EINVAL; + } + if (timeout > 0) + return 0; + return -ETIME; +} + +/* + * Write to the keyboard command register + */ + +static int omnibook_kbc_write_command(u8 cmd) +{ + int retval; + + spin_lock_irq(&omnibook_kbc_lock); + retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF); + if (retval) + goto end; + outb(cmd, OMNIBOOK_KBC_SC); + retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF); + end: + spin_unlock_irq(&omnibook_kbc_lock); + return retval; +} + +/* + * Write to the keyboard data register + */ + +static int omnibook_kbc_write_data(u8 data) +{ + int retval; + + spin_lock_irq(&omnibook_kbc_lock); + retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF); + if (retval) + goto end; + outb(data, OMNIBOOK_KBC_DATA); + retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF); + end: + spin_unlock_irq(&omnibook_kbc_lock); + return retval; +} + +/* + * Send a command to keyboard controller + */ + +static int omnibook_kbc_command(const struct omnibook_operation *io_op, u8 data) +{ + int retval; + + if ((retval = omnibook_kbc_write_command(OMNIBOOK_KBC_CONTROL_CMD))) + return retval; + + retval = omnibook_kbc_write_data(data); + return retval; +} + +/* + * Onetouch button hotkey handler + */ +static int omnibook_kbc_hotkeys(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval; + + retval = __omnibook_toggle(io_op, !!(state & HKEY_ONETOUCH)); + return retval; +} + +/* + * Backend interface declarations + */ +struct omnibook_backend kbc_backend = { + .name = "i8042", + .hotkeys_write_cap = HKEY_ONETOUCH, + .byte_write = omnibook_kbc_command, + .hotkeys_set = omnibook_kbc_hotkeys, +}; + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/laptop.h +++ linux-2.6.37/ubuntu/omnibook/laptop.h @@ -0,0 +1,1077 @@ +/* + * laptop.h -- Various structures about supported hardware + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Written by Mathieu Bérard , 2006 + */ + + +#define HP_SIGNATURE "Hewlett-Packard" + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) +static int __init dmi_matched(struct dmi_system_id *dmi); +#else +static int __init dmi_matched(const struct dmi_system_id *dmi); +#endif + +static struct dmi_system_id omnibook_ids[] __initdata = { + { + .callback = dmi_matched, + .ident = "HP OmniBook XE3 GF", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GF"), + }, + .driver_data = (void *) XE3GF + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook XT1000", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XT1000"), + }, + .driver_data = (void *) XE3GF + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook XE2 DC", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE2 DC"), + }, + .driver_data = (void *) XE2 + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook XE3 GC", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GC"), + }, + .driver_data = (void*) XE3GC + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook XE3 GD / Pavilion N5430", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GD"), + }, + .driver_data = (void*) XE3GC + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook XE3 GE / Pavilion N5415", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook XE3 GE"), + }, + .driver_data = (void*) XE3GC + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook 500 FA", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 500 FA"), + }, + .driver_data = (void*) OB500 + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook 510 FB", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 510 FB"), + }, + .driver_data = (void*) OB510 + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook 4150", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 4150"), + }, + .driver_data = (void*) OB4150 + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook 900 B", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 900 B"), + }, + .driver_data = (void*) OB4150 + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook 6000 EA", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 6000 EA"), + }, + .driver_data = (void*) OB6000 + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook 6100 EB", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 6100 EB"), + }, + .driver_data = (void*) OB6100 + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook xe4000/xe4100", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook xe4000"), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook xe4400", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook xe4400"), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook xe4500", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook xe4500"), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP OmniBook 6200 EG / vt6200 / xt 6200", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook 6200 EG"), + }, + .driver_data = (void*) XE4500 + }, + /* There are no model specific strings of some HP OmniBook XT1500 */ + { + .callback = dmi_matched, + .ident = "HP OmniBook XT1500", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP OmniBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP OmniBook"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "HP Pavilion ze4000 / ze4125", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP NoteBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP NoteBook ze4000"), + }, + .driver_data = (void*) XE4500 + }, + /* There are no model specific strings of some HP Pavilion xt155 and some HP Pavilion ze4100 + * There are no model specific strings of some HP nx9000 */ + { + .callback = dmi_matched, + .ident = "HP Pavilion xt155 / ze4100 / nx9000", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP NoteBook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP NoteBook PC"), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP Pavilion ZU1000 FA / ZU1000 FA / ZU1175", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion ZU1000 FA"), + }, + .driver_data = (void*) OB500 + }, + { + .callback = dmi_matched, + .ident = "HP Pavilion Notebook XE3 GC / N5290", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook XE3 GC"), + }, + .driver_data = (void*) XE3GC + }, + { + .callback = dmi_matched, + .ident = "HP Pavilion Notebook GD / N5441", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GD"), + }, + .driver_data = (void*) XE3GC + }, + { + .callback = dmi_matched, + .ident = "HP Pavilion Notebook GE / XH545", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook Model GE"), + }, + .driver_data = (void*) XE3GC + }, + { + .callback = dmi_matched, + .ident = "HP Pavilion Notebook ZT1000 / ZT1141", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook ZT1000"), + }, + .driver_data = (void*) XE3GF + }, + /* There are no model specific strings of some HP Pavilion ZT1175 and ZT1195 notebooks */ + { + .callback = dmi_matched, + .ident = "HP Pavilion ZT1175 / ZT1195", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), + DMI_MATCH(DMI_PRODUCT_VERSION, "HP Pavilion Notebook"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "HP Pavilion ze4200 series", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze4200"), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP Pavilion ze4300 series", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze4300"), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP Pavilion ze4500 series", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze4500"), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP Pavilion ze8500 series", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ze8500"), + }, + .driver_data = (void*) XE4500 + }, + /* Compaq nx9000 */ + { + .callback = dmi_matched, + .ident = "HP Compaq nx9000", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP nx9000"), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP Compaq nx9005", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP nx9005"), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP Compaq nx9010", + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP nx9010"), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1000", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1000"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1005", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1005"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1110", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1110"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1115", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1115"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1130", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1130"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1700-100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1700-100"), + }, + .driver_data = (void*) AMILOD + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1700-200", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1700-200"), + }, + .driver_data = (void*) AMILOD + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1700-300", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1700-300"), + }, + .driver_data = (void*) AMILOD + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1700-400", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1700-400"), + }, + .driver_data = (void*) AMILOD + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1700-500", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1700-500"), + }, + .driver_data = (void*) AMILOD + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1900", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1900"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1905", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1905"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1950", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1950"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1955", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S1955"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 2430", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S2430"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 2435", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S2435"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 3000", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S3000"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 3005", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "S3005"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1000", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1000"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1005", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1005"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1110", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1110"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1115", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1115"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1115", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Toshiba 1115"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1900", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1900"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1905", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1905"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1950", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1950"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 1955", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 1955"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 2430", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 2430"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 2435", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 2435"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 3000", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 3000"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite 3005", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite 3005"), + }, + .driver_data = (void*) XE3GF, + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite A70", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A70"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite A75", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A75"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite A80", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A80"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite A105", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A105"), + }, + .driver_data = (void*) TSA105 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite A100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite A100"), + }, + .driver_data = (void*) TSA105 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite P100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P100"), + }, + .driver_data = (void*) TSA105 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite P10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"), + }, + .driver_data = (void*) TSP10 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite P15", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P15"), + }, + .driver_data = (void*) TSP10 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite P20", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P20"), + }, + .driver_data = (void*) TSP10 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite P25", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P25"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite M30X", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M30X"), + }, + .driver_data = (void*) TSM30X + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite M35X", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M35X"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite M50", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M50"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite M60", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M60"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite M70", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M70"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite M100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE M100"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite M100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M100"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite M115", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M115"), + }, + .driver_data = (void*) TSA105 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite M40X", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M40X"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite M40", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M40"), + }, + .driver_data = (void*) TSM40 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite M45", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite M45"), + }, + .driver_data = (void*) TSM40 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Satellite X205-S9800", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite X205"), + }, + .driver_data = (void*) TSX205 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Tecra S1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TECRA S1"), + }, + .driver_data = (void*) TSM40 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Tecra S1", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Tecra S1"), + }, + .driver_data = (void*) TSM40 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Tecra S2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Tecra S2"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Tecra A4", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Tecra A4"), + }, + .driver_data = (void*) TSM40 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Tecra A6", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A6"), + }, + .driver_data = (void*) TSM70 + }, + { + .callback = dmi_matched, + .ident = "Toshiba Equium A110", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"), + }, + .driver_data = (void*) TSM30X /* FIXME: provisional */ + }, + { + .callback = dmi_matched, + .ident = "Compal ACL00", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"), + DMI_MATCH(DMI_BOARD_NAME, "ACL00"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Compal ACL10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"), + DMI_MATCH(DMI_BOARD_NAME, "ACL10"), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "Fujitsu-Siemens Amilo D series", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D-Series"), + }, + .driver_data = (void*) AMILOD + }, +/* HP Technology code Matching: + * Technology code appears in the first two chracters of BIOS version string + * ended by a dot, but it prefixed a space character on some models and BIOS + * versions. + * New HP/Compaq models use more characters (eg. KF_KH.). + */ + { + .callback = dmi_matched, + .ident = "HP model with technology code CI", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "CI."), + }, + .driver_data = (void*) OB4150 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code CL", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "CL."), + }, + .driver_data = (void*) OB4150 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code DC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "DC."), + }, + .driver_data = (void*) XE2 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code EA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "EA."), + }, + .driver_data = (void*) OB6000 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code EB", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "EB."), + }, + .driver_data = (void*) OB6100 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code EG", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "EG."), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code FA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "FA."), + }, + .driver_data = (void*) OB500 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code FB", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "FB."), + }, + .driver_data = (void*) OB510 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code GC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "GC."), + }, + .driver_data = (void*) XE3GC + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code GD", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "GD."), + }, + .driver_data = (void*) XE3GC + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code GE", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "GE."), + }, + .driver_data = (void*) XE3GC + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code GF", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "GF."), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code IB", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "IB."), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code IC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "IC."), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code ID", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "ID."), + }, + .driver_data = (void*) XE3GF + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code KA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "KA."), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code KB", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "KB."), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code KC", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "KC."), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code KD", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "KD."), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code KE", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "KE."), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code KE_KG", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "KE_KG."), + }, + .driver_data = (void*) XE4500 + }, + { + .callback = dmi_matched, + .ident = "HP model with technology code KF_KH", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, HP_SIGNATURE), + DMI_MATCH(DMI_BIOS_VERSION, "KF_KH."), + }, + .driver_data = (void*) XE4500 + }, + { NULL, } +}; --- linux-2.6.37.orig/ubuntu/omnibook/lcd.c +++ linux-2.6.37/ubuntu/omnibook/lcd.c @@ -0,0 +1,207 @@ +/* + * lcd.c -- LCD brightness and on/off + * + * 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, 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. + * + * Written by Maciek Górniak , 2002 + * Modified by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" +#include + +#ifdef CONFIG_OMNIBOOK_BACKLIGHT +#include +#endif + +#include "hardware.h" + +unsigned int omnibook_max_brightness; + +#ifdef CONFIG_OMNIBOOK_BACKLIGHT +static struct backlight_device *omnibook_backlight_device; + +static int omnibook_get_backlight(struct backlight_device *bd); +static int omnibook_set_backlight(struct backlight_device *bd); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) +static struct backlight_ops omnibookbl_ops = { +#else /* 2.6.21 */ +static struct backlight_properties omnibookbl_data = { + .owner = THIS_MODULE, +#endif /* 2.6.21 */ + .get_brightness = omnibook_get_backlight, + .update_status = omnibook_set_backlight, +}; + +static int omnibook_get_backlight(struct backlight_device *bd) +{ + int retval = 0; + struct omnibook_operation *io_op; + u8 brgt; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + io_op = bl_get_data(bd); +#else /* 2.6.23 */ + io_op = class_get_devdata(&bd->class_dev); +#endif /* 2.6.23 */ + retval = backend_byte_read(io_op, &brgt); + if (!retval) + retval = brgt; + + return retval; +} + +static int omnibook_set_backlight(struct backlight_device *bd) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + u8 intensity = bd->props.brightness; +#else /* 2.6.21 */ + u8 intensity = bd->props->brightness; +#endif /* 2.6.21 */ + struct omnibook_operation *io_op; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) + io_op = bl_get_data(bd); +#else /* 2.6.23 */ + io_op = class_get_devdata(&bd->class_dev); +#endif /* 2.6.23 */ + return backend_byte_write(io_op, intensity); +} +#endif /* CONFIG_OMNIBOOK_BACKLIGHT */ + +static int omnibook_brightness_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + u8 brgt; + + backend_byte_read(io_op, &brgt); + + len += + sprintf(buffer + len, "LCD brightness: %2d (max value: %d)\n", brgt, + omnibook_max_brightness); + + return len; +} + +static int omnibook_brightness_write(char *buffer, struct omnibook_operation *io_op) +{ + unsigned int brgt = 0; + char *endp; + + if (strncmp(buffer, "off", 3) == 0) + omnibook_lcd_blank(1); + else if (strncmp(buffer, "on", 2) == 0) + omnibook_lcd_blank(0); + else { + brgt = simple_strtoul(buffer, &endp, 10); + if ((endp == buffer) || (brgt > omnibook_max_brightness)) + return -EINVAL; + else { + backend_byte_write(io_op, brgt); +#ifdef CONFIG_OMNIBOOK_BACKLIGHT +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + omnibook_backlight_device->props.brightness = brgt; +#else /* 2.6.21 */ + omnibookbl_data.brightness = brgt; +#endif +#endif + } + } + return 0; +} + +static int __init omnibook_brightness_init(struct omnibook_operation *io_op) +{ + /* + * FIXME: What is exactly the max value for each model ? + * I know that it's 7 for the TSM30X, TSM70, TSM40 and TSA105 + * and previous versions of this driver (wrongly) assumed it was 10 for + * all models. + * + * XE3GF + * TSM30X + * TSM70 + * TSM40 + * TSA105 + * TSX205 + */ + if (omnibook_ectype & (XE3GF | TSM70 | TSM30X | TSM40 | TSA105 | TSX205)) + omnibook_max_brightness = 7; + else { + omnibook_max_brightness = 10; + printk(O_WARN "Assuming that LCD brightness is between 0 and %i,\n", + omnibook_max_brightness); + printk(O_WARN + "please contact http://sourceforge.net/projects/omnibook to confirm.\n"); + } + +#ifdef CONFIG_OMNIBOOK_BACKLIGHT + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + omnibook_backlight_device = + backlight_device_register(OMNIBOOK_MODULE_NAME, NULL, (void *)io_op, &omnibookbl_ops); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + omnibook_backlight_device = + backlight_device_register(OMNIBOOK_MODULE_NAME, NULL, (void *)io_op, &omnibookbl_data); +#else /* < 2.6.20 */ + omnibook_backlight_device = + backlight_device_register(OMNIBOOK_MODULE_NAME, (void *)io_op, &omnibookbl_data); +#endif + if (IS_ERR(omnibook_backlight_device)) { + printk(O_ERR "Unable to register as backlight device.\n"); + return -ENODEV; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + omnibook_backlight_device->props.max_brightness = omnibook_max_brightness; + backend_byte_read(io_op, (u8*) &omnibook_backlight_device->props.brightness); +#else /* < 2.6.21 */ + omnibookbl_data.max_brightness = omnibook_max_brightness; + backend_byte_read(io_op, (u8*) &omnibookbl_data.brightness); +#endif + +#endif /* CONFIG_OMNIBOOK_BACKLIGHT */ + return 0; +} +static void __exit omnibook_brightness_cleanup(struct omnibook_operation *io_op) +{ +#ifdef CONFIG_OMNIBOOK_BACKLIGHT + backlight_device_unregister(omnibook_backlight_device); +#endif +} + +static struct omnibook_tbl lcd_table[] __initdata = { + {TSM70 | TSX205, {CDI, TSM70_LCD_READ, TSM70_LCD_WRITE, 0, 0, 0}}, + {TSM40, {SMI, SMI_GET_LCD_BRIGHTNESS, SMI_SET_LCD_BRIGHTNESS, 0, 0, 0}}, + {XE3GF | TSP10 | TSM70 | TSM30X, SIMPLE_BYTE(EC, XE3GF_BRTS, XE3GF_BRTS_MASK)}, + {XE3GC, SIMPLE_BYTE(EC, XE3GC_BTVL, XE3GC_BTVL_MASK)}, + {AMILOD, SIMPLE_BYTE(EC, AMILOD_CBRG, XE3GC_BTVL_MASK)}, + {TSA105, SIMPLE_BYTE(EC, A105_BNDT, A105_BNDT_MASK)}, + {0,} +}; + +static struct omnibook_feature __declared_feature lcd_driver = { + .name = "lcd", + .enabled = 1, + .read = omnibook_brightness_read, + .write = omnibook_brightness_write, + .init = omnibook_brightness_init, + .exit = omnibook_brightness_cleanup, + .ectypes = XE3GF | XE3GC | AMILOD | TSP10 | TSM70 | TSM30X | TSM40 | TSA105 | TSX205, + .tbl = lcd_table, +}; + +module_param_named(lcd, lcd_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(lcd, "Use 0 to disable, 1 to enable to LCD brightness support"); + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/lib.c +++ linux-2.6.37/ubuntu/omnibook/lib.c @@ -0,0 +1,81 @@ +/* + * lib.c -- Generic helpers functions + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" + +#include "hardware.h" +#include "compat.h" +#include + +/* + * Generic funtion for applying a mask on a value + * Hack: degenerate to omnibook_toggle if there is no read method + * of if the read address is 0, this is used in blank.c + */ +int __omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle) +{ + int retval = 0; + int mask; + u8 data; + + if(!(io_op->backend->byte_read && io_op->read_addr)) + return __omnibook_toggle(io_op,toggle); + + if ((retval = __backend_byte_read(io_op, &data))) + return retval; + + if (toggle == 1) + mask = io_op->on_mask; + else if (toggle == 0) + mask = io_op->off_mask; + else + return -EINVAL; + + if (mask > 0) + data |= (u8) mask; + else if (mask < 0) + data &= ~((u8) (-mask)); + else + return -EINVAL; + + retval = __backend_byte_write(io_op, data); + + return retval; +} + +/* + * Helper for toggle like operations + */ +int __omnibook_toggle(const struct omnibook_operation *io_op, int toggle) +{ + int retval; + u8 data; + + data = toggle ? io_op->on_mask : io_op->off_mask; + retval = __backend_byte_write(io_op, data); + return retval; +} + +void omnibook_report_key( struct input_dev *dev, unsigned int keycode) +{ + input_report_key(dev, keycode, 1); + input_sync(dev); + input_report_key(dev, keycode, 0); + input_sync(dev); +} + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/muteled.c +++ linux-2.6.37/ubuntu/omnibook/muteled.c @@ -0,0 +1,109 @@ +/* + * mutled.c -- MUTE LED control + * + * 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, 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. + * + * Written by Thomas Perl , 2006 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" +#include "hardware.h" + +static int omnibook_muteled_set(struct omnibook_operation *io_op, int status) +{ + int retval = 0; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + if((retval = __omnibook_toggle(io_op, !!status))) { + printk(O_ERR "Failed muteled %s command.\n", status ? "on" : "off"); + goto out; + } + + io_op->backend->muteled_state = !!status; + + out: + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +/* + * Hardware query is unsupported, reading is unreliable. + */ +static int omnibook_muteled_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + len += + sprintf(buffer + len, "Last mute LED action was an %s command.\n", + io_op->backend->touchpad_state ? "on" : "off"); + + mutex_unlock(&io_op->backend->mutex); + return len; +} + +static int omnibook_muteled_write(char *buffer, struct omnibook_operation *io_op) +{ + int cmd; + + if (*buffer == '0' || *buffer == '1') { + cmd = *buffer - '0'; + if (!omnibook_muteled_set(io_op, cmd)) { + dprintk("Switching mute LED to %s state.\n", cmd ? "on" : "off"); + } + } else { + return -EINVAL; + } + return 0; +} + +/* + * May re-enable muteled upon resume + */ +static int omnibook_muteled_resume(struct omnibook_operation *io_op) +{ + int retval; + mutex_lock(&io_op->backend->mutex); + retval = __omnibook_toggle(io_op, !!io_op->backend->touchpad_state); + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +/* + * Switch muteled off upon exit + */ +static void __exit omnibook_muteled_cleanup(struct omnibook_operation *io_op) +{ + omnibook_muteled_set(io_op, 0); +} + +static struct omnibook_tbl muteled_table[] __initdata = { + {XE4500, COMMAND(KBC, OMNIBOOK_KBC_CMD_MUTELED_ON, OMNIBOOK_KBC_CMD_MUTELED_OFF)}, + {0,} +}; + +static struct omnibook_feature __declared_feature muteled_driver = { + .name = "muteled", + .enabled = 1, + .read = omnibook_muteled_read, + .write = omnibook_muteled_write, + .exit = omnibook_muteled_cleanup, + .resume = omnibook_muteled_resume, + .ectypes = XE4500, + .tbl = muteled_table, +}; + +module_param_named(muteled, muteled_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(muteled, "Use 0 to disable, 1 to enable 'Audo Mute' LED control"); --- linux-2.6.37.orig/ubuntu/omnibook/nbsmi.c +++ linux-2.6.37/ubuntu/omnibook/nbsmi.c @@ -0,0 +1,968 @@ +/* + * nbsmi.c -- Toshiba SMI low-level acces code + * + * 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, 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. + * + * Written by Mathieu Bérard , 2006 + * + * Sources of inspirations for this code were: + * -Toshiba via provided hardware specification + * -Thorsten Zachmann with the 's1bl' project + * -Frederico Munoz with the 'tecra_acpi' project + * Thanks to them + */ + +#include "omnibook.h" +#include "hardware.h" +#include +#include +#include +#include +#include +#include +#include + +/* copied from drivers/input/serio/i8042-io.h */ +#define I8042_KBD_PHYS_DESC "isa0060/serio0" + +/* + * ATI's IXP PCI-LPC bridge + */ +#define INTEL_PMBASE 0x40 +#define INTEL_GPE0_EN 0x2c + +#define BUFFER_SIZE 0x20 +#define INTEL_OFFSET 0x60 +#define INTEL_SMI_PORT 0xb2 /* APM_CNT port in INTEL ICH specs */ + +/* + * Toshiba Specs state 0xef here but: + * -this would overflow (ef + 19 > ff) + * -code from Toshiba use e0, which make much more sense + */ + +#define ATI_OFFSET 0xe0 +#define ATI_SMI_PORT 0xb0 + +#define EC_INDEX_PORT 0x300 +#define EC_DATA_PORT 0x301 + +/* Masks decode for GetAeral */ +#define WLEX_MASK 0x4 +#define WLAT_MASK 0x8 +#define BTEX_MASK 0x1 +#define BTAT_MASK 0x2 + +/* + * Private data of this backend + */ +struct nbsmi_backend_data { + struct pci_dev *lpc_bridge; /* Southbridge chip ISA bridge/LPC interface PCI device */ + u8 start_offset; /* Start offset in CMOS memory */ + struct input_dev *nbsmi_input_dev; + struct work_struct fnkey_work; +}; + +/* + * Possible list of supported southbridges + * Here mostly to implement a more or less clean PCI probing + * Works only because of previous DMI probing. + * It's in compal.c + */ +extern const struct pci_device_id lpc_bridge_table[]; + +/* + * Since we are going to trigger an SMI, all registers (I assume this does not + * include esp and maybe ebp) and eflags may be mangled in the + * process. + * We also disable preemtion and IRQs upon SMI call. + */ +static inline u32 ati_do_smi_call(u16 function) +{ + unsigned long flags; + u32 retval = 0; + + local_irq_save(flags); + preempt_disable(); + +/* + * eflags, eax, ebx, ecx, edx, esi and edi are clobbered upon writing to SMI_PORT + * thus the clobber list. + * + * Equivalent pseudocode: + * + * eax = function; [non null] + * outw(eax, ATI_SMI_PORT); <- This Trigger an SMI + * if( eax == 0 ) [success if eax has been cleared] + * goto out; + * if( inb(ATI_SMI_PORT + 1) == 0) [if not in eax, success maybe be stored here] + * goto out; + * retval = -EIO; [too bad] + * out: + */ + __asm__ __volatile__("outw %%ax, %2; \ + orw %%ax, %%ax; \ + jz 1f; \ + inw %3, %%ax; \ + orw %%ax, %%ax; \ + jz 1f; \ + movl %4, %0; \ + 1:;" + : "=m" (retval) + : "a"(function), "N"(ATI_SMI_PORT), "N"(ATI_SMI_PORT+1), "i"(-EIO) + : "memory", "ebx", "ecx", "edx", "esi", "edi", "cc"); + + local_irq_restore(flags); + preempt_enable_no_resched(); + return retval; +} + +static inline u32 intel_do_smi_call(u16 function, struct pci_dev *lpc_bridge) +{ + u32 state; + unsigned long flags; + u32 retval = 0; + u32 sci_en = 0; + + local_irq_save(flags); + preempt_disable(); + +/* + * We get the PMBASE offset ( bits 15:7 at 0x40 offset of PCI config space ) + * And we access offset 2c (GPE0_EN), save the state, disable all SCI + * and restore the state after the SMI call + */ + pci_read_config_dword(lpc_bridge, INTEL_PMBASE, &sci_en); + sci_en = sci_en & 0xff80; /* Keep bits 15:7 */ + sci_en += INTEL_GPE0_EN; /* GPEO_EN offset */ + state = inl(sci_en); + outl(0, sci_en); + +/* + * eflags, eax, ebx, ecx, edx, esi and edi are clobbered upon writing to SMI_PORT + * thus the clobber list. + * + * Equivalent pseudocode: + * + * eax = function; [non null] + * outw(eax, INTEL_SMI_PORT); <- This Trigger an SMI + * if( eax == 0 ) [success if eax has been cleared] + * goto out; + * retval = -EIO; [too bad] + * out: + */ + __asm__ __volatile__("outw %%ax, %2; \ + orw %%ax, %%ax; \ + jz 1f; \ + movl %3, %0; \ + 1:;" + : "=m" (retval) + : "a"(function), "N"(INTEL_SMI_PORT), "i"(-EIO) + : "memory", "ebx", "ecx", "edx", "esi", "edi", "cc"); + + outl(state, sci_en); + local_irq_restore(flags); + preempt_enable_no_resched(); + return retval; +} + +static int nbsmi_smi_command(u16 function, + const u8 * inputbuffer, + u8 * outputbuffer, + const struct nbsmi_backend_data *priv_data) +{ + int count; + u32 retval = 0; + + + for (count = 0; count < BUFFER_SIZE; count++) { + outb(count + priv_data->start_offset, RTC_PORT(2)); + outb(*(inputbuffer + count), RTC_PORT(3)); + } + +/* + * We have to write 0xe4XX to smi_port + * where XX is the SMI function code + */ + function = (function & 0xff) << 8; + function |= 0xe4; + + switch (priv_data->lpc_bridge->vendor) { + case PCI_VENDOR_ID_INTEL: + retval = intel_do_smi_call(function, priv_data->lpc_bridge); + break; + case PCI_VENDOR_ID_ATI: + retval = ati_do_smi_call(function); + break; + default: + BUG(); + } + + if (retval) + printk(O_ERR "smi_command failed with error %u.\n", retval); + + for (count = 0; count < BUFFER_SIZE; count++) { + outb(count + priv_data->start_offset, RTC_PORT(2)); + *(outputbuffer + count) = inb(RTC_PORT(3)); + } + + return retval; +} + +static int nbsmi_smi_read_command(const struct omnibook_operation *io_op, u8 * data) +{ + int retval; + u8 *inputbuffer; + u8 *outputbuffer; + struct nbsmi_backend_data *priv_data = io_op->backend->data; + + if (!priv_data) + return -ENODEV; + + inputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL); + if (!inputbuffer) { + retval = -ENOMEM; + goto error1; + } + + outputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL); + if (!outputbuffer) { + retval = -ENOMEM; + goto error2; + } + + retval = nbsmi_smi_command((u16) io_op->read_addr, inputbuffer, outputbuffer, priv_data); + if (retval) + goto out; + + *data = outputbuffer[0]; + + if (io_op->read_mask) + *data &= io_op->read_mask; + + out: + kfree(outputbuffer); + error2: + kfree(inputbuffer); + error1: + return retval; +} + +static int nbsmi_smi_write_command(const struct omnibook_operation *io_op, u8 data) +{ + int retval; + u8 *inputbuffer; + u8 *outputbuffer; + struct nbsmi_backend_data *priv_data = io_op->backend->data; + + if (!priv_data) + return -ENODEV; + + inputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL); + if (!inputbuffer) { + retval = -ENOMEM; + goto error1; + } + + outputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL); + if (!outputbuffer) { + retval = -ENOMEM; + goto error2; + } + + inputbuffer[0] = data; + + retval = nbsmi_smi_command((u16) io_op->write_addr, inputbuffer, outputbuffer, priv_data); + + kfree(outputbuffer); + error2: + kfree(inputbuffer); + error1: + return retval; +} + +/* + * Read/Write to INDEX/DATA interface at port 0x300 (SMSC Mailbox registers) + */ +static inline void nbsmi_ec_read_command(u8 index, u8 * data) +{ + outb(index, EC_INDEX_PORT); + *data = inb(EC_DATA_PORT); +} + +#if 0 +static inline void nbsmi_ec_write_command(u8 index, u8 data) +{ + outb(index, EC_INDEX_PORT); + outb(data, EC_DATA_PORT); +} +#endif + + +/* + * Hotkeys workflow: + * 1. Fn+Foo pressed + * 2. Scancode 0x6d generated by kbd controller + * 3. Scancode 0x6d caught by omnibook input handler + * 4. SMI Call issued -> Got keycode of last actually pressed Fn key + * 5. nbsmi_scan_table used to associate a detected keycode with a generated one + * 6. Generated keycode issued using the omnibook input device + */ + +/* + * The input handler should only bind with the standard AT keyboard. + * XXX: Scancode 0x6d won't be detected if the keyboard has already been + * grabbed (the Xorg event input driver do that) + */ +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) +static int hook_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) +static struct input_handle *hook_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +#else +static struct input_handle *hook_connect(struct input_handler *handler, + struct input_dev *dev, + struct input_device_id *id) +#endif +{ + struct input_handle *handle; + int error; + + /* the 0x0001 vendor magic number is found in atkbd.c */ + if(!(dev->id.bustype == BUS_I8042 && dev->id.vendor == 0x0001)) + goto out_nobind; + + if(!strstr(dev->phys, I8042_KBD_PHYS_DESC)) + goto out_nobind; + + dprintk("hook_connect for device %s.\n", dev->name); + + if(dev->grab) + printk(O_WARN "Input device is grabbed by %s, Fn hotkeys won't work.\n", + dev->grab->name); + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) + return -ENOMEM; +#else + return NULL; +#endif + + handle->dev = dev; + handle->handler = handler; + handle->name = "omnibook_scancode_hook"; + handle->private = handler->private; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) + error = input_register_handle(handle); + if (error) { + dprintk("register_handle failed\n"); + goto out_nobind_free; + } + error = input_open_device(handle); + if (error) { + dprintk("register_handle failed\n"); + input_unregister_handle(handle); + goto out_nobind_free; + } + +#else + error = input_open_device(handle); + if (error==0) dprintk("Input device opened\n"); + else { + dprintk("opening input device failed\n"); + goto out_nobind_free; + } +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) + return 0; +out_nobind_free: + kfree(handle); +out_nobind: + return -ENODEV; +#else + return handle; +out_nobind_free: + kfree(handle); +out_nobind: + return NULL; +#endif +} + +static void hook_disconnect(struct input_handle *handle) +{ + dprintk("hook_disconnect.\n"); + input_close_device(handle); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21)) + input_unregister_handle(handle); +#endif + kfree(handle); +} + +/* + * Hook for scancode 0x6d. Actual handling is done in a workqueue as + * the nbsmi backend might sleep. + */ + +static void hook_event(struct input_handle *handle, unsigned int event_type, + unsigned int event_code, int value) +{ + if (event_type == EV_MSC && event_code == MSC_SCAN && value == SMI_FN_SCAN) + schedule_work(&((struct nbsmi_backend_data *)handle->private)->fnkey_work); +} + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) +static const struct input_device_id hook_ids[] = { +#else +static struct input_device_id hook_ids[] = { +#endif + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT(EV_KEY) }, + }, + { }, /* Terminating entry */ +}; + +static struct input_handler hook_handler = { + .event = hook_event, + .connect = hook_connect, + .disconnect = hook_disconnect, + .name = OMNIBOOK_MODULE_NAME, + .id_table = hook_ids, +}; + +/* + * Define some KEY_ that may be missing in input.h for some kernel versions + */ +#ifndef KEY_WLAN +#define KEY_WLAN 238 +#endif + +/* + * Detected scancode to keycode table + */ +static const struct { + unsigned int scancode; + unsigned int keycode; +} nbsmi_scan_table[] = { + { KEY_ESC, KEY_MUTE}, + { KEY_F1, KEY_FN_F1}, + { KEY_F2, KEY_PROG1}, + { KEY_F3, KEY_SLEEP}, + { KEY_F4, KEY_SUSPEND}, + { KEY_F5, KEY_SWITCHVIDEOMODE}, + { KEY_F6, KEY_BRIGHTNESSDOWN}, + { KEY_F7, KEY_BRIGHTNESSUP}, + { KEY_F8, KEY_WLAN}, + { KEY_F9, KEY_FN_F9}, + { KEY_SPACE, KEY_ZOOM}, + { 0,0}, +}; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)) +static void omnibook_handle_fnkey(struct work_struct *work); +#else +static void omnibook_handle_fnkey(void* data); +#endif + +/* + * Register the input handler and the input device in the input subsystem + */ +static int register_input_subsystem(struct nbsmi_backend_data *priv_data) +{ + int i, retval = 0; + struct input_dev *nbsmi_input_dev; + + nbsmi_input_dev = input_allocate_device(); + if (!nbsmi_input_dev) { + retval = -ENOMEM; + goto out; + } + + nbsmi_input_dev->name = "Omnibook NbSMI scancode generator"; + nbsmi_input_dev->phys = "omnibook/input0"; + nbsmi_input_dev->id.bustype = BUS_HOST; + + set_bit(EV_KEY, nbsmi_input_dev->evbit); + + for(i=0 ; i < ARRAY_SIZE(nbsmi_scan_table); i++) + set_bit(nbsmi_scan_table[i].keycode, nbsmi_input_dev->keybit); + + retval = input_register_device(nbsmi_input_dev); + if(retval) { + input_free_device(nbsmi_input_dev); + goto out; + } + + priv_data->nbsmi_input_dev = nbsmi_input_dev; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)) + INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey); +#else + INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey, priv_data); +#endif + + + hook_handler.private = priv_data; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) + retval = input_register_handler(&hook_handler); +#else + input_register_handler(&hook_handler); +#endif + + out: + return retval; +} + +/* + * Try to init the backend + * This function can be called blindly as it use a kref + * to check if the init sequence was already done. + */ +static int omnibook_nbsmi_init(const struct omnibook_operation *io_op) +{ + int retval = 0; + int i; + u8 ec_data; + u32 smi_port = 0; + struct nbsmi_backend_data *priv_data; + + /* ectypes other than TSM40 have no business with this backend */ + if (!(omnibook_ectype & TSM40)) + return -ENODEV; + + if (io_op->backend->already_failed) { + dprintk("NbSmi backend init already failed, skipping.\n"); + return -ENODEV; + } + + if (!io_op->backend->data) { + /* Fist use of the backend */ + dprintk("Try to init NbSmi\n"); + mutex_init(&io_op->backend->mutex); + mutex_lock(&io_op->backend->mutex); + kref_init(&io_op->backend->kref); + + priv_data = kzalloc(sizeof(struct nbsmi_backend_data), GFP_KERNEL); + if (!priv_data) { + retval = -ENOMEM; + goto error0; + } + + /* PCI probing: find the LPC Super I/O bridge PCI device */ + for (i = 0; !priv_data->lpc_bridge && lpc_bridge_table[i].vendor; ++i) + priv_data->lpc_bridge = + pci_get_device(lpc_bridge_table[i].vendor, lpc_bridge_table[i].device, + NULL); + + if (!priv_data->lpc_bridge) { + printk(O_ERR "Fail to find a supported LPC I/O bridge, please report\n"); + retval = -ENODEV; + goto error1; + } + + if ((retval = pci_enable_device(priv_data->lpc_bridge))) { + printk(O_ERR "Unable to enable PCI device.\n"); + goto error2; + } + + switch (priv_data->lpc_bridge->vendor) { + case PCI_VENDOR_ID_INTEL: + priv_data->start_offset = INTEL_OFFSET; + smi_port = INTEL_SMI_PORT; + break; + case PCI_VENDOR_ID_ATI: + priv_data->start_offset = ATI_OFFSET; + smi_port = ATI_SMI_PORT; + break; + default: + BUG(); + } + + if (!request_region(smi_port, 2, OMNIBOOK_MODULE_NAME)) { + printk(O_ERR "Request SMI I/O region error\n"); + retval = -ENODEV; + goto error2; + } + + if (!request_region(EC_INDEX_PORT, 2, OMNIBOOK_MODULE_NAME)) { + printk(O_ERR "Request EC I/O region error\n"); + retval = -ENODEV; + goto error3; + } + + /* + * Try some heuristic tests to avoid enabling this interface on unsuported laptops: + * See what a port 300h read index 8f gives. Guess there is nothing if read 0xff + */ + + nbsmi_ec_read_command(SMI_FN_PRESSED, &ec_data); + dprintk("NbSmi test probe read: %x\n", ec_data); + if (ec_data == 0xff) { + printk(O_ERR "Probing at SMSC Mailbox registers failed, disabling NbSmi\n"); + retval = -ENODEV; + goto error4; + } + + retval = register_input_subsystem(priv_data); + if(retval) + goto error4; + + io_op->backend->data = priv_data; + + dprintk("NbSmi init ok\n"); + mutex_unlock(&io_op->backend->mutex); + return 0; + } else { + dprintk("NbSmi has already been initialized\n"); + kref_get(&io_op->backend->kref); + return 0; + } + error4: + release_region(EC_INDEX_PORT, 2); + error3: + release_region(smi_port, 2); + error2: + pci_dev_put(priv_data->lpc_bridge); + error1: + kfree(priv_data); + io_op->backend->data = NULL; + error0: + io_op->backend->already_failed = 1; + mutex_unlock(&io_op->backend->mutex); + mutex_destroy(&io_op->backend->mutex); + return retval; +} + +/* + * Free all allocated stuff and unregister from the input subsystem + */ +static void nbsmi_free(struct kref *ref) +{ + u32 smi_port = 0; + struct omnibook_backend *backend; + struct nbsmi_backend_data *priv_data; + + dprintk("NbSmi not used anymore: disposing\n"); + + backend = container_of(ref, struct omnibook_backend, kref); + priv_data = backend->data; + + flush_scheduled_work(); + input_unregister_handler(&hook_handler); + input_unregister_device(priv_data->nbsmi_input_dev); + + mutex_lock(&backend->mutex); + + switch (priv_data->lpc_bridge->vendor) { + case PCI_VENDOR_ID_INTEL: + smi_port = INTEL_SMI_PORT; + break; + case PCI_VENDOR_ID_ATI: + smi_port = ATI_SMI_PORT; + break; + default: + BUG(); + } + + pci_dev_put(priv_data->lpc_bridge); + release_region(smi_port, 2); + release_region(EC_INDEX_PORT, 2); + kfree(priv_data); + backend->data = NULL; + mutex_unlock(&backend->mutex); + mutex_destroy(&backend->mutex); +} + +static void omnibook_nbsmi_exit(const struct omnibook_operation *io_op) +{ + /* ectypes other than TSM40 have no business with this backend */ + BUG_ON(!(omnibook_ectype & TSM40)); + dprintk("Trying to dispose NbSmi\n"); + kref_put(&io_op->backend->kref, nbsmi_free); +} + +/* + * Adjust the lcd backlight level by delta. + * Used for Fn+F6/F7 keypress + */ +static int adjust_brighness(int delta) +{ + struct omnibook_feature *lcd_feature = omnibook_find_feature("lcd"); + struct omnibook_operation *io_op; + int retval = 0; + u8 brgt; + + if(!lcd_feature) + return -ENODEV; + + io_op = lcd_feature->io_op; + + mutex_lock(&io_op->backend->mutex); + + if(( retval = __backend_byte_read(io_op, &brgt))) + goto out; + + dprintk("FnF6/F7 pressed: adjusting britghtnes.\n"); + + if (((int) brgt + delta) < 0) + brgt = 0; + else if ((brgt + delta) > omnibook_max_brightness) + brgt = omnibook_max_brightness; + else + brgt += delta; + + retval = __backend_byte_write(io_op, brgt); + + out: + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +static const struct omnibook_operation last_scan_op = SIMPLE_BYTE(SMI,SMI_GET_FN_LAST_SCAN,0); + +/* + * Workqueue handler for Fn hotkeys + */ +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)) +static void omnibook_handle_fnkey(struct work_struct *work) +#else +static void omnibook_handle_fnkey(void* data) +#endif +{ + int i; + u8 gen_scan; + struct input_dev *input_dev; + + if(backend_byte_read(&last_scan_op, &gen_scan)) + return; + + dprintk("detected scancode %x.\n", gen_scan); + switch(gen_scan) { + case KEY_F6: + adjust_brighness(-1); + break; + case KEY_F7: + adjust_brighness(+1); + break; + } + + for(i = 0 ; i < ARRAY_SIZE(nbsmi_scan_table); i++) { + if( gen_scan == nbsmi_scan_table[i].scancode) { + dprintk("generating keycode %i.\n", nbsmi_scan_table[i].keycode); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)) + input_dev = container_of(work, struct nbsmi_backend_data, fnkey_work)->nbsmi_input_dev; +#else + input_dev = ((struct nbsmi_backend_data *) data)->nbsmi_input_dev; +#endif + omnibook_report_key(input_dev, nbsmi_scan_table[i].keycode); + break; + } + } +} + +static int omnibook_nbsmi_get_wireless(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval = 0; + struct omnibook_operation aerial_op = SIMPLE_BYTE(SMI, SMI_GET_KILL_SWITCH, 0); + u8 data; + + if ((retval = nbsmi_smi_read_command(&aerial_op, &data))) + goto out; + + dprintk("get_wireless (kill switch) raw_state: %x\n", data); + + *state = data ? KILLSWITCH : 0; + + aerial_op.read_addr = SMI_GET_AERIAL; + + if ((retval = nbsmi_smi_read_command(&aerial_op, &data))) + goto out; + + dprintk("get_wireless (aerial) raw_state: %x\n", data); + + *state |= (data & WLEX_MASK) ? WIFI_EX : 0; + *state |= (data & WLAT_MASK) ? WIFI_STA : 0; + *state |= (data & BTEX_MASK) ? BT_EX : 0; + *state |= (data & BTAT_MASK) ? BT_STA : 0; + + out: + return retval; +} + +static int omnibook_nbsmi_set_wireless(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval = 0; + u8 data; + struct omnibook_operation aerial_op = SIMPLE_BYTE(SMI, SMI_SET_AERIAL, 0); + + data = !!(state & BT_STA); + data |= !!(state & WIFI_STA) << 0x1; + + dprintk("set_wireless raw_state: %x\n", data); + + retval = nbsmi_smi_write_command(&aerial_op, data); + + return retval; +} + +static int omnibook_nbmsi_hotkeys_get(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval; + u8 data = 0; + struct omnibook_operation hotkeys_op = SIMPLE_BYTE(SMI, SMI_GET_FN_INTERFACE, 0); + + retval = nbsmi_smi_read_command(&hotkeys_op, &data); + if (retval < 0) + return retval; + + dprintk("get_hotkeys raw_state: %x\n", data); + + *state = (data & SMI_FN_KEYS_MASK) ? HKEY_FN : 0; + *state |= (data & SMI_STICK_KEYS_MASK) ? HKEY_STICK : 0; + *state |= (data & SMI_FN_TWICE_LOCK_MASK) ? HKEY_TWICE_LOCK : 0; + *state |= (data & SMI_FN_DOCK_MASK) ? HKEY_DOCK : 0; + + return 0; +} + + +static int omnibook_nbmsi_hotkeys_set(const struct omnibook_operation *io_op, unsigned int state) +{ + int i, retval; + u8 data, rdata; + struct omnibook_operation hotkeys_op = SIMPLE_BYTE(SMI, SMI_SET_FN_F5_INTERFACE, 0); + u8* data_array; + + data = !!(state & HKEY_FNF5); + + dprintk("set_hotkeys (Fn F5) raw_state: %x\n", data); + + retval = nbsmi_smi_write_command(&hotkeys_op, data); + if (retval < 0) + return retval; + + hotkeys_op.write_addr = SMI_SET_FN_INTERFACE; + hotkeys_op.read_addr = SMI_GET_FN_INTERFACE; + + data = (state & HKEY_FN) ? SMI_FN_KEYS_MASK : 0; + data |= (state & HKEY_STICK) ? SMI_STICK_KEYS_MASK : 0; + data |= (state & HKEY_TWICE_LOCK) ? SMI_FN_TWICE_LOCK_MASK : 0; + data |= (state & HKEY_DOCK) ? SMI_FN_DOCK_MASK : 0; + + dprintk("set_hotkeys (Fn interface) raw_state: %x\n", data); + + /* + * Hardware seems to be quite stubborn and multiple retries may be + * required. The criteria here is simple: retry until probed state match + * the requested one (with timeout). + */ + + data_array = kcalloc(250, sizeof(u8), GFP_KERNEL); + if(!data_array) + return -ENODEV; + + for (i = 0; i < 250; i++) { + retval = nbsmi_smi_write_command(&hotkeys_op, data); + if (retval) + goto out; + mdelay(1); + retval = nbsmi_smi_read_command(&hotkeys_op, &rdata); + if(retval) + goto out; + data_array[i] = rdata; + if(rdata == data) { + dprintk("check loop ok after %i iters\n.",i); + retval = 0; + goto out; + } + } + dprintk("error or check loop timeout !!\n"); + dprintk("forensics datas: "); + for (i = 0; i < 250; i++) + dprintk_simple("%x ", data_array[i]); + dprintk_simple("\n"); +out: + kfree(data_array); + return retval; +} + +static const unsigned int nbsmi_display_mode_list[] = { + DISPLAY_LCD_ON, + DISPLAY_LCD_ON | DISPLAY_CRT_ON, + DISPLAY_CRT_ON, + DISPLAY_LCD_ON | DISPLAY_TVO_ON, + DISPLAY_TVO_ON, +}; + +static int omnibook_nbmsi_display_get(const struct omnibook_operation *io_op, unsigned int *state) +{ + int retval = 0; + u8 data; + + retval = nbsmi_smi_read_command(io_op, &data); + if (retval < 0) + return retval; + + if (data > (ARRAY_SIZE(nbsmi_display_mode_list) - 1)) + return -EIO; + + *state = nbsmi_display_mode_list[data]; + + return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON; +} + +static int omnibook_nbmsi_display_set(const struct omnibook_operation *io_op, unsigned int state) +{ + int retval; + int i; + u8 matched = 255; + + for (i = 0; i < ARRAY_SIZE(nbsmi_display_mode_list); i++) { + if (nbsmi_display_mode_list[i] == state) { + matched = i; + break; + } + } + + if(matched == 255) { + printk(O_ERR "Display mode %x is unsupported.\n", state); + return -EINVAL; + } + + retval = nbsmi_smi_write_command(io_op, matched); + if (retval < 0) + return retval; + + return DISPLAY_LCD_ON | DISPLAY_CRT_ON | DISPLAY_TVO_ON; +} + +struct omnibook_backend nbsmi_backend = { + .name = "nbsmi", + .hotkeys_read_cap = HKEY_FN | HKEY_STICK | HKEY_TWICE_LOCK | HKEY_DOCK, + .hotkeys_write_cap = HKEY_FN | HKEY_STICK | HKEY_TWICE_LOCK | HKEY_DOCK | HKEY_FNF5, + .init = omnibook_nbsmi_init, + .exit = omnibook_nbsmi_exit, + .byte_read = nbsmi_smi_read_command, + .byte_write = nbsmi_smi_write_command, + .aerial_get = omnibook_nbsmi_get_wireless, + .aerial_set = omnibook_nbsmi_set_wireless, + .hotkeys_get = omnibook_nbmsi_hotkeys_get, + .hotkeys_set = omnibook_nbmsi_hotkeys_set, + .display_get = omnibook_nbmsi_display_get, + .display_set = omnibook_nbmsi_display_set, +}; --- linux-2.6.37.orig/ubuntu/omnibook/omnibook.h +++ linux-2.6.37/ubuntu/omnibook/omnibook.h @@ -0,0 +1,145 @@ +/* + * omnibook.h -- High level data structures and functions of omnibook + * support code + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006-2007 + */ + +#include +#include +#include +#include + +/* + * EC types + */ + +extern enum omnibook_ectype_t { + NONE = 0, /* 0 Default/unknown EC type */ + XE3GF = (1<<0), /* 1 HP OmniBook XE3 GF, most old Toshiba Satellites */ + XE3GC = (1<<1), /* 2 HP OmniBook XE3 GC, GD, GE and compatible */ + OB500 = (1<<2), /* 3 HP OmniBook 500 and compatible */ + OB510 = (1<<3), /* 4 HP OmniBook 510 */ + OB6000 = (1<<4), /* 5 HP OmniBook 6000 */ + OB6100 = (1<<5), /* 6 HP OmniBook 6100 */ + XE4500 = (1<<6), /* 7 HP OmniBook xe4500 and compatible */ + OB4150 = (1<<7), /* 8 HP OmniBook 4150 */ + XE2 = (1<<8), /* 9 HP OmniBook XE2 */ + AMILOD = (1<<9), /* 10 Fujitsu Amilo D */ + TSP10 = (1<<10), /* 11 Toshiba Satellite P10, P15, P20 and compatible */ + TSM70 = (1<<11), /* 12 Toshiba Satellite M40X, M70 and compatible */ + TSM40 = (1<<12), /* 13 Toshiba Satellite M40, M45 and Tecra S1 */ + TSA105 = (1<<13), /* 14 Toshiba Satellite A105 and compatible (Real support is MISSING) */ + TSM30X = (1<<14), /* 15 Toshiba Stallite M30X and compatible */ + TSX205 = (1<<15) /* 16 Toshiba Stallite X205 and compatible */ +} omnibook_ectype; + +#define ALL_ECTYPES XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|OB4150|XE2|AMILOD|TSP10|TSM70|TSM40|TSA105|TSM30X|TSX205 + +/* + * This represent a feature provided by this module + */ + +struct omnibook_operation; + +struct omnibook_feature { + char *name; /* Name */ + int enabled; /* Set from module parameter */ + int (*read) (char *,struct omnibook_operation *); /* Procfile read function */ + int (*write) (char *,struct omnibook_operation *); /* Procfile write function */ + int (*init) (struct omnibook_operation *); /* Specific Initialization function */ + void (*exit) (struct omnibook_operation *); /* Specific Cleanup function */ + int (*suspend) (struct omnibook_operation *); /* PM Suspend function */ + int (*resume) (struct omnibook_operation *); /* PM Resume function */ + int ectypes; /* Type(s) of EC we support for this feature (bitmask) */ + struct omnibook_tbl *tbl; + struct omnibook_operation *io_op; + struct list_head list; +}; + +/* + * State of a Wifi/Bluetooth adapter + */ +enum { + WIFI_EX = (1<<0), /* 1 1=present 0=absent */ + WIFI_STA = (1<<1), /* 2 1=enabled 0=disabled */ + KILLSWITCH = (1<<2), /* 4 1=radio on 0=radio off */ + BT_EX = (1<<3), /* 8 1=present 0=absent */ + BT_STA = (1<<4), /* 16 1=enabled 0=disabled */ +}; + +/* + * Hotkeys state backend neutral masks + */ +enum { + HKEY_ONETOUCH = (1<<0), /* 1 Ontetouch button scancode generation */ + HKEY_MULTIMEDIA = (1<<1), /* 2 "Multimedia hotkeys" scancode generation */ + HKEY_FN = (1<<2), /* 4 Fn + foo hotkeys scancode generation */ + HKEY_STICK = (1<<3), /* 8 Stick key (Fn locked/unlocked on keypress) */ + HKEY_TWICE_LOCK = (1<<4), /* 16 Press Fn twice to lock */ + HKEY_DOCK = (1<<5), /* 32 (Un)Dock events scancode generation */ + HKEY_FNF5 = (1<<6), /* 64 Fn + F5 (toggle display) is enabled */ +}; + +#define HKEY_LAST_SHIFT 6 + +/* + * Display state backend neutral masks + * _ON masks = port is powered up and running + * _DET masks = a plugged display have been detected + */ + +enum { + DISPLAY_LCD_ON = (1<<0), /* 1 Internal LCD panel */ + DISPLAY_CRT_ON = (1<<1), /* 2 External VGA port */ + DISPLAY_TVO_ON = (1<<2), /* 4 External TV-OUT port */ + DISPLAY_DVI_ON = (1<<3), /* 8 External DVI port */ + DISPLAY_LCD_DET = (1<<4), /* 16 Internal LCD panel */ + DISPLAY_CRT_DET = (1<<5), /* 32 External VGA port */ + DISPLAY_TVO_DET = (1<<6), /* 64 External TV-OUT port */ + DISPLAY_DVI_DET = (1<<7), /* 128 External DVI port */ +}; + +extern unsigned int omnibook_max_brightness; +int set_omnibook_param(const char *val, struct kernel_param *kp); +int omnibook_lcd_blank(int blank); +struct omnibook_feature *omnibook_find_feature(char *name); +void omnibook_report_key(struct input_dev *dev, unsigned int keycode); + +/* + * __attribute_used__ is not defined anymore in 2.6.24 + * but __used appeared only in 2.6.22 + */ +#ifndef __used +#define __used __attribute_used__ +#endif + +#define __declared_feature __attribute__ (( __section__(".features"), __aligned__(__alignof__ (struct omnibook_feature)))) __used + +/* + * yet another printk wrapper + */ +#define O_INFO KERN_INFO OMNIBOOK_MODULE_NAME ": " +#define O_WARN KERN_WARNING OMNIBOOK_MODULE_NAME ": " +#define O_ERR KERN_ERR OMNIBOOK_MODULE_NAME ": " + +#ifdef CONFIG_OMNIBOOK_DEBUG +#define dprintk(fmt, args...) printk(KERN_INFO "%s: " fmt, OMNIBOOK_MODULE_NAME, ## args) +#define dprintk_simple(fmt, args...) printk(fmt, ## args) +#else +#define dprintk(fmt, args...) do { } while(0) +#define dprintk_simple(fmt, args...) do { } while(0) +#endif + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/pio.c +++ linux-2.6.37/ubuntu/omnibook/pio.c @@ -0,0 +1,173 @@ +/* + * pio.c -- low level functions I/O ports + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" + +#include +#include +#include +#include +#include + +#include +#include "hardware.h" + +/* + * IO port backend. Only support single or dual ports operations + * private data structure: it's the linked list of requested ports + * + * Race condition issue: omnibook_pio_init/exit functions are only called from + * omnibook_backend_match and omnibook_remove from init.c, this should happen + * only at module init/exit time so there is no need for a lock. + */ + +struct pio_priv_data_t { + unsigned long addr; + struct kref refcount; + struct list_head list; +}; + +static struct pio_priv_data_t pio_priv_data = { + .addr = 0, + .list = LIST_HEAD_INIT(pio_priv_data.list), +}; + +/* + * Match an entry in the linked list helper function: see if we have and entry + * whose addr field match maddr + */ +static struct pio_priv_data_t *omnibook_match_port(struct pio_priv_data_t *data, + unsigned long maddr) +{ + struct pio_priv_data_t *cursor; + + list_for_each_entry(cursor, &data->list, list) { + if (cursor->addr == maddr) { + return cursor; + } + } + return NULL; +} + +/* + * See if we have to request raddr + */ +static int omnibook_claim_port(struct pio_priv_data_t *data, unsigned long raddr) +{ + struct pio_priv_data_t *match, *new; + + match = omnibook_match_port(data, raddr); + if (match) { + /* Already requested by us: increment kref and quit */ + kref_get(&match->refcount); + return 0; + } + + /* there was no match: request the region and add to list */ + if (!request_region(raddr, 1, OMNIBOOK_MODULE_NAME)) { + printk(O_ERR "Request I/O port error\n"); + return -ENODEV; + } + + new = kmalloc(sizeof(struct pio_priv_data_t), GFP_KERNEL); + if (!new) { + release_region(raddr, 1); + return -ENOMEM; + } + + kref_init(&new->refcount); + new->addr = raddr; + list_add(&new->list, &data->list); + + return 0; +} + +/* + * Register read_addr and write_addr + */ +static int omnibook_pio_init(const struct omnibook_operation *io_op) +{ + int retval = 0; + + if (io_op->read_addr + && (retval = omnibook_claim_port(io_op->backend->data, io_op->read_addr))) + goto out; + + if (io_op->write_addr && (io_op->write_addr != io_op->read_addr)) + retval = omnibook_claim_port(io_op->backend->data, io_op->write_addr); + + out: + return retval; +} + +/* + * REALLY release a port + */ +static void omnibook_free_port(struct kref *ref) +{ + struct pio_priv_data_t *data; + + data = container_of(ref, struct pio_priv_data_t, refcount); + release_region(data->addr, 1); + list_del(&data->list); + kfree(data); +} + +/* + * Unregister read_addr and write_addr + */ +static void omnibook_pio_exit(const struct omnibook_operation *io_op) +{ + struct pio_priv_data_t *match; + + match = omnibook_match_port(io_op->backend->data, io_op->read_addr); + if (match) + kref_put(&match->refcount, omnibook_free_port); + + match = omnibook_match_port(io_op->backend->data, io_op->write_addr); + if (match) + kref_put(&match->refcount, omnibook_free_port); + +} + +static int omnibook_io_read(const struct omnibook_operation *io_op, u8 * value) +{ + *value = inb(io_op->read_addr); + if (io_op->read_mask) + *value &= io_op->read_mask; + return 0; +} + +static int omnibook_io_write(const struct omnibook_operation *io_op, u8 value) +{ + outb(io_op->write_addr, value); + return 0; +} + +/* + * Backend interface declarations + */ +struct omnibook_backend pio_backend = { + .name = "pio", + .data = &pio_priv_data, + .init = omnibook_pio_init, + .exit = omnibook_pio_exit, + .byte_read = omnibook_io_read, + .byte_write = omnibook_io_write, +}; + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/polling.c +++ linux-2.6.37/ubuntu/omnibook/polling.c @@ -0,0 +1,259 @@ +/* + * polling.c -- scancode emulation for volume buttons + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" +#include "hardware.h" +#include +#include + +/* + * XE3GC type key_polling polling: + * + * Polling interval for keys (100 ms) + */ + +#define OMNIBOOK_POLL msecs_to_jiffies(100) + +/* + * workqueue manipulations are mutex protected and thus kept in sync with key_polling_enabled + */ +static struct workqueue_struct *omnibook_wq; +static int key_polling_enabled; +static DEFINE_MUTEX(poll_mutex); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)) +static void omnibook_key_poller(struct work_struct *work); +DECLARE_DELAYED_WORK(omnibook_poll_work, *omnibook_key_poller); +#else +static void omnibook_key_poller(void *data); +DECLARE_WORK(omnibook_poll_work, *omnibook_key_poller, NULL); +#endif + +static struct omnibook_feature key_polling_driver; +static struct input_dev *poll_input_dev; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,19)) + static void omnibook_key_poller(struct work_struct *work) +#else + static void omnibook_key_poller(void *data) +#endif +{ + u8 q0a; + int retval; + + mutex_lock(&key_polling_driver.io_op->backend->mutex); + __backend_byte_read(key_polling_driver.io_op, &q0a); + __backend_byte_write(key_polling_driver.io_op, 0); + mutex_unlock(&key_polling_driver.io_op->backend->mutex); + +#ifdef CONFIG_OMNIBOOK_DEBUG + if (unlikely(q0a & XE3GC_SLPB_MASK)) + dprintk("Sleep button pressed.\n"); + if (unlikely(q0a & XE3GC_F5_MASK)) + dprintk("Fn-F5 - LCD/CRT switch pressed.\n"); + if (unlikely(q0a & XE3GC_CNTR_MASK)) + dprintk("Fn+F3/Fn+F4 - Contrast up or down pressed.\n"); + if (unlikely(q0a & XE3GC_BRGT_MASK)) + dprintk("Fn+F1/Fn+F2 - Brightness up or down pressed.\n"); +#endif + + /* + * Volume button scancode emulaton + * It emulates a key press and a release without repeat as other OneTouch buttons do. + */ + + if (unlikely(q0a & XE3GC_VOLD_MASK)) { + dprintk("Fn-down arrow or Volume down pressed.\n"); + omnibook_report_key(poll_input_dev, KEY_VOLUMEDOWN); + } + if (unlikely(q0a & XE3GC_VOLU_MASK)) { + dprintk("Fn-up arrow or Volume up pressed.\n"); + omnibook_report_key(poll_input_dev, KEY_VOLUMEUP); + } + if (unlikely(q0a & XE3GC_MUTE_MASK)) { + dprintk("Fn+F7 - Volume mute pressed.\n"); + omnibook_report_key(poll_input_dev, KEY_MUTE); + } + + retval = queue_delayed_work(omnibook_wq, &omnibook_poll_work, OMNIBOOK_POLL); + if(unlikely(!retval)) /* here non-zero on success */ + printk(O_ERR "Key_poller failed to rearm.\n"); +} + +static int omnibook_key_polling_enable(void) +{ + int retval = 0; + + if(mutex_lock_interruptible(&poll_mutex)) + return -ERESTARTSYS; + + if(key_polling_enabled) + goto out; + + retval = !queue_delayed_work(omnibook_wq, &omnibook_poll_work, OMNIBOOK_POLL); + if(retval) + printk(O_ERR "Key_poller enabling failed.\n"); + else { + dprintk("Scancode emulation for volume buttons enabled.\n"); + key_polling_enabled = 1; + } + + out: + mutex_unlock(&poll_mutex); + return retval; +} + +static int omnibook_key_polling_disable(void) +{ + if(mutex_lock_interruptible(&poll_mutex)) + return -ERESTARTSYS; + + if(!key_polling_enabled) + goto out; + + cancel_rearming_delayed_workqueue(omnibook_wq, &omnibook_poll_work); + dprintk("Scancode emulation for volume buttons disabled.\n"); + key_polling_enabled = 0; + + out: + mutex_unlock(&poll_mutex); + return 0; +} + + +static int omnibook_key_polling_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + + if(mutex_lock_interruptible(&poll_mutex)) + return -ERESTARTSYS; + + len += sprintf(buffer + len, "Volume buttons polling is %s.\n", + (key_polling_enabled) ? "enabled" : "disabled"); +#ifdef CONFIG_OMNIBOOK_DEBUG + if(key_polling_enabled) + len += sprintf(buffer + len, "Will poll in %i msec.\n", + jiffies_to_msecs(omnibook_poll_work.timer.expires - jiffies)); +#endif + mutex_unlock(&poll_mutex); + return len; +} + +static int omnibook_key_polling_write(char *buffer, struct omnibook_operation *io_op) +{ + int retval; + switch (*buffer) { + case '0': + retval = omnibook_key_polling_disable(); + break; + case '1': + retval = omnibook_key_polling_enable(); + break; + default: + retval = -EINVAL; + } + return retval; +} + + +/* + * Stop polling upon suspend an restore it upon resume + */ +static int omnibook_key_polling_resume(struct omnibook_operation *io_op) +{ + int retval = 0; + + mutex_lock(&poll_mutex); + if(key_polling_enabled) + retval = !queue_delayed_work(omnibook_wq, &omnibook_poll_work, OMNIBOOK_POLL); + mutex_unlock(&poll_mutex); + return retval; +} + +static int omnibook_key_polling_suspend(struct omnibook_operation *io_op) +{ + mutex_lock(&poll_mutex); + if(key_polling_enabled) + cancel_rearming_delayed_workqueue(omnibook_wq, &omnibook_poll_work); + mutex_unlock(&poll_mutex); + return 0; +} + +static int __init omnibook_key_polling_init(struct omnibook_operation *io_op) +{ + int retval = 0; + + poll_input_dev = input_allocate_device(); + if (!poll_input_dev) { + retval = -ENOMEM; + goto out; + } + + poll_input_dev->name = "Omnibook legacy laptop scancode generator"; + poll_input_dev->phys = "omnibook/input0"; + poll_input_dev->id.bustype = BUS_HOST; + + /* this device has three keys */ + set_bit(EV_KEY, poll_input_dev->evbit); + set_bit(KEY_VOLUMEDOWN, poll_input_dev->keybit); + set_bit(KEY_VOLUMEUP, poll_input_dev->keybit); + set_bit(KEY_MUTE, poll_input_dev->keybit); + + retval = input_register_device(poll_input_dev); + if (retval) { + input_free_device(poll_input_dev); + goto out; + } + + omnibook_wq = create_singlethread_workqueue("omnibook"); + if(!omnibook_wq) + retval = -ENOMEM; + else + retval = omnibook_key_polling_enable(); + +out: + return retval; +} + +static void __exit omnibook_key_polling_cleanup(struct omnibook_operation *io_op) +{ + omnibook_key_polling_disable(); + destroy_workqueue(omnibook_wq); + input_unregister_device(poll_input_dev); +} + +static struct omnibook_tbl key_polling_table[] __initdata = { + {XE3GC, SIMPLE_BYTE(EC, XE3GC_Q0A, 0)}, + {0,} +}; + +static struct omnibook_feature __declared_feature key_polling_driver = { + .name = "key_polling", + .enabled = 0, /* dangerous */ + .read = omnibook_key_polling_read, + .write = omnibook_key_polling_write, + .init = omnibook_key_polling_init, + .exit = omnibook_key_polling_cleanup, + .suspend = omnibook_key_polling_suspend, + .resume = omnibook_key_polling_resume, + .ectypes = XE3GC, + .tbl = key_polling_table, +}; + +module_param_named(key_polling, key_polling_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(key_polling, "Use 0 to disable, 1 to enable key polling"); +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/sections.lds +++ linux-2.6.37/ubuntu/omnibook/sections.lds @@ -0,0 +1,11 @@ +SECTIONS +{ + .data : + { + . = ALIGN(32); + _start_features_driver = .; + *(.features) + _end_features_driver = .; + *(.data) + } +} --- linux-2.6.37.orig/ubuntu/omnibook/temperature.c +++ linux-2.6.37/ubuntu/omnibook/temperature.c @@ -0,0 +1,55 @@ +/* + * temperature.c -- CPU temprature monitoring + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" +#include "hardware.h" + +static int omnibook_temperature_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + int retval; + u8 temp; + + if ((retval = backend_byte_read(io_op, &temp))) + return retval; + + len += sprintf(buffer + len, "CPU temperature: %2d C\n", temp); + + return len; +} + +static struct omnibook_tbl temp_table[] __initdata = { + {XE3GF | TSP10 | TSM70 | TSM30X | TSX205, SIMPLE_BYTE(EC, XE3GF_CTMP, 0)}, + {XE3GC | AMILOD, SIMPLE_BYTE(EC, XE3GC_CTMP, 0)}, + {OB500 | OB510 | OB6000 | OB6100 | XE4500 | XE2, SIMPLE_BYTE(EC, OB500_CTMP, 0)}, + {OB4150, SIMPLE_BYTE(EC, OB4150_TMP, 0)}, + {0,} +}; + +static struct omnibook_feature __declared_feature temperature_driver = { + .name = "temperature", + .enabled = 1, + .read = omnibook_temperature_read, + .ectypes = + XE3GF | XE3GC | OB500 | OB510 | OB6000 | OB6100 | XE4500 | OB4150 | XE2 | AMILOD | TSP10 + | TSM70 | TSM30X | TSX205, + .tbl = temp_table, +}; + +module_param_named(temperature, temperature_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(temperature, "Use 0 to disable, 1 to enable thermal status and policy support"); +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/throttling.c +++ linux-2.6.37/ubuntu/omnibook/throttling.c @@ -0,0 +1,83 @@ +/* + * throttling.c --CPU throttling control feature + * + * 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, 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. + * + * Written by Mathieu Bérard , 2007 + */ + +#include "omnibook.h" +#include "hardware.h" + +/* + * Throttling level/rate mapping found in ICH6M datasheets + * the output is set to mimic the one of /proc/acpi/cpu/CPU0/throttling + * XXX: We always assume that there are 8 T-States and one processor. + */ +static const int trate[8] = { 0, 12, 25, 37, 50, 62, 75, 87 }; + +static int omnibook_throttle_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + int tstate = 0; + int retval, i; + + retval = backend_throttle_get(io_op, &tstate); + if (retval < 0) + return retval; + + len += sprintf(buffer + len, "state count: 8\n"); + len += sprintf(buffer + len, "active state: T%d\n", tstate); + for (i = 0; i < 8; i += 1) + { + len += sprintf(buffer + len, " %cT%d: %02d%%\n", + (i == tstate ? '*' : ' '), + i, + trate[i]); + } + + return len; +} + +static int omnibook_throttle_write(char *buffer, struct omnibook_operation *io_op) +{ + int retval = 0; + int data; + char *endp; + + data = simple_strtoul(buffer, &endp, 10); + if ((endp == buffer) || (data > 7)) /* There are 8 throttling levels */ + return -EINVAL; + else + retval = backend_throttle_set(io_op, data); + + return retval; +} + + +static struct omnibook_tbl throttle_table[] __initdata = { + {TSM70 | TSX205, {ACPI,}}, + {0,} +}; + +struct omnibook_feature __declared_feature throttle_driver = { + .name = "throttling", + .enabled = 1, + .read = omnibook_throttle_read, + .write = omnibook_throttle_write, + .ectypes = TSM70 | TSX205, + .tbl = throttle_table, +}; + +module_param_named(throttle, throttle_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(throttle, "Use 0 to disable, 1 to enable CPU throttling control"); + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/touchpad.c +++ linux-2.6.37/ubuntu/omnibook/touchpad.c @@ -0,0 +1,126 @@ +/* + * touchpad.c -- enable/disable touchpad + * + * 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, 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. + * + * Written by Soós Péter , 2002-2004 + * Modified by Mathieu Bérard , 2006 + */ + +#include "omnibook.h" +#include "hardware.h" + +static int omnibook_touchpad_set(struct omnibook_operation *io_op, int status) +{ + int retval = 0; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + if ((retval = __omnibook_toggle(io_op, !!status))) { + printk(O_ERR "Failed touchpad %sable command.\n", status ? "en" : "dis"); + goto out; + } + + io_op->backend->touchpad_state = !!status; + + out: + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +/* + * Power management handlers: redisable touchpad on resume (if necessary) + */ +static int omnibook_touchpad_resume(struct omnibook_operation *io_op) +{ + int retval; + mutex_lock(&io_op->backend->mutex); + retval = __omnibook_toggle(io_op, !!io_op->backend->touchpad_state); + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +/* + * Hardware query is unsupported, so reading is unreliable. + */ +static int omnibook_touchpad_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + len += + sprintf(buffer + len, "Last touchpad action was an %s command.\n", + io_op->backend->touchpad_state ? "enable" : "disable"); + + mutex_unlock(&io_op->backend->mutex); + return len; +} + +static int omnibook_touchpad_write(char *buffer, struct omnibook_operation *io_op) +{ + int cmd; + + if (*buffer == '0' || *buffer == '1') { + cmd = *buffer - '0'; + if (!omnibook_touchpad_set(io_op, cmd)) { + dprintk("%sabling touchpad.\n", cmd ? "En" : "Dis"); + } + } else { + return -EINVAL; + } + return 0; +} + + +static int __init omnibook_touchpad_init(struct omnibook_operation *io_op) +{ + mutex_lock(&io_op->backend->mutex); + /* Touchpad is assumed to be enabled by default */ + io_op->backend->touchpad_state = 1; + mutex_unlock(&io_op->backend->mutex); + return 0; +} + +/* + * Reenable touchpad upon exit + */ +static void __exit omnibook_touchpad_cleanup(struct omnibook_operation *io_op) +{ + omnibook_touchpad_set(io_op, 1); + printk(O_INFO "Enabling touchpad.\n"); +} + +static struct omnibook_tbl touchpad_table[] __initdata = { + {XE3GF | XE3GC | TSP10, + COMMAND(KBC, OMNIBOOK_KBC_CMD_TOUCHPAD_ENABLE, OMNIBOOK_KBC_CMD_TOUCHPAD_DISABLE)}, + {TSM70, {CDI, 0, TSM70_FN_INDEX, 0, TSM70_TOUCHPAD_ON, TSM70_TOUCHPAD_OFF}}, + {0,} +}; + +static struct omnibook_feature __declared_feature touchpad_driver = { + .name = "touchpad", + .enabled = 1, + .read = omnibook_touchpad_read, + .write = omnibook_touchpad_write, + .init = omnibook_touchpad_init, + .exit = omnibook_touchpad_cleanup, + .resume = omnibook_touchpad_resume, + .ectypes = XE3GF | XE3GC | TSP10 | TSM70, + .tbl = touchpad_table, +}; + +module_param_named(touchpad, touchpad_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(touchpad, "Use 0 to disable, 1 to enable touchpad handling"); + +/* End of file */ --- linux-2.6.37.orig/ubuntu/omnibook/wireless.c +++ linux-2.6.37/ubuntu/omnibook/wireless.c @@ -0,0 +1,108 @@ +/* + * wireless.c Wifi feature + * + * 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, 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. + * + * Written by Mathieu Bérard , 2006 + * + */ + +#include "omnibook.h" +#include "hardware.h" + +static int omnibook_wifi_read(char *buffer, struct omnibook_operation *io_op) +{ + int len = 0; + int retval; + unsigned int state; + + if ((retval = backend_aerial_get(io_op, &state))) + return retval; + + len += + sprintf(buffer + len, "Wifi adapter is %s", (state & WIFI_EX) ? "present" : "absent"); + if (state & WIFI_EX) + len += + sprintf(buffer + len, " and %s", (state & WIFI_STA) ? "enabled" : "disabled"); + len += sprintf(buffer + len, ".\n"); + len += + sprintf(buffer + len, "Wifi Kill switch is %s.\n", (state & KILLSWITCH) ? "on" : "off"); + + return len; + +} + +static int omnibook_wifi_write(char *buffer, struct omnibook_operation *io_op) +{ + int retval = 0; + unsigned int state; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + if ((retval = __backend_aerial_get(io_op, &state))) + goto out; + + if (*buffer == '0') + state &= ~WIFI_STA; + else if (*buffer == '1') + state |= WIFI_STA; + else { + retval = -EINVAL; + goto out; + } + + if ((retval = __backend_aerial_set(io_op, state))) + return retval; + + out: + mutex_unlock(&io_op->backend->mutex); + return retval; +} + +static struct omnibook_feature wifi_driver; + +static int __init omnibook_wifi_init(struct omnibook_operation *io_op) +{ + int retval = 0; + unsigned int state; + +/* + * Refuse enabling/disabling a non-existent device + */ + + if ((retval = backend_aerial_get(io_op, &state))) + return retval; + + if (!(state & WIFI_EX)) + wifi_driver.write = NULL; + + return retval; +} + +static struct omnibook_tbl wireless_table[] __initdata = { + {TSM70 | TSX205, {ACPI,}}, /* stubs to select backend */ + {TSM40, {SMI,}}, /* stubs to select backend */ + {0,} +}; + +static struct omnibook_feature __declared_feature wifi_driver = { + .name = "wifi", + .enabled = 1, + .read = omnibook_wifi_read, + .write = omnibook_wifi_write, + .init = omnibook_wifi_init, + .ectypes = TSM70 | TSM40 | TSX205, + .tbl = wireless_table, +}; + +module_param_named(wifi, wifi_driver.enabled, int, S_IRUGO); +MODULE_PARM_DESC(wifi, "Use 0 to disable, 1 to enable Wifi adapter control"); --- linux-2.6.37.orig/ubuntu/omnibook/debian/README.Debian +++ linux-2.6.37/ubuntu/omnibook/debian/README.Debian @@ -0,0 +1,30 @@ +omnibook for Debian +------------------- + +Please see docs/README for a description of the omnibook kernel module. + +The Debian omnibook source package provides omnibook-source, package +which provides the source for the kernel module. + +The omnibook-source package can be used in several ways, + + - Using the make-kpkg(1) command provided by the kernel-package Debian + package. This will produce a corresponding omnibook-modules package for + the Debian kernel-image package that you are using. + See the "modules_image" section of the make-kpkg(1) man page. + + - Using module-assistant. Simply issue the following command (as root): + $ module-assistant auto-install omnibook + Please see the module-assistant documentation for futher details. + + - Changing to the /usr/src/modules/omnibook/ directory and building as + the README file instructs using "make; make install". This will build + and install a module specific to the system you are building on and is + not under control of the packaging system. + +If your are not using module-assisatant, you have to unpack +/usr/src/omnibook-source.tar.bz2 to /usr/src. + + -- Peter Soos , Wed, 25 Jan 2006 21:06:28 +0100 + -- Julien Valroff Sun, 07 Oct 2007 10:38:07 +0200 + --- linux-2.6.37.orig/ubuntu/omnibook/debian/changelog +++ linux-2.6.37/ubuntu/omnibook/debian/changelog @@ -0,0 +1,170 @@ +omnibook (2:2.20070211+svn20090714b-1) unstable; urgency=low + + * New SVN snapshot: + + fix build issue induced by previous patches + + fix build with kernel >= 2.6.30 + + -- Julien Valroff Tue, 14 Jul 2009 18:17:49 +0200 + +omnibook (2:2.20070211+svn20090714-1) unstable; urgency=low + + * New SVN snapshot: + + Applied patches from Azael Avalos + to add support to Satellite X205 and other laptops based on + ICH8 + * New Standards version 3.8.2 + * Bumped DH compat to 7 + * Updated copyright information + * Now use dh_prep instead of dh_clean -k + + -- Julien Valroff Tue, 14 Jul 2009 10:03:00 +0200 + +omnibook (2:2.20070211+svn20090227-1) unstable; urgency=low + + * New SVN snapshot + + Applied patch from Danny Kukawka to + fix compiler warning about use uninitialized variable + + Applied patch from Danny Kukawka to + fix build the driver on older kernel versions + + * New Standards version 3.8.0 - no further changes needed + * Updated copryight information + + -- Julien Valroff Fri, 27 Feb 2009 19:57:35 +0100 + +omnibook (2:2.20070211+svn20071217-1) unstable; urgency=low + + * New SVN snapshot (r271) + * Added amd64 as a compatible architecture for the module + * New Standards version 3.7.3 - no further changes needed + + -- Julien Valroff Mon, 17 Dec 2007 18:00:29 +0100 + +omnibook (2:2.20070211+svn20071006-1) unstable; urgency=low + + * New SVN snapshot (r264): + + Update for acpi and backlight API changes in linux 2.6.23 + * First upload to Debian (Closes: #445602): + + Improved debian/copyright + + Bumped debhelper compat to version 5 + + Added myself as maintainer + + Updated README.Debian + * debian/control: + + Moved Homepage to own field (from pseudo-field in long description) + + Added Vcs-* fields + + -- Julien Valroff Thu, 29 Nov 2007 18:30:27 +0100 + +omnibook (2:2.20070211+svn20070905-1) unstable; urgency=low + + * Added dependency on dpatch + * [debian/rules]: + - Fixed lintian warning in the clean target + + -- Julien Valroff Wed, 05 Sep 2007 20:25:13 +0200 + +omnibook (2:2.20070211+svn20070526-1) unstable; urgency=low + + * New SVN snapshot (r259): + + Fixed compilation issue with kernel 2.6.21 + + DMI signature added: + Toshiba Satellite P25 (ectype 11) + Toshiba Satellite M60 (ectype 12) + * Added patch to disable debug for SVN snasphot + + -- Julien Valroff Sat, 26 May 2007 15:19:57 +0200 + +omnibook (2:2.20070211-1) unstable; urgency=low + + * New upstream release: + + For ectype 12 (Satellite M40X, M70, M100, ...): + - improved bluetooth control + - cooling method control + - CPU throttling ( ACPI T-States) + + Full hotkeys support for Tecra S1 + + Bluetooth control for Ectype 14 (Satellite A100, A105, M115, ...) + * Updated homepage in long description + + -- Julien Valroff Mon, 12 Feb 2007 18:50:05 +0100 + +omnibook (2:2.20060921+svn20061202-1) unstable; urgency=low + + * New SVN snapshot (r228) + + -- Julien Valroff Sat, 2 Dec 2006 10:17:07 +0100 + +omnibook (2:2.20060921+svn20061112-1) unstable; urgency=low + + * SVN snapshot: + + Disabled Acer support + + Fixed and improved bluetooth handling for TSM30X class laptop + + DMI signature added: + HP Pavilion ze4500 (ectype 7) + Toshiba Satellite 1130 (ectype 1) + Toshiba Satellite A75 (ectype 12) + Toshiba Tecra A4 (ectype 13) + + Implemented Volume down,up and Mute buttons polling for ectype 2 + + Implemented ectype 13 Fn hotkeys handling. + * changed compression of the sources in /usr/src/ to bzip2 + + -- Julien Valroff Sat, 11 Nov 2006 14:08:47 +0100 + +omnibook (2:2.20060921-1) unstable; urgency=low + + * New upstream release: + + Expand display and hotkeys features + + Added support for more laptops + + Code cleanups + + Minor bug fixes + + -- Julien Valroff Mon, 25 Sep 2006 08:14:59 +0200 + +omnibook (2:2.20060817-1) unstable; urgency=low + + * New upstream release + * [01_makfefile.dpatch] Removed - fixed upstream + * Changed defaut STEM value to linux (follows kernel-package) + * Uses dh_installmodules for maintainance scripts + + -- Julien Valroff Mon, 11 Sep 2006 18:00:50 +0200 + +omnibook (2:2.20060809-2) unstable; urgency=low + + * Include copyright and Debian changelog in omnibook-module + * Fix Makefile issue in a more elegant way + + -- Julien Valroff Thu, 10 Aug 2006 10:16:47 +0200 + +omnibook (2:2.20060809-1) unstable; urgency=low + + * New upstream release: + + Addeed autodetection of the Toshiba Satellite M40X laptop + + -- Julien Valroff Thu, 10 Aug 2006 09:40:45 +0200 + +omnibook (2:2.20060806-1) unstable; urgency=low + + * New upstream branch - Mathieu Bérard launched new project + * Added myself as co-maintainer + * Bumped upstream version and use epoch to ensure upgrades + * [debian/rules]: + + Clean-ups + + Recommends linux-image or kernel-image + * [debian/control] Improved long description + * [debian/post*.modules.in] Fixed bashisms + * Added patch to fix install target in Makefile + + -- Julien Valroff Thu, 10 Aug 2006 01:35:38 +0200 + +omnibook (20060126-1) unstable; urgency=low + + * Minor build inconveniences corrected. + + -- Daniel Gimpelevich Sun, 18 Jun 2006 12:28:55 -0700 + +omnibook (20060126-0) unstable; urgency=low + + * Locally built. + + -- Péter Soós Wed, 25 Jan 2006 21:06:28 +0100 + --- linux-2.6.37.orig/ubuntu/omnibook/debian/compat +++ linux-2.6.37/ubuntu/omnibook/debian/compat @@ -0,0 +1 @@ +7 --- linux-2.6.37.orig/ubuntu/omnibook/debian/control +++ linux-2.6.37/ubuntu/omnibook/debian/control @@ -0,0 +1,21 @@ +Source: omnibook +Section: misc +Priority: optional +Maintainer: Julien Valroff +Build-Depends: debhelper (>> 7.0.0), dpatch, bzip2 +Standards-Version: 3.8.2 +Homepage: http://omnibook.sf.net +Vcs-Svn: https://omnibook.svn.sourceforge.net/svnroot/omnibook/omnibook/trunk +Vcs-Browser: http://omnibook.svn.sourceforge.net/viewvc/omnibook/ + +Package: omnibook-source +Architecture: all +Depends: debhelper (>= 4.0.0), make, module-assistant, kernel-package, bzip2, dpatch +Description: Source for the omnibook driver + This package contains the loadable kernel modules for the HP OmniBooks, + Pavilions, Toshiba Satellites and some other laptops manufactured by + Compal Electronics, Inc as ODM. + . + This module is only compatible with Linux kernels >= 2.6.9 + . + Kernel source is required to compile this module. --- linux-2.6.37.orig/ubuntu/omnibook/debian/control.modules.in +++ linux-2.6.37/ubuntu/omnibook/debian/control.modules.in @@ -0,0 +1,23 @@ +Source: omnibook +Section: misc +Priority: optional +Maintainer: Julien Valroff +Build-Depends: debhelper (>> 7.0.0) +Standards-Version: 3.8.2 + +Package: omnibook-module-_KVERS_ +Architecture: i386 amd64 +Recommends: _STEM_-image-_KVERS_ +Provides: omnibook-module +Description: omnibook module for Linux (kernel _KVERS_) + This package contains the loadable kernel modules for the HP OmniBooks, + Pavilions, Toshiba Satellites and some other laptops manufactured by + Compal Electronics, Inc as ODM. + . + This package contains the compiled kernel modules for _KVERS_ + . + If you have compiled your own kernel, you will most likely need to build + your own omnibook-module. The omnibook-source package has been + provided for use with the Debian kernel-package utility to produce a version + of omnibook-module for your kernel. + --- linux-2.6.37.orig/ubuntu/omnibook/debian/copyright +++ linux-2.6.37/ubuntu/omnibook/debian/copyright @@ -0,0 +1,32 @@ +This package was debianized by Peter Soos on +Wed, 25 Jan 2006 21:06:28 +0100. +Debian package was improved by Julien Valroff + +It was downloaded from http://sourceforge.net/projects/omnibook + +Copyright Holder: 2006-2007 Mathieu Bérard + +dump.c: + Copyright (C) 2004-2005 Borislav Deianov + +License: + + This package 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 package 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. + +The Debian packaging is + Copyright (C) 2006 Peter Soos + Copyright (C) 2006-2009 Julien Valroff +It is licensed under the GPL, version 2. + +You should have received a copy of the GNU General Public License with +the Debian GNU/Linux distribution in file /usr/share/common-licenses/GPL-2; +if not, write to the Free Software Foundation, Inc., 51 Franklin St, +Fifth Floor, Boston, MA 02110-1301, USA. --- linux-2.6.37.orig/ubuntu/omnibook/debian/docs +++ linux-2.6.37/ubuntu/omnibook/debian/docs @@ -0,0 +1,4 @@ +doc/BUGS +doc/CREDITS +doc/README +misc/hotkeys --- linux-2.6.37.orig/ubuntu/omnibook/debian/rules +++ linux-2.6.37/ubuntu/omnibook/debian/rules @@ -0,0 +1,135 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +include /usr/share/dpatch/dpatch.make + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +# Name of the source package +psource := omnibook-source + +# The short upstream name, used for the module source directory +sname := omnibook + +# prefix of the target package name +PACKAGE=omnibook-module + +### end KERNEL SETUP + +configure: configure-stamp +configure-stamp: + dh_testdir + touch configure-stamp + + +build-arch: configure-stamp build-arch-stamp +build-arch-stamp: + dh_testdir + touch build-arch-stamp + +build-indep: patch configure-stamp build-indep-stamp +build-indep-stamp: + dh_testdir + + touch build-indep-stamp + +build: patch build-arch build-indep + +clean: unpatch + dh_testdir + rm -f build-arch-stamp build-indep-stamp configure-stamp + + dh_clean + +install: DH_OPTIONS= +install: patch build + dh_testdir + dh_testroot + dh_prep + dh_installdirs + + # Create the directories to install the source into + dh_installdirs -p$(psource) usr/src/modules/$(sname)/debian + cp debian/compat debian/rules debian/changelog \ + debian/control debian/copyright debian/*.modules.in \ + debian/$(psource)/usr/src/modules/$(sname)/debian + cp Makefile *.c *.h *.lds debian/$(psource)/usr/src/modules/$(sname) + + cd debian/$(psource)/usr/src && tar c modules | bzip2 -9 > $(sname).tar.bz2 && rm -rf modules + dh_install + +# Build architecture-independent files here. +# Pass -i to all debhelper commands in this target to reduce clutter. +binary-indep: build install + dh_testdir -i + dh_testroot -i + dh_installchangelogs -i doc/ChangeLog + dh_installdocs -i + dh_installexamples -i + dh_installman -i + dh_link -i + dh_compress -i + dh_fixperms -i + dh_installdeb -i + dh_installdeb -i + dh_shlibdeps -i + dh_gencontrol -i + dh_md5sums -i + dh_builddeb -i + +# Build architecture-dependent files here. +binary-arch: build install + +# modifieable for experiments or debugging m-a +MA_DIR ?= /usr/share/modass +# load generic variable handling +-include $(MA_DIR)/include/generic.make +# load default rules, including kdist, kdist_image, ... +-include $(MA_DIR)/include/common-rules.make + +ifndef KPKG_STEM +STEM:=linux +else +STEM:=${KPKG_STEM} +endif + +kdist_clean: prep-deb-files + [ ! -f Makefile ] || $(MAKE) KSRC=$(KSRC) clean + dh_clean + +kdist_config: prep-deb-files + sed -i -e 's/_STEM_/$(STEM)/g' debian/control + +binary-modules: kdist_config prep-deb-files + dh_testroot + dh_prep + dh_installdirs lib/modules/$(KVERS)/extra + + # Build the module + $(MAKE) KSRC=$(KSRC) KVERS=$(KVERS) + + # Install the module + $(MAKE) install KSRC=$(KSRC) DESTDIR=$(CURDIR)/debian/$(PKGNAME) INSTDIR=extra DEPMOD="/bin/true" + + dh_installdocs + dh_compress + dh_installmodules + dh_installchangelogs + dh_fixperms + dh_installdeb + dh_gencontrol -- -v$(VERSION) + dh_md5sums + dh_builddeb --destdir=$(DEB_DESTDIR) + dh_prep + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure binary-modules kdist kdist_config kdist_image kdist_clean --- linux-2.6.37.orig/ubuntu/omnibook/doc/BUGS +++ linux-2.6.37/ubuntu/omnibook/doc/BUGS @@ -0,0 +1,17 @@ +Bugs and problems in omnibook module code +========================================= + +* Volume Control buttons on machine (not on docking station) do not generate + scancodes on OB500 style models. It is unhandled yet. +* Setting the LCD brightness on HP OmniBook XE3 GF via /proc/omnibook/lcd + is working if you press one of the brightness control keys once after + writing the value into /proc/omnibook/lcd. +* I'm not a native English speaker so text corrections are welcome. +* obtest can BADLY confuse the in-kernel ACPI code due to its racy + implementation. +* Reenabling wifi adapter after previous disabling is broken on + Toshiba Satellite M100 (ipw3945) +* Real support of ectype 14 is still missing +* See http://sourceforge.net/tracker/?atid=868542&group_id=174260&func=browse + for sf.net bug tracking system. + --- linux-2.6.37.orig/ubuntu/omnibook/doc/COPYING +++ linux-2.6.37/ubuntu/omnibook/doc/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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. + + GNU GENERAL PUBLIC LICENSE + 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 + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. --- linux-2.6.37.orig/ubuntu/omnibook/doc/CREDITS +++ linux-2.6.37/ubuntu/omnibook/doc/CREDITS @@ -0,0 +1,39 @@ +The module was originally written by + +* Soós Péter + +Special thanks to the following persons and/or organisations (without +particular order): + +* Al Stone and Linux Systems Operation at HP for lending + an HP OmniBook 500 for the project purposes. +* Pavel Mihaylov for his omke project discovering a lot of + OmniBook features, providing some code for XE3 GC machines and testing. +* Ducrot Bruno sharing lots of information about + embedded controller and related code, added lots of Toshiba support, + writing tosh3k code, sending patches etc. + +Thanks to the following people (without particular order): + +* Al Stone for sharing some programming information. +* Guido Guenther for initial OneTouch enabling code. +* Jens Thoms Toerring for initial + OneTouch power management code. +* Maciek Gorniak for initial HP Pavilion N5415 detecting + code and initial lcd brighness code. +* Rick Richardson for some bugfixes and useful patches. +* Bob McElrath for initial Compal ACL00 + code. +* Luisimi Moya for Acer Aspire 1400 support. +* Bernhard Kaindl for bugfixes and patches +* Gabriele Vivinetto for documentation + enhancements and testing. +* Mark Chappell for building on kernel 2.6. +* Massimo Dal Zotto for his i8k code. +* Jonathan A. Buzzard for his toshiba code. +* Some others on OmniBook mailing list at + http://zurich.ai.mit.edu/mailman/listinfo/omnibook + for providing information and testing. + +Last but not least thanks to Linus Torvald and more for creating and +maintaining the Linux kernel. --- linux-2.6.37.orig/ubuntu/omnibook/doc/ChangeLog +++ linux-2.6.37/ubuntu/omnibook/doc/ChangeLog @@ -0,0 +1,521 @@ +Changelog file for omnibook package: +------------------------------------ + +2.XXXXXXXX Mathieu Bérard +* DMI signature added: + Toshiba Satellite P25 (ectype 11) + Toshiba Satellite M60 (ectype 12) +* Applied patch from Danny Kukawka to + fix compiler warning about use uninitialized variable +* Applied patch from Danny Kukawka to + fix build the driver on older kernel versions +* Applied patches from Azael Avalos + to add support to Satellite X205 and other laptops based on + ICH8 +* Fix build with kernel >= 2.6.30 + +2.20070211 Mathieu Bérard +* Disable Acer support, acerhk module should provided better + support with a far more complete autodetection database + (see http://www2.informatik.hu-berlin.de/~tauber/acerhk/) +* Fix and improve bluetooth handling for TSM30X class laptops + bluetooth now also works for TSA105 +* Implement Volume down,up and Mute buttons polling for ectype 2 + It was the last missing part from the "omke" module which never + got ported to linux 2.6 +* Implement ectype 13 Fn hotkeys handling. +* DMI signature added: + HP Pavilion ze4500 (ectype 7) + Toshiba Satellite 1130 (ectype 1) + Toshiba Satellite A75 (ectype 12) + Toshiba Tecra A4 (ectype 13) + Toshiba Satellite A80 (ectype 12) + Toshiba Satellite P100 (ectype 14) +* Split TSM30X (ectype 12) : this ectype was reimplemented and if the + new implementation works with Toshiba M40X, M70, M100... it does not + (and will never, due to hardware) with Toshiba M30X, the only way + to fix this is to split TSM30X (ectype 12) in : + -TSM70 (ectype 12) => new implementation (compal.c & acpi.c backends) + -TSM30X (ectype 15) => old implementation (legacy backends) + This is done by renaming TSM30X to TSM40 and restore old TSM30X + The state of the Toshiba M35X is unknown and is assigned to TSM70, one + should send a bug report if that fail. + Fix bugs 1617818 and 1605278 +* New features for TSM70 class laptops: + -Cooling method control (can tune fan behaviour to 'Save power' or + to 'Maximize performance') provided in /proc/omnibook/cooling + -CPU Throttling status&control (also known as ACPI T-States) should + be supported out of the box via /proc/acpi/processor/CPU0/throttling + but at least Toshiba Satellite M70 as a deficient ACPI FADT table + which prevent than, thus a custom access to ACPI Throttling is + provided in /proc/omnibook/throttling + +2.20060921 Mathieu Bérard +* The minimal required kernel version is now 2.6.9 (kref API) +* Convert semaphore to mutex with fallback for pre 2.6.16 kernel +* Kill CONFIG_OMNIBOOK_APMEMU and introduce OMNIBOOK_LEGACY: + pre-ACPI features now depends on it. + Default enabling of ac and battery features also + depends on it. It is _disabled_ by default. +* Introduce ACPI methods execution backend: TSM70 needs it + for Display and Wifi/Bluetooth features +* Expand display and hotkeys features +* Introduce experimental NbSmi backend for TSM40. It is + based on technical documentation provided by Toshiba. + Thanks Toshiba ! +* Kill unused omnibook_mem_read/write function for mmio + access +* Cleanup in blank.c fan.c temperature.c +* Unbreak Pio backend: use request/release_region +* Introduce bluetooth and wifi frontend features : they allow + adapter state querry and control (existence probing, wifi + kill switch probing and adapter enabling/disabling). + Supported by TSM30X and TSM40 +* Introduce omnibook_backend struct as a uniform way of + communication between backend and frontend, this + kill omnibook_io_{read/write} and friends. +* Modify ombibook_feature struct to incorporate pointers + to an omnibook_table table and to a omnibook_operation + struct which is picked-up from the ectype matching + omnibook_table entry upon feature initialization +* Add muteled resume handler +* Add touchpad handling for TSM30X +* Add proper display handling for TSM30X +* Change all features struct name from foo_feature to + foo_driver to kept modpost section mismatch detection + silent. Put tbl, init and exit entries to their relevant + sections. +* Many bugfix and dock support for TSM40 by Holger Nelson. +* Add DMI Signature for Toshiba Satellite 1700-Series, with ectype 10. + LCD does not work. +* Add DMI Signature for Toshiba Equium A110, added with + ectype 1, until implementation of a better backend +* Add DMI Signature for Toshiba _Satellite_ M100, Satellite A70 + and Tecra S2. added with ectype 12 +* Add DMI Signature for Toshiba Tecra S1, added with + ectype 13 + +2.200608017 Mathieu Bérard +* Fix bug un omnibook_io_match +* Fix DMI handling behaviour: we stop on the FIRST matched + DMI entry. This is restoring pre-20060806 behaviour. + Invert M40 vs. M40X entry position. + +2.20060816 Mathieu Bérard +* Merge from the new-backend branch: Add new backend code + (in compal.c) used with TSM30X class laptops: + Used for lcd access + Used for hotkeys support: now most Fn+key generate a scancode, + as well as the wifi kill switch. + Warning: tested only on TSM40X an TSM70 laptops. +* Create omnibook_io_operation struct and omnibook_io_{read/write} + funtions to simplify implementation of some simple features. + Used with ac display dock and led features. +* Rename onetouch feature to "hotkeys" which is a vendor neutral name. +* The minimal required kernel version is now 2.6.9 (kref API) +* Convert semaphore to mutex with fallback for pre 2.6.16 kernel +* Kill CONFIG_OMNIBOOK_APMEMU and introduce OMNIBOOK_LEGACY: + pre-ACPI features now depends on it. + Default enabling of ac and battery features also + depends on it. It is _disabled_ by default. +* Introduce ACPI methods execution backend: TSM70 needs it + for Display and Wifi/Bluetooth features +* Expand display and hotkeys features +* Introduce experimental NbSmi backend for TSM40. It is + based on technical documentation provided by Toshiba. + Thanks Toshiba ! +* Kill unused omnibook_mem_read/write function for mmio + access +* Cleanup in blank.c fan.c temperature.c +* Unbreak Pio backend: use request/release_region +* Introduce bluetooth and wifi frontend features : they allow + adapter state querry and control (existence probing, wifi + kill switch probing and adapter enabling/disabling). + Supported by TSM30X and TSM40 +* Introduce omnibook_backend struct as a uniform way of + communication between backend and frontend, this + kill omnibook_io_{read/write} and friends. +* Modify ombibook_feature struct to incorporate pointers + to an omnibook_table table and to a omnibook_operation + struct which is picked-up from the ectype matching + omnibook_table entry upon feature initialization +* Add muteled resume handler +* Add touchpad handling for TSM30X +* Add proper display handling for TSM30X +* Change all features struct name from foo_feature to + foo_driver to kept modpost section mismatch detection + silent. Put tbl, init and exit entries to their relevant + sections. + +2.20060809 Mathieu Bérard +* Add dmi info for Toshiba Satellite M40X (Thanks Julien Valroff) +* Fix two brown paper bag bugs in Debian/Ubuntu support + +2.20060806 Mathieu Bérard +* Make the module linux 2.6 only + Kernel versions from 2.6.8 to a least 2.6.17 are supported + Code for compatibility with kernels older than 2.6.17 is + mostly implemented in compat.h +* Integrate with Driver Model: + register as a platform device and optional + registration as a backlight device (2.6.17+ required here) +* Get rid of deprecated pm_legacy functions +* Use kernel-provided DMI information: + Use kernel-provided dmi_check_system for system identification + omnibook_tc_t and omnibook_models_t are merged and converted into a + dmi_system_id struct and moved from init.c to laptop.h +* MODULE_PARAM -> 2.6-style module_parm_* +* Move some code from "feature".c files back to init.c + Interface is provided by the new omnibook_feature struct + Enabled features are now in placed in a linked list + This eliminate util.c + Rationale: Reduce code duplication and create a standard template for features +* Move dmi and version display into their own file: info.c +* Remove all (as unneeded) EXPORT_SYMBOL +* Misc fixes in Makefile + Also make more use of Kbuild +* Use sscanf and simple_stro{u}l for strings parsing instead of custom code +* Run lindent for better conformance with kernel coding style +* Add very limited support for some Toshiba M40 (more info needed) +* Use bitmasks for EC types matching, this change is transparent for the user + (e.g. one can still use ectype=num module parameter) + Rationale: Reduce the size of the omnibook_feature struct +* Polish Debian support: Use module-assistant and fix all Lintian warning + Fix building against non-running kernel (Thanks to Daniel Gimpelevich) +* Update documentation and omnibook-integration.patch +* Fix spinlock usage: they can be used unconditionally as they are automatically + optimized out at build-time on UP. This should improve PREEMPT safety +* Spinlock protect omnibook_mem_* and use ioread8 and iowrite8 +* Fix: Custom EC access function are also used if ACPI is compiled but disabled +* Cleanup: remove lots of unneeded #ifdef +* Add a new feature for testers: dump + Dump was stolen from the ibm_acpi driver + It is disabled by default +* Bump version to 2.YYYYMMDD + +2006-05-15 Thomas Perl +* Added support for xe4500's "audio mute" led + +2006-01-26 Soós Péter +* Added support for kernels >= 2.6.15 (pm_legacy.h) +* Added Toshiba Satellite M30X +* Added support for Toshiba Satellite M70 +* Added support for HP Pavilion ze4300 series +* Fixed module unloading on 2.6 series kernels (thanks to + math_b@users.sourceforge.net) +* Changed version number to +%Y%m%d format +* Added Debian support + +2005-02-17 Soós Péter +* Fixed Makefile +* Updated Toshiba 1115 information + +2004-12-15 Scott Barnes +* Added Toshiba Satellite M35X + +2004-09-16 Soós Péter +* Added INSTALL-2.6 file +* Little spelling fixes in documentation +* Little bugfixes +* Added Compal ACL10 + +2004-07-01 Soós Péter +* Added new technology codes +* Added some new HP nx9000 detection string +* Added Toshiba Satellite P20 + +2004-06-07 Chris Green +* Added Toshiba Satellite P15 + +2004-06-01 Soós Péter +* Added Toshiba Satellite 1955 +* Added Toshiba Satellite 2435 +* Added Toshiba Satellite P10 (new ectype) +* Acer Aspire 1350 + +2004-01-23 Soós Péter +* Added HP Pavilion ze8500 (HP nx9010) +* fixed PM handler for OneTouch keys and touchpad + +2004-01-20 Soós Péter +* Only fan status supported on HP OmniBook 4150, XE2 and + Fujitsu-Siemens Amilo D, fan control is unsupported +* #include fixes in ec.c + +2004-01-16 Soós Péter +* Added fan support for Fujitsu-Siemens Amilo D series laptops + +2004-01-14 Soós Péter +* Fixed Makefile for kernels 2.6 +* Added Fujitsu-Siemens Amilo D series laptops (new ectype) + +2003-12-08 Soós Péter + +* Fixed tecnology code detection +* Added HP/Compaq nx9005 +* Fixed Makefile for kernel 2.4 + +2003-11-12 Soós Péter + +* Fixed KERNEL_WARNING in init.c + +2003-11-10 Soós Péter + +* Fixed timeout bugs in ec.c +* Fixed touchpad dependency code for kernel 2.6 +* Added Compaq nx9000 + +2003-11-10 Mark Chappell + +* Added kernel 2.6 support to Makefile + +2003-10-23 Soós Péter + +* Totally removed key polling code for kernels >= 2.5.0 but 2.5/2.6 kernels + is unsuported yet +* proc_battery is static +* Added HP OmniBook 900 B support +* Added HP OmniBook XE2 support (added new ectype value for it) +* Added Compaq nx9010 +* Reversed ChangeLog +* Some documentation changes + +2003-08-28 Soós Péter + +* Added Toshiba Satellite 2430 +* Documentation enhancements + +2003-04-03 Soós Péter + +* Really fixed __init bug in user parameter code +* Fixed omnibook_dmi_ident (it was static) + +2003-03-31 Soós Péter + +* Fixed HP technology code detection +* Key polling is disabled by default on XE3GC style machines +* Fixed PM code in polling.c +* Added util.c +* Fixed __init bug in user parameter code +* Cleaned up ec.h +* Added Toshiba Satellite 1950 detection +* Documentation enhancements + +2003-03-13 Soós Péter + +* Added HP Pavilion ZU1155 and ZU1175 detection + +2003-03-11 Soós Péter + +* Fixed bogus version information + +2003-03-06 Ducrot Bruno + +* Fan off hack for XE3GF style machines + +2003-03-04 Ducrot Bruno + +* Fixed spinlock problem + +2003-02-28 Soós Péter + +* Added /proc/omnibook/version +* Added OMNIBOOK_ prefix to MODULE_NAME and MODULE_VERSION definitions +* Fixed bugs in lcd.c (thanks to Bernhard Kaindl ) +* Some code tuning and cosmetic changes +* Fixed OmniBook 4150 support + +2003-02-26 Soós Péter + +* Fixed kernel Oops in technology code identification +* Some minor changes in logging + +2003-02-25 Soós Péter + +* Try to identify HP laptops by technology code if machine is unsupported +* Fixed dmi identification code + +2003-02-14 Soós Péter + +* Added HP Pavilion ze4100 support +* Added HP Pavilion ze4200 support +* Fixed HP Pavilion xt155 detection +* Added Acer Aspire 1400 series laptop support +* Fixed APM status detection bug +* Cleaned up dmi identification code +* Removed "Asset Tag:" field from dmi string structure + +2003-01-27 Soós Péter + +* Added HP Pavilion N5430 support +* EC functions are work even if boot parameter acpi=off is given +* Improved error handling in externally callable functions +* Fixed kernel integration patch +* Removed unreliable undocking feature for OB500 +* Fixed HP Pavilion N5415 support +* Added new format hotkeys sample files + +2003-01-09 Ducrot Bruno + +* Added to use ACPI_EC if available + +2003-01-09 Soós Péter + +* Fixed reverse console blanking bug on OB5xx and OB6xxx +* Disabled unreliable undocking feature on OB500 + +2003-01-08 Ducrot Bruno + +* Added Toshiba Satellite 3000, 3005, 1000, 1005, 1110, 1115, 1900, 1905 + support + +2003-01-08 Soós Péter + +* The ectype values changed again! See the README! +* Fixed new ectypes detection bug +* Added OmniBook xe4400 support +* Added LCD display turn off at console blanking on OB5xx and OB6xxx +* Documentation fixes + +2003-01-07 Soós Péter + +* Fixed bit level negation bug in fan.c +* Added turn fan on for Toshiba 3000 +* Corrected OmniBook 4150 support code + +2003-01-06 Soós Péter + +* Changed ectype values! See the README! +* Fixed some bugs in obtest utility +* Fixed second battery status bug in battery.c +* Added textual descriptions to some functions in /proc/omnibook +* Fix APM emulation to work when APM support is present but APM power + status reporting flagged broken +* Added docking station support +* Added fan support +* Added module parameter: user +* Added OmniBook xe155, xe4100 and ze4125 support +* Fan policy moved to /proc/omnibook/fan_policy +* Reorganized scancode emulation code for XE3 GC +* Polling of volume buttons on XE3CG style models can be enabled/disabled + via /proc/omnibook/key_polling +* Finished abstraction layer +* Some minor changes in Rick's model detection code +* New kernel integration code + +2002-12-22 Rick Richardson + +* Added on and off as valid input to /proc/omnibook/lcd, to turn + the LCD backlight on and off. + +2002-12-15 Rick Richardson + +* Reimplemented model detection so you only have to modify one file + to add a new model. features.h is now deprecated. +* Added the Toshiba Satellite 1115/S103 to the supported models +* Fixed bug in apmemu.c which caused /proc/apm to report the battery + status as critical when the battery was charging. + +2002-10-16 Soós Péter + +* Added HP Pavilion N5415 support +* Corrected HP Pavilion N5441 support +* Fix values of OB500 type machines in ec.h +* LCD brightness support added for XE3GC and XE3GF style machines +* Added HP OmniBook 510 FB support +* AC adapter status monitoring is working on all machines +* External display status monitoring is working on all machines +* CPU temperature monitoring is working on all machines +* __init functions gone to init.h +* Added an abstraction layer between the low level, hardware dependent + functions and the applications (not yet finished). See omnibook.h for + details. + +2002-09-20 Soós Péter + +* Using save_flags()/cli() instead spinlocks in ec.c because of laptops do + not have more than one CPU (yet ;)). This improves performance and + eliminates packet loss in ppp stack +* The previous version of XE3 GC scancode emulation was buggy: it worked only + when ACPI enabled. Current version is working ACPI independent way + +2002-09-05 Soós Péter + +* Added secondary battery support (untested, please report!) +* Added ectype module parameter to specify the type of embedded + controller firmware +* Added some OmniBook XE3 GC support code +* Added some OmniBook 500 style embedded controller firmware support code + (OmniBook 5xx, 6xxx and some Pavilions) +* Reorganized features matrix (again): the features depends on the embedded + controller firmware, not the model +* Added external display status monitoring on some machine +* Added scancode emulation on OmniBook XE3 GC + +2002-08-14 Soós Péter + +* Added HP OmniBook 6000 EA support (OneTouch only) +* Added HP OmniBook 6100 EB support (OneTouch only) +* Fixed Toshiba Satellite 3000-100 detection +* Fixed timeout and locking bugs in ec.c +* Added HP Pavilion Notebook ZT1141 +* Reorganized the feature matrix and parameter detection code to make easy + to add new features differents machine by machine + +2002-08-11 Soós Péter + +* Fixed removing of procfs entries +* Fixed APM detection +* Added kernel source integration +* Fixed __initdata bugs +* Handling difference between untesed and unsupported features + +2002-08-09 Soós Péter + +* Added Compal ACL00 laptop support +* Updated documentation +* Added touchpad support +* Some bugfixes +* /proc/apm emulation added + +2002-08-06 Soós Péter + +* Corrected full charged battery info +* Added OneTouch handling via procfs +* Added console blank handling via procfs +* Added temperature policy handling via procfs +* Corrected the bug in DMI code to report the serial number +* Added module parameter support +* Added HP Pavilion Notebook N5490, ZT1195 (and probably other Pavilions) + +2002-07-17 Soós Péter + +* Improved error handling +* Some text corrections +* Added Toshiba Satellite 3000-100 support +* Some code tuning +* Added omnibook prefix for variables and functions to prevent conflicts + with another code +* Added /proc filesystem support +* Added battery status monitoring +* Added CPU temperature monitoring + +2002-06-03 Soós Péter + +* Some code tuning + +2002-05-07 Soós Péter + +* Added missing #include to main.c +* Some text corrections +* Added HP OmniBook 500 FA support (OneTouch only) + +2002-05-06 Soós Péter + +* LCD display turn off at console blanking added +* Code cleanup + +2002-05-02 Soós Péter + +* The first release of omnibook module +* OneTouch button support --- linux-2.6.37.orig/ubuntu/omnibook/doc/README +++ linux-2.6.37/ubuntu/omnibook/doc/README @@ -0,0 +1,42 @@ +=============================================================== +Kernel Support for HP OmniBooks, Pavilions and Compal laptops +=============================================================== + +This package is intended to provide Linux kernel support for many laptops such as: +- HP OmniBook and Pavilion +- Toshiba Satellite and Tecra which are not supported by the toshiba_acpi module +- Compal ACL00 +- Many laptops manufactured by Compal Electronics, Inc as ODM + +Supported features depends on the exact laptop model but may include: +- Enabling hotkey buttons +- Console (LCD display) blanking +- Battery status monitoring. +- Fan and fan policy support +- Touchpad control +- AC Adapter status monitoring +- External display monitors status monitoring and control +- LCD brightness (backlight) monitoring and control +- Docking station/port replicator status +- CPU temperature monitoring +- Mute LED monitoring and control +- Wifi and Bluetooth adapters monitoring and control +- Cooling method control +- CPU Throttling control + +Useful links: + +Full documentation (HOWTO, Installation instructions, Supported laptops list... ): +http://omnibook.sourceforge.net/doku.php?id=start + +Sourceforge project page: +http://sourceforge.net/projects/omnibook + +Other links not related to the project: + +For HP Omnibook specific issues ou can see the OmniBook mailing list: +http://zurich.ai.mit.edu/mailman/listinfo/omnibook + +or the Toshiba linux mailing list: +http://linux.toshiba-dme.co.jp/linux/ + --- linux-2.6.37.orig/ubuntu/omnibook/misc/README.mmkeys +++ linux-2.6.37/ubuntu/omnibook/misc/README.mmkeys @@ -0,0 +1,9 @@ +This patch maps some extra Fn+key combinations to keycodes for multimedia +keyboards and only works for the nbsmi-backend. It might be useful if you +want to control some mediaplayer while working with other applications. + +Following combinations are mapped: +Fn+Y => Previous song +Fn+X => Play/pause +Fn+V => Stop CD +Fn+B => Next song \ No newline at end of file --- linux-2.6.37.orig/ubuntu/omnibook/misc/dmi_strings.txt +++ linux-2.6.37/ubuntu/omnibook/misc/dmi_strings.txt @@ -0,0 +1,857 @@ +HP OmniBook XT1000 ------------------------- + +BIOS Vendor: Insyde Software +BIOS Version: IB.M1.05 +BIOS Release: 02/28/2002 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook XT1000 +Board Vendor: Hewlett-Packard +Board Name: HP OmniBook PC +Board Version: HP OmniBook XT1000 + +--------------------------------------------- +HP OmniBook XT1500 -------------------------- + +BIOS Vendor: Insyde Software +BIOS Version: IC.M1.05 +BIOS Release: 08/13/2002 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook +Board Vendor: Hewlett-Packard +Board Name: HP OmniBook PC +Board Version: HP OmniBook + +--------------------------------------------- +HP OmniBook XT1500 ------------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: ID.M1.04 +BIOS Release: 08/14/2002 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook XE3 GF +Board Vendor: Hewlett-Packard +Board Name: N/A +Board Version: OmniBook Zinfandel 4.5 + +--------------------------------------------- +HP OmniBook XE3 GC -------------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: GC.M1.63 +BIOS Release: 01/01/1992 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook XE3 GC +Board Vendor: Hewlett-Packard +Board Name: N/A +Board Version: OmniBook N32N-733 + +--------------------------------------------- +HP OmniBook XE3 GF -------------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: GF.M1.07 +BIOS Release: 03/05/2002 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook XE3 GF +Board Vendor: Hewlett-Packard +Board Name: N/A +Board Version: OmniBook N32N-101 + +--------------------------------------------- +HP OmniBook 500 FA -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd +BIOS Version: FA.M2.62 +BIOS Release: 11/30/1999 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook 500 FA +Board Vendor: Hewlett-Packard +Board Name: HP OmniBook PC +Board Version: 500 FA + +--------------------------------------------- +HP OmniBook 510 FB -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: FB.M1.20 +BIOS Release: 04/12/02 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook 510 FB +Board Vendor: Hewlett-Packard +Board Name: HP OmniBook PC +Board Version: 510FB + +--------------------------------------------- +Toshiba Satellite 3000-100 ------------------ + +BIOS Vendor: TOSHIBA +BIOS Version: V2.20 +BIOS Release: 10/12/01 +System Vendor: TOSHIBA +Product Name: S3000-100 +Version: PS300E-03EKL-FR +Board Vendor: Null +Board Name: 888M1 +Board Version: Null + +--------------------------------------------- +Toshiba Satellite 1115-s103------------------ + +BIOS Vendor: TOSHIBA +BIOS Version: V1.20 +BIOS Release: 09/11/2002 +System Vendor: TOSHIBA +Product Name: Satellite 1115 +Version: PS111U-001FUV +Board Vendor: TOSHIBA +Board Name: BTK20 +Board Version: Null + +--------------------------------------------- +Toshiba Satellite 1110 ---------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.20 +BIOS Release: 09/11/2002 +System Vendor: TOSHIBA +Product Name: S1110 +Version: PS111E-003DN-GR +Board Vendor: TOSHIBA +Board Name: BTK20 +Board Version: Null + +--------------------------------------------- +Toshiba Satellite 1130 ---------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.70A +BIOS Release: 09/02/2003 +System Vendor: TOSHIBA +Product Name: Satellite 1130 +Version: PS113E-05ZYF-GR +Board Vendor: TOSHIBA +Board Name: BTW30 +Board Version: Null + +--------------------------------------------- +Toshiba Satellite 1900-704 ------------------ + +BIOS Vendor: TOSHIBA +BIOS Version: V1.50 +BIOS Release: 11/25/2002 +System Vendor: TOSHIBA +Product Name: Satellite 1950 +Version: PS195E-008QY-DU +Board Vendor: TOSHIBA +Board Name: ATR60 + +--------------------------------------------- +Toshiba Satellite 1955-s805 ----------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.00 +BIOS Release: 01/17/2003 +System Vendor: TOSHIBA +Product Name: Satellite 1955 +Version: PS197U-000LEV +Board Vendor: TOSHIBA +Board Name: BTR80 +Board Version: Null + +--------------------------------------------- +Toshiba Satellite A70 ----------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.50 +BIOS Release: 11/16/2004 +System Vendor: TOSHIBA +Product Name: Satellite A70 +Version: PSA70C-KL100E +Serial Number: X4451615K +Board Vendor: TOSHIBA +Board Name: EDW10 +Board Version: Null + +--------------------------------------------- +Toshiba Satellite A80 ----------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V2.50 +BIOS Release: 01/11/2006 +System Vendor: TOSHIBA +Product Name: Satellite A80 +Version: PSA80E-03T00JSP +Board Vendor: TOSHIBA +Board Name: Null + +--------------------------------------------- +Toshiba Satellite A105 ---------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: 1.30 +BIOS Release: 02/09/2006 +System Vendor: TOSHIBA +Product Name: Satellite A105 +Version: PSAA8U-02000U +Board Vendor: Intel Corporation +Board Name: Not Applicable + +--------------------------------------------- +Toshiba Satellite P10 ----------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.20 +BIOS Release: 09/12/2003 +System Vendor: TOSHIBA +Product Name: Satellite P10 +Version: PSP10E-34FJR +Board Vendor: TOSHIBA +Board Name: DAL00 +Board Version: Null + +--------------------------------------------- +Toshiba Satellite P15 ----------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.20 +BIOS Release: 09/12/2003 +System Vendor: TOSHIBA +Product Name: Satellite P15 +Version: PSP10U-0DUJPV +Board Vendor: TOSHIBA +Board Name: DAL00 +Board Version: Null + +--------------------------------------------- +Toshiba Satellite P25 ----------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V2.10 +BIOS Release: 12/27/2004 +System Vendor: TOSHIBA +Product Name: Satellite P25 +Version: PSP20U-19PS8R +Board Vendor: TOSHIBA +Board Name: Null + +--------------------------------------------- +Toshiba Satellite P100 ---------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V3.30 +BIOS Release: 12/22/2006 +System Vendor: TOSHIBA +Product Name: Satellite P100 +Version: PSPA3E-02E013G3 +Board Vendor: TOSHIBA +Board Name: Not Applicable + +--------------------------------------------- +Toshiba Satellite M40 ----------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: 1.10 +BIOS Release: 08/24/05 +System Vendor: TOSHIBA +Product Name: Satellite M40 +Version: PSM44E-00U00EFR +Board Vendor: ATI +Board Name: SB400 +Board Version: Rev0.4b + +--------------------------------------------- +Toshiba Satellite M45 (S355) ---------------- + +BIOS Vendor: TOSHIBA +BIOS Version: Version 2.00 +BIOS Release: 02/07/2006 +System Vendor: TOSHIBA +Product Name: Satellite M45 +Version: PSM40U-073001 +Board Vendor: TOSHIBA +Board Name: Version A0 + +--------------------------------------------- +Toshiba Satellite M40X (-131)---------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.60 +BIOS Release: 06/09/2005 +System Vendor: TOSHIBA +Product Name: Satellite M40X +Version: PSM4XE-01400GFR +Board Vendor: TOSHIBA +Board Name: EAL30 +Board Version: Null + +--------------------------------------------- +Toshiba Satellite M50------------------------ + +BIOS Vendor: TOSHIBA +BIOS Version: V2.10 +BIOS Release: 05/08/2006 +System Vendor: TOSHIBA +Product Name: Satellite M50 +Version: PSM51E-01C011IT +Board Vendor: TOSHIBA +Board Name: Null + +--------------------------------------------- +Toshiba Satellite M60 ----------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.60 +BIOS Release: 03/16/2006 +System Vendor: TOSHIBA +Product Name: Satellite M60 +Version: PSM60E-0CD01FIT +Board Vendor: TOSHIBA +Board Name: Null + +--------------------------------------------- +Toshiba Satellite M70 ----------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.10 +BIOS Release: 09/15/2005 +System Vendor: TOSHIBA +Product Name: Satellite M70 +Version: PSM71E-01100KFR +Board Vendor: TOSHIBA +Board Name: HTW00 +Board Version: Null + +--------------------------------------------- +Toshiba Satellite A75 ----------------------- + +IOS Vendor: TOSHIBA +BIOS Version: V1.50 +BIOS Release: 11/16/2004 +System Vendor: TOSHIBA +Product Name: Satellite A75 +Version: PSA70U-004004B +Board Vendor: TOSHIBA +Board Name: Null + +--------------------------------------------- +Toshiba Satellite M100 ---------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.90 +BIOS Release: 07/20/2006 +System Vendor: TOSHIBA +Product Name: SATELLITE M100 +Version: PSMA0E-030019TE +Board Vendor: TOSHIBA +Board Name: HAQAA +Board Version: Null + +--------------------------------------------- +Toshiba Satellite M100 ---------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.00 +BIOS Release: 03/30/2006 +System Vendor: TOSHIBA +Product Name: Satellite M100 +Version: PSMA2U-00T00G +Board Vendor: TOSHIBA +Board Name: HAWAA +Board Version: None + +--------------------------------------------- +Toshiba Satellite M115 ---------------------- + +Bios vender: Phoenix Tech. LTD +Bios version: 1.00 +Bios release: 08/31/2006 +System Vendor: Toshiba +Product Name: Satellite M115 +Version: PSMBOU-015007 +Board vendor Intel +Board name: N/a + +--------------------------------------------- +Toshiba Equium A110 ------------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V1.30 +BIOS Release: 07/20/2006 +System Vendor: TOSHIBA +Product Name: EQUIUM A110 +Version: PSAB2E-002006AV +Board Vendor: TOSHIBA +Board Name: Null + +--------------------------------------------- +Toshiba Tecra A4 ---------------------------- + + +BIOS Vendor: TOSHIBA +BIOS Version: Version 1.70 +BIOS Release: 10/14/2005 +System Vendor: TOSHIBA +Product Name: Tecra A4 +Version: PTA40E-0UN00FSP +Board Vendor: TOSHIBA +Board Name: Version A0 + +--------------------------------------------- +Toshiba Tecra A6 ---------------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V2.70 +BIOS Release: 04/26/2007 +System Vendor: TOSHIBA +Product Name: TECRA A6 +Version: PTA60U-0FK00D +Board Vendor: TOSHIBA +Board Name: Null + +--------------------------------------------- +Toshiba Tecra S2 ---------------------------- + +BIOS Vendor: TOSHIBA +BIOS Version: V2.50 +BIOS Release: 01/11/2006 +System Vendor: TOSHIBA +Product Name: Tecra S2 +Version: PTS20E-1FE04Q8M +Board Vendor: TOSHIBA +Board Name: Null + +--------------------------------------------- +Compal ACL00 -------------------------------- + +BIOS Vendor: COMPAL +BIOS Version: V2.10C +BIOS Release: 03/25/02 +System Vendor: COMPAL +Product Name: * +Version: * +Board Vendor: Null +Board Name: ACL00 +Board Version: Null + +--------------------------------------------- +Compal ACL10 -------------------------------- + +BIOS Vendor: COMPAL +BIOS Version: V1.10 +BIOS Release: 04/12/2001 +System Vendor: * +Product Name: * +Version: * +Board Vendor: COMPAL +Board Name: ACL10 +Board Version: Null + +--------------------------------------------- +HP Pavilion ZT1195 -------------------------- + +BIOS Vendor: Insyde Software +BIOS Version: IC.M1.00 +BIOS Release: 03/20/2002 +System Vendor: Hewlett-Packard +Product Name: HP Pavilion Notebook PC +Version: HP Pavilion Notebook +Board Vendor: Hewlett-Packard +Board Name: HP Pavilion Notebook PC +Board Version: HP Pavilion Notebook + +--------------------------------------------- +HP Pavilion ZT1141 -------------------------- + +BIOS Vendor: Insyde Software +BIOS Version: IB.M1.05 +BIOS Release: 02/28/2002 +System Vendor: Hewlett-Packard +Product Name: HP Pavilion Notebook PC +Version: HP Pavilion Notebook ZT1000 +Board Vendor: Hewlett-Packard +Board Name: HP Pavilion Notebook PC +Board Version: HP Pavilion Notebook ZT1000 + +--------------------------------------------- +HP OmniBook 6100 EB ------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: EB.M2.20 +BIOS Release: 02/27/02 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook 6100 EB +Board Vendor: Hewlett-Packard +Board Name: HP OmniBook PC +Board Version: 6100EB + +--------------------------------------------- +HP OmniBook 6000 EA ------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: EA.M1.81 +BIOS Release: 02/22/2002 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook 6000 EA +Board Vendor: Hewlett-Packard +Board Name: HP OmniBook PC +Board Version: 6000EA + +--------------------------------------------- +HP OmniBook xe4500 -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KB.M1.30 +BIOS Release: 08/05/20022 +System Vendor: Hewlett-Packard. +Product Name: HP OmniBook PC +Version: HP OmniBook xe4500 +Board Vendor: Hewlett-Packard +Board Name: HP OmniBook PC +Board Version: xe4500 + +--------------------------------------------- +HP Pavilion N5441 --------------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: GD.M1.08 +BIOS Release: 09/27/2001 +System Vendor: Hewlett-Packard +Product Name: HP Pavilion Notebook PC +Version: HP Pavilion Notebook Model GD +Board Vendor: Hewlett-Packard +Board Name: N/A +Board Version: OmniBook N32N-736 + +--------------------------------------------- +HP Pavilion N5430 --------------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: GD.M1.08 +BIOS Release: 09/27/2001 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook XE3 GD +Board Vendor: Hewlett-Packard +Board Name: N/A +Board Version: OmniBook N32N-736 + +--------------------------------------------- +HP Pavilion N5415 --------------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: GE.M1.04 +BIOS Release: 07/30/2002 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook XE3 GE +Board Vendor: Hewlett-Packard +Board Name: N/A +Board Version: OmniBook N32N-736 + +--------------------------------------------- +HP Pavilion N5290 --------------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: GC.M1.63 +BIOS Release: 01/01/1992 +System Vendor: Hewlett-Packard +Product Name: HP Pavilion Notebook PC +Version: HP Pavilion Notebook XE3 GC +Board Vendor: Hewlett-Packard +Board Name: N/A +Board Version: OmniBook N32N-733 + +--------------------------------------------- +HP OmniBook vt6200 ------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: EG.M2.10 +BIOS Release: 09/19/02 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook 6200 EG +Board Vendor: Hewlett-Packard +Board Name: HP OmniBook PC +Board Version: 6200EG + +--------------------------------------------- +HP OmniBook 4150 ---------------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: CI.M2.250 +BIOS Release: 06/10/99 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook 4150 +Board Vendor: Hewlett-Packard +Board Name: N/A +Board Version: OmniBook TS32T2 + +--------------------------------------------- +HP OmniBook xt6200 -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd +BIOS Version: EG.M2.10 +BIOS Release: 09/19/02 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook 6200 EG +Board Vendor: Hewlett-Packard +Board Name: HP OmniBook PC +Board Version: 6200EG + +--------------------------------------------- +HP Pavilion ze4125 -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd +BIOS Version: KA.M1.20 +BIOS Release: 09/13/2002 +System Vendor: Hewlett-Packard +Product Name: HP NoteBook PC +Version: HP NoteBook ze4000 +Board Vendor: Hewlett-Packard +Board Name: HP NoteBook PC +Board Version: HP NoteBook ze4000 + +--------------------------------------------- +HP OmniBook xt155 --------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KE.M1.40 +BIOS Release: 10/11/20022 +System Vendor: Hewlett-Packard +Product Name: HP NoteBook PC +Version: HP Notebook PC +Board Vendor: Hewlett-Packard +Board Name: HP NoteBook PC +Board Version: HP Notebook PC + +--------------------------------------------- +HP OmniBook xe4100 -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KC.M1.10 +BIOS Release: 07/11/2002 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook xe4000 +Board Vendor: Hewlett-Packard +Board Name: HP OmniBook PC +Board Version: 4000KC + +--------------------------------------------- +HP Omnibook xe4400 -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KD.M1.60 +BIOS Release: 09/19/20022 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP Omnibook xe4400 +Board Vendor: Hewlett-Packard +Board Name: HP OmniBook PC +Board Version: xe4400 + +--------------------------------------------- +HP Pavilion ze4100 -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KE.M1.40 +BIOS Release: 10/11/20022 +System Vendor: Hewlett-Packard +Product Name: HP NoteBook PC +Version: HP Notebook PC +Board Vendor: Hewlett-Packard +Board Name: HP NoteBook PC +Board Version: HP Notebook PC + +--------------------------------------------- +Acer Aspire 1350 ---------------------------- +BIOS Vendor: Acer +BIOS Version: 3A24 +BIOS Release: 12/01/2003 +System Vendor: Acer,Inc. +Product Name: Aspire 1350 +Version: 3A24 +Board Vendor: Acer,Inc. +Board Name: Aspire 1350 +Board Version: Rev.A + +--------------------------------------------- +Acer Aspire 1406 LC ------------------------- + +BIOS Vendor: Acer +BIOS Version: V2.30 +BIOS Release: 10/04/02 +System Vendor: Acer +Product Name: Aspire 1400 series +Version: * +Board Vendor: Null +Board Name: BR20 +Board Version: Null + +--------------------------------------------- +HP Pavilion ze4200 -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KE.M1.53 +BIOS Release: 12/10/20022 +System Vendor: Hewlett-Packard +Product Name: Pavilion ze4200 +Version: KE.M1.53 +Board Vendor: Hewlett-Packard +Board Name: 002A +Board Version: NS570 Version PQ1A74 + +--------------------------------------------- +HP Pavilion ze4500 -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KAM1.57 +BIOS Release: 02/19/2004 +System Vendor: Hewlett-Packard +Product Name: Pavilion ze4500 (DP793E) +Version: KAM1.57 +Board Vendor: Hewlett-Packard +Board Name: PQ1A83 + +--------------------------------------------- +HP Pavilion ZU1175 -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: FA.M2.60 +BIOS Release: 11/30/1999 +System Vendor: Hewlett-Packard +Product Name: HP Pavilion Notebook PC +Version: HP Pavilion ZU1000 FA +Board Vendor: Hewlett-Packard +Board Name: HP Pavilion Notebook PC +Board Version: 1000FA + +--------------------------------------------- +HP Pavilion XH545 --------------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: GE.M1.03 +BIOS Release: 11/08/2001 +System Vendor: Hewlett-Packard +Product Name: HP Pavilion Notebook PC +Version: HP Pavilion Notebook Model GE +Board Vendor: Hewlett-Packard +Board Name: N/A +Board Version: OmniBook N32N-736 + +--------------------------------------------- +Toshiba Satellite 2430-402 ------------------ + +BIOS Vendor: TOSHIBA +BIOS Version: V1.30 +BIOS Release: 01/16/2003 +System Vendor: TOSHIBA +Product Name: Satellite 2430 +Version: PS243E-06P4S-4V +Board Vendor: TOSHIBA +Board Name: BTS88 +Board Version: Null + +--------------------------------------------- +HP OmniBook 900 B --------------------------- + +BIOS Vendor: Phoenix Technologies LTD +BIOS Version: CL.M3.13 +BIOS Release: 11/11/99 +System Vendor: Hewlett-Packard +Product Name: HP OmniBook PC +Version: HP OmniBook 900 B +Board Vendor: Hewlett-Packard +Board Name: N/A +Board Version: OmniBook TS32U2 + +--------------------------------------------- +HP Compaq nx9000 ---------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KE_KG.M1.06 +BIOS Release: 05/16/2003 +System Vendor: Hewlett-Packard +Product Name: HP nx9000 (DG223T) +Version: KG.M1.06 +Board Vendor: Hewlett-Packard +Board Name: 002A +Board Version: NS570 Version PQ1A78 + +--------------------------------------------- +HP Compaq nx9000 ---------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KE_KG.M1.15 +BIOS Release: 12/19/2003 +System Vendor: Hewlett-Packard +Product Name: HP Notebook PC +Version: HP Notebook PC +Board Vendor: +Board Name: +Board Version: + +--------------------------------------------- +HP Compaq nx9005 ---------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KAM1.46 +BIOS Release: 07/21/200392 +System Vendor: Hewlett-Packard +Product Name: HP nx9005 (DJ163A) +Version: KAM1.46 +Board Vendor: Hewlett-Packard +Board Name: 0024 +Board Version: PQ1A78 + +---------------------------------------------- +HP Compaq nx9010 ----------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KF_KH.F.08 +BIOS Release: 06/06/2003 +System Vendor: Hewlett-Packard +Product Name: HP nx9010 (DJ123A) +Version: KH.F.08 +Board Vendor: Hewlett-Packard +Board Name: 0850 +Board Version: NS570 Version PQ1B56 + +---------------------------------------------- +HP Pavilion ze8500 -------------------------- + +BIOS Vendor: Phoenix Technologies Ltd. +BIOS Version: KF_KH.F.18 +BIOS Release: 11/13/2003 +System Vendor: Hewlett-Packard +Product Name: Pavilion ze8500 (DJ317A) +Version: KH.F.18 +Board Vendor: Hewlett-Packard +Board Name: 0850 +Board Version: NS570 Version PQ1B60 + +--------------------------------------------- +Fujitsu-Siemens Amilo D --------------------- + +BIOS Vendor: Phoenix +BIOS Version: V1.20 +BIOS Release: 11/14/2001 +System Vendor: FUJITSU SIEMENS +Product Name: Amilo D-Series +Version: DESKTOP CPU ONLY +Board Vendor: CY23 +Board Name: 8606-686B +Board Version: None + +--------------------------------------------- --- linux-2.6.37.orig/ubuntu/omnibook/misc/hotkeys/README.hotkeys +++ linux-2.6.37/ubuntu/omnibook/misc/hotkeys/README.hotkeys @@ -0,0 +1,22 @@ +HotKeys is a program to use the special keys on internet/multimedia +keyboards. + +The HotKeys daemon listens for the "special" hotkeys that you won't +normally use on your Internet/Multimedia keyboards. The buttons +perform their intended behaviors, such as volume up and down, mute the +speaker, or launch applications. It has On-screen display (OSD) to +show the volume, program that's being started, etc. It features an +XML-based keycode configuration file format, which makes it possible +to define the hotkeys to launch any programs you want. + +You may reach it at http://ypwong.org/hotkeys/ + +Files in this directory provide examles for hotkeys definition files +for certain laptop models supported by omnibook module: + +ob5xx.def: HP OmniBook 5xx +xe3gc.def: HP OmniBook XE3 GC, GD, GE and HP Pavilion N5xxx +xe3gf.def: HP OmniBook XE3 GF +xe4xxx.def: HP OmniBook xe4xxx and ze4xxx +xt155.def: HP OmniBook xt155 +nx9xxx.def: HP/Compaq nx9xxx --- linux-2.6.37.orig/ubuntu/omnibook/misc/hotkeys/nx9xxx.def +++ linux-2.6.37/ubuntu/omnibook/misc/hotkeys/nx9xxx.def @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + Sound muted + + + + + Soos, Peter + sp@osb.hu + + --- linux-2.6.37.orig/ubuntu/omnibook/misc/hotkeys/ob5xx.def +++ linux-2.6.37/ubuntu/omnibook/misc/hotkeys/ob5xx.def @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + Soos, Peter + sp@osb.hu + + --- linux-2.6.37.orig/ubuntu/omnibook/misc/hotkeys/xe3gc.def +++ linux-2.6.37/ubuntu/omnibook/misc/hotkeys/xe3gc.def @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + Sound muted + + + + + Soos, Peter + sp@osb.hu + + --- linux-2.6.37.orig/ubuntu/omnibook/misc/hotkeys/xe3gf.def +++ linux-2.6.37/ubuntu/omnibook/misc/hotkeys/xe3gf.def @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + Sound muted + + + + + Soos, Peter + sp@osb.hu + + --- linux-2.6.37.orig/ubuntu/omnibook/misc/hotkeys/xe4xxx.def +++ linux-2.6.37/ubuntu/omnibook/misc/hotkeys/xe4xxx.def @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + Sound muted + + + + + Soos, Peter + sp@osb.hu + + --- linux-2.6.37.orig/ubuntu/omnibook/misc/hotkeys/xt155.def +++ linux-2.6.37/ubuntu/omnibook/misc/hotkeys/xt155.def @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + Soos, Peter + sp@osb.hu + + --- linux-2.6.37.orig/ubuntu/rfkill/BOM +++ linux-2.6.37/ubuntu/rfkill/BOM @@ -0,0 +1,6 @@ +Downloaded from: http://sourceforge.net/project/showfiles.php?group_id=108766 +Current Version: 1.3 +Comments: + +Had to change &proc_root to NULL due to changes in create/remove proc +entry usage. --- linux-2.6.37.orig/ubuntu/rfkill/Kconfig +++ linux-2.6.37/ubuntu/rfkill/Kconfig @@ -0,0 +1,9 @@ +config AVERATEC_5100P + tristate "Software kill switch for Averatec 5100P" + depends on X86 + default m + +config PACKARDBELL_E5 + tristate "Software kill switch for Packard Bell EasyNote E5" + depends on X86 + default m --- linux-2.6.37.orig/ubuntu/rfkill/Makefile +++ linux-2.6.37/ubuntu/rfkill/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for Ubuntu additional drivers +# + +obj-$(CONFIG_AVERATEC_5100P) += av5100.o +obj-$(CONFIG_PACKARDBELL_E5) += pbe5.o --- linux-2.6.37.orig/ubuntu/rfkill/av5100.c +++ linux-2.6.37/ubuntu/rfkill/av5100.c @@ -0,0 +1,174 @@ +/******************************************************************************* + + Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + James P. Ketrenos + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DRV_NAME "av5100" +#define DRV_VERSION "1.3" +#define DRV_DESCRIPTION "SW RF kill switch for Averatec 5100P" +#define DRV_COPYRIGHT "Copyright(c) 2003-2004 Intel Corporation" + +static int radio = 1; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + +MODULE_PARM(radio, "i"); + +#else /* LINUX_VERSION_CODE < 2.6.0 */ + +#include +module_param(radio, int, 1); + +#endif /* LINUX_VERSION_CODE < 2.6.0 */ + +MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)"); + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_COPYRIGHT); +MODULE_LICENSE("GPL"); + +#define AV5100_RADIO_ON (0xe0) +#define AV5100_RADIO_OFF (0xe1) + +static int av5100_radio = AV5100_RADIO_OFF; + +static void av5100_set_radio(int state) +{ + printk(KERN_INFO DRV_NAME ": Radio being turned %s\n", + (state == AV5100_RADIO_ON) ? "ON" : "OFF"); + outl(0x80020800, 0xcf8); + outb(0x6f, 0x0072); + outl(0x1800ffff, 0x1184); + outb(state, 0x00b2); + av5100_radio = state; +} + + +/* + * proc stuff + */ +static struct proc_dir_entry *dir_base = NULL; + +static int proc_set_radio(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + av5100_set_radio(buffer[0] == '0' ? AV5100_RADIO_OFF : AV5100_RADIO_ON); + + return count; +} + +static int proc_get_radio(char *page, char **start, off_t offset, + int count, int *eof, void *data) +{ + int len = 0; + + len += snprintf(page, count, DRV_NAME ": %d\n", + av5100_radio == AV5100_RADIO_OFF ? 0 : 1); + + *eof = 1; + return len; +} + + +static void av5100_proc_cleanup(void) +{ + if (dir_base) { + remove_proc_entry("radio", dir_base); + remove_proc_entry(DRV_NAME, NULL); + dir_base = NULL; + } +} + + +static int av5100_proc_init(void) +{ + struct proc_dir_entry *ent; + int err = 0; + + dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL); + if (dir_base == NULL) { + printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/" + DRV_NAME "\n"); + err = -ENOMEM; + goto fail; + } + + + ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR, + dir_base); + if (ent) { + ent->read_proc = proc_get_radio; + ent->write_proc = proc_set_radio; + } else { + printk(KERN_ERR + "Unable to initialize /proc/" DRV_NAME "/radio\n"); + err = -ENOMEM; + goto fail; + } + + return 0; + + fail: + av5100_proc_cleanup(); + return err; +} + +/* + * module stuff + */ +static int __init av5100_init(void) +{ + av5100_proc_init(); + + av5100_set_radio((radio == 1) ? AV5100_RADIO_ON : AV5100_RADIO_OFF); + + return 0; +} + +static void __exit av5100_exit(void) +{ + av5100_set_radio(AV5100_RADIO_OFF); + + av5100_proc_cleanup(); +} + +module_init(av5100_init); +module_exit(av5100_exit); + +/* + 1 2 3 4 5 6 7 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +*/ --- linux-2.6.37.orig/ubuntu/rfkill/pbe5.c +++ linux-2.6.37/ubuntu/rfkill/pbe5.c @@ -0,0 +1,205 @@ +/******************************************************************************* + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Author: + Pedro Ramalhais + + Based on: + av5100.c from http://ipw2100.sourceforge.net/ + +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "pbe5" +#define DRV_VERSION "1.3" +#define DRV_DESCRIPTION "SW RF kill switch for Packard Bell EasyNote E5" +#define DRV_AUTHOR "Pedro Ramalhais" +#define DRV_LICENSE "GPL" + +static int radio = 1; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) + +MODULE_PARM(radio, "i"); + +#else /* LINUX_VERSION_CODE < 2.6.0 */ + +#include +module_param(radio, int, 1); + +#endif /* LINUX_VERSION_CODE < 2.6.0 */ + +MODULE_PARM_DESC(radio, "controls state of radio (1=on, 0=off)"); + +MODULE_DESCRIPTION(DRV_DESCRIPTION); +MODULE_AUTHOR(DRV_AUTHOR); +MODULE_LICENSE(DRV_LICENSE); + +/* + * NOTE: These values were obtained from disassembling the Icon.exe program + * installed in the Packard Bell EasyNote E5 laptop. The names were guessed, + * so don't rely on them. + */ +#define PBE5_PORT_TOGGLE 0x0b3 +#define PBE5_VALUE_TOGGLE_ON 0x01 +#define PBE5_VALUE_TOGGLE_OFF 0x00 +#define PBE5_PORT_APPLY 0x0b2 +#define PBE5_VALUE_APPLY 0xef + +// Some "booleans" =;-) +#define PBE5_RADIO_OFF 0 +#define PBE5_RADIO_ON 1 + +static int pbe5_radio_status = PBE5_RADIO_ON; + +unsigned char pbe5_get_radio(void) +{ + unsigned char val = 0x00; + + val = inb(PBE5_PORT_TOGGLE); + + return val; +} + +static void pbe5_set_radio(int state_set) +{ + pbe5_radio_status = pbe5_get_radio(); + + if (pbe5_radio_status != state_set) { + // Set the radio toggle register + outb(PBE5_VALUE_TOGGLE_ON, PBE5_PORT_TOGGLE); + // Commit the radio toggle register value + outb(PBE5_VALUE_APPLY, PBE5_PORT_APPLY); + // Update the radio status + pbe5_radio_status = pbe5_get_radio(); + + printk(KERN_INFO DRV_NAME ": Radio turned %s\n", + (state_set == PBE5_RADIO_ON) ? "ON" : "OFF"); + } else { + printk(KERN_INFO DRV_NAME ": Radio already %s\n", + (state_set == PBE5_RADIO_ON) ? "ON" : "OFF"); + } +} + + +/* + * proc stuff + */ +static struct proc_dir_entry *dir_base = NULL; + +static int proc_set_radio(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + pbe5_set_radio(buffer[0] == '0' ? PBE5_RADIO_OFF : PBE5_RADIO_ON); + + return count; +} + +static int proc_get_radio(char *page, char **start, off_t offset, + int count, int *eof, void *data) +{ + int len = 0; + + len += snprintf(page, count, DRV_NAME ": %d\n", + pbe5_radio_status == PBE5_RADIO_OFF ? 0 : 1); + + *eof = 1; + return len; +} + + +static void pbe5_proc_cleanup(void) +{ + if (dir_base) { + remove_proc_entry("radio", dir_base); + remove_proc_entry(DRV_NAME, NULL); + dir_base = NULL; + } +} + + +static int pbe5_proc_init(void) +{ + struct proc_dir_entry *ent; + int err = 0; + + dir_base = create_proc_entry(DRV_NAME, S_IFDIR, NULL); + if (dir_base == NULL) { + printk(KERN_ERR DRV_NAME ": Unable to initialise /proc/" + DRV_NAME "\n"); + err = -ENOMEM; + goto fail; + } + + + ent = create_proc_entry("radio", S_IFREG | S_IRUGO | S_IWUSR, + dir_base); + if (ent) { + ent->read_proc = proc_get_radio; + ent->write_proc = proc_set_radio; + } else { + printk(KERN_ERR + "Unable to initialize /proc/" DRV_NAME "/radio\n"); + err = -ENOMEM; + goto fail; + } + + return 0; + + fail: + pbe5_proc_cleanup(); + return err; +} + +/* + * module stuff + */ +static int __init pbe5_init(void) +{ + pbe5_proc_init(); + + pbe5_set_radio((radio == 1) ? PBE5_RADIO_ON : PBE5_RADIO_OFF); + + return 0; +} + +static void __exit pbe5_exit(void) +{ + pbe5_set_radio(PBE5_RADIO_OFF); + + pbe5_proc_cleanup(); +} + +module_init(pbe5_init); +module_exit(pbe5_exit); + +/* + 1 2 3 4 5 6 7 +12345678901234567890123456789012345678901234567890123456789012345678901234567890 +*/ --- linux-2.6.37.orig/ubuntu/rtl8192se/BOM +++ linux-2.6.37/ubuntu/rtl8192se/BOM @@ -0,0 +1,2 @@ +Downloaded from: http://www.realtek.com/products/productsView.aspx?Langid=1&PFid=48&Level=5&Conn=4&ProdID=230 +Current Version: 0017.0507.2010 --- linux-2.6.37.orig/ubuntu/rtl8192se/Kconfig +++ linux-2.6.37/ubuntu/rtl8192se/Kconfig @@ -0,0 +1,5 @@ +config RTL8192SE + tristate "Kernel module for RTL81991/2SE or RTL8171 wireless" + depends on X86 + default m + ---help--- --- linux-2.6.37.orig/ubuntu/rtl8192se/Makefile +++ linux-2.6.37/ubuntu/rtl8192se/Makefile @@ -0,0 +1,924 @@ +NIC_SELECT = RTL8192SE + +CC = gcc +KVER := $(shell uname -r) +MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/ + +ifeq ($(shell uname -r|cut -d. -f1,2), 2.6) +###################### KERNEL 2.6 ################################ +ifeq ($(NIC_SELECT),RTL8192CE) +sub_folder = rtl8192c +EXTRA_CFLAGS = -DRTL8192CE +EXTRA_CFLAGS += -DEEPROM_OLD_FORMAT_SUPPORT=0 \ + -DRTL8192SU_DISABLE_CCK_RATE=0 \ + -DDISABLE_BB_RF=0 \ + -DRTL92SE_FPGA_VERIFY=0 \ + -DSIMULATE_ETHERNET=0 \ + -DSUPERMAC_92D_ENABLE=0 \ + -DEARLYMODE_ENABLE_FOR_92D=0 \ + -DRTL8192S_DISABLE_FW_DM=0 \ + -DMP_CCK_WORKAROUND=0 \ + -DRTL8192SE_DISABLE_MGNT_QUEUE=0 \ + -DRTL8190_Download_Firmware_From_Header=1 \ + -DMUTUAL_AUTHENTICATION=1 \ + -DFOR_QMI=0 \ + -DCONFIG_PM_RTL \ + -DCONFIG_PM \ + -DENABLE_IPS \ + -DENABLE_LPS \ + -DCONFIG_ASPM_OR_D3 \ + -DENABLE_GPIO_RADIO_CTL \ + -DMP_DRIVER=0 \ + -DENABLE_DOT11D \ + # \ + -DENABLE_TKIP11N \ + -D_ENABLE_SW_BEACON \ + -DUSE_FW_SOURCE_IMG_FILE \ + -DEFUSE_REPG_WORKAROUND \ + -DENABLE_AMSDU \ + -DADHOC_11N \ + -DFOR_ANDROID_X86 \ + -DCONFIG_64BIT_DMA \ + -DCONFIG_BT_30 \ + # +endif + +ifeq ($(NIC_SELECT),RTL8192SE) +sub_folder = rtl8192s +EXTRA_CFLAGS = -DRTL8192SE +EXTRA_CFLAGS += -DEEPROM_OLD_FORMAT_SUPPORT=0 \ + -DRTL92SE_FPGA_VERIFY=0 \ + -DDEMO_BOARD_SUPPORT=1 \ + -DRTL8192SU_DISABLE_CCK_RATE=0 \ + -DRTL8192S_DISABLE_FW_DM=0 \ + -DHAL_MAC_ENABLE=1 \ + -DHAL_BB_ENABLE=1 \ + -DHAL_RF_ENABLE=1 \ + -DRTL8192S_PREPARE_FOR_NORMAL_RELEASE=1 \ + -DDISABLE_BB_RF=0 \ + -DCONFIG_PM_RTL \ + -DCONFIG_PM \ + -DENABLE_GPIO_RADIO_CTL \ + -DRTL8190_Download_Firmware_From_Header=1 \ + -DENABLE_LPS \ + -DCONFIG_RX_CMD \ + -DENABLE_IPS \ + -DUSE_FW_SOURCE_IMG_FILE \ + -DENABLE_DOT11D \ + -DCONFIG_ASPM_OR_D3 \ + -DRTLLIB_RADIOTAP \ + -DCONFIG_CFG_80211 \ + -DCONFIG_RTL_RFKILL \ + # \ + -DCONFIG_CRDA \ + -DCONFIG_FW_SETCHAN \ + -DRTL8192S_WAPI_SUPPORT \ + -D_ENABLE_SW_BEACON \ + -DCONFIG_MP \ + -DENABLE_AMSDU \ + -DADHOC_11N \ + -DEFUSE_REPG_WORKAROUN \ + -DENABLE_TKIP11N \ + -DFOR_ANDROID_X86 \ + # + #NOTICE: + #[1] CONFIG_MP is for MP test, + # you should close IPS/LPS/GPIO/ASPM + #[2] In order to support CRDA, RFKILL + # CONFIG_CFG_80211 need to be enabled at first. + #[3] In order to support CRDA, + # DOT11D need to be enabled at first. + #[4] CRDA and RFKILL can be enabled individually. + + +endif +ifeq ($(NIC_SELECT),RTL8190P) +sub_folder = rtl8192e +EXTRA_CFLAGS += -DRTL8190P \ + -DUSE_FW_SOURCE_IMG_FILE \ + -DEEPROM_OLD_FORMAT_SUPPORT=1 \ + -DENABLE_DOT11D \ + -DCONFIG_PM \ + -DCONFIG_PM_RTL \ + # \ + -DENABLE_TKIP11N \ + -DFOR_ANDROID_X86 \ + # +endif +ifeq ($(NIC_SELECT),RTL8192E) +sub_folder = rtl8192e +EXTRA_CFLAGS+=-DRTL8192E \ + -DEEPROM_OLD_FORMAT_SUPPORT=1 \ + -DUSE_FW_SOURCE_IMG_FILE \ + -DENABLE_IPS \ + -DENABLE_LPS \ + -DENABLE_GPIO_RADIO_CTL \ + -DCONFIG_PM_RTL \ + -DCONFIG_PM \ + -DENABLE_DOT11D + # \ + -DCONFIG_RTL8192_IO_MAP \ + -DCONFIG_ASPM_OR_D3 \ + -DENABLE_TKIP11N \ + -DFOR_ANDROID_X86 \ + # +endif +ifeq ($(NIC_SELECT),RTL8191SE_MESH) +sub_folder = rtl8192s +EXTRA_CFLAGS += -DRTL8192SE \ + -DEEPROM_OLD_FORMAT_SUPPORT=0 \ + -DRTL92SE_FPGA_VERIFY=0 \ + -DDEMO_BOARD_SUPPORT=1 \ + -DRTL8192SU_DISABLE_CCK_RATE=0 \ + -DRTL8192S_DISABLE_FW_DM=0 \ + -DHAL_MAC_ENABLE=1 \ + -DHAL_BB_ENABLE=1 \ + -DHAL_RF_ENABLE=1 \ + -DRTL8192S_PREPARE_FOR_NORMAL_RELEASE=1 \ + -DDISABLE_BB_RF=0 \ + -DRTL8190_Download_Firmware_From_Header=1 \ + -DEFUSE_REPG_WORKAROUND \ + -DCONFIG_PM \ + -DCONFIG_PM_RTL \ + -DENABLE_GPIO_RADIO_CTL \ + -DENABLE_IPS \ + -DENABLE_LPS \ + -DCONFIG_ASPM_OR_D3 \ + -DCUSTOMER_ID_INTEL_CMPC \ + -DMESH_8192_SPECIFIED \ + -D_RTL8192_EXT_PATCH_ \ + -D_MESH_DEBUG_ \ + -DTREE_BASED_ROUTING_ENABLE \ + -DMESH_PATHSEL_DBG_LV=0 \ + -DMESH_PATHSEL_DBG_SIMPLE=0 \ + -DMESH_PATHSEL_DBG_TEST=0 \ + -DBUILT_IN_MSHCLASS \ + -DENABLE_AMSDU \ + -DUSE_FW_SOURCE_IMG_FILE \ + -DENABLE_DOT11D \ + -DCONFIG_RX_CMD \ + # \ + -DADHOC_11N \ + -DCOMPATIBLE_WITH_RALINK_MESH \ + -DCONFIG_CRDA \ + -DCONFIG_FW_SETCHAN \ + -DRTL8192S_WAPI_SUPPORT \ + -DMESH_AUTO_TEST \ + -D_ENABLE_SW_BEACON \ + -DEFUSE_REPG_WORKAROUND \ + -DENABLE_TKIP11N \ + -DFOR_ANDROID_X86 \ + -DCONFIG_MP \ + # +endif + +ifeq ($(NIC_SELECT),RTL8192CE_MESH) +sub_folder = rtl8192c +EXTRA_CFLAGS = -DRTL8192CE +EXTRA_CFLAGS += -DEEPROM_OLD_FORMAT_SUPPORT=0 \ + -DRTL8192SU_DISABLE_CCK_RATE=0 \ + -DDISABLE_BB_RF=0 \ + -DRTL92SE_FPGA_VERIFY=0 \ + -DSIMULATE_ETHERNET=0 \ + -DSUPERMAC_92D_ENABLE=0 \ + -DEARLYMODE_ENABLE_FOR_92D=0 \ + -DRTL8192S_DISABLE_FW_DM=0 \ + -DMP_CCK_WORKAROUND=0 \ + -DRTL8192SE_DISABLE_MGNT_QUEUE=0 \ + -DRTL8190_Download_Firmware_From_Header=1 \ + -DMUTUAL_AUTHENTICATION=1 \ + -DFOR_QMI=0 \ + -DENABLE_TKIP11N \ + -DCONFIG_PM_RTL \ + -DCONFIG_PM \ + -DENABLE_IPS \ + -DENABLE_LPS \ + -DCONFIG_ASPM_OR_D3 \ + -DENABLE_GPIO_RADIO_CTL \ + -DMP_DRIVER=0 \ + -DENABLE_DOT11D \ + -DEFUSE_REPG_WORKAROUND \ + -DCUSTOMER_ID_INTEL_CMPC \ + -DMESH_8192_SPECIFIED \ + -D_RTL8192_EXT_PATCH_ \ + -D_MESH_DEBUG_ \ + -DTREE_BASED_ROUTING_ENABLE \ + -DMESH_PATHSEL_DBG_LV=0 \ + -DMESH_PATHSEL_DBG_SIMPLE=0 \ + -DMESH_PATHSEL_DBG_TEST=0 \ + -DBUILT_IN_MSHCLASS \ + -DENABLE_AMSDU \ + # \ + -D_ENABLE_SW_BEACON \ + -DUSE_FW_SOURCE_IMG_FILE \ + -DCOMPATIBLE_WITH_RALINK_MESH \ + -DEFUSE_REPG_WORKAROUND \ + -DENABLE_AMSDU \ + -DADHOC_11N \ + -DFOR_ANDROID_X86 \ + -DCONFIG_64BIT_DMA \ + # +endif + +#it will fail to compile in suse linux enterprise 10 sp2. This flag is to solve this problem. +ifeq ($(shell uname -r | cut -d. -f1,2,3,4), 2.6.16.60-0) + EXTRA_CFLAGS += -DOPENSUSE_SLED=1 +else + EXTRA_CFLAGS += -DOPENSUSE_SLED=0 +endif + +# Switch AP will fail in moblin2. This flag is to solve this issue. +ifeq ($(shell uname -r | cut -d. -f6 | cut -d- -f1), moblin2) + EXTRA_CFLAGS += -DFOR_MOBLIN +endif + +EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/wireless +EXTRA_CFLAGS += -std=gnu89 +EXTRA_CFLAGS += -O2 +EXTRA_CFLAGS += -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y +EXTRA_CFLAGS += -DTHOMAS_TURBO +#flag for single module compile +EXTRA_CFLAGS += -DBUILT_IN_RTLLIB +#EXTRA_CFLAGS += -DCONFIG_RTLWIFI_DEBUGFS +ifeq ($(NIC_SELECT),RTL8190P) +r8190_pci-objs := rtl_core.o \ + rtl_eeprom.o \ + rtl_ps.o \ + rtl_wx.o \ + rtl_cam.o \ + rtl_dm.o \ + rtl_pm.o \ + rtl_pci.o \ + rtl_debug.o \ + rtl_ethtool.o \ + rtl8192e/r8190P_hwimg.o \ + rtl8192e/r8190P_rtl8256.o \ + rtl8192e/r8192E_dev.o \ + rtl8192e/r8192E_phy.o \ + rtl8192e/r8192E_firmware.o \ + rtl8192e/r8192E_cmdpkt.o \ + ../../rtllib/rtllib_rx.o \ + ../../rtllib/rtllib_softmac.o \ + ../../rtllib/rtllib_tx.o \ + ../../rtllib/rtllib_wx.o \ + ../../rtllib/rtllib_module.o \ + ../../rtllib/rtllib_softmac_wx.o \ + ../../rtllib/rtl819x_HTProc.o \ + ../../rtllib/rtl819x_TSProc.o \ + ../../rtllib/rtl819x_BAProc.o \ + ../../rtllib/dot11d.o \ + ../../rtllib/rtllib_crypt.o \ + ../../rtllib/rtllib_crypt_tkip.o \ + ../../rtllib/rtllib_crypt_ccmp.o \ + ../../rtllib/rtllib_crypt_wep.o + +obj-m := r8190_pci.o +endif +ifeq ($(NIC_SELECT),RTL8192E) +r8192e_pci-objs := rtl_core.o \ + rtl_eeprom.o \ + rtl_ps.o \ + rtl_wx.o \ + rtl_cam.o \ + rtl_dm.o \ + rtl_pm.o \ + rtl_pci.o \ + rtl_debug.o \ + rtl_ethtool.o \ + rtl8192e/r8192E_dev.o \ + rtl8192e/r8192E_phy.o \ + rtl8192e/r8192E_firmware.o \ + rtl8192e/r8192E_cmdpkt.o \ + rtl8192e/r8192E_hwimg.o \ + rtl8192e/r8190P_rtl8256.o \ + ../../rtllib/rtllib_rx.o \ + ../../rtllib/rtllib_softmac.o \ + ../../rtllib/rtllib_tx.o \ + ../../rtllib/rtllib_wx.o \ + ../../rtllib/rtllib_module.o \ + ../../rtllib/rtllib_softmac_wx.o \ + ../../rtllib/rtl819x_HTProc.o \ + ../../rtllib/rtl819x_TSProc.o \ + ../../rtllib/rtl819x_BAProc.o \ + ../../rtllib/dot11d.o \ + ../../rtllib/rtllib_crypt.o \ + ../../rtllib/rtllib_crypt_tkip.o \ + ../../rtllib/rtllib_crypt_ccmp.o \ + ../../rtllib/rtllib_crypt_wep.o +obj-m := r8192e_pci.o +endif +ifeq ($(NIC_SELECT),RTL8192SE) +r8192se_pci-objs := rtl_core.o \ + rtl_regd.o \ + rtl_rfkill.o \ + rtl_eeprom.o \ + rtl_wx.o \ + rtl_cam.o \ + rtl_pm.o \ + rtl_pci.o \ + rtl_ps.o \ + rtl_dm.o \ + rtl_debug.o \ + rtl_ethtool.o \ + rtl8192s/r8192S_dev.o \ + rtl8192s/r8192S_Efuse.o \ + rtl8192s/r8192S_phy.o \ + rtl8192s/r8192S_firmware.o \ + rtl8192s/r8192S_rtl6052.o \ + rtl8192s/r8192S_hwimg.o \ + rtl8192s/r8192S_led.o \ + rtl8192s/r8192S_mp.o \ + rtl8192s/r8192S_scan.o \ + rtllib/rtllib_rx.o \ + rtllib/rtllib_softmac.o \ + rtllib/rtllib_tx.o \ + rtllib/rtllib_wx.o \ + rtllib/rtllib_module.o \ + rtllib/rtllib_softmac_wx.o \ + rtllib/rtl819x_HTProc.o \ + rtllib/rtl819x_TSProc.o \ + rtllib/rtl819x_BAProc.o \ + rtllib/dot11d.o \ + rtllib/rtllib_crypt.o \ + rtllib/rtllib_crypt_tkip.o \ + rtllib/rtllib_crypt_ccmp.o \ + rtllib/rtllib_crypt_wep.o \ + rtllib/wapi.o \ + rtllib/wapi_interface.o +# rtl8192e/r8190P_rtl8256.o +obj-m := r8192se_pci.o +endif + +ifeq ($(NIC_SELECT),RTL8192CE) +r8192ce_pci-objs := rtl_core.o \ + rtl_eeprom.o \ + rtl_wx.o \ + rtl_cam.o \ + rtl_pm.o \ + rtl_pci.o \ + rtl_ps.o \ + rtl_debug.o \ + rtl_ethtool.o \ + rtl8192c/r8192C_dev.o \ + rtl8192c/r8192C_Efuse.o \ + rtl8192c/r8192C_phy.o \ + rtl8192c/r8192C_firmware.o \ + rtl8192c/r8192C_dm.o \ + rtl8192c/r8192C_rtl6052.o \ + rtl8192c/r8192C_hwimg.o \ + rtl8192c/r8192C_led.o \ + rtl8192c/r8192C_com.o \ + ../../rtllib/rtllib_rx.o \ + ../../rtllib/rtllib_softmac.o \ + ../../rtllib/rtllib_tx.o \ + ../../rtllib/rtllib_wx.o \ + ../../rtllib/rtllib_module.o \ + ../../rtllib/rtllib_softmac_wx.o \ + ../../rtllib/rtl819x_HTProc.o \ + ../../rtllib/rtl819x_TSProc.o \ + ../../rtllib/rtl819x_BAProc.o \ + ../../rtllib/dot11d.o \ + ../../rtllib/rtllib_crypt.o \ + ../../rtllib/rtllib_crypt_tkip.o \ + ../../rtllib/rtllib_crypt_ccmp.o \ + ../../rtllib/rtllib_crypt_wep.o \ + # BT3.0 \ + ../../btlib/bt_aes.o \ + ../../btlib/bt_rc4.o \ + ../../btlib/bt_md5c.o \ + ../../btlib/bt_kmsm_hmac.o \ + ../../btlib/bt_kmsm_prf.o \ + ../../btlib/bt_kmsm_eapolkey.o \ + ../../btlib/bt_hci.o \ + ../../btlib/bt_handlePacket.o \ + ../../btlib/bt_wifi.o +obj-m := r8192ce_pci.o +endif + +ifeq ($(NIC_SELECT),RTL8191SE_MESH) +r8192se_pci_mesh-objs := rtl_core.o \ + rtl_regd.o \ + rtl_rfkill.o \ + rtl_eeprom.o \ + rtl_ps.o \ + rtl_wx.o \ + rtl_cam.o \ + rtl_dm.o \ + rtl_pm.o \ + rtl_pci.o \ + rtl_debug.o \ + rtl_ethtool.o \ + rtl_mesh.o \ + rtl8192s/r8192S_dev.o \ + rtl8192s/r8192S_Efuse.o \ + rtl8192s/r8192S_phy.o \ + rtl8192s/r8192S_firmware.o \ + rtl8192s/r8192S_rtl6052.o \ + rtl8192s/r8192S_hwimg.o \ + rtl8192s/r8192S_led.o \ + rtl8192s/r8192S_mp.o \ + rtl8192s/r8192S_scan.o \ + ../../rtllib/rtllib_rx.o \ + ../../rtllib/rtllib_softmac.o \ + ../../rtllib/rtllib_tx.o \ + ../../rtllib/rtllib_wx.o \ + ../../rtllib/rtllib_module.o \ + ../../rtllib/rtllib_softmac_wx.o \ + ../../rtllib/rtl819x_HTProc.o \ + ../../rtllib/rtl819x_TSProc.o \ + ../../rtllib/rtl819x_BAProc.o \ + ../../rtllib/dot11d.o \ + ../../rtllib/rtllib_crypt.o \ + ../../rtllib/rtllib_crypt_tkip.o \ + ../../rtllib/rtllib_crypt_ccmp.o \ + ../../rtllib/rtllib_crypt_wep.o \ + ../../mshclass/msh_class.o \ + ../../mshclass/mesh_8192_util.o \ + ../../mshclass/rtl8192_mesh.o \ + ../../mshclass/rtl8192s_sme.o \ + ../../mshclass/rtl8192_proc.o \ + ../../mshclass/8192s_pathsel.o \ + ../../mshclass/hash_table.o \ + ../../mshclass/rtl8192_sha1.o \ + ../../mshclass/rtl8192_sha256.o \ + ../../mshclass/rtl8192_aes.o \ + ../../mshclass/mesh_abbr_handshk.o \ + ../../mshclass/rtl8192_bn_ctx.o \ + ../../mshclass/rtl8192_bn_asm.o \ + ../../mshclass/rtl8192_bn_gcd.o \ + ../../mshclass/rtl8192_bn_mont.o \ + ../../mshclass/rtl8192_bn_recp.o \ + ../../mshclass/rtl8192_bn_lib.o \ + ../../mshclass/mesh_ath.o \ + ../../mshclass/pathselection.o \ + ../../mshclass/tree_proactive.o +# rtl8192e/r8190P_rtl8256.o +obj-m := r8192se_pci_mesh.o +endif + +ifeq ($(NIC_SELECT),RTL8192CE_MESH) +r8192ce_pci_mesh-objs := rtl_core.o \ + rtl_eeprom.o \ + rtl_wx.o \ + rtl_cam.o \ + rtl_pm.o \ + rtl_pci.o \ + rtl_ps.o \ + rtl_debug.o \ + rtl_ethtool.o \ + rtl_mesh.o \ + rtl8192c/r8192C_dev.o \ + rtl8192c/r8192C_Efuse.o \ + rtl8192c/r8192C_phy.o \ + rtl8192c/r8192C_firmware.o \ + rtl8192c/r8192C_dm.o \ + rtl8192c/r8192C_rtl6052.o \ + rtl8192c/r8192C_hwimg.o \ + rtl8192c/r8192C_led.o \ + rtl8192c/r8192C_com.o \ + rtl8192c/r8192C_PhyParam.o \ + ../../rtllib/rtllib_rx.o \ + ../../rtllib/rtllib_softmac.o \ + ../../rtllib/rtllib_tx.o \ + ../../rtllib/rtllib_wx.o \ + ../../rtllib/rtllib_module.o \ + ../../rtllib/rtllib_softmac_wx.o \ + ../../rtllib/rtl819x_HTProc.o \ + ../../rtllib/rtl819x_TSProc.o \ + ../../rtllib/rtl819x_BAProc.o \ + ../../rtllib/dot11d.o \ + ../../rtllib/rtllib_crypt.o \ + ../../rtllib/rtllib_crypt_tkip.o \ + ../../rtllib/rtllib_crypt_ccmp.o \ + ../../rtllib/rtllib_crypt_wep.o \ + ../../mshclass/msh_class.o \ + ../../mshclass/mesh_8192_util.o \ + ../../mshclass/rtl8192_mesh.o \ + ../../mshclass/rtl8192s_sme.o \ + ../../mshclass/rtl8192_proc.o \ + ../../mshclass/8192s_pathsel.o \ + ../../mshclass/hash_table.o \ + ../../mshclass/rtl8192_sha1.o \ + ../../mshclass/rtl8192_sha256.o \ + ../../mshclass/rtl8192_aes.o \ + ../../mshclass/mesh_abbr_handshk.o \ + ../../mshclass/rtl8192_bn_ctx.o \ + ../../mshclass/rtl8192_bn_asm.o \ + ../../mshclass/rtl8192_bn_gcd.o \ + ../../mshclass/rtl8192_bn_mont.o \ + ../../mshclass/rtl8192_bn_recp.o \ + ../../mshclass/rtl8192_bn_lib.o \ + ../../mshclass/mesh_ath.o \ + ../../mshclass/pathselection.o \ + ../../mshclass/tree_proactive.o + +obj-m := r8192ce_pci_mesh.o +endif + +KSRC := /lib/modules/$(KVER)/build +INSTALL_PREFIX := +IMG_DIR := /lib/firmware/ +all: modules + +modules: + $(MAKE) -C $(KSRC) M=$(PWD) CC=$(CC) modules +install: modules +ifeq ($(NIC_SELECT),RTL8190P) + install -p -m 644 r8190_pci.ko $(MODDESTDIR) +endif +ifeq ($(NIC_SELECT),RTL8192E) + install -p -m 644 r8192e_pci.ko $(MODDESTDIR) +endif +ifeq ($(NIC_SELECT),RTL8192SE) + install -p -m 644 r8192se_pci.ko $(MODDESTDIR) +endif +ifeq ($(NIC_SELECT),RTL8192CE) + install -p -m 644 r8192ce_pci.ko $(MODDESTDIR) +endif +ifeq ($(NIC_SELECT),RTL8191SE_MESH) + mkdir /usr/share/enhanced-easy-network -p + cp ../../script/mesh-tools /usr/share/enhanced-easy-network/ -rf + cp ../../script/mesh.conf /etc/ + cp ../../script/wpa_mesh_tkip.conf /etc/ + cp ../../script/wpa_mesh_ccmp.conf /etc/ + chmod 777 ../../script/do_install + ../../script/do_install + install -p -m 644 r8192se_pci_mesh.ko $(MODDESTDIR) +endif +ifeq ($(NIC_SELECT),RTL8192CE_MESH) + mkdir /usr/share/enhanced-easy-network -p + cp ../../script/mesh-tools /usr/share/enhanced-easy-network/ -rf + cp ../../script/mesh.conf /etc/ + cp ../../script/wpa_mesh_tkip.conf /etc/ + cp ../../script/wpa_mesh_ccmp.conf /etc/ + chmod 777 ../../script/do_install + ../../script/do_install + install -p -m 644 r8192ce_pci_mesh.ko $(MODDESTDIR) +endif + + depmod -a + @#copy firmware img to target fold + $(shell [ -d "$(IMG_DIR)/`uname -r`" ] && cp -fr $(RTL819x_FIRM_DIR)/$(NIC_SELECT) $(IMG_DIR)/`uname -r`/.) + $(shell [ ! -d "$(IMG_DIR)/`uname -r`" ] && cp -fr $(RTL819x_FIRM_DIR)/$(NIC_SELECT) $(IMG_DIR)/.) +uninstall: +ifeq ($(NIC_SELECT),RTL8190P) + $(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8190_pci.ko) +endif +ifeq ($(NIC_SELECT),RTL8192E) + $(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192e_pci.ko) +endif +ifeq ($(NIC_SELECT),RTL8192SE) + $(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192se_pci.ko) +endif +ifeq ($(NIC_SELECT),RTL8192CE) + $(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192ce_pci.ko) +endif +ifeq ($(NIC_SELECT),RTL8191SE_MESH) + rm -f /etc/wpa_mesh_tkip.conf + rm -f /etc/wpa_mesh_ccmp.conf + $(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192se_pci_mesh.ko) +endif + depmod -a + @#delete the firmware img + @rm -fr /lib/firmware/$(NIC_SELECT) + @rm -fr /lib/firmware/`uname -r`/$(NIC_SELECT) +else +###################### KERNEL 2.4 ################################ +LD := ld +KSRC := /lib/modules/$(KVER)/build +CONFIG_FILE := $(KSRC)/include/linux/autoconf.h +CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall +CFLAGS += -I$(KSRC)/include -I. +CFLAGS += -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h +#CFLAGS += -D__NO_VERSION__ -DEXPORT_SYMTAB + +ifeq ($(NIC_SELECT),RTL8190P) +sub_folder = rtl8192e +CFLAGS += -DRTL8190P +CFLAGS+=-DEEPROM_OLD_FORMAT_SUPPORT=1 +#CFLAGS +=-DCONFIG_RTLWIFI_DEBUGFS +endif + +ifeq ($(NIC_SELECT),RTL8192E) +sub_folder = rtl8192e +CFLAGS += -DRTL8192E +CFLAGS+=-DEEPROM_OLD_FORMAT_SUPPORT=1 +CFLAGS+=-DENABLE_GPIO_RADIO_CTL +#CFLAGS += -DENABLE_IPS +#CFLAGS += -DENABLE_IPS +#CFLAGS +=-DCONFIG_RTLWIFI_DEBUGFS +endif + +ifeq ($(NIC_SELECT),RTL8192SE) +sub_folder = rtl8192s +CFLAGS += -DRTL8192SE +CFLAGS += -DEEPROM_OLD_FORMAT_SUPPORT=0 +CFLAGS += -DRTL92SE_FPGA_VERIFY=0 +CFLAGS += -DDEMO_BOARD_SUPPORT=1 +CFLAGS += -DRTL8192SU_DISABLE_CCK_RATE=0 +CFLAGS += -DRTL8192S_DISABLE_FW_DM=0 +CFLAGS += -DHAL_MAC_ENABLE=1 +CFLAGS += -DHAL_BB_ENABLE=1 +CFLAGS += -DHAL_RF_ENABLE=1 +CFLAGS += -DRTL8192S_PREPARE_FOR_NORMAL_RELEASE=1 +CFLAGS += -DDISABLE_BB_RF=0 +CFLAGS += -DRTL8190_Download_Firmware_From_Header=1 +#CFLAGS += -DRTL8192S_WAPI_SUPPORT=1 +#CFLAGS +=-DCONFIG_RTLWIFI_DEBUGFS +#CFLAGS += -DCONFIG_PM_RTL +#CFLAGS += -DENABLE_GPIO_RADIO_CTL +#EXTRA_CFLAGS += -DCONFIG_PM +#EXTRA_CFLAGS += -DENABLE_IPS +#EXTRA_CFLAGS += -DENABLE_LPS +#EXTRA_CFLAGS += -DCONFIG_ASPM_OR_D3 +#CFLAGS += -DENABLE_AMSDU +#CFLAGS += -DADHOC_11N +endif + +ifeq ($(NIC_SELECT),RTL8191SE_MESH) +sub_folder = rtl8192s +CFLAGS += -DRTL8192SE +CFLAGS +=-DEEPROM_OLD_FORMAT_SUPPORT=1 +#CFLAGS +=-DCONFIG_RTLWIFI_DEBUGFS +CFLAGS += -DEEPROM_OLD_FORMAT_SUPPORT=0 +CFLAGS += -DRTL92SE_FPGA_VERIFY=0 +CFLAGS += -DDEMO_BOARD_SUPPORT=1 +CFLAGS += -DRTL8192SU_DISABLE_CCK_RATE=0 +CFLAGS += -DRTL8192S_DISABLE_FW_DM=0 +CFLAGS += -DHAL_MAC_ENABLE=1 +CFLAGS += -DHAL_BB_ENABLE=1 +CFLAGS += -DHAL_RF_ENABLE=1 +CFLAGS += -DRTL8192S_PREPARE_FOR_NORMAL_RELEASE=1 +CFLAGS += -DDISABLE_BB_RF=0 +CFLAGS += -DCONFIG_PM_RTL +CFLAGS += -DENABLE_GPIO_RADIO_CTL +CFLAGS += -DRTL8190_Download_Firmware_From_Header=1 +CFLAGS += -DENABLE_IPS +CFLAGS += -DENABLE_LPS +CFLAGS += -DCONFIG_ASPM_OR_D3 +CFLAGS += -D_RTL8192_EXT_PATCH_ \ + -DMESH_8192_SPECIFIED \ + -D_MESH_DEBUG_ \ + -DTREE_BASED_ROUTING_ENABLE \ + -DMESH_PATHSEL_DBG_LV=0 \ + -DMESH_PATHSEL_DBG_SIMPLE=0 \ + -DMESH_PATHSEL_DBG_TEST=0\ + -DBUILT_IN_MSHCLASS \ + -DCUSTOMER_ID_INTEL_CMPC \ + -DENABLE_AMSDU +endif +CFLAGS += -DTHOMAS_TURBO +CFLAGS += -DENABLE_DOT11D + +#flag for single module compile +CFLAGS += -DBUILT_IN_RTLLIB +CFLAGS += -DBUILT_IN_CRYPTO +#CFLAGS += -DENABLE_TKIP11N + +SMP := $(shell $(CC) $(CFLAGS) -E -dM $(CONFIG_FILE) | \ + grep CONFIG_SMP | awk '{print $$3}') +ifneq ($(SMP),1) + SMP := 0 +endif +ifeq ($(SMP),1) + CFLAGS += -D__SMP__ +endif +OBJS := ${patsubst %.c, %.o, ${wildcard *.c}} + +ifeq ($(NIC_SELECT),RTL8190P) +all:r8190_pci.o +r8190_pci.o: \ + rtl_core.o \ + rtl_eeprom.o \ + rtl_ps.o \ + rtl_dm.o \ + rtl_wx.o \ + rtl_cam.o \ + rtl_pm.o \ + rtl_pci.o \ + rtl_debug.o \ + rtl_ethtool.o \ + rtl8192e/r8190P_rtl8256.o \ + rtl8192e/r8190P_hwimg.o \ + rtl8192e/r8192E_dev.o \ + rtl8192e/r8192E_cmdpkt.o\ + rtl8192e/r8192E_firmware.o \ + rtl8192e/r8192E_phy.o \ + ../../rtllib/rtllib_rx.o \ + ../../rtllib/rtllib_softmac.o \ + ../../rtllib/rtllib_tx.o \ + ../../rtllib/rtllib_wx.o \ + ../../rtllib/rtllib_module.o \ + ../../rtllib/rtllib_softmac_wx.o \ + ../../rtllib/rtl819x_HTProc.o \ + ../../rtllib/rtl819x_TSProc.o \ + ../../rtllib/rtl819x_BAProc.o \ + ../../rtllib/dot11d.o \ + ../../rtllib/rtllib_crypt.o \ + ../../rtllib/rtllib_crypt_tkip.o \ + ../../rtllib/rtllib_crypt_ccmp.o \ + ../../rtllib/rtllib_crypt_wep.o \ + ../../rtllib/api.o \ + ../../rtllib/compress.o \ + ../../rtllib/digest.o \ + ../../rtllib/cipher.o \ + ../../rtllib/scatterwalk.o \ + ../../rtllib/arc4.o \ + ../../rtllib/michael_mic.o \ + ../../rtllib/aes.o \ + ../../rtllib/proc.o + + $(LD) -r $^ -o $@ +install:r8190_pci.o + install -p -m 644 r8190_pci.o $(MODDESTDIR) + @depmod -a +uninstall: + $(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8190_pci.o) + @depmod -a +endif + +ifeq ($(NIC_SELECT),RTL8192E) +all:r8192e_pci.o +r8192e_pci.o: \ + rtl_core.o \ + rtl_eeprom.o \ + rtl_ps.o \ + rtl_dm.o \ + rtl_wx.o \ + rtl_cam.o \ + rtl_pm.o \ + rtl_pci.o \ + rtl_debug.o \ + rtl_ethtool.o \ + rtl8192e/r8192E_dev.o \ + rtl8192e/r8190P_rtl8256.o \ + rtl8192e/r8192E_hwimg.o \ + rtl8192e/r8192E_cmdpkt.o\ + rtl8192e/r8192E_firmware.o \ + rtl8192e/r8192E_phy.o \ + ../../rtllib/rtllib_rx.o \ + ../../rtllib/rtllib_softmac.o \ + ../../rtllib/rtllib_tx.o \ + ../../rtllib/rtllib_wx.o \ + ../../rtllib/rtllib_module.o \ + ../../rtllib/rtllib_softmac_wx.o \ + ../../rtllib/rtl819x_HTProc.o \ + ../../rtllib/rtl819x_TSProc.o \ + ../../rtllib/rtl819x_BAProc.o \ + ../../rtllib/dot11d.o \ + ../../rtllib/rtllib_crypt.o \ + ../../rtllib/rtllib_crypt_tkip.o \ + ../../rtllib/rtllib_crypt_ccmp.o \ + ../../rtllib/rtllib_crypt_wep.o \ + ../../rtllib/api.o \ + ../../rtllib/compress.o \ + ../../rtllib/digest.o \ + ../../rtllib/cipher.o \ + ../../rtllib/scatterwalk.o \ + ../../rtllib/arc4.o \ + ../../rtllib/michael_mic.o \ + ../../rtllib/aes.o \ + ../../rtllib/proc.o + + $(LD) -r $^ -o $@ +install: + install -p -m 644 r8192e_pci.o $(MODDESTDIR) + @depmod -a +uninstall: + $(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192e_pci.o) + @depmod -a +endif + +ifeq ($(NIC_SELECT),RTL8192SE) +all:r8192se_pci.o +r8192se_pci.o: rtl_core.o \ + rtl_debug.o \ + rtl_ethtool.o \ + rtl_eeprom.o \ + rtl_ps.o \ + rtl_dm.o \ + rtl_wx.o \ + rtl_cam.o \ + rtl_pm.o \ + rtl_pci.o \ + rtl8192s/r8192S_dev.o \ + rtl8192s/r8192S_Efuse.o \ + rtl8192s/r8192S_firmware.o \ + rtl8192s/r8192S_hwimg.o \ + rtl8192s/r8192S_led.o \ + rtl8192s/r8192S_phy.o \ + rtl8192s/r8192S_rtl6052.o \ + ../../rtllib/rtllib_rx.o \ + ../../rtllib/rtllib_softmac.o \ + ../../rtllib/rtllib_tx.o \ + ../../rtllib/rtllib_wx.o \ + ../../rtllib/rtllib_module.o \ + ../../rtllib/rtllib_softmac_wx.o \ + ../../rtllib/rtl819x_HTProc.o \ + ../../rtllib/rtl819x_TSProc.o \ + ../../rtllib/rtl819x_BAProc.o \ + ../../rtllib/dot11d.o \ + ../../rtllib/rtllib_crypt.o \ + ../../rtllib/rtllib_crypt_tkip.o \ + ../../rtllib/rtllib_crypt_ccmp.o \ + ../../rtllib/rtllib_crypt_wep.o \ + ../../rtllib/api.o \ + ../../rtllib/compress.o \ + ../../rtllib/digest.o \ + ../../rtllib/cipher.o \ + ../../rtllib/scatterwalk.o \ + ../../rtllib/arc4.o \ + ../../rtllib/michael_mic.o \ + ../../rtllib/aes.o \ + ../../rtllib/proc.o \ + ../../rtllib/wapi.o \ + ../../rtllib/wapi_interface.o +# rtl8192e/r8192E_cmdpkt.o +# rtl8192e/r8190P_rtl8256.o + $(LD) -r $^ -o $@ +install:r8192se_pci.o + install -p -m 644 r8192se_pci.o $(MODDESTDIR) + @depmod -a +uninstall: + $(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192se_pci.o) + @depmod -a +endif + +ifeq ($(NIC_SELECT),RTL8191SE_MESH ) +all:r8192se_pci_mesh.o +r8192se_pci_mesh.o: \ + rtl_core.o \ + rtl_eeprom.o \ + rtl_ps.o \ + rtl_dm.o \ + rtl_wx.o \ + rtl_cam.o \ + rtl_pm.o \ + rtl_pci.o \ + rtl_debug.o \ + rtl_ethtool.o \ + rtl_mesh.o \ + rtl8192s/r8192S_dev.o \ + rtl8192s/r8192S_Efuse.o \ + rtl8192s/r8192S_firmware.o \ + rtl8192s/r8192S_hwimg.o \ + rtl8192s/r8192S_led.o \ + rtl8192s/r8192S_phy.o \ + rtl8192s/r8192S_rtl6052.o \ + ../../rtllib/rtllib_rx.o \ + ../../rtllib/rtllib_softmac.o \ + ../../rtllib/rtllib_tx.o \ + ../../rtllib/rtllib_wx.o \ + ../../rtllib/rtllib_module.o \ + ../../rtllib/rtllib_softmac_wx.o \ + ../../rtllib/rtl819x_HTProc.o \ + ../../rtllib/rtl819x_TSProc.o \ + ../../rtllib/rtl819x_BAProc.o \ + ../../rtllib/dot11d.o \ + ../../rtllib/rtllib_crypt.o \ + ../../rtllib/rtllib_crypt_tkip.o \ + ../../rtllib/rtllib_crypt_ccmp.o \ + ../../rtllib/rtllib_crypt_wep.o \ + ../../mshclass/msh_class.o \ + ../../mshclass/mesh_8192_util.o \ + ../../mshclass/rtl8192_mesh.o \ + ../../mshclass/rtl8192s_sme.o \ + ../../mshclass/rtl8192_proc.o \ + ../../mshclass/8192s_pathsel.o \ + ../../mshclass/hash_table.o \ + ../../mshclass/pathselection.o \ + ../../mshclass/tree_proactive.o \ + ../../mshclass/hash_table.o \ + ../../mshclass/sha1.o \ + ../../mshclass/sha256.o \ + ../../mshclass/aes.o \ + ../../mshclass/mesh_abbr_handshk.o \ + ../../mshclass/bn_ctx.o \ + ../../mshclass/bn_asm.o \ + ../../mshclass/bn_gcd.o \ + ../../mshclass/bn_mont.o \ + ../../mshclass/bn_recp.o \ + ../../mshclass/bn_lib.o \ + ../../mshclass/mesh_ath.o +# rtl8192e/r8190P_rtl8256.o \ +# rtl8192e/r8192E_cmdpkt.o + $(LD) -r $^ -o $@ +install:r8192se_pci_mesh.o + install -p -m 644 r8192se_pci_mesh.o $(MODDESTDIR) + @depmod -a +uninstall: + $(shell [ -d $(MODDESTDIR) ] && rm -f $(MODDESTDIR)/r8192se_pci_mesh.o) + @depmod -a +endif +endif + +.PHONY:clean +clean: + rm -fr *.mod.c *.mod *.o .*.cmd *.ko *~ + rm -fr .tmp_versions + rm -fr Modules.symvers + rm -fr Module.symvers + rm -fr Module.markers + rm -fr modules.order + rm -fr tags + @make -C $(sub_folder)/ clean --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_cam.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_cam.c @@ -0,0 +1,562 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#include "rtl_core.h" + +extern int hwwep; +void CamResetAllEntry(struct net_device *dev) +{ + u32 ulcommand = 0; + + ulcommand |= BIT31|BIT30; + write_nic_dword(dev, RWCAM, ulcommand); +} + +#ifdef _RTL8192_EXT_PATCH_ +void CamDeleteOneEntry(struct net_device *dev, u8 EntryNo) +{ + u32 ulCommand = EntryNo * CAM_CONTENT_COUNT; + u32 ulContent = 0; + + ulCommand = ulCommand | BIT31 | BIT16; + + write_nic_dword(dev,WCAMI,ulContent); + write_nic_dword(dev,RWCAM,ulCommand); +} + +void CamRestoreEachIFEntry(struct net_device* dev,u8 is_mesh) +{ + u32 i; + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + for( i = 0 ; i< TOTAL_CAM_ENTRY; i++) { + + if (is_mesh) { + if(ieee->swmeshcamtable[i].bused ) + { + setKey(dev, + i, + ieee->swmeshcamtable[i].key_index, + ieee->swmeshcamtable[i].key_type, + ieee->swmeshcamtable[i].macaddr, + ieee->swmeshcamtable[i].useDK, + (u32*)(&ieee->swmeshcamtable[i].key_buf[0]) + ); + } + } else { + if(ieee->swcamtable[i].bused ) + { + setKey(dev, + i, + ieee->swcamtable[i].key_index, + ieee->swcamtable[i].key_type, + ieee->swcamtable[i].macaddr, + ieee->swcamtable[i].useDK, + (u32*)(&ieee->swcamtable[i].key_buf[0])); + } + } + } +} +#endif + +void write_cam(struct net_device *dev, u8 addr, u32 data) +{ + write_nic_dword(dev, WCAMI, data); + write_nic_dword(dev, RWCAM, BIT31|BIT16|(addr&0xff) ); +} + +u32 read_cam(struct net_device *dev, u8 addr) +{ + write_nic_dword(dev, RWCAM, 0x80000000|(addr&0xff) ); + return read_nic_dword(dev, 0xa8); +} + +void EnableHWSecurityConfig8192(struct net_device *dev) +{ + u8 SECR_value = 0x0; + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + SECR_value = SCR_TxEncEnable | SCR_RxDecEnable; +#ifdef _RTL8192_EXT_PATCH_ + if ((((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->rtllib->auth_mode != 2)) + &&(ieee->iw_mode != IW_MODE_MESH)) +#else + if (((KEY_TYPE_WEP40 == ieee->pairwise_key_type) || (KEY_TYPE_WEP104 == ieee->pairwise_key_type)) && (priv->rtllib->auth_mode != 2)) +#endif + { + SECR_value |= SCR_RxUseDK; + SECR_value |= SCR_TxUseDK; + } + else if ((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->pairwise_key_type & (KEY_TYPE_CCMP | KEY_TYPE_TKIP))) + { + SECR_value |= SCR_RxUseDK; + SECR_value |= SCR_TxUseDK; + } + + + ieee->hwsec_active = 1; +#ifdef _RTL8192_EXT_PATCH_ + if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep ) + { + ieee->hwsec_active = 0; + SECR_value &= ~SCR_RxDecEnable; + SECR_value &= ~SCR_TxUseDK; + SECR_value &= ~SCR_RxUseDK; + SECR_value &= ~SCR_TxEncEnable; + } +#else + if ((ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE) || !hwwep) + { + ieee->hwsec_active = 0; + SECR_value &= ~SCR_RxDecEnable; + } +#endif + +#ifdef RTL8192CE + if(IS_NORMAL_CHIP(priv->card_8192_version)) + SECR_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK); + + write_nic_byte(dev, REG_CR+1,0x02); + + RT_TRACE(COMP_SEC,"The SECR-value %x \n",SECR_value) + priv->rtllib->SetHwRegHandler(dev, HW_VAR_WPA_CONFIG, &SECR_value); +#else + RT_TRACE(COMP_SEC,"%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n", __FUNCTION__, \ + ieee->hwsec_active, ieee->pairwise_key_type, SECR_value); + { + write_nic_byte(dev, SECR, SECR_value); + } +#endif +} + +void set_swcam(struct net_device *dev, + u8 EntryNo, + u8 KeyIndex, + u16 KeyType, + u8 *MacAddr, + u8 DefaultKey, + u32 *KeyContent, + u8 is_mesh) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + printk("===========>%s():EntryNo is %d,KeyIndex is %d,KeyType is %d,is_mesh is %d\n",__FUNCTION__,EntryNo,KeyIndex,KeyType,is_mesh); + if(is_mesh){ +#ifdef _RTL8192_EXT_PATCH_ + ieee->swmeshcamtable[EntryNo].bused=true; + ieee->swmeshcamtable[EntryNo].key_index=KeyIndex; + ieee->swmeshcamtable[EntryNo].key_type=KeyType; + memcpy(ieee->swmeshcamtable[EntryNo].macaddr,MacAddr,6); + ieee->swmeshcamtable[EntryNo].useDK=DefaultKey; + memcpy(ieee->swmeshcamtable[EntryNo].key_buf,(u8*)KeyContent,16); +#endif + } + else + { + ieee->swcamtable[EntryNo].bused=true; + ieee->swcamtable[EntryNo].key_index=KeyIndex; + ieee->swcamtable[EntryNo].key_type=KeyType; + memcpy(ieee->swcamtable[EntryNo].macaddr,MacAddr,6); + ieee->swcamtable[EntryNo].useDK=DefaultKey; + memcpy(ieee->swcamtable[EntryNo].key_buf,(u8*)KeyContent,16); + } +} +#ifdef _RTL8192_EXT_PATCH_ +void reset_IFswcam(struct net_device *dev, u8 is_mesh) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + if(is_mesh){ + memset(ieee->swmeshcamtable,0,sizeof(SW_CAM_TABLE)*32); + } + else{ + memset(ieee->swcamtable,0,sizeof(SW_CAM_TABLE)*32); + } +} +#endif +void setKey(struct net_device *dev, + u8 EntryNo, + u8 KeyIndex, + u16 KeyType, + u8 *MacAddr, + u8 DefaultKey, + u32 *KeyContent ) +{ + u32 TargetCommand = 0; + u32 TargetContent = 0; + u16 usConfig = 0; + u8 i; +#ifdef ENABLE_IPS + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + RT_RF_POWER_STATE rtState; + rtState = priv->rtllib->eRFPowerState; + if(priv->rtllib->PowerSaveControl.bInactivePs){ + if(rtState == eRfOff){ + if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) + { + RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__); + return ; + } + else{ + down(&priv->rtllib->ips_sem); + IPSLeave(dev); + up(&priv->rtllib->ips_sem); } + } + } + priv->rtllib->is_set_key = true; +#endif + if (EntryNo >= TOTAL_CAM_ENTRY) + RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n"); + + RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr"MAC_FMT"\n", dev,EntryNo, KeyIndex, KeyType, MAC_ARG(MacAddr)); + + if (DefaultKey) + usConfig |= BIT15 | (KeyType<<2); + else + usConfig |= BIT15 | (KeyType<<2) | KeyIndex; + + + for(i=0 ; i= KERNEL_VERSION(2,6,31)) + udelay(100); +#endif + } + } + } + RT_TRACE(COMP_SEC,"=========>after set key, usconfig:%x\n", usConfig); +} +#if 0 +void CamPrintDbgReg(struct net_device* dev) +{ + unsigned long rvalue; + unsigned char ucValue; + write_nic_dword(dev, DCAM, 0x80000000); + msleep(40); + rvalue = read_nic_dword(dev, DCAM); + RT_TRACE(COMP_SEC, " TX CAM=%8lX ",rvalue); + if((rvalue & 0x40000000) != 0x4000000) + RT_TRACE(COMP_SEC, "-->TX Key Not Found "); + msleep(20); + write_nic_dword(dev, DCAM, 0x00000000); + rvalue = read_nic_dword(dev, DCAM); + RT_TRACE(COMP_SEC, "RX CAM=%8lX ",rvalue); + if((rvalue & 0x40000000) != 0x4000000) + RT_TRACE(COMP_SEC, "-->CAM Key Not Found "); + ucValue = read_nic_byte(dev, SECR); + RT_TRACE(COMP_SEC, "WPA_Config=%x \n",ucValue); +} +#endif +void CAM_read_entry(struct net_device *dev, u32 iIndex) +{ + u32 target_command=0; + u32 target_content=0; + u8 entry_i=0; + u32 ulStatus; + s32 i=100; + for(entry_i=0;entry_i=0) + { + ulStatus = read_nic_dword(dev, RWCAM); + if(ulStatus & BIT31){ + continue; + } + else{ + break; + } + } +#endif + write_nic_dword(dev, RWCAM, target_command); + RT_TRACE(COMP_SEC,"CAM_read_entry(): WRITE A0: %x \n",target_command); + target_content = read_nic_dword(dev, RCAMO); + RT_TRACE(COMP_SEC, "CAM_read_entry(): WRITE A8: %x \n",target_content); + } + printk("\n"); +} + +void CamRestoreAllEntry( struct net_device *dev) +{ + u8 EntryId = 0; + struct r8192_priv *priv = rtllib_priv(dev); + u8* MacAddr = priv->rtllib->current_network.bssid; + + static u8 CAM_CONST_ADDR[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}}; + static u8 CAM_CONST_BROAD[] = + {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + RT_TRACE(COMP_SEC, "CamRestoreAllEntry: \n"); + + + if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40)|| + (priv->rtllib->pairwise_key_type == KEY_TYPE_WEP104)) + { + + for(EntryId=0; EntryId<4; EntryId++) + { + { + MacAddr = CAM_CONST_ADDR[EntryId]; + if(priv->rtllib->swcamtable[EntryId].bused ) + { + setKey(dev, + EntryId , + EntryId, + priv->rtllib->pairwise_key_type, + MacAddr, + 0, + (u32*)(&priv->rtllib->swcamtable[EntryId].key_buf[0]) + ); + } + } + } + + } + else if(priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) + { + + { + if(priv->rtllib->iw_mode == IW_MODE_ADHOC) + { + setKey(dev, + 4, + 0, + priv->rtllib->pairwise_key_type, + (u8*)dev->dev_addr, + 0, + (u32*)(&priv->rtllib->swcamtable[4].key_buf[0]) + ); + } + else + { + setKey(dev, + 4, + 0, + priv->rtllib->pairwise_key_type, + MacAddr, + 0, + (u32*)(&priv->rtllib->swcamtable[4].key_buf[0]) + ); + } + + } + } + else if(priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) + { + + { + if(priv->rtllib->iw_mode == IW_MODE_ADHOC) + { + setKey(dev, + 4, + 0, + priv->rtllib->pairwise_key_type, + (u8*)dev->dev_addr, + 0, + (u32*)(&priv->rtllib->swcamtable[4].key_buf[0]) + ); + } + else + { + setKey(dev, + 4, + 0, + priv->rtllib->pairwise_key_type, + MacAddr, + 0, + (u32*)(&priv->rtllib->swcamtable[4].key_buf[0]) + ); + } + } + } + + + + if(priv->rtllib->group_key_type == KEY_TYPE_TKIP) + { + MacAddr = CAM_CONST_BROAD; + for(EntryId=1 ; EntryId<4 ; EntryId++) + { + if(priv->rtllib->swcamtable[EntryId].bused ) + { + setKey(dev, + EntryId, + EntryId, + priv->rtllib->group_key_type, + MacAddr, + 0, + (u32*)(&priv->rtllib->swcamtable[EntryId].key_buf[0]) + ); + } + } + if(priv->rtllib->iw_mode == IW_MODE_ADHOC) + { + if(priv->rtllib->swcamtable[0].bused ){ + setKey(dev, + 0, + 0, + priv->rtllib->group_key_type, + CAM_CONST_ADDR[0], + 0, + (u32*)(&priv->rtllib->swcamtable[0].key_buf[0]) + ); + } + else + { + RT_TRACE(COMP_ERR,"===>%s():ERR!! ADHOC TKIP ,but 0 entry is have no data\n",__FUNCTION__); + return; + } + } + } else if(priv->rtllib->group_key_type == KEY_TYPE_CCMP) { + MacAddr = CAM_CONST_BROAD; + for(EntryId=1; EntryId<4 ; EntryId++) + { + if(priv->rtllib->swcamtable[EntryId].bused ) + { + setKey(dev, + EntryId , + EntryId, + priv->rtllib->group_key_type, + MacAddr, + 0, + (u32*)(&priv->rtllib->swcamtable[EntryId].key_buf[0])); + } + } + + if (priv->rtllib->iw_mode == IW_MODE_ADHOC) { + if (priv->rtllib->swcamtable[0].bused) { + setKey(dev, + 0 , + 0, + priv->rtllib->group_key_type, + CAM_CONST_ADDR[0], + 0, + (u32*)(&priv->rtllib->swcamtable[0].key_buf[0])); + } else { + RT_TRACE(COMP_ERR,"===>%s():ERR!! ADHOC CCMP ,but 0 entry is have no data\n", + __FUNCTION__); + return; + } + } + } +} + + +#ifdef _RTL8192_EXT_PATCH_ +u8 rtl8192_get_free_hwsec_cam_entry(struct rtllib_device *ieee, u8 *sta_addr) +{ + u32 bitmap = (ieee->HwSecCamBitMap)>>4; + u8 entry_idx = 0; + u8 i, *addr; + + if ((NULL == ieee) || (NULL == sta_addr)) { + printk("%s: ieee or sta_addr is NULL.\n", __FUNCTION__); + return TOTAL_CAM_ENTRY; + } + + /* Does STA already exist? */ + /* CAM Index 31 is for AP */ + for (i = 4; i < TOTAL_CAM_ENTRY-1; i++) { + addr = ieee->HwSecCamStaAddr[i]; + if(memcmp(addr, sta_addr, ETH_ALEN) == 0) + return i; + } + + /* Get a free CAM entry. */ + for (entry_idx = 4; entry_idx < TOTAL_CAM_ENTRY - 1; entry_idx++) { + if ((bitmap & BIT0) == 0) { + ieee->HwSecCamBitMap |= BIT0<HwSecCamStaAddr[entry_idx], sta_addr, ETH_ALEN); + return entry_idx; + } + bitmap = bitmap >>1; + } + + return TOTAL_CAM_ENTRY; +} + +void rtl8192_del_hwsec_cam_entry(struct rtllib_device *ieee, u8 *sta_addr) +{ + u32 bitmap; + u8 i, *addr; + + if ((NULL == ieee) || (NULL == sta_addr)) { + printk("%s: ieee or sta_addr is NULL.\n", __FUNCTION__); + return; + } + + if ((sta_addr[0]|sta_addr[1]|sta_addr[2]|sta_addr[3]|\ + sta_addr[4]|sta_addr[5]) == 0) { + printk("%s: sta_addr is 00:00:00:00:00:00.\n", __FUNCTION__); + return; + } + + /* Does STA already exist? */ + for (i = 4; i < TOTAL_CAM_ENTRY; i++) { + addr = ieee->HwSecCamStaAddr[i]; + bitmap = (ieee->HwSecCamBitMap)>>i; + if (((bitmap & BIT0) == BIT0) && (memcmp(addr, sta_addr, ETH_ALEN) == 0)) { + /* Remove from HW Security CAM */ + CamDeleteOneEntry(ieee->dev, i); + memset(ieee->HwSecCamStaAddr[i], 0, ETH_ALEN); + ieee->HwSecCamBitMap &= ~(BIT0<swmeshcamtable[i]), 0, sizeof(SW_CAM_TABLE)); + RT_TRACE(COMP_SEC, "====>del sw entry, EntryNo:%d, MacAddr:"MAC_FMT"\n", + i, MAC_ARG(sta_addr)); + } + } + return; +} +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_cam.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl_cam.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef _RTL_CAM_H +#define _RTL_CAM_H + +#include +struct net_device; + +void CamResetAllEntry(struct net_device* dev); +void EnableHWSecurityConfig8192(struct net_device *dev); +void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, u8 *MacAddr, u8 DefaultKey, u32 *KeyContent ); +void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh); +void CamPrintDbgReg(struct net_device* dev); + +#ifdef _RTL8192_EXT_PATCH_ +void CamDeleteOneEntry(struct net_device *dev, u8 EntryNo); +void CamRestoreEachIFEntry(struct net_device* dev,u8 is_mesh); +#endif + +u32 read_cam(struct net_device *dev, u8 addr); +void write_cam(struct net_device *dev, u8 addr, u32 data); + +void CamRestoreAllEntry(struct net_device *dev); +#ifdef _RTL8192_EXT_PATCH_ +void reset_IFswcam(struct net_device *dev, u8 is_mesh); +void CamRestoreEachIFEntry(struct net_device* dev,u8 is_mesh); +int rtl8192_set_key_for_AP(struct rtllib_device *ieee); +#endif + +void CAM_read_entry(struct net_device *dev, u32 iIndex); + +#ifdef _RTL8192_EXT_PATCH_ +u8 rtl8192_get_free_hwsec_cam_entry(struct rtllib_device *ieee, u8 *sta_addr); +void rtl8192_del_hwsec_cam_entry(struct rtllib_device *ieee, u8 *sta_addr); +int meshdev_set_key_for_peer(struct net_device *dev, u8 *Addr, u8 KeyIndex, u16 KeyType, u32 *KeyContent); +#endif + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_core.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_core.c @@ -0,0 +1,5988 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#undef LOOP_TEST +#undef RX_DONT_PASS_UL +#undef DEBUG_EPROM +#undef DEBUG_RX_VERBOSE +#undef DUMMY_RX +#undef DEBUG_ZERO_RX +#undef DEBUG_RX_SKB +#undef DEBUG_TX_FRAG +#undef DEBUG_RX_FRAG +#undef DEBUG_TX_FILLDESC +#undef DEBUG_TX +#undef DEBUG_IRQ +#undef DEBUG_RX +#undef DEBUG_RXALLOC +#undef DEBUG_REGISTERS +#undef DEBUG_RING +#undef DEBUG_IRQ_TASKLET +#undef DEBUG_TX_ALLOC +#undef DEBUG_TX_DESC + +#include +#include +#include "rtl_core.h" + +#include "rtl_wx.h" +#ifndef RTL8192CE +#include "rtl_dm.h" +#endif + +#ifdef CONFIG_PM_RTL +#include "rtl_pm.h" +#endif + +#ifdef _RTL8192_EXT_PATCH_ +#include "../../mshclass/msh_class.h" +#include "rtl_mesh.h" +#endif + +#ifdef RTL8192S_WAPI_SUPPORT +#include "../../rtllib/wapi.h" +#include "../../rtllib/wapi_interface.h" +#endif + +int hwwep = 1; +static int channels = 0x3fff; +#ifdef _RTL8192_EXT_PATCH_ +char* ifname = "ra%d"; +#else +char* ifname = "wlan%d"; +#endif + + +#ifdef RTL8192SE +struct rtl819x_ops rtl8192se_ops = { + .nic_type = NIC_8192SE, + .get_eeprom_size = rtl8192se_get_eeprom_size, + .init_adapter_variable = rtl8192se_InitializeVariables, + .init_before_adapter_start = MacConfigBeforeFwDownload, + .initialize_adapter = rtl8192se_adapter_start, + .link_change = rtl8192se_link_change, + .tx_fill_descriptor = rtl8192se_tx_fill_desc, + .tx_fill_cmd_descriptor = rtl8192se_tx_fill_cmd_desc, + .rx_query_status_descriptor = rtl8192se_rx_query_status_desc, + .rx_command_packet_handler = rtl8192se_RxCommandPacketHandle, + .stop_adapter = rtl8192se_halt_adapter, + .update_ratr_table = rtl8192se_update_ratr_table, + .irq_enable = rtl8192se_EnableInterrupt, + .irq_disable = rtl8192se_DisableInterrupt, + .irq_clear = rtl8192se_ClearInterrupt, + .rx_enable = rtl8192se_enable_rx, + .tx_enable = rtl8192se_enable_tx, + .interrupt_recognized = rtl8192se_interrupt_recognized, + .TxCheckStuckHandler = rtl8192se_HalTxCheckStuck, + .RxCheckStuckHandler = rtl8192se_HalRxCheckStuck, +}; +#elif defined RTL8192CE +struct rtl819x_ops rtl8192ce_ops = { + .nic_type = NIC_8192CE, + .get_eeprom_size = rtl8192ce_get_eeprom_size, + .init_adapter_variable = rtl8192ce_InitializeVariables, + .initialize_adapter = rtl8192ce_adapter_start, + .link_change = rtl8192ce_link_change, + .tx_fill_descriptor = rtl8192ce_tx_fill_desc, + .tx_fill_cmd_descriptor = rtl8192ce_tx_fill_cmd_desc, + .rx_query_status_descriptor = rtl8192ce_rx_query_status_desc, + .rx_command_packet_handler = NULL, + .stop_adapter = rtl8192ce_halt_adapter, + .update_ratr_table = rtl8192ce_UpdateHalRATRTable, + .irq_enable = rtl8192ce_EnableInterrupt, + .irq_disable = rtl8192ce_DisableInterrupt, + .irq_clear = rtl8192ce_ClearInterrupt, + .rx_enable = rtl8192ce_enable_rx, + .tx_enable = rtl8192ce_enable_tx, + .interrupt_recognized = rtl8192ce_interrupt_recognized, + .TxCheckStuckHandler = rtl8192ce_HalTxCheckStuck, + .RxCheckStuckHandler = rtl8192ce_HalRxCheckStuck, +}; +#else +struct rtl819x_ops rtl819xp_ops = { +#ifdef RTL8192E + .nic_type = NIC_8192E, +#elif defined RTL8190P + .nic_type = NIC_8190P, +#endif + .get_eeprom_size = rtl8192_get_eeprom_size, + .init_adapter_variable = rtl8192_InitializeVariables, + .initialize_adapter = rtl8192_adapter_start, + .link_change = rtl8192_link_change, + .tx_fill_descriptor = rtl8192_tx_fill_desc, + .tx_fill_cmd_descriptor = rtl8192_tx_fill_cmd_desc, + .rx_query_status_descriptor = rtl8192_rx_query_status_desc, + .rx_command_packet_handler = NULL, + .stop_adapter = rtl8192_halt_adapter, + .update_ratr_table = rtl8192_update_ratr_table, + .irq_enable = rtl8192_EnableInterrupt, + .irq_disable = rtl8192_DisableInterrupt, + .irq_clear = rtl8192_ClearInterrupt, + .rx_enable = rtl8192_enable_rx, + .tx_enable = rtl8192_enable_tx, + .interrupt_recognized = rtl8192_interrupt_recognized, + .TxCheckStuckHandler = rtl8192_HalTxCheckStuck, + .RxCheckStuckHandler = rtl8192_HalRxCheckStuck, +}; +#endif + +static struct pci_device_id rtl8192_pci_id_tbl[] __devinitdata = { +#ifdef RTL8190P + /* Realtek */ + /* Dlink */ + {RTL_PCI_DEVICE(0x10ec, 0x8190, rtl819xp_ops)}, + /* Corega */ + {RTL_PCI_DEVICE(0x07aa, 0x0045, rtl819xp_ops)}, + {RTL_PCI_DEVICE(0x07aa, 0x0046, rtl819xp_ops)}, +#elif defined(RTL8192E) + {RTL_PCI_DEVICE(0x10ec, 0x8192, rtl819xp_ops)}, + {RTL_PCI_DEVICE(0x07aa, 0x0044, rtl819xp_ops)}, + {RTL_PCI_DEVICE(0x07aa, 0x0047, rtl819xp_ops)}, +#elif defined(RTL8192SE) /*8192SE*/ + /* take care of auto load fail case */ + {RTL_PCI_DEVICE(0x10ec, 0x8192, rtl8192se_ops)}, + {RTL_PCI_DEVICE(0x10ec, 0x8171, rtl8192se_ops)}, + {RTL_PCI_DEVICE(0x10ec, 0x8172, rtl8192se_ops)}, + {RTL_PCI_DEVICE(0x10ec, 0x8173, rtl8192se_ops)}, + {RTL_PCI_DEVICE(0x10ec, 0x8174, rtl8192se_ops)}, +#elif defined(RTL8192CE) /*8192CE*/ + {RTL_PCI_DEVICE(0x10ec, 0x8191, rtl8192ce_ops)}, + {RTL_PCI_DEVICE(0x10ec, 0x8178, rtl8192ce_ops)}, + {RTL_PCI_DEVICE(0x10ec, 0x8177, rtl8192ce_ops)}, + {RTL_PCI_DEVICE(0x10ec, 0x8176, rtl8192ce_ops)}, + {RTL_PCI_DEVICE(0x10ec, 0x092D, rtl8192ce_ops)}, +#endif + {} +}; +MODULE_DEVICE_TABLE(pci, rtl8192_pci_id_tbl); + +static int __devinit rtl8192_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id); +static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev); + +static struct pci_driver rtl8192_pci_driver = { + .name = DRV_NAME, /* Driver name */ + .id_table = rtl8192_pci_id_tbl, /* PCI_ID table */ + .probe = rtl8192_pci_probe, /* probe fn */ + .remove = __devexit_p(rtl8192_pci_disconnect), /* remove fn */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0) +#ifdef CONFIG_PM_RTL + .suspend = rtl8192E_suspend, /* PM suspend fn */ + .resume = rtl8192E_resume, /* PM resume fn */ +#else + .suspend = NULL, /* PM suspend fn */ + .resume = NULL, /* PM resume fn */ +#endif +#endif +}; + +/**************************************************************************** + -----------------------------IO STUFF------------------------- +*****************************************************************************/ +bool +PlatformIOCheckPageLegalAndGetRegMask( + u32 u4bPage, + u8* pu1bPageMask +) +{ + bool bReturn = false; + *pu1bPageMask = 0xfe; + + switch(u4bPage) + { + case 1: case 2: case 3: case 4: + case 8: case 9: case 10: case 12: case 13: + bReturn = true; + *pu1bPageMask = 0xf0; + break; + + default: + bReturn = false; + break; + } + + return bReturn; +} + +void write_nic_io_byte(struct net_device *dev, int x,u8 y) +{ + u32 u4bPage = (x >> 8); + u8 u1PageMask = 0; + bool bIsLegalPage = false; + + if(u4bPage == 0) + { + outb(y&0xff,dev->base_addr +x); + }else + { + bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask); + if(bIsLegalPage) + { + u8 u1bPsr = read_nic_io_byte(dev, PSR); + + write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); + write_nic_io_byte(dev, (x & 0xff), y); + write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); + + }else + { + ; + } + } + + +} + +void write_nic_io_word(struct net_device *dev, int x,u16 y) +{ + u32 u4bPage = (x >> 8); + u8 u1PageMask = 0; + bool bIsLegalPage = false; + + if(u4bPage == 0) + { + outw(y,dev->base_addr +x); + }else + { + bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask); + if(bIsLegalPage) + { + u8 u1bPsr = read_nic_io_byte(dev, PSR); + + write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); + write_nic_io_word(dev, (x & 0xff), y); + write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); + + }else + { + ; + } + } + +} + +void write_nic_io_dword(struct net_device *dev, int x,u32 y) +{ + u32 u4bPage = (x >> 8); + u8 u1PageMask = 0; + bool bIsLegalPage = false; + + if(u4bPage == 0) + { + outl(y,dev->base_addr +x); + }else + { + bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask); + if(bIsLegalPage) + { + u8 u1bPsr = read_nic_io_byte(dev, PSR); + + write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); + write_nic_io_dword(dev, (x & 0xff), y); + write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); + + }else + { + ; + } + } + +} +u8 read_nic_io_byte(struct net_device *dev, int x) +{ + u32 u4bPage = (x >> 8); + u8 u1PageMask = 0; + bool bIsLegalPage = false; + u8 Data = 0; + + if(u4bPage == 0) + { + return 0xff&inb(dev->base_addr +x); + }else + { + bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask); + if(bIsLegalPage) + { + u8 u1bPsr = read_nic_io_byte(dev, PSR); + + write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); + Data = read_nic_io_byte(dev, (x & 0xff)); + write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); + + }else + { + ; + } + } + + return Data; +} + +u16 read_nic_io_word(struct net_device *dev, int x) +{ + u32 u4bPage = (x >> 8); + u8 u1PageMask = 0; + bool bIsLegalPage = false; + u16 Data = 0; + + if(u4bPage == 0) + { + return inw(dev->base_addr +x); + }else + { + bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask); + if(bIsLegalPage) + { + u8 u1bPsr = read_nic_io_byte(dev, PSR); + + write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); + Data = read_nic_io_word(dev, (x & 0xff)); + write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); + + }else + { + ; + } + } + + return Data; +} + +u32 read_nic_io_dword(struct net_device *dev, int x) +{ + u32 u4bPage = (x >> 8); + u8 u1PageMask = 0; + bool bIsLegalPage = false; + u32 Data = 0; + + if(u4bPage == 0) + { + return inl(dev->base_addr +x); + }else + { + bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage, &u1PageMask); + if(bIsLegalPage) + { + u8 u1bPsr = read_nic_io_byte(dev, PSR); + + write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) | (u8)u4bPage)); + Data = read_nic_io_dword(dev, (x & 0xff)); + write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask)); + + }else + { + ; + } + } + + return Data; +} + +u8 read_nic_byte(struct net_device *dev, int x) +{ +#ifdef CONFIG_RTL8192_IO_MAP + return read_nic_io_byte(dev, x); +#else + return 0xff&readb((u8*)dev->mem_start +x); +#endif +} + +u32 read_nic_dword(struct net_device *dev, int x) +{ +#ifdef CONFIG_RTL8192_IO_MAP + return read_nic_io_dword(dev, x); +#else + return readl((u8*)dev->mem_start +x); +#endif +} + +u16 read_nic_word(struct net_device *dev, int x) +{ +#ifdef CONFIG_RTL8192_IO_MAP + return read_nic_io_word(dev, x); +#else + return readw((u8*)dev->mem_start +x); +#endif +} + +void write_nic_byte(struct net_device *dev, int x,u8 y) +{ +#ifdef CONFIG_RTL8192_IO_MAP + write_nic_io_byte(dev, x, y); +#else + writeb(y,(u8*)dev->mem_start +x); + +#if !(defined RTL8192SE || defined RTL8192CE) + udelay(20); +#endif + +#if defined RTL8192CE + read_nic_byte(dev, x); +#endif + +#endif +} + +void write_nic_dword(struct net_device *dev, int x,u32 y) +{ +#ifdef CONFIG_RTL8192_IO_MAP + write_nic_io_dword(dev, x, y); +#else + writel(y,(u8*)dev->mem_start +x); + +#if !(defined RTL8192SE || defined RTL8192CE) + udelay(20); +#endif + +#if defined RTL8192CE + read_nic_dword(dev, x); +#endif + +#endif +} + +void write_nic_word(struct net_device *dev, int x,u16 y) +{ +#ifdef CONFIG_RTL8192_IO_MAP + write_nic_io_word(dev, x, y); +#else + writew(y,(u8*)dev->mem_start +x); + +#if !(defined RTL8192SE || defined RTL8192CE) + udelay(20); +#endif + +#if defined RTL8192CE + read_nic_word(dev, x); +#endif + +#endif +} + +/**************************************************************************** + -----------------------------GENERAL FUNCTION------------------------- +*****************************************************************************/ +bool +MgntActSet_RF_State( + struct net_device* dev, + RT_RF_POWER_STATE StateToSet, + RT_RF_CHANGE_SOURCE ChangeSource, + bool ProtectOrNot + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device * ieee = priv->rtllib; + bool bActionAllowed = false; + bool bConnectBySSID = false; + RT_RF_POWER_STATE rtState; + u16 RFWaitCounter = 0; + unsigned long flag; + RT_TRACE((COMP_PS | COMP_RF), "===>MgntActSet_RF_State(): StateToSet(%d)\n",StateToSet); + + + + if(!ProtectOrNot) + { + while(true) + { + spin_lock_irqsave(&priv->rf_ps_lock,flag); + if(priv->RFChangeInProgress) + { + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + RT_TRACE((COMP_PS | COMP_RF), "MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n", StateToSet); + printk("MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n", StateToSet); + #if 1 + while(priv->RFChangeInProgress) + { + RFWaitCounter ++; + RT_TRACE((COMP_PS | COMP_RF), "MgntActSet_RF_State(): Wait 1 ms (%d times)...\n", RFWaitCounter); + mdelay(1); + + if(RFWaitCounter > 100) + { + RT_TRACE(COMP_ERR, "MgntActSet_RF_State(): Wait too logn to set RF\n"); + return false; + } + } + #endif + } + else + { + priv->RFChangeInProgress = true; + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + break; + } + } + } + +#if 0 + if(!priv->up) + { + + if(!ProtectOrNot) + { + spin_lock_irqsave(&priv->rf_ps_lock,flag); + priv->RFChangeInProgress = false; + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + } + return false; + } +#endif + + rtState = priv->rtllib->eRFPowerState; + + switch(StateToSet) + { + case eRfOn: + + priv->rtllib->RfOffReason &= (~ChangeSource); + + if((ChangeSource == RF_CHANGE_BY_HW) && (priv->bHwRadioOff == true)){ + priv->bHwRadioOff = false; + } + + if(! priv->rtllib->RfOffReason) + { + priv->rtllib->RfOffReason = 0; + bActionAllowed = true; + + + if(rtState == eRfOff && ChangeSource >=RF_CHANGE_BY_HW ) + { + bConnectBySSID = true; + } + } + else{ + RT_TRACE((COMP_PS | COMP_RF), "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n", priv->rtllib->RfOffReason, ChangeSource); + } + + break; + + case eRfOff: + + if((priv->rtllib->iw_mode == IW_MODE_INFRA) || (priv->rtllib->iw_mode == IW_MODE_ADHOC)) + { + if ((priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) || (ChangeSource > RF_CHANGE_BY_IPS)) + { + if(ieee->state == RTLLIB_LINKED) + priv->blinked_ingpio = true; + else + priv->blinked_ingpio = false; + rtllib_MgntDisconnect(priv->rtllib,disas_lv_ss); + + + + } + } + if((ChangeSource == RF_CHANGE_BY_HW) && (priv->bHwRadioOff == false)){ + priv->bHwRadioOff = true; + } + priv->rtllib->RfOffReason |= ChangeSource; + bActionAllowed = true; + break; + + case eRfSleep: + priv->rtllib->RfOffReason |= ChangeSource; + bActionAllowed = true; + break; + + default: + break; + } + + if(bActionAllowed) + { + RT_TRACE((COMP_PS | COMP_RF), "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, priv->rtllib->RfOffReason); + PHY_SetRFPowerState(dev, StateToSet); + if(StateToSet == eRfOn) + { + + if(bConnectBySSID && (priv->blinked_ingpio == true)) + { + queue_delayed_work_rsl(ieee->wq, &ieee->associate_procedure_wq, 0); + priv->blinked_ingpio = false; + + } +#ifdef _RTL8192_EXT_PATCH_ + if(priv->rtllib->iw_mode == IW_MODE_MESH){ + queue_work_rsl(ieee->wq, &ieee->ext_start_mesh_protocol_wq); + + } +#endif + } + else if(StateToSet == eRfOff) + { + } + } + else + { + RT_TRACE((COMP_PS | COMP_RF), "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", StateToSet, ChangeSource, priv->rtllib->RfOffReason); + } + + if(!ProtectOrNot) + { + spin_lock_irqsave(&priv->rf_ps_lock,flag); + priv->RFChangeInProgress = false; + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + } + + RT_TRACE((COMP_PS && COMP_RF), "<===MgntActSet_RF_State()\n"); + return bActionAllowed; +} + + +short rtl8192_get_nic_desc_num(struct net_device *dev, int prio) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtl8192_tx_ring *ring = &priv->tx_ring[prio]; + + /* For now, we reserved two free descriptor as a safety boundary + * between the tail and the head + */ + if((prio == MGNT_QUEUE) &&(skb_queue_len(&ring->queue)>10)) + printk("-----[%d]---------ring->idx=%d queue_len=%d---------\n", + prio,ring->idx, skb_queue_len(&ring->queue)); + return skb_queue_len(&ring->queue); +} + +short rtl8192_check_nic_enough_desc(struct net_device *dev, int prio) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtl8192_tx_ring *ring = &priv->tx_ring[prio]; + + if (ring->entries - skb_queue_len(&ring->queue) >= 2) { + return 1; + } else { + return 0; + } +} + +void rtl8192_tx_timeout(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) + schedule_work(&priv->reset_wq); +#else + schedule_task(&priv->reset_wq); +#endif + printk("TXTIMEOUT"); +} + +void rtl8192_irq_enable(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + priv->irq_enabled = 1; + + priv->ops->irq_enable(dev); +} + +void rtl8192_irq_disable(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + priv->ops->irq_disable(dev); + + priv->irq_enabled = 0; +} + +void rtl8192_irq_clear(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + priv->ops->irq_clear(dev); +} + + +void rtl8192_set_chan(struct net_device *dev,short ch) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + RT_TRACE(COMP_CH, "=====>%s()====ch:%d\n", __FUNCTION__, ch); + printk("=====>%s()====ch:%d\n", __FUNCTION__, ch); + if (priv->chan_forced) + return; + + priv->chan = ch; + + +#ifndef LOOP_TEST + + + if (priv->rf_set_chan) + priv->rf_set_chan(dev,priv->chan); + +#ifdef CONFIG_FW_SETCHAN + priv->rtllib->SetFwCmdHandler(dev, FW_CMD_CHAN_SET); +#endif + +#endif +} + +void rtl8192_update_cap(struct net_device* dev, u16 cap) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_network *net = &priv->rtllib->current_network; + + + { + bool ShortPreamble; + + if(cap & WLAN_CAPABILITY_SHORT_PREAMBLE) + { + if(priv->dot11CurrentPreambleMode != PREAMBLE_SHORT) + { + ShortPreamble = true; + priv->dot11CurrentPreambleMode = PREAMBLE_SHORT; + printk("%s(): WLAN_CAPABILITY_SHORT_PREAMBLE\n", __func__); + priv->rtllib->SetHwRegHandler( dev, HW_VAR_ACK_PREAMBLE, (unsigned char *)&ShortPreamble ); + } + } + else + { + if(priv->dot11CurrentPreambleMode != PREAMBLE_LONG) + { + ShortPreamble = false; + priv->dot11CurrentPreambleMode = PREAMBLE_LONG; + printk("%s(): WLAN_CAPABILITY_LONG_PREAMBLE\n", __func__); + priv->rtllib->SetHwRegHandler( dev, HW_VAR_ACK_PREAMBLE, (unsigned char *)&ShortPreamble ); + } + } + } + +#ifdef RTL8192CE + if( net->mode & IEEE_G) +#elif defined RTL8192SE || defined RTL8192E || defined RTL8190P + if (net->mode & (IEEE_G|IEEE_N_24G)) +#endif + { + u8 slot_time_val; + u8 CurSlotTime = priv->slot_time; + +#ifdef RTL8192CE + if( (cap & WLAN_CAPABILITY_SHORT_SLOT_TIME) && (!(priv->rtllib->pHTInfo->RT2RT_HT_Mode & RT_HT_CAP_USE_LONG_PREAMBLE))) +#elif defined RTL8192SE || defined RTL8192E || defined RTL8190P + if ((cap & WLAN_CAPABILITY_SHORT_SLOT_TIME) && (!priv->rtllib->pHTInfo->bCurrentRT2RTLongSlotTime)) +#endif + { + if(CurSlotTime != SHORT_SLOT_TIME) + { + slot_time_val = SHORT_SLOT_TIME; + priv->rtllib->SetHwRegHandler( dev, HW_VAR_SLOT_TIME, &slot_time_val ); + } + } + else + { + if(CurSlotTime != NON_SHORT_SLOT_TIME) + { + slot_time_val = NON_SHORT_SLOT_TIME; + priv->rtllib->SetHwRegHandler( dev, HW_VAR_SLOT_TIME, &slot_time_val ); + } + } + } +} + +static struct rtllib_qos_parameters def_qos_parameters = { + {3,3,3,3}, + {7,7,7,7}, + {2,2,2,2}, + {0,0,0,0}, + {0,0,0,0} +}; + +void rtl8192_update_beacon(void *data) +{ +#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) + struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv, update_beacon_wq.work); + struct net_device *dev = priv->rtllib->dev; +#else + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = rtllib_priv(dev); +#endif + struct rtllib_device* ieee = priv->rtllib; + struct rtllib_network* net = &ieee->current_network; + + if (ieee->pHTInfo->bCurrentHTSupport) + HTUpdateSelfAndPeerSetting(ieee, net); + ieee->pHTInfo->bCurrentRT2RTLongSlotTime = net->bssht.bdRT2RTLongSlotTime; + ieee->pHTInfo->RT2RT_HT_Mode = net->bssht.RT2RT_HT_Mode; + rtl8192_update_cap(dev, net->capability); +} + +#define MOVE_INTO_HANDLER +#ifdef RTL8192CE +int WDCAPARA_ADD[] = {REG_EDCA_BE_PARAM,REG_EDCA_BK_PARAM,REG_EDCA_VI_PARAM,REG_EDCA_VO_PARAM}; +#else +int WDCAPARA_ADD[] = {EDCAPARA_BE,EDCAPARA_BK,EDCAPARA_VI,EDCAPARA_VO}; +#endif +void rtl8192_qos_activate(void *data) +{ +#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) + struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv, qos_activate); + struct net_device *dev = priv->rtllib->dev; +#else + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = rtllib_priv(dev); +#endif +#ifndef MOVE_INTO_HANDLER + struct rtllib_qos_parameters *qos_parameters = &priv->rtllib->current_network.qos_data.parameters; + u8 mode = priv->rtllib->current_network.mode; + u8 u1bAIFS; + u32 u4bAcParam; +#endif + int i; + + if (priv == NULL) + return; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) + down(&priv->mutex); +#else + mutex_lock(&priv->mutex); +#endif + if(priv->rtllib->state != RTLLIB_LINKED) + goto success; + RT_TRACE(COMP_QOS,"qos active process with associate response received\n"); + + for (i = 0; i < QOS_QUEUE_NUM; i++) { +#ifndef MOVE_INTO_HANDLER + u1bAIFS = qos_parameters->aifs[i] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime; + u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[i]))<< AC_PARAM_TXOP_LIMIT_OFFSET)| + (((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)| + (((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)| + ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET)); + printk("===>ACI:%d:u4bAcParam:%x\n", i, u4bAcParam); + write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam); +#else + priv->rtllib->SetHwRegHandler(dev, HW_VAR_AC_PARAM, (u8*)(&i)); +#endif + } + +success: +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) + up(&priv->mutex); +#else + mutex_unlock(&priv->mutex); +#endif +} + +static int rtl8192_qos_handle_probe_response(struct r8192_priv *priv, + int active_network, + struct rtllib_network *network) +{ + int ret = 0; + u32 size = sizeof(struct rtllib_qos_parameters); + + if(priv->rtllib->state !=RTLLIB_LINKED) + return ret; + +#ifdef _RTL8192_EXT_PATCH_ + if (!((priv->rtllib->iw_mode == IW_MODE_INFRA ) || + ((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->only_mesh == 0)))) +#else + if ((priv->rtllib->iw_mode != IW_MODE_INFRA)) +#endif + return ret; + + if (network->flags & NETWORK_HAS_QOS_MASK) { + if (active_network && + (network->flags & NETWORK_HAS_QOS_PARAMETERS)) + network->qos_data.active = network->qos_data.supported; + + if ((network->qos_data.active == 1) && (active_network == 1) && + (network->flags & NETWORK_HAS_QOS_PARAMETERS) && + (network->qos_data.old_param_count != + network->qos_data.param_count)) { + network->qos_data.old_param_count = + network->qos_data.param_count; + priv->rtllib->wmm_acm = network->qos_data.wmm_acm; + queue_work_rsl(priv->priv_wq, &priv->qos_activate); + RT_TRACE (COMP_QOS, "QoS parameters change call " + "qos_activate\n"); + } + } else { + memcpy(&priv->rtllib->current_network.qos_data.parameters,\ + &def_qos_parameters, size); + + if ((network->qos_data.active == 1) && (active_network == 1)) { + queue_work_rsl(priv->priv_wq, &priv->qos_activate); + RT_TRACE(COMP_QOS, "QoS was disabled call qos_activate \n"); + } + network->qos_data.active = 0; + network->qos_data.supported = 0; + } + + return 0; +} + +static int rtl8192_handle_beacon(struct net_device * dev, + struct rtllib_beacon * beacon, + struct rtllib_network * network) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + rtl8192_qos_handle_probe_response(priv,1,network); + + queue_delayed_work_rsl(priv->priv_wq, &priv->update_beacon_wq, 0); + return 0; + +} + +static int rtl8192_qos_association_resp(struct r8192_priv *priv, + struct rtllib_network *network) +{ + int ret = 0; + unsigned long flags; + u32 size = sizeof(struct rtllib_qos_parameters); + int set_qos_param = 0; + + if ((priv == NULL) || (network == NULL)) + return ret; + + if(priv->rtllib->state !=RTLLIB_LINKED) + return ret; + +#ifdef _RTL8192_EXT_PATCH_ + if (!((priv->rtllib->iw_mode == IW_MODE_INFRA ) || + ((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->only_mesh == 0)))) +#else + if ((priv->rtllib->iw_mode != IW_MODE_INFRA)) +#endif + return ret; + + spin_lock_irqsave(&priv->rtllib->lock, flags); + if (network->flags & NETWORK_HAS_QOS_PARAMETERS) { + memcpy(&priv->rtllib->current_network.qos_data.parameters,\ + &network->qos_data.parameters,\ + sizeof(struct rtllib_qos_parameters)); + priv->rtllib->current_network.qos_data.active = 1; + priv->rtllib->wmm_acm = network->qos_data.wmm_acm; +#if 0 + if((priv->rtllib->current_network.qos_data.param_count != \ + network->qos_data.param_count)) +#endif + { + set_qos_param = 1; + priv->rtllib->current_network.qos_data.old_param_count = \ + priv->rtllib->current_network.qos_data.param_count; + priv->rtllib->current_network.qos_data.param_count = \ + network->qos_data.param_count; + } + } else { + memcpy(&priv->rtllib->current_network.qos_data.parameters,\ + &def_qos_parameters, size); + priv->rtllib->current_network.qos_data.active = 0; + priv->rtllib->current_network.qos_data.supported = 0; + set_qos_param = 1; + } + + spin_unlock_irqrestore(&priv->rtllib->lock, flags); + + RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n", __FUNCTION__, + network->flags ,priv->rtllib->current_network.qos_data.active); + if (set_qos_param == 1) { + dm_init_edca_turbo(priv->rtllib->dev); + queue_work_rsl(priv->priv_wq, &priv->qos_activate); + } + return ret; +} + +static int rtl8192_handle_assoc_response(struct net_device *dev, + struct rtllib_assoc_response_frame *resp, + struct rtllib_network *network) +{ + struct r8192_priv *priv = rtllib_priv(dev); + rtl8192_qos_association_resp(priv, network); + return 0; +} + +#if 0 +void rtl8192_prepare_beacon(struct r8192_priv *priv) +{ +#ifdef _RTL8192_EXT_PATCH_ + struct net_device *dev = priv->rtllib->dev; +#endif + struct sk_buff *skb; + cb_desc *tcb_desc; + +#ifdef _RTL8192_EXT_PATCH_ + if((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->mesh_state == RTLLIB_NOLINK)) + return; +#endif + skb = rtllib_get_beacon(priv->rtllib); + tcb_desc = (cb_desc *)(skb->cb + 8); +#ifdef _RTL8192_EXT_PATCH_ + memset(skb->cb, 0, sizeof(skb->cb)); +#endif + tcb_desc->queue_index = BEACON_QUEUE; + tcb_desc->data_rate = 2; + tcb_desc->RATRIndex = 7; + tcb_desc->bTxDisableRateFallBack = 1; + tcb_desc->bTxUseDriverAssingedRate = 1; +#ifdef _RTL8192_EXT_PATCH_ + tcb_desc->bTxEnableFwCalcDur = 0; + memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); +#endif + skb_push(skb, priv->rtllib->tx_headroom); + if(skb){ + rtl8192_tx(priv->rtllib->dev,skb); + } +} +#else +void rtl8192_prepare_beacon(struct r8192_priv *priv) +{ + struct net_device *dev = priv->rtllib->dev; + struct sk_buff *pskb = NULL, *pnewskb = NULL; + cb_desc *tcb_desc = NULL; + struct rtl8192_tx_ring *ring = NULL; + tx_desc *pdesc = NULL; + +#ifdef _RTL8192_EXT_PATCH_ + if((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->mesh_state == RTLLIB_NOLINK)) + return; +#endif + ring = &priv->tx_ring[BEACON_QUEUE]; + pskb = __skb_dequeue(&ring->queue); + if(pskb) + kfree_skb(pskb); + + pnewskb = rtllib_get_beacon(priv->rtllib); + if(!pnewskb) + return; + +#ifdef _RTL8192_EXT_PATCH_ + memset(pnewskb->cb, 0, sizeof(pnewskb->cb)); +#endif + tcb_desc = (cb_desc *)(pnewskb->cb + 8); + tcb_desc->queue_index = BEACON_QUEUE; + tcb_desc->data_rate = 2; + tcb_desc->RATRIndex = 7; + tcb_desc->bTxDisableRateFallBack = 1; + tcb_desc->bTxUseDriverAssingedRate = 1; +#ifdef _RTL8192_EXT_PATCH_ + tcb_desc->bTxEnableFwCalcDur = 0; + memcpy((unsigned char *)(pnewskb->cb),&dev,sizeof(dev)); +#endif + skb_push(pnewskb, priv->rtllib->tx_headroom); + + pdesc = &ring->desc[0]; + priv->ops->tx_fill_descriptor(dev, pdesc, tcb_desc, pnewskb); + __skb_queue_tail(&ring->queue, pnewskb); + pdesc->OWN = 1; + + return; +} +#endif +void rtl8192_stop_beacon(struct net_device *dev) +{ +} + +void rtl8192_config_rate(struct net_device* dev, u16* rate_config) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_network *net; + u8 i=0, basic_rate = 0; +#ifdef _RTL8192_EXT_PATCH_ + if(priv->rtllib->iw_mode == IW_MODE_MESH) + net = & priv->rtllib->current_mesh_network; + else + net = & priv->rtllib->current_network; +#else + net = & priv->rtllib->current_network; +#endif + + for (i = 0; i < net->rates_len; i++) { + basic_rate = net->rates[i] & 0x7f; + switch (basic_rate) { + case MGN_1M: + *rate_config |= RRSR_1M; + break; + case MGN_2M: + *rate_config |= RRSR_2M; + break; + case MGN_5_5M: + *rate_config |= RRSR_5_5M; + break; + case MGN_11M: + *rate_config |= RRSR_11M; + break; + case MGN_6M: + *rate_config |= RRSR_6M; + break; + case MGN_9M: + *rate_config |= RRSR_9M; + break; + case MGN_12M: + *rate_config |= RRSR_12M; + break; + case MGN_18M: + *rate_config |= RRSR_18M; + break; + case MGN_24M: + *rate_config |= RRSR_24M; + break; + case MGN_36M: + *rate_config |= RRSR_36M; + break; + case MGN_48M: + *rate_config |= RRSR_48M; + break; + case MGN_54M: + *rate_config |= RRSR_54M; + break; + } + } + + for (i = 0; i < net->rates_ex_len; i++) { + basic_rate = net->rates_ex[i] & 0x7f; + switch (basic_rate) { + case MGN_1M: + *rate_config |= RRSR_1M; + break; + case MGN_2M: + *rate_config |= RRSR_2M; + break; + case MGN_5_5M: + *rate_config |= RRSR_5_5M; + break; + case MGN_11M: + *rate_config |= RRSR_11M; + break; + case MGN_6M: + *rate_config |= RRSR_6M; + break; + case MGN_9M: + *rate_config |= RRSR_9M; + break; + case MGN_12M: + *rate_config |= RRSR_12M; + break; + case MGN_18M: + *rate_config |= RRSR_18M; + break; + case MGN_24M: + *rate_config |= RRSR_24M; + break; + case MGN_36M: + *rate_config |= RRSR_36M; + break; + case MGN_48M: + *rate_config |= RRSR_48M; + break; + case MGN_54M: + *rate_config |= RRSR_54M; + break; + } + } +} + +void rtl8192_refresh_supportrate(struct r8192_priv* priv) +{ + struct rtllib_device* ieee = priv->rtllib; + if (ieee->mode == WIRELESS_MODE_N_24G || ieee->mode == WIRELESS_MODE_N_5G) { + memcpy(ieee->Regdot11HTOperationalRateSet, ieee->RegHTSuppRateSet, 16); + memcpy(ieee->Regdot11TxHTOperationalRateSet, ieee->RegHTSuppRateSet, 16); + +#ifdef RTL8192CE + if(priv->rf_type == RF_1T1R) { + ieee->Regdot11HTOperationalRateSet[1] = 0; + } +#endif + +#ifdef RTL8192SE + if(priv->rf_type == RF_1T1R) { + ieee->Regdot11HTOperationalRateSet[1] = 0; + } + if(priv->rf_type == RF_1T1R || priv->rf_type == RF_1T2R) + { + ieee->Regdot11TxHTOperationalRateSet[1] = 0; + } + + if(priv->rtllib->b1SSSupport == true) { + ieee->Regdot11HTOperationalRateSet[1] = 0; + } +#endif + } else { + memset(ieee->Regdot11HTOperationalRateSet, 0, 16); + } + return; +} + +u8 rtl8192_getSupportedWireleeMode(struct net_device*dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 ret = 0; + + switch(priv->rf_chip) { + case RF_8225: + case RF_8256: + case RF_6052: + case RF_PSEUDO_11N: + ret = (WIRELESS_MODE_N_24G|WIRELESS_MODE_G | WIRELESS_MODE_B); + break; + case RF_8258: + ret = (WIRELESS_MODE_A | WIRELESS_MODE_N_5G); + break; + default: + ret = WIRELESS_MODE_B; + break; + } + return ret; +} + +void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev); + +#if 0 + if( (wireless_mode != WIRELESS_MODE_B) && + (wireless_mode != WIRELESS_MODE_G) && + (wireless_mode != WIRELESS_MODE_A) && + (wireless_mode != WIRELESS_MODE_AUTO) && + (wireless_mode != WIRELESS_MODE_N_24G) && + (wireless_mode != WIRELESS_MODE_N_5G) ) + { + wireless_mode = WIRELESS_MODE_AUTO; + } +#endif + if ((wireless_mode == WIRELESS_MODE_AUTO) || ((wireless_mode & bSupportMode) == 0)) { + if (bSupportMode & WIRELESS_MODE_N_24G) { + wireless_mode = WIRELESS_MODE_N_24G; + } else if (bSupportMode & WIRELESS_MODE_N_5G) { + wireless_mode = WIRELESS_MODE_N_5G; + } else if((bSupportMode & WIRELESS_MODE_A)) { + wireless_mode = WIRELESS_MODE_A; + } else if((bSupportMode & WIRELESS_MODE_G)) { + wireless_mode = WIRELESS_MODE_G; + } else if((bSupportMode & WIRELESS_MODE_B)) { + wireless_mode = WIRELESS_MODE_B; + } else { + RT_TRACE(COMP_ERR, "%s(), No valid wireless mode supported (%x)!!!\n", + __FUNCTION__, bSupportMode); + wireless_mode = WIRELESS_MODE_B; + } + } + +#ifdef _RTL8192_EXT_PATCH_ + if ((wireless_mode & WIRELESS_MODE_N_24G) == WIRELESS_MODE_N_24G) + wireless_mode = WIRELESS_MODE_N_24G; + else if((wireless_mode & WIRELESS_MODE_N_5G) == WIRELESS_MODE_N_5G) + wireless_mode = WIRELESS_MODE_N_5G; + else if ((wireless_mode & WIRELESS_MODE_A) == WIRELESS_MODE_A) + wireless_mode = WIRELESS_MODE_A; + else if ((wireless_mode & WIRELESS_MODE_G) == WIRELESS_MODE_G) + wireless_mode = WIRELESS_MODE_G; + else + wireless_mode = WIRELESS_MODE_B; +#else + if ((wireless_mode & (WIRELESS_MODE_B | WIRELESS_MODE_G)) == (WIRELESS_MODE_G | WIRELESS_MODE_B)) + wireless_mode = WIRELESS_MODE_G; +#endif + + priv->rtllib->mode = wireless_mode; + + ActUpdateChannelAccessSetting( dev, wireless_mode, &priv->ChannelAccessSetting); + + if ((wireless_mode == WIRELESS_MODE_N_24G) || (wireless_mode == WIRELESS_MODE_N_5G)){ + priv->rtllib->pHTInfo->bEnableHT = 1; + printk("%s(), wireless_mode:%x, bEnableHT = 1\n", __FUNCTION__,wireless_mode); + }else{ + priv->rtllib->pHTInfo->bEnableHT = 0; + printk("%s(), wireless_mode:%x, bEnableHT = 0\n", __FUNCTION__,wireless_mode); + } + + RT_TRACE(COMP_INIT, "Current Wireless Mode is %x\n", wireless_mode); + rtl8192_refresh_supportrate(priv); +} + + +#ifdef _RTL8192_EXT_PATCH_ +#define KEEP_ALIVE_INTERVAL 20 +#define DEFAULT_KEEP_ALIVE_LEVEL 1 + +static void MgntLinkKeepAlive(struct r8192_priv *priv ) +{ + if (priv->keepAliveLevel == 0) + return; + + if((priv->rtllib->state == RTLLIB_LINKED) && (!priv->rtllib->is_roaming)) + { + + if ( (priv->keepAliveLevel== 2) || + (priv->rtllib->LinkDetectInfo.LastNumTxUnicast == priv->rtllib->LinkDetectInfo.NumTxUnicastOkInPeriod && + priv->rtllib->LinkDetectInfo.NumRxUnicastOkInPeriod == 0) + ) + { + priv->rtllib->LinkDetectInfo.IdleCount++; + + if(priv->rtllib->LinkDetectInfo.IdleCount >= ((KEEP_ALIVE_INTERVAL / RT_CHECK_FOR_HANG_PERIOD)-1) ) + { + priv->rtllib->LinkDetectInfo.IdleCount = 0; + rtllib_sta_ps_send_null_frame(priv->rtllib, false); + } + } + else + { + priv->rtllib->LinkDetectInfo.IdleCount = 0; + } + priv->rtllib->LinkDetectInfo.LastNumTxUnicast = priv->rtllib->LinkDetectInfo.NumTxUnicastOkInPeriod; + priv->rtllib->LinkDetectInfo.LastNumRxUnicast = priv->rtllib->LinkDetectInfo.NumRxUnicastOkInPeriod; + } +} + +static void rtl8192_init_mesh_variable(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 i; + + priv->rtllib->mesh_security_setting = 0; + memset(priv->rtllib->swmeshcamtable,0,sizeof(SW_CAM_TABLE)*32); + priv->rtllib->mesh_sec_type = 0; + + priv->keepAliveLevel = DEFAULT_KEEP_ALIVE_LEVEL; + + priv->FwCmdIOMap = 0; + priv->FwCmdIOParam = 0; + priv->ThermalValue = 0; + priv->DMFlag = 0; + priv->rssi_level = 0; + priv->rtllib->bUseRAMask = 0; + + priv->rtllib->set_key_for_AP = rtl8192_set_key_for_AP; + memset(priv->rtllib->swmeshratrtable,0,8*(sizeof(SW_RATR_TABLE))); + priv->rtllib->mesh_amsdu_in_process = 0; + priv->rtllib->HwSecCamBitMap = 0; + memset(priv->rtllib->HwSecCamStaAddr,0,TOTAL_CAM_ENTRY * ETH_ALEN); + priv->rtllib->LinkingPeerBitMap = 0; + memset(priv->rtllib->LinkingPeerAddr,0,(MAX_MP-1) * ETH_ALEN); + memset(priv->rtllib->LinkingPeerSecState, 0, (MAX_MP-1)); + memset(priv->rtllib->peer_AID_Addr,0,30 * ETH_ALEN); + priv->rtllib->peer_AID_bitmap = 0; + priv->rtllib->backup_channel = 1; + priv->rtllib->del_hwsec_cam_entry = rtl8192_del_hwsec_cam_entry; + priv->rtllib->set_key_for_peer = meshdev_set_key_for_peer; + priv->rtllib->hostname_len = 0; + memset(priv->rtllib->hostname, 0, sizeof(priv->rtllib->hostname)); + strcpy(priv->rtllib->hostname, "Crab"); + priv->rtllib->hostname_len = strlen(priv->rtllib->hostname); + priv->rtllib->meshScanMode = 0; + priv->rtllib->currentRate = 0xffffffff; + priv->mshobj = alloc_mshobj(priv); + printk("priv is %p,mshobj is %p\n",priv,priv->mshobj); + + if (priv->mshobj) { + priv->rtllib->ext_patch_rtllib_start_protocol = + priv->mshobj->ext_patch_rtllib_start_protocol; + priv->rtllib->ext_patch_rtllib_stop_protocol = + priv->mshobj->ext_patch_rtllib_stop_protocol; + priv->rtllib->ext_patch_rtllib_start_mesh = + priv->mshobj->ext_patch_rtllib_start_mesh; + priv->rtllib->ext_patch_rtllib_probe_req_1 = + priv->mshobj->ext_patch_rtllib_probe_req_1; + priv->rtllib->ext_patch_rtllib_probe_req_2 = + priv->mshobj->ext_patch_rtllib_probe_req_2; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_auth = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_auth; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_deauth = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_deauth; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_open = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_peerlink_open; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_close = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_peerlink_close; + priv->rtllib->ext_patch_rtllib_close_all_peerlink = + priv->mshobj->ext_patch_rtllib_close_all_peerlink; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann = + priv->mshobj->ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann; + priv->rtllib->ext_patch_rtllib_ext_stop_scan_wq_set_channel = + priv->mshobj->ext_patch_rtllib_ext_stop_scan_wq_set_channel; + priv->rtllib->ext_patch_r819x_wx_set_mesh_chan = + priv->mshobj->ext_patch_r819x_wx_set_mesh_chan; + priv->rtllib->ext_patch_r819x_wx_set_channel = + priv->mshobj->ext_patch_r819x_wx_set_channel; + priv->rtllib->ext_patch_rtllib_process_probe_response_1 = + priv->mshobj->ext_patch_rtllib_process_probe_response_1; + priv->rtllib->ext_patch_rtllib_rx_mgt_on_probe_req = + priv->mshobj->ext_patch_rtllib_rx_mgt_on_probe_req; + priv->rtllib->ext_patch_rtllib_rx_mgt_update_expire = + priv->mshobj->ext_patch_rtllib_rx_mgt_update_expire; + priv->rtllib->ext_patch_get_beacon_get_probersp = + priv->mshobj->ext_patch_get_beacon_get_probersp; + priv->rtllib->ext_patch_rtllib_rx_on_rx = + priv->mshobj->ext_patch_rtllib_rx_on_rx; + priv->rtllib->ext_patch_rtllib_rx_frame_get_hdrlen = + priv->mshobj->ext_patch_rtllib_rx_frame_get_hdrlen; + priv->rtllib->ext_patch_rtllib_rx_frame_get_mac_hdrlen = + priv->mshobj->ext_patch_rtllib_rx_frame_get_mac_hdrlen; + priv->rtllib->ext_patch_rtllib_rx_frame_get_mesh_hdrlen_llc = + priv->mshobj->ext_patch_rtllib_rx_frame_get_mesh_hdrlen_llc; + priv->rtllib->ext_patch_rtllib_rx_is_valid_framectl = + priv->mshobj->ext_patch_rtllib_rx_is_valid_framectl; + priv->rtllib->ext_patch_rtllib_softmac_xmit_get_rate = + priv->mshobj->ext_patch_rtllib_softmac_xmit_get_rate; + /* added by david for setting acl dynamically */ + priv->rtllib->ext_patch_rtllib_acl_query = + priv->mshobj->ext_patch_rtllib_acl_query; + priv->rtllib->ext_patch_rtllib_is_mesh = + priv->mshobj->ext_patch_rtllib_is_mesh; + priv->rtllib->ext_patch_rtllib_create_crypt_for_peer = + priv->mshobj->ext_patch_rtllib_create_crypt_for_peer; + priv->rtllib->ext_patch_rtllib_get_peermp_htinfo = + priv->mshobj->ext_patch_rtllib_get_peermp_htinfo; + priv->rtllib->ext_patch_rtllib_send_ath_commit = + priv->mshobj->ext_patch_rtllib_send_ath_commit; + priv->rtllib->ext_patch_rtllib_send_ath_confirm = + priv->mshobj->ext_patch_rtllib_send_ath_confirm; + priv->rtllib->ext_patch_rtllib_rx_ath_commit = + priv->mshobj->ext_patch_rtllib_rx_ath_commit; + priv->rtllib->ext_patch_rtllib_rx_ath_confirm = + priv->mshobj->ext_patch_rtllib_rx_ath_confirm; + } + for (i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_head_init(&priv->rtllib->skb_meshaggQ[i]); + } +} + +int _rtl8192_mesh_up(struct net_device *dev,bool is_silent_reset) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + bool init_status = true; + priv->bDriverIsGoingToUnload = false; + priv->bdisable_nic = false; + + if(priv->mesh_up){ + RT_TRACE(COMP_ERR,"%s(): since mesh0 is already up, ra0 is forbidden to open.\n",__FUNCTION__); + return 0; + } + RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__); + if(!is_silent_reset) + priv->rtllib->iw_mode = IW_MODE_INFRA; + if(priv->up){ + RT_TRACE(COMP_ERR,"%s():%s is up,return\n",__FUNCTION__,DRV_NAME); + return -1; + } +#ifdef RTL8192SE + priv->ReceiveConfig = + RCR_APPFCS | RCR_APWRMGT | /*RCR_ADD3 |*/ + RCR_AMF | RCR_ADF | RCR_APP_MIC | RCR_APP_ICV | + RCR_AICV | RCR_ACRC32 | + RCR_AB | RCR_AM | + RCR_APM | + /*RCR_AAP |*/ + RCR_APP_PHYST_STAFF | RCR_APP_PHYST_RXFF | + (priv->EarlyRxThreshold<ReceiveConfig = (\ + RCR_APPFCS + | RCR_AMF | RCR_ADF| RCR_APP_MIC| RCR_APP_ICV + | RCR_AICV | RCR_ACRC32 + | RCR_AB | RCR_AM + | RCR_APM + | RCR_APP_PHYST_RXFF + | RCR_HTC_LOC_CTRL + ); +#endif + + if(!priv->mesh_up) + { + RT_TRACE(COMP_INIT, "Bringing up iface"); + priv->bfirst_init = true; + init_status = priv->ops->initialize_adapter(dev); + if(init_status != true) + { + RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__); + return -1; + } + RT_TRACE(COMP_INIT, "start adapter finished\n"); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); + priv->rtllib->ieee_up=1; + priv->bfirst_init = false; +#ifdef ENABLE_GPIO_RADIO_CTL + if(priv->polling_timer_on == 0){ + check_rfctrl_gpio_timer((unsigned long)dev); + } +#endif + priv->rtllib->current_network.channel = INIT_DEFAULT_CHAN; + priv->rtllib->current_mesh_network.channel = INIT_DEFAULT_CHAN; + if((priv->mshobj->ext_patch_r819x_wx_set_mesh_chan) && (!is_silent_reset)) + priv->mshobj->ext_patch_r819x_wx_set_mesh_chan(dev,INIT_DEFAULT_CHAN); + if((priv->mshobj->ext_patch_r819x_wx_set_channel) && (!is_silent_reset)) + { + priv->mshobj->ext_patch_r819x_wx_set_channel(priv->rtllib, INIT_DEFAULT_CHAN); + } + dm_InitRateAdaptiveMask(dev); + } + else + { + rtllib_stop_scan_syncro(priv->rtllib); + } + priv->up=1; + printk("%s():set chan %d\n",__FUNCTION__,INIT_DEFAULT_CHAN); + priv->rtllib->set_chan(dev, INIT_DEFAULT_CHAN); + priv->up_first_time = 0; + if(!priv->rtllib->proto_started) + { +#ifdef RTL8192E + if(priv->rtllib->eRFPowerState!=eRfOn) + MgntActSet_RF_State(dev, eRfOn, priv->rtllib->RfOffReason,true); +#endif + if(priv->rtllib->state != RTLLIB_LINKED) + rtllib_softmac_start_protocol(priv->rtllib, 0); + } + if(!priv->mesh_up) + watch_dog_timer_callback((unsigned long) dev); + rtllib_reset_queue(priv->rtllib); + if(!netif_queue_stopped(dev)) + netif_start_queue(dev); + else + netif_wake_queue(dev); + RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__); + + return 0; +} + +int rtl8192_mesh_down(struct net_device *dev, bool shutdownrf) +{ + struct r8192_priv *priv = rtllib_priv(dev); + unsigned long flags = 0; + u8 RFInProgressTimeOut = 0; + + if (priv->up == 0) + return -1; + + RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__); +#ifdef ENABLE_LPS + if(priv->rtllib->state == RTLLIB_LINKED) + LeisurePSLeave(dev); +#endif + priv->up=0; + + /* FIXME */ + if (!netif_queue_stopped(dev)) + netif_stop_queue(dev); + if(!priv->mesh_up) + { + priv->bDriverIsGoingToUnload = true; + priv->rtllib->ieee_up = 0; + /* mesh stack has also be closed, then disalbe the hardware function at + * the same time */ + priv->rtllib->wpa_ie_len = 0; + if(priv->rtllib->wpa_ie) + kfree(priv->rtllib->wpa_ie); + priv->rtllib->wpa_ie = NULL; +#ifdef RTL8192S_WAPI_SUPPORT + priv->rtllib->wapiInfo.wapiTxMsk.bTxEnable = false; + priv->rtllib->wapiInfo.wapiTxMsk.bSet = false; +#endif + CamResetAllEntry(dev); + memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32); + rtl8192_irq_disable(dev); + rtl8192_cancel_deferred_work(priv); +#ifndef RTL8190P + cancel_delayed_work(&priv->rtllib->hw_wakeup_wq); +#endif + deinit_hal_dm(dev); + del_timer_sync(&priv->watch_dog_timer); + + rtllib_softmac_stop_protocol(priv->rtllib, 0, true); + SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock); + while(priv->RFChangeInProgress) + { + SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock); + if(RFInProgressTimeOut > 100) + { + SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock); + break; + } + printk("===>%s():RF is in progress, need to wait until rf chang is done.\n",__FUNCTION__); + mdelay(1); + RFInProgressTimeOut ++; + SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock); + } + priv->RFChangeInProgress = true; + SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock); + priv->ops->stop_adapter(dev, false); + SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock); + priv->RFChangeInProgress = false; + SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock); + udelay(100); + memset(&priv->rtllib->current_network, 0 , offsetof(struct rtllib_network, list)); + priv->rtllib->wap_set = 0; + priv->rtllib->current_network.channel = INIT_DEFAULT_CHAN; +#ifdef CONFIG_ASPM_OR_D3 + RT_ENABLE_ASPM(dev); +#endif + } else { + priv->rtllib->wpa_ie_len = 0; + if(priv->rtllib->wpa_ie) + kfree(priv->rtllib->wpa_ie); + priv->rtllib->wpa_ie = NULL; +#ifdef RTL8192S_WAPI_SUPPORT + priv->rtllib->wapiInfo.wapiTxMsk.bTxEnable = false; + priv->rtllib->wapiInfo.wapiTxMsk.bSet = false; +#endif + CamResetAllEntry(dev); + CamRestoreEachIFEntry(dev,1); + memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32); + + rtllib_softmac_stop_protocol(priv->rtllib, 0, true); + memset(&priv->rtllib->current_network, 0 , offsetof(struct rtllib_network, list)); + priv->rtllib->current_network.channel = INIT_DEFAULT_CHAN; + priv->rtllib->wap_set = 0; + } + + RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__); + + return 0; +} + +void rtl8192_dinit_mshobj(struct r8192_priv *priv) +{ + + if(priv && priv->mshobj) + { + if(priv->mshobj->ext_patch_remove_proc) + priv->mshobj->ext_patch_remove_proc(priv); + priv->rtllib->ext_patch_rtllib_start_protocol = 0; + priv->rtllib->ext_patch_rtllib_stop_protocol = 0; + priv->rtllib->ext_patch_rtllib_probe_req_1 = 0; + priv->rtllib->ext_patch_rtllib_probe_req_2 = 0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_auth =0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_deauth =0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_open = 0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm = 0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_peerlink_close = 0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report= 0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req= 0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq = 0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep=0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr = 0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann=0; + priv->rtllib->ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann=0; + priv->rtllib->ext_patch_rtllib_ext_stop_scan_wq_set_channel = 0; + priv->rtllib->ext_patch_rtllib_process_probe_response_1 = 0; + priv->rtllib->ext_patch_rtllib_rx_mgt_on_probe_req = 0; + priv->rtllib->ext_patch_rtllib_rx_mgt_update_expire = 0; + priv->rtllib->ext_patch_rtllib_rx_on_rx = 0; + priv->rtllib->ext_patch_get_beacon_get_probersp = 0; + priv->rtllib->ext_patch_rtllib_rx_frame_get_hdrlen = 0; + priv->rtllib->ext_patch_rtllib_rx_frame_get_mac_hdrlen = 0; + priv->rtllib->ext_patch_rtllib_rx_frame_get_mesh_hdrlen_llc = 0; + priv->rtllib->ext_patch_rtllib_rx_is_valid_framectl = 0; + priv->rtllib->ext_patch_rtllib_softmac_xmit_get_rate = 0; + priv->rtllib->ext_patch_rtllib_is_mesh = 0; + priv->rtllib->ext_patch_rtllib_create_crypt_for_peer = 0; + priv->rtllib->ext_patch_rtllib_get_peermp_htinfo = 0; + priv->rtllib->ext_patch_rtllib_send_ath_commit = 0; + priv->rtllib->ext_patch_rtllib_send_ath_confirm = 0; + priv->rtllib->ext_patch_rtllib_rx_ath_commit = 0; + priv->rtllib->ext_patch_rtllib_rx_ath_confirm = 0; + free_mshobj(&priv->mshobj); + } + +} +#else +int _rtl8192_sta_up(struct net_device *dev,bool is_silent_reset) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + bool init_status = true; + priv->bDriverIsGoingToUnload = false; + priv->bdisable_nic = false; + + priv->up=1; + priv->rtllib->ieee_up=1; + + priv->up_first_time = 0; + RT_TRACE(COMP_INIT, "Bringing up iface"); + priv->bfirst_init = true; + init_status = priv->ops->initialize_adapter(dev); + if(init_status != true) + { + RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__); + priv->bfirst_init = false; + return -1; + } + + RT_TRACE(COMP_INIT, "start adapter finished\n"); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); + priv->bfirst_init = false; +#if defined RTL8192SE || defined RTL8192CE + if(priv->rtllib->eRFPowerState!=eRfOn) + MgntActSet_RF_State(dev, eRfOn, priv->rtllib->RfOffReason,true); +#endif + +#ifdef ENABLE_GPIO_RADIO_CTL + if(priv->polling_timer_on == 0){ + check_rfctrl_gpio_timer((unsigned long)dev); + } +#endif + + if(priv->rtllib->state != RTLLIB_LINKED) +#ifndef CONFIG_MP + rtllib_softmac_start_protocol(priv->rtllib, 0); +#endif + rtllib_reset_queue(priv->rtllib); +#ifndef CONFIG_MP + watch_dog_timer_callback((unsigned long) dev); +#endif + + + if(!netif_queue_stopped(dev)) + netif_start_queue(dev); + else + netif_wake_queue(dev); + + return 0; +} + +int rtl8192_sta_down(struct net_device *dev, bool shutdownrf) +{ + struct r8192_priv *priv = rtllib_priv(dev); + unsigned long flags = 0; + u8 RFInProgressTimeOut = 0; + + if (priv->up == 0) return -1; + +#ifdef ENABLE_IPS + if(priv->rtllib->rtllib_ips_leave != NULL) + priv->rtllib->rtllib_ips_leave(dev); +#endif + +#ifdef ENABLE_LPS + if(priv->rtllib->state == RTLLIB_LINKED) + LeisurePSLeave(dev); +#endif + if(priv->rtllib->LedControlHandler) + priv->rtllib->LedControlHandler(dev, LED_CTL_POWER_OFF); + + priv->bDriverIsGoingToUnload = true; + priv->up=0; + priv->rtllib->ieee_up = 0; + priv->bfirst_after_down = 1; + RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__); + if (!netif_queue_stopped(dev)) + netif_stop_queue(dev); + + priv->rtllib->wpa_ie_len = 0; + if(priv->rtllib->wpa_ie) + kfree(priv->rtllib->wpa_ie); + priv->rtllib->wpa_ie = NULL; +#ifdef RTL8192S_WAPI_SUPPORT + priv->rtllib->wapiInfo.wapiTxMsk.bTxEnable = false; + priv->rtllib->wapiInfo.wapiTxMsk.bSet = false; +#endif + CamResetAllEntry(dev); + memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32); + rtl8192_irq_disable(dev); + + del_timer_sync(&priv->watch_dog_timer); + rtl8192_cancel_deferred_work(priv); +#ifndef RTL8190P +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + cancel_delayed_work(&priv->rtllib->hw_wakeup_wq); +#endif +#endif + + rtllib_softmac_stop_protocol(priv->rtllib, 0, true); + spin_lock_irqsave(&priv->rf_ps_lock,flags); + while(priv->RFChangeInProgress) + { + spin_unlock_irqrestore(&priv->rf_ps_lock,flags); + if(RFInProgressTimeOut > 100) + { + spin_lock_irqsave(&priv->rf_ps_lock,flags); + break; + } + printk("===>%s():RF is in progress, need to wait until rf chang is done.\n",__FUNCTION__); + mdelay(1); + RFInProgressTimeOut ++; + spin_lock_irqsave(&priv->rf_ps_lock,flags); + } + priv->RFChangeInProgress = true; + spin_unlock_irqrestore(&priv->rf_ps_lock,flags); + priv->ops->stop_adapter(dev, false); + spin_lock_irqsave(&priv->rf_ps_lock,flags); + priv->RFChangeInProgress = false; + spin_unlock_irqrestore(&priv->rf_ps_lock,flags); + udelay(100); + memset(&priv->rtllib->current_network, 0 , offsetof(struct rtllib_network, list)); +#ifdef CONFIG_ASPM_OR_D3 + RT_ENABLE_ASPM(dev); +#endif + RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__); + + return 0; +} + +#endif + +static void rtl8192_init_priv_handler(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + priv->rtllib->softmac_hard_start_xmit = rtl8192_hard_start_xmit; + priv->rtllib->set_chan = rtl8192_set_chan; + priv->rtllib->link_change = priv->ops->link_change; + priv->rtllib->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit; + priv->rtllib->data_hard_stop = rtl8192_data_hard_stop; + priv->rtllib->data_hard_resume = rtl8192_data_hard_resume; + priv->rtllib->check_nic_enough_desc = rtl8192_check_nic_enough_desc; + priv->rtllib->get_nic_desc_num = rtl8192_get_nic_desc_num; +#ifdef _RTL8192_EXT_PATCH_ + priv->rtllib->set_mesh_key = r8192_mesh_set_enc_ext; +#endif + priv->rtllib->handle_assoc_response = rtl8192_handle_assoc_response; + priv->rtllib->handle_beacon = rtl8192_handle_beacon; + priv->rtllib->SetWirelessMode = rtl8192_SetWirelessMode; + +#ifdef ENABLE_LPS + priv->rtllib->LeisurePSLeave = LeisurePSLeave; +#endif + +#ifdef RTL8192CE + priv->rtllib->SetBWModeHandler = PHY_SetBWMode8192C; + priv->rf_set_chan = PHY_SwChnl8192C; + +#ifdef _ENABLE_SW_BEACON + priv->rtllib->start_send_beacons = NULL; + priv->rtllib->stop_send_beacons = NULL; +#else + priv->rtllib->start_send_beacons = rtl8192ce_SetBeaconRelatedRegisters; + priv->rtllib->stop_send_beacons = rtl8192_stop_beacon; + priv->rtllib->UpdateBeaconInterruptHandler = rtl8192ce_UpdateBeaconInterruptMask; + priv->rtllib->UpdateInterruptMaskHandler = rtl8192ce_UpdateInterruptMask; +#endif + + priv->rtllib->sta_wake_up = rtl8192_hw_wakeup; + priv->rtllib->enter_sleep_state = rtl8192_hw_to_sleep; + priv->rtllib->ps_is_queue_empty = rtl8192_is_tx_queue_empty; + + priv->rtllib->GetNmodeSupportBySecCfg = rtl8192ce_GetNmodeSupportBySecCfg; + priv->rtllib->GetHalfNmodeSupportByAPsHandler = rtl8192ce_GetHalfNmodeSupportByAPs; + + priv->rtllib->SetHwRegHandler = rtl8192ce_SetHwReg; + priv->rtllib->GetHwRegHandler = rtl8192ce_GetHwReg; + priv->rtllib->AllowAllDestAddrHandler = rtl8192ce_AllowAllDestAddr; + priv->rtllib->SetFwCmdHandler = rtl8192ce_phy_SetFwCmdIO; + priv->rtllib->UpdateHalRAMaskHandler = rtl8192ce_UpdateHalRAMask; + priv->rtllib->rtl_11n_user_show_rates = rtl8192_11n_user_show_rates; +#ifdef ENABLE_IPS + priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq; + priv->rtllib->rtllib_ips_leave = rtllib_ips_leave; +#endif + + priv->rtllib->LedControlHandler = LedControl8192CE; + priv->rtllib->ScanOperationBackupHandler = PHY_ScanOperationBackup8192C; +#endif + +#ifdef RTL8192SE + priv->rtllib->SetBWModeHandler = rtl8192_SetBWMode; + priv->rf_set_chan = rtl8192_phy_SwChnl; + +#ifdef _ENABLE_SW_BEACON + priv->rtllib->start_send_beacons = NULL; + priv->rtllib->stop_send_beacons = NULL; +#else + priv->rtllib->start_send_beacons = rtl8192se_start_beacon; + priv->rtllib->stop_send_beacons = rtl8192_stop_beacon; +#endif + priv->rtllib->sta_wake_up = rtl8192_hw_wakeup; + priv->rtllib->enter_sleep_state = rtl8192_hw_to_sleep; + priv->rtllib->ps_is_queue_empty = rtl8192_is_tx_queue_empty; + + priv->rtllib->GetNmodeSupportBySecCfg = rtl8192se_GetNmodeSupportBySecCfg; + priv->rtllib->GetHalfNmodeSupportByAPsHandler = rtl8192se_GetHalfNmodeSupportByAPs; + + priv->rtllib->SetBeaconRelatedRegistersHandler = SetBeaconRelatedRegisters8192SE; + priv->rtllib->Adhoc_InitRateAdaptive = Adhoc_InitRateAdaptive; + priv->rtllib->check_ht_cap = rtl8192se_check_ht_cap; + priv->rtllib->SetHwRegHandler = SetHwReg8192SE; + priv->rtllib->GetHwRegHandler = GetHwReg8192SE; + priv->rtllib->AllowAllDestAddrHandler = rtl8192se_AllowAllDestAddr; + priv->rtllib->SetFwCmdHandler = rtl8192se_set_fw_cmd; + priv->rtllib->UpdateHalRAMaskHandler = UpdateHalRAMask8192SE; + priv->rtllib->UpdateBeaconInterruptHandler = NULL; + priv->rtllib->rtl_11n_user_show_rates = rtl8192_11n_user_show_rates; +#ifdef ENABLE_IPS + priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq; + priv->rtllib->rtllib_ips_leave = rtllib_ips_leave; +#endif + + priv->rtllib->LedControlHandler = LedControl8192SE; + priv->rtllib->rtllib_start_hw_scan = rtl8192se_hw_scan_initiate; + priv->rtllib->rtllib_stop_hw_scan = rtl8192se_cancel_hw_scan; + + priv->rtllib->ScanOperationBackupHandler = PHY_ScanOperationBackup8192S; +#endif + +#ifdef RTL8192E + priv->rtllib->SetBWModeHandler = rtl8192_SetBWMode; + priv->rf_set_chan = rtl8192_phy_SwChnl; + +#ifdef _ENABLE_SW_BEACON + priv->rtllib->start_send_beacons = NULL; + priv->rtllib->stop_send_beacons = NULL; +#else + priv->rtllib->start_send_beacons = rtl8192e_start_beacon; + priv->rtllib->stop_send_beacons = rtl8192_stop_beacon; +#endif + + priv->rtllib->sta_wake_up = rtl8192_hw_wakeup; + priv->rtllib->enter_sleep_state = rtl8192_hw_to_sleep; + priv->rtllib->ps_is_queue_empty = rtl8192_is_tx_queue_empty; + + priv->rtllib->GetNmodeSupportBySecCfg = rtl8192_GetNmodeSupportBySecCfg; + priv->rtllib->GetHalfNmodeSupportByAPsHandler = rtl8192_GetHalfNmodeSupportByAPs; + + priv->rtllib->SetHwRegHandler = rtl8192e_SetHwReg; + priv->rtllib->AllowAllDestAddrHandler = rtl8192_AllowAllDestAddr; + priv->rtllib->SetFwCmdHandler = NULL; + priv->rtllib->InitialGainHandler = InitialGain819xPci; +#ifdef ENABLE_IPS + priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq; + priv->rtllib->rtllib_ips_leave = rtllib_ips_leave; +#endif + + priv->rtllib->LedControlHandler = NULL; + priv->rtllib->UpdateBeaconInterruptHandler = NULL; + + priv->rtllib->ScanOperationBackupHandler = PHY_ScanOperationBackup8192; +#endif + +#ifdef RTL8190P + priv->rtllib->SetBWModeHandler = rtl8192_SetBWMode; + priv->rf_set_chan = rtl8192_phy_SwChnl; + +#ifdef _ENABLE_SW_BEACON + priv->rtllib->start_send_beacons = NULL; + priv->rtllib->stop_send_beacons = NULL; +#else + priv->rtllib->start_send_beacons = rtl8192e_start_beacon; + priv->rtllib->stop_send_beacons = rtl8192_stop_beacon; +#endif + + priv->rtllib->GetNmodeSupportBySecCfg = rtl8192_GetNmodeSupportBySecCfg; + priv->rtllib->GetHalfNmodeSupportByAPsHandler = rtl8192_GetHalfNmodeSupportByAPs; + + priv->rtllib->SetHwRegHandler = rtl8192e_SetHwReg; + priv->rtllib->SetFwCmdHandler = NULL; + priv->rtllib->InitialGainHandler = InitialGain819xPci; +#ifdef ENABLE_IPS + priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq; + priv->rtllib->rtllib_ips_leave = rtllib_ips_leave; +#endif + + priv->rtllib->LedControlHandler = NULL; + priv->rtllib->UpdateBeaconInterruptHandler = NULL; + + priv->rtllib->ScanOperationBackupHandler = PHY_ScanOperationBackup8192; +#endif + +#ifdef CONFIG_RTL_RFKILL + priv->rtllib->rtllib_rfkill_poll = rtl8192_rfkill_poll; +#else + priv->rtllib->rtllib_rfkill_poll = NULL; +#endif +} + +static void rtl8192_init_priv_constant(struct net_device* dev) +{ +#if defined RTL8192SE || defined RTL8192CE || defined RTL8192E + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); +#endif + +#if defined RTL8192SE || defined RTL8192CE || defined RTL8192E + pPSC->RegMaxLPSAwakeIntvl = 5; +#endif + +#ifdef RTL8192CE + priv->bWEPinNmodeFromReg = 0; + priv->bTKIPinNmodeFromReg = 0; + + priv->RegAMDPciASPM = 0; + + priv->RegPciASPM = 3; + + priv->RegDevicePciASPMSetting = 0x03; + + priv->RegHostPciASPMSetting = 0x02; + + priv->RegHwSwRfOffD3 = 0; + + priv->RegSupportPciASPM = 1; + +#elif defined RTL8192SE + priv->RegPciASPM = 2; + + priv->RegDevicePciASPMSetting = 0x03; + + priv->RegHostPciASPMSetting = 0x02; + + priv->RegHwSwRfOffD3 = 2; + + priv->RegSupportPciASPM = 2; + +#elif defined RTL8192E + priv->RegPciASPM = 2; + + priv->RegDevicePciASPMSetting = 0x03; + + priv->RegHostPciASPMSetting = 0x02; + + priv->RegHwSwRfOffD3 = 2; + + priv->RegSupportPciASPM = 2; + +#elif defined RTL8190P +#endif +} + + +static void rtl8192_init_priv_variable(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 i; + + priv->AcmMethod = eAcmWay2_SW; + priv->dot11CurrentPreambleMode = PREAMBLE_AUTO; + priv->rtllib->hwscan_sem_up = 1; + priv->rtllib->status = 0; + priv->H2CTxCmdSeq = 0; + priv->bDisableFrameBursting = 0; + priv->bDMInitialGainEnable = 1; + priv->polling_timer_on = 0; + priv->up_first_time = 1; + priv->blinked_ingpio = false; + priv->bDriverIsGoingToUnload = false; + priv->being_init_adapter = false; + priv->initialized_at_probe = false; + priv->sw_radio_on = true; + priv->bdisable_nic = false; + priv->bfirst_init = false; + priv->txringcount = 64; + priv->rxbuffersize = 9100; + priv->rxringcount = MAX_RX_COUNT; + priv->irq_enabled=0; + priv->chan = 1; + priv->RegWirelessMode = WIRELESS_MODE_AUTO; + priv->RegChannelPlan = 0xf; + priv->nrxAMPDU_size = 0; + priv->nrxAMPDU_aggr_num = 0; + priv->last_rxdesc_tsf_high = 0; + priv->last_rxdesc_tsf_low = 0; + priv->rtllib->mode = WIRELESS_MODE_AUTO; + priv->rtllib->iw_mode = IW_MODE_INFRA; + priv->rtllib->bNetPromiscuousMode = false; + priv->rtllib->IntelPromiscuousModeInfo.bPromiscuousOn = false; + priv->rtllib->IntelPromiscuousModeInfo.bFilterSourceStationFrame = false; + priv->rtllib->ieee_up=0; + priv->retry_rts = DEFAULT_RETRY_RTS; + priv->retry_data = DEFAULT_RETRY_DATA; + priv->rtllib->rts = DEFAULT_RTS_THRESHOLD; + priv->rtllib->rate = 110; + priv->rtllib->short_slot = 1; + priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0; + priv->bcck_in_ch14 = false; + priv->bfsync_processing = false; + priv->CCKPresentAttentuation = 0; + priv->rfa_txpowertrackingindex = 0; + priv->rfc_txpowertrackingindex = 0; + priv->CckPwEnl = 6; + priv->ScanDelay = 50; + priv->ResetProgress = RESET_TYPE_NORESET; + priv->bForcedSilentReset = 0; + priv->bDisableNormalResetCheck = false; + priv->force_reset = false; + memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32); + + memset(&priv->InterruptLog,0,sizeof(LOG_INTERRUPT_8190_T)); + priv->RxCounter = 0; + priv->rtllib->wx_set_enc = 0; + priv->bHwRadioOff = false; + priv->RegRfOff = 0; + priv->isRFOff = false; + priv->bInPowerSaveMode = false; + priv->rtllib->RfOffReason = 0; + priv->RFChangeInProgress = false; + priv->bHwRfOffAction = 0; + priv->SetRFPowerStateInProgress = false; + priv->rtllib->PowerSaveControl.bInactivePs = true; + priv->rtllib->PowerSaveControl.bIPSModeBackup = false; + priv->rtllib->PowerSaveControl.bLeisurePs = true; + priv->rtllib->PowerSaveControl.bFwCtrlLPS = false; + priv->rtllib->LPSDelayCnt = 0; + priv->rtllib->sta_sleep = LPS_IS_WAKE; + priv->rtllib->eRFPowerState = eRfOn; + + priv->txpower_checkcnt = 0; + priv->thermal_readback_index =0; + priv->txpower_tracking_callback_cnt = 0; + priv->ccktxpower_adjustcnt_ch14 = 0; + priv->ccktxpower_adjustcnt_not_ch14 = 0; + +#if defined RTL8192SE + for(i = 0; irtllib->peer_assoc_list[i]=NULL; + priv->rtllib->AvailableAIDTable[i] = 99; + } + priv->RATRTableBitmap = 0; + priv->rtllib->amsdu_in_process = 0; +#endif + + priv->rtllib->current_network.beacon_interval = DEFAULT_BEACONINTERVAL; + priv->rtllib->iw_mode = IW_MODE_INFRA; + priv->rtllib->active_scan = 1; + priv->rtllib->be_scan_inprogress = false; + priv->rtllib->modulation = RTLLIB_CCK_MODULATION | RTLLIB_OFDM_MODULATION; + priv->rtllib->host_encrypt = 1; + priv->rtllib->host_decrypt = 1; + + priv->rtllib->dot11PowerSaveMode = eActive; +#if defined (RTL8192S_WAPI_SUPPORT) + priv->rtllib->wapiInfo.bWapiPSK = false; +#endif + priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD; + priv->rtllib->MaxMssDensity = 0; + priv->rtllib->MinSpaceCfg = 0; + + priv->card_type = PCI; + +#if 0 + { + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC; + pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_CLK_REQ; + pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM; + pPSC->RegRfPsLevel |= RT_RF_LPS_LEVEL_ASPM; + printk("=================>%s():RegRfPsLevel:%#x\n", __func__,pPSC->RegRfPsLevel); + } +#endif + + priv->AcmControl = 0; + priv->pFirmware = (rt_firmware*)vmalloc(sizeof(rt_firmware)); + if (priv->pFirmware) + memset(priv->pFirmware, 0, sizeof(rt_firmware)); + + skb_queue_head_init(&priv->rx_queue); + skb_queue_head_init(&priv->skb_queue); + + for(i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_head_init(&priv->rtllib->skb_waitQ [i]); + } + for(i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_head_init(&priv->rtllib->skb_aggQ [i]); + } + +} + +static void rtl8192_init_priv_lock(struct r8192_priv* priv) +{ + spin_lock_init(&priv->fw_scan_lock); + spin_lock_init(&priv->tx_lock); + spin_lock_init(&priv->irq_lock); + spin_lock_init(&priv->irq_th_lock); + spin_lock_init(&priv->rf_ps_lock); + spin_lock_init(&priv->ps_lock); + spin_lock_init(&priv->rf_lock); + spin_lock_init(&priv->rt_h2c_lock); +#ifdef CONFIG_ASPM_OR_D3 + spin_lock_init(&priv->D3_lock); +#endif + sema_init(&priv->wx_sem,1); + sema_init(&priv->rf_sem,1); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) + sema_init(&priv->mutex, 1); +#else + mutex_init(&priv->mutex); +#endif +} + +static void rtl8192_init_priv_task(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) +#ifdef PF_SYNCTHREAD + priv->priv_wq = create_workqueue(DRV_NAME,0); +#else + priv->priv_wq = create_workqueue(DRV_NAME); +#endif +#endif + INIT_WORK_RSL(&priv->reset_wq, (void*)rtl8192_restart, dev); +#ifdef ENABLE_IPS + INIT_WORK_RSL(&priv->rtllib->ips_leave_wq, (void*)IPSLeave_wq, dev); +#endif + INIT_DELAYED_WORK_RSL(&priv->watch_dog_wq, (void*)rtl819x_watchdog_wqcallback, dev); + INIT_DELAYED_WORK_RSL(&priv->txpower_tracking_wq, (void*)dm_txpower_trackingcallback, dev); + INIT_DELAYED_WORK_RSL(&priv->rfpath_check_wq, (void*)dm_rf_pathcheck_workitemcallback, dev); + INIT_DELAYED_WORK_RSL(&priv->update_beacon_wq, (void*)rtl8192_update_beacon, dev); + INIT_WORK_RSL(&priv->qos_activate, (void*)rtl8192_qos_activate, dev); +#ifndef RTL8190P + INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_wakeup_wq,(void*) rtl8192_hw_wakeup_wq, dev); + INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_sleep_wq,(void*) rtl8192_hw_sleep_wq, dev); +#endif +#if defined RTL8192SE + INIT_DELAYED_WORK_RSL(&priv->check_hw_scan_wq, (void*)rtl8192se_check_hw_scan, dev); + INIT_DELAYED_WORK_RSL(&priv->hw_scan_simu_wq, (void*)rtl8192se_hw_scan_simu, dev); + INIT_DELAYED_WORK_RSL(&priv->start_hw_scan_wq, (void*)rtl8192se_start_hw_scan, dev); + INIT_DELAYED_WORK_RSL(&priv->rtllib->check_tsf_wq,(void*)rtl8192se_check_tsf_wq, dev); + INIT_DELAYED_WORK_RSL(&priv->rtllib->update_assoc_sta_info_wq, + (void*)rtl8192se_update_assoc_sta_info_wq, dev); +#endif +#ifdef _RTL8192_EXT_PATCH_ + INIT_WORK_RSL(&priv->rtllib->ext_create_crypt_for_peers_wq, (void*)msh_create_crypt_for_peers_wq, dev); + INIT_WORK_RSL(&priv->rtllib->ext_path_sel_ops_wq,(void*) path_sel_ops_wq, dev); + INIT_WORK_RSL(&priv->rtllib->ext_update_extchnloffset_wq, + (void*) meshdev_update_ext_chnl_offset_as_client, dev); + INIT_DELAYED_WORK_RSL(&priv->rtllib->ext_wx_set_key_wq, (void*)ext_mesh_set_key_wq,priv->rtllib); + INIT_WORK_RSL(&priv->rtllib->ext_start_mesh_protocol_wq, + (void*) meshdev_start_mesh_protocol_wq, dev); +#endif + tasklet_init(&priv->irq_rx_tasklet, + (void(*)(unsigned long))rtl8192_irq_rx_tasklet, + (unsigned long)priv); + tasklet_init(&priv->irq_tx_tasklet, + (void(*)(unsigned long))rtl8192_irq_tx_tasklet, + (unsigned long)priv); + tasklet_init(&priv->irq_prepare_beacon_tasklet, + (void(*)(unsigned long))rtl8192_prepare_beacon, + (unsigned long)priv); +} + +short rtl8192_get_channel_map(struct net_device * dev) +{ + int i; + +#ifdef ENABLE_DOT11D + struct r8192_priv *priv = rtllib_priv(dev); + if ((priv->rf_chip != RF_8225) && (priv->rf_chip != RF_8256) + && (priv->rf_chip != RF_6052)) { + RT_TRACE(COMP_ERR, "%s: unknown rf chip, can't set channel map\n", __FUNCTION__); + return -1; + } + + if (priv->ChannelPlan > COUNTRY_CODE_MAX) { + printk("rtl819x_init:Error channel plan! Set to default.\n"); + priv->ChannelPlan= COUNTRY_CODE_FCC; + } + RT_TRACE(COMP_INIT, "Channel plan is %d\n",priv->ChannelPlan); + Dot11d_Init(priv->rtllib); +#ifndef CONFIG_CRDA + Dot11d_Channelmap(priv->ChannelPlan, priv->rtllib); +#endif +#else + struct r8192_priv *priv = rtllib_priv(dev); + int ch; + if(!channels){ + DMESG("No channels, aborting"); + return -1; + } + + ch = channels; + priv->ChannelPlan = 0; + for (i = 1; i <= 14; i++) { + (priv->rtllib->channel_map)[i] = (u8)(ch & 0x01); + ch >>= 1; + } + priv->rtllib->IbssStartChnl= 10; + priv->rtllib->ibss_maxjoin_chal = 11; +#endif + for (i = 1; i <= 11; i++) { + (priv->rtllib->active_channel_map)[i] = 1; + } + (priv->rtllib->active_channel_map)[12] = 2; + (priv->rtllib->active_channel_map)[13] = 2; + + return 0; +} + +short rtl8192_init(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + memset(&(priv->stats),0,sizeof(struct Stats)); + +#ifdef CONFIG_BT_30 + bt_wifi_init(dev); +#endif + +#ifdef CONFIG_MP + rtl8192_init_mp(dev); +#endif + + rtl8192_dbgp_flag_init(dev); + + rtl8192_init_priv_handler(dev); + rtl8192_init_priv_constant(dev); + rtl8192_init_priv_variable(dev); +#ifdef _RTL8192_EXT_PATCH_ + rtl8192_init_mesh_variable(dev); +#endif + rtl8192_init_priv_lock(priv); + rtl8192_init_priv_task(dev); + priv->ops->get_eeprom_size(dev); + priv->ops->init_adapter_variable(dev); + rtl8192_get_channel_map(dev); + +#ifdef CONFIG_CFG_80211 + /* channel map setting for the cfg80211 style */ + { + struct r8192_priv* priv = rtllib_priv(dev); + rtllib_set_geo(priv); + } +#endif + + init_hal_dm(dev); + +#if defined RTL8192SE || defined RTL8192CE + InitSwLeds(dev); +#endif + init_timer(&priv->watch_dog_timer); + setup_timer(&priv->watch_dog_timer, + watch_dog_timer_callback, + (unsigned long) dev); + + init_timer(&priv->gpio_polling_timer); + setup_timer(&priv->gpio_polling_timer, + check_rfctrl_gpio_timer, + (unsigned long)dev); + + rtl8192_irq_disable(dev); +#if defined(IRQF_SHARED) + if (request_irq(dev->irq, (void*)rtl8192_interrupt_rsl, IRQF_SHARED, dev->name, dev)) +#else + if (request_irq(dev->irq, (void *)rtl8192_interrupt_rsl, SA_SHIRQ, dev->name, dev)) +#endif + { + printk("Error allocating IRQ %d",dev->irq); + return -1; + } else { + priv->irq=dev->irq; + RT_TRACE(COMP_INIT, "IRQ %d\n",dev->irq); + } + + if (rtl8192_pci_initdescring(dev) != 0) { + printk("Endopoints initialization failed"); + return -1; + } + + return 0; +} + +#if defined CONFIG_ASPM_OR_D3 +static void +rtl8192_update_default_setting(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + + pPSC->RegRfPsLevel = 0; + priv->bSupportASPM = 0; + + + pPSC->RegAMDPciASPM = priv->RegAMDPciASPM ; + switch(priv->RegPciASPM) + { + case 0: + break; + + case 1: + pPSC->RegRfPsLevel |= RT_RF_LPS_LEVEL_ASPM; + break; + + case 2: + pPSC->RegRfPsLevel |= (RT_RF_LPS_LEVEL_ASPM | RT_RF_OFF_LEVL_CLK_REQ); + break; + + case 3: + pPSC->RegRfPsLevel &= ~(RT_RF_LPS_LEVEL_ASPM); + pPSC->RegRfPsLevel |= (RT_RF_PS_LEVEL_ALWAYS_ASPM | RT_RF_OFF_LEVL_CLK_REQ); + break; + + case 4: + pPSC->RegRfPsLevel &= ~(RT_RF_LPS_LEVEL_ASPM | RT_RF_OFF_LEVL_CLK_REQ); + pPSC->RegRfPsLevel |= RT_RF_PS_LEVEL_ALWAYS_ASPM; + break; + } + + pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC; + + switch(priv->RegHwSwRfOffD3) + { + case 1: + if(pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM) + pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM; + break; + + case 2: + if(pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM) + pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM; + pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC; + break; + + case 3: + pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_PCI_D3; + break; + } + + + switch(priv->RegSupportPciASPM) + { + case 0: + { + bool bSupportASPM = false; + priv->bSupportASPM = bSupportASPM; + } + break; + + case 1: + { + bool bSupportASPM = true; + bool bSupportBackDoor = true; + + priv->bSupportASPM = bSupportASPM; + + if(priv->CustomerID == RT_CID_TOSHIBA && !priv->NdisAdapter.AMDL1PATCH) + bSupportBackDoor = false; + + priv->bSupportBackDoor = bSupportBackDoor; + } + break; + + case 2: + if(priv->NdisAdapter.PciBridgeVendor == PCI_BRIDGE_VENDOR_INTEL) + { + bool bSupportASPM = true; + priv->bSupportASPM = bSupportASPM; + } + break; + + default: + break; + } +} +#endif + +#if defined CONFIG_ASPM_OR_D3 +static void +rtl8192_initialize_adapter_common(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + + rtl8192_update_default_setting(dev); + +#ifdef CONFIG_ASPM_OR_D3 + if(pPSC->RegRfPsLevel & RT_RF_PS_LEVEL_ALWAYS_ASPM) + { + RT_ENABLE_ASPM(dev); + RT_SET_PS_LEVEL(pPSC, RT_RF_PS_LEVEL_ALWAYS_ASPM); + } +#endif +} +#endif + +/*************************************************************************** + -------------------------------WATCHDOG STUFF--------------------------- +***************************************************************************/ +short rtl8192_is_tx_queue_empty(struct net_device *dev) +{ + int i=0; + struct r8192_priv *priv = rtllib_priv(dev); + for (i=0; i<=MGNT_QUEUE; i++) + { + if ((i== TXCMD_QUEUE) || (i == HCCA_QUEUE) ) + continue; + if (skb_queue_len(&(&priv->tx_ring[i])->queue) > 0){ + printk("===>tx queue is not empty:%d, %d\n", i, skb_queue_len(&(&priv->tx_ring[i])->queue)); + return 0; + } + } + return 1; +} + +RESET_TYPE +rtl819x_TxCheckStuck(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 QueueID; + u8 ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE; + bool bCheckFwTxCnt = false; + struct rtl8192_tx_ring *ring = NULL; + struct sk_buff* skb = NULL; + cb_desc * tcb_desc = NULL; + unsigned long flags = 0; + +#if 0 + switch (priv->rtllib->dot11PowerSaveMode) + { + case eActive: + ResetThreshold = NIC_SEND_HANG_THRESHOLD_NORMAL; + break; + case eMaxPs: + ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE; + break; + case eFastPs: + ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE; + break; + default: + break; + } +#else + switch (priv->rtllib->ps) + { + case RTLLIB_PS_DISABLED: + ResetThreshold = NIC_SEND_HANG_THRESHOLD_NORMAL; + break; + case (RTLLIB_PS_MBCAST|RTLLIB_PS_UNICAST): + ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE; + break; + default: + ResetThreshold = NIC_SEND_HANG_THRESHOLD_POWERSAVE; + break; + } +#endif + spin_lock_irqsave(&priv->irq_th_lock,flags); + for(QueueID = 0; QueueID < MAX_TX_QUEUE; QueueID++) + { + if(QueueID == TXCMD_QUEUE) + continue; + + if(QueueID == BEACON_QUEUE) + continue; + + ring = &priv->tx_ring[QueueID]; + + if(skb_queue_len(&ring->queue) == 0) + continue; + else + { + skb = (&ring->queue)->next; + tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + tcb_desc->nStuckCount++; + bCheckFwTxCnt = true; + if(tcb_desc->nStuckCount > 1) + printk("%s: QueueID=%d tcb_desc->nStuckCount=%d\n",__func__,QueueID,tcb_desc->nStuckCount); +#if defined RTL8192SE || defined RTL8192CE + if(tcb_desc->nStuckCount > ResetThreshold) + { + RT_TRACE( COMP_RESET, "TxCheckStuck(): Need silent reset because nStuckCount > ResetThreshold.\n" ); + spin_unlock_irqrestore(&priv->irq_th_lock,flags); + return RESET_TYPE_SILENT; + } + bCheckFwTxCnt = false; + #endif + } + } + spin_unlock_irqrestore(&priv->irq_th_lock,flags); + + if(bCheckFwTxCnt) { + if (priv->ops->TxCheckStuckHandler(dev)) + { + RT_TRACE(COMP_RESET, "TxCheckStuck(): Fw indicates no Tx condition! \n"); + return RESET_TYPE_SILENT; + } + } + + return RESET_TYPE_NORESET; +} + +RESET_TYPE rtl819x_RxCheckStuck(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->ops->RxCheckStuckHandler(dev)) + { + RT_TRACE(COMP_RESET, "RxStuck Condition\n"); + return RESET_TYPE_SILENT; + } + + return RESET_TYPE_NORESET; +} + +RESET_TYPE +rtl819x_ifcheck_resetornot(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + RESET_TYPE TxResetType = RESET_TYPE_NORESET; + RESET_TYPE RxResetType = RESET_TYPE_NORESET; + RT_RF_POWER_STATE rfState; + + rfState = priv->rtllib->eRFPowerState; + + if(rfState == eRfOn) + TxResetType = rtl819x_TxCheckStuck(dev); + + if( rfState == eRfOn && + (priv->rtllib->iw_mode == IW_MODE_INFRA) && + (priv->rtllib->state == RTLLIB_LINKED)) { + + RxResetType = rtl819x_RxCheckStuck(dev); + } + + if(TxResetType==RESET_TYPE_NORMAL || RxResetType==RESET_TYPE_NORMAL){ + printk("%s(): TxResetType is %d, RxResetType is %d\n",__FUNCTION__,TxResetType,RxResetType); + return RESET_TYPE_NORMAL; + } else if(TxResetType==RESET_TYPE_SILENT || RxResetType==RESET_TYPE_SILENT){ + printk("%s(): TxResetType is %d, RxResetType is %d\n",__FUNCTION__,TxResetType,RxResetType); + return RESET_TYPE_SILENT; + } else { + return RESET_TYPE_NORESET; + } + +} + +#ifdef _RTL8192_EXT_PATCH_ +void rtl819x_silentreset_mesh_start(struct net_device *dev, + u8 *pbackup_channel_wlan, + u8 *pbackup_channel_mesh, + u8 *pIsPortal) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + + *pbackup_channel_wlan = ieee->current_network.channel; + *pbackup_channel_mesh = ieee->current_mesh_network.channel; + if((ieee->state == RTLLIB_LINKED) && ((ieee->iw_mode == IW_MODE_INFRA) || (ieee->iw_mode == IW_MODE_ADHOC))) + { + printk("====>down, infra or adhoc\n"); + SEM_DOWN_IEEE_WX(&ieee->wx_sem); + printk("ieee->state is RTLLIB_LINKED\n"); + rtllib_stop_send_beacons(priv->rtllib); + del_timer_sync(&ieee->associate_timer); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + cancel_delayed_work(&ieee->associate_retry_wq); +#endif + rtllib_stop_scan(ieee); + netif_carrier_off(dev); + SEM_UP_IEEE_WX(&ieee->wx_sem); + } + else if((ieee->iw_mode == IW_MODE_MESH) && (ieee->mesh_state == RTLLIB_MESH_LINKED)) + { + if(priv->mshobj->ext_patch_r819x_wx_get_AsPortal) + priv->mshobj->ext_patch_r819x_wx_get_AsPortal(priv, pIsPortal); + if((!ieee->only_mesh) && (ieee->state == RTLLIB_LINKED)){ + printk("====>down, wlan server\n"); + SEM_DOWN_IEEE_WX(&ieee->wx_sem); + printk("ieee->state is RTLLIB_LINKED\n"); + rtllib_stop_send_beacons(priv->rtllib); + del_timer_sync(&ieee->associate_timer); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + cancel_delayed_work(&ieee->associate_retry_wq); +#endif + rtllib_stop_scan(ieee); + netif_carrier_off(dev); + SEM_UP_IEEE_WX(&ieee->wx_sem); + if(priv->mshobj->ext_patch_rtllib_stop_protocol) + priv->mshobj->ext_patch_rtllib_stop_protocol(ieee,1); + } + else if((!ieee->only_mesh) && (ieee->state != RTLLIB_LINKED)){ + printk("====>down, wlan server\n"); + SEM_DOWN_IEEE_WX(&ieee->wx_sem); + printk("ieee->state is Not RTLLIB_LINKED\n"); + rtllib_stop_send_beacons(priv->rtllib); + rtllib_stop_scan(ieee); + netif_carrier_off(dev); + SEM_UP_IEEE_WX(&ieee->wx_sem); + if(priv->mshobj->ext_patch_rtllib_stop_protocol) + priv->mshobj->ext_patch_rtllib_stop_protocol(ieee,1); + } + else if(ieee->only_mesh && (*pIsPortal)) + { + printk("====>down, eth0 server\n"); + if(priv->mshobj->ext_patch_rtllib_stop_protocol) + priv->mshobj->ext_patch_rtllib_stop_protocol(ieee,1); + } + else if(ieee->only_mesh && !(*pIsPortal)) + { + printk("====>down, p2p or client\n"); + if(priv->mshobj->ext_patch_rtllib_stop_protocol) + priv->mshobj->ext_patch_rtllib_stop_protocol(ieee,1); + } + else{ + printk("====>down, no link\n"); + if(priv->mshobj->ext_patch_rtllib_stop_protocol) + priv->mshobj->ext_patch_rtllib_stop_protocol(ieee,1); + } + } + else{ + printk("====>down, no link\n"); + printk("ieee->state is NOT LINKED\n"); + rtllib_softmac_stop_protocol(priv->rtllib,0,true); + } +} +#endif + +void rtl819x_silentreset_mesh_bk(struct net_device *dev, u8 IsPortal) +{ +#ifdef _RTL8192_EXT_PATCH_ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + u8 updateBW = 0; + u8 bserverHT = 0; + + if(!ieee->only_mesh) + { + printk("===>up, wlan0 server\n"); + ieee->set_chan(ieee->dev, ieee->current_network.channel); + + queue_work_rsl(ieee->wq, &ieee->associate_complete_wq); + if (ieee->current_mesh_network.beacon_interval == 0) + ieee->current_mesh_network.beacon_interval = 100; + ieee->mesh_state = RTLLIB_MESH_LINKED; + ieee->link_change(ieee->dev); + if(priv->mshobj->ext_patch_rtllib_start_protocol) + priv->mshobj->ext_patch_rtllib_start_protocol(ieee); + } + else if(ieee->only_mesh && IsPortal) + { + printk("===>up, eth0 server\n"); + if (ieee->current_mesh_network.beacon_interval == 0) + ieee->current_mesh_network.beacon_interval = 100; + ieee->mesh_state = RTLLIB_MESH_LINKED; + ieee->link_change(ieee->dev); + if(priv->mshobj->ext_patch_rtllib_start_protocol) + priv->mshobj->ext_patch_rtllib_start_protocol(ieee); + ieee->current_network.channel = ieee->current_mesh_network.channel; + if(ieee->pHTInfo->bCurBW40MHz) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + } + else if(ieee->only_mesh && !IsPortal) + { + printk("===>up, p2p or client\n"); + if (ieee->current_mesh_network.beacon_interval == 0) + ieee->current_mesh_network.beacon_interval = 100; + ieee->mesh_state = RTLLIB_MESH_LINKED; + ieee->link_change(ieee->dev); + if(priv->mshobj->ext_patch_rtllib_start_protocol) + priv->mshobj->ext_patch_rtllib_start_protocol(ieee); + if(ieee->p2pmode){ + printk("===>up, p2p\n"); + ieee->current_network.channel = ieee->current_mesh_network.channel; + if(ieee->pHTInfo->bCurBW40MHz) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + }else{ + printk("===>up, client\n"); + updateBW = priv->mshobj->ext_patch_r819x_wx_update_beacon(ieee->dev,&bserverHT); + printk("$$$$$$ Cur_networ.chan=%d, cur_mesh_net.chan=%d,bserverHT=%d\n", + ieee->current_network.channel,ieee->current_mesh_network.channel,bserverHT); + if (updateBW == 1) { + if (bserverHT == 0) { + printk("===>server is not HT supported,set 20M\n"); + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + } else { + printk("===>updateBW is 1,bCurBW40MHz is %d,ieee->serverExtChlOffset is %d\n", + ieee->pHTInfo->bCurBW40MHz,ieee->serverExtChlOffset); + if (ieee->pHTInfo->bCurBW40MHz) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, ieee->serverExtChlOffset); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, ieee->serverExtChlOffset); + } + } else { + printk("===>there is no same hostname server, ERR!!!\n"); + } + } + } +#endif +} + +void rtl819x_ifsilentreset(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 reset_times = 0; + int reset_status = 0; + struct rtllib_device *ieee = priv->rtllib; + unsigned long flag; + +#ifdef _RTL8192_EXT_PATCH_ + bool wlansilentreset = false,meshsilentreset = false; + u8 backup_channel_wlan = 1,backup_channel_mesh = 1; + int i=0; +#endif + u8 IsPortal = 0; + + + if(priv->ResetProgress==RESET_TYPE_NORESET) { + + RT_TRACE(COMP_RESET,"=========>Reset progress!! \n"); + + priv->ResetProgress = RESET_TYPE_SILENT; + + spin_lock_irqsave(&priv->rf_ps_lock,flag); + if(priv->RFChangeInProgress) + { + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + goto END; + } + priv->RFChangeInProgress = true; + priv->bResetInProgress = true; + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + +RESET_START: + + down(&priv->wx_sem); + +#ifdef ENABLE_LPS + if(priv->rtllib->state == RTLLIB_LINKED) + LeisurePSLeave(dev); +#endif + + if (IS_NIC_DOWN(priv)) { + RT_TRACE(COMP_ERR,"%s():the driver is not up! return\n",__FUNCTION__); + up(&priv->wx_sem); + return ; + } +#ifdef _RTL8192_EXT_PATCH_ + if (priv->up == 1) { + printk("================>wlansilentreset is true\n"); + wlansilentreset = true; + priv->up = 0; + } + if (priv->mesh_up == 1) { + printk("================>meshsilentreset is true\n"); + meshsilentreset = true; + priv->mesh_up = 0; + } +#else + priv->up = 0; +#endif + + RT_TRACE(COMP_RESET,"%s():======>start to down the driver\n",__FUNCTION__); + mdelay(1000); + RT_TRACE(COMP_RESET,"%s():111111111111111111111111======>start to down the driver\n",__FUNCTION__); + + if(!netif_queue_stopped(dev)) + netif_stop_queue(dev); + + rtl8192_irq_disable(dev); + del_timer_sync(&priv->watch_dog_timer); + rtl8192_cancel_deferred_work(priv); + deinit_hal_dm(dev); + rtllib_stop_scan_syncro(ieee); + +#ifdef _RTL8192_EXT_PATCH_ + rtl819x_silentreset_mesh_start(dev, &backup_channel_wlan, + &backup_channel_mesh, &IsPortal); +#else + if (ieee->state == RTLLIB_LINKED) { + SEM_DOWN_IEEE_WX(&ieee->wx_sem); + printk("ieee->state is RTLLIB_LINKED\n"); + rtllib_stop_send_beacons(priv->rtllib); + del_timer_sync(&ieee->associate_timer); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + cancel_delayed_work(&ieee->associate_retry_wq); +#endif + rtllib_stop_scan(ieee); + netif_carrier_off(dev); + SEM_UP_IEEE_WX(&ieee->wx_sem); + } else { + printk("ieee->state is NOT LINKED\n"); + rtllib_softmac_stop_protocol(priv->rtllib, 0 ,true); + } +#endif + +#if !(defined RTL8192SE || defined RTL8192CE) + dm_backup_dynamic_mechanism_state(dev); +#endif + +#ifdef RTL8190P + priv->ops->stop_adapter(dev, true); +#endif + + up(&priv->wx_sem); + RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__); + + RT_TRACE(COMP_RESET,"%s():<===========up process start\n",__FUNCTION__); +#ifdef _RTL8192_EXT_PATCH_ + if(wlansilentreset == true){ + reset_status = _rtl8192_up(dev,true); + } + if(meshsilentreset == true) + reset_status = meshdev_up(ieee->meshdev,true); +#else + reset_status = _rtl8192_up(dev,true); +#endif + + RT_TRACE(COMP_RESET,"%s():<===========up process is finished\n",__FUNCTION__); + if (reset_status == -1) { + if(reset_times < 3) { + reset_times++; + goto RESET_START; + } else { + RT_TRACE(COMP_ERR," ERR!!! %s(): Reset Failed!!\n",__FUNCTION__); + } + } + + ieee->is_silent_reset = 1; + + spin_lock_irqsave(&priv->rf_ps_lock,flag); + priv->RFChangeInProgress = false; + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + + EnableHWSecurityConfig8192(dev); + +#ifdef _RTL8192_EXT_PATCH_ + ieee->current_network.channel = backup_channel_wlan; + ieee->current_mesh_network.channel = backup_channel_mesh; +#endif + + if (ieee->state == RTLLIB_LINKED && ieee->iw_mode == IW_MODE_INFRA) { + ieee->set_chan(ieee->dev, ieee->current_network.channel); + + queue_work_rsl(ieee->wq, &ieee->associate_complete_wq); + + } else if (ieee->state == RTLLIB_LINKED && ieee->iw_mode == IW_MODE_ADHOC) { + ieee->set_chan(ieee->dev, ieee->current_network.channel); + ieee->link_change(ieee->dev); + + notify_wx_assoc_event(ieee); + + rtllib_start_send_beacons(ieee); + + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + netif_carrier_on(ieee->dev); + } else if (ieee->iw_mode == IW_MODE_MESH) { + rtl819x_silentreset_mesh_bk(dev, IsPortal); + } + +#ifdef _RTL8192_EXT_PATCH_ + if(wlansilentreset){ + printk("==========>wlansilentreset\n"); + CamRestoreEachIFEntry(dev,0); + } + if(meshsilentreset){ + printk("==========>meshsilentreset\n"); + CamRestoreEachIFEntry(dev,1); + for(i=0;i<8;i++) + { + if(ieee->swmeshratrtable[i].bused == true) + { + printk("====>restore ratr table: index=%d,value=%x\n",i,ieee->swmeshratrtable[i].ratr_value); +#ifdef RTL8192SE + write_nic_dword(dev,ARFR0+i*4,ieee->swmeshratrtable[i].ratr_value); +#elif defined Rtl8192CE + write_nic_dword(dev,REG_ARFR0+i*4,ieee->swmeshratrtable[i].ratr_value); +#endif + } + } + } +#else + CamRestoreAllEntry(dev); +#endif +#if !(defined RTL8192SE || defined RTL8192CE) + dm_restore_dynamic_mechanism_state(dev); +#endif +END: + priv->ResetProgress = RESET_TYPE_NORESET; + priv->reset_count++; + + priv->bForcedSilentReset =false; + priv->bResetInProgress = false; + +#if !(defined RTL8192SE || defined RTL8192CE) + write_nic_byte(dev, UFWP, 1); +#endif + RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n", priv->reset_count); + } +} + +void rtl819x_update_rxcounts(struct r8192_priv *priv, + u32 *TotalRxBcnNum, + u32 *TotalRxDataNum) +{ + u16 SlotIndex; + u8 i; + + *TotalRxBcnNum = 0; + *TotalRxDataNum = 0; + + SlotIndex = (priv->rtllib->LinkDetectInfo.SlotIndex++)%(priv->rtllib->LinkDetectInfo.SlotNum); + priv->rtllib->LinkDetectInfo.RxBcnNum[SlotIndex] = priv->rtllib->LinkDetectInfo.NumRecvBcnInPeriod; + priv->rtllib->LinkDetectInfo.RxDataNum[SlotIndex] = priv->rtllib->LinkDetectInfo.NumRecvDataInPeriod; + for (i = 0; i < priv->rtllib->LinkDetectInfo.SlotNum; i++) { + *TotalRxBcnNum += priv->rtllib->LinkDetectInfo.RxBcnNum[i]; + *TotalRxDataNum += priv->rtllib->LinkDetectInfo.RxDataNum[i]; + } +} + + +void rtl819x_watchdog_wqcallback(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,watch_dog_wq); + struct net_device *dev = priv->rtllib->dev; +#else + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = rtllib_priv(dev); +#endif + struct rtllib_device* ieee = priv->rtllib; + RESET_TYPE ResetType = RESET_TYPE_NORESET; + static u8 check_reset_cnt = 0; +#ifdef _RTL8192_EXT_PATCH_ + static u8 last_reset_count = 0; +#endif + unsigned long flags; + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + bool bBusyTraffic = false; + bool bHigherBusyTraffic = false; + bool bHigherBusyRxTraffic = false; +#ifdef ENABLE_LPS + bool bEnterPS = false; +#endif + if(IS_NIC_DOWN(priv) || (priv->bHwRadioOff == true)) + return; + + if(priv->rtllib->state >= RTLLIB_LINKED) + { + if(priv->rtllib->CntAfterLink<2) + priv->rtllib->CntAfterLink++; + } + else + { + priv->rtllib->CntAfterLink = 0; + } + + hal_dm_watchdog(dev); + +#ifdef ENABLE_IPS + if(rtllib_act_scanning(priv->rtllib,false) == false){ + if((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == RTLLIB_NOLINK) &&\ + (ieee->eRFPowerState == eRfOn)&&!ieee->is_set_key &&\ + (!ieee->proto_stoppping) && !ieee->wx_set_enc +#ifdef CONFIG_RTLWIFI_DEBUGFS + && (!priv->debug->hw_holding) +#endif + ){ + if((ieee->PowerSaveControl.ReturnPoint == IPS_CALLBACK_NONE)&& + (!ieee->bNetPromiscuousMode)) + { + RT_TRACE(COMP_PS, "====================>haha:IPSEnter()\n"); + IPSEnter(dev); + } + } + } +#endif +#ifdef _RTL8192_EXT_PATCH_ + if((ieee->iw_mode == IW_MODE_INFRA) || (ieee->iw_mode == IW_MODE_MESH && ieee->only_mesh == 0)) + MgntLinkKeepAlive(priv); +#endif + { + if((ieee->state == RTLLIB_LINKED) && (ieee->iw_mode == IW_MODE_INFRA) && (!ieee->bNetPromiscuousMode)) + { + if( ieee->LinkDetectInfo.NumRxOkInPeriod> 100 || + ieee->LinkDetectInfo.NumTxOkInPeriod> 100 ) { + bBusyTraffic = true; + } + + + if( ieee->LinkDetectInfo.NumRxOkInPeriod > 4000 || + ieee->LinkDetectInfo.NumTxOkInPeriod > 4000 ) + { + bHigherBusyTraffic = true; + if(ieee->LinkDetectInfo.NumRxOkInPeriod > 5000) + bHigherBusyRxTraffic = true; + else + bHigherBusyRxTraffic = false; + } + +#ifdef ENABLE_LPS + if( ((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod + ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) || + (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) ) + { + bEnterPS= false; + } + else + { + bEnterPS= true; + } + + if (ieee->current_network.beacon_interval < 95) + bEnterPS= false; + + if(bEnterPS) + { + LeisurePSEnter(dev); + } + else + { + LeisurePSLeave(dev); + } +#endif + + } + else + { +#ifdef ENABLE_LPS + RT_TRACE(COMP_LPS,"====>no link LPS leave\n"); + LeisurePSLeave(dev); +#endif + } + + ieee->LinkDetectInfo.NumRxOkInPeriod = 0; + ieee->LinkDetectInfo.NumTxOkInPeriod = 0; + ieee->LinkDetectInfo.NumRxUnicastOkInPeriod = 0; + ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic; + + ieee->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic; + ieee->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic; + + } + + { +#if defined RTL8192SE + if(priv->rtllib->iw_mode == IW_MODE_ADHOC) + IbssAgeFunction(ieee); +#endif + + if(ieee->state == RTLLIB_LINKED && ieee->iw_mode == IW_MODE_INFRA) + { + u32 TotalRxBcnNum = 0; + u32 TotalRxDataNum = 0; + + rtl819x_update_rxcounts(priv, &TotalRxBcnNum, &TotalRxDataNum); + + if((TotalRxBcnNum+TotalRxDataNum) == 0) + priv->check_roaming_cnt ++; + else + priv->check_roaming_cnt = 0; + + + if(priv->check_roaming_cnt > 0) + { + if( ieee->eRFPowerState == eRfOff) + RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__); + + printk("===>%s(): AP is power off,chan:%d, connect another one\n",__FUNCTION__, priv->chan); + + ieee->state = RTLLIB_ASSOCIATING; + +#if defined(RTL8192S_WAPI_SUPPORT) + if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)) + WapiReturnOneStaInfo(ieee,priv->rtllib->current_network.bssid,0); +#endif + RemovePeerTS(priv->rtllib,priv->rtllib->current_network.bssid); + ieee->is_roaming = true; + ieee->is_set_key = false; + ieee->link_change(dev); + if(ieee->LedControlHandler) + ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK); + + notify_wx_assoc_event(ieee); + + if(!(ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_CCMP|SEC_ALG_TKIP))) + queue_delayed_work_rsl(ieee->wq, &ieee->associate_procedure_wq, 0); + + priv->check_roaming_cnt = 0; + } + } + ieee->LinkDetectInfo.NumRecvBcnInPeriod=0; + ieee->LinkDetectInfo.NumRecvDataInPeriod=0; + + } + + spin_lock_irqsave(&priv->tx_lock,flags); + if((check_reset_cnt++ >= 3) && (!ieee->is_roaming) && + (!priv->RFChangeInProgress) && (!pPSC->bSwRfProcessing)) + { + ResetType = rtl819x_ifcheck_resetornot(dev); +#ifdef _RTL8192_EXT_PATCH_ + if(check_reset_cnt == 0xFF) +#endif + check_reset_cnt = 3; + } + spin_unlock_irqrestore(&priv->tx_lock,flags); + + if(!priv->bDisableNormalResetCheck && ResetType == RESET_TYPE_NORMAL) + { + priv->ResetProgress = RESET_TYPE_NORMAL; + RT_TRACE(COMP_RESET,"%s(): NOMAL RESET\n",__FUNCTION__); + return; + } + +#ifdef _RTL8192_EXT_PATCH_ + if( ((priv->force_reset) || (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT))) + { + if((check_reset_cnt != (last_reset_count + 1)) && !priv->force_reset){ + printk("=======================>%s: Resume firmware\n", __FUNCTION__); +#ifdef RTL8192SE + r8192se_resume_firm(dev); +#elif defined Rtl8192CE +#endif + last_reset_count = check_reset_cnt; + }else{ + printk("=======================>%s: Silent Reset\n", __FUNCTION__); + rtl819x_ifsilentreset(dev); + } + } +#else + if( ((priv->force_reset) || (!priv->bDisableNormalResetCheck && ResetType==RESET_TYPE_SILENT))) + { + rtl819x_ifsilentreset(dev); + } +#endif + priv->force_reset = false; + priv->bForcedSilentReset = false; + priv->bResetInProgress = false; + RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n"); + +} + +void watch_dog_timer_callback(unsigned long data) +{ + struct r8192_priv *priv = rtllib_priv((struct net_device *) data); + queue_delayed_work_rsl(priv->priv_wq,&priv->watch_dog_wq,0); + mod_timer(&priv->watch_dog_timer, jiffies + MSECS(RTLLIB_WATCH_DOG_TIME)); +} + +/**************************************************************************** + ---------------------------- NIC TX/RX STUFF--------------------------- +*****************************************************************************/ +void rtl8192_rx_enable(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + priv->ops->rx_enable(dev); +} + +void rtl8192_tx_enable(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + priv->ops->tx_enable(dev); + + rtllib_reset_queue(priv->rtllib); +} + + +static void rtl8192_free_rx_ring(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int i,rx_queue_idx; + + for(rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx ++){ + for (i = 0; i < priv->rxringcount; i++) { + struct sk_buff *skb = priv->rx_buf[rx_queue_idx][i]; + if (!skb) + continue; + + pci_unmap_single(priv->pdev, + *((dma_addr_t *)skb->cb), + priv->rxbuffersize, PCI_DMA_FROMDEVICE); + kfree_skb(skb); + } + + pci_free_consistent(priv->pdev, sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount, + priv->rx_ring[rx_queue_idx], priv->rx_ring_dma[rx_queue_idx]); + priv->rx_ring[rx_queue_idx] = NULL; + } +} + +static void rtl8192_free_tx_ring(struct net_device *dev, unsigned int prio) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtl8192_tx_ring *ring = &priv->tx_ring[prio]; + + while (skb_queue_len(&ring->queue)) { + tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb = __skb_dequeue(&ring->queue); + + pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr), + skb->len, PCI_DMA_TODEVICE); + kfree_skb(skb); + ring->idx = (ring->idx + 1) % ring->entries; + } + + pci_free_consistent(priv->pdev, sizeof(*ring->desc)*ring->entries, + ring->desc, ring->dma); + ring->desc = NULL; +} + +void rtl8192_data_hard_stop(struct net_device *dev) +{ + #if 0 + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + priv->dma_poll_mask |= (1<dma_poll_mask); + rtl8192_set_mode(dev,EPROM_CMD_NORMAL); + #endif +} + + +void rtl8192_data_hard_resume(struct net_device *dev) +{ + #if 0 + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + priv->dma_poll_mask &= ~(1<dma_poll_mask); + rtl8192_set_mode(dev,EPROM_CMD_NORMAL); + #endif +} + +void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + int ret; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + u8 queue_index = tcb_desc->queue_index; + + if((priv->rtllib->eRFPowerState == eRfOff) || IS_NIC_DOWN(priv) || priv->bResetInProgress){ + kfree_skb(skb); + return; + } + + assert(queue_index != TXCMD_QUEUE); + + + memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); +#if 0 + tcb_desc->RATRIndex = 7; + tcb_desc->bTxDisableRateFallBack = 1; + tcb_desc->bTxUseDriverAssingedRate = 1; + tcb_desc->bTxEnableFwCalcDur = 1; +#endif + skb_push(skb, priv->rtllib->tx_headroom); + ret = rtl8192_tx(dev, skb); + if(ret != 0) { + kfree_skb(skb); + }; + + if(queue_index!=MGNT_QUEUE) { + priv->rtllib->stats.tx_bytes+=(skb->len - priv->rtllib->tx_headroom); + priv->rtllib->stats.tx_packets++; + } + + + return; +} + +int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + int ret; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + u8 queue_index = tcb_desc->queue_index; + + if(queue_index != TXCMD_QUEUE){ + if((priv->rtllib->eRFPowerState == eRfOff) ||IS_NIC_DOWN(priv) || priv->bResetInProgress){ + printk("=====>%s() retrun :%d:%d:%d\n", __func__, (priv->rtllib->eRFPowerState == eRfOff), IS_NIC_DOWN(priv), priv->bResetInProgress); + kfree_skb(skb); + return 0; + } + } + + memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); + if(queue_index == TXCMD_QUEUE) { + rtl8192_tx_cmd(dev, skb); + ret = 0; + return ret; + } else { + tcb_desc->RATRIndex = 7; + tcb_desc->bTxDisableRateFallBack = 1; + tcb_desc->bTxUseDriverAssingedRate = 1; + tcb_desc->bTxEnableFwCalcDur = 1; + skb_push(skb, priv->rtllib->tx_headroom); + ret = rtl8192_tx(dev, skb); + if(ret != 0) { + kfree_skb(skb); + }; + } + + + + return ret; + +} + +void rtl8192_tx_isr(struct net_device *dev, int prio) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + struct rtl8192_tx_ring *ring = &priv->tx_ring[prio]; + + while (skb_queue_len(&ring->queue)) { + tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb; + + if(prio != BEACON_QUEUE) { + if(entry->OWN) + return; + ring->idx = (ring->idx + 1) % ring->entries; + } + + skb = __skb_dequeue(&ring->queue); + pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr), + skb->len, PCI_DMA_TODEVICE); + + kfree_skb(skb); + } + if(prio != BEACON_QUEUE) { + tasklet_schedule(&priv->irq_tx_tasklet); + } + +} + +void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtl8192_tx_ring *ring; + tx_desc_cmd* entry; + unsigned int idx; + cb_desc *tcb_desc; + unsigned long flags; + + spin_lock_irqsave(&priv->irq_th_lock,flags); + ring = &priv->tx_ring[TXCMD_QUEUE]; + + idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; + entry = (tx_desc_cmd*) &ring->desc[idx]; + + tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + + priv->ops->tx_fill_cmd_descriptor(dev, entry, tcb_desc, skb); + + __skb_queue_tail(&ring->queue, skb); + spin_unlock_irqrestore(&priv->irq_th_lock,flags); + + return; +} + +short rtl8192_tx(struct net_device *dev, struct sk_buff* skb) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtl8192_tx_ring *ring; + unsigned long flags; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + tx_desc *pdesc = NULL; + struct rtllib_hdr_1addr * header = NULL; + u16 fc=0, type=0,stype=0; + bool multi_addr=false,broad_addr=false,uni_addr=false; + u8* pda_addr = NULL; + int idx; + u32 fwinfo_size = 0; + + if(priv->bdisable_nic){ + RT_TRACE(COMP_ERR,"%s: ERR!! Nic is disabled! Can't tx packet len=%d qidx=%d!!!\n", __FUNCTION__, skb->len, tcb_desc->queue_index); + return skb->len; + } + + priv->rtllib->bAwakePktSent = true; + +#if defined RTL8192SE || defined RTL8192CE + fwinfo_size = 0; +#else + fwinfo_size = sizeof(TX_FWINFO_8190PCI); +#endif + + header = (struct rtllib_hdr_1addr *)(((u8*)skb->data) + fwinfo_size); + fc = header->frame_ctl; + type = WLAN_FC_GET_TYPE(fc); + stype = WLAN_FC_GET_STYPE(fc); + pda_addr = header->addr1; + + if(is_multicast_ether_addr(pda_addr)) + multi_addr = true; + else if(is_broadcast_ether_addr(pda_addr)) + broad_addr = true; + else { + uni_addr = true; + } + + if(uni_addr) + priv->stats.txbytesunicast += skb->len - fwinfo_size; + else if(multi_addr) + priv->stats.txbytesmulticast += skb->len - fwinfo_size; + else + priv->stats.txbytesbroadcast += skb->len - fwinfo_size; + + spin_lock_irqsave(&priv->irq_th_lock,flags); + ring = &priv->tx_ring[tcb_desc->queue_index]; + if (tcb_desc->queue_index != BEACON_QUEUE) { + idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; + } else { +#ifdef _ENABLE_SW_BEACON + idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; +#else + idx = 0; +#endif + } + + pdesc = &ring->desc[idx]; + if((pdesc->OWN == 1) && (tcb_desc->queue_index != BEACON_QUEUE)) { + RT_TRACE(COMP_ERR,"No more TX desc@%d, ring->idx = %d,idx = %d, skblen = 0x%x queuelen=%d", \ + tcb_desc->queue_index,ring->idx, idx,skb->len, skb_queue_len(&ring->queue)); + spin_unlock_irqrestore(&priv->irq_th_lock,flags); + return skb->len; + } + + if(tcb_desc->queue_index == MGNT_QUEUE){ + } + + if(type == RTLLIB_FTYPE_DATA){ + if(priv->rtllib->LedControlHandler) + priv->rtllib->LedControlHandler(dev, LED_CTL_TX); + } + priv->ops->tx_fill_descriptor(dev, pdesc, tcb_desc, skb); + __skb_queue_tail(&ring->queue, skb); + pdesc->OWN = 1; + spin_unlock_irqrestore(&priv->irq_th_lock,flags); + dev->trans_start = jiffies; + +#ifdef RTL8192CE + if(tcb_desc->queue_index == BEACON_QUEUE){ + write_nic_word(dev, REG_PCIE_CTRL_REG, BIT4); + }else{ + write_nic_word(dev, REG_PCIE_CTRL_REG, BIT0<<(tcb_desc->queue_index)); + } +#else + write_nic_word(dev,TPPoll,0x01<queue_index); +#endif + return 0; +} + +short rtl8192_alloc_rx_desc_ring(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + rx_desc *entry = NULL; + int i, rx_queue_idx; + + for(rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx ++){ + priv->rx_ring[rx_queue_idx] = pci_alloc_consistent(priv->pdev, + sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount, &priv->rx_ring_dma[rx_queue_idx]); + + if (!priv->rx_ring[rx_queue_idx] || (unsigned long)priv->rx_ring[rx_queue_idx] & 0xFF) { + RT_TRACE(COMP_ERR,"Cannot allocate RX ring\n"); + return -ENOMEM; + } + + memset(priv->rx_ring[rx_queue_idx], 0, sizeof(*priv->rx_ring[rx_queue_idx]) * priv->rxringcount); + priv->rx_idx[rx_queue_idx] = 0; + + for (i = 0; i < priv->rxringcount; i++) { + struct sk_buff *skb = dev_alloc_skb(priv->rxbuffersize); + dma_addr_t *mapping; + entry = &priv->rx_ring[rx_queue_idx][i]; + if (!skb) + return 0; + skb->dev = dev; + priv->rx_buf[rx_queue_idx][i] = skb; + mapping = (dma_addr_t *)skb->cb; + *mapping = pci_map_single(priv->pdev, skb_tail_pointer_rsl(skb), + priv->rxbuffersize, PCI_DMA_FROMDEVICE); + + entry->BufferAddress = cpu_to_le32(*mapping); + + entry->Length = priv->rxbuffersize; + entry->OWN = 1; + } + + entry->EOR = 1; + } + return 0; +} + +static int rtl8192_alloc_tx_desc_ring(struct net_device *dev, + unsigned int prio, unsigned int entries) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + tx_desc *ring; + dma_addr_t dma; + int i; + + ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma); + if (!ring || (unsigned long)ring & 0xFF) { + RT_TRACE(COMP_ERR, "Cannot allocate TX ring (prio = %d)\n", prio); + return -ENOMEM; + } + + memset(ring, 0, sizeof(*ring)*entries); + priv->tx_ring[prio].desc = ring; + priv->tx_ring[prio].dma = dma; + priv->tx_ring[prio].idx = 0; + priv->tx_ring[prio].entries = entries; + skb_queue_head_init(&priv->tx_ring[prio].queue); + + for (i = 0; i < entries; i++) + ring[i].NextDescAddress = + cpu_to_le32((u32)dma + ((i + 1) % entries) * sizeof(*ring)); + + return 0; +} + + +short rtl8192_pci_initdescring(struct net_device *dev) +{ + u32 ret; + int i; + struct r8192_priv *priv = rtllib_priv(dev); + + ret = rtl8192_alloc_rx_desc_ring(dev); + if (ret) { + return ret; + } + + + for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) { + if ((ret = rtl8192_alloc_tx_desc_ring(dev, i, priv->txringcount))) + goto err_free_rings; + } + +#if 0 + if ((ret = rtl8192_alloc_tx_desc_ring(dev, MAX_TX_QUEUE_COUNT - 1, 2))) + goto err_free_rings; +#endif + + return 0; + +err_free_rings: + rtl8192_free_rx_ring(dev); + for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) + if (priv->tx_ring[i].desc) + rtl8192_free_tx_ring(dev, i); + return 1; +} + +void rtl8192_pci_resetdescring(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int i,rx_queue_idx; + unsigned long flags = 0; + + for(rx_queue_idx = 0; rx_queue_idx < MAX_RX_QUEUE; rx_queue_idx ++){ + if(priv->rx_ring[rx_queue_idx]) { + rx_desc *entry = NULL; + for (i = 0; i < priv->rxringcount; i++) { + entry = &priv->rx_ring[rx_queue_idx][i]; + entry->OWN = 1; + } + priv->rx_idx[rx_queue_idx] = 0; + } + } + + spin_lock_irqsave(&priv->irq_th_lock,flags); + for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) { + if (priv->tx_ring[i].desc) { + struct rtl8192_tx_ring *ring = &priv->tx_ring[i]; + + while (skb_queue_len(&ring->queue)) { + tx_desc *entry = &ring->desc[ring->idx]; + struct sk_buff *skb = __skb_dequeue(&ring->queue); + + pci_unmap_single(priv->pdev, le32_to_cpu(entry->TxBuffAddr), + skb->len, PCI_DMA_TODEVICE); + kfree_skb(skb); + ring->idx = (ring->idx + 1) % ring->entries; + } + ring->idx = 0; + } + } + spin_unlock_irqrestore(&priv->irq_th_lock,flags); +} + +void rtl819x_UpdateRxPktTimeStamp (struct net_device *dev, struct rtllib_rx_stats *stats) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + if(stats->bIsAMPDU && !stats->bFirstMPDU) { + stats->mac_time[0] = priv->LastRxDescTSFLow; + stats->mac_time[1] = priv->LastRxDescTSFHigh; + } else { + priv->LastRxDescTSFLow = stats->mac_time[0]; + priv->LastRxDescTSFHigh = stats->mac_time[1]; + } +} + +long rtl819x_translate_todbm(struct r8192_priv * priv, u8 signal_strength_index ) +{ + long signal_power; + +#ifdef _RTL8192_EXT_PATCH_ + if(priv->CustomerID == RT_CID_819x_Lenovo) + { + signal_power = (long)signal_strength_index; + if(signal_power >= 45) + signal_power -= 110; + else + { + signal_power = ((signal_power*6)/10); + signal_power -= 93; + } + return signal_power; + } +#endif + signal_power = (long)((signal_strength_index + 1) >> 1); + signal_power -= 95; + + return signal_power; +} + + +void +rtl819x_update_rxsignalstatistics8190pci( + struct r8192_priv * priv, + struct rtllib_rx_stats * pprevious_stats + ) +{ + int weighting = 0; + + + if(priv->stats.recv_signal_power == 0) + priv->stats.recv_signal_power = pprevious_stats->RecvSignalPower; + + if(pprevious_stats->RecvSignalPower > priv->stats.recv_signal_power) + weighting = 5; + else if(pprevious_stats->RecvSignalPower < priv->stats.recv_signal_power) + weighting = (-5); + priv->stats.recv_signal_power = (priv->stats.recv_signal_power * 5 + pprevious_stats->RecvSignalPower + weighting) / 6; +} + +void +rtl819x_process_cck_rxpathsel( + struct r8192_priv * priv, + struct rtllib_rx_stats * pprevious_stats + ) +{ +#ifdef RTL8190P + char last_cck_adc_pwdb[4]={0,0,0,0}; + u8 i; + if(priv->rf_type == RF_2T4R && DM_RxPathSelTable.Enable) + { + if(pprevious_stats->bIsCCK && + (pprevious_stats->bPacketToSelf ||pprevious_stats->bPacketBeacon)) + { + if(priv->stats.cck_adc_pwdb.TotalNum++ >= PHY_RSSI_SLID_WIN_MAX) + { + priv->stats.cck_adc_pwdb.TotalNum = PHY_RSSI_SLID_WIN_MAX; + for(i=RF90_PATH_A; istats.cck_adc_pwdb.elements[i][priv->stats.cck_adc_pwdb.index]; + priv->stats.cck_adc_pwdb.TotalVal[i] -= last_cck_adc_pwdb[i]; + } + } + for(i=RF90_PATH_A; istats.cck_adc_pwdb.TotalVal[i] += pprevious_stats->cck_adc_pwdb[i]; + priv->stats.cck_adc_pwdb.elements[i][priv->stats.cck_adc_pwdb.index] = pprevious_stats->cck_adc_pwdb[i]; + } + priv->stats.cck_adc_pwdb.index++; + if(priv->stats.cck_adc_pwdb.index >= PHY_RSSI_SLID_WIN_MAX) + priv->stats.cck_adc_pwdb.index = 0; + + for(i=RF90_PATH_A; istats.cck_adc_pwdb.TotalVal[i]/priv->stats.cck_adc_pwdb.TotalNum; + } + + for(i=RF90_PATH_A; icck_adc_pwdb[i] > (char)priv->undecorated_smoothed_cck_adc_pwdb[i]) + { + priv->undecorated_smoothed_cck_adc_pwdb[i] = + ( (priv->undecorated_smoothed_cck_adc_pwdb[i]*(Rx_Smooth_Factor-1)) + + (pprevious_stats->cck_adc_pwdb[i])) /(Rx_Smooth_Factor); + priv->undecorated_smoothed_cck_adc_pwdb[i] = priv->undecorated_smoothed_cck_adc_pwdb[i] + 1; + } + else + { + priv->undecorated_smoothed_cck_adc_pwdb[i] = + ( (priv->undecorated_smoothed_cck_adc_pwdb[i]*(Rx_Smooth_Factor-1)) + + (pprevious_stats->cck_adc_pwdb[i])) /(Rx_Smooth_Factor); + } + } + } + } +#endif +} + + +u8 rtl819x_query_rxpwrpercentage( + char antpower + ) +{ + if ((antpower <= -100) || (antpower >= 20)) + { + return 0; + } + else if (antpower >= 0) + { + return 100; + } + else + { + return (100+antpower); + } + +} /* QueryRxPwrPercentage */ + +u8 +rtl819x_evm_dbtopercentage( + char value + ) +{ + char ret_val; + + ret_val = value; + + if(ret_val >= 0) + ret_val = 0; + if(ret_val <= -33) + ret_val = -33; + ret_val = 0 - ret_val; + ret_val*=3; + if(ret_val == 99) + ret_val = 100; + return(ret_val); +} + +void +rtl8192_record_rxdesc_forlateruse( + struct rtllib_rx_stats * psrc_stats, + struct rtllib_rx_stats * ptarget_stats +) +{ + ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU; + ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU; +} + + + +void rtl8192_rx_normal(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct rtllib_hdr_1addr *rtllib_hdr = NULL; + bool unicast_packet = false; + bool bLedBlinking=true; + u16 fc=0, type=0; + u32 skb_len = 0; + int rx_queue_idx = RX_MPDU_QUEUE; + + struct rtllib_rx_stats stats = { + .signal = 0, + .noise = -98, + .rate = 0, + .freq = RTLLIB_24GHZ_BAND, + }; + unsigned int count = priv->rxringcount; + + stats.nic_type = NIC_8192E; + + while (count--) { + rx_desc *pdesc = &priv->rx_ring[rx_queue_idx][priv->rx_idx[rx_queue_idx]]; + struct sk_buff *skb = priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]]; + + if (pdesc->OWN){ + return; + } else { + + struct sk_buff *new_skb = NULL; + if (!priv->ops->rx_query_status_descriptor(dev, &stats, pdesc, skb)) + goto done; + + pci_unmap_single(priv->pdev, + *((dma_addr_t *)skb->cb), + priv->rxbuffersize, + PCI_DMA_FROMDEVICE); + + skb_put(skb, pdesc->Length); + skb_reserve(skb, stats.RxDrvInfoSize + stats.RxBufShift); + skb_trim(skb, skb->len - 4/*sCrcLng*/); + rtllib_hdr = (struct rtllib_hdr_1addr *)skb->data; + if(is_broadcast_ether_addr(rtllib_hdr->addr1)) { + }else if(is_multicast_ether_addr(rtllib_hdr->addr1)){ + }else { + /* unicast packet */ + unicast_packet = true; + } + fc = le16_to_cpu(rtllib_hdr->frame_ctl); + type = WLAN_FC_GET_TYPE(fc); + if(type == RTLLIB_FTYPE_MGMT) + { + bLedBlinking = false; + } + if(bLedBlinking) + if(priv->rtllib->LedControlHandler) + priv->rtllib->LedControlHandler(dev, LED_CTL_RX); + + if(stats.bCRC) { + if(type != RTLLIB_FTYPE_MGMT) + priv->stats.rxdatacrcerr ++; + else + priv->stats.rxmgmtcrcerr ++; + } + + skb_len = skb->len; + +#ifdef RTL8192CE + if (!stats.bCRC) +#else + if (1) +#endif + { + if(!rtllib_rx(priv->rtllib, skb, &stats)){ + dev_kfree_skb_any(skb); + skb = NULL; + } else { + priv->stats.rxok++; + if(unicast_packet) { + priv->stats.rxbytesunicast += skb_len; + } + } + }else{ + dev_kfree_skb_any(skb); + skb = NULL; + } +#if 1 + new_skb = dev_alloc_skb(priv->rxbuffersize); + if (unlikely(!new_skb)) + { + printk("==========>can't alloc skb for rx\n"); + goto done; + } + skb=new_skb; + skb->dev = dev; +#endif + priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]] = skb; + *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer_rsl(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE); + + } +done: + pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); + pdesc->OWN = 1; + pdesc->Length = priv->rxbuffersize; + if (priv->rx_idx[rx_queue_idx] == priv->rxringcount-1) + pdesc->EOR = 1; + priv->rx_idx[rx_queue_idx] = (priv->rx_idx[rx_queue_idx] + 1) % priv->rxringcount; + } + +} + +void rtl8192_rx_cmd(struct net_device *dev) +{ +#ifdef RTL8192SE + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + unsigned int count = priv->rxringcount; + int rx_queue_idx = RX_CMD_QUEUE; + + struct rtllib_rx_stats stats = { + .signal = 0, + .noise = -98, + .rate = 0, + .freq = RTLLIB_24GHZ_BAND, + }; + stats.nic_type = NIC_8192E; + + while (count--) { + rx_desc *pdesc = &priv->rx_ring[rx_queue_idx][priv->rx_idx[rx_queue_idx]]; + struct sk_buff *skb = priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]]; + + if (pdesc->OWN){ + return; + } else { + struct sk_buff *new_skb = NULL; + + pci_unmap_single(priv->pdev, + *((dma_addr_t *)skb->cb), + priv->rxbuffersize, + PCI_DMA_FROMDEVICE); + + skb_put(skb, pdesc->Length); + + if(pdesc->MACID == 0x1e){ + + pdesc->Length = pdesc->Length - 32; + pdesc->DrvInfoSize = 4; + printk(">>>>%s()CMD PKT RX, beacon_len:%d payload_len:%d\n",__func__, pdesc->Length,skb->len); + + + priv->ops->rx_query_status_descriptor(dev, &stats, pdesc, skb); + skb_reserve(skb, stats.RxDrvInfoSize + stats.RxBufShift); + if(0) + { + u8 i = 0; + u8 *arry = (u8*) skb->data; + + printk("\n==============>\n"); + for(i = 0; i < 32; i ++){ + if((i % 4 == 0)&&(i != 0)) + printk("\n"); + printk("%2.2x ", arry[i]); + } + printk("\n<==============\n"); + } + } + + skb_trim(skb, skb->len - 4/*sCrcLng*/); + + if(pdesc->MACID == 0x1e){ + if(!rtllib_rx(priv->rtllib, skb, &stats)){ + dev_kfree_skb_any(skb); + skb = NULL; + } + }else{ + if(priv->ops->rx_command_packet_handler != NULL) + priv->ops->rx_command_packet_handler(dev, skb, pdesc); + dev_kfree_skb_any(skb); + skb = NULL; + } + + + new_skb = dev_alloc_skb(priv->rxbuffersize); + if (unlikely(!new_skb)) + { + printk("==========>can't alloc skb for rx\n"); + goto done; + } + skb=new_skb; + skb->dev = dev; + + priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]] = skb; + *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer_rsl(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE); + + } +done: + pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); + pdesc->OWN = 1; + pdesc->Length = priv->rxbuffersize; + if (priv->rx_idx[rx_queue_idx] == priv->rxringcount-1) + pdesc->EOR = 1; + priv->rx_idx[rx_queue_idx] = (priv->rx_idx[rx_queue_idx] + 1) % priv->rxringcount; + } +#endif +} + + +void rtl8192_tx_resume(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + struct sk_buff *skb; + int queue_index; + + for(queue_index = BK_QUEUE; queue_index < MAX_QUEUE_SIZE;queue_index++) { + while((!skb_queue_empty(&ieee->skb_waitQ[queue_index]))&& + (priv->rtllib->check_nic_enough_desc(dev,queue_index) > 0)) { + skb = skb_dequeue(&ieee->skb_waitQ[queue_index]); + ieee->softmac_data_hard_start_xmit(skb,dev,0/* rate useless now*/); + #if 0 + if(queue_index!=MGNT_QUEUE) { + ieee->stats.tx_packets++; + ieee->stats.tx_bytes += skb->len; + } + #endif + } +#ifdef ENABLE_AMSDU + while((skb_queue_len(&priv->rtllib->skb_aggQ[queue_index]) > 0)&&\ + (!(priv->rtllib->queue_stop)) && \ + (priv->rtllib->check_nic_enough_desc(dev,queue_index) > 0)){ + + struct sk_buff_head pSendList; + u8 dst[ETH_ALEN]; + cb_desc *tcb_desc = NULL; + int qos_actived = priv->rtllib->current_network.qos_data.active; + struct sta_info *psta = NULL; + u8 bIsSptAmsdu = false; + +#ifdef WIFI_TEST + if (queue_index <= VO_QUEUE) + queue_index = wmm_queue_select(priv, queue_index, priv->rtllib->skb_aggQ); +#endif + priv->rtllib->amsdu_in_process = true; + + skb = skb_dequeue(&(priv->rtllib->skb_aggQ[queue_index])); + if(skb == NULL) + { + printk("In %s:Skb is NULL\n",__FUNCTION__); + return; + } + tcb_desc = (pcb_desc)(skb->cb + MAX_DEV_ADDR_SIZE); + if(tcb_desc->bFromAggrQ) + { + rtllib_xmit_inter(skb, dev); + return; + } + + memcpy(dst, skb->data, ETH_ALEN); + if(priv->rtllib->iw_mode == IW_MODE_ADHOC) + { + psta = GetStaInfo(priv->rtllib, dst); + if(psta) { + if(psta->htinfo.bEnableHT) + bIsSptAmsdu = true; + } + } + else if(priv->rtllib->iw_mode == IW_MODE_INFRA) + bIsSptAmsdu = true; + else + bIsSptAmsdu = true; + bIsSptAmsdu = true; + + bIsSptAmsdu = bIsSptAmsdu && priv->rtllib->pHTInfo->bCurrent_AMSDU_Support && qos_actived; + + if(qos_actived && !is_broadcast_ether_addr(dst) && + !is_multicast_ether_addr(dst) && + bIsSptAmsdu) + { + skb_queue_head_init(&pSendList); + if(AMSDU_GetAggregatibleList(priv->rtllib, skb, &pSendList,queue_index)) + { + struct sk_buff * pAggrSkb = AMSDU_Aggregation(priv->rtllib, &pSendList); + if(NULL != pAggrSkb) + rtllib_xmit_inter(pAggrSkb, dev); + } + } + else + { + memset(skb->cb,0,sizeof(skb->cb)); + tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + tcb_desc->bFromAggrQ = true; + rtllib_xmit_inter(skb, dev); + } + } +#endif +#ifdef _RTL8192_EXT_PATCH_ + while((!skb_queue_empty(&priv->rtllib->skb_meshaggQ[queue_index]) )&&\ + (priv->rtllib->check_nic_enough_desc(dev,queue_index)> 0)) + { + u8 dst[ETH_ALEN]; + cb_desc *tcb_desc = NULL; + u8 IsHTEnable = false; +#ifdef ENABLE_AMSDU + struct sk_buff_head pSendList; + int qos_actived = 1; +#endif + priv->rtllib->mesh_amsdu_in_process = true; + skb = skb_dequeue(&(priv->rtllib->skb_meshaggQ[queue_index])); + if(skb == NULL) + { + priv->rtllib->mesh_amsdu_in_process = false; + printk("In %s:Skb is NULL\n",__FUNCTION__); + return; + } + tcb_desc = (pcb_desc)(skb->cb + MAX_DEV_ADDR_SIZE); + if(tcb_desc->bFromAggrQ) + { + rtllib_mesh_xmit(skb, dev); + continue; + } + memcpy(dst, skb->data, ETH_ALEN); + +#if 0 + ppeerMP_htinfo phtinfo = NULL; + bool is_mesh = false; + if(priv->mshobj->ext_patch_rtllib_is_mesh) + is_mesh = priv->mshobj->ext_patch_rtllib_is_mesh(priv->rtllib,dst); + if(is_mesh){ + if(priv->rtllib->ext_patch_rtllib_get_peermp_htinfo) + { + phtinfo = priv->rtllib->ext_patch_rtllib_get_peermp_htinfo(ieee,dst); + if(phtinfo == NULL) + { + RT_TRACE(COMP_ERR,"%s(): No htinfo\n",__FUNCTION__); + } + else + { + if(phtinfo->bEnableHT) + IsHTEnable = true; + } + } + } + else + { + printk("===>%s():tx AMSDU data has not entry,dst: "MAC_FMT"\n",__FUNCTION__,MAC_ARG(dst)); + IsHTEnable = true; + } +#else + IsHTEnable = true; +#endif +#ifdef ENABLE_AMSDU + IsHTEnable = (IsHTEnable && ieee->pHTInfo->bCurrent_Mesh_AMSDU_Support && qos_actived); + if( !is_broadcast_ether_addr(dst) && + !is_multicast_ether_addr(dst) && + IsHTEnable) + { + skb_queue_head_init(&pSendList); + if(msh_AMSDU_GetAggregatibleList(priv->rtllib, skb, &pSendList,queue_index)) + { + struct sk_buff * pAggrSkb = msh_AMSDU_Aggregation(priv->rtllib, &pSendList); + if(NULL != pAggrSkb) + rtllib_mesh_xmit(pAggrSkb, dev); + }else{ + priv->rtllib->mesh_amsdu_in_process = false; + return; + } + } + else +#endif + { + memset(skb->cb,0,sizeof(skb->cb)); + tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + tcb_desc->bFromAggrQ = true; + rtllib_mesh_xmit(skb, dev); + } + } +#endif + } +} + +void rtl8192_irq_tx_tasklet(struct r8192_priv *priv) +{ + rtl8192_tx_resume(priv->rtllib->dev); +} + +void rtl8192_irq_rx_tasklet(struct r8192_priv *priv) +{ + rtl8192_rx_normal(priv->rtllib->dev); + + if(MAX_RX_QUEUE > 1) + rtl8192_rx_cmd(priv->rtllib->dev); + +#ifndef RTL8192CE + write_nic_dword(priv->rtllib->dev, INTA_MASK,read_nic_dword(priv->rtllib->dev, INTA_MASK) | IMR_RDU); +#endif +} + +/**************************************************************************** + ---------------------------- NIC START/CLOSE STUFF--------------------------- +*****************************************************************************/ +void rtl8192_cancel_deferred_work(struct r8192_priv* priv) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + cancel_delayed_work(&priv->watch_dog_wq); + cancel_delayed_work(&priv->update_beacon_wq); +#ifndef RTL8190P + cancel_delayed_work(&priv->rtllib->hw_sleep_wq); +#endif +#if defined RTL8192SE + cancel_delayed_work(&priv->check_hw_scan_wq); + cancel_delayed_work(&priv->hw_scan_simu_wq); + cancel_delayed_work(&priv->start_hw_scan_wq); + cancel_delayed_work(&priv->rtllib->update_assoc_sta_info_wq); + cancel_delayed_work(&priv->rtllib->check_tsf_wq); +#endif +#endif + +#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,22) + cancel_work_sync(&priv->reset_wq); + cancel_work_sync(&priv->qos_activate); +#elif ((LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))) + cancel_delayed_work(&priv->reset_wq); + cancel_delayed_work(&priv->qos_activate); +#if defined RTL8192SE + cancel_delayed_work(&priv->rtllib->update_assoc_sta_info_wq); + cancel_delayed_work(&priv->rtllib->check_tsf_wq); +#endif +#endif + +} + +int _rtl8192_up(struct net_device *dev,bool is_silent_reset) +{ +#ifdef _RTL8192_EXT_PATCH_ + if(_rtl8192_mesh_up(dev, is_silent_reset) == -1) + return -1; +#else + if(_rtl8192_sta_up(dev, is_silent_reset) == -1) + return -1; +#endif + + return 0; +} + + +int rtl8192_open(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int ret; + + down(&priv->wx_sem); + ret = rtl8192_up(dev); + up(&priv->wx_sem); + return ret; + +} + + +int rtl8192_up(struct net_device *dev) +{ +#ifndef _RTL8192_EXT_PATCH_ + struct r8192_priv *priv = rtllib_priv(dev); + + if (priv->up == 1) return -1; + return _rtl8192_up(dev,false); +#else + return _rtl8192_up(dev,false); +#endif +} + + +int rtl8192_close(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int ret; + + if ((rtllib_act_scanning(priv->rtllib, false)) && + !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){ + rtllib_stop_scan(priv->rtllib); + } + + down(&priv->wx_sem); + + ret = rtl8192_down(dev,true); + + up(&priv->wx_sem); + + return ret; + +} + +int rtl8192_down(struct net_device *dev, bool shutdownrf) +{ +#ifdef CONFIG_MP + struct r8192_priv *priv = rtllib_priv(dev); +#endif + +#ifdef _RTL8192_EXT_PATCH_ + if(rtl8192_mesh_down(dev, shutdownrf) == -1) + return -1; +#else + if(rtl8192_sta_down(dev, shutdownrf) == -1) + return -1; +#endif + +#ifdef CONFIG_MP + if (priv->bCckContTx) { + printk("####RTL819X MP####stop single cck continious TX\n"); + mpt_StopCckCoNtTx(dev); + } + if (priv->bOfdmContTx) { + printk("####RTL819X MP####stop single ofdm continious TX\n"); + mpt_StopOfdmContTx(dev); + } + if (priv->bSingleCarrier) { + printk("####RTL819X MP####stop single carrier mode\n"); + MPT_ProSetSingleCarrier(dev, false); + } +#endif + return 0; +} + +void rtl8192_commit(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + +#ifdef _RTL8192_EXT_PATCH_ + if (IS_NIC_DOWN(priv)) + return ; + rtllib_softmac_stop_protocol(priv->rtllib,0,true); + rtl8192_irq_disable(dev); + priv->ops->stop_adapter(dev, true); + priv->up = 0; + _rtl8192_up(dev,false); +#else + if (priv->up == 0) return ; + rtllib_softmac_stop_protocol(priv->rtllib, 0 , true); + rtl8192_irq_disable(dev); + priv->ops->stop_adapter(dev, true); + _rtl8192_up(dev,false); +#endif + +} + +void rtl8192_restart(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv, reset_wq); + struct net_device *dev = priv->rtllib->dev; +#else + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = rtllib_priv(dev); +#endif + + down(&priv->wx_sem); + + rtl8192_commit(dev); + + up(&priv->wx_sem); +} + +static void r8192_set_multicast(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + short promisc; + + + + promisc = (dev->flags & IFF_PROMISC) ? 1:0; + + if (promisc != priv->promisc) { + ; + } + + priv->promisc = promisc; + +} + + +int r8192_set_mac_adr(struct net_device *dev, void *mac) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct sockaddr *addr = mac; + + down(&priv->wx_sem); + + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) + schedule_work(&priv->reset_wq); +#else + schedule_task(&priv->reset_wq); +#endif + up(&priv->wx_sem); + + return 0; +} + +#if defined (RTL8192S_WAPI_SUPPORT) +extern int wapi_ioctl_set_mode(struct net_device *dev, struct iw_request_info *a,union iwreq_data *wrqu, char *b); +int WAPI_Ioctl(struct net_device *dev, struct iwreq *wrq, int cmd) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + static u8 QueueData[WAPI_MAX_BUFF_LEN]; +#define DATAQUEUE_EMPTY "Queue is empty" + int ret = 0; + + switch(cmd){ + case WAPI_CMD_GET_WAPI_SUPPORT: + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_GET_WAPI_SUPPORT!\n",__FUNCTION__); + if(copy_to_user((u8 *)(wrq->u.data.pointer), &ieee->WapiSupport, sizeof(u8))==0) + wrq->u.data.length = sizeof(u8); + break; + case WAPI_CMD_SET_WAPI_ENABLE: + { + u8 wapi_enable = *(u8 *)wrq->u.data.pointer; + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_WAPI_ENABLE!\n",__FUNCTION__); + if((ieee->WapiSupport) && (wapi_enable == 1)){ + ieee->wapiInfo.bWapiEnable = true; + ieee->pairwise_key_type = KEY_TYPE_SMS4; + ieee->group_key_type = KEY_TYPE_SMS4; + ieee->wapiInfo.extra_prefix_len = WAPI_EXT_LEN; + ieee->wapiInfo.extra_postfix_len = SMS4_MIC_LEN; + } + else if (wapi_enable == 0) { + ieee->wapiInfo.bWapiEnable = false; + ieee->pairwise_key_type = KEY_TYPE_NA; + ieee->group_key_type = KEY_TYPE_NA; + } + break; + } + case WAPI_CMD_SET_WAPI_PSK: + { + u8 wapi_psk = *(u8 *)wrq->u.data.pointer; + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_WAPI_PSK!\n",__FUNCTION__); + if(ieee->wapiInfo.bWapiEnable){ + ieee->wapiInfo.bWapiPSK = (wapi_psk > 0)?1:0; + WAPI_TRACE(WAPI_API, "%s(): bWapiPSK=%d!\n",__FUNCTION__, ieee->wapiInfo.bWapiPSK); + } + break; + } + case WAPI_CMD_SET_KEY: + { /*Data: keyType(1) + bTxEnable(1) + bAuthenticator(1) + bUpdate(1) + PeerAddr(6) + DataKey(16) + MicKey(16) + KeyId(1)*/ + PRT_WAPI_T pWapiInfo = &ieee->wapiInfo; + PRT_WAPI_BKID pWapiBkid; + PRT_WAPI_STA_INFO pWapiSta; + u8 data[43]; + bool bTxEnable; + bool bUpdate; + bool bAuthenticator; + u8 PeerAddr[6]; + u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; + u8 WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; + u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; + + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_KEY!\n",__FUNCTION__); + if (!ieee->WapiSupport){ + ret = -1; + break; + } + if(wrq->u.data.length < 26){ + ret = -1; + break; + } + + copy_from_user(data, (u8 *)wrq->u.data.pointer, wrq->u.data.length); + bTxEnable = data[1]; + bAuthenticator = data[2]; + bUpdate = data[3]; + memcpy(PeerAddr,data+4,6); + + if(data[0] == 0x3){ + if(!list_empty(&(pWapiInfo->wapiBKIDIdleList))){ + pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID,list); + list_del_init(&pWapiBkid->list); + memcpy(pWapiBkid->bkid, data+10, 16); + list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDStoreList); + WAPI_DATA(WAPI_API, "SetKey - BKID", pWapiBkid->bkid, 16); + } + } else if (data[0] == 0x04){ + list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { + if(!memcmp(pWapiSta->PeerMacAddr,PeerAddr,6)){ + if(bUpdate){ + if(bAuthenticator) { + memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiAEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiAEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiAEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiAEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPN,WapiAEPNInitialValueSrc,16); + } else { + memcpy(pWapiSta->lastTxUnicastPN,WapiAEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16); + } + } + } + } + } + else{ + list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { + if(!memcmp(pWapiSta->PeerMacAddr,PeerAddr,6)){ + pWapiSta->bAuthenticatorInUpdata = false; + switch(data[0]){ + case 1: + if(bAuthenticator){ + memcpy(pWapiSta->lastTxUnicastPN,WapiAEPNInitialValueSrc,16); + if(!bUpdate) { + WAPI_TRACE(WAPI_API, "%s(): AE fisrt set usk!\n",__FUNCTION__); + pWapiSta->wapiUsk.bSet = true; + memcpy(pWapiSta->wapiUsk.dataKey,data+10,16); + memcpy(pWapiSta->wapiUsk.micKey,data+26,16); + pWapiSta->wapiUsk.keyId = *(data+42); + pWapiSta->wapiUsk.bTxEnable = true; + WAPI_DATA(WAPI_API, "SetKey - AE Usk Data Key", pWapiSta->wapiUsk.dataKey, 16); + WAPI_DATA(WAPI_API, "SetKey - AE Usk Mic Key", pWapiSta->wapiUsk.micKey, 16); + } + else + { + WAPI_TRACE(WAPI_API, "%s(): AE update usk!\n",__FUNCTION__); + pWapiSta->wapiUskUpdate.bSet = true; + pWapiSta->bAuthenticatorInUpdata = true; + memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16); + memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16); + memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16); + pWapiSta->wapiUskUpdate.keyId = *(data+42); + pWapiSta->wapiUskUpdate.bTxEnable = true; + WAPI_TRACE(WAPI_API, "%s(): keyid=%d\n",__FUNCTION__, pWapiSta->wapiUskUpdate.keyId); + WAPI_DATA(WAPI_API, "SetKey - AE Usk Data Key", pWapiSta->wapiUskUpdate.dataKey, 16); + WAPI_DATA(WAPI_API, "SetKey - AE Usk Mic Key", pWapiSta->wapiUskUpdate.micKey, 16); + } + } + else{ + if(!bUpdate){ + WAPI_TRACE(WAPI_API, "%s(): ASUE fisrt set usk!\n",__FUNCTION__); + if(bTxEnable){ + pWapiSta->wapiUsk.bTxEnable = true; + memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16); + WAPI_TRACE(WAPI_API, "%s(): Tx enable!\n",__FUNCTION__); + }else{ + pWapiSta->wapiUsk.bSet = true; + memcpy(pWapiSta->wapiUsk.dataKey,data+10,16); + memcpy(pWapiSta->wapiUsk.micKey,data+26,16); + pWapiSta->wapiUsk.keyId = *(data+42); + pWapiSta->wapiUsk.bTxEnable = false; + WAPI_TRACE(WAPI_API, "%s(): Tx disable!\n",__FUNCTION__); + WAPI_DATA(WAPI_API, "SetKey - AE Usk Data Key", pWapiSta->wapiUsk.dataKey, 16); + WAPI_DATA(WAPI_API, "SetKey - AE Usk Mic Key", pWapiSta->wapiUsk.micKey, 16); + } + }else{ + WAPI_TRACE(WAPI_API, "%s(): ASUE update usk!\n",__FUNCTION__); + if(bTxEnable){ + pWapiSta->wapiUskUpdate.bTxEnable = true; + if(pWapiSta->wapiUskUpdate.bSet){ + WAPI_TRACE(WAPI_API, "%s(): ASUE set usk!\n",__FUNCTION__); + memcpy(pWapiSta->wapiUsk.dataKey,pWapiSta->wapiUskUpdate.dataKey,16); + memcpy(pWapiSta->wapiUsk.micKey,pWapiSta->wapiUskUpdate.micKey,16); + pWapiSta->wapiUsk.keyId=pWapiSta->wapiUskUpdate.keyId; + memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiAEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiAEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiAEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiAEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPN,WapiAEPNInitialValueSrc,16); + pWapiSta->wapiUskUpdate.bTxEnable = false; + pWapiSta->wapiUskUpdate.bSet = false; + } + memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16); + }else{ + WAPI_TRACE(WAPI_API, "%s(): ASUE set update usk!\n",__FUNCTION__); + pWapiSta->wapiUskUpdate.bSet = true; + memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16); + memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16); + pWapiSta->wapiUskUpdate.keyId = *(data+42); + pWapiSta->wapiUskUpdate.bTxEnable = false; + WAPI_TRACE(WAPI_API, "%s(): keyid=%d\n",__FUNCTION__, pWapiSta->wapiUskUpdate.keyId); + WAPI_DATA(WAPI_API, "SetKey - AE Usk Data Key", pWapiSta->wapiUskUpdate.dataKey, 16); + WAPI_DATA(WAPI_API, "SetKey - AE Usk Mic Key", pWapiSta->wapiUskUpdate.micKey, 16); + } + } + } + break; + case 2: + if(bAuthenticator){ + pWapiInfo->wapiTxMsk.bSet = true; + memcpy(pWapiInfo->wapiTxMsk.dataKey,data+10,16); + memcpy(pWapiInfo->wapiTxMsk.micKey,data+26,16); + pWapiInfo->wapiTxMsk.keyId = *(data+42); + pWapiInfo->wapiTxMsk.bTxEnable = true; + memcpy(pWapiInfo->lastTxMulticastPN,WapiAEMultiCastPNInitialValueSrc,16); + if(!bUpdate){ + WAPI_TRACE(WAPI_API, "%s(): AE fisrt set msk!\n",__FUNCTION__); + if(!pWapiSta->bSetkeyOk) + pWapiSta->bSetkeyOk = true; + pWapiInfo->bFirstAuthentiateInProgress= false; + }else{ + WAPI_TRACE(WAPI_API, "%s():AE update msk!\n",__FUNCTION__); + } + WAPI_TRACE(WAPI_API, "%s(): keyid=%d\n",__FUNCTION__, pWapiInfo->wapiTxMsk.keyId); + WAPI_DATA(WAPI_API, "SetKey - AE Msk Data Key", pWapiInfo->wapiTxMsk.dataKey, 16); + WAPI_DATA(WAPI_API, "SetKey - AE Msk Mic Key", pWapiInfo->wapiTxMsk.micKey, 16); + } + else{ + if(!bUpdate){ + WAPI_TRACE(WAPI_API, "%s(): ASUE fisrt set msk!\n",__FUNCTION__); + pWapiSta->wapiMsk.bSet = true; + memcpy(pWapiSta->wapiMsk.dataKey,data+10,16); + memcpy(pWapiSta->wapiMsk.micKey,data+26,16); + pWapiSta->wapiMsk.keyId = *(data+42); + pWapiSta->wapiMsk.bTxEnable = false; + if(!pWapiSta->bSetkeyOk) + pWapiSta->bSetkeyOk = true; + pWapiInfo->bFirstAuthentiateInProgress= false; + WAPI_DATA(WAPI_API, "SetKey - ASUE Msk Data Key", pWapiSta->wapiMsk.dataKey, 16); + WAPI_DATA(WAPI_API, "SetKey - ASUE Msk Mic Key", pWapiSta->wapiMsk.micKey, 16); + }else{ + WAPI_TRACE(WAPI_API, "%s(): ASUE update msk!\n",__FUNCTION__); + pWapiSta->wapiMskUpdate.bSet = true; + memcpy(pWapiSta->wapiMskUpdate.dataKey,data+10,16); + memcpy(pWapiSta->wapiMskUpdate.micKey,data+26,16); + pWapiSta->wapiMskUpdate.keyId = *(data+42); + pWapiSta->wapiMskUpdate.bTxEnable = false; + WAPI_TRACE(WAPI_API, "%s(): keyid=%d\n",__FUNCTION__, pWapiSta->wapiMskUpdate.keyId); + WAPI_DATA(WAPI_API, "SetKey - ASUE Msk Data Key", pWapiSta->wapiMskUpdate.dataKey, 16); + WAPI_DATA(WAPI_API, "SetKey - ASUE Msk Mic Key", pWapiSta->wapiMskUpdate.micKey, 16); + } + } + break; + default: + WAPI_TRACE(WAPI_ERR, "%s(): Unknown Flag!\n",__FUNCTION__); + break; + } + } + } + } + break; + } + case WAPI_CMD_SET_MULTICAST_PN: + { + PRT_WAPI_T pWapiInfo = &ieee->wapiInfo; + PRT_WAPI_STA_INFO pWapiSta; + u8 data[22]; + u8 k; + + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_MULTICAST_PN!\n",__FUNCTION__); + if (!ieee->WapiSupport) + { + ret = -1; + break; + } + if(wrq->u.data.length < 22){ + ret = -1; + break; + } + + memcpy(data, (u8 *)wrq->u.data.pointer, 22); + list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { + if(!memcmp(pWapiSta->PeerMacAddr,data,6)) + { + for(k=0;k<16;k++) + pWapiSta->lastRxMulticastPN[k] = data[21-k]; + break; + } + } + WAPI_DATA(WAPI_API, "Multicast Rx PN:", pWapiSta->lastRxMulticastPN, 16); + break; + } + case WAPI_CMD_GET_PN: + { + PRT_WAPI_T pWapiInfo = &ieee->wapiInfo; + + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_GET_PN!\n",__FUNCTION__); + if (!ieee->WapiSupport){ + ret = -1; + break; + } + if(wrq->u.data.length<16){ + ret = -1; + break; + } + if(copy_to_user((void *)(wrq->u.data.pointer), pWapiInfo->lastTxMulticastPN, 16)==0) + wrq->u.data.length = 16; + break; + } + case WAPI_CMD_GET_WAPIIE: + { + PRT_WAPI_T pWapiInfo = &ieee->wapiInfo; + u8 data[512]; + u8 Length = 0; + + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_GET_WAPIIE!\n",__FUNCTION__); + if (!ieee->WapiSupport){ + ret = -1; + break; + } + if(wrq->u.data.length<257){ + ret = -1; + break; + } + + if(ieee->iw_mode == IW_MODE_INFRA){ + data[0]= pWapiInfo->assoReqWapiIELength; + Length ++; + memcpy(data+Length,pWapiInfo->assoReqWapiIE,pWapiInfo->assoReqWapiIELength); + Length += pWapiInfo->assoReqWapiIELength; + } + else if(ieee->iw_mode == IW_MODE_ADHOC){ + WAPI_DATA(WAPI_API, "GetWapiIE - ADHOC", pWapiInfo->sendbeaconWapiIE, pWapiInfo->sendbeaconWapiIELength); + data[0] = pWapiInfo->sendbeaconWapiIELength; + Length++; + memcpy(data+Length,pWapiInfo->sendbeaconWapiIE,pWapiInfo->sendbeaconWapiIELength); + Length += pWapiInfo->sendbeaconWapiIELength; + } + + if(copy_to_user((void *)(wrq->u.data.pointer), data, Length)==0) + wrq->u.data.length = Length; + break; + } + case WAPI_CMD_SET_SSID: + { + u8 ssid[IW_ESSID_MAX_SIZE + 1]; + + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_SSID!\n",__FUNCTION__); + if (!ieee->WapiSupport){ + ret = -1; + break; + } + if((wrq->u.data.length == 0) || (NULL == wrq->u.data.pointer)){ + ret = -1; + break; + } + if(wrq->u.data.length > IW_ESSID_MAX_SIZE){ + ret = -1; + break; + } + printk("===>%s(): wrq->u.essid.flags is %d\n",__FUNCTION__,wrq->u.essid.flags); + copy_from_user(ssid, (u8 *)wrq->u.essid.pointer, wrq->u.essid.length); + +#ifdef TO_DO_LIST + if(!ieee->wapiInfo.bWapiEnable) + SetEncryptState(dev); +#endif + if((priv->bHwRadioOff == true) || (!priv->up)){ + ret = -1; + break; + } + ret = rtllib_wx_set_essid(ieee,NULL,(union iwreq_data *)&(wrq->u),ssid); + + break; + } + case WAPI_CMD_GET_BSSID: + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_GET_BSSID!\n",__FUNCTION__); + if (!ieee->WapiSupport){ + ret = -1; + break; + } + if((ieee->iw_mode == IW_MODE_INFRA) || (ieee->iw_mode == IW_MODE_ADHOC) ){ + if(copy_to_user((void *)(wrq->u.data.pointer), ieee->current_network.bssid, ETH_ALEN)==0) + wrq->u.data.length = ETH_ALEN; + }else{ + ret = -1; + } + break; +#if 0 + case WAPI_CMD_GET_LINK_STATUS: + { + u8 connect_status = 0; + + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_GET_LINK_STATUS!\n",__FUNCTION__); + if(ieee->state == IEEE80211_LINKED) + connect_status = 1; + if(copy_to_user((void *)(wrq->u.data.pointer), &connect_status, sizeof(u8))==0) + wrq->u.data.length = sizeof(u8); + break; + } +#endif + case WAPI_CMD_SET_IW_MODE: + { + union iwreq_data *wrqu = (union iwreq_data *)&(wrq->u); + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_IW_MODE!\n",__FUNCTION__); + if (!ieee->WapiSupport){ + ret = -1; + break; + } + WAPI_TRACE(WAPI_API, "%s(): Set iw_mode %d!\n",__FUNCTION__, wrqu->mode); + wapi_ioctl_set_mode(dev, NULL, wrqu, NULL); + if(wrqu->mode == IW_MODE_ADHOC) + ConstructWapiIEForInit(ieee); + break; + } + case WAPI_CMD_SET_DISASSOCIATE: + { + u8 destAddr[6]; + + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SET_DISASSOCIATE!\n",__FUNCTION__); + if (!ieee->WapiSupport){ + ret = -1; + break; + } + if(wrq->u.data.length != 6){ + ret = -1; + break; + } + copy_from_user(destAddr, (u8 *)(wrq->u.data.pointer), wrq->u.data.length); + + if(ieee->iw_mode == IW_MODE_INFRA){ + SendDisassociation(ieee,1,deauth_lv_ss); + ieee80211_disassociate_from_app(ieee); + }else if(ieee->iw_mode == IW_MODE_ADHOC){ + WAPI_TRACE(WAPI_API, "%s(): Disassociate "MAC_FMT"!\n",__FUNCTION__, MAC_ARG(destAddr)); + WapiReturnOneStaInfo(ieee, destAddr, 1); + DelStaInfo(ieee, destAddr); + } + break; + } + case WAPI_CMD_SAVE_PID: + { + u8 strPID[10]; + u32 len = 0; + int i = 0; + + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_SAVE_PID!\n",__FUNCTION__); + if (!ieee->WapiSupport){ + ret = -1; + break; + } + if ( !wrq->u.data.pointer ){ + ret = -1; + break; + } + + len = wrq->u.data.length; + memset(strPID, 0, sizeof(strPID)); + if(copy_from_user(strPID, (void *)wrq->u.data.pointer, len)){ + ret = -1; + break; + } + + pid_wapi = 0; + for(i = 0; i < len; i++) { + pid_wapi = pid_wapi * 10 + (strPID[i] - 48); + } + WAPI_TRACE(WAPI_API, "%s(): strPID=%s pid_wapi=%d!\n",__FUNCTION__, strPID, pid_wapi); + break; + } + case WAPI_CMD_DEQUEUE: + { + int QueueDataLen = 0; + + WAPI_TRACE(WAPI_API, "%s(): WAPI_CMD_DEQUEUE!\n",__FUNCTION__); + if((ret = WAPI_DeQueue(&ieee->wapi_queue_lock, ieee->wapi_queue, QueueData, &QueueDataLen)) != 0){ + if(copy_to_user((void *)(wrq->u.data.pointer), DATAQUEUE_EMPTY, sizeof(DATAQUEUE_EMPTY))==0) + wrq->u.data.length = sizeof(DATAQUEUE_EMPTY); + }else{ + if(copy_to_user((void *)wrq->u.data.pointer, (void *)QueueData, QueueDataLen)==0) + wrq->u.data.length = QueueDataLen; + } + break; + } + default: + WAPI_TRACE(WAPI_ERR, "%s(): Error CMD!\n",__FUNCTION__); + break; + } + + return ret; +} +#endif + +/* based on ipw2200 driver */ +int rtl8192_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct iwreq *wrq = (struct iwreq *)rq; + int ret=-1; + struct rtllib_device *ieee = priv->rtllib; + u32 key[4]; + u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + u8 zero_addr[6] = {0}; + struct iw_point *p = &wrq->u.data; + + down(&priv->wx_sem); + + switch (cmd) { + case RTL_IOCTL_WPA_SUPPLICANT: + { + struct ieee_param *ipw = NULL; + if (p->length < sizeof(struct ieee_param) || !p->pointer){ + ret = -EINVAL; + goto out; + } + + ipw = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL); + if (ipw == NULL){ + ret = -ENOMEM; + goto out; + } + if (copy_from_user(ipw, p->pointer, p->length)) { + kfree(ipw); + ret = -EFAULT; + goto out; + } + + if (ipw->cmd == IEEE_CMD_SET_ENCRYPTION) + { + if (ipw->u.crypt.set_tx) + { + if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) + ieee->pairwise_key_type = KEY_TYPE_CCMP; + else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) + ieee->pairwise_key_type = KEY_TYPE_TKIP; + else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) + { + if (ipw->u.crypt.key_len == 13) + ieee->pairwise_key_type = KEY_TYPE_WEP104; + else if (ipw->u.crypt.key_len == 5) + ieee->pairwise_key_type = KEY_TYPE_WEP40; + } + else + ieee->pairwise_key_type = KEY_TYPE_NA; + + if (ieee->pairwise_key_type) + { + if (memcmp(ieee->ap_mac_addr, zero_addr, 6) == 0) + ieee->iw_mode = IW_MODE_ADHOC; + + memcpy((u8*)key, ipw->u.crypt.key, 16); + EnableHWSecurityConfig8192(dev); + set_swcam(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key,0); + setKey(dev, 4, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key); + if (ieee->iw_mode == IW_MODE_ADHOC){ + set_swcam(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key,0); + setKey(dev, ipw->u.crypt.idx, ipw->u.crypt.idx, ieee->pairwise_key_type, (u8*)ieee->ap_mac_addr, 0, key); + } + } +#ifdef RTL8192E + if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){ + write_nic_byte(dev, 0x173, 1); + } +#endif + + } + else + { + memcpy((u8*)key, ipw->u.crypt.key, 16); + if (strcmp(ipw->u.crypt.alg, "CCMP") == 0) + ieee->group_key_type= KEY_TYPE_CCMP; + else if (strcmp(ipw->u.crypt.alg, "TKIP") == 0) + ieee->group_key_type = KEY_TYPE_TKIP; + else if (strcmp(ipw->u.crypt.alg, "WEP") == 0) + { + if (ipw->u.crypt.key_len == 13) + ieee->group_key_type = KEY_TYPE_WEP104; + else if (ipw->u.crypt.key_len == 5) + ieee->group_key_type = KEY_TYPE_WEP40; + } + else + ieee->group_key_type = KEY_TYPE_NA; + + if (ieee->group_key_type) + { + set_swcam( dev, + ipw->u.crypt.idx, + ipw->u.crypt.idx, + ieee->group_key_type, + broadcast_addr, + 0, + key, + 0); + setKey( dev, + ipw->u.crypt.idx, + ipw->u.crypt.idx, + ieee->group_key_type, + broadcast_addr, + 0, + key); + } + } + } +#ifdef JOHN_DEBUG + { + int i; + printk("@@ wrq->u pointer = "); + for(i=0;iu.data.length;i++){ + if(i%10==0) printk("\n"); + printk( "%8x|", ((u32*)wrq->u.data.pointer)[i] ); + } + printk("\n"); + } +#endif +#ifdef _RTL8192_EXT_PATCH_ + ret = rtllib_wpa_supplicant_ioctl(priv->rtllib, &wrq->u.data,0); +#else + ret = rtllib_wpa_supplicant_ioctl(priv->rtllib, &wrq->u.data, 0); +#endif + kfree(ipw); + break; + } +#if defined (RTL8192S_WAPI_SUPPORT) + case WAPI_CMD_GET_WAPI_SUPPORT: + case WAPI_CMD_SET_WAPI_ENABLE: + case WAPI_CMD_SET_WAPI_PSK: + case WAPI_CMD_SET_KEY: + case WAPI_CMD_SET_MULTICAST_PN: + case WAPI_CMD_GET_PN: + case WAPI_CMD_GET_WAPIIE: + case WAPI_CMD_SET_SSID: + case WAPI_CMD_GET_BSSID: + case WAPI_CMD_SET_IW_MODE: + case WAPI_CMD_SET_DISASSOCIATE: + case WAPI_CMD_SAVE_PID: + case WAPI_CMD_DEQUEUE: + ret = WAPI_Ioctl(dev, wrq, cmd); + break; +#endif + default: + ret = -EOPNOTSUPP; + break; + } + +out: + up(&priv->wx_sem); + + return ret; +} + +void FairBeacon(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct rtllib_network *net = &priv->rtllib->current_network; + static u8 i=100; + static u8 forceturn =0; + u16 beaconint = net->beacon_interval; + + if(priv->rtllib->iw_mode != IW_MODE_ADHOC) + return; + + if(priv->bIbssCoordinator){ + i--; + + if(forceturn ==2){ + forceturn =0; + priv->rtllib->SetHwRegHandler(dev, HW_VAR_BEACON_INTERVAL, (u8*)(&beaconint)); + i=100; + } + + if(i<=94){ + beaconint=beaconint+2; + priv->rtllib->SetHwRegHandler(dev, HW_VAR_BEACON_INTERVAL, (u8*)(&beaconint)); + forceturn =1; + } + } else { + i++; + + if(forceturn ==1){ + forceturn =0; + priv->rtllib->SetHwRegHandler(dev, HW_VAR_BEACON_INTERVAL, (u8*)(&beaconint)); + i=100; + } + + if(i>=106){ + beaconint=beaconint-2; + priv->rtllib->SetHwRegHandler(dev, HW_VAR_BEACON_INTERVAL, (u8*)(&beaconint)); + forceturn =2; + } + } +} + + +irqreturn_type rtl8192_interrupt(int irq, void *netdev, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) netdev; + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); +#ifdef _RTL8192_EXT_PATCH_ + struct net_device *meshdev = ((struct rtllib_device *)netdev_priv_rsl(dev))->meshdev; +#endif + unsigned long flags; + u32 inta; + u32 intb; + intb = 0; + + if(priv->irq_enabled == 0){ + goto done; + } + + spin_lock_irqsave(&priv->irq_th_lock,flags); + + priv->ops->interrupt_recognized(dev, &inta, &intb); + priv->stats.shints++; + + if (!inta) { + spin_unlock_irqrestore(&priv->irq_th_lock,flags); + goto done; + } + + if (inta == 0xffff) { + spin_unlock_irqrestore(&priv->irq_th_lock,flags); + goto done; + } + + priv->stats.ints++; + +#ifdef _RTL8192_EXT_PATCH_ + if (!netif_running(dev) && !netif_running(meshdev)) +#else + if (!netif_running(dev)) +#endif + { + spin_unlock_irqrestore(&priv->irq_th_lock,flags); + goto done; + } + +#if defined RTL8192SE + if(intb & IMR_TBDOK){ + RT_TRACE(COMP_INTR, "beacon ok interrupt!\n"); + priv->stats.txbeaconokint++; + priv->bIbssCoordinator = true; + } + + if(intb & IMR_TBDER){ + RT_TRACE(COMP_INTR, "beacon error interrupt!\n"); + priv->stats.txbeaconerr++; + priv->bIbssCoordinator = false; + } + + if ((intb & IMR_TBDOK) ||(intb & IMR_TBDER)) + FairBeacon(dev); +#else + if(inta & IMR_TBDOK){ + RT_TRACE(COMP_INTR, "beacon ok interrupt!\n"); + priv->stats.txbeaconokint++; + } + + if(inta & IMR_TBDER){ + RT_TRACE(COMP_INTR, "beacon ok interrupt!\n"); + priv->stats.txbeaconerr++; + } +#endif + + if(inta & IMR_BDOK) { + RT_TRACE(COMP_INTR, "beacon interrupt!\n"); +#ifdef _ENABLE_SW_BEACON + rtl8192_tx_isr(dev, BEACON_QUEUE); +#endif + } + + if(inta & IMR_MGNTDOK ) { + RT_TRACE(COMP_INTR, "Manage ok interrupt!\n"); + priv->stats.txmanageokint++; + rtl8192_tx_isr(dev,MGNT_QUEUE); + spin_unlock_irqrestore(&priv->irq_th_lock,flags); + if (priv->rtllib->ack_tx_to_ieee){ + if (rtl8192_is_tx_queue_empty(dev)){ + priv->rtllib->ack_tx_to_ieee = 0; + rtllib_ps_tx_ack(priv->rtllib, 1); + } + } + spin_lock_irqsave(&priv->irq_th_lock,flags); + } + +#ifndef RTL8192CE + if (inta & IMR_COMDOK) { + priv->stats.txcmdpktokint++; + rtl8192_tx_isr(dev,TXCMD_QUEUE); + } +#endif + + if (inta & IMR_HIGHDOK) { + rtl8192_tx_isr(dev,HIGH_QUEUE); + } + +#ifdef RTL8192SE + if ((inta & IMR_ROK) || (inta & IMR_RXCMDOK)) +#else + if (inta & IMR_ROK) +#endif + { + priv->stats.rxint++; + priv->InterruptLog.nIMR_ROK++; + tasklet_schedule(&priv->irq_rx_tasklet); + } + + if (inta & IMR_BcnInt) { + RT_TRACE(COMP_INTR, "prepare beacon for interrupt!\n"); +#ifndef _ENABLE_SW_BEACON + tasklet_schedule(&priv->irq_prepare_beacon_tasklet); +#endif + } + + if (inta & IMR_RDU) { + RT_TRACE(COMP_INTR, "rx descriptor unavailable!\n"); + priv->stats.rxrdu++; +#ifndef RTL8192CE + write_nic_dword(dev,INTA_MASK,read_nic_dword(dev, INTA_MASK) & ~IMR_RDU); +#endif + tasklet_schedule(&priv->irq_rx_tasklet); + } + + if (inta & IMR_RXFOVW) { + RT_TRACE(COMP_INTR, "rx overflow !\n"); + priv->stats.rxoverflow++; + tasklet_schedule(&priv->irq_rx_tasklet); + } + + if (inta & IMR_TXFOVW) priv->stats.txoverflow++; + + if (inta & IMR_BKDOK) { + RT_TRACE(COMP_INTR, "BK Tx OK interrupt!\n"); + priv->stats.txbkokint++; + priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++; + rtl8192_tx_isr(dev,BK_QUEUE); + } + + if (inta & IMR_BEDOK) { + RT_TRACE(COMP_INTR, "BE TX OK interrupt!\n"); + priv->stats.txbeokint++; + priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++; + rtl8192_tx_isr(dev,BE_QUEUE); + } + + if (inta & IMR_VIDOK) { + RT_TRACE(COMP_INTR, "VI TX OK interrupt!\n"); + priv->stats.txviokint++; + priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++; + rtl8192_tx_isr(dev,VI_QUEUE); + } + + if (inta & IMR_VODOK) { + priv->stats.txvookint++; + RT_TRACE(COMP_INTR, "Vo TX OK interrupt!\n"); + priv->rtllib->LinkDetectInfo.NumTxOkInPeriod++; + rtl8192_tx_isr(dev,VO_QUEUE); + } + + spin_unlock_irqrestore(&priv->irq_th_lock,flags); + +done: + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + return; +#else + return IRQ_HANDLED; +#endif +} + + + +/**************************************************************************** + ---------------------------- PCI_STUFF--------------------------- +*****************************************************************************/ +#ifdef HAVE_NET_DEVICE_OPS +static const struct net_device_ops rtl8192_netdev_ops = { + .ndo_open = rtl8192_open, + .ndo_stop = rtl8192_close, + .ndo_tx_timeout = rtl8192_tx_timeout, + .ndo_do_ioctl = rtl8192_ioctl, + .ndo_set_multicast_list = r8192_set_multicast, + .ndo_set_mac_address = r8192_set_mac_adr, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = eth_change_mtu, + .ndo_start_xmit = rtllib_xmit, +}; +#endif + +static int __devinit rtl8192_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + unsigned long ioaddr = 0; + struct net_device *dev = NULL; + struct r8192_priv *priv= NULL; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct rtl819x_ops *ops = (struct rtl819x_ops *)(id->driver_data); +#endif + +#ifdef CONFIG_RTL8192_IO_MAP + unsigned long pio_start, pio_len, pio_flags; +#else + unsigned long pmem_start, pmem_len, pmem_flags; +#endif + int err = 0; +#ifdef _RTL8192_EXT_PATCH_ + int result; + struct net_device *meshdev = NULL; + struct meshdev_priv *mpriv; + char meshifname[]="mesh0"; +#endif + bool bdma64 = false; + + RT_TRACE(COMP_INIT,"Configuring chip resources"); + + if( pci_enable_device (pdev) ){ + RT_TRACE(COMP_ERR,"Failed to enable PCI device"); + return -EIO; + } + + pci_set_master(pdev); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) +#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL < (n)) -1)) +#endif + +#ifdef CONFIG_64BIT_DMA + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { + printk("RTL819xCE: Using 64bit DMA\n"); + if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { + printk( "Unable to obtain 64bit DMA for consistent allocations\n"); + pci_disable_device(pdev); + return -ENOMEM; + } + bdma64 = true; + } else +#endif + { + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { + printk( "Unable to obtain 32bit DMA for consistent allocations\n"); + pci_disable_device(pdev); + return -ENOMEM; + } +#endif + } + } + dev = alloc_rtllib(sizeof(struct r8192_priv)); + if (!dev) + return -ENOMEM; + + if(bdma64){ + dev->features |= NETIF_F_HIGHDMA; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + SET_MODULE_OWNER(dev); +#endif + + pci_set_drvdata(pdev, dev); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + SET_NETDEV_DEV(dev, &pdev->dev); +#endif + priv = rtllib_priv(dev); + priv->rtllib = (struct rtllib_device *)netdev_priv_rsl(dev); + priv->pdev=pdev; + priv->rtllib->pdev=pdev; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + if((pdev->subsystem_vendor == PCI_VENDOR_ID_DLINK)&&(pdev->subsystem_device == 0x3304)){ + priv->rtllib->bSupportRemoteWakeUp = 1; + } else +#endif + { + priv->rtllib->bSupportRemoteWakeUp = 0; + } + +#ifdef CONFIG_RTL8192_IO_MAP + pio_start = (unsigned long)pci_resource_start (pdev, 0); + pio_len = (unsigned long)pci_resource_len (pdev, 0); + pio_flags = (unsigned long)pci_resource_flags (pdev, 0); + + if (!(pio_flags & IORESOURCE_IO)) { + RT_TRACE(COMP_ERR,"region #0 not a PIO resource, aborting"); + goto fail; + } + + printk("Io mapped space start: 0x%08lx \n", pio_start ); + if( ! request_region( pio_start, pio_len, DRV_NAME ) ){ + RT_TRACE(COMP_ERR,"request_region failed!"); + goto fail; + } + + ioaddr = pio_start; + dev->base_addr = ioaddr; +#else +#ifdef RTL8192CE + pmem_start = pci_resource_start(pdev, 2); + pmem_len = pci_resource_len(pdev, 2); + pmem_flags = pci_resource_flags (pdev, 2); +#else + pmem_start = pci_resource_start(pdev, 1); + pmem_len = pci_resource_len(pdev, 1); + pmem_flags = pci_resource_flags (pdev, 1); +#endif + + if (!(pmem_flags & IORESOURCE_MEM)) { + RT_TRACE(COMP_ERR,"region #1 not a MMIO resource, aborting"); + goto fail; + } + + printk("Memory mapped space start: 0x%08lx \n", pmem_start); + if (!request_mem_region(pmem_start, pmem_len, DRV_NAME)) { + RT_TRACE(COMP_ERR,"request_mem_region failed!"); + goto fail; + } + + + ioaddr = (unsigned long)ioremap_nocache( pmem_start, pmem_len); + if( ioaddr == (unsigned long)NULL ){ + RT_TRACE(COMP_ERR,"ioremap failed!"); + goto fail1; + } + + dev->mem_start = ioaddr; + dev->mem_end = ioaddr + pci_resource_len(pdev, 0); + +#endif +#if defined RTL8192SE || defined RTL8192CE + pci_write_config_byte(pdev, 0x81,0); + pci_write_config_byte(pdev,0x44,0); + pci_write_config_byte(pdev,0x04,0x06); + pci_write_config_byte(pdev,0x04,0x07); +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + priv->ops = ops; +#else +#if defined RTL8190P || defined RTL8192E + priv->ops = &rtl819xp_ops; +#else + priv->ops = &rtl8192se_ops; +#endif +#endif + + if(rtl8192_pci_findadapter(pdev, dev) == false) + goto fail1; + + dev->irq = pdev->irq; + priv->irq = 0; + +#ifdef HAVE_NET_DEVICE_OPS + dev->netdev_ops = &rtl8192_netdev_ops; +#else + dev->open = rtl8192_open; + dev->stop = rtl8192_close; + dev->tx_timeout = rtl8192_tx_timeout; + dev->do_ioctl = rtl8192_ioctl; + dev->set_multicast_list = r8192_set_multicast; + dev->set_mac_address = r8192_set_mac_adr; + dev->hard_start_xmit = rtllib_xmit; +#endif + +#if WIRELESS_EXT >= 12 +#if WIRELESS_EXT < 17 + dev->get_wireless_stats = r8192_get_wireless_stats; +#endif + dev->wireless_handlers = (struct iw_handler_def *) &r8192_wx_handlers_def; +#endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + dev->ethtool_ops = &rtl819x_ethtool_ops; +#endif + + dev->type = ARPHRD_ETHER; + dev->watchdog_timeo = HZ*3; + + if (dev_alloc_name(dev, ifname) < 0){ + RT_TRACE(COMP_INIT, "Oops: devname already taken! Trying wlan%%d...\n"); + dev_alloc_name(dev, ifname); + } + + RT_TRACE(COMP_INIT, "Driver probe completed1\n"); + if(rtl8192_init(dev)!=0){ + RT_TRACE(COMP_ERR, "Initialization failed"); + goto fail1; + } + +#ifdef CONFIG_CFG_80211 + if(!rtl8192_register_wiphy_dev(dev)) + goto fail1; +#endif + + netif_carrier_off(dev); + netif_stop_queue(dev); + + register_netdev(dev); + RT_TRACE(COMP_INIT, "dev name: %s\n",dev->name); + err = rtl_debug_module_init(priv, dev->name); + if (err) { + RT_TRACE(COMP_DBG, "failed to create debugfs files. Ignoring error: %d\n", err); + } + rtl8192_proc_init_one(dev); + +#ifdef ENABLE_GPIO_RADIO_CTL + if(priv->polling_timer_on == 0){ + check_rfctrl_gpio_timer((unsigned long)dev); + } +#endif +#ifdef _RTL8192_EXT_PATCH_ + meshdev = alloc_netdev(sizeof(struct meshdev_priv),meshifname,meshdev_init); + netif_stop_queue(meshdev); + memcpy(meshdev->dev_addr, dev->dev_addr, ETH_ALEN); + DMESG("Card MAC address for meshdev is "MAC_FMT, MAC_ARG(meshdev->dev_addr)); + + meshdev->base_addr = dev->base_addr; + meshdev->irq = dev->irq; + meshdev->mem_start = dev->mem_start; + meshdev->mem_end = dev->mem_end; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) + SET_NETDEV_DEV(meshdev, dev->dev.parent); +#endif + + if ((result = register_netdev(meshdev))) + { + printk("Error %i registering device %s",result, meshdev->name); + goto fail; + } + else + { + mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + priv->rtllib->meshdev=meshdev; + priv->rtllib->meshstats=meshdev_stats(meshdev); + priv->rtllib->only_mesh = 1; + priv->rtllib->p2pmode = 0; + priv->rtllib->serverExtChlOffset = 0; + priv->rtllib->APExtChlOffset = 0; + mpriv->rtllib = priv->rtllib; + mpriv->priv = priv; + } +#endif + +#ifdef RTL8192CE + mdelay(1000); +#endif + +#ifdef CONFIG_RTL_RFKILL + if (priv->ops->init_before_adapter_start) { + priv->ops->init_before_adapter_start(dev); + priv->initialized_at_probe = true; + } + if (!rtl8192_rfkill_init(dev)) { + goto fail1; + } +#endif + +#if defined CONFIG_ASPM_OR_D3 + rtl8192_initialize_adapter_common(dev); +#endif + + RT_TRACE(COMP_INIT, "Driver probe completed\n"); + return 0; + +fail1: +#ifdef CONFIG_RTL8192_IO_MAP + + if( dev->base_addr != 0 ){ + + release_region(dev->base_addr, + pci_resource_len(pdev, 0) ); + } +#else + if( dev->mem_start != (unsigned long)NULL ){ + iounmap( (void *)dev->mem_start ); +#ifdef RTL8192CE + release_mem_region( pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2) ); +#else + release_mem_region( pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1) ); +#endif + } +#endif + +fail: + if(dev){ + + if (priv->irq) { + free_irq(dev->irq, dev); + dev->irq=0; + } + free_rtllib(dev); + } + + pci_disable_device(pdev); + + DMESG("wlan driver load failed\n"); + pci_set_drvdata(pdev, NULL); + return -ENODEV; + +} + +static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct r8192_priv *priv ; +#ifdef _RTL8192_EXT_PATCH_ + struct net_device *meshdev; +#endif + if(dev){ +#ifdef CONFIG_RTL_RFKILL + rtl8192_rfkill_exit(dev); +#endif + unregister_netdev(dev); + + priv = rtllib_priv(dev); + +#ifdef _RTL8192_EXT_PATCH_ + rtl8192_dinit_mshobj(priv); +#endif + +#ifdef CONFIG_BT_30 + bt_wifi_deinit(dev); +#endif + +#ifdef ENABLE_GPIO_RADIO_CTL + del_timer_sync(&priv->gpio_polling_timer); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + cancel_delayed_work(&priv->gpio_change_rf_wq); +#endif + priv->polling_timer_on = 0; +#endif + rtl_debug_module_remove(priv); + rtl8192_proc_remove_one(dev); +#ifdef _RTL8192_EXT_PATCH_ + rtl8192_down(dev,true); + if(priv && priv->rtllib->meshdev) + { + meshdev = priv->rtllib->meshdev; + priv->rtllib->meshdev = NULL; + + if(meshdev){ + meshdev_down(meshdev); + unregister_netdev(meshdev); + } + } +#else + rtl8192_down(dev,true); +#endif + deinit_hal_dm(dev); +#ifdef CONFIG_ASPM_OR_D3 + ; +#endif +#ifdef RTL8192SE + DeInitSwLeds(dev); +#endif + if (priv->pFirmware) + { + vfree(priv->pFirmware); + priv->pFirmware = NULL; + } +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + destroy_workqueue(priv->priv_wq); +#endif + { + u32 i; + rtl8192_free_rx_ring(dev); + for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) { + rtl8192_free_tx_ring(dev, i); + } + } + + if(priv->irq){ + + printk("Freeing irq %d\n",dev->irq); + free_irq(dev->irq, dev); + priv->irq=0; + + } +#ifdef CONFIG_RTL8192_IO_MAP + if( dev->base_addr != 0 ){ + + release_region(dev->base_addr, + pci_resource_len(pdev, 0) ); + } +#else + if( dev->mem_start != (unsigned long)NULL ){ + iounmap( (void *)dev->mem_start ); +#ifdef RTL8192CE + release_mem_region( pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2) ); +#else + release_mem_region( pci_resource_start(pdev, 1), + pci_resource_len(pdev, 1) ); +#endif + } +#endif /*end #ifdef RTL_IO_MAP*/ + free_rtllib(dev); + + if(priv->scan_cmd) + kfree(priv->scan_cmd); + + } else{ + priv=rtllib_priv(dev); + } + + pci_disable_device(pdev); +#ifdef RTL8192SE + pci_write_config_byte(pdev, 0x81,1); + pci_write_config_byte(pdev,0x44,3); +#endif + RT_TRACE(COMP_DOWN, "wlan driver removed\n"); +} + +bool NicIFEnableNIC(struct net_device* dev) +{ + bool init_status = true; + struct r8192_priv* priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + + if(IS_NIC_DOWN(priv)){ + RT_TRACE(COMP_ERR, "ERR!!! %s(): Driver is already down!\n",__FUNCTION__); + priv->bdisable_nic = false; + return RT_STATUS_FAILURE; + } + + RT_TRACE(COMP_PS, "===========>%s()\n",__FUNCTION__); + priv->bfirst_init = true; + init_status = priv->ops->initialize_adapter(dev); + if (init_status != true) { + RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__); + priv->bdisable_nic = false; + return -1; + } + RT_TRACE(COMP_INIT, "start adapter finished\n"); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); + priv->bfirst_init = false; + + rtl8192_irq_enable(dev); + priv->bdisable_nic = false; + RT_TRACE(COMP_PS,"<===========%s()\n",__FUNCTION__); + return init_status; +} +bool NicIFDisableNIC(struct net_device* dev) +{ + bool status = true; + struct r8192_priv* priv = rtllib_priv(dev); + u8 tmp_state = 0; + RT_TRACE(COMP_PS, "=========>%s()\n",__FUNCTION__); + priv->bdisable_nic = true; + tmp_state = priv->rtllib->state; +#ifdef _RTL8192_EXT_PATCH_ + if((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->only_mesh)) + rtllib_softmac_stop_protocol(priv->rtllib, 1, false); + else + rtllib_softmac_stop_protocol(priv->rtllib, 0, false); +#else + rtllib_softmac_stop_protocol(priv->rtllib, 0, false); +#endif + priv->rtllib->state = tmp_state; + rtl8192_cancel_deferred_work(priv); + rtl8192_irq_disable(dev); + + priv->ops->stop_adapter(dev, false); + RT_TRACE(COMP_PS, "<=========%s()\n",__FUNCTION__); + + return status; +} + +static int __init rtl8192_pci_module_init(void) +{ + int ret; + int error; + +#ifdef BUILT_IN_CRYPTO + ret = arc4_init(); + if (ret) { + printk(KERN_ERR "arc4_init() failed %d\n", ret); + return ret; + } + + + ret = michael_mic_init(); + if (ret) { + printk(KERN_ERR "michael_mic_init() failed %d\n", ret); + return ret; + } + + ret = aes_init(); + if (ret) { + printk(KERN_ERR "aes_init() failed %d\n", ret); + return ret; + } +#endif +#ifdef BUILT_IN_RTLLIB + ret = rtllib_init(); + if (ret) { + printk(KERN_ERR "rtllib_init() failed %d\n", ret); + return ret; + } + ret = rtllib_crypto_init(); + if (ret) { + printk(KERN_ERR "rtllib_crypto_init() failed %d\n", ret); + return ret; + } + ret = rtllib_crypto_tkip_init(); + if (ret) { + printk(KERN_ERR "rtllib_crypto_tkip_init() failed %d\n", ret); + return ret; + } + ret = rtllib_crypto_ccmp_init(); + if (ret) { + printk(KERN_ERR "rtllib_crypto_ccmp_init() failed %d\n", ret); + return ret; + } + ret = rtllib_crypto_wep_init(); + if (ret) { + printk(KERN_ERR "rtllib_crypto_wep_init() failed %d\n", ret); + return ret; + } +#endif +#ifdef BUILT_IN_MSHCLASS + ret = msh_init(); + if (ret) { + printk(KERN_ERR "msh_init() failed %d\n", ret); + return ret; + } +#endif + printk(KERN_INFO "\nLinux kernel driver for RTL8192 based WLAN cards\n"); + printk(KERN_INFO "Copyright (c) 2007-2008, Realsil Wlan Driver\n"); + RT_TRACE(COMP_INIT, "Initializing module"); + RT_TRACE(COMP_INIT, "Wireless extensions version %d", WIRELESS_EXT); + + error = rtl_create_debugfs_root(); + if (error) { + RT_TRACE(COMP_DBG, "Create debugfs root fail: %d\n", error); + goto err_out; + } + + rtl8192_proc_module_init(); +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)) + if(0!=pci_module_init(&rtl8192_pci_driver)) +#else + if(0!=pci_register_driver(&rtl8192_pci_driver)) +#endif + { + DMESG("No device found"); + /*pci_unregister_driver (&rtl8192_pci_driver);*/ + return -ENODEV; + } + return 0; +err_out: + return error; + +} + +static void __exit rtl8192_pci_module_exit(void) +{ + pci_unregister_driver(&rtl8192_pci_driver); + + RT_TRACE(COMP_DOWN, "Exiting"); + rtl8192_proc_module_remove(); + rtl_remove_debugfs_root(); +#ifdef BUILT_IN_RTLLIB + rtllib_crypto_tkip_exit(); + rtllib_crypto_ccmp_exit(); + rtllib_crypto_wep_exit(); + rtllib_crypto_deinit(); + rtllib_exit(); +#endif +#ifdef BUILT_IN_CRYPTO + arc4_exit(); + michael_mic_exit(); + aes_fini(); +#endif +#ifdef BUILT_IN_MSHCLASS + msh_exit(); +#endif + +} + +void check_rfctrl_gpio_timer(unsigned long data) +{ + struct r8192_priv* priv = rtllib_priv((struct net_device *)data); + + priv->polling_timer_on = 1; + + queue_delayed_work_rsl(priv->priv_wq,&priv->gpio_change_rf_wq,0); + + mod_timer(&priv->gpio_polling_timer, jiffies + MSECS(RTLLIB_WATCH_DOG_TIME)); +} + +/*************************************************************************** + ------------------- module init / exit stubs ---------------- +****************************************************************************/ +module_init(rtl8192_pci_module_init); +module_exit(rtl8192_pci_module_exit); + +MODULE_DESCRIPTION("Linux driver for Realtek RTL819x WiFi cards"); +MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +MODULE_VERSION(DRV_VERSION); +#endif +MODULE_LICENSE("GPL"); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9) +module_param(ifname, charp, S_IRUGO|S_IWUSR ); +module_param(hwwep,int, S_IRUGO|S_IWUSR); +module_param(channels,int, S_IRUGO|S_IWUSR); +#else +MODULE_PARM(ifname, "s"); +MODULE_PARM(hwwep,"i"); +MODULE_PARM(channels,"i"); +#endif + +MODULE_PARM_DESC(ifname," Net interface name, wlan%d=default"); +MODULE_PARM_DESC(hwwep," Try to use hardware WEP support(default use hw. set 0 to use software security)"); +MODULE_PARM_DESC(channels," Channel bitmask for specific locales. NYI"); --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_core.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl_core.h @@ -0,0 +1,1359 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + +#ifndef _RTL_CORE_H +#define _RTL_CORE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)) +#include +#endif +#include "rtllib/rtllib.h" +#ifdef CONFIG_BT_30 +#include "../../btlib/bt_inc.h" +#endif + +#ifdef ENABLE_DOT11D +#include "rtllib/dot11d.h" +#endif + + + +#ifdef RTL8192SE +#include "rtl_dm.h" +#include "rtl8192s/r8192S_inc.h" +#elif defined RTL8190P || defined RTL8192E +#include "rtl_dm.h" +#include "rtl8192e/r8192E_inc.h" +#elif defined RTL8192CE +#include "rtl8192c/r8192C_inc.h" +#endif + +#ifdef CONFIG_CFG_80211 +#include "rtl_regd.h" +#endif + +#ifdef CONFIG_RTL_RFKILL +#include "rtl_rfkill.h" +#endif + +#include "rtl_debug.h" +#include "rtl_eeprom.h" +#include "rtl_ps.h" +#include "rtl_pci.h" +#include "rtl_cam.h" + +#define DRV_COPYRIGHT "Copyright(c) 2008 - 2010 Realsil Semiconductor Corporation" +#define DRV_AUTHOR "" +#define DRV_VERSION "0017.0507.2010" + +#ifdef RTL8190P +#define DRV_NAME "rtl819xP" +#elif defined RTL8192E +#define DRV_NAME "rtl819xE" +#elif defined RTL8192SE +#define DRV_NAME "rtl819xSE" +#elif defined RTL8192CE +#define DRV_NAME "rtl8192CE" +#endif + +#define IS_HARDWARE_TYPE_819xP(_priv) ((((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8190P)||\ + (((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192E)) +#define IS_HARDWARE_TYPE_8192SE(_priv) (((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192SE) +#define IS_HARDWARE_TYPE_8192CE(_priv) (((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192CE) +#define IS_HARDWARE_TYPE_8192CU(_priv) (((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192CU) +#define IS_HARDWARE_TYPE_8192DE(_priv) (((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192DE) +#define IS_HARDWARE_TYPE_8192DU(_priv) (((struct r8192_priv*)rtllib_priv(dev))->card_8192==NIC_8192DU) + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#define RTL_PCI_DEVICE(vend, dev, cfg) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice =PCI_ANY_ID , \ + .driver_data = (kernel_ulong_t)&(cfg) +#else +#define RTL_PCI_DEVICE(vend, dev, cfg) \ + .vendor = (vend), .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice =PCI_ANY_ID +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + typedef void irqreturn_type; +#else + typedef irqreturn_t irqreturn_type; +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) + +#if !defined(PCI_CAP_ID_EXP) +#define PCI_CAP_ID_EXP 0x10 +#endif +#if !defined(PCI_EXP_LNKCTL) +#define PCI_EXP_LNKCTL 0x10 +#endif + +typedef int __bitwise pci_power_t; +#define PCI_D0 ((pci_power_t __force) 0) +#define PCI_D1 ((pci_power_t __force) 1) +#define PCI_D2 ((pci_power_t __force) 2) +#define PCI_D3hot ((pci_power_t __force) 3) +#define PCI_D3cold ((pci_power_t __force) 4) +#define PCI_UNKNOWN ((pci_power_t __force) 5) +#define PCI_POWER_ERROR ((pci_power_t __force) -1) + +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) + #define rtl8192_interrupt(x,y,z) rtl8192_interrupt_rsl(x,y,z) +#else + #define rtl8192_interrupt(x,y,z) rtl8192_interrupt_rsl(x,y) +#endif + +#define RTL_MAX_SCAN_SIZE 128 + +#define RTL_RATE_MAX 30 + +#define TOTAL_CAM_ENTRY 32 +#define CAM_CONTENT_COUNT 8 + +#ifndef BIT +#define BIT(_i) (1<<(_i)) +#endif + +#ifdef _RTL8192_EXT_PATCH_ +#define IS_NIC_DOWN(priv) ((!(priv)->up) && (!(priv)->mesh_up)) +#else +#define IS_NIC_DOWN(priv) (!(priv)->up) +#endif + +#define IS_ADAPTER_SENDS_BEACON(dev) 0 + +#ifdef _RTL8192_EXT_PATCH_ +#define IS_UNDER_11N_AES_MODE(_rtllib) ((_rtllib->pHTInfo->bCurrentHTSupport == true) &&\ + ((_rtllib->pairwise_key_type == KEY_TYPE_CCMP) || \ + (_rtllib->mesh_pairwise_key_type == KEY_TYPE_CCMP))) +#else +#define IS_UNDER_11N_AES_MODE(_rtllib) ((_rtllib->pHTInfo->bCurrentHTSupport == true) &&\ + (_rtllib->pairwise_key_type == KEY_TYPE_CCMP)) +#endif + +#define HAL_MEMORY_MAPPED_IO_RANGE_8190PCI 0x1000 +#define HAL_HW_PCI_REVISION_ID_8190PCI 0x00 +#define HAL_MEMORY_MAPPED_IO_RANGE_8192PCIE 0x4000 +#define HAL_HW_PCI_REVISION_ID_8192PCIE 0x01 +#define HAL_MEMORY_MAPPED_IO_RANGE_8192SE 0x4000 +#define HAL_HW_PCI_REVISION_ID_8192SE 0x10 +#define HAL_HW_PCI_REVISION_ID_8192CE 0x1 +#define HAL_MEMORY_MAPPED_IO_RANGE_8192CE 0x4000 +#define HAL_HW_PCI_REVISION_ID_8192DE 0x0 +#define HAL_MEMORY_MAPPED_IO_RANGE_8192DE 0x4000 + +#define HAL_HW_PCI_8180_DEVICE_ID 0x8180 +#define HAL_HW_PCI_8185_DEVICE_ID 0x8185 +#define HAL_HW_PCI_8188_DEVICE_ID 0x8188 +#define HAL_HW_PCI_8198_DEVICE_ID 0x8198 +#define HAL_HW_PCI_8190_DEVICE_ID 0x8190 +#define HAL_HW_PCI_8192_DEVICE_ID 0x8192 +#define HAL_HW_PCI_8192SE_DEVICE_ID 0x8192 +#define HAL_HW_PCI_8174_DEVICE_ID 0x8174 +#define HAL_HW_PCI_8173_DEVICE_ID 0x8173 +#define HAL_HW_PCI_8172_DEVICE_ID 0x8172 +#define HAL_HW_PCI_8171_DEVICE_ID 0x8171 +#define HAL_HW_PCI_0045_DEVICE_ID 0x0045 +#define HAL_HW_PCI_0046_DEVICE_ID 0x0046 +#define HAL_HW_PCI_0044_DEVICE_ID 0x0044 +#define HAL_HW_PCI_0047_DEVICE_ID 0x0047 +#define HAL_HW_PCI_700F_DEVICE_ID 0x700F +#define HAL_HW_PCI_701F_DEVICE_ID 0x701F +#define HAL_HW_PCI_DLINK_DEVICE_ID 0x3304 +#define HAL_HW_PCI_8192CET_DEVICE_ID 0x8191 +#define HAL_HW_PCI_8192CE_DEVICE_ID 0x8178 +#define HAL_HW_PCI_8191CE_DEVICE_ID 0x8177 +#define HAL_HW_PCI_8188CE_DEVICE_ID 0x8176 +#define HAL_HW_PCI_8192CU_DEVICE_ID 0x8191 +#define HAL_HW_PCI_8192DE_DEVICE_ID 0x092D +#define HAL_HW_PCI_8192DU_DEVICE_ID 0x092D + +#ifdef RTL8192CE +#define RTL819X_DEFAULT_RF_TYPE RF_2T2R +#else +#define RTL819X_DEFAULT_RF_TYPE RF_1T2R +#endif + +#define RTLLIB_WATCH_DOG_TIME 2000 + +#define MAX_DEV_ADDR_SIZE 8 /* support till 64 bit bus width OS */ +#define MAX_FIRMWARE_INFORMATION_SIZE 32 +#define MAX_802_11_HEADER_LENGTH (40 + MAX_FIRMWARE_INFORMATION_SIZE) +#define ENCRYPTION_MAX_OVERHEAD 128 +#define MAX_FRAGMENT_COUNT 8 +#define MAX_TRANSMIT_BUFFER_SIZE (1600+(MAX_802_11_HEADER_LENGTH+ENCRYPTION_MAX_OVERHEAD)*MAX_FRAGMENT_COUNT) + +#define scrclng 4 + +#define DEFAULT_FRAG_THRESHOLD 2342U +#define MIN_FRAG_THRESHOLD 256U +#define DEFAULT_BEACONINTERVAL 0x64U + +#define DEFAULT_SSID "" +#define DEFAULT_RETRY_RTS 7 +#define DEFAULT_RETRY_DATA 7 +#define PRISM_HDR_SIZE 64 + +#define PHY_RSSI_SLID_WIN_MAX 100 + +#define RTL_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30 + +#define TxBBGainTableLength 37 +#define CCKTxBBGainTableLength 23 + +#define CHANNEL_PLAN_LEN 10 +#define sCrcLng 4 + +#define NIC_SEND_HANG_THRESHOLD_NORMAL 4 +#define NIC_SEND_HANG_THRESHOLD_POWERSAVE 8 + +#define MAX_TX_QUEUE 9 + +#if defined RTL8192SE || defined RTL8192CE +#define MAX_RX_QUEUE 2 +#else +#define MAX_RX_QUEUE 1 +#endif + +#define MAX_RX_COUNT 64 +#define MAX_TX_QUEUE_COUNT 9 + +enum RTL819x_PHY_PARAM { + RTL819X_PHY_MACPHY_REG = 0, + RTL819X_PHY_MACPHY_REG_PG = 1, + RTL8188C_PHY_MACREG =2, + RTL8192C_PHY_MACREG =3, + RTL819X_PHY_REG = 4, + RTL819X_PHY_REG_1T2R = 5, + RTL819X_PHY_REG_to1T1R = 6, + RTL819X_PHY_REG_to1T2R = 7, + RTL819X_PHY_REG_to2T2R = 8, + RTL819X_PHY_REG_PG = 9, + RTL819X_AGC_TAB = 10, + RTL819X_PHY_RADIO_A =11, + RTL819X_PHY_RADIO_A_1T =12, + RTL819X_PHY_RADIO_A_2T =13, + RTL819X_PHY_RADIO_B =14, + RTL819X_PHY_RADIO_B_GM =15, + RTL819X_PHY_RADIO_C =16, + RTL819X_PHY_RADIO_D =17, + RTL819X_EEPROM_MAP =18, + RTL819X_EFUSE_MAP =19, +}; + +enum RTL_DEBUG { + COMP_TRACE = BIT0, + COMP_DBG = BIT1, + COMP_INIT = BIT2, + COMP_RECV = BIT3, + COMP_SEND = BIT4, + COMP_CMD = BIT5, + COMP_POWER = BIT6, + COMP_EPROM = BIT7, + COMP_SWBW = BIT8, + COMP_SEC = BIT9, + COMP_LPS = BIT10, + COMP_QOS = BIT11, + COMP_RATE = BIT12, + COMP_RXDESC = BIT13, + COMP_PHY = BIT14, + COMP_DIG = BIT15, + COMP_TXAGC = BIT16, + COMP_HALDM = BIT17, + COMP_POWER_TRACKING = BIT18, + COMP_CH = BIT19, + COMP_RF = BIT20, + COMP_FIRMWARE = BIT21, + COMP_HT = BIT22, + COMP_RESET = BIT23, + COMP_CMDPKT = BIT24, + COMP_SCAN = BIT25, + COMP_PS = BIT26, + COMP_DOWN = BIT27, + COMP_INTR = BIT28, + COMP_LED = BIT29, + COMP_MLME = BIT30, + COMP_ERR = BIT31 +}; + +typedef enum{ + NIC_UNKNOWN = 0, + NIC_8192E = 1, + NIC_8190P = 2, + NIC_8192SE = 4, + NIC_8192CE = 5, + NIC_8192CU = 6, + NIC_8192DE = 7, + NIC_8192DU = 8, + } nic_t; + +typedef enum _RT_EEPROM_TYPE{ + EEPROM_93C46, + EEPROM_93C56, + EEPROM_BOOT_EFUSE, +}RT_EEPROM_TYPE,*PRT_EEPROM_TYPE; + +typedef enum _tag_TxCmd_Config_Index{ + TXCMD_TXRA_HISTORY_CTRL = 0xFF900000, + TXCMD_RESET_TX_PKT_BUFF = 0xFF900001, + TXCMD_RESET_RX_PKT_BUFF = 0xFF900002, + TXCMD_SET_TX_DURATION = 0xFF900003, + TXCMD_SET_RX_RSSI = 0xFF900004, + TXCMD_SET_TX_PWR_TRACKING = 0xFF900005, + TXCMD_XXXX_CTRL, +}DCMD_TXCMD_OP; + +typedef enum _RT_RF_TYPE_819xU{ + RF_TYPE_MIN = 0, + RF_8225, + RF_8256, + RF_8258, + RF_6052=4, + RF_PSEUDO_11N = 5, +}RT_RF_TYPE_819xU, *PRT_RF_TYPE_819xU; + +typedef enum tag_Rf_Operatetion_State +{ + RF_STEP_INIT = 0, + RF_STEP_NORMAL, + RF_STEP_MAX +}RF_STEP_E; + +typedef enum _RT_STATUS{ + RT_STATUS_SUCCESS, + RT_STATUS_FAILURE, + RT_STATUS_PENDING, + RT_STATUS_RESOURCE +}RT_STATUS,*PRT_STATUS; + +typedef enum _RT_CUSTOMER_ID +{ + RT_CID_DEFAULT = 0, + RT_CID_8187_ALPHA0 = 1, + RT_CID_8187_SERCOMM_PS = 2, + RT_CID_8187_HW_LED = 3, + RT_CID_8187_NETGEAR = 4, + RT_CID_WHQL = 5, + RT_CID_819x_CAMEO = 6, + RT_CID_819x_RUNTOP = 7, + RT_CID_819x_Senao = 8, + RT_CID_TOSHIBA = 9, + RT_CID_819x_Netcore = 10, + RT_CID_Nettronix = 11, + RT_CID_DLINK = 12, + RT_CID_PRONET = 13, + RT_CID_COREGA = 14, + RT_CID_819x_ALPHA = 15, + RT_CID_819x_Sitecom = 16, + RT_CID_CCX = 17, + RT_CID_819x_Lenovo = 18, + RT_CID_819x_QMI = 19, + RT_CID_819x_Edimax_Belkin = 20, + RT_CID_819x_Sercomm_Belkin = 21, + RT_CID_819x_CAMEO1 = 22, + RT_CID_819x_MSI = 23, + RT_CID_819x_Acer = 24, + RT_CID_819x_HP =27, + RT_CID_819x_CLEVO = 28, + RT_CID_819x_Arcadyan_Belkin = 29, + RT_CID_819x_SAMSUNG = 30, + RT_CID_819x_WNC_COREGA = 31, + RT_CID_819x_Foxcoon = 32, + RT_CID_819x_DELL = 33, +}RT_CUSTOMER_ID, *PRT_CUSTOMER_ID; + +typedef enum _RESET_TYPE { + RESET_TYPE_NORESET = 0x00, + RESET_TYPE_NORMAL = 0x01, + RESET_TYPE_SILENT = 0x02 +} RESET_TYPE; + +typedef enum _IC_INFERIORITY_8192S{ + IC_INFERIORITY_A = 0, + IC_INFERIORITY_B = 1, +}IC_INFERIORITY_8192S, *PIC_INFERIORITY_8192S; + +typedef enum _PCI_BRIDGE_VENDOR { + PCI_BRIDGE_VENDOR_INTEL = 0x0, + PCI_BRIDGE_VENDOR_ATI, + PCI_BRIDGE_VENDOR_AMD, + PCI_BRIDGE_VENDOR_SIS , + PCI_BRIDGE_VENDOR_UNKNOWN, + PCI_BRIDGE_VENDOR_MAX , +} PCI_BRIDGE_VENDOR; + +typedef struct buffer +{ + struct buffer *next; + u32 *buf; + dma_addr_t dma; + +} buffer; + +typedef struct rtl_reg_debug{ + unsigned int cmd; + struct { + unsigned char type; + unsigned char addr; + unsigned char page; + unsigned char length; + } head; + unsigned char buf[0xff]; +}rtl_reg_debug; + +typedef struct _rt_9x_tx_rate_history { + u32 cck[4]; + u32 ofdm[8]; + u32 ht_mcs[4][16]; +}rt_tx_rahis_t, *prt_tx_rahis_t; + +typedef struct _RT_SMOOTH_DATA_4RF { + char elements[4][100]; + u32 index; + u32 TotalNum; + u32 TotalVal[4]; +}RT_SMOOTH_DATA_4RF, *PRT_SMOOTH_DATA_4RF; + +typedef struct _RT_SMOOTH_DATA { + u32 elements[100]; + u32 index; + u32 TotalNum; + u32 TotalVal; +}RT_SMOOTH_DATA, *PRT_SMOOTH_DATA; + +typedef struct Stats +{ + unsigned long txrdu; + unsigned long rxrdu; + unsigned long rxok; + unsigned long rxframgment; + unsigned long rxcmdpkt[4]; + unsigned long rxurberr; + unsigned long rxstaterr; + unsigned long rxdatacrcerr; + unsigned long rxmgmtcrcerr; + unsigned long rxcrcerrmin; + unsigned long rxcrcerrmid; + unsigned long rxcrcerrmax; + unsigned long received_rate_histogram[4][32]; + unsigned long received_preamble_GI[2][32]; + unsigned long rx_AMPDUsize_histogram[5]; + unsigned long rx_AMPDUnum_histogram[5]; + unsigned long numpacket_matchbssid; + unsigned long numpacket_toself; + unsigned long num_process_phyinfo; + unsigned long numqry_phystatus; + unsigned long numqry_phystatusCCK; + unsigned long numqry_phystatusHT; + unsigned long received_bwtype[5]; + unsigned long txnperr; + unsigned long txnpdrop; + unsigned long txresumed; + unsigned long rxoverflow; + unsigned long rxint; + unsigned long txnpokint; + unsigned long ints; + unsigned long shints; + unsigned long txoverflow; + unsigned long txlpokint; + unsigned long txlpdrop; + unsigned long txlperr; + unsigned long txbeokint; + unsigned long txbedrop; + unsigned long txbeerr; + unsigned long txbkokint; + unsigned long txbkdrop; + unsigned long txbkerr; + unsigned long txviokint; + unsigned long txvidrop; + unsigned long txvierr; + unsigned long txvookint; + unsigned long txvodrop; + unsigned long txvoerr; + unsigned long txbeaconokint; + unsigned long txbeacondrop; + unsigned long txbeaconerr; + unsigned long txmanageokint; + unsigned long txmanagedrop; + unsigned long txmanageerr; + unsigned long txcmdpktokint; + unsigned long txdatapkt; + unsigned long txfeedback; + unsigned long txfeedbackok; + unsigned long txoktotal; + unsigned long txokbytestotal; + unsigned long txokinperiod; + unsigned long txmulticast; + unsigned long txbytesmulticast; + unsigned long txbroadcast; + unsigned long txbytesbroadcast; + unsigned long txunicast; + unsigned long txbytesunicast; + unsigned long rxbytesunicast; + unsigned long txfeedbackfail; + unsigned long txerrtotal; + unsigned long txerrbytestotal; + unsigned long txerrmulticast; + unsigned long txerrbroadcast; + unsigned long txerrunicast; + unsigned long txretrycount; + unsigned long txfeedbackretry; + u8 last_packet_rate; + unsigned long slide_signal_strength[100]; + unsigned long slide_evm[100]; + unsigned long slide_rssi_total; + unsigned long slide_evm_total; + long signal_strength; + long signal_quality; + long last_signal_strength_inpercent; + long recv_signal_power; + u8 rx_rssi_percentage[4]; + u8 rx_evm_percentage[2]; + long rxSNRdB[4]; + rt_tx_rahis_t txrate; + u32 Slide_Beacon_pwdb[100]; + u32 Slide_Beacon_Total; + RT_SMOOTH_DATA_4RF cck_adc_pwdb; + u32 CurrentShowTxate; + u32 RssiCalculateCnt; + RT_SMOOTH_DATA ui_rssi; + RT_SMOOTH_DATA ui_link_quality; +} Stats; + +typedef struct ChnlAccessSetting { + u16 SIFS_Timer; + u16 DIFS_Timer; + u16 SlotTimeTimer; + u16 EIFS_Timer; + u16 CWminIndex; + u16 CWmaxIndex; +}*PCHANNEL_ACCESS_SETTING,CHANNEL_ACCESS_SETTING; + +typedef enum _TWO_PORT_STATUS +{ + TWO_PORT_STATUS__DEFAULT_ONLY, + TWO_PORT_STATUS__EXTENSION_ONLY, + TWO_PORT_STATUS__EXTENSION_FOLLOW_DEFAULT, + TWO_PORT_STATUS__DEFAULT_G_EXTENSION_N20, + TWO_PORT_STATUS__ADHOC, + TWO_PORT_STATUS__WITHOUT_ANY_ASSOCIATE +}TWO_PORT_STATUS; + +typedef struct _txbbgain_struct +{ + long txbb_iq_amplifygain; + u32 txbbgain_value; +} txbbgain_struct, *ptxbbgain_struct; + +typedef struct _ccktxbbgain_struct +{ + u8 ccktxbb_valuearray[8]; +} ccktxbbgain_struct,*pccktxbbgain_struct; + +typedef struct _init_gain +{ + u8 xaagccore1; + u8 xbagccore1; + u8 xcagccore1; + u8 xdagccore1; + u8 cca; + +} init_gain, *pinit_gain; + +typedef struct _tx_ring{ + u32 * desc; + u8 nStuckCount; + struct _tx_ring * next; +}__attribute__ ((packed)) tx_ring, * ptx_ring; + +struct rtl8192_tx_ring { + tx_desc *desc; + dma_addr_t dma; + unsigned int idx; + unsigned int entries; + struct sk_buff_head queue; +}; + + + +struct rtl819x_ops{ + nic_t nic_type; + void (* get_eeprom_size)(struct net_device* dev); + void (* init_adapter_variable)(struct net_device* dev); + void (* init_before_adapter_start)(struct net_device* dev); + bool (* initialize_adapter)(struct net_device* dev); + void (*link_change)(struct net_device* dev); + void (* tx_fill_descriptor)(struct net_device* dev, tx_desc * tx_desc, cb_desc * cb_desc, struct sk_buff *skb); + void (* tx_fill_cmd_descriptor)(struct net_device* dev, tx_desc_cmd * entry, cb_desc * cb_desc, struct sk_buff *skb); + bool (* rx_query_status_descriptor)(struct net_device* dev, struct rtllib_rx_stats* stats, rx_desc *pdesc, struct sk_buff* skb); + bool (* rx_command_packet_handler)(struct net_device *dev, struct sk_buff* skb, rx_desc *pdesc); + void (* stop_adapter)(struct net_device *dev, bool reset); +#if defined RTL8192SE || defined RTL8192CE + void (* update_ratr_table)(struct net_device* dev,u8* pMcsRate,struct sta_info* pEntry); +#else + void (* update_ratr_table)(struct net_device* dev); +#endif + void (* irq_enable)(struct net_device* dev); + void (* irq_disable)(struct net_device* dev); + void (* irq_clear)(struct net_device* dev); + void (* rx_enable)(struct net_device* dev); + void (* tx_enable)(struct net_device* dev); + void (* interrupt_recognized)(struct net_device *dev, u32 *p_inta, u32 *p_intb); + bool (* TxCheckStuckHandler)(struct net_device* dev); + bool (* RxCheckStuckHandler)(struct net_device* dev); +}; + +typedef struct r8192_priv +{ + struct pci_dev *pdev; + struct pci_dev *bridge_pdev; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) + u32 pci_state; +#endif + + bool bfirst_init; + bool bfirst_after_down; + bool initialized_at_probe; + bool being_init_adapter; + bool bDriverIsGoingToUnload; + + int irq; + short irq_enabled; + + short up; + short up_first_time; +#ifdef _RTL8192_EXT_PATCH_ + short mesh_up; +#endif + + delayed_work_struct_rsl update_beacon_wq; + delayed_work_struct_rsl watch_dog_wq; + delayed_work_struct_rsl txpower_tracking_wq; + delayed_work_struct_rsl rfpath_check_wq; + delayed_work_struct_rsl gpio_change_rf_wq; + delayed_work_struct_rsl initialgain_operate_wq; + delayed_work_struct_rsl check_hw_scan_wq; + delayed_work_struct_rsl hw_scan_simu_wq; + delayed_work_struct_rsl start_hw_scan_wq; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct workqueue_struct *priv_wq; +#else + u32 *priv_wq; +#endif + +#ifdef _RTL8192_EXT_PATCH_ + struct mshclass *mshobj; +#endif + + CHANNEL_ACCESS_SETTING ChannelAccessSetting; + + mp_adapter NdisAdapter; + + struct rtl819x_ops *ops; + struct rtllib_device *rtllib; + +#ifdef CONFIG_BT_30 + BT30Info BtInfo; + delayed_work_struct_rsl HCICmdWorkItem; + delayed_work_struct_rsl HCISendACLDataWorkItem; + delayed_work_struct_rsl HCISendBeaconWorkItem; +#endif + +#ifdef CONFIG_RTLWIFI_DEBUGFS + rtl_fs_debug *debug; +#endif /* CONFIG_IWLWIFI_DEBUGFS */ + + work_struct_rsl reset_wq; + + LOG_INTERRUPT_8190_T InterruptLog; + + RT_CUSTOMER_ID CustomerID; + + + RT_RF_TYPE_819xU rf_chip; + IC_INFERIORITY_8192S IC_Class; + HT_CHANNEL_WIDTH CurrentChannelBW; + BB_REGISTER_DEFINITION_T PHYRegDef[4]; + rate_adaptive rate_adaptive; + + ccktxbbgain_struct cck_txbbgain_table[CCKTxBBGainTableLength]; + ccktxbbgain_struct cck_txbbgain_ch14_table[CCKTxBBGainTableLength]; + + txbbgain_struct txbbgain_table[TxBBGainTableLength]; + + ACM_METHOD AcmMethod; + +#if defined RTL8192SE || defined RTL8192CE + LED_STRATEGY_8190 LedStrategy; + LED_8190 SwLed0; + LED_8190 SwLed1; +#endif + + prt_firmware pFirmware; + rtl819x_loopback_e LoopbackMode; + firmware_source_e firmware_source; + + struct timer_list watch_dog_timer; + struct timer_list fsync_timer; + struct timer_list gpio_polling_timer; + + spinlock_t fw_scan_lock; + spinlock_t irq_lock; + spinlock_t irq_th_lock; + spinlock_t tx_lock; + spinlock_t rf_ps_lock; + spinlock_t rw_lock; + spinlock_t rt_h2c_lock; +#ifdef CONFIG_ASPM_OR_D3 + spinlock_t D3_lock; +#endif + spinlock_t rf_lock; + spinlock_t ps_lock; + + struct sk_buff_head rx_queue; + struct sk_buff_head skb_queue; + + struct tasklet_struct irq_rx_tasklet; + struct tasklet_struct irq_tx_tasklet; + struct tasklet_struct irq_prepare_beacon_tasklet; + + struct semaphore wx_sem; + struct semaphore rf_sem; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)) + struct semaphore mutex; +#else + struct mutex mutex; +#endif + + struct Stats stats; + struct iw_statistics wstats; + struct proc_dir_entry *dir_dev; + + short (*rf_set_sens)(struct net_device *dev,short sens); + u8 (*rf_set_chan)(struct net_device *dev,u8 ch); + void (*rf_close)(struct net_device *dev); + void (*rf_init)(struct net_device *dev); + +#ifdef CONFIG_CFG_80211 + struct ieee80211_rate rates[IEEE80211_NUM_BANDS][RTL_RATE_MAX]; + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; +#endif + + rx_desc *rx_ring[MAX_RX_QUEUE]; + struct sk_buff *rx_buf[MAX_RX_QUEUE][MAX_RX_COUNT]; + dma_addr_t rx_ring_dma[MAX_RX_QUEUE]; + unsigned int rx_idx[MAX_RX_QUEUE]; + int rxringcount; + u16 rxbuffersize; + + u32 LastRxDescTSFHigh; + u32 LastRxDescTSFLow; + + u16 EarlyRxThreshold; + u32 ReceiveConfig; + u8 AcmControl; + u8 RFProgType; + u8 retry_data; + u8 retry_rts; + u16 rts; + + struct rtl8192_tx_ring tx_ring[MAX_TX_QUEUE_COUNT]; + int txringcount; + int txbuffsize; + int txfwbuffersize; + atomic_t tx_pending[0x10]; + + u16 ShortRetryLimit; + u16 LongRetryLimit; + u32 TransmitConfig; + u8 RegCWinMin; + u8 keepAliveLevel; + +#ifdef CONFIG_RTL_RFKILL + bool rfkill_off; +#endif + bool sw_radio_on; + bool bHwRadioOff; + bool pwrdown; + bool blinked_ingpio; + u8 polling_timer_on; + + /**********************************************************/ + + enum card_type {PCI,MINIPCI,CARDBUS,USB}card_type; + + work_struct_rsl qos_activate; + + u8 bIbssCoordinator; + + short promisc; + short crcmon; + + int txbeaconcount; + + short chan; + short sens; + short max_sens; + u32 rx_prevlen; + + u8 ScanDelay; + bool ps_force; + + u32 irq_mask[2]; + + long RSSI_sum; + long RSSI_cnt; + + u8 Rf_Mode; + nic_t card_8192; + u8 card_8192_version; + + short enable_gpio0; + + u8 rf_type; + u8 IC_Cut; + char nick[IW_ESSID_MAX_SIZE + 1]; + + u32 RegBcnCtrlVal; + u8 AntDivCfg; + + bool bTKIPinNmodeFromReg; + bool bWEPinNmodeFromReg; + + bool bLedOpenDrain; + + u8 check_roaming_cnt; + + bool bIgnoreSilentReset; + u32 SilentResetRxSoltNum; + u32 SilentResetRxSlotIndex; + u32 SilentResetRxStuckEvent[MAX_SILENT_RESET_RX_SLOT_NUM]; + + void *scan_cmd; + u8 hwscan_bw_40; + + u16 nrxAMPDU_size; + u8 nrxAMPDU_aggr_num; + + u32 last_rxdesc_tsf_high; + u32 last_rxdesc_tsf_low; + + + u16 basic_rate; + u8 short_preamble; + u8 dot11CurrentPreambleMode; + u8 slot_time; + u16 SifsTime; + + u8 RegWirelessMode; + + u8 firmware_version; + u16 FirmwareSubVersion; + u16 rf_pathmap; + bool AutoloadFailFlag; + + u8 RegPciASPM; + u8 RegAMDPciASPM; + u8 RegHwSwRfOffD3; + u8 RegSupportPciASPM; + bool bSupportASPM; + bool bSupportBackDoor; + + bool bCurrentMrcSwitch; + u8 CurrentTxRate; + + u32 RfRegChnlVal[2]; + + u8 ShowRateMode; + u8 RATRTableBitmap; + + u8 EfuseMap[2][HWSET_MAX_SIZE_92S]; + u16 EfuseUsedBytes; + u8 EfuseUsedPercentage; + +#ifdef EFUSE_REPG_WORKAROUND + bool efuse_RePGSec1Flag; + u8 efuse_RePGData[8]; +#endif + + short epromtype; + u16 eeprom_vid; + u16 eeprom_did; + u16 eeprom_svid; + u16 eeprom_smid; + u8 eeprom_CustomerID; + u16 eeprom_ChannelPlan; + u8 eeprom_version; + + u8 EEPROMRegulatory; + u8 EEPROMPwrGroup[2][3]; + u8 EEPROMOptional; + +#if (EEPROM_OLD_FORMAT_SUPPORT == 1) + u8 EEPROMTxPowerLevelCCK[14]; + u8 EEPROMTxPowerLevelOFDM24G[14]; + u8 EEPROMTxPowerLevelOFDM5G[24]; +#else + u8 RfCckChnlAreaTxPwr[2][3]; + u8 RfOfdmChnlAreaTxPwr1T[2][3]; + u8 RfOfdmChnlAreaTxPwr2T[2][3]; +#endif + u8 EEPROMRfACCKChnl1TxPwLevel[3]; + u8 EEPROMRfAOfdmChnlTxPwLevel[3]; + u8 EEPROMRfCCCKChnl1TxPwLevel[3]; + u8 EEPROMRfCOfdmChnlTxPwLevel[3]; +#if defined (RTL8192S_WAPI_SUPPORT) + u8 EEPROMWapiSupport; + u8 WapiSupport; +#endif + u16 EEPROMTxPowerDiff; + u16 EEPROMAntPwDiff; + u8 EEPROMThermalMeter; + u8 EEPROMPwDiff; + u8 EEPROMCrystalCap; + + u8 EEPROMBluetoothCoexist; + u8 EEPROMBluetoothType; + u8 EEPROMBluetoothAntNum; + u8 EEPROMBluetoothAntIsolation; + u8 EEPROMBluetoothRadioShared; + + + u8 EEPROMSupportWoWLAN; + u8 EEPROMBoardType; + u8 EEPROM_Def_Ver; + u8 EEPROMHT2T_TxPwr[6]; + u8 EEPROMTSSI_A; + u8 EEPROMTSSI_B; + u8 EEPROMTxPowerLevelCCK_V1[3]; + u8 EEPROMLegacyHTTxPowerDiff; + + u8 BluetoothCoexist; + + u8 CrystalCap; + u8 ThermalMeter[2]; + + u16 FwCmdIOMap; + u32 FwCmdIOParam; + + u8 SwChnlInProgress; + u8 SwChnlStage; + u8 SwChnlStep; + u8 SetBWModeInProgress; + + u8 nCur40MhzPrimeSC; + + u32 RfReg0Value[4]; + u8 NumTotalRFPath; + bool brfpath_rxenable[4]; + + bool bTXPowerDataReadFromEEPORM; + + u16 RegChannelPlan; + u16 ChannelPlan; + bool bChnlPlanFromHW; + + bool RegRfOff; + bool isRFOff; + bool bInPowerSaveMode; + u8 bHwRfOffAction; + + bool aspm_clkreq_enable; + u32 pci_bridge_vendor; + u8 RegHostPciASPMSetting; + u8 RegDevicePciASPMSetting; + + bool RFChangeInProgress; + bool SetRFPowerStateInProgress; + bool bdisable_nic; + + u8 pwrGroupCnt; + + u8 ThermalValue_LCK; + u8 ThermalValue_IQK; + bool bRfPiEnable; + + u32 APKoutput[2][2]; + bool bAPKdone; + + long RegE94; + long RegE9C; + long RegEB4; + long RegEBC; + + u32 RegC04; + u32 Reg874; + u32 RegC08; + u32 ADDA_backup[16]; +#if defined RTL8192CE + u32 IQK_MAC_backup[IQK_MAC_REG_NUM]; +#endif + + bool SetFwCmdInProgress; + u8 CurrentFwCmdIO; + + u8 rssi_level; + + bool bInformFWDriverControlDM; + u8 PwrGroupHT20[2][14]; + u8 PwrGroupHT40[2][14]; + + u8 ThermalValue; + long EntryMinUndecoratedSmoothedPWDB; + long EntryMaxUndecoratedSmoothedPWDB; + u8 DynamicTxHighPowerLvl; + u8 LastDTPLvl; + u32 CurrentRATR0; + FALSE_ALARM_STATISTICS FalseAlmCnt; + + u8 DMFlag; + u8 DM_Type; + + u8 CckPwEnl; + u16 TSSI_13dBm; + u32 Pwr_Track; + u8 CCKPresentAttentuation_20Mdefault; + u8 CCKPresentAttentuation_40Mdefault; + char CCKPresentAttentuation_difference; + char CCKPresentAttentuation; + u8 bCckHighPower; + long undecorated_smoothed_pwdb; + long undecorated_smoothed_cck_adc_pwdb[4]; + +#if defined RTL8192CE + u32 MCSTxPowerLevelOriginalOffset[4][16]; +#elif defined RTL8192SE + u32 MCSTxPowerLevelOriginalOffset[4][7]; +#else + u32 MCSTxPowerLevelOriginalOffset[6]; +#endif + u32 CCKTxPowerLevelOriginalOffset; + u8 TxPowerLevelCCK[14]; + u8 TxPowerLevelCCK_A[14]; + u8 TxPowerLevelCCK_C[14]; + u8 TxPowerLevelOFDM24G[14]; + u8 TxPowerLevelOFDM5G[14]; + u8 TxPowerLevelOFDM24G_A[14]; + u8 TxPowerLevelOFDM24G_C[14]; + u8 LegacyHTTxPowerDiff; + u8 TxPowerDiff; + s8 RF_C_TxPwDiff; + s8 RF_B_TxPwDiff; + u8 RfTxPwrLevelCck[2][14]; + u8 RfTxPwrLevelOfdm1T[2][14]; + u8 RfTxPwrLevelOfdm2T[2][14]; + u8 AntennaTxPwDiff[3]; + char TxPwrHt20Diff[2][14]; + u8 TxPwrLegacyHtDiff[2][14]; + u8 TxPwrSafetyFlag; + u8 HT2T_TxPwr_A[14]; + u8 HT2T_TxPwr_B[14]; + u8 CurrentCckTxPwrIdx; + u8 CurrentOfdm24GTxPwrIdx; + + bool bdynamic_txpower; + bool bDynamicTxHighPower; + bool bDynamicTxLowPower; + bool bLastDTPFlag_High; + bool bLastDTPFlag_Low; + + bool bstore_last_dtpflag; + bool bstart_txctrl_bydtp; + + u8 rfa_txpowertrackingindex; + u8 rfa_txpowertrackingindex_real; + u8 rfa_txpowertracking_default; + u8 rfc_txpowertrackingindex; + u8 rfc_txpowertrackingindex_real; + u8 rfc_txpowertracking_default; + bool btxpower_tracking; + bool bcck_in_ch14; + + u8 TxPowerTrackControl; + u8 txpower_count; + bool btxpower_trackingInit; + +#ifdef RTL8192CE + char OFDM_index[2]; + char CCK_index; +#else + u8 OFDM_index[2]; + u8 CCK_index; +#endif + + u8 Record_CCK_20Mindex; + u8 Record_CCK_40Mindex; + + init_gain initgain_backup; + u8 DefaultInitialGain[4]; + bool bis_any_nonbepkts; + bool bcurrent_turbo_EDCA; + bool bis_cur_rdlstate; + + bool bCCKinCH14; + + u8 MidHighPwrTHR_L1; + u8 MidHighPwrTHR_L2; + + bool bfsync_processing; + u32 rate_record; + u32 rateCountDiffRecord; + u32 ContiuneDiffCount; + bool bswitch_fsync; + u8 framesync; + u32 framesyncC34; + u8 framesyncMonitor; + + bool bDMInitialGainEnable; + bool MutualAuthenticationFail; + + bool bDisableFrameBursting; + + u32 reset_count; + bool bpbc_pressed; + + u32 txpower_checkcnt; + u32 txpower_tracking_callback_cnt; + u8 thermal_read_val[40]; + u8 thermal_readback_index; + u32 ccktxpower_adjustcnt_not_ch14; + u32 ccktxpower_adjustcnt_ch14; + + RESET_TYPE ResetProgress; + bool bForcedSilentReset; + bool bDisableNormalResetCheck; + u16 TxCounter; + u16 RxCounter; + int IrpPendingCount; + bool bResetInProgress; + bool force_reset; + bool force_lps; + u8 InitialGainOperateType; + + bool chan_forced; + bool bSingleCarrier; + bool RegBoard; + bool bCckContTx; + bool bOfdmContTx; + bool bStartContTx; + u8 RegPaModel; + u8 btMpCckTxPower; + u8 btMpOfdmTxPower; + + u32 MptActType; + u32 MptIoOffset; + u32 MptIoValue; + u32 MptRfPath; + + u32 MptBandWidth; + u32 MptRateIndex; + u8 MptChannelToSw; + u32 MptRCR; + + u8 PwrDomainProtect; + u8 H2CTxCmdSeq; + +#ifdef RTL8192CE + u8 EEPROMTSSI[2]; + u8 EEPROMPwrLimitHT20[3]; + u8 EEPROMPwrLimitHT40[3]; + u8 EEPROMChnlAreaTxPwrCCK[2][3]; + u8 EEPROMChnlAreaTxPwrHT40_1S[2][3]; + u8 EEPROMChnlAreaTxPwrHT40_2SDiff[2][3]; + u8 TxPwrLevelCck[2][14]; + u8 TxPwrLevelHT40_1S[2][14]; + u8 TxPwrLevelHT40_2S[2][14]; + bool bRPDownloadFinished; + bool bH2CSetInProgress; + u8 SetIOInProgress; + IO_TYPE CurrentIOType; + + u8 CurFwCmdRegSet; + u8 LastHMEBoxNum; + + H2C_CMD_8192C H2CCmd; + + BT_COEXIST_STR bt_coexist; + u8 bRegBT_Iso; + u8 bRegBT_Sco; + u8 bBT_Ampdu; + + bool bAPKThermalMeterIgnore; + bool bInterruptMigration; + bool bDisableTxInt; +#endif + +}r8192_priv; + + +#ifdef _RTL8192_EXT_PATCH_ +struct meshdev_priv { + struct net_device_stats stats; + struct rtllib_device *rtllib; + struct r8192_priv * priv; +}; +#endif + +extern const struct ethtool_ops rtl819x_ethtool_ops; + +#ifdef RTL8192CE +#define Rtl819XFwImageArray Rtl8192CEFwImgArray +#define Rtl819XMAC_Array Rtl8192CEMAC_2T_Array +#define Rtl819XAGCTAB_2TArray Rtl8192CEAGCTAB_2TArray +#define Rtl819XAGCTAB_1TArray Rtl8192CEAGCTAB_1TArray +#define Rtl819XPHY_REG_2TArray Rtl8192CEPHY_REG_2TArray +#define Rtl819XPHY_REG_1TArray Rtl8192CEPHY_REG_1TArray +#define Rtl819XRadioA_2TArray Rtl8192CERadioA_2TArray +#define Rtl819XRadioA_1TArray Rtl8192CERadioA_1TArray +#define Rtl819XRadioB_2TArray Rtl8192CERadioB_2TArray +#define Rtl819XRadioB_1TArray Rtl8192CERadioB_1TArray +#define Rtl819XPHY_REG_Array_PG Rtl8192CEPHY_REG_Array_PG +#endif + +void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb); +short rtl8192_tx(struct net_device *dev, struct sk_buff* skb); + +u8 read_nic_io_byte(struct net_device *dev, int x); +u32 read_nic_io_dword(struct net_device *dev, int x); +u16 read_nic_io_word(struct net_device *dev, int x) ; +void write_nic_io_byte(struct net_device *dev, int x,u8 y); +void write_nic_io_word(struct net_device *dev, int x,u16 y); +void write_nic_io_dword(struct net_device *dev, int x,u32 y); + +u8 read_nic_byte(struct net_device *dev, int x); +u32 read_nic_dword(struct net_device *dev, int x); +u16 read_nic_word(struct net_device *dev, int x) ; +void write_nic_byte(struct net_device *dev, int x,u8 y); +void write_nic_word(struct net_device *dev, int x,u16 y); +void write_nic_dword(struct net_device *dev, int x,u32 y); + +void force_pci_posting(struct net_device *dev); + +void rtl8192_rx_enable(struct net_device *); +void rtl8192_tx_enable(struct net_device *); + +int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev); +void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, int rate); +void rtl8192_data_hard_stop(struct net_device *dev); +void rtl8192_data_hard_resume(struct net_device *dev); +void rtl8192_restart(void *data); +void rtl819x_watchdog_wqcallback(void *data); +void rtl8192_hw_sleep_wq (void *data); +void watch_dog_timer_callback(unsigned long data); +void rtl8192_irq_rx_tasklet(struct r8192_priv *priv); +void rtl8192_irq_tx_tasklet(struct r8192_priv *priv); +int rtl8192_down(struct net_device *dev,bool shutdownrf); +int rtl8192_up(struct net_device *dev); +void rtl8192_commit(struct net_device *dev); +void rtl8192_set_chan(struct net_device *dev,short ch); + +void check_rfctrl_gpio_timer(unsigned long data); + +void rtl8192_hw_wakeup_wq(void *data); +irqreturn_type rtl8192_interrupt(int irq, void *netdev, struct pt_regs *regs); + +short rtl8192_pci_initdescring(struct net_device *dev); + +void rtl8192_cancel_deferred_work(struct r8192_priv* priv); + +int _rtl8192_up(struct net_device *dev,bool is_silent_reset); + +short rtl8192_is_tx_queue_empty(struct net_device *dev); +void rtl8192_irq_disable(struct net_device *dev); + +#ifdef _RTL8192_EXT_PATCH_ +extern int r8192_mesh_set_enc_ext(struct net_device *dev, struct iw_point *encoding, struct iw_encode_ext *ext, u8 *addr); +#ifdef BUILT_IN_MSHCLASS +extern int msh_init(void); +extern void msh_exit(void); +#endif +#endif + + +void rtl8192_tx_timeout(struct net_device *dev); +void rtl8192_pci_resetdescring(struct net_device *dev); +void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode); +void rtl8192_irq_enable(struct net_device *dev); +void rtl8192_config_rate(struct net_device* dev, u16* rate_config); +void rtl8192_update_cap(struct net_device* dev, u16 cap); +void rtl8192_irq_disable(struct net_device *dev); + +void rtl819x_UpdateRxPktTimeStamp (struct net_device *dev, struct rtllib_rx_stats *stats); +long rtl819x_translate_todbm(struct r8192_priv * priv, u8 signal_strength_index ); +void rtl819x_update_rxsignalstatistics8190pci(struct r8192_priv * priv,struct rtllib_rx_stats * pprevious_stats); +u8 rtl819x_evm_dbtopercentage(char value); +void rtl819x_process_cck_rxpathsel(struct r8192_priv * priv,struct rtllib_rx_stats * pprevious_stats); +u8 rtl819x_query_rxpwrpercentage( char antpower ); +void rtl8192_record_rxdesc_forlateruse(struct rtllib_rx_stats * psrc_stats,struct rtllib_rx_stats * ptarget_stats); + +bool NicIFEnableNIC(struct net_device* dev); +bool NicIFDisableNIC(struct net_device* dev); + +bool +MgntActSet_RF_State( + struct net_device* dev, + RT_RF_POWER_STATE StateToSet, + RT_RF_CHANGE_SOURCE ChangeSource, + bool ProtectOrNot + ); +void +ActUpdateChannelAccessSetting( + struct net_device* dev, + WIRELESS_MODE WirelessMode, + PCHANNEL_ACCESS_SETTING ChnlAccessSetting + ); + +#ifdef CONFIG_CFG_80211 +struct net_device *wiphy_to_net_device(struct wiphy *wiphy); +#endif + +#endif + + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_debug.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_debug.c @@ -0,0 +1,1537 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#include "rtl_debug.h" +#include "rtl_core.h" + +#ifdef _RTL8192_EXT_PATCH_ +#include "../../mshclass/msh_class.h" +#endif + +u32 rt_global_debug_component = \ + COMP_ERR ; + +/*------------------Declare variable-----------------------*/ +u32 DBGP_Type[DBGP_TYPE_MAX]; + +/*----------------------------------------------------------------------------- + * Function: DBGP_Flag_Init + * + * Overview: Refresh all debug print control flag content to zero. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 10/20/2006 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +void rtl8192_dbgp_flag_init(struct net_device *dev) +{ + u8 i; + + for (i = 0; i < DBGP_TYPE_MAX; i++) + { + DBGP_Type[i] = 0; + } + + + DBGP_Type[FIOCTL] = \ + IOCTL_TRACE | + IOCTL_BT_EVENT | + IOCTL_BT_EVENT_DETAIL | + IOCTL_BT_TX_ACLDATA | + IOCTL_BT_TX_ACLDATA_DETAIL | + IOCTL_BT_RX_ACLDATA | + IOCTL_BT_RX_ACLDATA_DETAIL | + IOCTL_BT_HCICMD | + IOCTL_BT_HCICMD_DETAIL | + IOCTL_IRP | + IOCTL_IRP_DETAIL | + IOCTL_CALLBACK_FUN | + IOCTL_STATE | + IOCTL_BT_TP | + IOCTL_BT_LOGO | + 0; +} /* DBGP_Flag_Init */ + +/* this is only for debugging */ +void print_buffer(u32 *buffer, int len) +{ + int i; + u8 *buf =(u8*)buffer; + + printk("ASCII BUFFER DUMP (len: %x):\n",len); + + for(i=0;i ", n); + for (i = 0; i < 16 && n <= max; i++, n++) + printk("%2x ", read_nic_byte(dev, n)); + } + printk("\n"); +} + +#ifdef RTL8192CE +void rtl8192ce_dump_tx_desc(tx_desc *pDesc) +{ +#if 0 + RTPRINT(FTX, TX_DESC, ("DW 0 =========\r\n")); + RTPRINT(FTX, TX_DESC, ("Own = %d\n", pDesc->OWN)); + RTPRINT(FTX, TX_DESC, ("GF = %d\n", pDesc->GF)); + RTPRINT(FTX, TX_DESC, ("LINIP = %d\n", pDesc->LINIP)); + RTPRINT(FTX, TX_DESC, ("FS = %d\n", pDesc->FirstSeg)); + RTPRINT(FTX, TX_DESC, ("LS = %d\n", pDesc->LastSeg)); + RTPRINT(FTX, TX_DESC, ("Offset = %d\n", pDesc->Offset)); + RTPRINT(FTX, TX_DESC, ("PktSize = %d\r\n", pDesc->PktSize)); + + RTPRINT(FTX, TX_DESC, ("DW 1 ==========\r\n")); + RTPRINT(FTX, TX_DESC, ("PKTOFFSET = %d\n", pDesc->PktOffset)); + RTPRINT(FTX, TX_DESC, ("HTC = %d\n", pDesc->HTC)); + RTPRINT(FTX, TX_DESC, ("SecType = %d\n", pDesc->SecType)); + RTPRINT(FTX, TX_DESC, ("EnDescID = %d\n", pDesc->EnDescID)); + RTPRINT(FTX, TX_DESC, ("NoACM = %d\n", pDesc->NOACM)); + RTPRINT(FTX, TX_DESC, ("QueueSelect = %d\n", pDesc->QueueSel)); + RTPRINT(FTX, TX_DESC, ("PIFS = %d\n", pDesc->PIFS)); + RTPRINT(FTX, TX_DESC, ("MoreFrag = %d\n", pDesc->MoreFrag)); + RTPRINT(FTX, TX_DESC, ("MacID = %d\r\n", pDesc->MacID)); + + RTPRINT(FTX, TX_DESC, ("DW 2 ==========\r\n")); + RTPRINT(FTX, TX_DESC, ("BK = %d\n", pDesc->Bk)); + RTPRINT(FTX, TX_DESC, ("AGG_EN = %d\n", pDesc->AggEn)); + RTPRINT(FTX, TX_DESC, ("Data Retry CNT = %d\n", pDesc->DATARC)); + RTPRINT(FTX, TX_DESC, ("RTS Retry CNT = %d\n", pDesc->RTSRC)); + RTPRINT(FTX, TX_DESC, ("TSFL = %d\n", pDesc->TSFL)); + RTPRINT(FTX, TX_DESC, ("RetryLmtEn = %d\n", pDesc->RetryLmtEn)); + RTPRINT(FTX, TX_DESC, ("DataRetryLmt = %d\r\n", pDesc->TxRetryLmt)); + + RTPRINT(FTX, TX_DESC, ("DW 3 ==========\r\n")); + RTPRINT(FTX, TX_DESC, ("Seq = %d\n", pDesc->Seq)); + RTPRINT(FTX, TX_DESC, ("TailPage = %d\n", pDesc->TailPage)); + RTPRINT(FTX, TX_DESC, ("NextHeadPage = %d\r\n", pDesc->NextHeadPage)); + + RTPRINT(FTX, TX_DESC, ("DW 4 ==========\r\n")); + RTPRINT(FTX, TX_DESC, ("UserRate = %d\n", pDesc->UserRate)); + RTPRINT(FTX, TX_DESC, ("RTS STBC = %d\n", pDesc->RTSSTBC)); + RTPRINT(FTX, TX_DESC, ("RTSSC = %d\n", pDesc->RTSSC)); + RTPRINT(FTX, TX_DESC, ("STBC = %d\n", pDesc->STBC)); + RTPRINT(FTX, TX_DESC, ("TXSC = %d\n", pDesc->TxSc)); + RTPRINT(FTX, TX_DESC, ("TxBw = %d\n", pDesc->TxBW)); + RTPRINT(FTX, TX_DESC, ("TxShort = %d\n", pDesc->TxShort)); + RTPRINT(FTX, TX_DESC, ("RTSEn = %d\n", pDesc->RTSEn)); + RTPRINT(FTX, TX_DESC, ("CTS2Self = %d\n", pDesc->CTS2Self)); + RTPRINT(FTX, TX_DESC, ("RTSRateFBLmt = %d\n", pDesc->RTSRateFBLmt)); + RTPRINT(FTX, TX_DESC, ("DisRTSFB = %d\n", pDesc->DisRTSFB)); + RTPRINT(FTX, TX_DESC, ("RTSRate = %d\r\n", pDesc->RTSRate)); + + RTPRINT(FTX, TX_DESC, ("DW 5 ==========\r\n")); + RTPRINT(FTX, TX_DESC, ("TxAGC = %d\n", pDesc->TXAGCA)); + RTPRINT(FTX, TX_DESC, ("TxAGC = %d\n", pDesc->TXAGCB)); + RTPRINT(FTX, TX_DESC, ("DataRateFBLmt = %d\n", pDesc->TxRateFBLmt)); + RTPRINT(FTX, TX_DESC, ("Disable Feedback = %d\n", pDesc->DisDataFB)); + RTPRINT(FTX, TX_DESC, ("TX_Rate = %d\n", pDesc->TxRate)); + RTPRINT(FTX, TX_DESC, ("PktID = %d\r\n", pDesc->PktID)); + + RTPRINT(FTX, TX_DESC, ("DW 6 ==========\r\n")); + + RTPRINT(FTX, TX_DESC, ("DW 7-9 ==========\r\n")); + RTPRINT(FTX, TX_DESC, ("TxBufferSize = %d\r\n", pDesc->TxBufferSize)); + + RTPRINT(FTX, TX_DESC, ("PhyAddressLow = %08x\n", pDesc->TxBuffAddr)); + + RTPRINT(FTX, TX_DESC, ("NextDescAddress= %08X\n", pDesc->NextDescAddress)); +#else + u32* desc = (u32*)pDesc; + u8 i=0; + printk("#########################\n"); + for(i=0;i<=9;i++){ + printk("#########>%x\n", desc[i]); + } + printk("#########################\n\n"); +#endif +} +#endif + +#ifdef RTL8192SE +void rtl8192se_dump_tx_desc(tx_desc* pDesc) +{ + printk("DW 0 =========\r\n"); + printk("Own = %d\n", pDesc->OWN); + printk("GF = %d\n", pDesc->GF); + printk("LINIP = %d\n", pDesc->LINIP); + printk("FS = %d\n", pDesc->FirstSeg); + printk("LS = %d\n", pDesc->LastSeg); + printk("Offset = %d\n", pDesc->Offset); + printk("PktSize = %d\r\n", pDesc->PktSize); + + printk("DW 1 ==========\r\n"); + printk("HWPC = %d\n", pDesc->HWPC); + printk("PKTOFFSET = %d\n", pDesc->PktOffset); + printk("WDS = %d\n", pDesc->WDS); + printk("HTC = %d\n", pDesc->HTC); + printk("SecType = %d\n", pDesc->SecType); + printk("EnDescID = %d\n", pDesc->EnDescID); + printk("PktType = %d\n", pDesc->PktType); + printk("OUI = %d\n", pDesc->OUI); + printk("SecKeyId = %d\n", pDesc->KeyID); + printk("NonQos = %d\n", pDesc->NonQos); + printk("NoACM = %d\n", pDesc->NoACM); + printk("AckPolicy = %d\n", pDesc->AckPolicy); + printk("QueueSelect = %d\n", pDesc->QueueSel); + printk("PIFS = %d\n", pDesc->PIFS); + printk("MoreFrag = %d\n", pDesc->MoreFrag); + printk("MoreData = %d\n", pDesc->MoreData); + printk("MacID = %d\r\n", pDesc->MacID); + + printk("DW 2 ==========\r\n"); + printk("OwnMAC = %d\n", pDesc->OwnMAC); + printk("BK = %d\n", pDesc->BK); + printk("AGG_EN = %d\n", pDesc->AggEn); + printk("Data Retry CNT = %d\n", pDesc->DATARC); + printk("RTS Retry CNT = %d\n", pDesc->RTSRC); + printk("TSFL = %d\n", pDesc->TSFL); + printk("RetryLmtEn = %d\n", pDesc->RetryLmtEn); + printk("DataRetryLmt = %d\r\n", pDesc->DataRetryLmt); + + printk("DW 3 ==========\r\n"); + printk("Frag = %d\n", pDesc->Frag); + printk("Seq = %d\n", pDesc->Seq); + printk("TailPage = %d\n", pDesc->TailPage); + printk("NextHeadPage = %d\r\n", pDesc->NextHeadPage); + + printk("DW 4 ==========\r\n"); + printk("UserRate = %d\n", pDesc->UserRate); + printk("RTS STBC = %d\n", pDesc->RTSSTBC); + printk("RTSSC = %d\n", pDesc->RTSSC); + printk("RTSBW = %d\n", pDesc->RTSBW); + printk("RTSShort = %d\n", pDesc->RTSShort); + printk("RTSHT = %d\n", pDesc->RTSHT); + printk("RD = %d\n", pDesc->RD); + printk("STBC = %d\n", pDesc->STBC); + printk("TXSC = %d\n", pDesc->TXSC); + printk("TxBw = %d\n", pDesc->TxBw); + printk("TxShort = %d\n", pDesc->TxShort); + printk("TXHT = %d\n", pDesc->TXHT); + printk("RaBRSRID = %d\n", pDesc->RaBRSRID); + printk("RTSEn = %d\n", pDesc->RTSEn); + printk("CTS2Self = %d\n", pDesc->CTS2Self); + printk("RTSRateFBLmt = %d\n", pDesc->RTSRateFBLmt); + printk("DisRTSFB = %d\n", pDesc->DisRTSFB); + printk("RTSRate = %d\r\n", pDesc->RTSRate); + + printk("DW 5 ==========\r\n"); + printk("TxAGC = %d\n", pDesc->TxAGC); + printk("DataRateFBLmt = %d\n", pDesc->DataRateFBLmt); + printk("Disable Feedback = %d\n", pDesc->DISFB); + printk("TX_Rate = %d\n", pDesc->TxRate); + printk("PktID = %d\r\n", pDesc->PktID); + + printk("DW 6 ==========\r\n"); + printk("TCPChkSum = %d\n", pDesc->TCPChkSum); + printk("IPChkSum = %d\r\n", pDesc->IPChkSum); + + printk("DW 7-9 ==========\r\n"); + printk("TCPEn = %d\n", pDesc->TCPEn); + printk("IPHdrOffset = %d\n", pDesc->IPHdrOffset); + printk("TxBufferSize = %d\r\n", pDesc->TxBufferSize); + + printk("PhyAddressLow = %08x\n", pDesc->TxBuffAddr); + + printk("NextDescAddress= %08X\n", pDesc->NextDescAddress); +} +#endif + +#ifdef CONFIG_RTLWIFI_DEBUGFS +/* debugfs related stuff */ +static struct dentry *rtl_debugfs_root; +static int rtl_dbgfs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t rtl_dbgfs_register_write(struct file *file, + const char __user *user_buf, + size_t count, + loff_t *ppos) +{ + struct r8192_priv *priv = (struct r8192_priv *)file->private_data; + char buf[32]; + int buf_size; + u32 type, offset; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + + if (sscanf(buf, "%x,%x", &type, &offset ) == 2) { + priv->debug->hw_type = type; + priv->debug->hw_offset = offset; + } else { + priv->debug->hw_type = 0; + priv->debug->hw_offset = 0; + } + + return count; +} + +void rtl_hardware_grab(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int t = 0; + int timeout = 20; + u32 mask = RF_CHANGE_BY_HW|RF_CHANGE_BY_PS|RF_CHANGE_BY_IPS; + + priv->debug->hw_holding = true; +#ifdef ENABLE_IPS + rtllib_ips_leave_wq(dev); +#endif + do { + if ((priv->rtllib->RfOffReason & mask)) { + msleep(100); + t++; + } else { + return; + } + } while (t < timeout); + + return; +} + +static ssize_t rtl_dbgfs_register_read(struct file *file, + char __user *user_buf, + size_t count, + loff_t *ppos) +{ + struct r8192_priv *priv = (struct r8192_priv *)file->private_data; + struct net_device *dev = priv->rtllib->dev; + ssize_t ret = 0; + char buf[2048]; + int n,i; + u32 len = 0; + u32 max = 0xff; + u32 page_no, path; + + rtl_hardware_grab(dev); + + if(!priv->debug->hw_type) { + page_no = (priv->debug->hw_offset > 0x0f)? 0x0f: priv->debug->hw_offset; +#ifdef RTL8192SE + if(page_no >= 0x08 ) { + len += snprintf(buf + len, count - len, + "\n#################### BB page- %x##################\n ", page_no); + for(n=0;n<=max;) + { + len += snprintf(buf + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(buf + len, count - len, + "%8.8x ",rtl8192_QueryBBReg(dev,(page_no << 8|n), + bMaskDWord)); + } + + } else +#endif + { + len += snprintf(buf + len,count - len, + "\n#################### MAC page- %x##################\n ", page_no); + for(n=0;n<=max;) { + len += snprintf(buf + len, count - len, "\nD: %2x > ",n); + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(buf + len, count - len, + "%2.2x ",read_nic_byte(dev,((page_no<<8)|n))); + } + } + } else { + path = (priv->debug->hw_offset < RF90_PATH_MAX)? priv->debug->hw_offset:(RF90_PATH_MAX - 1); + len += snprintf(buf + len, count - len, + "\n#################### RF-PATH-%x ##################\n ", 0x0a+path); + for(n=0;n<=max;) { + len += snprintf(buf+ len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(buf + len, count - len, + "%8.8x ",rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)path,\ + n, bMaskDWord)); + } + } + + priv->debug->hw_holding = false; + + len += snprintf(buf + len, count - len, "\n"); + ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); + return ret; +} + +static const struct file_operations rtl_register_debug = { + .read = rtl_dbgfs_register_read, + .write = rtl_dbgfs_register_write, + .open = rtl_dbgfs_open, + .owner = THIS_MODULE +}; + +int rtl_debug_module_init(struct r8192_priv *priv, const char *name) +{ + rtl_fs_debug *debug; + int ret = 0; + + if (!rtl_debugfs_root) + return -ENOENT; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) + debug = kzalloc(sizeof(rtl_fs_debug), GFP_KERNEL); +#else + rtl_fs_debug = kmalloc(sizeof(*rtl_fs_debug), GFP_KERNEL); + memset(rtl_fs_debug,0,sizeof(*rtl_fs_debug)); +#endif + if (!debug) { + ret = -ENOMEM; + goto err; + } + priv->debug = debug; + + debug->name = name; + debug->dir_drv = debugfs_create_dir(name, rtl_debugfs_root); + if (!debug->dir_drv ) { + ret = -ENOENT; + goto err; + } + + debug->debug_register = debugfs_create_file("debug_register", S_IRUGO, + debug->dir_drv, priv, &rtl_register_debug); + if(!debug->debug_register) { + ret = -ENOENT; + goto err; + } + + return 0; +err: + RT_TRACE(COMP_DBG, "Can't open the debugfs directory\n"); + rtl_debug_module_remove(priv); + return ret; + +} + +void rtl_debug_module_remove(struct r8192_priv *priv) +{ + if (!priv->debug) + return; + debugfs_remove(priv->debug->debug_register); + debugfs_remove(priv->debug->dir_drv); + kfree(priv->debug); + priv->debug = NULL; +} + +int rtl_create_debugfs_root(void) +{ + rtl_debugfs_root = debugfs_create_dir(DRV_NAME, NULL); + if (!rtl_debugfs_root) + return -ENOENT; + + return 0; +} + +void rtl_remove_debugfs_root(void) +{ + debugfs_remove(rtl_debugfs_root); + rtl_debugfs_root = NULL; +} +#endif + +/**************************************************************************** + -----------------------------PROCFS STUFF------------------------- +*****************************************************************************/ +/*This part is related to PROC, which will record some statistics. */ +static struct proc_dir_entry *rtl8192_proc = NULL; + +static int proc_get_stats_ap(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + struct rtllib_network *target; + + int len = 0; + + list_for_each_entry(target, &ieee->network_list, list) { + + len += snprintf(page + len, count - len, + "%s ", target->ssid); + + if(target->wpa_ie_len>0 || target->rsn_ie_len>0){ + len += snprintf(page + len, count - len, + "WPA\n"); + } + else{ + len += snprintf(page + len, count - len, + "non_WPA\n"); + } + + } + + *eof = 1; + return len; +} + +static int proc_get_registers_0(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0x000; + +#ifdef RTL8192SE + /* This dump the current register page */ + if(!IS_BB_REG_OFFSET_92S(page0)){ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, + "\nD: %2x > ",n); + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(page + len, count - len, + "%2.2x ",read_nic_byte(dev,(page0|n))); + } + }else +#endif + { + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + len += snprintf(page + len, count - len, + "\nD: OF > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<16 && n<=max;n++,i++) + len += snprintf(page + len, count - len, + "%2.2x ",read_nic_byte(dev,(page0|n))); + } + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; + +} +static int proc_get_registers_1(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0x100; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + len += snprintf(page + len, count - len, + "\nD: OF > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, + "\nD: %2x > ",n); + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(page + len, count - len, + "%2.2x ",read_nic_byte(dev,(page0|n))); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; + +} +static int proc_get_registers_2(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0x200; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + len += snprintf(page + len, count - len, + "\nD: OF > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, + "\nD: %2x > ",n); + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(page + len, count - len, + "%2.2x ",read_nic_byte(dev,(page0|n))); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; + +} +static int proc_get_registers_3(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0x300; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + len += snprintf(page + len, count - len, + "\nD: OF > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, + "\nD: %2x > ",n); + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(page + len, count - len, + "%2.2x ",read_nic_byte(dev,(page0|n))); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; + +} +static int proc_get_registers_4(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0x400; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + len += snprintf(page + len, count - len, + "\nD: OF > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, + "\nD: %2x > ",n); + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(page + len, count - len, + "%2.2x ",read_nic_byte(dev,(page0|n))); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; + +} +static int proc_get_registers_5(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0x500; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + len += snprintf(page + len, count - len, + "\nD: OF > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, + "\nD: %2x > ",n); + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(page + len, count - len, + "%2.2x ",read_nic_byte(dev,(page0|n))); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; + +} +static int proc_get_registers_6(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0x600; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + len += snprintf(page + len, count - len, + "\nD: OF > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, + "\nD: %2x > ",n); + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(page + len, count - len, + "%2.2x ",read_nic_byte(dev,(page0|n))); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; + +} +static int proc_get_registers_7(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0x700; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + len += snprintf(page + len, count - len, + "\nD: OF > 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, + "\nD: %2x > ",n); + for(i=0;i<16 && n<=max;i++,n++) + len += snprintf(page + len, count - len, + "%2.2x ",read_nic_byte(dev,(page0|n))); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; + +} +static int proc_get_registers_8(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0x800; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(page + len, count - len, + "%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord)); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; + +} +static int proc_get_registers_9(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0x900; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(page + len, count - len, + "%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord)); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} +static int proc_get_registers_a(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0xa00; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(page + len, count - len, + "%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord)); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} +static int proc_get_registers_b(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0xb00; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(page + len, count - len, + "%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord)); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} +static int proc_get_registers_c(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0xc00; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(page + len, count - len, + "%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord)); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} +static int proc_get_registers_d(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0xd00; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(page + len, count - len, + "%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord)); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} +static int proc_get_registers_e(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n,page0; + + int max=0xff; + page0 = 0xe00; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n####################page %x##################\n ", (page0>>8)); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(page + len, count - len, + "%8.8x ",rtl8192_QueryBBReg(dev,(page0|n), bMaskDWord)); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} + +static int proc_get_reg_rf_a(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n; + + int max=0xff; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n#################### RF-A ##################\n "); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(page + len, count - len, + "%8.8x ",rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A,n, bMaskDWord)); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} + +static int proc_get_reg_rf_b(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n; + + int max=0xff; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n#################### RF-B ##################\n "); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(page + len, count - len, + "%8.8x ",rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_B, n, bMaskDWord)); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} + +static int proc_get_reg_rf_c(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n; + + int max=0xff; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n#################### RF-C ##################\n "); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(page + len, count - len, + "%8.8x ",rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_C, n, bMaskDWord)); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} + +static int proc_get_reg_rf_d(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + + int len = 0; + int i,n; + + int max=0xff; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n#################### RF-D ##################\n "); + for(n=0;n<=max;) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",n); + for(i=0;i<4 && n<=max;n+=4,i++) + len += snprintf(page + len, count - len, + "%8.8x ",rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_D, n, bMaskDWord)); + } + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} + +static int proc_get_cam_register_1(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + u32 target_command=0; + u32 target_content=0; + u8 entry_i=0; + u32 ulStatus; + int len = 0; + int i=100, j = 0; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n#################### SECURITY CAM (0-10) ##################\n "); + for(j=0; j<11; j++) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",j); + for(entry_i=0;entry_i=0) + { + ulStatus = read_nic_dword(dev, RWCAM); + if(ulStatus & BIT31){ + continue; + } + else{ + break; + } + } + write_nic_dword(dev, RWCAM, target_command); + target_content = read_nic_dword(dev, RCAMO); + len += snprintf(page + len, count - len,"%8.8x ",target_content); + } + } + + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} + +static int proc_get_cam_register_2(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + u32 target_command=0; + u32 target_content=0; + u8 entry_i=0; + u32 ulStatus; + int len = 0; + int i=100, j = 0; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n#################### SECURITY CAM (11-21) ##################\n "); + for(j=11; j<22; j++) + { + len += snprintf(page + len, count - len, "\nD: %2x > ",j); + for(entry_i=0;entry_i=0) + { + ulStatus = read_nic_dword(dev, RWCAM); + if(ulStatus & BIT31){ + continue; + } + else{ + break; + } + } + write_nic_dword(dev, RWCAM, target_command); + target_content = read_nic_dword(dev, RCAMO); + len += snprintf(page + len, count - len,"%8.8x ",target_content); + } + } + + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} + +static int proc_get_cam_register_3(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + u32 target_command=0; + u32 target_content=0; + u8 entry_i=0; + u32 ulStatus; + int len = 0; + int i=100, j = 0; + + /* This dump the current register page */ + len += snprintf(page + len, count - len, + "\n#################### SECURITY CAM (22-31) ##################\n "); + for(j=22; j ",j); + for(entry_i=0;entry_i=0) + { + ulStatus = read_nic_dword(dev, RWCAM); + if(ulStatus & BIT31){ + continue; + } + else{ + break; + } + } + write_nic_dword(dev, RWCAM, target_command); + target_content = read_nic_dword(dev, RCAMO); + len += snprintf(page + len, count - len,"%8.8x ",target_content); + } + } + + len += snprintf(page + len, count - len,"\n"); + *eof = 1; + return len; +} +static int proc_get_stats_tx(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + int len = 0; + + len += snprintf(page + len, count - len, + "TX VI priority ok int: %lu\n" + "TX VO priority ok int: %lu\n" + "TX BE priority ok int: %lu\n" + "TX BK priority ok int: %lu\n" + "TX MANAGE priority ok int: %lu\n" + "TX BEACON priority ok int: %lu\n" + "TX BEACON priority error int: %lu\n" + "TX CMDPKT priority ok int: %lu\n" + "TX queue stopped?: %d\n" + "TX fifo overflow: %lu\n" + "TX total data packets %lu\n" + "TX total data bytes :%lu\n", + priv->stats.txviokint, + priv->stats.txvookint, + priv->stats.txbeokint, + priv->stats.txbkokint, + priv->stats.txmanageokint, + priv->stats.txbeaconokint, + priv->stats.txbeaconerr, + priv->stats.txcmdpktokint, + netif_queue_stopped(dev), + priv->stats.txoverflow, + priv->rtllib->stats.tx_packets, + priv->rtllib->stats.tx_bytes + + + ); + + *eof = 1; + return len; +} + + + +static int proc_get_stats_rx(char *page, char **start, + off_t offset, int count, + int *eof, void *data) +{ + struct net_device *dev = data; + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + int len = 0; + + len += snprintf(page + len, count - len, + "RX packets: %lu\n" + "RX data crc err: %lu\n" + "RX mgmt crc err: %lu\n" + "RX desc err: %lu\n" + "RX rx overflow error: %lu\n", + priv->stats.rxint, + priv->stats.rxdatacrcerr, + priv->stats.rxmgmtcrcerr, + priv->stats.rxrdu, + priv->stats.rxoverflow); + + *eof = 1; + return len; +} + +void rtl8192_proc_module_init(void) +{ + RT_TRACE(COMP_INIT, "Initializing proc filesystem"); +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + rtl8192_proc=create_proc_entry(DRV_NAME, S_IFDIR, proc_net); +#else + rtl8192_proc=create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net); +#endif +} + + +void rtl8192_proc_module_remove(void) +{ +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + remove_proc_entry(DRV_NAME, proc_net); +#else + remove_proc_entry(DRV_NAME, init_net.proc_net); +#endif +} + + +void rtl8192_proc_remove_one(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + printk("dev name %s\n",dev->name); + + if (priv->dir_dev) { + remove_proc_entry("stats-tx", priv->dir_dev); + remove_proc_entry("stats-rx", priv->dir_dev); + remove_proc_entry("stats-ap", priv->dir_dev); + remove_proc_entry("registers-0", priv->dir_dev); + remove_proc_entry("registers-1", priv->dir_dev); + remove_proc_entry("registers-2", priv->dir_dev); + remove_proc_entry("registers-3", priv->dir_dev); + remove_proc_entry("registers-4", priv->dir_dev); + remove_proc_entry("registers-5", priv->dir_dev); + remove_proc_entry("registers-6", priv->dir_dev); + remove_proc_entry("registers-7", priv->dir_dev); + remove_proc_entry("registers-8", priv->dir_dev); + remove_proc_entry("registers-9", priv->dir_dev); + remove_proc_entry("registers-a", priv->dir_dev); + remove_proc_entry("registers-b", priv->dir_dev); + remove_proc_entry("registers-c", priv->dir_dev); + remove_proc_entry("registers-d", priv->dir_dev); + remove_proc_entry("registers-e", priv->dir_dev); + remove_proc_entry("RF-A", priv->dir_dev); + remove_proc_entry("RF-B", priv->dir_dev); + remove_proc_entry("RF-C", priv->dir_dev); + remove_proc_entry("RF-D", priv->dir_dev); + remove_proc_entry("SEC-CAM-1", priv->dir_dev); + remove_proc_entry("SEC-CAM-2", priv->dir_dev); + remove_proc_entry("SEC-CAM-3", priv->dir_dev); +#ifdef _RTL8192_EXT_PATCH_ + remove_proc_entry("ra0", rtl8192_proc); +#else + remove_proc_entry("wlan0", rtl8192_proc); +#endif + priv->dir_dev = NULL; + } +} + + +void rtl8192_proc_init_one(struct net_device *dev) +{ + struct proc_dir_entry *e; + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + priv->dir_dev = create_proc_entry(dev->name, + S_IFDIR | S_IRUGO | S_IXUGO, + rtl8192_proc); + if (!priv->dir_dev) { + RT_TRACE(COMP_ERR, "Unable to initialize /proc/net/rtl8192/%s\n", + dev->name); + return; + } + e = create_proc_read_entry("stats-rx", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_stats_rx, dev); + + if (!e) { + RT_TRACE(COMP_ERR,"Unable to initialize " + "/proc/net/rtl8192/%s/stats-rx\n", + dev->name); + } + + + e = create_proc_read_entry("stats-tx", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_stats_tx, dev); + + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/stats-tx\n", + dev->name); + } + + e = create_proc_read_entry("stats-ap", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_stats_ap, dev); + + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/stats-ap\n", + dev->name); + } + + e = create_proc_read_entry("registers-0", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_0, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-0\n", + dev->name); + } + e = create_proc_read_entry("registers-1", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_1, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-1\n", + dev->name); + } + e = create_proc_read_entry("registers-2", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_2, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-2\n", + dev->name); + } + e = create_proc_read_entry("registers-3", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_3, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-3\n", + dev->name); + } + e = create_proc_read_entry("registers-4", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_4, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-4\n", + dev->name); + } + e = create_proc_read_entry("registers-5", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_5, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-5\n", + dev->name); + } + e = create_proc_read_entry("registers-6", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_6, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-6\n", + dev->name); + } + e = create_proc_read_entry("registers-7", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_7, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-7\n", + dev->name); + } + e = create_proc_read_entry("registers-8", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_8, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-8\n", + dev->name); + } + e = create_proc_read_entry("registers-9", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_9, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-9\n", + dev->name); + } + e = create_proc_read_entry("registers-a", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_a, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-a\n", + dev->name); + } + e = create_proc_read_entry("registers-b", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_b, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-b\n", + dev->name); + } + e = create_proc_read_entry("registers-c", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_c, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-c\n", + dev->name); + } + e = create_proc_read_entry("registers-d", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_d, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-d\n", + dev->name); + } + e = create_proc_read_entry("registers-e", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_registers_e, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/registers-e\n", + dev->name); + } + e = create_proc_read_entry("RF-A", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_reg_rf_a, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/RF-A\n", + dev->name); + } + e = create_proc_read_entry("RF-B", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_reg_rf_b, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/RF-B\n", + dev->name); + } + e = create_proc_read_entry("RF-C", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_reg_rf_c, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/RF-C\n", + dev->name); + } + e = create_proc_read_entry("RF-D", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_reg_rf_d, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/RF-D\n", + dev->name); + } + e = create_proc_read_entry("SEC-CAM-1", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_cam_register_1, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/SEC-CAM-1\n", + dev->name); + } + e = create_proc_read_entry("SEC-CAM-2", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_cam_register_2, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/SEC-CAM-2\n", + dev->name); + } + e = create_proc_read_entry("SEC-CAM-3", S_IFREG | S_IRUGO, + priv->dir_dev, proc_get_cam_register_3, dev); + if (!e) { + RT_TRACE(COMP_ERR, "Unable to initialize " + "/proc/net/rtl8192/%s/SEC-CAM-3\n", + dev->name); + } +#ifdef _RTL8192_EXT_PATCH_ + if( priv->mshobj && priv->mshobj->ext_patch_create_proc ) + priv->mshobj->ext_patch_create_proc(priv); +#endif + +} + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_debug.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl_debug.h @@ -0,0 +1,319 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef _RTL_DEBUG_H +#define _RTL_DEBUG_H +#include +#include +#include +#if(LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)) +#include +#endif + +struct r8192_priv; +struct _tx_desc_8192se; +struct _TX_DESC_8192CE; +struct net_device; + +#define DBG_LOUD 4 + +#define RT_ASSERT(_Exp,Fmt) \ + if(!(_Exp)) \ + { \ + printk("Rtl819x: "); \ + printk Fmt; \ + } + +typedef enum tag_DBGP_Flag_Type_Definition +{ + FQoS = 0, + FTX = 1, + FRX = 2, + FSEC = 3, + FMGNT = 4, + FMLME = 5, + FRESOURCE = 6, + FBEACON = 7, + FISR = 8, + FPHY = 9, + FMP = 10, + FEEPROM = 11, + FPWR = 12, + FDM = 13, + FDBGCtrl = 14, + FC2H = 15, + FBT = 16, + FINIT = 17, + FIOCTL = 18, + DBGP_TYPE_MAX +}DBGP_FLAG_E; + +#define QoS_INIT BIT0 +#define QoS_VISTA BIT1 + +#define TX_DESC BIT0 +#define TX_DESC_TID BIT1 + +#define RX_DATA BIT0 +#define RX_PHY_STS BIT1 +#define RX_PHY_SS BIT2 +#define RX_PHY_SQ BIT3 +#define RX_PHY_ASTS BIT4 +#define RX_ERR_LEN BIT5 +#define RX_DEFRAG BIT6 +#define RX_ERR_RATE BIT7 + + + +#define MEDIA_STS BIT0 +#define LINK_STS BIT1 + +#define OS_CHK BIT0 + +#define BCN_SHOW BIT0 +#define BCN_PEER BIT1 + +#define ISR_CHK BIT0 + +#define PHY_BBR BIT0 +#define PHY_BBW BIT1 +#define PHY_RFR BIT2 +#define PHY_RFW BIT3 +#define PHY_MACR BIT4 +#define PHY_MACW BIT5 +#define PHY_ALLR BIT6 +#define PHY_ALLW BIT7 +#define PHY_TXPWR BIT8 +#define PHY_PWRDIFF BIT9 + +#define MP_RX BIT0 +#define MP_SWICH_CH BIT1 + +#define EEPROM_W BIT0 +#define EFUSE_PG BIT1 +#define EFUSE_READ_ALL BIT2 + +#define LPS BIT0 +#define IPS BIT1 +#define PWRSW BIT2 +#define PWRHW BIT3 +#define PWRHAL BIT4 + +#define WA_IOT BIT0 +#define DM_PWDB BIT1 +#define DM_Monitor BIT2 +#define DM_DIG BIT3 +#define DM_EDCA_Turbo BIT4 + +#define DbgCtrl_Trace BIT0 +#define DbgCtrl_InbandNoise BIT1 + +#define BT_TRACE BIT0 +#define BT_RFPoll BIT1 + +#define C2H_Summary BIT0 +#define C2H_PacketData BIT1 +#define C2H_ContentData BIT2 +#define BT_TRACE BIT0 +#define BT_RFPoll BIT1 + +#define INIT_EEPROM BIT0 +#define INIT_TxPower BIT1 +#define INIT_IQK BIT2 +#define INIT_RF BIT3 + +#define IOCTL_TRACE BIT0 +#define IOCTL_BT_EVENT BIT1 +#define IOCTL_BT_EVENT_DETAIL BIT2 +#define IOCTL_BT_TX_ACLDATA BIT3 +#define IOCTL_BT_TX_ACLDATA_DETAIL BIT4 +#define IOCTL_BT_RX_ACLDATA BIT5 +#define IOCTL_BT_RX_ACLDATA_DETAIL BIT6 +#define IOCTL_BT_HCICMD BIT7 +#define IOCTL_BT_HCICMD_DETAIL BIT8 +#define IOCTL_IRP BIT9 +#define IOCTL_IRP_DETAIL BIT10 +#define IOCTL_CALLBACK_FUN BIT11 +#define IOCTL_STATE BIT12 +#define IOCTL_BT_TP BIT13 +#define IOCTL_BT_LOGO BIT14 + +/* 2007/07/13 MH ------For DeBuG Print modeue------*/ +/*------------------------------Define structure----------------------------*/ + + +/*------------------------Export Marco Definition---------------------------*/ +#define DEBUG_PRINT 1 + +#if (DEBUG_PRINT == 1) +#define RTPRINT(dbgtype, dbgflag, printstr) \ +{ \ + if (DBGP_Type[dbgtype] & dbgflag)\ + { \ + printk printstr; \ + } \ +} + +#define RTPRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr)\ +{\ + if (DBGP_Type[dbgtype] & dbgflag)\ + {\ + int __i; \ + u8* ptr = (u8*)_Ptr; \ + printk printstr; \ + printk(" "); \ + for( __i=0; __i<6; __i++ ) \ + printk("%02X%s", ptr[__i], (__i==5)?"":"-"); \ + printk("\n"); \ + }\ +} + +#define RTPRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen)\ +{\ + if (DBGP_Type[dbgtype] & dbgflag)\ + {\ + int __i; \ + u8* ptr = (u8*)_HexData; \ + printk(_TitleString); \ + for( __i=0; __i<(int)_HexDataLen; __i++ ) \ + { \ + printk("%02X%s", ptr[__i], (((__i + 1) % 4) == 0)?" ":" ");\ + if (((__i + 1) % 16) == 0) printk("\n");\ + } \ + printk("\n"); \ + }\ +} +#else +#define RTPRINT(dbgtype, dbgflag, printstr) +#define RTPRINT_ADDR(dbgtype, dbgflag, printstr, _Ptr) +#define RTPRINT_DATA(dbgtype, dbgflag, _TitleString, _HexData, _HexDataLen) +#endif + +extern u32 DBGP_Type[DBGP_TYPE_MAX]; + +#define RT_PRINT_DATA(_Comp, _Level, _TitleString, _HexData, _HexDataLen) \ +do {\ + if(((_Comp) & rt_global_debug_component ) && (_Level <= rt_global_debug_component )) \ + { \ + int __i; \ + u8* ptr = (u8*)_HexData; \ + printk("Rtl819x: "); \ + printk(_TitleString); \ + for( __i=0; __i<(int)_HexDataLen; __i++ ) \ + { \ + printk("%02X%s", ptr[__i], (((__i + 1) % 4) == 0)?" ":" "); \ + if (((__i + 1) % 16) == 0) printk("\n"); \ + } \ + printk("\n"); \ + } \ +}while(0); + +#define DMESG(x,a...) +#define DMESGW(x,a...) +#define DMESGE(x,a...) +extern u32 rt_global_debug_component; +#define RT_TRACE(component, x, args...) \ +do { if(rt_global_debug_component & component) \ + printk(KERN_DEBUG DRV_NAME ":" x "\n" , \ + ##args);\ +}while(0); + +#define RTL819x_DEBUG +#ifdef RTL819x_DEBUG +#define assert(expr) \ + if (!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n", \ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + } +#define RT_DEBUG_DATA(level, data, datalen) \ + do{ if ((rt_global_debug_component & (level)) == (level)) \ + { \ + int _i; \ + u8* _pdata = (u8*) data; \ + printk(KERN_DEBUG DRV_NAME ": %s()\n", __FUNCTION__); \ + for(_i=0; _i<(int)(datalen); _i++) \ + { \ + printk("%2x ", _pdata[_i]); \ + if ((_i+1)%16 == 0) printk("\n"); \ + } \ + printk("\n"); \ + } \ + } while (0) +#else +#define assert(expr) do {} while (0) +#define RT_DEBUG_DATA(level, data, datalen) do {} while(0) +#endif + +typedef struct _rtl_fs_debug +{ + const char *name; + struct dentry *dir_drv; + struct dentry *debug_register; + u32 hw_type; + u32 hw_offset; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20)) + bool hw_holding; +#else + u8 hw_holding; +#endif +} rtl_fs_debug; + +void print_buffer(u32 *buffer, int len); +void dump_eprom(struct net_device *dev); +void rtl8192_dump_reg(struct net_device *dev); + +#ifdef RTL8192SE +void rtl8192se_dump_tx_desc(struct _tx_desc_8192se *pDesc); +#endif +#ifdef RTL8192CE +void rtl8192ce_dump_tx_desc(struct _TX_DESC_8192CE *pDesc); +#endif + +/* debugfs stuff */ +#ifdef CONFIG_RTLWIFI_DEBUGFS +int rtl_debug_module_init(struct r8192_priv *priv, const char *name); +void rtl_debug_module_remove(struct r8192_priv *priv); +int rtl_create_debugfs_root(void); +void rtl_remove_debugfs_root(void); +#else +static inline int rtl_debug_module_init(struct r8192_priv *priv, const char *name) { + return 0; +} +static inline void rtl_debug_module_remove(struct r8192_priv *priv) { + +} +static inline int rtl_create_debugfs_root(void) { + return 0; +} +static inline void rtl_remove_debugfs_root(void) { +} +#endif + +/* proc stuff */ +void rtl8192_proc_init_one(struct net_device *dev); +void rtl8192_proc_remove_one(struct net_device *dev); +void rtl8192_proc_module_init(void); +void rtl8192_proc_module_remove(void); +void rtl8192_dbgp_flag_init(struct net_device *dev); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_dm.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_dm.c @@ -0,0 +1,5353 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#include "rtl_core.h" +#ifdef _RTL8192_EXT_PATCH_ +#include "../../mshclass/msh_class.h" +#endif + +/*---------------------------Define Local Constant---------------------------*/ +#ifdef RTL8190P +static u32 edca_setting_DL[HT_IOT_PEER_MAX] = +{ 0x5e4322, + 0x5e4322, + 0x5ea44f, + 0x5e4322, + 0x604322, + 0xa44f, + 0x5e4322, + 0x5e4322 + }; + +static u32 edca_setting_DL_GMode[HT_IOT_PEER_MAX] = +{ 0x5e4322, + 0x5e4322, + 0x5e4322, + 0x5e4322, + 0x604322, + 0xa44f, + 0x5e4322, + 0x5e4322 +}; + +static u32 edca_setting_UL[HT_IOT_PEER_MAX] = +{ 0x5e4322, + 0xa44f, + 0x5ea44f, + 0x5e4322, + 0x604322, + 0x5e4322, + 0x5e4322, + 0x5e4322 +}; + +#elif defined RTL8192E +static u32 edca_setting_DL[HT_IOT_PEER_MAX] = +{ 0x5e4322, + 0x5e4322, + 0x5ea44f, + 0x5e4322, + 0x604322, + 0xa44f, + 0x5e4322, + 0x5e4332 + }; + +static u32 edca_setting_DL_GMode[HT_IOT_PEER_MAX] = +{ 0x5e4322, + 0x5e4322, + 0x5e4322, + 0x5e4322, + 0x604322, + 0xa44f, + 0x5e4322, + 0x5e4322 +}; + +static u32 edca_setting_UL[HT_IOT_PEER_MAX] = +{ 0x5e4322, + 0xa44f, + 0x5ea44f, + 0x5e4322, + 0x604322, + 0x5e4322, + 0x5e4322, + 0x5e4332 +}; + +#elif defined(RTL8192SE) +static u32 edca_setting_DL[HT_IOT_PEER_MAX] = +{ 0xa44f, + 0x5ea44f, + 0x5ea44f, + 0xa630, + 0xa44f, + 0xa630, + 0xa630, + 0xa42b, + 0x5e4322, + 0x5e4322 + }; + +static u32 edca_setting_DL_GMode[HT_IOT_PEER_MAX] = + +{ 0x4322, + 0xa44f, + 0x5ea44f, + 0xa42b, + 0x5e4322, + 0x4322, + 0xa430, + 0x5ea44f, + 0x3ea430, + 0x5e4322 +}; + +static u32 edca_setting_UL[HT_IOT_PEER_MAX] = +{ 0x5e4322, + 0xa44f, + 0x5ea44f, + 0x5ea322, + 0x5ea422, + 0x5ea322, + 0x3ea44f, + 0x5ea44f, + 0x5e4322, + 0x5e4322 + }; +#endif + +#define RTK_UL_EDCA 0xa44f +#define RTK_DL_EDCA 0x5e4322 +/*---------------------------Define Local Constant---------------------------*/ + + +/*------------------------Define global variable-----------------------------*/ +dig_t dm_digtable; +u8 dm_shadow[16][256] = {{0}}; +DRxPathSel DM_RxPathSelTable; +/*------------------------Define global variable-----------------------------*/ + + +/*------------------------Define local variable------------------------------*/ +/*------------------------Define local variable------------------------------*/ + + +/*--------------------Define export function prototype-----------------------*/ +extern void init_hal_dm(struct net_device *dev); +extern void deinit_hal_dm(struct net_device *dev); + +extern void hal_dm_watchdog(struct net_device *dev); + + +extern void init_rate_adaptive(struct net_device *dev); +extern void dm_txpower_trackingcallback(void *data); + +extern void dm_restore_dynamic_mechanism_state(struct net_device *dev); +extern void dm_backup_dynamic_mechanism_state(struct net_device *dev); +extern void dm_change_dynamic_initgain_thresh(struct net_device *dev, + u32 dm_type, + u32 dm_value); +extern void DM_ChangeFsyncSetting(struct net_device *dev, + s32 DM_Type, + s32 DM_Value); +extern void dm_force_tx_fw_info(struct net_device *dev, + u32 force_type, + u32 force_value); +extern void dm_init_edca_turbo(struct net_device *dev); +extern void dm_rf_operation_test_callback(unsigned long data); +extern void dm_rf_pathcheck_workitemcallback(void *data); +extern void dm_fsync_timer_callback(unsigned long data); +#if 0 +extern bool dm_check_lbus_status(struct net_device *dev); +#endif +extern void dm_check_fsync(struct net_device *dev); +extern void dm_shadow_init(struct net_device *dev); +extern void dm_initialize_txpower_tracking(struct net_device *dev); + +#if (defined RTL8192E || defined RTL8192SE) +extern void dm_CheckRfCtrlGPIO(void *data); +#endif + +#ifdef RTL8192SE +extern void DM_TXPowerTracking92SDirectCall(struct net_device *dev); +static void dm_CtrlInitGainByTwoPort(struct net_device *dev); +static void dm_CtrlInitGainBeforeConnectByRssiAndFalseAlarm(struct net_device *dev); +static void dm_initial_gain_STABeforeConnect(struct net_device *dev); + +void dm_InitRateAdaptiveMask(struct net_device *dev); +#if 0 +static void Adhoc_dm_CheckRateAdaptive(struct net_device * dev); +#endif +void Adhoc_InitRateAdaptive(struct net_device *dev,struct sta_info *pEntry); +#endif + +/*--------------------Define export function prototype-----------------------*/ + + +/*---------------------Define local function prototype-----------------------*/ +static void dm_check_rate_adaptive(struct net_device *dev); + +static void dm_init_bandwidth_autoswitch(struct net_device *dev); +static void dm_bandwidth_autoswitch( struct net_device *dev); + + +static void dm_check_txpower_tracking(struct net_device *dev); + + + + + +#if defined(RTL8192E)||defined(RTL8190P) +static void dm_bb_initialgain_restore(struct net_device *dev); + + +static void dm_bb_initialgain_backup(struct net_device *dev); +#endif + +static void dm_dig_init(struct net_device *dev); +static void dm_ctrl_initgain_byrssi(struct net_device *dev); +static void dm_ctrl_initgain_byrssi_highpwr(struct net_device *dev); +static void dm_ctrl_initgain_byrssi_by_driverrssi( struct net_device *dev); +static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm(struct net_device *dev); +static void dm_initial_gain(struct net_device *dev); +static void dm_pd_th(struct net_device *dev); +static void dm_cs_ratio(struct net_device *dev); + +static void dm_init_ctstoself(struct net_device *dev); +static void dm_Init_WA_Broadcom_IOT(struct net_device *dev); +#ifdef RTL8192SE +static void dm_WA_Broadcom_IOT(struct net_device *dev); +#endif + +static void dm_check_edca_turbo(struct net_device *dev); + +#if 0 +static void dm_check_rfctrl_gpio(struct net_device *dev); +#endif + +#ifndef RTL8190P +#endif +static void dm_check_pbc_gpio(struct net_device *dev); + + +static void dm_check_rx_path_selection(struct net_device *dev); +static void dm_init_rxpath_selection(struct net_device *dev); +static void dm_rxpath_sel_byrssi(struct net_device *dev); + + +static void dm_init_fsync(struct net_device *dev); +static void dm_deInit_fsync(struct net_device *dev); + +static void dm_check_txrateandretrycount(struct net_device *dev); +static void dm_check_ac_dc_power(struct net_device *dev); + +/*---------------------Define local function prototype-----------------------*/ + +static void dm_init_dynamic_txpower(struct net_device *dev); +static void dm_dynamic_txpower(struct net_device *dev); + + +static void dm_send_rssi_tofw(struct net_device *dev); +static void dm_ctstoself(struct net_device *dev); +#if defined RTL8192SE +static void dm_RefreshRateAdaptiveMask(struct net_device *dev); +#endif +/*---------------------------Define function prototype------------------------*/ + +extern void +init_hal_dm(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + priv->DM_Type = DM_Type_ByDriver; + + priv->undecorated_smoothed_pwdb = -1; + + dm_init_dynamic_txpower(dev); + +#ifdef RTL8192SE + if (IS_HARDWARE_TYPE_8192SE(dev)) + dm_InitRateAdaptiveMask(dev); + else +#endif + init_rate_adaptive(dev); + + dm_dig_init(dev); + dm_init_edca_turbo(dev); + dm_init_bandwidth_autoswitch(dev); + dm_init_fsync(dev); + dm_init_rxpath_selection(dev); + dm_init_ctstoself(dev); + if (IS_HARDWARE_TYPE_8192SE(dev)) { + dm_Init_WA_Broadcom_IOT(dev); + +#ifdef RTL8192SE + write_nic_dword(dev, WFM5, FW_CCA_CHK_ENABLE); +#endif + } + +#if (defined RTL8192E || defined RTL8192SE) + INIT_DELAYED_WORK_RSL(&priv->gpio_change_rf_wq, (void *)dm_CheckRfCtrlGPIO,dev); +#endif + +} + +extern void deinit_hal_dm(struct net_device *dev) +{ + + dm_deInit_fsync(dev); + +} + + +#ifdef USB_RX_AGGREGATION_SUPPORT +void dm_CheckRxAggregation(struct net_device *dev) { + struct r8192_priv *priv = rtllib_priv((struct net_device *)dev); + PRT_HIGH_THROUGHPUT pHTInfo = priv->rtllib->pHTInfo; + static unsigned long lastTxOkCnt = 0; + static unsigned long lastRxOkCnt = 0; + unsigned long curTxOkCnt = 0; + unsigned long curRxOkCnt = 0; + + curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; + curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; + + if((curTxOkCnt + curRxOkCnt) < 15000000) { + return; + } + + if(curTxOkCnt > 4*curRxOkCnt) { + if (priv->bCurrentRxAggrEnable) { + write_nic_dword(dev, 0x1a8, 0); + priv->bCurrentRxAggrEnable = false; + } + }else{ + if (!priv->bCurrentRxAggrEnable && !pHTInfo->bCurrentRT2RTAggregation) { + u32 ulValue; + ulValue = (pHTInfo->UsbRxFwAggrEn<<24) | (pHTInfo->UsbRxFwAggrPageNum<<16) | + (pHTInfo->UsbRxFwAggrPacketNum<<8) | (pHTInfo->UsbRxFwAggrTimeout); + write_nic_dword(dev, 0x1a8, ulValue); + priv->bCurrentRxAggrEnable = true; + } + } + + lastTxOkCnt = priv->stats.txbytesunicast; + lastRxOkCnt = priv->stats.rxbytesunicast; +} +#endif + + + +extern void hal_dm_watchdog(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + if(priv->being_init_adapter) + return; + + dm_check_ac_dc_power(dev); + + dm_check_pbc_gpio(dev); + dm_check_txrateandretrycount(dev); + dm_check_edca_turbo(dev); + + if (IS_HARDWARE_TYPE_8192SE(dev)){ +#ifdef RTL8192SE + dm_RefreshRateAdaptiveMask(dev); + dm_WA_Broadcom_IOT(dev); + + return; +#if 0 + dm_check_txpower_tracking(dev); + dm_ctrl_initgain_byrssi(dev); + dm_dynamic_txpower(dev); + dm_RefreshRateAdaptiveMask(dev); + dm_check_fsync(dev); + if(priv->rtllib->iw_mode == IW_MODE_ADHOC) + Adhoc_dm_CheckRateAdaptive(dev); + else + dm_check_rate_adaptive(dev); +#endif +#endif + } + dm_check_rate_adaptive(dev); + dm_dynamic_txpower(dev); + dm_check_txpower_tracking(dev); + + dm_ctrl_initgain_byrssi(dev); + dm_bandwidth_autoswitch(dev); + + dm_check_rx_path_selection(dev); + dm_check_fsync(dev); + + dm_send_rssi_tofw(dev); + dm_ctstoself(dev); + +#ifdef USB_RX_AGGREGATION_SUPPORT + dm_CheckRxAggregation(dev); +#endif +} + +void dm_check_ac_dc_power(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + static char *ac_dc_check_script_path = "/etc/realtek/wireless-rtl-ac-dc-power.sh"; + char *argv[] = {ac_dc_check_script_path,DRV_NAME,NULL}; + static char *envp[] = {"HOME=/", + "TERM=linux", + "PATH=/usr/bin:/bin", + NULL}; + + if(priv->ResetProgress == RESET_TYPE_SILENT) + { + RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), "GPIOChangeRFWorkItemCallBack(): Silent Reseting!!!!!!!\n"); + return; + } + + if(priv->rtllib->state != RTLLIB_LINKED) { + return; + } + call_usermodehelper(ac_dc_check_script_path,argv,envp,1); + + return; +}; + + +extern void init_rate_adaptive(struct net_device * dev) +{ + + struct r8192_priv *priv = rtllib_priv(dev); + prate_adaptive pra = (prate_adaptive)&priv->rate_adaptive; + + pra->ratr_state = DM_RATR_STA_MAX; + pra->high2low_rssi_thresh_for_ra = RateAdaptiveTH_High; + pra->low2high_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M+5; + pra->low2high_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M+5; + + pra->high_rssi_thresh_for_ra = RateAdaptiveTH_High+5; + pra->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M; + pra->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M; + + if(priv->CustomerID == RT_CID_819x_Netcore) + pra->ping_rssi_enable = 1; + else + pra->ping_rssi_enable = 0; + pra->ping_rssi_thresh_for_ra = 15; + + + if (priv->rf_type == RF_2T4R) + { + pra->upper_rssi_threshold_ratr = 0x8f0f0000; + pra->middle_rssi_threshold_ratr = 0x8f0ff000; + pra->low_rssi_threshold_ratr = 0x8f0ff001; + pra->low_rssi_threshold_ratr_40M = 0x8f0ff005; + pra->low_rssi_threshold_ratr_20M = 0x8f0ff001; + pra->ping_rssi_ratr = 0x0000000d; + } + else if (priv->rf_type == RF_1T2R) + { + pra->upper_rssi_threshold_ratr = 0x000fc000; + pra->middle_rssi_threshold_ratr = 0x000ff000; + pra->low_rssi_threshold_ratr = 0x000ff001; + pra->low_rssi_threshold_ratr_40M = 0x000ff005; + pra->low_rssi_threshold_ratr_20M = 0x000ff001; + pra->ping_rssi_ratr = 0x0000000d; + } + +} + + +static void dm_check_rate_adaptive(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_HIGH_THROUGHPUT pHTInfo = priv->rtllib->pHTInfo; + prate_adaptive pra = (prate_adaptive)&priv->rate_adaptive; + u32 currentRATR, targetRATR = 0; + u32 LowRSSIThreshForRA = 0, HighRSSIThreshForRA = 0; + bool bshort_gi_enabled = false; + static u8 ping_rssi_state=0; + + if(IS_NIC_DOWN(priv)){ + RT_TRACE(COMP_RATE, "<---- dm_check_rate_adaptive(): driver is going to unload\n"); + return; + } + + if(pra->rate_adaptive_disabled) + return; + + if( !(priv->rtllib->mode == WIRELESS_MODE_N_24G || + priv->rtllib->mode == WIRELESS_MODE_N_5G)) + return; + + if( priv->rtllib->state == RTLLIB_LINKED ) + { + + bshort_gi_enabled = (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) || + (!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz); + + + pra->upper_rssi_threshold_ratr = + (pra->upper_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + + pra->middle_rssi_threshold_ratr = + (pra->middle_rssi_threshold_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + pra->low_rssi_threshold_ratr = + (pra->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + } + else + { + pra->low_rssi_threshold_ratr = + (pra->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + } + pra->ping_rssi_ratr = + (pra->ping_rssi_ratr & (~BIT31)) | ((bshort_gi_enabled)? BIT31:0) ; + + if (pra->ratr_state == DM_RATR_STA_HIGH) + { + HighRSSIThreshForRA = pra->high2low_rssi_thresh_for_ra; + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M); + } + else if (pra->ratr_state == DM_RATR_STA_LOW) + { + HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra; + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + (pra->low2high_rssi_thresh_for_ra40M):(pra->low2high_rssi_thresh_for_ra20M); + } + else + { + HighRSSIThreshForRA = pra->high_rssi_thresh_for_ra; + LowRSSIThreshForRA = (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + (pra->low_rssi_thresh_for_ra40M):(pra->low_rssi_thresh_for_ra20M); + } + + if(priv->undecorated_smoothed_pwdb >= (long)HighRSSIThreshForRA) + { + pra->ratr_state = DM_RATR_STA_HIGH; + targetRATR = pra->upper_rssi_threshold_ratr; + }else if(priv->undecorated_smoothed_pwdb >= (long)LowRSSIThreshForRA) + { + pra->ratr_state = DM_RATR_STA_MIDDLE; + targetRATR = pra->middle_rssi_threshold_ratr; + }else + { + pra->ratr_state = DM_RATR_STA_LOW; + targetRATR = pra->low_rssi_threshold_ratr; + } + + if(pra->ping_rssi_enable) + { + if(priv->undecorated_smoothed_pwdb < (long)(pra->ping_rssi_thresh_for_ra+5)) + { + if( (priv->undecorated_smoothed_pwdb < (long)pra->ping_rssi_thresh_for_ra) || + ping_rssi_state ) + { + pra->ratr_state = DM_RATR_STA_LOW; + targetRATR = pra->ping_rssi_ratr; + ping_rssi_state = 1; + } + } + else + { + ping_rssi_state = 0; + } + } + +#if 1 + if(priv->rtllib->GetHalfNmodeSupportByAPsHandler(dev)) + targetRATR &= 0xf00fffff; +#endif + + currentRATR = read_nic_dword(dev, RATR0); + if( targetRATR != currentRATR ) + { + u32 ratr_value; + ratr_value = targetRATR; + RT_TRACE(COMP_RATE,"currentRATR = %x, targetRATR = %x\n", currentRATR, targetRATR); + if(priv->rf_type == RF_1T2R) + { + ratr_value &= ~(RATE_ALL_OFDM_2SS); + } + write_nic_dword(dev, RATR0, ratr_value); + write_nic_byte(dev, UFWP, 1); + + pra->last_ratr = targetRATR; + } + + } + else + { + pra->ratr_state = DM_RATR_STA_MAX; + } + +} + +#ifdef RTL8192SE +void dm_InitRateAdaptiveMask(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + prate_adaptive pRA = (prate_adaptive)&priv->rate_adaptive; + + pRA->ratr_state = DM_RATR_STA_MAX; + pRA->PreRATRState = DM_RATR_STA_MAX; + +#ifdef _RTL8192_EXT_PATCH_ + if (priv->DM_Type == DM_Type_ByDriver && priv->pFirmware->FirmwareVersion >= 60) + priv->rtllib->bUseRAMask = true; + else +#endif + priv->rtllib->bUseRAMask = false; + + printk("=========>%s: bUseRAMask=%d\n", __func__, priv->rtllib->bUseRAMask); + priv->bInformFWDriverControlDM = false; + +} +#endif + +static void dm_init_bandwidth_autoswitch(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz = BW_AUTO_SWITCH_LOW_HIGH; + priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz = BW_AUTO_SWITCH_HIGH_LOW; + priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = false; + priv->rtllib->bandwidth_auto_switch.bautoswitch_enable = false; + +} + + +static void dm_bandwidth_autoswitch(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 ||!priv->rtllib->bandwidth_auto_switch.bautoswitch_enable){ + return; + }else{ + if(priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz == false){ + if(priv->undecorated_smoothed_pwdb <= priv->rtllib->bandwidth_auto_switch.threshold_40Mhzto20Mhz) + priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = true; + }else{ + if(priv->undecorated_smoothed_pwdb >= priv->rtllib->bandwidth_auto_switch.threshold_20Mhzto40Mhz) + priv->rtllib->bandwidth_auto_switch.bforced_tx20Mhz = false; + + } + } +} + +#ifdef Rtl8192SE +u32 OFDMSwingTable[OFDM_Table_Length] = { + 0x7f8001fe, + 0x788001e2, + 0x71c001c7, + 0x6b8001ae, + 0x65400195, + 0x5fc0017f, + 0x5a400169, + 0x55400155, + 0x50800142, + 0x4c000130, + 0x47c0011f, + 0x43c0010f, + 0x40000100, + 0x3c8000f2, + 0x390000e4, + 0x35c000d7, + 0x32c000cb, + 0x300000c0, + 0x2d4000b5, + 0x2ac000ab, + 0x288000a2, + 0x26000098, + 0x24000090, + 0x22000088, + 0x20000080, + 0x1e400079, + 0x1c800072, + 0x1b00006c, + 0x19800066, + 0x18000060, + 0x16c0005b, + 0x15800056, + 0x14400051, + 0x1300004c, + 0x12000048, + 0x11000044, + 0x10000040, +}; + +u8 CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = { + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, + {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, + {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, + {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, + {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, + {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, + {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, + {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, + {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, + {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, + {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, + {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, + {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, + {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, + {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, + {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, + {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, + {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, + {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, + {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, + {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, + {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01} +}; + + +u8 CCKSwingTable_Ch14[CCK_Table_length][8] = { + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, + {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, + {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, + {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, + {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, + {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, + {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, + {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, + {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, + {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, + {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, + {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, + {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, + {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, + {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, + {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, + {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00} +}; +#elif defined RTL8192E +static u32 OFDMSwingTable[OFDM_Table_Length] = { + 0x7f8001fe, + 0x71c001c7, + 0x65400195, + 0x5a400169, + 0x50800142, + 0x47c0011f, + 0x40000100, + 0x390000e4, + 0x32c000cb, + 0x2d4000b5, + 0x288000a2, + 0x24000090, + 0x20000080, + 0x1c800072, + 0x19800066, + 0x26c0005b, + 0x24400051, + 0x12000048, + 0x10000040 +}; +static u8 CCKSwingTable_Ch1_Ch13[CCK_Table_length][8] = { + {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, + {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, + {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, + {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, + {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, + {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, + {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, + {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, + {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, + {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, + {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, + {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01} +}; + +static u8 CCKSwingTable_Ch14[CCK_Table_length][8] = { + {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, + {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, + {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, + {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, + {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, + {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, + {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, + {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, + {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, + {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, + {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, + {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00} +}; +#endif +#define Pw_Track_Flag 0x11d +#define Tssi_Mea_Value 0x13c +#define Tssi_Report_Value1 0x134 +#define Tssi_Report_Value2 0x13e +#define FW_Busy_Flag 0x13f + +#ifndef RTL8192SE +static void dm_TXPowerTrackingCallback_TSSI(struct net_device * dev) + { + struct r8192_priv *priv = rtllib_priv(dev); + bool bHighpowerstate, viviflag = false; + DCMD_TXCMD_T tx_cmd; + u8 powerlevelOFDM24G; + int i =0, j = 0, k = 0; + u8 RF_Type, tmp_report[5]={0, 0, 0, 0, 0}; + u32 Value; + u8 Pwr_Flag; + u16 Avg_TSSI_Meas, TSSI_13dBm, Avg_TSSI_Meas_from_driver=0; +#ifdef RTL8192U + RT_STATUS rtStatus = RT_STATUS_SUCCESS; +#endif + u32 delta=0; + RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__); + write_nic_byte(dev, Pw_Track_Flag, 0); + write_nic_byte(dev, FW_Busy_Flag, 0); + priv->rtllib->bdynamic_txpower_enable = false; + bHighpowerstate = priv->bDynamicTxHighPower; + + powerlevelOFDM24G = (u8)(priv->Pwr_Track>>24); + RF_Type = priv->rf_type; + Value = (RF_Type<<8) | powerlevelOFDM24G; + + RT_TRACE(COMP_POWER_TRACKING, "powerlevelOFDM24G = %x\n", powerlevelOFDM24G); + + +#ifdef RTL8190P + for(j = 0; j<1; j++) +#else + for(j = 0; j<=30; j++) +#endif +{ + + tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING; + tx_cmd.Length = 4; + tx_cmd.Value = Value; +#ifdef RTL8192U + rtStatus = SendTxCommandPacket(dev, &tx_cmd, 12); + if (rtStatus == RT_STATUS_FAILURE) + { + RT_TRACE(COMP_POWER_TRACKING, "Set configuration with tx cmd queue fail!\n"); + } +#else + cmpk_message_handle_tx(dev, (u8*)&tx_cmd, DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T)); +#endif + mdelay(1); + for(i = 0;i <= 30; i++) + { + Pwr_Flag = read_nic_byte(dev, Pw_Track_Flag); + + if (Pwr_Flag == 0) + { + mdelay(1); + + if(priv->bResetInProgress) + { + RT_TRACE(COMP_POWER_TRACKING, "we are in slient reset progress, so return\n"); + write_nic_byte(dev, Pw_Track_Flag, 0); + write_nic_byte(dev, FW_Busy_Flag, 0); + return; + } +#ifdef RTL8192E + if((priv->rtllib->eRFPowerState != eRfOn)) + { + RT_TRACE(COMP_POWER_TRACKING, "we are in power save, so return\n"); + write_nic_byte(dev, Pw_Track_Flag, 0); + write_nic_byte(dev, FW_Busy_Flag, 0); + return; + } + +#endif + continue; + } + + Avg_TSSI_Meas = read_nic_word(dev, Tssi_Mea_Value); + + if(Avg_TSSI_Meas == 0) + { + write_nic_byte(dev, Pw_Track_Flag, 0); + write_nic_byte(dev, FW_Busy_Flag, 0); + return; + } + + for(k = 0;k < 5; k++) + { + if(k !=4) + tmp_report[k] = read_nic_byte(dev, Tssi_Report_Value1+k); + else + tmp_report[k] = read_nic_byte(dev, Tssi_Report_Value2); + + RT_TRACE(COMP_POWER_TRACKING, "TSSI_report_value = %d\n", tmp_report[k]); + + { + if(tmp_report[k] <= 20) + { + viviflag =true; + break; + } + } + } + + if(viviflag ==true) + { + write_nic_byte(dev, Pw_Track_Flag, 0); + viviflag = false; + RT_TRACE(COMP_POWER_TRACKING, "we filted this data\n"); + for(k = 0;k < 5; k++) + tmp_report[k] = 0; + break; + } + + for(k = 0;k < 5; k++) + { + Avg_TSSI_Meas_from_driver += tmp_report[k]; + } + + Avg_TSSI_Meas_from_driver = Avg_TSSI_Meas_from_driver*100/5; + RT_TRACE(COMP_POWER_TRACKING, "Avg_TSSI_Meas_from_driver = %d\n", Avg_TSSI_Meas_from_driver); + TSSI_13dBm = priv->TSSI_13dBm; + RT_TRACE(COMP_POWER_TRACKING, "TSSI_13dBm = %d\n", TSSI_13dBm); + + if(Avg_TSSI_Meas_from_driver > TSSI_13dBm) + delta = Avg_TSSI_Meas_from_driver - TSSI_13dBm; + else + delta = TSSI_13dBm - Avg_TSSI_Meas_from_driver; + + if(delta <= E_FOR_TX_POWER_TRACK) + { + priv->rtllib->bdynamic_txpower_enable = true; + write_nic_byte(dev, Pw_Track_Flag, 0); + write_nic_byte(dev, FW_Busy_Flag, 0); + RT_TRACE(COMP_POWER_TRACKING, "tx power track is done\n"); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); +#ifdef RTL8190P + RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real); +#endif + RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference); + RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation); + return; + } + else + { + if(Avg_TSSI_Meas_from_driver < TSSI_13dBm - E_FOR_TX_POWER_TRACK) + { + if (RF_Type == RF_2T4R) + { + + if((priv->rfa_txpowertrackingindex > 0) &&(priv->rfc_txpowertrackingindex > 0)) + { + priv->rfa_txpowertrackingindex--; + if(priv->rfa_txpowertrackingindex_real > 4) + { + priv->rfa_txpowertrackingindex_real--; + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); + } + + priv->rfc_txpowertrackingindex--; + if(priv->rfc_txpowertrackingindex_real > 4) + { + priv->rfc_txpowertrackingindex_real--; + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value); + } + } + else + { + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value); + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value); + } + } + else + { + { +#ifdef RTL8190P + { + if(priv->rfc_txpowertrackingindex > 0) + { + priv->rfc_txpowertrackingindex--; + if(priv->rfc_txpowertrackingindex_real > 4) + { + priv->rfc_txpowertrackingindex_real--; + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value); + } + } + else + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value); + } +#endif +#ifdef RTL8192E + { + if(priv->rfa_txpowertrackingindex > 0) + { + priv->rfa_txpowertrackingindex--; + if(priv->rfa_txpowertrackingindex_real > 4) + { + priv->rfa_txpowertrackingindex_real--; + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); + } + } + else + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[4].txbbgain_value); + } +#endif + } + + } + } + else + { + if (RF_Type == RF_2T4R) + { + if((priv->rfa_txpowertrackingindex < TxBBGainTableLength - 1) &&(priv->rfc_txpowertrackingindex < TxBBGainTableLength - 1)) + { + priv->rfa_txpowertrackingindex++; + priv->rfa_txpowertrackingindex_real++; + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); + priv->rfc_txpowertrackingindex++; + priv->rfc_txpowertrackingindex_real++; + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value); + } + else + { + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value); + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value); + } + } + else + { + { +#ifdef RTL8190P + { + if(priv->rfc_txpowertrackingindex < (TxBBGainTableLength - 1)) + { + priv->rfc_txpowertrackingindex++; + priv->rfc_txpowertrackingindex_real++; + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex_real].txbbgain_value); + } + else + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value); + } +#endif +#ifdef RTL8192E + { + if(priv->rfa_txpowertrackingindex < (TxBBGainTableLength - 1)) + { + priv->rfa_txpowertrackingindex++; + priv->rfa_txpowertrackingindex_real++; + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex_real].txbbgain_value); + } + else + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[TxBBGainTableLength - 1].txbbgain_value); + } +#endif + } + } + } + if (RF_Type == RF_2T4R){ + priv->CCKPresentAttentuation_difference + = priv->rfa_txpowertrackingindex - priv->rfa_txpowertracking_default; + }else{ + { +#ifdef RTL8190P + priv->CCKPresentAttentuation_difference + = priv->rfc_txpowertrackingindex - priv->rfc_txpowertracking_default; +#endif +#ifdef RTL8192E + priv->CCKPresentAttentuation_difference + = priv->rfa_txpowertrackingindex_real - priv->rfa_txpowertracking_default; +#endif + } + } + + if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + priv->CCKPresentAttentuation + = priv->CCKPresentAttentuation_20Mdefault + priv->CCKPresentAttentuation_difference; + else + priv->CCKPresentAttentuation + = priv->CCKPresentAttentuation_40Mdefault + priv->CCKPresentAttentuation_difference; + + if(priv->CCKPresentAttentuation > (CCKTxBBGainTableLength-1)) + priv->CCKPresentAttentuation = CCKTxBBGainTableLength-1; + if(priv->CCKPresentAttentuation < 0) + priv->CCKPresentAttentuation = 0; + + if(priv->CCKPresentAttentuation > -1&&priv->CCKPresentAttentuation < CCKTxBBGainTableLength) + { + if(priv->rtllib->current_network.channel == 14 && !priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = true; + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + } + else if(priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = false; + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + } + else + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + } + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex = %d\n", priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfa_txpowertrackingindex_real = %d\n", priv->rfa_txpowertrackingindex_real); +#ifdef RTL8190P + RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex = %d\n", priv->rfc_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "priv->rfc_txpowertrackingindex_real = %d\n", priv->rfc_txpowertrackingindex_real); +#endif + RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation_difference = %d\n", priv->CCKPresentAttentuation_difference); + RT_TRACE(COMP_POWER_TRACKING, "priv->CCKPresentAttentuation = %d\n", priv->CCKPresentAttentuation); + + if (priv->CCKPresentAttentuation_difference <= -12||priv->CCKPresentAttentuation_difference >= 24) + { + priv->rtllib->bdynamic_txpower_enable = true; + write_nic_byte(dev, Pw_Track_Flag, 0); + write_nic_byte(dev, FW_Busy_Flag, 0); + RT_TRACE(COMP_POWER_TRACKING, "tx power track--->limited\n"); + return; + } + + + } + write_nic_byte(dev, Pw_Track_Flag, 0); + Avg_TSSI_Meas_from_driver = 0; + for(k = 0;k < 5; k++) + tmp_report[k] = 0; + break; + } + write_nic_byte(dev, FW_Busy_Flag, 0); +} + priv->rtllib->bdynamic_txpower_enable = true; + write_nic_byte(dev, Pw_Track_Flag, 0); +} +#endif + +#ifdef RTL8192E +static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev) +{ +#define ThermalMeterVal 9 + struct r8192_priv *priv = rtllib_priv(dev); + u32 tmpRegA, TempCCk; + u8 tmpOFDMindex, tmpCCKindex, tmpCCK20Mindex, tmpCCK40Mindex, tmpval; + int i =0, CCKSwingNeedUpdate=0; + + if(!priv->btxpower_trackingInit) + { + tmpRegA= rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance, bMaskDWord); + for(i=0; iOFDM_index[0]= (u8)i; + RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, OFDM_index=0x%x\n", + rOFDM0_XATxIQImbalance, tmpRegA, priv->OFDM_index[0]); + } + } + + TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2); + for(i=0 ; iCCK_index =(u8) i; + RT_TRACE(COMP_POWER_TRACKING, "Initial reg0x%x = 0x%x, CCK_index=0x%x\n", + rCCK0_TxFilter1, TempCCk, priv->CCK_index); + break; + } +} + priv->btxpower_trackingInit = true; + return; + } + +#if 0 +{ + UINT32 curr_addr; + UINT32 reg_value; + + for (curr_addr = 0; curr_addr < 0x2d; curr_addr++) + { + reg_value = PHY_QueryRFReg( dev, (RF90_RADIO_PATH_E)RF90_PATH_A, + curr_addr, bMaskDWord); + } + + pHalData->TXPowercount = 0; + return; +} +#endif + + tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078); + RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d \n", tmpRegA); + if(tmpRegA < 3 || tmpRegA > 13) + return; + if(tmpRegA >= 12) + tmpRegA = 12; + RT_TRACE(COMP_POWER_TRACKING, "Valid ThermalMeterA = %d \n", tmpRegA); + priv->ThermalMeter[0] = ThermalMeterVal; + priv->ThermalMeter[1] = ThermalMeterVal; + + if(priv->ThermalMeter[0] >= (u8)tmpRegA) + { + tmpOFDMindex = tmpCCK20Mindex = 6+(priv->ThermalMeter[0]-(u8)tmpRegA); + tmpCCK40Mindex = tmpCCK20Mindex - 6; + if(tmpOFDMindex >= OFDM_Table_Length) + tmpOFDMindex = OFDM_Table_Length-1; + if(tmpCCK20Mindex >= CCK_Table_length) + tmpCCK20Mindex = CCK_Table_length-1; + if(tmpCCK40Mindex >= CCK_Table_length) + tmpCCK40Mindex = CCK_Table_length-1; + } + else + { + tmpval = ((u8)tmpRegA - priv->ThermalMeter[0]); + if(tmpval >= 6) + tmpOFDMindex = tmpCCK20Mindex = 0; + else + tmpOFDMindex = tmpCCK20Mindex = 6 - tmpval; + tmpCCK40Mindex = 0; + } + if(priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + tmpCCKindex = tmpCCK40Mindex; + else + tmpCCKindex = tmpCCK20Mindex; + + priv->Record_CCK_20Mindex = tmpCCK20Mindex; + priv->Record_CCK_40Mindex = tmpCCK40Mindex; + RT_TRACE(COMP_POWER_TRACKING, "Record_CCK_20Mindex / Record_CCK_40Mindex = %d / %d.\n", + priv->Record_CCK_20Mindex, priv->Record_CCK_40Mindex); + + if(priv->rtllib->current_network.channel == 14 && !priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = true; + CCKSwingNeedUpdate = 1; + } + else if(priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14) + { + priv->bcck_in_ch14 = false; + CCKSwingNeedUpdate = 1; + } + + if(priv->CCK_index != tmpCCKindex) +{ + priv->CCK_index = tmpCCKindex; + CCKSwingNeedUpdate = 1; + } + + if(CCKSwingNeedUpdate) + { + dm_cck_txpower_adjust(dev, priv->bcck_in_ch14); + } + if(priv->OFDM_index[0] != tmpOFDMindex) + { + priv->OFDM_index[0] = tmpOFDMindex; + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, OFDMSwingTable[priv->OFDM_index[0]]); + RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n", + priv->OFDM_index[0], OFDMSwingTable[priv->OFDM_index[0]]); + } + priv->txpower_count = 0; +} +#elif defined (RTL8192SE) +static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 ThermalValue=0; + u32 FwCmdVal=0; + + priv->btxpower_trackingInit = true; + + + ThermalValue = (u8)rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, RF_T_METER, 0x1f); + RT_TRACE(COMP_POWER_TRACKING, "Readback Thermal Meter = 0x%x\n", ThermalValue); + printk("%s()Readback Thermal Meter = 0x%x\n", __func__,ThermalValue); + if(ThermalValue) + { + priv->ThermalValue = ThermalValue; + if(priv->pFirmware->FirmwareVersion >= 0x35) + { + priv->rtllib->SetFwCmdHandler(dev, FW_CMD_TXPWR_TRACK_THERMAL); + } + else + { + FwCmdVal = (FW_TXPWR_TRACK_THERMAL| + (priv->ThermalMeter[0]<<8)|(ThermalValue<<16)); + RT_TRACE(COMP_POWER_TRACKING, "Write to FW Thermal Val = 0x%x\n", FwCmdVal); + write_nic_dword(dev, WFM5, FwCmdVal); + ChkFwCmdIoDone(dev); + } + } + + priv->txpower_count = 0; +} +#endif + +void dm_txpower_trackingcallback(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,txpower_tracking_wq); + struct net_device *dev = priv->rtllib->dev; +#else + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = rtllib_priv(dev); +#endif + +#ifdef RTL8190P + dm_TXPowerTrackingCallback_TSSI(dev); +#elif defined(RTL8192E) + if(priv->IC_Cut >= IC_VersionCut_D) + dm_TXPowerTrackingCallback_TSSI(dev); + else + dm_TXPowerTrackingCallback_ThermalMeter(dev); +#elif defined(RTL8192SE) + dm_TXPowerTrackingCallback_ThermalMeter(dev); +#endif +} + +#ifndef RTL8192SE +static void dm_InitializeTXPowerTracking_TSSI(struct net_device *dev) +{ + + struct r8192_priv *priv = rtllib_priv(dev); + + priv->txbbgain_table[0].txbb_iq_amplifygain = 12; + priv->txbbgain_table[0].txbbgain_value=0x7f8001fe; + priv->txbbgain_table[1].txbb_iq_amplifygain = 11; + priv->txbbgain_table[1].txbbgain_value=0x788001e2; + priv->txbbgain_table[2].txbb_iq_amplifygain = 10; + priv->txbbgain_table[2].txbbgain_value=0x71c001c7; + priv->txbbgain_table[3].txbb_iq_amplifygain = 9; + priv->txbbgain_table[3].txbbgain_value=0x6b8001ae; + priv->txbbgain_table[4].txbb_iq_amplifygain = 8; + priv->txbbgain_table[4].txbbgain_value=0x65400195; + priv->txbbgain_table[5].txbb_iq_amplifygain = 7; + priv->txbbgain_table[5].txbbgain_value=0x5fc0017f; + priv->txbbgain_table[6].txbb_iq_amplifygain = 6; + priv->txbbgain_table[6].txbbgain_value=0x5a400169; + priv->txbbgain_table[7].txbb_iq_amplifygain = 5; + priv->txbbgain_table[7].txbbgain_value=0x55400155; + priv->txbbgain_table[8].txbb_iq_amplifygain = 4; + priv->txbbgain_table[8].txbbgain_value=0x50800142; + priv->txbbgain_table[9].txbb_iq_amplifygain = 3; + priv->txbbgain_table[9].txbbgain_value=0x4c000130; + priv->txbbgain_table[10].txbb_iq_amplifygain = 2; + priv->txbbgain_table[10].txbbgain_value=0x47c0011f; + priv->txbbgain_table[11].txbb_iq_amplifygain = 1; + priv->txbbgain_table[11].txbbgain_value=0x43c0010f; + priv->txbbgain_table[12].txbb_iq_amplifygain = 0; + priv->txbbgain_table[12].txbbgain_value=0x40000100; + priv->txbbgain_table[13].txbb_iq_amplifygain = -1; + priv->txbbgain_table[13].txbbgain_value=0x3c8000f2; + priv->txbbgain_table[14].txbb_iq_amplifygain = -2; + priv->txbbgain_table[14].txbbgain_value=0x390000e4; + priv->txbbgain_table[15].txbb_iq_amplifygain = -3; + priv->txbbgain_table[15].txbbgain_value=0x35c000d7; + priv->txbbgain_table[16].txbb_iq_amplifygain = -4; + priv->txbbgain_table[16].txbbgain_value=0x32c000cb; + priv->txbbgain_table[17].txbb_iq_amplifygain = -5; + priv->txbbgain_table[17].txbbgain_value=0x300000c0; + priv->txbbgain_table[18].txbb_iq_amplifygain = -6; + priv->txbbgain_table[18].txbbgain_value=0x2d4000b5; + priv->txbbgain_table[19].txbb_iq_amplifygain = -7; + priv->txbbgain_table[19].txbbgain_value=0x2ac000ab; + priv->txbbgain_table[20].txbb_iq_amplifygain = -8; + priv->txbbgain_table[20].txbbgain_value=0x288000a2; + priv->txbbgain_table[21].txbb_iq_amplifygain = -9; + priv->txbbgain_table[21].txbbgain_value=0x26000098; + priv->txbbgain_table[22].txbb_iq_amplifygain = -10; + priv->txbbgain_table[22].txbbgain_value=0x24000090; + priv->txbbgain_table[23].txbb_iq_amplifygain = -11; + priv->txbbgain_table[23].txbbgain_value=0x22000088; + priv->txbbgain_table[24].txbb_iq_amplifygain = -12; + priv->txbbgain_table[24].txbbgain_value=0x20000080; + priv->txbbgain_table[25].txbb_iq_amplifygain = -13; + priv->txbbgain_table[25].txbbgain_value=0x1a00006c; + priv->txbbgain_table[26].txbb_iq_amplifygain = -14; + priv->txbbgain_table[26].txbbgain_value=0x1c800072; + priv->txbbgain_table[27].txbb_iq_amplifygain = -15; + priv->txbbgain_table[27].txbbgain_value=0x18000060; + priv->txbbgain_table[28].txbb_iq_amplifygain = -16; + priv->txbbgain_table[28].txbbgain_value=0x19800066; + priv->txbbgain_table[29].txbb_iq_amplifygain = -17; + priv->txbbgain_table[29].txbbgain_value=0x15800056; + priv->txbbgain_table[30].txbb_iq_amplifygain = -18; + priv->txbbgain_table[30].txbbgain_value=0x26c0005b; + priv->txbbgain_table[31].txbb_iq_amplifygain = -19; + priv->txbbgain_table[31].txbbgain_value=0x14400051; + priv->txbbgain_table[32].txbb_iq_amplifygain = -20; + priv->txbbgain_table[32].txbbgain_value=0x24400051; + priv->txbbgain_table[33].txbb_iq_amplifygain = -21; + priv->txbbgain_table[33].txbbgain_value=0x1300004c; + priv->txbbgain_table[34].txbb_iq_amplifygain = -22; + priv->txbbgain_table[34].txbbgain_value=0x12000048; + priv->txbbgain_table[35].txbb_iq_amplifygain = -23; + priv->txbbgain_table[35].txbbgain_value=0x11000044; + priv->txbbgain_table[36].txbb_iq_amplifygain = -24; + priv->txbbgain_table[36].txbbgain_value=0x10000040; + + priv->cck_txbbgain_table[0].ccktxbb_valuearray[0] = 0x36; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[1] = 0x35; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[2] = 0x2e; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[3] = 0x25; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[4] = 0x1c; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[5] = 0x12; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[6] = 0x09; + priv->cck_txbbgain_table[0].ccktxbb_valuearray[7] = 0x04; + + priv->cck_txbbgain_table[1].ccktxbb_valuearray[0] = 0x33; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[1] = 0x32; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[2] = 0x2b; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[3] = 0x23; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[4] = 0x1a; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[5] = 0x11; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[6] = 0x08; + priv->cck_txbbgain_table[1].ccktxbb_valuearray[7] = 0x04; + + priv->cck_txbbgain_table[2].ccktxbb_valuearray[0] = 0x30; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[1] = 0x2f; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[2] = 0x29; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[3] = 0x21; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[4] = 0x19; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[5] = 0x10; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[6] = 0x08; + priv->cck_txbbgain_table[2].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[3].ccktxbb_valuearray[0] = 0x2d; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[1] = 0x2d; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[2] = 0x27; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[3] = 0x1f; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[4] = 0x18; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[5] = 0x0f; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[6] = 0x08; + priv->cck_txbbgain_table[3].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[4].ccktxbb_valuearray[0] = 0x2b; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[1] = 0x2a; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[2] = 0x25; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[3] = 0x1e; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[4] = 0x16; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[5] = 0x0e; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[6] = 0x07; + priv->cck_txbbgain_table[4].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[5].ccktxbb_valuearray[0] = 0x28; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[1] = 0x28; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[2] = 0x22; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[3] = 0x1c; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[4] = 0x15; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[5] = 0x0d; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[6] = 0x07; + priv->cck_txbbgain_table[5].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[6].ccktxbb_valuearray[0] = 0x26; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[1] = 0x25; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[2] = 0x21; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[3] = 0x1b; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[4] = 0x14; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[5] = 0x0d; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[6] = 0x06; + priv->cck_txbbgain_table[6].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[7].ccktxbb_valuearray[0] = 0x24; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[1] = 0x23; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[2] = 0x1f; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[3] = 0x19; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[4] = 0x13; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[5] = 0x0c; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[6] = 0x06; + priv->cck_txbbgain_table[7].ccktxbb_valuearray[7] = 0x03; + + priv->cck_txbbgain_table[8].ccktxbb_valuearray[0] = 0x22; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[1] = 0x21; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[2] = 0x1d; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[3] = 0x18; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[4] = 0x11; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[5] = 0x0b; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[6] = 0x06; + priv->cck_txbbgain_table[8].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[9].ccktxbb_valuearray[0] = 0x20; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[1] = 0x20; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[2] = 0x1b; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[3] = 0x16; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[4] = 0x11; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[5] = 0x08; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[6] = 0x05; + priv->cck_txbbgain_table[9].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[10].ccktxbb_valuearray[0] = 0x1f; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[1] = 0x1e; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[2] = 0x1a; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[3] = 0x15; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[4] = 0x10; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[5] = 0x0a; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[6] = 0x05; + priv->cck_txbbgain_table[10].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[11].ccktxbb_valuearray[0] = 0x1d; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[1] = 0x1c; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[2] = 0x18; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[3] = 0x14; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[4] = 0x0f; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[5] = 0x0a; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[6] = 0x05; + priv->cck_txbbgain_table[11].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[12].ccktxbb_valuearray[0] = 0x1b; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[1] = 0x1a; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[2] = 0x17; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[3] = 0x13; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[4] = 0x0e; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[5] = 0x09; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[6] = 0x04; + priv->cck_txbbgain_table[12].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[13].ccktxbb_valuearray[0] = 0x1a; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[1] = 0x19; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[2] = 0x16; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[3] = 0x12; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[4] = 0x0d; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[5] = 0x09; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[6] = 0x04; + priv->cck_txbbgain_table[13].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[14].ccktxbb_valuearray[0] = 0x18; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[1] = 0x17; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[2] = 0x15; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[3] = 0x11; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[4] = 0x0c; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[5] = 0x08; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[6] = 0x04; + priv->cck_txbbgain_table[14].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[15].ccktxbb_valuearray[0] = 0x17; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[1] = 0x16; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[2] = 0x13; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[3] = 0x10; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[4] = 0x0c; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[5] = 0x08; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[6] = 0x04; + priv->cck_txbbgain_table[15].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[16].ccktxbb_valuearray[0] = 0x16; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[1] = 0x15; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[2] = 0x12; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[3] = 0x0f; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[4] = 0x0b; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[5] = 0x07; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[6] = 0x04; + priv->cck_txbbgain_table[16].ccktxbb_valuearray[7] = 0x01; + + priv->cck_txbbgain_table[17].ccktxbb_valuearray[0] = 0x14; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[1] = 0x14; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[2] = 0x11; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[3] = 0x0e; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[4] = 0x0b; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[5] = 0x07; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[17].ccktxbb_valuearray[7] = 0x02; + + priv->cck_txbbgain_table[18].ccktxbb_valuearray[0] = 0x13; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[1] = 0x13; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[2] = 0x10; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[3] = 0x0d; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[4] = 0x0a; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[5] = 0x06; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[18].ccktxbb_valuearray[7] = 0x01; + + priv->cck_txbbgain_table[19].ccktxbb_valuearray[0] = 0x12; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[1] = 0x12; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[2] = 0x0f; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[3] = 0x0c; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[4] = 0x09; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[5] = 0x06; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[19].ccktxbb_valuearray[7] = 0x01; + + priv->cck_txbbgain_table[20].ccktxbb_valuearray[0] = 0x11; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[1] = 0x11; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[2] = 0x0f; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[3] = 0x0c; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[4] = 0x09; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[5] = 0x06; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[20].ccktxbb_valuearray[7] = 0x01; + + priv->cck_txbbgain_table[21].ccktxbb_valuearray[0] = 0x10; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[1] = 0x10; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[2] = 0x0e; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[3] = 0x0b; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[4] = 0x08; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[5] = 0x05; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[21].ccktxbb_valuearray[7] = 0x01; + + priv->cck_txbbgain_table[22].ccktxbb_valuearray[0] = 0x0f; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[1] = 0x0f; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[2] = 0x0d; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[3] = 0x0b; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[4] = 0x08; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[5] = 0x05; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[6] = 0x03; + priv->cck_txbbgain_table[22].ccktxbb_valuearray[7] = 0x01; + + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[0] = 0x36; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[1] = 0x35; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[2] = 0x2e; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[3] = 0x1b; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[0].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[0] = 0x33; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[1] = 0x32; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[2] = 0x2b; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[3] = 0x19; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[1].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[0] = 0x30; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[1] = 0x2f; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[2] = 0x29; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[3] = 0x18; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[2].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[0] = 0x2d; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[1] = 0x2d; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[2] = 0x27; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[3] = 0x17; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[3].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[0] = 0x2b; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[1] = 0x2a; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[2] = 0x25; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[3] = 0x15; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[4].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[0] = 0x28; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[1] = 0x28; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[2] = 0x22; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[3] = 0x14; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[5].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[0] = 0x26; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[1] = 0x25; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[2] = 0x21; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[3] = 0x13; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[6].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[0] = 0x24; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[1] = 0x23; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[2] = 0x1f; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[3] = 0x12; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[7].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[0] = 0x22; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[1] = 0x21; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[2] = 0x1d; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[3] = 0x11; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[8].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[0] = 0x20; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[1] = 0x20; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[2] = 0x1b; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[3] = 0x10; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[9].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[0] = 0x1f; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[1] = 0x1e; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[2] = 0x1a; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[3] = 0x0f; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[10].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[0] = 0x1d; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[1] = 0x1c; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[2] = 0x18; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[3] = 0x0e; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[11].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[0] = 0x1b; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[1] = 0x1a; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[2] = 0x17; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[3] = 0x0e; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[12].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[0] = 0x1a; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[1] = 0x19; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[2] = 0x16; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[3] = 0x0d; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[13].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[0] = 0x18; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[1] = 0x17; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[2] = 0x15; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[3] = 0x0c; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[14].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[0] = 0x17; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[1] = 0x16; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[2] = 0x13; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[3] = 0x0b; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[15].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[0] = 0x16; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[1] = 0x15; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[2] = 0x12; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[3] = 0x0b; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[16].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[0] = 0x14; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[1] = 0x14; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[2] = 0x11; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[3] = 0x0a; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[17].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[0] = 0x13; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[1] = 0x13; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[2] = 0x10; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[3] = 0x0a; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[18].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[0] = 0x12; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[1] = 0x12; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[2] = 0x0f; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[3] = 0x09; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[19].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[0] = 0x11; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[1] = 0x11; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[2] = 0x0f; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[3] = 0x09; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[20].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[0] = 0x10; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[1] = 0x10; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[2] = 0x0e; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[3] = 0x08; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[21].ccktxbb_valuearray[7] = 0x00; + + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[0] = 0x0f; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[1] = 0x0f; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[2] = 0x0d; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[3] = 0x08; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[4] = 0x00; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[5] = 0x00; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[6] = 0x00; + priv->cck_txbbgain_ch14_table[22].ccktxbb_valuearray[7] = 0x00; + + priv->btxpower_tracking = true; + priv->txpower_count = 0; + priv->btxpower_trackingInit = false; + +} +#endif +#ifndef RTL8190P +static void dm_InitializeTXPowerTracking_ThermalMeter(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + +#ifdef RTL8192SE + priv->btxpower_tracking = false; + priv->txpower_count = 0; + priv->btxpower_trackingInit = false; +#else + + if(priv->rtllib->FwRWRF) + priv->btxpower_tracking = true; + else + priv->btxpower_tracking = false; + priv->txpower_count = 0; + priv->btxpower_trackingInit = false; +#endif + RT_TRACE(COMP_POWER_TRACKING, "pMgntInfo->bTXPowerTracking = %d\n", priv->btxpower_tracking); +} +#endif + +void dm_initialize_txpower_tracking(struct net_device *dev) +{ +#ifdef RTL8192E + struct r8192_priv *priv = rtllib_priv(dev); +#endif +#ifdef RTL8190P + dm_InitializeTXPowerTracking_TSSI(dev); +#elif defined RTL8192E + if(priv->IC_Cut >= IC_VersionCut_D) + dm_InitializeTXPowerTracking_TSSI(dev); + else + dm_InitializeTXPowerTracking_ThermalMeter(dev); +#elif defined RTL8192SE + dm_InitializeTXPowerTracking_ThermalMeter(dev); +#endif +} + +#if (defined RTL8192E || defined RTL8190P) +static void dm_CheckTXPowerTracking_TSSI(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + static u32 tx_power_track_counter = 0; + RT_TRACE(COMP_POWER_TRACKING,"%s()\n",__FUNCTION__); + if(read_nic_byte(dev, 0x11e) ==1) + return; + if(!priv->btxpower_tracking) + return; + tx_power_track_counter++; + + + if(tx_power_track_counter >= 180) + { + queue_delayed_work_rsl(priv->priv_wq,&priv->txpower_tracking_wq,0); + tx_power_track_counter =0; + } + +} +#endif +#ifndef RTL8190P +static void dm_CheckTXPowerTracking_ThermalMeter(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + static u8 TM_Trigger=0; + u8 TxPowerCheckCnt = 0; + + if(IS_HARDWARE_TYPE_8192SE(dev)) + TxPowerCheckCnt = 5; + else + TxPowerCheckCnt = 2; + if(!priv->btxpower_tracking){ + return; + } else { + if(priv->txpower_count <= TxPowerCheckCnt) { + priv->txpower_count++; + return; + } + } + + if(!TM_Trigger) + { +#ifdef RTL8192SE + if(IS_HARDWARE_TYPE_8192SE(dev)) + { + rtl8192_phy_SetRFReg(dev, RF90_PATH_A, RF_T_METER, bRFRegOffsetMask, 0x60); + RT_TRACE(COMP_POWER_TRACKING, "Trigger 92S Thermal Meter!!\n"); + } + else +#endif + { + rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); + rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); + rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); + rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); + } + TM_Trigger = 1; + return; + } else { + printk("===============>Schedule TxPowerTrackingWorkItem\n"); +#ifdef RTL8192SE + DM_TXPowerTracking92SDirectCall(dev); +#else + + queue_delayed_work_rsl(priv->priv_wq,&priv->txpower_tracking_wq,0); +#endif + TM_Trigger = 0; + } + + } +#endif + +#ifdef RTL8192SE +void DM_TXPowerTracking92SDirectCall(struct net_device *dev) +{ + dm_TXPowerTrackingCallback_ThermalMeter(dev); + } +#endif + +static void dm_check_txpower_tracking(struct net_device *dev) +{ +#ifdef RTL8192E + struct r8192_priv *priv = rtllib_priv(dev); +#endif +#ifdef RTL8190P + dm_CheckTXPowerTracking_TSSI(dev); +#elif defined RTL8192E + if(priv->IC_Cut >= IC_VersionCut_D) + dm_CheckTXPowerTracking_TSSI(dev); + else + dm_CheckTXPowerTracking_ThermalMeter(dev); +#elif defined RTL8192SE + dm_CheckTXPowerTracking_ThermalMeter(dev); +#endif + +} + +#ifndef RTL8192SE +static void dm_CCKTxPowerAdjust_TSSI(struct net_device *dev, bool bInCH14) +{ + u32 TempVal; + struct r8192_priv *priv = rtllib_priv(dev); + TempVal = 0; + if(!bInCH14){ + TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] + + (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ; + + rtl8192_setBBreg(dev, rCCK0_TxFilter1,bMaskHWord, TempVal); + TempVal = 0; + TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] + + (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) + + (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+ + (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24)); + rtl8192_setBBreg(dev, rCCK0_TxFilter2,bMaskDWord, TempVal); + TempVal = 0; + TempVal = (u32)(priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] + + (priv->cck_txbbgain_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ; + + rtl8192_setBBreg(dev, rCCK0_DebugPort,bMaskLWord, TempVal); + } + else + { + TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[0] + + (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[1]<<8)) ; + + rtl8192_setBBreg(dev, rCCK0_TxFilter1,bMaskHWord, TempVal); + TempVal = 0; + TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[2] + + (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[3]<<8) + + (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[4]<<16 )+ + (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[5]<<24)); + rtl8192_setBBreg(dev, rCCK0_TxFilter2,bMaskDWord, TempVal); + TempVal = 0; + TempVal = (u32)(priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[6] + + (priv->cck_txbbgain_ch14_table[(u8)(priv->CCKPresentAttentuation)].ccktxbb_valuearray[7]<<8)) ; + + rtl8192_setBBreg(dev, rCCK0_DebugPort,bMaskLWord, TempVal); + } + + +} +#endif +#ifdef RTL8192E +static void dm_CCKTxPowerAdjust_ThermalMeter(struct net_device *dev, bool bInCH14) +{ + u32 TempVal; + struct r8192_priv *priv = rtllib_priv(dev); + + TempVal = 0; + if(!bInCH14) + { + TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] + + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][1]<<8) ; + rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", + rCCK0_TxFilter1, TempVal); + TempVal = 0; + TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][2] + + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][3]<<8) + + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][4]<<16 )+ + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][5]<<24); + rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", + rCCK0_TxFilter2, TempVal); + TempVal = 0; + TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] + + (CCKSwingTable_Ch1_Ch13[priv->CCK_index][7]<<8) ; + + rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING, "CCK not chnl 14, reg 0x%x = 0x%x\n", + rCCK0_DebugPort, TempVal); + } + else + { + TempVal = CCKSwingTable_Ch14[priv->CCK_index][0] + + (CCKSwingTable_Ch14[priv->CCK_index][1]<<8) ; + + rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", + rCCK0_TxFilter1, TempVal); + TempVal = 0; + TempVal = CCKSwingTable_Ch14[priv->CCK_index][2] + + (CCKSwingTable_Ch14[priv->CCK_index][3]<<8) + + (CCKSwingTable_Ch14[priv->CCK_index][4]<<16 )+ + (CCKSwingTable_Ch14[priv->CCK_index][5]<<24); + rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n", + rCCK0_TxFilter2, TempVal); + TempVal = 0; + TempVal = CCKSwingTable_Ch14[priv->CCK_index][6] + + (CCKSwingTable_Ch14[priv->CCK_index][7]<<8) ; + + rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal); + RT_TRACE(COMP_POWER_TRACKING,"CCK chnl 14, reg 0x%x = 0x%x\n", + rCCK0_DebugPort, TempVal); + } + } +#endif + +#ifndef RTL8192SE +extern void dm_cck_txpower_adjust( + struct net_device *dev, + bool binch14 +) +{ +#ifndef RTL8190P + struct r8192_priv *priv = rtllib_priv(dev); +#endif +#ifdef RTL8190P + dm_CCKTxPowerAdjust_TSSI(dev, binch14); +#else + if(priv->IC_Cut >= IC_VersionCut_D) + dm_CCKTxPowerAdjust_TSSI(dev, binch14); + else + dm_CCKTxPowerAdjust_ThermalMeter(dev, binch14); +#endif +} +#endif + + +#if defined(RTL8192E)||defined(RTL8190P) +static void dm_txpower_reset_recovery( + struct net_device *dev +) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + RT_TRACE(COMP_POWER_TRACKING, "Start Reset Recovery ==>\n"); + rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFA_txPowerTrackingIndex is %x\n",priv->rfa_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF A I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfa_txpowertrackingindex].txbb_iq_amplifygain); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: CCK Attenuation is %d dB\n",priv->CCKPresentAttentuation); + dm_cck_txpower_adjust(dev,priv->bcck_in_ch14); + + rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord, priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbbgain_value); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in RFC_txPowerTrackingIndex is %x\n",priv->rfc_txpowertrackingindex); + RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery : RF C I/Q Amplify Gain is %ld\n",priv->txbbgain_table[priv->rfc_txpowertrackingindex].txbb_iq_amplifygain); + +} + +extern void dm_restore_dynamic_mechanism_state(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 reg_ratr = priv->rate_adaptive.last_ratr; + + if(IS_NIC_DOWN(priv)){ + RT_TRACE(COMP_RATE, "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n"); + return; + } + + if(priv->rate_adaptive.rate_adaptive_disabled) + return; + if( !(priv->rtllib->mode==WIRELESS_MODE_N_24G || + priv->rtllib->mode==WIRELESS_MODE_N_5G)) + return; + { + u32 ratr_value; + ratr_value = reg_ratr; + if(priv->rf_type == RF_1T2R) + { + ratr_value &=~ (RATE_ALL_OFDM_2SS); + } + write_nic_dword(dev, RATR0, ratr_value); + write_nic_byte(dev, UFWP, 1); +#if 0 + u1Byte index; + u4Byte input_value; + index = (u1Byte)((((pu4Byte)(val))[0]) >> 28); + input_value = (((pu4Byte)(val))[0]) & 0x0fffffff; + PlatformEFIOWrite4Byte(dev, RATR0+index*4, input_value); +#endif + } + if(priv->btxpower_trackingInit && priv->btxpower_tracking){ + dm_txpower_reset_recovery(dev); + } + + dm_bb_initialgain_restore(dev); + +} + +static void dm_bb_initialgain_restore(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 bit_mask = 0x7f; + + if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + return; + + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); + rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bit_mask, (u32)priv->initgain_backup.xaagccore1); + rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bit_mask, (u32)priv->initgain_backup.xbagccore1); + rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, bit_mask, (u32)priv->initgain_backup.xcagccore1); + rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, bit_mask, (u32)priv->initgain_backup.xdagccore1); + bit_mask = bMaskByte2; + rtl8192_setBBreg(dev, rCCK0_CCA, bit_mask, (u32)priv->initgain_backup.cca); + + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n",priv->initgain_backup.xaagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc58 is %x\n",priv->initgain_backup.xbagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc60 is %x\n",priv->initgain_backup.xcagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc68 is %x\n",priv->initgain_backup.xdagccore1); + RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n",priv->initgain_backup.cca); + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); + +} + + +extern void dm_backup_dynamic_mechanism_state(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + priv->bswitch_fsync = false; + priv->bfsync_processing = false; + dm_bb_initialgain_backup(dev); + +} + + +static void dm_bb_initialgain_backup(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 bit_mask = bMaskByte0; + + if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + return; + + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); + priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bit_mask); + priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bit_mask); + priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bit_mask); + priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, bit_mask); + bit_mask = bMaskByte2; + priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, bit_mask); + + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n",priv->initgain_backup.xaagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc58 is %x\n",priv->initgain_backup.xbagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc60 is %x\n",priv->initgain_backup.xcagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc68 is %x\n",priv->initgain_backup.xdagccore1); + RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xa0a is %x\n",priv->initgain_backup.cca); + +} + +#endif +extern void dm_change_dynamic_initgain_thresh(struct net_device *dev, + u32 dm_type, + u32 dm_value) +{ +#ifdef RTL8192SE + struct r8192_priv *priv = rtllib_priv(dev); + if(dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) + priv->MidHighPwrTHR_L2 = (u8)dm_value; + else if(dm_type == DIG_TYPE_THRESH_HIGHPWR_LOW) + priv->MidHighPwrTHR_L1 = (u8)dm_value; + return; +#endif + if (dm_type == DIG_TYPE_THRESH_HIGH) + { + dm_digtable.rssi_high_thresh = dm_value; + } + else if (dm_type == DIG_TYPE_THRESH_LOW) + { + dm_digtable.rssi_low_thresh = dm_value; + } + else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) + { + dm_digtable.rssi_high_power_highthresh = dm_value; + } + else if (dm_type == DIG_TYPE_THRESH_HIGHPWR_HIGH) + { + dm_digtable.rssi_high_power_highthresh = dm_value; + } + else if (dm_type == DIG_TYPE_ENABLE) + { + dm_digtable.dig_state = DM_STA_DIG_MAX; + dm_digtable.dig_enable_flag = true; + } + else if (dm_type == DIG_TYPE_DISABLE) + { + dm_digtable.dig_state = DM_STA_DIG_MAX; + dm_digtable.dig_enable_flag = false; + } + else if (dm_type == DIG_TYPE_DBG_MODE) + { + if(dm_value >= DM_DBG_MAX) + dm_value = DM_DBG_OFF; + dm_digtable.dbg_mode = (u8)dm_value; + } + else if (dm_type == DIG_TYPE_RSSI) + { + if(dm_value > 100) + dm_value = 30; + dm_digtable.rssi_val = (long)dm_value; + } + else if (dm_type == DIG_TYPE_ALGORITHM) + { + if (dm_value >= DIG_ALGO_MAX) + dm_value = DIG_ALGO_BY_FALSE_ALARM; + if(dm_digtable.dig_algorithm != (u8)dm_value) + dm_digtable.dig_algorithm_switch = 1; + dm_digtable.dig_algorithm = (u8)dm_value; + } + else if (dm_type == DIG_TYPE_BACKOFF) + { + if(dm_value > 30) + dm_value = 30; + dm_digtable.backoff_val = (u8)dm_value; + } + else if(dm_type == DIG_TYPE_RX_GAIN_MIN) + { + if(dm_value == 0) + dm_value = 0x1; + dm_digtable.rx_gain_range_min = (u8)dm_value; + } + else if(dm_type == DIG_TYPE_RX_GAIN_MAX) + { + if(dm_value > 0x50) + dm_value = 0x50; + dm_digtable.rx_gain_range_max = (u8)dm_value; + } +} +extern void +dm_change_fsync_setting( + struct net_device *dev, + s32 DM_Type, + s32 DM_Value) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if (DM_Type == 0) + { + if(DM_Value > 1) + DM_Value = 1; + priv->framesyncMonitor = (u8)DM_Value; + } +} + +extern void +dm_change_rxpath_selection_setting( + struct net_device *dev, + s32 DM_Type, + s32 DM_Value) +{ + struct r8192_priv *priv = rtllib_priv(dev); + prate_adaptive pRA = (prate_adaptive)&(priv->rate_adaptive); + + + if(DM_Type == 0) + { + if(DM_Value > 1) + DM_Value = 1; + DM_RxPathSelTable.Enable = (u8)DM_Value; + } + else if(DM_Type == 1) + { + if(DM_Value > 1) + DM_Value = 1; + DM_RxPathSelTable.DbgMode = (u8)DM_Value; + } + else if(DM_Type == 2) + { + if(DM_Value > 40) + DM_Value = 40; + DM_RxPathSelTable.SS_TH_low = (u8)DM_Value; + } + else if(DM_Type == 3) + { + if(DM_Value > 25) + DM_Value = 25; + DM_RxPathSelTable.diff_TH = (u8)DM_Value; + } + else if(DM_Type == 4) + { + if(DM_Value >= CCK_Rx_Version_MAX) + DM_Value = CCK_Rx_Version_1; + DM_RxPathSelTable.cck_method= (u8)DM_Value; + } + else if(DM_Type == 10) + { + if(DM_Value > 100) + DM_Value = 50; + DM_RxPathSelTable.rf_rssi[0] = (u8)DM_Value; + } + else if(DM_Type == 11) + { + if(DM_Value > 100) + DM_Value = 50; + DM_RxPathSelTable.rf_rssi[1] = (u8)DM_Value; + } + else if(DM_Type == 12) + { + if(DM_Value > 100) + DM_Value = 50; + DM_RxPathSelTable.rf_rssi[2] = (u8)DM_Value; + } + else if(DM_Type == 13) + { + if(DM_Value > 100) + DM_Value = 50; + DM_RxPathSelTable.rf_rssi[3] = (u8)DM_Value; + } + else if(DM_Type == 20) + { + if(DM_Value > 1) + DM_Value = 1; + pRA->ping_rssi_enable = (u8)DM_Value; + } + else if(DM_Type == 21) + { + if(DM_Value > 30) + DM_Value = 30; + pRA->ping_rssi_thresh_for_ra = DM_Value; + } +} + +#if 0 +extern void dm_force_tx_fw_info(struct net_device *dev, + u32 force_type, + u32 force_value) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if (force_type == 0) + { + priv->tx_fwinfo_force_subcarriermode = 0; + } + else if(force_type == 1) + { + priv->tx_fwinfo_force_subcarriermode = 1; + if(force_value > 3) + force_value = 3; + priv->tx_fwinfo_force_subcarrierval = (u8)force_value; + } +} +#endif + +static void dm_dig_init(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + dm_digtable.dig_enable_flag = true; + dm_digtable.Backoff_Enable_Flag = true; + +#ifdef RTL8192SE + if((priv->DM_Type == DM_Type_ByDriver) && (priv->pFirmware->FirmwareVersion >= 0x3c)) + dm_digtable.dig_algorithm = DIG_ALGO_BY_TOW_PORT; + else + dm_digtable.dig_algorithm = DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM; +#else + dm_digtable.dig_algorithm = DIG_ALGO_BY_RSSI; +#endif + + dm_digtable.Dig_TwoPort_Algorithm = DIG_TWO_PORT_ALGO_RSSI; + dm_digtable.Dig_Ext_Port_Stage = DIG_EXT_PORT_STAGE_MAX; + dm_digtable.dbg_mode = DM_DBG_OFF; + dm_digtable.dig_algorithm_switch = 0; + + dm_digtable.dig_state = DM_STA_DIG_MAX; + dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX; + dm_digtable.CurSTAConnectState = dm_digtable.PreSTAConnectState = DIG_STA_DISCONNECT; + dm_digtable.CurAPConnectState = dm_digtable.PreAPConnectState = DIG_AP_DISCONNECT; + dm_digtable.initialgain_lowerbound_state = false; + + dm_digtable.rssi_low_thresh = DM_DIG_THRESH_LOW; + dm_digtable.rssi_high_thresh = DM_DIG_THRESH_HIGH; + + dm_digtable.FALowThresh = DM_FALSEALARM_THRESH_LOW; + dm_digtable.FAHighThresh = DM_FALSEALARM_THRESH_HIGH; + + dm_digtable.rssi_high_power_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW; + dm_digtable.rssi_high_power_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH; + + dm_digtable.rssi_val = 50; + dm_digtable.backoff_val = DM_DIG_BACKOFF; + dm_digtable.rx_gain_range_max = DM_DIG_MAX; + if(priv->CustomerID == RT_CID_819x_Netcore) + dm_digtable.rx_gain_range_min = DM_DIG_MIN_Netcore; + else + dm_digtable.rx_gain_range_min = DM_DIG_MIN; + + dm_digtable.BackoffVal_range_max = DM_DIG_BACKOFF_MAX; + dm_digtable.BackoffVal_range_min = DM_DIG_BACKOFF_MIN; +} + +void dm_FalseAlarmCounterStatistics(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 ret_value; + PFALSE_ALARM_STATISTICS FalseAlmCnt = &(priv->FalseAlmCnt); + + ret_value = rtl8192_QueryBBReg(dev, rOFDM_PHYCounter1, bMaskDWord); + FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16); + + ret_value = rtl8192_QueryBBReg(dev, rOFDM_PHYCounter2, bMaskDWord); + FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff); + FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16); + ret_value = rtl8192_QueryBBReg(dev, rOFDM_PHYCounter3, bMaskDWord); + FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff); + + FalseAlmCnt->Cnt_Ofdm_fail = FalseAlmCnt->Cnt_Parity_Fail + FalseAlmCnt->Cnt_Rate_Illegal + + FalseAlmCnt->Cnt_Crc8_fail + FalseAlmCnt->Cnt_Mcs_fail; + + ret_value = rtl8192_QueryBBReg(dev, 0xc64, bMaskDWord); + FalseAlmCnt->Cnt_Cck_fail = (ret_value&0xffff); + FalseAlmCnt->Cnt_all = (FalseAlmCnt->Cnt_Parity_Fail + + FalseAlmCnt->Cnt_Rate_Illegal + + FalseAlmCnt->Cnt_Crc8_fail + + FalseAlmCnt->Cnt_Mcs_fail + + FalseAlmCnt->Cnt_Cck_fail); + + RT_TRACE(COMP_DIG, "Cnt_Ofdm_fail = %d, Cnt_Cck_fail = %d, Cnt_all = %d\n", + FalseAlmCnt->Cnt_Ofdm_fail, FalseAlmCnt->Cnt_Cck_fail , FalseAlmCnt->Cnt_all); +} + +#ifdef RTL8192SE +static void dm_CtrlInitGainAPByFalseAlarm(struct net_device *dev) +{ + static u8 binitialized = false; + + { + binitialized = false; + dm_digtable.Dig_Ext_Port_Stage = DIG_EXT_PORT_STAGE_MAX; + return; + } +} +#endif + +static void dm_ctrl_initgain_byrssi(struct net_device *dev) +{ + + if (dm_digtable.dig_enable_flag == false) + return; + + if(dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM) + dm_ctrl_initgain_byrssi_by_fwfalse_alarm(dev); + else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI) + dm_ctrl_initgain_byrssi_by_driverrssi(dev); +#ifdef RTL8192SE + else if(dm_digtable.dig_algorithm == DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM) + dm_CtrlInitGainBeforeConnectByRssiAndFalseAlarm(dev); + else if(dm_digtable.dig_algorithm == DIG_ALGO_BY_TOW_PORT) + dm_CtrlInitGainByTwoPort(dev); +#endif + else + return; +} + +#ifdef RTL8192SE +static void dm_CtrlInitGainByTwoPort(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if(rtllib_act_scanning(priv->rtllib,true) == true) + return; + + if((priv->rtllib->state > RTLLIB_NOLINK) && (priv->rtllib->state < RTLLIB_LINKED)) + dm_digtable.CurSTAConnectState = DIG_STA_BEFORE_CONNECT; + else if((priv->rtllib->state == RTLLIB_LINKED) ||(priv->rtllib->state == RTLLIB_LINKED_SCANNING)) + dm_digtable.CurSTAConnectState = DIG_STA_CONNECT; + else + dm_digtable.CurSTAConnectState = DIG_STA_DISCONNECT; + + dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb; + + if(dm_digtable.CurSTAConnectState != DIG_STA_DISCONNECT) + { + if(dm_digtable.Dig_TwoPort_Algorithm == DIG_TWO_PORT_ALGO_FALSE_ALARM) + { + dm_digtable.Dig_TwoPort_Algorithm = DIG_TWO_PORT_ALGO_RSSI; + priv->rtllib->SetFwCmdHandler(dev, FW_CMD_DIG_MODE_SS); + } + } + + dm_FalseAlarmCounterStatistics(dev); + dm_initial_gain_STABeforeConnect(dev); + dm_CtrlInitGainAPByFalseAlarm(dev); + + dm_digtable.PreSTAConnectState = dm_digtable.CurSTAConnectState; +} +#endif + +/*----------------------------------------------------------------------------- + * Function: dm_CtrlInitGainBeforeConnectByRssiAndFalseAlarm() + * + * Overview: Driver monitor RSSI and False Alarm to change initial gain. + Only change initial gain during link in progress. + * + * Input: IN PADAPTER pAdapter + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 03/04/2009 hpfan Create Version 0. + * + *---------------------------------------------------------------------------*/ + +#ifdef RTL8192SE +static void dm_CtrlInitGainBeforeConnectByRssiAndFalseAlarm(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if(rtllib_act_scanning(priv->rtllib,true) == true) + return; + + if((priv->rtllib->state > RTLLIB_NOLINK) && (priv->rtllib->state < RTLLIB_LINKED)) + dm_digtable.CurSTAConnectState = DIG_STA_BEFORE_CONNECT; + else if((priv->rtllib->state == RTLLIB_LINKED) ||(priv->rtllib->state == RTLLIB_LINKED_SCANNING)) + dm_digtable.CurSTAConnectState = DIG_STA_CONNECT; + else + dm_digtable.CurSTAConnectState = DIG_STA_DISCONNECT; + + if(dm_digtable.dbg_mode == DM_DBG_OFF) + dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb; + + dm_FalseAlarmCounterStatistics(dev); + dm_initial_gain_STABeforeConnect(dev); + dm_digtable.PreSTAConnectState = dm_digtable.CurSTAConnectState; + +} +#endif +static void dm_ctrl_initgain_byrssi_by_driverrssi( + struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 i; + static u8 fw_dig=0; + + if (dm_digtable.dig_enable_flag == false) + return; + + if(dm_digtable.dig_algorithm_switch) + fw_dig = 0; + if(fw_dig <= 3) + { + for(i=0; i<3; i++) + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); + fw_dig++; + dm_digtable.dig_state = DM_STA_DIG_OFF; + } + + if(priv->rtllib->state == RTLLIB_LINKED) + dm_digtable.CurSTAConnectState = DIG_STA_CONNECT; + else + dm_digtable.CurSTAConnectState = DIG_STA_DISCONNECT; + + + if(dm_digtable.dbg_mode == DM_DBG_OFF) + dm_digtable.rssi_val = priv->undecorated_smoothed_pwdb; + dm_initial_gain(dev); + dm_pd_th(dev); + dm_cs_ratio(dev); + if(dm_digtable.dig_algorithm_switch) + dm_digtable.dig_algorithm_switch = 0; + dm_digtable.PreSTAConnectState = dm_digtable.CurSTAConnectState; + +} + +static void dm_ctrl_initgain_byrssi_by_fwfalse_alarm( + struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + static u32 reset_cnt = 0; + u8 i; + + if (dm_digtable.dig_enable_flag == false) + return; + + if(dm_digtable.dig_algorithm_switch) + { + dm_digtable.dig_state = DM_STA_DIG_MAX; + for(i=0; i<3; i++) + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); + dm_digtable.dig_algorithm_switch = 0; + } + + if (priv->rtllib->state != RTLLIB_LINKED) + return; + + if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_low_thresh) && + (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_thresh)) + { + return; + } + if ((priv->undecorated_smoothed_pwdb <= dm_digtable.rssi_low_thresh)) + { + if (dm_digtable.dig_state == DM_STA_DIG_OFF && + (priv->reset_count == reset_cnt)) + { + return; + } + else + { + reset_cnt = priv->reset_count; + } + + dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX; + dm_digtable.dig_state = DM_STA_DIG_OFF; + + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8); + + write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x17); + write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x17); + write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x17); + write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17); + + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x40); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00); + #endif + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(pAdapter, rOFDM0_RxDetector1, 0x40); + */ + + + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + + write_nic_byte(dev, 0xa0a, 0x08); + + return; + + } + + if ((priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) ) + { + u8 reset_flag = 0; + + if (dm_digtable.dig_state == DM_STA_DIG_ON && + (priv->reset_count == reset_cnt)) + { + dm_ctrl_initgain_byrssi_highpwr(dev); + return; + } + else + { + if (priv->reset_count != reset_cnt) + reset_flag = 1; + + reset_cnt = priv->reset_count; + } + + dm_digtable.dig_state = DM_STA_DIG_ON; + + if (reset_flag == 1) + { + write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c); + write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x2c); + write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x2c); + write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x2c); + } + else + { + write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x20); + write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x20); + write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x20); + write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x20); + } + + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); + #endif + /* + else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + */ + + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); + + write_nic_byte(dev, 0xa0a, 0xcd); + + + rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1); + + } + + dm_ctrl_initgain_byrssi_highpwr(dev); + +} + + +static void dm_ctrl_initgain_byrssi_highpwr( + struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + static u32 reset_cnt_highpwr = 0; + + if ((priv->undecorated_smoothed_pwdb > dm_digtable.rssi_high_power_lowthresh) && + (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_highthresh)) + { + return; + } + + if (priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_power_highthresh) + { + if (dm_digtable.dig_highpwr_state == DM_STA_DIG_ON && + (priv->reset_count == reset_cnt_highpwr)) + return; + else + dm_digtable.dig_highpwr_state = DM_STA_DIG_ON; + + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); + #endif + + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); + */ + + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x43); + } + else + { + if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF&& + (priv->reset_count == reset_cnt_highpwr)) + return; + else + dm_digtable.dig_highpwr_state = DM_STA_DIG_OFF; + + if (priv->undecorated_smoothed_pwdb < dm_digtable.rssi_high_power_lowthresh && + priv->undecorated_smoothed_pwdb >= dm_digtable.rssi_high_thresh) + { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); + #endif + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + */ + + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); + } + } + + reset_cnt_highpwr = priv->reset_count; + +} + + +static void dm_initial_gain( + struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 initial_gain=0; + static u8 initialized=0, force_write=0; + static u32 reset_cnt=0; + + if(dm_digtable.dig_algorithm_switch) + { + initialized = 0; + reset_cnt = 0; + } + + if(rtllib_act_scanning(priv->rtllib,true) == true) + { + force_write = 1; + return; + } + + if(dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState) + { + if(dm_digtable.CurSTAConnectState == DIG_STA_CONNECT) + { + if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max) + dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max; + else if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min) + dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min; + else + dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val; + } + else + { + if(dm_digtable.cur_ig_value == 0) + dm_digtable.cur_ig_value = priv->DefaultInitialGain[0]; + else + dm_digtable.cur_ig_value = dm_digtable.pre_ig_value; + } + } + else + { + dm_digtable.cur_ig_value = priv->DefaultInitialGain[0]; + dm_digtable.pre_ig_value = 0; + } + + if(priv->reset_count != reset_cnt) + { + force_write = 1; + reset_cnt = priv->reset_count; + } + + if(dm_digtable.pre_ig_value != read_nic_byte(dev, rOFDM0_XAAGCCore1)) + force_write = 1; + + { + if((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value) + || !initialized || force_write) + { + initial_gain = (u8)dm_digtable.cur_ig_value; + write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain); + write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain); + write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain); + write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain); + dm_digtable.pre_ig_value = dm_digtable.cur_ig_value; + initialized = 1; + force_write = 0; + } + } +} + +void dm_initial_gain_STABeforeConnect( + struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 initial_gain=0; + static u8 initialized=0, force_write=0; + + RT_TRACE(COMP_DIG, "PreSTAConnectState = %x, CurSTAConnectState = %x\n", + dm_digtable.PreSTAConnectState, dm_digtable.CurSTAConnectState); + + + if((dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState) || + (dm_digtable.CurSTAConnectState == DIG_STA_BEFORE_CONNECT)) + { + if(dm_digtable.CurSTAConnectState == DIG_STA_BEFORE_CONNECT) + { + if(priv->rtllib->eRFPowerState != eRfOn) + return; + + if(dm_digtable.Backoff_Enable_Flag == true) + { + if(priv->FalseAlmCnt.Cnt_all > dm_digtable.FAHighThresh) + { + if((dm_digtable.backoff_val -6) < dm_digtable.BackoffVal_range_min) + dm_digtable.backoff_val = dm_digtable.BackoffVal_range_min; + else + dm_digtable.backoff_val -= 6; + } + else if(priv->FalseAlmCnt.Cnt_all < dm_digtable.FALowThresh) + { + if((dm_digtable.backoff_val+6) > dm_digtable.BackoffVal_range_max) + dm_digtable.backoff_val = dm_digtable.BackoffVal_range_max; + else + dm_digtable.backoff_val +=6; + } + } + else + dm_digtable.backoff_val =DM_DIG_BACKOFF; + + if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) > dm_digtable.rx_gain_range_max) + dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max; + else if((dm_digtable.rssi_val+10-dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min) + dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_min; + else + dm_digtable.cur_ig_value = dm_digtable.rssi_val+10-dm_digtable.backoff_val; + + if(priv->FalseAlmCnt.Cnt_all > 10000) + dm_digtable.cur_ig_value = (dm_digtable.cur_ig_value>0x33)?dm_digtable.cur_ig_value:0x33; + + if(priv->FalseAlmCnt.Cnt_all > 16000) + dm_digtable.cur_ig_value = dm_digtable.rx_gain_range_max; + + } + else + { + return; + } + } + else + { + dm_digtable.Dig_Ext_Port_Stage = DIG_EXT_PORT_STAGE_MAX; + priv->rtllib->SetFwCmdHandler(dev, FW_CMD_DIG_ENABLE); + + dm_digtable.backoff_val = DM_DIG_BACKOFF; + dm_digtable.cur_ig_value = priv->DefaultInitialGain[0]; + dm_digtable.pre_ig_value = 0; + return; + } + + if(dm_digtable.pre_ig_value != rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bMaskByte0)) + force_write = 1; + + if((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value) || !initialized || force_write) + { + priv->rtllib->SetFwCmdHandler(dev, FW_CMD_DIG_DISABLE); + + initial_gain = (u8)dm_digtable.cur_ig_value; + + rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bMaskByte0, initial_gain); + rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bMaskByte0, initial_gain); + dm_digtable.pre_ig_value = dm_digtable.cur_ig_value; + initialized = 1; + force_write = 0; + } + + RT_TRACE(COMP_DIG, "CurIGValue = 0x%x, pre_ig_value = 0x%x, backoff_val = %d\n", + dm_digtable.cur_ig_value, dm_digtable.pre_ig_value, dm_digtable.backoff_val); + +} + +static void dm_pd_th( + struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + static u8 initialized=0, force_write=0; + static u32 reset_cnt = 0; + + if(dm_digtable.dig_algorithm_switch) + { + initialized = 0; + reset_cnt = 0; + } + + if(dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState) + { + if(dm_digtable.CurSTAConnectState == DIG_STA_CONNECT) + { + if (dm_digtable.rssi_val >= dm_digtable.rssi_high_power_highthresh) + dm_digtable.curpd_thstate = DIG_PD_AT_HIGH_POWER; + else if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)) + dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; + else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) && + (dm_digtable.rssi_val < dm_digtable.rssi_high_power_lowthresh)) + dm_digtable.curpd_thstate = DIG_PD_AT_NORMAL_POWER; + else + dm_digtable.curpd_thstate = dm_digtable.prepd_thstate; + } + else + { + dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; + } + } + else + { + dm_digtable.curpd_thstate = DIG_PD_AT_LOW_POWER; + } + + if(priv->reset_count != reset_cnt) + { + force_write = 1; + reset_cnt = priv->reset_count; + } + + { + if((dm_digtable.prepd_thstate != dm_digtable.curpd_thstate) || + (initialized<=3) || force_write) + { + if(dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) + { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x40); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00); + #endif + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x40); + */ + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + } + else if(dm_digtable.curpd_thstate == DIG_PD_AT_NORMAL_POWER) + { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20); + #endif + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x42); + */ + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x44); + } + else if(dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) + { + if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); + #else + write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10); + #endif + /*else if (priv->card_8192 == HARDWARE_TYPE_RTL8190P) + write_nic_byte(dev, rOFDM0_RxDetector1, 0x41); + */ + } + else + write_nic_byte(dev, rOFDM0_RxDetector1, 0x43); + } + dm_digtable.prepd_thstate = dm_digtable.curpd_thstate; + if(initialized <= 3) + initialized++; + force_write = 0; + } + } +} + +static void dm_cs_ratio( + struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + static u8 initialized=0,force_write=0; + static u32 reset_cnt = 0; + + if(dm_digtable.dig_algorithm_switch) + { + initialized = 0; + reset_cnt = 0; + } + + if(dm_digtable.PreSTAConnectState == dm_digtable.CurSTAConnectState) + { + if(dm_digtable.CurSTAConnectState == DIG_STA_CONNECT) + { + if ((dm_digtable.rssi_val <= dm_digtable.rssi_low_thresh)) + dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; + else if ((dm_digtable.rssi_val >= dm_digtable.rssi_high_thresh) ) + dm_digtable.curcs_ratio_state = DIG_CS_RATIO_HIGHER; + else + dm_digtable.curcs_ratio_state = dm_digtable.precs_ratio_state; + } + else + { + dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; + } + } + else + { + dm_digtable.curcs_ratio_state = DIG_CS_RATIO_LOWER; + } + + if(priv->reset_count != reset_cnt) + { + force_write = 1; + reset_cnt = priv->reset_count; + } + + + { + if((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) || + !initialized || force_write) + { + if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER) + { + write_nic_byte(dev, 0xa0a, 0x08); + } + else if(dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER) + { + write_nic_byte(dev, 0xa0a, 0xcd); + } + dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state; + initialized = 1; + force_write = 0; + } + } +} + +extern void dm_init_edca_turbo(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + priv->bcurrent_turbo_EDCA = false; + priv->rtllib->bis_any_nonbepkts = false; + priv->bis_cur_rdlstate = false; +} + +#if 1 +static void dm_check_edca_turbo( + struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_HIGH_THROUGHPUT pHTInfo = priv->rtllib->pHTInfo; + + static unsigned long lastTxOkCnt = 0; + static unsigned long lastRxOkCnt = 0; + unsigned long curTxOkCnt = 0; + unsigned long curRxOkCnt = 0; + + if(priv->rtllib->iw_mode == IW_MODE_ADHOC) + { + goto dm_CheckEdcaTurbo_EXIT; + } + if(priv->rtllib->state != RTLLIB_LINKED) + { + goto dm_CheckEdcaTurbo_EXIT; + } + if(priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_EDCA_TURBO) + { + goto dm_CheckEdcaTurbo_EXIT; + } + + { + u8* peername[11] = {"unknown", "realtek_90", "realtek_92se","broadcom", "ralink", "atheros", "cisco", "marvell", "92u_softap", "self_softap"}; + static int wb_tmp = 0; + if (wb_tmp == 0){ + printk("%s():iot peer is %s, bssid:"MAC_FMT"\n",__FUNCTION__,peername[pHTInfo->IOTPeer], MAC_ARG(priv->rtllib->current_network.bssid)); + wb_tmp = 1; + } + } + if(!priv->rtllib->bis_any_nonbepkts) + { + curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; + curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; + if(pHTInfo->IOTAction & HT_IOT_ACT_EDCA_BIAS_ON_RX) + { + if(curTxOkCnt > 4*curRxOkCnt) + { + if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) + { + write_nic_dword(dev, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]); + priv->bis_cur_rdlstate = false; + } + } + else + { + if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) + { + if(priv->rtllib->mode == WIRELESS_MODE_G) + write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL_GMode[pHTInfo->IOTPeer]); + else + write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]); + priv->bis_cur_rdlstate = true; + } + } + priv->bcurrent_turbo_EDCA = true; + } + else + { + if(curRxOkCnt > 4*curTxOkCnt) + { + if(!priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) + { + if(priv->rtllib->mode == WIRELESS_MODE_G) + write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL_GMode[pHTInfo->IOTPeer]); + else + write_nic_dword(dev, EDCAPARA_BE, edca_setting_DL[pHTInfo->IOTPeer]); + priv->bis_cur_rdlstate = true; + } + } + else + { + if(priv->bis_cur_rdlstate || !priv->bcurrent_turbo_EDCA) + { + write_nic_dword(dev, EDCAPARA_BE, edca_setting_UL[pHTInfo->IOTPeer]); + priv->bis_cur_rdlstate = false; + } + + } + + priv->bcurrent_turbo_EDCA = true; + } + } + else + { + if(priv->bcurrent_turbo_EDCA) + { + +#if 0 + { + u8 u1bAIFS; + u32 u4bAcParam; + struct rtllib_qos_parameters *qos_parameters = &priv->rtllib->current_network.qos_data.parameters; + u8 mode = priv->rtllib->mode; + + dm_init_edca_turbo(dev); + u1bAIFS = qos_parameters->aifs[0] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime; + u4bAcParam = ((((u32)(qos_parameters->tx_op_limit[0]))<< AC_PARAM_TXOP_LIMIT_OFFSET)| + (((u32)(qos_parameters->cw_max[0]))<< AC_PARAM_ECW_MAX_OFFSET)| + (((u32)(qos_parameters->cw_min[0]))<< AC_PARAM_ECW_MIN_OFFSET)| + ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET)); + write_nic_dword(dev, EDCAPARA_BE, u4bAcParam); + + { + + PACI_AIFSN pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]); + u8 AcmCtrl = read_nic_byte( dev, AcmHwCtrl ); + if( pAciAifsn->f.ACM ) + { + AcmCtrl |= AcmHw_BeqEn; + } + else + { + AcmCtrl &= (~AcmHw_BeqEn); + } + + RT_TRACE( COMP_QOS,"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl ) ; + write_nic_byte(dev, AcmHwCtrl, AcmCtrl ); + } + } +#else + u8 tmp = AC0_BE; + priv->rtllib->SetHwRegHandler(dev, HW_VAR_AC_PARAM, (u8*)(&tmp) ); +#endif + priv->bcurrent_turbo_EDCA = false; + } + } + + +dm_CheckEdcaTurbo_EXIT: + priv->rtllib->bis_any_nonbepkts = false; + lastTxOkCnt = priv->stats.txbytesunicast; + lastRxOkCnt = priv->stats.rxbytesunicast; +} +#endif + +extern void DM_CTSToSelfSetting(struct net_device * dev,u32 DM_Type, u32 DM_Value) +{ + struct r8192_priv *priv = rtllib_priv((struct net_device *)dev); + + if (DM_Type == 0) + { + if(DM_Value > 1) + DM_Value = 1; + priv->rtllib->bCTSToSelfEnable = (bool)DM_Value; + } + else if(DM_Type == 1) + { + if(DM_Value >= 50) + DM_Value = 50; + priv->rtllib->CTSToSelfTH = (u8)DM_Value; + } +} + +static void dm_init_ctstoself(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv((struct net_device *)dev); + + priv->rtllib->bCTSToSelfEnable = true; + priv->rtllib->CTSToSelfTH = CTSToSelfTHVal; +} + +static void dm_ctstoself(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv((struct net_device *)dev); + PRT_HIGH_THROUGHPUT pHTInfo = priv->rtllib->pHTInfo; + static unsigned long lastTxOkCnt = 0; + static unsigned long lastRxOkCnt = 0; + unsigned long curTxOkCnt = 0; + unsigned long curRxOkCnt = 0; + + if(priv->rtllib->bCTSToSelfEnable != true) + { + pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF; + return; + } + if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) + { + curTxOkCnt = priv->stats.txbytesunicast - lastTxOkCnt; + curRxOkCnt = priv->stats.rxbytesunicast - lastRxOkCnt; + if(curRxOkCnt > 4*curTxOkCnt) + { + pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF; + } + else + { + #if 1 + pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF; + #else + if(priv->undecorated_smoothed_pwdb < priv->rtllib->CTSToSelfTH) + { + pHTInfo->IOTAction &= ~HT_IOT_ACT_FORCED_CTS2SELF; + } + else if(priv->undecorated_smoothed_pwdb >= (priv->rtllib->CTSToSelfTH+5)) + { + pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF; + } + #endif + } + + lastTxOkCnt = priv->stats.txbytesunicast; + lastRxOkCnt = priv->stats.rxbytesunicast; + } +} + + +static void +dm_Init_WA_Broadcom_IOT(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv((struct net_device *)dev); + PRT_HIGH_THROUGHPUT pHTInfo = priv->rtllib->pHTInfo; + + pHTInfo->bWAIotBroadcom = false; + pHTInfo->WAIotTH = WAIotTHVal; +} + +#ifdef RTL8192SE +static void +dm_WA_Broadcom_IOT(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv((struct net_device *)dev); + PRT_HIGH_THROUGHPUT pHTInfo = priv->rtllib->pHTInfo; + u8 update=0; + static enum rtllib_state connectState = RTLLIB_NOLINK; + + if( (pHTInfo->bWAIotBroadcom != true) || + (priv->rtllib->mode == WIRELESS_MODE_B) || + (pHTInfo->bCurBW40MHz)) + { + if(pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) + { + pHTInfo->IOTAction &= ~HT_IOT_ACT_WA_IOT_Broadcom; + update = 1; + printk(" dm_WA_Broadcom_IOT(), disable HT_IOT_ACT_WA_IOT_Broadcom\n"); + } + else + return; + } + + if(connectState == RTLLIB_LINKED && priv->rtllib->state == RTLLIB_LINKED) + { + if(pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) + { + pHTInfo->IOTAction &= ~HT_IOT_ACT_WA_IOT_Broadcom; + update = 1; + pHTInfo->bWAIotBroadcom = false; + printk("dm_WA_Broadcom_IOT(), from connect to disconnected, disable HT_IOT_ACT_WA_IOT_Broadcom\n"); + } + } + connectState = priv->rtllib->state; + + if(!update && pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) + { + if(priv->undecorated_smoothed_pwdb < pHTInfo->WAIotTH) + { + if(pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) + { + pHTInfo->IOTAction &= ~HT_IOT_ACT_WA_IOT_Broadcom; + update = 1; + printk("dm_WA_Broadcom_IOT() ==> WA_IOT enable cck rates\n"); + } + } + else if(priv->undecorated_smoothed_pwdb >= (priv->rtllib->CTSToSelfTH+5)) + { + if((pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) == 0) + { + pHTInfo->IOTAction |= HT_IOT_ACT_WA_IOT_Broadcom; + update = 1; + printk("dm_WA_Broadcom_IOT() ==> WA_IOT disable cck rates\n"); + } + } + } + + if(update){ + if(priv->rtllib->bUseRAMask){ + priv->rtllib->UpdateHalRAMaskHandler( + dev, + false, + 0, + priv->rtllib->pHTInfo->PeerMimoPs, + priv->rtllib->mode, + priv->rtllib->pHTInfo->bCurTxBW40MHz, + 0); + }else{ + priv->ops->update_ratr_table(dev, priv->rtllib->dot11HTOperationalRateSet, NULL); + } + priv->rtllib->SetHwRegHandler( dev, HW_VAR_BASIC_RATE, (u8*)(&priv->basic_rate)); + } +} +#endif + + +#if 0 +extern void dm_rf_operation_test_callback(unsigned long dev) +{ + u8 erfpath; + + + for(erfpath=0; erfpath<4; erfpath++) + { + udelay(100); + } + + { + } + + { +#if 0 + for(i=0; i<50; i++) + { + PHY_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d); + PHY_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f); + PHY_SetRFReg(dev, RF90_PATH_C, 0x02, bMask12Bits, 0x4d); + PHY_SetRFReg(dev, RF90_PATH_C, 0x02, bMask12Bits, 0x4f); + +#if 0 + PHY_QueryRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits); + PHY_QueryRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits); + PHY_QueryRFReg(dev, RF90_PATH_A, 0x12, bMask12Bits); + PHY_QueryRFReg(dev, RF90_PATH_A, 0x12, bMask12Bits); + PHY_QueryRFReg(dev, RF90_PATH_A, 0x21, bMask12Bits); + PHY_QueryRFReg(dev, RF90_PATH_A, 0x21, bMask12Bits); +#endif + } +#endif + } + +} +#endif + +#if 0 +static void dm_check_rfctrl_gpio(struct net_device * dev) +{ +#ifdef RTL8192E + struct r8192_priv *priv = rtllib_priv(dev); +#endif + + +#ifdef RTL8190P + return; +#endif +#ifdef RTL8192U + return; +#endif +#ifdef RTL8192E + queue_delayed_work_rsl(priv->priv_wq,&priv->gpio_change_rf_wq,0); +#endif + +} + +#endif +static void dm_check_pbc_gpio(struct net_device *dev) +{ +#ifdef RTL8192U + struct r8192_priv *priv = rtllib_priv(dev); + u8 tmp1byte; + + + tmp1byte = read_nic_byte(dev,GPI); + if(tmp1byte == 0xff) + return; + + if (tmp1byte&BIT6 || tmp1byte&BIT0) + { + RT_TRACE(COMP_IO, "CheckPbcGPIO - PBC is pressed\n"); + priv->bpbc_pressed = true; + } +#endif + +} + +#ifdef RTL8192E + +extern void dm_CheckRfCtrlGPIO(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,gpio_change_rf_wq); + struct net_device *dev = priv->rtllib->dev; +#else + struct r8192_priv *priv = rtllib_priv((struct net_device *)data); + struct net_device *dev = priv->rtllib->dev; +#endif + u8 tmp1byte; + RT_RF_POWER_STATE eRfPowerStateToSet; + bool bActuallySet = false; + + char *argv[3]; + static char *RadioPowerPath = "/etc/realtek/RadioPower.sh"; + static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL}; + + bActuallySet=false; + + if((priv->up_first_time == 1) || (priv->being_init_adapter)) + { + return; + } + + if(priv->bfirst_after_down){ + priv->bfirst_after_down = 1; + return; + } + + + + { + tmp1byte = read_nic_byte(dev,GPI); + + eRfPowerStateToSet = (tmp1byte&BIT1) ? eRfOn : eRfOff; + + if( (priv->bHwRadioOff == true) && (eRfPowerStateToSet == eRfOn)) + { + RT_TRACE(COMP_RF, "gpiochangeRF - HW Radio ON\n"); + printk("gpiochangeRF - HW Radio ON\n"); + priv->bHwRadioOff = false; + bActuallySet = true; + } + else if ( (priv->bHwRadioOff == false) && (eRfPowerStateToSet == eRfOff)) + { + RT_TRACE(COMP_RF, "gpiochangeRF - HW Radio OFF\n"); + printk("gpiochangeRF - HW Radio OFF\n"); + priv->bHwRadioOff = true; + bActuallySet = true; + } + + if(bActuallySet) + { + mdelay(1000); + priv->bHwRfOffAction = 1; + MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW,true); + { + if(priv->bHwRadioOff == true) + argv[1] = "RFOFF"; + else + argv[1] = "RFON"; + + argv[0] = RadioPowerPath; + argv[2] = NULL; + call_usermodehelper(RadioPowerPath,argv,envp,1); + } + + } +#if 0 + else + { + msleep(2000); + } +#endif + + } + +} +#elif defined RTL8192SE +extern void Power_DomainInit92SE(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 tmpU1b; + u16 tmpU2b; + + + + priv->PwrDomainProtect = true; + + tmpU1b = read_nic_byte(dev, (SYS_CLKR + 1)); + if(tmpU1b & BIT7) + { + tmpU1b &= ~(BIT6 | BIT7); + if(!HalSetSysClk8192SE(dev, tmpU1b)){ + priv->PwrDomainProtect = false; + return; + } + } + + write_nic_byte(dev, AFE_PLL_CTRL, 0x0); + write_nic_byte(dev, LDOA15_CTRL, 0x34); + +#if 0 + tmpU2b = read_nic_word(dev, SYS_CLKR); + if (tmpU2b & BIT15) + { + tmpU2b &= ~(BIT14|BIT15); + RT_TRACE(COMP_INIT, DBG_LOUD, ("Return to HW CTRL\n")); + write_nic_word(dev, SYS_CLKR, tmpU2b); + } + udelay(200); +#endif + + tmpU1b = read_nic_byte(dev, SYS_FUNC_EN+1); + if (priv->rtllib->RfOffReason & (RF_CHANGE_BY_IPS | RF_CHANGE_BY_HW)) { + tmpU1b &= 0xFB; + } else { + tmpU1b &= 0x73; + } + + write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b); + udelay(1000); + + write_nic_byte(dev, CMDR, 0); + write_nic_byte(dev, TCR, 0); + + tmpU1b = read_nic_byte(dev, 0x562); + tmpU1b |= 0x08; + write_nic_byte(dev, 0x562, tmpU1b); + tmpU1b &= ~(BIT3); + write_nic_byte(dev, 0x562, tmpU1b); + + tmpU1b = read_nic_byte(dev, AFE_XTAL_CTRL); + write_nic_byte(dev, AFE_XTAL_CTRL, (tmpU1b|0x01)); + udelay(1500); + tmpU1b = read_nic_byte(dev, AFE_XTAL_CTRL+1); + write_nic_byte(dev, AFE_XTAL_CTRL+1, (tmpU1b&0xfb)); + + + tmpU1b = read_nic_byte(dev, AFE_MISC); + write_nic_byte(dev, AFE_MISC, (tmpU1b|BIT0)); + udelay(1000); + + tmpU1b = read_nic_byte(dev, AFE_MISC); + write_nic_byte(dev, AFE_MISC, (tmpU1b|0x02)); + udelay(1000); + + tmpU1b = read_nic_byte(dev, LDOA15_CTRL); + write_nic_byte(dev, LDOA15_CTRL, (tmpU1b|BIT0)); + + tmpU2b = read_nic_word(dev, SYS_ISO_CTRL); + write_nic_word(dev, SYS_ISO_CTRL, (tmpU2b|BIT11)); + + + tmpU2b = read_nic_word(dev, SYS_FUNC_EN); + write_nic_word(dev, SYS_FUNC_EN, (tmpU2b |BIT13)); + + write_nic_byte(dev, SYS_ISO_CTRL+1, 0x68); + + tmpU1b = read_nic_byte(dev, AFE_PLL_CTRL); + write_nic_byte(dev, AFE_PLL_CTRL, (tmpU1b|BIT0|BIT4)); + tmpU1b = read_nic_byte(dev, AFE_PLL_CTRL+1); + write_nic_byte(dev, AFE_PLL_CTRL+1, (tmpU1b|BIT0)); + udelay(1000); + + write_nic_byte(dev, SYS_ISO_CTRL, 0xA6); + + tmpU2b = read_nic_word(dev, SYS_CLKR); + write_nic_word(dev, SYS_CLKR, (tmpU2b|BIT12|BIT11)); + + tmpU2b = read_nic_word(dev, SYS_FUNC_EN); + write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|BIT11)); + write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|BIT11|BIT15)); + + tmpU2b = read_nic_word(dev, SYS_CLKR); + write_nic_word(dev, SYS_CLKR, (tmpU2b&(~BIT2))); + + tmpU1b = read_nic_byte(dev, (SYS_CLKR + 1)); + tmpU1b = ((tmpU1b | BIT7) & (~BIT6)); + if(!HalSetSysClk8192SE(dev, tmpU1b)) + { + priv->PwrDomainProtect = false; + return; + } +#if 0 + tmpU2b = read_nic_word(dev, SYS_CLKR); + write_nic_word(dev, SYS_CLKR, ((tmpU2b|BIT15)&(~BIT14))); +#endif + + write_nic_word(dev, CMDR, 0x37FC); + + gen_RefreshLedState(dev); + + priv->PwrDomainProtect = false; + +} + +void SET_RTL8192SE_RF_HALT(struct net_device *dev) +{ + u8 u1bTmp; + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->rtllib->RfOffReason == RF_CHANGE_BY_IPS && priv->LedStrategy == SW_LED_MODE8) + { + SET_RTL8192SE_RF_SLEEP(dev); + return; + } + + u1bTmp = read_nic_byte(dev, LDOV12D_CTRL); + u1bTmp |= BIT0; + write_nic_byte(dev, LDOV12D_CTRL, u1bTmp); + write_nic_byte(dev, SPS1_CTRL, 0x0); + write_nic_byte(dev, TXPAUSE, 0xFF); + write_nic_word(dev, CMDR, 0x57FC); + udelay(100); + write_nic_word(dev, CMDR, 0x77FC); + write_nic_byte(dev, PHY_CCA, 0x0); + udelay(10); + write_nic_word(dev, CMDR, 0x37FC); + udelay(10); + write_nic_word(dev, CMDR, 0x77FC); + udelay(10); + write_nic_word(dev, CMDR, 0x57FC); + write_nic_word(dev, CMDR, 0x0000); + u1bTmp = read_nic_byte(dev, (SYS_CLKR + 1)); + if(u1bTmp & BIT7) + { + u1bTmp &= ~(BIT6 | BIT7); + if(!HalSetSysClk8192SE(dev, u1bTmp)) + return; + } + if(priv->rtllib->RfOffReason==RF_CHANGE_BY_IPS ) + { + write_nic_byte(dev, 0x03, 0xF9); + } + else + { + write_nic_byte(dev, 0x03, 0x71); + } + write_nic_byte(dev, SYS_CLKR+1, 0x70); + write_nic_byte(dev, AFE_PLL_CTRL+1, 0x68); + write_nic_byte(dev, AFE_PLL_CTRL, 0x00); + write_nic_byte(dev, LDOA15_CTRL, 0x34); + write_nic_byte(dev, AFE_XTAL_CTRL, 0x0E); + +} + +u8 RfOnOffDetect(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 u1Tmp; + u8 retval=eRfOn; + + if(priv->pwrdown) + { + u1Tmp = read_nic_byte(dev, 0x06); + printk("pwrdown, 0x6(BIT6)=%02x\n", u1Tmp); + retval = (u1Tmp & BIT6) ? eRfOn: eRfOff; + } + else + { +#ifdef CONFIG_BT_COEXIST + if(pHalData->bt_coexist.BluetoothCoexist) + { + if(pHalData->bt_coexist.BT_CoexistType == BT_2Wire) + { + PlatformEFIOWrite1Byte(pAdapter, MAC_PINMUX_CFG, 0xa); + u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IO_SEL); + delay_us(100); + u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IN); + RTPRINT(FPWR, PWRHW, ("GPIO_IN=%02x\n", u1Tmp)); + retval = (u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? eRfOn : eRfOff; + } + else if( (pHalData->bt_coexist.BT_CoexistType == BT_ISSC_3Wire) || + (pHalData->bt_coexist.BT_CoexistType == BT_Accel) || + (pHalData->bt_coexist.BT_CoexistType == BT_CSR) ) + { + u4tmp = PHY_QueryBBReg(pAdapter, 0x87c, bMaskDWord); + if((u4tmp & BIT17) != 0) + { + PHY_SetBBReg(pAdapter, 0x87c, bMaskDWord, u4tmp & ~BIT17); + delay_us(50); + RTPRINT(FBT, BT_RFPoll, ("BT write 0x87c (~BIT17) = 0x%x\n", u4tmp &~BIT17)); + } + u4tmp = PHY_QueryBBReg(pAdapter, 0x8e0, bMaskDWord); + RTPRINT(FBT, BT_RFPoll, ("BT read 0x8e0 (BIT24)= 0x%x\n", u4tmp)); + retval = (u4tmp & BIT24) ? eRfOn : eRfOff; + RTPRINT(FBT, BT_RFPoll, ("BT check RF state to %s\n", (retval==eRfOn)? "ON":"OFF")); + } + } + else +#endif + { + write_nic_byte(dev, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); + u1Tmp = read_nic_byte(dev, GPIO_IO_SEL); + + u1Tmp &= HAL_8192S_HW_GPIO_OFF_MASK; + write_nic_byte(dev, GPIO_IO_SEL, u1Tmp); + + mdelay(10); + + u1Tmp = read_nic_byte(dev, GPIO_IN); + retval = (u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? eRfOn : eRfOff; + } + } + + return retval; +} + +extern void dm_CheckRfCtrlGPIO(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,gpio_change_rf_wq); + struct net_device *dev = priv->rtllib->dev; +#else + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = rtllib_priv(dev); +#endif + + RT_RF_POWER_STATE eRfPowerStateToSet, CurRfState; + bool bActuallySet = false; + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + unsigned long flag = 0; + bool turnonbypowerdomain = false; + + +#ifdef CONFIG_RTL_RFKILL + return; +#endif + if((priv->up_first_time == 1) || (priv->being_init_adapter)) + { + ; + return; + } + + if(priv->ResetProgress == RESET_TYPE_SILENT) + { + RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), "GPIOChangeRFWorkItemCallBack(): Silent Reseting!!!!!!!\n"); + return; + } + + + if (pPSC->bSwRfProcessing) + { + RT_TRACE(COMP_SCAN, "GPIOChangeRFWorkItemCallBack(): Rf is in switching state.\n"); + return; + } + + RT_TRACE(COMP_RF, "GPIOChangeRFWorkItemCallBack() ---------> \n"); + + spin_lock_irqsave(&priv->rf_ps_lock,flag); + if (priv->RFChangeInProgress) { + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + RT_TRACE(COMP_RF, "GPIOChangeRFWorkItemCallBack(): RF Change in progress! \n"); + return; + } else { + priv->RFChangeInProgress = true; + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + } + CurRfState = priv->rtllib->eRFPowerState; +#ifdef CONFIG_ASPM_OR_D3 + if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM)) + { + RT_DISABLE_ASPM(dev); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM); + } + else if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3)) + { +#ifdef TODO + RT_LEAVE_D3(dev, false); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3); +#endif + } + +#endif + if(RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) + { + Power_DomainInit92SE(dev); + turnonbypowerdomain = true; + } + + eRfPowerStateToSet = RfOnOffDetect(dev); + if (priv->bResetInProgress) { + spin_lock_irqsave(&priv->rf_ps_lock,flag); + priv->RFChangeInProgress = false; + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + return; + } + + if( (priv->bHwRadioOff == true) && \ + (((eRfPowerStateToSet == eRfOn)&&(priv->sw_radio_on == true)) +#ifdef CONFIG_RTLWIFI_DEBUGFS + ||priv->debug->hw_holding +#endif + )) + { + RT_TRACE(COMP_RF, "GPIOChangeRF - HW Radio ON, RF ON\n"); + printk("GPIOChangeRF - HW Radio ON, RF ON\n"); + eRfPowerStateToSet = eRfOn; + bActuallySet = true; + } else if ((priv->bHwRadioOff == false) && + ((eRfPowerStateToSet == eRfOff) || (priv->sw_radio_on == false))) + { + RT_TRACE(COMP_RF, "GPIOChangeRF - HW Radio OFF\n"); + printk("GPIOChangeRF - HW Radio OFF\n"); + eRfPowerStateToSet = eRfOff; + bActuallySet = true; + } + + if (bActuallySet) { + priv->bHwRfOffAction = 1; +#ifdef CONFIG_ASPM_OR_D3 + if(eRfPowerStateToSet == eRfOn) + { + if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM)) + { + RT_DISABLE_ASPM(dev); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM); + } +#ifdef TODO + else if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3)) + { + RT_LEAVE_D3(dev, false); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3); + } +#endif + } +#endif + spin_lock_irqsave(&priv->rf_ps_lock,flag); + priv->RFChangeInProgress = false; + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW,true); + + { +#ifdef CONFIG_CFG_80211 + struct wireless_dev *wdev = &priv->rtllib->wdev; + wiphy_rfkill_set_hw_state(wdev->wiphy, priv->bHwRadioOff); +#else + char *argv[3]; + static char *RadioPowerPath = "/etc/realtek/RadioPower.sh"; + static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL}; + + if(priv->bHwRadioOff == true) + argv[1] = "RFOFF"; + else + argv[1] = "RFON"; + + argv[0] = RadioPowerPath; + argv[2] = NULL; + call_usermodehelper(RadioPowerPath,argv,envp,1); + +#endif + } + + if(eRfPowerStateToSet == eRfOff) + { + if(priv->pwrdown){ + + write_nic_byte(dev, SYS_FUNC_EN+1, 0x31); + } +#ifdef CONFIG_ASPM_OR_D3 + if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) + { + RT_ENABLE_ASPM(dev); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM); + } +#ifdef TODO + else if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) + { + RT_ENTER_D3(dev, false); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3); + } +#endif +#endif + + gen_RefreshLedState(dev); + } + } + else if(eRfPowerStateToSet == eRfOff || CurRfState == eRfOff || priv->bDriverIsGoingToUnload) + { + + if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && turnonbypowerdomain) + { + PHY_SetRtl8192seRfHalt(dev); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); + } +#ifdef CONFIG_ASPM_OR_D3 + if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) + { + RT_ENABLE_ASPM(dev); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM); + } +#ifdef TODO + else if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) + { + RT_ENTER_D3(dev, false); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3); + } +#endif +#endif + spin_lock_irqsave(&priv->rf_ps_lock,flag); + priv->RFChangeInProgress = false; + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + } + else + { + spin_lock_irqsave(&priv->rf_ps_lock,flag); + priv->RFChangeInProgress = false; + spin_unlock_irqrestore(&priv->rf_ps_lock,flag); + } + RT_TRACE(COMP_RF, "GPIOChangeRFWorkItemCallBack() <--------- \n"); +} +#endif +void dm_rf_pathcheck_workitemcallback(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,rfpath_check_wq); + struct net_device *dev =priv->rtllib->dev; +#else + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = rtllib_priv(dev); +#endif + u8 rfpath = 0, i; + + + rfpath = read_nic_byte(dev, 0xc04); + + for (i = 0; i < RF90_PATH_MAX; i++) + { + if (rfpath & (0x01<brfpath_rxenable[i] = 1; + else + priv->brfpath_rxenable[i] = 0; + } + if(!DM_RxPathSelTable.Enable) + return; + + dm_rxpath_sel_byrssi(dev); +} + +static void dm_init_rxpath_selection(struct net_device * dev) +{ + u8 i; + struct r8192_priv *priv = rtllib_priv(dev); + DM_RxPathSelTable.Enable = 1; + DM_RxPathSelTable.SS_TH_low = RxPathSelection_SS_TH_low; + DM_RxPathSelTable.diff_TH = RxPathSelection_diff_TH; + if(priv->CustomerID == RT_CID_819x_Netcore) + DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; + else + DM_RxPathSelTable.cck_method = CCK_Rx_Version_1; + DM_RxPathSelTable.DbgMode = DM_DBG_OFF; + DM_RxPathSelTable.disabledRF = 0; + for(i=0; i<4; i++) + { + DM_RxPathSelTable.rf_rssi[i] = 50; + DM_RxPathSelTable.cck_pwdb_sta[i] = -64; + DM_RxPathSelTable.rf_enable_rssi_th[i] = 100; + } +} + +static void dm_rxpath_sel_byrssi(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 i, max_rssi_index=0, min_rssi_index=0, sec_rssi_index=0, rf_num=0; + u8 tmp_max_rssi=0, tmp_min_rssi=0, tmp_sec_rssi=0; + u8 cck_default_Rx=0x2; + u8 cck_optional_Rx=0x3; + long tmp_cck_max_pwdb=0, tmp_cck_min_pwdb=0, tmp_cck_sec_pwdb=0; + u8 cck_rx_ver2_max_index=0, cck_rx_ver2_min_index=0, cck_rx_ver2_sec_index=0; + u8 cur_rf_rssi; + long cur_cck_pwdb; + static u8 disabled_rf_cnt=0, cck_Rx_Path_initialized=0; + u8 update_cck_rx_path; + + if(priv->rf_type != RF_2T4R) + return; + + if(!cck_Rx_Path_initialized) + { + DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(dev, 0xa07)&0xf); + cck_Rx_Path_initialized = 1; + } + + DM_RxPathSelTable.disabledRF = 0xf; + DM_RxPathSelTable.disabledRF &=~ (read_nic_byte(dev, 0xc04)); + + if(priv->rtllib->mode == WIRELESS_MODE_B) + { + DM_RxPathSelTable.cck_method = CCK_Rx_Version_2; + } + + for (i=0; istats.rx_rssi_percentage[i]; + + if(priv->brfpath_rxenable[i]) + { + rf_num++; + cur_rf_rssi = DM_RxPathSelTable.rf_rssi[i]; + + if(rf_num == 1) + { + max_rssi_index = min_rssi_index = sec_rssi_index = i; + tmp_max_rssi = tmp_min_rssi = tmp_sec_rssi = cur_rf_rssi; + } + else if(rf_num == 2) + { + if(cur_rf_rssi >= tmp_max_rssi) + { + tmp_max_rssi = cur_rf_rssi; + max_rssi_index = i; + } + else + { + tmp_sec_rssi = tmp_min_rssi = cur_rf_rssi; + sec_rssi_index = min_rssi_index = i; + } + } + else + { + if(cur_rf_rssi > tmp_max_rssi) + { + tmp_sec_rssi = tmp_max_rssi; + sec_rssi_index = max_rssi_index; + tmp_max_rssi = cur_rf_rssi; + max_rssi_index = i; + } + else if(cur_rf_rssi == tmp_max_rssi) + { + tmp_sec_rssi = cur_rf_rssi; + sec_rssi_index = i; + } + else if((cur_rf_rssi < tmp_max_rssi) &&(cur_rf_rssi > tmp_sec_rssi)) + { + tmp_sec_rssi = cur_rf_rssi; + sec_rssi_index = i; + } + else if(cur_rf_rssi == tmp_sec_rssi) + { + if(tmp_sec_rssi == tmp_min_rssi) + { + tmp_sec_rssi = cur_rf_rssi; + sec_rssi_index = i; + } + else + { + } + } + else if((cur_rf_rssi < tmp_sec_rssi) && (cur_rf_rssi > tmp_min_rssi)) + { + } + else if(cur_rf_rssi == tmp_min_rssi) + { + if(tmp_sec_rssi == tmp_min_rssi) + { + tmp_min_rssi = cur_rf_rssi; + min_rssi_index = i; + } + else + { + } + } + else if(cur_rf_rssi < tmp_min_rssi) + { + tmp_min_rssi = cur_rf_rssi; + min_rssi_index = i; + } + } + } + } + + rf_num = 0; + if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) + { + for (i=0; ibrfpath_rxenable[i]) + { + rf_num++; + cur_cck_pwdb = DM_RxPathSelTable.cck_pwdb_sta[i]; + + if(rf_num == 1) + { + cck_rx_ver2_max_index = cck_rx_ver2_min_index = cck_rx_ver2_sec_index = i; + tmp_cck_max_pwdb = tmp_cck_min_pwdb = tmp_cck_sec_pwdb = cur_cck_pwdb; + } + else if(rf_num == 2) + { + if(cur_cck_pwdb >= tmp_cck_max_pwdb) + { + tmp_cck_max_pwdb = cur_cck_pwdb; + cck_rx_ver2_max_index = i; + } + else + { + tmp_cck_sec_pwdb = tmp_cck_min_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = cck_rx_ver2_min_index = i; + } + } + else + { + if(cur_cck_pwdb > tmp_cck_max_pwdb) + { + tmp_cck_sec_pwdb = tmp_cck_max_pwdb; + cck_rx_ver2_sec_index = cck_rx_ver2_max_index; + tmp_cck_max_pwdb = cur_cck_pwdb; + cck_rx_ver2_max_index = i; + } + else if(cur_cck_pwdb == tmp_cck_max_pwdb) + { + tmp_cck_sec_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = i; + } + else if((cur_cck_pwdb < tmp_cck_max_pwdb) &&(cur_cck_pwdb > tmp_cck_sec_pwdb)) + { + tmp_cck_sec_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = i; + } + else if(cur_cck_pwdb == tmp_cck_sec_pwdb) + { + if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb) + { + tmp_cck_sec_pwdb = cur_cck_pwdb; + cck_rx_ver2_sec_index = i; + } + else + { + } + } + else if((cur_cck_pwdb < tmp_cck_sec_pwdb) && (cur_cck_pwdb > tmp_cck_min_pwdb)) + { + } + else if(cur_cck_pwdb == tmp_cck_min_pwdb) + { + if(tmp_cck_sec_pwdb == tmp_cck_min_pwdb) + { + tmp_cck_min_pwdb = cur_cck_pwdb; + cck_rx_ver2_min_index = i; + } + else + { + } + } + else if(cur_cck_pwdb < tmp_cck_min_pwdb) + { + tmp_cck_min_pwdb = cur_cck_pwdb; + cck_rx_ver2_min_index = i; + } + } + + } + } + } + + + update_cck_rx_path = 0; + if(DM_RxPathSelTable.cck_method == CCK_Rx_Version_2) + { + cck_default_Rx = cck_rx_ver2_max_index; + cck_optional_Rx = cck_rx_ver2_sec_index; + if(tmp_cck_max_pwdb != -64) + update_cck_rx_path = 1; + } + + if(tmp_min_rssi < DM_RxPathSelTable.SS_TH_low && disabled_rf_cnt < 2) + { + if((tmp_max_rssi - tmp_min_rssi) >= DM_RxPathSelTable.diff_TH) + { + DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] = tmp_max_rssi+5; + rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<>i) & 0x1) + { + if(tmp_max_rssi >= DM_RxPathSelTable.rf_enable_rssi_th[i]) + { + rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x1<priv_wq,&priv->rfpath_check_wq,0); +} + + +static void dm_init_fsync (struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + priv->rtllib->fsync_time_interval = 500; + priv->rtllib->fsync_rate_bitmap = 0x0f000800; + priv->rtllib->fsync_rssi_threshold = 30; +#ifdef RTL8190P + priv->rtllib->bfsync_enable = true; +#elif defined RTL8192E || defined RTL8192SE + priv->rtllib->bfsync_enable = false; +#endif + priv->rtllib->fsync_multiple_timeinterval = 3; + priv->rtllib->fsync_firstdiff_ratethreshold= 100; + priv->rtllib->fsync_seconddiff_ratethreshold= 200; + priv->rtllib->fsync_state = Default_Fsync; + +#ifdef RTL8192SE + priv->framesyncMonitor = 0; +#elif defined RTL8192E || defined RTL8190P + priv->framesyncMonitor = 1; +#endif + + init_timer(&priv->fsync_timer); + setup_timer(&priv->fsync_timer, dm_fsync_timer_callback,(unsigned long) dev); +} + + +static void dm_deInit_fsync(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + del_timer_sync(&priv->fsync_timer); +} + +extern void dm_fsync_timer_callback(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = rtllib_priv((struct net_device *)data); + u32 rate_index, rate_count = 0, rate_count_diff=0; + bool bSwitchFromCountDiff = false; + bool bDoubleTimeInterval = false; + + if( priv->rtllib->state == RTLLIB_LINKED && + priv->rtllib->bfsync_enable && + (priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_CDD_FSYNC)) + { + u32 rate_bitmap; + for(rate_index = 0; rate_index <= 27; rate_index++) + { + rate_bitmap = 1 << rate_index; + if(priv->rtllib->fsync_rate_bitmap & rate_bitmap) + rate_count+= priv->stats.received_rate_histogram[1][rate_index]; + } + + if(rate_count < priv->rate_record) + rate_count_diff = 0xffffffff - rate_count + priv->rate_record; + else + rate_count_diff = rate_count - priv->rate_record; + if(rate_count_diff < priv->rateCountDiffRecord) + { + + u32 DiffNum = priv->rateCountDiffRecord - rate_count_diff; + if(DiffNum >= priv->rtllib->fsync_seconddiff_ratethreshold) + priv->ContiuneDiffCount++; + else + priv->ContiuneDiffCount = 0; + + if(priv->ContiuneDiffCount >=2) + { + bSwitchFromCountDiff = true; + priv->ContiuneDiffCount = 0; + } + } + else + { + priv->ContiuneDiffCount = 0; + } + + if(rate_count_diff <= priv->rtllib->fsync_firstdiff_ratethreshold) + { + bSwitchFromCountDiff = true; + priv->ContiuneDiffCount = 0; + } + priv->rate_record = rate_count; + priv->rateCountDiffRecord = rate_count_diff; + RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync); + if(priv->undecorated_smoothed_pwdb > priv->rtllib->fsync_rssi_threshold && bSwitchFromCountDiff) + { + bDoubleTimeInterval = true; + priv->bswitch_fsync = !priv->bswitch_fsync; + if(priv->bswitch_fsync) + { + #ifdef RTL8190P + write_nic_byte(dev,0xC36, 0x00); +#elif defined RTL8192E + write_nic_byte(dev,0xC36, 0x1c); + #endif + write_nic_byte(dev, 0xC3e, 0x90); + } + else + { + #ifdef RTL8190P + write_nic_byte(dev, 0xC36, 0x40); + #else + write_nic_byte(dev, 0xC36, 0x5c); + #endif + write_nic_byte(dev, 0xC3e, 0x96); + } + } + else if(priv->undecorated_smoothed_pwdb <= priv->rtllib->fsync_rssi_threshold) + { + if(priv->bswitch_fsync) + { + priv->bswitch_fsync = false; + #ifdef RTL8190P + write_nic_byte(dev, 0xC36, 0x40); +#elif defined RTL8192E + write_nic_byte(dev, 0xC36, 0x5c); + #endif + write_nic_byte(dev, 0xC3e, 0x96); + } + } + if(bDoubleTimeInterval){ + if(timer_pending(&priv->fsync_timer)) + del_timer_sync(&priv->fsync_timer); + priv->fsync_timer.expires = jiffies + MSECS(priv->rtllib->fsync_time_interval*priv->rtllib->fsync_multiple_timeinterval); + add_timer(&priv->fsync_timer); + } + else{ + if(timer_pending(&priv->fsync_timer)) + del_timer_sync(&priv->fsync_timer); + priv->fsync_timer.expires = jiffies + MSECS(priv->rtllib->fsync_time_interval); + add_timer(&priv->fsync_timer); + } + } + else + { + if(priv->bswitch_fsync) + { + priv->bswitch_fsync = false; + #ifdef RTL8190P + write_nic_byte(dev, 0xC36, 0x40); +#elif defined RTL8192E + write_nic_byte(dev, 0xC36, 0x5c); + #endif + write_nic_byte(dev, 0xC3e, 0x96); + } + priv->ContiuneDiffCount = 0; + #ifdef RTL8190P + write_nic_dword(dev, rOFDM0_RxDetector2, 0x164052cd); +#elif defined RTL8192E + write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd); + #endif + } + RT_TRACE(COMP_HALDM, "ContiuneDiffCount %d\n", priv->ContiuneDiffCount); + RT_TRACE(COMP_HALDM, "rateRecord %d rateCount %d, rateCountdiff %d bSwitchFsync %d\n", priv->rate_record, rate_count, rate_count_diff , priv->bswitch_fsync); +} + +static void dm_StartHWFsync(struct net_device *dev) +{ +#if defined RTL8192E + u8 rf_timing = 0x77; + struct r8192_priv *priv = rtllib_priv(dev); + RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__); + write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cf); + priv->rtllib->SetHwRegHandler(dev, HW_VAR_RF_TIMING, (u8*)(&rf_timing)); + write_nic_byte(dev, 0xc3b, 0x41); +#elif defined RTL8192SE + write_nic_byte(dev, rOFDM0_RxDetector3, 0x96); +#endif +} + +static void dm_EndHWFsync(struct net_device *dev) +{ +#if defined RTL8192E + u8 rf_timing = 0xaa; + struct r8192_priv *priv = rtllib_priv(dev); + RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__); + write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd); + priv->rtllib->SetHwRegHandler(dev, HW_VAR_RF_TIMING, (u8*)(&rf_timing)); + write_nic_byte(dev, 0xc3b, 0x49); +#elif defined RTL8192SE + write_nic_byte(dev, rOFDM0_RxDetector3, 0x94); +#endif + +} + +static void dm_EndSWFsync(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + RT_TRACE(COMP_HALDM, "%s\n", __FUNCTION__); + del_timer_sync(&(priv->fsync_timer)); + + if(priv->bswitch_fsync) + { + priv->bswitch_fsync = false; + + #ifdef RTL8190P + write_nic_byte(dev, 0xC36, 0x40); +#elif defined RTL8192E + write_nic_byte(dev, 0xC36, 0x5c); +#endif + + write_nic_byte(dev, 0xC3e, 0x96); + } + + priv->ContiuneDiffCount = 0; +#ifdef RTL8192E + write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd); +#endif + +} + +static void dm_StartSWFsync(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 rateIndex; + u32 rateBitmap; + + RT_TRACE(COMP_HALDM,"%s\n", __FUNCTION__); + priv->rate_record = 0; + priv->ContiuneDiffCount = 0; + priv->rateCountDiffRecord = 0; + priv->bswitch_fsync = false; + + if(priv->rtllib->mode == WIRELESS_MODE_N_24G) + { + priv->rtllib->fsync_firstdiff_ratethreshold= 600; + priv->rtllib->fsync_seconddiff_ratethreshold = 0xffff; + } + else + { + priv->rtllib->fsync_firstdiff_ratethreshold= 200; + priv->rtllib->fsync_seconddiff_ratethreshold = 200; + } + for(rateIndex = 0; rateIndex <= 27; rateIndex++) + { + rateBitmap = 1 << rateIndex; + if(priv->rtllib->fsync_rate_bitmap & rateBitmap) + priv->rate_record += priv->stats.received_rate_histogram[1][rateIndex]; + } + if(timer_pending(&priv->fsync_timer)) + del_timer_sync(&priv->fsync_timer); + priv->fsync_timer.expires = jiffies + MSECS(priv->rtllib->fsync_time_interval); + add_timer(&priv->fsync_timer); + +#ifdef RTL8192E + write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd); +#endif + +} + +void dm_check_fsync(struct net_device *dev) +{ +#define RegC38_Default 0 +#define RegC38_NonFsync_Other_AP 1 +#define RegC38_Fsync_AP_BCM 2 + struct r8192_priv *priv = rtllib_priv(dev); + static u8 reg_c38_State=RegC38_Default; + static u32 reset_cnt=0; + + RT_TRACE(COMP_HALDM, "RSSI %d TimeInterval %d MultipleTimeInterval %d\n", priv->rtllib->fsync_rssi_threshold, priv->rtllib->fsync_time_interval, priv->rtllib->fsync_multiple_timeinterval); + RT_TRACE(COMP_HALDM, "RateBitmap 0x%x FirstDiffRateThreshold %d SecondDiffRateThreshold %d\n", priv->rtllib->fsync_rate_bitmap, priv->rtllib->fsync_firstdiff_ratethreshold, priv->rtllib->fsync_seconddiff_ratethreshold); + + if( priv->rtllib->state == RTLLIB_LINKED && + priv->rtllib->pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) + { + if(priv->rtllib->bfsync_enable == 0) + { + switch(priv->rtllib->fsync_state) + { + case Default_Fsync: + dm_StartHWFsync(dev); + priv->rtllib->fsync_state = HW_Fsync; + break; + case SW_Fsync: + dm_EndSWFsync(dev); + dm_StartHWFsync(dev); + priv->rtllib->fsync_state = HW_Fsync; + break; + case HW_Fsync: + default: + break; + } + } + else + { + switch(priv->rtllib->fsync_state) + { + case Default_Fsync: + dm_StartSWFsync(dev); + priv->rtllib->fsync_state = SW_Fsync; + break; + case HW_Fsync: + dm_EndHWFsync(dev); + dm_StartSWFsync(dev); + priv->rtllib->fsync_state = SW_Fsync; + break; + case SW_Fsync: + default: + break; + + } + } + if(priv->framesyncMonitor) + { + if(reg_c38_State != RegC38_Fsync_AP_BCM) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector3, 0x15); + #else + write_nic_byte(dev, rOFDM0_RxDetector3, 0x95); + #endif + + reg_c38_State = RegC38_Fsync_AP_BCM; + } + } + } + else + { + switch(priv->rtllib->fsync_state) + { + case HW_Fsync: + dm_EndHWFsync(dev); + priv->rtllib->fsync_state = Default_Fsync; + break; + case SW_Fsync: + dm_EndSWFsync(dev); + priv->rtllib->fsync_state = Default_Fsync; + break; + case Default_Fsync: + default: + break; + } + + if(priv->framesyncMonitor) + { + if(priv->rtllib->state == RTLLIB_LINKED) + { + if(priv->undecorated_smoothed_pwdb <= RegC38_TH) + { + if(reg_c38_State != RegC38_NonFsync_Other_AP) + { + #ifdef RTL8190P + write_nic_byte(dev, rOFDM0_RxDetector3, 0x10); + #else + write_nic_byte(dev, rOFDM0_RxDetector3, 0x90); + #endif + + reg_c38_State = RegC38_NonFsync_Other_AP; + #if 0 + if (dev->HardwareType == HARDWARE_TYPE_RTL8190P) + DbgPrint("Fsync is idle, rssi<=35, write 0xc38 = 0x%x \n", 0x10); + else + DbgPrint("Fsync is idle, rssi<=35, write 0xc38 = 0x%x \n", 0x90); + #endif + } + } + else if(priv->undecorated_smoothed_pwdb >= (RegC38_TH+5)) + { + if(reg_c38_State) + { + write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); + reg_c38_State = RegC38_Default; + } + } + } + else + { + if(reg_c38_State) + { + write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); + reg_c38_State = RegC38_Default; + } + } + } + } + if(priv->framesyncMonitor) + { + if(priv->reset_count != reset_cnt) + { + write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); + reg_c38_State = RegC38_Default; + reset_cnt = priv->reset_count; + } + } + else + { + if(reg_c38_State) + { + write_nic_byte(dev, rOFDM0_RxDetector3, priv->framesync); + reg_c38_State = RegC38_Default; + } + } +} + +#if 0 +extern s1Byte DM_CheckLBusStatus(IN PADAPTER dev) +{ + PMGNT_INFO pMgntInfo=&dev->MgntInfo; + +#if (HAL_CODE_BASE & RTL819X) + +#if (HAL_CODE_BASE == RTL8192) + +#if( DEV_BUS_TYPE==PCI_INTERFACE) + return true; +#endif + +#if( DEV_BUS_TYPE==USB_INTERFACE) + return true; +#endif + +#endif + +#if (HAL_CODE_BASE == RTL8190) + return true; +#endif + +#endif +} + +#endif + +extern void dm_shadow_init(struct net_device *dev) +{ + u8 page; + u16 offset; + + for (page = 0; page < 5; page++) + for (offset = 0; offset < 256; offset++) + { + dm_shadow[page][offset] = read_nic_byte(dev, offset+page*256); + } + + for (page = 8; page < 11; page++) + for (offset = 0; offset < 256; offset++) + dm_shadow[page][offset] = read_nic_byte(dev, offset+page*256); + + for (page = 12; page < 15; page++) + for (offset = 0; offset < 256; offset++) + dm_shadow[page][offset] = read_nic_byte(dev, offset+page*256); + +} + +/*---------------------------Define function prototype------------------------*/ +static void dm_init_dynamic_txpower(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + +#ifdef RTL8192SE + if(((priv->pFirmware->FirmwareVersion) >= 60) && + (priv->DM_Type == DM_Type_ByDriver)){ + priv->rtllib->bdynamic_txpower_enable = true; + RT_TRACE(COMP_INIT, "Dynamic Tx Power is enabled by Driver \n"); + } else { + priv->rtllib->bdynamic_txpower_enable = false; + RT_TRACE(COMP_INIT, "Dynamic Tx Power is enabled by FW \n"); + } + + priv->LastDTPLvl = TxHighPwrLevel_Normal; + priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal; + +#elif defined RTL8190P || defined RTL8192E + priv->rtllib->bdynamic_txpower_enable = true; + priv->bLastDTPFlag_High = false; + priv->bLastDTPFlag_Low = false; + priv->bDynamicTxHighPower = false; + priv->bDynamicTxLowPower = false; +#endif +} + +#if defined RTL8190P || defined RTL8192E +static void dm_dynamic_txpower(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + unsigned int txhipower_threshhold=0; + unsigned int txlowpower_threshold=0; + if(priv->rtllib->bdynamic_txpower_enable != true) + { + priv->bDynamicTxHighPower = false; + priv->bDynamicTxLowPower = false; + return; + } + if((priv->rtllib->pHTInfo->IOTPeer == HT_IOT_PEER_ATHEROS) && (priv->rtllib->mode == IEEE_G)){ + txhipower_threshhold = TX_POWER_ATHEROAP_THRESH_HIGH; + txlowpower_threshold = TX_POWER_ATHEROAP_THRESH_LOW; + } + else + { + txhipower_threshhold = TX_POWER_NEAR_FIELD_THRESH_HIGH; + txlowpower_threshold = TX_POWER_NEAR_FIELD_THRESH_LOW; + } + + + RT_TRACE(COMP_TXAGC,"priv->undecorated_smoothed_pwdb = %ld \n" , priv->undecorated_smoothed_pwdb); + + if(priv->rtllib->state == RTLLIB_LINKED) + { + if(priv->undecorated_smoothed_pwdb >= txhipower_threshhold) + { + priv->bDynamicTxHighPower = true; + priv->bDynamicTxLowPower = false; + } + else + { + if(priv->undecorated_smoothed_pwdb < txlowpower_threshold && priv->bDynamicTxHighPower == true) + { + priv->bDynamicTxHighPower = false; + } + if(priv->undecorated_smoothed_pwdb < 35) + { + priv->bDynamicTxLowPower = true; + } + else if(priv->undecorated_smoothed_pwdb >= 40) + { + priv->bDynamicTxLowPower = false; + } + } + } + else + { + priv->bDynamicTxHighPower = false; + priv->bDynamicTxLowPower = false; + } + + if( (priv->bDynamicTxHighPower != priv->bLastDTPFlag_High ) || + (priv->bDynamicTxLowPower != priv->bLastDTPFlag_Low ) ) + { + RT_TRACE(COMP_TXAGC,"SetTxPowerLevel8190() channel = %d \n" , priv->rtllib->current_network.channel); + + rtl8192_phy_setTxPower(dev,priv->rtllib->current_network.channel); + } + priv->bLastDTPFlag_High = priv->bDynamicTxHighPower; + priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower; + +} +#elif defined RTL8192SE +static void dm_dynamic_txpower(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + long UndecoratedSmoothedPWDB; + + if( (priv->rtllib->bdynamic_txpower_enable != true) || + (priv->DMFlag & HAL_DM_HIPWR_DISABLE) || + priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_HIGH_POWER) { + priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal; + return; + } + + if((!priv->rtllib->state != RTLLIB_LINKED) && + (priv->EntryMinUndecoratedSmoothedPWDB == 0)) { + RT_TRACE(COMP_POWER, "Not connected to any \n"); + priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal; + return; + } + + if(priv->rtllib->state == RTLLIB_LINKED) { + if(priv->rtllib->OpMode == RT_OP_MODE_IBSS) { + UndecoratedSmoothedPWDB = priv->EntryMinUndecoratedSmoothedPWDB; + RT_TRACE(COMP_POWER, "AP Client PWDB = %ld \n", UndecoratedSmoothedPWDB); + } else { + UndecoratedSmoothedPWDB = priv->undecorated_smoothed_pwdb; + RT_TRACE(COMP_POWER, "STA Default Port PWDB = %ld \n", UndecoratedSmoothedPWDB); + } + } else { + UndecoratedSmoothedPWDB = priv->EntryMinUndecoratedSmoothedPWDB; + RT_TRACE(COMP_POWER, "AP Ext Port PWDB = %ld \n", UndecoratedSmoothedPWDB); + } + + if(UndecoratedSmoothedPWDB >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { + priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Level2; + RT_TRACE(COMP_POWER, "TxHighPwrLevel_Level2 (TxPwr=0x0)\n"); + } else if((UndecoratedSmoothedPWDB < (TX_POWER_NEAR_FIELD_THRESH_LVL2-3)) && + (UndecoratedSmoothedPWDB >= TX_POWER_NEAR_FIELD_THRESH_LVL1) ) { + priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Level1; + RT_TRACE(COMP_POWER, "TxHighPwrLevel_Level1 (TxPwr=0x10)\n"); + } else if(UndecoratedSmoothedPWDB < (TX_POWER_NEAR_FIELD_THRESH_LVL1-3)) { + priv->DynamicTxHighPowerLvl = TxHighPwrLevel_Normal; + RT_TRACE(COMP_POWER, "TxHighPwrLevel_Normal\n"); + } + + if( (priv->DynamicTxHighPowerLvl != priv->LastDTPLvl) ) { + RT_TRACE(COMP_POWER, "PHY_SetTxPowerLevel8192S() Channel = %d \n" , priv->rtllib->current_network.channel); + rtl8192_phy_setTxPower(dev, priv->rtllib->current_network.channel); + } + priv->LastDTPLvl = priv->DynamicTxHighPowerLvl; +} +#endif + +static void dm_check_txrateandretrycount(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + +#ifdef RTL8192SE + static u8 LegacyRateSet[12] = {0x02 , 0x04 , 0x0b , 0x16 , 0x0c , 0x12 , 0x18 , 0x24 , 0x30 , 0x48 , 0x60 , 0x6c}; + u8 RateIdx = 0; + RateIdx = read_nic_byte(dev, TX_RATE_REG); + + if(ieee->softmac_stats.CurrentShowTxate < 76) + ieee->softmac_stats.CurrentShowTxate = (RateIdx<12)?(LegacyRateSet[RateIdx]):((RateIdx-12)|0x80); + else + ieee->softmac_stats.CurrentShowTxate = 0; +#else + ieee->softmac_stats.CurrentShowTxate = read_nic_byte(dev, Current_Tx_Rate_Reg); +#endif + + ieee->softmac_stats.last_packet_rate = read_nic_byte(dev ,Initial_Tx_Rate_Reg); + + ieee->softmac_stats.txretrycount = read_nic_dword(dev, Tx_Retry_Count_Reg); +} + +static void dm_send_rssi_tofw(struct net_device *dev) +{ +#ifndef RTL8192SE + DCMD_TXCMD_T tx_cmd; + struct r8192_priv *priv = rtllib_priv(dev); + + write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb); + return; + tx_cmd.Op = TXCMD_SET_RX_RSSI; + tx_cmd.Length = 4; + tx_cmd.Value = priv->undecorated_smoothed_pwdb; + + cmpk_message_handle_tx(dev, (u8*)&tx_cmd, + DESC_PACKET_TYPE_INIT, sizeof(DCMD_TXCMD_T)); +#endif +} + +#if defined RTL8192SE + +/*----------------------------------------------------------------------------- + * Function: dm_RefreshRateAdaptiveMask() + * + * Overview: Update rate table mask according to rssi + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/27/2009 hpfan Create Version 0. + * + *---------------------------------------------------------------------------*/ +static void dm_RefreshRateAdaptiveMask(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + prate_adaptive pRA = (prate_adaptive)&priv->rate_adaptive; + u32 LowRSSIThreshForRA = 0,MiddleRSSIThreshForRA = 0, HighRSSIThreshForRA = 0; + u8 rssi_level; + + if(IS_NIC_DOWN(priv)){ + RT_TRACE(COMP_RATE,"<---- dm_RefreshRateAdaptiveMask(): driver is going to unload\n"); + return; + } + + if(!priv->rtllib->bUseRAMask){ + return; + } + + if(priv->pFirmware->FirmwareVersion >= 61 && !priv->bInformFWDriverControlDM){ + RT_TRACE(COMP_RATE, "<---- dm_RefreshRateAdaptiveMask(): inform fw driver control dm\n"); + priv->rtllib->SetFwCmdHandler(dev, FW_CMD_CTRL_DM_BY_DRIVER); + priv->bInformFWDriverControlDM = true; + } + + if((priv->rtllib->state == RTLLIB_LINKED && (priv->rtllib->iw_mode == IW_MODE_INFRA)) +#ifdef _RTL8192_EXT_PATCH_ + || ((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->rtllib->only_mesh == 0)) +#endif + ) + { + + switch (pRA->PreRATRState){ + case DM_RATR_STA_HIGH: + { + HighRSSIThreshForRA = 40; + MiddleRSSIThreshForRA = 30; + LowRSSIThreshForRA = 20; + } + break; + + + case DM_RATR_STA_MIDDLE: + { + HighRSSIThreshForRA = 44; + MiddleRSSIThreshForRA = 30; + LowRSSIThreshForRA = 20; + } + break; + + + case DM_RATR_STA_LOW: + { + HighRSSIThreshForRA = 44; + MiddleRSSIThreshForRA = 34; + LowRSSIThreshForRA = 20; + } + break; + + + case DM_RATR_STA_ULTRALOW: + { + HighRSSIThreshForRA = 44; + MiddleRSSIThreshForRA = 34; + LowRSSIThreshForRA = 24; + } + break; + + default: + { + HighRSSIThreshForRA = 44; + MiddleRSSIThreshForRA = 34; + LowRSSIThreshForRA = 24; + } + break; + } + + if(priv->undecorated_smoothed_pwdb > (long)HighRSSIThreshForRA) + { + pRA->ratr_state = DM_RATR_STA_HIGH; + rssi_level = 1; + } +#if 0 + else if(priv->undecorated_smoothed_pwdb > (long)MiddleRSSIThreshForRA) + { + pRA->ratr_state = DM_RATR_STA_MIDDLEHIGH; + rssi_level = 2; + } +#endif + else if(priv->undecorated_smoothed_pwdb > (long)MiddleRSSIThreshForRA) + { + pRA->ratr_state = DM_RATR_STA_LOW; + rssi_level = 3; + } +#if 0 + else if(priv->undecorated_smoothed_pwdb > (long)LowRSSIThreshForRA) + { + pRA->ratr_state = DM_RATR_STA_MIDDLELOW; + rssi_level = 4; + } +#endif + else if(priv->undecorated_smoothed_pwdb > (long)LowRSSIThreshForRA) + { + pRA->ratr_state = DM_RATR_STA_LOW; + rssi_level = 5; + } + else + { + pRA->ratr_state = DM_RATR_STA_ULTRALOW; + rssi_level = 6; + } + + if((pRA->PreRATRState != pRA->ratr_state) || ((pRA->PreRATRState == pRA->ratr_state) && (rssi_level != priv->rssi_level))) + { + RT_TRACE(COMP_RATE, "Target AP addr : "MAC_FMT"\n", MAC_ARG(priv->rtllib->current_network.bssid)); + RT_TRACE(COMP_RATE, "RSSI = %ld\n", priv->undecorated_smoothed_pwdb); + RT_TRACE(COMP_RATE, "RSSI_LEVEL = %d\n", rssi_level); + RT_TRACE(COMP_RATE, "PreState = %d, CurState = %d\n", pRA->PreRATRState, pRA->ratr_state); + priv->rtllib->UpdateHalRAMaskHandler( + dev, + false, + 0, + priv->rtllib->pHTInfo->PeerMimoPs, + priv->rtllib->mode, + priv->rtllib->pHTInfo->bCurTxBW40MHz, + rssi_level); + priv->rssi_level = rssi_level; + pRA->PreRATRState = pRA->ratr_state; + } + } + if((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_ADHOC)){ + int i; + struct sta_info *pEntry; + + for(i = 0; i < PEER_MAX_ASSOC; i++){ + pEntry = priv->rtllib->peer_assoc_list[i]; + if(NULL != pEntry){ + pRA = &pEntry->rate_adaptive; + switch (pRA->PreRATRState){ + case DM_RATR_STA_HIGH: + HighRSSIThreshForRA = 50; + LowRSSIThreshForRA = 20; + break; + case DM_RATR_STA_MIDDLE: + HighRSSIThreshForRA = 55; + LowRSSIThreshForRA = 20; + break; + case DM_RATR_STA_LOW: + HighRSSIThreshForRA = 50; + LowRSSIThreshForRA = 25; + break; + default: + HighRSSIThreshForRA = 50; + LowRSSIThreshForRA = 20; + break; + } + + if(pEntry->rssi_stat.UndecoratedSmoothedPWDB > HighRSSIThreshForRA){ + pRA->ratr_state = DM_RATR_STA_HIGH; + rssi_level = 1; + }else if(pEntry->rssi_stat.UndecoratedSmoothedPWDB > LowRSSIThreshForRA){ + pRA->ratr_state = DM_RATR_STA_MIDDLE; + rssi_level = 2; + }else{ + pRA->ratr_state = DM_RATR_STA_LOW; + rssi_level = 3; + } + + if(pRA->PreRATRState != pRA->ratr_state){ + RT_TRACE(COMP_RATE, "AsocEntry addr : "MAC_FMT"\n", MAC_ARG(pEntry->macaddr)); + RT_TRACE(COMP_RATE, "RSSI = %ld\n", pEntry->rssi_stat.UndecoratedSmoothedPWDB); + RT_TRACE(COMP_RATE, "RSSI_LEVEL = %d\n", rssi_level); + RT_TRACE(COMP_RATE, "PreState = %d, CurState = %d\n", pRA->PreRATRState, pRA->ratr_state); + priv->rtllib->UpdateHalRAMaskHandler( + dev, + false, + pEntry->aid+1, + pEntry->htinfo.MimoPs, + pEntry->wireless_mode, + pEntry->htinfo.bCurTxBW40MHz, + rssi_level); + pRA->PreRATRState = pRA->ratr_state; + } + + } + } + } +#ifdef _RTL8192_EXT_PATCH_ + if(priv->rtllib->iw_mode == IW_MODE_MESH) + { + if(priv->mshobj->ext_refresh_rate_adaptive_mask) + priv->mshobj->ext_refresh_rate_adaptive_mask(priv); + } +#endif +} + +void Adhoc_InitRateAdaptive(struct net_device *dev,struct sta_info *pEntry) +{ + prate_adaptive pRA = (prate_adaptive)&pEntry->rate_adaptive; + struct r8192_priv *priv = rtllib_priv(dev); + + pRA->ratr_state = DM_RATR_STA_MAX; + pRA->high2low_rssi_thresh_for_ra = RateAdaptiveTH_High; + pRA->low2high_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M+5; + pRA->low2high_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M+5; + + pRA->high_rssi_thresh_for_ra = RateAdaptiveTH_High+5; + pRA->low_rssi_thresh_for_ra20M = RateAdaptiveTH_Low_20M; + pRA->low_rssi_thresh_for_ra40M = RateAdaptiveTH_Low_40M; + + if (priv->rf_type == RF_2T4R) + { + /* 2008/01/11 MH Modify 2T RATR table for different RSSI. */ + pRA->upper_rssi_threshold_ratr = 0x8f0f0000; + pRA->middle_rssi_threshold_ratr = 0x8d0ff000; + pRA->low_rssi_threshold_ratr = 0x8f0ff003; + pRA->low_rssi_threshold_ratr_40M = 0x8f0ff007; + pRA->low_rssi_threshold_ratr_20M = 0x8f0ff003; + } + else if (priv->rf_type == RF_1T2R) + { + pRA->upper_rssi_threshold_ratr = 0x000f0000; + pRA->middle_rssi_threshold_ratr = 0x000ff000; + pRA->low_rssi_threshold_ratr = 0x000ff003; + pRA->low_rssi_threshold_ratr_40M = 0x000ff007; + pRA->low_rssi_threshold_ratr_20M = 0x000ff003; + } + +} + + +void Adhoc_InitRateAdaptiveState(struct net_device *dev,struct sta_info *pEntry) +{ + prate_adaptive pRA = (prate_adaptive)&pEntry->rate_adaptive; + + pRA->ratr_state = DM_RATR_STA_MAX; + pRA->PreRATRState = DM_RATR_STA_MAX; +} + +#if 0 +static void Adhoc_dm_CheckRateAdaptive(struct net_device * dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + prate_adaptive pRA; + u32 currentRATR, targetRATR = 0; + u32 LowRSSIThreshForRA = 0, HighRSSIThreshForRA = 0; + bool bShortGIEnabled = false; + u8 i = 0; + struct sta_info *pEntry = NULL; + + if(!priv->up) + { + RT_TRACE(COMP_RATE, "<---- AP_dm_CheckRateAdaptive(): driver is going to unload\n"); + return; + } + + for(i=0;ipeer_assoc_list[i]; + if(NULL != pEntry) + { + pRA = (prate_adaptive)&pEntry->rate_adaptive; + if(pRA->rate_adaptive_disabled) + continue; + if((pEntry->wireless_mode!=WIRELESS_MODE_N_24G) && (pEntry->wireless_mode != WIRELESS_MODE_N_5G)) + continue; + bShortGIEnabled = (pEntry->htinfo.bCurTxBW40MHz && priv->rtllib->pHTInfo->bCurShortGI40MHz && pEntry->htinfo.bCurShortGI40MHz) | + (!pEntry->htinfo.bCurTxBW40MHz && priv->rtllib->pHTInfo->bCurShortGI20MHz && pEntry->htinfo.bCurShortGI20MHz); + pRA->upper_rssi_threshold_ratr = + (pRA->upper_rssi_threshold_ratr & (~BIT31)) | ((bShortGIEnabled)? BIT31:0) ; + + pRA->middle_rssi_threshold_ratr = + (pRA->middle_rssi_threshold_ratr & (~BIT31)) | ((bShortGIEnabled)? BIT31:0) ; + + + if (pEntry->htinfo.bBw40MHz) + { + pRA->low_rssi_threshold_ratr = + (pRA->low_rssi_threshold_ratr_40M & (~BIT31)) | ((bShortGIEnabled)? BIT31:0) ; + } + else + { + pRA->low_rssi_threshold_ratr = + (pRA->low_rssi_threshold_ratr_20M & (~BIT31)) | ((bShortGIEnabled)? BIT31:0) ; + } + if (pRA->ratr_state == DM_RATR_STA_HIGH) + { + HighRSSIThreshForRA = pRA->high2low_rssi_thresh_for_ra; + LowRSSIThreshForRA = + (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + (pRA->low_rssi_thresh_for_ra40M):(pRA->low_rssi_thresh_for_ra20M); + } + else if (pRA->ratr_state == DM_RATR_STA_LOW) + { + HighRSSIThreshForRA = pRA->high_rssi_thresh_for_ra; + LowRSSIThreshForRA = + (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + (pRA->low2high_rssi_thresh_for_ra40M):(pRA->low2high_rssi_thresh_for_ra20M); + } + else + { + HighRSSIThreshForRA = pRA->high_rssi_thresh_for_ra; + LowRSSIThreshForRA = + (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)? + (pRA->low_rssi_thresh_for_ra40M):(pRA->low_rssi_thresh_for_ra20M); + } + if(priv->undecorated_smoothed_pwdb >= (int)HighRSSIThreshForRA) + { + pRA->ratr_state = DM_RATR_STA_HIGH; + targetRATR = pRA->upper_rssi_threshold_ratr; + } + else if(priv->undecorated_smoothed_pwdb >= (int)LowRSSIThreshForRA) + { + pRA->ratr_state = DM_RATR_STA_MIDDLE; + targetRATR = pRA->middle_rssi_threshold_ratr; + } + else + { + pRA->ratr_state = DM_RATR_STA_LOW; + targetRATR = pRA->low_rssi_threshold_ratr; + } + currentRATR = read_nic_dword(dev, pEntry->ratr_index*4 + RATR0); + if( targetRATR != currentRATR ) + { + if(priv->rf_type == RF_1T2R) + { + targetRATR &=~ (RATE_ALL_OFDM_2SS); + } + printk("<<<<<<<<<<ratr_index*4, targetRATR); + write_nic_byte(dev, UFWP, 1); + pRA->last_ratr = targetRATR; + } + } + } + +} +#endif + +#endif +/*---------------------------Define function prototype------------------------*/ + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_dm.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl_dm.h @@ -0,0 +1,348 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef __R8192UDM_H__ +#define __R8192UDM_H__ + + +/*--------------------------Define Parameters-------------------------------*/ +#define OFDM_Table_Length 19 +#define CCK_Table_length 12 + +#define DM_DIG_THRESH_HIGH 40 +#define DM_DIG_THRESH_LOW 35 + +#define DM_FALSEALARM_THRESH_LOW 40 +#define DM_FALSEALARM_THRESH_HIGH 1000 + +#define DM_DIG_HIGH_PWR_THRESH_HIGH 75 +#define DM_DIG_HIGH_PWR_THRESH_LOW 70 + +#define BW_AUTO_SWITCH_HIGH_LOW 25 +#define BW_AUTO_SWITCH_LOW_HIGH 30 + +#define DM_check_fsync_time_interval 500 + + +#define DM_DIG_BACKOFF 12 +#ifdef RTL8192SE +#define DM_DIG_MAX 0x3e +#elif defined RTL8190P || defined RTL8192E +#define DM_DIG_MAX 0x36 +#endif +#define DM_DIG_MIN 0x1c +#define DM_DIG_MIN_Netcore 0x12 + +#define DM_DIG_BACKOFF_MAX 12 +#define DM_DIG_BACKOFF_MIN -4 + +#define RxPathSelection_SS_TH_low 30 +#define RxPathSelection_diff_TH 18 + +#define RateAdaptiveTH_High 50 +#define RateAdaptiveTH_Low_20M 30 +#define RateAdaptiveTH_Low_40M 10 +#define VeryLowRSSI 15 + +#ifdef RTL8192SE +#define CTSToSelfTHVal 30 +#elif defined RTL8190P || defined RTL8192E +#define CTSToSelfTHVal 35 +#endif + +#define WAIotTHVal 25 + +#define E_FOR_TX_POWER_TRACK 300 +#define TX_POWER_NEAR_FIELD_THRESH_HIGH 68 +#define TX_POWER_NEAR_FIELD_THRESH_LOW 62 +#define TX_POWER_ATHEROAP_THRESH_HIGH 78 +#define TX_POWER_ATHEROAP_THRESH_LOW 72 + +#define Current_Tx_Rate_Reg 0x1e0 +#define Initial_Tx_Rate_Reg 0x1e1 +#define Tx_Retry_Count_Reg 0x1ac +#define RegC38_TH 20 + +#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 +#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 + +#define TxHighPwrLevel_Normal 0 +#define TxHighPwrLevel_Level1 1 +#define TxHighPwrLevel_Level2 2 + +#define DM_Type_ByFW 0 +#define DM_Type_ByDriver 1 + +/*--------------------------Define Parameters-------------------------------*/ + + +/*------------------------------Define structure----------------------------*/ +typedef struct _dynamic_initial_gain_threshold_ +{ + u8 dig_enable_flag; + u8 dig_algorithm; + u8 Dig_TwoPort_Algorithm; + u8 Dig_Ext_Port_Stage; + u8 dbg_mode; + u8 dig_algorithm_switch; + + long rssi_low_thresh; + long rssi_high_thresh; + + u32 FALowThresh; + u32 FAHighThresh; + + long rssi_high_power_lowthresh; + long rssi_high_power_highthresh; + + u8 dig_state; + u8 dig_highpwr_state; + u8 CurSTAConnectState; + u8 PreSTAConnectState; + u8 CurAPConnectState; + u8 PreAPConnectState; + + u8 curpd_thstate; + u8 prepd_thstate; + u8 curcs_ratio_state; + u8 precs_ratio_state; + + u32 pre_ig_value; + u32 cur_ig_value; + + u8 Backoff_Enable_Flag; + u8 backoff_val; + char BackoffVal_range_max; + char BackoffVal_range_min; + u8 rx_gain_range_max; + u8 rx_gain_range_min; + bool initialgain_lowerbound_state; + + long rssi_val; +}dig_t; + +typedef enum tag_dynamic_init_gain_state_definition +{ + DM_STA_DIG_OFF = 0, + DM_STA_DIG_ON, + DM_STA_DIG_MAX +}dm_dig_sta_e; + +#ifndef RTL8192SE +typedef enum tag_dynamic_ratr_state_definition +{ + DM_RATR_STA_HIGH = 0, + DM_RATR_STA_MIDDLE = 1, + DM_RATR_STA_LOW = 2, + + DM_RATR_STA_MAX +}dm_ratr_sta_e; +#else +typedef enum tag_dynamic_ratr_state_definition +{ + DM_RATR_STA_HIGH = 0, + DM_RATR_STA_MIDDLEHIGH = 1, + DM_RATR_STA_MIDDLE = 2, + DM_RATR_STA_MIDDLELOW = 3, + DM_RATR_STA_LOW = 4, + DM_RATR_STA_ULTRALOW = 5, + DM_RATR_STA_MAX +}dm_ratr_sta_e; +#endif + +typedef enum tag_dynamic_init_gain_operation_type_definition +{ + DIG_TYPE_THRESH_HIGH = 0, + DIG_TYPE_THRESH_LOW = 1, + DIG_TYPE_THRESH_HIGHPWR_HIGH = 2, + DIG_TYPE_THRESH_HIGHPWR_LOW = 3, + DIG_TYPE_DBG_MODE = 4, + DIG_TYPE_RSSI = 5, + DIG_TYPE_ALGORITHM = 6, + DIG_TYPE_BACKOFF = 7, + DIG_TYPE_PWDB_FACTOR = 8, + DIG_TYPE_RX_GAIN_MIN = 9, + DIG_TYPE_RX_GAIN_MAX = 10, + DIG_TYPE_ENABLE = 20, + DIG_TYPE_DISABLE = 30, + DIG_OP_TYPE_MAX +}dm_dig_op_e; + +typedef enum tag_dig_algorithm_definition +{ + DIG_ALGO_BY_FALSE_ALARM = 0, + DIG_ALGO_BY_RSSI = 1, + DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM = 2, + DIG_ALGO_BY_TOW_PORT = 3, + DIG_ALGO_MAX +}dm_dig_alg_e; + +typedef enum tag_DIG_TWO_PORT_ALGO_Definition +{ + DIG_TWO_PORT_ALGO_RSSI = 0, + DIG_TWO_PORT_ALGO_FALSE_ALARM = 1, +}DM_DIG_TWO_PORT_ALG_E; + + +typedef enum tag_DIG_EXT_PORT_ALGO_Definition +{ + DIG_EXT_PORT_STAGE_0 = 0, + DIG_EXT_PORT_STAGE_1 = 1, + DIG_EXT_PORT_STAGE_2 = 2, + DIG_EXT_PORT_STAGE_3 = 3, + DIG_EXT_PORT_STAGE_MAX = 4, +}DM_DIG_EXT_PORT_ALG_E; + +typedef enum tag_dig_dbgmode_definition +{ + DIG_DBG_OFF = 0, + DIG_DBG_ON = 1, + DIG_DBG_MAX +}dm_dig_dbg_e; + +typedef enum tag_dig_connect_definition +{ + DIG_STA_DISCONNECT = 0, + DIG_STA_CONNECT = 1, + DIG_STA_BEFORE_CONNECT = 2, + DIG_AP_DISCONNECT = 3, + DIG_AP_CONNECT = 4, + DIG_AP_ADD_STATION = 5, + DIG_CONNECT_MAX +}dm_dig_connect_e; + +typedef enum tag_dig_packetdetection_threshold_definition +{ + DIG_PD_AT_LOW_POWER = 0, + DIG_PD_AT_NORMAL_POWER = 1, + DIG_PD_AT_HIGH_POWER = 2, + DIG_PD_MAX +}dm_dig_pd_th_e; + +typedef enum tag_dig_cck_cs_ratio_state_definition +{ + DIG_CS_RATIO_LOWER = 0, + DIG_CS_RATIO_HIGHER = 1, + DIG_CS_MAX +}dm_dig_cs_ratio_e; +typedef struct _Dynamic_Rx_Path_Selection_ +{ + u8 Enable; + u8 DbgMode; + u8 cck_method; + u8 cck_Rx_path; + + u8 SS_TH_low; + u8 diff_TH; + u8 disabledRF; + u8 reserved; + + u8 rf_rssi[4]; + u8 rf_enable_rssi_th[4]; + long cck_pwdb_sta[4]; +}DRxPathSel; + +typedef enum tag_CCK_Rx_Path_Method_Definition +{ + CCK_Rx_Version_1 = 0, + CCK_Rx_Version_2= 1, + CCK_Rx_Version_MAX +}DM_CCK_Rx_Path_Method; + + +typedef enum tag_DM_DbgMode_Definition +{ + DM_DBG_OFF = 0, + DM_DBG_ON = 1, + DM_DBG_MAX +}DM_DBG_E; + +typedef struct tag_Tx_Config_Cmd_Format +{ + u32 Op; + u32 Length; + u32 Value; +}DCMD_TXCMD_T, *PDCMD_TXCMD_T; +/*------------------------------Define structure----------------------------*/ + + +/*------------------------Export global variable----------------------------*/ +extern dig_t dm_digtable; +extern u8 dm_shadow[16][256]; +extern DRxPathSel DM_RxPathSelTable; + +extern u8 test_flag; +/*------------------------Export global variable----------------------------*/ + + +/*------------------------Export Marco Definition---------------------------*/ +#define DM_APInitGainChangeNotify(Event) {dm_digtable.CurAPConnectState = Event;} +/*------------------------Export Marco Definition---------------------------*/ + + +/*--------------------------Exported Function prototype---------------------*/ +/*--------------------------Exported Function prototype---------------------*/ +extern void init_hal_dm(struct net_device *dev); +extern void deinit_hal_dm(struct net_device *dev); + +extern void hal_dm_watchdog(struct net_device *dev); + + +extern void init_rate_adaptive(struct net_device *dev); +extern void dm_txpower_trackingcallback(void *data); + +#ifndef RTL8192SE +extern void dm_cck_txpower_adjust(struct net_device *dev,bool binch14); +#endif + +extern void dm_restore_dynamic_mechanism_state(struct net_device *dev); +extern void dm_backup_dynamic_mechanism_state(struct net_device *dev); +extern void dm_change_dynamic_initgain_thresh(struct net_device *dev, + u32 dm_type, + u32 dm_value); +extern void DM_ChangeFsyncSetting(struct net_device *dev, + s32 DM_Type, + s32 DM_Value); +extern void dm_force_tx_fw_info(struct net_device *dev, + u32 force_type, + u32 force_value); +extern void dm_init_edca_turbo(struct net_device *dev); +extern void dm_rf_operation_test_callback(unsigned long data); +extern void dm_rf_pathcheck_workitemcallback(void *data); +extern void dm_fsync_timer_callback(unsigned long data); +#if 0 +extern bool dm_check_lbus_status(struct net_device *dev); +#endif +extern void dm_check_fsync(struct net_device *dev); +extern void dm_shadow_init(struct net_device *dev); +extern void dm_initialize_txpower_tracking(struct net_device *dev); + +#if (defined RTL8192E || defined RTL8192SE) +extern void dm_CheckRfCtrlGPIO(void *data); +#endif + +#ifdef RTL8192SE +extern void Power_DomainInit92SE(struct net_device *dev); +#endif + +extern void dm_InitRateAdaptiveMask(struct net_device * dev); + +#endif /*__R8192UDM_H__ */ + + +/* End of r8192U_dm.h */ --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_eeprom.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_eeprom.c @@ -0,0 +1,140 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#include "rtl_core.h" +#include "rtl_eeprom.h" + +void eprom_cs(struct net_device *dev, short bit) +{ + if(bit) + write_nic_byte(dev, EPROM_CMD, + (1<epromtype==EEPROM_93C56){ + addr_str[7]=addr & 1; + addr_str[6]=addr & (1<<1); + addr_str[5]=addr & (1<<2); + addr_str[4]=addr & (1<<3); + addr_str[3]=addr & (1<<4); + addr_str[2]=addr & (1<<5); + addr_str[1]=addr & (1<<6); + addr_str[0]=addr & (1<<7); + addr_len=8; + }else{ + addr_str[5]=addr & 1; + addr_str[4]=addr & (1<<1); + addr_str[3]=addr & (1<<2); + addr_str[2]=addr & (1<<3); + addr_str[1]=addr & (1<<4); + addr_str[0]=addr & (1<<5); + addr_len=6; + } + eprom_cs(dev, 1); + eprom_ck_cycle(dev); + eprom_send_bits_string(dev, read_cmd, 3); + eprom_send_bits_string(dev, addr_str, addr_len); + + eprom_w(dev, 0); + + for(i=0;i<16;i++){ + eprom_ck_cycle(dev); + ret |= (eprom_r(dev)<<(15-i)); + } + + eprom_cs(dev, 0); + eprom_ck_cycle(dev); + + write_nic_byte(dev, EPROM_CMD, + (EPROM_CMD_NORMAL<, et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + + +#define EPROM_DELAY 10 +#if 0 +#define EPROM_ANAPARAM_ADDRLWORD 0xd +#define EPROM_ANAPARAM_ADDRHWORD 0xe + +#define EPROM_RFCHIPID 0x6 +#define EPROM_TXPW_BASE 0x05 +#define EPROM_RFCHIPID_RTL8225U 5 +#define EPROM_RF_PARAM 0x4 +#define EPROM_CONFIG2 0xc + +#define EPROM_VERSION 0x1E +#define MAC_ADR 0x7 + +#define CIS 0x18 + +#define EPROM_TXPW0 0x16 +#define EPROM_TXPW2 0x1b +#define EPROM_TXPW1 0x3d +#endif + +u32 eprom_read(struct net_device *dev,u32 addr); --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_ethtool.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_ethtool.c @@ -0,0 +1,59 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + ***************************************************************************** + */ +#include +#include +#include + +#include "rtl_core.h" + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) +static void rtl819x_ethtool_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); +#if defined RTL8192SE + snprintf(info->fw_version, sizeof(info->fw_version), "%d", + priv->pFirmware->FirmwareVersion); +#endif + strcpy(info->bus_info, pci_name(priv->pdev)); +} + +static u32 rtl819x_ethtool_get_link(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + return ((priv->rtllib->state == RTLLIB_LINKED) || + (priv->rtllib->state == RTLLIB_LINKED_SCANNING)); +} + +const struct ethtool_ops rtl819x_ethtool_ops = { + .get_drvinfo = rtl819x_ethtool_get_drvinfo, + .get_link = rtl819x_ethtool_get_link, +}; +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_mesh.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_mesh.c @@ -0,0 +1,375 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifdef _RTL8192_EXT_PATCH_ + +#include +#include + +#include "rtl_wx.h" +#include "rtl_core.h" +#include "../../mshclass/msh_class.h" + +int meshdev_up(struct net_device *meshdev,bool is_silent_reset) +{ + struct meshdev_priv * mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(mpriv->priv->rtllib->PowerSaveControl)); + bool init_status; + struct net_device *dev = ieee->dev; + RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__); + + mpriv->priv->up_first_time = 0; + mpriv->rtllib->iw_mode = IW_MODE_MESH; + if(mpriv->priv->mesh_up){ + RT_TRACE(COMP_INIT,"%s():mesh is up,return\n",__FUNCTION__); + return -1; + } +#ifdef RTL8192SE + mpriv->priv->ReceiveConfig = + RCR_APPFCS | RCR_APWRMGT | /*RCR_ADD3 |*/ + RCR_AMF | RCR_ADF | RCR_APP_MIC | RCR_APP_ICV | + RCR_AICV | RCR_ACRC32 | + RCR_AB | RCR_AM | + RCR_APM | + /*RCR_AAP |*/ + RCR_APP_PHYST_STAFF | RCR_APP_PHYST_RXFF | + (mpriv->priv->EarlyRxThreshold<priv->ReceiveConfig = (\ + RCR_APPFCS + | RCR_AMF | RCR_ADF| RCR_APP_MIC| RCR_APP_ICV + | RCR_AICV | RCR_ACRC32 + | RCR_AB | RCR_AM + | RCR_APM + | RCR_APP_PHYST_RXFF + | RCR_HTC_LOC_CTRL + ); +#else + mpriv->priv->ReceiveConfig = RCR_ADD3 | + RCR_AMF | RCR_ADF | + RCR_AICV | + RCR_AB | RCR_AM | RCR_APM | + RCR_AAP | ((u32)7<priv->up) { + RT_TRACE(COMP_INIT, "Bringing up iface"); + mpriv->priv->bfirst_init = true; + init_status = mpriv->priv->ops->initialize_adapter(dev); + if(init_status != true) { + RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__); + return -1; + } + RT_TRACE(COMP_INIT, "start adapter finished\n"); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); + printk("==>%s():priv->up is 0\n",__FUNCTION__); + mpriv->rtllib->ieee_up=1; + mpriv->priv->bfirst_init = false; +#ifdef ENABLE_GPIO_RADIO_CTL + if(mpriv->priv->polling_timer_on == 0){ + check_rfctrl_gpio_timer((unsigned long)dev); + } +#endif + if(!is_silent_reset){ + mpriv->rtllib->current_network.channel = INIT_DEFAULT_CHAN; + mpriv->rtllib->current_mesh_network.channel = INIT_DEFAULT_CHAN; + if(mpriv->priv->mshobj->ext_patch_r819x_wx_set_mesh_chan) + mpriv->priv->mshobj->ext_patch_r819x_wx_set_mesh_chan(dev,INIT_DEFAULT_CHAN); + if(mpriv->priv->mshobj->ext_patch_r819x_wx_set_channel) + { + mpriv->priv->mshobj->ext_patch_r819x_wx_set_channel(mpriv->rtllib, INIT_DEFAULT_CHAN); + } + printk("%s():set chan %d\n",__FUNCTION__,INIT_DEFAULT_CHAN); + mpriv->rtllib->set_chan(dev, INIT_DEFAULT_CHAN); + } + dm_InitRateAdaptiveMask(dev); + watch_dog_timer_callback((unsigned long) dev); + + } else { + rtllib_stop_scan(ieee); + msleep(1000); + } + if(!ieee->mesh_started) { +#ifdef RTL8192E + if(ieee->eRFPowerState!=eRfOn) + MgntActSet_RF_State(dev, eRfOn, ieee->RfOffReason,true); +#endif + if(mpriv->priv->mshobj && mpriv->priv->mshobj->ext_patch_rtl819x_up ) + mpriv->priv->mshobj->ext_patch_rtl819x_up(mpriv->priv->mshobj); + + + if(!netif_queue_stopped(meshdev)) + netif_start_queue(meshdev); + else + netif_wake_queue(meshdev); + + rtllib_reset_queue(ieee); + } + + mpriv->priv->mesh_up = 1; + + RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__); + return 0; +} + +int meshdev_down(struct net_device *meshdev) +{ + struct meshdev_priv * mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct r8192_priv *priv = (void*)ieee->priv; + struct net_device *dev = ieee->dev; + unsigned long flags = 0; + u8 RFInProgressTimeOut = 0; + if(priv->mesh_up == 0) { + RT_TRACE(COMP_ERR,"%s():ERR!!! mesh is already down\n",__FUNCTION__) + return -1; + } + + RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__); + + if (netif_running(meshdev)) { + netif_stop_queue(meshdev); + } + + if(!priv->up) + { + priv->bDriverIsGoingToUnload = true; + ieee->ieee_up = 0; + rtl8192_irq_disable(dev); + rtl8192_cancel_deferred_work(priv); +#ifndef RTL8190P + cancel_delayed_work(&priv->rtllib->hw_wakeup_wq); +#endif + deinit_hal_dm(dev); + del_timer_sync(&priv->watch_dog_timer); + rtllib_softmac_stop_protocol(ieee, 1, true); + + SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock); + while(priv->RFChangeInProgress) + { + SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock); + if(RFInProgressTimeOut > 100) + { + SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock); + break; + } + printk("===>%s():RF is in progress, need to wait until rf chang is done.\n",__FUNCTION__); + mdelay(1); + RFInProgressTimeOut ++; + SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock); + } + priv->RFChangeInProgress = true; + SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock); + priv->ops->stop_adapter(dev, false); + SPIN_LOCK_PRIV_RFPS(&priv->rf_ps_lock); + priv->RFChangeInProgress = false; + SPIN_UNLOCK_PRIV_RFPS(&priv->rf_ps_lock); + udelay(100); + memset(&priv->rtllib->current_network, 0 , offsetof(struct rtllib_network, list)); + priv->rtllib->current_network.channel = INIT_DEFAULT_CHAN; +#ifdef CONFIG_ASPM_OR_D3 + RT_ENABLE_ASPM(dev); +#endif + memset(&ieee->current_mesh_network, 0 , offsetof(struct rtllib_network, list)); + priv->rtllib->current_mesh_network.channel = INIT_DEFAULT_CHAN; + ieee->mesh_state = RTLLIB_NOLINK; + } else { + rtllib_softmac_stop_protocol(ieee, 1, true); + memset(&ieee->current_mesh_network, 0 , offsetof(struct rtllib_network, list)); + if((ieee->current_network.channel > 0) && (ieee->current_network.channel < 15)) + priv->rtllib->current_mesh_network.channel = ieee->current_network.channel; + else + priv->rtllib->current_mesh_network.channel = INIT_DEFAULT_CHAN; + + ieee->mesh_state = RTLLIB_NOLINK; + ieee->iw_mode = IW_MODE_INFRA; + } + priv->mesh_up = 0; + RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__); + + return 0; +} + +static int meshdev_open(struct net_device *meshdev) +{ + struct meshdev_priv * mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct r8192_priv *priv = (void*)ieee->priv; + int ret; + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + ret = meshdev_up(meshdev,false); + SEM_UP_PRIV_WX(&priv->wx_sem); + + return ret; +} + +static int meshdev_close(struct net_device *meshdev) +{ + struct meshdev_priv * mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct r8192_priv *priv = (void *)ieee->priv; + int ret; + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + ret = meshdev_down(meshdev); + SEM_UP_PRIV_WX(&priv->wx_sem); + + return ret; +} + +extern int meshdev_wx_mesh(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +static int meshdev_ioctl(struct net_device *meshdev, struct ifreq *rq, int cmd) +{ + struct iwreq *wrq = (struct iwreq *)rq; + int ret = -1; + if(cmd == 0x8BEE) + { + ret = meshdev_wx_mesh(meshdev, NULL, &(wrq->u), wrq->u.data.pointer); + } + return ret; +} + +struct net_device_stats *meshdev_stats(struct net_device *meshdev) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + return &((struct meshdev_priv*)netdev_priv(meshdev))->stats; +#else + return &((struct meshdev_priv*)meshdev->priv)->stats; +#endif +} + +static int meshdev_tx(struct sk_buff *skb, struct net_device *meshdev) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device * ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + memset(skb->cb,0,sizeof(skb->cb)); + + return rtllib_mesh_xmit(skb, dev); +} + +static void meshdev_tx_timeout(struct net_device *meshdev) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device * ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + rtl8192_tx_timeout(dev); +} + +#ifdef HAVE_NET_DEVICE_OPS +static const struct net_device_ops mesh_netdev_ops = { + .ndo_open = meshdev_open, + .ndo_stop = meshdev_close, + .ndo_get_stats = meshdev_stats, + .ndo_tx_timeout = meshdev_tx_timeout, + .ndo_do_ioctl = meshdev_ioctl, + .ndo_start_xmit = meshdev_tx, +}; +#endif + +void meshdev_init(struct net_device* meshdev) +{ + struct meshdev_priv *mpriv; + ether_setup(meshdev); + +#ifdef HAVE_NET_DEVICE_OPS + meshdev->netdev_ops = &mesh_netdev_ops; +#else + meshdev->open = meshdev_open; + meshdev->stop = meshdev_close; + meshdev->tx_timeout = meshdev_tx_timeout; + meshdev->do_ioctl = meshdev_ioctl; + meshdev->get_stats = meshdev_stats; + meshdev->hard_start_xmit = meshdev_tx; +#endif + meshdev->wireless_handlers = &meshdev_wx_handlers_def; + meshdev->destructor = free_netdev; + meshdev->watchdog_timeo = HZ*3; + meshdev->type = ARPHRD_ETHER; + memset(meshdev->broadcast,0xFF, ETH_ALEN); + + meshdev->watchdog_timeo = 3 * HZ; + + mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + memset(mpriv, 0, sizeof(struct meshdev_priv)); + + return; +} + +int meshdev_update_ext_chnl_offset_as_client(void *data) +{ + struct rtllib_device *ieee = container_of_work_rsl(data, struct rtllib_device, + ext_update_extchnloffset_wq); + struct r8192_priv *priv = (void *)ieee->priv; + struct net_device *dev = ieee->dev; + struct mshclass *mshobj= priv->mshobj; + u8 updateBW = 0; + u8 bserverHT = 0; + + updateBW=mshobj->ext_patch_r819x_wx_update_beacon(dev,&bserverHT); + printk("%s(): Cur_network.chan=%d, cur_mesh_net.chan=%d, updateBW=%d, bserverHT=%d\n", + __FUNCTION__,ieee->current_network.channel,ieee->current_mesh_network.channel,updateBW, bserverHT); + if (updateBW == 1) { + if (bserverHT == 0) { + printk("===>server is not HT supported,set 20M\n"); + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + } else { + printk("===>updateBW is 1,bCurBW40MHz is %d,ieee->serverExtChlOffset is %d\n", + ieee->pHTInfo->bCurBW40MHz,ieee->serverExtChlOffset); + if (ieee->pHTInfo->bCurBW40MHz) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, ieee->serverExtChlOffset); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, ieee->serverExtChlOffset); + } + } else { + printk("===>there is no same hostname server, ERR!!!\n"); + return -1; + } + return 0; +} + +int meshdev_start_mesh_protocol_wq(void *data) +{ + struct rtllib_device *ieee = container_of_work_rsl(data, struct rtllib_device, + ext_start_mesh_protocol_wq); + + ieee->set_chan(ieee->dev, ieee->current_mesh_network.channel); + if(ieee->pHTInfo->bCurBW40MHz) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + + rtllib_start_mesh_protocol(ieee); + + return 0; +} +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_mesh.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl_mesh.h @@ -0,0 +1,40 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifdef _RTL8192_EXT_PATCH_ +#ifndef _RTL_MESH_H +#define _RTL_MESH_H + +struct net_device; +struct net_device_stats; + +int meshdev_up(struct net_device *meshdev,bool is_silent_reset); +int meshdev_down(struct net_device *meshdev); +struct net_device_stats *meshdev_stats(struct net_device *meshdev); +void meshdev_init(struct net_device* meshdev); + +int meshdev_update_ext_chnl_offset_as_client(void *data); +int meshdev_start_mesh_protocol_wq(void *data); +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_pci.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_pci.c @@ -0,0 +1,489 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + *****************************************************************************/ +#include "rtl_pci.h" +#include "rtl_core.h" + +#if defined RTL8192CE || defined RTL8192SE +bool +rtl8192_get_LinkControl_field( + struct net_device *dev, + u8 BusNum, + u8 DevNum, + u8 FuncNum + ) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + RT_PCI_CAPABILITIES_HEADER CapabilityHdr; + unsigned char CapabilityOffset, Num4Bytes; + u32 PciCfgAddrPort=0; + u8 LinkCtrlReg; + bool Status = false; + + if( BusNum == 0xff && DevNum == 0xff && FuncNum == 0xff ){ + printk("GetLinkControlField(): Fail to find PCIe Capability\n"); + return false; + } + + + PciCfgAddrPort= (BusNum<< 16)|(DevNum << 11)|(FuncNum << 8)|(1 << 31); + + + Num4Bytes = 0x34/4; + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort+( Num4Bytes<< 2)); + NdisRawReadPortUchar(PCI_CONF_DATA, &CapabilityOffset); + + + while (CapabilityOffset != 0) + { + Num4Bytes = CapabilityOffset/4; + + + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort+( Num4Bytes<< 2)); + NdisRawReadPortUshort(PCI_CONF_DATA, (u16*)&CapabilityHdr); + + if (CapabilityHdr.CapabilityID == PCI_CAPABILITY_ID_PCI_EXPRESS) + { + break; + } + else + { + CapabilityOffset = CapabilityHdr.Next; + } + } + + + if (CapabilityHdr.CapabilityID == PCI_CAPABILITY_ID_PCI_EXPRESS) + { + Num4Bytes = (CapabilityOffset+0x10)/4; + + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort+(Num4Bytes << 2)); + NdisRawReadPortUchar(PCI_CONF_DATA, &LinkCtrlReg); + + priv->NdisAdapter.PciBridgePCIeHdrOffset = CapabilityOffset; + priv->NdisAdapter.PciBridgeLinkCtrlReg = LinkCtrlReg; + + Status = true; + } + else + { + printk("GetLinkControlField(): Cannot Find PCIe Capability\n"); + } + + return Status; +} + +bool +rtl8192_get_pci_BusInfo( + struct net_device *dev, + u16 VendorId, + u16 DeviceId, + u8 IRQL, + u8 BaseCode, + u8 SubClass, + u8 filed19val, + u8* BusNum, + u8* DevNum, + u8* FuncNum + ) +{ + + u8 busNumIdx, deviceNumIdx, functionNumIdx; + u32 PciCfgAddrPort=0; + u32 devVenID = 0, classCode, field19, headertype; + u16 venId, devId; + u8 basec, subc, irqLine; + u16 RegOffset; + bool bSingleFunc = false; + bool bBridgeChk = false; + + *BusNum = 0xFF; + *DevNum = 0xFF; + *FuncNum = 0xFF; + + if((BaseCode == PCI_CLASS_BRIDGE_DEV) && (SubClass==PCI_SUBCLASS_BR_PCI_TO_PCI) && (filed19val==U1DONTCARE)) + bBridgeChk = true; + + for (busNumIdx = 0; busNumIdx < PCI_MAX_BRIDGE_NUMBER ; busNumIdx++) + { + for (deviceNumIdx = 0; deviceNumIdx < PCI_MAX_DEVICES; deviceNumIdx ++) + { + bSingleFunc = false; + for (functionNumIdx = 0; functionNumIdx < PCI_MAX_FUNCTION; functionNumIdx++) + { + + if(functionNumIdx == 0) + { + PciCfgAddrPort= (busNumIdx << 16)|(deviceNumIdx << 11)|(functionNumIdx << 8)|(1 << 31); + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort + (3 << 2)); + NdisRawReadPortUlong(PCI_CONF_DATA, &headertype); + headertype = ((headertype >> 16) & 0x0080) >> 7; + if( headertype == 0) + bSingleFunc = true; + } + else + { + if(bSingleFunc == true) break; + } + + PciCfgAddrPort= (busNumIdx << 16)|(deviceNumIdx << 11)|(functionNumIdx << 8)|(1 << 31); + + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort); + NdisRawReadPortUlong(PCI_CONF_DATA, &devVenID); + + if ( devVenID == 0xFFFFFFFF||devVenID == 0 ) continue; + + RegOffset = 0x3C; + PciCfgAddrPort= (busNumIdx << 16)|(deviceNumIdx << 11)|(functionNumIdx << 8)|(1 << 31)|(RegOffset & 0xFFFFFFFC); + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort); + NdisRawReadPortUchar((PCI_CONF_DATA+ (RegOffset & 0x3)), &irqLine); + + venId = (u16)(devVenID >> 0)& 0xFFFF; + devId = (u16)(devVenID >> 16)& 0xFFFF; + + if(!bBridgeChk && (venId != VendorId) && (VendorId != U2DONTCARE)) + continue; + + if(!bBridgeChk && (devId != DeviceId) && (DeviceId != U2DONTCARE)) + continue; + + if(!bBridgeChk && (irqLine != IRQL) && (IRQL != U1DONTCARE)) + continue; + + PciCfgAddrPort= (busNumIdx << 16)|(deviceNumIdx << 11)|(functionNumIdx << 8)|(1 << 31); + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort + (2 << 2)); + NdisRawReadPortUlong(PCI_CONF_DATA, &classCode); + classCode = classCode >> 8; + + basec = (u8)(classCode >>16 ) & 0xFF; + subc = (u8)(classCode >>8 ) & 0xFF; + if(bBridgeChk && (venId != VendorId) &&(basec == BaseCode) && (subc== SubClass ) ) + return true; + + if(bBridgeChk && (venId != VendorId) && (VendorId != U2DONTCARE)) + continue; + + if(bBridgeChk && (devId != DeviceId) && (DeviceId != U2DONTCARE)) + continue; + + if(bBridgeChk && (irqLine != IRQL) && (IRQL != U1DONTCARE)) + continue; + + + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort + (6 << 2)); + NdisRawReadPortUlong(PCI_CONF_DATA, &field19); + field19 = (field19 >> 8)& 0xFF; + + if((basec == BaseCode) && (subc== SubClass ) && ((field19 == filed19val) ||(filed19val==U1DONTCARE) )) + { + *BusNum = busNumIdx; + *DevNum = deviceNumIdx; + *FuncNum = functionNumIdx; + + printk( "GetPciBusInfo(): Find Device(%X:%X) bus=%d dev=%d, func=%d\n",VendorId, DeviceId, busNumIdx, deviceNumIdx, functionNumIdx); + return true; + } + } + } + } + + printk( "GetPciBusInfo(): Cannot Find Device(%X:%X:%X)\n",VendorId, DeviceId, devVenID); + return false; +} + +bool rtl8192_get_pci_BridegInfo( + struct net_device *dev, + u8 BaseCode, + u8 SubClass, + u8 filed19val, + u8* BusNum, + u8* DevNum, + u8* FuncNum, + u16* VendorId, + u16* DeviceId + ) + +{ + + u8 busNumIdx, deviceNumIdx, functionNumIdx; + u32 PciCfgAddrPort=0; + u32 devVenID, classCode, field19, headertype; + u16 venId, devId; + u8 basec, subc, irqLine; + u16 RegOffset; + bool bSingleFunc = false; + + *BusNum = 0xFF; + *DevNum = 0xFF; + *FuncNum = 0xFF; + + for (busNumIdx = 0; busNumIdx < PCI_MAX_BRIDGE_NUMBER ; busNumIdx++) + { + for (deviceNumIdx = 0; deviceNumIdx < PCI_MAX_DEVICES; deviceNumIdx ++) + { + bSingleFunc = false; + for (functionNumIdx = 0; functionNumIdx < PCI_MAX_FUNCTION; functionNumIdx++) + { + + if(functionNumIdx == 0) + { + PciCfgAddrPort= (busNumIdx << 16)|(deviceNumIdx << 11)|(functionNumIdx << 8)|(1 << 31); + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort + (3 << 2)); + NdisRawReadPortUlong(PCI_CONF_DATA, &headertype); + headertype = ((headertype >> 16) & 0x0080) >> 7; + if( headertype == 0) + bSingleFunc = true; + } + else + { + if( bSingleFunc ==true ) break; + } + + PciCfgAddrPort= (busNumIdx << 16)|(deviceNumIdx << 11)|(functionNumIdx << 8)|(1 << 31); + + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort); + NdisRawReadPortUlong(PCI_CONF_DATA, &devVenID); + + RegOffset = 0x3C; + PciCfgAddrPort= (busNumIdx << 16)|(deviceNumIdx << 11)|(functionNumIdx << 8)|(1 << 31)|(RegOffset & 0xFFFFFFFC); + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort); + NdisRawReadPortUchar((PCI_CONF_DATA+ (RegOffset & 0x3)), &irqLine); + + venId = (u16)(devVenID >> 0)& 0xFFFF; + devId = (u16)(devVenID >> 16)& 0xFFFF; + + PciCfgAddrPort= (busNumIdx << 16)|(deviceNumIdx << 11)|(functionNumIdx << 8)|(1 << 31); + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort + (2 << 2)); + NdisRawReadPortUlong(PCI_CONF_DATA, &classCode); + classCode = classCode >> 8; + + basec = (u8)(classCode >>16 ) & 0xFF; + subc = (u8)(classCode >>8 ) & 0xFF; + + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort + (6 << 2)); + NdisRawReadPortUlong(PCI_CONF_DATA, &field19); + field19 = (field19 >> 8)& 0xFF; + + if((basec == BaseCode) && (subc== SubClass ) && ((field19 == filed19val) ||(filed19val==U1DONTCARE) )) + { + *BusNum = busNumIdx; + *DevNum = deviceNumIdx; + *FuncNum = functionNumIdx; + *VendorId = venId; + *DeviceId = devId; + + printk("GetPciBridegInfo : Find Device(%X:%X) bus=%d dev=%d, func=%d\n", + venId, devId, busNumIdx, deviceNumIdx, functionNumIdx); + + return true; + } + } + } + } + + printk( "GetPciBridegInfo(): Cannot Find PciBridge for Device\n"); + + return false; +} + + +static u16 PciBridgeVendorArray[PCI_BRIDGE_VENDOR_MAX] + = {INTEL_VENDOR_ID,ATI_VENDOR_ID,AMD_VENDOR_ID,SIS_VENDOR_ID}; + +void +rtl8192_pci_find_BridgeInfo(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + u8 PciBridgeBusNum = 0xff; + u8 PciBridgeDevNum = 0xff; + u8 PciBridgeFuncNum = 0xff; + u16 PciBridgeVendorId= 0xff; + u16 PciBridgeDeviceId = 0xff; + u8 tmp = 0; + + rtl8192_get_pci_BridegInfo(dev, + PCI_CLASS_BRIDGE_DEV, + PCI_SUBCLASS_BR_PCI_TO_PCI , + priv->NdisAdapter.BusNumber, + &PciBridgeBusNum, + &PciBridgeDevNum, + &PciBridgeFuncNum, + &PciBridgeVendorId, + &PciBridgeDeviceId); + + + priv->NdisAdapter.PciBridgeVendor = PCI_BRIDGE_VENDOR_UNKNOWN; + + for(tmp = 0; tmp < PCI_BRIDGE_VENDOR_MAX; tmp++) + { + if(PciBridgeVendorId == PciBridgeVendorArray[tmp]) + { + priv->NdisAdapter.PciBridgeVendor = tmp; + printk("Pci Bridge Vendor is found index: %d\n",tmp); + break; + } + } + printk("Pci Bridge Vendor is %x\n",PciBridgeVendorArray[tmp]); + + priv->NdisAdapter.PciBridgeBusNum = PciBridgeBusNum; + priv->NdisAdapter.PciBridgeDevNum = PciBridgeDevNum; + priv->NdisAdapter.PciBridgeFuncNum = PciBridgeFuncNum; + priv->NdisAdapter.PciBridgeVendorId = PciBridgeVendorId; + priv->NdisAdapter.PciBridgeDeviceId = PciBridgeDeviceId; + + +} + +bool +rtl8192_GetAMDL1Patch( + struct net_device *dev, + u8 BusNum, + u8 DevNum, + u8 FuncNum + ) +{ + bool Status = false; + u8 OffsetE0; + unsigned OffsetE4; + u32 PciCfgAddrPort=0; + + PciCfgAddrPort= (BusNum<< 16)|(DevNum << 11)|(FuncNum << 8)|(1 << 31); + + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort+0xE0); + NdisRawWritePortUchar(PCI_CONF_DATA, 0xA0); + + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort+0xE0); + NdisRawReadPortUchar(PCI_CONF_DATA, &OffsetE0); + + if(OffsetE0 == 0xA0) + { + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort+0xE4); + NdisRawReadPortUlong(PCI_CONF_DATA, &OffsetE4); + if(OffsetE4 & BIT23) + Status = true; + } + + return Status; +} + + +#endif + +static void rtl8192_parse_pci_configuration(struct pci_dev *pdev, struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + u8 tmp; + int pos; + u8 LinkCtrlReg; + + pos = pci_find_capability(priv->pdev, PCI_CAP_ID_EXP); + pci_read_config_byte(priv->pdev, pos + PCI_EXP_LNKCTL, &LinkCtrlReg); + priv->NdisAdapter.LinkCtrlReg = LinkCtrlReg; + + RT_TRACE(COMP_INIT, "Link Control Register =%x\n", priv->NdisAdapter.LinkCtrlReg); + + pci_read_config_byte(pdev, 0x98, &tmp); + tmp |=BIT4; + pci_write_config_byte(pdev, 0x98, tmp); + + tmp = 0x17; + pci_write_config_byte(pdev, 0x70f, tmp); +} + +bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u16 VenderID; + u16 DeviceID; + u8 RevisionID; + u16 IrqLine; + + VenderID = pdev->vendor; + DeviceID = pdev->device; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) + pci_read_config_byte(pdev, 0x8, &RevisionID); +#else + RevisionID = pdev->revision; +#endif + pci_read_config_word(pdev, 0x3C, &IrqLine); + + priv->card_8192 = priv->ops->nic_type; + + if (DeviceID == 0x8172) { + switch (RevisionID) { + case HAL_HW_PCI_REVISION_ID_8192PCIE: + printk("Adapter(8192 PCI-E) is found - DeviceID=%x\n", DeviceID); + priv->card_8192 = NIC_8192E; + break; + case HAL_HW_PCI_REVISION_ID_8192SE: + printk("Adapter(8192SE) is found - DeviceID=%x\n", DeviceID); + priv->card_8192 = NIC_8192SE; + break; + default: + printk("UNKNOWN nic type(%4x:%4x)\n", pdev->vendor, pdev->device); + priv->card_8192 = NIC_UNKNOWN; + return false; + } + } + + if (priv->ops->nic_type != priv->card_8192) { + printk("Detect info(%x) and hardware info(%x) not match!\n", + priv->ops->nic_type, priv->card_8192); + printk("Please select proper driver before install!!!!\n"); + return false; + } + +#if defined RTL8192CE || defined RTL8192SE + rtl8192_get_pci_BusInfo(dev, + VenderID, + DeviceID, + (u8)IrqLine, + 0x02,0x80, U1DONTCARE, + &priv->NdisAdapter.BusNumber, + &priv->NdisAdapter.DevNumber, + &priv->NdisAdapter.FuncNumber); + + rtl8192_pci_find_BridgeInfo(dev); + + if(priv->NdisAdapter.PciBridgeVendor != PCI_BRIDGE_VENDOR_UNKNOWN) + { + rtl8192_get_LinkControl_field(dev, priv->NdisAdapter.PciBridgeBusNum, + priv->NdisAdapter.PciBridgeDevNum, priv->NdisAdapter.PciBridgeFuncNum); + + if(priv->NdisAdapter.PciBridgeVendor == PCI_BRIDGE_VENDOR_AMD) + { + priv->NdisAdapter.AMDL1PATCH = rtl8192_GetAMDL1Patch(dev, priv->NdisAdapter.PciBridgeBusNum, + priv->NdisAdapter.PciBridgeDevNum, priv->NdisAdapter.PciBridgeFuncNum); + } + } + +#endif + + rtl8192_parse_pci_configuration(pdev, dev); + + return true; +} --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_pci.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl_pci.h @@ -0,0 +1,106 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + ******************************************************************************/ +#ifndef _RTL_PCI_H +#define _RTL_PCI_H + +#include +#include +#include "rtllib/rtllib.h" + +static inline void NdisRawWritePortUlong(u32 port, u32 val) +{ + outl(val, port); +} + +static inline void NdisRawWritePortUchar(u32 port, u8 val) +{ + outb(val, port); +} + +static inline void NdisRawReadPortUchar(u32 port, u8 *pval) +{ + *pval = inb(port); +} + +static inline void NdisRawReadPortUshort(u32 port, u16 *pval) +{ + *pval = inw(port); +} + +static inline void NdisRawReadPortUlong(u32 port, u32 *pval) +{ + *pval = inl(port); +} + +typedef struct _mp_adapter{ + u8 LinkCtrlReg; + + u8 BusNumber; + u8 DevNumber; + u8 FuncNumber; + + u8 PciBridgeBusNum; + u8 PciBridgeDevNum; + u8 PciBridgeFuncNum; + u8 PciBridgeVendor; + u16 PciBridgeVendorId; + u16 PciBridgeDeviceId; + u8 PciBridgePCIeHdrOffset; + u8 PciBridgeLinkCtrlReg; + + bool AMDL1PATCH; +}mp_adapter,*pmp_adapter; + +typedef struct _RT_PCI_CAPABILITIES_HEADER { + unsigned char CapabilityID; + unsigned char Next; +} RT_PCI_CAPABILITIES_HEADER, *PRT_PCI_CAPABILITIES_HEADER; + +#define PCI_MAX_BRIDGE_NUMBER 255 +#define PCI_MAX_DEVICES 32 +#define PCI_MAX_FUNCTION 8 + +#define PCI_CONF_ADDRESS 0x0CF8 +#define PCI_CONF_DATA 0x0CFC + +#define PCI_CLASS_BRIDGE_DEV 0x06 +#define PCI_SUBCLASS_BR_PCI_TO_PCI 0x04 + +#define U1DONTCARE 0xFF +#define U2DONTCARE 0xFFFF +#define U4DONTCARE 0xFFFFFFFF + +#define INTEL_VENDOR_ID 0x8086 +#define SIS_VENDOR_ID 0x1039 +#define ATI_VENDOR_ID 0x1002 +#define ATI_DEVICE_ID 0x7914 +#define AMD_VENDOR_ID 0x1022 + +#define PCI_CAPABILITY_ID_PCI_EXPRESS 0x10 + +struct net_device; +bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev); + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_pm.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_pm.c @@ -0,0 +1,188 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + +#ifdef CONFIG_PM_RTL + +#include "rtl_core.h" +#include "rtl_pm.h" + +int rtl8192E_save_state (struct pci_dev *dev, pm_message_t state) +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) + printk(KERN_NOTICE "r8192E save state call (state %u).\n", state); +#else + printk(KERN_NOTICE "r8192E save state call (state %u).\n", state.event); +#endif + return(-EAGAIN); +} + + +int rtl8192E_suspend (struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct r8192_priv *priv = rtllib_priv(dev); +#if !(defined RTL8192SE || defined RTL8192CE) + u32 ulRegRead; +#endif + + RT_TRACE(COMP_POWER, "============> r8192E suspend call.\n"); + printk("============> r8192E suspend call.\n"); +#ifdef ENABLE_GPIO_RADIO_CTL + del_timer_sync(&priv->gpio_polling_timer); + cancel_delayed_work(&priv->gpio_change_rf_wq); + priv->polling_timer_on = 0; +#endif + + if (!netif_running(dev)){ + printk("RTL819XE:UI is open out of suspend function\n"); + goto out_pci_suspend; + } + +#ifdef HAVE_NET_DEVICE_OPS + if (dev->netdev_ops->ndo_stop) + dev->netdev_ops->ndo_stop(dev); +#else + dev->stop(dev); +#endif + netif_device_detach(dev); + +#if !(defined RTL8192SE || defined RTL8192CE) + if(!priv->rtllib->bSupportRemoteWakeUp) { + MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_INIT,true); + ulRegRead = read_nic_dword(dev, CPU_GEN); + ulRegRead|=CPU_GEN_SYSTEM_RESET; + write_nic_dword(dev, CPU_GEN, ulRegRead); + } else { + write_nic_dword(dev, WFCRC0, 0xffffffff); + write_nic_dword(dev, WFCRC1, 0xffffffff); + write_nic_dword(dev, WFCRC2, 0xffffffff); +#ifdef RTL8190P + { + u8 ucRegRead; + ucRegRead = read_nic_byte(dev, GPO); + ucRegRead |= BIT0; + write_nic_byte(dev, GPO, ucRegRead); + } +#endif + write_nic_byte(dev, PMR, 0x5); + write_nic_byte(dev, MacBlkCtrl, 0xa); + } +#endif +out_pci_suspend: + RT_TRACE(COMP_POWER, "r8192E support WOL call??????????????????????\n"); + printk("r8192E support WOL call??????????????????????\n"); + if(priv->rtllib->bSupportRemoteWakeUp) { + RT_TRACE(COMP_POWER, "r8192E support WOL call!!!!!!!!!!!!!!!!!!.\n"); + } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) + pci_save_state(pdev,&(priv->pci_state)); + pci_disable_device(pdev); + pci_enable_wake(pdev, state,\ + priv->rtllib->bSupportRemoteWakeUp?1:0); + pci_set_power_state(pdev,state); +#else + pci_save_state(pdev); + pci_disable_device(pdev); + pci_enable_wake(pdev, pci_choose_state(pdev,state),\ + priv->rtllib->bSupportRemoteWakeUp?1:0); + pci_set_power_state(pdev,pci_choose_state(pdev,state)); +#endif + + mdelay(20); + + return 0; +} + +int rtl8192E_resume (struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); +#if defined ENABLE_GPIO_RADIO_CTL || !(defined RTL8192SE || defined RTL8192CE) + struct r8192_priv *priv = rtllib_priv(dev); +#endif + int err; + u32 val; + + RT_TRACE(COMP_POWER, "================>r8192E resume call."); + printk("================>r8192E resume call.\n"); + + pci_set_power_state(pdev, PCI_D0); + + err = pci_enable_device(pdev); + if(err) { + printk(KERN_ERR "%s: pci_enable_device failed on resume\n", + dev->name); + return err; + } +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) + pci_restore_state(pdev,&(priv->pci_state)); +#else + pci_restore_state(pdev); +#endif + + pci_read_config_dword(pdev, 0x40, &val); + if ((val & 0x0000ff00) != 0) { + pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); + } + + pci_enable_wake(pdev, PCI_D0, 0); + +#ifdef ENABLE_GPIO_RADIO_CTL + if(priv->polling_timer_on == 0){ + check_rfctrl_gpio_timer((unsigned long)dev); + } +#endif + + if(!netif_running(dev)){ + printk("RTL819XE:UI is open out of resume function\n"); + goto out; + } + + netif_device_attach(dev); +#ifdef HAVE_NET_DEVICE_OPS + if (dev->netdev_ops->ndo_open) + dev->netdev_ops->ndo_open(dev); +#else + dev->open(dev); +#endif + +#if !(defined RTL8192SE || defined RTL8192CE) + if(!priv->rtllib->bSupportRemoteWakeUp) { + MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_INIT,true); + } +#endif + +out: + RT_TRACE(COMP_POWER, "<================r8192E resume call.\n"); + return 0; +} + + +int rtl8192E_enable_wake (struct pci_dev *dev, pm_message_t state, int enable) +{ +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) + printk(KERN_NOTICE "r8192E enable wake call (state %u, enable %d).\n", + state, enable); +#else + printk(KERN_NOTICE "r8192E enable wake call (state %u, enable %d).\n", + state.event, enable); +#endif + return(-EAGAIN); +} + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_pm.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl_pm.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + +#ifdef CONFIG_PM_RTL + +#ifndef R8192E_PM_H +#define R8192E_PM_H + +#include +#include + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) +#define pm_message_t u32 +#endif + +int rtl8192E_save_state (struct pci_dev *dev, pm_message_t state); +int rtl8192E_suspend (struct pci_dev *dev, pm_message_t state); +int rtl8192E_resume (struct pci_dev *dev); +int rtl8192E_enable_wake (struct pci_dev *dev, pm_message_t state, int enable); + +#endif + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_ps.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_ps.c @@ -0,0 +1,923 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + *****************************************************************************/ +#include "rtl_ps.h" +#include "rtl_core.h" + +#if defined(RTL8192E) || defined(RTL8192SE) || defined RTL8192CE +void rtl8192_hw_sleep_down(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + unsigned long flags = 0; +#ifdef CONFIG_ASPM_OR_D3 + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); +#endif + spin_lock_irqsave(&priv->rf_ps_lock,flags); + if (priv->RFChangeInProgress) { + spin_unlock_irqrestore(&priv->rf_ps_lock,flags); + RT_TRACE(COMP_RF, "rtl8192_hw_sleep_down(): RF Change in progress! \n"); + printk("rtl8192_hw_sleep_down(): RF Change in progress!\n"); + return; + } + spin_unlock_irqrestore(&priv->rf_ps_lock,flags); + RT_TRACE(COMP_PS, "%s()============>come to sleep down\n", __FUNCTION__); + +#ifdef CONFIG_RTLWIFI_DEBUGFS + if(priv->debug->hw_holding) { + return; + } +#endif + MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS,false); +#ifdef CONFIG_ASPM_OR_D3 + if(pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM) + { + RT_ENABLE_ASPM(dev); + RT_SET_PS_LEVEL(pPSC, RT_RF_LPS_LEVEL_ASPM); + } +#endif +} + +void rtl8192_hw_sleep_wq(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct rtllib_device *ieee = container_of_dwork_rsl(data,struct rtllib_device,hw_sleep_wq); + struct net_device *dev = ieee->dev; +#else + struct net_device *dev = (struct net_device *)data; +#endif + rtl8192_hw_sleep_down(dev); +} + +void rtl8192_hw_wakeup(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + unsigned long flags = 0; +#ifdef CONFIG_ASPM_OR_D3 + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); +#endif + spin_lock_irqsave(&priv->rf_ps_lock,flags); + if (priv->RFChangeInProgress) { + spin_unlock_irqrestore(&priv->rf_ps_lock,flags); + RT_TRACE(COMP_RF, "rtl8192_hw_wakeup(): RF Change in progress! \n"); + printk("rtl8192_hw_wakeup(): RF Change in progress! schedule wake up task again\n"); + queue_delayed_work_rsl(priv->rtllib->wq,&priv->rtllib->hw_wakeup_wq,MSECS(10)); + return; + } + spin_unlock_irqrestore(&priv->rf_ps_lock,flags); +#ifdef CONFIG_ASPM_OR_D3 + if (pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM) { + RT_DISABLE_ASPM(dev); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_LPS_LEVEL_ASPM); + } +#endif + RT_TRACE(COMP_PS, "%s()============>come to wake up\n", __FUNCTION__); + MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS,false); +} + +void rtl8192_hw_wakeup_wq(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct rtllib_device *ieee = container_of_dwork_rsl(data,struct rtllib_device,hw_wakeup_wq); + struct net_device *dev = ieee->dev; +#else + struct net_device *dev = (struct net_device *)data; +#endif + rtl8192_hw_wakeup(dev); + +} + +#define MIN_SLEEP_TIME 50 +#define MAX_SLEEP_TIME 10000 +void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl) +{ +#ifdef _RTL8192_EXT_PATCH_ + struct r8192_priv *priv = rtllib_priv(dev); + u32 rb = jiffies, sleep_cost = MSECS(8+16+7), delta = 0; + unsigned long flags; + + if((tl > rb) && (th > 0)) + return; + + spin_lock_irqsave(&priv->ps_lock,flags); + + if (tl >= sleep_cost) + tl -= sleep_cost; + else if (th > 0) { + tl = 0xffffffff - sleep_cost + tl; + th--; + } else { + spin_unlock_irqrestore(&priv->ps_lock,flags); + return; + } + + if (tl > rb) { + delta = tl - rb; + } else if (th > 0) { + delta = 0xffffffff - rb + tl; + th --; + } else { + spin_unlock_irqrestore(&priv->ps_lock,flags); + return; + } + + if (delta <= MSECS(MIN_SLEEP_TIME)) { + spin_unlock_irqrestore(&priv->ps_lock,flags); + printk("too short to sleep::%x, %x, %lx\n",tl, rb, MSECS(MIN_SLEEP_TIME)); + return; + } + + if(delta > MSECS(MAX_SLEEP_TIME)) { + spin_unlock_irqrestore(&priv->ps_lock,flags); + printk("========>too long to sleep:%x, %x, %lx\n", tl, rb, MSECS(MAX_SLEEP_TIME)); + return; + } + + RT_TRACE(COMP_LPS, "==============>%s(): wake up time is %d,%d\n",__FUNCTION__,delta,jiffies_to_msecs(delta)); + queue_delayed_work_rsl(priv->rtllib->wq,&priv->rtllib->hw_wakeup_wq,delta); + queue_delayed_work_rsl(priv->rtllib->wq, (void *)&priv->rtllib->hw_sleep_wq,0); + + spin_unlock_irqrestore(&priv->ps_lock,flags); +#else + struct r8192_priv *priv = rtllib_priv(dev); + + u32 rb = jiffies; + unsigned long flags; + + spin_lock_irqsave(&priv->ps_lock,flags); + + tl -= MSECS(8+16+7); + + if(((tl>=rb)&& (tl-rb) <= MSECS(MIN_SLEEP_TIME)) + ||((rb>tl)&& (rb-tl) < MSECS(MIN_SLEEP_TIME))) { + spin_unlock_irqrestore(&priv->ps_lock,flags); + printk("too short to sleep::%x, %x, %lx\n",tl, rb, MSECS(MIN_SLEEP_TIME)); + return; + } + + if(((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME)))|| + ((tl < rb) && (tl>MSECS(69)) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))|| + ((tlMSECS(MAX_SLEEP_TIME)))) { + printk("========>too long to sleep:%x, %x, %lx\n", tl, rb, MSECS(MAX_SLEEP_TIME)); + spin_unlock_irqrestore(&priv->ps_lock,flags); + return; + } + { + u32 tmp = (tl>rb)?(tl-rb):(rb-tl); + queue_delayed_work_rsl(priv->rtllib->wq, + &priv->rtllib->hw_wakeup_wq,tmp); + } + queue_delayed_work_rsl(priv->rtllib->wq, + (void *)&priv->rtllib->hw_sleep_wq,0); + spin_unlock_irqrestore(&priv->ps_lock,flags); +#endif +} +#endif + +#ifdef ENABLE_IPS +void InactivePsWorkItemCallback(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + + RT_TRACE(COMP_PS, "InactivePsWorkItemCallback() ---------> \n"); + pPSC->bSwRfProcessing = true; + + RT_TRACE(COMP_PS, "InactivePsWorkItemCallback(): Set RF to %s.\n", \ + pPSC->eInactivePowerState == eRfOff?"OFF":"ON"); +#ifdef CONFIG_ASPM_OR_D3 + if(pPSC->eInactivePowerState == eRfOn) + { + + if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM)) + { + RT_DISABLE_ASPM(dev); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM); + } +#ifdef TODO + else if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3)) + { + RT_LEAVE_D3(dev, false); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3); + } +#endif + } +#endif + MgntActSet_RF_State(dev, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS,false); + +#ifdef CONFIG_ASPM_OR_D3 + if(pPSC->eInactivePowerState == eRfOff) + { + if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) + { + RT_ENABLE_ASPM(dev); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM); + } +#ifdef TODO + else if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) + { + RT_ENTER_D3(dev, false); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3); + } +#endif + } +#endif + +#if 0 + if(pPSC->eInactivePowerState == eRfOn) + { + while( index < 4 ) + { + if( ( pMgntInfo->SecurityInfo.PairwiseEncAlgorithm == WEP104_Encryption ) || + (pMgntInfo->SecurityInfo.PairwiseEncAlgorithm == WEP40_Encryption) ) + { + if( pMgntInfo->SecurityInfo.KeyLen[index] != 0) + pAdapter->HalFunc.SetKeyHandler(pAdapter, index, 0, false, pMgntInfo->SecurityInfo.PairwiseEncAlgorithm, true, false); + + } + index++; + } + } +#endif + pPSC->bSwRfProcessing = false; + RT_TRACE(COMP_PS, "InactivePsWorkItemCallback() <--------- \n"); +} + +void +IPSEnter(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + RT_RF_POWER_STATE rtState; + + if (pPSC->bInactivePs) + { + rtState = priv->rtllib->eRFPowerState; + if (rtState == eRfOn && !pPSC->bSwRfProcessing &&\ + (priv->rtllib->state != RTLLIB_LINKED)&&\ + (priv->rtllib->iw_mode != IW_MODE_MASTER)) + { + RT_TRACE(COMP_PS,"IPSEnter(): Turn off RF.\n"); + pPSC->eInactivePowerState = eRfOff; + priv->isRFOff = true; + priv->bInPowerSaveMode = true; + InactivePsWorkItemCallback(dev); + } + } +} + +void +IPSLeave(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + RT_RF_POWER_STATE rtState; + + if (pPSC->bInactivePs) + { + rtState = priv->rtllib->eRFPowerState; + if (rtState != eRfOn && !pPSC->bSwRfProcessing && priv->rtllib->RfOffReason <= RF_CHANGE_BY_IPS) + { + RT_TRACE(COMP_PS, "IPSLeave(): Turn on RF.\n"); + pPSC->eInactivePowerState = eRfOn; + priv->bInPowerSaveMode = false; + InactivePsWorkItemCallback(dev); + } + } +} +void IPSLeave_wq(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct rtllib_device *ieee = container_of_work_rsl(data,struct rtllib_device,ips_leave_wq); + struct net_device *dev = ieee->dev; +#else + struct net_device *dev = (struct net_device *)data; +#endif + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + down(&priv->rtllib->ips_sem); + IPSLeave(dev); + up(&priv->rtllib->ips_sem); +} +void rtllib_ips_leave_wq(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + RT_RF_POWER_STATE rtState; + rtState = priv->rtllib->eRFPowerState; + + if(priv->rtllib->PowerSaveControl.bInactivePs){ + if(rtState == eRfOff){ + if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) + { + RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__); + return; + } + else{ + printk("=========>%s(): IPSLeave\n",__FUNCTION__); + queue_work_rsl(priv->rtllib->wq,&priv->rtllib->ips_leave_wq); + } + } + } +} +void rtllib_ips_leave(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + down(&priv->rtllib->ips_sem); + IPSLeave(dev); + up(&priv->rtllib->ips_sem); +} +#endif + +#ifdef ENABLE_LPS +bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev, u8 rtPsMode) +{ + struct r8192_priv *priv = rtllib_priv(dev); + +#ifdef _RTL8192_EXT_PATCH_ + if((priv->rtllib->iw_mode == IW_MODE_ADHOC) || (priv->rtllib->iw_mode == IW_MODE_MASTER) + || (priv->rtllib->iw_mode == IW_MODE_MESH)) +#else + if(priv->rtllib->iw_mode == IW_MODE_ADHOC) +#endif + { + return false; + } + + + RT_TRACE(COMP_LPS,"%s(): set ieee->ps = %x\n",__FUNCTION__,rtPsMode); + if(!priv->ps_force) { + priv->rtllib->ps = rtPsMode; + } +#if 0 + priv->rtllib->dot11PowerSaveMode = rtPsMode; + + if(priv->rtllib->dot11PowerSaveMode == eMaxPs) + { + } + else + { + } +#endif + if(priv->rtllib->sta_sleep != LPS_IS_WAKE && rtPsMode == RTLLIB_PS_DISABLED) + { + unsigned long flags; + + rtl8192_hw_wakeup(dev); + priv->rtllib->sta_sleep = LPS_IS_WAKE; + + spin_lock_irqsave(&(priv->rtllib->mgmt_tx_lock), flags); + printk("LPS leave: notify AP we are awaked ++++++++++ SendNullFunctionData\n"); + rtllib_sta_ps_send_null_frame(priv->rtllib, 0); + spin_unlock_irqrestore(&(priv->rtllib->mgmt_tx_lock), flags); + } + +#if 0 + if((pPSC->bFwCtrlLPS) && (pPSC->bLeisurePs)) + { + if(priv->rtllib->dot11PowerSaveMode == eActive) + { + RpwmVal = 0x0C; + FwPwrMode = FW_PS_ACTIVE_MODE; + Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_SET_RPWM, (pu1Byte)(&RpwmVal)); + Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_H2C_FW_PWRMODE, (pu1Byte)(&FwPwrMode)); + } + else + { + if(GetFwLPS_Doze(Adapter)) + { + RpwmVal = 0x02; + Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_H2C_FW_PWRMODE, (pu1Byte)(&pPSC->FWCtrlPSMode)); + Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_SET_RPWM, (pu1Byte)(&RpwmVal)); + } + else + { + pMgntInfo->dot11PowerSaveMode = eActive; + Adapter->bInPowerSaveMode = false; + } + } + } +#endif + return true; +} + + +void LeisurePSEnter(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + + RT_TRACE(COMP_PS, "LeisurePSEnter()...\n"); + RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdleCount is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n", + pPSC->bLeisurePs, priv->rtllib->ps,pPSC->LpsIdleCount,RT_CHECK_FOR_HANG_PERIOD); + +#ifdef _RTL8192_EXT_PATCH_ + if(!((priv->rtllib->iw_mode == IW_MODE_INFRA) && (priv->rtllib->state == RTLLIB_LINKED)) + || (priv->rtllib->iw_mode == IW_MODE_ADHOC) || (priv->rtllib->iw_mode == IW_MODE_MASTER) + || (priv->rtllib->iw_mode == IW_MODE_MESH)) +#else + if(!((priv->rtllib->iw_mode == IW_MODE_INFRA) && (priv->rtllib->state == RTLLIB_LINKED)) + || (priv->rtllib->iw_mode == IW_MODE_ADHOC) || (priv->rtllib->iw_mode == IW_MODE_MASTER)) +#endif + return; + + if (pPSC->bLeisurePs) + { + if(pPSC->LpsIdleCount >= RT_CHECK_FOR_HANG_PERIOD) + { + + if(priv->rtllib->ps == RTLLIB_PS_DISABLED) + { + + RT_TRACE(COMP_LPS, "LeisurePSEnter(): Enter 802.11 power save mode...\n"); + + if(!pPSC->bFwCtrlLPS) + { + if (priv->rtllib->SetFwCmdHandler) + { + priv->rtllib->SetFwCmdHandler(dev, FW_CMD_LPS_ENTER); + } + } + MgntActSet_802_11_PowerSaveMode(dev, RTLLIB_PS_MBCAST|RTLLIB_PS_UNICAST); + + /*if(pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM) + { + RT_ENABLE_ASPM(pAdapter); + RT_SET_PS_LEVEL(pAdapter, RT_RF_LPS_LEVEL_ASPM); + }*/ + + } + } + else + pPSC->LpsIdleCount++; + } +} + + +void LeisurePSLeave(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + + + RT_TRACE(COMP_PS, "LeisurePSLeave()...\n"); + RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d\n", + pPSC->bLeisurePs, priv->rtllib->ps); + + if (pPSC->bLeisurePs) + { + if(priv->rtllib->ps != RTLLIB_PS_DISABLED) + { +#ifdef CONFIG_ASPM_OR_D3 + if(pPSC->RegRfPsLevel & RT_RF_LPS_LEVEL_ASPM && RT_IN_PS_LEVEL(pPSC, RT_RF_LPS_LEVEL_ASPM)) + { + RT_DISABLE_ASPM(dev); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_LPS_LEVEL_ASPM); + } +#endif + RT_TRACE(COMP_LPS, "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n"); + MgntActSet_802_11_PowerSaveMode(dev, RTLLIB_PS_DISABLED); + + if(!pPSC->bFwCtrlLPS) + { + if (priv->rtllib->SetFwCmdHandler) + { + priv->rtllib->SetFwCmdHandler(dev, FW_CMD_LPS_LEAVE); + } + } + } + } +} +#endif + +#ifdef CONFIG_ASPM_OR_D3 + +void +PlatformDisableHostL0s(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u32 PciCfgAddrPort=0; + u8 Num4Bytes; + u8 uPciBridgeASPMSetting = 0; + + + if( (priv->NdisAdapter.BusNumber == 0xff && priv->NdisAdapter.DevNumber == 0xff && priv->NdisAdapter.FuncNumber == 0xff) || + (priv->NdisAdapter.PciBridgeBusNum == 0xff && priv->NdisAdapter.PciBridgeDevNum == 0xff && priv->NdisAdapter.PciBridgeFuncNum == 0xff) ) + { + printk("PlatformDisableHostL0s(): Fail to enable ASPM. Cannot find the Bus of PCI(Bridge).\n"); + return; + } + + PciCfgAddrPort= (priv->NdisAdapter.PciBridgeBusNum << 16)|(priv->NdisAdapter.PciBridgeDevNum<< 11)|(priv->NdisAdapter.PciBridgeFuncNum << 8)|(1 << 31); + Num4Bytes = (priv->NdisAdapter.PciBridgePCIeHdrOffset+0x10)/4; + + + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort+(Num4Bytes << 2)); + + NdisRawReadPortUchar(PCI_CONF_DATA, &uPciBridgeASPMSetting); + + if(uPciBridgeASPMSetting & BIT0) + uPciBridgeASPMSetting &= ~(BIT0); + + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort+(Num4Bytes << 2)); + NdisRawWritePortUchar(PCI_CONF_DATA, uPciBridgeASPMSetting); + + udelay(50); + + printk("PlatformDisableHostL0s():PciBridge BusNumber[%x], DevNumbe[%x], FuncNumber[%x], Write reg[%x] = %x\n", + priv->NdisAdapter.PciBridgeBusNum, priv->NdisAdapter.PciBridgeDevNum, priv->NdisAdapter.PciBridgeFuncNum, + (priv->NdisAdapter.PciBridgePCIeHdrOffset+0x10), (priv->NdisAdapter.PciBridgeLinkCtrlReg | (priv->RegDevicePciASPMSetting&~BIT0))); +} + +bool +PlatformEnable92CEBackDoor(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + bool bResult = true; + u8 value; + + if( (priv->NdisAdapter.BusNumber == 0xff && priv->NdisAdapter.DevNumber == 0xff && priv->NdisAdapter.FuncNumber == 0xff) || + (priv->NdisAdapter.PciBridgeBusNum == 0xff && priv->NdisAdapter.PciBridgeDevNum == 0xff && priv->NdisAdapter.PciBridgeFuncNum == 0xff) ) + { + RT_TRACE(COMP_INIT, "PlatformEnableASPM(): Fail to enable ASPM. Cannot find the Bus of PCI(Bridge).\n"); + return false; + } + + pci_read_config_byte(priv->pdev, 0x70f, &value); + + if(priv->NdisAdapter.PciBridgeVendor == PCI_BRIDGE_VENDOR_INTEL) + { + value |= BIT7; + } + else + { + value = 0x23; + } + + pci_write_config_byte(priv->pdev, 0x70f, value); + + + pci_read_config_byte(priv->pdev, 0x719, &value); + value |= (BIT3|BIT4); + pci_write_config_byte(priv->pdev, 0x719, value); + + + return bResult; +} + +bool PlatformSwitchDevicePciASPM(struct net_device *dev, u8 value) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + bool bResult = false; + +#ifdef RTL8192CE + value |= 0x40; +#endif + + pci_write_config_byte(priv->pdev, 0x80, value); + +#ifdef RTL8192SE + udelay(100); +#endif + + return bResult; +} + +bool PlatformSwitchClkReq(struct net_device *dev, u8 value) +{ + bool bResult = false; + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u8 Buffer; + + Buffer= value; + +#ifdef MERGE_TO_DO + if(Adapter->bDriverIsGoingToPnpSetPowerSleep && pDevice->RegSupportLowPowerState + && value == 0x0) + return false; +#endif + + pci_write_config_byte(priv->pdev,0x81,value); + bResult = true; + +#ifdef TODO + if(Buffer) { + priv->ClkReqState = true; + } else { + priv->ClkReqState = false; + } +#endif + +#ifdef RTL8192SE + udelay(100); +#endif + + return bResult; +} + +void +PlatformDisableASPM(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); +#if 1 + u32 PciCfgAddrPort=0; + u8 Num4Bytes; +#endif + u8 LinkCtrlReg; + u16 PciBridgeLinkCtrlReg, ASPMLevel=0; + +#ifdef RTL8192CE + if( (priv->NdisAdapter.BusNumber == 0xff && priv->NdisAdapter.DevNumber == 0xff && priv->NdisAdapter.FuncNumber == 0xff) || + (priv->NdisAdapter.PciBridgeBusNum == 0xff && priv->NdisAdapter.PciBridgeDevNum == 0xff && priv->NdisAdapter.PciBridgeFuncNum == 0xff) ) + { + RT_TRACE(COMP_INIT, "PlatformEnableASPM(): Fail to enable ASPM. Cannot find the Bus of PCI(Bridge).\n"); + return; + } +#endif + +#ifdef RTL8192SE + if(priv->NdisAdapter.PciBridgeVendor != PCI_BRIDGE_VENDOR_INTEL ) + { + RT_TRACE(COMP_POWER, "%s(): Dont modify ASPM for non intel chipset. For Bridge Vendor %d.\n" + ,__func__,priv->NdisAdapter.PciBridgeVendor); + return; + } +#endif + + if(priv->NdisAdapter.PciBridgeVendor == PCI_BRIDGE_VENDOR_UNKNOWN) + { + RT_TRACE(COMP_POWER, "%s(): Disable ASPM. Recognize the Bus of PCI(Bridge) as UNKNOWN.\n",__func__); + } + +#ifdef RTL8192CE + if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_CLK_REQ) + { + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_CLK_REQ); + PlatformSwitchClkReq(dev, 0x0); + } + + { + u8 tmpU1b; + + pci_read_config_byte(priv->pdev, 0x80, &tmpU1b); + } +#endif + + LinkCtrlReg = priv->NdisAdapter.LinkCtrlReg; + PciBridgeLinkCtrlReg = priv->NdisAdapter.PciBridgeLinkCtrlReg; + + ASPMLevel |= BIT0|BIT1; + LinkCtrlReg &=~ASPMLevel; + PciBridgeLinkCtrlReg &=~(BIT0|BIT1); + +#ifdef RTL8192CE + PlatformSwitchDevicePciASPM(dev, LinkCtrlReg); + udelay( 50); +#endif + + if( (priv->NdisAdapter.BusNumber == 0xff && priv->NdisAdapter.DevNumber == 0xff && priv->NdisAdapter.FuncNumber == 0xff) || + (priv->NdisAdapter.PciBridgeBusNum == 0xff && priv->NdisAdapter.PciBridgeDevNum == 0xff && priv->NdisAdapter.PciBridgeFuncNum == 0xff) ) + { + } else { +#if 1 + PciCfgAddrPort= (priv->NdisAdapter.PciBridgeBusNum << 16)|(priv->NdisAdapter.PciBridgeDevNum<< 11)|(priv->NdisAdapter.PciBridgeFuncNum << 8)|(1 << 31); + Num4Bytes = (priv->NdisAdapter.PciBridgePCIeHdrOffset+0x10)/4; + + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort+(Num4Bytes << 2)); + + NdisRawWritePortUchar(PCI_CONF_DATA, PciBridgeLinkCtrlReg); + RT_TRACE(COMP_POWER, "PlatformDisableASPM():PciBridge BusNumber[%x], DevNumbe[%x], FuncNumber[%x], Write reg[%x] = %x\n", + priv->NdisAdapter.PciBridgeBusNum, priv->NdisAdapter.PciBridgeDevNum, priv->NdisAdapter.PciBridgeFuncNum, + (priv->NdisAdapter.PciBridgePCIeHdrOffset+0x10), PciBridgeLinkCtrlReg); + + udelay(50); +#else + pci_write_config_byte(priv->bridge_pdev,priv->PciBridgeASPMRegOffset,PciBridgeLinkCtrlReg); + RT_TRACE(COMP_POWER, "Write reg[%x]=%x\n", (priv->PciBridgeASPMRegOffset), PciBridgeLinkCtrlReg); + udelay(100); +#endif + } + +#ifdef RTL8192SE + PlatformSwitchDevicePciASPM(dev, priv->NdisAdapter.LinkCtrlReg); + + PlatformSwitchClkReq(dev, 0x0); + if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_CLK_REQ) + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_CLK_REQ); + udelay(100); +#endif + +} + +void PlatformEnableASPM(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + u16 ASPMLevel = 0; + u32 PciCfgAddrPort=0; + u8 Num4Bytes; + u8 uPciBridgeASPMSetting = 0; + u8 uDeviceASPMSetting = 0; + + + if( (priv->NdisAdapter.BusNumber == 0xff && priv->NdisAdapter.DevNumber == 0xff && priv->NdisAdapter.FuncNumber == 0xff) || + (priv->NdisAdapter.PciBridgeBusNum == 0xff && priv->NdisAdapter.PciBridgeDevNum == 0xff && priv->NdisAdapter.PciBridgeFuncNum == 0xff) ) + { + RT_TRACE(COMP_INIT, "PlatformEnableASPM(): Fail to enable ASPM. Cannot find the Bus of PCI(Bridge).\n"); + return; + } + +#ifdef RTL8192SE + if(priv->NdisAdapter.PciBridgeVendor != PCI_BRIDGE_VENDOR_INTEL ) + { + RT_TRACE(COMP_POWER, "%s(): Dont modify ASPM for non intel chipset. For Bridge Vendor %d.\n" + ,__func__,priv->NdisAdapter.PciBridgeVendor); + return; + } +#endif + +#ifdef RTL8192CE + PciCfgAddrPort= (priv->NdisAdapter.PciBridgeBusNum << 16)|(priv->NdisAdapter.PciBridgeDevNum<< 11) + |(priv->NdisAdapter.PciBridgeFuncNum << 8)|(1 << 31); + Num4Bytes = (priv->NdisAdapter.PciBridgePCIeHdrOffset+0x10)/4; + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort+(Num4Bytes << 2)); + + uPciBridgeASPMSetting = priv->NdisAdapter.PciBridgeLinkCtrlReg |priv->RegHostPciASPMSetting; + +#ifdef RTL8192SE + if(priv->CustomerID == RT_CID_TOSHIBA && priv->NdisAdapter.PciBridgeVendor == PCI_BRIDGE_VENDOR_AMD + && pPSC->RegAMDPciASPM) + { + if(priv->NdisAdapter.PciBridgeLinkCtrlReg & BIT1) + uPciBridgeASPMSetting |= BIT0; + } + else +#endif + if(priv->NdisAdapter.PciBridgeVendor == PCI_BRIDGE_VENDOR_INTEL ) + uPciBridgeASPMSetting &= ~ BIT0; + + NdisRawWritePortUchar(PCI_CONF_DATA, uPciBridgeASPMSetting); + RT_TRACE(COMP_INIT, "PlatformEnableASPM():PciBridge BusNumber[%x], DevNumbe[%x], FuncNumber[%x], Write reg[%x] = %x\n", + priv->NdisAdapter.PciBridgeBusNum, priv->NdisAdapter.PciBridgeDevNum, priv->NdisAdapter.PciBridgeFuncNum, (priv->NdisAdapter.PciBridgePCIeHdrOffset+0x10), + uPciBridgeASPMSetting); + + udelay(50); +#endif + + ASPMLevel |= priv->RegDevicePciASPMSetting; + uDeviceASPMSetting = priv->NdisAdapter.LinkCtrlReg; + + +#ifdef RTL8192SE + if(priv->CustomerID == RT_CID_TOSHIBA && priv->NdisAdapter.PciBridgeVendor == PCI_BRIDGE_VENDOR_AMD) + { + if(priv->NdisAdapter.LinkCtrlReg & BIT1) + uDeviceASPMSetting |= BIT0; + else + uDeviceASPMSetting |= ASPMLevel; + } + else +#endif + uDeviceASPMSetting |= ASPMLevel; + + PlatformSwitchDevicePciASPM(dev, uDeviceASPMSetting); + + if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_CLK_REQ) { + PlatformSwitchClkReq(dev,(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_CLK_REQ) ? 1 : 0); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_CLK_REQ); + } + udelay(100); + +#ifdef RTL8192SE +#if 0 + pci_write_config_byte(priv->bridge_pdev,priv->PciBridgeASPMRegOffset,\ + ((priv->NdisAdapter.PciBridgeLinkCtrlReg | priv->RegHostPciASPMSetting)&~BIT0)&0xff); + RT_TRACE(COMP_INIT, "Write reg[%x] = %x\n", + priv->PciBridgeASPMRegOffset, + (priv->NdisAdapter.PciBridgeLinkCtrlReg|priv->RegHostPciASPMSetting)); +#else + PciCfgAddrPort= (priv->NdisAdapter.PciBridgeBusNum << 16)|(priv->NdisAdapter.PciBridgeDevNum<< 11)|(priv->NdisAdapter.PciBridgeFuncNum << 8)|(1 << 31); + Num4Bytes = (priv->NdisAdapter.PciBridgePCIeHdrOffset+0x10)/4; + NdisRawWritePortUlong(PCI_CONF_ADDRESS , PciCfgAddrPort+(Num4Bytes << 2)); + + uPciBridgeASPMSetting = priv->NdisAdapter.PciBridgeLinkCtrlReg |priv->RegHostPciASPMSetting; + + if(priv->CustomerID == RT_CID_TOSHIBA && priv->NdisAdapter.PciBridgeVendor == PCI_BRIDGE_VENDOR_AMD + && pPSC->RegAMDPciASPM) + { + if(priv->NdisAdapter.PciBridgeLinkCtrlReg & BIT1) + uPciBridgeASPMSetting |= BIT0; + } + else if(priv->NdisAdapter.PciBridgeVendor == PCI_BRIDGE_VENDOR_INTEL ) + uPciBridgeASPMSetting &= ~ BIT0; + + NdisRawWritePortUchar(PCI_CONF_DATA, uPciBridgeASPMSetting); + RT_TRACE(COMP_INIT, "PlatformEnableASPM():PciBridge BusNumber[%x], DevNumbe[%x], FuncNumber[%x], Write reg[%x] = %x\n", + priv->NdisAdapter.PciBridgeBusNum, priv->NdisAdapter.PciBridgeDevNum, priv->NdisAdapter.PciBridgeFuncNum, (priv->NdisAdapter.PciBridgePCIeHdrOffset+0x10), + uPciBridgeASPMSetting); +#endif +#endif + + udelay(100); +} + +u32 PlatformResetPciSpace(struct net_device *dev,u8 Value) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + pci_write_config_byte(priv->pdev,0x04,Value); + + return 1; + +} +bool PlatformSetPMCSR(struct net_device *dev,u8 value,bool bTempSetting) +{ + bool bResult = false; + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u8 Buffer; + bool bActuallySet=false, bSetFunc=false; + unsigned long flag; + + Buffer= value; + spin_lock_irqsave(&priv->D3_lock,flag); +#ifdef TODO + if(bTempSetting) + { + if(Buffer==0x00) + { + priv->LeaveD3Cnt++; + + { + bActuallySet =true; + } + } + else + { + priv->LeaveD3Cnt--; + + if(priv->LeaveD3Cnt == 0) + { + bActuallySet=true; + } + } + } + else + { + priv->LeaveD3Cnt=0; + bActuallySet=true; + bSetFunc=true; + } +#endif + if (bActuallySet) { + if (Buffer) { + PlatformSwitchClkReq(dev, 0x01); + } else { + PlatformSwitchClkReq(dev, 0x00); + } + + pci_write_config_byte(priv->pdev,0x44,Buffer); + RT_TRACE(COMP_POWER, "PlatformSetPMCSR(): D3(value: %d)\n", Buffer); + + bResult = true; + if (!Buffer) { + PlatformResetPciSpace(dev, 0x06); + PlatformResetPciSpace(dev, 0x07); + } + + if (bSetFunc) { + if(Buffer) + { +#ifdef TO_DO_LIST + RT_DISABLE_FUNC(Adapter, DF_IO_D3_BIT); +#endif + } else { +#ifdef TO_DO_LIST + RT_ENABLE_FUNC(Adapter, DF_IO_D3_BIT); +#endif + } + } + + } + spin_unlock_irqrestore(&priv->D3_lock,flag); + return bResult; +} +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_ps.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl_ps.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + ******************************************************************************/ +#ifndef _RTL_PS_H +#define _RTL_PS_H + +#include +#include "rtllib/rtllib.h" +struct net_device; + +#define RT_CHECK_FOR_HANG_PERIOD 2 +#define INIT_DEFAULT_CHAN 1 + +#if defined CONFIG_ASPM_OR_D3 +#define RT_DISABLE_ASPM(dev) PlatformDisableASPM(dev) +#define RT_ENABLE_ASPM(dev) PlatformEnableASPM(dev) +#define RT_ENTER_D3(dev, _bTempSetting) PlatformSetPMCSR(dev, 0x03, _bTempSetting) +#define RT_LEAVE_D3(dev, _bTempSetting) PlatformSetPMCSR(dev, 0, _bTempSetting) + +#define RT_DISABLE_HOST_L0S(_PADAPTER) PlatformDisableHostL0s(dev) + +void PlatformDisableHostL0s(struct net_device *dev); +bool PlatformEnable92CEBackDoor(struct net_device *dev); +void PlatformDisableASPM(struct net_device *dev); +void PlatformEnableASPM(struct net_device *dev); +u32 PlatformResetPciSpace(struct net_device *dev,u8 Value); +#endif + +#if defined(RTL8192E) || defined(RTL8192SE) || defined RTL8192CE +void rtl8192_hw_wakeup(struct net_device *dev); +void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl); +void rtllib_ips_leave_wq(struct net_device *dev); +void rtllib_ips_leave(struct net_device *dev); +void IPSLeave_wq (void *data); +#endif + +#ifdef ENABLE_IPS +void IPSEnter(struct net_device *dev); +void IPSLeave(struct net_device *dev); +#endif + +#ifdef ENABLE_LPS +void LeisurePSEnter(struct net_device *dev); +void LeisurePSLeave(struct net_device *dev); +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_regd.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_regd.c @@ -0,0 +1,390 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the ath driver, which is: + * Copyright (c) 2008-2009 Atheros Communications Inc. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + ******************************************************************************/ +#ifdef CONFIG_CFG_80211 +#include "rtl_core.h" +#include +#include +#include + +#ifdef CONFIG_CRDA +static struct country_code_to_enum_rd allCountries[] = { + {COUNTRY_CODE_FCC, "US"}, + {COUNTRY_CODE_IC, "US"}, + {COUNTRY_CODE_ETSI, "EC"}, + {COUNTRY_CODE_SPAIN, "EC"}, + {COUNTRY_CODE_FRANCE, "EC"}, + {COUNTRY_CODE_MKK, "JP"}, + {COUNTRY_CODE_MKK1, "JP"}, + {COUNTRY_CODE_ISRAEL, "EC"}, + {COUNTRY_CODE_TELEC, "JP"}, + {COUNTRY_CODE_MIC, "JP"}, + {COUNTRY_CODE_GLOBAL_DOMAIN, "JP"}, + {COUNTRY_CODE_WORLD_WIDE_13, "EC"}, + {COUNTRY_CODE_TELEC_NETGEAR, "EC"}, +}; + +/* Only these channels all allow active scan on all world regulatory domains */ +#define RTL819x_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) + +/* We enable active scan on these a case by case basis by regulatory domain */ +#define RTL819x_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20, NL80211_RRF_PASSIVE_SCAN) +#define RTL819x_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20, NL80211_RRF_PASSIVE_SCAN | \ + NL80211_RRF_NO_OFDM) + +static const struct ieee80211_regdomain rtl_regdom_11 = { + .n_reg_rules = 1, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_global = { + .n_reg_rules = 3, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + RTL819x_2GHZ_CH14, + } +}; + +static const struct ieee80211_regdomain rtl_regdom_world = { + .n_reg_rules = 2, + .alpha2 = "99", + .reg_rules = { + RTL819x_2GHZ_CH01_11, + RTL819x_2GHZ_CH12_13, + } +}; + +static void rtl_reg_apply_chan_plan(struct wiphy *wiphy) +{ + struct net_device *dev = wiphy_to_net_device(wiphy); + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct rtllib_device *rtllib = priv->rtllib; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + int i; + + sband = wiphy->bands[IEEE80211_BAND_2GHZ]; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + if (ch->flags & IEEE80211_CHAN_DISABLED) { + GET_DOT11D_INFO(rtllib)->channel_map[ch->hw_value] = 0; + } else { + if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) { + GET_DOT11D_INFO(rtllib)->channel_map[ch->hw_value] = 2; + } else { + GET_DOT11D_INFO(rtllib)->channel_map[ch->hw_value] = 1; + } + } + + } + + for (i = sband->n_channels - 1; i >= 0; i--) { + ch = &sband->channels[i]; + if (!(ch->flags & IEEE80211_CHAN_NO_IBSS)) { + rtllib->ibss_maxjoin_chal = ch->hw_value; + break; + } + } + + rtllib->IbssStartChnl = 10; + + return; +} + +void rtl_dump_channel_map(struct wiphy *wiphy) +{ + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + struct ieee80211_channel *ch; + unsigned int i; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + + if (!wiphy->bands[band]) + continue; + + sband = wiphy->bands[band]; + + for (i = 0; i < sband->n_channels; i++) { + ch = &sband->channels[i]; + printk("chan:%d, NO_IBSS:%d," + " PASSIVE_SCAN:%d, RADAR:%d, DISABLED:%d\n", i+1, + (ch->flags&IEEE80211_CHAN_NO_IBSS) ? 1:0, + (ch->flags&IEEE80211_CHAN_PASSIVE_SCAN) ? 1:0, + (ch->flags&IEEE80211_CHAN_RADAR) ? 1:0, + (ch->flags&IEEE80211_CHAN_DISABLED) ? 1:0 + ); + } + + } +} + +static void rtl_reg_apply_world_flags(struct wiphy *wiphy, + enum nl80211_reg_initiator initiator, + struct rtl_regulatory *reg) +{ + rtl_reg_apply_chan_plan(wiphy); + return; +} + +int rtl_reg_notifier_apply(struct wiphy *wiphy, + struct regulatory_request *request, + struct rtl_regulatory *reg) +{ + switch (request->initiator) { + case NL80211_REGDOM_SET_BY_CORE: + break; + case NL80211_REGDOM_SET_BY_DRIVER: + case NL80211_REGDOM_SET_BY_USER: + rtl_reg_apply_world_flags(wiphy, request->initiator, reg); + rtl_dump_channel_map(wiphy); + break; + case NL80211_REGDOM_SET_BY_COUNTRY_IE: + rtl_reg_apply_world_flags(wiphy, request->initiator, reg); + rtl_dump_channel_map(wiphy); + break; + } + + return 0; +} + +static const struct +ieee80211_regdomain *rtl_regdomain_select(struct rtl_regulatory *reg) +{ + switch (reg->country_code) { + case COUNTRY_CODE_FCC: + case COUNTRY_CODE_IC: + return &rtl_regdom_11; + case COUNTRY_CODE_ETSI: + case COUNTRY_CODE_SPAIN: + case COUNTRY_CODE_FRANCE: + case COUNTRY_CODE_ISRAEL: + case COUNTRY_CODE_TELEC_NETGEAR: + return &rtl_regdom_world; + case COUNTRY_CODE_MKK: + case COUNTRY_CODE_MKK1: + case COUNTRY_CODE_TELEC: + case COUNTRY_CODE_MIC: + return &rtl_regdom_global; + case COUNTRY_CODE_GLOBAL_DOMAIN: + return &rtl_regdom_global; + case COUNTRY_CODE_WORLD_WIDE_13: + return &rtl_regdom_world; + default: + WARN_ON(1); + return &rtl_regdom_world; + } +} + +static int +rtl_regd_init_wiphy(struct rtl_regulatory *reg, + struct wiphy *wiphy, + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)) +{ + const struct ieee80211_regdomain *regd; + + wiphy->reg_notifier = reg_notifier; + + wiphy->custom_regulatory = true; + wiphy->strict_regulatory = false; + + regd = rtl_regdomain_select(reg); + + wiphy->disable_beacon_hints = true; + wiphy_apply_custom_regulatory(wiphy, regd); + + rtl_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); + return 0; +} + +static struct +country_code_to_enum_rd *rtl_regd_find_country(u16 countryCode) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(allCountries); i++) { + if (allCountries[i].countryCode == countryCode) + return &allCountries[i]; + } + return NULL; +} + +int rtl_regd_init(struct net_device *dev, + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct rtl_regulatory *reg = &priv->rtllib->regulatory; + struct wiphy *wiphy = priv->rtllib->wdev.wiphy; + struct country_code_to_enum_rd *country = NULL; + + if (wiphy == NULL || reg == NULL){ + return -EINVAL; + } + + printk(KERN_DEBUG "rtl: EEPROM regdomain: 0x%0x\n", priv->ChannelPlan); + + reg->country_code = priv->ChannelPlan; + + if (reg->country_code >= COUNTRY_CODE_MAX) { + printk(KERN_DEBUG "rtl: EEPROM indicates invalid contry code" + "world wide 13 should be used\n"); + reg->country_code = COUNTRY_CODE_WORLD_WIDE_13; + } + + country = rtl_regd_find_country(reg->country_code); + + if (country) { + reg->alpha2[0] = country->isoName[0]; + reg->alpha2[1] = country->isoName[1]; + } else { + reg->alpha2[0] = '0'; + reg->alpha2[1] = '0'; + } + + printk(KERN_DEBUG "rtl: Country alpha2 being used: %c%c\n", + reg->alpha2[0], reg->alpha2[1]); + rtl_regd_init_wiphy(reg, wiphy, reg_notifier); + rtl_dump_channel_map(wiphy); + return 0; +} + +int rtl_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request) +{ + struct net_device *dev = wiphy_to_net_device(wiphy); + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct rtl_regulatory *reg = &priv->rtllib->regulatory; + + printk("rtl_regd: %s\n", __func__); + return rtl_reg_notifier_apply(wiphy, request, reg); +} +#endif + +struct net_device *wiphy_to_net_device(struct wiphy *wiphy) +{ + struct rtllib_device *rtllib; + + rtllib = wiphy_priv(wiphy); + return rtllib->dev; +} + +static const struct ieee80211_rate rtl819x_rates[] = { + { .bitrate = 10, .hw_value = 0, }, + { .bitrate = 20, .hw_value = 1, }, + { .bitrate = 55, .hw_value = 2, }, + { .bitrate = 110, .hw_value = 3, }, + { .bitrate = 60, .hw_value = 4, }, + { .bitrate = 90, .hw_value = 5, }, + { .bitrate = 120, .hw_value = 6, }, + { .bitrate = 180, .hw_value = 7, }, + { .bitrate = 240, .hw_value = 8, }, + { .bitrate = 360, .hw_value = 9, }, + { .bitrate = 480, .hw_value = 10, }, + { .bitrate = 540, .hw_value = 11, }, +}; + +#define CHAN2G(_freq, _flags, _idx) { \ + .band = IEEE80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .flags = (_flags), \ + .hw_value = (_idx), \ + .max_power = 20, \ +} + +static struct ieee80211_channel rtl819x_2ghz_chantable[] = { + CHAN2G(2412, 0, 1), /* Channel 1 */ + CHAN2G(2417, 0, 2), /* Channel 2 */ + CHAN2G(2422, 0, 3), /* Channel 3 */ + CHAN2G(2427, 0, 4), /* Channel 4 */ + CHAN2G(2432, 0, 5), /* Channel 5 */ + CHAN2G(2437, 0, 6), /* Channel 6 */ + CHAN2G(2442, 0, 7), /* Channel 7 */ + CHAN2G(2447, 0, 8), /* Channel 8 */ + CHAN2G(2452, 0, 9), /* Channel 9 */ + CHAN2G(2457, 0, 10), /* Channel 10 */ + CHAN2G(2462, 0, 11), /* Channel 11 */ + CHAN2G(2467, IEEE80211_CHAN_NO_IBSS|IEEE80211_CHAN_PASSIVE_SCAN, 12), /* Channel 12 */ + CHAN2G(2472, IEEE80211_CHAN_NO_IBSS|IEEE80211_CHAN_PASSIVE_SCAN, 13), /* Channel 13 */ + CHAN2G(2484, IEEE80211_CHAN_NO_IBSS|IEEE80211_CHAN_PASSIVE_SCAN, 14), /* Channel 14 */ +}; + +int rtllib_set_geo(struct r8192_priv *priv) +{ + priv->bands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; + priv->bands[IEEE80211_BAND_2GHZ].channels = rtl819x_2ghz_chantable; + priv->bands[IEEE80211_BAND_2GHZ].n_channels = ARRAY_SIZE(rtl819x_2ghz_chantable); + + memcpy(&priv->rates[IEEE80211_BAND_2GHZ], rtl819x_rates, sizeof(rtl819x_rates)); + + priv->bands[IEEE80211_BAND_2GHZ].n_bitrates = ARRAY_SIZE(rtl819x_rates); + priv->bands[IEEE80211_BAND_2GHZ].bitrates = priv->rates[IEEE80211_BAND_2GHZ]; + + return 0; +} + +bool rtl8192_register_wiphy_dev(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct wireless_dev *wdev = &priv->rtllib->wdev; +#ifdef CONFIG_CRDA + struct rtl_regulatory *reg; +#endif + memcpy(wdev->wiphy->perm_addr, dev->dev_addr, ETH_ALEN); + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &(priv->bands[IEEE80211_BAND_2GHZ]); + set_wiphy_dev(wdev->wiphy, &priv->pdev->dev); + +#ifdef CONFIG_CRDA + if (rtl_regd_init(dev, rtl_reg_notifier)) { + return false; + } +#endif + + if (wiphy_register(wdev->wiphy)) { + return false; + } + +#ifdef CONFIG_CRDA + reg = &priv->rtllib->regulatory; + if (reg != NULL) { + if (regulatory_hint(wdev->wiphy, reg->alpha2)) { + printk("########>%s() regulatory_hint fail\n", __func__); + ; + } else { + printk("########>#%s() regulatory_hint success\n", __func__); + } + } else { + printk("#########%s() regulator null\n", __func__); + } +#endif + return true; +} +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_regd.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl_regd.h @@ -0,0 +1,53 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the ath driver, which is: + * Copyright (c) 2008-2009 Atheros Communications Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + ******************************************************************************/ +#ifndef RTL_REGD_H +#define RTL_REGD_H + +#ifdef CONFIG_CFG_80211 + +#include +#include +#include "rtl_core.h" + +struct r8192_priv; + +struct country_code_to_enum_rd { + u16 countryCode; + const char *isoName; +}; + + +int rtl_regd_init(struct net_device *dev, + int (*reg_notifier)(struct wiphy *wiphy, + struct regulatory_request *request)); +int rtl_reg_notifier(struct wiphy *wiphy, + struct regulatory_request *request); +void rtl_dump_channel_map(struct wiphy *wiphy); +int rtllib_set_geo(struct r8192_priv *priv); +bool rtl8192_register_wiphy_dev(struct net_device *dev); + +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_rfkill.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_rfkill.c @@ -0,0 +1,221 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae + ******************************************************************************/ +#include "rtl_core.h" +#include "rtl_dm.h" +#include "rtl_rfkill.h" + +#ifdef CONFIG_RTL_RFKILL +static void rtl8192_before_radio_check(struct net_device *dev, + bool *rf_state, + bool *turnonbypowerdomain) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + + *rf_state = (priv->rtllib->eRFPowerState != eRfOn); +#ifdef CONFIG_ASPM_OR_D3 + if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM)) + { + RT_DISABLE_ASPM(dev); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM); + } + else if((pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3)) + { +#ifdef TODO + RT_LEAVE_D3(dev, false); + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3); +#endif + } +#endif + if (RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) { + Power_DomainInit92SE(dev); + *turnonbypowerdomain = true; + } + +} + +static bool rtl8192_radio_on_off_checking(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u8 u1Tmp = 0; + u8 gpio; + + if (priv->pwrdown) { + u1Tmp = read_nic_byte(dev, 0x06); + gpio = u1Tmp & BIT6; + } else +#ifdef CONFIG_BT_COEXIST + if (pHalData->bt_coexist.BluetoothCoexist) { + if (pHalData->bt_coexist.BT_CoexistType == BT_2Wire) { + PlatformEFIOWrite1Byte(pAdapter, MAC_PINMUX_CFG, 0xa); + u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IO_SEL); + delay_us(100); + u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IN); + RTPRINT(FPWR, PWRHW, ("GPIO_IN=%02x\n", u1Tmp)); + retval = (u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? eRfOn : eRfOff; + } else if ((pHalData->bt_coexist.BT_CoexistType == BT_ISSC_3Wire) || + (pHalData->bt_coexist.BT_CoexistType == BT_Accel) || + (pHalData->bt_coexist.BT_CoexistType == BT_CSR)) { + u4tmp = PHY_QueryBBReg(pAdapter, 0x87c, bMaskDWord); + if ((u4tmp & BIT17) != 0) { + PHY_SetBBReg(pAdapter, 0x87c, bMaskDWord, u4tmp & ~BIT17); + delay_us(50); + RTPRINT(FBT, BT_RFPoll, ("BT write 0x87c (~BIT17) = 0x%x\n", u4tmp &~BIT17)); + } + u4tmp = PHY_QueryBBReg(pAdapter, 0x8e0, bMaskDWord); + RTPRINT(FBT, BT_RFPoll, ("BT read 0x8e0 (BIT24)= 0x%x\n", u4tmp)); + retval = (u4tmp & BIT24) ? eRfOn : eRfOff; + RTPRINT(FBT, BT_RFPoll, ("BT check RF state to %s\n", (retval==eRfOn)? "ON":"OFF")); + } + } else +#endif + { + write_nic_byte(dev, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); + u1Tmp = read_nic_byte(dev, GPIO_IO_SEL); + + u1Tmp &= HAL_8192S_HW_GPIO_OFF_MASK; + write_nic_byte(dev, GPIO_IO_SEL, u1Tmp); + + mdelay(10); + + u1Tmp = read_nic_byte(dev, GPIO_IN); + gpio = u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT; + } +#ifdef DEBUG_RFKILL + { + static u8 gpio_test; + printk("%s: gpio = %x\n", __FUNCTION__, gpio); + if(gpio_test % 5 == 0) { + gpio = 0; + } else { + gpio = 1; + } + printk("%s: gpio_test = %d, gpio = %x\n", __FUNCTION__, gpio_test++ % 20, gpio); + } +#endif + + return gpio; +} + +static void rtl8192_after_radio_check(struct net_device *dev, bool rf_state, bool turnonbypowerdomain) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + + if (turnonbypowerdomain) { + PHY_SetRtl8192seRfHalt(dev); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); + } +#ifdef CONFIG_ASPM_OR_D3 + if (!rf_state) { + if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_ASPM) { + RT_ENABLE_ASPM(dev); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_ASPM); + } +#ifdef TODO + else if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_PCI_D3) { + RT_ENTER_D3(dev, false); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_PCI_D3); + } +#endif + } +#endif + return; +} + +static bool rtl8192_is_radio_enabled(struct net_device *dev, bool *radio_enabled) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + bool rf_state = false; + bool turnonbypowerdomain = false; + bool valid; + + rtl8192_before_radio_check(dev, &rf_state, &turnonbypowerdomain); + *radio_enabled = rtl8192_radio_on_off_checking(dev); + rtl8192_after_radio_check(dev, rf_state, turnonbypowerdomain); + if (priv->bResetInProgress) { + priv->RFChangeInProgress = false; + valid = false; + } else { + valid = true; + } + + return valid; +} + +bool rtl8192_rfkill_init(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct wireless_dev *wdev = &priv->rtllib->wdev; + bool radio_enabled; + bool valid = rtl8192_is_radio_enabled(dev, &radio_enabled); + + if (valid) { + priv->rfkill_off = radio_enabled; + printk(KERN_INFO "rtl8192: wireless switch is %s\n", + priv->rfkill_off ? "on" : "off"); + wiphy_rfkill_set_hw_state(wdev->wiphy, !priv->rfkill_off); + wiphy_rfkill_start_polling(wdev->wiphy); + return true; + } else { + return false; + } +} + +void rtl8192_rfkill_poll(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct wireless_dev *wdev = &priv->rtllib->wdev; + bool radio_enabled; + bool valid; + + if (priv->being_init_adapter) { + return; + } + + if (priv->ResetProgress == RESET_TYPE_SILENT) { + RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), + "%s(): silent Reseting, ignore rf polling!\n", __FUNCTION__); + return; + } + + valid = rtl8192_is_radio_enabled(dev, &radio_enabled); + if (valid) { + if (unlikely(radio_enabled != priv->rfkill_off)) { + priv->rfkill_off = radio_enabled; + printk(KERN_INFO "rtl8192: wireless radio switch turned %s\n", + radio_enabled ? "on" : "off"); + wiphy_rfkill_set_hw_state(wdev->wiphy, !radio_enabled); + } + } +} + +void rtl8192_rfkill_exit(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct wireless_dev *wdev = &priv->rtllib->wdev; + + wiphy_rfkill_stop_polling(wdev->wiphy); +} + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_rfkill.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl_rfkill.h @@ -0,0 +1,12 @@ +#ifndef RTL_RFKILL_H +#define RTL_RFKILL_H + +#ifdef CONFIG_RTL_RFKILL +struct net_device; + +bool rtl8192_rfkill_init(struct net_device *dev); +void rtl8192_rfkill_poll(struct net_device *dev); +void rtl8192_rfkill_exit(struct net_device *dev); +#endif + +#endif /* RTL_RFKILL_H */ --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_wx.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl_wx.c @@ -0,0 +1,4376 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + +#include +#include "rtl_core.h" +#ifdef ENABLE_DOT11D +#include "rtllib/dot11d.h" +#endif +#ifdef _RTL8192_EXT_PATCH_ +#include "../../mshclass/msh_class.h" +#endif + +#ifdef CONFIG_MP +#include "r8192S_mp.h" +#endif + +#define RATE_COUNT 12 +u32 rtl8192_rates[] = {1000000,2000000,5500000,11000000, + 6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000}; + + +#ifndef ENETDOWN +#define ENETDOWN 1 +#endif +extern int hwwep; +#ifdef _RTL8192_EXT_PATCH_ +int r8192_wx_set_channel(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +static int r8192_wx_mesh_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +static int r8192_wx_get_mesh_list(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +#endif + +static int r8192_wx_get_freq(struct net_device *dev, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + struct r8192_priv *priv = rtllib_priv(dev); + +#ifdef _RTL8192_EXT_PATCH_ + return rtllib_wx_get_freq(priv->rtllib,a,wrqu,b,0); +#else + return rtllib_wx_get_freq(priv->rtllib,a,wrqu,b); +#endif +} + + +#if 0 + +static int r8192_wx_set_beaconinterval(struct net_device *dev, struct iw_request_info *aa, + union iwreq_data *wrqu, char *b) +{ + int *parms = (int *)b; + int bi = parms[0]; + + struct r8192_priv *priv = rtllib_priv(dev); + + down(&priv->wx_sem); + DMESG("setting beacon interval to %x",bi); + + priv->rtllib->beacon_interval=bi; + rtl8192_commit(dev); + up(&priv->wx_sem); + + return 0; +} + + +static int r8192_wx_set_forceassociate(struct net_device *dev, struct iw_request_info *aa, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv=rtllib_priv(dev); + int *parms = (int *)extra; + + priv->rtllib->force_associate = (parms[0] > 0); + + + return 0; +} + +#endif +static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + struct r8192_priv *priv=rtllib_priv(dev); + + return rtllib_wx_get_mode(priv->rtllib,a,wrqu,b); +} + +static int r8192_wx_get_rate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + return rtllib_wx_get_rate(priv->rtllib,info,wrqu,extra); +} + + + +static int r8192_wx_set_rate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->bHwRadioOff == true) + return 0; + + down(&priv->wx_sem); + + ret = rtllib_wx_set_rate(priv->rtllib,info,wrqu,extra); + + up(&priv->wx_sem); + + return ret; +} + + +static int r8192_wx_set_rts(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->bHwRadioOff == true) + return 0; + + down(&priv->wx_sem); + + ret = rtllib_wx_set_rts(priv->rtllib,info,wrqu,extra); + + up(&priv->wx_sem); + + return ret; +} + +static int r8192_wx_get_rts(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + return rtllib_wx_get_rts(priv->rtllib,info,wrqu,extra); +} + +static int r8192_wx_set_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->bHwRadioOff == true){ + RT_TRACE(COMP_ERR,"%s():Hw is Radio Off, we can't set Power,return\n",__FUNCTION__); + return 0; + } + down(&priv->wx_sem); + + ret = rtllib_wx_set_power(priv->rtllib,info,wrqu,extra); + + up(&priv->wx_sem); + + return ret; +} + +static int r8192_wx_get_power(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + return rtllib_wx_get_power(priv->rtllib,info,wrqu,extra); +} + +static int r8192_wx_set_rawtx(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int ret; + + if(priv->bHwRadioOff == true) + return 0; + + down(&priv->wx_sem); + + ret = rtllib_wx_set_rawtx(priv->rtllib, info, wrqu, extra); + + up(&priv->wx_sem); + + return ret; + +} + +static int r8192_wx_force_reset(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + down(&priv->wx_sem); + + printk("%s(): force reset ! extra is %d\n",__FUNCTION__, *extra); + priv->force_reset = *extra; + up(&priv->wx_sem); + return 0; + +} + +static int r8192_wx_force_mic_error(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + + down(&priv->wx_sem); + + printk("%s(): force mic error ! \n",__FUNCTION__); + ieee->force_mic_error = true; + up(&priv->wx_sem); + return 0; + +} + +#define MAX_ADHOC_PEER_NUM 64 +typedef struct +{ + unsigned char MacAddr[ETH_ALEN]; + unsigned char WirelessMode; + unsigned char bCurTxBW40MHz; +} adhoc_peer_entry_t, *p_adhoc_peer_entry_t; +typedef struct +{ + adhoc_peer_entry_t Entry[MAX_ADHOC_PEER_NUM]; + unsigned char num; +} adhoc_peers_info_t, *p_adhoc_peers_info_t; +int r8192_wx_get_adhoc_peers(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ +#ifndef RTL8192SE + return 0; +#else + struct r8192_priv *priv = rtllib_priv(dev); + struct sta_info * psta = NULL; + adhoc_peers_info_t adhoc_peers_info; + p_adhoc_peers_info_t padhoc_peers_info = &adhoc_peers_info; + p_adhoc_peer_entry_t padhoc_peer_entry = NULL; + int k=0; + + + memset(extra, 0, 2047); + padhoc_peers_info->num = 0; + + down(&priv->wx_sem); + + for(k=0; krtllib->peer_assoc_list[k]; + if(NULL != psta) + { + padhoc_peer_entry = &padhoc_peers_info->Entry[padhoc_peers_info->num]; + memset(padhoc_peer_entry,0, sizeof(adhoc_peer_entry_t)); + memcpy(padhoc_peer_entry->MacAddr, psta->macaddr, ETH_ALEN); + padhoc_peer_entry->WirelessMode = psta->wireless_mode; + padhoc_peer_entry->bCurTxBW40MHz = psta->htinfo.bCurTxBW40MHz; + padhoc_peers_info->num ++; + printk("[%d] MacAddr:"MAC_FMT" \tWirelessMode:%d \tBW40MHz:%d \n", \ + k, MAC_ARG(padhoc_peer_entry->MacAddr), padhoc_peer_entry->WirelessMode, padhoc_peer_entry->bCurTxBW40MHz); + sprintf(extra, "[%d] MacAddr:"MAC_FMT" \tWirelessMode:%d \tBW40MHz:%d \n", \ + k, MAC_ARG(padhoc_peer_entry->MacAddr), padhoc_peer_entry->WirelessMode, padhoc_peer_entry->bCurTxBW40MHz); + } + } + + up(&priv->wx_sem); + + wrqu->data.length = strlen(extra); + wrqu->data.flags = 0; + return 0; + +#endif +} + + +static int r8191se_wx_get_firm_version(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrqu, char *extra) +{ +#if defined RTL8192SE || defined RTL8192CE + struct r8192_priv *priv = rtllib_priv(dev); + u16 firmware_version; + + down(&priv->wx_sem); + printk("%s(): Just Support 92SE tmp\n", __FUNCTION__); +#ifdef RTL8192CE + firmware_version = priv->firmware_version; +#else + firmware_version = priv->pFirmware->FirmwareVersion; +#endif + wrqu->value = firmware_version; + wrqu->fixed = 1; + + up(&priv->wx_sem); +#endif + return 0; +} + +static int r8192_wx_adapter_power_status(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ +#ifdef ENABLE_LPS + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + struct rtllib_device* ieee = priv->rtllib; + + down(&priv->wx_sem); + + RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra == 6)?"DC power":"AC power"); + if(*extra || priv->force_lps) { + priv->ps_force = false; + pPSC->bLeisurePs = true; + } else { + if(priv->rtllib->state == RTLLIB_LINKED) + LeisurePSLeave(dev); + + priv->ps_force = true; + pPSC->bLeisurePs = false; + ieee->ps = *extra; + } + + up(&priv->wx_sem); +#endif + + return 0; + +} + +#ifdef _RTL8192_EXT_PATCH_ +static int r8192_wx_print_reg(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + u8 reg1=0,reg2=0,reg3=0,reg4=0; + u32 reg5 = 0, len = 0; + + memset(extra, 0, 512); + sprintf(extra,"\nStart Log: Set 0x08000000 to 0x230\n"); + write_nic_dword(dev, 0x230 , 0x08000000); + reg1 = read_nic_byte(dev, 0xf0); + reg2 = read_nic_byte(dev, 0xf4); + reg3 = read_nic_byte(dev, 0x140); + reg4 = read_nic_byte(dev, 0x124); + mdelay(10); + reg5 = read_nic_dword(dev, 0x230); + len = strlen(extra); + sprintf(extra+len, "0xf0: %2.2x\n0xf4: %2.2x\n0x140: %2.2x\n0x124: %2.2x\n", reg1,reg2,reg3,reg4); + len = strlen(extra); + sprintf(extra+len,"After delay 10ms, read 0x230: %8.8x\n", reg5); + + write_nic_dword(dev, 0x230 , 0x40000000); + reg5 = read_nic_dword(dev, 0x230); + len = strlen(extra); + sprintf(extra+len,"Set 0x40000000 to 0x230. Read 0x230: %8.8x\n", reg5); + + write_nic_dword(dev, 0x230 , 0x80000000); + reg5 = read_nic_dword(dev, 0x230); + len = strlen(extra); + sprintf(extra+len,"Set 0x80000000 to 0x230. Read 0x230: %8.8x\n", reg5); + + wrqu->data.length = strlen(extra); + return 0; +} + +static int r8192_wx_resume_firm(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + write_nic_byte(dev, 0x42, 0xFF); + write_nic_word(dev, 0x40, 0x77FC); + write_nic_word(dev, 0x40, 0x57FC); + write_nic_word(dev, 0x40, 0x37FC); + write_nic_word(dev, 0x40, 0x77FC); + + udelay(100); + + write_nic_word(dev, 0x40, 0x57FC); + write_nic_word(dev, 0x40, 0x37FC); + write_nic_byte(dev, 0x42, 0x00); + + return 0; +} +#endif +static int r8192se_wx_set_radio(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + down(&priv->wx_sem); + + printk("%s(): set radio ! extra is %d\n",__FUNCTION__, *extra); + if((*extra != 0) && (*extra != 1)) + { + RT_TRACE(COMP_ERR, "%s(): set radio an err value,must 0(radio off) or 1(radio on)\n",__FUNCTION__); + return -1; + } + priv->sw_radio_on = *extra; + up(&priv->wx_sem); + return 0; + +} + +static int r8192se_wx_set_lps_awake_interval(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + + down(&priv->wx_sem); + + printk("%s(): set lps awake interval ! extra is %d\n",__FUNCTION__, *extra); + + pPSC->RegMaxLPSAwakeIntvl = *extra; + up(&priv->wx_sem); + return 0; + +} + +static int r8192se_wx_set_force_lps(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + down(&priv->wx_sem); + + printk("%s(): force LPS ! extra is %d (1 is open 0 is close)\n",__FUNCTION__, *extra); + priv->force_lps = *extra; + up(&priv->wx_sem); + return 0; + +} + +#ifdef _RTL8192_EXT_PATCH_ +static int r8192_wx_get_drv_version(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + memset(extra, 0, 64); + sprintf(extra, "Support Mesh"); + + ((struct iw_point *)wrqu)->length = strlen(extra); + return 0; +} +#endif + +static int r8192_wx_set_debugflag(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 c = *extra; + + if(priv->bHwRadioOff == true) + return 0; + + printk("=====>%s(), *extra:%x, debugflag:%x\n", __FUNCTION__, *extra, rt_global_debug_component); + if (c > 0) { + rt_global_debug_component |= (1<bHwRadioOff == true) + return 0; +#ifdef _RTL8192_EXT_PATCH_ + if (priv->mshobj && (priv->rtllib->iw_mode==IW_MODE_MESH)) { + return 0; + } +#endif + rtState = priv->rtllib->eRFPowerState; + down(&priv->wx_sem); +#ifdef ENABLE_IPS + if(wrqu->mode == IW_MODE_ADHOC || wrqu->mode == IW_MODE_MONITOR + || ieee->bNetPromiscuousMode ) + { + if(priv->rtllib->PowerSaveControl.bInactivePs){ + if(rtState == eRfOff){ + if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) + { + RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__); + up(&priv->wx_sem); + return -1; + } else { + printk("=========>%s(): IPSLeave\n",__FUNCTION__); + down(&priv->rtllib->ips_sem); + IPSLeave(dev); + up(&priv->rtllib->ips_sem); + } + } + } + } +#endif + ret = rtllib_wx_set_mode(priv->rtllib,a,wrqu,b); + + up(&priv->wx_sem); + return ret; +} +#if defined (RTL8192S_WAPI_SUPPORT) +int wapi_ioctl_set_mode(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + struct r8192_priv *priv = rtllib_priv(dev); + RT_RF_POWER_STATE rtState; + int ret; + + printk("===============================>%s\n", __FUNCTION__); + if(priv->bHwRadioOff == true) + return 0; +#ifdef _RTL8192_EXT_PATCH_ + if (priv->mshobj && (priv->rtllib->iw_mode==IW_MODE_MESH)) { + return 0; + } +#endif + rtState = priv->rtllib->eRFPowerState; +#ifdef ENABLE_IPS + if(wrqu->mode == IW_MODE_ADHOC){ + if(priv->rtllib->PowerSaveControl.bInactivePs){ + if(rtState == eRfOff){ + if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) + { + RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__); + up(&priv->wx_sem); + return -1; + } else { + printk("=========>%s(): IPSLeave\n",__FUNCTION__); + down(&priv->rtllib->ips_sem); + IPSLeave(dev); + up(&priv->rtllib->ips_sem); + } + } + } + } +#endif + ret = rtllib_wx_set_mode(priv->rtllib,a,wrqu,b); + + return ret; +} +#endif +struct iw_range_with_scan_capa +{ + /* Informative stuff (to choose between different interface) */ + __u32 throughput; /* To give an idea... */ + /* In theory this value should be the maximum benchmarked + * TCP/IP throughput, because with most of these devices the + * bit rate is meaningless (overhead an co) to estimate how + * fast the connection will go and pick the fastest one. + * I suggest people to play with Netperf or any benchmark... + */ + + /* NWID (or domain id) */ + __u32 min_nwid; /* Minimal NWID we are able to set */ + __u32 max_nwid; /* Maximal NWID we are able to set */ + + /* Old Frequency (backward compat - moved lower ) */ + __u16 old_num_channels; + __u8 old_num_frequency; + + /* Scan capabilities */ + __u8 scan_capa; +}; + +static int rtl8192_wx_get_range(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct iw_range *range = (struct iw_range *)extra; + struct r8192_priv *priv = rtllib_priv(dev); + u16 val; + int i; + + wrqu->data.length = sizeof(*range); + memset(range, 0, sizeof(*range)); + + /* ~130 Mb/s real (802.11n) */ + range->throughput = 130 * 1000 * 1000; + + if(priv->rf_set_sens != NULL) + range->sensitivity = priv->max_sens; /* signal level threshold range */ + + range->max_qual.qual = 100; + range->max_qual.level = 0; + range->max_qual.noise = 0; + range->max_qual.updated = 7; /* Updated all three */ + + range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */ + range->avg_qual.level = 0; + range->avg_qual.noise = 0; + range->avg_qual.updated = 7; /* Updated all three */ + + range->num_bitrates = min(RATE_COUNT, IW_MAX_BITRATES); + + for (i = 0; i < range->num_bitrates; i++) { + range->bitrate[i] = rtl8192_rates[i]; + } + + range->max_rts = DEFAULT_RTS_THRESHOLD; + range->min_frag = MIN_FRAG_THRESHOLD; + range->max_frag = MAX_FRAG_THRESHOLD; + + range->min_pmp = 0; + range->max_pmp = 5000000; + range->min_pmt = 0; + range->max_pmt = 65535*1000; + range->pmp_flags = IW_POWER_PERIOD; + range->pmt_flags = IW_POWER_TIMEOUT; + range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; + range->we_version_compiled = WIRELESS_EXT; + range->we_version_source = 18; + + for (i = 0, val = 0; i < 14; i++) { + if ((priv->rtllib->active_channel_map)[i+1]) { + range->freq[val].i = i + 1; + range->freq[val].m = rtllib_wlan_frequencies[i] * 100000; + range->freq[val].e = 1; + val++; + } else { + } + + if (val == IW_MAX_FREQUENCIES) + break; + } + range->num_frequency = val; + range->num_channels = val; +#if WIRELESS_EXT > 17 + range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2| + IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP; +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) + { + struct iw_range_with_scan_capa* tmp = (struct iw_range_with_scan_capa*)range; + tmp->scan_capa = 0x01; + } +#else + range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE; +#endif + + /* Event capability (kernel + driver) */ + + return 0; +} + +static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + RT_RF_POWER_STATE rtState; + int ret; + +#ifdef CONFIG_MP + printk("######################%s(): In MP Test Can not Scan\n",__FUNCTION__); + return 0; +#endif + if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)){ + if((ieee->state >= RTLLIB_ASSOCIATING) && (ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED)){ + return 0; + } + if((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->CntAfterLink<2)){ + return 0; + } + } + + if(priv->bHwRadioOff == true){ + printk("================>%s(): hwradio off\n",__FUNCTION__); + return 0; + } + rtState = priv->rtllib->eRFPowerState; + if(!priv->up) return -ENETDOWN; + if (priv->rtllib->LinkDetectInfo.bBusyTraffic == true) + return -EAGAIN; + +#ifdef _RTL8192_EXT_PATCH_ + if((ieee->iw_mode == IW_MODE_MESH)&&(ieee->mesh_state == RTLLIB_MESH_LINKED)) + { + return 0; + } +#endif +#if WIRELESS_EXT > 17 + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) + { + struct iw_scan_req* req = (struct iw_scan_req*)b; + if (req->essid_len) + { + ieee->current_network.ssid_len = req->essid_len; + memcpy(ieee->current_network.ssid, req->essid, req->essid_len); + } + } +#endif + + down(&priv->wx_sem); + + priv->rtllib->FirstIe_InScan = true; + + if(priv->rtllib->state != RTLLIB_LINKED){ +#ifdef ENABLE_IPS + if(priv->rtllib->PowerSaveControl.bInactivePs){ + if(rtState == eRfOff){ + if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS){ + RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__); + up(&priv->wx_sem); + return -1; + }else{ + RT_TRACE(COMP_PS, "=========>%s(): IPSLeave\n",__FUNCTION__); + down(&priv->rtllib->ips_sem); + IPSLeave(dev); + up(&priv->rtllib->ips_sem); + } + } + } +#endif + rtllib_stop_scan(priv->rtllib); + if(priv->rtllib->LedControlHandler) + priv->rtllib->LedControlHandler(dev, LED_CTL_SITE_SURVEY); + + if(priv->rtllib->eRFPowerState != eRfOff){ + priv->rtllib->actscanning = true; + + if(ieee->ScanOperationBackupHandler) + ieee->ScanOperationBackupHandler(ieee->dev,SCAN_OPT_BACKUP); + + rtllib_start_scan_syncro(priv->rtllib, 0); + + if(ieee->ScanOperationBackupHandler) + ieee->ScanOperationBackupHandler(ieee->dev,SCAN_OPT_RESTORE); + } + ret = 0; + } else { + priv->rtllib->actscanning = true; + ret = rtllib_wx_set_scan(priv->rtllib,a,wrqu,b); + } + + up(&priv->wx_sem); + return ret; +} + + +static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + + int ret; + struct r8192_priv *priv = rtllib_priv(dev); + + if(!priv->up) return -ENETDOWN; + + if(priv->bHwRadioOff == true) + return 0; + + + down(&priv->wx_sem); + + ret = rtllib_wx_get_scan(priv->rtllib,a,wrqu,b); + + up(&priv->wx_sem); + + return ret; +} + +static int r8192_wx_set_essid(struct net_device *dev, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int ret; + + if ((rtllib_act_scanning(priv->rtllib, false)) && !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){ + ; + } +#ifdef CONFIG_MP + printk("######################%s(): In MP Test Can not Set Essid\n",__FUNCTION__); + return 0; +#endif + if(priv->bHwRadioOff == true){ + printk("=========>%s():hw radio off,or Rf state is eRfOff, return\n",__FUNCTION__); + return 0; + } + down(&priv->wx_sem); + ret = rtllib_wx_set_essid(priv->rtllib,a,wrqu,b); + + up(&priv->wx_sem); + + return ret; +} + +static int r8192_wx_get_essid(struct net_device *dev, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + int ret; + struct r8192_priv *priv = rtllib_priv(dev); + + down(&priv->wx_sem); + + ret = rtllib_wx_get_essid(priv->rtllib, a, wrqu, b); + + up(&priv->wx_sem); + + return ret; +} + +static int r8192_wx_set_nick(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if (wrqu->data.length > IW_ESSID_MAX_SIZE) + return -E2BIG; + down(&priv->wx_sem); + wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick)); + memset(priv->nick, 0, sizeof(priv->nick)); + memcpy(priv->nick, extra, wrqu->data.length); + up(&priv->wx_sem); + return 0; + +} + +static int r8192_wx_get_nick(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + down(&priv->wx_sem); + wrqu->data.length = strlen(priv->nick); + memcpy(extra, priv->nick, wrqu->data.length); + wrqu->data.flags = 1; /* active */ + up(&priv->wx_sem); + return 0; +} + +static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + int ret; + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->bHwRadioOff == true) + return 0; + + down(&priv->wx_sem); + + ret = rtllib_wx_set_freq(priv->rtllib, a, wrqu, b); + + up(&priv->wx_sem); + return ret; +} + +static int r8192_wx_get_name(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + return rtllib_wx_get_name(priv->rtllib, info, wrqu, extra); +} + + +static int r8192_wx_set_frag(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->bHwRadioOff == true) + return 0; + + if (wrqu->frag.disabled) + priv->rtllib->fts = DEFAULT_FRAG_THRESHOLD; + else { + if (wrqu->frag.value < MIN_FRAG_THRESHOLD || + wrqu->frag.value > MAX_FRAG_THRESHOLD) + return -EINVAL; + + priv->rtllib->fts = wrqu->frag.value & ~0x1; + } + + return 0; +} + + +static int r8192_wx_get_frag(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + wrqu->frag.value = priv->rtllib->fts; + wrqu->frag.fixed = 0; /* no auto select */ + wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); + + return 0; +} + + +static int r8192_wx_set_wap(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *awrq, + char *extra) +{ + + int ret; + struct r8192_priv *priv = rtllib_priv(dev); + + if ((rtllib_act_scanning(priv->rtllib, false)) && !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){ + ; + } + + if(priv->bHwRadioOff == true) + return 0; + +#ifdef _RTL8192_EXT_PATCH_ + if (priv->mshobj && (priv->rtllib->iw_mode==IW_MODE_MESH)){ + return 0; + } +#endif + down(&priv->wx_sem); + + ret = rtllib_wx_set_wap(priv->rtllib,info,awrq,extra); + + up(&priv->wx_sem); + + return ret; + +} + + +static int r8192_wx_get_wap(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + return rtllib_wx_get_wap(priv->rtllib,info,wrqu,extra); +} + + +static int r8192_wx_get_enc(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key) +{ + struct r8192_priv *priv = rtllib_priv(dev); + +#ifdef _RTL8192_EXT_PATCH_ + return rtllib_wx_get_encode(priv->rtllib, info, wrqu, key,0); +#else + return rtllib_wx_get_encode(priv->rtllib, info, wrqu, key); +#endif +} + +static int r8192_wx_set_enc(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int ret; + + struct rtllib_device *ieee = priv->rtllib; + u32 hwkey[4]={0,0,0,0}; + u8 mask=0xff; + u32 key_idx=0; + u8 zero_addr[4][6] ={ {0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x01}, + {0x00,0x00,0x00,0x00,0x00,0x02}, + {0x00,0x00,0x00,0x00,0x00,0x03} }; + int i; + + if ((rtllib_act_scanning(priv->rtllib, false)) && !(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){ + ; + } +#ifdef CONFIG_MP + printk("######################%s(): In MP Test Can not Set Enc\n",__FUNCTION__); + return 0; +#endif + if(priv->bHwRadioOff == true) + return 0; + + if(!priv->up) return -ENETDOWN; + + priv->rtllib->wx_set_enc = 1; +#ifdef ENABLE_IPS + down(&priv->rtllib->ips_sem); + IPSLeave(dev); + up(&priv->rtllib->ips_sem); +#endif + down(&priv->wx_sem); + + RT_TRACE(COMP_SEC, "Setting SW wep key"); +#ifdef _RTL8192_EXT_PATCH_ + ret = rtllib_wx_set_encode(priv->rtllib,info,wrqu,key,0); +#else + ret = rtllib_wx_set_encode(priv->rtllib,info,wrqu,key); +#endif + up(&priv->wx_sem); + + + if (wrqu->encoding.flags & IW_ENCODE_DISABLED) { + ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA; + CamResetAllEntry(dev); +#ifdef _RTL8192_EXT_PATCH_ + CamRestoreEachIFEntry(dev,1); + reset_IFswcam(dev,0); + priv->rtllib->wx_set_enc = 0; +#else + memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32); +#endif + goto end_hw_sec; + } + if(wrqu->encoding.length!=0){ + + for(i=0 ; i<4 ; i++){ + hwkey[i] |= key[4*i+0]&mask; + if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00; + if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00; + hwkey[i] |= (key[4*i+1]&mask)<<8; + hwkey[i] |= (key[4*i+2]&mask)<<16; + hwkey[i] |= (key[4*i+3]&mask)<<24; + } + + #define CONF_WEP40 0x4 + #define CONF_WEP104 0x14 + + switch(wrqu->encoding.flags & IW_ENCODE_INDEX){ + case 0: key_idx = ieee->tx_keyidx; break; + case 1: key_idx = 0; break; + case 2: key_idx = 1; break; + case 3: key_idx = 2; break; + case 4: key_idx = 3; break; + default: break; + } + if(wrqu->encoding.length==0x5){ + ieee->pairwise_key_type = KEY_TYPE_WEP40; + EnableHWSecurityConfig8192(dev); +#ifndef _RTL8192_EXT_PATCH_ + setKey( dev, + key_idx, + key_idx, + KEY_TYPE_WEP40, + zero_addr[key_idx], + 0, + hwkey); + + set_swcam( dev, + key_idx, + key_idx, + KEY_TYPE_WEP40, + zero_addr[key_idx], + 0, + hwkey, + 0); + +#endif + } + + else if(wrqu->encoding.length==0xd){ + ieee->pairwise_key_type = KEY_TYPE_WEP104; + EnableHWSecurityConfig8192(dev); +#ifndef _RTL8192_EXT_PATCH_ + setKey( dev, + key_idx, + key_idx, + KEY_TYPE_WEP104, + zero_addr[key_idx], + 0, + hwkey); + set_swcam( dev, + key_idx, + key_idx, + KEY_TYPE_WEP104, + zero_addr[key_idx], + 0, + hwkey, + 0); +#endif + } + else printk("wrong type in WEP, not WEP40 and WEP104\n"); +#ifdef _RTL8192_EXT_PATCH_ + if(ieee->state == RTLLIB_LINKED){ + if(ieee->iw_mode == IW_MODE_ADHOC) + { + + setKey( dev, + key_idx, + key_idx, + ieee->pairwise_key_type, + zero_addr[key_idx], + 0, + hwkey); + set_swcam( dev, + key_idx, + key_idx, + ieee->pairwise_key_type, + zero_addr[key_idx], + 0, + hwkey, + 0); + } + else{ + setKey( dev, + 31, + key_idx, + ieee->pairwise_key_type, + ieee->ap_mac_addr, + 0, + hwkey); + set_swcam( dev, + 31, + key_idx, + ieee->pairwise_key_type, + ieee->ap_mac_addr, + 0, + hwkey, + 0); + } + } +#endif + } + +#if 0 + if(wrqu->encoding.length==0 && (wrqu->encoding.flags >>8) == 0x8 ){ + printk("===>1\n"); + EnableHWSecurityConfig8192(dev); + key_idx = (wrqu->encoding.flags & 0xf)-1 ; + write_cam(dev, (4*6), 0xffff0000|read_cam(dev, key_idx*6) ); + write_cam(dev, (4*6)+1, 0xffffffff); + write_cam(dev, (4*6)+2, read_cam(dev, (key_idx*6)+2) ); + write_cam(dev, (4*6)+3, read_cam(dev, (key_idx*6)+3) ); + write_cam(dev, (4*6)+4, read_cam(dev, (key_idx*6)+4) ); + write_cam(dev, (4*6)+5, read_cam(dev, (key_idx*6)+5) ); + } +#endif +#ifdef _RTL8192_EXT_PATCH_ + priv->rtllib->wx_set_enc = 0; + printk("===================>%s():set ieee->wx_set_enc 0\n",__FUNCTION__); +end_hw_sec: +#else +end_hw_sec: + priv->rtllib->wx_set_enc = 0; +#endif + return ret; +} + + +static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union + iwreq_data *wrqu, char *p){ + + struct r8192_priv *priv = rtllib_priv(dev); + int *parms=(int*)p; + int mode=parms[0]; + + if(priv->bHwRadioOff == true) + return 0; + + priv->rtllib->active_scan = mode; + + return 1; +} + + + +#define R8192_MAX_RETRY 255 +static int r8192_wx_set_retry(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int err = 0; + + if(priv->bHwRadioOff == true) + return 0; + + down(&priv->wx_sem); + + if (wrqu->retry.flags & IW_RETRY_LIFETIME || + wrqu->retry.disabled){ + err = -EINVAL; + goto exit; + } + if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){ + err = -EINVAL; + goto exit; + } + + if(wrqu->retry.value > R8192_MAX_RETRY){ + err= -EINVAL; + goto exit; + } + if (wrqu->retry.flags & IW_RETRY_MAX) { + priv->retry_rts = wrqu->retry.value; + DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value); + + }else { + priv->retry_data = wrqu->retry.value; + DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value); + } + + + rtl8192_commit(dev); + /* + if(priv->up){ + rtl8180_halt_adapter(dev); + rtl8180_rx_enable(dev); + rtl8180_tx_enable(dev); + + } + */ +exit: + up(&priv->wx_sem); + + return err; +} + +static int r8192_wx_get_retry(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + + wrqu->retry.disabled = 0; /* can't be disabled */ + + if ((wrqu->retry.flags & IW_RETRY_TYPE) == + IW_RETRY_LIFETIME) + return -EINVAL; + + if (wrqu->retry.flags & IW_RETRY_MAX) { + wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX; + wrqu->retry.value = priv->retry_rts; + } else { + wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN; + wrqu->retry.value = priv->retry_data; + } + + + return 0; +} + +static int r8192_wx_get_sens(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + if(priv->rf_set_sens == NULL) + return -1; /* we have not this support for this radio */ + wrqu->sens.value = priv->sens; + return 0; +} + + +static int r8192_wx_set_sens(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + struct r8192_priv *priv = rtllib_priv(dev); + + short err = 0; + + if(priv->bHwRadioOff == true) + return 0; + + down(&priv->wx_sem); + if(priv->rf_set_sens == NULL) { + err= -1; /* we have not this support for this radio */ + goto exit; + } + if(priv->rf_set_sens(dev, wrqu->sens.value) == 0) + priv->sens = wrqu->sens.value; + else + err= -EINVAL; + +exit: + up(&priv->wx_sem); + + return err; +} + +#if (WIRELESS_EXT >= 18) +#if 0 +static int r8192_wx_get_enc_ext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int ret = 0; +#ifdef _RTL8192_EXT_PATCH_ + ret = rtllib_wx_get_encode_ext(priv->rtllib, info, wrqu, extra,0); +#else + ret = rtllib_wx_get_encode_ext(priv->rtllib, info, wrqu, extra); +#endif + return ret; +} +#endif + +#ifdef _RTL8192_EXT_PATCH_ +static int meshdev_set_key_for_linked_peers(struct net_device *dev, u8 KeyIndex,u16 KeyType, u32 *KeyContent ); +static int r8192_set_hw_enc(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra, u8 is_mesh) +{ + int ret=0; + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + u32 key[4] = {0}; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + struct iw_point *encoding = &wrqu->encoding; + u8 idx = 0, alg = 0, group = 0; + u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + u8 zero[6] = {0}; + priv->rtllib->wx_set_enc = 1; +#ifdef ENABLE_IPS + down(&priv->rtllib->ips_sem); + IPSLeave(dev); + up(&priv->rtllib->ips_sem); +#endif +#if 0 + static u8 CAM_CONST_ADDR[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}}; +#endif + if ((encoding->flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE) + { + if(is_mesh) + ieee->mesh_pairwise_key_type = ieee->mesh_pairwise_key_type = KEY_TYPE_NA; + else + ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA; + CamResetAllEntry(dev); + if(is_mesh) + CamRestoreEachIFEntry(dev,0); + else + CamRestoreEachIFEntry(dev,1); + reset_IFswcam(dev,is_mesh); + goto end_hw_sec; + } + alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) + idx --; + group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; + printk("====>group is %x\n",group); + if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40) || (IW_MODE_MESH == ieee->iw_mode)) + { + if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) ) + alg = KEY_TYPE_WEP104; + if(is_mesh) + ieee->mesh_pairwise_key_type = alg; + else + ieee->pairwise_key_type = alg; + EnableHWSecurityConfig8192(dev); + } + memcpy((u8*)key, ext->key, 16); + if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) ) + { + printk("=====>set WEP key\n"); + if (ext->key_len == 13){ + if(is_mesh) + ieee->mesh_pairwise_key_type = alg = KEY_TYPE_WEP104; + else + ieee->pairwise_key_type = alg = KEY_TYPE_WEP104; + } + if(ieee->iw_mode == IW_MODE_ADHOC){ + set_swcam( dev, + idx, + idx, + alg, + zero, + 0, + key, + is_mesh); + setKey( dev, + idx, + idx, + alg, + zero, + 0, + key); + } + + if(!is_mesh){ + if(ieee->state == RTLLIB_LINKED){ + setKey( dev, + 31, + idx, + ieee->pairwise_key_type, + ieee->ap_mac_addr, + 0, + key); + set_swcam( dev, + 31, + idx, + ieee->pairwise_key_type, + ieee->ap_mac_addr, + 0, + key, + 0); + } + } + } + else if (group) + { + printk("set group key\n"); + if(is_mesh) + ieee->mesh_group_key_type = alg; + else + ieee->group_key_type = alg; + if(ieee->iw_mode == IW_MODE_ADHOC){ + set_swcam( dev, + idx, + idx, + alg, + broadcast_addr, + 0, + key, + is_mesh); + setKey( dev, + idx, + idx, + alg, + broadcast_addr, + 0, + key); + } + + if(is_mesh) + meshdev_set_key_for_linked_peers(dev, + idx, + alg, + key); + } + else + { + printk("=============>set pairwise key\n"); +#ifdef RTL8192E + if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){ + write_nic_byte(dev, 0x173, 1); + } +#endif + set_swcam( dev, + 31, + idx, + alg, + (u8*)ieee->ap_mac_addr, + 0, + key, + is_mesh); + setKey( dev, + 31, + idx, + alg, + (u8*)ieee->ap_mac_addr, + 0, + key); + } + +end_hw_sec: + priv->rtllib->wx_set_enc = 0; + return ret; +} + +int rtl8192_set_key_for_AP(struct rtllib_device *ieee) +{ + struct rtllib_crypt_data **crypt; + int key_len=0; + char key[32]; + u16 keytype = IW_ENCODE_ALG_NONE; +#ifdef _RTL8192_EXT_PATCH_ + crypt = &ieee->sta_crypt[ieee->tx_keyidx]; +#else + crypt = &ieee->crypt[ieee->tx_keyidx]; +#endif + if (*crypt == NULL || (*crypt)->ops == NULL) + { + printk("%s():no encrypt now\n",__FUNCTION__); + return 0; + } + if (!((*crypt)->ops->set_key && (*crypt)->ops->get_key)) + return -1; + + key_len = (*crypt)->ops->get_key(key, 32, NULL, (*crypt)->priv); + if (strcmp((*crypt)->ops->name, "WEP") == 0 ) + { + if(key_len == 5) + keytype = KEY_TYPE_WEP40; + else + keytype = KEY_TYPE_WEP104; + } + else if (strcmp((*crypt)->ops->name, "TKIP") == 0) + return 0; + else if (strcmp((*crypt)->ops->name, "CCMP") == 0) + return 0; + + set_swcam( ieee->dev, + 31, + ieee->tx_keyidx, + keytype, + ieee->ap_mac_addr, + 0, + (u32 *)key , + 0); + setKey( ieee->dev, + 31, + ieee->tx_keyidx, + keytype, + ieee->ap_mac_addr, + 0, + (u32 *)key); + + + return 0; +} + +static int r8192_wx_set_enc_ext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret=0; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + + if(priv->bHwRadioOff == true) + return 0; + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra, 0); + + ret |= r8192_set_hw_enc(dev,info,wrqu,extra, 0); + SEM_UP_PRIV_WX(&priv->wx_sem); +#endif + + return ret; +} +/* + * set key for mesh, not a wireless extension handler. + * place it here because of porting from r8192_wx_set_enc_ext(). + */ +int r8192_mesh_set_enc_ext(struct net_device *dev, + struct iw_point *encoding, struct iw_encode_ext *ext, u8 *addr) +{ + int ret=0; + int i=0; + u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + u8 entry_idx = 0; + down(&priv->wx_sem); + if(memcmp(addr,broadcast_addr,6)) + { + if ((i=rtllib_find_MP(ieee, addr, 0)) < 0) + { + i = rtllib_find_MP(ieee, addr, 1); + if (i<0) + return -1; + } + } + ret = rtllib_mesh_set_encode_ext(ieee, encoding, ext, i); + if ((-EINVAL == ret) || (-ENOMEM == ret)) { + goto end_hw_sec; + } + { +#if 0 + u8 zero[6] = {0}; +#endif + u32 key[4] = {0}; + u8 idx = 0, alg = 0, group = 0; + if ((encoding->flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE) + { + CamResetAllEntry(dev); + CamRestoreEachIFEntry(dev,0); + reset_IFswcam(dev,1); + goto end_hw_sec; + } + alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) + idx --; + group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; + + if (!group) + { + ieee->mesh_pairwise_key_type = alg; + EnableHWSecurityConfig8192(dev); + } + + memcpy((u8*)key, ext->key, 16); + + if(group) + { + ieee->mesh_group_key_type = alg; +#if 0 + setKey( dev, + idx, + idx, + alg, + broadcast_addr, + 0, + key); +#endif + } + else + { +#if 0 + if ((ieee->mesh_pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){ + write_nic_byte(dev, 0x173, 1); + } +#endif + entry_idx = rtl8192_get_free_hwsec_cam_entry(ieee,addr); +#if 0 + printk("%s(): Can't find free hw security cam entry\n",__FUNCTION__); + ret = -1; +#else + if (entry_idx >= TOTAL_CAM_ENTRY-1) { + printk("%s(): Can't find free hw security cam entry\n",__FUNCTION__); + ret = -1; + } else { + set_swcam( dev, + entry_idx, + idx, + alg, + (u8*)addr, + 0, + key, + 1); + setKey( dev, + entry_idx, + idx, + alg, + (u8*)addr, + 0, + key); + ret = 0; + } +#endif + } + + + } + +end_hw_sec: + up(&priv->wx_sem); +#endif + return ret; + +} +#else +static int r8192_wx_set_enc_ext(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret=0; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + + if(priv->bHwRadioOff == true) + return 0; + + down(&priv->wx_sem); + + priv->rtllib->wx_set_enc = 1; +#ifdef ENABLE_IPS + down(&priv->rtllib->ips_sem); + IPSLeave(dev); + up(&priv->rtllib->ips_sem); +#endif + + ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra); + + { + u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + u8 zero[6] = {0}; + u32 key[4] = {0}; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + struct iw_point *encoding = &wrqu->encoding; +#if 0 + static u8 CAM_CONST_ADDR[4][6] = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}}; +#endif + u8 idx = 0, alg = 0, group = 0; + if ((encoding->flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE) + { + ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA; + CamResetAllEntry(dev); + memset(priv->rtllib->swcamtable,0,sizeof(SW_CAM_TABLE)*32); + goto end_hw_sec; + } + alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) + idx --; + group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; + + if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40)) + { + if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) ) + alg = KEY_TYPE_WEP104; + ieee->pairwise_key_type = alg; + EnableHWSecurityConfig8192(dev); + } + memcpy((u8*)key, ext->key, 16); + + if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) ) + { + if (ext->key_len == 13) + ieee->pairwise_key_type = alg = KEY_TYPE_WEP104; + setKey( dev, + idx, + idx, + alg, + zero, + 0, + key); + set_swcam( dev, + idx, + idx, + alg, + zero, + 0, + key, + 0); + } + else if (group) + { + ieee->group_key_type = alg; + setKey( dev, + idx, + idx, + alg, + broadcast_addr, + 0, + key); + set_swcam( dev, + idx, + idx, + alg, + broadcast_addr, + 0, + key, + 0); + } + else + { + #ifdef RTL8192E + if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){ + write_nic_byte(dev, 0x173, 1); + } + #endif + setKey( dev, + 4, + idx, + alg, + (u8*)ieee->ap_mac_addr, + 0, + key); + set_swcam( dev, + 4, + idx, + alg, + (u8*)ieee->ap_mac_addr, + 0, + key, + 0); + } + + + } + +end_hw_sec: + priv->rtllib->wx_set_enc = 0; + up(&priv->wx_sem); +#endif + return ret; + +} +#endif +static int r8192_wx_set_auth(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + int ret=0; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->bHwRadioOff == true) + return 0; + + down(&priv->wx_sem); + ret = rtllib_wx_set_auth(priv->rtllib, info, &(data->param), extra); + up(&priv->wx_sem); +#endif + return ret; +} + +static int r8192_wx_set_mlme(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + int ret=0; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->bHwRadioOff == true) + return 0; + + down(&priv->wx_sem); + ret = rtllib_wx_set_mlme(priv->rtllib, info, wrqu, extra); + up(&priv->wx_sem); +#endif + return ret; +} +#endif + +static int r8192_wx_set_gen_ie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + int ret = 0; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->bHwRadioOff == true) + return 0; + + down(&priv->wx_sem); + ret = rtllib_wx_set_gen_ie(priv->rtllib, extra, data->data.length); + up(&priv->wx_sem); +#endif + return ret; +} + +static int r8192_wx_get_gen_ie(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *data, char *extra) +{ + int ret = 0; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + + if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) { + data->data.length = 0; + return 0; + } + + if (data->data.length < ieee->wpa_ie_len) { + return -E2BIG; + } + + data->data.length = ieee->wpa_ie_len; + memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); +#endif + return ret; +} + +#ifdef _RTL8192_EXT_PATCH_ +/* + Output: + (case 1) Mesh: Enable. MESHID=[%s] (max length of %s is 32 bytes). + (case 2) Mesh: Disable. +*/ +static int r8192_wx_get_meshinfo(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_get_meshinfo ) + return 0; + return priv->mshobj->ext_patch_r819x_wx_get_meshinfo(dev, info, wrqu, extra); +} + + +static int r8192_wx_enable_mesh(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + RT_RF_POWER_STATE rtState; + int ret = 0; + rtState = priv->rtllib->eRFPowerState; + + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_enable_mesh ) + return 0; + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + if(priv->mshobj->ext_patch_r819x_wx_enable_mesh(dev)) + { + union iwreq_data tmprqu; +#ifdef ENABLE_IPS + if(priv->rtllib->PowerSaveControl.bInactivePs){ + if(rtState == eRfOff){ + if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) + { + RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__); + SEM_UP_PRIV_WX(&priv->wx_sem); + return -1; + } + else{ + printk("=========>%s(): IPSLeave\n",__FUNCTION__); + IPSLeave(dev); + } + } + } +#endif + if(ieee->only_mesh == 0) + { + tmprqu.mode = ieee->iw_mode; + ieee->iw_mode = 0; + ret = rtllib_wx_set_mode(ieee, info, &tmprqu, extra); + } + } + + SEM_UP_PRIV_WX(&priv->wx_sem); + + return ret; + +} + +static int r8192_wx_disable_mesh(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + + int ret = 0; + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_disable_mesh ) + return 0; + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + if(priv->mshobj->ext_patch_r819x_wx_disable_mesh(dev)) + { + union iwreq_data tmprqu; + tmprqu.mode = ieee->iw_mode; + ieee->iw_mode = 999; + ret = rtllib_wx_set_mode(ieee, info, &tmprqu, extra); + } + + SEM_UP_PRIV_WX(&priv->wx_sem); + + return ret; +} + + +int r8192_wx_set_channel(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ch = *extra; + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + + if (!priv->mshobj || (ieee->iw_mode != IW_MODE_MESH) || !priv->mshobj->ext_patch_r819x_wx_set_channel || !ieee->only_mesh) + return 0; + + if ( ch < 0 ) + { + rtllib_start_scan(ieee); + ieee->meshScanMode =2; + } + else + { + ieee->meshScanMode =0; + if(priv->mshobj->ext_patch_r819x_wx_set_channel) + { + priv->mshobj->ext_patch_r819x_wx_set_channel(ieee, ch); + priv->mshobj->ext_patch_r819x_wx_set_mesh_chan(dev,ch); + } + queue_work_rsl(ieee->wq, &ieee->ext_stop_scan_wq); + ieee->set_chan(ieee->dev, ch); +printk("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!set current mesh network channel %d\n", ch); + ieee->current_mesh_network.channel = ch; + if(ieee->only_mesh) + ieee->current_network.channel = ch; + + ieee->current_network.channel = ieee->current_mesh_network.channel; + if(ieee->pHTInfo->bCurBW40MHz) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + if(rtllib_act_scanning(ieee,true) == true) + rtllib_stop_scan_syncro(ieee); + } + + return 0; +} + +static int r8192_wx_set_meshID(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_meshID ) + return 0; + + return priv->mshobj->ext_patch_r819x_wx_set_meshID(dev, wrqu->data.pointer); +} + + +/* reserved for future +static int r8192_wx_add_mac_deny(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_add_mac_deny ) + return 0; + + return priv->mshobj->ext_patch_r819x_wx_set_add_mac_deny(dev, info, wrqu, extra); +} + +static int r8192_wx_del_mac_deny(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_del_mac_deny ) + return 0; + + return priv->mshobj->ext_patch_r819x_wx_set_del_mac_deny(dev, info, wrqu, extra); +} +*/ +/* reserved for future +static int r8192_wx_get_mac_deny(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_get_mac_deny ) + return 0; + + return priv->mshobj->ext_patch_r819x_wx_get_mac_deny(dev, info, wrqu, extra); +} +static int r8192_wx_join_mesh(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int ret=0; + char ch; + if(priv->rtllib->iw_mode == IW_MODE_MESH) { + printk("join mesh %s\n",extra); + if (wrqu->essid.length > IW_ESSID_MAX_SIZE){ + ret= -E2BIG; + goto out; + } + if((wrqu->essid.length == 1) && (wrqu->essid.flags == 1)){ + ret = 0; + goto out; + } + if (wrqu->essid.flags && wrqu->essid.length) { + if(priv->mshobj->ext_patch_r819x_wx_get_selected_mesh_channel(dev, extra, &ch)) + { + priv->mshobj->ext_patch_r819x_wx_set_meshID(dev, extra); + priv->mshobj->ext_patch_r819x_wx_set_mesh_chan(dev,ch); + r8192_wx_set_channel(dev, NULL, NULL, &ch); + } + else + printk("invalid mesh #\n"); + } + } +out: + return ret; +} +*/ + +static int r8192_wx_get_mesh_list(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_get_mesh_list ) + return 0; + return priv->mshobj->ext_patch_r819x_wx_get_mesh_list(dev, info, wrqu, extra); +} + +static int r8192_wx_mesh_scan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_mesh_scan ) + return 0; + return priv->mshobj->ext_patch_r819x_wx_mesh_scan(dev, info, wrqu, extra); +} + +static int r8192_wx_set_meshmode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + + printk("%s(): set mesh mode ! extra is %d\n",__FUNCTION__, *extra); + if((*extra != WIRELESS_MODE_A) && (*extra != WIRELESS_MODE_B) && + (*extra != WIRELESS_MODE_G) && (*extra != WIRELESS_MODE_AUTO) && + (*extra != WIRELESS_MODE_N_24G) && (*extra != WIRELESS_MODE_N_5G)) + { + printk("ERR!! you should input 1 | 2 | 4 | 8 | 16 | 32\n"); + SEM_UP_PRIV_WX(&priv->wx_sem); + return -1; + } + if(priv->rtllib->state == RTLLIB_LINKED) + { + if((priv->rtllib->mode != WIRELESS_MODE_N_5G) && (priv->rtllib->mode != WIRELESS_MODE_N_24G)){ + printk("===>wlan0 is linked,and ieee->mode is not N mode ,do not need to set mode,return\n"); + SEM_UP_PRIV_WX(&priv->wx_sem); + return 0; + } + } + priv->rtllib->mode = *extra; + if(priv->ResetProgress == RESET_TYPE_NORESET) + rtl8192_SetWirelessMode(dev, priv->rtllib->mode); + HTUseDefaultSetting(priv->rtllib); + SEM_UP_PRIV_WX(&priv->wx_sem); + return 0; + +} + +static int r8192_wx_set_meshBW(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + + printk("%s(): set mesh BW ! extra is %d\n",__FUNCTION__, *extra); + priv->rtllib->pHTInfo->bRegBW40MHz = *extra; + SEM_UP_PRIV_WX(&priv->wx_sem); + return 0; +} +static int r8192_wx_set_mesh_security(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + + down(&priv->wx_sem); + + printk("%s(): set mesh security! extra is %d\n",__FUNCTION__, *extra); + ieee->mesh_security_setting = *extra; + + if (0 == ieee->mesh_security_setting) + { + ieee->mesh_pairwise_key_type = ieee->mesh_group_key_type = KEY_TYPE_NA; + CamResetAllEntry(dev); + CamRestoreEachIFEntry(dev,0); + reset_IFswcam(dev,1); + } + else + { + ieee->mesh_pairwise_key_type = KEY_TYPE_CCMP; + ieee->mesh_group_key_type = KEY_TYPE_CCMP; + } + up(&priv->wx_sem); + return 0; + +} + +static int r8192_wx_set_mkdd_id(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + printk("===>%s()\n",__FUNCTION__); + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_mkdd_id) + return 0; + + return priv->mshobj->ext_patch_r819x_wx_set_mkdd_id(dev, wrqu->data.pointer); +} + +static int r8192_wx_set_mesh_key(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + printk("===>%s()\n",__FUNCTION__); + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_mesh_key) + return 0; + return priv->mshobj->ext_patch_r819x_wx_set_mesh_key(dev, wrqu->data.pointer); +} + +static int r8192_wx_set_mesh_sec_type(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + + printk("%s(): set mesh security type! extra is %d\n",__FUNCTION__, *extra); + if (ieee->mesh_sec_type == 1 && *extra != 1 && ieee->mesh_security_setting == 3) { + rtl8192_abbr_handshk_disable_key(ieee); + + if(priv->mshobj->ext_patch_r819x_wx_release_sae_info) + priv->mshobj->ext_patch_r819x_wx_release_sae_info(ieee); + } + down(&priv->wx_sem); + + ieee->mesh_sec_type = *extra; + + if(ieee->mesh_sec_type == 0) + ieee->mesh_pairwise_key_type = ieee->mesh_group_key_type = KEY_TYPE_NA; + + up(&priv->wx_sem); + return 0; +} + +#endif + +#define OID_RT_INTEL_PROMISCUOUS_MODE 0xFF0101F6 + +static int r8192_wx_set_PromiscuousMode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + + u32 *info_buf = (u32*)(wrqu->data.pointer); + + u32 oid = info_buf[0]; + u32 bPromiscuousOn = info_buf[1]; + u32 bFilterSourceStationFrame = info_buf[2]; + + if (OID_RT_INTEL_PROMISCUOUS_MODE == oid) + { + ieee->IntelPromiscuousModeInfo.bPromiscuousOn = + (bPromiscuousOn)? (true) : (false); + ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame = + (bFilterSourceStationFrame)? (true) : (false); + + (bPromiscuousOn) ? (rtllib_EnableIntelPromiscuousMode(dev, false)) : + (rtllib_DisableIntelPromiscuousMode(dev, false)); + + printk("=======>%s(), on = %d, filter src sta = %d\n", __FUNCTION__, + bPromiscuousOn, bFilterSourceStationFrame); + } else { + return -1; + } + + return 0; +} + + +static int r8192_wx_get_PromiscuousMode(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + + down(&priv->wx_sem); + + snprintf(extra, 45, "PromiscuousMode:%d, FilterSrcSTAFrame:%d",\ + ieee->IntelPromiscuousModeInfo.bPromiscuousOn,\ + ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame); + wrqu->data.length = strlen(extra) + 1; + + up(&priv->wx_sem); + + return 0; +} + +#ifdef CONFIG_BT_30 +static int r8192_wx_creat_physical_link( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + u32 *info_buf = (u32*)(wrqu->data.pointer); + + struct r8192_priv* priv = rtllib_priv(dev); + PBT30Info pBTInfo = &priv->BtInfo; + PPACKET_IRP_HCICMD_DATA pHciCmd = NULL; + u8 joinaddr[6] = {0x00, 0xe0, 0x4c, 0x76, 0x00, 0x33}; + u8 i = 0; + + for(i=0; i<6; i++) + joinaddr[i] = (u8)(info_buf[i]); + + printk("===++===++===> RemoteJoinerAddr: %02x:%02x:%02x:%02x:%02x:%02x\n", + joinaddr[0],joinaddr[1],joinaddr[2],joinaddr[3],joinaddr[4],joinaddr[5]); + + pHciCmd = (PPACKET_IRP_HCICMD_DATA)kmalloc(sizeof(PACKET_IRP_HCICMD_DATA)+4, GFP_KERNEL); + + BT_HCI_RESET(dev, false); + BT_HCI_CREATE_PHYSICAL_LINK(dev, pHciCmd); + + memcpy(priv->BtInfo.BtAsocEntry[0].BTRemoteMACAddr, joinaddr, 6); + + bt_wifi_set_enc(dev, type_Pairwise, 0, 1); + BT_HCI_StartBeaconAndConnect(dev, pHciCmd, 0); + + kfree(pHciCmd); + + return 1; +} + +static int r8192_wx_accept_physical_link( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + struct r8192_priv* priv = rtllib_priv(dev); + PBT30Info pBTInfo = &priv->BtInfo; + PPACKET_IRP_HCICMD_DATA pHciCmd = NULL; + + u8 amp_ssid[32] = {0}; + u8 amp_len = strlen(wrqu->data.pointer); + + memcpy(amp_ssid, wrqu->data.pointer, amp_len); + + pHciCmd = (PPACKET_IRP_HCICMD_DATA)kmalloc(sizeof(PACKET_IRP_HCICMD_DATA)+4, GFP_KERNEL); + + BT_HCI_RESET(dev, false); + BT_HCI_ACCEPT_PHYSICAL_LINK(dev, pHciCmd); + + snprintf(pBTInfo->BtAsocEntry[0].BTSsidBuf, 32, "AMP-%02x-%02x-%02x-%02x-%02x-%02x", 0x00,0xe0,0x4c,0x78,0x00,0x00); + pBTInfo->BtAsocEntry[0].BTSsid.Octet = pBTInfo->BtAsocEntry[0].BTSsidBuf; + pBTInfo->BtAsocEntry[0].BTSsid.Length = 21; + printk("==++==++==++==>%s() AMP-SSID:%s:%s, len:%d\n", __func__, amp_ssid, pBTInfo->BtAsocEntry[0].BTSsid.Octet, amp_len); + +#if 1 + { + unsigned long flags; + struct rtllib_network *target; + + spin_lock_irqsave(&priv->rtllib->lock, flags); + + list_for_each_entry(target, &priv->rtllib->network_list, list) { + + if(!CompareSSID(pBTInfo->BtAsocEntry[0].BTSsidBuf, pBTInfo->BtAsocEntry[0].BTSsid.Length, + target->ssid,target->ssid_len)){ + continue; + } + + printk("===++===++===> CreaterBssid: %02x:%02x:%02x:%02x:%02x:%02x\n", + target->bssid[0],target->bssid[1],target->bssid[2], + target->bssid[3],target->bssid[4],target->bssid[5]); + memcpy(pBTInfo->BtAsocEntry[0].BTRemoteMACAddr, target->bssid, 6); + } + + spin_unlock_irqrestore(&priv->rtllib->lock, flags); + } +#endif + + BT_HCI_StartBeaconAndConnect(dev, pHciCmd, 0); + + + mdelay(100); + + snprintf(pBTInfo->BtAsocEntry[0].BTSsidBuf, 32, "AMP-%02x-%02x-%02x-%02x-%02x-%02x", 0x00,0xe0,0x4c,0x78,0x00,0x00); + pBTInfo->BtAsocEntry[0].BTSsid.Octet = pBTInfo->BtAsocEntry[0].BTSsidBuf; + pBTInfo->BtAsocEntry[0].BTSsid.Length = 21; + + bt_wifi_set_enc(dev, type_Pairwise, 0, 1); + BT_ConnectProcedure(dev, 0); + + kfree(pHciCmd); + + return 1; +} +#endif + + +#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] +static iw_handler r8192_wx_handlers[] = +{ + IW_IOCTL(SIOCGIWNAME) = r8192_wx_get_name, + IW_IOCTL(SIOCSIWFREQ) = r8192_wx_set_freq, + IW_IOCTL(SIOCGIWFREQ) = r8192_wx_get_freq, + IW_IOCTL(SIOCSIWMODE) = r8192_wx_set_mode, + IW_IOCTL(SIOCGIWMODE) = r8192_wx_get_mode, + IW_IOCTL(SIOCSIWSENS) = r8192_wx_set_sens, + IW_IOCTL(SIOCGIWSENS) = r8192_wx_get_sens, + IW_IOCTL(SIOCGIWRANGE) = rtl8192_wx_get_range, + IW_IOCTL(SIOCSIWAP) = r8192_wx_set_wap, + IW_IOCTL(SIOCGIWAP) = r8192_wx_get_wap, + IW_IOCTL(SIOCSIWSCAN) = r8192_wx_set_scan, + IW_IOCTL(SIOCGIWSCAN) = r8192_wx_get_scan, + IW_IOCTL(SIOCSIWESSID) = r8192_wx_set_essid, + IW_IOCTL(SIOCGIWESSID) = r8192_wx_get_essid, + IW_IOCTL(SIOCSIWNICKN) = r8192_wx_set_nick, + IW_IOCTL(SIOCGIWNICKN) = r8192_wx_get_nick, + IW_IOCTL(SIOCSIWRATE) = r8192_wx_set_rate, + IW_IOCTL(SIOCGIWRATE) = r8192_wx_get_rate, + IW_IOCTL(SIOCSIWRTS) = r8192_wx_set_rts, + IW_IOCTL(SIOCGIWRTS) = r8192_wx_get_rts, + IW_IOCTL(SIOCSIWFRAG) = r8192_wx_set_frag, + IW_IOCTL(SIOCGIWFRAG) = r8192_wx_get_frag, + IW_IOCTL(SIOCSIWRETRY) = r8192_wx_set_retry, + IW_IOCTL(SIOCGIWRETRY) = r8192_wx_get_retry, + IW_IOCTL(SIOCSIWENCODE) = r8192_wx_set_enc, + IW_IOCTL(SIOCGIWENCODE) = r8192_wx_get_enc, + IW_IOCTL(SIOCSIWPOWER) = r8192_wx_set_power, + IW_IOCTL(SIOCGIWPOWER) = r8192_wx_get_power, +#if (WIRELESS_EXT >= 18) + IW_IOCTL(SIOCSIWGENIE) = r8192_wx_set_gen_ie, + IW_IOCTL(SIOCGIWGENIE) = r8192_wx_get_gen_ie, + IW_IOCTL(SIOCSIWMLME) = r8192_wx_set_mlme, + IW_IOCTL(SIOCSIWAUTH) = r8192_wx_set_auth, + IW_IOCTL(SIOCSIWENCODEEXT) = r8192_wx_set_enc_ext, +#endif +}; + +/* + * the following rule need to be follwing, + * Odd : get (world access), + * even : set (root access) + * */ +static const struct iw_priv_args r8192_private_args[] = { + { + SIOCIWFIRSTPRIV + 0x0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_debugflag" + }, + { + SIOCIWFIRSTPRIV + 0x1, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan" + }, + { + SIOCIWFIRSTPRIV + 0x2, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" + } + , + { + SIOCIWFIRSTPRIV + 0x3, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset" + } + , + { + SIOCIWFIRSTPRIV + 0x4, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "force_mic_error" + } + , + { + SIOCIWFIRSTPRIV + 0x5, + IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT|IW_PRIV_SIZE_FIXED|1, + "firm_ver" + } + , + { + SIOCIWFIRSTPRIV + 0x6, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, + "set_power" + } +#ifdef _RTL8192_EXT_PATCH_ + , + { + SIOCIWFIRSTPRIV + 0x7, + IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR|512, + "print_reg" + } + , + { + SIOCIWFIRSTPRIV + 0x8, + IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR|64, + "resume_firm" + } +#endif + , + { + SIOCIWFIRSTPRIV + 0x9, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, + "radio" + } + , + { + SIOCIWFIRSTPRIV + 0xa, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, + "lps_interv" + } + , + { + SIOCIWFIRSTPRIV + 0xb, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, + "lps_force" + } + , + { + SIOCIWFIRSTPRIV + 0xc, + 0, IW_PRIV_TYPE_CHAR|2047, "adhoc_peer_list" + } +#ifdef _RTL8192_EXT_PATCH_ + , + { + SIOCIWFIRSTPRIV + 0xd, + IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_CHAR|64, + "driverVer" + } +#endif +#ifdef CONFIG_MP + , + { + SIOCIWFIRSTPRIV + 0xe, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "SetChan" + } + , + { + SIOCIWFIRSTPRIV + 0xf, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "SetRate" + } + , + { + SIOCIWFIRSTPRIV + 0x10, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "SetTxPower" + } + , + { + SIOCIWFIRSTPRIV + 0x11, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "SetBW" + } + , + { + SIOCIWFIRSTPRIV + 0x12, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "TxStart" + } + , + { + SIOCIWFIRSTPRIV + 0x13, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,0, "SetSingleCarrier" + } + , + { + SIOCIWFIRSTPRIV + 0x14, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "WriteRF" + } + , + { + SIOCIWFIRSTPRIV + 0x15, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "WriteMAC" + } +#endif + , + { + SIOCIWFIRSTPRIV + 0x16, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "setpromisc" + } + , + { + SIOCIWFIRSTPRIV + 0x17, + 0,IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 45, "getpromisc" + } +#ifdef CONFIG_BT_30 + , + { + SIOCIWFIRSTPRIV + 0x18, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 6, 0, "amp_creater" + } + , + { + SIOCIWFIRSTPRIV + 0x19, + IW_PRIV_TYPE_CHAR | 64, 0, "amp_joiner" + } +#endif +}; + +static iw_handler r8192_private_handler[] = { + (iw_handler)r8192_wx_set_debugflag, /*SIOCIWSECONDPRIV*/ + (iw_handler)r8192_wx_set_scan_type, + (iw_handler)r8192_wx_set_rawtx, + (iw_handler)r8192_wx_force_reset, + (iw_handler)r8192_wx_force_mic_error, + (iw_handler)r8191se_wx_get_firm_version, + (iw_handler)r8192_wx_adapter_power_status, +#ifdef _RTL8192_EXT_PATCH_ + (iw_handler)r8192_wx_print_reg, + (iw_handler)r8192_wx_resume_firm, +#else + (iw_handler)NULL, + (iw_handler)NULL, +#endif + (iw_handler)r8192se_wx_set_radio, + (iw_handler)r8192se_wx_set_lps_awake_interval, + (iw_handler)r8192se_wx_set_force_lps, + (iw_handler)r8192_wx_get_adhoc_peers, +#ifdef _RTL8192_EXT_PATCH_ + (iw_handler)r8192_wx_get_drv_version, +#else + (iw_handler)NULL, +#endif +#ifdef CONFIG_MP + (iw_handler)r8192_wx_mp_set_chan, + (iw_handler)r8192_wx_mp_set_txrate, + (iw_handler)r8192_wx_mp_set_txpower, + (iw_handler)r8192_wx_mp_set_bw, + (iw_handler)r8192_wx_mp_set_txstart, + (iw_handler)r8192_wx_mp_set_singlecarrier, + (iw_handler)r8192_wx_mp_write_rf, + (iw_handler)r8192_wx_mp_write_mac, +#else + (iw_handler)NULL, + (iw_handler)NULL, + (iw_handler)NULL, + (iw_handler)NULL, + (iw_handler)NULL, + (iw_handler)NULL, + (iw_handler)NULL, + (iw_handler)NULL, +#endif + (iw_handler)r8192_wx_set_PromiscuousMode, + (iw_handler)r8192_wx_get_PromiscuousMode, +#ifdef CONFIG_BT_30 + (iw_handler)r8192_wx_creat_physical_link, + (iw_handler)r8192_wx_accept_physical_link, +#else + (iw_handler)NULL, + (iw_handler)NULL, +#endif +}; + +struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + struct iw_statistics* wstats = &priv->wstats; + int tmp_level = 0; + int tmp_qual = 0; + int tmp_noise = 0; + if(ieee->state < RTLLIB_LINKED) + { + wstats->qual.qual = 10; + wstats->qual.level = 0; + wstats->qual.noise = -100; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)) + wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; +#else + wstats->qual.updated = 0x0f; +#endif + return wstats; + } + + tmp_level = (&ieee->current_network)->stats.rssi; + tmp_qual = (&ieee->current_network)->stats.signal; + tmp_noise = (&ieee->current_network)->stats.noise; + + wstats->qual.level = tmp_level; + wstats->qual.qual = tmp_qual; + wstats->qual.noise = tmp_noise; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)) + wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; +#else + wstats->qual.updated = 0x0f; +#endif + return wstats; +} + +#if defined RTL8192SE || defined RTL8192CE +u8 SS_Rate_Map_G[6][2] = {{40, MGN_54M}, {30, MGN_48M}, {20, MGN_36M}, + {12, MGN_24M}, {7, MGN_18M}, {0, MGN_12M}}; +u8 SS_Rate_Map_G_MRC_OFF[6][2]= {{17, MGN_54M}, {15, MGN_48M}, + {13, MGN_36M}, {10, MGN_24M}, {3, MGN_18M}, {0, MGN_12M}}; +u8 MSI_SS_Rate_Map_G[6][2] = {{40, MGN_54M}, {30, MGN_54M}, {20, MGN_54M}, + {12, MGN_48M}, {7, MGN_36M}, {0, MGN_24M}}; +u8 SS_Rate_Map_B[2][2] = {{7, MGN_11M}, {0, MGN_5_5M}}; +u8 SS_Rate_Map_N_MCS7[7][2] = {{40, MGN_MCS7}, {30, MGN_MCS5}, {25, MGN_MCS4}, + {23, MGN_MCS3}, {19, MGN_MCS2}, {8, MGN_MCS1}, {0, MGN_MCS0}}; +u8 SS_Rate_Map_N_MCS15[7][2] = {{40, MGN_MCS15}, {35, MGN_MCS14}, {31, MGN_MCS12}, + {28, MGN_MCS7}, {25, MGN_MCS5}, {23, MGN_MCS3}, {20, MGN_MCS0}}; +#define TxRateTypeNormal 0 +#define TxRateTypeCurrent 1 +#define TxRateTypeStartRate 2 + +u8 rtl8192_decorate_txrate_by_singalstrength(u32 SignalStrength, u8 *SS_Rate_Map, u8 MapSize) +{ + u8 index = 0; + + for (index = 0; index < (MapSize * 2); index += 2) { + if (SignalStrength > SS_Rate_Map[index]) + return SS_Rate_Map[index+1]; + } + + return MGN_1M; +} + +u16 rtl8192_11n_user_show_rates(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + static u8 TimesForReportingFullRxSpeedAfterConnected = 100; + u8 rate = MGN_1M; + u32 Sgstrength; + bool TxorRx = priv->rtllib->bForcedShowRxRate; + u8 bCurrentMRC = 0; + + priv->rtllib->GetHwRegHandler(dev, HW_VAR_MRC, (u8*)(&bCurrentMRC)); + + + if (!TxorRx) { + { + return CONVERT_RATE(priv->rtllib, priv->rtllib->softmac_stats.CurrentShowTxate); + } + } + + if(priv->rtllib->bForcedShowRateStill) { + Sgstrength = 100; + } else { + Sgstrength = priv->undecorated_smoothed_pwdb; + } + + if (priv->rtllib->mode == WIRELESS_MODE_A || + priv->rtllib->mode == WIRELESS_MODE_G || + priv->rtllib->mode == (WIRELESS_MODE_G | WIRELESS_MODE_B )) { + if (priv->CustomerID == RT_CID_819x_MSI) { + rate = rtl8192_decorate_txrate_by_singalstrength(Sgstrength, + (u8*)MSI_SS_Rate_Map_G, sizeof(MSI_SS_Rate_Map_G)/2); + } else { + if(!bCurrentMRC) + rate = rtl8192_decorate_txrate_by_singalstrength(Sgstrength, + (u8*)SS_Rate_Map_G_MRC_OFF, sizeof(SS_Rate_Map_G_MRC_OFF)/2); + else + rate = rtl8192_decorate_txrate_by_singalstrength(Sgstrength, + (u8*)SS_Rate_Map_G, sizeof(SS_Rate_Map_G)/2); + } + } else if (priv->rtllib->mode == WIRELESS_MODE_B) { + rate = rtl8192_decorate_txrate_by_singalstrength(Sgstrength, (u8*)SS_Rate_Map_B, + sizeof(SS_Rate_Map_B)/2); + } else if(priv->rtllib->mode == WIRELESS_MODE_N_24G) { + bool bMaxRateMcs15; + bool b1SSSupport = priv->rtllib->b1x1RecvCombine; + u8 rftype = priv->rf_type; + if (((!TxorRx) && (rftype==RF_1T1R || rftype==RF_1T2R)) || + (TxorRx && (rftype==RF_1T1R || (rftype==RF_1T2R && b1SSSupport))) || + (rftype==RF_2T2R && priv->rtllib->HTHighestOperaRate<=MGN_MCS7)) + bMaxRateMcs15 = false; + else + bMaxRateMcs15 = true; + + if((priv->rtllib->state == RTLLIB_LINKED) && !(priv->rtllib->pHTInfo->bCurBW40MHz)) + bMaxRateMcs15 = false; + + if(priv->rtllib->state != RTLLIB_LINKED) + priv->rtllib->SystemQueryDataRateCount = 0; + if (TimesForReportingFullRxSpeedAfterConnected > priv->rtllib->SystemQueryDataRateCount) { + priv->rtllib->SystemQueryDataRateCount++; + if(bMaxRateMcs15) + return 600; + else + return 270; + } + + if (bMaxRateMcs15) + rate = rtl8192_decorate_txrate_by_singalstrength(Sgstrength, (u8*)SS_Rate_Map_N_MCS15, + sizeof(SS_Rate_Map_N_MCS15)/2); + else + rate = rtl8192_decorate_txrate_by_singalstrength(Sgstrength, (u8*)SS_Rate_Map_N_MCS7, + sizeof(SS_Rate_Map_N_MCS7)/2); + } else if (priv->rtllib->mode == WIRELESS_MODE_N_5G) { + return 580; + } else { + return 2; + } + + if (priv->rtllib->GetHalfNmodeSupportByAPsHandler(dev)) { + if (rate < 0x80) + return rate; + else + return HTHalfMcsToDataRate(priv->rtllib, rate); + } else { + return CONVERT_RATE(priv->rtllib, rate); + } +} +#endif + +struct iw_handler_def r8192_wx_handlers_def={ + .standard = r8192_wx_handlers, + .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler), + .private = r8192_private_handler, + .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler), + .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args), +#if WIRELESS_EXT >= 17 + .get_wireless_stats = r8192_get_wireless_stats, +#endif + .private_args = (struct iw_priv_args *)r8192_private_args, +}; + +#ifdef _RTL8192_EXT_PATCH_ +#define OID_802_11_MESH_SECURITY_INFO 0x0651 +#define OID_802_11_MESH_ID 0x0652 +#define OID_802_11_MESH_AUTO_LINK 0x0653 +#define OID_802_11_MESH_LINK_STATUS 0x0654 +#define OID_802_11_MESH_LIST 0x0655 +#define OID_802_11_MESH_ROUTE_LIST 0x0656 +#define OID_802_11_MESH_ADD_LINK 0x0657 +#define OID_802_11_MESH_DEL_LINK 0x0658 +#define OID_802_11_MESH_MAX_TX_RATE 0x0659 +#define OID_802_11_MESH_CHANNEL 0x065A +#define OID_802_11_MESH_HOSTNAME 0x065B +#define OID_802_11_MESH_ONLY_MODE 0x065C + +#define OID_GET_SET_TOGGLE 0x8000 +#define RTL_OID_802_11_MESH_SECURITY_INFO (OID_GET_SET_TOGGLE + OID_802_11_MESH_SECURITY_INFO) +#define RTL_OID_802_11_MESH_ID (OID_GET_SET_TOGGLE + OID_802_11_MESH_ID) +#define RTL_OID_802_11_MESH_AUTO_LINK (OID_GET_SET_TOGGLE + OID_802_11_MESH_AUTO_LINK) +#define RTL_OID_802_11_MESH_ADD_LINK (OID_GET_SET_TOGGLE + OID_802_11_MESH_ADD_LINK) +#define RTL_OID_802_11_MESH_DEL_LINK (OID_GET_SET_TOGGLE + OID_802_11_MESH_DEL_LINK) +#define RTL_OID_802_11_MESH_MAX_TX_RATE (OID_GET_SET_TOGGLE + OID_802_11_MESH_MAX_TX_RATE) +#define RTL_OID_802_11_MESH_CHANNEL (OID_GET_SET_TOGGLE + OID_802_11_MESH_CHANNEL) +#define RTL_OID_802_11_MESH_HOSTNAME (OID_GET_SET_TOGGLE + OID_802_11_MESH_HOSTNAME) +#define RTL_OID_802_11_MESH_ONLY_MODE (OID_GET_SET_TOGGLE + OID_802_11_MESH_ONLY_MODE) + +#define MAX_NEIGHBOR_NUM 64 +typedef struct _MESH_NEIGHBOR_ENTRY +{ + char Rssi; + unsigned char HostName[MAX_HOST_NAME_LENGTH]; + unsigned char MacAddr[ETH_ALEN]; + unsigned char MeshId[MAX_MESH_ID_LEN]; + unsigned char Channel; + unsigned char Status; + unsigned char MeshEncrypType; +} MESH_NEIGHBOR_ENTRY, *PMESH_NEIGHBOR_ENTRY; +typedef struct _MESH_NEIGHBOR_INFO +{ + MESH_NEIGHBOR_ENTRY Entry[MAX_NEIGHBOR_NUM]; + unsigned char num; +} MESH_NEIGHBOR_INFO, *PMESH_NEIGHBOR_INFO; + +static int meshdev_set_key_for_linked_peers(struct net_device *dev, u8 KeyIndex, + u16 KeyType, u32 *KeyContent ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + struct mshclass *mshobj = priv->mshobj; + PMESH_NEIGHBOR_INFO pmesh_neighbor = NULL; + PMESH_NEIGHBOR_ENTRY pneighbor_entry = NULL; + u8 entry_idx = 0; + int i = 0; + int found_idx = MAX_MP-1; + pmesh_neighbor = (PMESH_NEIGHBOR_INFO)kmalloc(sizeof(MESH_NEIGHBOR_INFO), GFP_KERNEL); + if(NULL == pmesh_neighbor) + return -1; + + if(mshobj->ext_patch_r819x_get_peers) + mshobj->ext_patch_r819x_get_peers(dev, (void*)pmesh_neighbor); + + for (i=0; inum; i++) { + pneighbor_entry = (PMESH_NEIGHBOR_ENTRY)&pmesh_neighbor->Entry[i]; + if (mshobj->ext_patch_r819x_insert_linking_crypt_peer_queue) + found_idx = mshobj->ext_patch_r819x_insert_linking_crypt_peer_queue(ieee,pneighbor_entry->MacAddr); + if (found_idx == -1) { + printk("%s(): found_idx is -1 , something is wrong, return\n",__FUNCTION__); + return -1; + } else if (found_idx == (MAX_MP - 1)) { + printk("%s(): found_idx is MAX_MP-1, peer entry is full, return\n",__FUNCTION__); + return -1; + } + if ((((ieee->LinkingPeerBitMap>>found_idx) & (BIT0)) == BIT0) && ((ieee->LinkingPeerSecState[found_idx] == USED) )) { + entry_idx = rtl8192_get_free_hwsec_cam_entry(ieee, pneighbor_entry->MacAddr); +#if 0 + printk("%s: Can not find free hw security cam entry, use software encryption entry(%d)\n", __FUNCTION__,entry_idx); + if (mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info) + mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info(ieee,pneighbor_entry->MacAddr,SW_SEC); + ieee->LinkingPeerSecState[found_idx] = SW_SEC; +#else + if (entry_idx >= TOTAL_CAM_ENTRY-1) { + printk("%s: Can not find free hw security cam entry, use software encryption entry(%d)\n", __FUNCTION__,entry_idx); + if (mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info) + mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info(ieee,pneighbor_entry->MacAddr,SW_SEC); + ieee->LinkingPeerSecState[found_idx] = SW_SEC; + } else { + printk("==========>%s():entry_idx is %d,set HW CAM\n",__FUNCTION__,entry_idx); + set_swcam( dev, + entry_idx, + KeyIndex, + KeyType, + pneighbor_entry->MacAddr, + 0, + KeyContent, + 1); + setKey( dev, + entry_idx, + KeyIndex, + KeyType, + pneighbor_entry->MacAddr, + 0, + KeyContent); + if (mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info) + mshobj->ext_patch_r819x_set_msh_peer_entry_sec_info(ieee,pneighbor_entry->MacAddr,HW_SEC); + ieee->LinkingPeerSecState[found_idx] = HW_SEC; + } +#endif + } + } + if(pmesh_neighbor) + kfree(pmesh_neighbor); + return 0; +} + +int meshdev_set_key_for_peer(struct net_device *dev, + u8 *Addr, + u8 KeyIndex, + u16 KeyType, + u32 *KeyContent ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + u8 entry_idx = 0; + + entry_idx = rtl8192_get_free_hwsec_cam_entry(ieee, Addr); +#if 0 + printk("%s: Can not find free hw security cam entry\n", __FUNCTION__); + return -1; +#else + if (entry_idx >= TOTAL_CAM_ENTRY-1) { + printk("%s: Can not find free hw security cam entry\n", __FUNCTION__); + return -1; + } else { + set_swcam(dev, + entry_idx, + KeyIndex, + KeyType, + Addr, + 0, + KeyContent, + 1); + setKey(dev, + entry_idx, + KeyIndex, + KeyType, + Addr, + 0, + KeyContent); + } + return 0; +#endif +} + +static struct net_device_stats *meshdev_stats(struct net_device *meshdev) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + return &((struct meshdev_priv*)netdev_priv(meshdev))->stats; +#else + return &((struct meshdev_priv*)meshdev->priv)->stats; +#endif +} + +static int meshdev_wx_get_name(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_get_name(dev, info, wrqu, extra); +} +static int meshdev_wx_get_freq(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = rtllib_priv(dev); + + return rtllib_wx_get_freq(priv->rtllib,info,wrqu,extra,1); +} +static int meshdev_wx_get_mode(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + if(0) + return r8192_wx_get_mode(dev, info, wrqu, extra); + else + return -1; +} +static int meshdev_wx_get_sens(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_get_sens(dev, info, wrqu, extra); +} +static int meshdev_wx_get_range(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return rtl8192_wx_get_range(dev, info, wrqu, extra); +} +static int meshdev_wx_get_wap(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_get_wap(dev, info, wrqu, extra); +} +static int meshdev_wx_get_essid(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = rtllib_priv(dev); + struct mshclass *mshobj = priv->mshobj; + int ret = 0; + + if(mshobj->ext_patch_r819x_wx_get_meshid) + ret = mshobj->ext_patch_r819x_wx_get_meshid(dev, info, wrqu, extra); + + return ret; +} +static int meshdev_wx_get_rate(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_get_rate(dev, info, wrqu, extra); +} +#if 0 +static int meshdev_wx_set_freq(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_freq(dev, info, wrqu, extra); +} +static int meshdev_wx_set_rate(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_rate(dev, info, wrqu, extra); +} +static int meshdev_wx_set_sens(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_sens(dev, info, wrqu, extra); +} +static int meshdev_wx_set_scan(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_scan(dev, info, wrqu, extra); +} +static int meshdev_wx_get_scan(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_get_scan(dev, info, wrqu, extra); +} +#endif +static int meshdev_wx_set_enc(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = (struct r8192_priv *)ieee->priv; + int ret; + u32 hwkey[4]={0,0,0,0}; + u8 mask=0xff; + u32 key_idx=0; +#if 0 + u8 zero_addr[4][6] ={ {0x00,0x00,0x00,0x00,0x00,0x00}, + {0x00,0x00,0x00,0x00,0x00,0x01}, + {0x00,0x00,0x00,0x00,0x00,0x02}, + {0x00,0x00,0x00,0x00,0x00,0x03} }; +#endif + int i; + + if(!priv->mesh_up) return -ENETDOWN; + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + + RT_TRACE(COMP_SEC, "Setting SW wep key"); + ret = rtllib_wx_set_encode(priv->rtllib,info,wrqu,key,1); + + SEM_UP_PRIV_WX(&priv->wx_sem); + + + if(wrqu->encoding.length!=0){ + + for(i=0 ; i<4 ; i++){ + hwkey[i] |= key[4*i+0]&mask; + if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00; + if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00; + hwkey[i] |= (key[4*i+1]&mask)<<8; + hwkey[i] |= (key[4*i+2]&mask)<<16; + hwkey[i] |= (key[4*i+3]&mask)<<24; + } + + #define CONF_WEP40 0x4 + #define CONF_WEP104 0x14 + + switch(wrqu->encoding.flags & IW_ENCODE_INDEX){ + case 0: key_idx = ieee->mesh_txkeyidx; break; + case 1: key_idx = 0; break; + case 2: key_idx = 1; break; + case 3: key_idx = 2; break; + case 4: key_idx = 3; break; + default: break; + } + + if(wrqu->encoding.length==0x5){ + ieee->mesh_pairwise_key_type = KEY_TYPE_WEP40; + EnableHWSecurityConfig8192(dev); + } + + else if(wrqu->encoding.length==0xd){ + ieee->mesh_pairwise_key_type = KEY_TYPE_WEP104; + EnableHWSecurityConfig8192(dev); + } + else + printk("wrong type in WEP, not WEP40 and WEP104\n"); + + meshdev_set_key_for_linked_peers(dev, + key_idx, + ieee->mesh_pairwise_key_type, + hwkey); + + } + +#if 0 + if(wrqu->encoding.length==0 && (wrqu->encoding.flags >>8) == 0x8 ){ + printk("===>1\n"); + EnableHWSecurityConfig8192(dev); + key_idx = (wrqu->encoding.flags & 0xf)-1 ; + write_cam(dev, (4*6), 0xffff0000|read_cam(dev, key_idx*6) ); + write_cam(dev, (4*6)+1, 0xffffffff); + write_cam(dev, (4*6)+2, read_cam(dev, (key_idx*6)+2) ); + write_cam(dev, (4*6)+3, read_cam(dev, (key_idx*6)+3) ); + write_cam(dev, (4*6)+4, read_cam(dev, (key_idx*6)+4) ); + write_cam(dev, (4*6)+5, read_cam(dev, (key_idx*6)+5) ); + } +#endif + + return ret; +} +static int meshdev_wx_get_enc(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device * dev = ieee->dev; + struct r8192_priv* priv = rtllib_priv(dev); + + if(!priv->mesh_up){ + return -ENETDOWN; + } + return rtllib_wx_get_encode(ieee, info, wrqu, extra,1); +} +#if 0 +static int meshdev_wx_set_frag(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_frag(dev, info, wrqu, extra); +} +static int meshdev_wx_get_frag(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_get_frag(dev, info, wrqu, extra); +} +static int meshdev_wx_set_retry(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_retry(dev, info, wrqu, extra); +} +static int meshdev_wx_get_retry(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_get_retry(dev, info, wrqu, extra); +} +#endif +static int meshdev_wx_set_mode(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ +#if 0 + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_mode(dev, info, wrqu, extra); +#endif + return 0; +} +static int meshdev_wx_set_wap(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ +#if 0 + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_wap(dev, info, wrqu, extra); +#endif + return 0; +} +static int meshdev_wx_set_mlme(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ +#if 0 + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_mlme(dev, info, wrqu, extra); +#endif + return 0; +} +static int meshdev_wx_set_essid(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ +#if 0 + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_essid(dev, info, wrqu, extra); +#endif + return 0; +} +static int meshdev_wx_set_gen_ie(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ +#if 0 + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_gen_ie(dev, info, wrqu, extra); +#endif + return 0; +} +static int meshdev_wx_set_auth(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ +#if 0 + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + return r8192_wx_set_auth(dev, info, wrqu, extra); +#endif + return 0; +} +static int meshdev_wx_set_enc_ext(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret=0; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = (struct r8192_priv *)ieee->priv; + + printk("============================================================>%s\n", __FUNCTION__); + SEM_DOWN_PRIV_WX(&priv->wx_sem); + ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra, 1); + + ret |= r8192_set_hw_enc(dev,info,wrqu,extra, 1); + SEM_UP_PRIV_WX(&priv->wx_sem); +#endif + + return ret; +} + +static int dummy(struct net_device *dev, struct iw_request_info *a, + union iwreq_data *wrqu,char *b) +{ + return -1; +} + +int rt_ioctl_siwpmksa(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra) +{ + return 0; +} + +static iw_handler meshdev_wx_handlers[] = +{ + NULL, /* SIOCSIWCOMMIT */ + meshdev_wx_get_name, /* SIOCGIWNAME */ + dummy, /* SIOCSIWNWID */ + dummy, /* SIOCGIWNWID */ + NULL, + meshdev_wx_get_freq, /* SIOCGIWFREQ */ + meshdev_wx_set_mode, /* SIOCSIWMODE */ + meshdev_wx_get_mode, /* SIOCGIWMODE */ + NULL, + meshdev_wx_get_sens, /* SIOCGIWSENS */ + NULL, /* SIOCSIWRANGE */ + meshdev_wx_get_range, /* SIOCGIWRANGE */ + NULL, /* SIOCSIWPRIV */ + NULL, /* SIOCGIWPRIV */ + NULL, /* SIOCSIWSTATS */ + NULL, /* SIOCGIWSTATS */ + dummy, /* SIOCSIWSPY */ + dummy, /* SIOCGIWSPY */ + NULL, /* SIOCGIWTHRSPY */ + NULL, /* SIOCWIWTHRSPY */ + meshdev_wx_set_wap, /* SIOCSIWAP */ + meshdev_wx_get_wap, /* SIOCGIWAP */ + meshdev_wx_set_mlme, + dummy, /* SIOCGIWAPLIST -- depricated */ + NULL, + NULL, + meshdev_wx_set_essid, /* SIOCSIWESSID */ + meshdev_wx_get_essid, /* SIOCGIWESSID */ + dummy, /* SIOCSIWNICKN */ + dummy, /* SIOCGIWNICKN */ + NULL, /* -- hole -- */ + NULL, /* -- hole -- */ + NULL, + meshdev_wx_get_rate, /* SIOCGIWRATE */ + dummy, /* SIOCSIWRTS */ + dummy, /* SIOCGIWRTS */ + NULL, + NULL, + dummy, /* SIOCSIWTXPOW */ + dummy, /* SIOCGIWTXPOW */ + NULL, + NULL, + meshdev_wx_set_enc, /* SIOCSIWENCODE */ + meshdev_wx_get_enc, /* SIOCGIWENCODE */ + dummy, /* SIOCSIWPOWER */ + dummy, /* SIOCGIWPOWER */ + NULL, /*---hole---*/ + NULL, /*---hole---*/ + meshdev_wx_set_gen_ie, + NULL, /* SIOCSIWGENIE */ + meshdev_wx_set_auth, + NULL, + meshdev_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ + NULL, + (iw_handler) rt_ioctl_siwpmksa, + NULL, /*---hole---*/ +}; + +static struct iw_priv_args meshdev_private_args[] = { + { + SIOCIWFIRSTPRIV + 0x0, + 0, 0, "enablemesh" + }, + { + SIOCIWFIRSTPRIV + 0x1, + 0, IW_PRIV_TYPE_CHAR | 64, "getmeshinfo" + }, + { + SIOCIWFIRSTPRIV + 0x2, + 0, 0, "disablemesh" + }, + { + SIOCIWFIRSTPRIV + 0x3, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setch" + }, + { + SIOCIWFIRSTPRIV + 0x4, + IW_PRIV_TYPE_CHAR | 64 , 0, "setmeshid" + }, + { SIOCIWFIRSTPRIV + 0x5, + 0,IW_PRIV_TYPE_CHAR | 64 , "getmeshlist" + }, + { SIOCIWFIRSTPRIV + 0x6, + IW_PRIV_TYPE_CHAR | 64,0 , "meshscan" + }, + { + SIOCIWFIRSTPRIV + 0x7, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setmode" + + }, + { + SIOCIWFIRSTPRIV + 0x8, + IW_PRIV_TYPE_CHAR | 64, 0, "sethostname" + }, + { + SIOCIWFIRSTPRIV + 0x9, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setBW" + + }, + { + SIOCIWFIRSTPRIV + 0xa, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "updateBW" + }, + { SIOCIWFIRSTPRIV + 0xb, + 0,IW_PRIV_TYPE_CHAR | 256 , "macdenyget" + }, + { SIOCIWFIRSTPRIV + 0xc, + IW_PRIV_TYPE_CHAR | 64,0 , "macdenyadd" + }, + /* + { + SIOCIWFIRSTPRIV + 0xe, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_MASK, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_MASK, "" + },*/ + { SIOCIWFIRSTPRIV + 0xf, + 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_MASK , "getneighborlist" + }, + /* Sub-ioctls definitions*/ + /* + { + OID_802_11_MESH_ID, + IW_PRIV_TYPE_INT | 2047, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_MASK, "meshid" + }, + { + OID_802_11_MESH_LIST, + IW_PRIV_TYPE_INT | 2047, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_MASK, "meshlist" + },*/ + { SIOCIWFIRSTPRIV + 0x10, + IW_PRIV_TYPE_CHAR | 64, 0, "set" + }, + { SIOCIWFIRSTPRIV + 0x12, + IW_PRIV_TYPE_CHAR | 64,0 , "macdenydel" + }, + { + SIOCIWFIRSTPRIV + 0x14, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setmeshsec" + }, + { + SIOCIWFIRSTPRIV + 0x15, + IW_PRIV_TYPE_CHAR | 6, 0, "setmkddid" + }, + { + SIOCIWFIRSTPRIV + 0x16, + IW_PRIV_TYPE_CHAR | 64, 0, "setkey" + }, + { + SIOCIWFIRSTPRIV + 0x17, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setsectype" + }, +}; + +int meshdev_wx_mesh(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *meshpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device * ieee = meshpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = rtllib_priv(dev); + struct mshclass *mshobj = priv->mshobj; + int ret = 0; + + printk("@@@@@%s: ", __FUNCTION__); + if(mshobj) + { + switch(wrqu->data.flags) + { + case OID_802_11_MESH_SECURITY_INFO: + { + printk("OID_802_11_MESH_SECURITY_INFO \n"); + if(mshobj->ext_patch_r819x_wx_get_security_info) + ret = mshobj->ext_patch_r819x_wx_get_security_info(dev, info, wrqu, extra); + break; + } + case OID_802_11_MESH_ID: + { + printk("OID_802_11_MESH_ID \n"); + if(mshobj->ext_patch_r819x_wx_get_meshid) + ret = mshobj->ext_patch_r819x_wx_get_meshid(dev, info, wrqu, extra); + break; + } + case OID_802_11_MESH_AUTO_LINK: + { + printk("OID_802_11_MESH_AUTO_LINK \n"); + if(mshobj->ext_patch_r819x_wx_get_auto_link) + ret = mshobj->ext_patch_r819x_wx_get_auto_link(dev, info, wrqu, extra); + break; + } + case OID_802_11_MESH_LINK_STATUS: + { + printk("OID_802_11_MESH_LINK_STATUS \n"); + if(mshobj->ext_patch_r819x_wx_get_link_status) + ret = mshobj->ext_patch_r819x_wx_get_link_status(dev, info, wrqu, extra); + break; + } + case OID_802_11_MESH_LIST: + { + printk("OID_802_11_MESH_LIST \n"); + if(mshobj->ext_patch_r819x_wx_get_neighbor_list) + ret = mshobj->ext_patch_r819x_wx_get_neighbor_list(dev, info, wrqu, extra); + break; + } + case OID_802_11_MESH_ROUTE_LIST: + { + printk("OID_802_11_MESH_ROUTE_LIST \n"); + if(mshobj->ext_patch_r819x_wx_get_route_list) + ret = mshobj->ext_patch_r819x_wx_get_route_list(dev, info, wrqu, extra); + break; + } + case OID_802_11_MESH_MAX_TX_RATE: + { + printk("OID_802_11_MESH_MAX_TX_RATE \n"); + if(mshobj->ext_patch_r819x_wx_get_maxrate) + ret = mshobj->ext_patch_r819x_wx_get_maxrate(dev, info, wrqu, extra); + break; + } + case OID_802_11_MESH_CHANNEL: + { + printk("OID_802_11_MESH_CHANNEL \n"); + if(mshobj->ext_patch_r819x_wx_get_channel) + ret = mshobj->ext_patch_r819x_wx_get_channel(dev, info, wrqu, extra); + break; + } + case OID_802_11_MESH_HOSTNAME: + { + printk("OID_802_11_MESH_HOSTNAME \n"); + if(mshobj->ext_patch_r819x_wx_get_host_name) + ret = mshobj->ext_patch_r819x_wx_get_host_name(dev, info, wrqu, extra); + break; + } + case OID_802_11_MESH_ONLY_MODE: + { + printk("OID_802_11_MESH_ONLY_MODE \n"); + if(mshobj->ext_patch_r819x_wx_get_mesh_only_mode) + ret = mshobj->ext_patch_r819x_wx_get_mesh_only_mode(dev, info, wrqu, extra); + break; + } + case RTL_OID_802_11_MESH_SECURITY_INFO: + { + printk("RTL_OID_802_11_MESH_SECURITY_INFO \n"); + if(mshobj->ext_patch_r819x_wx_set_security_info) + ret = mshobj->ext_patch_r819x_wx_set_security_info(dev, info, wrqu, extra); + break; + } + case RTL_OID_802_11_MESH_ID: + { + printk("RTL_OID_802_11_MESH_ID \n"); + if(mshobj->ext_patch_r819x_wx_set_meshID) + ret = mshobj->ext_patch_r819x_wx_set_meshID(dev, (u8*)wrqu->data.pointer); + break; + } + case RTL_OID_802_11_MESH_AUTO_LINK: + { + printk("RTL_OID_802_11_MESH_AUTO_LINK \n"); + if(mshobj->ext_patch_r819x_wx_set_auto_link) + ret = mshobj->ext_patch_r819x_wx_set_auto_link(dev, info, wrqu, extra); + break; + } + case RTL_OID_802_11_MESH_ADD_LINK: + { + printk("RTL_OID_802_11_MESH_ADD_LINK \n"); + if(mshobj->ext_patch_r819x_wx_set_add_link) + ret = mshobj->ext_patch_r819x_wx_set_add_link(dev, info, wrqu, extra); + break; + } + case RTL_OID_802_11_MESH_DEL_LINK: + { + printk("RTL_OID_802_11_MESH_DEL_LINK \n"); + if(mshobj->ext_patch_r819x_wx_set_del_link) + ret = mshobj->ext_patch_r819x_wx_set_del_link(dev, info, wrqu, extra); + break; + } + case RTL_OID_802_11_MESH_MAX_TX_RATE: + { + printk("RTL_OID_802_11_MESH_MAX_TX_RATE \n"); + if(mshobj->ext_patch_r819x_wx_set_maxrate) + ret = mshobj->ext_patch_r819x_wx_set_maxrate(dev, info, wrqu, extra); + break; + } + case RTL_OID_802_11_MESH_CHANNEL: + { + printk("RTL_OID_802_11_MESH_CHANNEL \n"); + printk("channel = %d\n",*(u8*)wrqu->data.pointer); + r8192_wx_set_channel(dev, info, wrqu, wrqu->data.pointer); + break; + } + case RTL_OID_802_11_MESH_HOSTNAME: + { + printk("RTL_OID_802_11_MESH_HOSTNAME \n"); + if(mshobj->ext_patch_r819x_wx_set_host_name) + ret = mshobj->ext_patch_r819x_wx_set_host_name(dev, info, wrqu, extra); + break; + } + case RTL_OID_802_11_MESH_ONLY_MODE: + { + printk("RTL_OID_802_11_MESH_ONLY_MODE \n"); + if(mshobj->ext_patch_r819x_wx_set_mesh_only_mode) + ret = mshobj->ext_patch_r819x_wx_set_mesh_only_mode(dev, info, wrqu, extra); + break; + } + default: + printk("Default \n"); + break; + } + } + return ret; +} + +static int meshdev_wx_get_meshinfo(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct net_device *dev = mpriv->rtllib->dev; + +printk("++++++======%s: dev=%p length=%d extra=%p\n", __FUNCTION__, dev, wrqu->data.length,extra); + return r8192_wx_get_meshinfo(dev, info, wrqu, extra); +} + +static int meshdev_wx_enable_mesh(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + +printk("++++++======%s\n", __FUNCTION__); + return r8192_wx_enable_mesh(dev, info, wrqu, extra); + +} + +static int meshdev_wx_disable_mesh(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + +printk("++++++======%s\n", __FUNCTION__); + return r8192_wx_disable_mesh(dev, info, wrqu, extra); +} + + +int meshdev_wx_set_channel(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; +printk("++++++======%s\n", __FUNCTION__); + + return r8192_wx_set_channel(dev, info, wrqu, extra); +} + +static int meshdev_wx_set_meshid(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; +printk("++++++======%s\n", __FUNCTION__); + + return r8192_wx_set_meshID(dev, info, wrqu, extra); +} + +static int meshdev_wx_mesh_scan(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + +printk("++++++======%s\n", __FUNCTION__); + return r8192_wx_mesh_scan(dev, info, wrqu, extra); +} +static int meshdev_wx_get_mesh_list(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; +printk("++++++======%s\n", __FUNCTION__); + + return r8192_wx_get_mesh_list(dev, info, wrqu, extra); +} +static int meshdev_wx_set_meshmode(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + +printk("++++++======%s\n", __FUNCTION__); + return r8192_wx_set_meshmode(dev, info, wrqu, extra); +} +static int meshdev_wx_set_meshbw(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + +printk("++++++======%s\n", __FUNCTION__); + return r8192_wx_set_meshBW(dev, info, wrqu, extra); +} +static int meshdev_wx_update_beacon(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = rtllib_priv(dev); + struct mshclass *mshobj= (priv)->mshobj; + u8 updateBW = 0; + u8 bserverHT = 0; + + printk("++++++======%s\n", __FUNCTION__); + if(*extra == 0) + { + ieee->p2pmode = 1; + ieee->current_network.channel = ieee->current_mesh_network.channel; + if(ieee->state!=RTLLIB_LINKED){ + if(ieee->pHTInfo->bCurBW40MHz) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + } + } + else + { + ieee->p2pmode = 0; + updateBW=mshobj->ext_patch_r819x_wx_update_beacon(dev,&bserverHT); + printk("$$$$$$ Cur_networ.chan=%d, cur_mesh_net.chan=%d,bserverHT=%d\n", ieee->current_network.channel,ieee->current_mesh_network.channel,bserverHT); + if(updateBW == 1) + { + if(bserverHT == 0) + { + printk("===>server is not HT supported,set 20M\n"); + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + } + else + { + printk("===>updateBW is 1,bCurBW40MHz is %d,ieee->serverExtChlOffset is %d\n",ieee->pHTInfo->bCurBW40MHz,ieee->serverExtChlOffset); + if(ieee->pHTInfo->bCurBW40MHz) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, ieee->serverExtChlOffset); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, ieee->serverExtChlOffset); + } + } + else + { + printk("===>there is no same hostname server, ERR!!!\n"); + return -1; + } + } +#ifdef RTL8192SE + write_nic_dword(dev,BSSIDR,((u32*)priv->rtllib->current_mesh_network.bssid)[0]); + write_nic_word(dev,BSSIDR+4,((u16*)priv->rtllib->current_mesh_network.bssid)[2]); +#elif defined RTL8192CE + write_nic_dword(dev,REG_BSSID,((u32*)priv->rtllib->current_mesh_network.bssid)[0]); + write_nic_word(dev,REG_BSSID+4,((u16*)priv->rtllib->current_mesh_network.bssid)[2]); +#endif + + return 0; +} +static int meshdev_wx_add_mac_deny(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = rtllib_priv(dev); + + + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_add_mac_deny ) + return 0; + + return priv->mshobj->ext_patch_r819x_wx_set_add_mac_deny(dev, info, wrqu, extra); +} + +static int meshdev_wx_del_mac_deny(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = rtllib_priv(dev); + + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_del_mac_deny ) + return 0; + + return priv->mshobj->ext_patch_r819x_wx_set_del_mac_deny(dev, info, wrqu, extra); +} + +static int meshdev_wx_get_neighbor_list(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = rtllib_priv(dev); + int ret = 0; + + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_get_neighbor_list ) + return 0; + ret = priv->mshobj->ext_patch_r819x_wx_get_neighbor_list(dev, info, wrqu, extra); +#ifdef MESH_AUTO_TEST + ret |= r8192_wx_set_channel(dev, info, wrqu, &ieee->current_network.channel); +#endif + return ret; +} + +/* reserved for future +static int r819x_wx_get_mac_allow(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + return 0; + + return priv->mshobj->ext_patch_r819x_wx_get_mac_allow(dev, info, wrqu, extra); +} +*/ + +static int meshdev_wx_get_mac_deny(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = rtllib_priv(dev); + + if( ! priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_get_mac_deny ) + return 0; + + return priv->mshobj->ext_patch_r819x_wx_get_mac_deny(dev, info, wrqu, extra); +} + + +static int meshdev_wx_set_hostname(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + + if(wrqu->data.length > MAX_HOST_NAME_LENGTH) + { + printk("%s: Host name is too long. len=%d\n", __FUNCTION__, wrqu->data.length); + return -1; + } + + ieee->hostname_len = wrqu->data.length; + memcpy(ieee->hostname, extra, wrqu->data.length); + +printk("++++++======%s: %s\n", __FUNCTION__, ieee->hostname); + + return 0; +} +static int meshdev_wx_set_mesh_security(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = netdev_priv(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + printk("++++++======%s\n", __FUNCTION__); + return r8192_wx_set_mesh_security(dev, info, wrqu, extra); +} +static int meshdev_wx_set_mkdd_id(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = netdev_priv(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + + printk("++++++======%s\n", __FUNCTION__); + return r8192_wx_set_mkdd_id(dev, info, wrqu, extra); +} +static int meshdev_wx_set_mesh_key(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = netdev_priv(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + printk("++++++======%s\n", __FUNCTION__); + return r8192_wx_set_mesh_key(dev, info, wrqu, extra); +} +static int meshdev_wx_set_sec_type(struct net_device *meshdev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct meshdev_priv *mpriv = netdev_priv(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + + printk("++++++======%s\n", __FUNCTION__); + return r8192_wx_set_mesh_sec_type(dev, info, wrqu, extra); +} +static u8 my_atoi(const char *arg) +{ + u8 val = 0; + for(; ; arg++){ + switch (*arg){ + case '0'...'9': + val = 10*val + (*arg-'0'); + break; + default: + return val; + } + } + return val; +} + +static int Set_Channel_Proc(struct net_device *meshdev, char *arg) +{ + int ch = my_atoi(arg); + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct r8192_priv *priv = (void *)ieee->priv; + struct net_device *dev = ieee->dev; + + if (!priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_set_channel || !ieee->only_mesh) + return 0; + +printk("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!set current mesh network channel %d\n", ch); + if ( ch < 0 ) + { + rtllib_start_scan(ieee); + ieee->meshScanMode =2; + } + else + { + ieee->meshScanMode =0; + if(priv->mshobj->ext_patch_r819x_wx_set_channel) + { + priv->mshobj->ext_patch_r819x_wx_set_channel(ieee, ch); + priv->mshobj->ext_patch_r819x_wx_set_mesh_chan(dev,ch); + } + queue_work_rsl(ieee->wq, &ieee->ext_stop_scan_wq); + ieee->set_chan(ieee->dev, ch); + ieee->current_mesh_network.channel = ch; + if(ieee->only_mesh) + ieee->current_network.channel = ch; + ieee->current_network.channel = ieee->current_mesh_network.channel; + if(ieee->pHTInfo->bCurBW40MHz) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_mesh_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + if(rtllib_act_scanning(ieee,true) == true) + rtllib_stop_scan_syncro(ieee); + } + return 0; +} +static int Set_MeshID_Proc(struct net_device *meshdev, char *arg) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = rtllib_priv(dev); + RT_RF_POWER_STATE rtState; + int ret = 0; + rtState = priv->rtllib->eRFPowerState; + + if(!priv->mshobj || !priv->mshobj->ext_patch_r819x_wx_enable_mesh || !priv->mshobj->ext_patch_r819x_wx_set_meshID) + return 0; + + if(rtllib_act_scanning(ieee,true) == true) + rtllib_stop_scan_syncro(ieee); + + /* Set Mesh ID */ + ret = priv->mshobj->ext_patch_r819x_wx_set_meshID(dev, arg); + if(ret) + goto End; + + /* Enable Mesh */ + SEM_DOWN_PRIV_WX(&priv->wx_sem); + ret = priv->mshobj->ext_patch_r819x_wx_enable_mesh(dev); + if(!ret) + { +#ifdef ENABLE_IPS + if(priv->rtllib->PowerSaveControl.bInactivePs){ + if(rtState == eRfOff){ + if(priv->rtllib->RfOffReason > RF_CHANGE_BY_IPS) + { + RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__); + SEM_UP_PRIV_WX(&priv->wx_sem); + return -1; + } + else{ + printk("=========>%s(): IPSLeave\n",__FUNCTION__); + IPSLeave(dev); + } + } + } +#endif + } + SEM_UP_PRIV_WX(&priv->wx_sem); +#if 1 + if (ieee->mesh_sec_type == 1) { + rtl8192_abbr_handshk_set_GTK(ieee,1); + } +#else + if (ieee->mesh_sec_type == 1) + rtl8192_abbr_handshk_set_key(ieee); +#endif +End: + return ret; +} +static int Set_Bw40MHz_Proc(struct net_device *meshdev, char *arg) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct r8192_priv *priv = (void *)ieee->priv; + u8 bBw40MHz = my_atoi(arg); + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + printk("%s(): set mesh BW ! extra is %d\n",__FUNCTION__, bBw40MHz); + priv->rtllib->pHTInfo->bRegBW40MHz = bBw40MHz; + SEM_UP_PRIV_WX(&priv->wx_sem); + + return 0; +} +static int Set_WirelessMode_Proc(struct net_device *meshdev, char *arg) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct r8192_priv *priv = (void *)ieee->priv; + struct net_device *dev = ieee->dev; + u8 wirelessmode = my_atoi(arg); + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + + printk("%s(): set mesh mode ! extra is %d\n",__FUNCTION__, wirelessmode); + if((wirelessmode != WIRELESS_MODE_A) && (wirelessmode != WIRELESS_MODE_B) && + (wirelessmode != WIRELESS_MODE_G) && (wirelessmode != WIRELESS_MODE_AUTO) && + (wirelessmode != WIRELESS_MODE_N_24G) && (wirelessmode != WIRELESS_MODE_N_5G)) + { + printk("ERR!! you should input 1 | 2 | 4 | 8 | 16 | 32\n"); + SEM_UP_PRIV_WX(&priv->wx_sem); + return -1; + } + if(priv->rtllib->state == RTLLIB_LINKED) + { + if((priv->rtllib->mode != WIRELESS_MODE_N_5G) && (priv->rtllib->mode != WIRELESS_MODE_N_24G)){ + printk("===>wlan0 is linked,and ieee->mode is not N mode ,do not need to set mode,return\n"); + SEM_UP_PRIV_WX(&priv->wx_sem); + return 0; + } + } + priv->rtllib->mode = wirelessmode; + if(priv->ResetProgress == RESET_TYPE_NORESET) + rtl8192_SetWirelessMode(dev, priv->rtllib->mode); + HTUseDefaultSetting(priv->rtllib); + SEM_UP_PRIV_WX(&priv->wx_sem); + return 0; +} +static int Set_ExtChnOffset_Proc(struct net_device *meshdev, char *arg) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; +#if 0 + struct r8192_priv *priv = (void *)ieee->priv; + struct net_device *dev = ieee->dev; + struct mshclass *mshobj= priv->mshobj; + u8 updateBW = 0; + u8 bserverHT = 0; +#endif + ieee->p2pmode = 0; +#if 0 + updateBW=mshobj->ext_patch_r819x_wx_update_beacon(dev,&bserverHT); + printk("$$$$$$ Cur_networ.chan=%d, cur_mesh_net.chan=%d,bserverHT=%d\n", ieee->current_network.channel,ieee->current_mesh_network.channel,bserverHT); + if(updateBW == 1) + { + if(bserverHT == 0) + { + printk("===>server is not HT supported,set 20M\n"); + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + } + else + { + printk("===>updateBW is 1,bCurBW40MHz is %d,ieee->serverExtChlOffset is %d\n",ieee->pHTInfo->bCurBW40MHz,ieee->serverExtChlOffset); + if(ieee->pHTInfo->bCurBW40MHz) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, ieee->serverExtChlOffset); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, ieee->serverExtChlOffset); + } + } + else + { + printk("===>there is no same hostname server, ERR!!!\n"); + return -1; + } +#endif + return 0; +} +static int Set_OnlyMesh_Proc(struct net_device *meshdev, char *arg) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + union iwreq_data tmprqu; + int ret = 0; + + ieee->p2pmode = 1; + ieee->only_mesh = my_atoi(arg); +printk("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!mesh only = %d, p2pmode = %d\n", ieee->only_mesh, ieee->p2pmode); + if(ieee->only_mesh) + ieee->current_network.channel = ieee->current_mesh_network.channel; + if(ieee->only_mesh == 0) + { + tmprqu.mode = ieee->iw_mode; + ieee->iw_mode = IW_MODE_INFRA; + ret = rtllib_wx_set_mode(ieee, NULL, &tmprqu, NULL); + } + return ret; +} +static int Set_AsPortal_Proc(struct net_device *meshdev, char *arg) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = (void *)ieee->priv; + u8 val = my_atoi(arg); + int ret = 0; + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + ret = priv->mshobj->ext_patch_r819x_wx_set_AsPortal(dev, val); + SEM_UP_PRIV_WX(&priv->wx_sem); + + return ret; +} +static int Set_AsRoot_Proc(struct net_device *meshdev, char *arg) +{ + struct meshdev_priv *mpriv = (struct meshdev_priv *)netdev_priv_rsl(meshdev); + struct rtllib_device *ieee = mpriv->rtllib; + struct net_device *dev = ieee->dev; + struct r8192_priv *priv = (void *)ieee->priv; + u8 val = my_atoi(arg); + int ret = 0; + + SEM_DOWN_PRIV_WX(&priv->wx_sem); + ret = priv->mshobj->ext_patch_r819x_wx_set_AsRoot(dev, val); + SEM_UP_PRIV_WX(&priv->wx_sem); + + return ret; +} + +static struct { + char* name; + int (*set_proc)(struct net_device *dev, char *arg); +} *private_set_proc, private_support_proc[] = { + {"Debug", NULL}, + {"Channel", Set_Channel_Proc}, + {"MeshId", Set_MeshID_Proc}, + {"Bw40MHz", Set_Bw40MHz_Proc}, + {"WirelessMode", Set_WirelessMode_Proc}, + {"ExtChnOffset", Set_ExtChnOffset_Proc}, + {"OnlyMesh", Set_OnlyMesh_Proc}, + {"AsPortal", Set_AsPortal_Proc}, + {"AsRoot", Set_AsRoot_Proc}, + {"MeshAuthMode", NULL}, + {"MeshEncrypType", NULL}, + {"", NULL}, +}; + +static char *rtlstrchr(const char *s, int c) +{ + for(; *s!=(char)c; ++s) + if(*s == '\0') + return NULL; + return (char *)s; +} + +static int meshdev_wx_set_param(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *w, char *extra) +{ + char * this_char = extra; + char *value = NULL; + int Status=0; + + printk("=======>%s: extra=%s\n", __FUNCTION__,extra); + if (!*this_char) + return -EINVAL; + + if ((value = rtlstrchr(this_char, '=')) != NULL) + *value++ = 0; + + for (private_set_proc = private_support_proc; strcmp(private_set_proc->name, ""); private_set_proc++) + { + if (strcmp(this_char, private_set_proc->name) == 0) + { + if(private_set_proc->set_proc) + { + if(private_set_proc->set_proc(dev, value)) + { + Status = -EINVAL; + } + } + break; + } + } + + if(strcmp(private_set_proc->name, "") == 0) + { + Status = -EINVAL; + printk("===>%s: (iwpriv) Not Support Set Command [%s]", __FUNCTION__, this_char); + if(value != NULL) + printk(" value=%s\n", value); + else + printk("\n"); + } + + return Status; +} + + +static iw_handler meshdev_private_handler[] = { + meshdev_wx_enable_mesh, + meshdev_wx_get_meshinfo, + meshdev_wx_disable_mesh, + meshdev_wx_set_channel, + meshdev_wx_set_meshid, + meshdev_wx_get_mesh_list, + meshdev_wx_mesh_scan, + meshdev_wx_set_meshmode, + meshdev_wx_set_hostname, + meshdev_wx_set_meshbw, + meshdev_wx_update_beacon, + meshdev_wx_get_mac_deny, + meshdev_wx_add_mac_deny, + NULL, + NULL, + meshdev_wx_get_neighbor_list, + meshdev_wx_set_param, + NULL, + meshdev_wx_del_mac_deny, + NULL, + meshdev_wx_set_mesh_security, + meshdev_wx_set_mkdd_id, + meshdev_wx_set_mesh_key, + meshdev_wx_set_sec_type, +}; + +struct iw_handler_def meshdev_wx_handlers_def={ + .standard = meshdev_wx_handlers, + .num_standard = sizeof(meshdev_wx_handlers) / sizeof(iw_handler), + .private = meshdev_private_handler, + .num_private = sizeof(meshdev_private_handler) / sizeof(iw_handler), + .num_private_args = sizeof(meshdev_private_args) / sizeof(struct iw_priv_args), +#if WIRELESS_EXT >= 17 + .get_wireless_stats = (void*)meshdev_stats, +#endif + .private_args = (struct iw_priv_args *)meshdev_private_args, +}; +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl_wx.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl_wx.h @@ -0,0 +1,34 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + +#ifndef R819x_WX_H +#define R819x_WX_H + +struct net_device; +struct iw_handler_def; +struct iw_statistics; + +extern struct iw_handler_def r8192_wx_handlers_def; +struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev); +u16 rtl8192_11n_user_show_rates(struct net_device* dev); + +#ifdef _RTL8192_EXT_PATCH_ +extern struct iw_handler_def meshdev_wx_handlers_def; +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/Makefile +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/Makefile @@ -0,0 +1,10 @@ +.PHONY:clean +clean: + rm -fr *.mod.c *.mod *.o .*.cmd *.ko *~ + rm -fr .tmp_versions + rm -fr Modules.symvers + rm -fr Module.symvers + rm -fr Module.markers + rm -fr modules.order + rm -fr tags + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_Efuse.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_Efuse.c @@ -0,0 +1,1867 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#include "../rtl_core.h" +#include + +#ifdef RTL8192SE +/*---------------------------Define Local Constant---------------------------*/ +#define _POWERON_DELAY_ +#define _PRE_EXECUTE_READ_CMD_ + +#define EFUSE_REPEAT_THRESHOLD_ 3 +#define EFUSE_ERROE_HANDLE 1 + + +typedef struct _EFUSE_MAP_A{ + u8 offset; + u8 word_start; + u8 byte_start; + u8 byte_cnts; + +}EFUSE_MAP, *PEFUSE_MAP; + +typedef struct PG_PKT_STRUCT_A{ + u8 offset; + u8 word_en; + u8 data[8]; +}PGPKT_STRUCT,*PPGPKT_STRUCT; + +typedef enum _EFUSE_DATA_ITEM{ + EFUSE_CHIP_ID=0, + EFUSE_LDO_SETTING, + EFUSE_CLK_SETTING, + EFUSE_SDIO_SETTING, + EFUSE_CCCR, + EFUSE_SDIO_MODE, + EFUSE_OCR, + EFUSE_F0CIS, + EFUSE_F1CIS, + EFUSE_MAC_ADDR, + EFUSE_EEPROM_VER, + EFUSE_CHAN_PLAN, + EFUSE_TXPW_TAB +} EFUSE_DATA_ITEM; + +struct efuse_priv +{ + u8 id[2]; + u8 ldo_setting[2]; + u8 clk_setting[2]; + u8 cccr; + u8 sdio_mode; + u8 ocr[3]; + u8 cis0[17]; + u8 cis1[48]; + u8 mac_addr[6]; + u8 eeprom_verno; + u8 channel_plan; + u8 tx_power_b[14]; + u8 tx_power_g[14]; +}; + +/*---------------------------Define Local Constant---------------------------*/ + + +/*------------------------Define global variable-----------------------------*/ +const u8 MAX_PGPKT_SIZE = 9; +const u8 PGPKT_DATA_SIZE = 8; +const u32 EFUSE_MAX_SIZE = 512; + +const u8 EFUSE_OOB_PROTECT_BYTES = 15; + + +const EFUSE_MAP RTL8712_SDIO_EFUSE_TABLE[]={ +/*ID*/ {0 ,0 ,0 ,2 }, +/*LDO Setting*/ {0 ,1 ,0 ,2 }, +/*CLK Setting*/ {0 ,2 ,0 ,2 }, +/*SDIO Setting*/{1 ,0 ,0 ,1 }, +/*CCCR*/ {1 ,0 ,1 ,1 }, +/*SDIO MODE*/ {1 ,1 ,0 ,1 }, +/*OCR*/ {1 ,1 ,1 ,3 }, +/*CCIS*/ {1 ,3 ,0 ,17 }, +/*F1CIS*/ {3 ,3 ,1 ,48 }, +/*MAC Addr*/ {10 ,0 ,0 ,6 }, +/*EEPROM ver*/ {10 ,3 ,0 ,1 }, +/*Channel plan*/{10 ,3 ,1 ,1 }, +/*TxPwIndex */ {11 ,0 ,0 ,28 } +}; + +/*------------------------Define global variable-----------------------------*/ + + +/*------------------------Define local variable------------------------------*/ + +/*------------------------Define local variable------------------------------*/ + + +/*--------------------Define function prototype-----------------------*/ +extern void +EFUSE_Initialize(struct net_device* dev); +extern u8 +EFUSE_Read1Byte(struct net_device* dev, u16 Address); +extern void +EFUSE_Write1Byte(struct net_device* dev, u16 Address,u8 Value); + +static void +efuse_ShadowRead1Byte(struct net_device* dev,u16 Offset,u8 *Value); +static void +efuse_ShadowRead2Byte(struct net_device* dev, u16 Offset,u16 *Value ); +static void +efuse_ShadowRead4Byte(struct net_device* dev, u16 Offset,u32 *Value ); +static void +efuse_ShadowWrite1Byte(struct net_device* dev, u16 Offset, u8 Value); +static void +efuse_ShadowWrite2Byte(struct net_device* dev, u16 Offset,u16 Value); +static void +efuse_ShadowWrite4Byte(struct net_device* dev, u16 Offset,u32 Value); + +static u8 +efuse_OneByteRead(struct net_device* dev,u16 addr,u8 *data); +static u8 +efuse_OneByteWrite(struct net_device* dev,u16 addr, u8 data); + +static void +efuse_ReadAllMap(struct net_device* dev,u8 *Efuse); +#ifdef TO_DO_LIST +static void +efuse_WriteAllMap(struct net_device* dev,u8 *eeprom,u32 eeprom_size); +static bool +efuse_ParsingMap(char* szStr,u32* pu4bVal,u32* pu4bMove); +#endif +static u8 +efuse_PgPacketRead( struct net_device* dev,u8 offset,u8 *data); +static u8 +efuse_PgPacketWrite(struct net_device* dev,u8 offset,u8 word_en,u8 *data); +static void +efuse_WordEnableDataRead( u8 word_en,u8 *sourdata,u8 *targetdata); +static u8 +efuse_WordEnableDataWrite( struct net_device* dev, u16 efuse_addr, u8 word_en, u8 *data); +static void +efuse_PowerSwitch(struct net_device* dev,u8 PwrState); +static u16 +efuse_GetCurrentSize(struct net_device* dev); +static u8 +efuse_CalculateWordCnts(u8 word_en); +#if 0 +static void +efuse_ResetLoader(struct net_device* dev); +#endif +#ifdef TO_DO_LIST +static void efuse_reg_ctrl(struct net_device* dev, u8 bPowerOn); +#endif +/*--------------------Define function prototype-----------------------*/ + + + +extern void +EFUSE_Initialize(struct net_device* dev) +{ + u8 Bytetemp = {0x00}; + u8 temp = {0x00}; + + Bytetemp = read_nic_byte(dev, SYS_FUNC_EN+1); + temp = Bytetemp | 0x20; + write_nic_byte(dev, SYS_FUNC_EN+1, temp); + + Bytetemp = read_nic_byte(dev, SYS_ISO_CTRL+1); + temp = Bytetemp & 0xFE; + write_nic_byte(dev, SYS_ISO_CTRL+1, temp); + + + Bytetemp = read_nic_byte(dev, EFUSE_TEST+3); + temp = Bytetemp | 0x80; + write_nic_byte(dev, EFUSE_TEST+3, temp); + + write_nic_byte(dev, 0x2F8, 0x3); + + write_nic_byte(dev, EFUSE_CTRL+3, 0x72); + +} /* EFUSE_Initialize */ + + +extern u8 +EFUSE_Read1Byte(struct net_device* dev, u16 Address) +{ + u8 data; + u8 Bytetemp = {0x00}; + u8 temp = {0x00}; + u32 k=0; + + if (Address < EFUSE_REAL_CONTENT_LEN) + { + temp = Address & 0xFF; + write_nic_byte(dev, EFUSE_CTRL+1, temp); + Bytetemp = read_nic_byte(dev, EFUSE_CTRL+2); + temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC); + write_nic_byte(dev, EFUSE_CTRL+2, temp); + + Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); + temp = Bytetemp & 0x7F; + write_nic_byte(dev, EFUSE_CTRL+3, temp); + + Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); + while(!(Bytetemp & 0x80)) + { + Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); + k++; + if(k==1000) + { + k=0; + break; + } + } + data=read_nic_byte(dev, EFUSE_CTRL); + return data; + } + else + return 0xFF; + +} /* EFUSE_Read1Byte */ + + +extern void +EFUSE_Write1Byte(struct net_device* dev, u16 Address,u8 Value) +{ + u8 Bytetemp = {0x00}; + u8 temp = {0x00}; + u32 k=0; + + + if( Address < EFUSE_REAL_CONTENT_LEN) + { + write_nic_byte(dev, EFUSE_CTRL, Value); + + temp = Address & 0xFF; + write_nic_byte(dev, EFUSE_CTRL+1, temp); + Bytetemp = read_nic_byte(dev, EFUSE_CTRL+2); + + temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC); + write_nic_byte(dev, EFUSE_CTRL+2, temp); + + Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); + temp = Bytetemp | 0x80; + write_nic_byte(dev, EFUSE_CTRL+3, temp); + + Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); + while(Bytetemp & 0x80) + { + Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); + k++; + if(k==100) + { + k=0; + break; + } + } + } + +} /* EFUSE_Write1Byte */ + + +#ifdef EFUSE_FOR_92SU +void do_93c46(struct net_device* dev, u8 addorvalue) +{ + u8 cs[1] = {0x88}; + u8 cssk[1] = {0x8c}; + u8 csdi[1] = {0x8a}; + u8 csskdi[1] = {0x8e}; + u8 count; + + for(count=0 ; count<8 ; count++) + { + if((addorvalue&0x80)!=0) + { + write_nic_byte(dev, EPROM_CMD, csdi[0]); + write_nic_byte(dev, EPROM_CMD, csskdi[0]); + } + else + { + write_nic_byte(dev, EPROM_CMD, cs[0]); + write_nic_byte(dev, EPROM_CMD, cssk[0]); + } + addorvalue = addorvalue << 1; + } +} + + +u16 Read93C46(struct net_device* dev, u16 Reg ) +{ + + u8 clear[1] = {0x0}; + u8 cs[1] = {0x88}; + u8 cssk[1] = {0x8c}; + u8 csdi[1] = {0x8a}; + u8 csskdi[1] = {0x8e}; + u8 EepromSEL[1]={0x00}; + u8 address; + + u16 storedataF[1] = {0x0}; + u8 t,data[1],storedata[1]; + + + address = (u8)Reg; + + *EepromSEL= read_nic_byte(dev, EPROM_CMD); + + if((*EepromSEL & 0x10) == 0x10) + { + address = address | 0x80; + + write_nic_byte(dev, EPROM_CMD, csdi[0]); + write_nic_byte(dev, EPROM_CMD, csskdi[0]); + do_93c46(dev, address); + } + + + for(t=0 ; t<16 ; t++) + { + write_nic_byte(dev, EPROM_CMD, cs[0]); + write_nic_byte(dev, EPROM_CMD, cssk[0]); + *data= read_nic_byte(dev, EPROM_CMD); + + if(*data & 0x8d) + { + *data = *data & 0x01; + *storedata = *data; + } + else + { + *data = *data & 0x01 ; + *storedata = *data; + } + *storedataF = (*storedataF << 1 ) + *storedata; + } + write_nic_byte(dev, EPROM_CMD, cs[0]); + write_nic_byte(dev, EPROM_CMD, clear[0]); + + return *storedataF; +} + + +void +ReadEFuseByte(struct net_device* dev,u16 _offset, u8 *pbuf) +{ + + u32 value32; + u8 readbyte; + u16 retry; + + + write_nic_byte(dev, EFUSE_CTRL+1, (_offset & 0xff)); + readbyte = read_nic_byte(dev, EFUSE_CTRL+2); + write_nic_byte(dev, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc)); + + readbyte = read_nic_byte(dev, EFUSE_CTRL+3); + write_nic_byte(dev, EFUSE_CTRL+3, (readbyte & 0x7f)); + + retry = 0; + value32 = read_nic_dword(dev, EFUSE_CTRL); + while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10000)) + { + value32 = read_nic_dword(dev, EFUSE_CTRL); + retry++; + } + *pbuf = (u8)(value32 & 0xff); +} + + +#define EFUSE_READ_SWITCH 1 +void +ReadEFuse(struct net_device* dev, u16 _offset, u16 _size_byte, u8 *pbuf) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 efuseTbl[EFUSE_MAP_LEN]; + u8 rtemp8[1]; + u16 eFuse_Addr = 0; + u8 offset, wren; + u16 i, j; + u16 eFuseWord[EFUSE_MAX_SECTION][EFUSE_MAX_WORD_UNIT]; + u16 efuse_utilized = 0; + u16 efuse_usage = 0; +#ifdef EFUSE_REPG_WORKAROUND + u16 sec1_addr = 0, sec5_addr = 0; +#endif + + if((_offset + _size_byte)>EFUSE_MAP_LEN) + { + printk("ReadEFuse(): Invalid offset with read bytes!!\n"); + return; + } + + for (i = 0; i < EFUSE_MAX_SECTION; i++) + for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) + eFuseWord[i][j]=0xFFFF; + + for (i = 0; i < EFUSE_MAP_LEN; i++) + efuseTbl[i] = 0xFF; + + ReadEFuseByte(dev, eFuse_Addr, rtemp8); + if(*rtemp8 != 0xFF) + { + efuse_utilized++; + eFuse_Addr++; + } + while((*rtemp8 != 0xFF) && (eFuse_Addr < EFUSE_REAL_CONTENT_LEN)) + { + offset = ((*rtemp8 >> 4) & 0x0f); +#ifdef EFUSE_REPG_WORKAROUND + if (IS_HARDWARE_TYPE_8192SE(dev)) + { + if (offset == 1) + { + sec1_addr = eFuse_Addr; + } + else if (offset == 5) + { + sec5_addr = eFuse_Addr; + } + + if (sec1_addr > sec5_addr) + { + priv->efuse_RePGSec1Flag = false; + } + else + { + priv->efuse_RePGSec1Flag = true; + } + } +#endif + if(offset < EFUSE_MAX_SECTION){ + wren = (*rtemp8 & 0x0f); + for(i=0; i<4; i++){ + if(!(wren & 0x01)){ + ReadEFuseByte(dev, eFuse_Addr, rtemp8); eFuse_Addr++; + efuse_utilized++; + eFuseWord[offset][i] = (*rtemp8 & 0xff); + if(eFuse_Addr >= EFUSE_REAL_CONTENT_LEN) break; + ReadEFuseByte(dev, eFuse_Addr, rtemp8); eFuse_Addr++; + efuse_utilized++; + eFuseWord[offset][i] |= (((u16)*rtemp8 << 8) & 0xff00); + if(eFuse_Addr >= EFUSE_REAL_CONTENT_LEN) break; + } + wren >>= 1; + } + } + ReadEFuseByte(dev, eFuse_Addr, rtemp8); + if(*rtemp8 != 0xFF && (eFuse_Addr < 512)) + { + efuse_utilized++; + eFuse_Addr++; + } + } + + for(i=0; i> 8) & 0xff); +#ifdef FUSE_REPG_WORKAROUND + if ((i == 1) && (priv->efuse_RePGSec1Flag == true)) + { + priv->efuse_RePGData[j*2]=(eFuseWord[i][j] & 0xff); + priv->efuse_RePGData[(j*2)+1]=((eFuseWord[i][j] >> 8) & 0xff); + } +#endif + } + } + for(i=0; i<_size_byte; i++) + pbuf[i] = efuseTbl[_offset+i]; + priv->EfuseUsedBytes = efuse_utilized; + efuse_usage = (u8)((efuse_utilized*100)/EFUSE_REAL_CONTENT_LEN); + priv->EfuseUsedPercentage = efuse_usage; +} +#endif + +extern bool EFUSE_ShadowUpdateChk(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 SectionIdx, i, Base; + u16 WordsNeed = 0, HdrNum = 0, TotalBytes = 0, EfuseUsed = 0; + bool bWordChanged, bResult = true; + + for (SectionIdx = 0; SectionIdx < 16; SectionIdx++) { + Base = SectionIdx * 8; + bWordChanged = false; + + for (i = 0; i < 8; i=i+2) { + if((priv->EfuseMap[EFUSE_INIT_MAP][Base+i] != + priv->EfuseMap[EFUSE_MODIFY_MAP][Base+i]) || + (priv->EfuseMap[EFUSE_INIT_MAP][Base+i+1] != + priv->EfuseMap[EFUSE_MODIFY_MAP][Base+i+1])) { + WordsNeed++; + bWordChanged = true; + } + } + + if( bWordChanged == true ) + HdrNum++; + } + + TotalBytes = HdrNum + WordsNeed * 2; + EfuseUsed = priv->EfuseUsedBytes; + + if ((TotalBytes + EfuseUsed) >= (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES)) + bResult = false; + + return bResult; +} + +extern void +EFUSE_ShadowRead( struct net_device* dev, u8 Type, u16 Offset, u32 *Value) +{ + + if (Type == 1) + efuse_ShadowRead1Byte(dev, Offset, (u8 *)Value); + else if (Type == 2) + efuse_ShadowRead2Byte(dev, Offset, (u16 *)Value); + else if (Type == 4) + efuse_ShadowRead4Byte(dev, Offset, (u32 *)Value); + +} + + +extern void +EFUSE_ShadowWrite( struct net_device* dev, u8 Type, u16 Offset,u32 Value) +{ + + if (Offset >= 0x18 && Offset <= 0x1F) + return; + + if (Type == 1) + efuse_ShadowWrite1Byte(dev, Offset, (u8)Value); + else if (Type == 2) + efuse_ShadowWrite2Byte(dev, Offset, (u16)Value); + else if (Type == 4) + efuse_ShadowWrite4Byte(dev, Offset, (u32)Value); + +} + + +extern bool EFUSE_ShadowUpdate(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u16 i, offset, base = 0; + u8 word_en = 0x0F; + bool first_pg = false; + + if (!EFUSE_ShadowUpdateChk(dev)) { + efuse_ReadAllMap(dev, &priv->EfuseMap[EFUSE_INIT_MAP][0]); + memcpy(&priv->EfuseMap[EFUSE_MODIFY_MAP][0], + (void *)&priv->EfuseMap[EFUSE_INIT_MAP][0], HWSET_MAX_SIZE_92S); + + printk("<---EFUSE_ShadowUpdate(): Efuse out of capacity!!\n"); + return false; + } + + efuse_PowerSwitch(dev, true); + + for (offset = 0; offset < 16; offset++) + { + if(IS_HARDWARE_TYPE_8192SE(dev)){ + if (offset == 3) + continue; + } + word_en = 0x0F; + base = offset * 8; + + for (i = 0; i < 8; i++) + { + if (offset == 0 && priv->EfuseMap[EFUSE_INIT_MAP][base+i] == 0xFF) + { + first_pg = true; + } + + if (first_pg == true && offset == 1 && IS_HARDWARE_TYPE_8192SE(dev)) + { + continue; + } + + if (first_pg == true) + { + word_en &= ~(BIT(i/2)); + priv->EfuseMap[EFUSE_INIT_MAP][base+i] = + priv->EfuseMap[EFUSE_MODIFY_MAP][base+i]; + }else + { + if ( priv->EfuseMap[EFUSE_INIT_MAP][base+i] != + priv->EfuseMap[EFUSE_MODIFY_MAP][base+i]) + { + word_en &= ~(EFUSE_BIT(i/2)); + + priv->EfuseMap[EFUSE_INIT_MAP][base+i] = + priv->EfuseMap[EFUSE_MODIFY_MAP][base+i]; + } + } + } + + if (word_en != 0x0F) + { + u8 tmpdata[8]; + + memcpy(tmpdata, &(priv->EfuseMap[EFUSE_MODIFY_MAP][base]), 8); + efuse_PgPacketWrite(dev,(u8)offset,word_en,tmpdata); + } + + } + if (first_pg == true && IS_HARDWARE_TYPE_8192SE(dev)) + { + u8 tmpdata[8]; + + memcpy(tmpdata, (&priv->EfuseMap[EFUSE_MODIFY_MAP][8]), 8); + efuse_PgPacketWrite(dev, 1, 0x0, tmpdata); +#if 0 + u1Byte tmpdata[8] = {0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF}; + + efuse_PgPacketWrite(pAdapter, 1, 0xD, tmpdata); +#endif + } + + + efuse_PowerSwitch(dev, false); + efuse_ReadAllMap(dev, &priv->EfuseMap[EFUSE_INIT_MAP][0]); + memcpy(&priv->EfuseMap[EFUSE_MODIFY_MAP][0], + (void *)&priv->EfuseMap[EFUSE_INIT_MAP][0], HWSET_MAX_SIZE_92S); + + return true; +} + + +extern void EFUSE_ShadowMapUpdate(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if (priv->AutoloadFailFlag == true){ + memset(&(priv->EfuseMap[EFUSE_INIT_MAP][0]), 0xff, 128); + }else{ + efuse_ReadAllMap(dev, &priv->EfuseMap[EFUSE_INIT_MAP][0]); + } + memcpy(&priv->EfuseMap[EFUSE_MODIFY_MAP][0], + &priv->EfuseMap[EFUSE_INIT_MAP][0], HWSET_MAX_SIZE_92S); + +} + + +extern void +EFUSE_ForceWriteVendorId( struct net_device* dev) +{ + u8 tmpdata[8] = {0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF}; + + efuse_PowerSwitch(dev, true); + + efuse_PgPacketWrite(dev, 1, 0xD, tmpdata); + + efuse_PowerSwitch(dev, false); + +} + +extern void +EFUSE_RePgSection1(struct net_device* dev) +{ +#ifdef EFUSE_REPG_WORKAROUND + + struct r8192_priv *priv = rtllib_priv(dev); + + if (priv->efuse_RePGSec1Flag == true) + { + efuse_PowerSwitch(dev, true); + RT_TRACE(COMP_INIT, "EFUSE REPG: %p, %u\n", priv->efuse_RePGData, 8); + + efuse_PgPacketWrite(dev, 1, 0x0d, priv->efuse_RePGData); + efuse_PowerSwitch(dev, false); + priv->efuse_RePGSec1Flag = false; + } +#endif +} + + +static void +efuse_ShadowRead1Byte(struct net_device* dev, u16 Offset, u8 *Value) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + *Value = priv->EfuseMap[EFUSE_MODIFY_MAP][Offset]; + +} + +static void +efuse_ShadowRead2Byte(struct net_device* dev, u16 Offset, u16 *Value) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + *Value = priv->EfuseMap[EFUSE_MODIFY_MAP][Offset]; + *Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1]<<8; + +} + +static void +efuse_ShadowRead4Byte(struct net_device* dev, u16 Offset, u32 *Value) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + *Value = priv->EfuseMap[EFUSE_MODIFY_MAP][Offset]; + *Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1]<<8; + *Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+2]<<16; + *Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+3]<<24; + +} + + + +static void +efuse_ShadowWrite1Byte(struct net_device* dev, u16 Offset, u8 Value) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + priv->EfuseMap[EFUSE_MODIFY_MAP][Offset] = Value; + +} + +static void +efuse_ShadowWrite2Byte(struct net_device* dev, u16 Offset, u16 Value) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + priv->EfuseMap[EFUSE_MODIFY_MAP][Offset] = Value&0x00FF; + priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1] = Value>>8; + +} + +static void +efuse_ShadowWrite4Byte(struct net_device* dev, u16 Offset, u32 Value) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + priv->EfuseMap[EFUSE_MODIFY_MAP][Offset] = (u8)(Value&0x000000FF); + priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1] = (u8)((Value>>8)&0x0000FF); + priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+2] = (u8)((Value>>16)&0x00FF); + priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+3] = (u8)((Value>>24)&0xFF); + +} + + +static u8 +efuse_OneByteRead(struct net_device* dev, u16 addr,u8 *data) +{ + u8 tmpidx = 0; + u8 bResult; + + write_nic_byte(dev, EFUSE_CTRL+1, (u8)(addr&0xff)); + write_nic_byte(dev, EFUSE_CTRL+2, ((u8)((addr>>8) &0x03) ) | + (read_nic_byte(dev, EFUSE_CTRL+2)&0xFC )); + + write_nic_byte(dev, EFUSE_CTRL+3, 0x72); + + while(!(0x80 &read_nic_byte(dev, EFUSE_CTRL+3))&&(tmpidx<100)) + { + tmpidx++; + } + if(tmpidx<100) + { + *data=read_nic_byte(dev, EFUSE_CTRL); + bResult = true; + } + else + { + *data = 0xff; + bResult = false; + } + return bResult; +} + +static u8 +efuse_OneByteWrite(struct net_device* dev, u16 addr, u8 data) +{ + u8 tmpidx = 0; + u8 bResult; + + + + write_nic_byte(dev, EFUSE_CTRL+1, (u8)(addr&0xff)); + write_nic_byte(dev, EFUSE_CTRL+2, + read_nic_byte(dev, EFUSE_CTRL+2)|(u8)((addr>>8)&0x03) ); + + write_nic_byte(dev, EFUSE_CTRL, data); + write_nic_byte(dev, EFUSE_CTRL+3, 0xF2); + + while((0x80 & read_nic_byte(dev, EFUSE_CTRL+3)) && (tmpidx<100) ){ + tmpidx++; + } + + if(tmpidx<100) + { + bResult = true; + } + else + { + bResult = false; + } + + return bResult; +} + + +static void +efuse_ReadAllMap(struct net_device* dev, u8 *Efuse) +{ + + efuse_PowerSwitch(dev, true); + ReadEFuse(dev, 0, 128, Efuse); + efuse_PowerSwitch(dev, false); +#if 0 + RT_TRACE(COMP_INIT, "efuse_ResetLoader\n"); + efuse_ResetLoader(dev); + + write_nic_byte(dev, EFUSE_CLK, 0x03); + + ReadEFuse(dev, 0, 128, Efuse); + + write_nic_byte(dev, EFUSE_CLK, 0x02); +#if 0 + for(offset = 0;offset<16;offset++) + { + PlatformFillMemory((PVOID)pg_data, 8, 0xff); + efuse_PgPacketRead(pAdapter,offset,pg_data); + + PlatformMoveMemory((PVOID)&Efuse[offset*8], (PVOID)pg_data, 8); + } +#endif + + if (Efuse[0] != 0x29 || Efuse[1] != 0x81) + { + if (index ++ < 5) + { + RT_TRACE(COMP_INIT, "EFUSE R FAIL %d\n", index); + efuse_ReadAllMap(dev, Efuse); + } + } + else + { + index = 0; + } + +#endif +} + + +#ifdef TO_DO_LIST +static void +efuse_WriteAllMap(struct net_device* dev,u8 *eeprom, u32 eeprom_size) +{ + unsigned char word_en = 0x00; + + unsigned char tmpdata[8]; + unsigned char offset; + + efuse_PowerSwitch(dev, true); + + for(offset=0 ; offset< eeprom_size/PGPKT_DATA_SIZE ; offset++) + { + if (IS_HARDWARE_TYPE_8192SE(dev)) + { + if (offset == 3/* || offset > 9*/) + continue; + else + word_en = 0x00; + } + + memcpy(tmpdata, (eeprom+(offset*PGPKT_DATA_SIZE)), 8); + + + efuse_PgPacketWrite(dev,offset,word_en,tmpdata); + + + } + + efuse_PowerSwitch(dev, false); + +} +#endif +static u8 +efuse_PgPacketRead( struct net_device* dev, u8 offset, u8 *data) +{ + u8 ReadState = PG_STATE_HEADER; + + bool bContinual = true; + bool bDataEmpty = true ; + + u8 efuse_data,word_cnts=0; + u16 efuse_addr = 0; + u8 hoffset=0,hworden=0; + u8 tmpidx=0; + u8 tmpdata[8]; + + if(data==NULL) return false; + if(offset>15) return false; + + memset(data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); + memset(tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); + + + while(bContinual && (efuse_addr < EFUSE_MAX_SIZE) ) + { + if(ReadState & PG_STATE_HEADER) + { + if(efuse_OneByteRead(dev, efuse_addr ,&efuse_data)&&(efuse_data!=0xFF)){ + hoffset = (efuse_data>>4) & 0x0F; + hworden = efuse_data & 0x0F; + word_cnts = efuse_CalculateWordCnts(hworden); + bDataEmpty = true ; + + if(hoffset==offset){ + for(tmpidx = 0;tmpidx< word_cnts*2 ;tmpidx++){ + if(efuse_OneByteRead(dev, efuse_addr+1+tmpidx ,&efuse_data) ){ + tmpdata[tmpidx] = efuse_data; + if(efuse_data!=0xff){ + bDataEmpty = false; + } + } + } + if(bDataEmpty==false){ + ReadState = PG_STATE_DATA; + }else{ + efuse_addr = efuse_addr + (word_cnts*2)+1; + ReadState = PG_STATE_HEADER; + } + } + else{ + efuse_addr = efuse_addr + (word_cnts*2)+1; + ReadState = PG_STATE_HEADER; + } + + } + else{ + bContinual = false ; + } + } + else if(ReadState & PG_STATE_DATA) + { + efuse_WordEnableDataRead(hworden,tmpdata,data); + efuse_addr = efuse_addr + (word_cnts*2)+1; + ReadState = PG_STATE_HEADER; + } + + } + + + if( (data[0]==0xff) &&(data[1]==0xff) && (data[2]==0xff) && (data[3]==0xff) && + (data[4]==0xff) &&(data[5]==0xff) && (data[6]==0xff) && (data[7]==0xff)) + return false; + else + return true; + +} + + +static u8 efuse_PgPacketWrite(struct net_device* dev, u8 offset, u8 word_en,u8 *data) +{ + u8 WriteState = PG_STATE_HEADER; + bool bContinual = true,bDataEmpty=true, bResult = true; + u16 efuse_addr = 0; + u8 efuse_data; + + u8 pg_header = 0; + + u8 tmp_word_cnts=0,target_word_cnts=0; + u8 tmp_header,match_word_en,tmp_word_en; + + PGPKT_STRUCT target_pkt; + PGPKT_STRUCT tmp_pkt; + + u8 originaldata[sizeof(u8)*8]; + u8 tmpindex = 0,badworden = 0x0F; + + static u32 repeat_times = 0; + + if (efuse_GetCurrentSize(dev) >= EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES) { + printk("efuse_PgPacketWrite error \n"); + return false; + } + + target_pkt.offset = offset; + target_pkt.word_en= word_en; + + memset(target_pkt.data,0xFF,sizeof(u8)*8); + + efuse_WordEnableDataRead(word_en,data,target_pkt.data); + target_word_cnts = efuse_CalculateWordCnts(target_pkt.word_en); + + printk("EFUSE Power ON\n"); + + while (bContinual && (efuse_addr < (EFUSE_MAX_SIZE - EFUSE_OOB_PROTECT_BYTES))) + { + if(WriteState==PG_STATE_HEADER) + { + bDataEmpty=true; + badworden = 0x0F; + printk("EFUSE PG_STATE_HEADER\n"); + if ( efuse_OneByteRead(dev, efuse_addr ,&efuse_data) && + (efuse_data!=0xFF)) + { + tmp_header = efuse_data; + + tmp_pkt.offset = (tmp_header>>4) & 0x0F; + tmp_pkt.word_en = tmp_header & 0x0F; + tmp_word_cnts = efuse_CalculateWordCnts(tmp_pkt.word_en); + + if(tmp_pkt.offset != target_pkt.offset) + { + efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; + #if (EFUSE_ERROE_HANDLE == 1) + WriteState = PG_STATE_HEADER; + #endif + } + else + { + for(tmpindex=0 ; tmpindex<(tmp_word_cnts*2) ; tmpindex++) + { + if(efuse_OneByteRead(dev, (efuse_addr+1+tmpindex) ,&efuse_data)&&(efuse_data != 0xFF)){ + bDataEmpty = false; + } + } + if(bDataEmpty == false) + { + efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; + #if (EFUSE_ERROE_HANDLE == 1) + WriteState=PG_STATE_HEADER; + #endif + } + else + { + match_word_en = 0x0F; + if( !( (target_pkt.word_en&BIT0)|(tmp_pkt.word_en&BIT0) )) + { + match_word_en &= (~BIT0); + } + if( !( (target_pkt.word_en&BIT1)|(tmp_pkt.word_en&BIT1) )) + { + match_word_en &= (~BIT1); + } + if( !( (target_pkt.word_en&BIT2)|(tmp_pkt.word_en&BIT2) )) + { + match_word_en &= (~BIT2); + } + if( !( (target_pkt.word_en&BIT3)|(tmp_pkt.word_en&BIT3) )) + { + match_word_en &= (~BIT3); + } + + if((match_word_en&0x0F)!=0x0F) + { + badworden = efuse_WordEnableDataWrite(dev,efuse_addr+1, tmp_pkt.word_en ,target_pkt.data); + + if(0x0F != (badworden&0x0F)) + { + u8 reorg_offset = offset; + u8 reorg_worden=badworden; + efuse_PgPacketWrite(dev,reorg_offset,reorg_worden,originaldata); + } + + tmp_word_en = 0x0F; + if( (target_pkt.word_en&BIT0)^(match_word_en&BIT0) ) + { + tmp_word_en &= (~BIT0); + } + if( (target_pkt.word_en&BIT1)^(match_word_en&BIT1) ) + { + tmp_word_en &= (~BIT1); + } + if( (target_pkt.word_en&BIT2)^(match_word_en&BIT2) ) + { + tmp_word_en &= (~BIT2); + } + if( (target_pkt.word_en&BIT3)^(match_word_en&BIT3) ) + { + tmp_word_en &=(~BIT3); + } + + if((tmp_word_en&0x0F)!=0x0F){ + efuse_addr = efuse_GetCurrentSize(dev); + target_pkt.offset = offset; + target_pkt.word_en= tmp_word_en; + }else{ + bContinual = false; + } + #if (EFUSE_ERROE_HANDLE == 1) + WriteState=PG_STATE_HEADER; + repeat_times++; + if(repeat_times>EFUSE_REPEAT_THRESHOLD_){ + bContinual = false; + bResult = false; + } + #endif + } + else{ + efuse_addr = efuse_addr + (2*tmp_word_cnts) +1; + target_pkt.offset = offset; + target_pkt.word_en= target_pkt.word_en; + #if (EFUSE_ERROE_HANDLE == 1) + WriteState=PG_STATE_HEADER; + #endif + } + } + } + printk("EFUSE PG_STATE_HEADER-1\n"); + } + else + { + pg_header = ((target_pkt.offset << 4)&0xf0) |target_pkt.word_en; + + efuse_OneByteWrite(dev,efuse_addr, pg_header); + efuse_OneByteRead(dev,efuse_addr, &tmp_header); + + if(tmp_header == pg_header) + { + WriteState = PG_STATE_DATA; + } + #if (EFUSE_ERROE_HANDLE == 1) + else if(tmp_header == 0xFF){ + WriteState = PG_STATE_HEADER; + repeat_times++; + if(repeat_times>EFUSE_REPEAT_THRESHOLD_){ + bContinual = false; + bResult = false; + } + } + #endif + else + { + tmp_pkt.offset = (tmp_header>>4) & 0x0F; + tmp_pkt.word_en= tmp_header & 0x0F; + tmp_word_cnts = efuse_CalculateWordCnts(tmp_pkt.word_en); + + memset(originaldata,0xff,sizeof(u8)*8); + + if(efuse_PgPacketRead( dev, tmp_pkt.offset,originaldata)) + { + badworden = efuse_WordEnableDataWrite(dev,efuse_addr+1,tmp_pkt.word_en,originaldata); + if(0x0F != (badworden&0x0F)) + { + u8 reorg_offset = tmp_pkt.offset; + u8 reorg_worden=badworden; + efuse_PgPacketWrite(dev,reorg_offset,reorg_worden,originaldata); + efuse_addr = efuse_GetCurrentSize(dev); + } + else{ + efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; + } + } + else + { + efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; + } + + #if (EFUSE_ERROE_HANDLE == 1) + WriteState=PG_STATE_HEADER; + repeat_times++; + if(repeat_times>EFUSE_REPEAT_THRESHOLD_){ + bContinual = false; + bResult = false; + } + #endif + + printk("EFUSE PG_STATE_HEADER-2\n"); + } + + } + + } + else if(WriteState==PG_STATE_DATA) + { + printk("EFUSE PG_STATE_DATA\n"); + badworden = 0x0f; + badworden = efuse_WordEnableDataWrite(dev,efuse_addr+1,target_pkt.word_en,target_pkt.data); + if((badworden&0x0F)==0x0F) + { + bContinual = false; + } + else + { + efuse_addr = efuse_addr + (2*target_word_cnts) +1; + + target_pkt.offset = offset; + target_pkt.word_en= badworden; + target_word_cnts = efuse_CalculateWordCnts(target_pkt.word_en); + #if (EFUSE_ERROE_HANDLE == 1) + WriteState=PG_STATE_HEADER; + repeat_times++; + if(repeat_times>EFUSE_REPEAT_THRESHOLD_){ + bContinual = false; + bResult = false; + } + #endif + printk("EFUSE PG_STATE_HEADER-3\n"); + } + } + } + + + return true; +} + + +static void +efuse_WordEnableDataRead( u8 word_en,u8 *sourdata,u8 *targetdata) +{ + + + + if (!(word_en&BIT0)) + { + targetdata[0] = sourdata[0]; + targetdata[1] = sourdata[1]; + } + if (!(word_en&BIT1)) + { + targetdata[2] = sourdata[2]; + targetdata[3] = sourdata[3]; + } + if (!(word_en&BIT2)) + { + targetdata[4] = sourdata[4]; + targetdata[5] = sourdata[5]; + } + if (!(word_en&BIT3)) + { + targetdata[6] = sourdata[6]; + targetdata[7] = sourdata[7]; + } +} + + +static u8 +efuse_WordEnableDataWrite( struct net_device* dev, u16 efuse_addr, u8 word_en, u8 *data) +{ + u16 tmpaddr = 0; + u16 start_addr = efuse_addr; + u8 badworden = 0x0F; + u8 tmpdata[8]; + + memset(tmpdata,0xff,PGPKT_DATA_SIZE); + + + + if(!(word_en&BIT0)) + { + tmpaddr = start_addr; + efuse_OneByteWrite(dev,start_addr++, data[0]); + efuse_OneByteWrite(dev,start_addr++, data[1]); + + efuse_OneByteRead(dev,tmpaddr, &tmpdata[0]); + efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[1]); + if((data[0]!=tmpdata[0])||(data[1]!=tmpdata[1])){ + badworden &= (~BIT0); + } + } + if(!(word_en&BIT1)) + { + tmpaddr = start_addr; + efuse_OneByteWrite(dev,start_addr++, data[2]); + efuse_OneByteWrite(dev,start_addr++, data[3]); + + efuse_OneByteRead(dev,tmpaddr , &tmpdata[2]); + efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[3]); + if((data[2]!=tmpdata[2])||(data[3]!=tmpdata[3])){ + badworden &=( ~BIT1); + } + } + if(!(word_en&BIT2)) + { + tmpaddr = start_addr; + efuse_OneByteWrite(dev,start_addr++, data[4]); + efuse_OneByteWrite(dev,start_addr++, data[5]); + + efuse_OneByteRead(dev,tmpaddr, &tmpdata[4]); + efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[5]); + if((data[4]!=tmpdata[4])||(data[5]!=tmpdata[5])){ + badworden &=( ~BIT2); + } + } + if(!(word_en&BIT3)) + { + tmpaddr = start_addr; + efuse_OneByteWrite(dev,start_addr++, data[6]); + efuse_OneByteWrite(dev,start_addr++, data[7]); + + efuse_OneByteRead(dev,tmpaddr, &tmpdata[6]); + efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[7]); + if((data[6]!=tmpdata[6])||(data[7]!=tmpdata[7])){ + badworden &=( ~BIT3); + } + } + return badworden; +} + + +static void +efuse_PowerSwitch(struct net_device* dev, u8 PwrState) +{ + u8 tempval; + if (PwrState == true) + { + tempval = read_nic_byte(dev, EFUSE_TEST+3); + write_nic_byte(dev, EFUSE_TEST+3, (tempval | 0x80)); + + write_nic_byte(dev, EFUSE_CLK, 0x03); + } + else + { + tempval = read_nic_byte(dev, EFUSE_TEST+3); + write_nic_byte(dev, EFUSE_TEST+3, (tempval & 0x7F)); + + write_nic_byte(dev, EFUSE_CLK, 0x02); + } + +} /* efuse_PowerSwitch */ + + +static u16 +efuse_GetCurrentSize(struct net_device* dev) +{ + bool bContinual = true; + + u16 efuse_addr = 0; + u8 hoffset=0,hworden=0; + u8 efuse_data,word_cnts=0; + + + while ( bContinual && + efuse_OneByteRead(dev, efuse_addr ,&efuse_data) && + (efuse_addr < EFUSE_MAX_SIZE) ) + { + if(efuse_data!=0xFF) + { + hoffset = (efuse_data>>4) & 0x0F; + hworden = efuse_data & 0x0F; + word_cnts = efuse_CalculateWordCnts(hworden); + efuse_addr = efuse_addr + (word_cnts*2)+1; + } + else + { + bContinual = false ; + } + } + + + return efuse_addr; + +} + + +static u8 +efuse_CalculateWordCnts(u8 word_en) +{ + u8 word_cnts = 0; + if(!(word_en & BIT0)) word_cnts++; + if(!(word_en & BIT1)) word_cnts++; + if(!(word_en & BIT2)) word_cnts++; + if(!(word_en & BIT3)) word_cnts++; + return word_cnts; +} + + +#if 0 +static void efuse_ResetLoader(struct net_device* dev) +{ + u16 tmpU2b; + + tmpU2b = read_nic_word(dev, SYS_FUNC_EN); + write_nic_word(dev, SYS_FUNC_EN, (tmpU2b&~(BIT12))); + mdelay(10); + write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|BIT12)); + mdelay(10); + +} +#endif + + #ifdef TO_DO_LIST +extern bool +EFUSE_ProgramMap(struct net_device* dev, char* pFileName,u8 TableType) +{ + struct r8192_priv *priv = rtllib_priv(dev); + s4Byte nLinesRead, ithLine; + RT_STATUS rtStatus = RT_STATUS_SUCCESS; + char* szLine; + u32 u4bRegValue, u4RegMask; + u32 u4bMove; + u16 index = 0; + u16 i; + u8 eeprom[HWSET_MAX_SIZE_92S]; + + rtStatus = PlatformReadFile( + dev, + pFileName, + (u8*)(priv->BufOfLines), + MAX_LINES_HWCONFIG_TXT, + MAX_BYTES_LINE_HWCONFIG_TXT, + &nLinesRead + ); + + if(rtStatus == RT_STATUS_SUCCESS) + { + memcp(pHalData->BufOfLines3, pHalData->BufOfLines, + nLinesRead*MAX_BYTES_LINE_HWCONFIG_TXT); + pHalData->nLinesRead3 = nLinesRead; + } + + if(rtStatus == RT_STATUS_SUCCESS) + { + printk("szEepromFile(): read %s ok\n", pFileName); + for(ithLine = 0; ithLine < nLinesRead; ithLine++) + { + szLine = pHalData->BufOfLines[ithLine]; + printk("Line-%d String =%s\n", ithLine, szLine); + + if(!IsCommentString(szLine)) + { + for (i = 0; i < 8; i++) + { + u32 j; + + efuse_ParsingMap(szLine, &u4bRegValue, &u4bMove); + + szLine += u4bMove; + eeprom[index++] = (u8)(u4bRegValue&0xff); + eeprom[index++] = (u8)((u4bRegValue>>8)&0xff); + + printk("Addr-%d = %x\n", (ithLine*8+i), u4bRegValue); + } + } + + } + + } + else + { + printk("szEepromFile(): Fail read%s\n", pFileName); + return RT_STATUS_FAILURE; + } + + + + if (TableType == 1) + { + efuse_WriteAllMap(dev, eeprom, HWSET_MAX_SIZE_92S); + } + else + { + for (i = 0; i < HWSET_MAX_SIZE_92S; i++) + EFUSE_ShadowWrite(dev, 1, i, (u32)eeprom[i]); + } + + return rtStatus; +} /* EFUSE_ProgramMap */ + +#endif + +bool IsHexDigit( char chTmp) +{ + if( (chTmp >= '0' && chTmp <= '9') || + (chTmp >= 'a' && chTmp <= 'f') || + (chTmp >= 'A' && chTmp <= 'F') ) + { + return true; + } + else + { + return false; + } +} + +u32 MapCharToHexDigit(char chTmp) +{ + if(chTmp >= '0' && chTmp <= '9') + return (chTmp - '0'); + else if(chTmp >= 'a' && chTmp <= 'f') + return (10 + (chTmp - 'a')); + else if(chTmp >= 'A' && chTmp <= 'F') + return (10 + (chTmp - 'A')); + else + return 0; +} + +#ifdef TO_DO_LIST +static bool +efuse_ParsingMap(char* szStr,u32* pu4bVal,u32* pu4bMove) +{ + char* szScan = szStr; + + if(szStr == NULL || pu4bVal == NULL || pu4bMove == NULL) + { + return false; + } + + *pu4bMove = 0; + *pu4bVal = 0; + + while( *szScan != '\0' && + (*szScan == ' ' || *szScan == '\t') ) + { + szScan++; + (*pu4bMove)++; + } + + if(!IsHexDigit(*szScan)) + { + return false; + } + + do + { + (*pu4bVal) <<= 4; + *pu4bVal += MapCharToHexDigit(*szScan); + + szScan++; + (*pu4bMove)++; + } while(IsHexDigit(*szScan)); + + return true; + +} /* efuse_ParsingMap */ +#endif + +int efuse_one_byte_rw(struct net_device* dev, u8 bRead, u16 addr, u8 *data) +{ + u32 bResult; + u8 tmpidx = 0; + u8 tmpv8=0; + + + write_nic_byte(dev, EFUSE_CTRL+1, (u8)(addr&0xff)); + tmpv8 = ((u8)((addr>>8) &0x03) ) | (read_nic_byte(dev, EFUSE_CTRL+2)&0xFC ); + write_nic_byte(dev, EFUSE_CTRL+2, tmpv8); + + if(true==bRead){ + + write_nic_byte(dev, EFUSE_CTRL+3, 0x72); + + while(!(0x80 & read_nic_byte(dev, EFUSE_CTRL+3)) && (tmpidx<100) ){ + tmpidx++; + } + if(tmpidx<100){ + *data=read_nic_byte(dev, EFUSE_CTRL); + bResult = true; + } + else + { + *data = 0; + bResult = false; + } + + } + else{ + write_nic_byte(dev, EFUSE_CTRL, *data); + + write_nic_byte(dev, EFUSE_CTRL+3, 0xF2); + + while((0x80 & read_nic_byte(dev, EFUSE_CTRL+3)) && (tmpidx<100) ){ + tmpidx++; + } + if(tmpidx<100) + { + *data=read_nic_byte(dev, EFUSE_CTRL); + bResult = true; + } + else + { + *data = 0; + bResult = false; + } + + } + return bResult; +} +void efuse_access(struct net_device* dev, u8 bRead,u16 start_addr, u8 cnts, u8 *data) +{ + u8 efuse_clk_ori,efuse_clk_new; + u32 i = 0; + + if(start_addr>0x200) return; + efuse_clk_ori = read_nic_byte(dev,SYS_FUNC_EN+1); + efuse_clk_new = efuse_clk_ori|0x20; + + if(efuse_clk_new!= efuse_clk_ori){ + write_nic_byte(dev, SYS_FUNC_EN+1, efuse_clk_new); + } +#ifdef _POWERON_DELAY_ + mdelay(10); +#endif + write_nic_byte(dev, EFUSE_TEST+3, (read_nic_byte(dev, EFUSE_TEST+3)|0x80)); + write_nic_byte(dev, EFUSE_CLK_CTRL, (read_nic_byte(dev, EFUSE_CLK_CTRL)|0x03)); + +#ifdef _PRE_EXECUTE_READ_CMD_ + { + unsigned char tmpdata; + efuse_OneByteRead(dev, 0,&tmpdata); + } +#endif + + for(i=0;i (sizeof(RTL8712_SDIO_EFUSE_TABLE)/sizeof(EFUSE_MAP))){ + return ; + } + + offset = RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].offset ; + word_start = RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].word_start; + byte_start = RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].byte_start; + byte_cnts = RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].byte_cnts; + + if(data_size!=byte_cnts){ + return; + } + + pg_pkt_cnts = (byte_cnts /PGPKT_DATA_SIZE) +1; + + if(pg_pkt_cnts > 1){ + tmpdata = efusedata; + + if(tmpdata!=NULL) + { + memset(tmpdata,0xff,pg_pkt_cnts*PGPKT_DATA_SIZE); + + for(tmpidx=0;tmpidx (sizeof(RTL8712_SDIO_EFUSE_TABLE)/sizeof(EFUSE_MAP))){ + return ; + } + + offset = RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].offset ; + word_start = RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].word_start; + byte_start = RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].byte_start; + byte_cnts = RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].byte_cnts; + + if(data_size > byte_cnts){ + return; + } + pg_pkt_cnts = (byte_cnts /PGPKT_DATA_SIZE) +1; + word_cnts = byte_cnts /2 ; + + if(byte_cnts %2){ + word_cnts+=1; + } + if((byte_start==1)||((byte_cnts%2)==1)){ + + if((efuse_write_item==EFUSE_F0CIS)||(efuse_write_item==EFUSE_F1CIS)){ + memset(pg_data,0xff,PGPKT_DATA_SIZE); + efuse_PgPacketRead(dev,offset,pg_data); + + if(efuse_write_item==EFUSE_F0CIS){ + word_en = 0x07; + memcpy(pg_data+word_start*2+byte_start,data,sizeof(u8)*2); + efuse_PgPacketWrite(dev,offset,word_en,pg_data+(word_start*2)); + + word_en = 0x00; + efuse_PgPacketWrite(dev,(offset+1),word_en,data+2); + + word_en = 0x00; + efuse_PgPacketRead(dev,offset+2,pg_data); + memcpy(pg_data,data+2+8,sizeof(u8)*7); + + efuse_PgPacketWrite(dev,(offset+2),word_en,pg_data); + } + else if(efuse_write_item==EFUSE_F1CIS){ + word_en = 0x07; + efuse_PgPacketRead(dev,offset,pg_data); + pg_data[7] = data[0]; + efuse_PgPacketWrite(dev,offset,word_en,pg_data+(word_start*2)); + + word_en = 0x00; + for(tmpidx = 0 ;tmpidx<(word_cnts/4);tmpidx++){ + efuse_PgPacketWrite(dev,(offset+1+tmpidx),word_en,data+1+(tmpidx*PGPKT_DATA_SIZE)); + } + } + + } + else{ + memset(pg_data,0xff,PGPKT_DATA_SIZE); + if((efuse_write_item==EFUSE_SDIO_SETTING)||(efuse_write_item==EFUSE_CCCR)){ + word_en = 0x0e ; + tmpbytes = 2; + } + else if(efuse_write_item == EFUSE_SDIO_MODE){ + word_en = 0x0d ; + tmpbytes = 2; + } + else if(efuse_write_item == EFUSE_OCR){ + word_en = 0x09 ; + tmpbytes = 4; + } + else if((efuse_write_item == EFUSE_EEPROM_VER)||(efuse_write_item==EFUSE_CHAN_PLAN)){ + word_en = 0x07 ; + tmpbytes = 2; + } + if(bWordUnit==true){ + memcpy(pg_data+word_start*2 ,data,sizeof(u8)*tmpbytes); + } + else{ + efuse_PgPacketRead(dev,offset,pg_data); + memcpy(pg_data+(2*word_start)+byte_start,data,sizeof(u8)*byte_cnts); + } + + efuse_PgPacketWrite(dev,offset,word_en,pg_data+(word_start*2)); + + } + + } + else if(pg_pkt_cnts>1){ + if(word_start==0){ + word_en = 0x00; + for(tmpidx = 0 ;tmpidx<(word_cnts/4);tmpidx++) + { + efuse_PgPacketWrite(dev,(offset+tmpidx),word_en,data+(tmpidx*PGPKT_DATA_SIZE)); + } + word_en = 0x0f; + for(tmpidx= 0; tmpidx<(word_cnts%4) ; tmpidx++) + { + tmpbitmask =tmpidx; + word_en &= (~(EFUSE_BIT(tmpbitmask))); + } + efuse_PgPacketWrite(dev,offset+(word_cnts/4),word_en,data+((word_cnts/4)*PGPKT_DATA_SIZE)); + }else + { + + } + } + else{ + word_en = 0x0f; + for(tmpidx= 0; tmpidx +******************************************************************************/ + +#ifndef __INC_EFUSE_H +#define __INC_EFUSE_H + +#define EFUSE_FOR_92SU 1 + +/*--------------------------Define Parameters-------------------------------*/ +#define EFUSE_REAL_CONTENT_LEN 512 +#define EFUSE_MAP_LEN 128 +#define EFUSE_MAX_SECTION 16 +#define EFUSE_MAX_WORD_UNIT 4 +#define EFUSE_IC_ID_OFFSET 506 + +#define EFUSE_INIT_MAP 0 +#define EFUSE_MODIFY_MAP 1 + +#define EFUSE_CLK_CTRL EFUSE_CTRL +#define EFUSE_BIT(x) (1 << (x)) + +#define PG_STATE_HEADER 0x01 +#define PG_STATE_WORD_0 0x02 +#define PG_STATE_WORD_1 0x04 +#define PG_STATE_WORD_2 0x08 +#define PG_STATE_WORD_3 0x10 +#define PG_STATE_DATA 0x20 + +#define PG_SWBYTE_H 0x01 +#define PG_SWBYTE_L 0x02 + +/*--------------------------Define Parameters-------------------------------*/ + + +/*------------------------------Define structure----------------------------*/ + +/*------------------------------Define structure----------------------------*/ + + +/*------------------------Export global variable----------------------------*/ +/*------------------------Export global variable----------------------------*/ + +/*------------------------Export Marco Definition---------------------------*/ + +/*------------------------Export Marco Definition---------------------------*/ + + +/*--------------------------Exported Function prototype---------------------*/ +extern void +EFUSE_Initialize(struct net_device* dev); +extern u8 +EFUSE_Read1Byte(struct net_device* dev,u16 Address); +extern void +EFUSE_Write1Byte(struct net_device* dev,u16 Address,u8 Value); + +#ifdef EFUSE_FOR_92SU +extern void +ReadEFuse(struct net_device* dev,u16 _offset,u16 _size_byte,u8* pbuf); +extern void +ReadEFuseByte(struct net_device* dev,u16 _offset,u8 *pbuf); +#endif + +extern void +EFUSE_ShadowRead(struct net_device* dev,unsigned char Type,unsigned short Offset,u32 *Value); +extern void +EFUSE_ShadowWrite(struct net_device* dev,unsigned char Type,unsigned short Offset,u32 Value); +extern bool +EFUSE_ShadowUpdate(struct net_device* dev); +extern bool +EFUSE_ShadowUpdateChk(struct net_device* dev); +extern void +EFUSE_ShadowMapUpdate(struct net_device* dev); +extern void +EFUSE_RePgSection1(struct net_device* dev); + +extern bool +EFUSE_ProgramMap(struct net_device* dev,char* pFileName, u8 TableType); +/*--------------------------Exported Function prototype---------------------*/ + +/* End of Efuse.h */ + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_def.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_def.h @@ -0,0 +1,756 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef R8192SE_DEF_H +#define R8192SE_DEF_H + +#include +#include "../rtllib/rtllib_endianfree.h" + +#define HAL_RETRY_LIMIT_INFRA 48 +#define HAL_RETRY_LIMIT_AP_ADHOC 7 + +#define HAL_DM_DIG_DISABLE BIT0 +#define HAL_DM_HIPWR_DISABLE BIT1 + +#define RX_DESC_SIZE 24 +#define RX_DRV_INFO_SIZE_UNIT 8 + + +#define TX_DESC_SIZE 32 + +#define SET_TX_DESC_PKT_SIZE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 0, 16, __Value) +#define SET_TX_DESC_OFFSET(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 16, 8, __Value) +#define SET_TX_DESC_TYPE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 24, 2, __Value) +#define SET_TX_DESC_LAST_SEG(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 26, 1, __Value) +#define SET_TX_DESC_FIRST_SEG(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 27, 1, __Value) +#define SET_TX_DESC_LINIP(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 28, 1, __Value) +#define SET_TX_DESC_AMSDU(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 29, 1, __Value) +#define SET_TX_DESC_GREEN_FIELD(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 30, 1, __Value) +#define SET_TX_DESC_OWN(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc, 31, 1, __Value) + +#define SET_TX_DESC_MACID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 0, 5, __Value) +#define SET_TX_DESC_MORE_DATA(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 5, 1, __Value) +#define SET_TX_DESC_MORE_FRAG(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 6, 1, __Value) +#define SET_TX_DESC_PIFS(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 7, 1, __Value) +#define SET_TX_DESC_QUEUE_SEL(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 8, 5, __Value) +#define SET_TX_DESC_ACK_POLICY(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 13, 2, __Value) +#define SET_TX_DESC_NO_ACM(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 15, 1, __Value) +#define SET_TX_DESC_NON_QOS(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 16, 1, __Value) +#define SET_TX_DESC_KEY_ID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 17, 2, __Value) +#define SET_TX_DESC_OUI(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 19, 1, __Value) +#define SET_TX_DESC_PKT_TYPE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 20, 1, __Value) +#define SET_TX_DESC_EN_DESC_ID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 21, 1, __Value) +#define SET_TX_DESC_SEC_TYPE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 22, 2, __Value) +#define SET_TX_DESC_WDS(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 24, 1, __Value) +#define SET_TX_DESC_HTC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 25, 1, __Value) +#define SET_TX_DESC_PKT_OFFSET(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 26, 5, __Value) +#define SET_TX_DESC_HWPC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+4, 27, 1, __Value) + +#define SET_TX_DESC_DATA_RETRY_LIMIT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 0, 6, __Value) +#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 6, 1, __Value) +#define SET_TX_DESC_TSFL(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 7, 5, __Value) +#define SET_TX_DESC_RTS_RETRY_COUNT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 12, 6, __Value) +#define SET_TX_DESC_DATA_RETRY_COUNT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 18, 6, __Value) +#define SET_TX_DESC_RSVD_MACID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(((__pTxDesc) + 8), 24, 5, __Value) +#define SET_TX_DESC_AGG_ENABLE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 29, 1, __Value) +#define SET_TX_DESC_AGG_BREAK(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 30, 1, __Value) +#define SET_TX_DESC_OWN_MAC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+8, 31, 1, __Value) + +#define SET_TX_DESC_NEXT_HEAP_PAGE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+12, 0, 8, __Value) +#define SET_TX_DESC_TAIL_PAGE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+12, 8, 8, __Value) +#define SET_TX_DESC_SEQ(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+12, 16, 12, __Value) +#define SET_TX_DESC_FRAG(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+12, 28, 4, __Value) + +#define SET_TX_DESC_RTS_RATE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 0, 6, __Value) +#define SET_TX_DESC_DISABLE_RTS_FB(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 6, 1, __Value) +#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 7, 4, __Value) +#define SET_TX_DESC_CTS_ENABLE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 11, 1, __Value) +#define SET_TX_DESC_RTS_ENABLE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 12, 1, __Value) +#define SET_TX_DESC_RA_BRSR_ID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 13, 3, __Value) +#define SET_TX_DESC_TXHT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 16, 1, __Value) +#define SET_TX_DESC_TX_SHORT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 17, 1, __Value) +#define SET_TX_DESC_TX_BANDWIDTH(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 18, 1, __Value) +#define SET_TX_DESC_TX_SUB_CARRIER(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 19, 2, __Value) +#define SET_TX_DESC_TX_STBC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 21, 2, __Value) +#define SET_TX_DESC_TX_REVERSE_DIRECTION(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 23, 1, __Value) +#define SET_TX_DESC_RTS_HT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 24, 1, __Value) +#define SET_TX_DESC_RTS_SHORT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 25, 1, __Value) +#define SET_TX_DESC_RTS_BANDWIDTH(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 26, 1, __Value) +#define SET_TX_DESC_RTS_SUB_CARRIER(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 27, 2, __Value) +#define SET_TX_DESC_RTS_STBC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 29, 2, __Value) +#define SET_TX_DESC_USER_RATE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+16, 31, 1, __Value) + +#define SET_TX_DESC_PACKET_ID(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+20, 0, 9, __Value) +#define SET_TX_DESC_TX_RATE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+20, 9, 6, __Value) +#define SET_TX_DESC_DISABLE_FB(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+20, 15, 1, __Value) +#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+20, 16, 5, __Value) +#define SET_TX_DESC_TX_AGC(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+20, 21, 11, __Value) + +#define SET_TX_DESC_IP_CHECK_SUM(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+24, 0, 16, __Value) +#define SET_TX_DESC_TCP_CHECK_SUM(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+24, 16, 16, __Value) + +#define SET_TX_DESC_TX_BUFFER_SIZE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+28, 0, 16, __Value) +#define SET_TX_DESC_IP_HEADER_OFFSET(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+28, 16, 8, __Value) +#define SET_TX_DESC_TCP_ENABLE(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+28, 31, 1, __Value) + +#define SET_TX_DESC_TX_BUFFER_ADDRESS(__pTxDesc, __Value) SET_BITS_TO_LE_4BYTE(__pTxDesc+32, 0, 32, __Value) + + +#define TX_DESC_NEXT_DESC_OFFSET 36 +#define CLEAR_PCI_TX_DESC_CONTENT(__pTxDesc, _size) \ + { \ + if(_size > TX_DESC_NEXT_DESC_OFFSET) \ + memset((void*)__pTxDesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ + else \ + memset((void*)__pTxDesc, 0, _size); \ + if(_size > (TX_DESC_NEXT_DESC_OFFSET + 4)) \ + memset((void*)(__pTxDesc + (TX_DESC_NEXT_DESC_OFFSET + 4)), 0, (_size - TX_DESC_NEXT_DESC_OFFSET)); \ + } + +#define C2H_RX_CMD_HDR_LEN 8 +#define GET_C2H_CMD_CMD_LEN(__pRxHeader) LE_BITS_TO_4BYTE((__pRxHeader), 0, 16) +#define GET_C2H_CMD_ELEMENT_ID(__pRxHeader) LE_BITS_TO_4BYTE((__pRxHeader), 16, 8) +#define GET_C2H_CMD_CMD_SEQ(__pRxHeader) LE_BITS_TO_4BYTE((__pRxHeader), 24, 7) +#define GET_C2H_CMD_CONTINUE(__pRxHeader) LE_BITS_TO_4BYTE((__pRxHeader), 31, 1) +#define GET_C2H_CMD_CONTENT(__pRxHeader) ((u8*)(__pRxHeader) + C2H_RX_CMD_HDR_LEN) + +#define GET_C2H_CMD_FEEDBACK_ELEMENT_ID(__pCmdFBHeader) LE_BITS_TO_4BYTE((__pCmdFBHeader), 0, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_LEN(__pCmdFBHeader) LE_BITS_TO_4BYTE((__pCmdFBHeader), 8, 8) +#define GET_C2H_CMD_FEEDBACK_CCX_CMD_CNT(__pCmdFBHeader) LE_BITS_TO_4BYTE((__pCmdFBHeader), 16, 16) +#define GET_C2H_CMD_FEEDBACK_CCX_MAC_ID(__pCmdFBHeader) LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 0, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_VALID(__pCmdFBHeader) LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 7, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_RETRY_CNT(__pCmdFBHeader) LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 8, 5) +#define GET_C2H_CMD_FEEDBACK_CCX_TOK(__pCmdFBHeader) LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 15, 1) +#define GET_C2H_CMD_FEEDBACK_CCX_QSEL(__pCmdFBHeader) LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 16, 4) +#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pCmdFBHeader) LE_BITS_TO_4BYTE(((__pCmdFBHeader) + 4), 20, 12) + + +#if 0 +#define BK_QUEUE 0 +#define BE_QUEUE 1 +#define VI_QUEUE 2 +#define VO_QUEUE 3 +#define BEACON_QUEUE 4 +#define TXCMD_QUEUE 5 +#define MGNT_QUEUE 6 +#define HIGH_QUEUE 7 +#define HCCA_QUEUE 8 + +#define LOW_QUEUE BE_QUEUE +#define NORMAL_QUEUE MGNT_QUEUE +#endif + +#define RX_MPDU_QUEUE 0 +#define RX_CMD_QUEUE 1 +#define RX_MAX_QUEUE 2 + + +typedef enum _rtl819x_loopback{ + RTL819X_NO_LOOPBACK = 0, + RTL819X_MAC_LOOPBACK = 1, + RTL819X_DMA_LOOPBACK = 2, + RTL819X_CCK_LOOPBACK = 3, +}rtl819x_loopback_e; + +#define RESET_DELAY_8185 20 + +#define RT_IBSS_INT_MASKS 0 + +#define DESC92S_RATE1M 0x00 +#define DESC92S_RATE2M 0x01 +#define DESC92S_RATE5_5M 0x02 +#define DESC92S_RATE11M 0x03 +#define DESC92S_RATE6M 0x04 +#define DESC92S_RATE9M 0x05 +#define DESC92S_RATE12M 0x06 +#define DESC92S_RATE18M 0x07 +#define DESC92S_RATE24M 0x08 +#define DESC92S_RATE36M 0x09 +#define DESC92S_RATE48M 0x0a +#define DESC92S_RATE54M 0x0b +#define DESC92S_RATEMCS0 0x0c +#define DESC92S_RATEMCS1 0x0d +#define DESC92S_RATEMCS2 0x0e +#define DESC92S_RATEMCS3 0x0f +#define DESC92S_RATEMCS4 0x10 +#define DESC92S_RATEMCS5 0x11 +#define DESC92S_RATEMCS6 0x12 +#define DESC92S_RATEMCS7 0x13 +#define DESC92S_RATEMCS8 0x14 +#define DESC92S_RATEMCS9 0x15 +#define DESC92S_RATEMCS10 0x16 +#define DESC92S_RATEMCS11 0x17 +#define DESC92S_RATEMCS12 0x18 +#define DESC92S_RATEMCS13 0x19 +#define DESC92S_RATEMCS14 0x1a +#define DESC92S_RATEMCS15 0x1b +#define DESC92S_RATEMCS15_SG 0x1c +#define DESC92S_RATEMCS32 0x20 + +#define SHORT_SLOT_TIME 9 +#define NON_SHORT_SLOT_TIME 20 + + +#define MAX_LINES_HWCONFIG_TXT 1000 +#define MAX_BYTES_LINE_HWCONFIG_TXT 256 + +#define SW_THREE_WIRE 0 +#define HW_THREE_WIRE 2 + +#define BT_DEMO_BOARD 0 +#define BT_QA_BOARD 1 +#define BT_FPGA 2 + +#define Rx_Smooth_Factor 20 + +#define QSLT_BK 0x2 +#define QSLT_BE 0x0 +#define QSLT_VI 0x5 +#define QSLT_VO 0x7 +#define QSLT_BEACON 0x10 +#define QSLT_HIGH 0x11 +#define QSLT_MGNT 0x12 +#define QSLT_CMD 0x13 + +#define NUM_OF_FIRMWARE_QUEUE 10 +#define NUM_OF_PAGES_IN_FW 0x100 +#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x07 +#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0x0 +#define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x0 +#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x02 +#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0x02 +#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x2 +#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0xA1 + +#define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM 0x026 +#define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM 0x048 +#define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM 0x048 +#define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM 0x026 +#define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM 0x00 + +#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0 +#define HAL_PRIME_CHNL_OFFSET_LOWER 1 +#define HAL_PRIME_CHNL_OFFSET_UPPER 2 + + + +#define MAX_SILENT_RESET_RX_SLOT_NUM 10 +typedef enum tag_Rf_OpType +{ + RF_OP_By_SW_3wire = 0, + RF_OP_By_FW, + RF_OP_MAX +}RF_OpType_E; + + +typedef enum _POWER_SAVE_MODE +{ + POWER_SAVE_MODE_ACTIVE, + POWER_SAVE_MODE_SAVE, +}POWER_SAVE_MODE; + +typedef enum _INTERFACE_SELECT_8190PCI{ + INTF_SEL1_MINICARD = 0, + INTF_SEL0_PCIE = 1, + INTF_SEL2_RSV = 2, + INTF_SEL3_RSV = 3, +} INTERFACE_SELECT_8190PCI, *PINTERFACE_SELECT_8190PCI; + + +typedef struct _BB_REGISTER_DEFINITION{ + u32 rfintfs; + u32 rfintfi; + u32 rfintfo; + u32 rfintfe; + u32 rf3wireOffset; + u32 rfLSSI_Select; + u32 rfTxGainStage; + u32 rfHSSIPara1; + u32 rfHSSIPara2; + u32 rfSwitchControl; + u32 rfAGCControl1; + u32 rfAGCControl2; + u32 rfRxIQImbalance; + u32 rfRxAFE; + u32 rfTxIQImbalance; + u32 rfTxAFE; + u32 rfLSSIReadBack; + u32 rfLSSIReadBackPi; +}BB_REGISTER_DEFINITION_T, *PBB_REGISTER_DEFINITION_T; + + + + +typedef struct _rx_fwinfo_8192s{ + + /*u32 gain_0:7; + u32 trsw_0:1; + u32 gain_1:7; + u32 trsw_1:1; + u32 gain_2:7; + u32 trsw_2:1; + u32 gain_3:7; + u32 trsw_3:1; */ + u8 gain_trsw[4]; + + /*u32 pwdb_all:8; + u32 cfosho_0:8; + u32 cfosho_1:8; + u32 cfosho_2:8;*/ + u8 pwdb_all; + u8 cfosho[4]; + + /*u32 cfosho_3:8; + u32 cfotail_0:8; + u32 cfotail_1:8; + u32 cfotail_2:8;*/ + u8 cfotail[4]; + + /*u32 cfotail_3:8; + u32 rxevm_0:8; + u32 rxevm_1:8; + u32 rxsnr_0:8;*/ + s8 rxevm[2]; + s8 rxsnr[4]; + + /*u32 rxsnr_1:8; + u32 rxsnr_2:8; + u32 rxsnr_3:8; + u32 pdsnr_0:8;*/ + u8 pdsnr[2]; + + /*u32 pdsnr_1:8; + u32 csi_current_0:8; + u32 csi_current_1:8; + u32 csi_target_0:8;*/ + u8 csi_current[2]; + u8 csi_target[2]; + + /*u32 csi_target_1:8; + u32 sigevm:8; + u32 max_ex_pwr:8; + u32 ex_intf_flag:1; + u32 sgi_en:1; + u32 rxsc:2; + u32 reserve:4;*/ + u8 sigevm; + u8 max_ex_pwr; + u8 ex_intf_flag:1; + u8 sgi_en:1; + u8 rxsc:2; + u8 reserve:4; + +}rx_fwinfo, *prx_fwinfo; + +typedef struct _LOG_INTERRUPT_8190 +{ + u32 nIMR_COMDOK; + u32 nIMR_MGNTDOK; + u32 nIMR_HIGH; + u32 nIMR_VODOK; + u32 nIMR_VIDOK; + u32 nIMR_BEDOK; + u32 nIMR_BKDOK; + u32 nIMR_ROK; + u32 nIMR_RCOK; + u32 nIMR_TBDOK; + u32 nIMR_BDOK; + u32 nIMR_RXFOVW; +} LOG_INTERRUPT_8190_T, *PLOG_INTERRUPT_8190_T; + +typedef struct _phy_cck_rx_status_report_819xpci +{ + u8 adc_pwdb_X[4]; + u8 sq_rpt; + u8 cck_agc_rpt; +}phy_sts_cck_819xpci_t, phy_sts_cck_8192s_t; + +#define PHY_RSSI_SLID_WIN_MAX 100 +#define PHY_LINKQUALITY_SLID_WIN_MAX 20 +#define PHY_Beacon_RSSI_SLID_WIN_MAX 10 + +typedef struct _tx_desc_8192se{ + + u32 PktSize:16; + u32 Offset:8; + u32 Type:2; + u32 LastSeg:1; + u32 FirstSeg:1; + u32 LINIP:1; + u32 AMSDU:1; + u32 GF:1; + u32 OWN:1; + + u32 MacID:5; + u32 MoreData:1; + u32 MoreFrag:1; + u32 PIFS:1; + u32 QueueSel:5; + u32 AckPolicy:2; + u32 NoACM:1; + u32 NonQos:1; + u32 KeyID:2; + u32 OUI:1; + u32 PktType:1; + u32 EnDescID:1; + u32 SecType:2; + u32 HTC:1; + u32 WDS:1; + u32 PktOffset:5; + u32 HWPC:1; + + u32 DataRetryLmt:6; + u32 RetryLmtEn:1; + u32 TSFL:5; + u32 RTSRC:6; + u32 DATARC:6; + u32 Rsvd_MacID:5; + u32 AggEn:1; + u32 BK:1; + u32 OwnMAC:1; + + u32 NextHeadPage:8; + u32 TailPage:8; + u32 Seq:12; + u32 Frag:4; + + u32 RTSRate:6; + u32 DisRTSFB:1; + u32 RTSRateFBLmt:4; + u32 CTS2Self:1; + u32 RTSEn:1; + u32 RaBRSRID:3; + u32 TXHT:1; + u32 TxShort:1; + u32 TxBw:1; + u32 TXSC:2; + u32 STBC:2; + u32 RD:1; + u32 RTSHT:1; + u32 RTSShort:1; + u32 RTSBW:1; + u32 RTSSC:2; + u32 RTSSTBC:2; + u32 UserRate:1; + + u32 PktID:9; + u32 TxRate:6; + u32 DISFB:1; + u32 DataRateFBLmt:5; + u32 TxAGC:11; + + u32 IPChkSum:16; + u32 TCPChkSum:16; + + u32 TxBufferSize:16; + u32 IPHdrOffset:8; + u32 Rsvd3:7; + u32 TCPEn:1; + + u32 TxBuffAddr; + + u32 NextDescAddress; + + u32 Reserve_Pass_92S_PCIE_MM_Limit[6]; + +} tx_desc, *ptx_desc; + + +typedef struct _tx_desc_cmd_8192se{ + u32 PktSize:16; + u32 Offset:8; + u32 Rsvd0:2; + u32 FirstSeg:1; + u32 LastSeg:1; + u32 LINIP:1; + u32 Rsvd1:2; + u32 OWN:1; + + u32 Rsvd2; + u32 Rsvd3; + u32 Rsvd4; + u32 Rsvd5; + u32 Rsvd6; + u32 Rsvd7; + + u32 TxBufferSize:16; + u32 Rsvd8:16; + + u32 TxBufferAddr; + + u32 NextTxDescAddress; + + u32 Reserve_Pass_92S_PCIE_MM_Limit[6]; + +}tx_desc_cmd, *ptx_desc_cmd; + + +typedef struct _tx_status_desc_8192se{ + + u32 PktSize:16; + u32 Offset:8; + u32 Type:2; + u32 LastSeg:1; + u32 FirstSeg:1; + u32 LINIP:1; + u32 AMSDU:1; + u32 GF:1; + u32 OWN:1; + + u32 MacID:5; + u32 MoreData:1; + u32 MoreFrag:1; + u32 PIFS:1; + u32 QueueSel:5; + u32 AckPolicy:2; + u32 NoACM:1; + u32 NonQos:1; + u32 KeyID:2; + u32 OUI:1; + u32 PktType:1; + u32 EnDescID:1; + u32 SecType:2; + u32 HTC:1; + u32 WDS:1; + u32 PktOffset:5; + u32 HWPC:1; + + u32 DataRetryLmt:6; + u32 RetryLmtEn:1; + u32 TSFL:5; + u32 RTSRC:6; + u32 DATARC:6; + u32 Rsvd1:5; + u32 AggEn:1; + u32 BK:1; + u32 OwnMAC:1; + + u32 NextHeadPage:8; + u32 TailPage:8; + u32 Seq:12; + u32 Frag:4; + + u32 RTSRate:6; + u32 DisRTSFB:1; + u32 RTSRateFBLmt:4; + u32 CTS2Self:1; + u32 RTSEn:1; + u32 RaBRSRID:3; + u32 TXHT:1; + u32 TxShort:1; + u32 TxBw:1; + u32 TXSC:2; + u32 STBC:2; + u32 RD:1; + u32 RTSHT:1; + u32 RTSShort:1; + u32 RTSBW:1; + u32 RTSSC:2; + u32 RTSSTBC:2; + u32 UserRate:1; + + u32 PktID:9; + u32 TxRate:6; + u32 DISFB:1; + u32 DataRateFBLmt:5; + u32 TxAGC:11; + + u32 IPChkSum:16; + u32 TCPChkSum:16; + + u32 TxBufferSize:16; + u32 IPHdrOffset:8; + u32 Rsvd2:7; + u32 TCPEn:1; + + u32 TxBufferAddr; + + u32 NextDescAddress; + + u32 Reserve_Pass_92S_PCIE_MM_Limit[6]; + +}tx_status_desc, *ptx_status_desc; + + +typedef struct _rx_desc_8192se{ + u32 Length:14; + u32 CRC32:1; + u32 ICVError:1; + u32 DrvInfoSize:4; + u32 Security:3; + u32 Qos:1; + u32 Shift:2; + u32 PHYStatus:1; + u32 SWDec:1; + u32 LastSeg:1; + u32 FirstSeg:1; + u32 EOR:1; + u32 OWN:1; + + u32 MACID:5; + u32 TID:4; + u32 HwRsvd:5; + u32 PAGGR:1; + u32 FAGGR:1; + u32 A1_FIT:4; + u32 A2_FIT:4; + u32 PAM:1; + u32 PWR:1; + u32 MoreData:1; + u32 MoreFrag:1; + u32 Type:2; + u32 MC:1; + u32 BC:1; + + u32 Seq:12; + u32 Frag:4; + u32 NextPktLen:14; + u32 NextIND:1; + u32 Rsvd:1; + + u32 RxMCS:6; + u32 RxHT:1; + u32 AMSDU:1; + u32 SPLCP:1; + u32 BandWidth:1; + u32 HTC:1; + u32 TCPChkRpt:1; + u32 IPChkRpt:1; + u32 TCPChkValID:1; + u32 HwPCErr:1; + u32 HwPCInd:1; + u32 IV0:16; + + u32 IV1; + + u32 TSFL; + + u32 BufferAddress; + + u32 NextRxDescAddress; + +#if 0 + u32 BA_SSN:12; + u32 BA_VLD:1; + u32 RSVD:19; +#endif + +} rx_desc, *prx_desc; + + + +typedef struct _rx_desc_status_8192se{ + u32 Length:14; + u32 CRC32:1; + u32 ICVError:1; + u32 DrvInfoSize:4; + u32 Security:3; + u32 Qos:1; + u32 Shift:2; + u32 PHYStatus:1; + u32 SWDec:1; + u32 LastSeg:1; + u32 FirstSeg:1; + u32 EOR:1; + u32 OWN:1; + + u32 MACID:5; + u32 TID:4; + u32 HwRsvd:5; + u32 PAGGR:1; + u32 FAGGR:1; + u32 A1_FIT:4; + u32 A2_FIT:4; + u32 PAM:1; + u32 PWR:1; + u32 MoreData:1; + u32 MoreFrag:1; + u32 Type:2; + u32 MC:1; + u32 BC:1; + + u32 Seq:12; + u32 Frag:4; + u32 NextPktLen:14; + u32 NextIND:1; + u32 Rsvd:1; + + u32 RxMCS:6; + u32 RxHT:1; + u32 AMSDU:1; + u32 SPLCP:1; + u32 BW:1; + u32 HTC:1; + u32 TCPChkRpt:1; + u32 IPChkRpt:1; + u32 TCPChkValID:1; + u32 HwPCErr:1; + u32 HwPCInd:1; + u32 IV0:16; + + u32 IV1; + + u32 TSFL; + + + u32 BufferAddress; + + u32 NextRxDescAddress; + +#if 0 + u32 BA_SSN:12; + u32 BA_VLD:1; + u32 RSVD:19; +#endif +}rx_desc_status, *prx_desc_status; + +typedef enum _HAL_FW_C2H_CMD_ID +{ + HAL_FW_C2H_CMD_Read_MACREG = 0, + HAL_FW_C2H_CMD_Read_BBREG = 1, + HAL_FW_C2H_CMD_Read_RFREG = 2, + HAL_FW_C2H_CMD_Read_EEPROM = 3, + HAL_FW_C2H_CMD_Read_EFUSE = 4, + HAL_FW_C2H_CMD_Read_CAM = 5, + HAL_FW_C2H_CMD_Get_BasicRate = 6, + HAL_FW_C2H_CMD_Get_DataRate = 7, + HAL_FW_C2H_CMD_Survey = 8 , + HAL_FW_C2H_CMD_SurveyDone = 9, + HAL_FW_C2H_CMD_JoinBss = 10, + HAL_FW_C2H_CMD_AddSTA = 11, + HAL_FW_C2H_CMD_DelSTA = 12, + HAL_FW_C2H_CMD_AtimDone = 13, + HAL_FW_C2H_CMD_TX_Report = 14, + HAL_FW_C2H_CMD_CCX_Report = 15, + HAL_FW_C2H_CMD_DTM_Report = 16, + HAL_FW_C2H_CMD_TX_Rate_Statistics = 17, + HAL_FW_C2H_CMD_C2HLBK = 18, + HAL_FW_C2H_CMD_C2HDBG = 19, + HAL_FW_C2H_CMD_C2HFEEDBACK = 20, + HAL_FW_C2H_CMD_BT_State = 25, + HAL_FW_C2H_CMD_BT_Service = 26, + HAL_FW_C2H_CMD_MAX +}HAL_FW_C2H_CMD_ID; + +#define HAL_FW_C2H_CMD_C2HFEEDBACK_CCX_PER_PKT_RPT 0x04 +#define HAL_FW_C2H_CMD_C2HFEEDBACK_DTM_TX_STATISTICS_RPT 0x05 +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_dev.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_dev.c @@ -0,0 +1,5469 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#include "../rtl_core.h" +#include "../rtl_dm.h" +#include "../rtl_wx.h" + +#ifdef _RTL8192_EXT_PATCH_ +#include "../../../mshclass/msh_class.h" +#include "../rtl_mesh.h" +#endif + +extern int WDCAPARA_ADD[]; + +void rtl8192se_start_beacon(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct rtllib_network *net = NULL; + u16 BcnTimeCfg = 0; + u16 BcnCW = 6; + u16 BcnIFS = 0xf; + + if((priv->rtllib->iw_mode == IW_MODE_ADHOC) || (priv->rtllib->iw_mode == IW_MODE_MASTER)) + net = &priv->rtllib->current_network; +#ifdef _RTL8192_EXT_PATCH_ + else if(priv->rtllib->iw_mode == IW_MODE_MESH) + net = &priv->rtllib->current_mesh_network; +#endif + else + return; + + rtl8192_irq_disable(dev); + + write_nic_word(dev, ATIMWND, 2); + + write_nic_word(dev, BCN_INTERVAL, net->beacon_interval); + PHY_SetBeaconHwReg(dev, net->beacon_interval); + +#ifdef RTL8192SE + write_nic_word(dev, BCN_DRV_EARLY_INT, 10<<4); +#else + write_nic_word(dev, BCN_DRV_EARLY_INT, 10); +#endif + write_nic_word(dev, BCN_DMATIME, 256); + + write_nic_byte(dev, BCN_ERR_THRESH, 100); + +if(priv->pFirmware->FirmwareVersion > 49){ + switch(priv->rtllib->iw_mode) + { + case IW_MODE_ADHOC: + case IW_MODE_MESH: + BcnTimeCfg |= (BcnCW<beacon_interval); + write_nic_dword(dev, WFM5, 0xF1000000 |((u16)( u1Temp) << 8)); + ChkFwCmdIoDone(dev); + } +}else{ + BcnTimeCfg |= BcnCW<rtllib->iw_mode) { + case IW_MODE_INFRA: + if (priv->rtllib->state == RTLLIB_LINKED) + msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT); + else + msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT); + LedAction = LED_CTL_LINK; + break; + case IW_MODE_ADHOC: + if (priv->rtllib->state == RTLLIB_LINKED) + msr |= (MSR_LINK_ADHOC << MSR_LINK_SHIFT); + else + msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT); + break; + case IW_MODE_MASTER: + if (priv->rtllib->state == RTLLIB_LINKED) + msr |= (MSR_LINK_MASTER << MSR_LINK_SHIFT); + else + msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT); + break; +#ifdef _RTL8192_EXT_PATCH_ + case IW_MODE_MESH: + printk("%s: iw_mode=%d state=%d only_mesh=%d mesh_state=%d\n", __FUNCTION__,priv->rtllib->iw_mode,priv->rtllib->state, priv->rtllib->only_mesh, priv->rtllib->mesh_state); + if (priv->rtllib->only_mesh) { + if (priv->rtllib->mesh_state == RTLLIB_MESH_LINKED) + msr |= (MSR_LINK_MASTER<rtllib->mesh_state == RTLLIB_MESH_LINKED) { + msr |= (MSR_LINK_ADHOC << MSR_LINK_SHIFT); + } else { + msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT); + } + if (priv->rtllib->state == RTLLIB_LINKED) + msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT); + } + break; +#endif + default: + break; + } + + write_nic_byte(dev, MSR, msr); + if(priv->rtllib->LedControlHandler) + priv->rtllib->LedControlHandler(dev, LedAction); +} + +static void rtl8192se_config_hw_for_load_fail(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u16 i; + u8 sMacAddr[6] = {0x00, 0xE0, 0x4C, 0x81, 0x92, 0x00}; + u8 rf_path, index; + u32 tmp1111 = 0; + u32 tmp2222 = 0; + + RT_TRACE(COMP_INIT, "====> rtl8192se_config_hw_for_load_fail\n"); + + for(;tmp2222<0xff;tmp2222+=4) + { + tmp1111= read_nic_dword(dev, tmp2222); + } + + write_nic_byte(dev, SYS_ISO_CTRL+1, 0xE8); + mdelay(10); + write_nic_byte(dev, PMC_FSM, 0x02); + + priv->eeprom_vid= 0; + priv->eeprom_did= 0; + priv->eeprom_ChannelPlan= 0; + priv->eeprom_CustomerID= 0; + + get_random_bytes(&sMacAddr[5], 1); + for(i = 0; i < 6; i++) + dev->dev_addr[i] = sMacAddr[i]; + + + priv->rf_type= RTL819X_DEFAULT_RF_TYPE; + priv->rf_chip = RF_6052; + +#if (EEPROM_OLD_FORMAT_SUPPORT == 1) + for(i=0; i<14; i++) + { + priv->EEPROMTxPowerLevelCCK[i] = (u8)(EEPROM_Default_TxPower & 0xff); + RT_TRACE(COMP_INIT, "CCK 2.4G Tx Pwr Index %d = 0x%02x\n", + i, priv->EEPROMTxPowerLevelCCK[i]); + } + + for(i=0; i<14; i++) + { + priv->EEPROMTxPowerLevelOFDM24G[i] = (u8)(EEPROM_Default_TxPower & 0xff); + RT_TRACE(COMP_INIT, "OFDM 2.4G Tx Pwr Index %d = 0x%02x\n", + i, priv->EEPROMTxPowerLevelOFDM24G[i]); + } + + for(i=0; i<14; i++) + { + priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[i]; + priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK[i]; + } + for(i=0; i<6; i++) + { + priv->EEPROMHT2T_TxPwr[i] = EEPROM_Default_HT2T_TxPwr; + } + +#else + for (rf_path = 0; rf_path < 2; rf_path++) + { + for (i = 0; i < 3; i++) + { + priv->RfCckChnlAreaTxPwr[rf_path][i] = + priv->RfOfdmChnlAreaTxPwr1T[rf_path][i] = + priv->RfOfdmChnlAreaTxPwr2T[rf_path][i] = + EEPROM_Default_TxPowerLevel; + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) + { + for(i=0; i<14; i++) + { + if (i < 3) + index = 0; + else if (i < 8) + index = 1; + else + index = 2; + + priv->RfTxPwrLevelCck[rf_path][i] = + priv->RfCckChnlAreaTxPwr[rf_path][index] = + priv->RfTxPwrLevelOfdm1T[rf_path][i] = + priv->RfOfdmChnlAreaTxPwr1T[rf_path][index] = + priv->RfTxPwrLevelOfdm2T[rf_path][i] = + priv->RfOfdmChnlAreaTxPwr2T[rf_path][index] = + (u8)(EEPROM_Default_TxPower & 0xff); + + if (rf_path == 0) + { + priv->TxPowerLevelOFDM24G[i] = (u8)(EEPROM_Default_TxPower & 0xff); + priv->TxPowerLevelCCK[i] = (u8)(EEPROM_Default_TxPower & 0xff); + } + } + + } + + RT_TRACE(COMP_INIT, "All TxPwr = 0x%x\n", EEPROM_Default_TxPower); + + for(i=0; i<14; i++) + { + priv->TxPwrHt20Diff[RF90_PATH_A][i] = DEFAULT_HT20_TXPWR_DIFF; + priv->TxPwrHt20Diff[RF90_PATH_B][i] = DEFAULT_HT20_TXPWR_DIFF; + + priv->TxPwrLegacyHtDiff[0][i] = EEPROM_Default_LegacyHTTxPowerDiff; + priv->TxPwrLegacyHtDiff[1][i] = EEPROM_Default_LegacyHTTxPowerDiff; + } + + priv->TxPwrSafetyFlag = 0; +#endif + + priv->EEPROMTxPowerDiff = EEPROM_Default_LegacyHTTxPowerDiff; + priv->LegacyHTTxPowerDiff = priv->EEPROMTxPowerDiff; + RT_TRACE(COMP_INIT, "TxPowerDiff = %#x\n", priv->EEPROMTxPowerDiff); + + for (rf_path = 0; rf_path < 2; rf_path++) + { + for (i = 0; i < 3; i++) + { + priv->EEPROMPwrGroup[rf_path][i] = 0; + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) + { + for(i=0; i<14; i++) + { + if (i < 3) + index = 0; + else if (i < 8) + index = 1; + else + index = 2; + priv->PwrGroupHT20[rf_path][i] = (priv->EEPROMPwrGroup[rf_path][index]&0xf); + priv->PwrGroupHT40[rf_path][i] = ((priv->EEPROMPwrGroup[rf_path][index]&0xf0)>>4); + } + } + priv->EEPROMRegulatory = 0; + + priv->EEPROMTSSI_A = EEPROM_Default_TSSI; + priv->EEPROMTSSI_B = EEPROM_Default_TSSI; + + for(i=0; i<6; i++) + { + priv->EEPROMHT2T_TxPwr[i] = EEPROM_Default_HT2T_TxPwr; + } + + + priv->EEPROMThermalMeter = EEPROM_Default_ThermalMeter; + priv->ThermalMeter[0] = (priv->EEPROMThermalMeter&0x1f); + priv->TSSI_13dBm = priv->EEPROMThermalMeter *100; + + priv->BluetoothCoexist = EEPROM_Default_BlueToothCoexist; + priv->EEPROMBluetoothType = EEPROM_Default_BlueToothType; + priv->EEPROMBluetoothAntNum = EEPROM_Default_BlueToothAntNum; + priv->EEPROMBluetoothAntIsolation = EEPROM_Default_BlueToothAntIso; + + priv->EEPROMCrystalCap = EEPROM_Default_CrystalCap; + priv->CrystalCap = priv->EEPROMCrystalCap; + + priv->eeprom_ChannelPlan = 0; + priv->eeprom_version = 1; + priv->bTXPowerDataReadFromEEPORM = false; + + priv->rf_type = RTL819X_DEFAULT_RF_TYPE; + priv->rf_chip = RF_6052; + priv->eeprom_CustomerID = 0; + RT_TRACE(COMP_INIT, "EEPROM Customer ID: 0x%2x\n", priv->eeprom_CustomerID); + + + priv->EEPROMBoardType = EEPROM_Default_BoardType; + RT_TRACE(COMP_INIT, "BoardType = %#x\n", priv->EEPROMBoardType); + + priv->LedStrategy = SW_LED_MODE7; + + + RT_TRACE(COMP_INIT,"<==== rtl8192se_config_hw_for_load_fail\n"); +} + +static void rtl8192se_get_IC_Inferiority(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 Efuse_ID; + + priv->IC_Class = IC_INFERIORITY_A; + if((priv->epromtype == EEPROM_BOOT_EFUSE) && !priv->AutoloadFailFlag) + { + Efuse_ID = EFUSE_Read1Byte(dev, EFUSE_IC_ID_OFFSET); + + if(Efuse_ID == 0xfe) + { + priv->IC_Class = IC_INFERIORITY_B; + + } + } +} + +void +HalCustomizedBehavior8192S(struct net_device* dev) +{ + struct r8192_priv* priv = rtllib_priv(dev); + priv->rtllib->bForcedShowRateStill = false; + switch(priv->CustomerID) + { + case RT_CID_DEFAULT: + case RT_CID_819x_SAMSUNG: + if(priv->CustomerID == RT_CID_819x_SAMSUNG) + ; + priv->LedStrategy = SW_LED_MODE7; + if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x1A3B && priv->eeprom_smid == 0x1A07) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + priv->rtllib->bForcedBgMode = true; + priv->rtllib->bForcedShowRateStill = true; + } + } + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x1A3B && priv->eeprom_smid == 0x1A04) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + priv->rtllib->bForcedBgMode = true; + priv->rtllib->bForcedShowRateStill = true; + } + } + else if(priv->eeprom_svid == 0x1A3B && (priv->eeprom_smid == 0x1104 || + priv->eeprom_smid == 0x1107)) + { + priv->rtllib->bForcedShowRateStill = true; + } + else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7171) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + priv->rtllib->bForcedBgMode = true; + } + } + else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7150) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7172) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7150) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7186) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7174) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + else if(priv->eeprom_vid == 0x10ec && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10ec && priv->eeprom_smid == 0x7150) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + + break; + + case RT_CID_819x_Acer: + priv->LedStrategy = SW_LED_MODE7; + + if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x7172) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x7173) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x7186) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x7187) + { + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + break; + + case RT_CID_TOSHIBA: + priv->rtllib->current_network.channel = 10; + priv->LedStrategy = SW_LED_MODE7; + priv->EEPROMRegulatory = 1; + if(priv->eeprom_smid >= 0x7000 && priv->eeprom_smid < 0x8000){ + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + priv->rtllib->bForcedBgMode = true; + } + } + break; + case RT_CID_CCX: + priv->DMFlag |= (HAL_DM_DIG_DISABLE | HAL_DM_HIPWR_DISABLE); + break; + + case RT_CID_819x_Lenovo: + priv->LedStrategy = SW_LED_MODE7; + if(priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE025){ + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + else if (priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8191) + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + break; + + case RT_CID_819x_QMI: + priv->LedStrategy = SW_LED_MODE8; + break; + + case RT_CID_819x_MSI: + priv->LedStrategy = SW_LED_MODE9; + if(priv->eeprom_svid == 0x1462 && priv->eeprom_smid == 0x897A){ + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + } + break; + + case RT_CID_819x_HP: + priv->LedStrategy = SW_LED_MODE7; + priv->bLedOpenDrain = true; + + case RT_CID_819x_Foxcoon: + priv->LedStrategy = SW_LED_MODE10; + if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8192) + if(priv->RegWirelessMode != WIRELESS_MODE_B){ + priv->RegWirelessMode = WIRELESS_MODE_G; + priv->rtllib->mode = WIRELESS_MODE_G; + } + break; + + case RT_CID_WHQL: + ; + break; + + default: + RT_TRACE(COMP_INIT,"Unkown hardware Type \n"); + break; + } +} + +static void rtl8192se_read_eeprom_info(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u16 i,usValue; + u16 EEPROMId; +#if (EEPROM_OLD_FORMAT_SUPPORT == 1) + u8 tmpBuffer[30]; +#endif + u8 tempval; + u8 hwinfo[HWSET_MAX_SIZE_92S]; + u8 rf_path, index; + + RT_TRACE(COMP_INIT, "====> rtl8192se_read_eeprom_info\n"); + + if (priv->epromtype== EEPROM_93C46) + { + write_nic_byte(dev, SYS_ISO_CTRL+1, 0xE8); + mdelay(10); + write_nic_byte(dev, PMC_FSM, 0x02); + + RT_TRACE(COMP_INIT, "EEPROM\n"); + for(i = 0; i < HWSET_MAX_SIZE_92S; i += 2) + { + usValue = eprom_read(dev, (u16) (i>>1)); + *((u16*)(&hwinfo[i])) = usValue; + } + } + else if (priv->epromtype == EEPROM_BOOT_EFUSE) + { + RT_TRACE(COMP_INIT, "EFUSE\n"); + + EFUSE_ShadowMapUpdate(dev); + + memcpy( hwinfo, &priv->EfuseMap[EFUSE_INIT_MAP][0], HWSET_MAX_SIZE_92S); + } + + + EEPROMId = *((u16 *)&hwinfo[0]); + if( EEPROMId != RTL8190_EEPROM_ID ) + { + RT_TRACE(COMP_ERR, "EEPROM ID(%#x) is invalid!!\n", EEPROMId); + priv->AutoloadFailFlag=true; + } + else + { + RT_TRACE(COMP_EPROM, "Autoload OK\n"); + priv->AutoloadFailFlag=false; + } + + if (priv->AutoloadFailFlag == true) + { + rtl8192se_config_hw_for_load_fail(dev); + return; + } + + rtl8192se_get_IC_Inferiority(dev); + + priv->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; + priv->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; + priv->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; + priv->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; + priv->eeprom_version = *(u16 *)&hwinfo[EEPROM_Version]; + + RT_TRACE(COMP_EPROM, "EEPROMId = 0x%4x\n", EEPROMId); + RT_TRACE(COMP_EPROM, "EEPROM VID = 0x%4x\n", priv->eeprom_vid); + RT_TRACE(COMP_EPROM, "EEPROM DID = 0x%4x\n", priv->eeprom_did); + RT_TRACE(COMP_EPROM, "EEPROM SVID = 0x%4x\n", priv->eeprom_svid); + RT_TRACE(COMP_EPROM, "EEPROM SMID = 0x%4x\n", priv->eeprom_smid); + + priv->EEPROMOptional = *(u8 *)&hwinfo[EEPROM_Optional]; + priv->ShowRateMode = 2; + priv->rtllib->bForcedShowRxRate = false; + + if(priv->ShowRateMode == 0) { + if((priv->EEPROMOptional & BIT3) == 0x08/*0000_1000*/) { + priv->rtllib->bForcedShowRxRate = true; + } + } else if(priv->ShowRateMode == 2){ + priv->rtllib->bForcedShowRxRate = true; + } + + for(i = 0; i < 6; i += 2) + { + usValue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR+i]; + *((u16*)(&dev->dev_addr[i])) = usValue; + } + for (i=0;i<6;i++) + write_nic_byte(dev, MACIDR0+i, dev->dev_addr[i]); + + RT_TRACE(COMP_EPROM, "ReadAdapterInfo8192S(), Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n", + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], + dev->dev_addr[4], dev->dev_addr[5]); + +#if (EEPROM_OLD_FORMAT_SUPPORT == 1) + for(i = 0; i < EEPROM_TX_PWR_INDEX_RANGE; i += 2) + { + usValue = *(u16 *)&hwinfo[EEPROM_TxPowerBase+i]; + *((u16 *)(&tmpBuffer[i])) = usValue; + } + for(i=0; i<14; i++) + { + priv->EEPROMTxPowerLevelCCK[i] = (u8)tmpBuffer[i]; + priv->EEPROMTxPowerLevelOFDM24G[i] = (u8)tmpBuffer[i+14]; + } + + + for(i=0; i<14; i++) + { + priv->TxPowerLevelOFDM24G[i] = priv->EEPROMTxPowerLevelOFDM24G[i]; + priv->TxPowerLevelCCK[i] = priv->EEPROMTxPowerLevelCCK[i]; + + RT_TRACE(COMP_EPROM, "CH%d CCK Tx PWR IDX = 0x%02x\n", i, priv->EEPROMTxPowerLevelCCK[i]); + RT_TRACE(COMP_EPROM, "CH%d OFDM Tx PWR IDX = 0x%02x\n", i, priv->EEPROMTxPowerLevelOFDM24G[i]); + } + + for(i = 0; i < 6; i += 2) + { + usValue = *(u16 *)&hwinfo[EEPROM_HT2T_CH1_A+i]; + *((u16*)(&priv->EEPROMHT2T_TxPwr[i])) = usValue; + } + for(i=0; i<6; i++) + { + RT_TRACE(COMP_EPROM, "EEPROMHT2T_TxPwr, Index %d = 0x%02x\n", i, priv->EEPROMHT2T_TxPwr[i]); + } + +#else + + for (rf_path = 0; rf_path < 2; rf_path++) + { + for (i = 0; i < 3; i++) + { + priv->RfCckChnlAreaTxPwr[rf_path][i] = + hwinfo[EEPROM_TxPowerBase+rf_path*3+i]; + + priv->RfOfdmChnlAreaTxPwr1T[rf_path][i] = + hwinfo[EEPROM_TxPowerBase+6+rf_path*3+i]; + + priv->RfOfdmChnlAreaTxPwr2T[rf_path][i] = + hwinfo[EEPROM_TxPowerBase+12+rf_path*3+i]; + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) + { + for (i = 0; i < 3; i++) + { + RT_TRACE(COMP_EPROM,"CCK RF-%d CHan_Area-%d = 0x%x\n", rf_path, i, + priv->RfCckChnlAreaTxPwr[rf_path][i]); + RT_TRACE(COMP_EPROM, "OFDM-1T RF-%d CHan_Area-%d = 0x%x\n", rf_path, i, + priv->RfOfdmChnlAreaTxPwr1T[rf_path][i]); + RT_TRACE(COMP_EPROM,"OFDM-2T RF-%d CHan_Area-%d = 0x%x\n", rf_path, i, + priv->RfOfdmChnlAreaTxPwr2T[rf_path][i]); + } + + for(i=0; i<14; i++) + { + if (i < 3) + index = 0; + else if (i < 8) + index = 1; + else + index = 2; + + priv->RfTxPwrLevelCck[rf_path][i] = + priv->RfCckChnlAreaTxPwr[rf_path][index]; + priv->RfTxPwrLevelOfdm1T[rf_path][i] = + priv->RfOfdmChnlAreaTxPwr1T[rf_path][index]; + priv->RfTxPwrLevelOfdm2T[rf_path][i] = + priv->RfOfdmChnlAreaTxPwr2T[rf_path][index]; + + if (rf_path == 0) + { + priv->TxPowerLevelOFDM24G[i] = priv->RfTxPwrLevelOfdm1T[rf_path][i] ; + priv->TxPowerLevelCCK[i] = priv->RfTxPwrLevelCck[rf_path][i]; + } + } + + for(i=0; i<14; i++) + { + RT_TRACE(COMP_EPROM, "Rf-%d TxPwr CH-%d CCK OFDM_1T OFDM_2T= 0x%x/0x%x/0x%x\n", + rf_path, i, priv->RfTxPwrLevelCck[rf_path][i], + priv->RfTxPwrLevelOfdm1T[rf_path][i] , + priv->RfTxPwrLevelOfdm2T[rf_path][i] ); + } + } + for (rf_path = 0; rf_path < 2; rf_path++) + { + for (i = 0; i < 3; i++) + { + priv->EEPROMPwrGroup[rf_path][i] = hwinfo[EEPROM_TxPWRGroup+rf_path*3+i]; + } + } + + for (rf_path = 0; rf_path < 2; rf_path++) + { + for(i=0; i<14; i++) + { + if (i < 3) + index = 0; + else if (i < 8) + index = 1; + else + index = 2; + priv->PwrGroupHT20[rf_path][i] = (priv->EEPROMPwrGroup[rf_path][index]&0xf); + priv->PwrGroupHT40[rf_path][i] = ((priv->EEPROMPwrGroup[rf_path][index]&0xf0)>>4); + RT_TRACE(COMP_INIT, "RF-%d PwrGroupHT20[%d] = 0x%x\n", rf_path, i, priv->PwrGroupHT20[rf_path][i]); + RT_TRACE(COMP_INIT, "RF-%d PwrGroupHT40[%d] = 0x%x\n", rf_path, i, priv->PwrGroupHT40[rf_path][i]); + } + } + + for(i=0; i<14; i++) + { + if (i < 3) + index = 0; + else if (i < 8) + index = 1; + else + index = 2; + + tempval = (*(u8 *)&hwinfo[EEPROM_TX_PWR_HT20_DIFF+index])&0xff; + priv->TxPwrHt20Diff[RF90_PATH_A][i] = (tempval&0xF); + priv->TxPwrHt20Diff[RF90_PATH_B][i] = ((tempval>>4)&0xF); + + if (i < 3) + index = 0; + else if (i < 8) + index = 0x11; + else + index = 1; + + tempval = (*(u8 *)&hwinfo[EEPROM_TX_PWR_OFDM_DIFF+index])&0xff; + priv->TxPwrLegacyHtDiff[RF90_PATH_A][i] = (tempval&0xF); + priv->TxPwrLegacyHtDiff[RF90_PATH_B][i] = ((tempval>>4)&0xF); + + tempval = (*(u8 *)&hwinfo[TX_PWR_SAFETY_CHK]); + priv->TxPwrSafetyFlag = (tempval&0x01); + } + + priv->EEPROMRegulatory = 0; + if(priv->eeprom_version >= 2) + { + if(priv->eeprom_version >= 4) + priv->EEPROMRegulatory = (hwinfo[EEPROM_Regulatory]&0x7); + else + priv->EEPROMRegulatory = (hwinfo[EEPROM_Regulatory]&0x1); + } + RT_TRACE(COMP_INIT, "EEPROMRegulatory = 0x%x\n", priv->EEPROMRegulatory); + + for(i=0; i<14; i++) + RT_TRACE(COMP_EPROM, "RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, priv->TxPwrHt20Diff[RF90_PATH_A][i]); + for(i=0; i<14; i++) + RT_TRACE(COMP_EPROM, "RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, priv->TxPwrLegacyHtDiff[RF90_PATH_A][i]); + for(i=0; i<14; i++) + RT_TRACE(COMP_EPROM, "RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, priv->TxPwrHt20Diff[RF90_PATH_B][i]); + for(i=0; i<14; i++) + RT_TRACE(COMP_EPROM, "RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, priv->TxPwrLegacyHtDiff[RF90_PATH_B][i]); +#endif + RT_TRACE(COMP_EPROM, "TxPwrSafetyFlag = %d\n", priv->TxPwrSafetyFlag); + + tempval = (*(u8 *)&hwinfo[EEPROM_RFInd_PowerDiff])&0xff; + priv->EEPROMTxPowerDiff = tempval; + priv->LegacyHTTxPowerDiff = priv->TxPwrLegacyHtDiff[RF90_PATH_A][0]; + + RT_TRACE(COMP_EPROM, "TxPowerDiff = %#x\n", priv->EEPROMTxPowerDiff); + + usValue = *(u16 *)&hwinfo[EEPROM_TSSI_A]; + priv->EEPROMTSSI_A = (u8)((usValue&0xff00)>>8); + usValue = *(u8 *)&hwinfo[EEPROM_TSSI_B]; + priv->EEPROMTSSI_B = (u8)(usValue&0xff); + RT_TRACE(COMP_EPROM, "TSSI_A = %#x, TSSI_B = %#x\n", + priv->EEPROMTSSI_A, priv->EEPROMTSSI_B); + + tempval = *(u8 *)&hwinfo[EEPROM_ThermalMeter]; + priv->EEPROMThermalMeter = tempval; + RT_TRACE(COMP_EPROM, "ThermalMeter = %#x\n", priv->EEPROMThermalMeter); + priv->ThermalMeter[0] =(priv->EEPROMThermalMeter&0x1f); + priv->TSSI_13dBm = priv->EEPROMThermalMeter *100; + + tempval = *(u8 *)&hwinfo[EEPROM_BLUETOOTH_COEXIST]; + priv->EEPROMBluetoothCoexist = ((tempval&0x2)>>1); + priv->BluetoothCoexist = priv->EEPROMBluetoothCoexist; + tempval = hwinfo[EEPROM_BLUETOOTH_TYPE]; + priv->EEPROMBluetoothType = ((tempval&0xe)>>1); + priv->EEPROMBluetoothAntNum = (tempval&0x1); + priv->EEPROMBluetoothAntIsolation = ((tempval&0x10)>>4); + RT_TRACE(COMP_EPROM, "BlueTooth Coexistance = %#x\n", priv->BluetoothCoexist); + +#ifdef MERGE_TO_DO + BT_VAR_INIT(Adapter); + + tempval = hwinfo[EEPROM_WoWLAN]; + priv->EEPROMSupportWoWLAN = ((tempval&0x4)>>2); + if (priv->EEPROMSupportWoWLAN) + priv->bHwSupportRemoteWakeUp = true; + else + priv->bHwSupportRemoteWakeUp = false; +#endif +#ifdef RTL8192S_WAPI_SUPPORT + tempval = *(u8 *)&hwinfo[EEPROM_WAPI_SUPPORT]; + priv->EEPROMWapiSupport = ((tempval&0x10)>>4); + priv->EEPROMWapiSupport = 1; + + priv->WapiSupport = priv->EEPROMWapiSupport; + priv->rtllib->WapiSupport = priv->WapiSupport; + RT_TRACE(COMP_EPROM, "WAPI Support = %#x\n", priv->WapiSupport); +#endif + + tempval = (*(u8 *)&hwinfo[EEPROM_CrystalCap])>>4; + priv->EEPROMCrystalCap =tempval; + RT_TRACE(COMP_EPROM, "CrystalCap = %#x\n", priv->EEPROMCrystalCap); + priv->CrystalCap = priv->EEPROMCrystalCap; + + priv->eeprom_ChannelPlan = *(u8 *)&hwinfo[EEPROM_ChannelPlan]; + priv->bTXPowerDataReadFromEEPORM = true; + RT_TRACE(COMP_EPROM, "EEPROM ChannelPlan = 0x%4x\n", priv->eeprom_ChannelPlan); + + tempval = *(u8*)&hwinfo[EEPROM_BoardType]; + if (tempval == 0) + priv->rf_type= RF_2T2R; + else if (tempval == 1) + priv->rf_type = RF_1T2R; + else if (tempval == 2) + priv->rf_type = RF_1T2R; + else if (tempval == 3) + priv->rf_type = RF_1T1R; + + priv->rtllib->RF_Type = priv->rf_type; + priv->rtllib->b1x1RecvCombine = false; + if (priv->rf_type == RF_1T2R) + { + tempval = read_nic_byte(dev, 0x07); + if (!(tempval & BIT0)) + { + priv->rtllib->b1x1RecvCombine = true; + RT_TRACE(COMP_INIT, "RF_TYPE=1T2R but only 1SS\n"); + } + } + priv->rtllib->b1SSSupport = priv->rtllib->b1x1RecvCombine; + + priv->rf_chip = RF_6052; + + priv->eeprom_CustomerID = *(u8 *)&hwinfo[EEPROM_CustomID]; + + RT_TRACE(COMP_EPROM, "EEPROM Customer ID: 0x%2x, rf_chip:%x\n", priv->eeprom_CustomerID, priv->rf_chip); + + priv->rtllib->b_customer_lenovo_id = false; + + switch(priv->eeprom_CustomerID) + { + case EEPROM_CID_DEFAULT: + + if(priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8190) + priv->CustomerID = RT_CID_819x_Lenovo; + else if(priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8191) + priv->CustomerID = RT_CID_819x_Lenovo; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE020) + priv->CustomerID = RT_CID_819x_Lenovo; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE025) + priv->CustomerID = RT_CID_819x_Lenovo; + else if(priv->eeprom_svid == 0x1A32 && priv->eeprom_smid == 0x0308) + priv->CustomerID = RT_CID_819x_QMI; + else if(priv->eeprom_svid == 0x1A32 && priv->eeprom_smid == 0x0311) + priv->CustomerID = RT_CID_819x_QMI; + else if(priv->eeprom_svid == 0x1462 && priv->eeprom_smid == 0x6897) + priv->CustomerID = RT_CID_819x_MSI; + else if(priv->eeprom_svid == 0x1462 && priv->eeprom_smid == 0x3821) + priv->CustomerID = RT_CID_819x_MSI; + else if(priv->eeprom_svid == 0x1462 && priv->eeprom_smid == 0x897A) + priv->CustomerID = RT_CID_819x_MSI; + /****************************************************************************/ + /* ACER ID */ + /****************************************************************************/ + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x7172) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x7173) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8186) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8187) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8156) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8157) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x7172) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x7173) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x8186) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x8187) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x8156) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x8157) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE021) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE022) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8158) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8159) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0xE021) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0xE022) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x8158) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x8159) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x7186) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x7187) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8186) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8187) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8156) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8157) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x7186) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x7187) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x8186) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x8187) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x8156) + priv->CustomerID = RT_CID_819x_Acer; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x1025 && priv->eeprom_smid == 0x8157) + priv->CustomerID = RT_CID_819x_Acer; + /****************************************************************************/ + /* ACER ID END */ + /****************************************************************************/ + + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x103C && priv->eeprom_smid == 0x1467) + priv->CustomerID = RT_CID_819x_HP; + + else if(priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8192) + priv->CustomerID = RT_CID_819x_Foxcoon; + else if(priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8193) + priv->CustomerID = RT_CID_819x_Foxcoon; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8188) + priv->CustomerID = RT_CID_819x_SAMSUNG; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8171 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8189) + priv->CustomerID = RT_CID_819x_SAMSUNG; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE023) + priv->CustomerID = RT_CID_819x_SAMSUNG; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8172 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0xE024) + priv->CustomerID = RT_CID_819x_SAMSUNG; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8190) + priv->CustomerID = RT_CID_819x_SAMSUNG; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8191) + priv->CustomerID = RT_CID_819x_SAMSUNG; + else if( priv->eeprom_vid == 0x10EC && priv->eeprom_did == 0x8174 && + priv->eeprom_svid == 0x10EC && priv->eeprom_smid == 0x8192) + priv->CustomerID = RT_CID_819x_SAMSUNG; + else + priv->CustomerID = RT_CID_DEFAULT; + break; + + case EEPROM_CID_TOSHIBA: + priv->CustomerID = RT_CID_TOSHIBA; + break; + + case EEPROM_CID_QMI: + priv->CustomerID = RT_CID_819x_QMI; + break; + + case EEPROM_CID_WHQL: +#ifdef TO_DO_LIST + priv->bInHctTest = true; + priv->bSupportTurboMode = false; + priv->bAutoTurboBy8186 = false; + priv->PowerSaveControl.bInactivePs = false; + priv->PowerSaveControl.bIPSModeBackup = false; + priv->PowerSaveControl.bLeisurePs = false; + priv->keepAliveLevel = 0; + priv->bUnloadDriverwhenS3S4 = false; +#endif + break; + + default: + priv->CustomerID = RT_CID_DEFAULT; + break; + + } + +#if defined (RTL8192S_WAPI_SUPPORT) + if (priv->rtllib->WapiSupport) + { + WapiInit(priv->rtllib); + } +#endif + RT_TRACE(COMP_INIT, "<==== rtl8192se_read_eeprom_info\n"); +} + +void rtl8192se_get_eeprom_size(struct net_device* dev) +{ + struct r8192_priv* priv = rtllib_priv(dev); + u8 curCR = 0; + curCR = read_nic_byte(dev, EPROM_CMD); + PHY_RFShadowRefresh(dev); + if (curCR & BIT4){ + RT_TRACE(COMP_EPROM, "Boot from EEPROM\n"); + priv->epromtype = EEPROM_93C46; + } + else{ + RT_TRACE(COMP_EPROM, "Boot from EFUSE\n"); + priv->epromtype = EEPROM_BOOT_EFUSE; + } + if (curCR & BIT5){ + RT_TRACE(COMP_EPROM,"Autoload OK\n"); + priv->AutoloadFailFlag=false; + rtl8192se_read_eeprom_info(dev); + } + else{ + RT_TRACE(COMP_INIT, "AutoLoad Fail reported from CR9346!!\n"); + priv->AutoloadFailFlag=true; + rtl8192se_config_hw_for_load_fail(dev); + + if (priv->epromtype == EEPROM_BOOT_EFUSE) + { +#if (RTL92SE_FPGA_VERIFY == 0) + EFUSE_ShadowMapUpdate(dev); +#endif + } + } +#ifdef TO_DO_LIST + if(Adapter->bInHctTest) + { + pMgntInfo->PowerSaveControl.bInactivePs = false; + pMgntInfo->PowerSaveControl.bIPSModeBackup = false; + pMgntInfo->PowerSaveControl.bLeisurePs = false; + pMgntInfo->keepAliveLevel = 0; + } +#endif +#ifdef ENABLE_DOT11D + priv->ChannelPlan = COUNTRY_CODE_WORLD_WIDE_13; + + if(priv->ChannelPlan == COUNTRY_CODE_GLOBAL_DOMAIN) { + GET_DOT11D_INFO(priv->rtllib)->bEnabled = 1; + RT_TRACE(COMP_INIT, "%s: Enable dot11d when RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN!\n", __FUNCTION__); + } +#endif + + RT_TRACE(COMP_INIT, "RegChannelPlan(%d) EEPROMChannelPlan(%d)", \ + priv->RegChannelPlan, priv->eeprom_ChannelPlan); + RT_TRACE(COMP_INIT, "ChannelPlan = %d\n" , priv->ChannelPlan); + HalCustomizedBehavior8192S(dev); +} + +#if (RTL92SE_FPGA_VERIFY == 1) +static void MacConfigBeforeFwDownload(struct net_device* dev) +{ + struct r8192_priv* priv = rtllib_priv(dev); + u8 i; + u8 tmpU1b; + u16 tmpU2b; + u32 addr; + + RT_TRACE(COMP_INIT, "Set some register before enable NIC\r\n"); + + tmpU1b = read_nic_byte(dev, 0x562); + tmpU1b |= 0x08; + write_nic_byte(dev, 0x562, tmpU1b); + tmpU1b &= ~(BIT3); + write_nic_byte(dev, 0x562, tmpU1b); + + tmpU1b = read_nic_byte(dev, SYS_FUNC_EN+1); + tmpU1b &= 0x73; + write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b); + + tmpU1b = read_nic_byte(dev, SYS_CLKR); + tmpU1b &= 0xfa; + write_nic_byte(dev, SYS_CLKR, tmpU1b); + + RT_TRACE(COMP_INIT, "Delay 1000ms before reset NIC. I dont know how long should we delay!!!!!\r\n"); + ssleep(1); + + write_nic_byte(dev, SYS_CLKR, SYS_CLKSEL_80M); + + tmpU1b = read_nic_byte(dev, SPS1_CTRL); + write_nic_byte(dev, SPS1_CTRL, (tmpU1b|SPS1_LDEN)); + + tmpU1b = read_nic_byte(dev, AFE_MISC); + write_nic_byte(dev, AFE_MISC, (tmpU1b|AFE_BGEN)); + + tmpU1b = read_nic_byte(dev, LDOA15_CTRL); + write_nic_byte(dev, LDOA15_CTRL, (tmpU1b|LDA15_EN)); + + tmpU1b = read_nic_byte(dev, SPS1_CTRL); + write_nic_byte(dev, SPS1_CTRL, (tmpU1b|SPS1_SWEN)); + + tmpU1b = read_nic_byte(dev, AFE_MISC); + write_nic_byte(dev, AFE_MISC, (tmpU1b|AFE_MBEN)); + + tmpU2b = read_nic_word(dev, SYS_ISO_CTRL); + write_nic_word(dev, SYS_ISO_CTRL, (tmpU2b|ISO_PWC_DV2RP)); + + tmpU2b = read_nic_word(dev, SYS_ISO_CTRL); + write_nic_word(dev, SYS_ISO_CTRL, (tmpU2b &(~ISO_PWC_RV2RP))); + + tmpU2b = read_nic_word(dev, AFE_XTAL_CTRL); + write_nic_word(dev, AFE_XTAL_CTRL, (tmpU2b &(~XTAL_GATE_AFE))); + + tmpU1b = read_nic_byte(dev, AFE_PLL_CTRL); + write_nic_byte(dev, AFE_PLL_CTRL, (tmpU1b|APLL_EN)); + + write_nic_byte(dev, SYS_ISO_CTRL, 0xEE); + + tmpU2b = read_nic_word(dev, SYS_CLKR); + write_nic_word(dev, SYS_CLKR, (tmpU2b|SYS_MAC_CLK_EN)); + + tmpU2b = read_nic_word(dev, SYS_FUNC_EN); + write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|FEN_DCORE|FEN_MREGEN)); + + tmpU2b = read_nic_word(dev, SYS_CLKR); + write_nic_word(dev, SYS_CLKR, ((tmpU2b|SYS_FWHW_SEL)&(~SYS_SWHW_SEL))); + + write_nic_byte(dev, RF_CTRL, 0); + write_nic_byte(dev, RF_CTRL, 7); + + write_nic_word(dev, CMDR, 0x37FC); + +#if 1 + write_nic_byte(dev, 0x6, 0x30); + write_nic_byte(dev, 0x49, 0xf0); + + write_nic_byte(dev, 0x4b, 0x81); + + write_nic_byte(dev, 0xb5, 0x21); + + write_nic_byte(dev, 0xdc, 0xff); + write_nic_byte(dev, 0xdd, 0xff); + write_nic_byte(dev, 0xde, 0xff); + write_nic_byte(dev, 0xdf, 0xff); + + write_nic_byte(dev, 0x11a, 0x00); + write_nic_byte(dev, 0x11b, 0x00); + + for (i = 0; i < 32; i++) + write_nic_byte(dev, INIMCS_SEL+i, 0x1b); + + write_nic_byte(dev, 0x236, 0xff); + + write_nic_byte(dev, 0x503, 0x22); + + if(priv->bSupportASPM){ + write_nic_byte(dev, 0x560, 0x40); + } else { + write_nic_byte(dev, 0x560, 0x00); + } + + write_nic_byte(dev, DBG_PORT, 0x91); +#endif + +#ifdef CONFIG_RX_CMD + write_nic_dword(dev, RCDA, priv->rx_ring_dma[RX_CMD_QUEUE]); +#endif + write_nic_dword(dev, RDQDA, priv->rx_ring_dma[RX_MPDU_QUEUE]); + rtl8192_tx_enable(dev); + + RT_TRACE(COMP_INIT, "<---MacConfig8192SE()\n"); + +} /* MacConfigBeforeFwDownload */ +#else +void gen_RefreshLedState(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed0 = &(priv->SwLed0); + + if(priv->bfirst_init) + { + RT_TRACE(COMP_INIT, "gen_RefreshLedState first init\n"); + return; + } + + if(priv->rtllib->RfOffReason == RF_CHANGE_BY_IPS ) + { + SwLedOn(dev, pLed0); + } + else + { + SwLedOff(dev, pLed0); + } + +} +void MacConfigBeforeFwDownload(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 i; + u8 tmpU1b; + u16 tmpU2b; + u8 PollingCnt = 20; + + RT_TRACE(COMP_INIT, "--->MacConfigBeforeFwDownload()\n"); + + if (priv->initialized_at_probe) { + return; + } + + if(priv->bfirst_init) + { + tmpU1b = read_nic_byte(dev, SYS_FUNC_EN+1); + tmpU1b &= 0xFE; + write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b); + udelay(1); + write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b|BIT0); + } + + tmpU1b = read_nic_byte(dev, (SYS_CLKR + 1)); + if(tmpU1b & BIT7) + { + tmpU1b &= ~(BIT6 | BIT7); + if(!HalSetSysClk8192SE(dev, tmpU1b)) + return; + } + +#ifdef MERGE_TO_DO + if( (pHalData->bt_coexist.BluetoothCoexist) && + (pHalData->bt_coexist.BT_CoexistType == BT_CSR) ) + { + write_nic_byte(dev, AFE_PLL_CTRL, 0x0); + udelay(50); + write_nic_byte(dev, LDOA15_CTRL, 0x34); + udelay(50); + } + else +#endif + { + write_nic_byte(dev, AFE_PLL_CTRL, 0x0); + udelay(50); + write_nic_byte(dev, LDOA15_CTRL, 0x34); + udelay(50); + } + + + write_nic_byte(dev, RPWM, 0x0); + + tmpU1b = read_nic_byte(dev, SYS_FUNC_EN+1); + tmpU1b &= 0x73; + write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b); + mdelay(1); + + write_nic_byte(dev, CMDR, 0); + write_nic_byte(dev, TCR, 0); + +#if (DEMO_BOARD_SUPPORT == 0) + tmpU1b = read_nic_byte(dev, SPS1_CTRL); + tmpU1b &= 0xfc; + write_nic_byte(dev, SPS1_CTRL, tmpU1b); +#endif + + tmpU1b = read_nic_byte(dev, 0x562); + tmpU1b |= 0x08; + write_nic_byte(dev, 0x562, tmpU1b); + tmpU1b &= ~(BIT3); + write_nic_byte(dev, 0x562, tmpU1b); + + + + + + RT_TRACE(COMP_INIT, "Enable AFE clock source\r\n"); + tmpU1b = read_nic_byte(dev, AFE_XTAL_CTRL); + write_nic_byte(dev, AFE_XTAL_CTRL, (tmpU1b|0x01)); + udelay(2000); + tmpU1b = read_nic_byte(dev, AFE_XTAL_CTRL+1); + write_nic_byte(dev, AFE_XTAL_CTRL+1, (tmpU1b&0xfb)); + + + RT_TRACE(COMP_INIT, "Enable AFE Macro Block's Bandgap\r\n"); + tmpU1b = read_nic_byte(dev, AFE_MISC); + write_nic_byte(dev, AFE_MISC, (tmpU1b|BIT0)); + mdelay(1); + + RT_TRACE(COMP_INIT, "Enable AFE Mbias\r\n"); + tmpU1b = read_nic_byte(dev, AFE_MISC); + write_nic_byte(dev, AFE_MISC, (tmpU1b|0x02)); + mdelay(1); + + tmpU1b = read_nic_byte(dev, LDOA15_CTRL); + write_nic_byte(dev, LDOA15_CTRL, (tmpU1b|BIT0)); + + + + tmpU2b = read_nic_word(dev, SYS_ISO_CTRL); + write_nic_word(dev, SYS_ISO_CTRL, (tmpU2b|BIT11)); + + + tmpU2b = read_nic_word(dev, SYS_FUNC_EN); + write_nic_word(dev, SYS_FUNC_EN, (tmpU2b |BIT13)); + + + write_nic_byte(dev, SYS_ISO_CTRL+1, 0x68); + + udelay(200); + tmpU1b = read_nic_byte(dev, AFE_PLL_CTRL); + write_nic_byte(dev, AFE_PLL_CTRL, (tmpU1b|BIT0|BIT4)); + +#if 1 + udelay(100); + write_nic_byte(dev, AFE_PLL_CTRL, (tmpU1b|BIT0|BIT4|BIT6)); + udelay(10); + write_nic_byte(dev, AFE_PLL_CTRL, (tmpU1b|BIT0|BIT4)); + udelay(10); +#endif + tmpU1b = read_nic_byte(dev, AFE_PLL_CTRL+1); + write_nic_byte(dev, AFE_PLL_CTRL+1, (tmpU1b|BIT0)); + mdelay(1); + + write_nic_byte(dev, SYS_ISO_CTRL, 0xA6); + + tmpU2b = read_nic_word(dev, SYS_CLKR); + write_nic_word(dev, SYS_CLKR, (tmpU2b|BIT12|BIT11)); + + tmpU2b = read_nic_word(dev, SYS_FUNC_EN); + write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|BIT11)); + + tmpU1b = read_nic_byte(dev, SYS_FUNC_EN+1); + write_nic_byte(dev, SYS_FUNC_EN+1, tmpU1b&~(BIT7)); + + write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|BIT11|BIT15)); + + tmpU2b = read_nic_word(dev, SYS_CLKR); + write_nic_word(dev, SYS_CLKR, (tmpU2b&(~BIT2))); + + tmpU1b = read_nic_byte(dev, (SYS_CLKR + 1)); + tmpU1b = ((tmpU1b | BIT7) & (~BIT6)); + if(!HalSetSysClk8192SE(dev, tmpU1b)) + return; + +#if 0 + tmpU2b = read_nic_word(dev, SYS_CLKR); + write_nic_word(dev, SYS_CLKR, ((tmpU2b|BIT15)&(~BIT14))); +#endif + + write_nic_word(dev, CMDR, 0x07FC); + +#if 1 + write_nic_byte(dev, 0x6, 0x30); + write_nic_byte(dev, 0x49, 0xf0); + + write_nic_byte(dev, 0x4b, 0x81); + + write_nic_byte(dev, 0xb5, 0x21); + + write_nic_byte(dev, 0xdc, 0xff); + write_nic_byte(dev, 0xdd, 0xff); + write_nic_byte(dev, 0xde, 0xff); + write_nic_byte(dev, 0xdf, 0xff); + + write_nic_byte(dev, 0x11a, 0x00); + write_nic_byte(dev, 0x11b, 0x00); + + for (i = 0; i < 32; i++) + write_nic_byte(dev, INIMCS_SEL+i, 0x1b); + + write_nic_byte(dev, 0x236, 0xff); + + write_nic_byte(dev, 0x503, 0x22); + if(priv->bSupportASPM && !priv->bSupportBackDoor){ + write_nic_byte(dev, 0x560, 0x40); + } else { + write_nic_byte(dev, 0x560, 0x00); + } + + write_nic_byte(dev, DBG_PORT, 0x91); +#endif + + write_nic_dword(dev, RDQDA, priv->rx_ring_dma[RX_MPDU_QUEUE]); +#ifdef CONFIG_RX_CMD + write_nic_dword(dev, RCDA, priv->rx_ring_dma[RX_CMD_QUEUE]); +#endif + rtl8192_tx_enable(dev); + + write_nic_word(dev, CMDR, 0x37FC); + do { + tmpU1b = read_nic_byte(dev, TCR); + if((tmpU1b & TXDMA_INIT_VALUE) == TXDMA_INIT_VALUE) + break; + + udelay(5); + } while(PollingCnt--); + + if(PollingCnt <= 0 ) + { + RT_TRACE(COMP_ERR, "MacConfigBeforeFwDownloadASIC(): Polling TXDMA_INIT_VALUE timeout!! Current TCR(%#x)\n", tmpU1b); + tmpU1b = read_nic_byte(dev, CMDR); + write_nic_byte(dev, CMDR, tmpU1b&(~TXDMA_EN)); + udelay(2); + write_nic_byte(dev, CMDR, tmpU1b|TXDMA_EN); + } + + gen_RefreshLedState(dev); + + RT_TRACE(COMP_INIT, "<---MacConfigBeforeFwDownload()\n"); + +} /* MacConfigBeforeFwDownload */ +#endif + +static void MacConfigAfterFwDownload(struct net_device* dev) +{ + u8 i; + u16 tmpU2b; + struct r8192_priv* priv = rtllib_priv(dev); + + + write_nic_byte(dev, CMDR, + (u8)(BBRSTn|BB_GLB_RSTn|SCHEDULE_EN|MACRXEN|MACTXEN|DDMA_EN|FW2HW_EN| + RXDMA_EN|TXDMA_EN|HCI_RXDMA_EN|HCI_TXDMA_EN)); + write_nic_dword(dev, TCR, + read_nic_dword(dev, TCR)|TXDMAPRE2FULL); + write_nic_dword(dev, RCR, priv->ReceiveConfig); + +#if 0 + for (i=0;i<6;i++) + write_nic_byte(dev, MACIDR0+i, dev->dev_addr[i]); +#endif + write_nic_word(dev, SIFS_CCK, 0x0a0a); + write_nic_word(dev, SIFS_OFDM, 0x1010); + write_nic_byte(dev, ACK_TIMEOUT, 0x40); + + write_nic_word(dev, BCN_INTERVAL, 100); + write_nic_word(dev, ATIMWND, 2); +#ifdef _ENABLE_SW_BEACON + write_nic_word(dev, BCN_DRV_EARLY_INT, BIT15); +#endif + +#if 0 + write_nic_dword(dev, RQPN1, + NUM_OF_PAGE_IN_FW_QUEUE_BK<<0 | NUM_OF_PAGE_IN_FW_QUEUE_BE<<8 |\ + NUM_OF_PAGE_IN_FW_QUEUE_VI<<16 | NUM_OF_PAGE_IN_FW_QUEUE_VO<<24); + write_nic_dword(dev, RQPN2, + NUM_OF_PAGE_IN_FW_QUEUE_HCCA << 0 | NUM_OF_PAGE_IN_FW_QUEUE_CMD << 8|\ + NUM_OF_PAGE_IN_FW_QUEUE_MGNT << 16 |NUM_OF_PAGE_IN_FW_QUEUE_HIGH << 24); + write_nic_dword(dev, RQPN3, + NUM_OF_PAGE_IN_FW_QUEUE_BCN<<0 | NUM_OF_PAGE_IN_FW_QUEUE_PUB<<8); + write_nic_byte(dev, LD_RQPN, BIT7); +#endif + + + + + write_nic_byte(dev, RXDMA, + read_nic_byte(dev, RXDMA)|BIT6); + + if (priv->card_8192_version== VERSION_8192S_ACUT) + write_nic_byte(dev, RRSR, 0xf0); + else if (priv->card_8192_version == VERSION_8192S_BCUT) + write_nic_byte(dev, RRSR, 0xff); + write_nic_byte(dev, RRSR+1, 0x01); + write_nic_byte(dev, RRSR+2, 0x00); + + for (i = 0; i < 8; i++) + { + + if (priv->card_8192_version == VERSION_8192S_ACUT) + write_nic_dword(dev, ARFR0+i*4, 0x1f0ff0f0); +#if 0 + else if (priv->card_8192_version == VERSION_8192S_BCUT) + write_nic_dword(dev, ARFR0+i*4, 0x1f0ff0f0); +#endif + } + + write_nic_byte(dev, AGGLEN_LMT_H, 0x0f); + write_nic_word(dev, AGGLEN_LMT_L, 0x7442); + write_nic_word(dev, AGGLEN_LMT_L+2, 0xddd7); + write_nic_word(dev, AGGLEN_LMT_L+4, 0xd772); + write_nic_word(dev, AGGLEN_LMT_L+6, 0xfffd); + + write_nic_dword(dev, DARFRC, 0x04010000); + write_nic_dword(dev, DARFRC+4, 0x09070605); + write_nic_dword(dev, RARFRC, 0x04010000); + write_nic_dword(dev, RARFRC+4, 0x09070605); + + + + write_nic_word(dev, SG_RATE, 0xFFFF); + + + write_nic_word(dev, NAV_PROT_LEN, 0x0080); + write_nic_byte(dev, CFEND_TH, 0xFF); + write_nic_byte(dev, AMPDU_MIN_SPACE, 0x07); + write_nic_byte(dev, TXOP_STALL_CTRL, 0x00); + + + /*write_nic_byte(dev, PCIF, ((MXDMA2_NoLimit<epromtype == EEPROM_BOOT_EFUSE) + { + u8 tempval; + + tempval = read_nic_byte(dev, SYS_ISO_CTRL+1); + tempval &= 0xFE; + write_nic_byte(dev, SYS_ISO_CTRL+1, tempval); + + + + write_nic_byte(dev, EFUSE_CTRL+3, 0x72); + RT_TRACE(COMP_INIT, "EFUSE CONFIG OK\n"); + } + RT_TRACE(COMP_INIT, "MacConfigAfterFwDownload OK\n"); + +} /* MacConfigAfterFwDownload */ + +static void rtl8192se_HalDetectPwrDownMode(struct net_device*dev) +{ + u8 tmpvalue; + struct r8192_priv *priv = rtllib_priv(dev); + EFUSE_ShadowRead(dev, 1, 0x78, (u32 *)&tmpvalue); + + if (tmpvalue & BIT0) { + priv->pwrdown = true; + } else { + priv->pwrdown = false; + } +} + +void HwConfigureRTL8192SE(struct net_device *dev) +{ + + struct r8192_priv* priv = rtllib_priv(dev); + + u8 regBwOpMode = 0; + u32 regRATR = 0, regRRSR = 0; + u8 regTmp = 0; + + + switch(priv->rtllib->mode) + { + case WIRELESS_MODE_B: + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK; + regRRSR = RATE_ALL_CCK; + break; + case WIRELESS_MODE_A: + regBwOpMode = BW_OPMODE_5G |BW_OPMODE_20MHZ; + regRATR = RATE_ALL_OFDM_AG; + regRRSR = RATE_ALL_OFDM_AG; + break; + case WIRELESS_MODE_G: + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + break; + case WIRELESS_MODE_AUTO: + case WIRELESS_MODE_N_24G: + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + break; + case WIRELESS_MODE_N_5G: + regBwOpMode = BW_OPMODE_5G; + regRATR = RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; + regRRSR = RATE_ALL_OFDM_AG; + break; + default: + regBwOpMode = BW_OPMODE_20MHZ; + regRATR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + regRRSR = RATE_ALL_CCK | RATE_ALL_OFDM_AG; + break; + } + + regTmp = read_nic_byte(dev, INIRTSMCS_SEL); +#if (RTL8192SU_DISABLE_CCK_RATE == 1) + regRRSR = ((regRRSR & 0x000ffff0)<<8) | regTmp; +#else + regRRSR = ((regRRSR & 0x000fffff)<<8) | regTmp; +#endif + write_nic_dword(dev, INIRTSMCS_SEL, regRRSR); + + write_nic_byte(dev, BW_OPMODE, regBwOpMode); + priv->rtllib->SetHwRegHandler(dev, HW_VAR_RETRY_LIMIT, (u8*)(&priv->ShortRetryLimit)); + + write_nic_byte(dev, MLT, 0x8f); + + + +#if 1 + switch(priv->rf_type) + { + case RF_1T2R: + case RF_1T1R: + RT_TRACE(COMP_INIT, "Initializeadapter: RF_Type%s\n", priv->rf_type==RF_1T1R? "(1T1R)":"(1T2R)"); + priv->rtllib->MinSpaceCfg = (MAX_MSS_DENSITY_1T<<3); + break; + case RF_2T2R: + case RF_2T2R_GREEN: + RT_TRACE(COMP_INIT, "Initializeadapter:RF_Type(2T2R)\n"); + priv->rtllib->MinSpaceCfg = (MAX_MSS_DENSITY_2T<<3); + break; + } + write_nic_byte(dev, AMPDU_MIN_SPACE, priv->rtllib->MinSpaceCfg); +#else + priv->rtllib->MinSpaceCfg = 0x90; + SetHwReg8192SE(dev, HW_VAR_AMPDU_MIN_SPACE, (u8*)(&priv->rtllib->MinSpaceCfg)); +#endif +} + +void +RF_RECOVERY(struct net_device*dev ,u8 Start, u8 End) +{ + u8 offset; + u8 counter; + + + for(offset = Start; offsetbeing_init_adapter = true; +#ifdef CONFIG_ASPM_OR_D3 + RT_DISABLE_ASPM(dev); +#endif +start: + rtl8192_pci_resetdescring(dev); + MacConfigBeforeFwDownload(dev); + priv->initialized_at_probe = false; + + priv->card_8192_version = priv->rtllib->VersionID + = (VERSION_8192S)((read_nic_dword(dev, PMC_FSM)>>16)&0xF); + + RT_TRACE(COMP_INIT, "NIC version : %s\n", ((read_nic_dword(dev, PMC_FSM)>>15)&0x1)?"C-cut":"B-cut"); + + rtl8192se_GPIOBit3CfgInputMode(dev); + + rtStatus = FirmwareDownload92S((struct net_device*)dev); + if(rtStatus != true) + { + if(fw_download_times <= 10){ + RT_TRACE(COMP_INIT, "rtl8192se_adapter_start(): Download Firmware failed %d times, Download again!!\n",fw_download_times); + fw_download_times = fw_download_times + 1; + goto start; + }else{ + RT_TRACE(COMP_INIT, "rtl8192se_adapter_start(): Download Firmware failed 10, end!!\n"); + goto end; + } + } + + MacConfigAfterFwDownload(dev); + + priv->FwCmdIOMap = read_nic_word(dev, LBUS_MON_ADDR); + priv->FwCmdIOParam = read_nic_dword(dev, LBUS_ADDR_MASK); + + +#if (RTL8192S_DISABLE_FW_DM == 1) + write_nic_dword(dev, WFM5, FW_DM_DISABLE); + ChkFwCmdIoDone(dev); + write_nic_dword(dev, WFM5, FW_TXANT_SWITCH_DISABLE); + ChkFwCmdIoDone(dev); +#endif + +#if (HAL_MAC_ENABLE == 1) + RT_TRACE(COMP_INIT, "MAC Config Start!\n"); + if (PHY_MACConfig8192S(dev) != true) + { + RT_TRACE(COMP_ERR, "MAC Config failed\n"); + return rtStatus; + } + RT_TRACE(COMP_INIT, "MAC Config Finished!\n"); +#endif + + write_nic_dword(dev, CMDR, 0x37FC); + +#if (HAL_BB_ENABLE == 1) + RT_TRACE(COMP_INIT, "BB Config Start!\n"); + if (PHY_BBConfig8192S(dev) != true) + { + RT_TRACE(COMP_INIT, "BB Config failed\n"); + return rtStatus; + } + RT_TRACE(COMP_INIT, "BB Config Finished!\n"); +#endif + + + +#if 1 + + priv->Rf_Mode = RF_OP_By_SW_3wire; +#else + priv->Rf_Mode = RF_OP_By_SW_3wire; +#if (HAL_RF_ENABLE == 1) + RT_TRACE(COMP_INIT, "RF Config started!\n"); + +#if (RTL92SE_FPGA_VERIFY == 0) + write_nic_byte(dev, AFE_XTAL_CTRL+1, 0xDB); + if(priv->card_8192_version== VERSION_8192S_ACUT) + write_nic_byte(dev, SPS1_CTRL+3, 0x07); + else + write_nic_byte(dev, RF_CTRL, 0x07); +#endif + if(PHY_RFConfig8192S(dev) != true) + { + RT_TRACE(COMP_ERR, "RF Config failed\n"); + return rtStatus; + } + RT_TRACE(COMP_INIT, "RF Config Finished!\n"); +#endif + + + priv->RfRegChnlVal[0] = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)0, RF_CHNLBW, bRFRegOffsetMask); + priv->RfRegChnlVal[1] = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)1, RF_CHNLBW, bRFRegOffsetMask); + + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1); + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1); + + HwConfigureRTL8192SE(dev); + + if(priv->ResetProgress == RESET_TYPE_NORESET) + rtl8192_SetWirelessMode(dev, priv->rtllib->mode); + CamResetAllEntry(dev); + { + u8 SECR_value = 0x0; + SECR_value |= SCR_TxEncEnable; + SECR_value |= SCR_RxDecEnable; + SECR_value |= SCR_NoSKMC; + write_nic_byte(dev, SECR, SECR_value); + } + + { + int i; + for (i=0; i<4; i++) + write_nic_dword(dev, WDCAPARA_ADD[i], 0x5e4322); + } + { + PHY_GetHWRegOriginalValue(dev); +#ifndef CONFIG_MP + rtl8192_phy_setTxPower(dev, priv->chan); +#endif + } +#endif + + + if(!priv->pwrdown){ + if(priv->RegRfOff == true) + { + RT_TRACE((COMP_INIT|COMP_RF), "==++==> InitializeAdapter8190(): Turn off RF for RegRfOff ----------\n"); + MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_SW,true); + + for(eRFPath = 0; eRFPath NumTotalRFPath; eRFPath++) + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x0); + + } + else if(priv->rtllib->RfOffReason > RF_CHANGE_BY_PS) + { + RT_RF_CHANGE_SOURCE rfoffreason = priv->rtllib->RfOffReason; + + RT_TRACE((COMP_INIT|COMP_RF), "InitializeAdapter8190(): ==++==> Turn off RF for RfOffReason(%d) ----------\n", priv->rtllib->RfOffReason); + printk("InitializeAdapter8190(): ==++==> Turn off RF for RfOffReason(%d) ----------\n", priv->rtllib->RfOffReason); + + priv->rtllib->RfOffReason = RF_CHANGE_BY_INIT; + priv->rtllib->eRFPowerState = eRfOn; + MgntActSet_RF_State(dev, eRfOff, rfoffreason,true); + + } + else + { +#if 0 + u8 u1Tmp; + RT_RF_POWER_STATE eRfPowerStateToSet; + + write_nic_byte(dev, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); + u1Tmp = read_nic_byte(dev, MAC_PINMUX_CFG); + u1Tmp = read_nic_byte(dev, GPIO_IO_SEL); + u1Tmp &= HAL_8192S_HW_GPIO_OFF_MASK; + write_nic_byte(dev, GPIO_IO_SEL, u1Tmp); + u1Tmp = read_nic_byte(dev, GPIO_IO_SEL); + mdelay(5); + u1Tmp = read_nic_byte(dev, GPIO_IN); + RTPRINT(FPWR, PWRHW, ("GPIO_IN=%02x\n", u1Tmp)); + eRfPowerStateToSet = (u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? eRfOn : eRfOff; + + RT_TRACE(COMP_INIT, "==++==> InitializeAdapter8190(): RF=%d \n", eRfPowerStateToSet); + if (eRfPowerStateToSet == eRfOff) + { + MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_HW, TRUE); + + } + else + { + priv->rtllib->RfOffReason = 0; + } +#else + if(priv->bHwRadioOff == false){ + priv->rtllib->eRFPowerState = eRfOn; + priv->rtllib->RfOffReason = 0; + if(priv->rtllib->LedControlHandler) + priv->rtllib->LedControlHandler(dev, LED_CTL_POWER_ON); + } +#endif + } + } + +#if 1 +#if (HAL_RF_ENABLE == 1) + RT_TRACE(COMP_INIT, "RF Config started!\n"); + +#if (RTL92SE_FPGA_VERIFY == 0) + write_nic_byte(dev, AFE_XTAL_CTRL+1, 0xDB); + if(priv->card_8192_version== VERSION_8192S_ACUT) + write_nic_byte(dev, SPS1_CTRL+3, 0x07); + else + write_nic_byte(dev, RF_CTRL, 0x07); +#endif + if(PHY_RFConfig8192S(dev) != true) + { + RT_TRACE(COMP_INIT, "RF Config failed\n"); + return rtStatus; + } + RT_TRACE(COMP_INIT, "RF Config Finished!\n"); +#endif + + priv->RfRegChnlVal[0] = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)0, RF_CHNLBW, bRFRegOffsetMask); + priv->RfRegChnlVal[1] = rtl8192_phy_QueryRFReg(dev, (RF90_RADIO_PATH_E)1, RF_CHNLBW, bRFRegOffsetMask); + + /*---- Set CCK and OFDM Block "ON"----*/ + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1); + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1); + + HwConfigureRTL8192SE(dev); + + + + { + /* Get original hw reg values */ + PHY_GetHWRegOriginalValue(dev); + /* Write correct tx power index */ +#ifndef CONFIG_MP + rtl8192_phy_setTxPower(dev, priv->chan); +#endif + } +#endif + + + + { + int i; + for (i=0;i<6;i++) + write_nic_byte(dev, MACIDR0+i, dev->dev_addr[i]); + } + + tmpU1b = read_nic_byte(dev, MAC_PINMUX_CFG); + write_nic_byte(dev, MAC_PINMUX_CFG, tmpU1b&(~BIT3)); + + if(priv->CustomerID == RT_CID_CCX) + { + RT_TRACE(COMP_INIT ,"InitializeAdapter8192SE(): Set FW Cmd FW_TX_FEEDBACK_CCX_ENABLE\n"); + write_nic_dword(dev, WFM5, FW_TX_FEEDBACK_CCX_ENABLE); + ChkFwCmdIoDone(dev); + + write_nic_dword(dev, WFM5, FW_HIGH_PWR_DISABLE); + ChkFwCmdIoDone(dev); + write_nic_dword(dev, WFM5, FW_DIG_HALT); + ChkFwCmdIoDone(dev); + + write_nic_byte(dev, 0xC50, 0x1C); + write_nic_byte(dev, 0xC58, 0x1C); + } + + write_nic_byte(dev, 0x4d, 0x0); + + if(priv->pFirmware->FirmwareVersion >= 0x49){ + u8 tmp_byte = 0; + + tmp_byte = read_nic_byte(dev, FW_RSVD_PG_CRTL) & (~BIT4); + tmp_byte = tmp_byte | BIT5; + write_nic_byte(dev, FW_RSVD_PG_CRTL, tmp_byte); + + write_nic_dword(dev, TXDESC_MSK, 0xFFFFCFFF); + } + + if(priv->pFirmware->FirmwareVersion >= 0x35) + { + priv->rtllib->SetFwCmdHandler(dev, FW_CMD_RA_INIT); + } + else if(priv->pFirmware->FirmwareVersion >= 0x34) + { + write_nic_dword(dev, WFM5, FW_RA_INIT); + ChkFwCmdIoDone(dev); + } + else + { + write_nic_dword(dev, WFM5, FW_RA_RESET); + ChkFwCmdIoDone(dev); + write_nic_dword(dev, WFM5, FW_RA_ACTIVE); + ChkFwCmdIoDone(dev); + write_nic_dword(dev, WFM5, FW_RA_REFRESH); + ChkFwCmdIoDone(dev); + } + + + + PHY_SwitchEphyParameter(dev); + RF_RECOVERY(dev, 0x25, 0x29); + + if(priv->ResetProgress == RESET_TYPE_NORESET) + rtl8192_SetWirelessMode(dev, priv->rtllib->mode); + + CamResetAllEntry(dev); + { + u8 SECR_value = 0x0; + SECR_value |= SCR_TxEncEnable; + SECR_value |= SCR_RxDecEnable; + SECR_value |= SCR_NoSKMC; + write_nic_byte(dev, SECR, SECR_value); + } + + { + int i; + for (i=0; i<4; i++) + write_nic_dword(dev, WDCAPARA_ADD[i], 0x5e4322); + } + + priv->SilentResetRxSlotIndex = 0; + for( i=0; i < MAX_SILENT_RESET_RX_SLOT_NUM; i++ ) + { + priv->SilentResetRxStuckEvent[i] = 0; + } + + if(priv->BluetoothCoexist) + { + printk("Write reg 0x%x = 1 for Bluetooth Co-existance\n", SYSF_CFG); + write_nic_byte(dev, SYSF_CFG, 0x1); + } + + priv->bIgnoreSilentReset = true; + + + if(priv->rf_type ==RF_1T2R) + { +#ifdef MERGE_TODO + bool MrcToSet = true; + RT_TRACE(COMP_INIT, "InitializeAdapter8192SE(): Set MRC settings on as default!!\n"); + priv->rtllib->SetHwRegHandler(dev, HW_VAR_MRC, (u8*)&MrcToSet); +#endif + } + +#ifdef CONFIG_FW_PARSEBEACON + if (!(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){ + write_nic_dword(dev, RXFILTERMAP, 0x0100); + } +#endif + rtl8192_irq_enable(dev); +end: + + priv->rtllib->LPSDelayCnt = 10; + + priv->being_init_adapter = false; + return rtStatus; + + +} + +void rtl8192se_net_update(struct net_device *dev) +{ + + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_network *net = &priv->rtllib->current_network; + u16 rate_config = 0; + u32 regTmp = 0; + u8 rateIndex = 0; + u8 RetryLimit = 0x30; + u16 cap = net->capability; + + priv->short_preamble = cap & WLAN_CAPABILITY_SHORT_PREAMBLE; + + { + rtl8192_config_rate(dev, &rate_config); + if (priv->card_8192_version== VERSION_8192S_ACUT) + priv->basic_rate = rate_config = rate_config & 0x150; + else if (priv->card_8192_version == VERSION_8192S_BCUT) + priv->basic_rate= rate_config = rate_config & 0x15f; + + priv->dot11CurrentPreambleMode = PREAMBLE_AUTO; + +#if 1 + if(priv->rtllib->pHTInfo->IOTPeer == HT_IOT_PEER_CISCO && ((rate_config &0x150)==0)) + { + rate_config |=0x010; + } + if(priv->rtllib->pHTInfo->IOTPeer & HT_IOT_ACT_WA_IOT_Broadcom) + { + rate_config &= 0x1f0; + printk("HW_VAR_BASIC_RATE, HT_IOT_ACT_WA_IOT_Broadcom, BrateCfg = 0x%x\n", rate_config); + } + + write_nic_byte(dev, RRSR, rate_config&0xff); + write_nic_byte(dev, RRSR+1, (rate_config>>8)&0xff); + + while(rate_config > 0x1) + { + rate_config = (rate_config>> 1); + rateIndex++; + } + write_nic_byte(dev, INIRTSMCS_SEL, rateIndex); + + regTmp = (priv->nCur40MhzPrimeSC) << 5; + if (priv->short_preamble) + regTmp |= 0x80; + write_nic_byte(dev, RRSR+2, regTmp); +#endif + } + + write_nic_dword(dev,BSSIDR,((u32*)net->bssid)[0]); + write_nic_word(dev,BSSIDR+4,((u16*)net->bssid)[2]); + + if (priv->rtllib->iw_mode == IW_MODE_ADHOC){ + RetryLimit = HAL_RETRY_LIMIT_AP_ADHOC; + } else { + RetryLimit = (priv->CustomerID == RT_CID_CCX) ? 7 : HAL_RETRY_LIMIT_INFRA; + } + priv->rtllib->SetHwRegHandler(dev, HW_VAR_RETRY_LIMIT, (u8*)(&RetryLimit)); + + if (priv->rtllib->iw_mode == IW_MODE_ADHOC){ + priv->rtllib->SetHwRegHandler( dev, HW_VAR_BEACON_INTERVAL, (u8*)(&net->beacon_interval)); + } + + rtl8192_update_cap(dev, cap); +} + +#ifdef _RTL8192_EXT_PATCH_ +void rtl8192se_mesh_net_update(struct net_device *dev) +{ + + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_network *net = &priv->rtllib->current_mesh_network; + u16 rate_config = 0; + u32 regTmp = 0; + u8 rateIndex = 0; + u8 retrylimit = 0x7; + u16 cap = net->capability; + /* At the peer mesh mode, the peer MP shall recognize the short preamble */ + priv->short_preamble = 1; + + if (priv->card_8192_version== VERSION_8192S_ACUT) + priv->basic_rate = rate_config = 0x150; + else if (priv->card_8192_version == VERSION_8192S_BCUT) + priv->basic_rate= rate_config = 0x15f; + + write_nic_byte(dev, RRSR, rate_config&0xff); + write_nic_byte(dev, RRSR+1, (rate_config>>8)&0xff); + + while(rate_config > 0x1) + { + rate_config = (rate_config>> 1); + rateIndex++; + } + write_nic_byte(dev, INIRTSMCS_SEL, rateIndex); + + regTmp = (priv->nCur40MhzPrimeSC) << 5; + if (priv->short_preamble) + regTmp |= 0x80; + write_nic_byte(dev, RRSR+2, regTmp); + + + write_nic_word(dev, BCN_INTERVAL, net->beacon_interval); + PHY_SetBeaconHwReg( dev, net->beacon_interval); + rtl8192_update_cap(dev, cap); + + priv->ShortRetryLimit = + priv->LongRetryLimit = retrylimit; + + write_nic_word(dev,RETRY_LIMIT, \ + retrylimit << RETRY_LIMIT_SHORT_SHIFT | \ + retrylimit << RETRY_LIMIT_LONG_SHIFT); +} +#endif + +void rtl8192se_link_change(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + u32 reg = 0; + + if(IS_NIC_DOWN(priv)) + return; + + priv->rtllib->GetHwRegHandler(dev, HW_VAR_RCR, (u8*)(®)); + + printk("===>%s():ieee->iw_mode is %d\n",__FUNCTION__,ieee->iw_mode); + if (ieee->state == RTLLIB_LINKED) { +#ifdef CONFIG_FW_PARSEBEACON + if (!(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){ + write_nic_dword(dev, RXFILTERMAP, 0x0000); + } +#endif + if(priv->DM_Type == DM_Type_ByFW) + { + if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_HIGH_POWER) + ieee->SetFwCmdHandler(dev, FW_CMD_HIGH_PWR_DISABLE); + else + ieee->SetFwCmdHandler(dev, FW_CMD_HIGH_PWR_ENABLE); + } + + rtl8192se_net_update(dev); + + if(ieee->bUseRAMask) + { + ieee->UpdateHalRAMaskHandler( + dev, + false, + 0, + ieee->pHTInfo->PeerMimoPs, + ieee->mode, + ieee->pHTInfo->bCurTxBW40MHz, + 0); + priv->rssi_level = 0; + } + else + { + rtl8192se_update_ratr_table(dev,ieee->dot11HTOperationalRateSet,NULL); + } + + { + prate_adaptive pRA = (prate_adaptive)&priv->rate_adaptive; + pRA->PreRATRState = DM_RATR_STA_MAX; + } + + if(ieee->IntelPromiscuousModeInfo.bPromiscuousOn) + ; + else + reg |= RCR_CBSSID; + } +#ifdef _RTL8192_EXT_PATCH_ + else if ((ieee->mesh_state == RTLLIB_MESH_LINKED) && ieee->only_mesh) { + rtl8192se_mesh_net_update(dev); + if(ieee->bUseRAMask){ + ieee->UpdateHalRAMaskHandler( + dev, + false, + 0, + ieee->pHTInfo->PeerMimoPs, + ieee->mode, + ieee->pHTInfo->bCurTxBW40MHz, + 0); + priv->rssi_level = 0; + }else{ + rtl8192se_update_ratr_table(dev,ieee->dot11HTOperationalRateSet,NULL); + } +#ifdef CONFIG_FW_PARSEBEACON + if (!(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){ + write_nic_dword(dev, RXFILTERMAP, 0x0100); + } +#endif + reg &= ~RCR_CBSSID; + } +#endif + else{ +#ifdef CONFIG_FW_PARSEBEACON + if (!(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){ + write_nic_dword(dev, RXFILTERMAP, 0x0100); + } +#endif + reg &= ~RCR_CBSSID; + } + priv->rtllib->SetHwRegHandler( dev, HW_VAR_RCR, (u8*)(®) ); + + rtl8192se_update_msr(dev); + { + u32 temp = read_nic_dword(dev, TCR); + write_nic_dword(dev, TCR, temp&(~BIT8)); + write_nic_dword(dev, TCR, temp|BIT8); + } +} + +void rtl8192se_AllowAllDestAddr(struct net_device* dev, + bool bAllowAllDA, bool WriteIntoReg) +{ + struct r8192_priv* priv = rtllib_priv(dev); + + if( bAllowAllDA ) + { + priv->ReceiveConfig |= RCR_AAP; + } + else + { + priv->ReceiveConfig &= ~RCR_AAP; + } + + if( WriteIntoReg ) + { + write_nic_dword( dev, RCR, priv->ReceiveConfig ); + } +} + + +u8 MRateToHwRate8192SE(struct net_device*dev, u8 rate) +{ + u8 ret = DESC92S_RATE1M; + u16 max_sg_rate; + static u16 multibss_sg_old = 0x1234; + u16 multibss_sg; + + switch(rate) + { + case MGN_1M: ret = DESC92S_RATE1M; break; + case MGN_2M: ret = DESC92S_RATE2M; break; + case MGN_5_5M: ret = DESC92S_RATE5_5M; break; + case MGN_11M: ret = DESC92S_RATE11M; break; + case MGN_6M: ret = DESC92S_RATE6M; break; + case MGN_9M: ret = DESC92S_RATE9M; break; + case MGN_12M: ret = DESC92S_RATE12M; break; + case MGN_18M: ret = DESC92S_RATE18M; break; + case MGN_24M: ret = DESC92S_RATE24M; break; + case MGN_36M: ret = DESC92S_RATE36M; break; + case MGN_48M: ret = DESC92S_RATE48M; break; + case MGN_54M: ret = DESC92S_RATE54M; break; + + case MGN_MCS0: ret = DESC92S_RATEMCS0; break; + case MGN_MCS1: ret = DESC92S_RATEMCS1; break; + case MGN_MCS2: ret = DESC92S_RATEMCS2; break; + case MGN_MCS3: ret = DESC92S_RATEMCS3; break; + case MGN_MCS4: ret = DESC92S_RATEMCS4; break; + case MGN_MCS5: ret = DESC92S_RATEMCS5; break; + case MGN_MCS6: ret = DESC92S_RATEMCS6; break; + case MGN_MCS7: ret = DESC92S_RATEMCS7; break; + case MGN_MCS8: ret = DESC92S_RATEMCS8; break; + case MGN_MCS9: ret = DESC92S_RATEMCS9; break; + case MGN_MCS10: ret = DESC92S_RATEMCS10; break; + case MGN_MCS11: ret = DESC92S_RATEMCS11; break; + case MGN_MCS12: ret = DESC92S_RATEMCS12; break; + case MGN_MCS13: ret = DESC92S_RATEMCS13; break; + case MGN_MCS14: ret = DESC92S_RATEMCS14; break; + case MGN_MCS15: ret = DESC92S_RATEMCS15; break; + + case MGN_MCS0_SG: + case MGN_MCS1_SG: + case MGN_MCS2_SG: + case MGN_MCS3_SG: + case MGN_MCS4_SG: + case MGN_MCS5_SG: + case MGN_MCS6_SG: + case MGN_MCS7_SG: + case MGN_MCS8_SG: + case MGN_MCS9_SG: + case MGN_MCS10_SG: + case MGN_MCS11_SG: + case MGN_MCS12_SG: + case MGN_MCS13_SG: + case MGN_MCS14_SG: + case MGN_MCS15_SG: + ret = DESC92S_RATEMCS15_SG; + max_sg_rate = rate&0xf; + multibss_sg = max_sg_rate | (max_sg_rate<<4) | (max_sg_rate<<8) | (max_sg_rate<<12); + if (multibss_sg_old != multibss_sg) + { + write_nic_dword(dev, SG_RATE, multibss_sg); + multibss_sg_old = multibss_sg; + } + break; + + + case (0x80|0x20): ret = DESC92S_RATEMCS32; break; + + default: ret = DESC92S_RATEMCS15; break; + + } + + return ret; +} + +u8 rtl8192se_MapHwQueueToFirmwareQueue(u8 QueueID, u8 priority) +{ + u8 QueueSelect = 0x0; + + switch(QueueID) { +#if defined RTL8192E || defined RTL8190P + case BE_QUEUE: + QueueSelect = QSLT_BE; + break; + + case BK_QUEUE: + QueueSelect = QSLT_BK; + break; + + case VO_QUEUE: + QueueSelect = QSLT_VO; + break; + + case VI_QUEUE: + QueueSelect = QSLT_VI; + break; + case MGNT_QUEUE: + QueueSelect = QSLT_MGNT; + break; + case BEACON_QUEUE: + QueueSelect = QSLT_BEACON; + break; + case TXCMD_QUEUE: + QueueSelect = QSLT_CMD; + break; + case HIGH_QUEUE: + QueueSelect = QSLT_HIGH; + break; +#elif defined RTL8192SE + case BE_QUEUE: + QueueSelect = priority; + break; + case BK_QUEUE: + QueueSelect = priority; + break; + case VO_QUEUE: + QueueSelect = priority; + break; + case VI_QUEUE: + QueueSelect = priority; + break; + case MGNT_QUEUE: + QueueSelect = QSLT_BE; + break; + case BEACON_QUEUE: + QueueSelect = QSLT_BEACON; + break; + case TXCMD_QUEUE: + QueueSelect = QSLT_CMD; + break; + case HIGH_QUEUE: + QueueSelect = QSLT_HIGH; + break; +#endif + default: + RT_TRACE(COMP_ERR, "TransmitTCB(): Impossible Queue Selection: %d \n", QueueID); + break; + } + return QueueSelect; +} + + +void rtl8192se_tx_fill_desc(struct net_device* dev, tx_desc * pDesc, cb_desc * cb_desc, struct sk_buff* skb) +{ + u8 *pSeq; + u16 Temp; + struct r8192_priv* priv = rtllib_priv(dev); + + struct rtllib_hdr_1addr * header = NULL; + + dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + + u16 fc=0, stype=0; + header = (struct rtllib_hdr_1addr *)(((u8*)skb->data)); + fc = header->frame_ctl; + stype = WLAN_FC_GET_STYPE(fc); + memset((void*)pDesc, 0, 32); + + { + + if(priv->rtllib->bUseRAMask){ + if(cb_desc->macId < 32) + { + pDesc->MacID = cb_desc->macId; + pDesc->Rsvd_MacID = cb_desc->macId; + } + } + pDesc->TXHT = (cb_desc->data_rate&0x80)?1:0; + +#if (RTL92SE_FPGA_VERIFY == 0) + if (priv->card_8192_version== VERSION_8192S_ACUT) + { + if (cb_desc->data_rate== MGN_1M || cb_desc->data_rate == MGN_2M || + cb_desc->data_rate == MGN_5_5M || cb_desc->data_rate == MGN_11M) + { + cb_desc->data_rate = MGN_12M; + } + } +#endif + pDesc->TxRate = MRateToHwRate8192SE(dev,cb_desc->data_rate); + pDesc->TxShort = rtl8192se_QueryIsShort(((cb_desc->data_rate&0x80)?1:0), MRateToHwRate8192SE(dev,cb_desc->data_rate), cb_desc); + + if(cb_desc->bAMPDUEnable) + { + pDesc->AggEn = 1; + } + else + { + pDesc->AggEn = 0; + } + + { + pSeq = (u8 *)(skb->data+22); + Temp = pSeq[0]; + Temp <<= 12; + Temp |= (*(u16 *)pSeq)>>4; + pDesc->Seq = Temp; + } + + pDesc->RTSEn = (cb_desc->bRTSEnable && cb_desc->bCTSEnable==false)?1:0; + pDesc->CTS2Self = (cb_desc->bCTSEnable)?1:0; + pDesc->RTSSTBC = (cb_desc->bRTSSTBC)?1:0; + pDesc->RTSHT = (cb_desc->rts_rate&0x80)?1:0; + +#if (RTL92SE_FPGA_VERIFY == 0) + if (priv->card_8192_version== VERSION_8192S_ACUT) + { + if (cb_desc->rts_rate == MGN_1M || cb_desc->rts_rate == MGN_2M || + cb_desc->rts_rate == MGN_5_5M || cb_desc->rts_rate == MGN_11M) + { + cb_desc->rts_rate = MGN_12M; + } + } +#endif + pDesc->RTSRate = MRateToHwRate8192SE(dev,cb_desc->rts_rate); + pDesc->RTSRate = MRateToHwRate8192SE(dev,MGN_24M); + pDesc->RTSBW = 0; + pDesc->RTSSC = cb_desc->RTSSC; + pDesc->RTSShort = (pDesc->RTSHT==0)?(cb_desc->bRTSUseShortPreamble?1:0):(cb_desc->bRTSUseShortGI?1:0); + if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + { + if(cb_desc->bPacketBW) + { + pDesc->TxBw = 1; + pDesc->TXSC = 0; + } + else + { + pDesc->TxBw = 0; + pDesc->TXSC = priv->nCur40MhzPrimeSC; + } + } + else + { + pDesc->TxBw = 0; + pDesc->TXSC = 0; + } + + pDesc->LINIP = 0; + pDesc->Offset = 32; + pDesc->PktSize = (u16)skb->len; + + pDesc->RaBRSRID = cb_desc->RATRIndex; +#if 0 +printk("*************TXDESC:\n"); +printk("\tTxRate: %d\n", pDesc->TxRate); +printk("\tAMPDUEn: %d\n", pDesc->AggEn); +printk("\tTxBw: %d\n", pDesc->TxBw); +printk("\tTXSC: %d\n", pDesc->TXSC); +printk("\tPktSize: %d\n", pDesc->PktSize); +printk("\tRatrIdx: %d\n", pDesc->RaBRSRID); +#endif + if (cb_desc->bHwSec) { + static u8 tmp =0; + if (!tmp) { + tmp = 1; + } +#ifdef _RTL8192_EXT_PATCH_ + if(cb_desc->mesh_pkt == 0) +#endif + { + switch (priv->rtllib->pairwise_key_type) { + case KEY_TYPE_WEP40: + case KEY_TYPE_WEP104: + pDesc->SecType = 0x1; + break; + case KEY_TYPE_TKIP: + pDesc->SecType = 0x2; + break; + case KEY_TYPE_CCMP: + pDesc->SecType = 0x3; + break; + case KEY_TYPE_NA: + pDesc->SecType = 0x0; + break; + } + } +#ifdef _RTL8192_EXT_PATCH_ + else if(cb_desc->mesh_pkt == 1) + { + switch (priv->rtllib->mesh_pairwise_key_type) { + case KEY_TYPE_WEP40: + case KEY_TYPE_WEP104: + pDesc->SecType = 0x1; + break; + case KEY_TYPE_TKIP: + pDesc->SecType = 0x2; + break; + case KEY_TYPE_CCMP: + pDesc->SecType = 0x3; + break; + case KEY_TYPE_NA: + pDesc->SecType = 0x0; + break; + } + } +#endif + } + + pDesc->PktID = 0x0; + pDesc->QueueSel = rtl8192se_MapHwQueueToFirmwareQueue(cb_desc->queue_index, cb_desc->priority); + + pDesc->DataRateFBLmt = 0x1F; + pDesc->DISFB = cb_desc->bTxDisableRateFallBack; + pDesc->UserRate = cb_desc->bTxUseDriverAssingedRate; + + if (pDesc->UserRate == true && pDesc->TXHT == true) + RF_ChangeTxPath(dev, cb_desc->data_rate); + + } + + + pDesc->FirstSeg = 1; + pDesc->LastSeg = 1; + + pDesc->TxBufferSize= (u16)skb->len; + + pDesc->TxBuffAddr = cpu_to_le32(mapping); + +} + +void rtl8192se_tx_fill_cmd_desc(struct net_device* dev, tx_desc_cmd * entry, cb_desc * cb_desc, struct sk_buff* skb) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if(cb_desc->bCmdOrInit == DESC_PACKET_TYPE_INIT) { + + dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + + memset((void*)entry, 0, 32); + + entry->LINIP = cb_desc->bLastIniPkt; + + entry->FirstSeg = 1; + entry->LastSeg = 1; + + entry->TxBufferSize= (u16)(skb->len); + entry->TxBufferAddr = cpu_to_le32(mapping); + entry->PktSize = (u16)(skb->len); + + { + entry->OWN = 1; + } + } else { + + u8* pDesc = (u8*)entry; + + dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + + CLEAR_PCI_TX_DESC_CONTENT(pDesc, sizeof(tx_desc_cmd)); + + SET_TX_DESC_FIRST_SEG(pDesc, 1); + SET_TX_DESC_LAST_SEG(pDesc, 1); + + SET_TX_DESC_OFFSET(pDesc, 0x20); + + SET_TX_DESC_PKT_SIZE(pDesc, (u16)(skb->len)); + SET_TX_DESC_QUEUE_SEL(pDesc, 0x13); + + + SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, priv->H2CTxCmdSeq); + + SET_TX_DESC_TX_BUFFER_SIZE(pDesc, (u16)(skb->len)); + SET_TX_DESC_TX_BUFFER_ADDRESS(pDesc, cpu_to_le32(mapping)); + + SET_TX_DESC_OWN(pDesc, 1); + + RT_TRACE(COMP_CMD, "TxFillCmdDesc8192SE(): H2C Tx Cmd Content ----->\n"); + } +} + +u8 HwRateToMRate92S(bool bIsHT, u8 rate) +{ + u8 ret_rate = 0x02; + + if (!bIsHT) { + switch (rate) { + case DESC92S_RATE1M: + ret_rate = MGN_1M; + break; + case DESC92S_RATE2M: + ret_rate = MGN_2M; + break; + case DESC92S_RATE5_5M: + ret_rate = MGN_5_5M; + break; + case DESC92S_RATE11M: + ret_rate = MGN_11M; + break; + case DESC92S_RATE6M: + ret_rate = MGN_6M; + break; + case DESC92S_RATE9M: + ret_rate = MGN_9M; + break; + case DESC92S_RATE12M: + ret_rate = MGN_12M; + break; + case DESC92S_RATE18M: + ret_rate = MGN_18M; + break; + case DESC92S_RATE24M: + ret_rate = MGN_24M; + break; + case DESC92S_RATE36M: + ret_rate = MGN_36M; + break; + case DESC92S_RATE48M: + ret_rate = MGN_48M; + break; + case DESC92S_RATE54M: + ret_rate = MGN_54M; + break; + default: + ret_rate = 0xff; + break; + } + } else { + switch (rate) { + case DESC92S_RATEMCS0: + ret_rate = MGN_MCS0; + break; + case DESC92S_RATEMCS1: + ret_rate = MGN_MCS1; + break; + case DESC92S_RATEMCS2: + ret_rate = MGN_MCS2; + break; + case DESC92S_RATEMCS3: + ret_rate = MGN_MCS3; + break; + case DESC92S_RATEMCS4: + ret_rate = MGN_MCS4; + break; + case DESC92S_RATEMCS5: + ret_rate = MGN_MCS5; + break; + case DESC92S_RATEMCS6: + ret_rate = MGN_MCS6; + break; + case DESC92S_RATEMCS7: + ret_rate = MGN_MCS7; + break; + case DESC92S_RATEMCS8: + ret_rate = MGN_MCS8; + break; + case DESC92S_RATEMCS9: + ret_rate = MGN_MCS9; + break; + case DESC92S_RATEMCS10: + ret_rate = MGN_MCS10; + break; + case DESC92S_RATEMCS11: + ret_rate = MGN_MCS11; + break; + case DESC92S_RATEMCS12: + ret_rate = MGN_MCS12; + break; + case DESC92S_RATEMCS13: + ret_rate = MGN_MCS13; + break; + case DESC92S_RATEMCS14: + ret_rate = MGN_MCS14; + break; + case DESC92S_RATEMCS15: + ret_rate = MGN_MCS15; + break; + case DESC92S_RATEMCS32: + ret_rate = (0x80|0x20); + break; + default: + ret_rate = 0xff; + break; + } + + } + return ret_rate; +} + +long +rtl8192se_signal_scale_mapping(struct r8192_priv * priv, + long currsig + ) +{ + long retsig = 0; + + if(currsig> 47) + retsig = 100; + else if(currsig >14 && currsig <=47) + retsig = 100 - ((47-currsig)*3)/2; + else if(currsig >2 && currsig <=14) + retsig = 48-((14-currsig)*15)/7; + else if(currsig >=0) + retsig = currsig * 9+1; + + return retsig; +} + + +#define rx_hal_is_cck_rate(_pdesc)\ + (_pdesc->RxMCS == DESC92S_RATE1M ||\ + _pdesc->RxMCS == DESC92S_RATE2M ||\ + _pdesc->RxMCS == DESC92S_RATE5_5M ||\ + _pdesc->RxMCS == DESC92S_RATE11M) +#ifdef _RTL8192_EXT_PATCH_ +void rtl8192se_query_rxphystatus( + struct r8192_priv * priv, + struct rtllib_rx_stats * pstats, + prx_desc pdesc, + prx_fwinfo pDrvInfo, + bool bpacket_match_bssid, + bool bpacket_toself, + bool bPacketBeacon + ) +{ + bool is_cck_rate; + phy_sts_cck_8192s_t* cck_buf; + u8 rx_pwr_all=0, rx_pwr[4], rf_rx_num=0, EVM, PWDB_ALL; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + u8 cck_highpwr = 0; + is_cck_rate = rx_hal_is_cck_rate(pdesc); + + pstats->bPacketMatchBSSID = bpacket_match_bssid; + pstats->bPacketToSelf = bpacket_toself; + pstats->bIsCCK = is_cck_rate; + pstats->bPacketBeacon = bPacketBeacon; + + pstats->RxMIMOSignalQuality[0] = -1; + pstats->RxMIMOSignalQuality[1] = -1; + + if (is_cck_rate){ + u8 report; + + cck_buf = (phy_sts_cck_8192s_t*)pDrvInfo; + + if(priv->rtllib->eRFPowerState == eRfOn) + cck_highpwr = (u8)priv->bCckHighPower; + else + cck_highpwr = false; + if (!cck_highpwr){ + report = cck_buf->cck_agc_rpt & 0xc0; + report = report >> 6; + switch(report){ + case 0x3: + rx_pwr_all = -40 - (cck_buf->cck_agc_rpt&0x3e); + break; + case 0x2: + rx_pwr_all = -20 - (cck_buf->cck_agc_rpt&0x3e); + break; + case 0x1: + rx_pwr_all = -2 - (cck_buf->cck_agc_rpt&0x3e); + break; + case 0x0: + rx_pwr_all = 14 - (cck_buf->cck_agc_rpt&0x3e); + break; + } + } + else{ + report = pDrvInfo->cfosho[0] & 0x60; + report = report >> 5; + switch(report){ + case 0x3: + rx_pwr_all = -40 - ((cck_buf->cck_agc_rpt & 0x1f)<<1); + break; + case 0x2: + rx_pwr_all = -20 - ((cck_buf->cck_agc_rpt & 0x1f)<<1); + break; + case 0x1: + rx_pwr_all = -2 - ((cck_buf->cck_agc_rpt & 0x1f)<<1); + break; + case 0x0: + rx_pwr_all = 14 - ((cck_buf->cck_agc_rpt & 0x1f)<<1); + break; + } + } + + PWDB_ALL= rtl819x_query_rxpwrpercentage(rx_pwr_all); + { + PWDB_ALL+=6; + if(PWDB_ALL > 100) + PWDB_ALL = 100; + if(PWDB_ALL > 34 && PWDB_ALL <= 42) + PWDB_ALL -= 2; + else if(PWDB_ALL > 26 && PWDB_ALL <= 34) + PWDB_ALL -= 6; + else if(PWDB_ALL > 14 && PWDB_ALL <= 26) + PWDB_ALL -= 8; + else if(PWDB_ALL > 4 && PWDB_ALL <= 14) + PWDB_ALL -= 4; + } + pstats->RxPWDBAll = PWDB_ALL; + pstats->RecvSignalPower = rx_pwr_all; + + if (bpacket_match_bssid){ + u8 sq; + if(priv->CustomerID == RT_CID_819x_Lenovo) + { + if(PWDB_ALL >= 50) + sq = 100; + else if(PWDB_ALL >= 35 && PWDB_ALL < 50) + sq = 80; + else if(PWDB_ALL >= 22 && PWDB_ALL < 35) + sq = 60; + else if(PWDB_ALL >= 18 && PWDB_ALL < 22) + sq = 40; + else + sq = 20; + } + else + { + if (pstats->RxPWDBAll > 40) + sq = 100; + else{ + sq = cck_buf->sq_rpt; + if (sq > 64) + sq = 0; + else if(sq < 20) + sq = 100; + else + sq = ((64-sq)*100)/44; + } + } + pstats->SignalQuality = sq; + pstats->RxMIMOSignalQuality[0] = sq; + pstats->RxMIMOSignalQuality[1] = -1; + } + } + else{ + priv->brfpath_rxenable[0] = priv->brfpath_rxenable[1] = true; + + for (i=RF90_PATH_A; ibrfpath_rxenable[i]) + rf_rx_num ++; + + rx_pwr[i] = ((pDrvInfo->gain_trsw[i]&0x3f)*2) - 110; + rssi = rtl819x_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + + priv->stats.rxSNRdB[i] = (long)(pDrvInfo->rxsnr[i]/2); + + if (bpacket_match_bssid){ + pstats->RxMIMOSignalStrength[i] = (u8)rssi; + if(priv->CustomerID == RT_CID_819x_Lenovo) + { + u8 SQ; + + if(i == 0) + { + if(rssi >= 50) + SQ = 100; + else if(rssi >= 35 && rssi < 50) + SQ = 80; + else if(rssi >= 22 && rssi < 35) + SQ = 60; + else if(rssi >= 18 && rssi < 22) + SQ = 40; + else + SQ = 20; + pstats->SignalQuality = SQ; + } + } + } + } + rx_pwr_all = ((pDrvInfo->pwdb_all >> 1) & 0x7f) - 106; + PWDB_ALL = rtl819x_query_rxpwrpercentage(rx_pwr_all); + + pstats->RxPWDBAll = PWDB_ALL; + pstats->RxPower = rx_pwr_all; + pstats->RecvSignalPower = rx_pwr_all; + + if(priv->CustomerID != RT_CID_819x_Lenovo){ + if (pdesc->RxHT && pdesc->RxMCS >= DESC92S_RATEMCS8 && pdesc->RxMCS <= DESC92S_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + + for(i=0; irxevm[i]); + + if (bpacket_match_bssid) + { + if (i==0) + pstats->SignalQuality = (u8)(EVM & 0xff); + pstats->RxMIMOSignalQuality[i] = (u8)(EVM&0xff); + } + } + } +#if 1 + if (pdesc->BandWidth) + priv->stats.received_bwtype[1+pDrvInfo->rxsc]++; + else + priv->stats.received_bwtype[0]++; +#endif + } + + if (is_cck_rate){ + pstats->SignalStrength = (u8)(rtl8192se_signal_scale_mapping(priv,PWDB_ALL)); + } + else { + if (rf_rx_num != 0) + pstats->SignalStrength = (u8)(rtl8192se_signal_scale_mapping(priv,total_rssi/=rf_rx_num)); + } +} +#else +void rtl8192se_query_rxphystatus( + struct r8192_priv * priv, + struct rtllib_rx_stats * pstats, + prx_desc pdesc, + prx_fwinfo pDrvInfo, + struct rtllib_rx_stats * precord_stats, + bool bpacket_match_bssid, + bool bpacket_toself, + bool bPacketBeacon, + bool bToSelfBA + ) +{ + bool is_cck_rate; + phy_sts_cck_8192s_t* cck_buf; + s8 rx_pwr_all=0, rx_pwr[4]; + u8 rf_rx_num=0, EVM, PWDB_ALL; + u8 i, max_spatial_stream; + u32 rssi, total_rssi = 0; + + is_cck_rate = rx_hal_is_cck_rate(pdesc); + + memset(precord_stats, 0, sizeof(struct rtllib_rx_stats)); + pstats->bPacketMatchBSSID = precord_stats->bPacketMatchBSSID = bpacket_match_bssid; + pstats->bPacketToSelf = precord_stats->bPacketToSelf = bpacket_toself; + pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate; + pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon; + pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA; + pstats->bIsCCK = precord_stats->bIsCCK = is_cck_rate; + + pstats->RxMIMOSignalQuality[0] = -1; + pstats->RxMIMOSignalQuality[1] = -1; + precord_stats->RxMIMOSignalQuality[0] = -1; + precord_stats->RxMIMOSignalQuality[1] = -1; + + if (is_cck_rate){ + u8 report, cck_highpwr; + + cck_buf = (phy_sts_cck_8192s_t*)pDrvInfo; + + if(!priv->bInPowerSaveMode) + cck_highpwr = (u8)rtl8192_QueryBBReg(priv->rtllib->dev, rFPGA0_XA_HSSIParameter2, BIT9); + else + cck_highpwr = false; + if (!cck_highpwr){ + report = cck_buf->cck_agc_rpt & 0xc0; + report = report >> 6; + switch(report){ + case 0x3: + rx_pwr_all = -35 - (cck_buf->cck_agc_rpt&0x3e); + break; + case 0x2: + rx_pwr_all = -23 - (cck_buf->cck_agc_rpt&0x3e); + break; + case 0x1: + rx_pwr_all = -11 - (cck_buf->cck_agc_rpt&0x3e); + break; + case 0x0: + rx_pwr_all = 8 - (cck_buf->cck_agc_rpt&0x3e); + break; + } + } + else{ + report = pDrvInfo->cfosho[0] & 0x60; + report = report >> 5; + switch(report){ + case 0x3: + rx_pwr_all = -35 - ((cck_buf->cck_agc_rpt & 0x1f)<<1); + break; + case 0x2: + rx_pwr_all = -23 - ((cck_buf->cck_agc_rpt & 0x1f)<<1); + break; + case 0x1: + rx_pwr_all = -11 - ((cck_buf->cck_agc_rpt & 0x1f)<<1); + break; + case 0x0: + rx_pwr_all = -8 - ((cck_buf->cck_agc_rpt & 0x1f)<<1); + break; + } + } + + PWDB_ALL= rtl819x_query_rxpwrpercentage(rx_pwr_all); + pstats->RxPWDBAll = precord_stats->RxPWDBAll = PWDB_ALL; + pstats->RecvSignalPower = rx_pwr_all; + + if (bpacket_match_bssid){ + u8 sq; + if (pstats->RxPWDBAll > 40) + sq = 100; + else{ + sq = cck_buf->sq_rpt; + if (sq > 64) + sq = 0; + else if(sq < 20) + sq = 100; + else + sq = ((64-sq)*100)/44; + } + pstats->SignalQuality = precord_stats->SignalQuality = sq; + pstats->RxMIMOSignalQuality[0] = precord_stats->RxMIMOSignalQuality[0] = sq; + pstats->RxMIMOSignalQuality[1] = precord_stats->RxMIMOSignalQuality[1] = -1; + } + } + else{ + priv->brfpath_rxenable[0] = priv->brfpath_rxenable[1] = true; + + for (i=RF90_PATH_A; ibrfpath_rxenable[i]) + rf_rx_num ++; + + rx_pwr[i] = ((pDrvInfo->gain_trsw[i]&0x3f)*2) - 110; + rssi = rtl819x_query_rxpwrpercentage(rx_pwr[i]); + total_rssi += rssi; + + priv->stats.rxSNRdB[i] = (long)(pDrvInfo->rxsnr[i]/2); + + if (bpacket_match_bssid){ + pstats->RxMIMOSignalStrength[i] = (u8)rssi; + precord_stats->RxMIMOSignalStrength [i] = (u8)rssi; + } + } + + rx_pwr_all = ((pDrvInfo->pwdb_all >> 1) & 0x7f) - 0x106; + PWDB_ALL = rtl819x_query_rxpwrpercentage(rx_pwr_all); + + pstats->RxPWDBAll = precord_stats->RxPWDBAll = PWDB_ALL; + pstats->RxPower = precord_stats->RxPower = rx_pwr_all; + pstats->RecvSignalPower = precord_stats->RecvSignalPower = rx_pwr_all; + + if (pdesc->RxHT && pdesc->RxMCS >= DESC92S_RATEMCS8 && pdesc->RxMCS <= DESC92S_RATEMCS15) + max_spatial_stream = 2; + else + max_spatial_stream = 1; + + for(i=0; irxevm[i]); + + if (bpacket_match_bssid) + { + if (i==0) + pstats->SignalQuality = + precord_stats->SignalQuality = (u8)(EVM&0xff); + pstats->RxMIMOSignalQuality[i] = + precord_stats->RxMIMOSignalQuality[i] = (u8)(EVM&0xff); + } + } +#if 0 + if (pdesc->BW) + priv->stats.received_bwtype[1+pDrvInfo->rxsc]++; + else + priv->stats.received_bwtype[0]++; +#endif + } + + if (is_cck_rate) + pstats->SignalStrength = + precord_stats->SignalStrength = (u8)(rtl8192se_signal_scale_mapping(priv,PWDB_ALL)); + else + if (rf_rx_num != 0) + pstats->SignalStrength = + precord_stats->SignalStrength = (u8)(rtl8192se_signal_scale_mapping(priv,total_rssi/=rf_rx_num)); + +} +#endif + +#ifdef _RTL8192_EXT_PATCH_ +void rtl819x_update_rxsignalstatistics8192S( + struct r8192_priv * priv, + struct rtllib_rx_stats * pstats + ) +{ + int weighting = 0; + + + if(priv->stats.recv_signal_power == 0) + priv->stats.recv_signal_power = pstats->RecvSignalPower; + + if(pstats->RecvSignalPower > priv->stats.recv_signal_power) + weighting = 5; + else if(pstats->RecvSignalPower < priv->stats.recv_signal_power) + weighting = (-5); + priv->stats.recv_signal_power = (priv->stats.recv_signal_power * 5 + pstats->RecvSignalPower + weighting) / 6; + +} + +void Process_UI_RSSI_8192S(struct r8192_priv * priv,struct rtllib_rx_stats * pstats) +{ + u8 rfPath; + u32 last_rssi, tmpVal; + + if(pstats->bPacketToSelf || pstats->bPacketBeacon) + { + priv->stats.RssiCalculateCnt++; + if(priv->stats.ui_rssi.TotalNum++ >= PHY_RSSI_SLID_WIN_MAX) + { + priv->stats.ui_rssi.TotalNum = PHY_RSSI_SLID_WIN_MAX; + last_rssi = priv->stats.ui_rssi.elements[priv->stats.ui_rssi.index]; + priv->stats.ui_rssi.TotalVal -= last_rssi; + } + priv->stats.ui_rssi.TotalVal += pstats->SignalStrength; + + priv->stats.ui_rssi.elements[priv->stats.ui_rssi.index++] = pstats->SignalStrength; + if(priv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) + priv->stats.ui_rssi.index = 0; + + tmpVal = priv->stats.ui_rssi.TotalVal/priv->stats.ui_rssi.TotalNum; + priv->stats.signal_strength = rtl819x_translate_todbm(priv, (u8)tmpVal); + + } + + if(!pstats->bIsCCK && pstats->bPacketToSelf) + { + for (rfPath = RF90_PATH_A; rfPath < priv->NumTotalRFPath; rfPath++) + { + if (!rtl8192_phy_CheckIsLegalRFPath(priv->rtllib->dev, rfPath)) + continue; + RT_TRACE(COMP_DBG, "pstats->RxMIMOSignalStrength[%d] = %d \n", rfPath, pstats->RxMIMOSignalStrength[rfPath] ); + + if(priv->stats.rx_rssi_percentage[rfPath] == 0) + { + priv->stats.rx_rssi_percentage[rfPath] = pstats->RxMIMOSignalStrength[rfPath]; + } + + if(pstats->RxMIMOSignalStrength[rfPath] > priv->stats.rx_rssi_percentage[rfPath]) + { + priv->stats.rx_rssi_percentage[rfPath] = + ( (priv->stats.rx_rssi_percentage[rfPath]*(Rx_Smooth_Factor-1)) + + (pstats->RxMIMOSignalStrength[rfPath])) /(Rx_Smooth_Factor); + priv->stats.rx_rssi_percentage[rfPath] = priv->stats.rx_rssi_percentage[rfPath] + 1; + } + else + { + priv->stats.rx_rssi_percentage[rfPath] = + ( (priv->stats.rx_rssi_percentage[rfPath]*(Rx_Smooth_Factor-1)) + + (pstats->RxMIMOSignalStrength[rfPath])) /(Rx_Smooth_Factor); + } + RT_TRACE(COMP_DBG, "priv->stats.rx_rssi_percentage[%d] = %d \n",rfPath, priv->stats.rx_rssi_percentage[rfPath] ); + } + } + +} + +void Process_PWDB_8192S(struct r8192_priv * priv,struct rtllib_rx_stats * pstats,struct rtllib_network* pnet, struct sta_info *pEntry) +{ + long UndecoratedSmoothedPWDB=0; + + if(priv->rtllib->iw_mode == IW_MODE_MESH){ + if(pnet){ + if(priv->mshobj->ext_patch_get_peermp_rssi_param) + UndecoratedSmoothedPWDB = priv->mshobj->ext_patch_get_peermp_rssi_param(pnet); + }else + UndecoratedSmoothedPWDB = priv->undecorated_smoothed_pwdb; + } + else if(priv->rtllib->iw_mode == IW_MODE_ADHOC){ + if(pEntry){ + UndecoratedSmoothedPWDB = pEntry->rssi_stat.UndecoratedSmoothedPWDB; + } + }else + UndecoratedSmoothedPWDB = priv->undecorated_smoothed_pwdb; + + if(pstats->bPacketToSelf || pstats->bPacketBeacon){ + if(UndecoratedSmoothedPWDB < 0){ + UndecoratedSmoothedPWDB = pstats->RxPWDBAll; + } + + if(pstats->RxPWDBAll > (u32)UndecoratedSmoothedPWDB){ + UndecoratedSmoothedPWDB = + ( ((UndecoratedSmoothedPWDB)*(Rx_Smooth_Factor-1)) + + (pstats->RxPWDBAll)) /(Rx_Smooth_Factor); + UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB + 1; + }else{ + UndecoratedSmoothedPWDB = + ( ((UndecoratedSmoothedPWDB)*(Rx_Smooth_Factor-1)) + + (pstats->RxPWDBAll)) /(Rx_Smooth_Factor); + } + if(priv->rtllib->iw_mode == IW_MODE_MESH){ + if(pnet){ + if(priv->mshobj->ext_patch_set_peermp_rssi_param) + priv->mshobj->ext_patch_set_peermp_rssi_param(pnet,UndecoratedSmoothedPWDB); + }else + priv->undecorated_smoothed_pwdb = UndecoratedSmoothedPWDB; + }else if(priv->rtllib->iw_mode == IW_MODE_ADHOC){ + if(pEntry){ + pEntry->rssi_stat.UndecoratedSmoothedPWDB = UndecoratedSmoothedPWDB; + } + }else{ + priv->undecorated_smoothed_pwdb = UndecoratedSmoothedPWDB; + } + rtl819x_update_rxsignalstatistics8192S(priv, pstats); + } +} + +void Process_UiLinkQuality8192S(struct r8192_priv * priv,struct rtllib_rx_stats * pstats) +{ + u32 last_evm=0, nSpatialStream, tmpVal; + + if(pstats->SignalQuality != 0) + { + if (pstats->bPacketToSelf || pstats->bPacketBeacon) + { + if(priv->stats.ui_link_quality.TotalNum++ >= PHY_LINKQUALITY_SLID_WIN_MAX) + { + priv->stats.ui_link_quality.TotalNum = PHY_LINKQUALITY_SLID_WIN_MAX; + last_evm = priv->stats.ui_link_quality.elements[priv->stats.ui_link_quality.index]; + priv->stats.ui_link_quality.TotalVal -= last_evm; + } + priv->stats.ui_link_quality.TotalVal += pstats->SignalQuality; + + priv->stats.ui_link_quality.elements[priv->stats.ui_link_quality.index++] = pstats->SignalQuality; + if(priv->stats.ui_link_quality.index >= PHY_LINKQUALITY_SLID_WIN_MAX) + priv->stats.ui_link_quality.index = 0; + + + tmpVal = priv->stats.ui_link_quality.TotalVal/priv->stats.ui_link_quality.TotalNum; + priv->stats.signal_quality = tmpVal; + priv->stats.last_signal_strength_inpercent = tmpVal; + + for(nSpatialStream = 0; nSpatialStream<2 ; nSpatialStream++) + { + if(pstats->RxMIMOSignalQuality[nSpatialStream] != -1) + { + if(priv->stats.rx_evm_percentage[nSpatialStream] == 0) + { + priv->stats.rx_evm_percentage[nSpatialStream] = pstats->RxMIMOSignalQuality[nSpatialStream]; + } + priv->stats.rx_evm_percentage[nSpatialStream] = + ( (priv->stats.rx_evm_percentage[nSpatialStream]*(Rx_Smooth_Factor-1)) + + (pstats->RxMIMOSignalQuality[nSpatialStream]* 1)) /(Rx_Smooth_Factor); + } + } + } + } + else + ; + +} +#endif + + +#ifdef _RTL8192_EXT_PATCH_ +void rtl8192se_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct rtllib_rx_stats * pcurrent_stats,struct rtllib_network * pnet, struct sta_info *pEntry) +#else +void rtl8192se_process_phyinfo(struct r8192_priv * priv, u8* buffer,struct rtllib_rx_stats * pprevious_stats, struct rtllib_rx_stats * pcurrent_stats) +#endif +{ +#ifdef _RTL8192_EXT_PATCH_ + if(!pcurrent_stats->bPacketMatchBSSID) + return; + Process_UI_RSSI_8192S(priv, pcurrent_stats); + Process_PWDB_8192S(priv, pcurrent_stats, pnet, pEntry); + Process_UiLinkQuality8192S(priv, pcurrent_stats); +#else + bool bcheck = false; + u8 rfpath; + u32 nspatial_stream, tmp_val; + static u32 slide_rssi_index=0, slide_rssi_statistics=0; + static u32 slide_evm_index=0, slide_evm_statistics=0; + static u32 last_rssi=0, last_evm=0; + static u32 slide_beacon_adc_pwdb_index=0, slide_beacon_adc_pwdb_statistics=0; + static u32 last_beacon_adc_pwdb=0; + + struct rtllib_hdr_3addr *hdr; + u16 sc ; + unsigned int frag,seq; + hdr = (struct rtllib_hdr_3addr *)buffer; + sc = le16_to_cpu(hdr->seq_ctl); + frag = WLAN_GET_SEQ_FRAG(sc); + seq = WLAN_GET_SEQ_SEQ(sc); + pcurrent_stats->Seq_Num = seq; + if(!pprevious_stats->bIsAMPDU) + { + bcheck = true; + }else { +#if 0 + if( !pcurrent_stats->bIsAMPDU || pcurrent_stats->bFirstMPDU) + bcheck = true; +#endif + } + + if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) + { + slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX; + last_rssi = priv->stats.slide_signal_strength[slide_rssi_index]; + priv->stats.slide_rssi_total -= last_rssi; + } + priv->stats.slide_rssi_total += pprevious_stats->SignalStrength; + + priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength; + if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX) + slide_rssi_index = 0; + + tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics; + priv->stats.signal_strength = rtl819x_translate_todbm(priv, (u8)tmp_val); + pcurrent_stats->rssi = priv->stats.signal_strength; + if(!pprevious_stats->bPacketMatchBSSID) + { + if(!pprevious_stats->bToSelfBA) + return; + } + + if(!bcheck) + return; + + rtl819x_process_cck_rxpathsel(priv,pprevious_stats); + + priv->stats.num_process_phyinfo++; +#if 0 + if(slide_rssi_statistics++ >= PHY_RSSI_SLID_WIN_MAX) + { + slide_rssi_statistics = PHY_RSSI_SLID_WIN_MAX; + last_rssi = priv->stats.slide_signal_strength[slide_rssi_index]; + priv->stats.slide_rssi_total -= last_rssi; + } + priv->stats.slide_rssi_total += pprevious_stats->SignalStrength; + + priv->stats.slide_signal_strength[slide_rssi_index++] = pprevious_stats->SignalStrength; + if(slide_rssi_index >= PHY_RSSI_SLID_WIN_MAX) + slide_rssi_index = 0; + + tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics; + priv->stats.signal_strength = rtl819x_translate_todbm(priv, (u8)tmp_val); + +#endif + if(!pprevious_stats->bIsCCK && pprevious_stats->bPacketToSelf) + { + for (rfpath = RF90_PATH_A; rfpath < RF90_PATH_C; rfpath++) + { + if (!rtl8192_phy_CheckIsLegalRFPath(priv->rtllib->dev, rfpath)) + continue; + RT_TRACE(COMP_DBG,"Jacken -> pPreviousstats->RxMIMOSignalStrength[rfpath] = %d \n" ,pprevious_stats->RxMIMOSignalStrength[rfpath] ); + if(priv->stats.rx_rssi_percentage[rfpath] == 0) + { + priv->stats.rx_rssi_percentage[rfpath] = pprevious_stats->RxMIMOSignalStrength[rfpath]; + } + if(pprevious_stats->RxMIMOSignalStrength[rfpath] > priv->stats.rx_rssi_percentage[rfpath]) + { + priv->stats.rx_rssi_percentage[rfpath] = + ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) + + (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor); + priv->stats.rx_rssi_percentage[rfpath] = priv->stats.rx_rssi_percentage[rfpath] + 1; + } + else + { + priv->stats.rx_rssi_percentage[rfpath] = + ( (priv->stats.rx_rssi_percentage[rfpath]*(Rx_Smooth_Factor-1)) + + (pprevious_stats->RxMIMOSignalStrength[rfpath])) /(Rx_Smooth_Factor); + } + RT_TRACE(COMP_DBG,"Jacken -> priv->RxStats.RxRSSIPercentage[rfPath] = %d \n" ,priv->stats.rx_rssi_percentage[rfpath] ); + } + } + + + if(pprevious_stats->bPacketBeacon) + { + if(slide_beacon_adc_pwdb_statistics++ >= PHY_Beacon_RSSI_SLID_WIN_MAX) + { + slide_beacon_adc_pwdb_statistics = PHY_Beacon_RSSI_SLID_WIN_MAX; + last_beacon_adc_pwdb = priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index]; + priv->stats.Slide_Beacon_Total -= last_beacon_adc_pwdb; + } + priv->stats.Slide_Beacon_Total += pprevious_stats->RxPWDBAll; + priv->stats.Slide_Beacon_pwdb[slide_beacon_adc_pwdb_index] = pprevious_stats->RxPWDBAll; + slide_beacon_adc_pwdb_index++; + if(slide_beacon_adc_pwdb_index >= PHY_Beacon_RSSI_SLID_WIN_MAX) + slide_beacon_adc_pwdb_index = 0; + pprevious_stats->RxPWDBAll = priv->stats.Slide_Beacon_Total/slide_beacon_adc_pwdb_statistics; + if(pprevious_stats->RxPWDBAll >= 3) + pprevious_stats->RxPWDBAll -= 3; + } + + RT_TRACE(COMP_RXDESC, "Smooth %s PWDB = %d\n", + pprevious_stats->bIsCCK? "CCK": "OFDM", + pprevious_stats->RxPWDBAll); + + if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) + { + if(priv->undecorated_smoothed_pwdb < 0) + { + priv->undecorated_smoothed_pwdb = pprevious_stats->RxPWDBAll; + } +#if 1 + if(pprevious_stats->RxPWDBAll > (u32)priv->undecorated_smoothed_pwdb) + { + priv->undecorated_smoothed_pwdb = + ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) + + (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor); + priv->undecorated_smoothed_pwdb = priv->undecorated_smoothed_pwdb + 1; + } + else + { + priv->undecorated_smoothed_pwdb = + ( ((priv->undecorated_smoothed_pwdb)*(Rx_Smooth_Factor-1)) + + (pprevious_stats->RxPWDBAll)) /(Rx_Smooth_Factor); + } +#else + if(pPreviousRfd->Status.RxPWDBAll > (u32)pHalData->UndecoratedSmoothedPWDB) + { + pHalData->UndecoratedSmoothedPWDB = + ( ((pHalData->UndecoratedSmoothedPWDB)* 5) + (pPreviousRfd->Status.RxPWDBAll)) / 6; + pHalData->UndecoratedSmoothedPWDB = pHalData->UndecoratedSmoothedPWDB + 1; + } + else + { + pHalData->UndecoratedSmoothedPWDB = + ( ((pHalData->UndecoratedSmoothedPWDB)* 5) + (pPreviousRfd->Status.RxPWDBAll)) / 6; + } +#endif + rtl819x_update_rxsignalstatistics8190pci(priv,pprevious_stats); + } + + if(pprevious_stats->SignalQuality == 0) + { + } + else + { + if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA){ + if(slide_evm_statistics++ >= PHY_RSSI_SLID_WIN_MAX){ + slide_evm_statistics = PHY_RSSI_SLID_WIN_MAX; + last_evm = priv->stats.slide_evm[slide_evm_index]; + priv->stats.slide_evm_total -= last_evm; + } + + priv->stats.slide_evm_total += pprevious_stats->SignalQuality; + + priv->stats.slide_evm[slide_evm_index++] = pprevious_stats->SignalQuality; + if(slide_evm_index >= PHY_RSSI_SLID_WIN_MAX) + slide_evm_index = 0; + + tmp_val = priv->stats.slide_evm_total/slide_evm_statistics; + priv->stats.signal_quality = tmp_val; + priv->stats.last_signal_strength_inpercent = tmp_val; + } + + if(pprevious_stats->bPacketToSelf || pprevious_stats->bPacketBeacon || pprevious_stats->bToSelfBA) + { + for(nspatial_stream = 0; nspatial_stream<2 ; nspatial_stream++) + { + if(pprevious_stats->RxMIMOSignalQuality[nspatial_stream] != -1) + { + if(priv->stats.rx_evm_percentage[nspatial_stream] == 0) + { + priv->stats.rx_evm_percentage[nspatial_stream] = pprevious_stats->RxMIMOSignalQuality[nspatial_stream]; + } + priv->stats.rx_evm_percentage[nspatial_stream] = + ( (priv->stats.rx_evm_percentage[nspatial_stream]* (Rx_Smooth_Factor-1)) + + (pprevious_stats->RxMIMOSignalQuality[nspatial_stream]* 1)) / (Rx_Smooth_Factor); + } + } + } + } +#endif + +} + + + +void rtl8192se_TranslateRxSignalStuff(struct net_device *dev, + struct sk_buff *skb, + struct rtllib_rx_stats * pstats, + prx_desc pdesc, + prx_fwinfo pdrvinfo) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + bool bpacket_match_bssid, bpacket_toself; + bool bPacketBeacon=false; + struct rtllib_hdr_3addr *hdr; +#ifdef _RTL8192_EXT_PATCH_ + struct rtllib_network* pnet=NULL; + u8 *psaddr; + struct sta_info *pEntry = NULL; +#else + bool bToSelfBA=false; + static struct rtllib_rx_stats previous_stats; +#endif + u16 fc,type; + u8* tmp_buf; + u8 *praddr; + + tmp_buf = skb->data + pstats->RxDrvInfoSize + pstats->RxBufShift; + + hdr = (struct rtllib_hdr_3addr *)tmp_buf; + fc = le16_to_cpu(hdr->frame_ctl); + type = WLAN_FC_GET_TYPE(fc); + praddr = hdr->addr1; + +#ifdef _RTL8192_EXT_PATCH_ + psaddr = hdr->addr2; + if((priv->rtllib->iw_mode == IW_MODE_MESH) && (priv->mshobj->ext_patch_get_mpinfo)) + pnet = priv->mshobj->ext_patch_get_mpinfo(dev,psaddr); + if(priv->rtllib->iw_mode == IW_MODE_ADHOC){ + pEntry = GetStaInfo(priv->rtllib, psaddr); + } +#endif +#ifdef _RTL8192_EXT_PATCH_ + bpacket_match_bssid = ((RTLLIB_FTYPE_CTL != type) && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV)); + if(pnet){ + bpacket_match_bssid = bpacket_match_bssid; + } + else{ + bpacket_match_bssid = bpacket_match_bssid && + (!compare_ether_addr(priv->rtllib->current_network.bssid, + (fc & RTLLIB_FCTL_TODS)? hdr->addr1 : + (fc & RTLLIB_FCTL_FROMDS )? hdr->addr2 : hdr->addr3)); + } +#else + bpacket_match_bssid = ((RTLLIB_FTYPE_CTL != type) && + (!compare_ether_addr(priv->rtllib->current_network.bssid, + (fc & RTLLIB_FCTL_TODS)? hdr->addr1 : + (fc & RTLLIB_FCTL_FROMDS )? hdr->addr2 : hdr->addr3)) + && (!pstats->bHwError) && (!pstats->bCRC)&& (!pstats->bICV)); +#endif + bpacket_toself = bpacket_match_bssid & (!compare_ether_addr(praddr, priv->rtllib->dev->dev_addr)); + if(WLAN_FC_GET_FRAMETYPE(fc)== RTLLIB_STYPE_BEACON){ + bPacketBeacon = true; + } +#ifndef _RTL8192_EXT_PATCH_ + if(WLAN_FC_GET_FRAMETYPE(fc) == RTLLIB_STYPE_BLOCKACK){ + if ((!compare_ether_addr(praddr,dev->dev_addr))) + bToSelfBA = true; + } +#endif + if(bpacket_match_bssid){ + priv->stats.numpacket_matchbssid++; + } + if(bpacket_toself){ + priv->stats.numpacket_toself++; + } +#ifdef _RTL8192_EXT_PATCH_ + rtl8192se_query_rxphystatus(priv, pstats, pdesc, pdrvinfo, bpacket_match_bssid, + bpacket_toself ,bPacketBeacon); + rtl8192se_process_phyinfo(priv, tmp_buf,pstats,pnet, pEntry); + +#else + rtl8192se_process_phyinfo(priv, tmp_buf,&previous_stats, pstats); + rtl8192se_query_rxphystatus(priv, pstats, pdesc, pdrvinfo, &previous_stats, bpacket_match_bssid, + bpacket_toself ,bPacketBeacon, bToSelfBA); + rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats); +#endif + +} + +void rtl8192se_UpdateReceivedRateHistogramStatistics( + struct net_device *dev, + struct rtllib_rx_stats* pstats + ) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u32 rcvType=1; + u32 rateIndex; + u32 preamble_guardinterval; + + #if 0 + if (pRfd->queue_id == CMPK_RX_QUEUE_ID) + return; + #endif + if(pstats->bCRC) + rcvType = 2; + else if(pstats->bICV) + rcvType = 3; + + if(pstats->bShortPreamble) + preamble_guardinterval = 1; + else + preamble_guardinterval = 0; + + switch(pstats->rate) + { + case MGN_1M: rateIndex = 0; break; + case MGN_2M: rateIndex = 1; break; + case MGN_5_5M: rateIndex = 2; break; + case MGN_11M: rateIndex = 3; break; + case MGN_6M: rateIndex = 4; break; + case MGN_9M: rateIndex = 5; break; + case MGN_12M: rateIndex = 6; break; + case MGN_18M: rateIndex = 7; break; + case MGN_24M: rateIndex = 8; break; + case MGN_36M: rateIndex = 9; break; + case MGN_48M: rateIndex = 10; break; + case MGN_54M: rateIndex = 11; break; + case MGN_MCS0: rateIndex = 12; break; + case MGN_MCS1: rateIndex = 13; break; + case MGN_MCS2: rateIndex = 14; break; + case MGN_MCS3: rateIndex = 15; break; + case MGN_MCS4: rateIndex = 16; break; + case MGN_MCS5: rateIndex = 17; break; + case MGN_MCS6: rateIndex = 18; break; + case MGN_MCS7: rateIndex = 19; break; + case MGN_MCS8: rateIndex = 20; break; + case MGN_MCS9: rateIndex = 21; break; + case MGN_MCS10: rateIndex = 22; break; + case MGN_MCS11: rateIndex = 23; break; + case MGN_MCS12: rateIndex = 24; break; + case MGN_MCS13: rateIndex = 25; break; + case MGN_MCS14: rateIndex = 26; break; + case MGN_MCS15: rateIndex = 27; break; + default: rateIndex = 28; break; + } + priv->stats.received_preamble_GI[preamble_guardinterval][rateIndex]++; + priv->stats.received_rate_histogram[0][rateIndex]++; + priv->stats.received_rate_histogram[rcvType][rateIndex]++; +} + +bool rtl8192se_rx_query_status_desc(struct net_device* dev, struct rtllib_rx_stats* stats, rx_desc *pdesc, struct sk_buff* skb) +{ + struct r8192_priv* priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + u32 PHYStatus = pdesc->PHYStatus; + rx_fwinfo* pDrvInfo; + stats->Length = (u16)pdesc->Length; + stats->RxDrvInfoSize = (u8)pdesc->DrvInfoSize*8; + stats->RxBufShift = (u8)((pdesc->Shift)&0x03); + stats->bICV = (u16)pdesc->ICVError; + stats->bCRC = (u16)pdesc->CRC32; + stats->bHwError = (u16)(pdesc->CRC32|pdesc->ICVError); + stats->Decrypted = !pdesc->SWDec; + stats->rate = (u8)pdesc->RxMCS; + stats->bShortPreamble= (u16)pdesc->SPLCP; + stats->bIsAMPDU = (bool)(pdesc->PAGGR==1); + stats->bFirstMPDU = (bool)((pdesc->PAGGR==1) && (pdesc->FAGGR==1)); + stats->TimeStampLow = pdesc->TSFL; + stats->RxIs40MHzPacket= (bool)pdesc->BandWidth; + if(IS_UNDER_11N_AES_MODE(ieee)) + { + if(stats->bICV && !stats->bCRC) + { + stats->bICV = false; + stats->bHwError = false; + } + } + + + if(stats->Length > 0x2000 || stats->Length < 24) + { + stats->bHwError |= 1; + } + rtl8192se_UpdateReceivedRateHistogramStatistics(dev, stats); + + if(!stats->bHwError) + stats->rate = HwRateToMRate92S((bool)(pdesc->RxHT), (u8)(pdesc->RxMCS)); + else + { + stats->rate = MGN_1M; + return false; + } + + rtl819x_UpdateRxPktTimeStamp(dev, stats); + + if((stats->RxBufShift + stats->RxDrvInfoSize) > 0) + stats->bShift = 1; + + if (PHYStatus == true) + { + pDrvInfo = (rx_fwinfo*)(skb->data + stats->RxBufShift); + + rtl8192se_TranslateRxSignalStuff(dev, skb, stats, pdesc, pDrvInfo); + + } + return true; +} + +void rtl8192se_halt_adapter(struct net_device *dev, bool bReset) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int i; + u8 wait = 30; + + RT_TRACE(COMP_INIT, "==> rtl8192se_halt_adapter()\n"); + +#if 1 + while (wait-- >= 10 && priv->PwrDomainProtect == true) + { + if (priv->PwrDomainProtect == true) + { + RT_TRACE(COMP_INIT, "Delay 20ms to wait PwrDomainProtect\n"); + mdelay(20); + } + else + break; + } + + if (wait == 9) + RT_TRACE(COMP_INIT, "PwrDomainProtect FAIL\n"); +#endif + + priv->rtllib->state = RTLLIB_NOLINK; + rtl8192se_update_msr(dev); +#if 1 + PHY_SetRtl8192seRfHalt(dev); +#endif + udelay(100); + +#if 0 + udelay(20); + if (!bReset) { + mdelay(20); + } +#endif + for(i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_purge(&priv->rtllib->skb_waitQ [i]); + } + for(i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_purge(&priv->rtllib->skb_aggQ [i]); + } +#ifdef _RTL8192_EXT_PATCH_ + for(i = 0; i < MAX_QUEUE_SIZE; i++) { + skb_queue_purge(&priv->rtllib->skb_meshaggQ [i]); + } +#endif + + skb_queue_purge(&priv->skb_queue); + RT_TRACE(COMP_INIT, "<== HaltAdapter8192SE()\n"); + return; +} + +u8 GetFreeRATRIndex8192SE (struct net_device* dev) +{ + struct r8192_priv* priv = rtllib_priv(dev); + u8 bitmap = priv->RATRTableBitmap; + u8 ratr_index = 0; + for( ;ratr_index<7; ratr_index++) + { + if((bitmap & BIT0) == 0) + { + priv->RATRTableBitmap |= BIT0<>1; + } + return ratr_index; +} + +void rtl8192se_update_ratr_table(struct net_device* dev,u8* pMcsRate,struct sta_info* pEntry) +{ + struct r8192_priv* priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + u32 ratr_value = 0; + u8 ratr_index = 0; + u8 bNMode = 0; + u16 shortGI_rate = 0; + u32 tmp_ratr_value = 0; + u8 MimoPs; + WIRELESS_MODE WirelessMode; + u8 bCurTxBW40MHz, bCurShortGI40MHz, bCurShortGI20MHz; + + if(ieee->iw_mode == IW_MODE_ADHOC){ + if(pEntry == NULL){ + printk("Doesn't have match Entry\n"); + return; + } + + if(pEntry->ratr_index != 8) + ratr_index = pEntry->ratr_index; + else + ratr_index = GetFreeRATRIndex8192SE(dev); + + if(ratr_index == 7){ + RT_TRACE(COMP_RATE, "Ratrtable are full"); + return; + } + MimoPs = pEntry->htinfo.MimoPs; + + if((ieee->mode == WIRELESS_MODE_G) && (pEntry->wireless_mode == WIRELESS_MODE_N_24G)) + WirelessMode = ieee->mode; + else + WirelessMode = pEntry->wireless_mode; + + bCurTxBW40MHz = pEntry->htinfo.bCurTxBW40MHz; + bCurShortGI40MHz = pEntry->htinfo.bCurShortGI40MHz; + bCurShortGI20MHz = pEntry->htinfo.bCurShortGI20MHz; + pEntry->ratr_index = ratr_index; + } + else + { + ratr_index = 0; + WirelessMode = ieee->mode; + MimoPs = ieee->pHTInfo->PeerMimoPs; + bCurTxBW40MHz = ieee->pHTInfo->bCurTxBW40MHz; + bCurShortGI40MHz = ieee->pHTInfo->bCurShortGI40MHz; + bCurShortGI20MHz = ieee->pHTInfo->bCurShortGI20MHz; + } + + rtl8192_config_rate(dev, (u16*)(&ratr_value)); + ratr_value |= (*(u16*)(pMcsRate)) << 12; + switch (WirelessMode) + { + case IEEE_A: + ratr_value &= 0x00000FF0; + break; + case IEEE_B: + ratr_value &= 0x0000000D; + break; + case IEEE_G: + case IEEE_G|IEEE_B: + ratr_value &= 0x00000FF5; + break; + case IEEE_N_24G: + case IEEE_N_5G: + bNMode = 1; + if (MimoPs == 0) + ratr_value &= 0x0007F005; + else{ + if (priv->rf_type == RF_1T2R ||priv->rf_type == RF_1T1R || (ieee->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_TX_2SS)){ + if ((bCurTxBW40MHz) && !(ieee->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_TX_40_MHZ)) + ratr_value &= 0x000FF015; + else + ratr_value &= 0x000ff005; + }else{ + if ((bCurTxBW40MHz) && !(ieee->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_TX_40_MHZ)) + ratr_value &= 0x0f0ff015; + else + ratr_value &= 0x0f0ff005; + } + } + break; + default: + printk("====>%s(), mode is not correct:%x\n", __FUNCTION__,WirelessMode); + break; + } + if (priv->card_8192_version>= VERSION_8192S_BCUT) + ratr_value &= 0x0FFFFFFF; + else if (priv->card_8192_version == VERSION_8192S_ACUT) + ratr_value &= 0x0FFFFFF0; + + if (((ieee->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_SHORT_GI)==0) && + bNMode && ((bCurTxBW40MHz && bCurShortGI40MHz) || + (!bCurTxBW40MHz && bCurShortGI20MHz))) + { + ratr_value |= 0x10000000; + tmp_ratr_value = (ratr_value>>12); + for(shortGI_rate=15; shortGI_rate>0; shortGI_rate--) + { + if((1<pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) + { + ratr_value &= 0xfffffff0; + printk("UpdateHalRATRTable8192SE(), for HT_IOT_ACT_WA_IOT_Broadcom, ratr_value = 0x%x\n", ratr_value); + } + + write_nic_dword(dev, ARFR0+ratr_index*4, ratr_value); + RT_TRACE(COMP_RATE, "%s: ratr_index=%d ratr_table=0x%8.8x\n", __FUNCTION__,ratr_index, read_nic_dword(dev, ARFR0+ratr_index*4)); + if (ratr_value & 0xfffff000){ + rtl8192se_set_fw_cmd(dev, FW_CMD_RA_REFRESH_N); + } + else{ + rtl8192se_set_fw_cmd(dev, FW_CMD_RA_REFRESH_BG); + } +} + +int r8192se_resume_firm(struct net_device *dev) +{ + write_nic_byte(dev, 0x42, 0xFF); + write_nic_word(dev, 0x40, 0x77FC); + write_nic_word(dev, 0x40, 0x57FC); + write_nic_word(dev, 0x40, 0x37FC); + write_nic_word(dev, 0x40, 0x77FC); + + udelay(100); + + write_nic_word(dev, 0x40, 0x57FC); + write_nic_word(dev, 0x40, 0x37FC); + write_nic_byte(dev, 0x42, 0x00); + + return 0; +} +void PHY_SetRtl8192seRfHalt(struct net_device* dev) +{ + struct r8192_priv* priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + u8 u1bTmp; + + if(priv->rtllib->RfOffReason == RF_CHANGE_BY_IPS && priv->LedStrategy == SW_LED_MODE8) + { + SET_RTL8192SE_RF_SLEEP(dev); + return; + } + +#ifdef LOW_DOWN_POWER + if(0) +#else + if(priv->bDriverIsGoingToUnload) +#endif + write_nic_byte(dev,0x560,0x0); + + RT_TRACE(COMP_PS, "PHY_SetRtl8192seRfHalt save BB/RF\n"); + u1bTmp = read_nic_byte(dev, LDOV12D_CTRL); + u1bTmp |= BIT0; + write_nic_byte(dev, LDOV12D_CTRL, u1bTmp); + write_nic_byte(dev, SPS1_CTRL, 0x0); + write_nic_byte(dev, TXPAUSE, 0xFF); + write_nic_word(dev, CMDR, 0x57FC); + udelay(100); + write_nic_word(dev, CMDR, 0x77FC); + write_nic_byte(dev, PHY_CCA, 0x0); + udelay(10); + write_nic_word(dev, CMDR, 0x37FC); + udelay(10); + write_nic_word(dev, CMDR, 0x77FC); + udelay(10); + write_nic_word(dev, CMDR, 0x57FC); + write_nic_word(dev, CMDR, 0x0000); + + +#ifdef LOW_DOWN_POWER + if(0) +#else + if(priv->bDriverIsGoingToUnload) +#endif + { + u1bTmp = read_nic_byte(dev, (SYS_FUNC_EN+ 1)); + u1bTmp &= ~(BIT0); + write_nic_byte(dev, SYS_FUNC_EN+1, u1bTmp); + } + + + u1bTmp = read_nic_byte(dev, (SYS_CLKR + 1)); + + if (u1bTmp & BIT7) { + u1bTmp &= ~(BIT6 | BIT7); + if(!HalSetSysClk8192SE(dev, u1bTmp)) { + printk("Switch ctrl path fail\n"); + return; + } + } + +#ifdef LOW_DOWN_POWER + if((priv->rtllib->RfOffReason & (RF_CHANGE_BY_IPS | RF_CHANGE_BY_HW)) && + !priv->bDriverIsGoingToUnload) +#else + if(priv->rtllib->RfOffReason==RF_CHANGE_BY_IPS && !priv->bDriverIsGoingToUnload) +#endif + { + write_nic_byte(dev, 0x03, 0xF9); + } else + { + write_nic_byte(dev, 0x03, 0xF9); + } + write_nic_byte(dev, SYS_CLKR+1, 0x70); + write_nic_byte(dev, AFE_PLL_CTRL+1, 0x68); + write_nic_byte(dev, AFE_PLL_CTRL, 0x00); + write_nic_byte(dev, LDOA15_CTRL, 0x34); + write_nic_byte(dev, AFE_XTAL_CTRL, 0x0E); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); +} + + +/* +* Description: +* Set RateAdaptive Mask +* /param Adapter Pionter to Adapter entity +* /param bMulticast TURE if broadcast or multicast, used for softAP basic rate +* /param macId macID to set +* /param wirelessMode wireless mode of associated AP/client +* /return void +* +*/ +void UpdateHalRAMask8192SE( + struct net_device* dev, + bool bMulticast, + u8 macId, + u8 MimoPs, + u8 WirelessMode, + u8 bCurTxBW40MHz, + u8 rssi_level){ + struct r8192_priv* priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + PRT_HIGH_THROUGHPUT pHTInfo = priv->rtllib->pHTInfo; + u8* pMcsRate = ieee->dot11HTOperationalRateSet; + u32 ratr_bitmap, RateSet, mask=0, band = 0, ratr_value = 0; + u8 shortGI_rate = 0, bShortGI = false; + + RT_TRACE(COMP_RATE, "%s: macid:%d MimoPs=%d WirelessMode=0x%x bCurTxBW40MHz=%d rssid_level=%d\n",__FUNCTION__, macId, MimoPs, WirelessMode,bCurTxBW40MHz, rssi_level); + rtl8192_config_rate(dev, (u16*)&RateSet); + RateSet |= (*(u16*)(pMcsRate)) << 12; + ratr_bitmap = RateSet; + + switch (WirelessMode){ + case WIRELESS_MODE_B: + band |= WIRELESS_11B; + ratr_bitmap &= 0x0000000d; + break; + case WIRELESS_MODE_G: + case (WIRELESS_MODE_G |WIRELESS_MODE_B): + band |= (WIRELESS_11G | WIRELESS_11B); + + if(rssi_level == 1) + ratr_bitmap &= 0x00000f00; + else if(rssi_level == 2) + ratr_bitmap &= 0x00000ff0; + else + ratr_bitmap &= 0x00000ff5; + break; + case WIRELESS_MODE_A: + band |= WIRELESS_11A; + ratr_bitmap &= 0x00000ff0; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + { + band |= (WIRELESS_11N| WIRELESS_11G| WIRELESS_11B); + if(MimoPs == MIMO_PS_STATIC){ + if(rssi_level == 1) + ratr_bitmap &= 0x00070000; + else if(rssi_level == 2) + ratr_bitmap &= 0x0007f000; + else + ratr_bitmap &= 0x0007f005; + }else{ + if (priv->rf_type == RF_1T2R || priv->rf_type == RF_1T1R) + { + + if(rssi_level == 1) + ratr_bitmap &= 0x000f0000; + else if(rssi_level ==3) + ratr_bitmap &= 0x000fc000; + else if(rssi_level == 5) + ratr_bitmap &= 0x000ff000; + else + { + if (bCurTxBW40MHz) + ratr_bitmap &= 0x000ff015; + else + ratr_bitmap &= 0x000ff005; + } + + } + else + { + if(rssi_level == 1) + ratr_bitmap &= 0x0f8f0000; + else if(rssi_level == 3) + ratr_bitmap &= 0x0f8fc000; + else if(rssi_level == 5) + ratr_bitmap &= 0x0f8ff000; + else + { + if (bCurTxBW40MHz) + ratr_bitmap &= 0x0f8ff015; + else + ratr_bitmap &= 0x0f8ff005; + } + + } + } + if( (pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI40MHz) || + (!pHTInfo->bCurTxBW40MHz && pHTInfo->bCurShortGI20MHz)){ + if(macId == 0) + bShortGI = true; + else + bShortGI = false; + } + break; + } + default: + band |= (WIRELESS_11N| WIRELESS_11G| WIRELESS_11B); + + if(priv->rf_type == RF_1T2R) + ratr_bitmap &= 0x000ff0ff; + else + ratr_bitmap &= 0x0f8ff0ff; + break; + } + + if (priv->card_8192_version >= VERSION_8192S_BCUT) + ratr_bitmap &= 0x0FFFFFFF; + else if (priv->card_8192_version == VERSION_8192S_ACUT) + ratr_bitmap &= 0x0FFFFFF0; + + if(bShortGI){ + ratr_bitmap |= 0x10000000; + ratr_value = (ratr_bitmap>>12); + for(shortGI_rate=15; shortGI_rate>0; shortGI_rate--){ + if((1<rtllib->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) + ratr_bitmap &= 0xfffffff0; + if(priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_SHORT_GI) + ratr_bitmap &=0x0fffffff; + } + mask |= (bMulticast ? 1 : 0)<<9 | (macId & 0x1f)<<4 | (band & 0xf); + + RT_TRACE(COMP_RATE, "%s(): mask = %x, bitmap = %x\n",__func__, mask, ratr_bitmap); + write_nic_dword(dev, 0x2c4, ratr_bitmap); + write_nic_dword(dev, WFM5, (FW_RA_UPDATE_MASK | (mask << 8))); +} + +u8 HalSetSysClk8192SE( struct net_device *dev, u8 Data) +{ +#if 0 + write_nic_byte(dev, (SYS_CLKR + 1), Data); + udelay(200);; + return 1; +#else + { + u8 WaitCount = 100; + bool bResult = false; + +#ifdef TO_DO_LIST + RT_DISABLE_FUNC(Adapter, DF_IO_BIT); + + do + { + if(pDevice->IOCount == 0) + break; + delay_us(10); + }while(WaitCount -- > 0); + + if(WaitCount == 0) + { + RT_ENABLE_FUNC(Adapter, DF_IO_BIT); + RT_TRACE(COMP_POWER, DBG_WARNING, ("HalSetSysClk8192SE(): Wait too long! Skip ....\n")); + return false; + } + #endif + write_nic_byte(dev,SYS_CLKR + 1,Data); + + udelay(400); + + + { + u8 TmpValue; + TmpValue=read_nic_byte(dev,SYS_CLKR + 1); + bResult = ((TmpValue&BIT7)== (Data & BIT7)); + if((Data &(BIT6|BIT7)) == false) + { + WaitCount = 100; + TmpValue = 0; + while(1) + { + WaitCount--; + TmpValue=read_nic_byte(dev, SYS_CLKR + 1); + if((TmpValue &BIT6)) + break; + printk("wait for BIT6 return value %x\n",TmpValue); + if(WaitCount==0) + break; + udelay(10); + } + if(WaitCount == 0) + bResult = false; + else + bResult = true; + } + } +#ifdef TO_DO_LIST + RT_ENABLE_FUNC(Adapter, DF_IO_BIT); +#endif + RT_TRACE(COMP_PS,"HalSetSysClk8192SE():Value = %02X, return: %d\n", Data, bResult); + return bResult; + } +#endif +} + +static u8 LegacyRateSet[12] = {0x02 , 0x04 , 0x0b , 0x16 , 0x0c , 0x12 , 0x18 , 0x24 , 0x30 , 0x48 , 0x60 , 0x6c}; +void GetHwReg8192SE(struct net_device *dev,u8 variable,u8* val) +{ + struct r8192_priv* priv = rtllib_priv(dev); + switch(variable) + { + case HW_VAR_INIT_TX_RATE: + { + u8 RateIdx = read_nic_byte(dev, TX_RATE_REG); + if(RateIdx < 76) + *((u8*)(val)) = (RateIdx<12)?(LegacyRateSet[RateIdx]):((RateIdx-12)|0x80); + else + *((u8*)(val)) = 0; + } + break; + + case HW_VAR_RCR: + *((u32*)(val)) = priv->ReceiveConfig; + break; + + case HW_VAR_MRC: + { + *((bool*)(val)) = priv->bCurrentMrcSwitch; + } + break; + + default: + break; + } +} + +void SetHwReg8192SE(struct net_device *dev,u8 variable,u8* val) +{ + struct r8192_priv* priv = rtllib_priv(dev); + switch(variable) + { + case HW_VAR_AMPDU_MIN_SPACE: + { + u8 MinSpacingToSet; + u8 SecMinSpace; + + MinSpacingToSet = *((u8*)val); + if(MinSpacingToSet <= 7) + { + if((priv->rtllib->current_network.capability & WLAN_CAPABILITY_PRIVACY) == 0) + SecMinSpace = 0; + else if (priv->rtllib->rtllib_ap_sec_type && + (priv->rtllib->rtllib_ap_sec_type(priv->rtllib) + & (SEC_ALG_WEP|SEC_ALG_TKIP))) + SecMinSpace = 7; + else + SecMinSpace = 1; + + if(MinSpacingToSet < SecMinSpace) + MinSpacingToSet = SecMinSpace; + priv->rtllib->MinSpaceCfg = ((priv->rtllib->MinSpaceCfg&0xf8) |MinSpacingToSet); + RT_TRACE(COMP_MLME, "Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", priv->rtllib->MinSpaceCfg); + write_nic_byte(dev, AMPDU_MIN_SPACE, priv->rtllib->MinSpaceCfg); + } + } + break; + case HW_VAR_SHORTGI_DENSITY: + { + u8 DensityToSet; + + DensityToSet = *((u8*)val); + priv->rtllib->MinSpaceCfg|= (DensityToSet<<3); + RT_TRACE(COMP_MLME, "Set HW_VAR_SHORTGI_DENSITY: %#x\n", priv->rtllib->MinSpaceCfg); + write_nic_byte(dev, AMPDU_MIN_SPACE, priv->rtllib->MinSpaceCfg); + break; + } + case HW_VAR_AMPDU_FACTOR: + { + u8 FactorToSet; + u8 RegToSet; + u8 FactorLevel[18] = {2, 4, 4, 7, 7, 13, 13, 13, 2, 7, 7, 13, 13, 15, 15, 15, 15, 0}; + u8 index = 0; + + FactorToSet = *((u8*)val); + if(FactorToSet <= 3) + { + FactorToSet = (1<<(FactorToSet + 2)); + if(FactorToSet>0xf) + FactorToSet = 0xf; + + for(index=0; index<17; index++) + { + if(FactorLevel[index] > FactorToSet) + FactorLevel[index] = FactorToSet; + } + + for(index=0; index<8; index++) + { + RegToSet = ((FactorLevel[index*2]) | (FactorLevel[index*2+1]<<4)); + write_nic_byte(dev, AGGLEN_LMT_L+index, RegToSet); + } + RegToSet = ((FactorLevel[16]) | (FactorLevel[17]<<4)); + write_nic_byte(dev, AGGLEN_LMT_H, RegToSet); + + RT_TRACE(COMP_MLME, "Set HW_VAR_AMPDU_FACTOR: %#x\n", FactorToSet); + } + } + break; + case HW_VAR_AC_PARAM: + { + u8 pAcParam = *((u8*)val); +#ifdef MERGE_TO_DO + u32 eACI = GET_WMM_AC_PARAM_ACI(pAcParam); +#else + u32 eACI = pAcParam; +#endif + u8 u1bAIFS; + u32 u4bAcParam; + u8 mode = priv->rtllib->mode; + struct rtllib_qos_parameters *qos_parameters = &priv->rtllib->current_network.qos_data.parameters; + + + u1bAIFS = qos_parameters->aifs[pAcParam] * ((mode&(IEEE_G|IEEE_N_24G)) ?9:20) + aSifsTime; + + dm_init_edca_turbo(dev); + + u4bAcParam = ( (((u32)(qos_parameters->tx_op_limit[pAcParam])) << AC_PARAM_TXOP_LIMIT_OFFSET) | + (((u32)(qos_parameters->cw_max[pAcParam])) << AC_PARAM_ECW_MAX_OFFSET) | + (((u32)(qos_parameters->cw_min[pAcParam])) << AC_PARAM_ECW_MIN_OFFSET) | + (((u32)u1bAIFS) << AC_PARAM_AIFS_OFFSET) ); + + printk("%s():HW_VAR_AC_PARAM eACI:%x:%x\n", __func__,eACI, u4bAcParam); + switch(eACI) + { + case AC1_BK: + write_nic_dword(dev, EDCAPARA_BK, u4bAcParam); + break; + + case AC0_BE: + write_nic_dword(dev, EDCAPARA_BE, u4bAcParam); + break; + + case AC2_VI: + write_nic_dword(dev, EDCAPARA_VI, u4bAcParam); + break; + + case AC3_VO: + write_nic_dword(dev, EDCAPARA_VO, u4bAcParam); + break; + + default: + printk("SetHwReg8185(): invalid ACI: %d !\n", eACI); + break; + } + if(priv->AcmMethod != eAcmWay2_SW) + priv->rtllib->SetHwRegHandler(dev, HW_VAR_ACM_CTRL, (u8*)(&pAcParam)); + } + break; + case HW_VAR_ACM_CTRL: + { + struct rtllib_qos_parameters *qos_parameters = &priv->rtllib->current_network.qos_data.parameters; + u8 pAcParam = *((u8*)val); +#ifdef MERGE_TO_DO + u32 eACI = GET_WMM_AC_PARAM_ACI(pAciAifsn); +#else + u32 eACI = pAcParam; +#endif + PACI_AIFSN pAciAifsn = (PACI_AIFSN)&(qos_parameters->aifs[0]); + u8 ACM = pAciAifsn->f.ACM; + u8 AcmCtrl = read_nic_byte( dev, AcmHwCtrl); + + printk("===========>%s():HW_VAR_ACM_CTRL:%x\n", __func__,eACI); + AcmCtrl = AcmCtrl | ((priv->AcmMethod == 2)?0x0:0x1); + + if( ACM ) + { + switch(eACI) + { + case AC0_BE: + AcmCtrl |= AcmHw_BeqEn; + break; + + case AC2_VI: + AcmCtrl |= AcmHw_ViqEn; + break; + case AC3_VO: + AcmCtrl |= AcmHw_VoqEn; + break; + + default: + RT_TRACE( COMP_QOS, "SetHwReg8185(): [HW_VAR_ACM_CTRL] ACM set failed: eACI is %d\n", eACI ); + break; + } + } + else + { + switch(eACI) + { + case AC0_BE: + AcmCtrl &= (~AcmHw_BeqEn); + break; + + case AC2_VI: + AcmCtrl &= (~AcmHw_ViqEn); + break; + + case AC3_VO: + AcmCtrl &= (~AcmHw_BeqEn); + break; + + default: + break; + } + } + + RT_TRACE( COMP_QOS, "SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl ); + write_nic_byte(dev, AcmHwCtrl, AcmCtrl ); + } + break; + + case HW_VAR_BASIC_RATE: + { + u16 BrateCfg = 0; + u8 RateIndex = 0; + + + rtl8192_config_rate(dev, &BrateCfg); + + if (priv->card_8192_version == VERSION_8192S_ACUT) + priv->basic_rate = BrateCfg = BrateCfg & 0x150; + else if (priv->card_8192_version == VERSION_8192S_BCUT) + priv->basic_rate = BrateCfg = BrateCfg & 0x15f; + + if(priv->rtllib->pHTInfo->IOTPeer == HT_IOT_PEER_CISCO && ((BrateCfg &0x150)==0)) + { + BrateCfg |=0x010; + } + if(priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) + { + BrateCfg &= 0x1f0; + printk("HW_VAR_BASIC_RATE, HT_IOT_ACT_WA_IOT_Broadcom, BrateCfg = 0x%x\n", BrateCfg); + } + + BrateCfg |= 0x01; + + write_nic_byte(dev, RRSR, BrateCfg&0xff); + write_nic_byte(dev, RRSR+1, (BrateCfg>>8)&0xff); + + while(BrateCfg > 0x1) + { + BrateCfg = (BrateCfg >> 1); + RateIndex++; + } + write_nic_byte(dev, INIRTSMCS_SEL, RateIndex); + } + break; + case HW_VAR_RETRY_LIMIT: + { + u8 RetryLimit = ((u8*)(val))[0]; + + priv->ShortRetryLimit = RetryLimit; + priv->LongRetryLimit = RetryLimit; + + write_nic_word(dev, RETRY_LIMIT, + RetryLimit << RETRY_LIMIT_SHORT_SHIFT | \ + RetryLimit << RETRY_LIMIT_LONG_SHIFT); + } + break; + case HW_VAR_BEACON_INTERVAL: + { + write_nic_word(dev, BCN_INTERVAL, *((u16*)val)); + PHY_SetBeaconHwReg(dev, *((u16*)val)); + } + break; + + case HW_VAR_BSSID: + write_nic_dword(dev, BSSIDR, ((u32*)(val))[0]); + write_nic_word(dev, BSSIDR+4, ((u16*)(val+4))[0]); + break; + + case HW_VAR_MEDIA_STATUS: + { + RT_OP_MODE OpMode = *((RT_OP_MODE *)(val)); + LED_CTL_MODE LedAction = LED_CTL_NO_LINK; + u8 btMsr = read_nic_byte(dev, MSR); + + btMsr &= 0xfc; + switch(OpMode) + { + case RT_OP_MODE_INFRASTRUCTURE: + btMsr |= MSR_INFRA; + LedAction = LED_CTL_LINK; + break; + + case RT_OP_MODE_IBSS: + btMsr |= MSR_ADHOC; + break; + + case RT_OP_MODE_AP: + btMsr |= MSR_AP; + LedAction = LED_CTL_LINK; + break; + + default: + btMsr |= MSR_NOLINK; + break; + } + + write_nic_byte(dev, MSR, btMsr); + + { + u32 temp = read_nic_dword(dev, TCR); + write_nic_dword(dev, TCR, temp&(~BIT8)); + write_nic_dword(dev, TCR, temp|BIT8); + } + priv->rtllib->LedControlHandler(dev, LedAction); + } + break; + + case HW_VAR_RCR: + { + write_nic_dword(dev, RCR,((u32*)(val))[0]); + priv->ReceiveConfig = ((u32*)(val))[0]; + } + break; + + case HW_VAR_CECHK_BSSID: + { + u32 RegRCR, Type; + + Type = ((u8*)(val))[0]; + priv->rtllib->GetHwRegHandler(dev, HW_VAR_RCR, (u8*)(&RegRCR)); + +#if (RTL92SE_FPGA_VERIFY == 1) + RegRCR &= (~RCR_CBSSID); +#else +#if 1 + if (Type == true) + RegRCR |= (RCR_CBSSID); + else if (Type == false) + RegRCR &= (~RCR_CBSSID); +#endif + priv->rtllib->SetHwRegHandler( dev, HW_VAR_RCR, (u8*)(&RegRCR) ); +#endif + } + break; + + case HW_VAR_SLOT_TIME: + { + + priv->slot_time = val[0]; + write_nic_byte(dev, SLOT_TIME, val[0]); + +#ifdef MERGE_TO_DO + if(priv->rtllib->current_network.qos_data.supported !=0) + { + for(eACI = 0; eACI < AC_MAX; eACI++) + { + priv->rtllib->SetHwRegHandler(dev, HW_VAR_AC_PARAM, (u8*)(&eACI)); + } + } + else + { + u8 u1bAIFS = aSifsTime + (2 * priv->slot_time); + + write_nic_byte(dev, EDCAPARA_VO, u1bAIFS); + write_nic_byte(dev, EDCAPARA_VI, u1bAIFS); + write_nic_byte(dev, EDCAPARA_BE, u1bAIFS); + write_nic_byte(dev, EDCAPARA_BK, u1bAIFS); + } +#endif + } + break; + + case HW_VAR_ACK_PREAMBLE: + { + u8 regTmp; + priv->short_preamble = (bool)(*(u8*)val ); + regTmp = (priv->nCur40MhzPrimeSC)<<5; + if(priv->short_preamble) + regTmp |= 0x80; + + write_nic_byte(dev, RRSR+2, regTmp); + } + break; + + case HW_VAR_SIFS: + write_nic_byte(dev, SIFS_OFDM, val[0]); + write_nic_byte(dev, SIFS_OFDM+1, val[1]); + break; + + case HW_VAR_MRC: + { + + bool bMrcToSet = *( (bool*)val ); + u8 U1bData = 0; + + if( bMrcToSet ) + { + + rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, bMaskByte0, 0x33); + U1bData = (u8)rtl8192_QueryBBReg(dev, rOFDM1_TRxPathEnable, bMaskByte0); + rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, bMaskByte0, ((U1bData&0xf0)|0x03)); + U1bData = (u8)rtl8192_QueryBBReg(dev, rOFDM0_TRxPathEnable, bMaskByte1); + rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, bMaskByte1, (U1bData|0x04)); + + priv->bCurrentMrcSwitch = bMrcToSet; + } + else + { + rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, bMaskByte0, 0x13); + U1bData = (u8)rtl8192_QueryBBReg(dev, rOFDM1_TRxPathEnable, bMaskByte0); + rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, bMaskByte0, ((U1bData&0xf0)|0x01)); + U1bData = (u8)rtl8192_QueryBBReg(dev, rOFDM0_TRxPathEnable, bMaskByte1); + rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, bMaskByte1, (U1bData&0xfb)); + + priv->bCurrentMrcSwitch = bMrcToSet; + } + } + break; + + default: + break; + } +} + +void SetBeaconRelatedRegisters8192SE(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + struct rtllib_network *net = &priv->rtllib->current_network; + u16 BcnTimeCfg = 0; + u16 BcnCW = 6, BcnIFS = 0xf; + u16 AtimWindow = 2; + int OpMode = priv->rtllib->iw_mode; + u16 BcnInterval = net->beacon_interval; + write_nic_word(dev, ATIMWND, AtimWindow); + + write_nic_word(dev, BCN_INTERVAL, BcnInterval); + + write_nic_word(dev, BCN_DRV_EARLY_INT, 10<<4); + + write_nic_word(dev, BCN_DMATIME, 256); + + write_nic_byte(dev, BCN_ERR_THRESH, 100); + + + switch(OpMode) + { + case IW_MODE_ADHOC: + BcnTimeCfg |= (BcnCW<rtllib; + u8 bitmap = 0; + int i; + + for (i = 0; i < PEER_MAX_ASSOC; i++) { + if (NULL != ieee->peer_assoc_list[i]) { + bitmap |= BIT0 << ieee->peer_assoc_list[i]->ratr_index; + } + } + + priv->RATRTableBitmap = bitmap; + return; +} + +bool rtl8192se_check_ht_cap(struct net_device* dev, struct sta_info *sta, + struct rtllib_network* net) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + PHT_CAPABILITY_ELE pHTCapIE = NULL; + PHT_INFORMATION_ELE pPeerHTInfo = NULL; + u8 ExtChlOffset=0; + u8 *pMcsFilter = NULL; + u16 nMaxAMSDUSize = 0; + static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; + static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34}; + + if ((ieee->mode != WIRELESS_MODE_N_24G) && + (ieee->mode != WIRELESS_MODE_N_5G)) { + if (net->mode == IEEE_N_5G) + sta->wireless_mode = IEEE_A; + else if (net->mode == IEEE_N_24G) { + if (net->rates_ex_len > 0) + sta->wireless_mode = IEEE_G; + else + sta->wireless_mode = IEEE_B; + } else + sta->wireless_mode = net->mode; + printk("%s():i am G mode ,do not need to check Cap IE. wireless_mode=0x%x\n", + __FUNCTION__, sta->wireless_mode); + return false; + } + if ((ieee->mode ==WIRELESS_MODE_N_24G) + && ieee->pHTInfo->bRegSuppCCK== false) { + if(net->mode == IEEE_B){ + sta->wireless_mode = net->mode; + printk("%s(): peer is B MODE return\n", __FUNCTION__); + return false; + } + } + if(net->bssht.bdHTCapLen != 0) + { + sta->htinfo.bEnableHT = true; + sta->htinfo.bCurRxReorderEnable = ieee->pHTInfo->bRegRxReorderEnable; + if(net->mode == IEEE_A) + sta->wireless_mode = IEEE_N_5G; + else + sta->wireless_mode = IEEE_N_24G; + } else { + printk("%s(): have no HTCap IE, mode is %d\n",__FUNCTION__,net->mode); + sta->wireless_mode = net->mode; + sta->htinfo.bEnableHT = false; + return true; + } + + if (!memcmp(net->bssht.bdHTCapBuf ,EWC11NHTCap, sizeof(EWC11NHTCap))) + pHTCapIE = (PHT_CAPABILITY_ELE)(&(net->bssht.bdHTCapBuf[4])); + else + pHTCapIE = (PHT_CAPABILITY_ELE)(net->bssht.bdHTCapBuf); + + if (!memcmp(net->bssht.bdHTInfoBuf, EWC11NHTInfo, sizeof(EWC11NHTInfo))) + pPeerHTInfo = (PHT_INFORMATION_ELE)(&net->bssht.bdHTInfoBuf[4]); + else + pPeerHTInfo = (PHT_INFORMATION_ELE)(net->bssht.bdHTInfoBuf); + + ExtChlOffset=((ieee->pHTInfo->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT: + (ieee->current_network.channel<=6)? + HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + printk("******** STA wireless mode %d\n", sta->wireless_mode); + + if (ieee->pHTInfo->bRegSuppCCK) + sta->htinfo.bSupportCck = (pHTCapIE->DssCCk==1)?true:false; + else { + if(pHTCapIE->DssCCk==1) + return false; + } + + sta->htinfo.MimoPs= pHTCapIE->MimoPwrSave; + + printk("******** PEER MP MimoPs %d\n", sta->htinfo.MimoPs); + if(ieee->pHTInfo->bRegBW40MHz) + sta->htinfo.bBw40MHz= (pHTCapIE->ChlWidth==1)?true:false; + else + sta->htinfo.bBw40MHz = false; + + if((pPeerHTInfo->ExtChlOffset) != ExtChlOffset) + sta->htinfo.bBw40MHz = false; + + ieee->Peer_bCurBW40M = sta->htinfo.bBw40MHz; + printk("******** PEER MP bCurBW40M %d\n", sta->htinfo.bBw40MHz); + if(ieee->pHTInfo->bRegBW40MHz == true) + sta->htinfo.bCurTxBW40MHz = sta->htinfo.bBw40MHz; + + printk("******** PEER MP bCurTxBW40MHz %d\n", sta->htinfo.bCurTxBW40MHz); + sta->htinfo.bCurShortGI20MHz= + ((ieee->pHTInfo->bRegShortGI20MHz)?((pHTCapIE->ShortGI20Mhz==1)?true:false):false); + sta->htinfo.bCurShortGI40MHz= + ((ieee->pHTInfo->bRegShortGI40MHz)?((pHTCapIE->ShortGI40Mhz==1)?true:false):false); + + printk("******** PEER MP bCurShortGI20MHz %d, bCurShortGI40MHz %d\n",sta->htinfo.bCurShortGI20MHz,sta->htinfo.bCurShortGI40MHz); + nMaxAMSDUSize = (pHTCapIE->MaxAMSDUSize==0)?3839:7935; + if(ieee->pHTInfo->nAMSDU_MaxSize >= nMaxAMSDUSize) + sta->htinfo.AMSDU_MaxSize = nMaxAMSDUSize; + else + sta->htinfo.AMSDU_MaxSize = ieee->pHTInfo->nAMSDU_MaxSize; + + printk("****************AMSDU_MaxSize=%d\n",sta->htinfo.AMSDU_MaxSize); + + if(ieee->pHTInfo->AMPDU_Factor >= pHTCapIE->MaxRxAMPDUFactor) + sta->htinfo.AMPDU_Factor = pHTCapIE->MaxRxAMPDUFactor; + else + sta->htinfo.AMPDU_Factor = ieee->pHTInfo->AMPDU_Factor; + + if(ieee->pHTInfo->MPDU_Density >= pHTCapIE->MPDUDensity) + sta->htinfo.MPDU_Density = pHTCapIE->MPDUDensity; + else + sta->htinfo.MPDU_Density = ieee->pHTInfo->MPDU_Density; + + HTFilterMCSRate(ieee, pHTCapIE->MCS, sta->htinfo.McsRateSet); + if(sta->htinfo.MimoPs == 0) + pMcsFilter = MCS_FILTER_1SS; + else + pMcsFilter = MCS_FILTER_ALL; + + sta->htinfo.HTHighestOperaRate = HTGetHighestMCSRate(ieee, sta->htinfo.McsRateSet, pMcsFilter); + printk("******** PEER MP HTHighestOperaRate %x\n",sta->htinfo.HTHighestOperaRate); + + return true; + +} + +#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) +void rtl8192se_check_tsf_wq(struct work_struct * work) +{ + struct delayed_work *dwork = container_of(work,struct delayed_work,work); + struct rtllib_device *ieee = container_of(dwork, struct rtllib_device, check_tsf_wq); + struct net_device *dev = ieee->dev; +#else +void rtl8192se_check_tsf_wq(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; +#endif + u32 CurrTsfHigh,CurrTsfLow; + u32 TargetTsfHigh,TargetTsfLow; + + CurrTsfHigh = read_nic_dword(dev, TSFR+4); + CurrTsfLow = (u32)(ieee->CurrTsf & 0xffff); + TargetTsfHigh = (u32)(ieee->TargetTsf >> 32); + TargetTsfLow = (u32)(ieee->TargetTsf & 0xffff); + + printk("Current TSF Low = %x, Hight = %x\n",CurrTsfLow,CurrTsfHigh); + printk("Target TSF Low = %x, Hight = %x\n",TargetTsfLow,TargetTsfHigh); + + ieee->CurrTsf |= (u64)CurrTsfHigh << 32; + + if(ieee->CurrTsf < ieee->TargetTsf) + { + down(&ieee->wx_sem); + + rtllib_stop_protocol(ieee,true); + + ieee->ssid_set = 1; + + rtllib_start_protocol(ieee); + + up(&ieee->wx_sem); + } +} + +#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) +void rtl8192se_update_assoc_sta_info_wq(struct work_struct * work) +{ + struct delayed_work *dwork = container_of(work,struct delayed_work,work); + struct rtllib_device *ieee = container_of(dwork, struct rtllib_device, update_assoc_sta_info_wq); + struct net_device *dev = ieee->dev; +#else +void rtl8192se_update_assoc_sta_info_wq(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; +#endif + struct sta_info * pEntry = NULL; + int idx = 0; + for(idx=0; idxpeer_assoc_list[idx]; + if(NULL != pEntry) + { + u8 * addr = pEntry->macaddr; + + if(ieee->bUseRAMask){ + if((pEntry->wireless_mode & WIRELESS_MODE_N_24G) || (pEntry->wireless_mode & WIRELESS_MODE_N_5G)) + pEntry->ratr_index = RATR_INX_WIRELESS_NGB; + else if(pEntry->wireless_mode & WIRELESS_MODE_G) + pEntry->ratr_index = RATR_INX_WIRELESS_GB; + else if(pEntry->wireless_mode & WIRELESS_MODE_B) + pEntry->ratr_index = RATR_INX_WIRELESS_B; + ieee->UpdateHalRAMaskHandler(dev, + false, + pEntry->aid+1, + pEntry->htinfo.MimoPs, + pEntry->wireless_mode, + pEntry->htinfo.bCurTxBW40MHz, + 0); + } + else + rtl8192se_update_ratr_table(dev,pEntry->htinfo.McsRateSet,pEntry); + printk("%s: STA:"MAC_FMT", aid:%d, wireless_mode=0x%x ratr_index=%d\n",__FUNCTION__,MAC_ARG(addr), pEntry->aid, pEntry->wireless_mode, pEntry->ratr_index); + } + } + if(!ieee->bUseRAMask) + UpdateHalRATRTableIndex(dev); + + if(ieee->Peer_bCurBW40M) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); +} + +bool +rtl8192se_RxCommandPacketHandle( + struct net_device *dev, + struct sk_buff* skb, + rx_desc *pdesc) +{ + u8* pRxCmdHeader; + u8* pCmdContent; + u16 total_length, offset; + u16 RxCmdLen; + u8 RxCmdElementID, RxCmdSeq; + bool RxCmdContinue; + +#if 0 + if ((pRfd->queue_id != CMPK_RX_QUEUE_ID) || (pRfd == NULL)) + { + return 0; + } +#endif + + +#if 0 + if(pdesc->MACID == 0x1e) + { + return 0; + } +#endif + + total_length = pdesc->Length; + pRxCmdHeader = skb->data; + offset = 0; + + do + { + RxCmdLen = (u16)GET_C2H_CMD_CMD_LEN(pRxCmdHeader + offset); + RxCmdElementID = (u8)GET_C2H_CMD_ELEMENT_ID(pRxCmdHeader + offset); + RxCmdSeq = (u8)GET_C2H_CMD_CMD_SEQ(pRxCmdHeader + offset); + RxCmdContinue = (bool)GET_C2H_CMD_CONTINUE(pRxCmdHeader + offset); + pCmdContent = (u8*)GET_C2H_CMD_CONTENT(pRxCmdHeader + offset); + + if((offset + C2H_RX_CMD_HDR_LEN + RxCmdLen) > total_length) + { + printk("Wrong C2H Cmd length!\n"); + break; + } + + RT_TRACE(COMP_CMD, "RxCmdLen = 0x%x, RxCmdElementID = 0x%x, RxCmdSeq = 0x%x, RxCmdContinue = 0x%x\n", + RxCmdLen, RxCmdElementID, RxCmdSeq, RxCmdContinue); + RT_TRACE(COMP_CMD, "Rx CMD Packet Hex Data :%x\n", total_length); + RT_TRACE(COMP_CMD, "Rx CMD Content Hex Data :%x:%x\n", *pCmdContent, RxCmdLen); + + switch(RxCmdElementID) + { + case HAL_FW_C2H_CMD_C2HFEEDBACK: + { + switch(GET_C2H_CMD_FEEDBACK_ELEMENT_ID(pCmdContent)) + { + case HAL_FW_C2H_CMD_C2HFEEDBACK_CCX_PER_PKT_RPT: + { + RT_TRACE(COMP_CMD, "HAL_FW_C2H_CMD_C2HFEEDBACK_CCX_PER_PKT_RPT FW_DBG CMD Hex:%x\n", total_length); + } + break; + + case HAL_FW_C2H_CMD_C2HFEEDBACK_DTM_TX_STATISTICS_RPT: + break; + + default: + break; + } + } + break; + + case HAL_FW_C2H_CMD_C2HDBG: + RT_TRACE(COMP_CMD, "rtl8192se_RxCommandPacketHandle(): %x:%x<*** FW_DBG CMD String ***>\n", *pCmdContent, RxCmdLen); + break; + + case HAL_FW_C2H_CMD_BT_State: + { + } + break; + case HAL_FW_C2H_CMD_BT_Service: + { + } + break; + case HAL_FW_C2H_CMD_SurveyDone: + { + rtl8192se_rx_surveydone_cmd(dev); + } + break; + default: + RT_TRACE(COMP_CMD, "rtl8192se_RxCommandPacketHandle(): Receive unhandled C2H CMD (%d)\n", RxCmdElementID); + break; + } + + offset += (C2H_RX_CMD_HDR_LEN + N_BYTE_ALIGMENT(RxCmdLen, 8)); + + if(!RxCmdContinue || ((offset + C2H_RX_CMD_HDR_LEN) > total_length)) + { + break; + } + }while(true); + RT_TRACE(COMP_RECV, "RxCommandPacketHandle8190Pci(): It is a command packet\n"); + + return 1; +} + +void +rtl8192se_InitializeVariables(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if (priv->rf_type == RF_1T1R) + strcpy(priv->nick, "rtl8191SEVA1"); + else if (priv->rf_type == RF_1T2R) + strcpy(priv->nick, "rtl8191SEVA2"); + else + strcpy(priv->nick, "rtl8192SE"); + +#ifdef _ENABLE_SW_BEACON + priv->rtllib->softmac_features = IEEE_SOFTMAC_SCAN | + IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ | + IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE | + IEEE_SOFTMAC_BEACONS; +#else +#ifdef _RTL8192_EXT_PATCH_ + priv->rtllib->softmac_features = IEEE_SOFTMAC_SCAN | + IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ | + IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE /* | + IEEE_SOFTMAC_BEACONS*/; +#else + priv->rtllib->softmac_features = IEEE_SOFTMAC_SCAN | + IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ | + IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE /* | + IEEE_SOFTMAC_BEACONS*/; +#endif +#endif + + priv->rtllib->tx_headroom = 0; + + priv->ShortRetryLimit = 0x30; + priv->LongRetryLimit = 0x30; + + priv->EarlyRxThreshold = 7; + priv->pwrGroupCnt = 0; + + priv->bIgnoreSilentReset = false; + priv->enable_gpio0 = 0; + + priv->TransmitConfig = 0; + + priv->ReceiveConfig = + RCR_APPFCS | RCR_APWRMGT | /*RCR_ADD3 |*/ + RCR_AMF | RCR_ADF | RCR_APP_MIC | RCR_APP_ICV | + RCR_AICV | RCR_ACRC32 | + RCR_AB | RCR_AM | + RCR_APM | + /*RCR_AAP |*/ + RCR_APP_PHYST_STAFF | RCR_APP_PHYST_RXFF | + (priv->EarlyRxThreshold<irq_mask[0] = + (IMR_ROK | IMR_VODOK | IMR_VIDOK | IMR_BEDOK | IMR_BKDOK | \ + IMR_HCCADOK | IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK | \ + IMR_BDOK | IMR_RXCMDOK | /*IMR_TIMEOUT0 |*/ IMR_RDU | IMR_RXFOVW/* | \ + IMR_BcnInt| IMR_TXFOVW | IMR_TBDOK | IMR_TBDER*/); +#else + priv->irq_mask[0] = + (IMR_ROK | IMR_VODOK | IMR_VIDOK | IMR_BEDOK | IMR_BKDOK | \ + IMR_HCCADOK | IMR_MGNTDOK | IMR_COMDOK | IMR_HIGHDOK | \ + IMR_BDOK | IMR_RXCMDOK | /*IMR_TIMEOUT0 |*/ IMR_RDU | IMR_RXFOVW | \ + IMR_BcnInt/*| IMR_TXFOVW*/ /*| IMR_TBDOK | IMR_TBDER*/); +#endif + priv->irq_mask[1] = 0;/* IMR_TBDOK | IMR_TBDER*/ + + + priv->MidHighPwrTHR_L1 = 0x3B; + priv->MidHighPwrTHR_L2 = 0x40; + priv->PwrDomainProtect = false; + + if (!(priv->rtllib->softmac_features & IEEE_SOFTMAC_SCAN)){ + if (!priv->scan_cmd) { + priv->scan_cmd = kmalloc(sizeof(H2C_SITESURVEY_PARA) + + RTL_MAX_SCAN_SIZE, GFP_KERNEL); + } + } + + rtl8192se_HalDetectPwrDownMode(dev); +} + +void rtl8192se_EnableInterrupt(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + priv->irq_enabled = 1; + +#ifdef RTL8192CE + write_nic_dword(dev, REG_HIMR, priv->irq_mask[0]&0xFFFFFFFF); +#else + write_nic_dword(dev,INTA_MASK, priv->irq_mask[0]); +#endif + +#ifdef RTL8192SE + write_nic_dword(dev,INTA_MASK+4, priv->irq_mask[1]&0x3F); +#endif + +} + +void rtl8192se_DisableInterrupt(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + +#ifdef RTL8192CE + write_nic_dword(dev, REG_HIMR, IMR8190_DISABLED); +#else + write_nic_dword(dev,INTA_MASK,0); +#endif + +#ifdef RTL8192SE + write_nic_dword(dev,INTA_MASK + 4,0); +#endif + priv->irq_enabled = 0; +} + +void rtl8192se_ClearInterrupt(struct net_device *dev) +{ + u32 tmp = 0; +#ifdef RTL8192CE + tmp = read_nic_dword(dev, REG_HISR); + write_nic_dword(dev, REG_HISR, tmp); +#else + tmp = read_nic_dword(dev, ISR); + write_nic_dword(dev, ISR, tmp); +#endif + +#ifdef RTL8192SE + tmp = read_nic_dword(dev, ISR+4); + write_nic_dword(dev, ISR+4, tmp); +#endif +} + +void rtl8192se_enable_rx(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + write_nic_dword(dev, RDQDA,priv->rx_ring_dma[RX_MPDU_QUEUE]); +#ifdef CONFIG_RX_CMD + write_nic_dword(dev, RCDA, priv->rx_ring_dma[RX_CMD_QUEUE]); +#endif +} + +u32 TX_DESC_BASE[] = {TBKDA, TBEDA, TVIDA, TVODA, TBDA, TCDA, TMDA, THPDA, HDA}; +void rtl8192se_enable_tx(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u32 i; + + for (i = 0; i < MAX_TX_QUEUE_COUNT; i++) + write_nic_dword(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma); +} + + +void rtl8192se_beacon_disable(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u32 reg; + +#ifdef RTL8192CE + reg = read_nic_dword(priv->rtllib->dev,REG_HIMR); + + reg &= ~(IMR_BcnInt | IMR_BcnInt | IMR_TBDOK | IMR_TBDER); + write_nic_dword(priv->rtllib->dev, REG_HIMR, reg); +#else + reg = read_nic_dword(priv->rtllib->dev,INTA_MASK); + + reg &= ~(IMR_BcnInt | IMR_BcnInt | IMR_TBDOK | IMR_TBDER); + write_nic_dword(priv->rtllib->dev, INTA_MASK, reg); +#endif +} + +void rtl8192se_interrupt_recognized(struct net_device *dev, u32 *p_inta, u32 *p_intb) +{ +#ifdef RTL8192SE + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + *p_inta = read_nic_dword(dev, ISR) & priv->irq_mask[0]; +#else + *p_inta = read_nic_dword(dev, ISR) ; +#endif + write_nic_dword(dev,ISR,*p_inta); +#ifdef RTL8192SE + *p_intb = read_nic_dword(dev, ISR+4); + write_nic_dword(dev, ISR+4, *p_intb); +#endif +} + +bool rtl8192se_HalRxCheckStuck(struct net_device *dev) +{ + + struct r8192_priv *priv = rtllib_priv(dev); + u16 RegRxCounter = (u16)(priv->InterruptLog.nIMR_ROK&0xffff); + bool bStuck = false; + u32 SlotIndex = 0, TotalRxStuckCount = 0; + u8 i; + u8 SilentResetRxSoltNum = 4; + + + SlotIndex = (priv->SilentResetRxSlotIndex++)%SilentResetRxSoltNum; + + if(priv->RxCounter==RegRxCounter) + { + priv->SilentResetRxStuckEvent[SlotIndex] = 1; + + for( i = 0; i < SilentResetRxSoltNum ; i++ ) + TotalRxStuckCount += priv->SilentResetRxStuckEvent[i]; + + if(TotalRxStuckCount == SilentResetRxSoltNum) + { + bStuck = true; + for( i = 0; i < SilentResetRxSoltNum ; i++ ) + TotalRxStuckCount += priv->SilentResetRxStuckEvent[i]; + } + + + } else { + priv->SilentResetRxStuckEvent[SlotIndex] = 0; + } + + priv->RxCounter = RegRxCounter; + + return bStuck; +} + +bool rtl8192se_HalTxCheckStuck(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + bool bStuck = false; +#if defined(RTL8192E) || defined(RTL8190P) + u16 RegTxCounter = read_nic_word(dev, 0x128); +#elif defined (RTL8192SE) || defined (RTL8192CE) + u16 RegTxCounter = read_nic_word(dev, 0x366); +#else + u16 RegTxCounter = priv->TxCounter + 1; + WARN_ON(1); +#endif + + RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n", + __FUNCTION__,RegTxCounter,priv->TxCounter); + + if(priv->TxCounter == RegTxCounter) + bStuck = true; + + priv->TxCounter = RegTxCounter; + + return bStuck; +} + +bool rtl8192se_GetNmodeSupportBySecCfg(struct net_device *dev) +{ +#ifdef RTL8192SE + return true; +#else + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + if (ieee->rtllib_ap_sec_type && + (ieee->rtllib_ap_sec_type(priv->rtllib)&(SEC_ALG_WEP|SEC_ALG_TKIP))) { + return false; + } else { + return true; + } +#endif +} + +bool rtl8192se_GetHalfNmodeSupportByAPs(struct net_device* dev) +{ +#ifdef RTL8192SE + return false; +#else + bool Reval; + struct r8192_priv* priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + + if(ieee->bHalfWirelessN24GMode == true) + Reval = true; + else + Reval = false; + + return Reval; +#endif +} + +u8 rtl8192se_QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc) +{ + u8 tmp_Short; + + tmp_Short = (TxHT==1)?((tcb_desc->bUseShortGI)?1:0):((tcb_desc->bUseShortPreamble)?1:0); +#if defined RTL8192SE || defined RTL8192CE + if(TxHT==1 && TxRate != DESC92S_RATEMCS15) +#elif defined RTL8192E || defined RTL8190P + if(TxHT==1 && TxRate != DESC90_RATEMCS15) +#endif + tmp_Short = 0; + + return tmp_Short; +} + +void +ActUpdateChannelAccessSetting( + struct net_device* dev, + WIRELESS_MODE WirelessMode, + PCHANNEL_ACCESS_SETTING ChnlAccessSetting + ) +{ + struct r8192_priv* priv = rtllib_priv(dev); + +#if 0 + WIRELESS_MODE Tmp_WirelessMode = WirelessMode; + + switch( Tmp_WirelessMode ) + { + case WIRELESS_MODE_A: + ChnlAccessSetting->SlotTimeTimer = 9; + ChnlAccessSetting->CWminIndex = 4; + ChnlAccessSetting->CWmaxIndex = 10; + break; + case WIRELESS_MODE_B: + ChnlAccessSetting->SlotTimeTimer = 20; + ChnlAccessSetting->CWminIndex = 5; + ChnlAccessSetting->CWmaxIndex = 10; + break; + case WIRELESS_MODE_G: + ChnlAccessSetting->SlotTimeTimer = 20; + ChnlAccessSetting->CWminIndex = 4; + ChnlAccessSetting->CWmaxIndex = 10; + break; + case WIRELESS_MODE_N_24G: + case WIRELESS_MODE_N_5G: + ChnlAccessSetting->SlotTimeTimer = 9; + ChnlAccessSetting->CWminIndex = 4; + ChnlAccessSetting->CWmaxIndex = 10; + break; + default: + RT_ASSERT(false, ("ActUpdateChannelAccessSetting(): Wireless mode is not defined!\n")); + break; + } + +#endif + + { + u16 SIFS_Timer; + + if(WirelessMode == WIRELESS_MODE_G) + SIFS_Timer = 0x0e0e; + else + SIFS_Timer = 0x1010; + + SIFS_Timer = 0x0e0e; + priv->rtllib->SetHwRegHandler( dev, HW_VAR_SIFS, (u8*)&SIFS_Timer); + + } + +} \ No newline at end of file --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_dev.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_dev.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef _RTL8192SE_H +#define _RTL8192SE_H + +#include "r8192S_def.h" + +u8 rtl8192se_QueryIsShort(u8 TxHT, u8 TxRate, cb_desc *tcb_desc); +bool rtl8192se_GetHalfNmodeSupportByAPs(struct net_device* dev); +bool rtl8192se_GetNmodeSupportBySecCfg(struct net_device *dev); +bool rtl8192se_HalTxCheckStuck(struct net_device *dev); +bool rtl8192se_HalRxCheckStuck(struct net_device *dev); +void rtl8192se_interrupt_recognized(struct net_device *dev, u32 *p_inta, u32 *p_intb); +void rtl8192se_enable_rx(struct net_device *dev); +void rtl8192se_enable_tx(struct net_device *dev); +void rtl8192se_EnableInterrupt(struct net_device *dev); +void rtl8192se_DisableInterrupt(struct net_device *dev); +void rtl8192se_ClearInterrupt(struct net_device *dev); +void rtl8192se_InitializeVariables(struct net_device *dev); +void rtl8192se_start_beacon(struct net_device *dev); +u8 MRateToHwRate8192SE(struct net_device*dev, u8 rate); +void rtl8192se_get_eeprom_size(struct net_device* dev); +void MacConfigBeforeFwDownload(struct net_device *dev); +bool rtl8192se_adapter_start(struct net_device* dev); +void rtl8192se_link_change(struct net_device *dev); +void rtl8192se_AllowAllDestAddr(struct net_device* dev, bool bAllowAllDA, bool WriteIntoReg); +void rtl8192se_tx_fill_desc(struct net_device *dev, tx_desc *pDesc, cb_desc *cb_desc, struct sk_buff *skb); +void rtl8192se_tx_fill_cmd_desc(struct net_device *dev, tx_desc_cmd *entry, cb_desc *cb_desc, + struct sk_buff *skb); +bool rtl8192se_rx_query_status_desc(struct net_device* dev, struct rtllib_rx_stats* stats, + rx_desc *pdesc, struct sk_buff* skb); +void rtl8192se_halt_adapter(struct net_device *dev, bool bReset); +void rtl8192se_update_ratr_table(struct net_device* dev,u8* pMcsRate,struct sta_info* pEntry); +int r8192se_resume_firm(struct net_device *dev); +void PHY_SetRtl8192seRfHalt(struct net_device* dev); +void UpdateHalRAMask8192SE(struct net_device* dev, bool bMulticast, u8 macId, u8 MimoPs, u8 WirelessMode, u8 bCurTxBW40MHz, u8 rssi_level); +u8 HalSetSysClk8192SE(struct net_device *dev, u8 Data); +bool rtl8192se_RxCommandPacketHandle(struct net_device *dev, struct sk_buff* skb,rx_desc *pdesc); +bool rtl8192se_check_ht_cap(struct net_device* dev, struct sta_info *sta, + struct rtllib_network* net); +u8 rtl8192se_MapHwQueueToFirmwareQueue(u8 QueueID, u8 priority); + +void GetHwReg8192SE(struct net_device *dev,u8 variable,u8* val); +void SetHwReg8192SE(struct net_device *dev,u8 variable,u8* val); +void Adhoc_InitRateAdaptive(struct net_device *dev,struct sta_info *pEntry); +void SetBeaconRelatedRegisters8192SE(struct net_device *dev); + +#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,20) +void rtl8192se_check_tsf_wq(struct work_struct * work); +void rtl8192se_update_assoc_sta_info_wq(struct work_struct * work); +#else +void rtl8192se_check_tsf_wq(struct net_device *dev); +void rtl8192se_update_assoc_sta_info_wq(struct net_device *dev); +#endif +void gen_RefreshLedState(struct net_device *dev); + +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_firmware.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_firmware.c @@ -0,0 +1,854 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#if defined(RTL8192SE) +#include "../rtl_core.h" +#include "../rtllib/rtllib_endianfree.h" + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) && defined(USE_FW_SOURCE_IMG_FILE) +#include +#endif +#define byte(x,n) ( (x >> (8 * n)) & 0xff ) + +static void fw_SetRQPN(struct net_device *dev) +{ + + write_nic_dword(dev, RQPN, 0xffffffff); + write_nic_dword(dev, RQPN+4, 0xffffffff); + write_nic_byte(dev, RQPN+8, 0xff); + write_nic_byte(dev, RQPN+0xB, 0x80); + + +} /* fw_SetRQPN */ + +bool FirmwareDownloadCode(struct net_device *dev, u8 * code_virtual_address,u32 buffer_len) +{ + struct r8192_priv *priv = rtllib_priv(dev); + bool rt_status = true; + u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; + u16 frag_length, frag_offset = 0; + struct sk_buff *skb; + unsigned char *seg_ptr; + cb_desc *tcb_desc; + u8 bLastIniPkt = 0; + u16 ExtraDescOffset = 0; + +#ifdef RTL8192SE + fw_SetRQPN(dev); +#endif + + RT_TRACE(COMP_FIRMWARE, "--->FirmwareDownloadCode()\n" ); + + if(buffer_len >= MAX_FIRMWARE_CODE_SIZE) + { + RT_TRACE(COMP_ERR, "Size over FIRMWARE_CODE_SIZE! \n"); + goto cmdsend_downloadcode_fail; + } + + ExtraDescOffset = 0; + + do { + if((buffer_len-frag_offset) > frag_threshold) + { + frag_length = frag_threshold + ExtraDescOffset; + } + else + { + frag_length = (u16)(buffer_len - frag_offset + ExtraDescOffset); + bLastIniPkt = 1; + } + + skb = dev_alloc_skb(frag_length); + memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); + + tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE); + tcb_desc->queue_index = TXCMD_QUEUE; + tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT; + tcb_desc->bLastIniPkt = bLastIniPkt; + + skb_reserve(skb, ExtraDescOffset); + seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length-ExtraDescOffset)); + memcpy(seg_ptr, code_virtual_address+frag_offset, (u32)(frag_length-ExtraDescOffset)); + + tcb_desc->txbuf_size= frag_length; + + if(!priv->rtllib->check_nic_enough_desc(dev,tcb_desc->queue_index)|| + (!skb_queue_empty(&priv->rtllib->skb_waitQ[tcb_desc->queue_index]))||\ + (priv->rtllib->queue_stop) ) + { + RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n"); + skb_queue_tail(&priv->rtllib->skb_waitQ[tcb_desc->queue_index], skb); + } + else + { + priv->rtllib->softmac_hard_start_xmit(skb,dev); + } + + frag_offset += (frag_length - ExtraDescOffset); + + }while(frag_offset < buffer_len); + write_nic_byte(dev, TPPoll, TPPoll_CQ); + return rt_status ; + + +cmdsend_downloadcode_fail: + rt_status = false; + RT_TRACE(COMP_ERR, "CmdSendDownloadCode fail !!\n"); + return rt_status; + +} + + + +bool +FirmwareEnableCPU(struct net_device *dev) +{ + + bool rtStatus = true; + u8 tmpU1b, CPUStatus = 0; + u16 tmpU2b; + u32 iCheckTime = 200; + + RT_TRACE(COMP_FIRMWARE, "-->FirmwareEnableCPU()\n" ); + + fw_SetRQPN(dev); + + tmpU1b = read_nic_byte(dev, SYS_CLKR); + write_nic_byte(dev, SYS_CLKR, (tmpU1b|SYS_CPU_CLKSEL)); + + tmpU2b = read_nic_word(dev, SYS_FUNC_EN); + write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|FEN_CPUEN)); + + do + { + CPUStatus = read_nic_byte(dev, TCR); + if(CPUStatus& IMEM_RDY) + { + RT_TRACE(COMP_FIRMWARE, "IMEM Ready after CPU has refilled.\n"); + break; + } + + udelay(100); + }while(iCheckTime--); + + if(!(CPUStatus & IMEM_RDY)) + return false; + + RT_TRACE(COMP_FIRMWARE, "<--FirmwareEnableCPU(): rtStatus(%#x)\n", rtStatus); + return rtStatus; +} + +FIRMWARE_8192S_STATUS +FirmwareGetNextStatus(FIRMWARE_8192S_STATUS FWCurrentStatus) +{ + FIRMWARE_8192S_STATUS NextFWStatus = 0; + + switch(FWCurrentStatus) + { + case FW_STATUS_INIT: + NextFWStatus = FW_STATUS_LOAD_IMEM; + break; + + case FW_STATUS_LOAD_IMEM: + NextFWStatus = FW_STATUS_LOAD_EMEM; + break; + + case FW_STATUS_LOAD_EMEM: + NextFWStatus = FW_STATUS_LOAD_DMEM; + break; + + case FW_STATUS_LOAD_DMEM: + NextFWStatus = FW_STATUS_READY; + break; + + default: + RT_TRACE(COMP_ERR,"Invalid FW Status(%#x)!!\n", FWCurrentStatus); + break; + } + return NextFWStatus; +} + +bool FirmwareCheckReady(struct net_device *dev, u8 LoadFWStatus) +{ + struct r8192_priv *priv = rtllib_priv(dev); + bool rtStatus = true; + rt_firmware *pFirmware = priv->pFirmware; + short PollingCnt = 1000; + u8 CPUStatus = 0; + u32 tmpU4b; + + RT_TRACE(COMP_FIRMWARE, "--->%s(): LoadStaus(%d),", __FUNCTION__, LoadFWStatus); + + pFirmware->FWStatus = (FIRMWARE_8192S_STATUS)LoadFWStatus; + + switch (LoadFWStatus) { + case FW_STATUS_LOAD_IMEM: + do { + CPUStatus = read_nic_byte(dev, TCR); + if(CPUStatus& IMEM_CODE_DONE) + break; + udelay(5); + } while (PollingCnt--); + if (!(CPUStatus & IMEM_CHK_RPT) || (PollingCnt <= 0)) { + RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\r\n", CPUStatus); + goto status_check_fail; + } + break; + + case FW_STATUS_LOAD_EMEM: + do { + CPUStatus = read_nic_byte(dev, TCR); + if(CPUStatus& EMEM_CODE_DONE) + break; + udelay(5); + } while(PollingCnt--); + if (!(CPUStatus & EMEM_CHK_RPT) || (PollingCnt <= 0)) { + RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\r\n", CPUStatus); + goto status_check_fail; + } + + rtStatus = FirmwareEnableCPU(dev); + if (rtStatus != true) { + RT_TRACE(COMP_ERR, "Enable CPU fail ! \n" ); + goto status_check_fail; + } + break; + + case FW_STATUS_LOAD_DMEM: + do { + CPUStatus = read_nic_byte(dev, TCR); + if (CPUStatus& DMEM_CODE_DONE) + break; + udelay(5); + } while(PollingCnt--); + + if (!(CPUStatus & DMEM_CODE_DONE) || (PollingCnt <= 0)) { + RT_TRACE(COMP_ERR, "Polling DMEM code done fail ! CPUStatus(%#x)\n", CPUStatus); + goto status_check_fail; + } + + RT_TRACE(COMP_FIRMWARE, "DMEM code download success, CPUStatus(%#x)\n", CPUStatus); + PollingCnt = 2000; + do { + CPUStatus = read_nic_byte(dev, TCR); + if(CPUStatus & FWRDY) + break; + udelay(40); + } while(PollingCnt--); + + RT_TRACE(COMP_FIRMWARE, "Polling Load Firmware ready, CPUStatus(%x)\n", CPUStatus); + if (((CPUStatus & LOAD_FW_READY) != LOAD_FW_READY) || (PollingCnt <= 0)) { + RT_TRACE(COMP_ERR, "Polling Load Firmware ready fail ! CPUStatus(%x)\n", CPUStatus); + goto status_check_fail; + } + +#ifdef RTL8192SE +#endif + + tmpU4b = read_nic_dword(dev,TCR); + write_nic_dword(dev, TCR, (tmpU4b&(~TCR_ICV))); + + tmpU4b = read_nic_dword(dev, RCR); + write_nic_dword(dev, RCR, + (tmpU4b|RCR_APPFCS|RCR_APP_ICV|RCR_APP_MIC)); + + RT_TRACE(COMP_FIRMWARE, "FirmwareCheckReady(): Current RCR settings(%#x)\n", tmpU4b); + +#if 0 + priv->TransmitConfig = read_nic_dword_E(dev, TCR); + RT_TRACE(COMP_FIRMWARE, "FirmwareCheckReady(): Current TCR settings(%#x)\n", priv->TransmitConfig); +#endif + + write_nic_byte(dev, LBKMD_SEL, LBK_NORMAL); + break; + default : + RT_TRACE(COMP_FIRMWARE, "Unknown status check!\n"); + rtStatus = false; + break; + } + +status_check_fail: + RT_TRACE(COMP_FIRMWARE, "<---%s: LoadFWStatus(%d), rtStatus(%x)\n", __FUNCTION__, + LoadFWStatus, rtStatus); + return rtStatus; +} +u8 FirmwareHeaderMapRfType(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + switch(priv->rf_type) + { + case RF_1T1R: return 0x11; + case RF_1T2R: return 0x12; + case RF_2T2R: return 0x22; + case RF_2T2R_GREEN: return 0x92; + default: + RT_TRACE(COMP_INIT, "Unknown RF type(%x)\n",priv->rf_type); + break; + } + return 0x22; +} + + +void FirmwareHeaderPriveUpdate(struct net_device *dev, PRT_8192S_FIRMWARE_PRIV pFwPriv) +{ + pFwPriv->rf_config = FirmwareHeaderMapRfType(dev); +} + + + +bool FirmwareDownload92S(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + bool rtStatus = true; + u8 *pucMappedFile = NULL; + u32 ulFileLength = 0; + u8 FwHdrSize = RT_8192S_FIRMWARE_HDR_SIZE; + rt_firmware *pFirmware = priv->pFirmware; + u8 FwStatus = FW_STATUS_INIT; + PRT_8192S_FIRMWARE_HDR pFwHdr = NULL; + PRT_8192S_FIRMWARE_PRIV pFwPriv = NULL; + + pFirmware->FWStatus = FW_STATUS_INIT; + + RT_TRACE(COMP_FIRMWARE, " --->FirmwareDownload92S()\n"); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) && defined(USE_FW_SOURCE_IMG_FILE) + priv->firmware_source = FW_SOURCE_IMG_FILE; +#else + priv->firmware_source = FW_SOURCE_HEADER_FILE; +#endif + + switch( priv->firmware_source ) + { + case FW_SOURCE_IMG_FILE: +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) && defined(USE_FW_SOURCE_IMG_FILE) + if(pFirmware->szFwTmpBufferLen == 0) + { +#ifdef _RTL8192_EXT_PATCH_ + const char *pFwImageFileName[1] = {"RTL8191SE_MESH/rtl8192sfw.bin"}; +#else + const char *pFwImageFileName[1] = {"RTL8192SE/rtl8192sfw.bin"}; +#endif + const struct firmware *fw_entry = NULL; + u32 ulInitStep = 0; + int rc = 0; + u32 file_length = 0; + rc = request_firmware(&fw_entry, pFwImageFileName[ulInitStep],&priv->pdev->dev); + if(rc < 0 ) { + RT_TRACE(COMP_ERR, "request firmware fail!\n"); + goto DownloadFirmware_Fail; + } + + if(fw_entry->size > sizeof(pFirmware->szFwTmpBuffer)) { + RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n"); + release_firmware(fw_entry); + goto DownloadFirmware_Fail; + } + + memcpy(pFirmware->szFwTmpBuffer,fw_entry->data,fw_entry->size); + pFirmware->szFwTmpBufferLen = fw_entry->size; + release_firmware(fw_entry); + + pucMappedFile = pFirmware->szFwTmpBuffer; + file_length = pFirmware->szFwTmpBufferLen; + + pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile; + pFwHdr = pFirmware->pFwHeader; + RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \ + pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \ + pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE); + pFirmware->FirmwareVersion = byte(pFwHdr->Version ,0); + if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM))) + { + RT_TRACE(COMP_ERR, "%s: memory for data image is less than IMEM required\n",\ + __FUNCTION__); + goto DownloadFirmware_Fail; + } else { + pucMappedFile+=FwHdrSize; + + memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE); + pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE; + } + + if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM)) + { + RT_TRACE(COMP_ERR, "%s: memory for data image is less than EMEM required\n",\ + __FUNCTION__); + goto DownloadFirmware_Fail; + } + else + { + pucMappedFile += pFirmware->FwIMEMLen; + + memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE); + pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE; + } + } +#endif + break; + + case FW_SOURCE_HEADER_FILE: +#if 1 +#define Rtl819XFwImageArray Rtl8192SEFwImgArray + pucMappedFile = Rtl819XFwImageArray; + ulFileLength = ImgArrayLength; + + RT_TRACE(COMP_INIT,"Fw download from header.\n"); + pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile; + pFwHdr = pFirmware->pFwHeader; + RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \ + pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \ + pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE); + pFirmware->FirmwareVersion = byte(pFwHdr->Version ,0); + + if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM))) + { + printk("FirmwareDownload92S(): memory for data image is less than IMEM required\n"); + goto DownloadFirmware_Fail; + } + else + { + pucMappedFile+=FwHdrSize; + + memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE); + pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE; + } + + if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM)) + { + printk(" FirmwareDownload92S(): memory for data image is less than EMEM required\n"); + goto DownloadFirmware_Fail; + } else { + pucMappedFile+= pFirmware->FwIMEMLen; + + memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE); + pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE; + } +#endif + break; + default: + break; + } + + FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus); + while(FwStatus!= FW_STATUS_READY) + { + switch(FwStatus) + { + case FW_STATUS_LOAD_IMEM: + pucMappedFile = pFirmware->FwIMEM; + ulFileLength = pFirmware->FwIMEMLen; + break; + + case FW_STATUS_LOAD_EMEM: + pucMappedFile = pFirmware->FwEMEM; + ulFileLength = pFirmware->FwEMEMLen; + break; + + case FW_STATUS_LOAD_DMEM: + pFwHdr = pFirmware->pFwHeader; + pFwPriv = (PRT_8192S_FIRMWARE_PRIV)&pFwHdr->FWPriv; + FirmwareHeaderPriveUpdate(dev, pFwPriv); + pucMappedFile = (u8*)(pFirmware->pFwHeader)+RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; + ulFileLength = FwHdrSize-RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; + break; + + default: + RT_TRACE(COMP_ERR, "Unexpected Download step!!\n"); + goto DownloadFirmware_Fail; + break; + } + + rtStatus = FirmwareDownloadCode(dev, pucMappedFile, ulFileLength); + + if(rtStatus != true) + { + RT_TRACE(COMP_ERR, "FirmwareDownloadCode() fail ! \n" ); + goto DownloadFirmware_Fail; + } + + rtStatus = FirmwareCheckReady(dev, FwStatus); + + if(rtStatus != true) + { + RT_TRACE(COMP_ERR, "FirmwareDownloadCode() fail ! \n"); + goto DownloadFirmware_Fail; + } + + FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus); + } + + RT_TRACE(COMP_FIRMWARE, "Firmware Download Success!!\n"); + return rtStatus; + + DownloadFirmware_Fail: + RT_TRACE(COMP_ERR, "Firmware Download Fail!!%x\n",read_nic_word(dev, TCR)); + rtStatus = false; + return rtStatus; +} +void rtl8192se_dump_skb_data(struct sk_buff *skb) +{ + u8 i = 0; + u8 *arry = skb->data; + + printk("\nSCAN_CMD/PROBE_REQ==============>\n"); + for(i = 0; i < skb->len; i ++){ + if((i % 4 == 0)&&(i != 0)) + printk("\n"); + printk("%2.2x ", arry[i]); + } + printk("\nSCAN_CMD/PROBE_REQ<==============\n"); +} + +void rtl8192se_dump_cmd_para(u8*SiteSurveyPara) +{ + u8 i = 0; + u8 desc_size = sizeof(tx_desc_fw); + u8 para_size = 8+desc_size; + u8 *arry = SiteSurveyPara; + + printk("\nSCAN_CMD_PARA==============>\n"); + for(i = 0; i < para_size; i ++){ + if((i % 4 == 0)&&(i != 0)) + printk("\n"); + printk("%2.2x ", arry[i]); + } + printk("\nSCAN_CMD_PARA<==============\n"); +} +#if 1 +RT_STATUS +CmdSendPacket( + struct net_device *dev, + cb_desc *pTcb, + struct sk_buff *skb, + u32 BufferLen, + u32 PacketType, + bool bLastInitPacket + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + RT_STATUS rtStatus = RT_STATUS_SUCCESS; + + pTcb->queue_index = TXCMD_QUEUE; + pTcb->bCmdOrInit = PacketType; + pTcb->bLastIniPkt = bLastInitPacket; + pTcb->txbuf_size = BufferLen; + + + if(!priv->rtllib->check_nic_enough_desc(dev,pTcb->queue_index)|| + (!skb_queue_empty(&priv->rtllib->skb_waitQ[pTcb->queue_index]))||\ + (priv->rtllib->queue_stop) ) { + RT_TRACE(COMP_CMD,"=========================> tx full!\n"); + skb_queue_tail(&priv->rtllib->skb_waitQ[pTcb->queue_index], skb); + } else { + priv->rtllib->softmac_hard_start_xmit(skb,dev); + } + + return rtStatus; +} + +u32 +FillH2CCmd( + struct sk_buff *skb, + u32 H2CBufferLen, + u32 CmdNum, + u32* pElementID, + u32* pCmdLen, + u8** pCmbBuffer, + u8* CmdStartSeq + ) +{ + u8 i = 0; + u32 TotalLen = 0, Len = 0, TxDescLen = 0; + u32 preContinueOffset = 0; + + u8* pH2CBuffer; + + do + { + Len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pCmdLen[i], 8); + + if(H2CBufferLen < TotalLen + Len + TxDescLen) + break; + + pH2CBuffer = (u8 *) skb_put(skb, (u32)Len); + memset((pH2CBuffer + TotalLen + TxDescLen),0,Len); + + SET_BITS_TO_LE_4BYTE((pH2CBuffer + TotalLen + TxDescLen), 0, 16, pCmdLen[i]); + + SET_BITS_TO_LE_4BYTE((pH2CBuffer + TotalLen + TxDescLen), 16, 8, pElementID[i]); + + *CmdStartSeq = *CmdStartSeq % 0x80; + SET_BITS_TO_LE_4BYTE((pH2CBuffer + TotalLen + TxDescLen), 24, 7, *CmdStartSeq); + ++ *CmdStartSeq; + + memcpy((pH2CBuffer + TotalLen + TxDescLen + H2C_TX_CMD_HDR_LEN), pCmbBuffer[i], pCmdLen[i]); + + if(i < CmdNum - 1) + SET_BITS_TO_LE_4BYTE((pH2CBuffer + preContinueOffset), 31, 1, 1); + + preContinueOffset = TotalLen; + + TotalLen += Len; + }while(++ i < CmdNum); + + return TotalLen; +} + +u32 +GetH2CCmdLen( + u32 H2CBufferLen, + u32 CmdNum, + u32* pCmdLen + ) +{ + u8 i = 0; + u32 TotalLen = 0, Len = 0, TxDescLen = 0; + + do + { + Len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pCmdLen[i], 8); + + if(H2CBufferLen < TotalLen + Len + TxDescLen) + break; + + TotalLen += Len; + }while(++ i < CmdNum); + + return TotalLen + TxDescLen; +} + +/*----------------------------------------------------------------------------- + * Function: FirmwareSetH2CCmd() + * + * Overview: Set FW H2C command (Decide ElementID, cmd content length, and get FW buffer) + * + * Input: H2CCmd: H2C command type. + * pCmdBuffer: Pointer of the H2C command content. + * + * Output: NONE + * + * Return: RT_STATUS + * + * Revised History: + * When Who Remark + * 2009/1/12 tynli Create the version 0. + * + *---------------------------------------------------------------------------*/ +RT_STATUS +FirmwareSetH2CCmd( + struct net_device *dev, + u8 H2CCmd, + u8* pCmdBuffer + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 ElementID; + u32 Cmd_Len; + cb_desc *pTcb; + struct sk_buff *skb; + u32 Len; + + RT_STATUS rtStatus; + + switch(H2CCmd){ + case FW_H2C_SETPWRMODE: + { + ElementID = H2C_SetPwrMode_CMD ; + Cmd_Len = sizeof(H2C_SETPWRMODE_PARM); + } + break; + case FW_H2C_JOINBSSRPT: + { + ElementID = H2C_JoinbssRpt_CMD; + Cmd_Len = sizeof(H2C_JOINBSSRPT_PARM); + } + break; + case FW_H2C_WoWLAN_UPDATE_GTK: + { + ElementID = H2C_WoWLAN_UPDATE_GTK_CMD; + Cmd_Len = sizeof(H2C_WPA_TWO_WAY_PARA); + } + break; + case FW_H2C_WoWLAN_UPDATE_IV: + { + ElementID = H2C_WoWLAN_UPDATE_IV_CMD; + Cmd_Len = sizeof(unsigned long long); + } + break; + + case FW_H2C_WoWLAN_OFFLOAD: + { + ElementID = H2C_WoWLAN_FW_OFFLOAD; + Cmd_Len = sizeof(u8); + } + break; + case FW_H2C_SITESURVEY: + { + ElementID = H2C_SiteSurvey_CMD; + Cmd_Len = sizeof(H2C_SITESURVEY_PARA) + ((PH2C_SITESURVEY_PARA)pCmdBuffer)->probe_req_len - sizeof(tx_desc_fw); + } + break; + default: + break; + } + + RT_TRACE(COMP_CMD, "FirmwareSetH2CCmd() HW_VAR_SET_TX_CMD: ElementID = %d, %d+%d=Cmd_Len = %d\n", ElementID, sizeof(H2C_SITESURVEY_PARA),((PH2C_SITESURVEY_PARA)pCmdBuffer)->probe_req_len, Cmd_Len); + + { + Len = GetH2CCmdLen(MAX_TRANSMIT_BUFFER_SIZE, 1, &Cmd_Len); + + RT_TRACE(COMP_CMD, "---------->%s(), cmdlen:%d,len:%d\n", __func__,Cmd_Len,Len); + skb = dev_alloc_skb(Len); + memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); + + pTcb = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE); + + FillH2CCmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &ElementID, &Cmd_Len, &pCmdBuffer, &priv->H2CTxCmdSeq); + + + rtStatus = CmdSendPacket(dev, pTcb, skb, Len, DESC_PACKET_TYPE_NORMAL, false); + + } + + write_nic_byte(dev, TPPoll, TPPoll_CQ); + + return RT_STATUS_SUCCESS; +} + + +void +rtl8192se_set_scan_cmd(struct net_device *dev, u32 start_flag) +{ + struct r8192_priv *priv = rtllib_priv(dev); + H2C_SITESURVEY_PARA *SiteSurveyPara; + + if (!priv->scan_cmd) { + priv->scan_cmd = kmalloc(sizeof(H2C_SITESURVEY_PARA) + + RTL_MAX_SCAN_SIZE, GFP_KERNEL); + if (!priv->scan_cmd) { + printk("----------->%s() Error!!!\n", __func__); + return; + } + } + + SiteSurveyPara = priv->scan_cmd; + memset(SiteSurveyPara, 0, sizeof(struct _H2C_SITESURVEY_PARA) + RTL_MAX_SCAN_SIZE); + + if(start_flag){ + struct sk_buff *skb = rtllib_probe_req(priv->rtllib); + cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8); + + + tcb_desc->queue_index = MGNT_QUEUE; + tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(priv->rtllib); + tcb_desc->RATRIndex = 7; + tcb_desc->bTxDisableRateFallBack = 1; + tcb_desc->bTxUseDriverAssingedRate = 1; + + + SiteSurveyPara->start_flag = start_flag; + SiteSurveyPara->probe_req_len = skb->len + sizeof(tx_desc_fw); + + SiteSurveyPara->desc.MacID = 0; + SiteSurveyPara->desc.TXHT = (tcb_desc->data_rate&0x80)?1:0; + SiteSurveyPara->desc.TxRate = MRateToHwRate8192SE(dev,tcb_desc->data_rate); + SiteSurveyPara->desc.TxShort = rtl8192se_QueryIsShort(((tcb_desc->data_rate&0x80)?1:0), MRateToHwRate8192SE(dev,tcb_desc->data_rate), tcb_desc); + + SiteSurveyPara->desc.AggEn = 0; + SiteSurveyPara->desc.Seq = 0; + SiteSurveyPara->desc.RTSEn = (tcb_desc->bRTSEnable && tcb_desc->bCTSEnable==false)?1:0; + SiteSurveyPara->desc.CTS2Self = (tcb_desc->bCTSEnable)?1:0; + SiteSurveyPara->desc.RTSSTBC = (tcb_desc->bRTSSTBC)?1:0; + SiteSurveyPara->desc.RTSHT = (tcb_desc->rts_rate&0x80)?1:0; + SiteSurveyPara->desc.RTSRate = MRateToHwRate8192SE(dev,tcb_desc->rts_rate); + SiteSurveyPara->desc.RTSRate = MRateToHwRate8192SE(dev,MGN_24M); + SiteSurveyPara->desc.RTSBW = 0; + SiteSurveyPara->desc.RTSSC = tcb_desc->RTSSC; + SiteSurveyPara->desc.RTSShort = (SiteSurveyPara->desc.RTSHT==0)?(tcb_desc->bRTSUseShortPreamble?1:0):(tcb_desc->bRTSUseShortGI?1:0); + + if(priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40){ + if(tcb_desc->bPacketBW) { + SiteSurveyPara->desc.TxBw = 1; + SiteSurveyPara->desc.TXSC = 0; + } else { + SiteSurveyPara->desc.TxBw = 0; + SiteSurveyPara->desc.TXSC = priv->nCur40MhzPrimeSC; + } + } else { + SiteSurveyPara->desc.TxBw = 0; + SiteSurveyPara->desc.TXSC = 0; + } + + SiteSurveyPara->desc.LINIP = 0; + SiteSurveyPara->desc.Offset = 32; + SiteSurveyPara->desc.PktSize = (u16)skb->len; + + SiteSurveyPara->desc.RaBRSRID = tcb_desc->RATRIndex; + + SiteSurveyPara->desc.PktID = 0x0; + SiteSurveyPara->desc.QueueSel = rtl8192se_MapHwQueueToFirmwareQueue(tcb_desc->queue_index, tcb_desc->priority); + + SiteSurveyPara->desc.DataRateFBLmt= 0x1F; + SiteSurveyPara->desc.DISFB = tcb_desc->bTxDisableRateFallBack; + SiteSurveyPara->desc.UserRate = tcb_desc->bTxUseDriverAssingedRate; + + + SiteSurveyPara->desc.FirstSeg = 1; + SiteSurveyPara->desc.LastSeg = 1; + + SiteSurveyPara->desc.TxBufferSize = (u16)skb->len; + + SiteSurveyPara->desc.OWN = 1; + + + memcpy(&SiteSurveyPara->probe_req[0], skb->data, (u16)skb->len); + + dev_kfree_skb_any(skb); + } else { + SiteSurveyPara->start_flag = start_flag; + SiteSurveyPara->probe_req_len = 0; + } + + FirmwareSetH2CCmd( dev ,FW_H2C_SITESURVEY, (u8*)SiteSurveyPara); +} + +int rtl8192se_send_scan_cmd(struct net_device *dev, bool start) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if(start){ + priv->rtllib->scan_watch_dog =0; +#if 0 + queue_delayed_work_rsl(priv->priv_wq,&priv->hw_scan_simu_wq,0); +#else + rtl8192se_set_scan_cmd(dev, start); +#endif + } else { +#if 0 + rtl8192se_rx_surveydone_cmd(dev); +#else + rtl8192se_set_scan_cmd(dev, start); +#endif + } + return true; +} +#endif + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_firmware.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_firmware.h @@ -0,0 +1,419 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef __INC_FIRMWARE_H +#define __INC_FIRMWARE_H + +#include "r8192S_def.h" + +#define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000 +#define RTL8190_CPU_START_OFFSET 0x80 +#define MAX_FIRMWARE_CODE_SIZE 0xFF00 + +#define H2C_TX_CMD_HDR_LEN 8 + +#define RTL8192S_FW_PKT_FRAG_SIZE 0x4000 + +#ifdef RTL8192SE +#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) 4*(v/4) - 8 +#else +#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4*(v/4) - 8 - USB_HWDESC_HEADER_LEN) +#endif + +typedef enum _DESC_PACKET_TYPE{ + DESC_PACKET_TYPE_INIT = 0, + DESC_PACKET_TYPE_NORMAL = 1, +}DESC_PACKET_TYPE; + + +#ifdef RTL8192S +typedef enum _firmware_init_step{ + FW_INIT_STEP0_IMEM = 0, + FW_INIT_STEP1_MAIN = 1, + FW_INIT_STEP2_DATA = 2, +}firmware_init_step_e; +#else +typedef enum _firmware_init_step{ + FW_INIT_STEP0_BOOT = 0, + FW_INIT_STEP1_MAIN = 1, + FW_INIT_STEP2_DATA = 2, +}firmware_init_step_e; +#endif + +typedef enum _firmware_source{ + FW_SOURCE_IMG_FILE = 0, + FW_SOURCE_HEADER_FILE = 1, +}firmware_source_e, *pfirmware_source_e; + +typedef enum _opt_rst_type{ + OPT_SYSTEM_RESET = 0, + OPT_FIRMWARE_RESET = 1, +}opt_rst_type_e; + +typedef enum _FIRMWARE_STATUS{ + FW_STATUS_0_INIT = 0, + FW_STATUS_1_MOVE_BOOT_CODE = 1, + FW_STATUS_2_MOVE_MAIN_CODE = 2, + FW_STATUS_3_TURNON_CPU = 3, + FW_STATUS_4_MOVE_DATA_CODE = 4, + FW_STATUS_5_READY = 5, +}FIRMWARE_STATUS; + +typedef enum _H2C_CMD{ + FW_H2C_SETPWRMODE = 0, + FW_H2C_JOINBSSRPT = 1, + FW_H2C_WoWLAN_UPDATE_GTK = 2, + FW_H2C_WoWLAN_UPDATE_IV = 3, + FW_H2C_WoWLAN_OFFLOAD = 4, + FW_H2C_SITESURVEY=5, +}H2C_CMD; + + typedef struct _H2C_SETPWRMODE_PARM { + u8 mode; + u8 flag_low_traffic_en; + u8 flag_lpnav_en; + u8 flag_rf_low_snr_en; + u8 flag_dps_en; + u8 bcn_rx_en; + u8 bcn_pass_cnt; + u8 bcn_to; // beacon TO (ms). ¡§=0¡¨ no limit. + u16 bcn_itv; + u8 app_itv; + u8 awake_bcn_itvl; + u8 smart_ps; + u8 bcn_pass_period; + }H2C_SETPWRMODE_PARM, *PH2C_SETPWRMODE_PARM; + +typedef struct _H2C_JOINBSSRPT_PARM { + u8 OpMode; + u8 Ps_Qos_Info; + u8 Bssid[6]; + u16 BcnItv; + u16 Aid; +}H2C_JOINBSSRPT_PARM, *PH2C_JOINBSSRPT_PARM; + +typedef struct _H2C_WPA_PTK { + u8 kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */ + u8 kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */ + u8 tk1[16]; /* Temporal Key 1 (TK1) */ + union { + u8 tk2[16]; + struct { + u8 tx_mic_key[8]; + u8 rx_mic_key[8]; + }Athu; + }U; +}H2C_WPA_PTK; + +typedef struct _H2C_WPA_TWO_WAY_PARA{ + u8 pairwise_en_alg; + u8 group_en_alg; + H2C_WPA_PTK wpa_ptk_value; +}H2C_WPA_TWO_WAY_PARA, *PH2C_WPA_TWO_WAY_PARA; + +typedef struct _tx_desc_8192se_fw{ + + u32 PktSize:16; + u32 Offset:8; + u32 Type:2; + u32 LastSeg:1; + u32 FirstSeg:1; + u32 LINIP:1; + u32 AMSDU:1; + u32 GF:1; + u32 OWN:1; + + u32 MacID:5; + u32 MoreData:1; + u32 MoreFrag:1; + u32 PIFS:1; + u32 QueueSel:5; + u32 AckPolicy:2; + u32 NoACM:1; + u32 NonQos:1; + u32 KeyID:2; + u32 OUI:1; + u32 PktType:1; + u32 EnDescID:1; + u32 SecType:2; + u32 HTC:1; + u32 WDS:1; + u32 PktOffset:5; + u32 HWPC:1; + + u32 DataRetryLmt:6; + u32 RetryLmtEn:1; + u32 TSFL:5; + u32 RTSRC:6; + u32 DATARC:6; + + u32 Rsvd1:5; + u32 AggEn:1; + u32 BK:1; + u32 OwnMAC:1; + + u32 NextHeadPage:8; + u32 TailPage:8; + u32 Seq:12; + u32 Frag:4; + + u32 RTSRate:6; + u32 DisRTSFB:1; + u32 RTSRateFBLmt:4; + u32 CTS2Self:1; + u32 RTSEn:1; + u32 RaBRSRID:3; + u32 TXHT:1; + u32 TxShort:1; + u32 TxBw:1; + u32 TXSC:2; + u32 STBC:2; + u32 RD:1; + u32 RTSHT:1; + u32 RTSShort:1; + u32 RTSBW:1; + u32 RTSSC:2; + u32 RTSSTBC:2; + u32 UserRate:1; + + u32 PktID:9; + u32 TxRate:6; + u32 DISFB:1; + u32 DataRateFBLmt:5; + u32 TxAGC:11; + + u32 IPChkSum:16; + u32 TCPChkSum:16; + + u32 TxBufferSize:16; + u32 IPHdrOffset:8; + u32 Rsvd3:7; + u32 TCPEn:1; +} tx_desc_fw, *ptx_desc_fw; + +typedef struct _H2C_SITESURVEY_PARA { + u32 start_flag; + u32 probe_req_len; + tx_desc_fw desc; + u8 probe_req[0]; +}H2C_SITESURVEY_PARA, *PH2C_SITESURVEY_PARA; + + typedef enum _FIRMWARE_H2C_CMD{ + H2C_Read_MACREG_CMD , /*0*/ + H2C_Write_MACREG_CMD , + H2C_ReadBB_CMD , + H2C_WriteBB_CMD , + H2C_ReadRF_CMD , + H2C_WriteRF_CMD , /*5*/ + H2C_Read_EEPROM_CMD , + H2C_Write_EEPROM_CMD , + H2C_Read_EFUSE_CMD , + H2C_Write_EFUSE_CMD , + H2C_Read_CAM_CMD , /*10*/ + H2C_Write_CAM_CMD , + H2C_setBCNITV_CMD, + H2C_setMBIDCFG_CMD, + H2C_JoinBss_CMD , + H2C_DisConnect_CMD, /*15*/ + H2C_CreateBss_CMD , + H2C_SetOpMode_CMD, + H2C_SiteSurvey_CMD, + H2C_SetAuth_CMD, + H2C_SetKey_CMD , /*20*/ + H2C_SetStaKey_CMD , + H2C_SetAssocSta_CMD, + H2C_DelAssocSta_CMD , + H2C_SetStaPwrState_CMD , + H2C_SetBasicRate_CMD , /*25*/ + H2C_GetBasicRate_CMD , + H2C_SetDataRate_CMD , + H2C_GetDataRate_CMD , + H2C_SetPhyInfo_CMD , + H2C_GetPhyInfo_CMD , /*30*/ + H2C_SetPhy_CMD , + H2C_GetPhy_CMD , + H2C_readRssi_CMD , + H2C_readGain_CMD , + H2C_SetAtim_CMD , /*35*/ + H2C_SetPwrMode_CMD , + H2C_JoinbssRpt_CMD, + H2C_SetRaTable_CMD , + H2C_GetRaTable_CMD , + H2C_GetCCXReport_CMD, /*40*/ + H2C_GetDTMReport_CMD, + H2C_GetTXRateStatistics_CMD, + H2C_SetUsbSuspend_CMD, + H2C_SetH2cLbk_CMD , + H2C_tmp1 , /*45*/ + H2C_WoWLAN_UPDATE_GTK_CMD , + H2C_WoWLAN_FW_OFFLOAD , + H2C_tmp2 , + H2C_tmp3 , + H2C_WoWLAN_UPDATE_IV_CMD , /*50*/ + H2C_tmp4, + MAX_H2CCMD /*52*/ +}FIRMWARE_H2C_CMD; + + +typedef struct _RT_8192S_FIRMWARE_PRIV { + + u8 signature_0; + u8 signature_1; + u8 hci_sel; + u8 chip_version; + u8 customer_ID_0; + u8 customer_ID_1; + u8 rf_config; + u8 usb_ep_num; + + u8 regulatory_class_0; + u8 regulatory_class_1; + u8 regulatory_class_2; + u8 regulatory_class_3; + u8 rfintfs; + u8 def_nettype; + u8 rsvd010; + u8 rsvd011; + + + u8 lbk_mode; + u8 mp_mode; + u8 rsvd020; + u8 rsvd021; + u8 rsvd022; + u8 rsvd023; + u8 rsvd024; + u8 rsvd025; + + u8 qos_en; + u8 bw_40MHz_en; + u8 AMSDU2AMPDU_en; + u8 AMPDU_en; + u8 rate_control_offload; + u8 aggregation_offload; + u8 rsvd030; + u8 rsvd031; + + + unsigned char beacon_offload; + unsigned char MLME_offload; + unsigned char hwpc_offload; + unsigned char tcp_checksum_offload; + unsigned char tcp_offload; + unsigned char ps_control_offload; + unsigned char WWLAN_offload; + unsigned char rsvd040; + + u8 tcp_tx_frame_len_L; + u8 tcp_tx_frame_len_H; + u8 tcp_rx_frame_len_L; + u8 tcp_rx_frame_len_H; + u8 rsvd050; + u8 rsvd051; + u8 rsvd052; + u8 rsvd053; +}RT_8192S_FIRMWARE_PRIV, *PRT_8192S_FIRMWARE_PRIV; + +typedef struct _RT_8192S_FIRMWARE_HDR { + + u16 Signature; + u16 Version; + u32 DMEMSize; + + + u32 IMG_IMEM_SIZE; + u32 IMG_SRAM_SIZE; + + u32 FW_PRIV_SIZE; + u32 Rsvd0; + + u32 Rsvd1; + u32 Rsvd2; + + RT_8192S_FIRMWARE_PRIV FWPriv; + +}RT_8192S_FIRMWARE_HDR, *PRT_8192S_FIRMWARE_HDR; + +#define RT_8192S_FIRMWARE_HDR_SIZE 80 +#define RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE 32 + +typedef enum _FIRMWARE_8192S_STATUS{ + FW_STATUS_INIT = 0, + FW_STATUS_LOAD_IMEM = 1, + FW_STATUS_LOAD_EMEM = 2, + FW_STATUS_LOAD_DMEM = 3, + FW_STATUS_READY = 4, +}FIRMWARE_8192S_STATUS; + +typedef struct _rt_firmware{ + firmware_source_e eFWSource; + PRT_8192S_FIRMWARE_HDR pFwHeader; + FIRMWARE_8192S_STATUS FWStatus; + u16 FirmwareVersion; + u8 FwIMEM[RTL8190_MAX_FIRMWARE_CODE_SIZE]; + u8 FwEMEM[RTL8190_MAX_FIRMWARE_CODE_SIZE]; + u32 FwIMEMLen; + u32 FwEMEMLen; + u8 szFwTmpBuffer[164000]; + u32 szFwTmpBufferLen; + u16 CmdPacketFragThresold; +}rt_firmware, *prt_firmware; + +#define FW_DIG_ENABLE_CTL BIT0 +#define FW_HIGH_PWR_ENABLE_CTL BIT1 +#define FW_SS_CTL BIT2 +#define FW_RA_INIT_CTL BIT3 +#define FW_RA_BG_CTL BIT4 +#define FW_RA_N_CTL BIT5 +#define FW_PWR_TRK_CTL BIT6 +#define FW_IQK_CTL BIT7 +#define FW_FA_CTL BIT8 +#define FW_DRIVER_CTRL_DM_CTL BIT9 +#define FW_PAPE_CTL_BY_SW_HW BIT10 +#define FW_DISABLE_ALL_DM 0 + +#define FW_PWR_TRK_PARAM_CLR 0x0000ffff +#define FW_RA_PARAM_CLR 0xffff0000 + +#define FW_CMD_IO_CLR(priv, _Bit) \ + udelay(1000); \ + priv->FwCmdIOMap &= (~_Bit); + +#define FW_CMD_IO_UPDATE(priv, _val) \ + priv->FwCmdIOMap = _val; + +#define FW_CMD_IO_SET(priv, _val) \ + write_nic_word(priv->rtllib->dev, LBUS_MON_ADDR, (u16)_val); \ + FW_CMD_IO_UPDATE(priv, _val);\ + +#define FW_CMD_PARA_SET(priv, _val) \ + write_nic_dword(priv->rtllib->dev, LBUS_ADDR_MASK, _val); \ + priv->FwCmdIOParam = _val; + +#define FW_CMD_IO_QUERY(priv) (u16)(priv->FwCmdIOMap) +#define FW_CMD_IO_PARA_QUERY(priv) ((u32)(priv->FwCmdIOParam)) + +bool FirmwareEnableCPU(struct net_device *dev); +bool FirmwareCheckReady(struct net_device *dev, u8 LoadFWStatus); + +bool FirmwareDownload92S(struct net_device *dev); +int rtl8192se_send_scan_cmd(struct net_device *dev, bool start); + +void rtl8192se_dump_skb_data(struct sk_buff *skb); +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hw.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_hw.h @@ -0,0 +1,1072 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef __INC_HAL8192SREG_H +#define __INC_HAL8192SREG_H + + +#if 0 +typedef enum _RT_RF_TYPE_DEF +{ + RF_1T2R = 0, + RF_2T4R, + RF_2T2R, + RF_1T1R, + RF_2T2R_GREEN, + RF_819X_MAX_TYPE +}RT_RF_TYPE_DEF; +#endif + +#define SYS_ISO_CTRL 0x0000 +#define SYS_FUNC_EN 0x0002 +#define PMC_FSM 0x0004 +#define SYS_CLKR 0x0008 +#define EPROM_CMD 0x000A +#define EE_VPD 0x000C +#define AFE_MISC 0x0010 +#define SPS0_CTRL 0x0011 +#define SPS1_CTRL 0x0018 +#define RF_CTRL 0x001F +#define LDOA15_CTRL 0x0020 +#define LDOV12D_CTRL 0x0021 +#define LDOHCI12_CTRL 0x0022 +#define LDO_USB_SDIO 0x0023 +#define LPLDO_CTRL 0x0024 +#define AFE_XTAL_CTRL 0x0026 +#define AFE_PLL_CTRL 0x0028 +#define EFUSE_CTRL 0x0030 +#define EFUSE_TEST 0x0034 +#define PWR_DATA 0x0038 +#define DBG_PORT 0x003A +#define DPS_TIMER 0x003C +#define RCLK_MON 0x003E + +#define CMDR 0x0040 +#define TXPAUSE 0x0042 +#define LBKMD_SEL 0x0043 +#define TCR 0x0044 +#define RCR 0x0048 +#define MSR 0x004C +#define SYSF_CFG 0x004D +#define RX_PKY_LIMIT 0x004E +#define MBIDCTRL 0x004F + +#define MACIDR 0x0050 +#define MACIDR0 0x0050 +#define MACIDR4 0x0054 +#define BSSIDR 0x0058 +#define HWVID 0x005E +#define MAR 0x0060 +#define MBIDCAMCONTENT 0x0068 +#define MBIDCAMCFG 0x0070 +#define BUILDTIME 0x0074 +#define BUILDUSER 0x0078 + +#define IDR0 MACIDR0 +#define IDR4 MACIDR4 + +#define TSFR 0x0080 +#define SLOT_TIME 0x0089 +#define USTIME 0x008A +#define SIFS_CCK 0x008C +#define SIFS_OFDM 0x008E +#define PIFS_TIME 0x0090 +#define ACK_TIMEOUT 0x0091 +#define EIFSTR 0x0092 +#define BCN_INTERVAL 0x0094 +#define ATIMWND 0x0096 +#define BCN_DRV_EARLY_INT 0x0098 +#define BCN_DMATIME 0x009A +#define BCN_ERR_THRESH 0x009C +#define MLT 0x009D +#define RSVD_MAC_TUNE_US 0x009E + +#define RQPN 0x00A0 +#define RQPN1 0x00A0 +#define RQPN2 0x00A1 +#define RQPN3 0x00A2 +#define RQPN4 0x00A3 +#define RQPN5 0x00A4 +#define RQPN6 0x00A5 +#define RQPN7 0x00A6 +#define RQPN8 0x00A7 +#define RQPN9 0x00A8 +#define RQPN10 0x00A9 +#define LD_RQPN 0x00AB +#define RXFF_BNDY 0x00AC +#define RXRPT_BNDY 0x00B0 +#define TXPKTBUF_PGBNDY 0x00B4 +#define PBP 0x00B5 +#define RXDRVINFO_SZ 0x00B6 +#define TXFF_STATUS 0x00B7 +#define RXFF_STATUS 0x00B8 +#define TXFF_EMPTY_TH 0x00B9 +#define SDIO_RX_BLKSZ 0x00BC +#define RXDMA 0x00BD +#define RXPKT_NUM 0x00BE +#define C2HCMD_UDT_SIZE 0x00C0 +#define C2HCMD_UDT_ADDR 0x00C2 +#define FIFOPAGE1 0x00C4 +#define FIFOPAGE2 0x00C8 +#define FIFOPAGE3 0x00CC +#define FIFOPAGE4 0x00D0 +#define FIFOPAGE5 0x00D4 +#define FW_RSVD_PG_CRTL 0x00D8 +#define RXDMA_AGG_PG_TH 0x00D9 +#define TXDESC_MSK 0x00DC +#define TXRPTFF_RDPTR 0x00E0 +#define TXRPTFF_WTPTR 0x00E4 +#define C2HFF_RDPTR 0x00E8 +#define C2HFF_WTPTR 0x00EC +#define RXFF0_RDPTR 0x00F0 +#define RXFF0_WTPTR 0x00F4 +#define RXFF1_RDPTR 0x00F8 +#define RXFF1_WTPTR 0x00FC +#define RXRPT0_RDPTR 0x0100 +#define RXRPT0_WTPTR 0x0104 +#define RXRPT1_RDPTR 0x0108 +#define RXRPT1_WTPTR 0x010C +#define RX0_UDT_SIZE 0x0110 +#define RX1PKTNUM 0x0114 +#define RXFILTERMAP 0x0116 +#define RXFILTERMAP_GP1 0x0118 +#define RXFILTERMAP_GP2 0x011A +#define RXFILTERMAP_GP3 0x011C +#define BCNQ_CTRL 0x0120 +#define MGTQ_CTRL 0x0124 +#define HIQ_CTRL 0x0128 +#define VOTID7_CTRL 0x012c +#define VOTID6_CTRL 0x0130 +#define VITID5_CTRL 0x0134 +#define VITID4_CTRL 0x0138 +#define BETID3_CTRL 0x013c +#define BETID0_CTRL 0x0140 +#define BKTID2_CTRL 0x0144 +#define BKTID1_CTRL 0x0148 +#define CMDQ_CTRL 0x014c +#define TXPKT_NUM_CTRL 0x0150 +#define TXQ_PGADD 0x0152 +#define TXFF_PG_NUM 0x0154 +#define TRXDMA_STATUS 0x0156 + +#define INIMCS_SEL 0x0160 +#define TX_RATE_REG INIMCS_SEL +#define INIRTSMCS_SEL 0x0180 +#define RRSR 0x0181 +#define ARFR0 0x0184 +#define ARFR1 0x0188 +#define ARFR2 0x018C +#define ARFR3 0x0190 +#define ARFR4 0x0194 +#define ARFR5 0x0198 +#define ARFR6 0x019C +#define ARFR7 0x01A0 +#define AGGLEN_LMT_H 0x01A7 +#define AGGLEN_LMT_L 0x01A8 +#define DARFRC 0x01B0 +#define RARFRC 0x01B8 +#define MCS_TXAGC 0x01C0 +#define CCK_TXAGC 0x01C8 + +#define EDCAPARA_VO 0x01D0 +#define EDCAPARA_VI 0x01D4 +#define EDCAPARA_BE 0x01D8 +#define EDCAPARA_BK 0x01DC +#define BCNTCFG 0x01E0 +#define CWRR 0x01E2 +#define ACMAVG 0x01E4 +#define AcmHwCtrl 0x01E7 +#define VO_ADMTM 0x01E8 +#define VI_ADMTM 0x01EC +#define BE_ADMTM 0x01F0 +#define RETRY_LIMIT 0x01F4 +#define SG_RATE 0x01F6 + +#define NAV_CTRL 0x0200 +#define BW_OPMODE 0x0203 +#define BACAMCMD 0x0204 +#define BACAMCONTENT 0x0208 + +#define LBDLY 0x0210 +#define FWDLY 0x0211 +#define HWPC_RX_CTRL 0x0218 +#define MQIR 0x0220 +#define MAIR 0x0222 +#define MSIR 0x0224 +#define CLM_RESULT 0x0227 +#define NHM_RPI_CNT 0x0228 +#define RXERR_RPT 0x0230 +#define NAV_PROT_LEN 0x0234 +#define CFEND_TH 0x0236 +#define AMPDU_MIN_SPACE 0x0237 +#define TXOP_STALL_CTRL 0x0238 + +#define RWCAM 0x0240 +#define WCAMI 0x0244 +#define RCAMO 0x0248 +#define CAMDBG 0x024C +#define SECR 0x0250 + +#define WOW_CTRL 0x0260 +#define PSSTATUS 0x0261 +#define PSSWITCH 0x0262 +#define MIMOPS_WAIT_PERIOD 0x0263 +#define LPNAV_CTRL 0x0264 +#define WFM0 0x0270 +#define WFM1 0x0280 +#define WFM2 0x0290 +#define WFM3 0x02A0 +#define WFM4 0x02B0 +#define WFM5 0x02C0 +#define WFCRC 0x02D0 +#define FW_RPT_REG 0x02c4 + +#define PSTIME 0x02E0 +#define TIMER0 0x02E4 +#define TIMER1 0x02E8 +#define GPIO_CTRL 0x02EC +#define GPIO_IN 0x02EC +#define GPIO_OUT 0x02ED +#define GPIO_IO_SEL 0x02EE +#define GPIO_MOD 0x02EF +#define GPIO_INTCTRL 0x02F0 +#define MAC_PINMUX_CFG 0x02F1 +#define LEDCFG 0x02F2 +#define PHY_REG 0x02F3 +#define PHY_REG_DATA 0x02F4 +#define EFUSE_CLK 0x02F8 + +#define INTA_MASK 0x0300 +#define ISR 0x0308 + +#define DBG_PORT_SWITCH 0x003A +#define BIST 0x0310 +#define DBS 0x0314 +#define CPUINST 0x0318 +#define CPUCAUSE 0x031C +#define LBUS_ERR_ADDR 0x0320 +#define LBUS_ERR_CMD 0x0324 +#define LBUS_ERR_DATA_L 0x0328 +#define LBUS_ERR_DATA_H 0x032C +#define LX_EXCEPTION_ADDR 0x0330 +#define WDG_CTRL 0x0334 +#define INTMTU 0x0338 +#define INTM 0x033A +#define FDLOCKTURN0 0x033C +#define FDLOCKTURN1 0x033D +#define TRXPKTBUF_DBG_DATA 0x0340 +#define TRXPKTBUF_DBG_CTRL 0x0348 +#define DPLL 0x034A +#define CBUS_ERR_ADDR 0x0350 +#define CBUS_ERR_CMD 0x0354 +#define CBUS_ERR_DATA_L 0x0358 +#define CBUS_ERR_DATA_H 0x035C +#define USB_SIE_INTF_ADDR 0x0360 +#define USB_SIE_INTF_WD 0x0361 +#define USB_SIE_INTF_RD 0x0362 +#define USB_SIE_INTF_CTRL 0x0363 +#define LBUS_MON_ADDR 0x0364 +#define LBUS_ADDR_MASK 0x0368 + + +#define TPPoll 0x0500 +#define PM_CTRL 0x0502 +#define PCIF 0x0503 + +#define THPDA 0x0514 +#define TMDA 0x0518 +#define TCDA 0x051C +#define HDA 0x0520 +#define TVODA 0x0524 +#define TVIDA 0x0528 +#define TBEDA 0x052C +#define TBKDA 0x0530 +#define TBDA 0x0534 +#define RCDA 0x0538 +#define RDQDA 0x053C +#define DBI_WDATA 0x0540 +#define DBI_RDATA 0x0544 +#define DBI_CTRL 0x0548 +#define MDIO_DATA 0x0550 +#define MDIO_CTRL 0x0554 +#define PCI_RPWM 0x0561 +#define PCI_CPWM 0x0563 + + +#define PHY_CCA 0x803 + + +#define USB_RX_AGG_TIMEOUT 0xFE5B + +#define FW_OFFLOAD_EN BIT7 + +#define MAX_MSS_DENSITY_2T 0x13 +#define MAX_MSS_DENSITY_1T 0x0A + +#define RXDMA_AGG_EN BIT7 + +#define RXDMA_AGG_TIMEOUT_DISABLE 0x00 +#define RXDMA_AGG_TIMEOUT_17MS 0x01 +#define RXDMA_AGG_TIMEOUT_17_2_MS 0x02 +#define RXDMA_AGG_TIMEOUT_17_4_MS 0x04 +#define RXDMA_AGG_TIMEOUT_17_10_MS 0x0A + +#define InvalidBBRFValue 0x12345678 + +#define USB_RPWM 0xFE58 + +#ifdef RTL8192SE +#define RPWM PCI_RPWM +#endif +#ifdef RTL8192SU +#define RPWM USB_RPWM +#endif + +#if 1 +#define AFR 0x010 +#define BCN_TCFG 0x062 +#define RATR0 0x320 +#endif +#define UnusedRegister 0x0320 +#define PSR UnusedRegister +#define DCAM UnusedRegister +#define BBAddr UnusedRegister +#define PhyDataR UnusedRegister +#define UFWP UnusedRegister + + + +#define ISO_MD2PP BIT0 +#define ISO_PA2PCIE BIT3 +#define ISO_PLL2MD BIT4 +#define ISO_PWC_DV2RP BIT11 +#define ISO_PWC_RV2RP BIT12 + +#define FEN_MREGEN BIT15 +#define FEN_DCORE BIT11 +#define FEN_CPUEN BIT10 + +#define PAD_HWPD_IDN BIT22 + +#define SYS_CLKSEL_80M BIT0 +#define SYS_PS_CLKSEL BIT1 +#define SYS_CPU_CLKSEL BIT2 +#define SYS_MAC_CLK_EN BIT11 +#define SYS_SWHW_SEL BIT14 +#define SYS_FWHW_SEL BIT15 + + +#define CmdEEPROM_En BIT5 +#define CmdEERPOMSEL BIT4 +#define Cmd9346CR_9356SEL BIT4 +#define AutoLoadEEPROM (CmdEEPROM_En|CmdEERPOMSEL) +#define AutoLoadEFUSE CmdEEPROM_En +#define EPROM_CMD_OPERATING_MODE_SHIFT 6 +#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) +#define EPROM_CMD_CONFIG 0x3 +#define EPROM_CMD_NORMAL 0 +#define EPROM_CMD_LOAD 1 +#define EPROM_CMD_PROGRAM 2 +#define EPROM_CS_SHIFT 3 +#define EPROM_CK_SHIFT 2 +#define EPROM_W_SHIFT 1 +#define EPROM_R_SHIFT 0 + +#define AFE_MBEN BIT1 +#define AFE_BGEN BIT0 + +#define SPS1_SWEN BIT1 +#define SPS1_LDEN BIT0 + +#define RF_EN BIT0 +#define RF_RSTB BIT1 +#define RF_SDMRSTB BIT2 + +#define LDA15_EN BIT0 + +#define LDV12_EN BIT0 +#define LDV12_SDBY BIT1 + +#define XTAL_GATE_AFE BIT10 + +#define APLL_EN BIT0 + +#define AFR_CardBEn BIT0 +#define AFR_CLKRUN_SEL BIT1 +#define AFR_FuncRegEn BIT2 + +#define APSDOFF_STATUS BIT15 +#define APSDOFF BIT14 +#define BBRSTn BIT13 +#define BB_GLB_RSTn BIT12 +#define SCHEDULE_EN BIT10 +#define MACRXEN BIT9 +#define MACTXEN BIT8 +#define DDMA_EN BIT7 +#define FW2HW_EN BIT6 +#define RXDMA_EN BIT5 +#define TXDMA_EN BIT4 +#define HCI_RXDMA_EN BIT3 +#define HCI_TXDMA_EN BIT2 + +#define StopHCCA BIT6 +#define StopHigh BIT5 +#define StopMgt BIT4 +#define StopVO BIT3 +#define StopVI BIT2 +#define StopBE BIT1 +#define StopBK BIT0 + +#define LBK_NORMAL 0x00 +#define LBK_MAC_LB (BIT0|BIT1|BIT3) +#define LBK_MAC_DLB (BIT0|BIT1) +#define LBK_DMA_LB (BIT0|BIT1|BIT2) + +#define TCP_OFDL_EN BIT25 +#define HWPC_TX_EN BIT24 +#define TXDMAPRE2FULL BIT23 +#define DISCW BIT20 +#define TCRICV BIT19 +#define CfendForm BIT17 +#define TCRCRC BIT16 +#define FAKE_IMEM_EN BIT15 +#define TSFRST BIT9 +#define TSFEN BIT8 +#define FWALLRDY (BIT0|BIT1|BIT2|BIT3|BIT4|BIT5|BIT6|BIT7) +#define FWRDY BIT7 +#define BASECHG BIT6 +#define IMEM BIT5 +#define DMEM_CODE_DONE BIT4 +#define EXT_IMEM_CHK_RPT BIT3 +#define EXT_IMEM_CODE_DONE BIT2 +#define IMEM_CHK_RPT BIT1 +#define IMEM_CODE_DONE BIT0 +#define IMEM_CODE_DONE BIT0 +#define IMEM_CHK_RPT BIT1 +#define EMEM_CODE_DONE BIT2 +#define EMEM_CHK_RPT BIT3 +#define DMEM_CODE_DONE BIT4 +#define IMEM_RDY BIT5 +#define BASECHG BIT6 +#define FWRDY BIT7 +#define LOAD_FW_READY (IMEM_CODE_DONE|IMEM_CHK_RPT|EMEM_CODE_DONE|\ + EMEM_CHK_RPT|DMEM_CODE_DONE|IMEM_RDY|BASECHG|\ + FWRDY) +#define TCR_TSFEN BIT8 +#define TCR_TSFRST BIT9 +#define TCR_FAKE_IMEM_EN BIT15 +#define TCR_CRC BIT16 +#define TCR_ICV BIT19 +#define TCR_DISCW BIT20 +#define TCR_HWPC_TX_EN BIT24 +#define TCR_TCP_OFDL_EN BIT25 +#define TXDMA_INIT_VALUE (IMEM_CHK_RPT|EXT_IMEM_CHK_RPT) + +#define RCR_APPFCS BIT31 +#define RCR_DIS_ENC_2BYTE BIT30 +#define RCR_DIS_AES_2BYTE BIT29 +#define RCR_HTC_LOC_CTRL BIT28 +#define RCR_ENMBID BIT27 +#define RCR_RX_TCPOFDL_EN BIT26 +#define RCR_APP_PHYST_RXFF BIT25 +#define RCR_APP_PHYST_STAFF BIT24 +#define RCR_CBSSID BIT23 +#define RCR_APWRMGT BIT22 +#define RCR_ADD3 BIT21 +#define RCR_AMF BIT20 +#define RCR_ACF BIT19 +#define RCR_ADF BIT18 +#define RCR_APP_MIC BIT17 +#define RCR_APP_ICV BIT16 +#define RCR_RXFTH BIT13 +#define RCR_AICV BIT12 +#define RCR_RXDESC_LK_EN BIT11 +#define RCR_APP_BA_SSN BIT6 +#define RCR_ACRC32 BIT5 +#define RCR_RXSHFT_EN BIT4 +#define RCR_AB BIT3 +#define RCR_AM BIT2 +#define RCR_APM BIT1 +#define RCR_AAP BIT0 +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 + +/* +Network Type +00: No link +01: Link in ad hoc network +10: Link in infrastructure network +11: AP mode +Default: 00b. +*/ +#define MSR_LINK_MASK ((1<<0)|(1<<1)) +#define MSR_LINK_MANAGED 2 +#define MSR_LINK_NONE 0 +#define MSR_LINK_SHIFT 0 +#define MSR_LINK_ADHOC 1 +#define MSR_LINK_MASTER 3 +#if 1 +#define MSR_NOLINK 0x00 +#define MSR_ADHOC 0x01 +#define MSR_INFRA 0x02 +#define MSR_AP 0x03 +#endif +#define ENUART BIT7 +#define ENJTAG BIT3 +#define BTMODE (BIT2|BIT1) +#define ENBT BIT0 + +#define ENMBID BIT7 +#define BCNUM (BIT6|BIT5|BIT4) + + +#define USTIME_EDCA 0xFF00 +#define USTIME_TSF 0x00FF + +#define SIFS_TRX 0xFF00 +#define SIFS_CTX 0x00FF + +#define ENSWBCN BIT15 +#define DRVERLY_TU 0x0FF0 +#define DRVERLY_US 0x000F +#define BCN_TCFG_CW_SHIFT 8 +#define BCN_TCFG_IFS 0 + + +#define RRSR_RSC_OFFSET 21 +#define RRSR_SHORT_OFFSET 23 +#define RRSR_RSC_BW_40M 0x600000 +#define RRSR_RSC_UPSUBCHNL 0x400000 +#define RRSR_RSC_LOWSUBCHNL 0x200000 +#define RRSR_SHORT 0x800000 +#define RRSR_1M BIT0 +#define RRSR_2M BIT1 +#define RRSR_5_5M BIT2 +#define RRSR_11M BIT3 +#define RRSR_6M BIT4 +#define RRSR_9M BIT5 +#define RRSR_12M BIT6 +#define RRSR_18M BIT7 +#define RRSR_24M BIT8 +#define RRSR_36M BIT9 +#define RRSR_48M BIT10 +#define RRSR_54M BIT11 +#define RRSR_MCS0 BIT12 +#define RRSR_MCS1 BIT13 +#define RRSR_MCS2 BIT14 +#define RRSR_MCS3 BIT15 +#define RRSR_MCS4 BIT16 +#define RRSR_MCS5 BIT17 +#define RRSR_MCS6 BIT18 +#define RRSR_MCS7 BIT19 +#define BRSR_AckShortPmb BIT23 + +#define RATR_1M 0x00000001 +#define RATR_2M 0x00000002 +#define RATR_55M 0x00000004 +#define RATR_11M 0x00000008 +#define RATR_6M 0x00000010 +#define RATR_9M 0x00000020 +#define RATR_12M 0x00000040 +#define RATR_18M 0x00000080 +#define RATR_24M 0x00000100 +#define RATR_36M 0x00000200 +#define RATR_48M 0x00000400 +#define RATR_54M 0x00000800 +#define RATR_MCS0 0x00001000 +#define RATR_MCS1 0x00002000 +#define RATR_MCS2 0x00004000 +#define RATR_MCS3 0x00008000 +#define RATR_MCS4 0x00010000 +#define RATR_MCS5 0x00020000 +#define RATR_MCS6 0x00040000 +#define RATR_MCS7 0x00080000 +#define RATR_MCS8 0x00100000 +#define RATR_MCS9 0x00200000 +#define RATR_MCS10 0x00400000 +#define RATR_MCS11 0x00800000 +#define RATR_MCS12 0x01000000 +#define RATR_MCS13 0x02000000 +#define RATR_MCS14 0x04000000 +#define RATR_MCS15 0x08000000 +#define RATE_ALL_CCK RATR_1M|RATR_2M|RATR_55M|RATR_11M +#define RATE_ALL_OFDM_AG RATR_6M|RATR_9M|RATR_12M|RATR_18M|RATR_24M|\ + RATR_36M|RATR_48M|RATR_54M +#define RATE_ALL_OFDM_1SS RATR_MCS0|RATR_MCS1|RATR_MCS2|RATR_MCS3 |\ + RATR_MCS4|RATR_MCS5|RATR_MCS6 |RATR_MCS7 +#define RATE_ALL_OFDM_2SS RATR_MCS8|RATR_MCS9 |RATR_MCS10|RATR_MCS11|\ + RATR_MCS12|RATR_MCS13|RATR_MCS14|RATR_MCS15 + +#define AC_PARAM_TXOP_LIMIT_OFFSET 16 +#define AC_PARAM_ECW_MAX_OFFSET 12 +#define AC_PARAM_ECW_MIN_OFFSET 8 +#define AC_PARAM_AIFS_OFFSET 0 + +#define AcmHw_HwEn BIT0 +#define AcmHw_BeqEn BIT1 +#define AcmHw_ViqEn BIT2 +#define AcmHw_VoqEn BIT3 +#define AcmHw_BeqStatus BIT4 +#define AcmHw_ViqStatus BIT5 +#define AcmHw_VoqStatus BIT6 + +#define RETRY_LIMIT_SHORT_SHIFT 8 +#define RETRY_LIMIT_LONG_SHIFT 0 + +#define NAV_UPPER_EN BIT16 +#define NAV_UPPER 0xFF00 +#define NAV_RTSRST 0xFF +#define BW_OPMODE_20MHZ BIT2 +#define BW_OPMODE_5G BIT1 +#define BW_OPMODE_11J BIT0 + +#define RXERR_RPT_RST BIT27 +#define RXERR_OFDM_PPDU 0 +#define RXERR_OFDM_FALSE_ALARM 1 +#define RXERR_OFDM_MPDU_OK 2 +#define RXERR_OFDM_MPDU_FAIL 3 +#define RXERR_CCK_PPDU 4 +#define RXERR_CCK_FALSE_ALARM 5 +#define RXERR_CCK_MPDU_OK 6 +#define RXERR_CCK_MPDU_FAIL 7 +#define RXERR_HT_PPDU 8 +#define RXERR_HT_FALSE_ALARM 9 +#define RXERR_HT_MPDU_TOTAL 10 +#define RXERR_HT_MPDU_OK 11 +#define RXERR_HT_MPDU_FAIL 12 +#define RXERR_RX_FULL_DROP 15 + + +#define CAM_CM_SecCAMPolling BIT31 +#define CAM_CM_SecCAMClr BIT30 +#define CAM_CM_SecCAMWE BIT16 +#define CAM_ADDR 0xFF + +#define Dbg_CAM_TXSecCAMInfo BIT31 +#define Dbg_CAM_SecKeyFound BIT30 + + +#define SCR_TxUseDK BIT0 +#define SCR_RxUseDK BIT1 +#define SCR_TxEncEnable BIT2 +#define SCR_RxDecEnable BIT3 +#define SCR_SKByA2 BIT4 +#define SCR_NoSKMC BIT5 +#define CAM_VALID BIT15 +#define CAM_NOTVALID 0x0000 +#define CAM_USEDK BIT5 + +#define CAM_NONE 0x0 +#define CAM_WEP40 0x01 +#define CAM_TKIP 0x02 +#define CAM_AES 0x04 +#define CAM_WEP104 0x05 + +#define TOTAL_CAM_ENTRY 32 +#define HALF_CAM_ENTRY 16 + +#define CAM_CONFIG_USEDK true +#define CAM_CONFIG_NO_USEDK false + +#define CAM_WRITE BIT16 +#define CAM_READ 0x00000000 +#define CAM_POLLINIG BIT31 + +#define SCR_UseDK 0x01 +#define SCR_TxSecEnable 0x02 +#define SCR_RxSecEnable 0x04 + +#define WOW_PMEN BIT0 +#define WOW_WOMEN BIT1 +#define WOW_MAGIC BIT2 +#define WOW_UWF BIT3 + +#define GPIOMUX_EN BIT3 +#define GPIOSEL_GPIO 0 +#define GPIOSEL_PHYDBG 1 +#define GPIOSEL_BT 2 +#define GPIOSEL_WLANDBG 3 +#define GPIOSEL_GPIO_MASK ~(BIT0|BIT1) + +#define HST_RDBUSY BIT0 +#define CPU_WTBUSY BIT1 + +#define IMR8190_DISABLED 0x0 +#define IMR_CPUERR BIT5 +#define IMR_ATIMEND BIT4 +#define IMR_TBDOK BIT3 +#define IMR_TBDER BIT2 +#define IMR_BCNDMAINT8 BIT1 +#define IMR_BCNDMAINT7 BIT0 +#define IMR_BCNDMAINT6 BIT31 +#define IMR_BCNDMAINT5 BIT30 +#define IMR_BCNDMAINT4 BIT29 +#define IMR_BCNDMAINT3 BIT28 +#define IMR_BCNDMAINT2 BIT27 +#define IMR_BCNDMAINT1 BIT26 +#define IMR_BCNDOK8 BIT25 +#define IMR_BCNDOK7 BIT24 +#define IMR_BCNDOK6 BIT23 +#define IMR_BCNDOK5 BIT22 +#define IMR_BCNDOK4 BIT21 +#define IMR_BCNDOK3 BIT20 +#define IMR_BCNDOK2 BIT19 +#define IMR_BCNDOK1 BIT18 +#define IMR_TIMEOUT2 BIT17 +#define IMR_TIMEOUT1 BIT16 +#define IMR_TXFOVW BIT15 +#define IMR_PSTIMEOUT BIT14 +#define IMR_BcnInt BIT13 +#define IMR_RXFOVW BIT12 +#define IMR_RDU BIT11 +#define IMR_RXCMDOK BIT10 +#define IMR_BDOK BIT9 +#define IMR_HIGHDOK BIT8 +#define IMR_COMDOK BIT7 +#define IMR_MGNTDOK BIT6 +#define IMR_HCCADOK BIT5 +#define IMR_BKDOK BIT4 +#define IMR_BEDOK BIT3 +#define IMR_VIDOK BIT2 +#define IMR_VODOK BIT1 +#define IMR_ROK BIT0 + + +#define TPPoll_BKQ BIT0 +#define TPPoll_BEQ BIT1 +#define TPPoll_VIQ BIT2 +#define TPPoll_VOQ BIT3 +#define TPPoll_BQ BIT4 +#define TPPoll_CQ BIT5 +#define TPPoll_MQ BIT6 +#define TPPoll_HQ BIT7 +#define TPPoll_HCCAQ BIT8 +#define TPPoll_StopBK BIT9 +#define TPPoll_StopBE BIT10 +#define TPPoll_StopVI BIT11 +#define TPPoll_StopVO BIT12 +#define TPPoll_StopMgt BIT13 +#define TPPoll_StopHigh BIT14 +#define TPPoll_StopHCCA BIT15 +#define TPPoll_SHIFT 8 + +#define MXDMA2_16bytes 0x000 +#define MXDMA2_32bytes 0x001 +#define MXDMA2_64bytes 0x010 +#define MXDMA2_128bytes 0x011 +#define MXDMA2_256bytes 0x100 +#define MXDMA2_512bytes 0x101 +#define MXDMA2_1024bytes 0x110 +#define MXDMA2_NoLimit 0x7 + +#define MULRW_SHIFT 3 +#define MXDMA2_RX_SHIFT 4 +#define MXDMA2_TX_SHIFT 0 + +#define CCX_CMD_CLM_ENABLE BIT0 +#define CCX_CMD_NHM_ENABLE BIT1 +#define CCX_CMD_FUNCTION_ENABLE BIT8 +#define CCX_CMD_IGNORE_CCA BIT9 +#define CCX_CMD_IGNORE_TXON BIT10 +#define CCX_CLM_RESULT_READY BIT16 +#define CCX_NHM_RESULT_READY BIT16 +#define CCX_CMD_RESET 0x0 + + +#define HWSET_MAX_SIZE_92S 128 + + + +#ifdef RTL8192SE +#define RTL8190_EEPROM_ID 0x8129 +#define EEPROM_HPON 0x02 +#define EEPROM_CLK 0x06 +#define EEPROM_TESTR 0x08 + +#define EEPROM_VID 0x0A +#define EEPROM_DID 0x0C +#define EEPROM_SVID 0x0E +#define EEPROM_SMID 0x10 + +#define EEPROM_MAC_ADDR 0x12 +#define EEPROM_NODE_ADDRESS_BYTE_0 0x12 + +#define EEPROM_PwDiff 0x54 + +#define EEPROM_TxPowerBase 0x50 +#define EEPROM_TX_PWR_INDEX_RANGE 28 + +#define EEPROM_TX_PWR_HT20_DIFF 0x62 +#define DEFAULT_HT20_TXPWR_DIFF 2 +#define EEPROM_TX_PWR_OFDM_DIFF 0x65 + +#define EEPROM_TxPWRGroup 0x67 +#define EEPROM_Regulatory 0x6D + +#define TX_PWR_SAFETY_CHK 0x6D +#define EEPROM_TxPwIndex_CCK_24G 0x5D +#define EEPROM_TxPwIndex_OFDM_24G 0x6B +#define EEPROM_HT2T_CH1_A 0x6c +#define EEPROM_HT2T_CH7_A 0x6d +#define EEPROM_HT2T_CH13_A 0x6e +#define EEPROM_HT2T_CH1_B 0x6f +#define EEPROM_HT2T_CH7_B 0x70 +#define EEPROM_HT2T_CH13_B 0x71 +#define EEPROM_TSSI_A 0x74 +#define EEPROM_TSSI_B 0x75 +#define EEPROM_RFInd_PowerDiff 0x76 +#define EEPROM_Default_LegacyHTTxPowerDiff 0x3 +#define EEPROM_ThermalMeter 0x77 +#define EEPROM_BLUETOOTH_COEXIST 0x78 +#define EEPROM_BLUETOOTH_TYPE 0x4f + +#define EEPROM_Optional 0x78 +#ifdef RTL8192S_WAPI_SUPPORT +#define EEPROM_WAPI_SUPPORT 0x78 +#endif +#define EEPROM_WoWLAN 0x78 + +#define EEPROM_CrystalCap 0x79 +#define EEPROM_ChannelPlan 0x7B +#define EEPROM_Version 0x7C +#define EEPROM_CustomID 0x7A +#define EEPROM_BoardType 0x7E + +#define EEPROM_Default_TSSI 0x0 +#define EEPROM_Default_TxPowerDiff 0x0 +#define EEPROM_Default_CrystalCap 0x5 +#define EEPROM_Default_BoardType 0x02 +#define EEPROM_Default_TxPower 0x1010 +#define EEPROM_Default_HT2T_TxPwr 0x10 + +#define EEPROM_Default_LegacyHTTxPowerDiff 0x3 +#define EEPROM_Default_ThermalMeter 0x12 +#define EEPROM_Default_BlueToothCoexist 0x0 +#define EEPROM_Default_BlueToothAntNum 0x0 +#define EEPROM_Default_BlueToothAntIso 0x0 +#define EEPROM_Default_BlueToothType 0x0 +#define EEPROM_Default_AntTxPowerDiff 0x0 +#define EEPROM_Default_TxPwDiff_CrystalCap 0x5 +#define EEPROM_Default_TxPowerLevel 0x22 + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_NCC 0xB +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + + +#define EEPROM_CID_DEFAULT 0x0 +#define EEPROM_CID_TOSHIBA 0x4 +#define EEPROM_CID_CCX 0x10 +#define EEPROM_CID_QMI 0x0D +#define EEPROM_CID_WHQL 0xFE + +#else +#define RTL8190_EEPROM_ID 0x8129 +#define EEPROM_HPON 0x02 +#define EEPROM_VID 0x08 +#define EEPROM_PID 0x0A +#define EEPROM_USB_OPTIONAL 0x0C +#define EEPROM_USB_PHY_PARA1 0x0D +#define EEPROM_NODE_ADDRESS_BYTE_0 0x12 +#define EEPROM_Version 0x50 +#define EEPROM_ChannelPlan 0x51 +#define EEPROM_CustomID 0x52 +#define EEPROM_SubCustomID 0x53 + +#if (EEPROM_OLD_FORMAT_SUPPORT ==1) +#define EEPROM_PwDiff 0x54 +#define EEPROM_ThermalMeter 0x55 +#define EEPROM_Reserved 0x56 +#define EEPROM_CrystalCap 0x57 +#define EEPROM_TxPowerBase 0x58 +#define EEPROM_TxPwIndex_CCK_24G 0x59 +#define EEPROM_TxPwIndex_OFDM_24G 0x67 +#define EEPROM_TSSI_A 0x75 +#define EEPROM_TSSI_B 0x76 +#define EEPROM_TxPwTkMode 0x77 +#define EEPROM_HT2T_CH1_A 0x78 +#define EEPROM_HT2T_CH7_A 0x79 +#define EEPROM_HT2T_CH13_A 0x7a +#define EEPROM_HT2T_CH1_B 0x7b +#define EEPROM_HT2T_CH7_B 0x7c +#define EEPROM_HT2T_CH13_B 0x7d +#define EEPROM_BoardType 0x7e +#else +#define EEPROM_BoardType 0x54 +#define EEPROM_TxPwIndex 0x55 +#define EEPROM_PwDiff 0x67 +#define EEPROM_ThermalMeter 0x68 +#define EEPROM_CrystalCap 0x69 +#define EEPROM_TxPowerBase 0x6a +#define EEPROM_TSSI_A 0x6b +#define EEPROM_TSSI_B 0x6c +#define EEPROM_TxPwTkMode 0x6d + +#define EEPROM_TX_PWR_HT20_DIFF 0x6e +#define DEFAULT_HT20_TXPWR_DIFF 2 +#define EEPROM_TX_PWR_OFDM_DIFF 0x71 +#define TX_PWR_SAFETY_CHK 0x79 +#endif +#define EEPROM_USB_Default_OPTIONAL_FUNC 0x8 +#define EEPROM_USB_Default_PHY_PARAM 0x0 +#define EEPROM_Default_TSSI 0x0 +#define EEPROM_Default_TxPwrTkMode 0x0 +#define EEPROM_Default_TxPowerDiff 0x0 +#define EEPROM_Default_TxPowerBase 0x0 +#define EEPROM_Default_ThermalMeter 0x7 +#define EEPROM_Default_PwDiff 0x4 +#define EEPROM_Default_CrystalCap 0x5 +#define EEPROM_Default_TxPower 0x1010 +#define EEPROM_Default_BoardType 0x02 +#define EEPROM_Default_HT2T_TxPwr 0x10 +#define EEPROM_USB_SN BIT0 +#define EEPROM_USB_REMOTE_WAKEUP BIT1 +#define EEPROM_USB_DEVICE_PWR BIT2 +#define EEPROM_EP_NUMBER (BIT3|BIT4) + + +#define EEPROM_CHANNEL_PLAN_FCC 0x0 +#define EEPROM_CHANNEL_PLAN_IC 0x1 +#define EEPROM_CHANNEL_PLAN_ETSI 0x2 +#define EEPROM_CHANNEL_PLAN_SPAIN 0x3 +#define EEPROM_CHANNEL_PLAN_FRANCE 0x4 +#define EEPROM_CHANNEL_PLAN_MKK 0x5 +#define EEPROM_CHANNEL_PLAN_MKK1 0x6 +#define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 +#define EEPROM_CHANNEL_PLAN_TELEC 0x8 +#define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 +#define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA +#define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 + +#define EEPROM_CID_DEFAULT 0x0 +#define EEPROM_CID_ALPHA 0x1 +#define EEPROM_CID_TOSHIBA 0x4 +#define EEPROM_CID_WHQL 0xFE +#endif + + +#define FW_DIG_DISABLE 0xfd00cc00 +#define FW_DIG_ENABLE 0xfd000000 +#define FW_DIG_HALT 0xfd000001 +#define FW_DIG_RESUME 0xfd000002 +#define FW_HIGH_PWR_DISABLE 0xfd000008 +#define FW_HIGH_PWR_ENABLE 0xfd000009 +#define FW_ADD_A2_ENTRY 0xfd000016 +#define FW_TXPWR_TRACK_ENABLE 0xfd000017 +#define FW_TXPWR_TRACK_DISABLE 0xfd000018 +#define FW_TXPWR_TRACK_THERMAL 0xfd000019 +#define FW_TXANT_SWITCH_ENABLE 0xfd000023 +#define FW_TXANT_SWITCH_DISABLE 0xfd000024 +#define FW_RA_INIT 0xfd000026 +#define FW_CTRL_DM_BY_DRIVER 0Xfd00002a +#define FW_RA_IOT_BG_COMB 0xfd000030 +#define FW_RA_IOT_N_COMB 0xfd000031 +#define FW_RA_REFRESH 0xfd0000a0 +#define FW_RA_UPDATE_MASK 0xfd0000a2 +#define FW_RA_DISABLE 0xfd0000a4 +#define FW_RA_ACTIVE 0xfd0000a6 +#define FW_RA_DISABLE_RSSI_MASK 0xfd0000ac +#define FW_RA_ENABLE_RSSI_MASK 0xfd0000ad +#define FW_RA_RESET 0xfd0000af +#define FW_DM_DISABLE 0xfd00aa00 +#define FW_IQK_ENABLE 0xf0000020 +#define FW_IQK_SUCCESS 0x0000dddd +#define FW_IQK_FAIL 0x0000ffff +#define FW_OP_FAILURE 0xffffffff +#define FW_TX_FEEDBACK_NONE 0xfb000000 +#define FW_TX_FEEDBACK_DTM_ENABLE (FW_TX_FEEDBACK_NONE | 0x1) +#define FW_TX_FEEDBACK_CCX_ENABLE (FW_TX_FEEDBACK_NONE | 0x2) +#define FW_BB_RESET_ENABLE 0xff00000d +#define FW_BB_RESET_DISABLE 0xff00000e +#define FW_CCA_CHK_ENABLE 0xff000011 +#define FW_CCK_RESET_CNT 0xff000013 +#define FW_LPS_ENTER 0xfe000010 +#define FW_LPS_LEAVE 0xfe000011 +#define FW_INDIRECT_READ 0xf2000000 +#define FW_INDIRECT_WRITE 0xf2000001 +#define FW_CHAN_SET 0xf3000001 + + + + + + + +#define RFPC 0x5F +#define RCR_9356SEL BIT6 +#define TCR_LRL_OFFSET 0 +#define TCR_SRL_OFFSET 8 +#define TCR_MXDMA_OFFSET 21 +#define TCR_SAT BIT24 +#define RCR_MXDMA_OFFSET 8 +#define RCR_FIFO_OFFSET 13 +#define RCR_OnlyErlPkt BIT31 +#define CWR 0xDC +#define RetryCTR 0xDE + + +#define LED1Cfg UnusedRegister +#define LED0Cfg UnusedRegister +#define GPI UnusedRegister +#define BRSR UnusedRegister +#define CPU_GEN UnusedRegister +#define SIFS UnusedRegister + +#define CPU_GEN_SYSTEM_RESET 0x00000001 + + + + +#define CCX_COMMAND_REG 0x890 +#define CLM_PERIOD_REG 0x894 +#define NHM_PERIOD_REG 0x896 +#define NHM_THRESHOLD0 0x898 +#define NHM_THRESHOLD1 0x899 +#define NHM_THRESHOLD2 0x89A +#define NHM_THRESHOLD3 0x89B +#define NHM_THRESHOLD4 0x89C +#define NHM_THRESHOLD5 0x89D +#define NHM_THRESHOLD6 0x89E +#define CLM_RESULT_REG 0x8D0 +#define NHM_RESULT_REG 0x8D4 +#define NHM_RPI_COUNTER0 0x8D8 +#define NHM_RPI_COUNTER1 0x8D9 +#define NHM_RPI_COUNTER2 0x8DA +#define NHM_RPI_COUNTER3 0x8DB +#define NHM_RPI_COUNTER4 0x8DC +#define NHM_RPI_COUNTER5 0x8DD +#define NHM_RPI_COUNTER6 0x8DE +#define NHM_RPI_COUNTER7 0x8DF + + +#define HAL_8192S_HW_GPIO_OFF_BIT BIT3 +#define HAL_8192S_HW_GPIO_OFF_MASK 0xF7 +#define HAL_8192S_HW_GPIO_WPS_BIT BIT4 + +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg.c @@ -0,0 +1,6302 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + +#ifdef RTL8192SE +#include "r8192S_hwimg.h" + +/*Created on 2010/ 4/12, 5:56*/ + +u8 Rtl8192SEFwImgArray[ImgArrayLength] = { +0x92,0x81,0x3e,0x70,0x30,0x00,0x00,0x00,0x08,0xc0,0x00,0x00,0x50,0x93,0x00,0x00, +0x30,0x00,0x00,0x00,0xc0,0x91,0x00,0x00,0x3e,0x00,0x13,0x00,0x04,0x09,0x09,0x44, +0x92,0x81,0x01,0x01,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x25,0xb0,0x1a,0x3c,0x80,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,0x80,0x00,0x7b,0x37, +0x00,0x00,0x5b,0xaf,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c, +0x80,0x00,0x7b,0x37,0x00,0x00,0x5b,0xaf,0x01,0x80,0x1a,0x3c,0x64,0xb7,0x5a,0x27, +0x08,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x04,0x00,0xa1,0xaf,0x08,0x00,0xa2,0xaf,0x0c,0x00,0xa3,0xaf,0x10,0x00,0xa4,0xaf, +0x14,0x00,0xa5,0xaf,0x18,0x00,0xa6,0xaf,0x1c,0x00,0xa7,0xaf,0x20,0x00,0xa8,0xaf, +0x24,0x00,0xa9,0xaf,0x28,0x00,0xaa,0xaf,0x2c,0x00,0xab,0xaf,0x30,0x00,0xac,0xaf, +0x34,0x00,0xad,0xaf,0x38,0x00,0xae,0xaf,0x3c,0x00,0xaf,0xaf,0x12,0x40,0x00,0x00, +0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0xb0,0xaf,0x44,0x00,0xb1,0xaf, +0x48,0x00,0xb2,0xaf,0x4c,0x00,0xb3,0xaf,0x50,0x00,0xb4,0xaf,0x54,0x00,0xb5,0xaf, +0x58,0x00,0xb6,0xaf,0x5c,0x00,0xb7,0xaf,0x60,0x00,0xb8,0xaf,0x64,0x00,0xb9,0xaf, +0x68,0x00,0xbc,0xaf,0x6c,0x00,0xbd,0xaf,0x70,0x00,0xbe,0xaf,0x74,0x00,0xbf,0xaf, +0x78,0x00,0xa8,0xaf,0x7c,0x00,0xa9,0xaf,0x80,0x00,0xaa,0xaf,0x71,0x2d,0x00,0x08, +0x21,0x20,0xa0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x25,0xb0,0x06,0x3c,0x00,0x80,0x02,0x3c,0xe8,0xff,0xbd,0x27,0x18,0x03,0xc3,0x34, +0x00,0x03,0x42,0x24,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x42,0xb0,0x03,0x3c, +0x03,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x02,0x80,0x0a,0x3c,0x02,0x80,0x10,0x3c, +0xff,0x00,0x42,0x30,0x00,0x46,0x02,0x00,0x10,0x00,0x42,0x30,0x13,0x00,0x40,0x10, +0x03,0x46,0x08,0x00,0xec,0x3d,0x42,0x8d,0x38,0x15,0x05,0x26,0xec,0x23,0xa4,0x94, +0x01,0x00,0x47,0x24,0x10,0x00,0x02,0x24,0xb0,0x03,0xc9,0x34,0x00,0x00,0x62,0xa0, +0x07,0x00,0x80,0x10,0x1c,0x03,0xc6,0x34,0xf0,0x23,0xa2,0x94,0xec,0x23,0xa0,0xa4, +0xf0,0x23,0xa0,0xa4,0x00,0x00,0x04,0x24,0x00,0x00,0xc2,0xa0,0x00,0x00,0x20,0xad, +0x01,0x00,0x82,0x24,0xec,0x3d,0x47,0xad,0xec,0x23,0xa2,0xa4,0x12,0x00,0x00,0x05, +0x42,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x38,0x15,0x04,0x26,0x18,0x0b,0x83,0x94,0x14,0x0b,0x85,0x94, +0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c, +0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4, +0x08,0x00,0xe0,0x03,0x14,0x0b,0x83,0xa4,0x80,0xff,0x03,0x24,0x03,0x00,0x42,0x34, +0x00,0x00,0x43,0xa0,0x0d,0x1e,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x38,0x15,0x04,0x26, +0x18,0x0b,0x83,0x94,0x14,0x0b,0x85,0x94,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f, +0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34, +0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,0x08,0x00,0xe0,0x03,0x14,0x0b,0x83,0xa4, +0xff,0x00,0x84,0x30,0x0b,0x00,0x82,0x2c,0xff,0xff,0xe7,0x30,0x10,0x00,0xa8,0x93, +0x19,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00, +0x50,0x8e,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00, +0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x43,0xb0,0x02,0x3c,0x78,0x00,0x44,0x34, +0x07,0x00,0xe2,0x30,0x00,0x00,0x85,0xac,0x04,0x00,0x86,0xac,0x04,0x00,0x40,0x18, +0x00,0x00,0x00,0x00,0xf8,0xff,0xe2,0x30,0x08,0x00,0x42,0x24,0xff,0xff,0x47,0x30, +0x21,0x10,0xe8,0x00,0x00,0x80,0x03,0x3c,0x08,0x00,0x82,0xac,0x25,0x10,0x43,0x00, +0x08,0x00,0x82,0xac,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x6c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c, +0x20,0x01,0x00,0x08,0x60,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08, +0x54,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x48,0x00,0x44,0x34, +0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x3c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c, +0x20,0x01,0x00,0x08,0x30,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08, +0x24,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x18,0x00,0x44,0x34, +0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x0c,0x00,0x44,0x34,0x20,0x01,0x00,0x08, +0x43,0xb0,0x04,0x3c,0x01,0x00,0x02,0x24,0x43,0xb0,0x03,0x3c,0x04,0x20,0x82,0x00, +0x88,0x00,0x65,0x34,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0xff,0x42,0x30, +0x05,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x00,0x00,0xa2,0x94, +0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x30,0x24,0x10,0x44,0x00,0xf5,0xff,0x40,0x1c, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c, +0x00,0x80,0x02,0x3c,0xd0,0xff,0xbd,0x27,0x18,0x03,0x03,0x35,0x7c,0x05,0x42,0x24, +0x00,0x00,0x62,0xac,0x28,0x00,0xb4,0xaf,0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf, +0x2c,0x00,0xbf,0xaf,0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x08,0x00,0xf3,0x8c, +0xff,0x00,0xc6,0x30,0x00,0x01,0x02,0x24,0x0c,0x00,0xf1,0x84,0x23,0x10,0x46,0x00, +0xff,0xff,0xa3,0x30,0xff,0xff,0x50,0x30,0xff,0x00,0x94,0x30,0xd0,0x03,0x08,0x35, +0x21,0x30,0xc5,0x00,0x21,0x20,0x80,0x02,0x21,0x28,0x60,0x02,0x21,0x38,0x00,0x02, +0x02,0x92,0x03,0x00,0x00,0x00,0x11,0xad,0x00,0x00,0x13,0xad,0x8f,0x01,0x00,0x08, +0x00,0x00,0x00,0x00,0x01,0x01,0x23,0x2a,0xff,0xff,0x22,0x32,0x21,0x98,0x70,0x02, +0x21,0x20,0x80,0x02,0x00,0x01,0x10,0x24,0x4d,0x01,0x00,0x0c,0x0b,0x80,0x43,0x00, +0xc0,0x10,0x12,0x00,0x28,0xb0,0x03,0x3c,0x21,0x10,0x43,0x00,0x00,0x00,0x45,0x90, +0x20,0x10,0x06,0x3c,0x21,0x20,0x80,0x02,0xff,0x00,0xb2,0x30,0x00,0x12,0x12,0x00, +0x21,0x30,0x46,0x00,0x21,0x28,0x60,0x02,0x21,0x38,0x00,0x02,0x10,0x01,0x00,0x0c, +0x10,0x00,0xa0,0xaf,0x23,0x18,0x30,0x02,0x00,0x8c,0x03,0x00,0x03,0x8c,0x11,0x00, +0xe8,0xff,0x20,0x1e,0x00,0x00,0x00,0x00,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c, +0x25,0xb0,0x04,0x3c,0x20,0x00,0xb2,0xaf,0x38,0x15,0x52,0x24,0x00,0x80,0x02,0x3c, +0x18,0x03,0x83,0x34,0x78,0x06,0x42,0x24,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf, +0x30,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x00,0x00,0x62,0xac,0xb0,0x03,0x93,0x34,0x21,0xa0,0x40,0x02,0xdc,0x24,0x42,0x8e, +0x48,0x25,0x50,0x8e,0x21,0x20,0x00,0x00,0x00,0x00,0x62,0xae,0xe0,0x24,0x42,0xae, +0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x48,0x25,0x44,0x8e, +0x4c,0x25,0x43,0x8e,0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00, +0x0a,0x18,0x82,0x00,0x48,0x25,0x43,0xae,0x48,0x25,0x85,0x8e,0x00,0x00,0x00,0x00, +0x00,0x00,0x65,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02, +0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0xff,0x00,0x15,0x24,0x21,0x20,0x00,0x00, +0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0x20,0x10,0x02,0x3c,0x40,0x00,0x07,0x24, +0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,0x05,0x00,0x35,0x12,0x21,0x30,0x60,0x00, +0x90,0x24,0x91,0xa2,0xdc,0x24,0x83,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x00,0x00,0x05,0x96,0x30,0x24,0x83,0x8e,0x2a,0xb0,0x02,0x3c,0x27,0x20,0x05,0x00, +0x01,0x00,0x46,0x34,0x21,0x10,0x65,0x00,0x2b,0x18,0x64,0x00,0x02,0x00,0x60,0x10, +0x00,0x00,0x00,0x00,0x30,0x24,0x82,0xae,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e, +0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00, +0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0xc0,0xff,0x02,0x24,0x25,0x18,0x64,0x00, +0x24,0x18,0x62,0x00,0x08,0x00,0x03,0xae,0x01,0x00,0x02,0x24,0x02,0x00,0x03,0x24, +0x00,0x00,0xc2,0xa0,0x00,0x00,0xc3,0xa0,0xbc,0xff,0x35,0x16,0x41,0xb0,0x03,0x3c, +0x08,0x0b,0x82,0x8e,0x30,0x00,0xbf,0x8f,0x00,0x38,0x42,0x34,0x00,0x00,0x62,0xac, +0x2c,0x00,0xb5,0x8f,0x08,0x0b,0x82,0xae,0x24,0x00,0xb3,0x8f,0x28,0x00,0xb4,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x38,0x00,0xbd,0x27,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27, +0x18,0x03,0x83,0x34,0x04,0x08,0x42,0x24,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf, +0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x02,0x80,0x02,0x3c,0x38,0x15,0x52,0x24,0xb0,0x03,0x95,0x34,0x25,0x02,0x00,0x08, +0x21,0xf0,0x40,0x02,0x08,0x00,0x04,0xae,0x82,0x0b,0x82,0x92,0x00,0x00,0x00,0x00, +0x45,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,0x09,0x00,0x42,0x34,0x01,0x00,0x03,0x24, +0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0,0x5a,0x00,0x36,0x12, +0x00,0x00,0x00,0x00,0xf4,0x24,0x42,0x8e,0x60,0x25,0x53,0x8e,0x01,0x00,0x04,0x24, +0x00,0x00,0xa2,0xae,0xf8,0x24,0x42,0xae,0x00,0x00,0xb3,0xae,0x4d,0x01,0x00,0x0c, +0x21,0xa0,0xc0,0x03,0x60,0x25,0x44,0x8e,0x64,0x25,0x43,0x8e,0x40,0x00,0x84,0x24, +0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x60,0x25,0x43,0xae, +0x60,0x25,0xc5,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0xa5,0xae,0x02,0x80,0x17,0x3c, +0xff,0xff,0x62,0x32,0x25,0x80,0x57,0x00,0x00,0x00,0xb0,0xae,0x0c,0x00,0x02,0x92, +0xff,0x00,0x16,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0xa2,0xae,0x0c,0x00,0x11,0x92, +0x20,0x10,0x02,0x3c,0x40,0x00,0x07,0x24,0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00, +0x05,0x00,0x36,0x12,0x21,0x30,0x60,0x00,0xf4,0x24,0xc3,0xaf,0x98,0x24,0xd1,0xa3, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e, +0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00, +0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0xc0,0xff,0x05,0x24, +0x82,0x11,0x03,0x00,0x24,0x20,0x65,0x00,0x01,0x00,0x42,0x30,0xbd,0xff,0x40,0x10, +0x04,0x00,0x84,0x34,0x08,0x00,0x03,0xae,0x82,0x0b,0x82,0x92,0x00,0x00,0x00,0x00, +0xbd,0xff,0x40,0x14,0x2a,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x01,0x00,0x03,0x24,0x82,0x0b,0x83,0xa2, +0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30, +0x25,0x10,0x57,0x00,0x02,0x00,0x43,0x94,0x00,0x00,0x00,0x00,0xff,0xc0,0x64,0x30, +0x00,0xc0,0x84,0x34,0x86,0x27,0x00,0x0c,0x83,0x0b,0x83,0xa2,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,0x09,0x00,0x42,0x34, +0x01,0x00,0x03,0x24,0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0, +0xa8,0xff,0x36,0x16,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x38,0x15,0x62,0x24, +0x08,0x0b,0x43,0x8c,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x38,0x63,0x34, +0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x83,0xac,0x08,0x00,0xe0,0x03, +0x08,0x0b,0x43,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27, +0x18,0x03,0x83,0x34,0x54,0x0a,0x42,0x24,0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf, +0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf, +0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c, +0x38,0x15,0xd3,0x26,0xb0,0x03,0x94,0x34,0x02,0x80,0x15,0x3c,0x21,0xb8,0x60,0x02, +0xe8,0x24,0x62,0x8e,0x54,0x25,0x70,0x8e,0x01,0x00,0x04,0x24,0x00,0x00,0x82,0xae, +0xec,0x24,0x62,0xae,0x00,0x00,0x90,0xae,0x4d,0x01,0x00,0x0c,0x21,0x88,0xe0,0x02, +0x54,0x25,0x64,0x8e,0x58,0x25,0x63,0x8e,0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24, +0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x54,0x25,0x63,0xae,0x54,0x25,0xe5,0x8e, +0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32, +0x25,0x80,0x02,0x02,0x00,0x00,0x90,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00, +0x00,0x00,0x82,0xae,0x0c,0x00,0x12,0x92,0xff,0x00,0x02,0x24,0x0a,0x00,0x42,0x12, +0x00,0x1a,0x12,0x00,0x20,0x10,0x02,0x3c,0x21,0x18,0x62,0x00,0xe8,0x24,0xe3,0xae, +0x94,0x24,0xf2,0xa2,0x21,0x30,0x60,0x00,0x01,0x00,0x04,0x24,0x40,0x00,0x07,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x10,0x24,0x22,0x8e,0x04,0x00,0x03,0x8e, +0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x5d,0x00,0x40,0x14,0x1f,0x00,0x64,0x30, +0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00, +0x00,0x26,0x04,0x00,0x25,0x28,0x44,0x00,0x08,0x00,0x05,0xae,0xc2,0x11,0x05,0x00, +0x01,0x00,0x43,0x30,0x47,0x00,0x60,0x14,0x01,0x00,0x02,0x24,0x00,0x00,0x04,0x96, +0x34,0x24,0x23,0x8e,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0x05,0x00,0x40,0x10, +0xff,0xdf,0x02,0x3c,0x21,0x10,0x64,0x00,0x34,0x24,0x22,0xae,0x08,0x00,0x05,0x8e, +0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x28,0xa2,0x00,0x00,0x40,0x03,0x3c, +0x25,0x28,0xa3,0x00,0x82,0x11,0x05,0x00,0x01,0x00,0x42,0x30,0x03,0x00,0x40,0x14, +0xc0,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,0x04,0x00,0x45,0x34,0x08,0x00,0x05,0xae, +0x38,0x15,0xc2,0x26,0x82,0x0b,0x44,0x90,0x01,0x00,0x03,0x24,0x3b,0x00,0x83,0x10, +0x7f,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,0x08,0x00,0x02,0xae,0x38,0x15,0xc5,0x26, +0xec,0x24,0xa2,0x8c,0x20,0x00,0x10,0x8e,0x00,0x80,0x03,0x3c,0x25,0x10,0x43,0x00, +0x2a,0xb0,0x03,0x3c,0x08,0x00,0x50,0xac,0x05,0x00,0x70,0x34,0x01,0x00,0x02,0x24, +0x02,0x00,0x03,0x24,0x00,0x00,0x02,0xa2,0x00,0x00,0x03,0xa2,0xfc,0x3d,0xa2,0x96, +0xff,0x00,0x03,0x24,0x01,0x00,0x42,0x24,0xfc,0x3d,0xa2,0xa6,0xfc,0x3d,0xa4,0x96, +0x25,0xb0,0x02,0x3c,0x66,0x03,0x42,0x34,0x00,0x00,0x44,0xa4,0x98,0xff,0x43,0x16, +0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x38,0x42,0x34, +0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x62,0xac,0x08,0x00,0xe0,0x03, +0x08,0x0b,0xa2,0xac,0xc3,0xff,0x62,0x14,0xff,0xdf,0x02,0x3c,0x00,0x00,0x04,0x96, +0x30,0x24,0x23,0x8e,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0xbd,0xff,0x40,0x10, +0xff,0xdf,0x02,0x3c,0x21,0x10,0x64,0x00,0xeb,0x02,0x00,0x08,0x30,0x24,0x22,0xae, +0x08,0x00,0x05,0x8e,0xe0,0x02,0x00,0x08,0xc2,0x11,0x05,0x00,0x80,0x00,0xa5,0x34, +0xff,0x02,0x00,0x08,0x08,0x00,0x05,0xae,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf, +0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x02,0x80,0x06,0x3c,0xb4,0x3e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x18,0x03,0x42,0x34,0xe8,0x0c,0x63,0x24,0x40,0x00,0xa4,0x30,0x00,0x00,0x43,0xac, +0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0x7f,0x00,0xa2,0x30,0xbf,0x00,0xa2,0x30, +0x01,0x00,0x16,0x24,0xb4,0x3e,0xc2,0xa0,0xb4,0x3e,0xc2,0x90,0x25,0xb0,0x04,0x3c, +0x88,0x02,0x83,0x34,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x02,0x80,0x14,0x3c,0x38,0x15,0x92,0x26,0xb0,0x03,0x93,0x34, +0x02,0x80,0x15,0x3c,0x7d,0x03,0x00,0x08,0x21,0xb8,0x40,0x02,0x08,0x00,0x03,0x8e, +0x01,0x00,0x04,0x24,0x25,0x18,0x62,0x00,0x82,0x17,0x03,0x00,0x01,0x00,0x42,0x30, +0x9a,0x00,0x44,0x10,0x08,0x00,0x03,0xae,0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30, +0x05,0x00,0x40,0x14,0x2a,0xb0,0x05,0x3c,0xc0,0xff,0x02,0x24,0x24,0x10,0x62,0x00, +0x04,0x00,0x42,0x34,0x08,0x00,0x02,0xae,0x0d,0x00,0xa6,0x34,0x04,0x00,0xc2,0x24, +0x0b,0x30,0x56,0x00,0x02,0x00,0x03,0x24,0x00,0x00,0xc4,0xa0,0x00,0x00,0xc3,0xa0, +0xfc,0x3d,0xa2,0x96,0x66,0x03,0x24,0x35,0x01,0x00,0x42,0x24,0xfc,0x3d,0xa2,0xa6, +0xfc,0x3d,0xa3,0x96,0xff,0x00,0x02,0x24,0x00,0x00,0x83,0xa4,0x98,0x00,0x22,0x12, +0x00,0x00,0x00,0x00,0xac,0x24,0x42,0x8e,0x18,0x25,0x50,0x8e,0x03,0x00,0x04,0x24, +0x00,0x00,0x62,0xae,0xb0,0x24,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c, +0x00,0x00,0x00,0x00,0x18,0x25,0x44,0x8e,0x1c,0x25,0x43,0x8e,0x40,0x00,0x84,0x24, +0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x18,0x25,0x43,0xae, +0x18,0x25,0xe2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c, +0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92, +0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24, +0x0d,0x00,0x22,0x12,0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00, +0x69,0x00,0xc0,0x12,0xac,0x24,0xe2,0xae,0x74,0x24,0xf1,0xa2,0x38,0x15,0x82,0x26, +0xac,0x24,0x46,0x8c,0x18,0x25,0x45,0x8c,0x03,0x00,0x04,0x24,0x40,0x00,0x07,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x38,0x15,0x86,0x26,0x10,0x24,0xc2,0x8c, +0x04,0x00,0x08,0x8e,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14, +0x1f,0x00,0x07,0x31,0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34, +0x24,0x10,0x43,0x00,0x00,0x26,0x07,0x00,0x25,0x18,0x44,0x00,0x08,0x00,0x03,0xae, +0x00,0x00,0x05,0x96,0x34,0x24,0xc4,0x8c,0xff,0xff,0xa3,0x30,0x27,0x10,0x03,0x00, +0x2b,0x10,0x82,0x00,0x04,0x00,0x40,0x10,0x21,0x10,0x83,0x00,0x34,0x24,0xc2,0xac, +0x04,0x00,0x08,0x8e,0x00,0x00,0x05,0x96,0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00, +0x47,0x00,0x80,0x04,0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00, +0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x04,0x00,0x40,0x14, +0xff,0xff,0xa2,0x30,0xfd,0x0f,0x42,0x28,0x09,0x00,0x40,0x14,0xff,0xff,0xa3,0x30, +0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x18,0x43,0x00, +0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x08,0x00,0x03,0xae,0xff,0xff,0xa3,0x30, +0xff,0x01,0x62,0x30,0x03,0x00,0x40,0x10,0x43,0x32,0x03,0x00,0x00,0x02,0x62,0x24, +0x43,0x32,0x02,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x02,0x22,0x08,0x00, +0x80,0x10,0x02,0x00,0x38,0x15,0x83,0x26,0x21,0x38,0x43,0x00,0x1f,0x00,0x84,0x30, +0x21,0x20,0xe4,0x00,0xf8,0x0c,0x82,0x90,0x25,0xb0,0x09,0x3c,0xb0,0x03,0x25,0x35, +0x21,0x10,0xc2,0x00,0xf8,0x0c,0x82,0xa0,0x00,0x00,0xa6,0xac,0x04,0x00,0x02,0x8e, +0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x1f,0x00,0x42,0x30,0x21,0x10,0xe2,0x00, +0xf8,0x0c,0x43,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xac,0x04,0x00,0x08,0x8e, +0xf7,0x0c,0xe4,0x90,0x02,0x12,0x08,0x00,0x1f,0x00,0x42,0x30,0x21,0x10,0xe2,0x00, +0xf8,0x0c,0x43,0x90,0x00,0x00,0x00,0x00,0x2b,0x20,0x83,0x00,0x67,0xff,0x80,0x14, +0x00,0x40,0x02,0x3c,0x08,0x00,0x03,0x8e,0x01,0x00,0x04,0x24,0x82,0x17,0x03,0x00, +0x01,0x00,0x42,0x30,0x68,0xff,0x44,0x14,0x00,0x00,0x00,0x00,0x02,0x12,0x08,0x00, +0x1f,0x00,0x42,0x30,0x21,0x10,0xe2,0x00,0xf8,0x0c,0x40,0xa0,0x08,0x00,0x03,0x8e, +0x67,0x03,0x00,0x08,0x82,0x11,0x03,0x00,0x9f,0x03,0x00,0x08,0x70,0x24,0xf1,0xa2, +0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30, +0x14,0x00,0x42,0x28,0xb7,0xff,0x40,0x14,0x42,0x12,0x03,0x00,0x9f,0xff,0x02,0x3c, +0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,0xc4,0x03,0x00,0x08,0x10,0x00,0x02,0xae, +0x21,0x00,0xc0,0x12,0x38,0x15,0x82,0x26,0x74,0x24,0x43,0x90,0x25,0xb0,0x02,0x3c, +0x41,0x00,0xa4,0x34,0xb0,0x03,0x42,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0x43,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x38,0x15,0x85,0x26, +0x08,0x0b,0xa4,0x8c,0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34, +0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac, +0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,0x70,0x24,0x43,0x90,0x25,0xb0,0x02,0x3c, +0x40,0x00,0xa4,0x34,0xb0,0x03,0x42,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0x43,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x38,0x15,0x85,0x26, +0x08,0x0b,0xa4,0x8c,0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34, +0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac, +0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf, +0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x02,0x80,0x06,0x3c,0xb4,0x3e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x18,0x03,0x42,0x34,0x58,0x11,0x63,0x24,0x10,0x00,0xa4,0x30,0x00,0x00,0x43,0xac, +0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0xdf,0x00,0xa2,0x30,0xef,0x00,0xa2,0x30, +0x01,0x00,0x16,0x24,0xb4,0x3e,0xc2,0xa0,0xb4,0x3e,0xc3,0x90,0x25,0xb0,0x02,0x3c, +0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x14,0x3c,0x38,0x15,0x92,0x26, +0x21,0x98,0x40,0x00,0x02,0x80,0x15,0x3c,0x9a,0x04,0x00,0x08,0x21,0xb8,0x40,0x02, +0x08,0x00,0x03,0x8e,0x01,0x00,0x04,0x24,0x25,0x18,0x62,0x00,0x82,0x17,0x03,0x00, +0x01,0x00,0x42,0x30,0x9a,0x00,0x44,0x10,0x08,0x00,0x03,0xae,0x82,0x11,0x03,0x00, +0x01,0x00,0x42,0x30,0x05,0x00,0x40,0x14,0x2a,0xb0,0x05,0x3c,0xc0,0xff,0x02,0x24, +0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,0x08,0x00,0x02,0xae,0x15,0x00,0xa6,0x34, +0x04,0x00,0xc2,0x24,0x0b,0x30,0x56,0x00,0x02,0x00,0x03,0x24,0x00,0x00,0xc4,0xa0, +0x00,0x00,0xc3,0xa0,0xfc,0x3d,0xa2,0x96,0x66,0x03,0x24,0x35,0x01,0x00,0x42,0x24, +0xfc,0x3d,0xa2,0xa6,0xfc,0x3d,0xa3,0x96,0xff,0x00,0x02,0x24,0x00,0x00,0x83,0xa4, +0x98,0x00,0x22,0x12,0x00,0x00,0x00,0x00,0xb8,0x24,0x42,0x8e,0x24,0x25,0x50,0x8e, +0x04,0x00,0x04,0x24,0x00,0x00,0x62,0xae,0xbc,0x24,0x42,0xae,0x00,0x00,0x70,0xae, +0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x24,0x25,0x44,0x8e,0x28,0x25,0x43,0x8e, +0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00, +0x24,0x25,0x43,0xae,0x24,0x25,0xe2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae, +0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae, +0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92, +0xff,0x00,0x02,0x24,0x0d,0x00,0x22,0x12,0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c, +0x21,0x10,0x43,0x00,0x69,0x00,0xc0,0x12,0xb8,0x24,0xe2,0xae,0x7c,0x24,0xf1,0xa2, +0x38,0x15,0x82,0x26,0xb8,0x24,0x46,0x8c,0x24,0x25,0x45,0x8c,0x04,0x00,0x04,0x24, +0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x38,0x15,0x86,0x26, +0x10,0x24,0xc2,0x8c,0x04,0x00,0x08,0x8e,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30, +0x08,0x00,0x40,0x14,0x1f,0x00,0x07,0x31,0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c, +0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,0x00,0x26,0x07,0x00,0x25,0x18,0x44,0x00, +0x08,0x00,0x03,0xae,0x00,0x00,0x05,0x96,0x34,0x24,0xc4,0x8c,0xff,0xff,0xa3,0x30, +0x27,0x10,0x03,0x00,0x2b,0x10,0x82,0x00,0x04,0x00,0x40,0x10,0x21,0x10,0x83,0x00, +0x34,0x24,0xc2,0xac,0x04,0x00,0x08,0x8e,0x00,0x00,0x05,0x96,0x10,0x00,0x04,0x8e, +0x00,0x00,0x00,0x00,0x47,0x00,0x80,0x04,0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e, +0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28, +0x04,0x00,0x40,0x14,0xff,0xff,0xa2,0x30,0xfd,0x0f,0x42,0x28,0x09,0x00,0x40,0x14, +0xff,0xff,0xa3,0x30,0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34, +0x24,0x18,0x43,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x08,0x00,0x03,0xae, +0xff,0xff,0xa3,0x30,0xff,0x01,0x62,0x30,0x03,0x00,0x40,0x10,0x43,0x32,0x03,0x00, +0x00,0x02,0x62,0x24,0x43,0x32,0x02,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00, +0x02,0x22,0x08,0x00,0x80,0x10,0x02,0x00,0x38,0x15,0x83,0x26,0x21,0x38,0x43,0x00, +0x1f,0x00,0x84,0x30,0x21,0x20,0xe4,0x00,0xf8,0x0c,0x82,0x90,0x25,0xb0,0x09,0x3c, +0xb0,0x03,0x25,0x35,0x21,0x10,0xc2,0x00,0xf8,0x0c,0x82,0xa0,0x00,0x00,0xa6,0xac, +0x04,0x00,0x02,0x8e,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x1f,0x00,0x42,0x30, +0x21,0x10,0xe2,0x00,0xf8,0x0c,0x43,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xac, +0x04,0x00,0x08,0x8e,0xf7,0x0c,0xe4,0x90,0x02,0x12,0x08,0x00,0x1f,0x00,0x42,0x30, +0x21,0x10,0xe2,0x00,0xf8,0x0c,0x43,0x90,0x00,0x00,0x00,0x00,0x2b,0x20,0x83,0x00, +0x67,0xff,0x80,0x14,0x00,0x40,0x02,0x3c,0x08,0x00,0x03,0x8e,0x01,0x00,0x04,0x24, +0x82,0x17,0x03,0x00,0x01,0x00,0x42,0x30,0x68,0xff,0x44,0x14,0x00,0x00,0x00,0x00, +0x02,0x12,0x08,0x00,0x1f,0x00,0x42,0x30,0x21,0x10,0xe2,0x00,0xf8,0x0c,0x40,0xa0, +0x08,0x00,0x03,0x8e,0x84,0x04,0x00,0x08,0x82,0x11,0x03,0x00,0xbc,0x04,0x00,0x08, +0x78,0x24,0xf1,0xa2,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00, +0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,0xb7,0xff,0x40,0x14,0x42,0x12,0x03,0x00, +0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,0xe1,0x04,0x00,0x08, +0x10,0x00,0x02,0xae,0x20,0x00,0xc0,0x12,0x38,0x15,0x82,0x26,0x7c,0x24,0x43,0x90, +0x25,0xb0,0x02,0x3c,0x43,0x00,0xa4,0x34,0xb0,0x03,0x42,0x34,0x00,0x00,0x83,0xa0, +0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x38,0x15,0x85,0x26,0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c, +0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac, +0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0x78,0x24,0x43,0x90,0x25,0xb0,0x02,0x3c, +0x42,0x00,0xa4,0x34,0xb0,0x03,0x42,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0x43,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x38,0x15,0x85,0x26, +0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f, +0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f, +0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,0x25,0x10,0x43,0x00, +0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03, +0x08,0x0b,0xa2,0xac,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf,0x38,0x00,0xbf,0xaf, +0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf, +0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c, +0xb4,0x3e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34, +0xc4,0x15,0x63,0x24,0x01,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,0x21,0xb0,0x00,0x00, +0x03,0x00,0x80,0x10,0xf7,0x00,0xa2,0x30,0xfe,0x00,0xa2,0x30,0x01,0x00,0x16,0x24, +0xb4,0x3e,0xc2,0xa0,0xb4,0x3e,0xc3,0x90,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34, +0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x02,0x80,0x14,0x3c,0x38,0x15,0x92,0x26,0x21,0x98,0x40,0x00,0x02,0x80,0x15,0x3c, +0xe1,0x05,0x00,0x08,0x21,0xb8,0x40,0x02,0xfd,0x0f,0x42,0x28,0x95,0x00,0x40,0x10, +0x00,0x20,0x02,0x3c,0x08,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x25,0x18,0x62,0x00, +0x08,0x00,0x03,0xae,0xff,0xff,0xa3,0x30,0xff,0x01,0x62,0x30,0x03,0x00,0x40,0x10, +0x43,0x32,0x03,0x00,0x00,0x02,0x62,0x24,0x43,0x32,0x02,0x00,0xc0,0x10,0x07,0x00, +0x21,0x10,0x47,0x00,0x02,0x22,0x08,0x00,0x80,0x10,0x02,0x00,0x38,0x15,0x83,0x26, +0x21,0x38,0x43,0x00,0x1f,0x00,0x84,0x30,0x21,0x20,0xe4,0x00,0xf8,0x0c,0x82,0x90, +0x25,0xb0,0x09,0x3c,0xb0,0x03,0x25,0x35,0x21,0x10,0xc2,0x00,0xf8,0x0c,0x82,0xa0, +0x00,0x00,0xa6,0xac,0x04,0x00,0x02,0x8e,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00, +0x1f,0x00,0x42,0x30,0x21,0x10,0xe2,0x00,0xf8,0x0c,0x43,0x90,0x00,0x00,0x00,0x00, +0x00,0x00,0xa3,0xac,0x04,0x00,0x08,0x8e,0xf7,0x0c,0xe4,0x90,0x02,0x12,0x08,0x00, +0x1f,0x00,0x42,0x30,0x21,0x10,0xe2,0x00,0xf8,0x0c,0x43,0x90,0x00,0x00,0x00,0x00, +0x2b,0x20,0x83,0x00,0x72,0x00,0x80,0x10,0x01,0x00,0x04,0x24,0x08,0x00,0x03,0x8e, +0x00,0x40,0x02,0x3c,0x25,0x18,0x62,0x00,0x82,0x17,0x03,0x00,0x01,0x00,0x42,0x30, +0x71,0x00,0x44,0x10,0x08,0x00,0x03,0xae,0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30, +0x05,0x00,0x40,0x14,0x2a,0xb0,0x05,0x3c,0xc0,0xff,0x02,0x24,0x24,0x10,0x62,0x00, +0x04,0x00,0x42,0x34,0x08,0x00,0x02,0xae,0x1d,0x00,0xa6,0x34,0x04,0x00,0xc2,0x24, +0x0b,0x30,0x56,0x00,0x02,0x00,0x03,0x24,0x00,0x00,0xc4,0xa0,0x00,0x00,0xc3,0xa0, +0xfc,0x3d,0xa2,0x96,0x66,0x03,0x24,0x35,0x01,0x00,0x42,0x24,0xfc,0x3d,0xa2,0xa6, +0xfc,0x3d,0xa3,0x96,0xff,0x00,0x02,0x24,0x00,0x00,0x83,0xa4,0x6f,0x00,0x22,0x12, +0x00,0x00,0x00,0x00,0xc4,0x24,0x42,0x8e,0x30,0x25,0x50,0x8e,0x05,0x00,0x04,0x24, +0x00,0x00,0x62,0xae,0xc8,0x24,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c, +0x00,0x00,0x00,0x00,0x30,0x25,0x44,0x8e,0x34,0x25,0x43,0x8e,0x40,0x00,0x84,0x24, +0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x30,0x25,0x43,0xae, +0x30,0x25,0xe2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c, +0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92, +0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24, +0x0d,0x00,0x22,0x12,0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00, +0x40,0x00,0xc0,0x12,0xc4,0x24,0xe2,0xae,0x8c,0x24,0xf1,0xa2,0x38,0x15,0x82,0x26, +0xc4,0x24,0x46,0x8c,0x30,0x25,0x45,0x8c,0x05,0x00,0x04,0x24,0x40,0x00,0x07,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x38,0x15,0x86,0x26,0x10,0x24,0xc2,0x8c, +0x04,0x00,0x08,0x8e,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14, +0x1f,0x00,0x07,0x31,0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34, +0x24,0x10,0x43,0x00,0x00,0x26,0x07,0x00,0x25,0x18,0x44,0x00,0x08,0x00,0x03,0xae, +0x00,0x00,0x05,0x96,0x34,0x24,0xc4,0x8c,0xff,0xff,0xa3,0x30,0x27,0x10,0x03,0x00, +0x2b,0x10,0x82,0x00,0x04,0x00,0x40,0x10,0x21,0x10,0x83,0x00,0x34,0x24,0xc2,0xac, +0x04,0x00,0x08,0x8e,0x00,0x00,0x05,0x96,0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00, +0x1e,0x00,0x80,0x04,0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00, +0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x6a,0xff,0x40,0x10, +0xff,0xff,0xa2,0x30,0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34, +0x24,0x18,0x43,0x00,0x00,0x40,0x04,0x3c,0x9c,0x05,0x00,0x08,0x25,0x18,0x64,0x00, +0x08,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x82,0x17,0x03,0x00,0x01,0x00,0x42,0x30, +0x91,0xff,0x44,0x14,0x00,0x00,0x00,0x00,0x02,0x12,0x08,0x00,0x1f,0x00,0x42,0x30, +0x21,0x10,0xe2,0x00,0xf8,0x0c,0x40,0xa0,0x08,0x00,0x03,0x8e,0xcb,0x05,0x00,0x08, +0x82,0x11,0x03,0x00,0x03,0x06,0x00,0x08,0x80,0x24,0xf1,0xa2,0x14,0x00,0x03,0x8e, +0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28, +0xe0,0xff,0x40,0x14,0x42,0x12,0x03,0x00,0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x10,0x82,0x00,0x28,0x06,0x00,0x08,0x10,0x00,0x02,0xae,0x20,0x00,0xc0,0x12, +0x38,0x15,0x82,0x26,0x8c,0x24,0x43,0x90,0x25,0xb0,0x02,0x3c,0x45,0x00,0xa4,0x34, +0xb0,0x03,0x42,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x38,0x15,0x85,0x26,0x08,0x0b,0xa2,0x8c, +0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f, +0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f, +0x18,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c, +0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac, +0x80,0x24,0x43,0x90,0x25,0xb0,0x02,0x3c,0x44,0x00,0xa4,0x34,0xb0,0x03,0x42,0x34, +0x00,0x00,0x83,0xa0,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x38,0x15,0x85,0x26,0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f, +0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x18,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27, +0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0xc0,0xff,0xbd,0x27, +0x30,0x00,0xb6,0xaf,0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf, +0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c,0xb4,0x3e,0xc5,0x90,0x00,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,0x3c,0x1a,0x63,0x24,0x02,0x00,0xa4,0x30, +0x00,0x00,0x43,0xac,0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0xfb,0x00,0xa2,0x30, +0xfd,0x00,0xa2,0x30,0x01,0x00,0x16,0x24,0xb4,0x3e,0xc2,0xa0,0xb4,0x3e,0xc3,0x90, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x14,0x3c,0x38,0x15,0x92,0x26, +0x21,0x98,0x40,0x00,0x02,0x80,0x15,0x3c,0xff,0x06,0x00,0x08,0x21,0xb8,0x40,0x02, +0xfd,0x0f,0x42,0x28,0x95,0x00,0x40,0x10,0x00,0x20,0x02,0x3c,0x08,0x00,0x03,0x8e, +0x00,0x00,0x00,0x00,0x25,0x18,0x62,0x00,0x08,0x00,0x03,0xae,0xff,0xff,0xa3,0x30, +0xff,0x01,0x62,0x30,0x03,0x00,0x40,0x10,0x43,0x32,0x03,0x00,0x00,0x02,0x62,0x24, +0x43,0x32,0x02,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x02,0x22,0x08,0x00, +0x80,0x10,0x02,0x00,0x38,0x15,0x83,0x26,0x21,0x38,0x43,0x00,0x1f,0x00,0x84,0x30, +0x21,0x20,0xe4,0x00,0xf8,0x0c,0x82,0x90,0x25,0xb0,0x09,0x3c,0xb0,0x03,0x25,0x35, +0x21,0x10,0xc2,0x00,0xf8,0x0c,0x82,0xa0,0x00,0x00,0xa6,0xac,0x04,0x00,0x02,0x8e, +0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x1f,0x00,0x42,0x30,0x21,0x10,0xe2,0x00, +0xf8,0x0c,0x43,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xac,0x04,0x00,0x08,0x8e, +0xf7,0x0c,0xe4,0x90,0x02,0x12,0x08,0x00,0x1f,0x00,0x42,0x30,0x21,0x10,0xe2,0x00, +0xf8,0x0c,0x43,0x90,0x00,0x00,0x00,0x00,0x2b,0x20,0x83,0x00,0x72,0x00,0x80,0x10, +0x01,0x00,0x04,0x24,0x08,0x00,0x03,0x8e,0x00,0x40,0x02,0x3c,0x25,0x18,0x62,0x00, +0x82,0x17,0x03,0x00,0x01,0x00,0x42,0x30,0x71,0x00,0x44,0x10,0x08,0x00,0x03,0xae, +0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30,0x05,0x00,0x40,0x14,0x2a,0xb0,0x05,0x3c, +0xc0,0xff,0x02,0x24,0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,0x08,0x00,0x02,0xae, +0x25,0x00,0xa6,0x34,0x04,0x00,0xc2,0x24,0x0b,0x30,0x56,0x00,0x02,0x00,0x03,0x24, +0x00,0x00,0xc4,0xa0,0x00,0x00,0xc3,0xa0,0xfc,0x3d,0xa2,0x96,0x66,0x03,0x24,0x35, +0x01,0x00,0x42,0x24,0xfc,0x3d,0xa2,0xa6,0xfc,0x3d,0xa3,0x96,0xff,0x00,0x02,0x24, +0x00,0x00,0x83,0xa4,0x6f,0x00,0x22,0x12,0x00,0x00,0x00,0x00,0xd0,0x24,0x42,0x8e, +0x3c,0x25,0x50,0x8e,0x06,0x00,0x04,0x24,0x00,0x00,0x62,0xae,0xd4,0x24,0x42,0xae, +0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x3c,0x25,0x44,0x8e, +0x40,0x25,0x43,0x8e,0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00, +0x0a,0x18,0x82,0x00,0x3c,0x25,0x43,0xae,0x3c,0x25,0xe2,0x8e,0x00,0x00,0x00,0x00, +0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02, +0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae, +0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x0d,0x00,0x22,0x12,0x00,0x12,0x11,0x00, +0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x40,0x00,0xc0,0x12,0xd0,0x24,0xe2,0xae, +0x88,0x24,0xf1,0xa2,0x38,0x15,0x82,0x26,0xd0,0x24,0x46,0x8c,0x3c,0x25,0x45,0x8c, +0x06,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x38,0x15,0x86,0x26,0x10,0x24,0xc2,0x8c,0x04,0x00,0x08,0x8e,0x42,0x10,0x02,0x00, +0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14,0x1f,0x00,0x07,0x31,0x08,0x00,0x02,0x8e, +0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,0x00,0x26,0x07,0x00, +0x25,0x18,0x44,0x00,0x08,0x00,0x03,0xae,0x00,0x00,0x05,0x96,0x34,0x24,0xc4,0x8c, +0xff,0xff,0xa3,0x30,0x27,0x10,0x03,0x00,0x2b,0x10,0x82,0x00,0x04,0x00,0x40,0x10, +0x21,0x10,0x83,0x00,0x34,0x24,0xc2,0xac,0x04,0x00,0x08,0x8e,0x00,0x00,0x05,0x96, +0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0x1e,0x00,0x80,0x04,0x00,0x00,0x00,0x00, +0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30, +0x0c,0x00,0x42,0x28,0x6a,0xff,0x40,0x10,0xff,0xff,0xa2,0x30,0x08,0x00,0x02,0x8e, +0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x18,0x43,0x00,0x00,0x40,0x04,0x3c, +0xba,0x06,0x00,0x08,0x25,0x18,0x64,0x00,0x08,0x00,0x03,0x8e,0x00,0x00,0x00,0x00, +0x82,0x17,0x03,0x00,0x01,0x00,0x42,0x30,0x91,0xff,0x44,0x14,0x00,0x00,0x00,0x00, +0x02,0x12,0x08,0x00,0x1f,0x00,0x42,0x30,0x21,0x10,0xe2,0x00,0xf8,0x0c,0x40,0xa0, +0x08,0x00,0x03,0x8e,0xe9,0x06,0x00,0x08,0x82,0x11,0x03,0x00,0x21,0x07,0x00,0x08, +0x84,0x24,0xf1,0xa2,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00, +0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,0xe0,0xff,0x40,0x14,0x42,0x12,0x03,0x00, +0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,0x46,0x07,0x00,0x08, +0x10,0x00,0x02,0xae,0x20,0x00,0xc0,0x12,0x38,0x15,0x82,0x26,0x88,0x24,0x43,0x90, +0x25,0xb0,0x02,0x3c,0x47,0x00,0xa4,0x34,0xb0,0x03,0x42,0x34,0x00,0x00,0x83,0xa0, +0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x38,0x15,0x85,0x26,0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x60,0x00,0x03,0x3c, +0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac, +0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0x84,0x24,0x43,0x90,0x25,0xb0,0x02,0x3c, +0x46,0x00,0xa4,0x34,0xb0,0x03,0x42,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0x43,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x38,0x15,0x85,0x26, +0x08,0x0b,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f, +0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f, +0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x60,0x00,0x03,0x3c,0x25,0x10,0x43,0x00, +0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03, +0x08,0x0b,0xa2,0xac,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xb4,0x1e,0x63,0x24, +0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x02,0x80,0x05,0x3c,0x38,0x15,0xa5,0x24,0x10,0x0b,0xa2,0x8c, +0x08,0x0b,0xa4,0x8c,0x00,0x08,0x03,0x3c,0x24,0x10,0x43,0x00,0x25,0x20,0x82,0x00, +0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac, +0x25,0xb0,0x05,0x3c,0x00,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27,0x18,0x03,0xa4,0x34, +0x10,0x1f,0x42,0x24,0x2a,0xb0,0x03,0x3c,0x00,0x00,0x82,0xac,0x3c,0x00,0xbf,0xaf, +0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf, +0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0x2c,0x00,0x63,0x34,0x00,0x00,0x69,0x8c,0xff,0x00,0x02,0x24, +0xff,0x00,0x24,0x31,0xbe,0x00,0x82,0x10,0x00,0x80,0x22,0x31,0x37,0x00,0x40,0x10, +0x00,0xff,0x02,0x3c,0x00,0x80,0x02,0x3c,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24, +0x14,0x00,0x82,0x10,0x02,0x80,0x03,0x3c,0x38,0x15,0x70,0x24,0xff,0x00,0x23,0x31, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x6c,0x25,0x05,0x8e, +0x25,0xb0,0x02,0x3c,0xff,0x00,0x28,0x31,0x7c,0x03,0x42,0x34,0x00,0x00,0x48,0xa4, +0x21,0x30,0x60,0x00,0x00,0x25,0x03,0xae,0x9c,0x24,0x09,0xa2,0x0a,0x00,0x04,0x24, +0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x01,0x00,0x03,0x24, +0x74,0x25,0x03,0xa2,0x02,0x80,0x02,0x3c,0x38,0x15,0x44,0x24,0x74,0x25,0x83,0x90, +0x01,0x00,0x02,0x24,0x28,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,0x38,0x15,0x70,0x24, +0x75,0x25,0x02,0x92,0x00,0x00,0x00,0x00,0x08,0x00,0x40,0x10,0x00,0x04,0x03,0x3c, +0x10,0x0b,0x02,0x8e,0x08,0x0b,0x04,0x8e,0x24,0x10,0x43,0x00,0x25,0x20,0x82,0x00, +0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x0b,0x04,0xae,0x3c,0x00,0xbf,0x8f, +0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f, +0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f, +0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x24,0x10,0x22,0x01, +0xcb,0xff,0x40,0x10,0xff,0x00,0x02,0x24,0x02,0x80,0x02,0x3c,0x38,0x15,0x43,0x24, +0x9c,0x24,0x62,0x90,0x20,0xb0,0x03,0x3c,0xb0,0x03,0xa4,0x34,0x00,0x12,0x02,0x00, +0x21,0x10,0x43,0x00,0x0c,0x00,0x49,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0xac, +0xdf,0x07,0x00,0x08,0xff,0x00,0x24,0x31,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0x21,0x88,0x80,0x00,0xb0,0x03,0x55,0x34, +0x01,0x00,0x13,0x24,0x21,0xb0,0x80,0x00,0x02,0x00,0x17,0x24,0x01,0x00,0x1e,0x24, +0x73,0x08,0x00,0x08,0x21,0xa0,0x80,0x00,0x20,0x00,0x02,0x24,0x61,0x00,0x82,0x14, +0x02,0x80,0x02,0x3c,0x50,0x93,0x46,0xac,0x21,0x20,0xc0,0x00,0x02,0x00,0x82,0x90, +0x75,0x25,0xc5,0x92,0x03,0x00,0x83,0x90,0x08,0x00,0xc6,0x24,0xff,0x00,0x52,0x30, +0x10,0x00,0xbe,0x14,0x7f,0x00,0x63,0x30,0x02,0x80,0x04,0x3c,0xf1,0x3d,0x82,0x90, +0x00,0x00,0x00,0x00,0x7f,0x00,0x42,0x30,0x07,0x00,0x62,0x10,0x25,0xb0,0x05,0x3c, +0xf2,0x23,0xc2,0x96,0x1e,0x03,0xa5,0x34,0x10,0x00,0x42,0x34,0x00,0x00,0xa2,0xa4, +0xf1,0x3d,0x83,0xa0,0xf2,0x23,0xc2,0xa6,0x31,0x00,0x42,0x2e,0x0b,0x00,0x40,0x10, +0x30,0x00,0x02,0x24,0x01,0x80,0x02,0x3c,0x84,0x7f,0x42,0x24,0xc0,0x18,0x12,0x00, +0x21,0x18,0x62,0x00,0x04,0x00,0x62,0x8c,0x02,0x80,0x03,0x3c,0x21,0x20,0xc0,0x00, +0x09,0xf8,0x40,0x00,0x4c,0x93,0x62,0xac,0x30,0x00,0x02,0x24,0x06,0x00,0x42,0x12, +0x02,0x80,0x05,0x3c,0x7c,0x8e,0xa5,0x24,0x00,0x00,0xa9,0x8c,0x00,0x00,0x00,0x00, +0x01,0x00,0x33,0xa1,0x01,0x00,0x37,0xa1,0x75,0x25,0x82,0x92,0x00,0x00,0x00,0x00, +0x3f,0x00,0x5e,0x14,0xff,0x00,0x02,0x24,0x0c,0x00,0x10,0x92,0x00,0x00,0x00,0x00, +0xff,0x00,0x09,0x32,0x3a,0x00,0x22,0x11,0x20,0x10,0x02,0x3c,0x9c,0x24,0x90,0xa2, +0x9c,0x24,0x28,0x92,0x6c,0x25,0x25,0x8e,0xff,0x00,0x03,0x31,0x00,0x1a,0x03,0x00, +0x21,0x18,0x62,0x00,0x25,0xb0,0x02,0x3c,0x7c,0x03,0x42,0x34,0x00,0x00,0xa9,0xae, +0x21,0x30,0x60,0x00,0x00,0x00,0x48,0xa4,0x0a,0x00,0x04,0x24,0x00,0x25,0x23,0xae, +0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x6c,0x25,0x30,0x8e, +0x0a,0x00,0x04,0x24,0x00,0x00,0xb0,0xae,0x4d,0x01,0x00,0x0c,0xff,0xff,0x10,0x32, +0x02,0x80,0x02,0x3c,0x02,0x80,0x05,0x3c,0x25,0x80,0x02,0x02,0xb2,0x3d,0xa3,0x90, +0x02,0x00,0x04,0x92,0x0f,0x00,0x63,0x30,0xaf,0xff,0x77,0x14,0x21,0x30,0x04,0x02, +0x00,0x00,0x02,0x8e,0x00,0x0c,0x03,0x3c,0x24,0x10,0x43,0x00,0x0d,0x00,0x43,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0x00,0x00,0x00,0x00,0x02,0x13,0x02,0x00, +0x3f,0x00,0x42,0x30,0x07,0x00,0x40,0x14,0x05,0x00,0x03,0x24,0x14,0x00,0x02,0x8e, +0x00,0x00,0x00,0x00,0x42,0x15,0x02,0x00,0x07,0x00,0x42,0x30,0xa1,0xff,0x43,0x10, +0x02,0x80,0x02,0x3c,0xbe,0x48,0x00,0x0c,0x01,0x00,0x04,0x24,0x62,0x24,0x22,0x96, +0x75,0x25,0x33,0xa2,0x01,0x00,0x42,0x24,0x52,0x08,0x00,0x08,0x62,0x24,0x22,0xa6, +0x02,0x80,0x05,0x3c,0x38,0x15,0xa2,0x24,0xf5,0x07,0x00,0x08,0x74,0x25,0x40,0xa0, +0x02,0x80,0x02,0x3c,0xa4,0x3e,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34, +0x00,0x00,0x64,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0xfb,0x07,0x00,0x08,0x02,0x80,0x03,0x3c,0xc8,0xff,0xbd,0x27, +0xff,0xff,0xa8,0x30,0x02,0x80,0x02,0x3c,0x25,0x40,0x02,0x01,0x30,0x00,0xb6,0xaf, +0x20,0x00,0xb2,0xaf,0x34,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x03,0x8d, +0xff,0xff,0xd2,0x30,0x21,0xb0,0xa0,0x00,0x00,0xc0,0x02,0x24,0x08,0x00,0x45,0x26, +0x04,0x00,0x06,0x8d,0x24,0x18,0x62,0x00,0xff,0x3f,0xa5,0x30,0xf0,0xff,0x02,0x3c, +0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x80,0x05,0x3c, +0x25,0x18,0x65,0x00,0xff,0x01,0xc6,0x34,0x00,0x00,0x03,0xad,0x04,0x00,0x06,0xad, +0x21,0x48,0x80,0x00,0xff,0xff,0xe7,0x30,0x18,0x00,0x12,0xa5,0x1a,0x00,0x07,0xa1, +0x18,0x00,0x03,0x8d,0xff,0x7f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x02,0x80,0x15,0x3c,0x18,0x00,0x03,0xad,0x38,0x15,0xa5,0x26,0xee,0x23,0xa3,0x90, +0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x24,0xee,0x23,0xa2,0xa0,0x18,0x00,0x04,0x8d, +0xff,0x80,0x02,0x3c,0x20,0x00,0x45,0x26,0xff,0xff,0x42,0x34,0x7f,0x00,0x63,0x30, +0xff,0xff,0xb2,0x30,0x24,0x20,0x82,0x00,0x00,0x1e,0x03,0x00,0x25,0xb0,0x02,0x3c, +0xc0,0x00,0x42,0x34,0x25,0x20,0x83,0x00,0x07,0x00,0x45,0x32,0x18,0x00,0x04,0xad, +0x00,0x00,0x52,0xa4,0x03,0x00,0xa0,0x10,0xff,0xff,0x42,0x32,0x08,0x00,0x42,0x26, +0xff,0xff,0x42,0x30,0x38,0x15,0xb4,0x26,0xd0,0x25,0x86,0x8e,0xd4,0x25,0x90,0x8e, +0xf8,0xff,0x52,0x30,0x21,0x10,0xd2,0x00,0x2b,0x10,0x02,0x02,0x31,0x00,0x40,0x10, +0xff,0x00,0x33,0x31,0x23,0x80,0x06,0x02,0x21,0x28,0xc0,0x02,0xff,0xff,0x07,0x32, +0x01,0x00,0x11,0x24,0x21,0x20,0x60,0x02,0x10,0x01,0x00,0x0c,0x10,0x00,0xb1,0xaf, +0x23,0x18,0x50,0x02,0xff,0xff,0x72,0x30,0x22,0x10,0x02,0x3c,0x21,0x10,0x42,0x02, +0x21,0x20,0x60,0x02,0x4d,0x01,0x00,0x0c,0xd0,0x25,0x82,0xae,0x21,0x28,0xd0,0x02, +0x21,0x38,0x40,0x02,0x21,0x20,0x60,0x02,0x10,0x00,0xb1,0xaf,0x22,0x10,0x06,0x3c, +0x10,0x01,0x00,0x0c,0x38,0x15,0xb1,0x26,0xd0,0x25,0x23,0x8e,0x25,0xb0,0x10,0x3c, +0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,0x4d,0x01,0x00,0x0c, +0x00,0x00,0x00,0x00,0xd0,0x25,0x25,0x8e,0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36, +0x00,0x00,0x45,0xac,0x00,0x00,0x83,0x90,0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f, +0x10,0x00,0x63,0x34,0x00,0x00,0x83,0xa0,0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6, +0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f, +0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03, +0x38,0x00,0xbd,0x27,0x21,0x28,0xc0,0x02,0x21,0x20,0x60,0x02,0x21,0x38,0x40,0x02, +0x01,0x00,0x02,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa2,0xaf,0xd0,0x25,0x83,0x8e, +0x38,0x15,0xb1,0x26,0x25,0xb0,0x10,0x3c,0x21,0x18,0x72,0x00,0xd0,0x25,0x83,0xae, +0xd0,0x25,0x23,0x8e,0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac, +0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0xd0,0x25,0x25,0x8e,0xec,0x00,0x02,0x36, +0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac,0x00,0x00,0x83,0x90,0xc2,0x00,0x10,0x36, +0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34,0x00,0x00,0x83,0xa0,0x30,0x00,0xb6,0x8f, +0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c, +0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0xbf,0x00,0x42,0x34, +0x00,0x00,0x43,0x90,0x21,0x28,0x00,0x00,0x08,0x00,0x06,0x24,0x04,0x00,0x63,0x2c, +0x12,0x00,0x60,0x14,0x21,0x88,0x80,0x00,0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x4c,0x3b,0x63,0x24, +0x04,0x00,0x64,0x8c,0x00,0x00,0x23,0xae,0x04,0x00,0x71,0xac,0x00,0x00,0x91,0xac, +0x04,0x00,0x24,0xae,0x00,0x60,0x82,0x40,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x08,0x00,0x82,0x94, +0x02,0x80,0x04,0x3c,0x58,0x45,0x00,0x0c,0x25,0x20,0x44,0x00,0x00,0x60,0x10,0x40, +0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x08,0x00,0x25,0x8e, +0x0c,0x00,0x26,0x96,0x14,0x00,0x27,0x96,0xa7,0x08,0x00,0x0c,0x09,0x00,0x04,0x24, +0x04,0x00,0x23,0x8e,0x00,0x00,0x22,0x8e,0x21,0x20,0x20,0x02,0x00,0x00,0x62,0xac, +0x04,0x00,0x43,0xac,0x00,0x00,0x31,0xae,0x40,0x49,0x00,0x0c,0x04,0x00,0x31,0xae, +0x00,0x60,0x90,0x40,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0xe8,0x25,0x63,0x24,0x18,0x03,0x42,0x34,0xe0,0xff,0xbd,0x27,0xff,0xff,0x84,0x30, +0x00,0x00,0x43,0xac,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf, +0x1c,0x00,0xbf,0xaf,0xff,0xff,0xb0,0x30,0xff,0xff,0xd2,0x30,0x1f,0x49,0x00,0x0c, +0xff,0xff,0xf1,0x30,0x21,0x20,0x40,0x00,0x0a,0x00,0x40,0x10,0x21,0x18,0x00,0x00, +0x08,0x00,0x43,0x94,0x14,0x00,0x50,0xac,0x02,0x80,0x02,0x3c,0x25,0x18,0x62,0x00, +0x18,0x00,0x63,0x24,0x06,0x00,0x71,0xa4,0x42,0x09,0x00,0x0c,0x04,0x00,0x72,0xa4, +0x01,0x00,0x03,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0x2a,0xb0,0x04,0x3c,0x28,0x00,0x85,0x34,0x03,0x00,0x82,0x90,0x04,0x00,0x84,0x24, +0x05,0x00,0x40,0x14,0x2b,0x18,0xa4,0x00,0xfb,0xff,0x60,0x10,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xa0,0x26,0x63,0x24,0x18,0x03,0x42,0x34, +0xd0,0xff,0xbd,0x27,0x00,0x00,0x43,0xac,0x24,0x00,0xb3,0xaf,0x28,0x00,0xbf,0xaf, +0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x9c,0x09,0x00,0x0c,0x18,0x00,0xb0,0xaf, +0x06,0x00,0x40,0x10,0x02,0x80,0x13,0x3c,0x38,0x15,0x63,0x26,0x82,0x0b,0x62,0x90, +0x00,0x00,0x00,0x00,0x9f,0x00,0x40,0x14,0x00,0xc0,0x04,0x34,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,0x36,0x00,0x42,0x34, +0x00,0x00,0x43,0x90,0x38,0x15,0x66,0x26,0xd8,0x25,0xc5,0x8c,0xc0,0x18,0x03,0x00, +0x23,0xb0,0x04,0x3c,0xf0,0x07,0x63,0x30,0xff,0x1f,0x02,0x3c,0x21,0x18,0x64,0x00, +0xff,0xff,0x42,0x34,0x24,0x20,0x62,0x00,0x23,0x88,0x85,0x00,0x00,0x04,0x22,0x26, +0x2b,0x28,0x85,0x00,0x88,0x25,0xc3,0x8c,0x0b,0x88,0x45,0x00,0xe1,0x01,0x22,0x2e, +0x84,0x25,0xc3,0xac,0xdc,0x25,0xc4,0xac,0x8e,0x25,0xc0,0xa4,0x14,0x00,0x40,0x14, +0x8d,0x25,0xc0,0xa0,0x20,0xfe,0x82,0x24,0x20,0x02,0x83,0x24,0x0a,0x18,0x45,0x00, +0x23,0x10,0x02,0x3c,0xff,0x03,0x42,0x34,0x2b,0x10,0x43,0x00,0x21,0x28,0x60,0x00, +0x34,0x00,0x40,0x14,0xd8,0x25,0xc3,0xac,0xdc,0x25,0xc2,0x8c,0x00,0x00,0x00,0x00, +0x2b,0x18,0x45,0x00,0x23,0x88,0x45,0x00,0x03,0x00,0x60,0x10,0xe1,0x01,0x22,0x2e, +0x00,0x04,0x31,0x26,0xe1,0x01,0x22,0x2e,0x0e,0x00,0x40,0x10,0x38,0x15,0x70,0x26, +0x38,0x15,0x70,0x26,0xdc,0x25,0x03,0x8e,0xd8,0x25,0x04,0x8e,0x00,0x00,0x00,0x00, +0x2b,0x10,0x83,0x00,0x26,0x00,0x40,0x14,0x2b,0x10,0x64,0x00,0x52,0x00,0x40,0x14, +0x25,0xb0,0x02,0x3c,0x80,0x00,0x03,0x24,0xd0,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x38,0x15,0x70,0x26,0xd8,0x25,0x03,0x96,0x2a,0xb0,0x02,0x3c,0x35,0x00,0x42,0x34, +0xc2,0x88,0x03,0x00,0x00,0x00,0x51,0xa0,0x4b,0x20,0x00,0x0c,0x00,0x00,0x00,0x00, +0x8e,0x25,0x03,0x96,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x08,0x0b,0x02,0x8e,0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,0x25,0x10,0x43,0x00, +0x00,0x00,0x82,0xac,0x28,0x00,0xbf,0x8f,0x08,0x0b,0x02,0xae,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x30,0x00,0xbd,0x27,0x00,0xfc,0xa5,0x24,0xde,0x09,0x00,0x08,0xd8,0x25,0xc5,0xac, +0x84,0x25,0x05,0x8e,0x21,0x30,0x80,0x00,0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x84,0x25,0x03,0x8e,0x8e,0x25,0x05,0x96, +0xd8,0x25,0x02,0x8e,0x21,0x18,0x71,0x00,0x21,0x28,0x25,0x02,0x21,0x10,0x51,0x00, +0x09,0x00,0x04,0x24,0xd8,0x25,0x02,0xae,0x84,0x25,0x03,0xae,0x4d,0x01,0x00,0x0c, +0x8e,0x25,0x05,0xa6,0x38,0x15,0x70,0x26,0xd8,0x25,0x03,0x96,0x2a,0xb0,0x02,0x3c, +0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,0x00,0x00,0x51,0xa0,0x4b,0x20,0x00,0x0c, +0x00,0x00,0x00,0x00,0x8e,0x25,0x03,0x96,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34, +0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x08,0x0b,0x02,0x8e,0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c, +0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x28,0x00,0xbf,0x8f,0x08,0x0b,0x02,0xae, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0xe0,0x25,0x02,0x8e,0x84,0x25,0x05,0x8e, +0x21,0x30,0x80,0x00,0x23,0x88,0x44,0x00,0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x84,0x25,0x03,0x8e,0x8e,0x25,0x02,0x96, +0xdc,0x25,0x12,0x96,0x21,0x18,0x71,0x00,0x21,0x10,0x22,0x02,0x23,0x10,0x11,0x3c, +0x84,0x25,0x03,0xae,0x8e,0x25,0x02,0xa6,0x0c,0x00,0x40,0x16,0xd8,0x25,0x11,0xae, +0x09,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,0x38,0x15,0x70,0x26,0x26,0x0a,0x00,0x08, +0x00,0x00,0x00,0x00,0x38,0x27,0x62,0x94,0x82,0x0b,0x60,0xa0,0x86,0x27,0x00,0x0c, +0x21,0x20,0x44,0x00,0xbb,0x09,0x00,0x08,0x00,0x00,0x00,0x00,0x4d,0x01,0x00,0x0c, +0x09,0x00,0x04,0x24,0x84,0x25,0x05,0x8e,0x09,0x00,0x04,0x24,0x23,0x10,0x06,0x3c, +0x21,0x38,0x40,0x02,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x84,0x25,0x03,0x8e, +0x8e,0x25,0x02,0x96,0x21,0x20,0x51,0x02,0x21,0x18,0x72,0x00,0x21,0x10,0x42,0x02, +0xd8,0x25,0x04,0xae,0x09,0x00,0x04,0x24,0x84,0x25,0x03,0xae,0x55,0x0a,0x00,0x08, +0x8e,0x25,0x02,0xa6,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x05,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x09,0x00,0x02,0x24,0x02,0x80,0x09,0x3c, +0x38,0x15,0x28,0x25,0xf4,0x23,0x06,0x8d,0xff,0xff,0x02,0x34,0x44,0x00,0xc2,0x10, +0x21,0x38,0x80,0x00,0x2b,0x10,0xc7,0x00,0x34,0x00,0x40,0x10,0x02,0x19,0x06,0x00, +0x21,0x10,0xc7,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0xf4,0x23,0x06,0xad, +0xf8,0x23,0x02,0xad,0x38,0x15,0x26,0x25,0x05,0x00,0xc4,0x90,0xff,0xff,0x02,0x34, +0xff,0x00,0x83,0x30,0x33,0x00,0x62,0x10,0x00,0x11,0x07,0x00,0xff,0x00,0x84,0x30, +0x2b,0x10,0x87,0x00,0x20,0x00,0x40,0x10,0x03,0x19,0x04,0x00,0x03,0x11,0x04,0x00, +0x21,0x18,0x87,0x00,0x23,0x18,0x62,0x00,0x10,0x00,0x64,0x24,0x05,0x00,0xc4,0xa0, +0xf8,0x23,0xc3,0xac,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x45,0x00,0x38,0x15,0x23,0x25,0x80,0x10,0x02,0x00,0x21,0x28,0x43,0x00, +0x80,0x11,0xa6,0x8c,0x00,0x21,0x07,0x00,0xff,0xff,0xc2,0x38,0x0a,0x30,0x82,0x00, +0x2b,0x18,0xc7,0x00,0x07,0x00,0x60,0x10,0x21,0x10,0xc7,0x00,0x02,0x19,0x06,0x00, +0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0x80,0x11,0xa6,0xac,0x08,0x00,0xe0,0x03, +0x84,0x11,0xa2,0xac,0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00,0x80,0x11,0xa2,0xac, +0x08,0x00,0xe0,0x03,0x84,0x11,0xa2,0xac,0x21,0x10,0x87,0x00,0x23,0x10,0x43,0x00, +0x05,0x00,0xc2,0xa0,0x95,0x0a,0x00,0x08,0xf8,0x23,0xc2,0xac,0x21,0x10,0xc7,0x00, +0x23,0x10,0x43,0x00,0xf4,0x23,0x02,0xad,0xf8,0x23,0x02,0xad,0x38,0x15,0x26,0x25, +0x05,0x00,0xc4,0x90,0xff,0xff,0x02,0x34,0xff,0x00,0x83,0x30,0xcf,0xff,0x62,0x14, +0x00,0x11,0x07,0x00,0x21,0x20,0x40,0x00,0x8b,0x0a,0x00,0x08,0x05,0x00,0xc2,0xa0, +0x00,0x31,0x04,0x00,0x7d,0x0a,0x00,0x08,0xf4,0x23,0x06,0xad,0x63,0x00,0x82,0x24, +0x77,0x00,0x42,0x2c,0x00,0x00,0x85,0x28,0x04,0x00,0x40,0x10,0x21,0x18,0x00,0x00, +0x64,0x00,0x82,0x24,0x64,0x00,0x03,0x24,0x0b,0x18,0x45,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0xe8,0xff,0xbd,0x27,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf, +0x0c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0x04,0x00,0x42,0x28, +0x0d,0x00,0x40,0x14,0x21,0x38,0xa0,0x00,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24, +0x0c,0x24,0x43,0x8c,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x63,0x24, +0x0c,0x24,0x43,0xac,0x04,0x00,0xa4,0x90,0x18,0x00,0xbd,0x27,0x42,0x20,0x04,0x00, +0xc3,0x0a,0x00,0x08,0x96,0xff,0x84,0x24,0x02,0x80,0x10,0x3c,0x25,0xb0,0x06,0x3c, +0x38,0x15,0x05,0x26,0x24,0x08,0xc3,0x34,0x00,0x00,0x64,0x8c,0x08,0x24,0xa2,0x8c, +0x00,0x02,0x84,0x30,0x01,0x00,0x42,0x24,0x21,0x00,0x80,0x10,0x08,0x24,0xa2,0xac, +0x05,0x00,0xe5,0x90,0x01,0x00,0x02,0x24,0x60,0x00,0xa6,0x30,0x42,0x31,0x06,0x00, +0x42,0x00,0xc2,0x10,0x02,0x00,0xc2,0x28,0x51,0x00,0x40,0x14,0x02,0x00,0x02,0x24, +0x47,0x00,0xc2,0x10,0x03,0x00,0x02,0x24,0x2e,0x00,0xc2,0x10,0x1f,0x00,0xa2,0x30, +0xc3,0x0a,0x00,0x0c,0x21,0x20,0x00,0x01,0x38,0x15,0x05,0x26,0x04,0x24,0xa4,0x8c, +0x21,0x30,0x40,0x00,0xff,0xff,0x02,0x34,0x31,0x00,0x82,0x10,0x00,0x00,0x00,0x00, +0x2b,0x10,0x86,0x00,0x26,0x00,0x40,0x10,0x02,0x19,0x04,0x00,0x21,0x10,0x86,0x00, +0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x23,0x20,0x43,0x00,0x10,0x00,0x84,0x24, +0x21,0x10,0xc0,0x00,0x18,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x04,0x24,0xa4,0xac, +0x05,0x00,0xe2,0x90,0x6b,0x0c,0xc3,0x34,0x82,0x31,0x02,0x00,0x00,0x00,0x66,0xa0, +0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x82,0x24,0x01,0x00,0x02,0x24,0x21,0x00,0xc2,0x10,0x00,0x00,0x00,0x00, +0x02,0x00,0xc2,0x28,0x30,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x25,0x00,0xc2,0x10, +0xe9,0xff,0x03,0x24,0x03,0x00,0x02,0x24,0xd9,0xff,0xc2,0x14,0xce,0xff,0x03,0x24, +0x05,0x00,0xe2,0x90,0x00,0x00,0x00,0x00,0x3e,0x00,0x42,0x30,0xf8,0x0a,0x00,0x08, +0x23,0x40,0x62,0x00,0x40,0x10,0x02,0x00,0x23,0x0b,0x00,0x08,0xce,0xff,0x03,0x24, +0x21,0x10,0x86,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x23,0x10,0x43,0x00, +0x04,0x24,0xa2,0xac,0x18,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x21,0x10,0xc0,0x00, +0x00,0x21,0x06,0x00,0x00,0x0b,0x00,0x08,0x04,0x24,0xa4,0xac,0x1f,0x00,0xa2,0x30, +0x40,0x10,0x02,0x00,0x05,0x00,0x03,0x24,0xf8,0x0a,0x00,0x08,0x23,0x40,0x62,0x00, +0x05,0x00,0xe2,0x90,0x05,0x00,0x03,0x24,0x36,0x0b,0x00,0x08,0x3e,0x00,0x42,0x30, +0x1f,0x00,0xa2,0x30,0x40,0x10,0x02,0x00,0xe9,0xff,0x03,0x24,0xf8,0x0a,0x00,0x08, +0x23,0x40,0x62,0x00,0x05,0x00,0xe2,0x90,0x3f,0x0b,0x00,0x08,0x3e,0x00,0x42,0x30, +0xb3,0xff,0xc0,0x14,0x1f,0x00,0xa2,0x30,0x40,0x10,0x02,0x00,0xfd,0xff,0x03,0x24, +0xf8,0x0a,0x00,0x08,0x23,0x40,0x62,0x00,0xad,0xff,0xc0,0x14,0xfd,0xff,0x03,0x24, +0x05,0x00,0xe2,0x90,0x48,0x0b,0x00,0x08,0x3e,0x00,0x42,0x30,0xe0,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x0c,0x00,0x82,0x8c, +0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,0x29,0x00,0x40,0x14, +0x21,0x80,0xa0,0x00,0x00,0x00,0xa4,0x8c,0x02,0x80,0x11,0x3c,0x3f,0x00,0x84,0x30, +0x40,0x20,0x04,0x00,0xc3,0x0a,0x00,0x0c,0x96,0xff,0x84,0x24,0x38,0x15,0x25,0x26, +0xfc,0x23,0xa4,0x8c,0x21,0x18,0x40,0x00,0xff,0xff,0x02,0x34,0x3c,0x00,0x82,0x10, +0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x27,0x00,0x40,0x10,0x21,0x10,0x83,0x00, +0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00,0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24, +0xfc,0x23,0xa4,0xac,0x00,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00, +0x7e,0x00,0x84,0x30,0xc3,0x0a,0x00,0x0c,0x96,0xff,0x84,0x24,0x38,0x15,0x25,0x26, +0x00,0x24,0xa4,0x8c,0x21,0x18,0x40,0x00,0xff,0xff,0x02,0x34,0x25,0x00,0x82,0x10, +0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x0b,0x00,0x40,0x10,0x21,0x10,0x83,0x00, +0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00,0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24, +0x00,0x24,0xa4,0xac,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x02,0x19,0x04,0x00,0x23,0x10,0x43,0x00,0x20,0x00,0xbd,0x27, +0x08,0x00,0xe0,0x03,0x00,0x24,0xa2,0xac,0x02,0x19,0x04,0x00,0x23,0x10,0x43,0x00, +0xfc,0x23,0xa2,0xac,0x00,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00, +0x7e,0x00,0x84,0x30,0xc3,0x0a,0x00,0x0c,0x96,0xff,0x84,0x24,0x38,0x15,0x25,0x26, +0x00,0x24,0xa4,0x8c,0x21,0x18,0x40,0x00,0xff,0xff,0x02,0x34,0xde,0xff,0x82,0x14, +0x2b,0x10,0x83,0x00,0x00,0x21,0x03,0x00,0x79,0x0b,0x00,0x08,0x00,0x24,0xa4,0xac, +0x00,0x21,0x03,0x00,0x65,0x0b,0x00,0x08,0xfc,0x23,0xa4,0xac,0x98,0xff,0xbd,0x27, +0x02,0x80,0x02,0x3c,0x58,0x00,0xb6,0xaf,0x64,0x00,0xbf,0xaf,0x60,0x00,0xbe,0xaf, +0x5c,0x00,0xb7,0xaf,0x54,0x00,0xb5,0xaf,0x50,0x00,0xb4,0xaf,0x4c,0x00,0xb3,0xaf, +0x48,0x00,0xb2,0xaf,0x44,0x00,0xb1,0xaf,0x40,0x00,0xb0,0xaf,0x38,0x15,0x56,0x24, +0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34,0x00,0x00,0x43,0x8c,0xc0,0x25,0xc7,0x8e, +0x00,0x00,0x00,0x00,0x33,0x00,0xe3,0x10,0xc4,0x25,0xc3,0xae,0x2b,0x10,0x67,0x00, +0xbf,0x00,0x40,0x14,0x2b,0x10,0xe3,0x00,0xe9,0x00,0x40,0x14,0x02,0x80,0x02,0x3c, +0x38,0x15,0x44,0x24,0x94,0x25,0x83,0x94,0x02,0x80,0x02,0x3c,0x21,0x88,0x00,0x00, +0x18,0x00,0x40,0x1a,0x25,0x98,0x62,0x00,0x21,0xf0,0x80,0x00,0x01,0x00,0x14,0x24, +0x21,0x20,0x00,0x00,0x21,0x80,0x93,0x00,0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00, +0x07,0x00,0xa0,0x10,0x01,0x00,0x22,0x26,0x04,0x00,0x02,0x8e,0x00,0xf0,0x03,0x3c, +0x00,0x20,0x04,0x3c,0x24,0x10,0x43,0x00,0x1f,0x00,0x44,0x10,0x06,0x00,0x22,0x26, +0xff,0xff,0x51,0x30,0x82,0x16,0x05,0x00,0x01,0x00,0x42,0x30,0x35,0x00,0x54,0x10, +0x02,0x80,0x03,0x3c,0x80,0x20,0x11,0x00,0x2a,0x10,0x92,0x00,0xed,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0x38,0x00,0xa4,0x8f,0x40,0x49,0x00,0x0c,0x00,0x00,0x00,0x00, +0x02,0x80,0x02,0x3c,0x08,0x04,0x44,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00, +0xc2,0x2e,0x00,0x0c,0x21,0x38,0x00,0x00,0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34, +0x00,0x00,0x43,0x8c,0xc0,0x25,0xc7,0x8e,0x00,0x00,0x00,0x00,0xcf,0xff,0xe3,0x14, +0xc4,0x25,0xc3,0xae,0x25,0xb0,0x04,0x3c,0x00,0x01,0x82,0x34,0x00,0x00,0x47,0xac, +0xdc,0x0b,0x00,0x08,0xc0,0x25,0xc7,0xae,0xc8,0x0c,0xc2,0x8f,0x00,0x00,0x00,0x00, +0x01,0x00,0x42,0x24,0xc8,0x0c,0xc2,0xaf,0x0c,0x00,0x04,0x8e,0x0c,0x00,0x02,0x24, +0x3f,0x00,0x83,0x30,0x7b,0x00,0x62,0x10,0x21,0x28,0xc0,0x03,0x3f,0x00,0x83,0x30, +0x0d,0x00,0x02,0x24,0x70,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x3f,0x00,0x83,0x30, +0x0e,0x00,0x02,0x24,0x04,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x8e, +0xd0,0x0b,0x00,0x08,0x06,0x00,0x22,0x26,0xd4,0x0c,0xc2,0x8f,0x00,0x00,0x00,0x00, +0x01,0x00,0x42,0x24,0xd4,0x0c,0xc2,0xaf,0x00,0x00,0x05,0x8e,0xd0,0x0b,0x00,0x08, +0x06,0x00,0x22,0x26,0x38,0x15,0x62,0x8c,0x00,0x00,0x00,0x00,0x42,0x11,0x02,0x00, +0x01,0x00,0x42,0x30,0x05,0x00,0x54,0x10,0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30, +0x21,0x10,0x51,0x00,0xd5,0x0b,0x00,0x08,0xff,0xff,0x51,0x30,0x38,0x15,0x64,0x24, +0x01,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x24,0x00,0x40,0x14,0x02,0x80,0x04,0x3c, +0x04,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x04,0x00,0x0f,0x00,0x45,0x30, +0x08,0x00,0xa3,0x28,0x1c,0x00,0x60,0x10,0x02,0x17,0x04,0x00,0x03,0x00,0x43,0x30, +0x08,0x00,0x60,0x10,0x00,0xc0,0x02,0x3c,0x24,0x10,0x82,0x00,0x16,0x00,0x40,0x14, +0x03,0x00,0x02,0x24,0x15,0x00,0x62,0x10,0x02,0x80,0x04,0x3c,0x14,0x00,0x60,0x10, +0x38,0x15,0x82,0x24,0x80,0x10,0x11,0x00,0x21,0xa8,0x53,0x00,0x02,0x80,0x02,0x3c, +0x38,0x15,0x42,0x24,0x21,0x18,0xa2,0x00,0xec,0xff,0xa2,0x8e,0xf0,0x04,0x77,0x90, +0x25,0xb0,0x03,0x3c,0xd4,0x02,0x63,0x34,0x21,0x28,0xa0,0x02,0x21,0x20,0x00,0x02, +0x00,0x00,0x62,0xac,0xcd,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00, +0x77,0x0a,0x00,0x0c,0x21,0x28,0xe0,0x02,0x02,0x80,0x04,0x3c,0x38,0x15,0x82,0x24, +0x01,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x80,0x00,0x74,0x10,0x00,0x00,0x00,0x00, +0x02,0x80,0x04,0x3c,0x38,0x15,0x84,0x24,0x01,0x00,0x83,0x90,0x02,0x00,0x02,0x24, +0x08,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00, +0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,0x21,0x10,0x51,0x00,0xd5,0x0b,0x00,0x08, +0xff,0xff,0x51,0x30,0x04,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x04,0x00, +0x0f,0x00,0x46,0x30,0x08,0x00,0xc3,0x28,0xf3,0xff,0x60,0x10,0x02,0x17,0x04,0x00, +0x03,0x00,0x42,0x30,0xf0,0xff,0x40,0x14,0x80,0x10,0x11,0x00,0x21,0xa8,0x53,0x00, +0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0x21,0x18,0xc2,0x00,0xec,0xff,0xa2,0x8e, +0xf0,0x04,0x77,0x90,0x25,0xb0,0x03,0x3c,0xd4,0x02,0x63,0x34,0x21,0x28,0xa0,0x02, +0x21,0x20,0x00,0x02,0x00,0x00,0x62,0xac,0xcd,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00, +0x21,0x20,0x40,0x00,0x77,0x0a,0x00,0x0c,0x21,0x28,0xe0,0x02,0x00,0x00,0x05,0x8e, +0x49,0x0c,0x00,0x08,0xc2,0x13,0x05,0x00,0xd0,0x0c,0xa2,0x8c,0x00,0x00,0x00,0x00, +0x01,0x00,0x42,0x24,0xd0,0x0c,0xa2,0xac,0x0c,0x00,0x04,0x8e,0xfc,0x0b,0x00,0x08, +0x3f,0x00,0x83,0x30,0xcc,0x0c,0xc2,0x8f,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24, +0xcc,0x0c,0xc2,0xaf,0x0c,0x00,0x04,0x8e,0xf8,0x0b,0x00,0x08,0x3f,0x00,0x83,0x30, +0xc8,0x25,0xc2,0x8e,0xff,0xff,0x71,0x30,0x23,0x10,0x47,0x00,0xff,0xff,0x50,0x30, +0x21,0x18,0x11,0x02,0xff,0xff,0x72,0x30,0x1f,0x49,0x00,0x0c,0x21,0x20,0x40,0x02, +0x74,0x00,0x40,0x10,0x38,0x00,0xa2,0xaf,0x38,0x00,0xa3,0x8f,0xc0,0x25,0xc6,0x8e, +0x21,0x38,0x00,0x02,0x08,0x00,0x62,0x8c,0x08,0x00,0x04,0x24,0x10,0x00,0xa0,0xaf, +0x21,0x18,0x52,0x00,0x21,0x28,0x40,0x00,0x90,0x25,0xc3,0xae,0x10,0x01,0x00,0x0c, +0x94,0x25,0xc2,0xae,0x4d,0x01,0x00,0x0c,0x08,0x00,0x04,0x24,0x94,0x25,0xc5,0x8e, +0x25,0xb0,0x04,0x3c,0x24,0x10,0x02,0x3c,0x21,0x28,0xb0,0x00,0x00,0x01,0x90,0x34, +0x00,0x00,0x02,0xae,0x21,0x38,0x20,0x02,0x08,0x00,0x04,0x24,0x24,0x10,0x06,0x3c, +0xc0,0x25,0xc2,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xc4,0x25,0xc3,0x8e, +0x08,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,0xc0,0x25,0xc3,0xae,0xc0,0x25,0xc2,0x8e, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xae,0xbc,0x0b,0x00,0x08,0x02,0x80,0x02,0x3c, +0x23,0x10,0x67,0x00,0xff,0xff,0x52,0x30,0x1f,0x49,0x00,0x0c,0x21,0x20,0x40,0x02, +0x53,0x00,0x40,0x10,0x38,0x00,0xa2,0xaf,0x38,0x00,0xa3,0x8f,0xc0,0x25,0xc6,0x8e, +0x08,0x00,0x04,0x24,0x08,0x00,0x62,0x8c,0x21,0x38,0x40,0x02,0x10,0x00,0xa0,0xaf, +0x21,0x18,0x52,0x00,0x21,0x28,0x40,0x00,0x90,0x25,0xc3,0xae,0x10,0x01,0x00,0x0c, +0x94,0x25,0xc2,0xae,0xc4,0x25,0xc3,0x8e,0x08,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c, +0xc0,0x25,0xc3,0xae,0xc0,0x25,0xc3,0x8e,0x25,0xb0,0x04,0x3c,0x00,0x01,0x82,0x34, +0x00,0x00,0x43,0xac,0xbc,0x0b,0x00,0x08,0x02,0x80,0x02,0x3c,0x04,0x00,0x04,0x8e, +0x00,0x00,0x00,0x00,0x02,0x14,0x04,0x00,0x0f,0x00,0x42,0x30,0x08,0x00,0x42,0x28, +0x06,0x00,0x40,0x10,0x00,0xc0,0x02,0x3c,0x02,0x17,0x04,0x00,0x03,0x00,0x42,0x30, +0x0b,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,0x00,0xc0,0x02,0x3c,0x24,0x10,0x82,0x00, +0x73,0xff,0x40,0x14,0x02,0x17,0x04,0x00,0x03,0x00,0x42,0x30,0x03,0x00,0x03,0x24, +0x6f,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x6d,0xff,0x40,0x10,0x02,0x80,0x03,0x3c, +0x38,0x15,0x62,0x8c,0x00,0x00,0x00,0x00,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30, +0x15,0x00,0x54,0x10,0x21,0xb8,0x00,0x00,0x80,0x10,0x11,0x00,0x21,0xa8,0x53,0x00, +0xec,0xff,0xa3,0x8e,0x25,0xb0,0x02,0x3c,0xd4,0x02,0x42,0x34,0x21,0x20,0x00,0x02, +0x21,0x28,0xa0,0x02,0x00,0x00,0x43,0xac,0xcd,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00, +0x21,0x20,0x40,0x00,0x77,0x0a,0x00,0x0c,0x21,0x28,0xe0,0x02,0x58,0xff,0xe0,0x16, +0x00,0x00,0x00,0x00,0x21,0x28,0xa0,0x02,0x4f,0x0b,0x00,0x0c,0x21,0x20,0x00,0x02, +0x41,0x0c,0x00,0x08,0x02,0x80,0x04,0x3c,0x02,0x14,0x04,0x00,0x0f,0x00,0x42,0x30, +0x38,0x15,0x63,0x24,0x21,0x10,0x43,0x00,0xf0,0x04,0x57,0x90,0xdb,0x0c,0x00,0x08, +0x80,0x10,0x11,0x00,0x25,0xb0,0x04,0x3c,0x44,0x44,0x02,0x3c,0xbc,0x02,0x83,0x34, +0x44,0x44,0x42,0x34,0x00,0x00,0x62,0xac,0xdd,0x0b,0x00,0x08,0x02,0x80,0x02,0x3c, +0xc4,0x25,0xc5,0x8e,0x25,0xb0,0x02,0x3c,0x00,0x01,0x43,0x34,0xbc,0x02,0x44,0x34, +0x66,0x66,0x02,0x3c,0x66,0x66,0x42,0x34,0x00,0x00,0x65,0xac,0x00,0x00,0x82,0xac, +0xdc,0x0b,0x00,0x08,0xc0,0x25,0xc5,0xae,0x00,0x80,0x02,0x3c,0x18,0x34,0x43,0x24, +0x25,0xb0,0x02,0x3c,0xc0,0xff,0xbd,0x27,0x18,0x03,0x42,0x34,0x38,0x00,0xbe,0xaf, +0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf, +0x3c,0x00,0xbf,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0x00,0x00,0x43,0xac,0x21,0xf0,0x00,0x00,0x02,0x80,0x14,0x3c, +0x02,0x80,0x15,0x3c,0x02,0x80,0x16,0x3c,0x02,0x80,0x17,0x3c,0x38,0x15,0x92,0x26, +0xf0,0x23,0x43,0x96,0x25,0xb0,0x04,0x3c,0x00,0x80,0x06,0x3c,0x18,0x03,0x85,0x34, +0x01,0x00,0x63,0x24,0x18,0x34,0xc2,0x24,0x00,0x00,0xa2,0xac,0xf0,0x23,0x43,0xa6, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0xc6,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0x00,0x00,0x00,0x00,0x11,0x00,0x42,0x2c, +0x08,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,0x02,0x80,0x04,0x3c,0xa4,0x3e,0x62,0x8c, +0xbc,0x3e,0x83,0x8c,0x02,0x80,0x06,0x3c,0xbc,0x3e,0x80,0xac,0x25,0x10,0x43,0x00, +0xa4,0x3e,0xc2,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x25,0xb0,0x10,0x3c,0xc0,0x02,0x02,0x36,0x00,0x00,0x53,0x8c,0xff,0x00,0x05,0x3c, +0xff,0xff,0xa2,0x34,0x2b,0x10,0x53,0x00,0x40,0x00,0x40,0x10,0x00,0xff,0x02,0x3c, +0xff,0x00,0x42,0x34,0x00,0xfd,0x04,0x3c,0x24,0x18,0x62,0x02,0x17,0x00,0x82,0x34, +0x2e,0x07,0x62,0x10,0x2b,0x10,0x43,0x00,0x33,0x02,0x40,0x14,0xb5,0x00,0x82,0x34, +0x00,0xf9,0x06,0x3c,0x43,0x07,0x66,0x10,0x2b,0x10,0xc3,0x00,0xfa,0x02,0x40,0x14, +0x01,0x00,0x82,0x34,0x00,0xf1,0x02,0x3c,0x04,0x00,0x42,0x34,0x5b,0x07,0x62,0x10, +0x2b,0x10,0x43,0x00,0x45,0x03,0x40,0x14,0x00,0xf0,0x06,0x3c,0x03,0x00,0xc2,0x34, +0xf2,0x07,0x62,0x10,0x2b,0x10,0x43,0x00,0xdb,0x03,0x40,0x14,0x00,0xe0,0x02,0x3c, +0x8e,0x05,0x62,0x10,0x2b,0x10,0x43,0x00,0x44,0x05,0x40,0x14,0x01,0x00,0xc2,0x34, +0x00,0xc0,0x02,0x3c,0x6c,0x03,0x62,0x10,0x00,0xd0,0x02,0x3c,0x40,0x08,0x62,0x10, +0x00,0x0f,0x62,0x32,0x00,0xf0,0x02,0x3c,0x24,0x28,0x62,0x02,0x18,0x00,0xa2,0x10, +0x0f,0x00,0x03,0x3c,0x00,0x70,0x0a,0x3c,0x24,0x10,0x6a,0x02,0x02,0x25,0x13,0x00, +0xff,0xff,0x63,0x34,0x00,0x50,0x06,0x3c,0x24,0x38,0x63,0x02,0x02,0x47,0x02,0x00, +0xff,0x00,0x84,0x30,0x99,0x03,0xa6,0x10,0xff,0x00,0x69,0x32,0x2b,0x10,0xc5,0x00, +0x8d,0x03,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0x20,0x02,0x3c,0xd7,0x06,0xa2,0x10, +0x2b,0x10,0x45,0x00,0x47,0x04,0x40,0x14,0x00,0x30,0x02,0x3c,0xd4,0x06,0xa0,0x10, +0x80,0x10,0x04,0x00,0x00,0x10,0x02,0x3c,0xd1,0x06,0xa2,0x10,0x80,0x10,0x04,0x00, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x08,0x3c, +0x64,0x03,0x02,0x35,0x00,0x00,0x43,0x94,0x68,0x03,0x04,0x35,0xf0,0x3d,0xa3,0xa6, +0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x3e,0xc2,0xae,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xf0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00, +0x01,0x00,0x42,0x30,0xca,0x01,0x40,0x10,0x38,0x15,0x86,0x26,0x38,0x15,0x87,0x26, +0x38,0x15,0x84,0x8e,0xd8,0x02,0xe5,0x8c,0xe8,0x02,0xe6,0x8c,0xf0,0xff,0x02,0x3c, +0xff,0xff,0x42,0x34,0x00,0x50,0x03,0x3c,0x24,0x28,0xa2,0x00,0x01,0x00,0x84,0x34, +0x24,0x30,0xc3,0x00,0x00,0x10,0x02,0x3c,0x38,0x15,0x84,0xae,0xb6,0x06,0xc2,0x10, +0xd8,0x02,0xe5,0xac,0xf0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30, +0xb4,0x01,0x40,0x10,0xfb,0xff,0x03,0x24,0x38,0x15,0x82,0x8e,0x00,0x00,0x00,0x00, +0x04,0x00,0x42,0x34,0x38,0x15,0x82,0xae,0xf0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00, +0x04,0x00,0x42,0x30,0x42,0x01,0x40,0x10,0xdf,0xff,0x03,0x24,0x38,0x15,0x82,0x8e, +0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x34,0x38,0x15,0x82,0xae,0xf0,0x3d,0xa2,0x96, +0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30,0x42,0x01,0x40,0x14,0x00,0x00,0x00,0x00, +0xf0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x30,0x26,0x00,0x40,0x10, +0x38,0x15,0x84,0x26,0xc9,0x02,0x82,0x90,0x00,0x3e,0xc3,0x8e,0x01,0x00,0x42,0x24, +0xc9,0x02,0x82,0xa0,0x0f,0x00,0x63,0x30,0x01,0x00,0x02,0x24,0xc3,0x06,0x62,0x10, +0x02,0x80,0x04,0x3c,0x00,0x3e,0x82,0x8c,0x02,0x00,0x03,0x24,0x0f,0x00,0x42,0x30, +0xc0,0x06,0x43,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x82,0x8c,0x03,0x00,0x03,0x24, +0x0f,0x00,0x42,0x30,0x02,0x00,0x43,0x10,0x03,0x00,0x04,0x24,0x21,0x20,0x00,0x00, +0x70,0x4a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x3e,0xc3,0x8e,0xf0,0x3d,0xa5,0x96, +0x25,0xb0,0x02,0x3c,0xf0,0x00,0x63,0x30,0x64,0x03,0x42,0x34,0x02,0x19,0x03,0x00, +0xef,0x00,0xa5,0x30,0x38,0x15,0x84,0x26,0x02,0x00,0x83,0xa0,0x00,0x00,0x45,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0xf0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00, +0x20,0x00,0x42,0x30,0x26,0x00,0x40,0x10,0x38,0x15,0x84,0x26,0xca,0x02,0x82,0x90, +0x00,0x3e,0xc3,0x8e,0x01,0x00,0x42,0x24,0xca,0x02,0x82,0xa0,0x0f,0x00,0x63,0x30, +0x01,0x00,0x02,0x24,0x97,0x06,0x62,0x10,0x02,0x80,0x04,0x3c,0x00,0x3e,0x82,0x8c, +0x02,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x98,0x06,0x43,0x10,0x00,0x00,0x00,0x00, +0x00,0x3e,0x82,0x8c,0x03,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x02,0x00,0x43,0x10, +0x03,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x70,0x4a,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x3e,0xc3,0x8e,0xf0,0x3d,0xa5,0x96,0x25,0xb0,0x02,0x3c,0xf0,0x00,0x63,0x30, +0x64,0x03,0x42,0x34,0x02,0x19,0x03,0x00,0xdf,0x00,0xa5,0x30,0x38,0x15,0x84,0x26, +0x02,0x00,0x83,0xa0,0x00,0x00,0x45,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0xf0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x30,0xbe,0x00,0x40,0x10, +0x38,0x15,0x84,0x26,0x38,0x15,0x8f,0x26,0x08,0x00,0xe4,0x8d,0x00,0x00,0x00,0x00, +0x42,0x17,0x04,0x00,0x03,0x00,0x42,0x30,0x71,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x00,0x3e,0xc2,0x8e,0xff,0x9f,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x18,0x83,0x00, +0x00,0xff,0x11,0x3c,0x00,0x20,0x04,0x3c,0x25,0x18,0x64,0x00,0x24,0x10,0x51,0x00, +0x08,0x00,0xe3,0xad,0xce,0x01,0x40,0x14,0x02,0x80,0x10,0x3c,0x25,0xb0,0x0e,0x3c, +0x03,0x0d,0xc2,0x35,0x00,0x00,0x43,0x90,0x10,0x00,0xe4,0x8d,0xff,0x3f,0x02,0x3c, +0xff,0xff,0x42,0x34,0x24,0x58,0x82,0x00,0x70,0x00,0x63,0x30,0x00,0x40,0x02,0x3c, +0x7a,0x06,0x60,0x10,0x25,0x58,0x62,0x01,0x94,0x0e,0xc2,0x35,0x9c,0x0e,0xc3,0x35, +0xa4,0x0e,0xc4,0x35,0xac,0x0e,0xc5,0x35,0x00,0x00,0x47,0x8c,0x00,0x00,0x6a,0x8c, +0x00,0x00,0x8c,0x8c,0x00,0x00,0xa6,0x8c,0x0c,0x00,0xe4,0x8d,0xb4,0x0e,0xc2,0x35, +0x00,0x00,0x49,0x8c,0xff,0x03,0x05,0x3c,0x00,0xfc,0x08,0x24,0xbc,0x0e,0xc2,0x35, +0x24,0x38,0xe5,0x00,0x24,0x30,0xc5,0x00,0x24,0x18,0x68,0x01,0x02,0x3c,0x07,0x00, +0x00,0x00,0x4b,0x8c,0x24,0x20,0x88,0x00,0x02,0x34,0x06,0x00,0xcc,0x0e,0xcd,0x35, +0xc4,0x0e,0xc8,0x35,0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x20,0x87,0x00, +0x25,0x18,0x66,0x00,0x00,0x00,0x07,0x8d,0x24,0x50,0x45,0x01,0x00,0x00,0xa6,0x8d, +0x24,0x48,0x25,0x01,0x24,0x18,0x62,0x00,0x24,0x20,0x82,0x00,0x82,0x51,0x0a,0x00, +0x82,0x49,0x09,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,0x25,0x20,0x8a,0x00, +0x25,0x18,0x69,0x00,0x24,0x60,0x85,0x01,0x24,0x58,0x65,0x01,0x24,0x18,0x62,0x00, +0x24,0x30,0xc5,0x00,0x00,0x61,0x0c,0x00,0x24,0x20,0x82,0x00,0x00,0x59,0x0b,0x00, +0x24,0x38,0xe5,0x00,0x25,0x20,0x8c,0x00,0x25,0x18,0x6b,0x00,0x02,0x3c,0x07,0x00, +0x02,0x34,0x06,0x00,0x16,0x00,0xe6,0xa5,0x0c,0x00,0xe4,0xad,0x10,0x00,0xe3,0xad, +0x14,0x00,0xe7,0xa5,0x38,0x15,0x83,0x26,0x0c,0x00,0x62,0x8c,0x00,0x00,0x00,0x00, +0x3a,0x06,0x40,0x04,0x00,0x00,0x00,0x00,0x00,0x3e,0xc2,0x8e,0xff,0x00,0x04,0x3c, +0x24,0x10,0x44,0x00,0x05,0x00,0x40,0x10,0x12,0x00,0x02,0x24,0x00,0x3e,0xc2,0x8e, +0x00,0x00,0x00,0x00,0x24,0x10,0x44,0x00,0x02,0x14,0x02,0x00,0xc3,0x02,0x62,0xa0, +0xb7,0x4f,0x00,0x0c,0x10,0x00,0xa4,0x27,0xf2,0x4e,0x00,0x0c,0x00,0x00,0x00,0x00, +0x38,0x15,0x82,0x26,0x0c,0x00,0x43,0x8c,0x00,0x80,0x04,0x3c,0x25,0x18,0x64,0x00, +0x0c,0x00,0x43,0xac,0x38,0x15,0x82,0x26,0xc3,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x61,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0xf0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x30,0x4c,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x8e,0x00,0x00,0x00,0x00,0x42,0x10,0x02,0x00, +0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xf0,0x3d,0xa2,0x96, +0x00,0x00,0x00,0x00,0x00,0x01,0x42,0x30,0xd8,0x00,0x40,0x14,0x02,0x80,0x02,0x3c, +0x38,0x15,0x82,0x26,0xea,0x02,0x40,0xa0,0xf0,0x3d,0xa2,0x96,0x01,0x00,0x03,0x24, +0x00,0x02,0x42,0x30,0xd9,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x8e, +0xfd,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x25,0xb0,0x05,0x3c,0x38,0x15,0x82,0xae, +0x4c,0x00,0xa3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30, +0x05,0x00,0x40,0x14,0x3f,0xff,0x03,0x24,0x38,0x15,0x82,0x8e,0x00,0x00,0x00,0x00, +0x24,0x10,0x43,0x00,0x38,0x15,0x82,0xae,0x4c,0x3b,0xe4,0x8e,0x00,0x80,0x06,0x3c, +0x18,0x35,0xc2,0x24,0x18,0x03,0xa3,0x34,0x4c,0x3b,0xe6,0x26,0x00,0x00,0x62,0xac, +0x11,0x00,0x86,0x10,0x02,0x80,0x02,0x3c,0xbf,0x00,0xb2,0x34,0x38,0x15,0x51,0x24, +0x21,0x80,0xc0,0x00,0x21,0xf0,0x00,0x00,0x00,0x00,0x42,0x92,0x00,0x00,0x00,0x00, +0x04,0x00,0x42,0x2c,0x09,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x14,0x26,0x24,0x8e, +0x42,0x09,0x00,0x0c,0x00,0x00,0x00,0x00,0x4c,0x3b,0xe2,0x8e,0x00,0x00,0x00,0x00, +0xf5,0xff,0x50,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x08,0x08,0x44,0x24, +0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0xc2,0x2e,0x00,0x0c,0x21,0x38,0x00,0x00, +0x1c,0x0d,0x00,0x08,0x38,0x15,0x92,0x26,0x08,0x00,0x83,0x8c,0xff,0x9f,0x02,0x3c, +0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x08,0x00,0x83,0xac,0xf0,0x3d,0xa2,0x96, +0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x30,0xb6,0xff,0x40,0x10,0x00,0x00,0x00,0x00, +0x38,0x15,0x85,0x26,0xc8,0x02,0xa4,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34, +0x02,0x1f,0x04,0x00,0x01,0x00,0x63,0x24,0x24,0x20,0x82,0x00,0x00,0x1f,0x03,0x00, +0x25,0x20,0x83,0x00,0xd1,0x4b,0x00,0x0c,0xc8,0x02,0xa4,0xac,0xf0,0x3d,0xa3,0x96, +0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x8d,0x0e,0x00,0x08,0x00,0x00,0x00,0x00, +0x38,0x15,0x82,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,0x38,0x15,0x82,0xae, +0xf0,0x3d,0xa2,0x96,0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30,0xc0,0xfe,0x40,0x10, +0x00,0x00,0x00,0x00,0x38,0x15,0x85,0x26,0xc8,0x02,0xa4,0x8c,0xff,0xf0,0x02,0x3c, +0xff,0xff,0x42,0x34,0x02,0x1e,0x04,0x00,0x0f,0x00,0x63,0x30,0x01,0x00,0x63,0x24, +0x0f,0x00,0x63,0x30,0x24,0x20,0x82,0x00,0x00,0x1e,0x03,0x00,0x25,0x20,0x83,0x00, +0x40,0x4a,0x00,0x0c,0xc8,0x02,0xa4,0xac,0xb8,0x4b,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x3e,0xc2,0x8e,0x01,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0xb7,0x0a,0x43,0x10, +0x02,0x80,0x04,0x3c,0x00,0x3e,0x82,0x8c,0x02,0x00,0x03,0x24,0x0f,0x00,0x42,0x30, +0xb4,0x0a,0x43,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x82,0x8c,0x03,0x00,0x03,0x24, +0x0f,0x00,0x42,0x30,0x02,0x00,0x43,0x10,0x03,0x00,0x04,0x24,0x21,0x20,0x00,0x00, +0x70,0x4a,0x00,0x0c,0x00,0x00,0x00,0x00,0x29,0xb0,0x02,0x3c,0x00,0x00,0x40,0xac, +0x08,0x00,0x44,0x34,0x0c,0x00,0x45,0x34,0x10,0x00,0x46,0x34,0x3c,0x00,0x51,0x34, +0x04,0x00,0x43,0x34,0x14,0x00,0x47,0x34,0x18,0x00,0x48,0x34,0x1c,0x00,0x49,0x34, +0x20,0x00,0x4a,0x34,0x24,0x00,0x4b,0x34,0x28,0x00,0x4c,0x34,0x2c,0x00,0x4d,0x34, +0x30,0x00,0x4e,0x34,0x34,0x00,0x4f,0x34,0x38,0x00,0x50,0x34,0x02,0x80,0x02,0x3c, +0x00,0x00,0x60,0xac,0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac,0xff,0xff,0x04,0x24, +0x00,0x00,0xc0,0xac,0x21,0x28,0x00,0x00,0x00,0x00,0xe0,0xac,0x38,0x15,0x46,0x24, +0x00,0x00,0x00,0xad,0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad,0x00,0x00,0x60,0xad, +0x00,0x00,0x80,0xad,0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad,0x00,0x00,0xe0,0xad, +0x00,0x00,0x00,0xae,0x00,0x00,0x20,0xae,0x21,0x18,0xa6,0x00,0x01,0x00,0xa5,0x24, +0x08,0x00,0xa2,0x28,0xfc,0xff,0x40,0x14,0xf0,0x04,0x64,0xa0,0x02,0x80,0x02,0x3c, +0x38,0x15,0x43,0x24,0x1f,0x00,0x05,0x24,0x90,0x11,0x62,0x8c,0xff,0xff,0xa5,0x24, +0xf0,0x00,0x42,0x34,0x90,0x11,0x62,0xac,0xfb,0xff,0xa1,0x04,0x94,0x00,0x63,0x24, +0xf0,0x3d,0xa3,0x96,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,0xf7,0x00,0x63,0x30, +0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0xb8,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x8e,0xa9,0x0d,0x00,0x08,0x24,0x10,0x43,0x00, +0x38,0x15,0x84,0x8e,0xe8,0x02,0xc5,0x8c,0xfe,0xff,0x02,0x24,0x00,0x90,0x03,0x3c, +0x24,0x20,0x82,0x00,0x24,0x18,0xa3,0x00,0x00,0x10,0x02,0x3c,0x3d,0xfe,0x62,0x14, +0x38,0x15,0x84,0xae,0x50,0x0c,0x03,0x35,0xff,0xbf,0x02,0x3c,0x00,0x00,0x64,0x90, +0xff,0xff,0x42,0x34,0x24,0x10,0xa2,0x00,0x00,0x80,0x03,0x3c,0x25,0x10,0x43,0x00, +0xe8,0x02,0xc2,0xac,0xa1,0x0d,0x00,0x08,0xdb,0x02,0xc4,0xa0,0xff,0xff,0x03,0x24, +0x38,0x15,0x42,0x24,0xea,0x02,0x43,0xa0,0xf0,0x3d,0xa2,0x96,0x01,0x00,0x03,0x24, +0x00,0x02,0x42,0x30,0x29,0xff,0x43,0x14,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x8e, +0xa2,0x0e,0x00,0x08,0x02,0x00,0x42,0x34,0x1a,0x05,0x62,0x10,0x00,0xfd,0x06,0x3c, +0x2b,0x10,0x43,0x00,0xe5,0x00,0x40,0x14,0x31,0x00,0x82,0x34,0x43,0x05,0x62,0x10, +0x2b,0x10,0x43,0x00,0x39,0x01,0x40,0x14,0xa6,0x00,0x82,0x34,0x24,0x00,0x82,0x34, +0x54,0x05,0x62,0x10,0x2b,0x10,0x43,0x00,0xe0,0x01,0x40,0x14,0x28,0x00,0x82,0x34, +0x20,0x00,0x82,0x34,0x25,0x06,0x62,0x10,0x2b,0x10,0x43,0x00,0xfc,0x02,0x40,0x14, +0x22,0x00,0xc2,0x34,0x18,0x00,0x82,0x34,0xdf,0x07,0x62,0x10,0x19,0x00,0x82,0x34, +0xd1,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xc0,0x02,0x62,0x34, +0x00,0x00,0x40,0xac,0x94,0x0e,0x64,0x34,0x9c,0x0e,0x62,0x34,0xa4,0x0e,0x65,0x34, +0xac,0x0e,0x66,0x34,0x00,0x00,0x89,0x8c,0x38,0x15,0x8f,0x26,0x00,0x00,0x4b,0x8c, +0x00,0x00,0xac,0x8c,0x00,0x00,0xc4,0x8c,0xb4,0x0e,0x62,0x34,0x0c,0x00,0xe5,0x8d, +0x10,0x00,0xe6,0x8d,0x00,0x00,0x4a,0x8c,0xff,0x03,0x07,0x3c,0x00,0xfc,0x08,0x24, +0xbc,0x0e,0x62,0x34,0x24,0x48,0x27,0x01,0x24,0x20,0x87,0x00,0x00,0x00,0x4d,0x8c, +0x24,0x30,0xc8,0x00,0x02,0x4c,0x09,0x00,0x24,0x28,0xa8,0x00,0x02,0x24,0x04,0x00, +0xcc,0x0e,0x68,0x34,0xf0,0xff,0x02,0x3c,0xc4,0x0e,0x63,0x34,0xff,0x03,0x42,0x34, +0x25,0x28,0xa9,0x00,0x25,0x30,0xc4,0x00,0x00,0x00,0x69,0x8c,0x08,0x00,0xe4,0x8d, +0x00,0x00,0x0e,0x8d,0x24,0x58,0x67,0x01,0x24,0x50,0x47,0x01,0x24,0x30,0xc2,0x00, +0x24,0x28,0xa2,0x00,0x82,0x59,0x0b,0x00,0x82,0x51,0x0a,0x00,0x0f,0xc0,0x03,0x3c, +0xff,0x9f,0x02,0x3c,0xff,0xff,0x63,0x34,0xff,0xff,0x42,0x34,0x25,0x28,0xab,0x00, +0x25,0x30,0xca,0x00,0x24,0x60,0x87,0x01,0x24,0x68,0xa7,0x01,0xff,0x00,0x08,0x3c, +0x24,0x20,0x82,0x00,0x24,0x30,0xc3,0x00,0x24,0x28,0xa3,0x00,0x24,0x70,0xc7,0x01, +0x00,0x61,0x0c,0x00,0x00,0x69,0x0d,0x00,0x24,0x48,0x27,0x01,0x00,0xff,0x03,0x35, +0x00,0x20,0x02,0x3c,0x25,0x20,0x82,0x00,0x25,0x28,0xac,0x00,0x25,0x30,0xcd,0x00, +0x02,0x4c,0x09,0x00,0x02,0x74,0x0e,0x00,0x24,0x18,0x63,0x02,0x08,0x00,0xe4,0xad, +0x0c,0x00,0xe5,0xad,0x10,0x00,0xe6,0xad,0x14,0x00,0xe9,0xa5,0x6b,0x09,0x60,0x10, +0x16,0x00,0xee,0xa5,0x24,0x10,0x68,0x02,0x02,0x14,0x02,0x00,0x02,0x1a,0x13,0x00, +0xc7,0x02,0xe2,0xa1,0xc3,0x02,0xe3,0xa1,0x38,0x15,0x82,0x26,0xc3,0x02,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x61,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0xb7,0x4f,0x00,0x0c,0x10,0x00,0xa4,0x27,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x25,0xb0,0x04,0x3c,0x94,0x0e,0x82,0x34,0x9c,0x0e,0x83,0x34,0xa4,0x0e,0x85,0x34, +0xac,0x0e,0x86,0x34,0x00,0x00,0x49,0x8c,0x00,0x00,0x6c,0x8c,0xb4,0x0e,0x82,0x34, +0x00,0x00,0xae,0x8c,0x10,0x00,0xe3,0x8d,0x00,0x00,0xc8,0x8c,0x0c,0x00,0xe5,0x8d, +0x00,0x00,0x4a,0x8c,0xff,0x3f,0x02,0x3c,0xff,0x03,0x06,0x3c,0xff,0xff,0x42,0x34, +0x00,0xfc,0x07,0x24,0x24,0x18,0x62,0x00,0x24,0x48,0x26,0x01,0xbc,0x0e,0x82,0x34, +0x24,0x40,0x06,0x01,0x00,0x00,0x4b,0x8c,0x24,0x18,0x67,0x00,0x24,0x28,0xa7,0x00, +0x02,0x44,0x08,0x00,0xcc,0x0e,0x8d,0x34,0x02,0x4c,0x09,0x00,0xc4,0x0e,0x84,0x34, +0xf0,0xff,0x02,0x3c,0x00,0x00,0x87,0x8c,0xff,0x03,0x42,0x34,0x00,0x00,0xa4,0x8d, +0x25,0x18,0x68,0x00,0x25,0x28,0xa9,0x00,0x24,0x60,0x86,0x01,0x24,0x50,0x46,0x01, +0x00,0x3e,0x08,0x8e,0x24,0x18,0x62,0x00,0x24,0x28,0xa2,0x00,0x82,0x61,0x0c,0x00, +0x82,0x51,0x0a,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,0x25,0x28,0xac,0x00, +0x25,0x18,0x6a,0x00,0x24,0x70,0xc6,0x01,0x24,0x58,0x66,0x01,0x24,0x18,0x62,0x00, +0x24,0x28,0xa2,0x00,0x24,0x20,0x86,0x00,0x00,0x71,0x0e,0x00,0x00,0x59,0x0b,0x00, +0x24,0x38,0xe6,0x00,0xff,0xff,0x02,0x3c,0x25,0x28,0xae,0x00,0x25,0x18,0x6b,0x00, +0x02,0x3c,0x07,0x00,0x02,0x24,0x04,0x00,0x24,0x40,0x02,0x01,0x0c,0x00,0xe5,0xad, +0x10,0x00,0xe3,0xad,0x14,0x00,0xe7,0xa5,0x64,0x00,0x00,0x11,0x16,0x00,0xe4,0xa5, +0x00,0x3e,0x03,0x8e,0x00,0x3e,0x02,0x8e,0x02,0x1c,0x03,0x00,0x24,0x10,0x51,0x00, +0x02,0x16,0x02,0x00,0xc7,0x02,0xe2,0xa1,0xc3,0x02,0xe3,0xa1,0xb7,0x4f,0x00,0x0c, +0x10,0x00,0xa4,0x27,0xf0,0x3d,0xa3,0x96,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34, +0xbf,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x7e,0x0e,0x00,0x08,0x38,0x15,0x82,0x26,0x72,0x04,0x62,0x10,0x00,0xfd,0x05,0x3c, +0x2b,0x10,0x43,0x00,0x9d,0x00,0x40,0x14,0x10,0x00,0x82,0x34,0x07,0x00,0xc2,0x34, +0xb3,0x04,0x62,0x10,0x2b,0x10,0x43,0x00,0x57,0x01,0x40,0x14,0x03,0x00,0xc2,0x34, +0xaa,0x05,0x62,0x10,0x2b,0x10,0x43,0x00,0x27,0x02,0x40,0x14,0x00,0xf9,0x02,0x3c, +0x01,0x00,0xc2,0x34,0x2e,0x07,0x62,0x10,0x02,0x00,0xc2,0x34,0x0a,0xfd,0x62,0x14, +0x00,0xf0,0x02,0x3c,0x38,0x15,0x82,0x26,0x84,0x24,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xff,0x06,0x3c, +0x0f,0x00,0xc2,0x34,0x68,0x04,0x62,0x10,0x2b,0x10,0x43,0x00,0x6a,0x00,0x40,0x14, +0x21,0x00,0xc2,0x34,0x00,0xfe,0x07,0x3c,0x1a,0x00,0xe2,0x34,0x81,0x04,0x62,0x10, +0x2b,0x10,0x43,0x00,0x0e,0x01,0x40,0x14,0x07,0x00,0xc2,0x34,0x11,0x00,0xe2,0x34, +0xe7,0x07,0x62,0x10,0x2b,0x10,0x43,0x00,0xe0,0x01,0x40,0x14,0x18,0x00,0xe2,0x34, +0xb6,0x00,0x82,0x34,0x9d,0x07,0x62,0x10,0x10,0x00,0xe2,0x34,0xea,0xfc,0x62,0x14, +0x00,0xf0,0x02,0x3c,0x38,0x15,0x83,0x26,0x82,0x0b,0x62,0x90,0x00,0x00,0x00,0x00, +0x00,0xfd,0x40,0x14,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34, +0x24,0x10,0x62,0x02,0x02,0xf2,0x02,0x00,0x01,0x00,0x02,0x24,0x21,0x20,0xc0,0x03, +0x82,0x0b,0x62,0xa0,0x86,0x27,0x00,0x0c,0x83,0x0b,0x7e,0xa0,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x12,0x00,0x02,0x24, +0xc7,0x02,0xe2,0xa1,0x37,0x10,0x00,0x08,0xc3,0x02,0xe2,0xa1,0x00,0xf8,0x04,0x3c, +0x14,0x00,0x82,0x34,0xd7,0x04,0x62,0x10,0x2b,0x10,0x43,0x00,0x86,0x00,0x40,0x14, +0x17,0x00,0x82,0x34,0x10,0x00,0x82,0x34,0xe4,0x04,0x62,0x10,0x2b,0x10,0x43,0x00, +0x43,0x01,0x40,0x14,0x12,0x00,0x82,0x34,0x00,0xf2,0x02,0x3c,0xd7,0x05,0x62,0x10, +0x01,0x00,0x42,0x34,0xbc,0xfc,0x62,0x14,0x00,0xf0,0x02,0x3c,0x25,0xb0,0x05,0x3c, +0xc4,0x02,0xa3,0x34,0x00,0x00,0x64,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x98,0x82,0x00,0x01,0x00,0x03,0x3c,0x2b,0x18,0x73,0x00,0xcd,0xfc,0x60,0x10, +0x25,0xb0,0x02,0x3c,0xc8,0x02,0xa2,0x34,0x00,0x00,0x52,0x8c,0x00,0xb0,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x25,0x98,0x63,0x02,0xc0,0x02,0x42,0x34,0x00,0x00,0x72,0xae, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xae,0x04,0x62,0x10, +0x00,0xfd,0x06,0x3c,0x2b,0x10,0x43,0x00,0x53,0x00,0x40,0x14,0xab,0x00,0x82,0x34, +0xa2,0x00,0x82,0x34,0x9f,0x06,0x62,0x10,0x2b,0x10,0x43,0x00,0x4e,0x01,0x40,0x14, +0xa4,0x00,0xc2,0x34,0xa0,0x00,0x82,0x34,0xd8,0x04,0x62,0x10,0xa1,0x00,0x82,0x34, +0x99,0xfc,0x62,0x14,0x00,0xf0,0x02,0x3c,0x02,0x24,0x13,0x00,0xb8,0x1d,0x00,0x0c, +0xff,0x00,0x84,0x30,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x6b,0x04,0x62,0x10,0x2b,0x10,0x43,0x00, +0x7f,0x00,0x40,0x14,0x31,0x00,0xc2,0x34,0x12,0x00,0xc2,0x34,0xb6,0x06,0x62,0x10, +0x2b,0x10,0x43,0x00,0x54,0x01,0x40,0x14,0x14,0x00,0xc2,0x34,0x10,0x00,0xc2,0x34, +0xb8,0x06,0x62,0x10,0x11,0x00,0xc2,0x34,0x83,0xfc,0x62,0x14,0x00,0xf0,0x02,0x3c, +0xe2,0x48,0x00,0x0c,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x04,0x62,0x10, +0x2b,0x10,0x43,0x00,0xa1,0x00,0x40,0x14,0x13,0x00,0x82,0x34,0x05,0x00,0x82,0x34, +0x2b,0x10,0x43,0x00,0xd7,0x00,0x40,0x14,0x08,0x00,0x82,0x34,0x03,0x00,0x82,0x34, +0x2b,0x10,0x62,0x00,0x8b,0xfc,0x40,0x10,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34, +0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x72,0x30,0x05,0x00,0x44,0x36, +0x00,0x00,0x44,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x63,0x04,0xa2,0x10,0x2b,0x10,0x45,0x00, +0x6a,0x01,0x40,0x14,0x00,0xa0,0x02,0x3c,0x00,0x60,0x02,0x3c,0x04,0x00,0xa2,0x10, +0x80,0x10,0x04,0x00,0x77,0xfc,0xaa,0x14,0x25,0xb0,0x02,0x3c,0x80,0x10,0x04,0x00, +0x21,0x10,0x44,0x00,0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,0x21,0x10,0x48,0x00, +0xc5,0x03,0x49,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x47,0x06,0x62,0x10,0x2b,0x10,0x43,0x00, +0x2a,0x01,0x40,0x14,0xaf,0x00,0xc2,0x34,0xa7,0x00,0x82,0x34,0xa0,0x06,0x62,0x10, +0xaa,0x00,0x82,0x34,0x48,0xfc,0x62,0x14,0x00,0xf0,0x02,0x3c,0xaa,0x53,0x00,0x0c, +0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x8e,0x06,0x62,0x10,0x2b,0x10,0x43,0x00, +0xdf,0x00,0x40,0x14,0x20,0x00,0x82,0x34,0x15,0x00,0x82,0x34,0x82,0x06,0x62,0x10, +0x16,0x00,0x82,0x34,0x38,0xfc,0x62,0x14,0x00,0xf0,0x02,0x3c,0xaf,0x1a,0x00,0x0c, +0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xf1,0x04,0x3c,0xda,0x04,0x64,0x10, +0x2b,0x10,0x83,0x00,0xd1,0x01,0x40,0x14,0x02,0x00,0x82,0x34,0x08,0x00,0xc2,0x34, +0xcd,0x06,0x62,0x10,0x20,0x00,0xc2,0x34,0x27,0xfc,0x62,0x14,0x00,0xf0,0x02,0x3c, +0x38,0x15,0x85,0x26,0xc8,0x02,0xa4,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34, +0x02,0x1f,0x04,0x00,0x01,0x00,0x63,0x24,0x24,0x20,0x82,0x00,0x00,0x1f,0x03,0x00, +0x25,0x20,0x83,0x00,0xc8,0x02,0xa4,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xd1,0x4b,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x65,0x04,0x62,0x10,0x2b,0x10,0x43,0x00,0x5d,0x01,0x40,0x14,0x42,0x00,0xc2,0x34, +0x22,0x00,0xc2,0x34,0xf6,0x04,0x62,0x10,0x30,0x00,0xc2,0x34,0x06,0xfc,0x62,0x14, +0x00,0xf0,0x02,0x3c,0x38,0x15,0x82,0x26,0x75,0x25,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x3a,0x05,0x62,0x10, +0x2b,0x10,0x43,0x00,0xb2,0x00,0x40,0x14,0x2a,0x00,0xc2,0x34,0x25,0x00,0x82,0x34, +0x2d,0x05,0x62,0x10,0x26,0x00,0x82,0x34,0xf3,0xfb,0x62,0x14,0x00,0xf0,0x02,0x3c, +0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00, +0xff,0x00,0x72,0x30,0x08,0x00,0x44,0x36,0x00,0x00,0x44,0xa0,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0xf7,0x04,0x62,0x10,0x2b,0x10,0x43,0x00,0x54,0x00,0x40,0x14,0x0d,0x00,0xc2,0x34, +0xec,0x04,0x66,0x10,0x01,0x00,0xc2,0x34,0xdf,0xfb,0x62,0x14,0x00,0xf0,0x02,0x3c, +0xa7,0x48,0x00,0x0c,0x01,0x00,0x04,0x24,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x43,0x04,0x62,0x10, +0x2b,0x10,0x43,0x00,0x37,0x01,0x40,0x14,0x15,0x00,0xa2,0x34,0x11,0x00,0x82,0x34, +0x9e,0x06,0x62,0x10,0x12,0x00,0x82,0x34,0xcf,0xfb,0x62,0x14,0x00,0xf0,0x02,0x3c, +0x02,0x1c,0x13,0x00,0xff,0x00,0x67,0x30,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x00,0xff,0x64,0x32,0x80,0x10,0x02,0x00, +0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,0x02,0x91,0x04,0x00,0x80,0x11,0x52,0xac, +0x84,0x11,0x52,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xfb,0x04,0x3c,0x01,0x00,0x82,0x34, +0x1b,0x04,0x62,0x10,0x2b,0x10,0x43,0x00,0x36,0x01,0x40,0x14,0x03,0x00,0x82,0x34, +0x20,0x00,0xc2,0x34,0xac,0x04,0x62,0x10,0xff,0x00,0x02,0x3c,0xb2,0xfb,0x64,0x14, +0x00,0xf0,0x02,0x3c,0x38,0x15,0x85,0x26,0x10,0x24,0xa2,0x8c,0xfd,0xff,0x03,0x24, +0xfe,0xff,0x04,0x24,0x24,0x10,0x43,0x00,0x24,0x10,0x44,0x00,0x10,0x24,0xa2,0xac, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x8d,0x02,0xa2,0x10,0x00,0x40,0x02,0x3c,0x47,0xff,0xa2,0x10, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0xd9,0x05,0x62,0x10,0x2b,0x10,0x43,0x00,0xbc,0x01,0x40,0x14, +0x09,0x00,0xa2,0x34,0x07,0x00,0x82,0x34,0x97,0xfb,0x62,0x14,0x00,0xf0,0x02,0x3c, +0x73,0x52,0x00,0x0c,0x21,0x20,0x60,0x02,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x74,0x04,0x62,0x10, +0x2b,0x10,0x43,0x00,0x4d,0x02,0x40,0x14,0x38,0x15,0x82,0x26,0x0c,0x00,0xc2,0x34, +0x89,0xfb,0x62,0x14,0x00,0xf0,0x02,0x3c,0x38,0x15,0x82,0x26,0x5c,0x24,0x44,0x94, +0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34, +0x00,0x00,0x64,0xa4,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x50,0x04,0x62,0x10,0x2b,0x10,0x43,0x00,0xd9,0x01,0x40,0x14,0x00,0xff,0x68,0x32, +0x02,0x22,0x08,0x00,0x21,0x90,0x00,0x00,0xef,0x11,0x00,0x08,0x27,0xb0,0x07,0x3c, +0x00,0x01,0x42,0x2e,0x0b,0x00,0x40,0x10,0x08,0x00,0xe7,0x24,0x00,0x00,0xe2,0x94, +0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x30,0xff,0x00,0xc3,0x33,0xf8,0xff,0x64,0x14, +0x01,0x00,0x52,0x26,0xff,0xff,0x52,0x26,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x00,0x00,0x52,0xa4,0xff,0x00,0x42,0x2e,0x82,0xfb,0x40,0x14,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x12,0x87,0x03,0x3c,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x74,0x05,0x62,0x10,0x2b,0x10,0x43,0x00,0x3d,0x01,0x40,0x14,0x21,0x00,0x82,0x34, +0x18,0x00,0x82,0x34,0x58,0xfb,0x62,0x14,0x00,0xf0,0x02,0x3c,0x08,0x1b,0x00,0x0c, +0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x1c,0x05,0x62,0x10,0x2b,0x10,0x43,0x00, +0x12,0x05,0x40,0x14,0x38,0x15,0x82,0x26,0x08,0x26,0x40,0xac,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0xfe,0x04,0x62,0x10,0x2b,0x10,0x62,0x00,0xdf,0x04,0x40,0x14,0x30,0x00,0xc2,0x34, +0x41,0xfb,0x62,0x14,0x00,0xf0,0x02,0x3c,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34, +0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x72,0x30,0x10,0x00,0x44,0x36, +0x00,0x00,0x44,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x0f,0x05,0x62,0x10,0x2b,0x10,0x62,0x00, +0xf8,0x01,0x40,0x14,0x38,0x15,0x82,0x26,0x20,0x00,0xc2,0x34,0x2e,0xfb,0x62,0x14, +0x00,0xf0,0x02,0x3c,0x02,0x80,0x04,0x3c,0xa4,0x3e,0x83,0x8c,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xf7,0x04,0x62,0x10, +0x2b,0x10,0x43,0x00,0x0e,0x01,0x40,0x14,0xb4,0x00,0xc2,0x34,0xae,0x00,0xc2,0x34, +0x1d,0xfb,0x62,0x14,0x00,0xf0,0x02,0x3c,0x00,0xff,0x65,0x32,0x02,0x24,0x13,0x00, +0xff,0x00,0x84,0x30,0xf2,0x49,0x00,0x0c,0x02,0x2a,0x05,0x00,0x25,0xb0,0x03,0x3c, +0xc4,0x02,0x63,0x34,0x00,0x00,0x62,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x99,0x04,0x62,0x10, +0x2b,0x10,0x43,0x00,0x92,0x01,0x40,0x14,0x12,0x00,0xe2,0x34,0x0a,0xfb,0x62,0x14, +0x00,0xf0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34,0x24,0x10,0x62,0x02, +0x02,0xf2,0x02,0x00,0x38,0x15,0x83,0x26,0x83,0x0b,0x7e,0xa0,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x78,0x04,0xa2,0x10, +0x2b,0x10,0x45,0x00,0x6f,0x01,0x40,0x14,0x00,0xb0,0x02,0x3c,0x00,0x90,0x02,0x3c, +0x0c,0xfb,0xa2,0x14,0x25,0xb0,0x02,0x3c,0x38,0x15,0x82,0x26,0x21,0x10,0x82,0x00, +0x77,0x04,0x49,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x05,0x00,0x42,0x34,0x5e,0x04,0x62,0x10, +0x2b,0x10,0x43,0x00,0x22,0x01,0x40,0x14,0x38,0x15,0x82,0x26,0x7c,0x24,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34, +0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x45,0x04,0x62,0x10,0x2b,0x10,0x43,0x00,0x09,0x01,0x40,0x14,0x38,0x15,0x85,0x26, +0x38,0x15,0x84,0x26,0x08,0x00,0x83,0x8c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x00,0x20,0x02,0x3c,0x25,0x18,0x62,0x00,0x02,0x34,0x13,0x00, +0x00,0x1f,0x65,0x32,0x25,0xb0,0x02,0x3c,0x02,0x92,0x05,0x00,0x3f,0x00,0xc8,0x30, +0xc0,0x02,0x42,0x34,0xc1,0x02,0x88,0xa0,0x08,0x00,0x83,0xac,0xbc,0x02,0x92,0xa0, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x1e,0x04,0x62,0x10, +0x2b,0x10,0x43,0x00,0x07,0x01,0x40,0x14,0x02,0x14,0x13,0x00,0xbe,0xfa,0x66,0x14, +0x00,0xf0,0x02,0x3c,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34,0x24,0x10,0x62,0x02, +0x25,0xb0,0x03,0x3c,0x02,0x9a,0x02,0x00,0x21,0x10,0x63,0x02,0x00,0x00,0x52,0x8c, +0xc4,0x02,0x63,0x34,0x00,0x00,0x72,0xac,0x00,0x00,0x52,0x8c,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x47,0x05,0x62,0x10,0x2b,0x10,0x43,0x00,0x81,0x01,0x40,0x14,0x43,0x00,0xc2,0x34, +0x41,0x00,0xc2,0x34,0xa8,0xfa,0x62,0x14,0x00,0xf0,0x02,0x3c,0x38,0x15,0x82,0x26, +0x62,0x24,0x44,0x94,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34, +0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xa4,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0xb6,0xfa,0x62,0x10,0x2b,0x10,0x43,0x00,0x9b,0x00,0x40,0x14, +0x02,0x14,0x13,0x00,0xff,0x00,0x04,0x3c,0x00,0xff,0x82,0x34,0x24,0x10,0x62,0x02, +0xb0,0xfa,0x40,0x10,0x25,0xb0,0x02,0x3c,0x38,0x15,0x83,0x26,0x00,0xff,0x65,0x32, +0x08,0x03,0x66,0x90,0x02,0x2a,0x05,0x00,0xfb,0xff,0xa2,0x24,0x24,0x20,0x64,0x02, +0x02,0x24,0x04,0x00,0x23,0x03,0x62,0xa0,0x25,0xb0,0x02,0x3c,0x00,0x01,0xc6,0x34, +0xfb,0xff,0x87,0x24,0xc0,0x02,0x42,0x34,0x08,0x03,0x66,0xac,0x21,0x03,0x67,0xa0, +0x20,0x03,0x64,0xa0,0x22,0x03,0x65,0xa0,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x10,0x05,0x62,0x10,0x2b,0x10,0x62,0x00,0x5d,0x01,0x40,0x14, +0x38,0x15,0x82,0x26,0x7c,0xfa,0x65,0x14,0x00,0xf0,0x02,0x3c,0x00,0xff,0x68,0x32, +0x02,0x1a,0x08,0x00,0xff,0x00,0x02,0x24,0xa4,0x03,0x62,0x10,0x25,0xb0,0x05,0x3c, +0x0e,0x00,0x60,0x14,0x00,0xcc,0x02,0x34,0x25,0xb0,0x04,0x3c,0x64,0x03,0x84,0x34, +0x38,0x15,0x87,0x26,0x00,0x00,0x85,0x94,0xe8,0x02,0xe6,0x8c,0xff,0xef,0x02,0x3c, +0xff,0xfe,0x03,0x24,0xff,0xff,0x42,0x34,0x24,0x28,0xa3,0x00,0x24,0x30,0xc2,0x00, +0x00,0x00,0x85,0xa4,0xe8,0x02,0xe6,0xac,0x00,0xcc,0x02,0x34,0x81,0xfa,0x02,0x15, +0x25,0xb0,0x02,0x3c,0x38,0x15,0x82,0x26,0xe8,0x02,0x43,0x8c,0x00,0x10,0x04,0x3c, +0x25,0x18,0x64,0x00,0xe8,0x02,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x74,0xfa,0x62,0x10, +0x2b,0x10,0x43,0x00,0x49,0x04,0x40,0x14,0x00,0xff,0x62,0x32,0x02,0xf2,0x02,0x00, +0xec,0x00,0xc0,0x13,0x25,0xb0,0x05,0x3c,0x94,0x00,0xa2,0x34,0x00,0x00,0x43,0x94, +0xb0,0x03,0xa6,0x34,0xff,0xff,0xca,0x27,0xff,0xff,0x72,0x30,0x1b,0x00,0x5e,0x02, +0x02,0x00,0xc0,0x17,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x00,0x00,0xd2,0xac, +0x38,0x15,0x88,0x26,0x01,0x00,0x02,0x24,0xef,0x0a,0x02,0xa1,0x80,0xff,0x02,0x24, +0x4f,0x00,0xab,0x34,0x9e,0x00,0xac,0x34,0xf2,0x0a,0x09,0x95,0x44,0x00,0xa7,0x34, +0xd8,0x00,0xa5,0x34,0x12,0x90,0x00,0x00,0x80,0x22,0x12,0x00,0x00,0xf8,0x84,0x24, +0x18,0x00,0xd2,0x03,0xff,0xff,0x5e,0x31,0x00,0x19,0x1e,0x00,0x25,0x18,0x62,0x00, +0x26,0xb0,0x02,0x3c,0x00,0x00,0xde,0xac,0x7c,0x00,0x42,0x34,0x00,0x00,0x63,0xa1, +0x00,0x00,0xd2,0xac,0x00,0x00,0x92,0xa5,0x42,0x91,0x04,0x00,0x00,0x00,0xd2,0xac, +0x00,0x00,0x52,0xa4,0x00,0x00,0xe3,0x94,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00, +0x00,0x00,0xe3,0xa4,0x00,0x00,0xe4,0x94,0x12,0x68,0x00,0x00,0x23,0x48,0x2d,0x01, +0x00,0x02,0x84,0x34,0xf4,0x0a,0x09,0xa5,0x00,0x00,0xe4,0xa4,0x00,0x00,0xa2,0x90, +0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x34,0x00,0x00,0xa2,0xa0,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x1d,0xfa,0x62,0x14,0x00,0xf0,0x02,0x3c,0x38,0x15,0x82,0x26,0x10,0x0b,0x43,0x8c, +0x00,0x04,0x04,0x3c,0x25,0x18,0x64,0x00,0x10,0x0b,0x43,0xac,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x11,0xfa,0x62,0x14,0x00,0xf0,0x02,0x3c,0xc2,0x13,0x13,0x00,0xfe,0x00,0x44,0x30, +0x00,0xff,0x63,0x32,0x41,0x00,0x82,0x2c,0xf0,0x05,0x40,0x10,0x02,0xf2,0x03,0x00, +0xc0,0x10,0x1e,0x00,0x21,0x10,0x5e,0x00,0x80,0x10,0x02,0x00,0x38,0x15,0x83,0x26, +0x21,0x10,0x43,0x00,0xf7,0x0c,0x44,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x1f,0x00,0x47,0x30, +0xc0,0x18,0x07,0x00,0x21,0x18,0x67,0x00,0x00,0x0f,0x64,0x32,0x80,0x18,0x03,0x00, +0x02,0x4a,0x04,0x00,0x25,0xb0,0x02,0x3c,0x38,0x15,0x84,0x26,0x21,0x18,0x67,0x00, +0xc8,0x02,0x46,0x34,0x21,0x28,0x24,0x01,0xc4,0x02,0x42,0x34,0x80,0x18,0x03,0x00, +0x00,0x00,0x52,0x8c,0x21,0x18,0x64,0x00,0x00,0x00,0xc8,0x8c,0xf0,0x04,0xa7,0xa0, +0x90,0x11,0x64,0x8c,0x0f,0xff,0x02,0x24,0xc0,0x28,0x09,0x00,0x24,0x20,0x82,0x00, +0x29,0xb0,0x02,0x3c,0x21,0x28,0xa2,0x00,0x00,0x31,0x09,0x00,0x25,0xb0,0x02,0x3c, +0x25,0x20,0x86,0x00,0xc0,0x02,0x42,0x34,0x90,0x11,0x64,0xac,0x00,0x00,0xb2,0xac, +0x04,0x00,0xa8,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0xdd,0xf9,0x62,0x14,0x00,0xf0,0x02,0x3c,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34, +0x00,0x00,0x44,0x90,0x38,0x15,0x85,0x26,0x08,0x03,0xa6,0x90,0xff,0x00,0x92,0x30, +0x02,0x00,0x43,0x36,0x08,0x03,0xa6,0xac,0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0xd8,0x02,0xa3,0x8c,0x0f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x10,0x00,0x04,0x3c,0x25,0xb0,0x02,0x3c,0x25,0x18,0x64,0x00,0xc0,0x02,0x42,0x34, +0xd8,0x02,0xa3,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x74,0x24,0x44,0x90,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34, +0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0xff,0x63,0x32,0xff,0x00,0x5e,0x30,0x04,0x00,0xc0,0x13, +0x02,0x9a,0x03,0x00,0x01,0x00,0x02,0x24,0x02,0x00,0xc2,0x13,0x01,0x00,0x04,0x24, +0x21,0x20,0x00,0x00,0x2a,0x42,0x00,0x0c,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36, +0x95,0x44,0x00,0x0c,0x21,0x20,0x60,0x02,0xff,0xff,0x10,0x36,0x24,0x90,0x50,0x00, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x52,0xac,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x28,0xb0,0x12,0x3c,0x00,0x00,0x42,0x96,0x02,0x1c,0x13,0x00,0xff,0x00,0x64,0x30, +0xff,0xff,0x5e,0x30,0xff,0x00,0xc3,0x33,0x0c,0x00,0x83,0x10,0xff,0x7f,0x03,0x3c, +0x08,0x00,0x52,0x26,0x00,0x00,0x42,0x96,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x30, +0xff,0x00,0xc3,0x33,0x04,0x00,0x83,0x10,0xff,0xff,0x42,0x32,0x00,0x08,0x42,0x2c, +0xf7,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0xff,0x7f,0x03,0x3c,0xff,0xff,0x63,0x34, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x24,0x18,0x43,0x02,0x00,0x00,0x43,0xac, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x9f,0xf9,0xa2,0x14,0x25,0xb0,0x02,0x3c,0x80,0x10,0x04,0x00, +0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,0x6c,0x05,0x47,0xac,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x38,0x15,0x82,0x26,0x82,0x0b,0x44,0x90,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34, +0x00,0x00,0x64,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x4f,0x00,0xa2,0x34,0x9e,0x00,0xa3,0x34,0x00,0x00,0x40,0xa0, +0x00,0x00,0x60,0xa4,0x94,0x00,0xa2,0x34,0x00,0x00,0x43,0x94,0x9a,0x00,0xa4,0x34, +0x98,0x00,0xa6,0x34,0xff,0xff,0x72,0x30,0x80,0x12,0x12,0x00,0x00,0xf8,0x42,0x24, +0x42,0x91,0x02,0x00,0x00,0x14,0x02,0x24,0x00,0x00,0x82,0xa4,0x26,0xb0,0x02,0x3c, +0xb0,0x03,0xa7,0x34,0xa0,0x80,0x03,0x24,0x7c,0x00,0x42,0x34,0x00,0x00,0xc3,0xa4, +0x44,0x00,0xa4,0x34,0x00,0x00,0xf2,0xac,0x00,0x00,0x52,0xa4,0x00,0x00,0x83,0x94, +0xff,0xfd,0x02,0x24,0xd8,0x00,0xa5,0x34,0x24,0x18,0x62,0x00,0x00,0x00,0x83,0xa4, +0x00,0x00,0x82,0x94,0x38,0x15,0x86,0x26,0x00,0x02,0x42,0x34,0x00,0x00,0x82,0xa4, +0x00,0x00,0xa3,0x90,0xbf,0xff,0x02,0x24,0xf4,0x0a,0xc0,0xa4,0x24,0x18,0x62,0x00, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0xef,0x0a,0xc0,0xa0,0x00,0x00,0xa3,0xa0, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x5e,0x24,0x40,0xa4, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x69,0x24,0x43,0x90,0x6a,0x24,0x44,0x94,0x68,0x24,0x45,0x90, +0x00,0x1a,0x03,0x00,0x00,0x24,0x04,0x00,0x25,0x28,0xa3,0x00,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x25,0x28,0xa4,0x00,0x00,0x00,0x45,0xac,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x29,0xf9,0x62,0x14,0x00,0xf0,0x02,0x3c,0xce,0x48,0x00,0x0c,0xff,0xff,0x04,0x34, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x10,0x24,0x43,0x8c,0xfe,0xff,0x04,0x24,0x02,0x00,0x63,0x34, +0x24,0x18,0x64,0x00,0x10,0x24,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x80,0x10,0x04,0x00, +0x21,0x10,0x44,0x00,0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,0x21,0x10,0x48,0x00, +0x38,0x03,0x49,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xdb,0x02,0xe3,0x90,0x50,0x0c,0x02,0x35, +0x21,0x28,0x00,0x00,0x00,0x00,0x43,0xa0,0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30, +0x06,0x00,0xa3,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0xa2,0x24,0x38,0x15,0x82,0x26, +0xdb,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,0x58,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x38,0x15,0x85,0x26,0xe8,0x02,0xa3,0x8c, +0x00,0x40,0x04,0x3c,0xff,0x7f,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0xa1,0x0d,0x00,0x08,0xe8,0x02,0xa3,0xac,0x68,0x03,0x05,0x36, +0x00,0x00,0xa3,0x8c,0x00,0xff,0x62,0x32,0x00,0x12,0x02,0x00,0xff,0xff,0x72,0x30, +0x25,0x10,0x52,0x00,0x00,0x00,0xa2,0xac,0x64,0x03,0x04,0x36,0x00,0x00,0x82,0x90, +0x00,0x00,0x00,0x00,0xff,0x00,0x52,0x30,0x25,0xb0,0x02,0x3c,0x40,0x00,0x43,0x36, +0xc0,0x02,0x42,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0xfa,0x0d,0x00,0x08,0x01,0x00,0x04,0x24,0xd0,0x0d,0x00,0x08, +0x01,0x00,0x04,0x24,0xd0,0x0d,0x00,0x08,0x02,0x00,0x04,0x24,0xfa,0x0d,0x00,0x08, +0x02,0x00,0x04,0x24,0x8c,0x24,0x43,0x92,0xc4,0x02,0x02,0x36,0x00,0x00,0x43,0xac, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0xff,0x63,0x32,0x02,0xf2,0x03,0x00,0xc0,0x10,0x1e,0x00, +0x21,0x10,0x5e,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x52,0x00,0xf7,0x0c,0x44,0x90, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x03,0x36,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xb7,0x4f,0x00,0x0c, +0x10,0x00,0xa4,0x27,0x7e,0x0e,0x00,0x08,0x38,0x15,0x82,0x26,0xd1,0x4b,0x00,0x0c, +0x10,0x00,0xeb,0xad,0x66,0x0e,0x00,0x08,0x38,0x15,0x83,0x26,0x24,0x10,0x65,0x02, +0x02,0x94,0x02,0x00,0x00,0xff,0x63,0x32,0x07,0x00,0x42,0x2e,0xcc,0xf8,0x40,0x10, +0x02,0xf2,0x03,0x00,0x02,0x80,0x04,0x3c,0x88,0x8e,0x83,0x24,0x80,0x10,0x12,0x00, +0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00, +0x00,0x00,0x00,0x00,0x64,0x03,0x03,0x36,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00, +0xfa,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x64,0x03,0x02,0x36, +0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x72,0x30,0x20,0x00,0x44,0x36, +0x00,0x00,0x44,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x56,0x01,0x02,0x36,0xff,0x00,0x03,0x24, +0x00,0x00,0x43,0xa4,0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,0xe0,0x3d,0x44,0xa0, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0xd8,0x02,0x43,0x8e,0x0f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x12,0x01,0x02,0x3c,0x13,0x13,0x42,0x34,0x0c,0x09,0x04,0x36, +0xd8,0x02,0x43,0xae,0x00,0x00,0x82,0xac,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0xff,0xa2,0x34,0x24,0x10,0x62,0x02,0x02,0xf2,0x02,0x00, +0x01,0x00,0x03,0x24,0x13,0x01,0xc3,0x13,0x02,0x00,0xc2,0x2b,0x54,0x02,0x40,0x14, +0x03,0x00,0x02,0x24,0x30,0x03,0xc2,0x13,0x38,0x15,0x82,0x26,0x7c,0x0b,0x44,0x94, +0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34, +0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x70,0x24,0x43,0x92,0xc4,0x02,0x02,0x36,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x29,0xb0,0x02,0x3c,0x04,0x00,0x44,0x34,0x08,0x00,0x45,0x34,0x0c,0x00,0x46,0x34, +0x3c,0x00,0x43,0x34,0x10,0x00,0x47,0x34,0x14,0x00,0x48,0x34,0x18,0x00,0x49,0x34, +0x1c,0x00,0x4a,0x34,0x20,0x00,0x4b,0x34,0x24,0x00,0x4c,0x34,0x28,0x00,0x4d,0x34, +0x2c,0x00,0x4e,0x34,0x30,0x00,0x4f,0x34,0x34,0x00,0x50,0x34,0x38,0x00,0x51,0x34, +0x00,0x00,0x40,0xac,0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac,0xff,0xff,0x04,0x24, +0x00,0x00,0xc0,0xac,0x21,0x28,0x00,0x00,0x00,0x00,0xe0,0xac,0x21,0x30,0x40,0x02, +0x00,0x00,0x00,0xad,0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad,0x00,0x00,0x60,0xad, +0x00,0x00,0x80,0xad,0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad,0x00,0x00,0xe0,0xad, +0x00,0x00,0x00,0xae,0x00,0x00,0x20,0xae,0x00,0x00,0x60,0xac,0x21,0x18,0xa6,0x00, +0x01,0x00,0xa5,0x24,0x08,0x00,0xa2,0x28,0xfc,0xff,0x40,0x14,0xf0,0x04,0x64,0xa0, +0x02,0x80,0x02,0x3c,0x38,0x15,0x43,0x24,0x1f,0x00,0x05,0x24,0x90,0x11,0x62,0x8c, +0xff,0xff,0xa5,0x24,0xf0,0x00,0x42,0x34,0x90,0x11,0x62,0xac,0xfb,0xff,0xa1,0x04, +0x94,0x00,0x63,0x24,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x06,0x3c,0xb8,0x3e,0xc3,0x8c, +0xc4,0x02,0x02,0x36,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x24,0x10,0x65,0x02, +0x00,0xff,0x63,0x32,0x02,0xf4,0x02,0x00,0x04,0x00,0xc0,0x13,0x02,0x9a,0x03,0x00, +0x01,0x00,0x02,0x24,0x02,0x00,0xc2,0x13,0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00, +0x25,0xb0,0x10,0x3c,0x2a,0x42,0x00,0x0c,0xc4,0x02,0x10,0x36,0x00,0x00,0x12,0x8e, +0x0f,0x00,0x11,0x3c,0x21,0x20,0x60,0x02,0x21,0x30,0x40,0x02,0x6a,0x44,0x00,0x0c, +0xff,0xff,0x25,0x36,0x21,0x20,0x60,0x02,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36, +0x00,0x00,0x02,0xae,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x21,0x10,0x82,0x00, +0x5a,0x04,0x49,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xb8,0x4b,0x00,0x0c,0x00,0x00,0x00,0x00, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x41,0x1a,0x00,0x0c,0xfd,0x00,0x04,0x24,0x00,0x1c,0x02,0x3c, +0x00,0x1c,0x42,0x34,0xa0,0x00,0x04,0x36,0x00,0x00,0x82,0xac,0x00,0xe0,0x02,0x3c, +0x00,0xbe,0x42,0x34,0xa8,0x00,0x06,0x36,0xa4,0x00,0x05,0x36,0x00,0x04,0x03,0x24, +0x00,0x00,0xa3,0xac,0x00,0x00,0xc2,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x21,0x90,0x00,0x00, +0x89,0x15,0x00,0x08,0x27,0xb0,0x04,0x3c,0x00,0x01,0x42,0x2e,0x0c,0x00,0x40,0x10, +0x08,0x00,0x84,0x24,0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0xff,0x7e,0x30, +0xff,0x00,0xc2,0x33,0xf0,0x00,0x42,0x28,0xf7,0xff,0x40,0x14,0x01,0x00,0x52,0x26, +0xff,0xff,0x52,0x26,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x5e,0xa4, +0xff,0x00,0x42,0x2e,0xe7,0xf7,0x40,0x14,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x12,0x87,0x03,0x3c,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x0f,0x62,0x32, +0x02,0x22,0x02,0x00,0x01,0x00,0x03,0x24,0x2b,0x04,0x83,0x10,0x02,0x00,0x02,0x24, +0x22,0x04,0x82,0x10,0x03,0x00,0x02,0x24,0xa9,0x03,0x82,0x10,0x00,0x00,0x00,0x00, +0x70,0x4a,0x00,0x0c,0x21,0x20,0x00,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x84,0x26, +0x08,0x00,0x83,0x8c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x08,0x00,0x83,0xac,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x70,0x25,0x44,0x8c, +0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34, +0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x38,0x15,0x82,0x26,0x10,0x24,0x43,0x8c,0xfd,0xff,0x04,0x24,0x24,0x18,0x64,0x00, +0x01,0x00,0x63,0x34,0x10,0x24,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x1c,0x13,0x00, +0x1f,0x00,0x67,0x30,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x38,0x15,0x84,0x26,0x21,0x30,0x44,0x00, +0x90,0x11,0xc3,0x90,0x0f,0x00,0x02,0x24,0x02,0x29,0x03,0x00,0x05,0x00,0xa2,0x10, +0x21,0x18,0xa4,0x00,0xf0,0x04,0x62,0x90,0x00,0x00,0x00,0x00,0x0a,0x00,0x47,0x10, +0xff,0xff,0x02,0x24,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0xff,0xff,0x03,0x24, +0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xf0,0x04,0x62,0xa0,0x90,0x11,0xc3,0x8c, +0x29,0xb0,0x02,0x3c,0xc0,0x20,0x05,0x00,0x21,0x20,0x82,0x00,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0xf0,0x00,0x63,0x34,0x90,0x11,0xc3,0xac,0x00,0x00,0x80,0xac, +0x04,0x00,0x80,0xac,0x00,0x00,0x45,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26, +0x80,0x24,0x44,0x90,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34, +0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x7a,0x0b,0x44,0x94,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x03,0x36,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xff,0xa5,0x34,0x24,0x28,0x65,0x02, +0x25,0xb0,0x04,0x3c,0x02,0x2a,0x05,0x00,0x94,0x00,0x83,0x34,0x40,0x11,0x05,0x00, +0x26,0xb0,0x06,0x3c,0x00,0x00,0x65,0xa4,0xc0,0xff,0x52,0x24,0x7c,0x00,0xcc,0x34, +0x04,0x00,0x07,0x24,0x9a,0x00,0x88,0x34,0x98,0x00,0x89,0x34,0x96,0x00,0x8a,0x34, +0x7a,0x00,0xc6,0x34,0xb0,0x03,0x8b,0x34,0x00,0x04,0x02,0x24,0xa0,0x00,0x03,0x24, +0x00,0x00,0x02,0xa5,0x44,0x00,0x84,0x34,0x00,0x00,0x23,0xa5,0x00,0x00,0x47,0xa5, +0x00,0x00,0xc7,0xa0,0x00,0x00,0x72,0xad,0x00,0x00,0x92,0xa5,0x00,0x00,0x83,0x94, +0xff,0xfd,0x02,0x24,0x38,0x15,0x86,0x26,0x24,0x18,0x62,0x00,0x00,0x00,0x83,0xa4, +0x00,0x00,0x82,0x94,0xf2,0x0a,0xc5,0xa4,0x00,0x02,0x42,0x34,0x00,0x00,0x82,0xa4, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x28,0xb0,0x02,0x3c,0x00,0x00,0x43,0x90,0xff,0x00,0x02,0x24, +0xff,0x00,0x73,0x30,0x42,0xf7,0x62,0x12,0x28,0xb0,0x05,0x3c,0xff,0x00,0x04,0x24, +0xc0,0x10,0x13,0x00,0x21,0x10,0x45,0x00,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00, +0xff,0x00,0x73,0x30,0xfb,0xff,0x64,0x16,0xc0,0x10,0x13,0x00,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x01,0x00,0x02,0x24,0x38,0x15,0x83,0x26,0x5e,0x24,0x62,0xa4,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x02,0x80,0x02,0x3c,0xbc,0x3e,0x43,0x8c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x34,0x24,0x10,0x62,0x02, +0x02,0xf2,0x02,0x00,0x07,0x00,0x03,0x24,0x04,0x03,0xc3,0x13,0x08,0x00,0xc2,0x2b, +0xf6,0x02,0x40,0x10,0x20,0x00,0x02,0x24,0x1a,0xf7,0xc0,0x17,0x25,0xb0,0x02,0x3c, +0x02,0x80,0x04,0x3c,0xb0,0x3d,0x83,0x94,0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0xa7,0x48,0x00,0x0c,0x21,0x20,0x00,0x00,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0xa7,0x48,0x00,0x0c,0x07,0x00,0x04,0x24,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0xb0,0x05,0x3c, +0xc4,0x02,0xa3,0x34,0x00,0x00,0x64,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x98,0x82,0x00,0x01,0x00,0x03,0x3c,0x2b,0x18,0x73,0x00,0xf9,0xf6,0x60,0x10, +0x25,0xb0,0x02,0x3c,0x00,0xb0,0x02,0x3c,0x25,0x98,0x62,0x02,0x00,0x00,0x72,0x8e, +0xc8,0x02,0xa2,0x34,0x00,0x00,0x52,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x64,0x03,0xa5,0x34, +0x38,0x15,0x86,0x26,0x00,0x00,0xa3,0x94,0xe8,0x02,0xc4,0x8c,0xff,0xef,0x02,0x3c, +0xff,0xff,0x42,0x34,0x24,0x20,0x82,0x00,0x00,0x01,0x63,0x34,0x00,0x00,0xa3,0xa4, +0xfa,0x12,0x00,0x08,0xe8,0x02,0xc4,0xac,0x38,0x15,0x82,0x26,0x02,0x1a,0x13,0x00, +0x02,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36, +0x60,0x00,0x06,0x24,0x6a,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0xf2,0x19,0x00,0x0c, +0xe8,0x03,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x24,0x00,0x04,0x24,0x95,0x44,0x00,0x0c,0xff,0xff,0x05,0x36, +0x1f,0x00,0x52,0x30,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x00,0x00,0x52,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xff,0x00,0x03,0x3c, +0xc4,0x02,0x44,0x34,0x00,0xff,0x63,0x34,0x00,0x00,0x92,0x8c,0x24,0x18,0x63,0x02, +0x02,0x9a,0x03,0x00,0x21,0x10,0x62,0x02,0x00,0x00,0x52,0xac,0x00,0x00,0x52,0x8c, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x92,0xac,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x14,0x13,0x00,0x00,0x1f,0x63,0x32, +0x3f,0x00,0x48,0x30,0x25,0xb0,0x02,0x3c,0x02,0x92,0x03,0x00,0xc0,0x02,0x42,0x34, +0x38,0x15,0x83,0x26,0xc1,0x02,0x68,0xa0,0xbc,0x02,0x72,0xa0,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x78,0x24,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34, +0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x80,0x10,0x04,0x00,0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,0xf8,0x04,0x47,0xac, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x38,0x15,0x82,0x26,0x83,0x0b,0x44,0x90,0x25,0xb0,0x03,0x3c, +0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x1c,0x13,0x00,0x00,0x1f,0x62,0x32, +0x38,0x15,0x90,0x26,0x02,0x92,0x02,0x00,0x3f,0x00,0x68,0x30,0xc1,0x02,0x08,0xa2, +0xbc,0x02,0x12,0xa2,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0xac,0x23,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x90,0x40,0x00, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x52,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x03,0x00,0x02,0x92,0x00,0x00,0x00,0x00, +0x01,0x00,0x42,0x24,0x03,0x00,0x02,0xa2,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c, +0x65,0x03,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x72,0x30, +0x02,0x00,0x44,0x36,0x00,0x00,0x44,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x24,0x13,0x00, +0xb6,0x4b,0x00,0x0c,0xff,0x00,0x84,0x30,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34, +0x38,0x15,0x83,0x26,0x08,0x26,0x62,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x40,0x4a,0x00,0x0c, +0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x6e,0x24,0x44,0x94, +0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34, +0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0xae,0xfd,0xc0,0x17,0x38,0x15,0x82,0x26,0x78,0x0b,0x44,0x94,0x25,0xb0,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x71,0x0a,0x00,0x0c, +0x21,0x20,0xc0,0x03,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x90,0x53,0x00,0x0c,0x21,0x20,0x60,0x02, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,0x00,0xff,0xa2,0x34,0xc4,0x02,0x63,0x34, +0x24,0x10,0x62,0x02,0x00,0x00,0x65,0x8c,0x02,0xf2,0x02,0x00,0x7c,0x4b,0x00,0x0c, +0x21,0x20,0xc0,0x03,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x84,0x26,0x08,0x00,0x83,0x8c, +0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x08,0x00,0x83,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x38,0x15,0x84,0x26,0x10,0x0b,0x83,0x8c,0xff,0xfb,0x02,0x3c, +0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x10,0x0b,0x83,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x38,0x15,0x82,0x26,0x88,0x24,0x44,0x90,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xeb,0x48,0x00,0x0c,0x00,0x00,0x00,0x00, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0xff,0x63,0x32,0x00,0xff,0x02,0x34,0x1e,0x01,0x62,0x10, +0x38,0x15,0x82,0x26,0x08,0x26,0x40,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c, +0x64,0x03,0x63,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0xfd,0x00,0x42,0x30, +0x00,0x00,0x62,0xa0,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x75,0x1a,0x00,0x0c,0x00,0x00,0x00,0x00, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x3b,0x1b,0x00,0x0c,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x00,0xff,0x62,0x32,0x02,0x92,0x02,0x00,0x02,0x1c,0x13,0x00,0x01,0x00,0x02,0x24, +0x76,0x01,0x42,0x12,0xff,0x00,0x67,0x30,0x02,0x00,0x02,0x24,0x63,0x01,0x42,0x12, +0x03,0x00,0x02,0x24,0x50,0x01,0x42,0x12,0x04,0x00,0x02,0x24,0x3e,0x01,0x42,0x12, +0x08,0x00,0x02,0x24,0x2b,0x01,0x42,0x12,0x09,0x00,0x02,0x24,0x18,0x01,0x42,0x12, +0x0a,0x00,0x02,0x24,0x05,0x01,0x42,0x12,0x0b,0x00,0x02,0x24,0xf2,0x00,0x42,0x12, +0x0c,0x00,0x02,0x24,0xd7,0x00,0x42,0x12,0x0d,0x00,0x02,0x24,0xc4,0x00,0x42,0x12, +0x0e,0x00,0x02,0x24,0xb1,0x00,0x42,0x12,0x0f,0x00,0x02,0x24,0x9e,0x00,0x42,0x12, +0x10,0x00,0x02,0x24,0xa7,0xf5,0x42,0x16,0x25,0xb0,0x02,0x3c,0xc0,0x10,0x07,0x00, +0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x38,0x15,0x83,0x26, +0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x64,0x11,0x44,0x94,0x60,0x11,0x45,0x94, +0x25,0xb0,0x06,0x3c,0x00,0x24,0x04,0x00,0xc4,0x02,0xc3,0x34,0x21,0x28,0xa4,0x00, +0x00,0x00,0x65,0xac,0x70,0x11,0x47,0x8c,0x6c,0x11,0x43,0x8c,0x68,0x11,0x44,0x94, +0x25,0xb0,0x02,0x3c,0x21,0x18,0x67,0x00,0x00,0x1c,0x03,0x00,0xc8,0x02,0xc6,0x34, +0x21,0x20,0x83,0x00,0xc0,0x02,0x42,0x34,0x00,0x00,0xc4,0xac,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x83,0x26,0x10,0x24,0x62,0x8c, +0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x34,0x10,0x24,0x62,0xac,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x38,0x15,0x82,0x26,0xf2,0x23,0x44,0x94,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xa4,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xff,0x62,0x32,0x02,0x9a,0x02,0x00, +0x62,0x00,0x60,0x12,0x01,0x00,0x02,0x24,0xd7,0x01,0x62,0x12,0x00,0x00,0x00,0x00, +0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0xff,0x62,0x32, +0x02,0xf2,0x02,0x00,0xc0,0x18,0x1e,0x00,0x21,0x18,0x7e,0x00,0x38,0x15,0x82,0x26, +0x02,0x24,0x13,0x00,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0xff,0x00,0x84,0x30, +0x21,0x18,0x64,0x00,0xf8,0x0c,0x64,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x7e,0x0b,0x44,0x94,0x25,0xb0,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x1c,0x13,0x00, +0x1f,0x00,0x67,0x30,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00, +0x25,0xb0,0x04,0x3c,0x21,0x10,0x47,0x00,0x02,0x80,0x03,0x3c,0xc8,0x02,0x85,0x34, +0x38,0x15,0x63,0x24,0xc4,0x02,0x84,0x34,0x80,0x10,0x02,0x00,0x00,0x00,0x92,0x8c, +0x21,0x48,0x43,0x00,0x00,0x00,0xa8,0x8c,0x21,0x58,0x80,0x00,0x21,0x28,0x00,0x00, +0xff,0x00,0x0a,0x24,0x29,0xb0,0x06,0x3c,0x21,0x20,0xa3,0x00,0xf0,0x04,0x82,0x90, +0x00,0x00,0x00,0x00,0x8f,0x01,0x4a,0x10,0x00,0x00,0x00,0x00,0x8d,0x01,0x47,0x10, +0x00,0x00,0x00,0x00,0x01,0x00,0xa5,0x24,0x08,0x00,0xa2,0x28,0xf6,0xff,0x40,0x14, +0x08,0x00,0xc6,0x24,0x08,0x00,0x02,0x24,0x2e,0xf5,0xa2,0x14,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0xff,0xff,0x03,0x24,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x00,0xff,0xa2,0x34,0x24,0x10,0x62,0x02,0x02,0xf2,0x02,0x00,0x38,0x15,0x83,0x26, +0x21,0x20,0xc0,0x03,0x86,0x27,0x00,0x0c,0x82,0x0b,0x60,0xa0,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x2a,0x42,0x00,0x0c, +0x21,0x20,0x00,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00, +0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,0x21,0x10,0x47,0x00,0xe8,0x26,0x83,0x24, +0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00, +0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x02,0x80,0x06,0x3c, +0xe4,0x26,0xc3,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c, +0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34, +0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c, +0x21,0x10,0x47,0x00,0xe0,0x26,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00, +0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34, +0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x47,0x00,0x02,0x80,0x06,0x3c,0xdc,0x26,0xc3,0x24,0x80,0x10,0x02,0x00, +0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34,0x38,0x15,0x83,0x26, +0x08,0x26,0x62,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00, +0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,0x21,0x10,0x47,0x00,0xd8,0x26,0x83,0x24, +0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00, +0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x02,0x80,0x06,0x3c, +0xd4,0x26,0xc3,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c, +0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34, +0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c, +0x21,0x10,0x47,0x00,0xd0,0x26,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00, +0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34, +0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x47,0x00,0x02,0x80,0x06,0x3c,0xcc,0x26,0xc3,0x24,0x80,0x10,0x02,0x00, +0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x38,0x15,0x83,0x26,0x80,0x10,0x02,0x00, +0x21,0x10,0x43,0x00,0xec,0x11,0x44,0x8c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00,0x21,0x10,0x47,0x00, +0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,0x21,0x10,0x47,0x00,0xc8,0x26,0x83,0x24, +0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00, +0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x38,0x15,0x83,0x26, +0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x8c,0x11,0x44,0x8c,0x25,0xb0,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x07,0x00, +0x21,0x10,0x47,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x47,0x00,0x38,0x15,0x83,0x26, +0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x88,0x11,0x44,0x8c,0x25,0xb0,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x63,0x34,0xc0,0x02,0x42,0x34,0x00,0x00,0x64,0xac, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x12,0x00,0x02,0x24, +0xc7,0x02,0xe2,0xa1,0xde,0x0f,0x00,0x08,0xc3,0x02,0xe2,0xa1,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0xb4,0xfd,0x03,0x24,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c, +0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00, +0x70,0x4a,0x00,0x0c,0x03,0x00,0x04,0x24,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0xf4,0xc2,0x17, +0x25,0xb0,0x02,0x3c,0x02,0x80,0x02,0x3c,0xca,0x3d,0x43,0x90,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x06,0x3c, +0xb7,0x3d,0xc3,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x11,0x1e,0x00,0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00, +0x2f,0x03,0x44,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x01,0x00,0x84,0x30, +0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x00,0x19,0x1e,0x00, +0x21,0x18,0x62,0x00,0x30,0x03,0x64,0x94,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x11,0x1e,0x00,0x38,0x15,0x83,0x26, +0x21,0x10,0x43,0x00,0x2c,0x03,0x44,0x8c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x42,0x26,0x04,0x00,0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26, +0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,0x36,0x03,0x64,0x94,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26, +0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,0x35,0x03,0x64,0x90,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26, +0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,0x34,0x03,0x64,0x90,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26, +0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,0x32,0x03,0x64,0x94,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34, +0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x18,0x0f,0x00,0x08, +0x01,0x00,0x04,0x24,0x18,0x0f,0x00,0x08,0x02,0x00,0x04,0x24,0x70,0x4a,0x00,0x0c, +0x02,0x00,0x04,0x24,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac, +0x7f,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,0x70,0x4a,0x00,0x0c,0x01,0x00,0x04,0x24, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0xf0,0x04,0x87,0xa0,0x90,0x11,0x22,0x8d,0x0f,0x00,0xa3,0x30, +0x0f,0xff,0x04,0x24,0x00,0x19,0x03,0x00,0x24,0x10,0x44,0x00,0x25,0x10,0x43,0x00, +0x90,0x11,0x22,0xad,0x00,0x00,0xd2,0xac,0x04,0x00,0xc8,0xac,0x00,0x00,0x65,0xad, +0x4e,0x18,0x00,0x08,0x08,0x00,0x02,0x24,0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x7f,0x0d,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x60,0x89,0x64,0xac,0x00,0x60,0x82,0x40, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x60,0x89,0x45,0x8c, +0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,0xc8,0x67,0x63,0x24, +0x00,0x00,0x43,0xac,0x04,0x00,0x02,0x24,0x1e,0x00,0xa2,0x10,0x05,0x00,0xa2,0x2c, +0x10,0x00,0x40,0x10,0x05,0x00,0x02,0x24,0x03,0x00,0x02,0x24,0x08,0x00,0xa2,0x10, +0x00,0x19,0x04,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0xc0,0x10,0x02,0x00, +0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,0x21,0x10,0x44,0x00,0x40,0x19,0x02,0x00, +0xff,0xff,0x63,0x24,0xfe,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xf3,0xff,0xa2,0x10,0x06,0x00,0x02,0x24,0xf2,0xff,0xa2,0x14, +0x80,0x10,0x04,0x00,0x40,0x11,0x04,0x00,0x23,0x10,0x44,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x44,0x00,0x00,0x19,0x02,0x00,0x23,0x18,0x62,0x00,0x08,0x1a,0x00,0x08, +0x00,0x19,0x03,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0xc0,0x10,0x02,0x00, +0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,0x21,0x10,0x44,0x00,0x08,0x1a,0x00,0x08, +0x00,0x19,0x02,0x00,0x02,0x80,0x02,0x3c,0x60,0x89,0x45,0x8c,0x00,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,0x84,0x68,0x63,0x24,0x00,0x00,0x43,0xac, +0x05,0x00,0x02,0x24,0x10,0x00,0xa2,0x10,0x06,0x00,0xa2,0x2c,0x09,0x00,0x40,0x14, +0x04,0x00,0x02,0x24,0x06,0x00,0x02,0x24,0x0f,0x00,0xa2,0x10,0x00,0x11,0x04,0x00, +0xff,0xff,0x84,0x24,0xfe,0xff,0x80,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xfa,0xff,0xa2,0x14,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00, +0x30,0x1a,0x00,0x08,0x40,0x20,0x02,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00, +0x30,0x1a,0x00,0x08,0x80,0x20,0x02,0x00,0x23,0x10,0x44,0x00,0x30,0x1a,0x00,0x08, +0x40,0x20,0x02,0x00,0xff,0xff,0x85,0x30,0x21,0x30,0x00,0x00,0x25,0xb0,0x03,0x3c, +0x2a,0xb0,0x04,0x3c,0xb4,0x00,0x63,0x34,0x01,0x00,0xa2,0x24,0x31,0x00,0x84,0x34, +0x00,0x00,0x65,0xa0,0x00,0x00,0x85,0xa0,0xff,0xff,0x45,0x30,0x12,0x00,0xa0,0x10, +0x01,0x00,0x03,0x24,0x28,0xb0,0x07,0x3c,0x56,0x1a,0x00,0x08,0xff,0xff,0x08,0x24, +0x00,0x00,0x83,0xa0,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,0x2b,0x10,0xa3,0x00, +0x09,0x00,0x40,0x14,0x08,0x00,0xc6,0x24,0xf9,0xff,0x65,0x14,0x21,0x20,0xc7,0x00, +0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,0x2b,0x10,0xa3,0x00,0x00,0x00,0x88,0xa0, +0xf9,0xff,0x40,0x10,0x08,0x00,0xc6,0x24,0x00,0x01,0xa2,0x2c,0x13,0x00,0x40,0x10, +0x21,0x18,0xa0,0x00,0xff,0x00,0x08,0x24,0x28,0xb0,0x07,0x3c,0x6a,0x1a,0x00,0x08, +0xff,0xff,0x09,0x24,0xff,0xff,0x43,0x30,0x00,0x00,0xa2,0xa0,0x00,0x01,0x62,0x2c, +0x0a,0x00,0x40,0x10,0x08,0x00,0xc6,0x24,0x01,0x00,0x62,0x24,0xf9,0xff,0x68,0x14, +0x21,0x28,0xc7,0x00,0x00,0x01,0x02,0x24,0xff,0xff,0x43,0x30,0x00,0x01,0x62,0x2c, +0x00,0x00,0xa9,0xa0,0xf8,0xff,0x40,0x14,0x08,0x00,0xc6,0x24,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x28,0x00,0xbf,0xaf,0x24,0x00,0xb5,0xaf, +0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf, +0x10,0x00,0xb0,0xaf,0x00,0x60,0x12,0x40,0x01,0x00,0x41,0x36,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x42,0x00,0x15,0x36,0xff,0xff,0x02,0x24, +0x00,0x00,0xa2,0xa2,0xd8,0x00,0x05,0x36,0x40,0x00,0x11,0x36,0xa8,0x00,0x14,0x36, +0xa0,0x00,0x13,0x36,0x00,0x10,0x03,0x24,0xa4,0x00,0x10,0x36,0x00,0x80,0x02,0x3c, +0x00,0x00,0x23,0xa6,0x00,0x00,0xa0,0xa0,0x00,0x00,0x60,0xae,0x00,0x00,0x00,0xae, +0x00,0x00,0x82,0xae,0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,0xfd,0x00,0x04,0x24, +0x25,0x18,0x62,0x00,0xfc,0x17,0x02,0x24,0x00,0x00,0xa3,0xa0,0x00,0x00,0x22,0xa6, +0x41,0x1a,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24, +0x74,0x0b,0x45,0x8c,0x6c,0x0b,0x43,0x8c,0x70,0x0b,0x44,0x8c,0xfc,0x37,0x02,0x24, +0x00,0x00,0x63,0xae,0x00,0x00,0x04,0xae,0x00,0x00,0x85,0xae,0x00,0x00,0x22,0xa6, +0x00,0x00,0xa0,0xa2,0x00,0x60,0x92,0x40,0x28,0x00,0xbf,0x8f,0x24,0x00,0xb5,0x8f, +0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27, +0x34,0x00,0xbf,0xaf,0x30,0x00,0xbe,0xaf,0x2c,0x00,0xb7,0xaf,0x28,0x00,0xb6,0xaf, +0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x16,0x40,0x01,0x00,0xc1,0x36, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x11,0x3c,0x40,0x00,0x30,0x36, +0xff,0xff,0x02,0x24,0x42,0x00,0x3e,0x36,0xfc,0x77,0x13,0x24,0x00,0x00,0xc2,0xa3, +0xfc,0x57,0x12,0x24,0x00,0x00,0x13,0xa6,0x21,0x1a,0x00,0x0c,0x32,0x00,0x04,0x24, +0xfc,0x37,0x17,0x24,0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6,0x21,0x1a,0x00,0x0c, +0x00,0x00,0x00,0x00,0x32,0x00,0x04,0x24,0x00,0x00,0x17,0xa6,0x21,0x1a,0x00,0x0c, +0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xa6,0x21,0x1a,0x00,0x0c,0x32,0x00,0x04,0x24, +0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6,0x21,0x1a,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x00,0x02,0x96,0x24,0xfa,0x03,0x24,0xd8,0x00,0x25,0x36,0x24,0x10,0x43,0x00, +0x00,0x00,0x02,0xa6,0x00,0x00,0xa3,0x90,0xa0,0x00,0x34,0x36,0xa4,0x00,0x35,0x36, +0xa8,0x00,0x33,0x36,0x7f,0x00,0x63,0x30,0x00,0x80,0x02,0x3c,0x00,0x00,0xa3,0xa0, +0x00,0x00,0x80,0xae,0x00,0x00,0xa0,0xae,0x00,0x00,0x62,0xae,0x00,0x00,0xa3,0x90, +0x80,0xff,0x02,0x24,0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00,0x00,0x00,0xa3,0xa0, +0x00,0x00,0x12,0xa6,0x41,0x1a,0x00,0x0c,0x56,0x01,0x31,0x36,0x02,0x80,0x02,0x3c, +0x38,0x15,0x42,0x24,0x74,0x0b,0x45,0x8c,0x6c,0x0b,0x43,0x8c,0x70,0x0b,0x44,0x8c, +0xff,0x0f,0x02,0x24,0x00,0x00,0x83,0xae,0x00,0x00,0xa4,0xae,0x00,0x00,0x65,0xae, +0x00,0x00,0x17,0xa6,0x00,0x00,0x22,0xa6,0x00,0x00,0xc0,0xa3,0x00,0x60,0x96,0x40, +0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f,0x28,0x00,0xb6,0x8f, +0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27, +0xd0,0xff,0xbd,0x27,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf, +0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf, +0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x40,0x00,0x05,0x36,0x00,0x00,0xa2,0x94, +0xaf,0xff,0x03,0x24,0xa8,0x00,0x13,0x36,0x24,0x10,0x43,0x00,0x00,0x00,0xa2,0xa4, +0xa0,0x00,0x12,0x36,0xa4,0x00,0x10,0x36,0x00,0x00,0x55,0x8e,0x00,0x00,0x16,0x8e, +0x00,0x00,0x71,0x8e,0x00,0x80,0x14,0x3c,0xfc,0x37,0x02,0x24,0x00,0x00,0x40,0xae, +0xfd,0x00,0x04,0x24,0x00,0x00,0x00,0xae,0x21,0x88,0x34,0x02,0x00,0x00,0x74,0xae, +0x00,0x00,0xa2,0xa4,0x41,0x1a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xae, +0x00,0x00,0x16,0xae,0x00,0x00,0x71,0xae,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f, +0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x04,0x3c, +0x40,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0xd8,0xfd,0x03,0x24,0x24,0x10,0x43,0x00, +0xfc,0x37,0x03,0x24,0x00,0x00,0x82,0xa4,0x00,0x00,0x83,0xa4,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x00,0x60,0x08,0x40,0x01,0x00,0x01,0x35,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x25,0xb0,0x02,0x3c,0x08,0x09,0x42,0x34,0x03,0x08,0x03,0x24,0x00,0x00,0x43,0xac, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x02,0x80,0x07,0x3c, +0x61,0x0a,0x45,0x34,0x38,0x15,0xe6,0x24,0xf4,0x0d,0x42,0x34,0x00,0x00,0x43,0x94, +0x00,0x00,0xa4,0x90,0x6e,0x24,0xc2,0x94,0xff,0xff,0x63,0x30,0x02,0x00,0x40,0x14, +0xff,0x00,0x84,0x30,0x6c,0x24,0xc0,0xa4,0x00,0x1c,0x03,0x00,0x01,0x00,0x42,0x24, +0x03,0x1c,0x03,0x00,0x2b,0x00,0x60,0x04,0x6e,0x24,0xc2,0xa4,0x38,0x15,0xe2,0x24, +0x6c,0x24,0x44,0xa4,0x69,0x24,0x40,0xa0,0x38,0x15,0xe3,0x24,0x69,0x24,0x62,0x90, +0x00,0x00,0x00,0x00,0x1a,0x00,0x42,0x2c,0x1d,0x00,0x40,0x14,0x14,0x00,0x02,0x24, +0x25,0xb0,0x02,0x3c,0x02,0x08,0x42,0x34,0x00,0x00,0x43,0x94,0x21,0x28,0x00,0x00, +0xff,0xfe,0x64,0x30,0x00,0x00,0x44,0xa4,0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30, +0x06,0x00,0xa3,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0xa2,0x24,0x25,0xb0,0x02,0x3c, +0x02,0x08,0x42,0x34,0x00,0x01,0x83,0x34,0x00,0x00,0x43,0xa4,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x38,0x15,0xe2,0x24,0x6a,0x24,0x43,0x94,0x6e,0x24,0x40,0xa4, +0x69,0x24,0x40,0xa0,0x01,0x00,0x63,0x24,0x6a,0x24,0x43,0xa4,0x14,0x00,0x02,0x24, +0x02,0x80,0x03,0x3c,0x84,0x93,0x62,0xac,0x00,0x60,0x88,0x40,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x6c,0x24,0xc2,0x94,0x00,0x00,0x00,0x00,0xd4,0xff,0x44,0x14, +0x38,0x15,0xe2,0x24,0x69,0x24,0xc2,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24, +0x6e,0x1b,0x00,0x08,0x69,0x24,0xc2,0xa0,0x00,0x00,0x82,0x8c,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x30,0x10,0x00,0x02,0x24,0x0c,0x00,0xc2,0x10, +0x11,0x00,0xc3,0x28,0x06,0x00,0x60,0x10,0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24, +0x0d,0x00,0xc2,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x06,0x00,0xc2,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x00,0x00,0x85,0xa4,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xa0,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90, +0xff,0xff,0xa5,0x24,0x00,0x2c,0x05,0x00,0xfd,0x00,0x63,0x30,0x03,0x2c,0x05,0x00, +0xff,0xff,0x87,0x30,0x00,0x00,0x43,0xa0,0x1a,0x00,0xa0,0x04,0x00,0x00,0x00,0x00, +0x21,0x30,0x40,0x00,0x07,0x10,0xa7,0x00,0x01,0x00,0x42,0x30,0xfd,0x00,0x64,0x30, +0x00,0x00,0x42,0x38,0x02,0x00,0x63,0x34,0x0a,0x18,0x82,0x00,0x00,0x00,0xc3,0xa0, +0x04,0x00,0x63,0x34,0x00,0x00,0xc3,0xa0,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24, +0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xfb,0x00,0x63,0x30,0x00,0x00,0xc3,0xa0, +0x04,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24, +0xff,0xff,0xa2,0x24,0x00,0x2c,0x02,0x00,0x03,0x2c,0x05,0x00,0xea,0xff,0xa1,0x04, +0x07,0x10,0xa7,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c, +0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0xff,0xff,0x84,0x24,0x00,0x24,0x04,0x00, +0x03,0x24,0x04,0x00,0xff,0x00,0x65,0x30,0x1d,0x00,0x80,0x04,0x21,0x38,0x00,0x00, +0x21,0x30,0x40,0x00,0x01,0x00,0x08,0x24,0x04,0x00,0xa5,0x34,0x00,0x00,0xc5,0xa0, +0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x45,0x30,0x01,0x00,0xa3,0x30, +0x05,0x00,0x60,0x10,0x04,0x00,0x02,0x24,0x04,0x10,0x88,0x00,0x25,0x10,0x47,0x00, +0xff,0xff,0x47,0x30,0x04,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04, +0xff,0xff,0x42,0x24,0xfb,0x00,0xa5,0x30,0x00,0x00,0xc5,0xa0,0x09,0x00,0x02,0x24, +0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xff,0xff,0x82,0x24, +0x00,0x24,0x02,0x00,0x03,0x24,0x04,0x00,0xe7,0xff,0x81,0x04,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf, +0x25,0xb0,0x10,0x3c,0x0a,0x00,0x10,0x36,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf, +0x00,0x00,0x02,0x92,0xff,0xff,0x91,0x30,0x03,0x00,0x05,0x24,0xc0,0x00,0x42,0x30, +0x80,0x00,0x43,0x34,0x00,0x00,0x03,0xa2,0x04,0x00,0x63,0x34,0x00,0x00,0x03,0xa2, +0xfb,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,0x08,0x00,0x63,0x34,0x00,0x00,0x03,0xa2, +0x04,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,0xfb,0x00,0x63,0x30,0x00,0x00,0x03,0xa2, +0xbd,0x1b,0x00,0x0c,0x06,0x00,0x04,0x24,0x42,0x20,0x11,0x00,0xbd,0x1b,0x00,0x0c, +0x06,0x00,0x05,0x24,0xe3,0x1b,0x00,0x0c,0x10,0x00,0x04,0x24,0x00,0x00,0x03,0x92, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0xc0,0x00,0x63,0x30,0x00,0x00,0x03,0xa2, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27, +0x14,0x00,0xb1,0xaf,0xff,0xff,0xb1,0x30,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf, +0x1c,0x00,0xbf,0xaf,0x21,0x90,0xc0,0x00,0x0a,0x00,0x20,0x12,0xff,0xff,0x90,0x30, +0x0a,0x1c,0x00,0x0c,0x21,0x20,0x00,0x02,0xfe,0xff,0x23,0x26,0x02,0x00,0x04,0x26, +0x00,0x00,0x42,0xa6,0xff,0xff,0x71,0x30,0xff,0xff,0x90,0x30,0xf8,0xff,0x20,0x16, +0x02,0x00,0x52,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x25,0xb0,0x03,0x3c, +0x0a,0x00,0x68,0x34,0x00,0x00,0x02,0x91,0xff,0xff,0xa5,0x30,0xff,0x00,0x84,0x30, +0x1f,0x00,0xa0,0x10,0xff,0x00,0x47,0x30,0x21,0x48,0x00,0x01,0x0c,0x00,0x6c,0x34, +0x0b,0x00,0x6b,0x34,0xc0,0xff,0x0a,0x24,0x21,0x68,0x00,0x01,0x25,0x10,0xea,0x00, +0xff,0x00,0x47,0x30,0x00,0x00,0x64,0xa1,0x00,0x00,0x27,0xa1,0x00,0x00,0x22,0x91, +0x00,0x00,0x00,0x00,0xff,0x00,0x47,0x30,0xc0,0x00,0xe3,0x30,0x08,0x00,0x60,0x10, +0x00,0x00,0x00,0x00,0x21,0x40,0xa0,0x01,0x00,0x00,0x02,0x91,0x00,0x00,0x00,0x00, +0xff,0x00,0x47,0x30,0xc0,0x00,0xe3,0x30,0xfb,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x00,0x00,0x82,0x8d,0xfc,0xff,0xa3,0x24,0x04,0x00,0x84,0x24,0xff,0xff,0x65,0x30, +0x00,0x00,0xc2,0xac,0xff,0x00,0x84,0x30,0xe8,0xff,0xa0,0x14,0x04,0x00,0xc6,0x24, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x84,0x30,0x21,0x68,0xe0,0x00, +0xff,0xff,0xa5,0x30,0xc0,0x50,0x04,0x00,0x00,0x60,0x0c,0x40,0x01,0x00,0x81,0x35, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0x00,0xc2,0x90,0x01,0x00,0xc3,0x90, +0x25,0xb0,0x07,0x3c,0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,0x00,0x1e,0x03,0x00, +0x01,0x80,0x08,0x3c,0x25,0x20,0xa3,0x00,0x40,0x02,0xe9,0x34,0x25,0x18,0x48,0x01, +0x44,0x02,0xe7,0x34,0x00,0x00,0xe4,0xac,0x00,0x00,0x23,0xad,0x03,0x00,0xc2,0x90, +0x02,0x00,0xc4,0x90,0x04,0x00,0xc3,0x90,0x05,0x00,0xc5,0x90,0x00,0x12,0x02,0x00, +0x25,0x20,0x82,0x00,0x00,0x1c,0x03,0x00,0x01,0x00,0x4a,0x25,0x25,0x20,0x83,0x00, +0x00,0x2e,0x05,0x00,0x25,0x40,0x48,0x01,0x25,0x20,0x85,0x00,0x00,0x00,0xe4,0xac, +0x01,0x00,0x4a,0x25,0x00,0x00,0x28,0xad,0x01,0x80,0x0b,0x3c,0x21,0x40,0x00,0x00, +0x21,0x10,0xa8,0x01,0x01,0x00,0x43,0x90,0x00,0x00,0x45,0x90,0x02,0x00,0x44,0x90, +0x03,0x00,0x46,0x90,0x00,0x1a,0x03,0x00,0x25,0x28,0xa3,0x00,0x00,0x24,0x04,0x00, +0x25,0x28,0xa4,0x00,0x00,0x36,0x06,0x00,0x04,0x00,0x08,0x25,0x25,0x10,0x4b,0x01, +0x25,0x20,0xa6,0x00,0x10,0x00,0x03,0x2d,0x00,0x00,0xe4,0xac,0x01,0x00,0x4a,0x25, +0x00,0x00,0x22,0xad,0xee,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x8c,0x40, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0xff,0x84,0x30,0x42,0xb0,0x08,0x3c, +0x80,0x10,0x04,0x00,0x21,0x10,0x48,0x00,0x04,0x00,0x46,0xac,0x00,0x00,0x07,0x91, +0x40,0x18,0x04,0x00,0x03,0x00,0x06,0x24,0xff,0x00,0xe7,0x30,0x04,0x30,0x66,0x00, +0x01,0x00,0x02,0x24,0x04,0x10,0x62,0x00,0x25,0x30,0xc7,0x00,0xff,0xff,0xa5,0x30, +0x25,0x10,0x47,0x00,0x02,0x00,0xa0,0x14,0xff,0x00,0xc7,0x30,0xff,0x00,0x47,0x30, +0x42,0xb0,0x02,0x3c,0x00,0x00,0x47,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x42,0xb0,0x02,0x3c,0x03,0x00,0x47,0x34,0x00,0x00,0xe3,0x90,0xff,0x00,0x84,0x30, +0x04,0x00,0x84,0x24,0xff,0x00,0x65,0x30,0x01,0x00,0x02,0x24,0x04,0x30,0x82,0x00, +0x07,0x18,0x85,0x00,0x25,0xb0,0x02,0x3c,0xe8,0x03,0x42,0x34,0x01,0x00,0x63,0x30, +0x21,0x20,0xc0,0x00,0x00,0x00,0x45,0xa0,0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0xe6,0xa0,0x08,0x00,0xe0,0x03,0x24,0x10,0x85,0x00,0x00,0x60,0x03,0x40, +0x01,0x00,0x61,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c, +0x6c,0x89,0x42,0x24,0x04,0x00,0x45,0x8c,0x00,0x00,0x82,0xac,0x04,0x00,0x44,0xac, +0x00,0x00,0xa4,0xac,0x04,0x00,0x85,0xac,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x14,0x00,0x83,0x90,0x01,0x00,0x02,0x24,0x08,0x00,0x86,0xac, +0x18,0x00,0x85,0xac,0x00,0x00,0x84,0xac,0x03,0x00,0x62,0x10,0x04,0x00,0x84,0xac, +0xd3,0x1c,0x00,0x08,0x0c,0x00,0x80,0xac,0x0c,0x00,0x82,0x8c,0xd3,0x1c,0x00,0x08, +0x10,0x00,0x82,0xac,0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x04,0x00,0x85,0x8c,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0xa2,0xac,0x04,0x00,0x45,0xac,0x00,0x00,0x84,0xac,0x04,0x00,0x84,0xac, +0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xc8,0xff,0xbd,0x27, +0x30,0x00,0xbe,0xaf,0x25,0xb0,0x02,0x3c,0x02,0x80,0x1e,0x3c,0x2c,0x00,0xb7,0xaf, +0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf, +0x34,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf, +0x18,0x03,0x56,0x34,0x00,0x80,0x17,0x3c,0x02,0x80,0x14,0x3c,0x02,0x80,0x15,0x3c, +0x6c,0x89,0xd3,0x27,0xec,0x73,0xe2,0x26,0x00,0x00,0xc2,0xae,0x6c,0x89,0xd1,0x8f, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0xec,0x3d,0x92,0x8e,0x00,0x00,0x00,0x00,0x24,0x00,0x40,0x12,0x00,0x00,0x00,0x00, +0xec,0x3d,0x80,0xae,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x21,0x00,0x33,0x12,0x21,0x80,0x20,0x02,0x14,0x00,0x23,0x92,0x01,0x00,0x02,0x24, +0x00,0x00,0x31,0x8e,0x29,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x14, +0x02,0x00,0x02,0x24,0x0c,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x02, +0x1c,0x00,0x40,0x10,0x23,0x10,0x72,0x00,0x1c,0x1d,0x00,0x08,0x0c,0x00,0x02,0xae, +0xef,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0x8e,0x00,0x00,0x00,0x00, +0xeb,0xff,0x60,0x10,0x2b,0x10,0x43,0x02,0xf7,0xff,0x40,0x14,0x23,0x10,0x72,0x00, +0x18,0x00,0x04,0x8e,0x08,0x00,0x02,0x8e,0x00,0x00,0x00,0x00,0x09,0xf8,0x40,0x00, +0x0c,0x00,0x00,0xae,0x1c,0x1d,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x0c,0xa4,0x26,0x21,0x28,0x00,0x00, +0x21,0x30,0x00,0x00,0xc2,0x2e,0x00,0x0c,0x21,0x38,0x00,0x00,0x0e,0x1d,0x00,0x08, +0xec,0x73,0xe2,0x26,0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00, +0x00,0x00,0x00,0x00,0x1c,0x1d,0x00,0x08,0x0c,0x00,0x02,0xae,0x0c,0x00,0x03,0x8e, +0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x02,0xdb,0xff,0x40,0x14,0x23,0x10,0x72,0x00, +0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,0x00,0x00,0x00,0x00, +0x10,0x00,0x03,0x8e,0x1c,0x1d,0x00,0x08,0x0c,0x00,0x03,0xae,0x02,0x80,0x02,0x3c, +0x48,0x39,0x43,0x8c,0x02,0x80,0x06,0x3c,0xb6,0x3d,0xc7,0x90,0xff,0x00,0xa5,0x30, +0x25,0xb0,0x02,0x3c,0x42,0x18,0x03,0x00,0xff,0x00,0x84,0x30,0x21,0x40,0xa2,0x00, +0x11,0x00,0x02,0x24,0x01,0x00,0x63,0x30,0x14,0x00,0x86,0x2c,0x0f,0x00,0xe2,0x10, +0x10,0x00,0xa9,0x2c,0x01,0x00,0x02,0x24,0x04,0x00,0x62,0x10,0x25,0xb0,0x03,0x3c, +0x60,0x01,0x04,0xa1,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x10,0x00,0xa2,0x34, +0x21,0x30,0x43,0x00,0xfa,0xff,0x20,0x11,0x21,0x10,0xa3,0x00,0x60,0x01,0x44,0xa0, +0x60,0x01,0xc4,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf1,0xff,0xc0,0x14, +0x1c,0x00,0x87,0x38,0x13,0x00,0x02,0x24,0x65,0x1d,0x00,0x08,0x0b,0x20,0x47,0x00, +0xff,0x00,0x84,0x30,0x01,0x00,0x03,0x24,0x10,0x00,0x02,0x3c,0x04,0x18,0x83,0x00, +0xf0,0x70,0x42,0x34,0x15,0x00,0x84,0x2c,0x06,0x00,0x80,0x10,0x24,0x28,0x62,0x00, +0x0f,0x00,0x63,0x30,0x04,0x00,0xa0,0x14,0x01,0x00,0x02,0x24,0x02,0x00,0x60,0x14, +0x02,0x00,0x02,0x24,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xc0,0x40,0x04,0x00,0x21,0x18,0x04,0x01,0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00, +0x02,0x80,0x02,0x3c,0x80,0x18,0x03,0x00,0x38,0x15,0x42,0x24,0x21,0x18,0x62,0x00, +0x8c,0x11,0x66,0x8c,0x21,0x38,0x60,0x00,0x92,0x11,0x60,0xa0,0x93,0x11,0x60,0xa0, +0x1c,0x00,0x05,0x24,0x99,0x1d,0x00,0x08,0x01,0x00,0x03,0x24,0x08,0x00,0xa0,0x04, +0x21,0x10,0x04,0x01,0x04,0x10,0xa3,0x00,0x24,0x10,0xc2,0x00,0xfb,0xff,0x40,0x10, +0xff,0xff,0xa5,0x24,0x01,0x00,0xa5,0x24,0x92,0x11,0xe5,0xa0,0x21,0x10,0x04,0x01, +0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00, +0x38,0x15,0x63,0x24,0x21,0x18,0x43,0x00,0x8c,0x11,0x66,0x8c,0x21,0x28,0x00,0x00, +0xad,0x1d,0x00,0x08,0x01,0x00,0x07,0x24,0x1d,0x00,0xa2,0x28,0x08,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x04,0x10,0xa7,0x00,0x24,0x10,0xc2,0x00,0xfa,0xff,0x40,0x10, +0x01,0x00,0xa5,0x24,0xff,0xff,0xa5,0x24,0x08,0x00,0xe0,0x03,0x93,0x11,0x65,0xa0, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xd8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02, +0x80,0x80,0x10,0x00,0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24, +0x80,0x80,0x10,0x00,0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf, +0x21,0x80,0x02,0x02,0x14,0x00,0xb1,0xaf,0x90,0x11,0x03,0x8e,0x25,0xb0,0x02,0x3c, +0x80,0x01,0x53,0x34,0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00, +0x00,0x00,0x71,0x92,0x88,0x11,0x05,0x8e,0x84,0x01,0x62,0x8c,0x21,0x90,0x80,0x00, +0xff,0x00,0x31,0x32,0x24,0x10,0x45,0x00,0x88,0x1d,0x00,0x0c,0x8c,0x11,0x02,0xae, +0x92,0x11,0x04,0x92,0x57,0x1d,0x00,0x0c,0xff,0x00,0x45,0x32,0x92,0x11,0x04,0x92, +0x78,0x1d,0x00,0x0c,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24, +0x0a,0x88,0x62,0x00,0x00,0x00,0x71,0xa2,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x28,0x00,0xbd,0x27,0xff,0xff,0x84,0x30,0x00,0x02,0x82,0x30,0x07,0x00,0x03,0x24, +0x0d,0x00,0x40,0x14,0x0b,0x00,0x84,0x30,0x0c,0x00,0x82,0x2c,0x0a,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,0xa4,0x8e,0x63,0x24, +0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00, +0x00,0x00,0x00,0x00,0x07,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x06,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x05,0x00,0x03,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x04,0x00,0x03,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x03,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x02,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x01,0x00,0x03,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x21,0x18,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x88,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x70,0x00,0xbe,0xaf, +0x6c,0x00,0xb7,0xaf,0x68,0x00,0xb6,0xaf,0x64,0x00,0xb5,0xaf,0x5c,0x00,0xb3,0xaf, +0x58,0x00,0xb2,0xaf,0x74,0x00,0xbf,0xaf,0x60,0x00,0xb4,0xaf,0x54,0x00,0xb1,0xaf, +0x50,0x00,0xb0,0xaf,0xd4,0x8e,0x42,0x24,0x00,0x00,0x54,0x8c,0x08,0x00,0x03,0x24, +0x02,0x80,0x0b,0x3c,0x21,0x98,0x00,0x00,0x21,0xa8,0x00,0x00,0x21,0xb8,0x00,0x00, +0x21,0xf0,0x00,0x00,0x21,0xb0,0x00,0x00,0x21,0x90,0x80,0x02,0x10,0x00,0xa3,0xaf, +0x14,0x00,0xa0,0xaf,0x18,0x00,0xa0,0xaf,0x1c,0x00,0xa0,0xaf,0x20,0x00,0xa0,0xaf, +0x24,0x00,0xa0,0xaf,0x28,0x00,0xa0,0xaf,0x2c,0x00,0xa0,0xaf,0x30,0x00,0xa0,0xaf, +0x34,0x00,0xa0,0xaf,0x38,0x00,0xa0,0xaf,0x3c,0x00,0xa0,0xaf,0x40,0x00,0xa0,0xaf, +0xc5,0x1e,0x00,0x08,0x44,0x00,0xa0,0xaf,0x5c,0x11,0x42,0xae,0x78,0x11,0x44,0x8e, +0x74,0x11,0x47,0x8e,0x60,0x11,0x48,0x8e,0x64,0x11,0x45,0x8e,0x6c,0x11,0x46,0x8e, +0x70,0x11,0x43,0x8e,0x21,0x38,0xe4,0x00,0x02,0x80,0x04,0x3c,0x38,0x15,0x84,0x24, +0x21,0x10,0x24,0x02,0x21,0x40,0x05,0x01,0x21,0x30,0xc3,0x00,0xce,0x04,0x42,0x90, +0x5c,0x11,0x4a,0x8e,0x0c,0x00,0xe0,0x10,0x21,0x48,0x00,0x00,0x2b,0x48,0x47,0x00, +0x0b,0x00,0x20,0x15,0x02,0x80,0x02,0x3c,0x07,0x00,0x22,0x2e,0xa3,0x01,0x40,0x14, +0xc0,0x10,0x07,0x00,0x0c,0x00,0x02,0x24,0x9f,0x01,0x22,0x12,0x0d,0x00,0x02,0x24, +0x9e,0x01,0x22,0x12,0xc0,0x10,0x07,0x00,0x93,0x00,0x20,0x11,0x02,0x80,0x02,0x3c, +0x38,0x15,0x42,0x24,0x80,0x18,0x11,0x00,0x21,0x18,0x62,0x00,0x21,0x20,0x51,0x02, +0xce,0x11,0x85,0x90,0xf8,0x04,0x62,0x8c,0x00,0x00,0x00,0x00,0x04,0x10,0xa2,0x00, +0x2b,0x10,0x4a,0x00,0x88,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xec,0x11,0x42,0x8e, +0x01,0x00,0x07,0x24,0x04,0x18,0x27,0x02,0x24,0x10,0x43,0x00,0x10,0x01,0x40,0x10, +0x1c,0x00,0x22,0x2e,0x21,0x28,0x51,0x02,0x94,0x11,0xa6,0x90,0xce,0x11,0xa2,0x90, +0x0a,0x00,0x04,0x24,0xff,0x00,0xc3,0x30,0x04,0x20,0x44,0x00,0x2a,0x18,0x64,0x00, +0x07,0x01,0x60,0x10,0x1c,0x00,0x22,0x2e,0x01,0x00,0xc2,0x24,0xff,0x00,0x43,0x30, +0xb7,0x01,0x64,0x10,0x94,0x11,0xa2,0xa0,0x38,0x15,0x65,0x25,0x80,0x10,0x11,0x00, +0x21,0x10,0x45,0x00,0x6c,0x05,0x44,0x8c,0xf8,0x04,0x43,0x8c,0x21,0x30,0xc5,0x02, +0x40,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x21,0x18,0x62,0x00,0x82,0x50,0x03,0x00, +0x5c,0x11,0xca,0xac,0x08,0x26,0xa3,0x8c,0xff,0xff,0x02,0x34,0x06,0x00,0x62,0x10, +0x21,0x20,0x20,0x02,0xff,0x00,0x65,0x32,0x57,0x1d,0x00,0x0c,0x48,0x00,0xab,0xaf, +0x48,0x00,0xab,0x8f,0x21,0x20,0x20,0x02,0x78,0x1d,0x00,0x0c,0x48,0x00,0xab,0xaf, +0x10,0x00,0xa4,0x8f,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x20,0x62,0x00, +0x10,0x00,0xa4,0xaf,0x48,0x00,0xab,0x8f,0xc7,0x00,0x60,0x12,0x38,0x15,0x70,0x25, +0x38,0x15,0x62,0x25,0x21,0x10,0xa2,0x02,0x70,0x11,0x40,0xac,0x74,0x11,0x40,0xac, +0x78,0x11,0x40,0xac,0x60,0x11,0x40,0xac,0x64,0x11,0x40,0xac,0x68,0x11,0x40,0xac, +0x6c,0x11,0x40,0xac,0x44,0x00,0xa2,0x8f,0x40,0x00,0xa4,0x8f,0x01,0x00,0x73,0x26, +0x94,0x00,0x42,0x24,0x44,0x00,0xa2,0xaf,0x3c,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24, +0x40,0x00,0xa4,0xaf,0x94,0x00,0x42,0x24,0x38,0x00,0xa4,0x8f,0x3c,0x00,0xa2,0xaf, +0x34,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24,0x38,0x00,0xa4,0xaf,0x94,0x00,0x42,0x24, +0x30,0x00,0xa4,0x8f,0x34,0x00,0xa2,0xaf,0x2c,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24, +0x30,0x00,0xa4,0xaf,0x94,0x00,0x42,0x24,0x28,0x00,0xa4,0x8f,0x2c,0x00,0xa2,0xaf, +0x24,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24,0x28,0x00,0xa4,0xaf,0x94,0x00,0x42,0x24, +0x20,0x00,0xa4,0x8f,0x24,0x00,0xa2,0xaf,0x1c,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24, +0x20,0x00,0xa4,0xaf,0x94,0x00,0x42,0x24,0x18,0x00,0xa4,0x8f,0x1c,0x00,0xa2,0xaf, +0x14,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24,0x20,0x00,0x63,0x2a,0x94,0x00,0x42,0x24, +0x94,0x00,0x52,0x26,0x94,0x00,0xd6,0x26,0x18,0x00,0xa4,0xaf,0x94,0x00,0xde,0x27, +0x14,0x00,0xa2,0xaf,0x94,0x00,0x94,0x26,0x94,0x00,0xf7,0x26,0x2e,0x01,0x60,0x10, +0x94,0x00,0xb5,0x26,0x90,0x11,0x42,0x8e,0x00,0x00,0x00,0x00,0x02,0x13,0x02,0x00, +0x01,0x00,0x42,0x30,0xc2,0xff,0x40,0x10,0x25,0xb0,0x02,0x3c,0x21,0x10,0x62,0x02, +0x60,0x01,0x44,0x90,0x78,0x11,0x43,0x8e,0x74,0x11,0x46,0x8e,0xff,0x00,0x91,0x30, +0x02,0x80,0x04,0x3c,0x38,0x15,0x84,0x24,0x21,0x10,0x24,0x02,0x77,0x04,0x44,0x90, +0x5a,0x04,0x45,0x90,0x5c,0x11,0x47,0x8e,0x18,0x00,0x64,0x00,0x12,0x18,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xc5,0x00,0x12,0x30,0x00,0x00, +0x21,0x30,0xc3,0x00,0x2b,0x10,0xe6,0x00,0x53,0xff,0x40,0x10,0x23,0x10,0xe6,0x00, +0x33,0x1e,0x00,0x08,0x5c,0x11,0x40,0xae,0x81,0x00,0xe0,0x10,0x00,0x00,0x00,0x00, +0x82,0x00,0x20,0x15,0x38,0x15,0x62,0x25,0x40,0x10,0x07,0x00,0x21,0x10,0x47,0x00, +0x82,0x10,0x02,0x00,0x2b,0x10,0x46,0x00,0x97,0xff,0x40,0x10,0x21,0x20,0x20,0x02, +0x20,0x00,0xa2,0x8f,0x38,0x15,0x68,0x25,0x01,0x00,0x05,0x24,0x21,0x20,0x48,0x00, +0x21,0x30,0x91,0x00,0xec,0x11,0x83,0x8c,0x04,0x10,0x25,0x02,0xb1,0x11,0xc7,0x90, +0x27,0x10,0x02,0x00,0x24,0x18,0x62,0x00,0xec,0x11,0x83,0xac,0x09,0x00,0xe5,0x10, +0x94,0x11,0xc0,0xa0,0x1c,0x00,0xa3,0x8f,0x21,0x38,0x00,0x00,0x21,0x20,0x68,0x00, +0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,0x1d,0x00,0xe2,0x28,0xfc,0xff,0x40,0x14, +0xce,0x11,0x60,0xa0,0x18,0x00,0xa4,0x8f,0x38,0x15,0x63,0x25,0x21,0x50,0x60,0x00, +0x21,0x10,0x83,0x00,0x21,0x10,0x51,0x00,0xb1,0x11,0x40,0xa0,0x02,0x80,0x03,0x3c, +0x02,0x80,0x02,0x3c,0xdc,0x8d,0x49,0x24,0x68,0x8d,0x68,0x24,0x21,0x38,0x00,0x00, +0x80,0x18,0x07,0x00,0x21,0x10,0x69,0x00,0x21,0x20,0x68,0x00,0x00,0x00,0x46,0x8c, +0x00,0x00,0x85,0x8c,0x01,0x00,0xe7,0x24,0x21,0x18,0x6a,0x00,0x1d,0x00,0xe2,0x28, +0xf8,0x04,0x65,0xac,0xf6,0xff,0x40,0x14,0x6c,0x05,0x66,0xac,0x14,0x00,0x20,0x12, +0x02,0x80,0x05,0x3c,0x93,0x11,0x82,0x92,0xff,0xff,0x27,0x26,0x2a,0x10,0xe2,0x00, +0x0f,0x00,0x40,0x14,0x02,0x80,0x0b,0x3c,0x38,0x15,0x62,0x25,0x21,0x10,0xc2,0x03, +0x93,0x11,0x45,0x90,0x8c,0x11,0x44,0x8c,0x01,0x00,0x06,0x24,0x04,0x18,0xe6,0x00, +0x24,0x10,0x83,0x00,0x23,0x01,0x43,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0xe7,0x24, +0x2a,0x10,0xe5,0x00,0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x02,0x80,0x05,0x3c, +0xb6,0x3d,0xa3,0x90,0x22,0x00,0x02,0x24,0x04,0x01,0x62,0x10,0x38,0x15,0x62,0x25, +0x38,0x15,0x63,0x25,0x80,0x10,0x11,0x00,0x21,0x10,0x43,0x00,0x6c,0x05,0x44,0x8c, +0xf8,0x04,0x43,0x8c,0xb6,0x3d,0xa5,0x90,0x40,0x10,0x04,0x00,0x21,0x10,0x44,0x00, +0x21,0x18,0x62,0x00,0x22,0x00,0x02,0x24,0xf3,0x00,0xa2,0x10,0x82,0x50,0x03,0x00, +0xec,0x11,0x83,0x8e,0x01,0x00,0x02,0x24,0x04,0x10,0x22,0x02,0x25,0x18,0x62,0x00, +0xec,0x11,0x83,0xae,0x38,0x15,0x63,0x25,0x21,0x10,0xe3,0x02,0x5c,0x11,0x4a,0xac, +0x08,0x26,0x64,0x8c,0xff,0xff,0x02,0x34,0x36,0xff,0x82,0x14,0x21,0x20,0x20,0x02, +0x78,0x1d,0x00,0x0c,0x48,0x00,0xab,0xaf,0x10,0x00,0xa4,0x8f,0x01,0x00,0x42,0x38, +0x04,0x00,0x03,0x24,0x0a,0x20,0x62,0x00,0x10,0x00,0xa4,0xaf,0x48,0x00,0xab,0x8f, +0x3b,0xff,0x60,0x16,0x38,0x15,0x70,0x25,0x64,0x11,0x05,0x96,0x60,0x11,0x02,0x96, +0x25,0xb0,0x11,0x3c,0x00,0x2c,0x05,0x00,0x21,0x28,0x45,0x00,0x5a,0x49,0x00,0x0c, +0x68,0x0c,0x24,0x36,0x70,0x11,0x02,0x8e,0x6c,0x11,0x05,0x8e,0x68,0x11,0x03,0x96, +0x6c,0x0c,0x24,0x36,0x21,0x28,0xa2,0x00,0x00,0x2c,0x05,0x00,0x5a,0x49,0x00,0x0c, +0x21,0x28,0x65,0x00,0x48,0x00,0xab,0x8f,0x8d,0x1e,0x00,0x08,0x38,0x15,0x62,0x25, +0x1d,0xff,0x20,0x11,0x21,0x20,0x20,0x02,0x38,0x15,0x62,0x25,0x80,0x18,0x11,0x00, +0x21,0x18,0x62,0x00,0x6c,0x05,0x64,0x8c,0x00,0x00,0x00,0x00,0x2b,0x20,0x44,0x01, +0x15,0xff,0x80,0x10,0x21,0x20,0x20,0x02,0xec,0x1e,0x00,0x08,0x00,0x00,0x00,0x00, +0xfe,0xfe,0x40,0x10,0x38,0x15,0x65,0x25,0x21,0x20,0x51,0x02,0xb1,0x11,0x83,0x90, +0x01,0x00,0x02,0x24,0x8d,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x44,0x00,0xa3,0x8f, +0x38,0x15,0x42,0x24,0x21,0x20,0x62,0x00,0x21,0x38,0x00,0x00,0x21,0x18,0x87,0x00, +0x01,0x00,0xe7,0x24,0x1d,0x00,0xe2,0x28,0xfc,0xff,0x40,0x14,0xce,0x11,0x60,0xa0, +0x40,0x00,0xa4,0x8f,0x02,0x80,0x0b,0x3c,0x38,0x15,0x65,0x25,0x21,0x30,0x85,0x00, +0xec,0x11,0xc2,0x8c,0x01,0x00,0x03,0x24,0x04,0x18,0x23,0x02,0x27,0x18,0x03,0x00, +0x21,0x20,0xd1,0x00,0x24,0x10,0x43,0x00,0xb1,0x11,0x80,0xa0,0xec,0x11,0xc2,0xac, +0x12,0x00,0x20,0x16,0x94,0x11,0x80,0xa0,0x92,0x11,0xc2,0x90,0x00,0x00,0x00,0x00, +0x0e,0x00,0x40,0x10,0x01,0x00,0x07,0x24,0x3c,0x00,0xa3,0x8f,0x01,0x00,0x06,0x24, +0x21,0x10,0x65,0x00,0x92,0x11,0x44,0x90,0x8c,0x11,0x45,0x8c,0x04,0x18,0xe6,0x00, +0x24,0x10,0xa3,0x00,0xad,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24, +0x2a,0x10,0x87,0x00,0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x38,0x00,0xa2,0x8f, +0x02,0x80,0x0b,0x3c,0x38,0x15,0x64,0x25,0x21,0x18,0x44,0x00,0x92,0x11,0x62,0x90, +0x01,0x00,0x27,0x26,0x2a,0x10,0x47,0x00,0x0f,0x00,0x40,0x14,0x02,0x80,0x05,0x3c, +0x34,0x00,0xa3,0x8f,0x01,0x00,0x06,0x24,0x21,0x10,0x64,0x00,0x92,0x11,0x45,0x90, +0x8c,0x11,0x44,0x8c,0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00,0x94,0x00,0x43,0x10, +0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,0x2a,0x10,0xa7,0x00,0xfa,0xff,0x40,0x10, +0x04,0x18,0xe6,0x00,0x02,0x80,0x05,0x3c,0xb6,0x3d,0xa3,0x90,0x22,0x00,0x02,0x24, +0x5e,0x00,0x62,0x10,0xee,0xff,0x22,0x26,0xb6,0x3d,0xa3,0x90,0x22,0x00,0x02,0x24, +0x50,0x00,0x62,0x10,0x11,0x00,0x02,0x24,0xb6,0x3d,0xa3,0x90,0x22,0x00,0x02,0x24, +0xae,0xfe,0x62,0x14,0x38,0x15,0x65,0x25,0x28,0x00,0xa2,0x8f,0x02,0x80,0x0b,0x3c, +0x38,0x15,0x66,0x25,0x21,0x20,0x46,0x00,0x90,0x11,0x85,0x8c,0x01,0x00,0x03,0x24, +0x42,0x13,0x05,0x00,0x07,0x00,0x42,0x30,0xa3,0xfe,0x43,0x10,0x14,0x00,0x22,0x2e, +0xa1,0xfe,0x40,0x14,0x1c,0x00,0x22,0x2e,0x9f,0xfe,0x40,0x10,0xff,0xff,0x02,0x3c, +0xff,0x1f,0x42,0x34,0x24,0x10,0xa2,0x00,0x00,0x20,0x42,0x34,0x90,0x11,0x82,0xac, +0x93,0x11,0x83,0x90,0xff,0xff,0x27,0x26,0x2a,0x18,0xe3,0x00,0x96,0xfe,0x60,0x14, +0x00,0x00,0x00,0x00,0x24,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x21,0x10,0x66,0x00, +0x93,0x11,0x45,0x90,0x8c,0x11,0x44,0x8c,0xe3,0x1f,0x00,0x08,0x01,0x00,0x06,0x24, +0x2a,0x10,0xe5,0x00,0x8c,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0x04,0x18,0xe6,0x00, +0x24,0x10,0x83,0x00,0xfa,0xff,0x43,0x14,0xff,0xff,0xe7,0x24,0x01,0x00,0xe7,0x24, +0x6e,0x1e,0x00,0x08,0xff,0x00,0xf1,0x30,0xc0,0x10,0x07,0x00,0x23,0x10,0x47,0x00, +0xc2,0x10,0x02,0x00,0x2b,0x10,0x48,0x00,0x6c,0xfe,0x40,0x14,0x00,0x00,0x00,0x00, +0x4e,0x1e,0x00,0x08,0x00,0x00,0x00,0x00,0x10,0x00,0xa3,0x8f,0x74,0x00,0xbf,0x8f, +0x70,0x00,0xbe,0x8f,0x6c,0x00,0xb7,0x8f,0x68,0x00,0xb6,0x8f,0x64,0x00,0xb5,0x8f, +0x60,0x00,0xb4,0x8f,0x5c,0x00,0xb3,0x8f,0x58,0x00,0xb2,0x8f,0x54,0x00,0xb1,0x8f, +0x50,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x78,0x00,0xbd,0x27, +0x00,0x00,0x43,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x18,0x00,0x22,0x2e, +0x21,0x00,0x40,0x14,0x05,0x00,0x22,0x2e,0xce,0x11,0x83,0x90,0x00,0x00,0x00,0x00, +0x05,0x00,0x62,0x2c,0x76,0xff,0x40,0x10,0x01,0x00,0x62,0x24,0x80,0x1f,0x00,0x08, +0xce,0x11,0x82,0xa0,0xb0,0xff,0x22,0x16,0x38,0x15,0x62,0x25,0x2c,0x00,0xa3,0x8f, +0x80,0x00,0x04,0x3c,0x21,0x10,0x62,0x00,0x8c,0x11,0x43,0x8c,0x17,0x00,0x02,0x24, +0x24,0x18,0x64,0x00,0xbe,0x1f,0x00,0x08,0x0b,0x88,0x43,0x00,0xff,0x00,0x42,0x30, +0x02,0x00,0x42,0x2c,0xa0,0xff,0x40,0x10,0x38,0x15,0x62,0x25,0x30,0x00,0xa4,0x8f, +0x00,0x00,0x00,0x00,0x21,0x10,0x82,0x00,0x8c,0x11,0x43,0x8c,0x00,0x01,0x04,0x3c, +0x18,0x00,0x02,0x24,0x24,0x18,0x64,0x00,0xba,0x1f,0x00,0x08,0x0b,0x88,0x43,0x00, +0x6e,0x1e,0x00,0x08,0xb1,0x11,0xa7,0xa0,0x04,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0xce,0x11,0x83,0x90,0x09,0x20,0x00,0x08,0x03,0x00,0x62,0x2c,0xce,0x11,0x83,0x90, +0x09,0x20,0x00,0x08,0x04,0x00,0x62,0x2c,0x13,0x00,0x02,0x24,0x0c,0xff,0x22,0x16, +0x38,0x15,0x63,0x25,0x43,0x1f,0x00,0x08,0x21,0x10,0xe3,0x02,0x14,0x00,0xa3,0x8f, +0x00,0x00,0x00,0x00,0x21,0x20,0x62,0x00,0x90,0x11,0x83,0x8c,0x00,0x00,0x00,0x00, +0x42,0x13,0x03,0x00,0x07,0x00,0x42,0x30,0xf5,0xfe,0x40,0x10,0x14,0x00,0x22,0x2e, +0xf3,0xfe,0x40,0x10,0x0c,0x00,0x22,0x2e,0xf1,0xfe,0x40,0x14,0xff,0xff,0x02,0x3c, +0xff,0x1f,0x42,0x34,0x24,0x10,0x62,0x00,0x30,0x1f,0x00,0x08,0x90,0x11,0x82,0xac, +0xff,0x00,0xf1,0x30,0xb6,0x1f,0x00,0x08,0x02,0x80,0x05,0x3c,0x9f,0x1f,0x00,0x08, +0xff,0x00,0xf1,0x30,0x2b,0x1f,0x00,0x08,0xff,0x00,0xf1,0x30,0xa8,0xff,0xbd,0x27, +0x02,0x80,0x02,0x3c,0x38,0x00,0xb2,0xaf,0x54,0x00,0xbf,0xaf,0x50,0x00,0xbe,0xaf, +0x4c,0x00,0xb7,0xaf,0x48,0x00,0xb6,0xaf,0x44,0x00,0xb5,0xaf,0x40,0x00,0xb4,0xaf, +0x3c,0x00,0xb3,0xaf,0x34,0x00,0xb1,0xaf,0x30,0x00,0xb0,0xaf,0x38,0x15,0x46,0x24, +0x8d,0x25,0xc4,0x90,0x88,0x25,0xc3,0x8c,0x84,0x25,0xc2,0x8c,0x21,0x90,0x64,0x00, +0x2b,0x10,0x42,0x02,0x7e,0x00,0x40,0x10,0x21,0x88,0xc0,0x00,0x02,0x80,0x1e,0x3c, +0x02,0x80,0x17,0x3c,0x21,0xa8,0xc0,0x00,0x21,0xb0,0xc0,0x00,0x6a,0x20,0x00,0x08, +0x01,0x00,0x14,0x24,0x84,0x25,0xc2,0x8e,0x10,0x00,0x52,0x26,0x2b,0x10,0x42,0x02, +0x73,0x00,0x40,0x10,0x21,0x88,0xc0,0x02,0x8d,0x25,0x22,0x92,0xff,0xff,0x45,0x32, +0x25,0x28,0xb7,0x00,0x10,0x00,0x42,0x24,0x8d,0x25,0x22,0xa2,0x14,0x39,0xc4,0x27, +0x60,0x45,0x00,0x0c,0x10,0x00,0x06,0x24,0x10,0x24,0x23,0x8e,0x00,0x00,0x00,0x00, +0x42,0x18,0x03,0x00,0x01,0x00,0x63,0x30,0x71,0x00,0x74,0x10,0x02,0x80,0x03,0x3c, +0x38,0x15,0x63,0x24,0xe0,0x23,0x62,0x8c,0x00,0x00,0x00,0x00,0x42,0x84,0x02,0x00, +0x1f,0x00,0x10,0x32,0xc0,0x48,0x10,0x00,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00, +0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x55,0x00,0x90,0x11,0x45,0x8c, +0x00,0x00,0x00,0x00,0x02,0x1b,0x05,0x00,0x01,0x00,0x63,0x30,0xdd,0xff,0x60,0x10, +0x21,0x30,0xa0,0x02,0x25,0xb0,0x02,0x3c,0x21,0x40,0x02,0x02,0xdc,0x23,0xa7,0x8e, +0x10,0x24,0xa2,0x8e,0x60,0x01,0x03,0x91,0x82,0x25,0x07,0x00,0x01,0x00,0x42,0x30, +0xff,0x00,0x6b,0x30,0x9a,0x00,0x54,0x10,0x3f,0x00,0x8a,0x30,0x02,0x80,0x04,0x3c, +0xd8,0x8e,0x84,0x24,0x00,0x00,0x86,0x8c,0x04,0x00,0x04,0x24,0xdc,0x23,0xc3,0x8c, +0x00,0x00,0x00,0x00,0x82,0x15,0x03,0x00,0x3f,0x00,0x42,0x30,0x05,0x00,0x42,0x28, +0x0a,0x00,0x60,0x04,0x0a,0x50,0x82,0x00,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00, +0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x7c,0x11,0x43,0x8c, +0x04,0x00,0x0a,0x24,0x01,0x00,0x63,0x24,0x7c,0x11,0x43,0xac,0xe0,0x23,0xc2,0x8c, +0x00,0x00,0x00,0x00,0x02,0x13,0x02,0x00,0x1f,0x00,0x42,0x30,0x08,0x00,0x42,0x28, +0xb8,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xdc,0x23,0xc2,0x8c,0x00,0x00,0x00,0x00, +0x3f,0x00,0x42,0x30,0xb3,0xff,0x4b,0x14,0x00,0x00,0x00,0x00,0x9f,0x00,0x40,0x11, +0x21,0x10,0x30,0x01,0xa8,0x00,0x54,0x11,0x80,0x10,0x02,0x00,0x02,0x00,0x02,0x24, +0xb0,0x00,0x42,0x11,0x21,0x10,0x30,0x01,0x03,0x00,0x02,0x24,0xb8,0x00,0x42,0x11, +0x21,0x10,0x30,0x01,0xc0,0x00,0x44,0x11,0x21,0x10,0x30,0x01,0x21,0x10,0x30,0x01, +0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x28,0x46,0x00, +0x80,0x11,0xa3,0x8c,0x21,0x10,0x66,0x01,0x94,0x04,0x44,0x90,0x02,0x19,0x03,0x00, +0x2b,0x18,0x64,0x00,0xc8,0x00,0x60,0x14,0x00,0x00,0x00,0x00,0x74,0x11,0xa3,0x8c, +0x80,0x10,0x0b,0x00,0x21,0x10,0x4b,0x00,0x01,0x00,0x63,0x24,0x21,0x10,0x46,0x00, +0x74,0x11,0xa3,0xac,0x21,0x10,0x4a,0x00,0x38,0x03,0x44,0x90,0x5c,0x11,0xa3,0x8c, +0x00,0x00,0x00,0x00,0x21,0x18,0x64,0x00,0x5c,0x11,0xa3,0xac,0x84,0x25,0xc2,0x8e, +0x10,0x00,0x52,0x26,0x2b,0x10,0x42,0x02,0x8f,0xff,0x40,0x14,0x21,0x88,0xc0,0x02, +0x54,0x00,0xbf,0x8f,0x50,0x00,0xbe,0x8f,0x4c,0x00,0xb7,0x8f,0x48,0x00,0xb6,0x8f, +0x44,0x00,0xb5,0x8f,0x40,0x00,0xb4,0x8f,0x3c,0x00,0xb3,0x8f,0x38,0x00,0xb2,0x8f, +0x34,0x00,0xb1,0x8f,0x30,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x58,0x00,0xbd,0x27, +0xe0,0x23,0x22,0x8e,0x00,0x00,0x00,0x00,0x42,0x14,0x02,0x00,0x10,0x00,0x43,0x30, +0x90,0xff,0x60,0x10,0x0f,0x00,0x50,0x30,0x1f,0x49,0x00,0x0c,0x48,0x00,0x04,0x24, +0x74,0xff,0x40,0x10,0x21,0x98,0x40,0x00,0x14,0x00,0x02,0x24,0x28,0x00,0x04,0x24, +0x14,0x00,0x62,0xae,0x0c,0x00,0x64,0xae,0x14,0x00,0xa3,0x8f,0xe0,0xff,0x04,0x24, +0x08,0x00,0x07,0x24,0x80,0x00,0x63,0x34,0x14,0x00,0xa3,0xaf,0xe0,0x23,0x26,0x8e, +0x24,0x18,0x64,0x00,0xff,0xe0,0x04,0x24,0x42,0x14,0x06,0x00,0x1f,0x00,0x42,0x30, +0x25,0x18,0x62,0x00,0x14,0x00,0xa3,0xaf,0xdc,0x23,0x25,0x8e,0x24,0x18,0x64,0x00, +0x02,0x23,0x06,0x00,0x82,0x13,0x05,0x00,0x00,0x1f,0x42,0x30,0x25,0x18,0x62,0x00, +0xff,0xff,0x02,0x3c,0xff,0x7f,0x42,0x34,0xc2,0x2f,0x05,0x00,0x24,0x18,0x62,0x00, +0xc0,0x2b,0x05,0x00,0x0f,0x00,0x02,0x3c,0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x00,0x35,0x06,0x00,0xf0,0xff,0x02,0x3c,0x25,0x18,0x66,0x00, +0xff,0xff,0x42,0x34,0x0f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00, +0x25,0x18,0x64,0x00,0x02,0x80,0x04,0x3c,0x10,0x00,0xa5,0x27,0x74,0x39,0x84,0x24, +0x02,0x00,0x06,0x24,0x04,0x00,0x02,0x24,0x11,0x00,0xa7,0xa3,0x14,0x00,0xa3,0xaf, +0x6c,0x45,0x00,0x0c,0x10,0x00,0xa2,0xa3,0x08,0x00,0x64,0x96,0x10,0x00,0xa5,0x27, +0x02,0x00,0x06,0x24,0x25,0x20,0x97,0x00,0x6c,0x45,0x00,0x0c,0x20,0x00,0x84,0x24, +0x42,0x09,0x00,0x0c,0x21,0x20,0x60,0x02,0x7e,0x20,0x00,0x08,0xc0,0x48,0x10,0x00, +0x02,0x12,0x05,0x00,0x01,0x00,0x42,0x30,0x14,0x00,0x54,0x10,0xc2,0x10,0x05,0x00, +0x01,0x00,0x42,0x30,0x76,0x00,0x54,0x10,0x00,0x00,0x00,0x00,0x1c,0x24,0xa2,0x96, +0x60,0x01,0x03,0x91,0xc2,0x27,0x07,0x00,0x21,0x10,0x42,0x01,0x38,0x24,0xa3,0xa2, +0x13,0x00,0x80,0x10,0x1c,0x24,0xa2,0xa6,0x59,0xff,0x94,0x14,0x02,0x80,0x04,0x3c, +0x18,0x24,0xa2,0x96,0x22,0x24,0xa3,0x96,0x01,0x00,0x42,0x24,0x01,0x00,0x63,0x24, +0x18,0x24,0xa2,0xa6,0x94,0x20,0x00,0x08,0x22,0x24,0xa3,0xa6,0x5d,0x00,0xe0,0x04, +0x00,0x00,0x00,0x00,0x1a,0x24,0xa3,0x96,0x26,0x24,0xa2,0x96,0x01,0x00,0x63,0x24, +0x01,0x00,0x42,0x24,0x26,0x24,0xa2,0xa6,0x93,0x20,0x00,0x08,0x1a,0x24,0xc3,0xa4, +0x1a,0x24,0xa3,0x96,0x28,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24, +0x28,0x24,0xa2,0xa6,0x93,0x20,0x00,0x08,0x1a,0x24,0xc3,0xa4,0x80,0x10,0x02,0x00, +0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x60,0x11,0x43,0x8c, +0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x5c,0xff,0x54,0x15,0x60,0x11,0x43,0xac, +0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x46,0x00,0x64,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24, +0x64,0x11,0x43,0xac,0x02,0x00,0x02,0x24,0x54,0xff,0x42,0x15,0x03,0x00,0x02,0x24, +0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x46,0x00,0x68,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24, +0x68,0x11,0x43,0xac,0x03,0x00,0x02,0x24,0x4a,0xff,0x42,0x15,0x21,0x10,0x30,0x01, +0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00, +0x6c,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x43,0xff,0x44,0x15, +0x6c,0x11,0x43,0xac,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x70,0x11,0x43,0x8c,0x00,0x00,0x00,0x00, +0x01,0x00,0x63,0x24,0x70,0x11,0x43,0xac,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00, +0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x28,0x46,0x00,0x80,0x11,0xa3,0x8c, +0x21,0x10,0x66,0x01,0x94,0x04,0x44,0x90,0x02,0x19,0x03,0x00,0x2b,0x18,0x64,0x00, +0x3a,0xff,0x60,0x10,0x00,0x00,0x00,0x00,0x78,0x11,0xa3,0x8c,0x80,0x10,0x0b,0x00, +0x02,0x80,0x04,0x3c,0x38,0x15,0x84,0x24,0x21,0x10,0x4b,0x00,0x01,0x00,0x63,0x24, +0x21,0x10,0x44,0x00,0x78,0x11,0xa3,0xac,0x21,0x10,0x4a,0x00,0xc9,0x03,0x44,0x90, +0x5c,0x11,0xa3,0x8c,0x00,0x00,0x00,0x00,0x21,0x18,0x64,0x00,0xd7,0x20,0x00,0x08, +0x5c,0x11,0xa3,0xac,0x18,0x24,0xa3,0x96,0x20,0x24,0xa2,0x96,0x01,0x00,0x63,0x24, +0x01,0x00,0x42,0x24,0x20,0x24,0xa2,0xa6,0x93,0x20,0x00,0x08,0x18,0x24,0xc3,0xa4, +0x08,0x00,0xe0,0x04,0x00,0x00,0x00,0x00,0x1a,0x24,0xa3,0x96,0x24,0x24,0xa2,0x96, +0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x24,0x24,0xa2,0xa6,0x93,0x20,0x00,0x08, +0x1a,0x24,0xc3,0xa4,0x18,0x24,0xa3,0x96,0x1e,0x24,0xa2,0x96,0x01,0x00,0x63,0x24, +0x01,0x00,0x42,0x24,0x1e,0x24,0xa2,0xa6,0x93,0x20,0x00,0x08,0x18,0x24,0xc3,0xa4, +0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x02,0x80,0x10,0x3c,0x38,0x15,0x02,0x8e, +0x00,0x00,0x00,0x00,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x11,0x00,0x40,0x14, +0x14,0x00,0xbf,0xaf,0x25,0xb0,0x05,0x3c,0x4c,0x00,0xa2,0x34,0x00,0x00,0x43,0x90, +0x38,0x15,0x07,0x26,0xf9,0x0a,0xe2,0x90,0x03,0x00,0x66,0x30,0x09,0x00,0x46,0x10, +0x58,0x00,0xa2,0x34,0x00,0x00,0x44,0x8c,0x29,0xb0,0x03,0x3c,0x5c,0x00,0xa2,0x34, +0x00,0x00,0x64,0xac,0x00,0x00,0x44,0x8c,0x04,0x00,0x63,0x34,0xf9,0x0a,0xe6,0xa0, +0x00,0x00,0x64,0xac,0x25,0xb0,0x02,0x3c,0x2d,0x0a,0x46,0x34,0xa2,0x0d,0x43,0x34, +0xa4,0x0d,0x44,0x34,0xa6,0x0d,0x45,0x34,0xa8,0x0d,0x42,0x34,0x00,0x00,0x67,0x94, +0x00,0x00,0x88,0x94,0x00,0x00,0xa9,0x94,0x00,0x00,0x44,0x94,0x00,0x00,0xc3,0x90, +0x38,0x15,0x02,0x26,0xe2,0x02,0x44,0xa4,0x40,0x00,0x63,0x34,0xff,0x00,0x63,0x30, +0x00,0x00,0xc3,0xa0,0xdc,0x02,0x47,0xa4,0xde,0x02,0x48,0xa4,0xe0,0x02,0x49,0xa4, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x07,0x3c,0x5b,0x0a,0xe2,0x34, +0x00,0x00,0x44,0x90,0x38,0x15,0x06,0x26,0x5c,0x0a,0xe2,0x34,0x00,0x00,0x45,0x90, +0xdc,0x02,0xc3,0x94,0xde,0x02,0xc2,0x94,0xe0,0x02,0xc9,0x94,0xe2,0x02,0xc8,0x94, +0xff,0x00,0x84,0x30,0x21,0x18,0x62,0x00,0x00,0x22,0x04,0x00,0xff,0x00,0xa5,0x30, +0x21,0x20,0x85,0x00,0x21,0x18,0x69,0x00,0xff,0xff,0x82,0x30,0x21,0x18,0x68,0x00, +0x21,0x18,0x62,0x00,0x64,0x0c,0xe7,0x34,0xff,0xff,0x42,0x30,0xe4,0x02,0xc3,0xac, +0x00,0x00,0xe2,0xa4,0xe8,0x02,0xc4,0xa4,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x02,0x26,0xfc,0x23,0x43,0x8c,0x25,0xb0,0x02,0x3c,0x68,0x0c,0x42,0x34, +0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x38,0x15,0x02,0x26,0x00,0x24,0x43,0x8c,0x25,0xb0,0x02,0x3c, +0x69,0x0c,0x42,0x34,0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30,0x00,0x00,0x43,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x38,0x15,0x02,0x26,0x04,0x24,0x43,0x8c, +0x25,0xb0,0x02,0x3c,0x6a,0x0c,0x42,0x34,0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30, +0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x38,0x15,0x02,0x26, +0x08,0x24,0x44,0x94,0x25,0xb0,0x03,0x3c,0x6c,0x0c,0x63,0x34,0x00,0x00,0x64,0xa4, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x38,0x15,0x02,0x26,0x0c,0x24,0x44,0x94, +0x25,0xb0,0x03,0x3c,0x6e,0x0c,0x63,0x34,0x00,0x00,0x64,0xa4,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x38,0x15,0x02,0x26,0x06,0x00,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x91,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x03,0x26,0x06,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x06,0x00,0x42,0x28, +0x06,0x00,0x40,0x10,0x02,0x80,0x04,0x3c,0xe8,0x02,0x62,0x94,0x00,0x00,0x00,0x00, +0x1f,0x00,0x42,0x28,0x16,0x00,0x40,0x14,0xf7,0xff,0x03,0x24,0x38,0x15,0x82,0x8c, +0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x34,0x38,0x15,0x82,0xac,0x38,0x15,0x02,0x8e, +0x38,0x15,0x04,0x26,0x06,0x00,0x80,0xa4,0x11,0x00,0x45,0x30,0x01,0x00,0x02,0x24, +0x16,0x00,0xa2,0x10,0xe8,0x02,0x80,0xa4,0x60,0x53,0x00,0x0c,0x00,0x00,0x00,0x00, +0x38,0x15,0x02,0x26,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x0c,0x24,0x40,0xac, +0x08,0x24,0x40,0xac,0x18,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x38,0x15,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,0x38,0x15,0x82,0xac, +0x38,0x15,0x02,0x8e,0x38,0x15,0x04,0x26,0x06,0x00,0x80,0xa4,0x11,0x00,0x45,0x30, +0x01,0x00,0x02,0x24,0xec,0xff,0xa2,0x14,0xe8,0x02,0x80,0xa4,0xe8,0x02,0x82,0x8c, +0x00,0x00,0x00,0x00,0x02,0x17,0x02,0x00,0x01,0x00,0x42,0x30,0xe6,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90, +0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,0x4e,0x00,0x65,0x10,0x38,0x15,0x05,0x26, +0xea,0x02,0xa2,0x90,0x00,0x00,0x00,0x00,0x07,0x00,0x40,0x14,0x38,0x15,0x06,0x26, +0x38,0x15,0x02,0x8e,0x01,0x00,0x03,0x24,0x42,0x11,0x02,0x00,0x01,0x00,0x42,0x30, +0x4b,0x00,0x43,0x10,0x3e,0x00,0x02,0x24,0xea,0x02,0xc3,0x90,0xff,0x00,0x02,0x24, +0xd1,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34, +0x00,0x00,0x45,0x90,0xcc,0x02,0xc4,0x94,0xe4,0x02,0xc7,0x8c,0x32,0x00,0x02,0x24, +0x20,0x00,0x03,0x24,0x7f,0x00,0xa5,0x30,0x2b,0x20,0xe4,0x00,0xd4,0x02,0xc2,0xa0, +0xd5,0x02,0xc3,0xa0,0x0c,0x00,0x80,0x14,0xff,0xff,0xa2,0x24,0xce,0x02,0xc2,0x94, +0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x00,0x09,0x00,0x40,0x14,0x38,0x15,0x04,0x26, +0xd0,0x02,0xc2,0x94,0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x00,0x02,0x00,0x40,0x10, +0x02,0x00,0xa2,0x24,0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30,0x38,0x15,0x04,0x26, +0xd4,0x02,0x83,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x65,0x00,0xca,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x21,0x28,0x60,0x00,0x38,0x15,0x03,0x26,0xe4,0x02,0x62,0x8c, +0x00,0x00,0x00,0x00,0x11,0x27,0x42,0x2c,0xbf,0x00,0x40,0x14,0x3a,0x00,0xa2,0x2c, +0x32,0x00,0x05,0x24,0x44,0x00,0x03,0x24,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34, +0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34,0x00,0x00,0x45,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x42,0x34, +0x00,0x00,0x45,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x66,0x22,0x00,0x08, +0x00,0x00,0x00,0x00,0xea,0x02,0x82,0x90,0x00,0x00,0x00,0x00,0xb0,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x24,0x88,0x22,0x00,0x08,0xea,0x02,0x82,0xa0, +0x02,0x00,0xa4,0x90,0xd4,0x02,0xa2,0xa0,0x1c,0x00,0x03,0x24,0x06,0x00,0x02,0x24, +0xa2,0x00,0x82,0x10,0xd5,0x02,0xa3,0xa0,0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34, +0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,0x7e,0xff,0x60,0x10, +0x38,0x15,0x04,0x26,0xfc,0x23,0x83,0x8c,0xff,0xff,0x02,0x34,0x7a,0xff,0x62,0x10, +0x00,0x00,0x00,0x00,0xe4,0x02,0x83,0x8c,0x00,0x00,0x00,0x00,0xe9,0x03,0x62,0x2c, +0xa7,0x00,0x40,0x14,0x90,0x01,0x62,0x2c,0xd6,0x02,0x83,0x90,0x00,0x00,0x00,0x00, +0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00,0xfe,0xff,0x42,0x24,0xfc,0xff,0x42,0x28, +0x02,0x00,0x40,0x10,0xfe,0xff,0x62,0x24,0xfc,0xff,0x02,0x24,0xd6,0x02,0x82,0xa0, +0x38,0x15,0x05,0x26,0x90,0x11,0xa2,0x8c,0x06,0x00,0x03,0x24,0x07,0x00,0x42,0x30, +0xa6,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0xfc,0x23,0xa2,0x8c,0x00,0x24,0xa3,0x8c, +0x0c,0x24,0xa4,0x8c,0x02,0x11,0x02,0x00,0x02,0x19,0x03,0x00,0x7f,0x00,0x4a,0x30, +0x7f,0x00,0x6b,0x30,0x2b,0x38,0x6a,0x01,0x21,0x30,0x40,0x01,0x05,0x00,0x80,0x14, +0x0a,0x30,0x67,0x01,0x80,0x11,0xa2,0x8c,0x00,0x00,0x00,0x00,0x02,0x11,0x02,0x00, +0x7f,0x00,0x46,0x30,0x25,0xb0,0x02,0x3c,0x04,0x0d,0x42,0x34,0x00,0x00,0x43,0x90, +0x01,0x00,0x02,0x24,0xff,0x00,0x63,0x30,0x8d,0x00,0x62,0x10,0x04,0x00,0xc2,0x24, +0x02,0x00,0xe0,0x14,0x23,0x10,0x4b,0x01,0x23,0x10,0x6a,0x01,0xff,0x00,0x42,0x30, +0x15,0x00,0x42,0x2c,0x05,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,0x38,0x15,0x03,0x26, +0x0a,0x00,0x02,0x24,0xd6,0x02,0x62,0xa0,0x25,0xb0,0x02,0x3c,0x6c,0x03,0x42,0x34, +0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00, +0x02,0x00,0x40,0x14,0x0a,0x00,0x42,0x24,0x0a,0x00,0xc2,0x24,0x38,0x15,0x04,0x26, +0xd6,0x02,0x83,0x90,0x00,0x36,0x02,0x00,0x03,0x36,0x06,0x00,0xd2,0x02,0x85,0x90, +0x23,0x18,0xc3,0x00,0x00,0x36,0x03,0x00,0x03,0x36,0x06,0x00,0xff,0x00,0xa2,0x30, +0x2a,0x10,0x46,0x00,0x5c,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x36,0x05,0x00, +0x03,0x36,0x06,0x00,0x38,0x15,0x03,0x26,0xe4,0x02,0x62,0x8c,0x00,0x00,0x00,0x00, +0x11,0x27,0x42,0x2c,0x50,0x00,0x40,0x14,0x3a,0x00,0xc2,0x28,0x32,0x00,0xc2,0x28, +0x4d,0x00,0x40,0x10,0x3a,0x00,0xc2,0x28,0x32,0x00,0x06,0x24,0x44,0x00,0x03,0x24, +0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,0x00,0x00,0x43,0xa0,0x38,0x15,0x03,0x26, +0x08,0x24,0x62,0x8c,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c, +0x0c,0x24,0x62,0x8c,0x00,0x00,0x00,0x00,0x15,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c, +0x50,0x0c,0x42,0x34,0xff,0x00,0xc4,0x30,0x00,0x00,0x44,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x42,0x34,0x00,0x00,0x44,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x66,0x22,0x00,0x08,0x00,0x00,0x00,0x00, +0xd3,0x02,0x63,0x90,0x50,0x0c,0x42,0x34,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x38,0x15,0x02,0x26,0xd3,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x58,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x66,0x22,0x00,0x08,0x00,0x00,0x00,0x00,0x43,0xff,0x40,0x10,0x48,0x00,0x03,0x24, +0xbe,0x22,0x00,0x08,0x44,0x00,0x03,0x24,0xd5,0x02,0x83,0x90,0x00,0x00,0x00,0x00, +0x2b,0x10,0xa3,0x00,0xb6,0x22,0x00,0x08,0x0b,0x28,0x62,0x00,0x25,0xb0,0x02,0x3c, +0x00,0x08,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x27,0x18,0x03,0x00, +0x01,0x00,0x63,0x30,0x59,0xff,0x60,0x10,0x25,0xb0,0x02,0x3c,0x36,0x00,0x02,0x24, +0xe2,0x22,0x00,0x08,0xd2,0x02,0xa2,0xa0,0xb5,0xff,0x40,0x10,0x48,0x00,0x03,0x24, +0x44,0x23,0x00,0x08,0x44,0x00,0x03,0x24,0xd3,0x02,0x83,0x80,0x00,0x00,0x00,0x00, +0xff,0x00,0x62,0x30,0x2a,0x10,0xc2,0x00,0x39,0x23,0x00,0x08,0x0b,0x30,0x62,0x00, +0x64,0xff,0x40,0x10,0x38,0x15,0x05,0x26,0xd6,0x02,0x83,0x90,0x00,0x00,0x00,0x00, +0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00,0x02,0x00,0x42,0x24,0x0d,0x00,0x42,0x28, +0x09,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xfb,0x22,0x00,0x08,0x0c,0x00,0x02,0x24, +0x00,0x36,0x02,0x00,0x18,0x23,0x00,0x08,0x03,0x36,0x06,0x00,0x80,0x11,0xa2,0x8c, +0x0f,0x23,0x00,0x08,0x2b,0x38,0x6a,0x01,0xfb,0x22,0x00,0x08,0x02,0x00,0x62,0x24, +0xc0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,0x25,0xb0,0x14,0x3c,0x24,0x00,0xb3,0xaf, +0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf, +0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x20,0x00,0xb2,0xaf, +0xd8,0x00,0x86,0x36,0x00,0x00,0xc3,0x90,0x02,0x80,0x02,0x3c,0x38,0x15,0x51,0x24, +0x2a,0xb0,0x10,0x3c,0xa0,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x34,0x00,0x05,0x36, +0xfe,0xff,0x02,0x24,0xbc,0x02,0x32,0x92,0x40,0x00,0x04,0x24,0x00,0x00,0xc3,0xa0, +0x00,0x00,0xa2,0xa0,0x1f,0x49,0x00,0x0c,0x00,0x96,0x12,0x00,0x21,0x98,0x40,0x00, +0x8d,0x00,0x60,0x12,0x00,0x40,0x02,0x3c,0x08,0x00,0x63,0x8e,0xb0,0x03,0x82,0x36, +0x25,0xb0,0x1e,0x3c,0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,0xfb,0x44,0x00,0x0c, +0x21,0xb8,0x20,0x02,0x42,0x00,0xd5,0x37,0x03,0x0c,0xd1,0x37,0x17,0x0e,0xd6,0x37, +0x04,0x00,0x14,0x24,0x2a,0xb0,0x03,0x3c,0x06,0x00,0x63,0x34,0x00,0x00,0x62,0x94, +0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30,0x0a,0x00,0x40,0x18,0x00,0x00,0x00,0x00, +0x02,0x80,0x04,0x3c,0x98,0x91,0x84,0x24,0x00,0x00,0x83,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30,0xfc,0xff,0x40,0x1c, +0x00,0x00,0x00,0x00,0x08,0x00,0x65,0x8e,0x20,0x10,0x06,0x3c,0x01,0x00,0x04,0x24, +0x00,0xfe,0xc6,0x34,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa4,0xaf, +0x4d,0x01,0x00,0x0c,0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,0x9c,0x91,0x42,0x24, +0x00,0x00,0x45,0x8c,0x01,0x00,0x03,0x24,0x21,0x20,0x00,0x00,0x00,0x00,0xa3,0xa0, +0xff,0xff,0x03,0x24,0x00,0x00,0xa3,0xa2,0x00,0x00,0x22,0x92,0x00,0x00,0x00,0x00, +0xff,0x00,0x42,0x30,0x40,0x00,0x42,0x34,0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24, +0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24, +0x02,0x00,0x02,0x24,0x02,0x80,0x04,0x3c,0x00,0x00,0xa2,0xa0,0x38,0x15,0x83,0x24, +0xc1,0x02,0x62,0x90,0x00,0x00,0xc4,0x92,0x21,0x28,0x00,0x00,0x00,0x00,0xc2,0xa2, +0xff,0x00,0x90,0x30,0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30,0x06,0x00,0xa3,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0xa2,0x24,0xef,0xff,0x02,0x24,0x64,0x00,0x04,0x24, +0x00,0x00,0xa2,0xa2,0x21,0x1a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x92, +0x21,0x20,0x00,0x00,0xbf,0x00,0x42,0x30,0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24, +0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24, +0x21,0x1a,0x00,0x0c,0x84,0x03,0x04,0x24,0xf4,0x08,0xc2,0x37,0x00,0x00,0x43,0x8c, +0x00,0x80,0x04,0x3c,0xdf,0x07,0x84,0x34,0x00,0x00,0xd0,0xa2,0x21,0x10,0x00,0x00, +0x24,0x28,0x64,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x00,0x00,0xa0,0xa2,0x00,0x00,0x22,0x92, +0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x40,0x00,0x42,0x34,0x00,0x00,0x22,0xa2, +0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x82,0x24,0xbe,0x02,0xe2,0x92,0x1f,0x00,0xa3,0x30,0x2b,0x10,0x62,0x00, +0x0a,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0xbf,0x02,0xe2,0x92,0x00,0x00,0x00,0x00, +0x2b,0x10,0x43,0x00,0x05,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x01,0x00,0x02,0x3c, +0x25,0x10,0x62,0x00,0x21,0x90,0x42,0x02,0x02,0x80,0x02,0x3c,0xb6,0x3d,0x43,0x90, +0x22,0x00,0x02,0x24,0x1c,0x00,0x62,0x10,0x92,0x00,0x02,0x24,0x1b,0x00,0x62,0x10, +0x02,0x80,0x03,0x3c,0xff,0xff,0x94,0x26,0x21,0x1a,0x00,0x0c,0xf4,0x01,0x04,0x24, +0x89,0xff,0x81,0x06,0x2a,0xb0,0x03,0x3c,0x04,0x00,0x60,0x12,0x25,0xb0,0x02,0x3c, +0x40,0x49,0x00,0x0c,0x21,0x20,0x60,0x02,0x25,0xb0,0x02,0x3c,0xd8,0x02,0x42,0x34, +0x00,0x00,0x52,0xac,0x21,0x10,0x40,0x02,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f, +0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,0x38,0x15,0x63,0x24, +0xbe,0x02,0x62,0x90,0xc0,0x07,0xa3,0x30,0x82,0x19,0x03,0x00,0x2b,0x10,0x62,0x00, +0xe0,0xff,0x40,0x10,0x02,0x80,0x04,0x3c,0x38,0x15,0x84,0x24,0xbf,0x02,0x82,0x90, +0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x00,0xda,0xff,0x40,0x10,0x00,0x12,0x03,0x00, +0x10,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x49,0x24,0x00,0x08,0x21,0x90,0x42,0x02, +0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36, +0xf0,0xf8,0x06,0x34,0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf, +0x6a,0x44,0x00,0x0c,0x14,0x00,0xb1,0xaf,0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24, +0x02,0x80,0x12,0x3c,0xff,0xff,0x05,0x36,0x56,0x30,0x06,0x24,0x6a,0x44,0x00,0x0c, +0x1a,0x00,0x04,0x24,0x38,0x15,0x51,0x26,0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24, +0x08,0x03,0x23,0x92,0x04,0x00,0x02,0x24,0x20,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c, +0x18,0x03,0x25,0x8e,0x25,0xb0,0x10,0x3c,0xed,0x53,0x00,0x0c,0x00,0x0e,0x04,0x36, +0x18,0x03,0x25,0x8e,0xed,0x53,0x00,0x0c,0x04,0x0e,0x04,0x36,0x1c,0x03,0x25,0x8e, +0xed,0x53,0x00,0x0c,0x08,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,0xed,0x53,0x00,0x0c, +0x10,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,0xed,0x53,0x00,0x0c,0x14,0x0e,0x04,0x36, +0x18,0x03,0x25,0x8e,0xed,0x53,0x00,0x0c,0x18,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e, +0xed,0x53,0x00,0x0c,0x1c,0x0e,0x04,0x36,0x38,0x15,0x43,0x26,0x1c,0x00,0xbf,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x04,0x00,0x02,0x24, +0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x62,0xa0,0x00,0x0e,0x42,0x34, +0x00,0x00,0x43,0x8c,0x18,0x03,0x25,0x8e,0x00,0x00,0x00,0x00,0xde,0xff,0x65,0x14, +0x25,0xb0,0x10,0x3c,0xa3,0x24,0x00,0x08,0x38,0x15,0x43,0x26,0xe0,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34, +0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x6a,0x44,0x00,0x0c, +0x14,0x00,0xb1,0xaf,0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36, +0x56,0x30,0x06,0x24,0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x02,0x80,0x10,0x3c, +0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24,0x38,0x15,0x02,0x26,0x08,0x03,0x46,0x90, +0x25,0xb0,0x11,0x3c,0x10,0x10,0x12,0x3c,0x01,0x00,0x03,0x24,0x00,0x0e,0x24,0x36, +0x1e,0x00,0xc3,0x10,0x10,0x10,0x45,0x36,0xed,0x53,0x00,0x0c,0x00,0x00,0x00,0x00, +0x04,0x0e,0x24,0x36,0xed,0x53,0x00,0x0c,0x10,0x10,0x45,0x36,0x08,0x0e,0x24,0x36, +0xed,0x53,0x00,0x0c,0x10,0x10,0x05,0x24,0x10,0x0e,0x24,0x36,0xed,0x53,0x00,0x0c, +0x10,0x10,0x45,0x36,0x14,0x0e,0x24,0x36,0xed,0x53,0x00,0x0c,0x10,0x10,0x45,0x36, +0x18,0x0e,0x24,0x36,0xed,0x53,0x00,0x0c,0x10,0x10,0x45,0x36,0x1c,0x0e,0x24,0x36, +0xed,0x53,0x00,0x0c,0x10,0x10,0x45,0x36,0x38,0x15,0x03,0x26,0x1c,0x00,0xbf,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24, +0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x62,0xa0,0x00,0x00,0x86,0x8c, +0x00,0x00,0x00,0x00,0xe0,0xff,0xc5,0x14,0x38,0x15,0x03,0x26,0x1c,0x00,0xbf,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24, +0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x62,0xa0,0xe0,0xff,0xbd,0x27, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x11,0x3c,0x01,0x00,0x10,0x3c, +0xff,0xff,0x25,0x36,0xf4,0x98,0x06,0x36,0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf, +0x6a,0x44,0x00,0x0c,0x18,0x00,0xb2,0xaf,0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24, +0x56,0x30,0x06,0x36,0xff,0xff,0x25,0x36,0x1a,0x00,0x04,0x24,0x6a,0x44,0x00,0x0c, +0x02,0x80,0x11,0x3c,0x38,0x15,0x30,0x26,0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24, +0x08,0x03,0x02,0x92,0x25,0xb0,0x12,0x3c,0x08,0x00,0x40,0x14,0x08,0x0e,0x44,0x36, +0x25,0xb0,0x02,0x3c,0x00,0x0e,0x42,0x34,0x00,0x00,0x45,0x8c,0xf0,0x02,0x03,0x8e, +0x00,0x00,0x00,0x00,0x17,0x00,0xa3,0x10,0x38,0x15,0x22,0x26,0xec,0x02,0x05,0x8e, +0xed,0x53,0x00,0x0c,0x00,0x00,0x00,0x00,0xf0,0x02,0x05,0x8e,0xed,0x53,0x00,0x0c, +0x00,0x0e,0x44,0x36,0xf4,0x02,0x05,0x8e,0xed,0x53,0x00,0x0c,0x04,0x0e,0x44,0x36, +0xf8,0x02,0x05,0x8e,0xed,0x53,0x00,0x0c,0x10,0x0e,0x44,0x36,0xfc,0x02,0x05,0x8e, +0xed,0x53,0x00,0x0c,0x14,0x0e,0x44,0x36,0x00,0x03,0x05,0x8e,0xed,0x53,0x00,0x0c, +0x18,0x0e,0x44,0x36,0x04,0x03,0x05,0x8e,0xed,0x53,0x00,0x0c,0x1c,0x0e,0x44,0x36, +0x38,0x15,0x22,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x40,0xa0, +0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x11,0x3c, +0x01,0x00,0x10,0x3c,0xff,0xff,0x25,0x36,0xf4,0x98,0x06,0x36,0x15,0x00,0x04,0x24, +0x1c,0x00,0xbf,0xaf,0x6a,0x44,0x00,0x0c,0x18,0x00,0xb2,0xaf,0x21,0x1a,0x00,0x0c, +0x64,0x00,0x04,0x24,0x02,0x80,0x12,0x3c,0xff,0xff,0x25,0x36,0x56,0x30,0x06,0x36, +0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x38,0x15,0x51,0x26,0x21,0x1a,0x00,0x0c, +0x64,0x00,0x04,0x24,0x08,0x03,0x23,0x92,0x03,0x00,0x02,0x24,0x2c,0x00,0x62,0x10, +0x25,0xb0,0x02,0x3c,0xf0,0x02,0x25,0x8e,0x25,0xb0,0x10,0x3c,0xed,0x53,0x00,0x0c, +0x00,0x0e,0x04,0x36,0xf4,0x02,0x25,0x8e,0xed,0x53,0x00,0x0c,0x04,0x0e,0x04,0x36, +0xf8,0x02,0x25,0x8e,0xed,0x53,0x00,0x0c,0x10,0x0e,0x04,0x36,0xfc,0x02,0x25,0x8e, +0xed,0x53,0x00,0x0c,0x14,0x0e,0x04,0x36,0x00,0x03,0x25,0x8e,0xed,0x53,0x00,0x0c, +0x18,0x0e,0x04,0x36,0x04,0x03,0x25,0x8e,0xed,0x53,0x00,0x0c,0x1c,0x0e,0x04,0x36, +0x0c,0x03,0x24,0x8e,0xec,0x02,0x22,0x8e,0x00,0x00,0x00,0x00,0x21,0x28,0x44,0x00, +0x00,0xff,0xa3,0x30,0xff,0xff,0x02,0x3c,0xff,0x00,0x42,0x34,0x01,0x3f,0x63,0x2c, +0x24,0x10,0xa2,0x00,0x0c,0x00,0x60,0x10,0x08,0x0e,0x04,0x36,0xed,0x53,0x00,0x0c, +0x00,0x00,0x00,0x00,0x38,0x15,0x43,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x03,0x00,0x02,0x24,0x20,0x00,0xbd,0x27, +0x08,0x00,0xe0,0x03,0x08,0x03,0x62,0xa0,0x6b,0x25,0x00,0x08,0x00,0x3f,0x45,0x34, +0x00,0x0e,0x42,0x34,0x00,0x00,0x43,0x8c,0xf0,0x02,0x25,0x8e,0x00,0x00,0x00,0x00, +0xd2,0xff,0x65,0x14,0x25,0xb0,0x10,0x3c,0x6e,0x25,0x00,0x08,0x38,0x15,0x43,0x26, +0x25,0xb0,0x03,0x3c,0x02,0x80,0x06,0x3c,0x50,0x0c,0x63,0x34,0x38,0x15,0xc4,0x8c, +0x00,0x00,0x65,0x90,0x1a,0x00,0x02,0x24,0x10,0x00,0x84,0x34,0x00,0x2e,0x05,0x00, +0x00,0x00,0x62,0xa0,0x03,0x2e,0x05,0x00,0x38,0x15,0xc4,0xac,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x25,0xb0,0x07,0x3c,0xf8,0x08,0xe2,0x34,0x00,0x00,0x43,0x90, +0x00,0x00,0x00,0x00,0x00,0x1e,0x03,0x00,0x03,0x1e,0x03,0x00,0x21,0x18,0xa3,0x00, +0x92,0xff,0x64,0x24,0xbb,0xff,0x82,0x28,0x07,0x00,0x40,0x14,0xff,0x00,0xa2,0x30, +0x38,0x15,0xc3,0x24,0x06,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24, +0x06,0x00,0x62,0xa4,0xff,0x00,0xa2,0x30,0x50,0x0c,0xe3,0x34,0x00,0x00,0x62,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x38,0x15,0xc3,0x8c,0xef,0xff,0x02,0x24, +0x23,0x20,0x04,0x00,0x24,0x18,0x62,0x00,0x25,0xb0,0x02,0x3c,0x92,0x0c,0x42,0x34, +0xff,0x00,0x84,0x30,0x38,0x15,0xc3,0xac,0x00,0x00,0x44,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xd8,0xff,0xbd,0x27, +0x18,0x00,0xb2,0xaf,0x02,0x80,0x12,0x3c,0x38,0x15,0x43,0x8e,0x25,0xb0,0x02,0x3c, +0x90,0x0c,0x42,0x34,0xc2,0x18,0x03,0x00,0x01,0x00,0x63,0x30,0x00,0x00,0x43,0xa0, +0x24,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf, +0x10,0x00,0xb0,0xaf,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x38,0x15,0x46,0x26, +0x90,0x11,0xc2,0x8c,0x06,0x00,0x03,0x24,0x07,0x00,0x42,0x30,0x7a,0x00,0x43,0x10, +0x00,0x00,0x00,0x00,0xfc,0x23,0xc4,0x8c,0x00,0x24,0xc2,0x8c,0x0c,0x24,0xc5,0x8c, +0x02,0x21,0x04,0x00,0x02,0x11,0x02,0x00,0x7f,0x00,0x84,0x30,0x7f,0x00,0x42,0x30, +0x2b,0x18,0x44,0x00,0x21,0xa0,0x80,0x00,0x6f,0x00,0xa0,0x10,0x0a,0xa0,0x43,0x00, +0x38,0x15,0x42,0x8e,0x38,0x15,0x44,0x26,0x40,0x00,0x03,0x24,0xc4,0x00,0x42,0x30, +0x08,0x03,0x93,0x90,0x73,0x00,0x43,0x10,0x01,0x00,0x02,0x24,0x25,0xb0,0x08,0x3c, +0x4c,0x00,0x03,0x35,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30, +0x34,0x00,0x40,0x10,0x38,0x15,0x45,0x26,0x38,0x15,0x42,0x92,0x00,0x00,0x00,0x00, +0x82,0x11,0x02,0x00,0x2f,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x0e,0x05,0x35, +0x00,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x69,0x00,0x40,0x10,0x10,0x0e,0x07,0x35, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x08,0x0e,0x02,0x35,0x04,0x0e,0x03,0x35,0x00,0x00,0x44,0x8c,0x00,0x00,0xa5,0x8c, +0x00,0x00,0x66,0x8c,0x02,0x80,0x02,0x3c,0x38,0x15,0x49,0x24,0xec,0x02,0x24,0xad, +0xf0,0x02,0x25,0xad,0xf4,0x02,0x26,0xad,0x14,0x0e,0x04,0x35,0x02,0x80,0x02,0x3c, +0x18,0x0e,0x05,0x35,0x00,0x00,0xe7,0x8c,0x1c,0x0e,0x06,0x35,0x00,0x00,0x83,0x8c, +0xb6,0x3d,0x4a,0x90,0x00,0x00,0xa2,0x8c,0x00,0x00,0xc4,0x8c,0xf8,0x02,0x27,0xad, +0x00,0x03,0x22,0xad,0x22,0x00,0x02,0x24,0xfc,0x02,0x23,0xad,0xa0,0x00,0x42,0x11, +0x04,0x03,0x24,0xad,0x92,0x00,0x02,0x24,0x9e,0x00,0x42,0x11,0x0d,0x08,0x02,0x35, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x38,0x15,0x42,0x8e, +0x3f,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x40,0x00,0x42,0x34,0x38,0x15,0x42,0xae, +0x38,0x15,0x45,0x26,0x08,0x03,0xa2,0x8c,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00, +0x0f,0x00,0x40,0x14,0x38,0x15,0x42,0x26,0x25,0xb0,0x02,0x3c,0x84,0x01,0x42,0x34, +0x00,0x00,0x44,0x8c,0x0d,0x00,0x03,0x24,0x81,0x00,0x83,0x10,0x40,0x00,0x02,0x24, +0x4a,0x00,0x03,0x24,0x23,0x03,0xa2,0xa0,0x45,0x00,0x02,0x24,0x20,0x03,0xa3,0xa0, +0x21,0x03,0xa2,0xa0,0x46,0x00,0x03,0x24,0x22,0x03,0xa3,0xa0,0x38,0x15,0x42,0x26, +0x80,0x11,0x43,0x8c,0x25,0xb0,0x02,0x3c,0x60,0x0c,0x42,0x34,0x02,0x19,0x03,0x00, +0xff,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x44,0x8e,0x44,0x00,0x02,0x24,0xc4,0x00,0x83,0x30,0x35,0x00,0x62,0x10, +0x38,0x15,0x45,0x26,0x24,0x00,0xbf,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x80,0x11,0xc2,0x8c,0x38,0x15,0x44,0x26, +0x40,0x00,0x03,0x24,0x02,0x11,0x02,0x00,0x7f,0x00,0x54,0x30,0x38,0x15,0x42,0x8e, +0x08,0x03,0x93,0x90,0xc4,0x00,0x42,0x30,0x91,0xff,0x43,0x14,0x25,0xb0,0x08,0x3c, +0x01,0x00,0x02,0x24,0x0d,0x00,0x62,0x12,0x04,0x00,0x02,0x24,0x0b,0x00,0x62,0x12, +0x38,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0xe7,0x25,0x00,0x08,0x08,0x03,0x62,0xa0, +0x00,0x00,0xe3,0x8c,0x3f,0x3f,0x02,0x3c,0x3f,0x3f,0x42,0x34,0x94,0xff,0x62,0x14, +0x00,0x00,0x00,0x00,0x21,0x26,0x00,0x08,0x38,0x15,0x45,0x26,0x0f,0x00,0x10,0x3c, +0x01,0x00,0x11,0x3c,0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0x6a,0x44,0x00,0x0c, +0x15,0x00,0x04,0x24,0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36, +0x56,0x30,0x26,0x36,0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x21,0x1a,0x00,0x0c, +0x64,0x00,0x04,0x24,0x38,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0xe7,0x25,0x00,0x08, +0x08,0x03,0x62,0xa0,0xfc,0x23,0xa3,0x8c,0xff,0xff,0x02,0x34,0xc9,0xff,0x62,0x10, +0x42,0x11,0x04,0x00,0x01,0x00,0x42,0x30,0x01,0x00,0x03,0x24,0xc5,0xff,0x43,0x14, +0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00, +0x03,0x00,0x63,0x30,0xbf,0xff,0x60,0x10,0x00,0x00,0x00,0x00,0x08,0x24,0xa2,0x8c, +0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x0c,0x24,0xa2,0x8c, +0x00,0x00,0x00,0x00,0x1a,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x38,0x15,0x42,0x8e, +0x00,0x00,0x00,0x00,0xc2,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x14,0x00,0x40,0x14, +0x02,0x80,0x03,0x3c,0x03,0x00,0x02,0x24,0x4b,0x00,0x62,0x12,0x04,0x00,0x62,0x2a, +0x2d,0x00,0x40,0x10,0x04,0x00,0x02,0x24,0x51,0x00,0x60,0x12,0x01,0x00,0x02,0x24, +0xa8,0xff,0x62,0x16,0x38,0x15,0x63,0x24,0x20,0x03,0x62,0x90,0x00,0x00,0x00,0x00, +0x2b,0x10,0x82,0x02,0x3c,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x23,0x03,0x62,0x90, +0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,0x2d,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0xf7,0x24,0x00,0x0c,0x00,0x00,0x00,0x00,0x45,0x26,0x00,0x08,0x00,0x00,0x00,0x00, +0x3b,0x00,0x02,0x24,0x46,0x00,0x03,0x24,0x23,0x03,0xa2,0xa0,0x20,0x03,0xa3,0xa0, +0x41,0x00,0x02,0x24,0x40,0x00,0x03,0x24,0x32,0x26,0x00,0x08,0x21,0x03,0xa2,0xa0, +0x0d,0x08,0x02,0x35,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x63,0x30, +0x08,0x00,0x62,0x2c,0x0f,0x00,0x63,0x38,0x5d,0xff,0x40,0x14,0x01,0x00,0x65,0x24, +0x00,0x16,0x05,0x00,0x00,0x24,0x05,0x00,0x00,0x1a,0x05,0x00,0x25,0x10,0x44,0x00, +0x25,0x10,0x43,0x00,0x25,0x10,0x45,0x00,0x25,0x18,0x65,0x00,0x1c,0x03,0x23,0xad, +0x18,0x26,0x00,0x08,0x18,0x03,0x22,0xad,0x11,0x00,0x62,0x12,0xff,0x00,0x02,0x24, +0x7c,0xff,0x62,0x16,0x38,0x15,0x63,0x24,0x22,0x03,0x62,0x90,0x00,0x00,0x00,0x00, +0x2b,0x10,0x82,0x02,0x24,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x20,0x03,0x62,0x90, +0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x0b,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0xb3,0x24,0x00,0x0c,0x00,0x00,0x00,0x00,0x45,0x26,0x00,0x08,0x00,0x00,0x00,0x00, +0x38,0x15,0x63,0x24,0x21,0x03,0x62,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00, +0xf7,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x74,0x24,0x00,0x0c,0x00,0x00,0x00,0x00, +0x45,0x26,0x00,0x08,0x00,0x00,0x00,0x00,0x38,0x15,0x63,0x24,0x24,0x03,0x62,0x90, +0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0xc1,0xff,0x40,0x10,0x00,0x00,0x00,0x00, +0x34,0x25,0x00,0x0c,0x00,0x00,0x00,0x00,0x45,0x26,0x00,0x08,0x00,0x00,0x00,0x00, +0x38,0x15,0x63,0x24,0x22,0x03,0x62,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02, +0xe3,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x25,0x03,0x62,0x90,0x00,0x00,0x00,0x00, +0x2b,0x10,0x54,0x00,0xb2,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x34,0x25,0x00,0x0c, +0x00,0x00,0x00,0x00,0x45,0x26,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x08,0x3c, +0x38,0x15,0x05,0x25,0x80,0x11,0xa4,0x8c,0xea,0x02,0xa3,0x90,0x02,0x11,0x04,0x00, +0x26,0x00,0x60,0x14,0x7f,0x00,0x46,0x30,0x25,0xb0,0x07,0x3c,0x4c,0x00,0xe2,0x34, +0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x60,0x10,0x00,0x00,0x00,0x00, +0xff,0xff,0x02,0x34,0x1d,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x00,0x08,0xe3,0x34, +0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x19,0x00,0x40,0x10, +0x4b,0x00,0xc2,0x2c,0x3e,0x00,0x40,0x10,0x01,0x00,0x04,0x24,0xd8,0xff,0xc2,0x24, +0x1e,0x00,0x42,0x2c,0x49,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,0x38,0x15,0x04,0x25, +0xd7,0x02,0x82,0x90,0x00,0x00,0x00,0x00,0x44,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c, +0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34,0x20,0x00,0x03,0x24,0x00,0x00,0x43,0xa0, +0xd7,0x02,0x80,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x17,0x00,0x40,0x10,0x01,0x00,0x04,0x24,0xd8,0xff,0xc2,0x24, +0x1e,0x00,0x42,0x2c,0x44,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,0x38,0x15,0x04,0x25, +0xd7,0x02,0x82,0x90,0x00,0x00,0x00,0x00,0x3f,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c, +0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,0x44,0x00,0x03,0x24,0x00,0x00,0x43,0xa0, +0xd7,0x02,0x80,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0xd7,0x02,0xa2,0x90,0x00,0x00,0x00,0x00,0xe7,0xff,0x44,0x10, +0x43,0x00,0x02,0x24,0x30,0x0c,0xe3,0x34,0xd7,0x02,0xa4,0xa0,0x00,0x00,0x62,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0xd7,0x02,0xa2,0x90,0x00,0x00,0x00,0x00,0xc0,0xff,0x44,0x10,0x10,0x00,0x02,0x24, +0x87,0x0c,0xe3,0x34,0xd7,0x02,0xa4,0xa0,0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xc7,0xff,0x40,0x10, +0x00,0x00,0x00,0x00,0x38,0x15,0x04,0x25,0xd7,0x02,0x82,0x90,0x02,0x00,0x03,0x24, +0xc2,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34, +0xd7,0x02,0x83,0xa0,0x00,0x00,0x40,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xb4,0xff,0x40,0x10,0x00,0x00,0x00,0x00, +0x38,0x15,0x04,0x25,0xd7,0x02,0x82,0x90,0x02,0x00,0x03,0x24,0xaf,0xff,0x43,0x10, +0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xd7,0x02,0x83,0xa0,0x30,0x0c,0x42,0x34, +0x42,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xff,0xff,0x8d,0x30,0x00,0x60,0x0f,0x40, +0x01,0x00,0xe1,0x35,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x06,0x3c, +0x38,0x15,0xce,0x24,0x82,0x0b,0xc2,0x91,0x00,0x00,0x00,0x00,0x1d,0x00,0x40,0x10, +0x25,0xb0,0x03,0x3c,0x38,0x02,0x64,0x34,0x80,0xff,0x02,0x24,0x00,0x00,0x82,0xa0, +0x34,0x02,0x6a,0x34,0xd2,0x01,0x65,0x34,0xd6,0x01,0x66,0x34,0xda,0x01,0x67,0x34, +0xde,0x01,0x63,0x34,0x00,0x00,0xa8,0x94,0x00,0x00,0xc9,0x94,0x00,0x00,0xeb,0x94, +0x00,0x00,0x6c,0x94,0x00,0x00,0x44,0x95,0xb0,0xfe,0xa2,0x25,0xff,0xff,0x4d,0x30, +0x80,0x0b,0xc4,0xa5,0x00,0x00,0xa0,0xa4,0x78,0x0b,0xc8,0xa5,0x00,0x00,0xc0,0xa4, +0x7a,0x0b,0xc9,0xa5,0x00,0x00,0xe0,0xa4,0x7c,0x0b,0xcb,0xa5,0x00,0x00,0x60,0xa4, +0x00,0x00,0x4d,0xa5,0x7e,0x0b,0xcc,0xa5,0x00,0x60,0x8f,0x40,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x2a,0xb0,0x02,0x3c,0x0a,0x00,0x45,0x34,0x63,0x00,0x03,0x24, +0xff,0xff,0x04,0x34,0x00,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,0x0a,0x00,0x40,0x10, +0x38,0x15,0xc2,0x24,0x64,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x42,0x30, +0xfe,0xff,0x40,0x14,0xff,0xff,0x42,0x24,0xff,0xff,0x62,0x24,0xff,0xff,0x43,0x30, +0xf4,0xff,0x64,0x14,0x38,0x15,0xc2,0x24,0x80,0x0b,0x48,0x94,0x7e,0x0b,0x47,0x94, +0x78,0x0b,0x49,0x94,0x7a,0x0b,0x4a,0x94,0x7c,0x0b,0x4b,0x94,0x25,0xb0,0x03,0x3c, +0x38,0x02,0x6c,0x34,0x34,0x02,0x62,0x34,0xd2,0x01,0x64,0x34,0xd6,0x01,0x65,0x34, +0xda,0x01,0x66,0x34,0xde,0x01,0x63,0x34,0x00,0x00,0x48,0xa4,0x00,0x00,0x89,0xa4, +0x00,0x00,0xaa,0xa4,0x00,0x00,0xcb,0xa4,0x00,0x00,0x67,0xa4,0x00,0x00,0x80,0xa1, +0x00,0x60,0x8f,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c, +0x08,0x00,0x83,0x34,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x00,0x14,0x02,0x00, +0x03,0x14,0x02,0x00,0x1a,0x00,0x40,0x04,0x60,0x02,0x85,0x34,0x00,0x00,0xa3,0x90, +0x05,0x00,0x02,0x24,0x00,0x03,0x8b,0x34,0xff,0x00,0x63,0x30,0x04,0x03,0x8c,0x34, +0xbd,0x00,0x8a,0x34,0x03,0x00,0x86,0x34,0x40,0x00,0x85,0x34,0xfc,0x77,0x09,0x24, +0x11,0x00,0x62,0x10,0x23,0x00,0x84,0x34,0x00,0x00,0xc2,0x90,0xfe,0xff,0x03,0x24, +0x24,0x10,0x43,0x00,0x00,0x00,0xc2,0xa0,0x22,0x00,0x02,0x24,0x00,0x00,0x60,0xad, +0x00,0x00,0x80,0xad,0x00,0x00,0x82,0xa0,0xfc,0x37,0x02,0x24,0x00,0x00,0xa9,0xa4, +0x00,0x00,0xa2,0xa4,0x00,0x00,0xa9,0xa4,0x00,0x00,0xa0,0xa4,0x00,0x00,0xa0,0xa4, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad, +0x00,0x00,0x42,0x91,0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x34,0x00,0x00,0x42,0xa1, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x1c,0x00,0xb1,0xaf, +0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf, +0x18,0x00,0xb0,0xaf,0xff,0xff,0x11,0x24,0x02,0x80,0x13,0x3c,0x41,0xb0,0x02,0x3c, +0x38,0x15,0x66,0x26,0x04,0x00,0x42,0x34,0x00,0x00,0x47,0x8c,0x0c,0x0b,0xc5,0x8c, +0x02,0x80,0x03,0x3c,0xbe,0x3d,0x64,0x90,0x08,0x0b,0xc8,0x8c,0x02,0x80,0x02,0x3c, +0xe0,0x3d,0x49,0x90,0x25,0xb0,0x0a,0x3c,0x25,0x90,0xa7,0x00,0xb0,0x03,0x42,0x35, +0x00,0x00,0x52,0xac,0x00,0x24,0x04,0x00,0x00,0x00,0x48,0xac,0x84,0x02,0x43,0x35, +0x8c,0x02,0x45,0x35,0x01,0x00,0x02,0x24,0x00,0x00,0x72,0xac,0x00,0x00,0xa4,0xac, +0x8d,0x04,0x22,0x11,0x0c,0x0b,0xd2,0xac,0x38,0x15,0x70,0x26,0x08,0x0b,0x02,0x8e, +0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x01,0x00,0x42,0x30,0x31,0x00,0x40,0x10, +0x02,0x80,0x14,0x3c,0x25,0xb0,0x0b,0x3c,0x04,0x00,0x63,0x35,0x00,0x00,0x6a,0x8c, +0x40,0x00,0x02,0x3c,0x24,0x10,0x42,0x01,0x70,0x04,0x40,0x14,0x01,0x00,0x03,0x24, +0xb2,0x3d,0x82,0x92,0x00,0x00,0x00,0x00,0x0f,0x00,0x42,0x30,0xcd,0x04,0x43,0x10, +0x20,0xbd,0x02,0x3c,0xec,0x02,0x65,0x35,0x4d,0x00,0x68,0x35,0xf1,0x02,0x69,0x35, +0x08,0x00,0x07,0x24,0x78,0x02,0x42,0x34,0x00,0x00,0x43,0xa4,0x00,0x00,0x00,0xa1, +0x00,0x00,0x27,0xa1,0x00,0x00,0xa0,0xac,0x00,0x00,0xa2,0x8c,0xff,0x00,0x03,0x3c, +0x80,0x00,0x04,0x3c,0xff,0x00,0x4a,0x30,0x25,0x50,0x43,0x01,0x24,0x20,0x44,0x01, +0xf2,0x02,0x66,0x35,0x0a,0x00,0x6a,0x35,0x80,0xff,0x02,0x24,0x00,0x00,0x00,0xa1, +0x00,0x00,0x27,0xa1,0x00,0x00,0xa3,0xac,0x00,0x00,0xa3,0xac,0x00,0x00,0xc0,0xa0, +0x00,0x00,0x42,0xa1,0x04,0x00,0x80,0x10,0x02,0x00,0x65,0x35,0x84,0xff,0x02,0x24, +0x00,0x00,0x42,0xa1,0x02,0x00,0x65,0x35,0x00,0x00,0xa3,0x94,0x0c,0x0b,0x04,0x8e, +0xff,0xbf,0x02,0x24,0x24,0x18,0x62,0x00,0x01,0x00,0x84,0x38,0x00,0x00,0xa3,0xa4, +0x0c,0x0b,0x04,0xae,0x38,0x15,0x66,0x26,0x08,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00, +0x24,0x28,0x52,0x00,0x04,0x00,0xa3,0x30,0x09,0x00,0x60,0x10,0x08,0x00,0xa2,0x30, +0x0c,0x0b,0xc2,0x8c,0x25,0xb0,0x03,0x3c,0x04,0x00,0x04,0x24,0x04,0x00,0x42,0x38, +0xb0,0x03,0x63,0x34,0x00,0x00,0x64,0xac,0x0c,0x0b,0xc2,0xac,0x08,0x00,0xa2,0x30, +0x06,0x00,0x40,0x10,0x10,0x00,0xa2,0x30,0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00, +0x08,0x00,0x42,0x38,0x0c,0x0b,0xc2,0xac,0x10,0x00,0xa2,0x30,0x06,0x00,0x40,0x10, +0x20,0x00,0xa2,0x30,0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x38, +0x0c,0x0b,0xc2,0xac,0x20,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,0x40,0x00,0xa2,0x30, +0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x38,0x0c,0x0b,0xc2,0xac, +0x40,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,0x80,0x00,0xa2,0x30,0x0c,0x0b,0xc2,0x8c, +0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x38,0x0c,0x0b,0xc2,0xac,0x80,0x00,0xa2,0x30, +0x06,0x00,0x40,0x10,0x00,0x01,0xa2,0x30,0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00, +0x80,0x00,0x42,0x38,0x0c,0x0b,0xc2,0xac,0x00,0x01,0xa2,0x30,0x06,0x00,0x40,0x10, +0x00,0x02,0xa2,0x30,0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x00,0x01,0x42,0x38, +0x0c,0x0b,0xc2,0xac,0x00,0x02,0xa2,0x30,0x06,0x00,0x40,0x10,0x00,0x04,0xa2,0x30, +0x0c,0x0b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x38,0x0c,0x0b,0xc2,0xac, +0x00,0x04,0xa2,0x30,0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x0c,0x0b,0xc2,0x8c, +0x00,0x00,0x00,0x00,0x00,0x04,0x42,0x38,0x0c,0x0b,0xc2,0xac,0x00,0x08,0xa2,0x30, +0x36,0x00,0x40,0x10,0x2a,0xb0,0x03,0x3c,0x00,0x00,0x6a,0x8c,0xff,0x00,0x02,0x24, +0xff,0x00,0x44,0x31,0x2c,0x00,0x82,0x10,0x00,0x80,0x42,0x31,0x17,0x04,0x40,0x14, +0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x0b,0x00,0x40,0x10, +0xff,0x00,0x02,0x24,0x90,0x24,0xc2,0x90,0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00, +0x21,0x10,0x43,0x00,0x0c,0x00,0x4a,0x8c,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34, +0x00,0x00,0x6a,0xac,0xff,0x00,0x44,0x31,0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10, +0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x48,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c, +0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xdc,0x24,0x03,0xae, +0x21,0x20,0x00,0x00,0x90,0x24,0x0a,0xa2,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c, +0x10,0x00,0xa0,0xaf,0x08,0x0b,0x05,0x8e,0x02,0x80,0x06,0x3c,0xa4,0x3e,0xc4,0x8c, +0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c,0x04,0x00,0x84,0x34, +0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac, +0xa4,0x3e,0xc4,0xac,0x08,0x0b,0x05,0xae,0x38,0x15,0x63,0x26,0x0c,0x0b,0x62,0x8c, +0x00,0x00,0x00,0x00,0x00,0x08,0x42,0x38,0x0c,0x0b,0x62,0xac,0x38,0x15,0x65,0x26, +0x08,0x0b,0xa2,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x00,0x10,0x42,0x30, +0x38,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,0x08,0x00,0x43,0x34,0x00,0x00,0x6a,0x8c, +0xff,0x00,0x02,0x24,0xff,0x00,0x44,0x31,0x2c,0x00,0x82,0x10,0x00,0x80,0x42,0x31, +0xdd,0x03,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01, +0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x98,0x24,0xa2,0x90,0x20,0xb0,0x03,0x3c, +0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x4a,0x8c,0x25,0xb0,0x03,0x3c, +0xb0,0x03,0x63,0x34,0x00,0x00,0x6a,0xac,0xff,0x00,0x44,0x31,0xff,0x00,0x02,0x24, +0x1a,0x00,0x82,0x10,0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x60,0x25,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0xf4,0x24,0x03,0xae,0x01,0x00,0x04,0x24,0x98,0x24,0x0a,0xa2,0x40,0x00,0x07,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x08,0x0b,0x05,0x8e,0x02,0x80,0x06,0x3c, +0xa4,0x3e,0xc4,0x8c,0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c, +0x10,0x00,0x84,0x34,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac, +0x00,0x00,0x65,0xac,0xa4,0x3e,0xc4,0xac,0x08,0x0b,0x05,0xae,0x38,0x15,0x63,0x26, +0x0c,0x0b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38,0x0c,0x0b,0x62,0xac, +0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00, +0x00,0x20,0x42,0x30,0x37,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,0x04,0x00,0x43,0x34, +0x00,0x00,0x6a,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x44,0x31,0xc1,0x03,0x82,0x10, +0x00,0x80,0x42,0x31,0xa3,0x03,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c, +0x24,0x10,0x42,0x01,0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x94,0x24,0xa2,0x90, +0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x4a,0x8c, +0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x6a,0xac,0xff,0x00,0x44,0x31, +0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31, +0x54,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x21,0x30,0x60,0x00,0xe8,0x24,0x03,0xae,0x01,0x00,0x04,0x24,0x94,0x24,0x0a,0xa2, +0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x08,0x0b,0x05,0x8e, +0x02,0x80,0x06,0x3c,0xa4,0x3e,0xc4,0x8c,0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00, +0x25,0xb0,0x02,0x3c,0x20,0x00,0x84,0x34,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c, +0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,0xa4,0x3e,0xc4,0xac,0x08,0x0b,0x05,0xae, +0x38,0x15,0x63,0x26,0x0c,0x0b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x20,0x42,0x38, +0x0c,0x0b,0x62,0xac,0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,0x00,0x00,0x00,0x00, +0x24,0x10,0x52,0x00,0x00,0x80,0x42,0x30,0x59,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c, +0x0c,0x00,0xc3,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31, +0x75,0x03,0x87,0x10,0x00,0x80,0x42,0x31,0x24,0x00,0x40,0x14,0x00,0x80,0x02,0x3c, +0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x22,0x00,0x40,0x10,0xff,0x00,0x02,0x24, +0x40,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30, +0x0f,0x00,0x87,0x10,0x38,0x15,0x62,0x26,0x70,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90, +0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x09,0x00,0x83,0x10,0x38,0x15,0x62,0x26, +0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00, +0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x70,0x24,0xe3,0xa0,0x38,0x15,0x62,0x26, +0x70,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31, +0x00,0x00,0x4a,0xac,0x81,0x29,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac, +0xff,0x00,0x02,0x24,0x24,0x00,0x82,0x10,0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31, +0x18,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x21,0x30,0x60,0x00,0x70,0x24,0x0a,0xa2,0xac,0x24,0x03,0xae,0x03,0x00,0x04,0x24, +0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c, +0xb4,0x3e,0x47,0x91,0x02,0x80,0x09,0x3c,0xa4,0x3e,0x25,0x8d,0x08,0x0b,0x06,0x8e, +0x01,0x00,0x08,0x3c,0x80,0xff,0x02,0x24,0x25,0x38,0xe2,0x00,0x00,0x80,0x03,0x35, +0x80,0x00,0xa5,0x34,0x27,0x18,0x03,0x00,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c, +0x24,0x30,0xc3,0x00,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c, +0x00,0x00,0x44,0xac,0x27,0x88,0x08,0x00,0x00,0x00,0x66,0xac,0xa4,0x3e,0x25,0xad, +0xb4,0x3e,0x47,0xa1,0x08,0x0b,0x06,0xae,0x38,0x15,0x63,0x26,0x0c,0x0b,0x62,0x8c, +0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,0x0c,0x0b,0x62,0xac,0x38,0x15,0x65,0x26, +0x08,0x0b,0xa2,0x8c,0x01,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00, +0x24,0x10,0x43,0x00,0x56,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x10,0x00,0xc3,0x34, +0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0x20,0x03,0x87,0x10, +0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c, +0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24, +0x41,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30, +0x0e,0x00,0x87,0x10,0x38,0x15,0x62,0x26,0x74,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90, +0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00, +0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14, +0xff,0x00,0x44,0x30,0x74,0x24,0xe3,0xa0,0x38,0x15,0x62,0x26,0x74,0x24,0x43,0x90, +0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac, +0xe0,0x29,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24, +0x22,0x00,0x82,0x10,0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x18,0x25,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0xac,0x24,0x03,0xae,0x03,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x74,0x24,0x0a,0xa2, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0xb4,0x3e,0x27,0x91, +0x02,0x80,0x08,0x3c,0xa4,0x3e,0x05,0x8d,0x08,0x0b,0x06,0x8e,0x01,0x00,0x02,0x3c, +0x00,0x80,0x42,0x34,0x40,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00, +0x80,0x00,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00, +0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac, +0xa4,0x3e,0x05,0xad,0xb4,0x3e,0x27,0xa1,0x08,0x0b,0x06,0xae,0x38,0x15,0x62,0x26, +0x0c,0x0b,0x43,0x8c,0x01,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac, +0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,0x02,0x00,0x03,0x3c,0x24,0x10,0x52,0x00, +0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x14,0x00,0xc3,0x34, +0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0xe4,0x02,0x87,0x10, +0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c, +0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24, +0x42,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30, +0x0e,0x00,0x87,0x10,0x38,0x15,0x62,0x26,0x78,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90, +0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00, +0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14, +0xff,0x00,0x44,0x30,0x78,0x24,0xe3,0xa0,0x38,0x15,0x62,0x26,0x78,0x24,0x43,0x90, +0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac, +0x3c,0x2a,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24, +0x25,0x00,0x82,0x10,0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x24,0x25,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0x78,0x24,0x0a,0xa2,0xb8,0x24,0x03,0xae,0x04,0x00,0x04,0x24,0x40,0x00,0x07,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,0xb4,0x3e,0x47,0x91, +0x02,0x80,0x09,0x3c,0xa4,0x3e,0x25,0x8d,0x08,0x0b,0x06,0x8e,0x06,0x00,0x02,0x3c, +0x20,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x01,0xa5,0x34, +0x25,0xb0,0x03,0x3c,0x04,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02, +0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c, +0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,0xa4,0x3e,0x25,0xad,0xb4,0x3e,0x47,0xa1, +0x08,0x0b,0x06,0xae,0x00,0x00,0x11,0xad,0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c, +0x02,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac,0x38,0x15,0x65,0x26, +0x08,0x0b,0xa2,0x8c,0x04,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00, +0x24,0x10,0x43,0x00,0x58,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x62,0x34, +0x2a,0xb0,0x08,0x3c,0x00,0x00,0x51,0xac,0x18,0x00,0x06,0x35,0x00,0x00,0xca,0x8c, +0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0x70,0x02,0x87,0x10,0x04,0x00,0x02,0x24, +0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c, +0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x43,0x00,0x06,0x35, +0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10, +0x38,0x15,0x62,0x26,0x7c,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30, +0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00, +0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30, +0x7c,0x24,0xe3,0xa0,0x38,0x15,0x62,0x26,0x7c,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c, +0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c, +0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0x9f,0x2a,0x00,0x08, +0xff,0x00,0x02,0x24,0x00,0x00,0xc2,0xac,0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10, +0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x24,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c, +0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xb8,0x24,0x03,0xae, +0x04,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x7c,0x24,0x0a,0xa2,0x10,0x01,0x00,0x0c, +0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0xb4,0x3e,0x27,0x91,0x02,0x80,0x08,0x3c, +0xa4,0x3e,0x05,0x8d,0x08,0x0b,0x06,0x8e,0x06,0x00,0x02,0x3c,0x10,0x00,0xe7,0x34, +0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x01,0xa5,0x34,0x00,0x26,0x07,0x00, +0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c, +0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,0xa4,0x3e,0x05,0xad,0xb4,0x3e,0x27,0xa1, +0x08,0x0b,0x06,0xae,0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x04,0x00,0x04,0x3c, +0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac,0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c, +0x08,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10, +0x2a,0xb0,0x06,0x3c,0x1c,0x00,0xc3,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24, +0xff,0x00,0x44,0x31,0x19,0x02,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31, +0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01, +0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x44,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90, +0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x38,0x15,0x62,0x26, +0x80,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30, +0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90, +0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x80,0x24,0xe3,0xa0, +0x38,0x15,0x62,0x26,0x80,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00, +0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34, +0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0xfa,0x2a,0x00,0x08,0xff,0x00,0x02,0x24, +0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x25,0x00,0x82,0x10,0x38,0x15,0x70,0x26, +0xff,0x00,0x43,0x31,0x30,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00, +0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x80,0x24,0x0a,0xa2,0xc4,0x24,0x03,0xae, +0x05,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x02,0x80,0x0a,0x3c,0xb4,0x3e,0x47,0x91,0x02,0x80,0x09,0x3c,0xa4,0x3e,0x25,0x8d, +0x08,0x0b,0x06,0x8e,0x18,0x00,0x02,0x3c,0x08,0x00,0xe7,0x34,0x27,0x10,0x02,0x00, +0x24,0x30,0xc2,0x00,0x00,0x02,0xa5,0x34,0x25,0xb0,0x03,0x3c,0x10,0x00,0x02,0x3c, +0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02,0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00, +0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c,0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac, +0xa4,0x3e,0x25,0xad,0xb4,0x3e,0x47,0xa1,0x08,0x0b,0x06,0xae,0x00,0x00,0x11,0xad, +0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x08,0x00,0x04,0x3c,0x26,0x18,0x64,0x00, +0x0c,0x0b,0x43,0xac,0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,0x10,0x00,0x03,0x3c, +0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x58,0x00,0x40,0x10, +0x25,0xb0,0x06,0x3c,0xb0,0x03,0xc2,0x34,0x2a,0xb0,0x08,0x3c,0x00,0x00,0x51,0xac, +0x20,0x00,0x03,0x35,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31, +0xbb,0x01,0x87,0x10,0x90,0x03,0xc2,0x34,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14, +0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10, +0xff,0x00,0x02,0x24,0x45,0x00,0x06,0x35,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00, +0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x38,0x15,0x62,0x26,0x8c,0x24,0xa4,0xa0, +0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10, +0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00, +0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x8c,0x24,0xe3,0xa0,0x38,0x15,0x62,0x26, +0x8c,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31, +0x00,0x00,0x4a,0xac,0x5d,0x2b,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac, +0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10,0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31, +0x30,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x21,0x30,0x60,0x00,0xc4,0x24,0x03,0xae,0x05,0x00,0x04,0x24,0x40,0x00,0x07,0x24, +0x8c,0x24,0x0a,0xa2,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c, +0xb4,0x3e,0x27,0x91,0x02,0x80,0x08,0x3c,0xa4,0x3e,0x05,0x8d,0x08,0x0b,0x06,0x8e, +0x18,0x00,0x02,0x3c,0x01,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00, +0x00,0x02,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00, +0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac, +0xa4,0x3e,0x05,0xad,0xb4,0x3e,0x27,0xa1,0x08,0x0b,0x06,0xae,0x38,0x15,0x62,0x26, +0x0c,0x0b,0x43,0x8c,0x10,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac, +0x38,0x15,0x65,0x26,0x08,0x0b,0xa2,0x8c,0x20,0x00,0x03,0x3c,0x24,0x10,0x52,0x00, +0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x24,0x00,0xc3,0x34, +0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0x63,0x01,0x87,0x10, +0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c, +0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24, +0x46,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30, +0x0e,0x00,0x87,0x10,0x38,0x15,0x62,0x26,0x84,0x24,0xa4,0xa0,0x00,0x00,0xc2,0x90, +0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00, +0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14, +0xff,0x00,0x44,0x30,0x84,0x24,0xe3,0xa0,0x38,0x15,0x62,0x26,0x84,0x24,0x43,0x90, +0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac, +0xb8,0x2b,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24, +0x25,0x00,0x82,0x10,0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x3c,0x25,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0x84,0x24,0x0a,0xa2,0xd0,0x24,0x03,0xae,0x06,0x00,0x04,0x24,0x40,0x00,0x07,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,0xb4,0x3e,0x47,0x91, +0x02,0x80,0x09,0x3c,0xa4,0x3e,0x25,0x8d,0x08,0x0b,0x06,0x8e,0x60,0x00,0x02,0x3c, +0x04,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x04,0xa5,0x34, +0x25,0xb0,0x03,0x3c,0x40,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02, +0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c, +0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,0xa4,0x3e,0x25,0xad,0xb4,0x3e,0x47,0xa1, +0x08,0x0b,0x06,0xae,0x00,0x00,0x11,0xad,0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c, +0x20,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac,0x38,0x15,0x65,0x26, +0x08,0x0b,0xa2,0x8c,0x40,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00, +0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x38,0x15,0x70,0x26,0x25,0xb0,0x02,0x3c, +0x2a,0xb0,0x07,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x51,0xac,0x28,0x00,0xe3,0x34, +0x00,0x00,0x6a,0x8c,0xff,0x00,0x06,0x24,0xff,0x00,0x44,0x31,0xd0,0x00,0x86,0x10, +0x25,0xbd,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c, +0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24, +0x47,0x00,0xe7,0x34,0x00,0x00,0xe2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30, +0x0e,0x00,0x86,0x10,0x38,0x15,0x62,0x26,0x88,0x24,0xa4,0xa0,0x00,0x00,0xe2,0x90, +0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x30,0xa0,0x00, +0x21,0x28,0xe0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14, +0xff,0x00,0x44,0x30,0x88,0x24,0xc3,0xa0,0x38,0x15,0x62,0x26,0x88,0x24,0x43,0x90, +0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac, +0x1c,0x2c,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24, +0x21,0x00,0x82,0x10,0x38,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x3c,0x25,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0xd0,0x24,0x03,0xae,0x06,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x88,0x24,0x0a,0xa2, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0xb4,0x3e,0x27,0x91, +0x02,0x80,0x08,0x3c,0xa4,0x3e,0x05,0x8d,0x08,0x0b,0x06,0x8e,0x60,0x00,0x02,0x3c, +0x02,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x04,0xa5,0x34, +0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34, +0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,0xa4,0x3e,0x05,0xad, +0xb4,0x3e,0x27,0xa1,0x08,0x0b,0x06,0xae,0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c, +0x40,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac,0x38,0x15,0x70,0x26, +0x08,0x0b,0x06,0x8e,0x00,0x04,0x11,0x3c,0x24,0x10,0xd2,0x00,0x24,0x10,0x51,0x00, +0x57,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x24,0x28,0xd2,0x00,0x00,0x08,0x04,0x3c, +0x24,0x10,0xa4,0x00,0x08,0x00,0x40,0x10,0x80,0x00,0x07,0x3c,0x0c,0x0b,0x03,0x8e, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,0x00,0x00,0x44,0xac, +0x0c,0x0b,0x03,0xae,0x80,0x00,0x07,0x3c,0x24,0x10,0xa7,0x00,0x21,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x0c,0x0b,0x03,0x8e,0x25,0xb0,0x08,0x3c,0xb0,0x03,0x09,0x35, +0x2a,0xb0,0x02,0x3c,0x00,0x00,0x23,0xad,0x36,0x00,0x42,0x34,0x00,0x00,0x43,0x90, +0x23,0xb0,0x04,0x3c,0xff,0x1f,0x02,0x3c,0xc0,0x18,0x03,0x00,0xf0,0x07,0x63,0x30, +0xd8,0x25,0x05,0x8e,0x21,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x60,0x00,0x65,0x10,0xdc,0x25,0x03,0xae,0x02,0x80,0x05,0x3c,0xa4,0x3e,0xa3,0x8c, +0x27,0x20,0x07,0x00,0x24,0x20,0xc4,0x00,0x00,0x08,0x63,0x34,0x41,0xb0,0x02,0x3c, +0x00,0x00,0x23,0xad,0x00,0x00,0x44,0xac,0xa4,0x3e,0xa3,0xac,0x08,0x0b,0x04,0xae, +0x38,0x15,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x80,0x00,0x04,0x3c,0x26,0x18,0x64,0x00, +0x0c,0x0b,0x43,0xac,0x38,0x15,0x66,0x26,0x08,0x0b,0xc3,0x8c,0x00,0x01,0x04,0x3c, +0x24,0x28,0x72,0x00,0x24,0x10,0xa4,0x00,0x06,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c, +0x0c,0x0b,0xc3,0x8c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,0x00,0x00,0x44,0xac, +0x0c,0x0b,0xc3,0xac,0x00,0x02,0x04,0x3c,0x24,0x10,0xa4,0x00,0x06,0x00,0x40,0x10, +0x25,0xb0,0x03,0x3c,0x0c,0x0b,0xc2,0x8c,0xb0,0x03,0x63,0x34,0x26,0x10,0x44,0x00, +0x0c,0x0b,0xc2,0xac,0x00,0x00,0x64,0xac,0xb2,0x3d,0x82,0x92,0x01,0x00,0x03,0x24, +0x0f,0x00,0x42,0x30,0x21,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x2c,0x00,0xbf,0x8f, +0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f, +0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x0c,0x0b,0x02,0x8e, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x38,0x55,0x28,0x00,0x08,0x0c,0x0b,0x02,0xae, +0xa7,0x48,0x00,0x0c,0x07,0x00,0x04,0x24,0x0c,0x0b,0x03,0x8e,0x08,0x0b,0x06,0x8e, +0x25,0xb0,0x02,0x3c,0x26,0x18,0x71,0x00,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x4a,0x2c,0x00,0x08,0x0c,0x0b,0x03,0xae,0x56,0x01,0x42,0x35,0x00,0x00,0x43,0x94, +0x00,0x00,0x00,0x00,0x70,0xfb,0x60,0x10,0x00,0x00,0x00,0x00,0xa7,0x48,0x00,0x0c, +0x07,0x00,0x04,0x24,0x1f,0x28,0x00,0x08,0x38,0x15,0x70,0x26,0x2c,0x00,0xbf,0x8f, +0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f, +0x18,0x00,0xb0,0x8f,0xd3,0x27,0x00,0x08,0x30,0x00,0xbd,0x27,0x00,0x00,0x62,0xac, +0xb3,0x28,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xf0,0x28,0x00,0x08, +0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0x2d,0x29,0x00,0x08,0xff,0x00,0x02,0x24, +0x01,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x3f,0x2c,0x00,0x08, +0x38,0x15,0x62,0x26,0xd0,0x03,0x03,0x35,0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac, +0x75,0x2c,0x00,0x08,0x38,0x15,0x62,0x26,0x25,0xb0,0x02,0x3c,0x07,0x00,0x03,0x24, +0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x38,0x15,0x63,0x26,0x0c,0x0b,0x62,0x8c, +0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,0xab,0x29,0x00,0x08,0x0c,0x0b,0x62,0xac, +0x06,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x04,0x2a,0x00,0x08, +0x38,0x15,0x62,0x26,0x25,0xb0,0x02,0x3c,0x07,0x00,0x03,0x24,0x90,0x03,0x42,0x34, +0x00,0x00,0x43,0xac,0x38,0x15,0x63,0x26,0x0c,0x0b,0x62,0x8c,0x00,0x00,0x00,0x00, +0x00,0x20,0x42,0x38,0x4d,0x29,0x00,0x08,0x0c,0x0b,0x62,0xac,0x90,0x03,0x63,0x34, +0x00,0x00,0x62,0xac,0xc2,0x2a,0x00,0x08,0x38,0x15,0x62,0x26,0x03,0x00,0x03,0x24, +0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x21,0x2b,0x00,0x08,0x38,0x15,0x62,0x26, +0x00,0x00,0x40,0xac,0x80,0x2b,0x00,0x08,0x38,0x15,0x62,0x26,0x02,0x00,0x03,0x24, +0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0xdf,0x2b,0x00,0x08,0x38,0x15,0x62,0x26, +0x05,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x63,0x2a,0x00,0x08, +0x38,0x15,0x62,0x26,0x01,0x00,0x04,0x24,0x17,0x00,0x05,0x24,0x21,0x30,0x00,0x00, +0x7a,0x09,0x00,0x0c,0x21,0x38,0x00,0x00,0x53,0xfb,0x40,0x10,0x38,0x15,0x66,0x26, +0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x38,0x56,0x28,0x00,0x08, +0x0c,0x0b,0x02,0xae,0x25,0xb0,0x0d,0x3c,0x01,0x80,0x02,0x3c,0x18,0x03,0xa4,0x35, +0x24,0xb4,0x42,0x24,0x02,0x80,0x03,0x3c,0x41,0xb0,0x08,0x3c,0x00,0x00,0x82,0xac, +0x38,0x15,0x6a,0x24,0x0a,0x00,0x02,0x35,0x00,0x00,0x44,0x94,0x16,0x0b,0x43,0x95, +0x14,0x0b,0x4b,0x95,0x25,0x18,0x64,0x00,0xff,0xff,0x6c,0x30,0x24,0x10,0x8b,0x01, +0x02,0x00,0x42,0x30,0x53,0x00,0x40,0x10,0x02,0x00,0x64,0x38,0x02,0x00,0x02,0x24, +0xc0,0x03,0xa3,0x35,0x00,0x00,0x62,0xac,0x16,0x0b,0x44,0xa5,0x24,0x38,0x8b,0x01, +0x04,0x00,0xe2,0x30,0x0a,0x00,0x40,0x10,0x08,0x00,0xe2,0x30,0x16,0x0b,0x43,0x95, +0x0c,0x00,0x04,0x35,0xc0,0x03,0xa5,0x35,0x04,0x00,0x63,0x38,0x04,0x00,0x02,0x24, +0x00,0x00,0x86,0x8c,0x00,0x00,0xa2,0xac,0x16,0x0b,0x43,0xa5,0x08,0x00,0xe2,0x30, +0x08,0x00,0x40,0x10,0x10,0x00,0xe2,0x30,0x16,0x0b,0x42,0x95,0xc0,0x03,0xa4,0x35, +0x08,0x00,0x03,0x24,0x08,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x16,0x0b,0x42,0xa5, +0x10,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,0x20,0x00,0xe2,0x30,0x16,0x0b,0x42,0x95, +0xc0,0x03,0xa4,0x35,0x10,0x00,0x03,0x24,0x10,0x00,0x42,0x38,0x00,0x00,0x83,0xac, +0x16,0x0b,0x42,0xa5,0x20,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,0x80,0x00,0xe2,0x30, +0x16,0x0b,0x42,0x95,0xc0,0x03,0xa4,0x35,0x20,0x00,0x03,0x24,0x20,0x00,0x42,0x38, +0x00,0x00,0x83,0xac,0x16,0x0b,0x42,0xa5,0x80,0x00,0xe2,0x30,0x15,0x00,0x40,0x10, +0x24,0x10,0x8b,0x01,0x02,0x80,0x09,0x3c,0x16,0x0b,0x46,0x95,0xa4,0x3e,0x25,0x8d, +0x10,0x00,0x02,0x3c,0x7f,0xff,0x04,0x24,0x24,0x20,0x64,0x01,0x25,0x28,0xa2,0x00, +0x80,0x00,0xc6,0x38,0xb0,0x03,0xa7,0x35,0x08,0x00,0x08,0x35,0xc0,0x03,0xa3,0x35, +0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0x21,0x58,0x80,0x00,0x00,0x00,0xe5,0xac, +0x16,0x0b,0x46,0xa5,0xa4,0x3e,0x25,0xad,0x00,0x00,0x04,0xa5,0x14,0x0b,0x44,0xa5, +0x24,0x10,0x8b,0x01,0x00,0x30,0x42,0x30,0x07,0x00,0x40,0x10,0x02,0x80,0x02,0x3c, +0x16,0x0b,0x42,0x95,0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38,0x00,0x20,0x42,0x34, +0x16,0x0b,0x42,0xa5,0x02,0x80,0x02,0x3c,0xb2,0x3d,0x43,0x90,0x01,0x00,0x02,0x24, +0x0f,0x00,0x63,0x30,0x05,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x1f,0x2d,0x00,0x08,0x16,0x0b,0x43,0xa5,0xd3,0x27,0x00,0x08, +0x00,0x00,0x00,0x00,0xf8,0xff,0xbd,0x27,0x25,0xb0,0x05,0x3c,0x04,0x00,0xb1,0xaf, +0x00,0x00,0xb0,0xaf,0x18,0x03,0xa6,0x34,0x00,0x00,0xc3,0x8c,0x1c,0x03,0xa2,0x34, +0x00,0x00,0x43,0xac,0x00,0x40,0x07,0x40,0x00,0x68,0x09,0x40,0x00,0x70,0x02,0x40, +0x00,0x60,0x08,0x40,0x01,0x80,0x02,0x3c,0xc4,0xb5,0x42,0x24,0x00,0x00,0xc2,0xac, +0x80,0x00,0x87,0x8c,0x7c,0x02,0xa2,0x34,0x84,0x02,0xa3,0x34,0x88,0x02,0xa6,0x34, +0x00,0x00,0x47,0xac,0x00,0x00,0x69,0xac,0x00,0x00,0xc8,0xac,0x74,0x00,0x83,0x8c, +0x8c,0x02,0xa2,0x34,0x90,0x02,0xa7,0x34,0x00,0x00,0x43,0xac,0x08,0x00,0x86,0x8c, +0x94,0x02,0xa8,0x34,0x98,0x02,0xa9,0x34,0x00,0x00,0xe6,0xac,0x0c,0x00,0x82,0x8c, +0x9c,0x02,0xa6,0x34,0xa0,0x02,0xa7,0x34,0x00,0x00,0x02,0xad,0x10,0x00,0x83,0x8c, +0xa4,0x02,0xa8,0x34,0xa8,0x02,0xaa,0x34,0x00,0x00,0x23,0xad,0x14,0x00,0x82,0x8c, +0xac,0x02,0xa9,0x34,0xb0,0x02,0xab,0x34,0x00,0x00,0xc2,0xac,0x18,0x00,0x83,0x8c, +0xb4,0x02,0xa6,0x34,0xb8,0x02,0xac,0x34,0x00,0x00,0xe3,0xac,0x1c,0x00,0x82,0x8c, +0xbc,0x02,0xa7,0x34,0xc0,0x02,0xad,0x34,0x00,0x00,0x02,0xad,0x20,0x00,0x83,0x8c, +0xc4,0x02,0xa8,0x34,0xc8,0x02,0xae,0x34,0x00,0x00,0x43,0xad,0x24,0x00,0x82,0x8c, +0xcc,0x02,0xaa,0x34,0xd0,0x02,0xaf,0x34,0x00,0x00,0x22,0xad,0x28,0x00,0x83,0x8c, +0xd4,0x02,0xa9,0x34,0xd8,0x02,0xb0,0x34,0x00,0x00,0x63,0xad,0x2c,0x00,0x82,0x8c, +0x70,0x02,0xab,0x34,0x74,0x02,0xb1,0x34,0x00,0x00,0xc2,0xac,0x30,0x00,0x83,0x8c, +0x78,0x02,0xa5,0x34,0x00,0x00,0x83,0xad,0x34,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0xe2,0xac,0x38,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xad, +0x3c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xad,0x40,0x00,0x83,0x8c, +0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0xad,0x44,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0x42,0xad,0x48,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe3,0xad, +0x4c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xad,0x50,0x00,0x83,0x8c, +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xae,0x54,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0x62,0xad,0x58,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xae, +0x5c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,0xd7,0x2d,0x00,0x08, +0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,0x64,0xb7,0x7b,0x27,0x25,0xb0,0x1a,0x3c, +0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00, +0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf, +0x0c,0x00,0x63,0xaf,0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf, +0x1c,0x00,0x67,0xaf,0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf, +0x2c,0x00,0x6b,0xaf,0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf, +0x3c,0x00,0x6f,0xaf,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40, +0x40,0x00,0x70,0xaf,0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf, +0x50,0x00,0x74,0xaf,0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf, +0x60,0x00,0x78,0xaf,0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf, +0x70,0x00,0x7e,0xaf,0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf, +0x80,0x00,0x6a,0xaf,0x00,0x68,0x1a,0x40,0x7f,0x00,0x5b,0x33,0x30,0x00,0x60,0x13, +0x00,0x00,0x00,0x00,0x25,0xb0,0x1b,0x3c,0x30,0x03,0x7b,0x37,0x00,0x00,0x00,0x00, +0x00,0x00,0x7a,0xaf,0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00, +0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf, +0x0c,0x00,0x63,0xaf,0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf, +0x1c,0x00,0x67,0xaf,0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf, +0x2c,0x00,0x6b,0xaf,0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf, +0x3c,0x00,0x6f,0xaf,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40, +0x40,0x00,0x70,0xaf,0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf, +0x50,0x00,0x74,0xaf,0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf, +0x60,0x00,0x78,0xaf,0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf, +0x70,0x00,0x7e,0xaf,0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf, +0x80,0x00,0x6a,0xaf,0x71,0x2d,0x00,0x08,0x21,0x20,0x60,0x03,0x00,0x00,0x00,0x00, +0x25,0xb0,0x08,0x3c,0x20,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0xad, +0x00,0x04,0x5b,0x33,0x0a,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x01,0x80,0x08,0x3c, +0xf8,0x9f,0x08,0x25,0x00,0x00,0x00,0x00,0x25,0xb0,0x1b,0x3c,0x24,0x03,0x7b,0x37, +0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xaf,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00, +0x00,0x08,0x5b,0x33,0x25,0xb0,0x08,0x3c,0x28,0x03,0x08,0x35,0x00,0x00,0x00,0x00, +0x00,0x00,0x1b,0xad,0x06,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x01,0x80,0x08,0x3c, +0x24,0xb4,0x08,0x25,0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00, +0x02,0x80,0x1a,0x3c,0xa4,0x3e,0x5a,0x27,0x04,0x00,0x5b,0x97,0x25,0xb0,0x08,0x3c, +0x30,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad,0x18,0x00,0x60,0x13, +0x00,0x00,0x00,0x00,0x08,0xec,0x9b,0x27,0x00,0x00,0x00,0x00,0x04,0x00,0x61,0x8f, +0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b, +0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b, +0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b, +0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b, +0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,0xc0,0x2e,0x00,0x08,0x00,0x00,0x00,0x00, +0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27, +0x08,0x00,0x5b,0xaf,0xfc,0xef,0x9d,0x27,0x00,0x00,0x4a,0x8f,0x00,0x00,0x00,0x00, +0x21,0x00,0x40,0x11,0x00,0x00,0x00,0x00,0x02,0x80,0x08,0x3c,0x04,0x3e,0x08,0x25, +0x21,0x48,0x00,0x00,0x21,0x58,0x00,0x00,0x01,0x00,0x6b,0x25,0x1a,0x00,0x40,0x11, +0x24,0x70,0x4b,0x01,0x14,0x00,0xc0,0x11,0x01,0x00,0x04,0x24,0x00,0x00,0x00,0x00, +0x04,0x00,0x44,0xa3,0x26,0x50,0x4b,0x01,0x00,0x00,0x4a,0xaf,0x80,0x80,0x09,0x00, +0x21,0x80,0x08,0x02,0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x02, +0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,0x2c,0xba,0x7b,0x27,0x25,0xb0,0x1a,0x3c, +0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0xa4,0x3e,0x5a,0x27, +0xe1,0xff,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x29,0x25,0x40,0x58,0x0b,0x00, +0x83,0x2e,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x1b,0x3c,0xa4,0x3e,0x7b,0x27, +0x21,0x60,0x00,0x00,0x04,0x00,0x6c,0xa7,0x08,0x00,0x7a,0x8f,0x00,0x00,0x00,0x00, +0xf8,0xff,0x5a,0x27,0x00,0x00,0x5a,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x5a,0x27, +0x84,0x00,0x44,0x8f,0x00,0x00,0x00,0x00,0xf9,0xff,0x80,0x10,0x00,0x00,0x00,0x00, +0x04,0x00,0x41,0x8f,0xfc,0x03,0x50,0x7b,0x7c,0x00,0x42,0x7b,0xbc,0x00,0x44,0x7b, +0xfc,0x00,0x46,0x7b,0x3c,0x01,0x48,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02, +0x7c,0x01,0x4a,0x7b,0xbc,0x01,0x4c,0x7b,0xfc,0x01,0x4e,0x7b,0x3c,0x02,0x50,0x7b, +0x7c,0x02,0x52,0x7b,0xbc,0x02,0x54,0x7b,0xfc,0x02,0x56,0x7b,0x3c,0x03,0x58,0x7b, +0x7c,0x03,0x5c,0x7b,0xbc,0x03,0x5e,0x7b,0x80,0x00,0x5b,0x8f,0x00,0x00,0x00,0x00, +0x08,0x00,0x60,0x03,0x10,0x00,0x00,0x42,0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00, +0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac, +0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac, +0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac, +0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac, +0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac, +0x54,0x00,0x95,0xac,0x58,0x00,0x96,0xac,0x5c,0x00,0x97,0xac,0x60,0x00,0x98,0xac, +0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac, +0x74,0x00,0x9f,0xac,0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac, +0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24, +0x84,0x00,0x86,0x8c,0x00,0x00,0x00,0x00,0xf9,0xff,0xc0,0x10,0x00,0x00,0x00,0x00, +0x21,0xd8,0x80,0x00,0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b, +0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b, +0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b, +0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b, +0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b, +0x80,0x00,0x7b,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40, +0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40, +0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac, +0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac, +0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00, +0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac, +0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac,0x54,0x00,0x94,0xac,0x58,0x00,0x96,0xac, +0x5c,0x00,0x96,0xac,0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac, +0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac,0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac, +0x80,0x00,0x9f,0xac,0x84,0x00,0x80,0xac,0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c, +0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c,0xfa,0xff,0xc0,0x10, +0x00,0x00,0x00,0x00,0x21,0xd8,0x80,0x00,0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f, +0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b, +0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b, +0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b, +0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b, +0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xb1,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,0x00,0x00,0x7b,0x27, +0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x00,0x00,0x05,0x24, +0x03,0x00,0xa4,0x24,0x00,0xa0,0x80,0x40,0x00,0xa0,0x84,0x40,0x01,0x80,0x04,0x3c, +0x98,0x03,0x84,0x24,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x01,0x80,0x1b,0x3c,0x98,0x03,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27, +0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x00,0x00,0x5a,0x27,0xfc,0x03,0x5d,0x27, +0x02,0x80,0x1c,0x3c,0x00,0x14,0x9c,0x27,0x00,0xf0,0x08,0x3c,0x00,0x0c,0x08,0x35, +0x00,0x60,0x88,0x40,0x02,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,0xff,0x7f,0x05,0x3c, +0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x20,0x84,0x4c,0xff,0xff,0x05,0x34, +0x21,0x28,0xa4,0x00,0x00,0x28,0x85,0x4c,0x00,0x80,0x04,0x3c,0x00,0x00,0x84,0x24, +0xff,0x7f,0x05,0x3c,0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x00,0x84,0x4c, +0xff,0xff,0x06,0x34,0x21,0x30,0xc4,0x00,0x24,0x30,0xc5,0x00,0x00,0x08,0x86,0x4c, +0x00,0xa0,0x04,0x40,0x10,0x00,0x84,0x34,0x00,0xa0,0x84,0x40,0x01,0x80,0x1b,0x3c, +0x24,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf, +0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x84, +0x20,0x00,0x06,0x24,0x25,0x28,0xa6,0x00,0x00,0x00,0x85,0xa4,0x01,0x80,0x1b,0x3c, +0x54,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf, +0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x8c,0x00,0x00,0x00,0x00, +0x10,0x00,0xa5,0x30,0xfc,0xff,0xa0,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x07,0x3c, +0xff,0xff,0xe7,0x34,0x02,0x80,0x05,0x3c,0xb0,0x3d,0xa5,0x24,0xff,0xff,0xa5,0x30, +0x40,0xb0,0x04,0x3c,0x25,0x28,0xa4,0x00,0x24,0x28,0xa7,0x00,0x21,0x30,0x00,0x00, +0x43,0xb0,0x02,0x3c,0x00,0x80,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x45,0xac, +0x04,0x00,0x46,0xac,0x08,0x00,0x44,0xac,0x9d,0x55,0x00,0x08,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24, +0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x42,0x24, +0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x21,0x18,0x40,0x00,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x44,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x04,0x00,0x85,0x8c,0x00,0x80,0x03,0x3c,0x01,0x00,0x02,0x24,0x25,0x28,0xa3,0x00, +0x00,0x00,0xa4,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x74,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x04,0x00,0x82,0x8c,0x02,0x00,0x83,0x94,0x00,0x80,0x07,0x3c,0x25,0x28,0x47,0x00, +0x00,0x00,0xa2,0x8c,0x10,0x00,0x02,0x24,0x13,0x00,0x62,0x10,0x11,0x00,0x66,0x28, +0x06,0x00,0xc0,0x10,0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24,0x17,0x00,0x62,0x10, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0xfd,0xff,0x62,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xac, +0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x25,0x10,0x47,0x00,0x00,0x00,0x42,0x8c, +0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0xa2,0xa4,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x25,0x18,0x67,0x00, +0x00,0x00,0x62,0x94,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c, +0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xa0,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00, +0x25,0x18,0x67,0x00,0x00,0x00,0x62,0x90,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24, +0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x1c,0x00,0xbf,0xaf, +0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x38,0x15,0x31,0x26,0x6c,0x25,0x30,0x96, +0x02,0x80,0x02,0x3c,0x01,0x80,0x03,0x3c,0x25,0x80,0x02,0x02,0x25,0xb0,0x02,0x3c, +0x38,0x06,0x63,0x24,0x18,0x03,0x42,0x34,0x60,0x00,0x04,0x26,0x80,0x00,0x05,0x26, +0x00,0x00,0x43,0xac,0x6c,0x45,0x00,0x0c,0x03,0x00,0x06,0x24,0x21,0x20,0x00,0x02, +0x21,0x28,0x00,0x00,0x58,0x45,0x00,0x0c,0x08,0x00,0x06,0x24,0x6c,0x25,0x22,0x8e, +0x0c,0x00,0x03,0x24,0x0c,0x00,0x43,0xae,0x08,0x00,0x42,0xae,0x12,0x00,0x02,0x24, +0x14,0x00,0x42,0xae,0x21,0x20,0x40,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x42,0x09,0x00,0x08,0x20,0x00,0xbd,0x27, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x02,0x80,0x02,0x3c,0x21,0x48,0x80,0x00, +0x38,0x15,0x48,0x24,0x21,0x38,0x00,0x00,0x21,0x28,0x27,0x01,0x00,0x00,0xa2,0x90, +0x21,0x20,0xe8,0x00,0x01,0x00,0xe7,0x24,0x50,0x0c,0x82,0xa0,0x1e,0x00,0xa3,0x90, +0x1e,0x00,0xe6,0x28,0x6e,0x0c,0x83,0xa0,0x3c,0x00,0xa2,0x90,0x00,0x00,0x00,0x00, +0x8c,0x0c,0x82,0xa0,0x5a,0x00,0xa3,0x90,0xf3,0xff,0xc0,0x14,0xaa,0x0c,0x83,0xa0, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24, +0x20,0xbd,0x03,0x3c,0x58,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x0f,0x27,0x07,0x24, +0x20,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0xff,0xff,0xe7,0x24,0xff,0xff,0xe1,0x04, +0xff,0xff,0xe7,0x24,0x62,0xbd,0x04,0x3c,0x24,0x10,0x82,0x34,0x00,0x00,0x40,0xa0, +0x28,0x10,0x83,0x34,0x0c,0x11,0x86,0x34,0x0e,0x00,0x02,0x24,0x00,0x00,0x60,0xa0, +0x00,0x11,0x85,0x34,0x00,0x00,0xc2,0xa0,0x00,0x00,0xa7,0x8c,0xdf,0xff,0x02,0x24, +0x10,0x00,0x86,0x34,0x24,0x38,0xe2,0x00,0x49,0x0c,0x03,0x24,0xcf,0xff,0x02,0x24, +0x00,0x00,0xc3,0xac,0x04,0x00,0x84,0x34,0x00,0x00,0xa7,0xac,0x24,0x38,0xe2,0x00, +0x41,0x0c,0x02,0x24,0x00,0x00,0xa7,0xac,0x00,0x00,0x80,0xac,0x00,0x00,0xc2,0xac, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x25,0xb0,0x05,0x3c,0x01,0x80,0x03,0x3c,0x21,0x38,0x80,0x00,0x18,0x03,0xa2,0x34, +0xa8,0x08,0x63,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0x35,0x00,0xe4,0x10, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x10,0x20,0x08,0xa2,0x34,0x02,0x00,0x02,0x24, +0x83,0x00,0xe2,0x10,0x03,0x00,0x02,0x24,0x5a,0x00,0xe2,0x10,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c, +0x38,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x8c,0x0b,0xc2,0xac, +0x40,0x08,0x02,0x24,0x90,0x0b,0xc3,0xac,0x9c,0x0b,0xc2,0xac,0x78,0x08,0x03,0x24, +0x0c,0x08,0x02,0x24,0xa0,0x0b,0xc3,0xac,0xa4,0x0b,0xc2,0xac,0x10,0x08,0x03,0x24, +0x20,0x08,0x02,0x24,0xa8,0x0b,0xc3,0xac,0xac,0x0b,0xc2,0xac,0x24,0x08,0x03,0x24, +0x58,0x08,0x02,0x24,0xb0,0x0b,0xc3,0xac,0xb4,0x0b,0xc2,0xac,0x50,0x0c,0x03,0x24, +0x54,0x0c,0x02,0x24,0xb8,0x0b,0xc3,0xac,0xbc,0x0b,0xc2,0xac,0x14,0x0c,0x03,0x24, +0x10,0x0c,0x02,0x24,0x60,0x08,0x05,0x24,0xc0,0x0b,0xc3,0xac,0xc4,0x0b,0xc2,0xac, +0x80,0x0c,0x03,0x24,0x84,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xcc,0x0b,0xc2,0xac, +0x98,0x0b,0xc5,0xac,0xc8,0x0b,0xc3,0xac,0x89,0x0b,0xc0,0xa0,0x94,0x0b,0xc5,0xac, +0x02,0x00,0x80,0x10,0xa0,0x08,0x02,0x24,0xb8,0x08,0x02,0x24,0x08,0x00,0xe0,0x03, +0xd0,0x0b,0xc2,0xac,0x28,0x08,0xa2,0x34,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c, +0x38,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x8c,0x0b,0xc2,0xac, +0x44,0x08,0x02,0x24,0x90,0x0b,0xc3,0xac,0x9c,0x0b,0xc2,0xac,0x78,0x08,0x03,0x24, +0x0c,0x08,0x02,0x24,0xa0,0x0b,0xc3,0xac,0xa4,0x0b,0xc2,0xac,0x14,0x08,0x03,0x24, +0x28,0x08,0x02,0x24,0xa8,0x0b,0xc3,0xac,0xac,0x0b,0xc2,0xac,0x2c,0x08,0x03,0x24, +0x58,0x08,0x02,0x24,0xb0,0x0b,0xc3,0xac,0xb4,0x0b,0xc2,0xac,0x58,0x0c,0x03,0x24, +0x5c,0x0c,0x02,0x24,0xb8,0x0b,0xc3,0xac,0xbc,0x0b,0xc2,0xac,0x1c,0x0c,0x03,0x24, +0x18,0x0c,0x02,0x24,0x64,0x08,0x05,0x24,0xc0,0x0b,0xc3,0xac,0xc4,0x0b,0xc2,0xac, +0x88,0x0c,0x03,0x24,0x8c,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xcc,0x0b,0xc2,0xac, +0x89,0x0b,0xc7,0xa0,0x98,0x0b,0xc5,0xac,0xc8,0x0b,0xc3,0xac,0x94,0x0b,0xc5,0xac, +0xd6,0xff,0x80,0x10,0xa4,0x08,0x02,0x24,0xbc,0x08,0x02,0x24,0x08,0x00,0xe0,0x03, +0xd0,0x0b,0xc2,0xac,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0xac,0x08,0x03,0x24, +0xd0,0x0b,0x43,0xac,0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x8c,0x0b,0x43,0xac, +0x4c,0x08,0x03,0x24,0x90,0x0b,0x44,0xac,0x9c,0x0b,0x43,0xac,0x7c,0x08,0x04,0x24, +0x0c,0x08,0x03,0x24,0xa0,0x0b,0x44,0xac,0xa4,0x0b,0x43,0xac,0x1c,0x08,0x04,0x24, +0x38,0x08,0x03,0x24,0xa8,0x0b,0x44,0xac,0xac,0x0b,0x43,0xac,0x3c,0x08,0x04,0x24, +0x5c,0x08,0x03,0x24,0xb0,0x0b,0x44,0xac,0xb4,0x0b,0x43,0xac,0x68,0x0c,0x04,0x24, +0x6c,0x0c,0x03,0x24,0xb8,0x0b,0x44,0xac,0xbc,0x0b,0x43,0xac,0x2c,0x0c,0x04,0x24, +0x28,0x0c,0x03,0x24,0x6c,0x08,0x05,0x24,0xc0,0x0b,0x44,0xac,0xc4,0x0b,0x43,0xac, +0x98,0x0c,0x04,0x24,0x9c,0x0c,0x03,0x24,0x89,0x0b,0x47,0xa0,0x98,0x0b,0x45,0xac, +0xc8,0x0b,0x44,0xac,0xcc,0x0b,0x43,0xac,0x08,0x00,0xe0,0x03,0x94,0x0b,0x45,0xac, +0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0xa8,0x08,0x03,0x24,0xd0,0x0b,0x43,0xac, +0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x8c,0x0b,0x43,0xac,0x48,0x08,0x03,0x24, +0x90,0x0b,0x44,0xac,0x9c,0x0b,0x43,0xac,0x7c,0x08,0x04,0x24,0x0c,0x08,0x03,0x24, +0xa0,0x0b,0x44,0xac,0xa4,0x0b,0x43,0xac,0x18,0x08,0x04,0x24,0x30,0x08,0x03,0x24, +0xa8,0x0b,0x44,0xac,0xac,0x0b,0x43,0xac,0x34,0x08,0x04,0x24,0x5c,0x08,0x03,0x24, +0xb0,0x0b,0x44,0xac,0xb4,0x0b,0x43,0xac,0x60,0x0c,0x04,0x24,0x64,0x0c,0x03,0x24, +0xb8,0x0b,0x44,0xac,0xbc,0x0b,0x43,0xac,0x24,0x0c,0x04,0x24,0x20,0x0c,0x03,0x24, +0x68,0x08,0x05,0x24,0xc0,0x0b,0x44,0xac,0xc4,0x0b,0x43,0xac,0x90,0x0c,0x04,0x24, +0x94,0x0c,0x03,0x24,0x89,0x0b,0x47,0xa0,0x98,0x0b,0x45,0xac,0xc8,0x0b,0x44,0xac, +0xcc,0x0b,0x43,0xac,0x08,0x00,0xe0,0x03,0x94,0x0b,0x45,0xac,0xe6,0x42,0x00,0x08, +0x21,0x18,0x00,0x00,0x20,0x00,0x62,0x2c,0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x06,0x10,0x64,0x00,0x01,0x00,0x42,0x30,0xfa,0xff,0x40,0x10,0x01,0x00,0x63,0x24, +0xff,0xff,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xd8,0xff,0xbd,0x27, +0x25,0xb0,0x02,0x3c,0x18,0x00,0xb2,0xaf,0x21,0x90,0x82,0x00,0xff,0xff,0x02,0x24, +0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf, +0x21,0x88,0xa0,0x00,0x21,0x20,0xa0,0x00,0x21,0x18,0x40,0x02,0x10,0x00,0xa2,0x10, +0x21,0x98,0xc0,0x00,0x00,0x00,0x50,0x8e,0xe1,0x42,0x00,0x0c,0x00,0x00,0x00,0x00, +0x04,0x10,0x53,0x00,0x27,0x18,0x11,0x00,0x25,0x18,0x62,0x00,0x24,0x18,0x70,0x00, +0x00,0x00,0x43,0xae,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27, +0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x28,0x00,0xbd,0x27,0x00,0x00,0x66,0xac,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x21,0x30,0x80,0x00,0xd4,0x20,0x44,0x8c, +0xed,0x42,0x00,0x08,0xff,0xff,0x05,0x24,0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c, +0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x20,0x82,0x00, +0x00,0x00,0x90,0x8c,0x21,0x88,0xa0,0x00,0xe1,0x42,0x00,0x0c,0x21,0x20,0xa0,0x00, +0x24,0x80,0x11,0x02,0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27, +0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x28,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf, +0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x24,0x00,0xb5,0xaf,0x10,0x00,0xb0,0xaf, +0x38,0x15,0x31,0x26,0xb0,0x0b,0x22,0x8e,0x25,0xb0,0x12,0x3c,0x24,0x08,0x53,0x36, +0x21,0x10,0x52,0x00,0x00,0x00,0x70,0x8e,0x00,0x00,0x55,0x8c,0x7f,0x80,0x03,0x3c, +0xff,0x7f,0x02,0x3c,0xff,0xff,0x63,0x34,0xff,0xff,0x42,0x34,0x24,0x10,0x02,0x02, +0x24,0x18,0xa3,0x02,0xc0,0x25,0x04,0x00,0x25,0x18,0x64,0x00,0x00,0x80,0x14,0x3c, +0x00,0x00,0x62,0xae,0x01,0x00,0x04,0x24,0xf2,0x19,0x00,0x0c,0x25,0xa8,0x74,0x00, +0xb0,0x0b,0x22,0x8e,0x25,0x80,0x14,0x02,0x01,0x00,0x04,0x24,0x21,0x10,0x52,0x00, +0x00,0x00,0x55,0xac,0xf2,0x19,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xae, +0xf2,0x19,0x00,0x0c,0x01,0x00,0x04,0x24,0xd0,0x0b,0x24,0x8e,0x0f,0x00,0x05,0x3c, +0x28,0x00,0xbf,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0xa5,0x34, +0x18,0x43,0x00,0x08,0x30,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf, +0x02,0x80,0x11,0x3c,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x38,0x15,0x27,0x26, +0x8b,0x0b,0xe5,0x90,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x70,0x0d,0x63,0x24, +0x18,0x03,0x42,0x34,0x02,0x00,0x06,0x24,0x00,0x00,0x43,0xac,0x34,0x00,0xa6,0x10, +0x21,0x80,0x80,0x00,0x03,0x00,0x03,0x24,0x3a,0x00,0xa3,0x10,0x2e,0x00,0x02,0x2e, +0x10,0x00,0x02,0x2e,0x07,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0x00,0x04,0x32, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x29,0x43,0x00,0x08, +0x20,0x00,0xbd,0x27,0xfa,0xff,0xa6,0x14,0xff,0x00,0x04,0x32,0x89,0x0b,0xe4,0x90, +0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x38,0x00,0x85,0x10,0x38,0x15,0x22,0x26,0x2e,0x00,0x83,0x10, +0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,0x18,0x43,0x00,0x0c,0xff,0xff,0x05,0x24, +0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24, +0xed,0x42,0x00,0x0c,0xff,0xff,0x05,0x24,0x38,0x15,0x22,0x26,0x89,0x0b,0x44,0x90, +0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14, +0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0xdb,0xff,0x82,0x14, +0x00,0x00,0x00,0x00,0x38,0x15,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c, +0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00,0x72,0x43,0x00,0x08,0xff,0x00,0x04,0x32, +0x25,0x00,0x82,0x2c,0xcc,0xff,0x40,0x14,0x03,0x00,0x03,0x24,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0xc7,0xff,0x40,0x14,0x10,0x00,0x02,0x2e,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x38,0x15,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c, +0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,0x84,0x43,0x00,0x08,0x00,0x08,0x04,0x24, +0xcc,0xff,0x80,0x14,0x38,0x15,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24, +0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,0x84,0x43,0x00,0x08,0x00,0x08,0x04,0x24, +0xb2,0xff,0x80,0x14,0x00,0x00,0x00,0x00,0x38,0x15,0x22,0x26,0x8c,0x0b,0x44,0x8c, +0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00,0x72,0x43,0x00,0x08, +0xff,0x00,0x04,0x32,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c, +0x38,0x15,0x28,0x26,0x8b,0x0b,0x06,0x91,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x1c,0x0f,0x63,0x24,0x18,0x03,0x42,0x34,0x02,0x00,0x07,0x24,0x18,0x00,0xb2,0xaf, +0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00, +0x39,0x00,0xc7,0x10,0xff,0x00,0x90,0x30,0x03,0x00,0x03,0x24,0x3f,0x00,0xc3,0x10, +0x2e,0x00,0x02,0x2e,0x10,0x00,0x02,0x2e,0x0c,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x0f,0x00,0x04,0x3c,0xff,0xff,0x84,0x34,0x24,0x20,0x44,0x02,0x00,0x15,0x10,0x00, +0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x25,0x20,0x44,0x00,0x13,0x43,0x00,0x08,0x20,0x00,0xbd,0x27,0xf5,0xff,0xc7,0x14, +0x0f,0x00,0x04,0x3c,0x89,0x0b,0x04,0x91,0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10, +0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x38,0x00,0x86,0x10, +0x38,0x15,0x22,0x26,0x2e,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24, +0x18,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34, +0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,0xed,0x42,0x00,0x0c,0xff,0xff,0x05,0x24, +0x38,0x15,0x22,0x26,0x89,0x0b,0x44,0x90,0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10, +0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10, +0x03,0x00,0x02,0x24,0xd6,0xff,0x82,0x14,0x00,0x00,0x00,0x00,0x38,0x15,0x22,0x26, +0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00, +0xdf,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0x25,0x00,0x02,0x2e,0xc7,0xff,0x40,0x14, +0x03,0x00,0x03,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xc1,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x38,0x15,0x22,0x26, +0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24, +0xf6,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xcc,0xff,0x80,0x14,0x38,0x15,0x22,0x26, +0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24, +0xf6,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xad,0xff,0x80,0x14,0x00,0x00,0x00,0x00, +0x38,0x15,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c, +0x21,0x30,0x00,0x00,0xdf,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0xe8,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00,0x14,0x00,0xbf,0xaf,0x29,0x43,0x00,0x0c, +0x21,0x20,0x00,0x00,0x40,0x01,0x44,0x34,0x21,0x18,0x40,0x00,0x1f,0x00,0x02,0x2e, +0x00,0x23,0x04,0x00,0x10,0x00,0x40,0x10,0x10,0x00,0x05,0x2e,0x00,0x01,0x64,0x34, +0x06,0x00,0xa0,0x10,0x00,0x23,0x04,0x00,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x13,0x43,0x00,0x0c, +0xf1,0xff,0x10,0x26,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x13,0x43,0x00,0x0c,0xe2,0xff,0x10,0x26, +0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x27,0x38,0x05,0x00,0x21,0x40,0x82,0x00, +0xff,0xff,0x02,0x24,0x07,0x00,0xa2,0x10,0x25,0x38,0xe6,0x00,0x00,0x00,0x02,0x8d, +0x00,0x00,0x00,0x00,0x24,0x10,0xe2,0x00,0x00,0x00,0x02,0xad,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xad,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xd8,0xff,0xbd,0x27,0xa8,0x11,0x42,0x24, +0x18,0x03,0x63,0x34,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf, +0x24,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac, +0x21,0x88,0xa0,0x00,0x21,0x98,0xc0,0x00,0x21,0xa0,0x80,0x00,0x00,0x60,0x12,0x40, +0x01,0x00,0x41,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x02,0x3c, +0xff,0xff,0x42,0x34,0x0a,0x00,0x22,0x12,0x21,0x28,0xc0,0x00,0x5c,0x43,0x00,0x0c, +0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02,0xe1,0x42,0x00,0x0c,0x21,0x80,0x40,0x00, +0x04,0x10,0x53,0x00,0x27,0x28,0x11,0x00,0x25,0x28,0xa2,0x00,0x24,0x28,0xb0,0x00, +0xc7,0x43,0x00,0x0c,0xff,0x00,0x84,0x32,0x00,0x60,0x92,0x40,0x24,0x00,0xbf,0x8f, +0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x01,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xe0,0xff,0xbd,0x27,0x54,0x12,0x63,0x24,0x18,0x03,0x42,0x34, +0x18,0x00,0xb2,0xaf,0x1c,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf, +0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00,0x00,0x60,0x11,0x40,0x01,0x00,0x21,0x36, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x5c,0x43,0x00,0x0c,0x00,0x00,0x00,0x00, +0x21,0x80,0x40,0x00,0xe1,0x42,0x00,0x0c,0x21,0x20,0x40,0x02,0x24,0x80,0x12,0x02, +0x06,0x80,0x50,0x00,0x00,0x60,0x91,0x40,0x21,0x10,0x00,0x02,0x1c,0x00,0xbf,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xc8,0xff,0xbd,0x27,0x2c,0x00,0xb1,0xaf,0xff,0xff,0x05,0x24, +0x21,0x88,0x80,0x00,0x02,0x00,0x06,0x24,0x10,0x00,0xa4,0x27,0x34,0x00,0xbf,0xaf, +0x30,0x00,0xb2,0xaf,0x58,0x45,0x00,0x0c,0x28,0x00,0xb0,0xaf,0x08,0x00,0x30,0x96, +0x02,0x80,0x02,0x3c,0x21,0x28,0x00,0x00,0x25,0x80,0x02,0x02,0x21,0x20,0x00,0x02, +0x58,0x45,0x00,0x0c,0x10,0x00,0x06,0x24,0x20,0x00,0x02,0x96,0x24,0x00,0x04,0x26, +0x10,0x00,0xa5,0x27,0x03,0xff,0x42,0x30,0xc8,0x00,0x42,0x34,0x20,0x00,0x02,0xa6, +0x60,0x45,0x00,0x0c,0x06,0x00,0x06,0x24,0x25,0xb0,0x03,0x3c,0x50,0x00,0x62,0x34, +0x00,0x00,0x44,0x8c,0x54,0x00,0x65,0x34,0x58,0x00,0x66,0x34,0x18,0x00,0xa4,0xaf, +0x00,0x00,0xa2,0x8c,0x5c,0x00,0x63,0x34,0x2a,0x00,0x04,0x26,0x1c,0x00,0xa2,0xaf, +0x00,0x00,0xc7,0x8c,0x18,0x00,0xa5,0x27,0x06,0x00,0x06,0x24,0x20,0x00,0xa7,0xaf, +0x00,0x00,0x62,0x8c,0x1a,0x00,0x12,0x24,0x60,0x45,0x00,0x0c,0x24,0x00,0xa2,0xaf, +0x30,0x00,0x04,0x26,0x20,0x00,0xa5,0x27,0x60,0x45,0x00,0x0c,0x06,0x00,0x06,0x24, +0x13,0x00,0x03,0x24,0x14,0x00,0x23,0xae,0x0c,0x00,0x32,0xae,0x08,0x00,0x05,0x8e, +0x04,0x00,0x04,0x8e,0xff,0xdf,0x02,0x3c,0x14,0x00,0x06,0x8e,0xff,0xff,0x42,0x34, +0x10,0x00,0x07,0x8e,0xff,0xe0,0x03,0x24,0x24,0x28,0xa2,0x00,0x00,0x40,0x02,0x3c, +0x24,0x20,0x83,0x00,0x25,0x28,0xa2,0x00,0xff,0x81,0x03,0x24,0xfe,0xff,0x02,0x3c, +0x24,0x30,0xc3,0x00,0xff,0xff,0x42,0x34,0x00,0x12,0x84,0x34,0x00,0x80,0x03,0x3c, +0x24,0x20,0x82,0x00,0x25,0x38,0xe3,0x00,0x00,0x26,0xc6,0x34,0x80,0x00,0xa5,0x34, +0x20,0x00,0x02,0x24,0x00,0x00,0x12,0xa6,0x10,0x00,0x07,0xae,0x02,0x00,0x02,0xa2, +0x14,0x00,0x06,0xae,0x04,0x00,0x04,0xae,0x08,0x00,0x05,0xae,0x34,0x00,0xbf,0x8f, +0x30,0x00,0xb2,0x8f,0x2c,0x00,0xb1,0x8f,0x28,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x38,0x00,0xbd,0x27,0x54,0x45,0x00,0x08,0xff,0x00,0xa5,0x30,0x00,0x00,0x85,0xa0, +0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24,0xfc,0xff,0xc0,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x05,0x00,0xc0,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0x85,0xac,0xff,0xff,0xc6,0x24,0xfd,0xff,0xc0,0x14,0x04,0x00,0x84,0x24, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10, +0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24, +0x01,0x00,0xa5,0x24,0x00,0x00,0xe2,0xa0,0xfb,0xff,0x66,0x14,0x01,0x00,0xe7,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10, +0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x8c,0xff,0xff,0x63,0x24, +0x04,0x00,0xa5,0x24,0x00,0x00,0xe2,0xac,0xfb,0xff,0x66,0x14,0x04,0x00,0xe7,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x2b,0x10,0xa4,0x00,0x0d,0x00,0x40,0x14, +0xff,0xff,0x02,0x24,0xff,0xff,0xc6,0x24,0x08,0x00,0xc2,0x10,0x21,0x18,0x80,0x00, +0xff,0xff,0x07,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0xa5,0x24, +0x00,0x00,0x62,0xa0,0xfb,0xff,0xc7,0x14,0x01,0x00,0x63,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x80,0x00,0x21,0x28,0xa6,0x00,0x21,0x18,0x86,0x00,0xff,0xff,0xc6,0x24, +0xfa,0xff,0xc2,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0x07,0x24,0xff,0xff,0xa5,0x24, +0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24,0xff,0xff,0xc6,0x24,0xfb,0xff,0xc7,0x14, +0x00,0x00,0x62,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x0c,0x00,0xc0,0x10, +0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0xa3,0x90,0x01,0x00,0x84,0x24, +0x23,0x10,0x43,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x04,0x00,0x40,0x14, +0x01,0x00,0xa5,0x24,0xff,0xff,0xc6,0x24,0xf6,0xff,0xc0,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0xc0,0x00,0xab,0x45,0x00,0x08,0x21,0x18,0x86,0x00, +0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x45,0x10,0x00,0x00,0x00,0x00, +0x01,0x00,0x84,0x24,0xfa,0xff,0x83,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x80,0x00,0x09,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,0xff,0x00,0xa5,0x30, +0xff,0xff,0x06,0x24,0x00,0x00,0x82,0x90,0xff,0xff,0x63,0x24,0x05,0x00,0x45,0x10, +0x01,0x00,0x84,0x24,0xfb,0xff,0x66,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0xff,0xff,0x82,0x24,0x21,0x38,0x00,0x00, +0x1f,0x00,0xc0,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x02,0x3c,0x40,0x92,0x4b,0x24, +0x00,0x00,0x87,0x90,0x00,0x00,0xa3,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24, +0x21,0x10,0xeb,0x00,0x16,0x00,0xe0,0x10,0x01,0x00,0xa5,0x24,0x14,0x00,0x60,0x10, +0x21,0x48,0x6b,0x00,0x10,0x00,0xe3,0x10,0x20,0x00,0xe8,0x24,0x00,0x00,0x42,0x90, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x02,0x00,0x40,0x10,0x20,0x00,0x6a,0x24, +0xff,0x00,0x07,0x31,0x00,0x00,0x22,0x91,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30, +0x02,0x00,0x40,0x10,0xff,0x00,0xe7,0x30,0xff,0x00,0x43,0x31,0xff,0x00,0x63,0x30, +0x03,0x00,0xe3,0x14,0x00,0x00,0x00,0x00,0xe5,0xff,0xc0,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x23,0x10,0xe3,0x00,0x21,0x18,0x80,0x00,0x00,0x00,0xa2,0x90, +0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x21,0x38,0x80,0x00,0xff,0xff,0x03,0x24, +0xff,0xff,0xc6,0x24,0x06,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90, +0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0xf9,0xff,0x40,0x14,0x01,0x00,0x84,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,0x00,0x00,0x82,0x80,0xfa,0x45,0x00,0x08, +0x21,0x18,0x80,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00, +0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24, +0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x12,0x00,0xc0,0x10,0x21,0x18,0x80,0x00,0x00,0x00,0x82,0x80, +0x0b,0x46,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80, +0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90, +0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0x05,0x00,0x40,0x10,0x01,0x00,0x84,0x24, +0xff,0xff,0xc6,0x24,0xf9,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xa0, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x00,0x00,0x83,0x90,0x00,0x00,0xa2,0x90, +0x01,0x00,0x84,0x24,0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00, +0x03,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,0xf7,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x0b,0x00,0xc0,0x10, +0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x00,0x00,0x83,0x90,0xff,0xff,0xc6,0x24, +0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14, +0x01,0x00,0xa5,0x24,0xf5,0xff,0x60,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x80,0x00,0x2e,0x05,0x00,0x21,0x10,0x80,0x00, +0x3c,0x46,0x00,0x08,0x03,0x2e,0x05,0x00,0x07,0x00,0x60,0x10,0x01,0x00,0x42,0x24, +0x00,0x00,0x43,0x80,0x00,0x00,0x00,0x00,0xfb,0xff,0x65,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x00,0x00,0x82,0x80,0x48,0x46,0x00,0x08,0x21,0x18,0x80,0x00,0x01,0x00,0x63,0x24, +0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x23,0x10,0x64,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf, +0x21,0x80,0xa0,0x00,0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,0x21,0x88,0x80,0x00, +0x42,0x46,0x00,0x0c,0x00,0x86,0x10,0x00,0x21,0x18,0x51,0x00,0x03,0x86,0x10,0x00, +0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00,0x0a,0x00,0x50,0x10,0x21,0x10,0x60,0x00, +0xff,0xff,0x63,0x24,0x2b,0x10,0x71,0x00,0xf9,0xff,0x40,0x10,0x21,0x10,0x00,0x00, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x21,0x30,0x80,0x00,0x0d,0x00,0xa0,0x10, +0xff,0xff,0xa3,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x24,0xff,0xff,0x63,0x24,0x05,0x00,0x65,0x10, +0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x80,0x00,0x00,0x00,0x00,0xfa,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x23,0x10,0xc4,0x00,0x00,0x00,0x82,0x90, +0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10,0x21,0x40,0x00,0x00,0x00,0x00,0xa9,0x80, +0x00,0x00,0x00,0x00,0x17,0x00,0x20,0x11,0x21,0x30,0xa0,0x00,0x00,0x3e,0x02,0x00, +0x03,0x3e,0x07,0x00,0x21,0x18,0x20,0x01,0x15,0x00,0xe3,0x10,0x00,0x00,0x00,0x00, +0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0x00,0x1e,0x02,0x00, +0x03,0x1e,0x03,0x00,0xf8,0xff,0x60,0x14,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00, +0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x90, +0x00,0x00,0x00,0x00,0xeb,0xff,0x40,0x14,0x01,0x00,0x08,0x25,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x01,0x00,0x00,0xa2,0x90,0x8d,0x46,0x00,0x08,0x00,0x16,0x02,0x00, +0x00,0x00,0xc2,0x90,0x8d,0x46,0x00,0x08,0x00,0x16,0x02,0x00,0x00,0x00,0x87,0x90, +0x00,0x00,0x00,0x00,0x14,0x00,0xe0,0x10,0x21,0x10,0x80,0x00,0x00,0x00,0xa4,0x90, +0x00,0x00,0x00,0x00,0x00,0x1e,0x04,0x00,0x03,0x1e,0x03,0x00,0x09,0x00,0x60,0x10, +0x21,0x30,0xa0,0x00,0x00,0x3e,0x07,0x00,0x03,0x3e,0x07,0x00,0x0b,0x00,0xe3,0x10, +0x01,0x00,0xc6,0x24,0x00,0x00,0xc3,0x80,0x00,0x00,0x00,0x00,0xfb,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0x00,0x00,0x47,0x90,0x00,0x00,0x00,0x00, +0xf0,0xff,0xe0,0x14,0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf, +0x18,0x00,0xbf,0xaf,0x21,0x80,0x80,0x00,0x1d,0x00,0x80,0x10,0x21,0x88,0xa0,0x00, +0x79,0x46,0x00,0x0c,0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82, +0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0x22,0x00,0x40,0x10,0x21,0x18,0x00,0x00, +0x9d,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x10,0x21,0x18,0x40,0x00, +0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00,0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x02,0x80,0x02,0x3c,0x70,0x93,0x43,0xac,0x21,0x18,0x00,0x02,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x00,0x00,0x60,0xa0,0xce,0x46,0x00,0x08,0x01,0x00,0x63,0x24, +0x02,0x80,0x02,0x3c,0x70,0x93,0x50,0x8c,0x00,0x00,0x00,0x00,0xf3,0xff,0x00,0x12, +0x21,0x18,0x00,0x00,0x79,0x46,0x00,0x0c,0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02, +0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0xe0,0xff,0x40,0x14, +0x21,0x18,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x02,0x80,0x02,0x3c,0x70,0x93,0x40,0xac,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0xe0,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf, +0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x90,0x8c,0x21,0x90,0x80,0x00, +0x21,0x88,0xa0,0x00,0x21,0x18,0x00,0x00,0x0f,0x00,0x00,0x12,0x21,0x20,0x00,0x02, +0x79,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82, +0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0x07,0x00,0x40,0x10,0x21,0x18,0x00,0x00, +0x9d,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x18,0x40,0x00,0x09,0x00,0x40,0x14, +0x00,0x00,0x42,0xae,0x21,0x18,0x00,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00,0xf5,0xff,0x40,0x10, +0x01,0x00,0x64,0x24,0x00,0x00,0x60,0xa0,0x07,0x47,0x00,0x08,0x00,0x00,0x44,0xae, +0xd8,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x21,0x88,0x80,0x00,0x21,0x20,0xa0,0x00, +0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf, +0x42,0x46,0x00,0x0c,0x21,0x98,0xa0,0x00,0x21,0x90,0x40,0x00,0x08,0x00,0x40,0x16, +0x21,0x10,0x20,0x02,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27, +0x42,0x46,0x00,0x0c,0x21,0x20,0x20,0x02,0x21,0x80,0x40,0x00,0x2a,0x10,0x52,0x00, +0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x02, +0x21,0x30,0x40,0x02,0x95,0x45,0x00,0x0c,0xff,0xff,0x10,0x26,0x0b,0x00,0x40,0x10, +0x2a,0x18,0x12,0x02,0xf8,0xff,0x60,0x10,0x01,0x00,0x31,0x26,0x20,0x00,0xbf,0x8f, +0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x23,0x47,0x00,0x08, +0x21,0x10,0x20,0x02,0x00,0x00,0x87,0x90,0x00,0x00,0x00,0x00,0x27,0x00,0xe0,0x10, +0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x90,0x00,0x00,0x00,0x00,0x0a,0x00,0xc0,0x10, +0xdf,0xff,0x02,0x24,0x24,0x18,0xc2,0x00,0x24,0x10,0xe2,0x00,0x00,0x16,0x02,0x00, +0x00,0x1e,0x03,0x00,0x03,0x16,0x02,0x00,0x03,0x1e,0x03,0x00,0x0a,0x00,0x43,0x10, +0x00,0x00,0x00,0x00,0xdf,0xff,0x02,0x24,0x24,0x18,0xc2,0x00,0x24,0x10,0xe2,0x00, +0x00,0x16,0x02,0x00,0x00,0x1e,0x03,0x00,0x03,0x1e,0x03,0x00,0x03,0x16,0x02,0x00, +0x08,0x00,0xe0,0x03,0x23,0x10,0x43,0x00,0x66,0x47,0x00,0x08,0xdf,0xff,0x08,0x24, +0x00,0x00,0xa6,0x90,0x00,0x00,0x00,0x00,0x24,0x10,0x06,0x01,0x00,0x16,0x02,0x00, +0xf0,0xff,0xc0,0x10,0x03,0x16,0x02,0x00,0xef,0xff,0x62,0x14,0xdf,0xff,0x02,0x24, +0x01,0x00,0x84,0x24,0x00,0x00,0x87,0x90,0x01,0x00,0xa5,0x24,0x24,0x10,0x07,0x01, +0x00,0x1e,0x02,0x00,0xf2,0xff,0xe0,0x14,0x03,0x1e,0x03,0x00,0x00,0x00,0xa6,0x90, +0xdf,0xff,0x02,0x24,0x24,0x18,0xc2,0x00,0x24,0x10,0xe2,0x00,0x00,0x16,0x02,0x00, +0x00,0x1e,0x03,0x00,0x03,0x1e,0x03,0x00,0x03,0x16,0x02,0x00,0x08,0x00,0xe0,0x03, +0x23,0x10,0x43,0x00,0xa8,0xff,0xbd,0x27,0x44,0x00,0xb5,0xaf,0x40,0x00,0xb4,0xaf, +0x38,0x00,0xb2,0xaf,0x34,0x00,0xb1,0xaf,0x54,0x00,0xbf,0xaf,0x50,0x00,0xbe,0xaf, +0x4c,0x00,0xb7,0xaf,0x48,0x00,0xb6,0xaf,0x3c,0x00,0xb3,0xaf,0x30,0x00,0xb0,0xaf, +0x21,0x90,0xa0,0x00,0x00,0x00,0xa5,0x90,0x21,0xa8,0x80,0x00,0x21,0xa0,0xc0,0x00, +0x00,0x26,0x05,0x00,0x03,0x26,0x04,0x00,0x0f,0x00,0x80,0x10,0x21,0x88,0xa0,0x02, +0x25,0x00,0x02,0x24,0x1b,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x58,0x00,0xa0,0x12, +0x00,0x00,0x00,0x00,0x00,0x00,0x25,0xa2,0x01,0x00,0x31,0x26,0x01,0x00,0x52,0x26, +0x00,0x00,0x45,0x92,0x00,0x00,0x00,0x00,0x00,0x26,0x05,0x00,0x03,0x26,0x04,0x00, +0xf4,0xff,0x80,0x14,0x25,0x00,0x02,0x24,0x02,0x00,0xa0,0x12,0x23,0x10,0x35,0x02, +0x00,0x00,0x20,0xa2,0x54,0x00,0xbf,0x8f,0x50,0x00,0xbe,0x8f,0x4c,0x00,0xb7,0x8f, +0x48,0x00,0xb6,0x8f,0x44,0x00,0xb5,0x8f,0x40,0x00,0xb4,0x8f,0x3c,0x00,0xb3,0x8f, +0x38,0x00,0xb2,0x8f,0x34,0x00,0xb1,0x8f,0x30,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x58,0x00,0xbd,0x27,0x01,0x00,0x52,0x26,0x00,0x00,0x44,0x92,0x73,0x00,0x02,0x24, +0x00,0x1e,0x04,0x00,0x03,0x1e,0x03,0x00,0x2c,0x00,0x62,0x10,0x10,0x00,0xb3,0x27, +0x23,0x00,0x02,0x24,0x21,0xf0,0x60,0x02,0x21,0x38,0x00,0x00,0x3b,0x00,0x62,0x10, +0x1c,0x00,0x05,0x24,0x00,0x16,0x04,0x00,0x03,0x16,0x02,0x00,0x68,0x00,0x03,0x24, +0x3d,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x00,0x16,0x04,0x00,0x03,0x16,0x02,0x00, +0x40,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x20,0x00,0x82,0x34,0x00,0x16,0x02,0x00, +0x03,0x16,0x02,0x00,0x78,0x00,0x03,0x24,0x43,0x00,0x43,0x10,0x20,0x00,0x86,0x30, +0x00,0x1e,0x04,0x00,0x03,0x1e,0x03,0x00,0x64,0x00,0x02,0x24,0x50,0x00,0x62,0x10, +0x40,0x00,0x02,0x24,0x82,0x00,0x62,0x10,0x21,0x00,0x02,0x24,0x93,0x00,0x62,0x10, +0x63,0x00,0x02,0x24,0x75,0x00,0x62,0x10,0x11,0x00,0xb3,0x27,0x10,0x00,0xa4,0xa3, +0x21,0x80,0xc0,0x03,0x2b,0x10,0x13,0x02,0xc0,0xff,0x40,0x10,0x00,0x00,0x00,0x00, +0xa1,0x00,0xa0,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x92,0x01,0x00,0x10,0x26, +0x00,0x00,0x22,0xa2,0xcf,0x47,0x00,0x08,0x01,0x00,0x31,0x26,0x00,0x00,0x82,0x8e, +0x04,0x00,0x94,0x26,0x21,0x80,0x40,0x00,0x00,0x00,0x02,0x92,0x00,0x00,0x00,0x00, +0xb2,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x64,0x00,0xa0,0x12,0x00,0x00,0x00,0x00, +0x00,0x00,0x22,0xa2,0x01,0x00,0x10,0x26,0xdc,0x47,0x00,0x08,0x01,0x00,0x31,0x26, +0x94,0x48,0x00,0x0c,0x01,0x00,0x52,0x26,0x00,0x00,0x45,0x92,0x00,0x00,0x00,0x00, +0x00,0x26,0x05,0x00,0x96,0x47,0x00,0x08,0x03,0x26,0x04,0x00,0x01,0x00,0x52,0x26, +0x00,0x00,0x44,0x92,0x68,0x00,0x03,0x24,0x00,0x16,0x04,0x00,0x03,0x16,0x02,0x00, +0xc5,0xff,0x43,0x14,0x01,0x00,0x07,0x24,0x01,0x00,0x52,0x26,0x00,0x00,0x44,0x92, +0x00,0x00,0x00,0x00,0x00,0x16,0x04,0x00,0x03,0x16,0x02,0x00,0xc2,0xff,0x43,0x14, +0x0c,0x00,0x05,0x24,0x01,0x00,0x52,0x26,0x00,0x00,0x44,0x92,0x78,0x00,0x03,0x24, +0x20,0x00,0x82,0x34,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0xc0,0xff,0x43,0x14, +0x04,0x00,0x05,0x24,0x20,0x00,0x86,0x30,0x00,0x00,0x84,0x8e,0x35,0x00,0xe0,0x14, +0x04,0x00,0x94,0x26,0xc6,0xff,0xa0,0x04,0x02,0x80,0x02,0x3c,0x80,0x8e,0x42,0x24, +0x00,0x00,0x47,0x8c,0x07,0x10,0xa4,0x00,0x0f,0x00,0x42,0x30,0x21,0x10,0x47,0x00, +0x00,0x00,0x43,0x90,0xfc,0xff,0xa5,0x24,0x25,0x18,0xc3,0x00,0x00,0x00,0x63,0xa2, +0xf8,0xff,0xa1,0x04,0x01,0x00,0x73,0x26,0xcf,0x47,0x00,0x08,0x21,0x80,0xc0,0x03, +0x00,0x00,0x82,0x8e,0x04,0x00,0x94,0x26,0x56,0x00,0x40,0x04,0x21,0x28,0x40,0x00, +0x21,0x80,0x60,0x02,0x02,0x80,0x02,0x3c,0x84,0x8e,0x42,0x24,0x00,0x00,0x46,0x8c, +0x00,0x00,0x00,0x00,0x18,0x00,0xa6,0x00,0xc3,0x27,0x05,0x00,0x10,0x10,0x00,0x00, +0x83,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x80,0x18,0x02,0x00,0x21,0x18,0x62,0x00, +0x40,0x18,0x03,0x00,0x23,0x18,0xa3,0x00,0x30,0x00,0x63,0x24,0x00,0x00,0x63,0xa2, +0x21,0x28,0x40,0x00,0xf3,0xff,0x40,0x14,0x01,0x00,0x73,0x26,0x36,0x48,0x00,0x08, +0xff,0xff,0x63,0x26,0x00,0x00,0x65,0x80,0x00,0x00,0x02,0x92,0x00,0x00,0x00,0x00, +0x00,0x00,0x62,0xa0,0x00,0x00,0x05,0xa2,0xff,0xff,0x63,0x24,0x01,0x00,0x10,0x26, +0x2b,0x10,0x03,0x02,0xf7,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0xcf,0x47,0x00,0x08, +0x21,0x80,0xc0,0x03,0x58,0x00,0xc3,0x34,0x30,0x00,0x02,0x24,0x12,0x00,0xb3,0x27, +0x10,0x00,0xa2,0xa3,0x07,0x48,0x00,0x08,0x11,0x00,0xa3,0xa3,0x00,0x00,0x82,0x8e, +0x04,0x00,0x94,0x26,0xce,0x47,0x00,0x08,0x10,0x00,0xa2,0xa3,0x00,0x00,0x04,0x82, +0x94,0x48,0x00,0x0c,0x01,0x00,0x10,0x26,0xdc,0x47,0x00,0x08,0x00,0x00,0x00,0x00, +0x00,0x00,0x83,0x8e,0x28,0x00,0xb0,0x27,0x2c,0x00,0xa4,0x27,0x2b,0x10,0x04,0x02, +0x28,0x00,0xa3,0xaf,0x0b,0x00,0x40,0x10,0x04,0x00,0x94,0x26,0x21,0xb8,0x80,0x00, +0x02,0x80,0x16,0x3c,0x00,0x00,0x06,0x92,0x21,0x20,0x60,0x02,0x01,0x00,0x10,0x26, +0x79,0x48,0x00,0x0c,0x54,0x89,0xc5,0x26,0x2b,0x18,0x17,0x02,0xf9,0xff,0x60,0x14, +0x21,0x98,0x62,0x02,0xce,0x47,0x00,0x08,0xff,0xff,0x73,0x26,0x00,0x00,0x82,0x8e, +0x00,0x00,0x00,0x00,0x06,0x00,0x56,0x24,0x21,0x80,0x40,0x00,0x2b,0x10,0x56,0x00, +0xf8,0xff,0x40,0x10,0x04,0x00,0x94,0x26,0x02,0x80,0x17,0x3c,0x00,0x00,0x06,0x82, +0x21,0x20,0x60,0x02,0x01,0x00,0x10,0x26,0x79,0x48,0x00,0x0c,0x58,0x89,0xe5,0x26, +0x2b,0x18,0x16,0x02,0xf9,0xff,0x60,0x14,0x21,0x98,0x62,0x02,0xce,0x47,0x00,0x08, +0xff,0xff,0x73,0x26,0x2d,0x00,0x02,0x24,0x23,0x28,0x05,0x00,0x11,0x00,0xb3,0x27, +0x1a,0x48,0x00,0x08,0x10,0x00,0xa2,0xa3,0x00,0x00,0x04,0x82,0x94,0x48,0x00,0x0c, +0x01,0x00,0x10,0x26,0xd0,0x47,0x00,0x08,0x2b,0x10,0x13,0x02,0xe8,0xff,0xbd,0x27, +0x20,0x00,0xa6,0xaf,0x20,0x00,0xa6,0x27,0x10,0x00,0xbf,0xaf,0x24,0x00,0xa7,0xaf, +0x77,0x47,0x00,0x0c,0x1c,0x00,0xa5,0xaf,0x10,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf, +0x02,0x80,0x06,0x3c,0x74,0x93,0xc5,0x8c,0x02,0x80,0x02,0x3c,0x40,0x93,0x42,0x24, +0x03,0x00,0xa3,0x30,0x21,0x18,0x62,0x00,0x00,0x00,0x64,0x80,0x01,0x00,0xa5,0x24, +0x94,0x48,0x00,0x0c,0x74,0x93,0xc5,0xac,0x10,0x00,0xbf,0x8f,0x08,0x00,0x04,0x24, +0x94,0x48,0x00,0x08,0x18,0x00,0xbd,0x27,0x00,0x26,0x04,0x00,0x03,0x26,0x04,0x00, +0x00,0x00,0x84,0x48,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x26,0x04,0x00, +0x03,0x26,0x04,0x00,0xf7,0xff,0x82,0x24,0x05,0x00,0x42,0x2c,0x06,0x00,0x40,0x14, +0x21,0x18,0x00,0x00,0x20,0x00,0x02,0x24,0x03,0x00,0x82,0x10,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x25,0xb0,0x05,0x3c,0x01,0x00,0x06,0x24,0x01,0x80,0x02,0x3c, +0x04,0x30,0x86,0x00,0xf1,0x02,0xa7,0x34,0xed,0x02,0xa4,0x34,0x9c,0x22,0x42,0x24, +0x18,0x03,0xa5,0x34,0x08,0x00,0x03,0x24,0x00,0x00,0xa2,0xac,0x00,0x00,0xe3,0xa0, +0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0, +0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0, +0x00,0x00,0x80,0xa0,0x00,0x00,0xe0,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xff,0xff,0x84,0x30,0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x02,0x80,0x05,0x3c,0x38,0x15,0xa5,0x24,0xf2,0x23,0xa3,0x94, +0x25,0xb0,0x02,0x3c,0x1e,0x03,0x42,0x34,0x25,0x20,0x83,0x00,0x00,0x00,0x44,0xa4, +0xf2,0x23,0xa4,0xa4,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xff,0xff,0x84,0x30,0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x02,0x80,0x05,0x3c,0x38,0x15,0xa5,0x24,0xf2,0x23,0xa2,0x94, +0x60,0x24,0xa3,0x94,0x27,0x20,0x04,0x00,0x24,0x18,0x83,0x00,0x24,0x20,0x82,0x00, +0x25,0xb0,0x02,0x3c,0x1e,0x03,0x42,0x34,0x60,0x24,0xa3,0xa4,0x00,0x00,0x44,0xa4, +0xf2,0x23,0xa4,0xa4,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x02,0x80,0x04,0x3c,0x38,0x15,0x84,0x24,0x14,0x00,0x05,0x24,0x02,0x80,0x02,0x3c, +0x01,0x00,0x03,0x24,0x84,0x93,0x45,0xac,0x68,0x24,0x83,0xa0,0x08,0x00,0xe0,0x03, +0x6e,0x24,0x80,0xa4,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x84,0x93,0x40,0xac, +0x08,0x00,0xe0,0x03,0xa0,0x39,0x60,0xa0,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c, +0xc0,0x23,0x42,0x24,0x18,0x03,0x63,0x34,0x00,0x00,0x62,0xac,0x00,0x00,0x83,0x90, +0x30,0x00,0x02,0x24,0x05,0x00,0x62,0x10,0x21,0x20,0x00,0x00,0x31,0x00,0x02,0x24, +0x02,0x00,0x62,0x10,0x01,0x00,0x04,0x24,0x07,0x00,0x04,0x24,0xa7,0x48,0x00,0x08, +0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xfc,0x23,0x42,0x24, +0x18,0x03,0x63,0x34,0x02,0x80,0x04,0x3c,0x00,0x00,0x62,0xac,0x08,0x00,0xe0,0x03, +0xec,0x3d,0x80,0xac,0x02,0x80,0x02,0x3c,0x54,0x3b,0x42,0x24,0xc0,0x20,0x04,0x00, +0x21,0x20,0x82,0x00,0x21,0x28,0x00,0x00,0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x09,0x00,0x44,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x43,0x8c,0x21,0x28,0x40,0x00, +0x00,0x00,0x42,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac, +0x00,0x00,0xa5,0xac,0x04,0x00,0xa5,0xac,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03, +0x21,0x10,0xa0,0x00,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00, +0x01,0x01,0x02,0x2e,0x14,0x00,0xbf,0xaf,0x01,0x00,0x04,0x24,0x01,0x02,0x03,0x2e, +0x0b,0x00,0x40,0x14,0x21,0x28,0x00,0x00,0x02,0x00,0x04,0x24,0x08,0x00,0x60,0x14, +0x01,0x08,0x02,0x2e,0x06,0x00,0x40,0x14,0x03,0x00,0x04,0x24,0x14,0x00,0xbf,0x8f, +0x10,0x00,0xb0,0x8f,0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27, +0x07,0x49,0x00,0x0c,0x00,0x00,0x00,0x00,0xf8,0xff,0x40,0x10,0x21,0x28,0x40,0x00, +0x0c,0x00,0x50,0xac,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0xa0,0x00, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,0x6c,0x3b,0x62,0x8c, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x10,0x00,0x83,0x8c,0x02,0x80,0x02,0x3c, +0x54,0x3b,0x42,0x24,0xc0,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x65,0x8c, +0x02,0x80,0x07,0x3c,0x02,0x80,0x08,0x3c,0x00,0x00,0x85,0xac,0x04,0x00,0xa4,0xac, +0x04,0x00,0x83,0xac,0xb8,0x3e,0xe5,0x8c,0x00,0x00,0x00,0x00,0x05,0x00,0xa0,0x10, +0x00,0x00,0x64,0xac,0xa4,0x3e,0x02,0x8d,0xb8,0x3e,0xe0,0xac,0x25,0x10,0x45,0x00, +0xa4,0x3e,0x02,0xad,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00, +0x21,0x10,0x04,0x02,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x02,0x80,0x06,0x3c, +0x14,0x00,0xb1,0xaf,0x80,0x10,0x02,0x00,0x21,0x88,0x80,0x00,0xff,0x1f,0x03,0x3c, +0x38,0x15,0xc4,0x24,0x21,0x20,0x44,0x00,0xff,0xff,0x63,0x34,0x25,0xb0,0x02,0x3c, +0x84,0x01,0x42,0x34,0x18,0x00,0xbf,0xaf,0x88,0x11,0x83,0xac,0x00,0x00,0x43,0x8c, +0x08,0x00,0x22,0x2a,0x07,0x00,0x25,0x32,0x28,0x00,0x40,0x10,0x8c,0x11,0x83,0xac, +0x90,0x11,0x82,0x8c,0xf8,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x25,0x10,0x45,0x00, +0x90,0x11,0x82,0xac,0x21,0x80,0x11,0x02,0x80,0x80,0x10,0x00,0x21,0x80,0x11,0x02, +0x38,0x15,0xc2,0x24,0x80,0x80,0x10,0x00,0x21,0x80,0x02,0x02,0x90,0x11,0x03,0x8e, +0xff,0xfe,0x02,0x24,0xff,0xef,0x05,0x24,0x24,0x18,0x62,0x00,0xff,0xff,0x02,0x3c, +0xff,0x1f,0x42,0x34,0x24,0x18,0x65,0x00,0x24,0x18,0x62,0x00,0x90,0x11,0x03,0xae, +0x88,0x1d,0x00,0x0c,0x21,0x20,0x20,0x02,0x92,0x11,0x03,0x92,0x25,0xb0,0x02,0x3c, +0x21,0x10,0x22,0x02,0x60,0x01,0x43,0xa0,0x18,0x00,0xbf,0x8f,0x7c,0x11,0x00,0xae, +0x60,0x11,0x00,0xae,0x64,0x11,0x00,0xae,0x68,0x11,0x00,0xae,0x6c,0x11,0x00,0xae, +0x70,0x11,0x00,0xae,0x74,0x11,0x00,0xae,0x78,0x11,0x00,0xae,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x90,0x11,0x83,0x8c, +0xf8,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x7f,0x49,0x00,0x08,0x90,0x11,0x83,0xac, +0xff,0x00,0xa5,0x30,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x45,0x00,0x02,0x80,0x03,0x3c,0x38,0x15,0x63,0x24,0x80,0x10,0x02,0x00, +0x21,0x10,0x43,0x00,0x90,0x11,0x43,0x8c,0x25,0xb0,0x05,0x3c,0xff,0x00,0xc6,0x30, +0x21,0x30,0xc5,0x00,0xaf,0x01,0xc2,0x90,0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00, +0x21,0x18,0x65,0x00,0xff,0x00,0x88,0x30,0xff,0x00,0x49,0x30,0x84,0x01,0x66,0x8c, +0x21,0x50,0x00,0x00,0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,0x21,0x20,0x00,0x01, +0x2b,0x00,0xc0,0x10,0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,0xc7,0x49,0x00,0x08, +0x01,0x00,0x07,0x24,0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,0x07,0x00,0x40,0x10, +0xff,0xff,0x02,0x25,0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,0xf9,0xff,0x40,0x10, +0x01,0x00,0xa3,0x24,0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,0xff,0x00,0x45,0x30, +0x2b,0x18,0xab,0x00,0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,0x01,0x00,0x04,0x24, +0x04,0x10,0xa4,0x00,0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,0x04,0x00,0x40,0x10, +0x01,0x00,0x43,0x25,0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,0x21,0x40,0xa0,0x00, +0xff,0x00,0xe5,0x30,0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,0x04,0x10,0xa4,0x00, +0x2b,0x10,0x49,0x01,0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,0x23,0x10,0x2a,0x01, +0x2a,0x10,0x62,0x01,0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x69,0x01, +0x21,0x10,0x4a,0x00,0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00, +0xfd,0xff,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,0xe8,0x49,0x00,0x08, +0xff,0x00,0x44,0x30,0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00, +0xff,0x00,0x84,0x30,0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c,0x38,0x15,0x63,0x24,0x80,0x10,0x02,0x00, +0x21,0x10,0x43,0x00,0x25,0xb0,0x06,0x3c,0x90,0x11,0x43,0x8c,0xff,0x00,0xa5,0x30, +0x21,0x20,0x86,0x00,0x21,0x28,0xa6,0x00,0x60,0x01,0x82,0x90,0xaf,0x01,0xa4,0x90, +0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x66,0x00,0xff,0x00,0x48,0x30, +0xff,0x00,0x89,0x30,0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,0x21,0x58,0x00,0x00, +0x2b,0x00,0x20,0x11,0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,0x2b,0x10,0x09,0x01, +0x21,0x28,0x00,0x00,0x15,0x4a,0x00,0x08,0x01,0x00,0x07,0x24,0xff,0x00,0x65,0x30, +0x1d,0x00,0xa2,0x2c,0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,0x04,0x10,0xa7,0x00, +0x24,0x10,0x46,0x00,0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,0x21,0x58,0xa0,0x00, +0xff,0xff,0x02,0x25,0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,0x0f,0x00,0x60,0x14, +0x2b,0x10,0x49,0x01,0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,0x24,0x10,0x46,0x00, +0xff,0xff,0xa7,0x24,0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,0x17,0x00,0x49,0x11, +0xff,0x00,0x6a,0x30,0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,0x2b,0x10,0xab,0x00, +0xf6,0xff,0x40,0x10,0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,0x08,0x00,0x40,0x10, +0x21,0x20,0x00,0x01,0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,0x04,0x00,0x40,0x14, +0x21,0x20,0x00,0x00,0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,0xff,0x00,0x44,0x30, +0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,0x21,0x20,0x00,0x00, +0x23,0x10,0x09,0x01,0x36,0x4a,0x00,0x08,0xff,0x00,0x44,0x30,0x21,0x20,0x00,0x01, +0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xd8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c, +0x18,0x00,0xb2,0xaf,0xff,0xff,0x03,0x3c,0x38,0x15,0x52,0x24,0x1c,0x00,0xb3,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x20,0x00,0xbf,0xaf,0xff,0x1f,0x73,0x34, +0x21,0x88,0x00,0x00,0x21,0x80,0x40,0x02,0x63,0x49,0x00,0x0c,0x21,0x20,0x20,0x02, +0x90,0x11,0x02,0x8e,0x21,0x28,0x00,0x00,0x24,0x10,0x53,0x00,0x00,0x20,0x42,0x34, +0x90,0x11,0x02,0xae,0x92,0x11,0x03,0x92,0x00,0x00,0x00,0x00,0x80,0x18,0x03,0x00, +0x21,0x18,0x72,0x00,0xf8,0x04,0x64,0x8c,0x6c,0x05,0x62,0x8c,0x00,0x00,0x00,0x00, +0x21,0x10,0x44,0x00,0x42,0x10,0x02,0x00,0x5c,0x11,0x02,0xae,0x21,0x10,0x05,0x02, +0x01,0x00,0xa5,0x24,0x1d,0x00,0xa3,0x28,0xce,0x11,0x40,0xa0,0x94,0x11,0x40,0xa0, +0xfa,0xff,0x60,0x14,0xb1,0x11,0x40,0xa0,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a, +0xec,0x11,0x00,0xae,0xe4,0xff,0x40,0x14,0x94,0x00,0x10,0x26,0x20,0x00,0xbf,0x8f, +0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xc0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c, +0x2c,0x00,0xb5,0xaf,0x38,0x15,0x46,0x24,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf, +0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf, +0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x08,0x26,0xc2,0x8c, +0xff,0x00,0x03,0x24,0xff,0x00,0x8d,0x30,0xff,0xff,0x42,0x38,0x0b,0x18,0x02,0x00, +0xff,0xff,0x04,0x34,0x10,0x00,0xa3,0xaf,0x08,0x26,0xc4,0xac,0xb9,0x00,0xa0,0x11, +0x08,0x00,0x15,0x24,0x02,0x80,0x02,0x3c,0x48,0x8d,0x45,0x24,0x94,0x04,0xc4,0x24, +0x91,0x4a,0x00,0x08,0x21,0x88,0x00,0x00,0x01,0x00,0x31,0x26,0x00,0x00,0x82,0xa0, +0x1d,0x00,0x22,0x2a,0x0b,0x00,0x40,0x10,0x01,0x00,0x84,0x24,0x21,0x10,0x25,0x02, +0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00,0xf7,0xff,0x40,0x10,0xfd,0xff,0x43,0x24, +0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0,0xf7,0xff,0x40,0x14, +0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,0x38,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c, +0x02,0x80,0x02,0x3c,0xe0,0x8a,0x6c,0x24,0x68,0x8a,0x4b,0x24,0x21,0x88,0x00,0x00, +0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,0x21,0x38,0x2c,0x01, +0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01, +0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc9,0x03,0x64,0xa0,0xf8,0xff,0x40,0x14, +0x38,0x03,0x65,0xa0,0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90, +0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x77,0x04,0x64,0xa0, +0x5a,0x04,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,0xaf,0x00,0xa0,0x11, +0x02,0x80,0x02,0x3c,0x38,0x15,0x48,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c, +0xdc,0x8d,0x69,0x24,0x68,0x8d,0x47,0x24,0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00, +0x21,0x10,0x69,0x00,0x21,0x20,0x67,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c, +0x01,0x00,0x31,0x26,0x21,0x18,0x68,0x00,0x04,0x00,0x22,0x2a,0xf8,0x04,0x65,0xac, +0xf6,0xff,0x40,0x14,0x6c,0x05,0x66,0xac,0x02,0x80,0x02,0x3c,0x38,0x15,0x49,0x24, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xdc,0x8d,0x68,0x24,0x68,0x8d,0x47,0x24, +0x04,0x00,0x11,0x24,0x80,0x20,0x11,0x00,0x21,0x10,0x88,0x00,0x21,0x30,0x87,0x00, +0x00,0x00,0x45,0x8c,0x00,0x00,0xc3,0x8c,0x01,0x00,0x31,0x26,0x21,0x20,0x89,0x00, +0x82,0x28,0x05,0x00,0x82,0x18,0x03,0x00,0x1d,0x00,0x22,0x2a,0xf8,0x04,0x83,0xac, +0xf4,0xff,0x40,0x14,0x6c,0x05,0x85,0xac,0x02,0x80,0x02,0x3c,0x38,0x15,0x56,0x24, +0xff,0xff,0x02,0x3c,0x21,0xf0,0xc0,0x02,0xff,0x1f,0x57,0x34,0x21,0x88,0x00,0x00, +0x21,0xa0,0x00,0x00,0xee,0x4a,0x00,0x08,0x21,0x90,0xc0,0x02,0x01,0x00,0x31,0x26, +0x20,0x00,0x22,0x2a,0x94,0x00,0x52,0x26,0x3d,0x00,0x40,0x10,0x94,0x00,0x94,0x26, +0x90,0x11,0x44,0x8e,0x01,0x00,0x03,0x24,0x02,0x13,0x04,0x00,0x01,0x00,0x53,0x30, +0xf6,0xff,0x63,0x16,0x07,0x00,0x82,0x30,0x25,0xb0,0x03,0x3c,0x80,0x10,0x02,0x00, +0x21,0x10,0x43,0x00,0x84,0x01,0x45,0x8c,0x88,0x11,0x43,0x8e,0x21,0x20,0x20,0x02, +0x24,0x28,0xa3,0x00,0x88,0x1d,0x00,0x0c,0x8c,0x11,0x45,0xae,0x92,0x11,0x44,0x92, +0x57,0x1d,0x00,0x0c,0xff,0x00,0x25,0x32,0x90,0x11,0x42,0x8e,0x00,0x00,0x00,0x00, +0x24,0x10,0x57,0x00,0x00,0x20,0x42,0x34,0x90,0x11,0x42,0xae,0x92,0x11,0x50,0x92, +0x00,0x00,0x00,0x00,0x21,0x20,0x00,0x02,0x78,0x1d,0x00,0x0c,0x80,0x80,0x10,0x00, +0x21,0x80,0x16,0x02,0x60,0x11,0x40,0xae,0x64,0x11,0x40,0xae,0x68,0x11,0x40,0xae, +0x6c,0x11,0x40,0xae,0x70,0x11,0x40,0xae,0x74,0x11,0x40,0xae,0x78,0x11,0x40,0xae, +0x7c,0x11,0x40,0xae,0xf8,0x04,0x04,0x8e,0x6c,0x05,0x03,0x8e,0x26,0x10,0x53,0x00, +0x21,0x30,0x00,0x00,0x21,0x18,0x64,0x00,0x42,0x18,0x03,0x00,0x04,0x00,0x04,0x24, +0x0a,0xa8,0x82,0x00,0x5c,0x11,0x43,0xae,0x21,0x20,0x9e,0x02,0x21,0x10,0x86,0x00, +0x01,0x00,0xc6,0x24,0x1d,0x00,0xc3,0x28,0xce,0x11,0x40,0xa0,0x94,0x11,0x40,0xa0, +0xfa,0xff,0x60,0x14,0xb1,0x11,0x40,0xa0,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a, +0xec,0x11,0x80,0xac,0x94,0x00,0x52,0x26,0xc5,0xff,0x40,0x14,0x94,0x00,0x94,0x26, +0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x00,0x00,0x55,0xa0,0x10,0x00,0xa3,0x8f, +0x00,0x00,0x00,0x00,0x03,0x00,0x60,0x14,0x02,0x80,0x03,0x3c,0x38,0x15,0x62,0x24, +0x08,0x26,0x40,0xac,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x40,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0x48,0x8d,0x45,0x24,0x94,0x04,0xc4,0x24, +0x21,0x88,0x00,0x00,0x21,0x10,0x25,0x02,0x00,0x00,0x43,0x90,0x01,0x00,0x31,0x26, +0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0,0xfa,0xff,0x40,0x14,0x01,0x00,0x84,0x24, +0x02,0x80,0x02,0x3c,0x38,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c, +0x04,0x8c,0x6c,0x24,0xa4,0x8a,0x4b,0x24,0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00, +0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,0x21,0x38,0x2c,0x01,0x21,0x10,0xe6,0x00, +0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24, +0x05,0x00,0xc2,0x28,0xc9,0x03,0x64,0xa0,0xf8,0xff,0x40,0x14,0x38,0x03,0x65,0xa0, +0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02, +0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x77,0x04,0x64,0xa0,0x5a,0x04,0x65,0xa0, +0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,0x02,0x80,0x02,0x3c,0x38,0x15,0x49,0x24, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xdc,0x8d,0x68,0x24,0x68,0x8d,0x47,0x24, +0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x10,0x68,0x00,0x21,0x20,0x67,0x00, +0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,0x21,0x18,0x69,0x00, +0x1d,0x00,0x22,0x2a,0xf8,0x04,0x65,0xac,0xf6,0xff,0x40,0x14,0x6c,0x05,0x66,0xac, +0xe1,0x4a,0x00,0x08,0x02,0x80,0x02,0x3c,0xd8,0xff,0xbd,0x27,0xff,0xff,0x84,0x30, +0x18,0x00,0xb2,0xaf,0xf0,0x01,0x92,0x30,0x02,0x91,0x12,0x00,0x14,0x00,0xb1,0xaf, +0xc0,0x88,0x12,0x00,0x21,0x88,0x32,0x02,0x80,0x88,0x11,0x00,0x21,0x88,0x32,0x02, +0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0x80,0x88,0x11,0x00,0x21,0x88,0x22,0x02, +0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x10,0x00,0xb0,0xaf,0x90,0x11,0x30,0x8e, +0x00,0x02,0x83,0x30,0xff,0xfe,0x02,0x24,0x2b,0x18,0x03,0x00,0x00,0x10,0x10,0x36, +0x24,0x80,0x02,0x02,0x00,0x1a,0x03,0x00,0x00,0x04,0x82,0x30,0x25,0x80,0x03,0x02, +0x2b,0x10,0x02,0x00,0xf7,0xff,0x03,0x24,0x24,0x80,0x03,0x02,0xc0,0x10,0x02,0x00, +0x25,0x80,0x02,0x02,0x88,0x11,0x25,0xae,0x90,0x11,0x30,0xae,0xe5,0x1d,0x00,0x0c, +0x21,0x98,0xa0,0x00,0xf8,0xff,0x03,0x24,0x24,0x80,0x03,0x02,0x07,0x00,0x42,0x30, +0x25,0x80,0x02,0x02,0x07,0x00,0x03,0x32,0x25,0xb0,0x02,0x3c,0x80,0x18,0x03,0x00, +0x90,0x11,0x30,0xae,0x21,0x18,0x62,0x00,0x84,0x01,0x62,0x8c,0x21,0x20,0x40,0x02, +0x24,0x10,0x53,0x00,0x88,0x1d,0x00,0x0c,0x8c,0x11,0x22,0xae,0x92,0x11,0x24,0x92, +0x21,0x28,0x40,0x02,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x57,0x1d,0x00,0x08,0x28,0x00,0xbd,0x27, +0x63,0x49,0x00,0x08,0xff,0x00,0x84,0x30,0x02,0x80,0x02,0x3c,0x38,0x15,0x43,0x24, +0x1f,0x00,0x04,0x24,0x90,0x11,0x62,0x8c,0xff,0xff,0x84,0x24,0x00,0x10,0x42,0x34, +0x90,0x11,0x62,0xac,0xfb,0xff,0x81,0x04,0x94,0x00,0x63,0x24,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x23,0x10,0xa4,0x00,0x2b,0x18,0xa4,0x00, +0x23,0x20,0x85,0x00,0x08,0x00,0xe0,0x03,0x0b,0x10,0x83,0x00,0x20,0xff,0xbd,0x27, +0xcc,0x00,0xb5,0xaf,0xdc,0x00,0xbf,0xaf,0xd8,0x00,0xbe,0xaf,0xd4,0x00,0xb7,0xaf, +0xd0,0x00,0xb6,0xaf,0xc8,0x00,0xb4,0xaf,0xc4,0x00,0xb3,0xaf,0xc0,0x00,0xb2,0xaf, +0xbc,0x00,0xb1,0xaf,0xb8,0x00,0xb0,0xaf,0x21,0xa8,0x00,0x00,0x40,0x11,0x15,0x00, +0x10,0x00,0xa3,0x27,0x21,0x10,0x43,0x00,0x07,0x00,0x16,0x24,0xff,0xff,0xd6,0x26, +0x00,0x00,0x40,0xac,0xfd,0xff,0xc1,0x06,0x04,0x00,0x42,0x24,0x01,0x00,0xb5,0x26, +0x03,0x00,0xa2,0x2e,0xf6,0xff,0x40,0x14,0x40,0x11,0x15,0x00,0x25,0xb0,0x10,0x3c, +0xc4,0x02,0x02,0x36,0x00,0x00,0x40,0xac,0x04,0x00,0x03,0x36,0x00,0x00,0x62,0x8c, +0x04,0x0c,0x03,0x36,0x00,0x00,0x63,0x8c,0x08,0x0c,0x04,0x36,0x0f,0x00,0x11,0x3c, +0xac,0x00,0xa3,0xaf,0x00,0x00,0x84,0x8c,0x24,0x10,0x51,0x00,0x02,0xf4,0x02,0x00, +0xb0,0x00,0xa4,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36, +0x70,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x74,0x00,0xa2,0xaf, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x21,0x1a,0x00,0x0c, +0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0xe0,0x0e,0x02,0x36, +0x21,0x20,0x40,0x00,0x00,0x00,0x42,0x8c,0xdc,0x0e,0x12,0x36,0x70,0x0e,0x13,0x36, +0x78,0x00,0xa2,0xaf,0x00,0x00,0x42,0x8e,0x74,0x0e,0x14,0x36,0x78,0x0e,0x15,0x36, +0x7c,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8e,0x7c,0x0e,0x16,0x36,0x80,0x0e,0x17,0x36, +0x80,0x00,0xa3,0xaf,0x00,0x00,0x82,0x8e,0xd4,0x0e,0x10,0x36,0xed,0x3f,0x11,0x3c, +0x84,0x00,0xa2,0xaf,0x00,0x00,0xa3,0x8e,0xfb,0x92,0x25,0x36,0x88,0x00,0xa3,0xaf, +0x00,0x00,0xc2,0x8e,0x00,0x00,0x00,0x00,0x8c,0x00,0xa2,0xaf,0x00,0x00,0xe3,0x8e, +0x25,0xb0,0x02,0x3c,0x84,0x0e,0x42,0x34,0x90,0x00,0xa3,0xaf,0x00,0x00,0x42,0x8c, +0x25,0xb0,0x03,0x3c,0x88,0x0e,0x63,0x34,0x94,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8c, +0x25,0xb0,0x02,0x3c,0x8c,0x0e,0x42,0x34,0x98,0x00,0xa3,0xaf,0x00,0x00,0x42,0x8c, +0x25,0xb0,0x03,0x3c,0xd0,0x0e,0x63,0x34,0x9c,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8c, +0x00,0x00,0x00,0x00,0xa0,0x00,0xa3,0xaf,0x00,0x00,0x02,0x8e,0x25,0xb0,0x03,0x3c, +0xd8,0x0e,0x63,0x34,0xa4,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8c,0xc3,0x4b,0x00,0x0c, +0xa8,0x00,0xa3,0xaf,0x21,0x20,0x40,0x02,0xc3,0x4b,0x00,0x0c,0xfb,0x92,0x25,0x36, +0x21,0x20,0x60,0x02,0xc3,0x4b,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0x80,0x02, +0xc3,0x4b,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0xa0,0x02,0xc3,0x4b,0x00,0x0c, +0xfb,0x92,0x25,0x36,0x21,0x20,0xc0,0x02,0xc3,0x4b,0x00,0x0c,0xfb,0x92,0x25,0x36, +0x21,0x20,0xe0,0x02,0xc3,0x4b,0x00,0x0c,0xfb,0x92,0x25,0x36,0x02,0x80,0x02,0x3c, +0xdc,0x8e,0x42,0x24,0x00,0x00,0x44,0x8c,0xfb,0x92,0x25,0x36,0xc3,0x4b,0x00,0x0c, +0x25,0xb0,0x13,0x3c,0x02,0x80,0x03,0x3c,0xe0,0x8e,0x63,0x24,0x00,0x00,0x64,0x8c, +0xfb,0x92,0x25,0x36,0xc3,0x4b,0x00,0x0c,0x21,0xb0,0x00,0x00,0x02,0x80,0x02,0x3c, +0xe4,0x8e,0x42,0x24,0x00,0x00,0x44,0x8c,0xfb,0x92,0x25,0x36,0xc3,0x4b,0x00,0x0c, +0xff,0x03,0x14,0x3c,0x02,0x80,0x03,0x3c,0xe8,0x8e,0x63,0x24,0x00,0x00,0x64,0x8c, +0xfb,0x92,0x25,0x36,0xc3,0x4b,0x00,0x0c,0x10,0x00,0xb7,0x27,0x21,0x20,0x00,0x02, +0xc3,0x4b,0x00,0x0c,0xfb,0x92,0x25,0x36,0x02,0x80,0x02,0x3c,0xec,0x8e,0x42,0x24, +0x00,0x00,0x44,0x8c,0xc3,0x4b,0x00,0x0c,0xfb,0x92,0x25,0x36,0xaf,0x4c,0x00,0x08, +0x21,0xa8,0x00,0x00,0x6e,0x00,0xc2,0x13,0x02,0x80,0x02,0x3c,0xac,0x0e,0x62,0x36, +0x94,0x0e,0x63,0x36,0x00,0x00,0x48,0x8c,0x00,0x00,0x64,0x8c,0xb4,0x0e,0x62,0x36, +0x9c,0x0e,0x63,0x36,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,0x25,0xb0,0x03,0x3c, +0xbc,0x0e,0x63,0x34,0x00,0x00,0x67,0x8c,0x24,0x20,0x94,0x00,0x00,0xd8,0x02,0x3c, +0x24,0x10,0x02,0x01,0x24,0x28,0xb4,0x00,0x24,0x30,0xd4,0x00,0x24,0x38,0xf4,0x00, +0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c,0x02,0x2c,0x05,0x00, +0x02,0x34,0x06,0x00,0xe8,0x00,0x83,0x10,0x02,0x3c,0x07,0x00,0xe6,0x00,0xa3,0x10, +0x20,0x00,0x03,0x24,0xe4,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0xe2,0x00,0xe3,0x10, +0x01,0x00,0x08,0x24,0x80,0x00,0x03,0x24,0x08,0x00,0x83,0x10,0x21,0x20,0x00,0x00, +0x06,0x00,0xa3,0x10,0x21,0x20,0x00,0x00,0xe0,0x03,0x03,0x24,0x03,0x00,0xc3,0x10, +0x00,0x00,0x00,0x00,0xdb,0x00,0xe3,0x10,0x01,0x00,0x04,0x24,0x05,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0xd7,0x00,0x80,0x14, +0x94,0x0e,0x63,0x36,0x01,0x00,0xb5,0x26,0x0a,0x00,0xa2,0x2e,0x01,0x01,0x40,0x10, +0x00,0x00,0x00,0x00,0xcb,0xff,0xc0,0x17,0x01,0x00,0x02,0x24,0xa0,0x00,0x03,0x3c, +0x30,0x54,0x65,0x34,0xc3,0x4b,0x00,0x0c,0x04,0x0c,0x64,0x36,0x08,0x00,0x05,0x3c, +0xe4,0x00,0xa5,0x34,0xc3,0x4b,0x00,0x0c,0x08,0x0c,0x64,0x36,0x28,0x0e,0x64,0x36, +0xc3,0x4b,0x00,0x0c,0x80,0x80,0x05,0x3c,0x14,0x02,0x02,0x3c,0x48,0x01,0x45,0x34, +0xc3,0x4b,0x00,0x0c,0x40,0x0e,0x64,0x36,0x16,0x68,0x05,0x3c,0xa2,0x04,0xa5,0x34, +0xc3,0x4b,0x00,0x0c,0x44,0x0e,0x64,0x36,0x4c,0x0e,0x64,0x36,0xc3,0x4b,0x00,0x0c, +0xd1,0x28,0x05,0x24,0x14,0x02,0x03,0x3c,0x4d,0x01,0x65,0x34,0xc3,0x4b,0x00,0x0c, +0x60,0x0e,0x64,0x36,0x16,0x28,0x05,0x3c,0xba,0x08,0xa5,0x34,0xc3,0x4b,0x00,0x0c, +0x64,0x0e,0x64,0x36,0x6c,0x0e,0x64,0x36,0xc3,0x4b,0x00,0x0c,0xd1,0x28,0x05,0x24, +0x00,0xfb,0x05,0x3c,0x01,0x00,0xa5,0x34,0xc3,0x4b,0x00,0x0c,0x48,0x0e,0x64,0x36, +0x00,0xf8,0x05,0x3c,0x01,0x00,0xa5,0x34,0xc3,0x4b,0x00,0x0c,0x48,0x0e,0x64,0x36, +0xf2,0x19,0x00,0x0c,0x03,0x00,0x04,0x24,0xa0,0x00,0x02,0x3c,0x33,0x54,0x45,0x34, +0xc3,0x4b,0x00,0x0c,0x04,0x0c,0x64,0x36,0x08,0x0c,0x64,0x36,0xc3,0x4b,0x00,0x0c, +0xe4,0x00,0x05,0x24,0x28,0x0e,0x64,0x36,0xc3,0x4b,0x00,0x0c,0x21,0x28,0x00,0x00, +0x01,0x00,0x02,0x24,0x96,0xff,0xc2,0x17,0xac,0x0e,0x62,0x36,0x02,0x80,0x02,0x3c, +0xf0,0x8e,0x42,0x24,0x25,0xb0,0x03,0x3c,0x00,0x00,0x44,0x8c,0x20,0x08,0x63,0x34, +0x00,0x00,0x71,0x8c,0x00,0x01,0x03,0x3c,0x00,0x01,0x65,0x34,0xc3,0x4b,0x00,0x0c, +0x25,0xb0,0x12,0x3c,0x00,0x01,0x02,0x3c,0x00,0x01,0x45,0x34,0xc3,0x4b,0x00,0x0c, +0x28,0x08,0x44,0x36,0xa0,0x00,0x03,0x3c,0x30,0x54,0x65,0x34,0xc3,0x4b,0x00,0x0c, +0x04,0x0c,0x44,0x36,0x08,0x00,0x05,0x3c,0xe4,0x00,0xa5,0x34,0xc3,0x4b,0x00,0x0c, +0x08,0x0c,0x44,0x36,0x28,0x0e,0x44,0x36,0xc3,0x4b,0x00,0x0c,0x80,0x80,0x05,0x3c, +0x00,0x01,0x02,0x3c,0x00,0x7c,0x45,0x34,0xc3,0x4b,0x00,0x0c,0x30,0x0e,0x44,0x36, +0x00,0x01,0x03,0x3c,0x00,0x48,0x65,0x34,0xc3,0x4b,0x00,0x0c,0x34,0x0e,0x44,0x36, +0x00,0x10,0x02,0x3c,0x1f,0xdc,0x45,0x34,0xc3,0x4b,0x00,0x0c,0x38,0x0e,0x44,0x36, +0x00,0x10,0x03,0x3c,0x1f,0x8c,0x65,0x34,0xc3,0x4b,0x00,0x0c,0x3c,0x0e,0x44,0x36, +0x14,0x02,0x02,0x3c,0x02,0x01,0x45,0x34,0xc3,0x4b,0x00,0x0c,0x40,0x0e,0x44,0x36, +0x16,0x68,0x05,0x3c,0xc7,0x04,0xa5,0x34,0xc3,0x4b,0x00,0x0c,0x44,0x0e,0x44,0x36, +0x4c,0x0e,0x44,0x36,0xc3,0x4b,0x00,0x0c,0xd1,0x28,0x05,0x24,0x6c,0x0e,0x44,0x36, +0xc3,0x4b,0x00,0x0c,0xd1,0x28,0x05,0x24,0x00,0x01,0x03,0x3c,0x00,0x7c,0x65,0x34, +0xc3,0x4b,0x00,0x0c,0x50,0x0e,0x44,0x36,0x00,0x01,0x02,0x3c,0x00,0x48,0x45,0x34, +0xc3,0x4b,0x00,0x0c,0x54,0x0e,0x44,0x36,0x00,0x10,0x03,0x3c,0x23,0xdc,0x65,0x34, +0xc3,0x4b,0x00,0x0c,0x58,0x0e,0x44,0x36,0x00,0x10,0x02,0x3c,0x23,0x8c,0x45,0x34, +0xc3,0x4b,0x00,0x0c,0x5c,0x0e,0x44,0x36,0x14,0x02,0x03,0x3c,0x02,0x01,0x65,0x34, +0xc3,0x4b,0x00,0x0c,0x60,0x0e,0x44,0x36,0x16,0x28,0x05,0x3c,0x07,0x0d,0xa5,0x34, +0xc3,0x4b,0x00,0x0c,0x64,0x0e,0x44,0x36,0x48,0x0e,0x44,0x36,0xc3,0x4b,0x00,0x0c, +0x00,0xfb,0x05,0x3c,0x00,0xf8,0x05,0x3c,0xc3,0x4b,0x00,0x0c,0x48,0x0e,0x44,0x36, +0x00,0x02,0x10,0x3c,0xf2,0x19,0x00,0x0c,0x03,0x00,0x04,0x24,0x4c,0x0e,0x44,0x36, +0xc3,0x4b,0x00,0x0c,0xd1,0x28,0x05,0x36,0xd1,0x28,0x05,0x36,0xc3,0x4b,0x00,0x0c, +0x6c,0x0e,0x44,0x36,0x48,0x0e,0x44,0x36,0xc3,0x4b,0x00,0x0c,0x00,0xfb,0x05,0x3c, +0x00,0xf8,0x05,0x3c,0xc3,0x4b,0x00,0x0c,0x48,0x0e,0x44,0x36,0xf2,0x19,0x00,0x0c, +0x03,0x00,0x04,0x24,0xac,0x00,0xa5,0x8f,0x04,0x0c,0x44,0x36,0xc3,0x4b,0x00,0x0c, +0x00,0x01,0x31,0x32,0xb0,0x00,0xa5,0x8f,0x08,0x0c,0x44,0x36,0xc3,0x4b,0x00,0x0c, +0x2b,0x88,0x11,0x00,0x28,0x0e,0x44,0x36,0xc3,0x4b,0x00,0x0c,0x21,0x28,0x00,0x00, +0x23,0xff,0x20,0x16,0xac,0x0e,0x62,0x36,0x02,0x80,0x02,0x3c,0xf0,0x8e,0x42,0x24, +0x00,0x00,0x44,0x8c,0xc3,0x4b,0x00,0x0c,0x00,0x01,0x05,0x3c,0x28,0x08,0x44,0x36, +0xc3,0x4b,0x00,0x0c,0x00,0x01,0x05,0x3c,0xac,0x0e,0x62,0x36,0x94,0x0e,0x63,0x36, +0x00,0x00,0x48,0x8c,0x00,0x00,0x64,0x8c,0xb4,0x0e,0x62,0x36,0x9c,0x0e,0x63,0x36, +0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,0x25,0xb0,0x03,0x3c,0xbc,0x0e,0x63,0x34, +0x00,0x00,0x67,0x8c,0x24,0x20,0x94,0x00,0x00,0xd8,0x02,0x3c,0x24,0x10,0x02,0x01, +0x24,0x28,0xb4,0x00,0x24,0x30,0xd4,0x00,0x24,0x38,0xf4,0x00,0x02,0x24,0x04,0x00, +0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c,0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00, +0x1a,0xff,0x83,0x14,0x02,0x3c,0x07,0x00,0x80,0x00,0x03,0x24,0x20,0xff,0x83,0x14, +0x21,0x40,0x00,0x00,0xa5,0x4c,0x00,0x08,0x21,0x20,0x00,0x00,0x00,0x00,0x62,0x8c, +0x9c,0x0e,0x65,0x36,0xa4,0x0e,0x66,0x36,0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00, +0x00,0x00,0xe2,0xae,0x00,0x00,0xa4,0x8c,0xac,0x0e,0x67,0x36,0xb4,0x0e,0x65,0x36, +0x24,0x20,0x94,0x00,0x02,0x24,0x04,0x00,0x04,0x00,0xe4,0xae,0x00,0x00,0xc3,0x8c, +0xc4,0x0e,0x64,0x36,0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,0x08,0x00,0xe3,0xae, +0x00,0x00,0xe2,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00, +0x0c,0x00,0xe2,0xae,0x00,0x00,0xa3,0x8c,0x00,0x00,0x00,0x00,0x24,0x18,0x74,0x00, +0x02,0x1c,0x03,0x00,0x10,0x00,0xe3,0xae,0x25,0xb0,0x03,0x3c,0xbc,0x0e,0x63,0x34, +0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00, +0x14,0x00,0xe2,0xae,0x00,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x24,0x18,0x74,0x00, +0x02,0x1c,0x03,0x00,0x18,0x00,0xe3,0xae,0x25,0xb0,0x03,0x3c,0xcc,0x0e,0x63,0x34, +0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00, +0x1c,0x00,0xe2,0xae,0x01,0x00,0xd6,0x26,0x03,0x00,0xc2,0x2e,0xc7,0xfe,0x40,0x14, +0x20,0x00,0xf7,0x26,0x10,0x00,0xb0,0x8f,0x00,0x00,0x00,0x00,0x39,0x01,0x00,0x16, +0x00,0x00,0x00,0x00,0x30,0x00,0xb1,0x8f,0x00,0x00,0x00,0x00,0x06,0x00,0x20,0x16, +0x21,0x20,0x00,0x02,0x50,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00,0x29,0x00,0x40,0x10, +0xff,0x00,0x05,0x24,0x21,0x20,0x00,0x02,0xcc,0x4b,0x00,0x0c,0x21,0x28,0x20,0x02, +0x03,0x00,0x42,0x2c,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x34,0x00,0xa5,0x8f, +0x14,0x00,0xa4,0x8f,0xcc,0x4b,0x00,0x0c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c, +0x1c,0x00,0x40,0x14,0x21,0x28,0x00,0x00,0x50,0x00,0xb2,0x8f,0x21,0x20,0x00,0x02, +0xcc,0x4b,0x00,0x0c,0x21,0x28,0x40,0x02,0x03,0x00,0x42,0x2c,0x09,0x00,0x40,0x10, +0x21,0x20,0x20,0x02,0x54,0x00,0xa5,0x8f,0x14,0x00,0xa4,0x8f,0xcc,0x4b,0x00,0x0c, +0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c,0x0e,0x00,0x40,0x14,0x21,0x28,0x00,0x00, +0x21,0x20,0x20,0x02,0xcc,0x4b,0x00,0x0c,0x21,0x28,0x40,0x02,0x03,0x00,0x42,0x2c, +0xd0,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x54,0x00,0xa5,0x8f,0x34,0x00,0xa4,0x8f, +0xcc,0x4b,0x00,0x0c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c,0xc9,0x00,0x40,0x10, +0x01,0x00,0x05,0x24,0xff,0x00,0x02,0x24,0xcb,0x00,0xa2,0x10,0x25,0xb0,0x03,0x3c, +0x10,0x00,0xa2,0x27,0x40,0x29,0x05,0x00,0x02,0x80,0x0f,0x3c,0x21,0x28,0xa2,0x00, +0x38,0x15,0xec,0x25,0x00,0x00,0xa6,0x8c,0x0c,0x00,0xa7,0x8c,0x0c,0x00,0x83,0x8d, +0x10,0x00,0x84,0x8d,0x04,0x00,0xa8,0x8c,0x10,0x00,0xa9,0x8c,0x00,0xfc,0x02,0x24, +0x08,0x00,0xaa,0x8c,0x14,0x00,0xab,0x8c,0x24,0x20,0x82,0x00,0xff,0x03,0xc6,0x30, +0x24,0x18,0x62,0x00,0xff,0x03,0xe7,0x30,0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34, +0x25,0x18,0x66,0x00,0x25,0x20,0x87,0x00,0xff,0x03,0x08,0x31,0xff,0x03,0x29,0x31, +0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00,0x80,0x42,0x08,0x00,0x80,0x4a,0x09,0x00, +0x0f,0xc0,0x02,0x3c,0x1c,0x00,0xa6,0x8c,0x18,0x00,0xa7,0x8c,0xff,0xff,0x42,0x34, +0x25,0x18,0x68,0x00,0x25,0x20,0x89,0x00,0xff,0x03,0x4a,0x31,0xff,0x03,0x6b,0x31, +0x24,0x20,0x82,0x00,0x00,0x55,0x0a,0x00,0x24,0x18,0x62,0x00,0x00,0x5d,0x0b,0x00, +0x25,0x18,0x6a,0x00,0x25,0x20,0x8b,0x00,0x16,0x00,0x86,0xa5,0x0c,0x00,0x83,0xad, +0x10,0x00,0x84,0xad,0x14,0x00,0x87,0xa5,0x38,0x15,0xf1,0x25,0x10,0x00,0x22,0x8e, +0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,0x4d,0x00,0x43,0x10,0x25,0xb0,0x12,0x3c, +0x0c,0x00,0x23,0x8e,0x80,0x0c,0x44,0x36,0x00,0x00,0x88,0x8c,0x00,0x02,0x62,0x30, +0xc0,0xff,0x13,0x3c,0x82,0x6d,0x08,0x00,0x03,0x00,0x40,0x10,0xff,0x03,0x65,0x30, +0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00,0x18,0x00,0xad,0x00,0x82,0x62,0x03,0x00, +0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31,0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00, +0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30,0x00,0xfc,0x02,0x24,0x25,0x60,0x82,0x01, +0x18,0x00,0x8d,0x01,0x00,0xfc,0x74,0x36,0x24,0x28,0x14,0x01,0x12,0x80,0x00,0x00, +0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00, +0xc3,0x4b,0x00,0x0c,0x25,0x28,0xa6,0x00,0x94,0x0c,0x44,0x36,0x00,0x00,0x85,0x8c, +0xff,0x0f,0x02,0x3c,0xff,0xff,0x55,0x34,0xc0,0x03,0x10,0x32,0x24,0x28,0xb5,0x00, +0x80,0x85,0x10,0x00,0xc3,0x4b,0x00,0x0c,0x25,0x28,0xb0,0x00,0x10,0x00,0x2c,0x8e, +0x88,0x0c,0x44,0x36,0x00,0x00,0x88,0x8c,0x82,0x2a,0x0c,0x00,0xff,0x03,0xa5,0x30, +0x24,0x10,0x13,0x01,0x00,0x02,0xa3,0x30,0x03,0x00,0x60,0x10,0x82,0x6d,0x02,0x00, +0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00,0x18,0x00,0xad,0x00,0x02,0x65,0x0c,0x00, +0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31,0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00, +0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30,0x00,0xfc,0x02,0x24,0x25,0x60,0x82,0x01, +0x18,0x00,0x8d,0x01,0x24,0x28,0x14,0x01,0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00, +0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,0xc3,0x4b,0x00,0x0c, +0x25,0x28,0xa6,0x00,0x9c,0x0c,0x44,0x36,0x00,0x00,0x85,0x8c,0xc0,0x03,0x10,0x32, +0x80,0x85,0x10,0x00,0x24,0x28,0xb5,0x00,0xc3,0x4b,0x00,0x0c,0x25,0x28,0xb0,0x00, +0x78,0x00,0xa5,0x8f,0x25,0xb0,0x10,0x3c,0xc3,0x4b,0x00,0x0c,0xe0,0x0e,0x04,0x36, +0x7c,0x00,0xa5,0x8f,0xc3,0x4b,0x00,0x0c,0xdc,0x0e,0x04,0x36,0x80,0x00,0xa5,0x8f, +0xc3,0x4b,0x00,0x0c,0x70,0x0e,0x04,0x36,0x84,0x00,0xa5,0x8f,0xc3,0x4b,0x00,0x0c, +0x74,0x0e,0x04,0x36,0x88,0x00,0xa5,0x8f,0xc3,0x4b,0x00,0x0c,0x78,0x0e,0x04,0x36, +0x8c,0x00,0xa5,0x8f,0xc3,0x4b,0x00,0x0c,0x7c,0x0e,0x04,0x36,0x90,0x00,0xa5,0x8f, +0xc3,0x4b,0x00,0x0c,0x80,0x0e,0x04,0x36,0x94,0x00,0xa5,0x8f,0xc3,0x4b,0x00,0x0c, +0x84,0x0e,0x04,0x36,0x98,0x00,0xa5,0x8f,0xc3,0x4b,0x00,0x0c,0x88,0x0e,0x04,0x36, +0x9c,0x00,0xa5,0x8f,0xc3,0x4b,0x00,0x0c,0x8c,0x0e,0x04,0x36,0xa0,0x00,0xa5,0x8f, +0xc3,0x4b,0x00,0x0c,0xd0,0x0e,0x04,0x36,0xa4,0x00,0xa5,0x8f,0xc3,0x4b,0x00,0x0c, +0xd4,0x0e,0x04,0x36,0xa8,0x00,0xa5,0x8f,0x88,0x0e,0x04,0x36,0xc3,0x4b,0x00,0x0c, +0x0f,0x00,0x10,0x3c,0x70,0x00,0xa6,0x8f,0xff,0xff,0x05,0x36,0x6a,0x44,0x00,0x0c, +0x21,0x20,0x00,0x00,0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c, +0x01,0x00,0x04,0x24,0x74,0x00,0xa6,0x8f,0xff,0xff,0x05,0x36,0x6a,0x44,0x00,0x0c, +0x21,0x20,0x00,0x00,0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c, +0x21,0x20,0x00,0x00,0xdc,0x00,0xbf,0x8f,0xd8,0x00,0xbe,0x8f,0xd4,0x00,0xb7,0x8f, +0xd0,0x00,0xb6,0x8f,0xcc,0x00,0xb5,0x8f,0xc8,0x00,0xb4,0x8f,0xc4,0x00,0xb3,0x8f, +0xc0,0x00,0xb2,0x8f,0xbc,0x00,0xb1,0x8f,0xb8,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0xe0,0x00,0xbd,0x27,0xff,0x00,0x05,0x24,0xff,0x00,0x02,0x24,0x39,0xff,0xa2,0x14, +0x10,0x00,0xa2,0x27,0x25,0xb0,0x03,0x3c,0x94,0x0e,0x62,0x34,0x9c,0x0e,0x64,0x34, +0xa4,0x0e,0x65,0x34,0xac,0x0e,0x66,0x34,0x02,0x80,0x0f,0x3c,0x00,0x00,0x49,0x8c, +0x38,0x15,0xed,0x25,0x00,0x00,0x8c,0x8c,0x00,0x00,0xae,0x8c,0x00,0x00,0xc7,0x8c, +0xb4,0x0e,0x62,0x34,0x0c,0x00,0xa4,0x8d,0x10,0x00,0xa5,0x8d,0x00,0x00,0x4a,0x8c, +0xff,0x03,0x06,0x3c,0x00,0xfc,0x08,0x24,0xbc,0x0e,0x62,0x34,0x24,0x48,0x26,0x01, +0x24,0x38,0xe6,0x00,0x00,0x00,0x4b,0x8c,0x24,0x28,0xa8,0x00,0x24,0x20,0x88,0x00, +0x02,0x3c,0x07,0x00,0xcc,0x0e,0x68,0x34,0x02,0x4c,0x09,0x00,0xc4,0x0e,0x63,0x34, +0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x28,0xa7,0x00,0x25,0x20,0x89,0x00, +0x00,0x00,0x67,0x8c,0x24,0x60,0x86,0x01,0x00,0x00,0x03,0x8d,0x24,0x50,0x46,0x01, +0x24,0x28,0xa2,0x00,0x24,0x20,0x82,0x00,0x82,0x61,0x0c,0x00,0x82,0x51,0x0a,0x00, +0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,0x25,0x20,0x8c,0x00,0x25,0x28,0xaa,0x00, +0x24,0x70,0xc6,0x01,0x24,0x58,0x66,0x01,0x24,0x28,0xa2,0x00,0x24,0x18,0x66,0x00, +0x00,0x71,0x0e,0x00,0x24,0x20,0x82,0x00,0x00,0x59,0x0b,0x00,0x24,0x38,0xe6,0x00, +0x25,0x20,0x8e,0x00,0x25,0x28,0xab,0x00,0x02,0x3c,0x07,0x00,0x02,0x1c,0x03,0x00, +0x16,0x00,0xa3,0xa5,0x0c,0x00,0xa4,0xad,0x10,0x00,0xa5,0xad,0x18,0x4e,0x00,0x08, +0x14,0x00,0xa7,0xa5,0x30,0x00,0xb1,0x8f,0xc0,0x4d,0x00,0x08,0x21,0x20,0x00,0x02, +0xe0,0xff,0xbd,0x27,0x44,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,0x49,0x00,0x03,0x24, +0x47,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x74,0x94,0xe7,0x24,0x11,0x00,0xa3,0xa3, +0x12,0x00,0xa2,0xa3,0x10,0x27,0x03,0x24,0x01,0x00,0x02,0x24,0x01,0x80,0x06,0x3c, +0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xdc,0x3e,0xc6,0x24,0x0c,0x00,0xe3,0xac, +0x14,0x00,0xe2,0xa0,0x18,0x00,0xbf,0xaf,0xe1,0x1c,0x00,0x0c,0x13,0x00,0xa0,0xa3, +0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0xd0,0xff,0xbd,0x27,0x25,0xb0,0x03,0x3c,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf, +0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,0x18,0x00,0xb2,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x03,0x0d,0x64,0x34,0x00,0x00,0x82,0x90, +0x00,0x00,0x00,0x00,0xff,0x00,0x54,0x30,0x70,0x00,0x93,0x32,0x63,0x00,0x60,0x12, +0x42,0x00,0x63,0x34,0x8f,0x00,0x82,0x32,0x00,0x00,0x82,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x5b,0x00,0x60,0x12,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c, +0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0xa8,0x40,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x21,0x1a,0x00,0x0c, +0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00, +0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0xb0,0x40,0x00,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x64,0x00,0x04,0x24,0x21,0x1a,0x00,0x0c, +0x08,0x00,0x10,0x3c,0xff,0xff,0x10,0x36,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00, +0x01,0x00,0x12,0x3c,0x24,0x30,0xb0,0x02,0x25,0x30,0xd2,0x00,0xff,0xff,0x25,0x36, +0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24, +0x24,0x80,0xd0,0x02,0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x25,0x30,0x12,0x02, +0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0x21,0x1a,0x00,0x0c, +0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c, +0x18,0x00,0x04,0x24,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x21,0x1a,0x00,0x0c, +0x64,0x00,0x04,0x24,0x18,0x00,0x04,0x24,0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c, +0x00,0x80,0x06,0x36,0xf2,0x19,0x00,0x0c,0x03,0x00,0x04,0x24,0x27,0x00,0x60,0x16, +0x25,0xb0,0x02,0x3c,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f, +0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,0x42,0x00,0x42,0x34,0x30,0x00,0xbd,0x27, +0x00,0x00,0x40,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x24, +0x00,0x00,0x62,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x18,0x00,0x04,0x24,0x95,0x44,0x00,0x0c, +0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24,0x18,0x00,0x04,0x24, +0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c,0x00,0x80,0x06,0x36,0xf2,0x19,0x00,0x0c, +0x03,0x00,0x04,0x24,0xdb,0xff,0x60,0x12,0x25,0xb0,0x02,0x3c,0x03,0x0d,0x42,0x34, +0x00,0x00,0x54,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x0f,0x00,0x10,0x3c, +0x21,0x30,0xa0,0x02,0xff,0xff,0x05,0x36,0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00, +0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24, +0xff,0xff,0x05,0x36,0x21,0x30,0xc0,0x02,0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00, +0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f, +0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x20,0x00,0x00,0x2a,0x42,0x00,0x08, +0x30,0x00,0xbd,0x27,0xc0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,0x02,0x80,0x14,0x3c, +0x30,0x00,0xb6,0xaf,0x38,0x15,0x85,0x26,0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf, +0x2c,0x00,0xb5,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0x0c,0x00,0xa2,0x8c,0xc8,0x02,0xa3,0x90,0x06,0x00,0x16,0x24, +0x82,0x17,0x02,0x00,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14, +0xc8,0x02,0xa3,0xa0,0x08,0x00,0xa2,0x8c,0x01,0x00,0x03,0x24,0x42,0x17,0x02,0x00, +0x03,0x00,0x42,0x30,0x4e,0x01,0x43,0x10,0x25,0xb0,0x02,0x3c,0x38,0x15,0x85,0x26, +0x0c,0x00,0xa2,0x8c,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,0x01,0x00,0x44,0x30, +0x0d,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x08,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00, +0x42,0x17,0x02,0x00,0x03,0x00,0x43,0x30,0xef,0xff,0x64,0x14,0x00,0x00,0x00,0x00, +0x10,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x82,0x17,0x02,0x00,0x60,0x02,0x43,0x10, +0x0f,0x00,0x10,0x3c,0xc7,0x02,0xb3,0x90,0x25,0xb0,0x02,0x3c,0x62,0x0c,0x42,0x34, +0xff,0x00,0x63,0x32,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x90,0x26,0xc6,0x02,0x02,0x92,0x00,0x00,0x00,0x00,0x6f,0x01,0x40,0x10, +0x01,0x00,0x02,0x24,0x25,0xb0,0x11,0x3c,0x03,0x0d,0x23,0x36,0x00,0x00,0x62,0x90, +0x00,0x00,0x00,0x00,0x70,0x00,0x42,0x30,0x95,0x01,0x40,0x14,0xcc,0x00,0x02,0x24, +0xc4,0x02,0x02,0x96,0x00,0x00,0x00,0x00,0x23,0x20,0x53,0x00,0x2b,0x18,0x53,0x00, +0x23,0x10,0x62,0x02,0x0a,0x10,0x83,0x00,0x03,0x00,0x42,0x2c,0x62,0x01,0x40,0x10, +0x00,0x00,0x00,0x00,0xc4,0x02,0x03,0x92,0x63,0x0c,0x22,0x36,0x21,0x20,0x00,0x00, +0x00,0x00,0x43,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x38,0x15,0x83,0x26,0xc3,0x02,0x62,0x90, +0x08,0x00,0x66,0x8c,0xc2,0x02,0x73,0xa0,0x23,0x20,0x53,0x00,0x2b,0x38,0x62,0x02, +0x23,0x90,0x62,0x02,0x02,0x2c,0x06,0x00,0x0b,0x90,0x87,0x00,0x3f,0x00,0xa5,0x30, +0x3f,0x00,0xc4,0x30,0x24,0x00,0x02,0x24,0x20,0x00,0x03,0x24,0x23,0x10,0x44,0x00, +0x7d,0x01,0x40,0x16,0x23,0x18,0x65,0x00,0x21,0x40,0x80,0x00,0x21,0xa8,0xa0,0x00, +0x02,0x80,0x17,0x3c,0x2b,0x28,0xc8,0x02,0xf3,0x01,0xa0,0x10,0x38,0x15,0x82,0x26, +0x80,0x10,0x08,0x00,0x38,0x15,0x83,0x26,0x21,0x10,0x43,0x00,0x18,0x00,0x44,0x8c, +0x00,0x00,0x00,0x00,0x82,0x25,0x04,0x00,0x38,0x15,0x86,0x26,0x0c,0x00,0xc3,0x8c, +0x00,0x00,0x00,0x00,0xff,0x03,0x67,0x30,0x7b,0x01,0xe0,0x10,0x00,0x02,0x62,0x30, +0x04,0x00,0x40,0x10,0x18,0x00,0xe4,0x00,0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00, +0x18,0x00,0xe4,0x00,0x82,0x82,0x03,0x00,0xff,0x03,0x10,0x32,0x00,0x02,0x03,0x32, +0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x45,0x30, +0x00,0xfc,0x02,0x24,0x25,0x80,0x02,0x02,0x18,0x00,0x04,0x02,0x80,0x1d,0x04,0x00, +0x25,0xb0,0x11,0x3c,0x80,0x0c,0x24,0x36,0x94,0x0c,0x31,0x36,0x12,0x80,0x00,0x00, +0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x18,0x62,0x00, +0x25,0x18,0x65,0x00,0x21,0x28,0x60,0x00,0xc3,0x4b,0x00,0x0c,0x10,0x00,0xa3,0xaf, +0x00,0x00,0x23,0x8e,0xff,0x0f,0x02,0x3c,0xc0,0x03,0x10,0x32,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x80,0x85,0x10,0x00,0x25,0x18,0x70,0x00,0x21,0x20,0x20,0x02, +0x21,0x28,0x60,0x00,0x10,0x00,0xa3,0xaf,0xc3,0x4b,0x00,0x0c,0x00,0x00,0x00,0x00, +0x38,0x15,0x83,0x26,0x08,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x59,0x01,0x40,0x04, +0xc0,0x28,0x15,0x00,0x21,0x10,0xa3,0x00,0xac,0x00,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x22,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xad,0x00,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x23,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xae,0x00,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x24,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xaf,0x00,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x25,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb0,0x00,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x26,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb1,0x00,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x27,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb2,0x00,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x28,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb3,0x00,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x29,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0xb6,0x3d,0xe3,0x92,0x22,0x00,0x02,0x24,0x03,0x00,0x62,0x10,0x92,0x00,0x02,0x24, +0x0d,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x38,0x15,0x82,0x26,0x08,0x00,0x43,0x8c, +0x01,0x00,0x44,0x3a,0x24,0x00,0x02,0x24,0x02,0x1a,0x03,0x00,0x3f,0x00,0x63,0x30, +0x01,0x00,0x84,0x30,0x67,0x01,0x80,0x10,0x23,0x28,0x43,0x00,0x42,0x18,0x12,0x00, +0x40,0x10,0x03,0x00,0x21,0x90,0x43,0x00,0x38,0x15,0x83,0x26,0xc3,0x02,0x62,0x90, +0x00,0x00,0x00,0x00,0x2b,0x10,0x62,0x02,0x46,0x01,0x40,0x10,0x2b,0x10,0x45,0x02, +0x06,0x00,0x40,0x10,0x24,0x00,0x06,0x24,0x08,0x00,0x62,0x8c,0x00,0x00,0x00,0x00, +0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x21,0x30,0x52,0x00,0x2b,0x28,0xc6,0x02, +0x46,0x01,0xa0,0x10,0x38,0x15,0x82,0x26,0x80,0x10,0x06,0x00,0x38,0x15,0x83,0x26, +0x21,0x10,0x43,0x00,0x18,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x82,0x25,0x04,0x00, +0x38,0x15,0x83,0x26,0x10,0x00,0x70,0x8c,0x00,0x00,0x00,0x00,0x82,0x3a,0x10,0x00, +0xff,0x03,0xe7,0x30,0x4d,0x01,0xe0,0x10,0x00,0x02,0xe2,0x30,0x04,0x00,0x40,0x10, +0x18,0x00,0xe4,0x00,0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00,0x18,0x00,0xe4,0x00, +0x02,0x85,0x10,0x00,0xff,0x03,0x10,0x32,0x00,0x02,0x03,0x32,0x12,0x10,0x00,0x00, +0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x45,0x30,0x00,0xfc,0x02,0x24, +0x25,0x80,0x02,0x02,0x18,0x00,0x04,0x02,0x80,0x1d,0x04,0x00,0x25,0xb0,0x11,0x3c, +0x88,0x0c,0x24,0x36,0x9c,0x0c,0x31,0x36,0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00, +0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x18,0x62,0x00,0x25,0x18,0x65,0x00, +0x21,0x28,0x60,0x00,0xc3,0x4b,0x00,0x0c,0x10,0x00,0xa3,0xaf,0x00,0x00,0x23,0x8e, +0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0xc0,0x03,0x10,0x32,0x24,0x18,0x62,0x00, +0x80,0x85,0x10,0x00,0x25,0x18,0x70,0x00,0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x00, +0xc3,0x4b,0x00,0x0c,0x10,0x00,0xa3,0xaf,0xd8,0x4f,0x00,0x08,0x00,0x00,0x00,0x00, +0x80,0x0c,0x42,0x34,0x00,0x00,0x43,0x8c,0x21,0x30,0xa0,0x00,0xc0,0xff,0x02,0x3c, +0x24,0x20,0x62,0x00,0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c,0x2b,0x51,0x00,0x08, +0x18,0x00,0xc3,0x24,0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,0x0d,0x00,0x40,0x10, +0x02,0x80,0x17,0x3c,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x45,0x00, +0xf8,0xff,0x44,0x14,0x04,0x00,0x63,0x24,0x08,0x00,0xc2,0x8c,0xc0,0xff,0x03,0x24, +0x3f,0x00,0x24,0x32,0x24,0x10,0x43,0x00,0x25,0x10,0x44,0x00,0x08,0x00,0xc2,0xac, +0x02,0x80,0x17,0x3c,0xb6,0x3d,0xe3,0x92,0x22,0x00,0x02,0x24,0x3a,0x00,0x62,0x10, +0x92,0x00,0x02,0x24,0x39,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0x25,0xb0,0x02,0x3c, +0x24,0x0a,0x42,0x34,0x00,0x00,0x44,0x8c,0x3f,0x3f,0x03,0x3c,0x3f,0x3f,0x63,0x34, +0x24,0x20,0x83,0x00,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0xe6,0x15,0x53,0x24, +0xee,0x16,0x72,0x24,0x21,0x88,0x00,0x00,0x52,0x51,0x00,0x08,0x10,0x00,0xa4,0xaf, +0x95,0x45,0x00,0x0c,0x00,0x00,0x00,0x00,0x43,0x00,0x40,0x10,0x38,0x15,0x85,0x26, +0x01,0x00,0x31,0x26,0x21,0x00,0x22,0x2e,0x17,0x00,0x40,0x10,0x38,0x15,0x82,0x26, +0xc0,0x80,0x11,0x00,0x10,0x00,0xa4,0x27,0x21,0x28,0x13,0x02,0x95,0x45,0x00,0x0c, +0x04,0x00,0x06,0x24,0x21,0x28,0x12,0x02,0x10,0x00,0xa4,0x27,0xf0,0xff,0x40,0x14, +0x04,0x00,0x06,0x24,0x38,0x15,0x85,0x26,0x08,0x00,0xa3,0x8c,0xc0,0xff,0x02,0x3c, +0xff,0xff,0x42,0x34,0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00, +0xff,0x7f,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x08,0x00,0xa3,0xac,0x38,0x15,0x82,0x26,0x0c,0x00,0x43,0x8c,0x00,0x40,0x04,0x3c, +0x25,0x18,0x64,0x00,0xd1,0x4f,0x00,0x08,0x0c,0x00,0x43,0xac,0xc6,0x02,0x02,0xa2, +0xff,0x4f,0x00,0x08,0xc4,0x02,0x13,0xa6,0x0a,0x4f,0x00,0x0c,0x00,0x00,0x00,0x00, +0x0f,0x50,0x00,0x08,0xc4,0x02,0x13,0xa6,0x25,0xb0,0x02,0x3c,0x88,0x0c,0x42,0x34, +0x00,0x00,0x44,0x8c,0x02,0x80,0x03,0x3c,0x38,0x15,0x66,0x24,0xc0,0xff,0x02,0x3c, +0x24,0x20,0x82,0x00,0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c,0x83,0x51,0x00,0x08, +0x18,0x00,0xc3,0x24,0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,0xbc,0xff,0x40,0x10, +0x25,0xb0,0x02,0x3c,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x45,0x00, +0xf8,0xff,0x44,0x14,0x04,0x00,0x63,0x24,0x08,0x00,0xc2,0x8c,0x3f,0x00,0x23,0x32, +0xff,0xc0,0x04,0x24,0x24,0x10,0x44,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x43,0x00, +0x3d,0x51,0x00,0x08,0x08,0x00,0xc2,0xac,0x08,0x00,0xa3,0x8c,0xc0,0xff,0x02,0x3c, +0xff,0xff,0x42,0x34,0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00, +0x25,0x18,0x64,0x00,0x00,0x80,0x02,0x3c,0x66,0x51,0x00,0x08,0x25,0x18,0x62,0x00, +0x63,0x0c,0x23,0x36,0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x19,0x50,0x00,0x08,0x38,0x15,0x83,0x26,0x8b,0x00,0xe0,0x10,0x21,0x40,0x00,0x00, +0x2b,0x10,0x42,0x02,0x21,0x20,0x92,0x00,0x00,0x00,0x42,0x38,0x24,0x00,0x08,0x24, +0x2b,0x18,0x43,0x02,0x0b,0x40,0x82,0x00,0x7d,0xfe,0x60,0x10,0x20,0x00,0x15,0x24, +0x38,0x15,0x83,0x26,0x0a,0x00,0x62,0x94,0x02,0x80,0x17,0x3c,0x3f,0x00,0x42,0x30, +0x2b,0x50,0x00,0x08,0x21,0xa8,0x52,0x00,0x83,0x00,0xa0,0x10,0x80,0x10,0x08,0x00, +0x21,0x10,0x46,0x00,0x18,0x00,0x45,0x8c,0x25,0xb0,0x04,0x3c,0xc3,0x4b,0x00,0x0c, +0x80,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,0x94,0x0c,0x84,0x34,0x60,0x50,0x00,0x08, +0x21,0x28,0x00,0x00,0x21,0x10,0xa3,0x00,0xb4,0x01,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x22,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb5,0x01,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x23,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb6,0x01,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x24,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb7,0x01,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x25,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb8,0x01,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x26,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb9,0x01,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x27,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xba,0x01,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x28,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x38,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xbb,0x01,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x29,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0xc6,0x50,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0x00,0x43,0x8c,0x34,0x50,0x00,0x08, +0x82,0x25,0x03,0x00,0x08,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00, +0x3f,0x00,0x42,0x30,0x2b,0x18,0x42,0x02,0xbc,0xfe,0x60,0x14,0x23,0x30,0x52,0x00, +0x21,0x30,0x00,0x00,0x21,0x28,0x00,0x00,0x38,0x15,0x82,0x26,0x30,0x00,0x43,0x8c, +0xee,0x50,0x00,0x08,0x82,0x25,0x03,0x00,0x23,0x10,0x92,0x00,0x2b,0x18,0x44,0x02, +0x2b,0x20,0x45,0x02,0x0b,0x40,0x43,0x00,0xf5,0xfd,0x80,0x14,0x23,0xa8,0xb2,0x00, +0x2a,0x50,0x00,0x08,0x21,0xa8,0x00,0x00,0x30,0x00,0xc5,0x8c,0xb9,0x51,0x00,0x08, +0x25,0xb0,0x04,0x3c,0xff,0xff,0x43,0x26,0x42,0x18,0x03,0x00,0x40,0x10,0x03,0x00, +0x21,0x10,0x43,0x00,0xd8,0x50,0x00,0x08,0x01,0x00,0x52,0x24,0x21,0x00,0xa0,0x10, +0x80,0x10,0x06,0x00,0x21,0x10,0x43,0x00,0x18,0x00,0x45,0x8c,0x25,0xb0,0x04,0x3c, +0xc3,0x4b,0x00,0x0c,0x88,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,0x9c,0x0c,0x84,0x34, +0xc3,0x4b,0x00,0x0c,0x21,0x28,0x00,0x00,0xd8,0x4f,0x00,0x08,0x00,0x00,0x00,0x00, +0xff,0xff,0x05,0x36,0x60,0x00,0x06,0x24,0x6a,0x44,0x00,0x0c,0x24,0x00,0x04,0x24, +0xf2,0x19,0x00,0x0c,0xe8,0x03,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x24,0x00,0x04,0x24,0x95,0x44,0x00,0x0c, +0xff,0xff,0x05,0x36,0x1f,0x00,0x53,0x30,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x21,0x1a,0x00,0x0c,0x64,0x00,0x04,0x24,0xf1,0x4f,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x30,0x00,0x65,0x8c,0x46,0x52,0x00,0x08,0x25,0xb0,0x04,0x3c, +0x00,0xff,0x84,0x30,0x02,0x22,0x04,0x00,0x08,0x00,0x80,0x10,0x02,0x80,0x02,0x3c, +0xff,0x00,0x02,0x24,0x04,0x00,0x82,0x10,0xcc,0xff,0x03,0x24,0x02,0x80,0x02,0x3c, +0x08,0x00,0xe0,0x03,0x22,0x18,0x43,0xa0,0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03, +0x22,0x18,0x44,0xa0,0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,0xc0,0x10,0x04,0x00, +0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c, +0x80,0x10,0x02,0x00,0x38,0x15,0x63,0x24,0x20,0x00,0x84,0x2c,0x09,0x00,0x80,0x10, +0x21,0x10,0x43,0x00,0x80,0x11,0x43,0x8c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x2c,0x39,0x43,0x8c,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xac, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x85,0x30,0xd2,0xff,0xa3,0x24, +0xfe,0xff,0xa2,0x24,0xda,0xff,0xa4,0x24,0x04,0x00,0x63,0x2c,0x08,0x00,0x84,0x2c, +0x06,0x00,0x60,0x14,0xff,0x00,0x42,0x30,0xf0,0xff,0xa2,0x24,0xfc,0xff,0xa3,0x24, +0x16,0x00,0x46,0x2c,0x03,0x00,0x80,0x10,0xff,0x00,0x62,0x30,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xfa,0xff,0xa3,0x24,0xfc,0xff,0xc0,0x10,0x21,0x10,0xa0,0x00, +0x08,0x00,0xe0,0x03,0xff,0x00,0x62,0x30,0xe0,0xff,0xbd,0x27,0x02,0x80,0x08,0x3c, +0x18,0x00,0xbf,0xaf,0x38,0x15,0x08,0x25,0xe8,0x02,0x07,0x8d,0x02,0x80,0x02,0x3c, +0xb6,0x3d,0x49,0x90,0x00,0x03,0x02,0x3c,0x25,0x38,0xe2,0x00,0xff,0xf3,0x02,0x3c, +0xff,0xff,0x42,0x34,0x02,0x80,0x03,0x3c,0x24,0x38,0xe2,0x00,0x3c,0x94,0x6a,0x24, +0x01,0x80,0x06,0x3c,0x22,0x00,0x02,0x24,0x21,0x20,0x40,0x01,0x34,0x4b,0xc6,0x24, +0x10,0x00,0xa5,0x27,0x05,0x00,0x22,0x11,0xe8,0x02,0x07,0xad,0x18,0x00,0xbf,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x44,0x00,0x02,0x24, +0x10,0x00,0xa2,0xa3,0x49,0x00,0x03,0x24,0x47,0x00,0x02,0x24,0x11,0x00,0xa3,0xa3, +0x12,0x00,0xa2,0xa3,0xd0,0x07,0x03,0x24,0x01,0x00,0x02,0x24,0x13,0x00,0xa0,0xa3, +0x0c,0x00,0x43,0xad,0xe1,0x1c,0x00,0x0c,0x14,0x00,0x42,0xa1,0x18,0x00,0xbf,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0x02,0x80,0x10,0x3c,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf, +0x38,0x15,0x04,0x26,0xd8,0x02,0x82,0x8c,0x01,0x00,0x03,0x24,0x02,0x15,0x02,0x00, +0x0f,0x00,0x42,0x30,0x07,0x00,0x43,0x10,0x25,0xb0,0x06,0x3c,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x4c,0x00,0xc3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00, +0x03,0x00,0x42,0x30,0x45,0x00,0x40,0x10,0xff,0xf3,0x02,0x3c,0xe8,0x02,0x85,0x8c, +0x00,0x00,0x00,0x00,0x82,0x16,0x05,0x00,0x03,0x00,0x42,0x30,0x17,0x00,0x40,0x14, +0x38,0x15,0x11,0x26,0x0c,0x09,0xc3,0x34,0x00,0x00,0x63,0x8c,0x12,0x01,0x02,0x3c, +0x13,0x13,0x42,0x34,0x6b,0x00,0x62,0x10,0xff,0xfc,0x02,0x3c,0x22,0x02,0x02,0x3c, +0x23,0x13,0x42,0x34,0x52,0x00,0x62,0x10,0xff,0xfc,0x02,0x3c,0x00,0x03,0x02,0x3c, +0x25,0x10,0xa2,0x00,0xe8,0x02,0x82,0xac,0x38,0x15,0x05,0x26,0xe8,0x02,0xa3,0x8c, +0xff,0xf3,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x04,0x04,0x3c, +0x25,0x18,0x64,0x00,0xe8,0x02,0xa3,0xac,0x38,0x15,0x11,0x26,0xfc,0x23,0x24,0x8e, +0xff,0xff,0x02,0x34,0xd5,0xff,0x82,0x10,0x00,0x00,0x00,0x00,0x80,0x11,0x22,0x8e, +0x00,0x00,0x00,0x00,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30,0x3f,0x00,0x43,0x2c, +0x28,0x00,0x60,0x14,0x3b,0x00,0x42,0x2c,0x00,0x24,0x22,0x8e,0x02,0x19,0x04,0x00, +0x02,0x11,0x02,0x00,0x23,0x18,0x62,0x00,0x3a,0x00,0x60,0x18,0x01,0x00,0x03,0x24, +0xeb,0x02,0x22,0x92,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x0e,0x00,0x43,0x10, +0x38,0x15,0x02,0x26,0x25,0xb0,0x04,0x3c,0x12,0x01,0x05,0x3c,0x0c,0x09,0x84,0x34, +0xc3,0x4b,0x00,0x0c,0x13,0x13,0xa5,0x34,0xe8,0x02,0x23,0x8e,0xff,0xfc,0x02,0x3c, +0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x01,0x04,0x3c,0x25,0x18,0x64,0x00, +0xe8,0x02,0x23,0xae,0x38,0x15,0x02,0x26,0xe8,0x02,0x43,0x8c,0x00,0x20,0x04,0x3c, +0x25,0x18,0x64,0x00,0xd9,0x52,0x00,0x08,0xe8,0x02,0x43,0xac,0xe8,0x02,0x83,0x8c, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x20,0x00,0xbd,0x27,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0xe8,0x02,0x83,0xac,0xa5,0xff,0x40,0x10,0x03,0x00,0x03,0x24,0xeb,0x02,0x22,0x92, +0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0xa0,0xff,0x43,0x10,0x32,0x03,0x05,0x3c, +0x25,0xb0,0x04,0x3c,0x0c,0x09,0x84,0x34,0xc3,0x4b,0x00,0x0c,0x33,0x13,0xa5,0x34, +0xe8,0x02,0x23,0x8e,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x00,0x03,0x04,0x3c,0x25,0x18,0x64,0x00,0xd9,0x52,0x00,0x08,0xe8,0x02,0x23,0xae, +0xff,0xff,0x42,0x34,0x24,0x10,0xa2,0x00,0x00,0x02,0x03,0x3c,0xf7,0x52,0x00,0x08, +0x25,0x10,0x43,0x00,0xeb,0x02,0x22,0x92,0x02,0x00,0x03,0x24,0x03,0x00,0x42,0x30, +0xd5,0xff,0x43,0x10,0x38,0x15,0x02,0x26,0x25,0xb0,0x04,0x3c,0x22,0x02,0x05,0x3c, +0x0c,0x09,0x84,0x34,0xc3,0x4b,0x00,0x0c,0x23,0x13,0xa5,0x34,0xe8,0x02,0x23,0x8e, +0xff,0xfc,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x21,0x53,0x00,0x08, +0x00,0x02,0x04,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0xa2,0x00,0x00,0x01,0x03,0x3c, +0xf7,0x52,0x00,0x08,0x25,0x10,0x43,0x00,0x25,0xb0,0x03,0x3c,0x03,0x0d,0x63,0x34, +0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x08,0x00,0x42,0x34, +0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x03,0x0d,0x63,0x34, +0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xf7,0x00,0x42,0x30,0x00,0x00,0x62,0xa0, +0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,0x00,0x00,0x62,0x90, +0x21,0x20,0x00,0x00,0x3f,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24, +0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24, +0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00, +0xff,0x00,0x42,0x30,0x80,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24, +0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xff,0x00,0x03,0x3c, +0x82,0x01,0x49,0x34,0x81,0x01,0x48,0x34,0x24,0x10,0x83,0x00,0x02,0x3c,0x02,0x00, +0x00,0xff,0x63,0x34,0x02,0x80,0x02,0x3c,0x38,0x15,0x45,0x24,0x02,0x32,0x04,0x00, +0x01,0x00,0x02,0x24,0x24,0x20,0x83,0x00,0xda,0x0c,0xa2,0xa0,0xc8,0x0c,0xa0,0xac, +0xcc,0x0c,0xa0,0xac,0xd0,0x0c,0xa0,0xac,0x06,0x00,0x80,0x14,0xd4,0x0c,0xa0,0xac, +0x00,0x00,0x02,0x91,0x00,0x00,0x23,0x91,0xd8,0x0c,0xa2,0xa0,0x08,0x00,0xe0,0x03, +0xd9,0x0c,0xa3,0xa0,0xd9,0x0c,0xa7,0xa0,0x08,0x00,0xe0,0x03,0xd8,0x0c,0xa6,0xa0, +0x02,0x80,0x03,0x3c,0x38,0x15,0x63,0x24,0xd9,0x0c,0x66,0x90,0xd8,0x0c,0x65,0x90, +0x25,0xb0,0x02,0x3c,0x82,0x01,0x44,0x34,0x81,0x01,0x42,0x34,0x00,0x00,0x45,0xa0, +0x00,0x00,0x86,0xa0,0x08,0x00,0xe0,0x03,0xda,0x0c,0x60,0xa0,0x02,0x80,0x08,0x3c, +0x38,0x15,0x04,0x25,0xda,0x0c,0x82,0x90,0x00,0x00,0x00,0x00,0x15,0x00,0x40,0x10, +0x21,0x18,0x00,0x00,0xcc,0x0c,0x82,0x8c,0xc8,0x0c,0x85,0x8c,0x25,0xb0,0x03,0x3c, +0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x82,0x01,0x67,0x34,0x0f,0x00,0x40,0x10, +0x81,0x01,0x66,0x34,0xd9,0x0c,0x83,0x90,0xd8,0x0c,0x82,0x90,0xf0,0x00,0x63,0x30, +0x1f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0,0x00,0x00,0xe3,0xa0,0x38,0x15,0x02,0x25, +0x01,0x00,0x03,0x24,0xd4,0x0c,0x40,0xac,0xc8,0x0c,0x40,0xac,0xcc,0x0c,0x40,0xac, +0xd0,0x0c,0x40,0xac,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xd0,0x0c,0x82,0x8c, +0x25,0xb0,0x03,0x3c,0x82,0x01,0x69,0x34,0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00, +0x0e,0x00,0x40,0x14,0x81,0x01,0x66,0x34,0xd4,0x0c,0x82,0x8c,0x00,0x00,0x00,0x00, +0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x08,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0xd9,0x0c,0x83,0x90,0xd8,0x0c,0x82,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa0, +0x00,0x00,0x23,0xa1,0xca,0x53,0x00,0x08,0x38,0x15,0x02,0x25,0xd9,0x0c,0x83,0x90, +0xd8,0x0c,0x82,0x90,0xf0,0x00,0x63,0x30,0x7f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0, +0x00,0x00,0x23,0xa1,0xca,0x53,0x00,0x08,0x38,0x15,0x02,0x25,0x00,0x00,0x85,0xac, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x25,0xb0,0x03,0x3c,0x33,0x02,0x65,0x34,0x00,0x11,0x04,0x00,0x00,0x00,0xa2,0xa0, +0x30,0x02,0x63,0x34,0x00,0x00,0x65,0x8c,0x0f,0x00,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x28,0xa2,0x00,0x01,0x00,0x03,0x24,0x04,0x18,0x83,0x00,0x02,0x00,0xa0,0x10, +0x21,0x10,0x00,0x00,0xff,0xff,0x62,0x30,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x25,0xb0,0x11,0x3c,0x18,0x00,0xb2,0xaf, +0x4c,0x00,0x22,0x36,0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x44,0x90, +0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x24,0xff,0x00,0x84,0x30,0x07,0x00,0x82,0x10, +0x38,0x15,0x72,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x5e,0x24,0x43,0x96, +0x01,0x00,0x02,0x24,0xf7,0xff,0x62,0x14,0x21,0x20,0x00,0x00,0xf6,0x53,0x00,0x0c, +0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x24,0xf6,0x53,0x00,0x0c,0x21,0x80,0x40,0x00, +0x25,0x80,0x02,0x02,0x33,0x02,0x23,0x36,0x08,0x00,0x02,0x24,0xff,0xff,0x10,0x32, +0x40,0x00,0x25,0x36,0x00,0x00,0x62,0xa0,0xea,0xff,0x00,0x16,0x00,0x00,0x00,0x00, +0x00,0x00,0xa2,0x94,0x5c,0x24,0x43,0x96,0xff,0xdf,0x42,0x30,0x00,0x20,0x44,0x34, +0x01,0x00,0x63,0x24,0x5c,0x24,0x43,0xa6,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa4,0xa4, +0x13,0x54,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xb8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c, +0x3c,0x00,0xb1,0xaf,0x38,0x00,0xb0,0xaf,0x40,0x00,0xbf,0xaf,0x38,0x15,0x50,0x24, +0x10,0x24,0x03,0x8e,0x02,0x80,0x11,0x3c,0x01,0x00,0x02,0x24,0x01,0x00,0x63,0x30, +0x10,0x00,0xa4,0x27,0x4c,0x39,0x25,0x26,0x07,0x00,0x62,0x10,0x0a,0x00,0x06,0x24, +0x40,0x00,0xbf,0x8f,0x3c,0x00,0xb1,0x8f,0x38,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,0x6c,0x45,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x21,0x28,0x00,0x00,0x4c,0x39,0x24,0x26,0x58,0x45,0x00,0x0c,0x0a,0x00,0x06,0x24, +0x28,0x00,0x03,0x24,0x05,0x00,0x02,0x24,0x15,0x24,0x03,0xa2,0x14,0x24,0x02,0xa2, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x1f,0x49,0x00,0x0c, +0x48,0x00,0x04,0x24,0x21,0x80,0x40,0x00,0x10,0x00,0xa5,0x27,0xe4,0xff,0x40,0x10, +0x0a,0x00,0x06,0x24,0x08,0x00,0x44,0x94,0x14,0x00,0x02,0x24,0x14,0x00,0x02,0xae, +0x02,0x80,0x02,0x3c,0x28,0x00,0x03,0x24,0x25,0x20,0x82,0x00,0x0c,0x00,0x03,0xae, +0x6c,0x45,0x00,0x0c,0x20,0x00,0x84,0x24,0x42,0x09,0x00,0x0c,0x21,0x20,0x00,0x02, +0x46,0x54,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x18,0x03,0x42,0x34,0xc0,0x51,0x63,0x24,0x00,0x00,0x43,0xac,0x63,0x00,0x02,0x24, +0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x02,0x80,0x02,0x3c, +0xb0,0x3d,0x45,0x94,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xb3,0x3d,0x66,0x90, +0xc0,0x3d,0x47,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xcb,0x3d,0x6a,0x90, +0xcd,0x3d,0x4b,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xd0,0x3d,0x6c,0x90, +0xd2,0x3d,0x4d,0x90,0x07,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x25,0xb0,0x04,0x3c, +0xbd,0x3d,0x43,0xa0,0xb0,0x03,0x84,0x34,0x02,0x80,0x02,0x3c,0x02,0x80,0x18,0x3c, +0xb2,0x3d,0x08,0x93,0x00,0x00,0x85,0xac,0xbe,0x3d,0x40,0xa0,0x02,0x80,0x02,0x3c, +0x00,0x00,0x86,0xac,0xbf,0x3d,0x40,0xa0,0x02,0x80,0x02,0x3c,0x00,0x00,0x87,0xac, +0x02,0x80,0x0f,0x3c,0xe0,0x3d,0x40,0xa0,0x02,0x80,0x02,0x3c,0xdc,0x3d,0x40,0xa4, +0x38,0x15,0xee,0x25,0x02,0x80,0x03,0x3c,0xfd,0xff,0x02,0x24,0xde,0x3d,0x60,0xa4, +0xe2,0x0a,0xc2,0xa1,0x01,0x00,0x03,0x24,0x00,0x78,0x02,0x24,0xe0,0x0a,0xc3,0xa1, +0xe4,0x0a,0xc2,0xa5,0xff,0x07,0x03,0x24,0x0f,0x00,0x09,0x31,0x02,0x00,0x02,0x24, +0xe6,0x0a,0xc3,0xa5,0x00,0x00,0x88,0xac,0x00,0x00,0x8a,0xac,0x00,0x00,0x8b,0xac, +0x00,0x00,0x8c,0xac,0x00,0x00,0x8d,0xac,0x0c,0x00,0x22,0x11,0x82,0x0b,0xc0,0xa1, +0xb2,0x3d,0x02,0x93,0x01,0x00,0x05,0x24,0x0f,0x00,0x42,0x30,0x20,0x00,0x45,0x10, +0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0xfc,0x3d,0x40,0xa4, +0xf1,0x3d,0x65,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c, +0xb7,0x3d,0x44,0x90,0x06,0x00,0x03,0x24,0x2d,0x00,0x83,0x10,0x0b,0x00,0x02,0x24, +0x22,0x00,0x82,0x10,0x02,0x80,0x02,0x3c,0xca,0x3d,0x43,0x90,0x00,0x00,0x00,0x00, +0x36,0x00,0x60,0x10,0x00,0xe0,0x02,0x3c,0x04,0xe0,0x02,0x3c,0x38,0x15,0xe4,0x25, +0x00,0x8e,0x42,0x34,0x00,0x15,0x03,0x3c,0x74,0x0b,0x82,0xac,0x00,0x15,0x63,0x34, +0x00,0x42,0x02,0x24,0x6c,0x0b,0x83,0xac,0x70,0x0b,0x82,0xac,0xb2,0x3d,0x02,0x93, +0x01,0x00,0x05,0x24,0x0f,0x00,0x42,0x30,0xe2,0xff,0x45,0x14,0x00,0x00,0x00,0x00, +0x00,0x80,0x02,0x3c,0x38,0x15,0xe4,0x25,0x02,0xbc,0x42,0x34,0x15,0x15,0x03,0x3c, +0x07,0x07,0x63,0x34,0x74,0x0b,0x82,0xac,0x02,0x02,0x02,0x3c,0x6c,0x0b,0x83,0xac, +0x70,0x0b,0x82,0xac,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xfc,0x3d,0x40,0xa4, +0xf1,0x3d,0x65,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x3c, +0x00,0xbc,0x42,0x34,0x15,0x15,0x03,0x3c,0x74,0x0b,0xc2,0xad,0x07,0x07,0x63,0x34, +0x03,0x03,0x02,0x3c,0x6c,0x0b,0xc3,0xad,0xae,0x54,0x00,0x08,0x70,0x0b,0xc2,0xad, +0x02,0x80,0x02,0x3c,0xca,0x3d,0x43,0x90,0x00,0x00,0x00,0x00,0x14,0x00,0x60,0x10, +0x00,0xc0,0x02,0x3c,0x04,0xc0,0x02,0x3c,0x00,0xb8,0x42,0x34,0x74,0x0b,0xc2,0xad, +0x00,0x15,0x03,0x3c,0x02,0x02,0x02,0x3c,0x00,0x07,0x63,0x34,0x00,0x22,0x42,0x34, +0x6c,0x0b,0xc3,0xad,0xae,0x54,0x00,0x08,0x70,0x0b,0xc2,0xad,0x38,0x15,0xe4,0x25, +0x00,0xb2,0x42,0x34,0x00,0x1c,0x03,0x3c,0x74,0x0b,0x82,0xac,0x00,0x1c,0x63,0x34, +0x00,0x04,0x02,0x24,0x6c,0x0b,0x83,0xac,0xcd,0x54,0x00,0x08,0x70,0x0b,0x82,0xac, +0x00,0xb2,0x42,0x34,0x1c,0x1c,0x03,0x3c,0x74,0x0b,0xc2,0xad,0x07,0x07,0x63,0x34, +0x00,0x04,0x02,0x24,0x6c,0x0b,0xc3,0xad,0xae,0x54,0x00,0x08,0x70,0x0b,0xc2,0xad, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x7f,0x00,0x02,0x3c,0x0d,0xb8,0x46,0x34, +0x80,0x00,0x03,0x3c,0x25,0x30,0xc3,0x00,0x00,0x04,0x02,0x3c,0x25,0x30,0xc2,0x00, +0x00,0x08,0x03,0x3c,0x25,0x30,0xc3,0x00,0x02,0x80,0x04,0x3c,0x01,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x38,0x15,0x84,0x24,0x41,0xb0,0x05,0x3c,0x30,0x54,0x63,0x24, +0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0xa6,0xac,0x10,0x0b,0x86,0xac, +0x08,0x0b,0x86,0xac,0x08,0x00,0xa5,0x34,0x86,0x00,0x06,0x24,0x00,0x00,0xa6,0xa4, +0x14,0x0b,0x86,0xa4,0x0c,0x0b,0x80,0xac,0x16,0x0b,0x80,0xa4,0x18,0x0b,0x86,0xa4, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x2b,0x55,0x00,0x08,0x00,0x00,0x00,0x00,0x42,0xb0,0x02,0x3c, +0xa0,0xff,0x03,0x24,0x01,0x00,0x42,0x34,0xe8,0xff,0xbd,0x27,0x21,0x20,0x00,0x00, +0x01,0x00,0x05,0x24,0x00,0x01,0x06,0x24,0x00,0x00,0x43,0xa0,0x10,0x00,0xbf,0xaf, +0xaa,0x1c,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,0x03,0x00,0x04,0x24, +0x01,0x00,0x05,0x24,0x40,0x1f,0x06,0x24,0xaa,0x1c,0x00,0x08,0x18,0x00,0xbd,0x27, +0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x14,0x00,0xbf,0xaf,0x81,0x58,0x00,0x0c, +0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x38,0x15,0x42,0x24,0xff,0xff,0x03,0x34, +0x21,0x80,0x40,0x00,0xf8,0x23,0x43,0xac,0xf0,0x23,0x40,0xa4,0xf2,0x23,0x40,0xa4, +0xf4,0x23,0x43,0xac,0x21,0x38,0x00,0x00,0x80,0xff,0x08,0x24,0x21,0x30,0x40,0x00, +0x21,0x28,0x40,0x00,0xdc,0x0c,0xa0,0xa4,0xde,0x0c,0xa0,0xa4,0xe0,0x0c,0xa0,0xa4, +0xe2,0x0c,0xa0,0xa4,0xe4,0x0c,0xa0,0xa4,0xe6,0x0c,0xa0,0xa4,0xe8,0x0c,0xa0,0xa4, +0xea,0x0c,0xa0,0xa4,0xec,0x0c,0xa0,0xa4,0x21,0x20,0x00,0x00,0x21,0x18,0xc4,0x00, +0x01,0x00,0x84,0x24,0x08,0x00,0x82,0x28,0xfc,0xff,0x40,0x14,0xf8,0x0c,0x60,0xa0, +0x01,0x00,0xe7,0x24,0x20,0x00,0xe2,0x28,0xf7,0x0c,0xc8,0xa0,0x24,0x00,0xa5,0x24, +0xec,0xff,0x40,0x14,0x24,0x00,0xc6,0x24,0x25,0xb0,0x02,0x3c,0x10,0x00,0x03,0x24, +0xb0,0x03,0x42,0x34,0x02,0x80,0x04,0x3c,0x60,0x18,0x84,0x24,0x00,0x00,0x43,0xac, +0x21,0x28,0x00,0x00,0x58,0x45,0x00,0x0c,0x04,0x00,0x06,0x24,0x51,0x59,0x00,0x0c, +0x00,0x00,0x00,0x00,0xc4,0x59,0x00,0x0c,0x08,0x26,0x00,0xae,0x26,0x5b,0x00,0x0c, +0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0xb6,0x3d,0x64,0x90,0x92,0x00,0x02,0x24, +0x03,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0xa0,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00, +0x86,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0xfd,0x59,0x00,0x0c,0x00,0x00,0x00,0x00, +0x29,0x5c,0x00,0x0c,0x00,0x00,0x00,0x00,0x5e,0x24,0x00,0xa6,0x0f,0x5c,0x00,0x0c, +0x5c,0x24,0x00,0xa6,0x02,0x80,0x05,0x3c,0x02,0x80,0x06,0x3c,0x44,0x3b,0xa3,0x24, +0x4c,0x3b,0xc4,0x24,0x80,0x00,0x02,0x24,0x64,0x24,0x02,0xa6,0x14,0x00,0xbf,0x8f, +0x04,0x00,0x63,0xac,0x44,0x3b,0xa3,0xac,0x4c,0x3b,0xc4,0xac,0x04,0x00,0x84,0xac, +0x68,0x24,0x00,0xa2,0x69,0x24,0x00,0xa2,0x6a,0x24,0x00,0xa6,0x60,0x24,0x00,0xa6, +0x62,0x24,0x00,0xa6,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27, +0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x58,0x56,0x63,0x24,0x18,0x03,0x42,0x34, +0x00,0x00,0x43,0xac,0x69,0x58,0x00,0x08,0x00,0x00,0x00,0x00,0xe8,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0x01,0x80,0x02,0x3c,0x25,0xb0,0x10,0x3c,0x18,0x03,0x03,0x36, +0x74,0x56,0x42,0x24,0x00,0x00,0x62,0xac,0x14,0x00,0xbf,0xaf,0x70,0x54,0x00,0x0c, +0x00,0x00,0x00,0x00,0x22,0x56,0x00,0x0c,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x24, +0x02,0x80,0x02,0x3c,0x45,0x58,0x00,0x0c,0xc3,0x20,0x43,0xa0,0x32,0x41,0x00,0x0c, +0x00,0x00,0x00,0x00,0x3e,0x55,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x00,0x03,0x36, +0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x34,0x00,0x00,0x62,0xa4, +0x96,0x55,0x00,0x0c,0x00,0x00,0x00,0x00,0x2d,0x55,0x00,0x0c,0x00,0x00,0x00,0x00, +0x11,0x58,0x00,0x0c,0x00,0x00,0x00,0x00,0xd5,0x57,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x80,0x04,0x3c,0x8c,0x2e,0x84,0x24,0x2e,0x58,0x00,0x0c,0x01,0x00,0x05,0x24, +0x00,0x80,0x04,0x3c,0x18,0x34,0x84,0x24,0x2e,0x58,0x00,0x0c,0x02,0x00,0x05,0x24, +0xff,0x48,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c,0xec,0x73,0x84,0x24, +0x2e,0x58,0x00,0x0c,0x03,0x00,0x05,0x24,0x02,0x80,0x02,0x3c,0xc0,0x3d,0x43,0x90, +0x43,0x00,0x04,0x36,0x29,0x00,0x60,0x10,0xd8,0x00,0x10,0x36,0x07,0x00,0x02,0x24, +0x2b,0x00,0x62,0x10,0x25,0xb0,0x04,0x3c,0x10,0x02,0x86,0x34,0x43,0x00,0x85,0x34, +0x03,0x00,0x02,0x24,0x10,0x00,0x03,0x24,0x00,0x00,0xa2,0xa0,0xd8,0x00,0x84,0x34, +0x00,0x00,0xc3,0xa0,0x00,0x00,0x82,0x90,0x80,0xff,0x03,0x24,0x42,0xb0,0x05,0x3c, +0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xa0,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34, +0x00,0x00,0x82,0x94,0x00,0x00,0x00,0x00,0xc0,0x00,0x42,0x34,0x00,0x00,0x82,0xa4, +0x00,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x34,0x00,0x00,0xa3,0xa0, +0x0c,0x55,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24, +0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0xc2,0x2e,0x00,0x0c,0x21,0x38,0x00,0x00, +0x2b,0x55,0x00,0x0c,0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f, +0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x00,0x00,0x80,0xa0, +0x00,0x00,0x03,0x92,0x80,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x00,0x00,0x03,0xa2, +0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0x42,0xb0,0x05,0x3c, +0xc0,0x00,0x42,0x34,0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,0x00,0x00,0x00,0x00, +0x01,0x00,0x63,0x34,0x00,0x00,0xa3,0xa0,0x0c,0x55,0x00,0x0c,0x00,0x00,0x00,0x00, +0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00, +0xc2,0x2e,0x00,0x0c,0x21,0x38,0x00,0x00,0x2b,0x55,0x00,0x0c,0x00,0x00,0x00,0x00, +0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0x21,0x20,0x00,0x00,0x20,0xb0,0x06,0x3c,0xff,0xff,0x05,0x34, +0x21,0x18,0x86,0x00,0x04,0x00,0x84,0x24,0x2a,0x10,0xa4,0x00,0x00,0x00,0x60,0xac, +0xfb,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xb8,0xff,0xbd,0x27,0x25,0xb0,0x04,0x3c,0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf, +0x3c,0x00,0xb7,0xaf,0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf, +0x2c,0x00,0xb3,0xaf,0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf, +0x0a,0x00,0x83,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x30, +0x0c,0x00,0x40,0x10,0x4c,0x87,0x02,0x3c,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00, +0x10,0x00,0x42,0x30,0x60,0x01,0x40,0x10,0x4c,0x87,0x02,0x3c,0x54,0x00,0x83,0x34, +0x50,0x00,0x82,0x34,0x00,0x00,0x45,0xac,0x00,0x00,0x65,0xa4,0x46,0x56,0x00,0x08, +0x02,0x80,0x03,0x3c,0x54,0x00,0x85,0x34,0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34, +0x12,0x01,0x03,0x24,0x00,0x00,0x82,0xac,0x00,0x00,0xa3,0xac,0x02,0x80,0x03,0x3c, +0x38,0x15,0x62,0x24,0xe2,0x0a,0x4f,0x90,0xe6,0x0a,0x45,0x94,0x25,0xb0,0x1e,0x3c, +0x1c,0x00,0xaf,0xa3,0x6c,0x0b,0x43,0x8c,0x58,0x00,0xc6,0x37,0x5c,0x00,0xc7,0x37, +0x10,0x00,0xa3,0xaf,0x70,0x0b,0x4f,0x8c,0x96,0x01,0x03,0x24,0xff,0xff,0x04,0x24, +0x14,0x00,0xaf,0xaf,0x74,0x0b,0x42,0x8c,0x60,0x00,0xc8,0x37,0x64,0x00,0xc9,0x37, +0x18,0x00,0xa2,0xaf,0x24,0x10,0x02,0x3c,0x21,0x28,0xa2,0x00,0x4c,0x81,0x02,0x3c, +0x00,0xe0,0x42,0x34,0x00,0x00,0xc2,0xac,0x8a,0x00,0xca,0x37,0x00,0x00,0xe3,0xac, +0x89,0x00,0xcb,0x37,0x28,0x28,0x02,0x24,0x09,0x00,0x03,0x24,0x00,0x00,0x04,0xad, +0x8c,0x00,0xcd,0x37,0x00,0x00,0x24,0xad,0x8e,0x00,0xce,0x37,0x00,0x00,0x42,0xa5, +0x00,0x00,0x63,0xa1,0x10,0x10,0x02,0x24,0x0a,0x0a,0x03,0x24,0x00,0x00,0xa2,0xa5, +0x00,0x00,0xc3,0xa5,0x25,0xb0,0x03,0x3c,0x13,0x00,0x02,0x24,0x90,0x00,0x63,0x34, +0x00,0x00,0x62,0xa0,0x25,0xb0,0x02,0x3c,0x40,0x00,0x03,0x24,0x91,0x00,0x42,0x34, +0x00,0x00,0x43,0xa0,0x92,0x00,0xd1,0x37,0x3a,0x01,0x02,0x24,0x21,0x00,0x03,0x24, +0xb5,0x00,0xd2,0x37,0x00,0x00,0x22,0xa6,0x00,0x00,0x43,0xa2,0x10,0x00,0xa3,0x8f, +0xa0,0x00,0xd3,0x37,0xa4,0x00,0xd4,0x37,0x00,0x00,0x63,0xae,0x14,0x00,0xa2,0x8f, +0xa8,0x00,0xd5,0x37,0xac,0x00,0xd6,0x37,0x00,0x00,0x82,0xae,0x18,0x00,0xa3,0x8f, +0x21,0x10,0x02,0x3c,0xff,0x77,0x42,0x34,0x00,0x00,0xa3,0xae,0x00,0x00,0xc2,0xae, +0x25,0xb0,0x02,0x3c,0xd8,0x00,0x42,0x34,0xb0,0x00,0xd7,0x37,0x00,0x00,0xe5,0xae, +0x00,0x00,0x40,0xa0,0x1c,0x00,0xa2,0x93,0x25,0xb0,0x03,0x3c,0xb4,0x00,0x63,0x34, +0x00,0x00,0x62,0xa0,0xb6,0x00,0xdf,0x37,0x04,0x00,0x03,0x24,0x25,0xb0,0x02,0x3c, +0x00,0x00,0xe3,0xa3,0xb9,0x00,0x42,0x34,0x25,0xb0,0x03,0x3c,0x00,0x00,0x44,0xa0, +0xba,0x00,0x63,0x34,0x0f,0x00,0x02,0x24,0x00,0x00,0x62,0xa4,0x25,0xb0,0x02,0x3c, +0x16,0x01,0x42,0x34,0x00,0x00,0x40,0xa4,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x18,0x01,0x63,0x34,0x1a,0x01,0x42,0x34,0x00,0x00,0x60,0xa4,0x00,0x00,0x40,0xa4, +0x25,0xb0,0x03,0x3c,0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,0xdc,0x00,0x63,0x34, +0x00,0x00,0x62,0xac,0x2f,0x00,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x32,0x32,0x63,0x34, +0xd0,0x01,0x42,0x34,0x00,0x00,0x43,0xac,0x5e,0x00,0x0c,0x3c,0x25,0xb0,0x03,0x3c, +0x08,0x00,0x02,0x3c,0x32,0x43,0x90,0x35,0xd8,0x01,0xcf,0x37,0xd4,0x01,0x63,0x34, +0x30,0xa5,0x42,0x34,0x00,0x00,0x70,0xac,0x28,0x83,0x8c,0x35,0x00,0x00,0xe2,0xad, +0xdc,0x01,0xc3,0x37,0x1a,0x06,0x02,0x24,0x02,0x80,0x0f,0x3c,0xe0,0x01,0xc4,0x37, +0xb6,0x3d,0xed,0x91,0x00,0x00,0x6c,0xac,0x00,0x00,0x82,0xa4,0xc2,0x00,0x02,0x3c, +0x07,0x07,0x03,0x24,0x51,0x10,0x42,0x34,0xf4,0x01,0xc5,0x37,0xf8,0x01,0xc6,0x37, +0x00,0x00,0xa3,0xa4,0x00,0x02,0xc7,0x37,0x00,0x00,0xc2,0xac,0x26,0x00,0x03,0x24, +0x04,0x00,0x02,0x24,0x03,0x02,0xc8,0x37,0x00,0x00,0xe3,0xa4,0x36,0x02,0xc9,0x37, +0x00,0x00,0x02,0xa1,0xc0,0x01,0x03,0x24,0x0c,0x00,0x02,0x24,0x34,0x02,0xca,0x37, +0x00,0x00,0x22,0xa1,0x37,0x02,0xcb,0x37,0x00,0x00,0x43,0xa5,0x03,0x00,0x02,0x24, +0x22,0x00,0x03,0x24,0x00,0x00,0x62,0xa1,0xd0,0x00,0xa3,0x11,0x1b,0x1b,0x02,0x3c, +0x13,0x13,0x02,0x3c,0x13,0x13,0x42,0x34,0x60,0x01,0xc3,0x37,0x64,0x01,0xc4,0x37, +0x68,0x01,0xc5,0x37,0x7c,0x01,0xca,0x37,0x6c,0x01,0xc6,0x37,0x70,0x01,0xc7,0x37, +0x74,0x01,0xc8,0x37,0x78,0x01,0xc9,0x37,0x00,0x00,0x62,0xac,0x00,0x00,0x82,0xac, +0x02,0x80,0x03,0x3c,0x00,0x00,0xa2,0xac,0x00,0x00,0xc2,0xac,0x00,0x00,0xe2,0xac, +0x00,0x00,0x02,0xad,0x00,0x00,0x22,0xad,0x00,0x00,0x42,0xad,0xb6,0x3d,0x65,0x90, +0x25,0xb0,0x0c,0x3c,0x01,0x70,0x03,0x3c,0x80,0x01,0x82,0x35,0x08,0x5f,0x63,0x34, +0x22,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0xaf,0x00,0xa4,0x10,0x0f,0x1f,0x02,0x3c, +0x92,0x00,0x02,0x24,0xac,0x00,0xa2,0x10,0x0f,0x1f,0x02,0x3c,0x0f,0x10,0x02,0x3c, +0x00,0xf0,0x51,0x34,0xf7,0x01,0x92,0x35,0x15,0xf0,0x4d,0x34,0x77,0x00,0x0e,0x24, +0x84,0x01,0x87,0x35,0x88,0x01,0x88,0x35,0x10,0xf0,0x44,0x34,0x8c,0x01,0x85,0x35, +0x05,0xf0,0x42,0x34,0x00,0x00,0xed,0xac,0x90,0x01,0x83,0x35,0x00,0x00,0x04,0xad, +0x94,0x01,0x86,0x35,0x00,0x00,0xa2,0xac,0xf5,0x0f,0x02,0x24,0x00,0x00,0x71,0xac, +0x98,0x01,0x89,0x35,0x00,0x00,0xc2,0xac,0x9c,0x01,0x8a,0x35,0xf0,0x0f,0x03,0x24, +0x0d,0x00,0x02,0x24,0x25,0xb0,0x0f,0x3c,0x00,0x00,0x23,0xad,0xa0,0x01,0x8b,0x35, +0x00,0x00,0x42,0xad,0xf6,0x01,0x8c,0x35,0xff,0xff,0x02,0x24,0xa7,0x01,0xef,0x35, +0x00,0x00,0x6d,0xad,0x25,0xb0,0x05,0x3c,0x00,0x00,0x8e,0xa1,0x00,0x00,0x4e,0xa2, +0x00,0x00,0xe2,0xa1,0x25,0xb0,0x02,0x3c,0xa8,0x01,0xb8,0x34,0xff,0xff,0x09,0x24, +0xac,0x01,0x42,0x34,0x03,0x04,0x04,0x3c,0x07,0x08,0x03,0x3c,0x25,0xb0,0x0f,0x3c, +0x00,0x00,0x09,0xaf,0x0c,0x00,0x06,0x24,0x00,0x00,0x49,0xac,0x01,0x02,0x84,0x34, +0x05,0x06,0x63,0x34,0xb4,0x01,0xb1,0x34,0xb8,0x01,0xb2,0x34,0xbc,0x01,0xb3,0x34, +0xc0,0x01,0xb4,0x34,0xc1,0x01,0xb5,0x34,0xc2,0x01,0xb6,0x34,0xc3,0x01,0xb7,0x34, +0x0d,0x00,0x08,0x24,0xc4,0x01,0xab,0x34,0xc5,0x01,0xac,0x34,0x0e,0x00,0x07,0x24, +0xc6,0x01,0xaa,0x34,0xc7,0x01,0xad,0x34,0xb0,0x01,0xef,0x35,0x0f,0x00,0x02,0x24, +0x00,0x00,0xe4,0xad,0x00,0x00,0x23,0xae,0x00,0x00,0x44,0xae,0x00,0x00,0x63,0xae, +0x00,0x00,0x86,0xa2,0x00,0x00,0xa6,0xa2,0x00,0x00,0xc6,0xa2,0x00,0x00,0xe8,0xa2, +0x00,0x00,0x68,0xa1,0x00,0x00,0x87,0xa1,0x00,0x00,0x47,0xa1,0x00,0x00,0xa2,0xa1, +0x57,0x01,0x02,0x3c,0x48,0x00,0xbf,0x34,0x46,0x00,0xae,0x34,0x0e,0xe2,0x42,0x34, +0x25,0xb0,0x03,0x3c,0x00,0x00,0xc0,0xa5,0x4c,0x00,0xbe,0x34,0x00,0x00,0xe2,0xaf, +0x40,0x00,0x63,0x34,0xbc,0x00,0x02,0x24,0x00,0x00,0xc0,0xa3,0x64,0x03,0xb9,0x34, +0x00,0x00,0x62,0xa4,0xfc,0x37,0x02,0x24,0x00,0x00,0x20,0xa3,0xd8,0x00,0xa7,0x34, +0x00,0x00,0x62,0xa4,0x00,0x00,0xe3,0x90,0x80,0xff,0x02,0x24,0x2a,0xb0,0x04,0x3c, +0x25,0x18,0x62,0x00,0x26,0xb0,0x06,0x3c,0x30,0x00,0x89,0x34,0x00,0x00,0xe3,0xa0, +0x38,0x00,0x84,0x34,0x20,0x20,0x02,0x24,0x40,0x00,0x03,0x24,0x00,0x00,0x82,0xa4, +0x79,0x00,0xc8,0x34,0x00,0x00,0x23,0xa1,0x94,0x00,0xaa,0x34,0x16,0x00,0x02,0x24, +0x64,0x00,0x03,0x24,0x00,0x00,0x02,0xa1,0x7c,0x00,0xd2,0x34,0x00,0x00,0x43,0xa5, +0x98,0x00,0xab,0x34,0x7a,0x00,0xc6,0x34,0x22,0x00,0x02,0x24,0x04,0x00,0x03,0x24, +0x00,0x00,0x62,0xa5,0x9c,0x00,0xac,0x34,0x00,0x00,0xc3,0xa0,0x20,0x0c,0x02,0x24, +0x0a,0x00,0x03,0x24,0x00,0x00,0x42,0xa6,0x9a,0x00,0xad,0x34,0x00,0x00,0x83,0xa1, +0x96,0x00,0xae,0x34,0xff,0x03,0x02,0x24,0x02,0x00,0x03,0x24,0x25,0xb0,0x0f,0x3c, +0x00,0x00,0xa2,0xa5,0x89,0x00,0xb1,0x34,0x00,0x00,0xc3,0xa5,0x20,0x00,0x02,0x24, +0xb7,0x00,0xef,0x35,0x09,0x00,0x03,0x24,0x00,0x00,0xe2,0xa1,0x44,0x00,0xa5,0x34, +0x00,0x00,0x23,0xa2,0x00,0x00,0xa3,0x94,0x02,0x80,0x02,0x3c,0x38,0x15,0x46,0x24, +0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00,0x00,0x00,0xa3,0xa4,0x00,0x00,0xa2,0x94, +0xe2,0x0a,0xc4,0x90,0x04,0x02,0x03,0x24,0x00,0x02,0x42,0x34,0x00,0x00,0xa2,0xa4, +0x29,0xb0,0x02,0x3c,0x40,0x00,0x42,0x34,0x00,0x00,0x43,0xa4,0x41,0x1a,0x00,0x0c, +0x00,0x00,0x00,0x00,0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f, +0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f, +0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,0x54,0x00,0x85,0x34,0x00,0xe0,0x42,0x34, +0x50,0x00,0x84,0x34,0x12,0x01,0x03,0x24,0x00,0x00,0x82,0xac,0x00,0x00,0xa3,0xa4, +0x46,0x56,0x00,0x08,0x02,0x80,0x03,0x3c,0x00,0xf0,0x51,0x34,0xf7,0x01,0x92,0x35, +0x15,0xf0,0x4d,0x34,0xfa,0x56,0x00,0x08,0xff,0xff,0x0e,0x24,0xd8,0x56,0x00,0x08, +0x1b,0x1b,0x42,0x34,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x08,0x3c,0xfc,0x37,0x02,0x24, +0x40,0x00,0x63,0x34,0x01,0x80,0x04,0x3c,0x00,0x00,0x62,0xa4,0x24,0x7b,0x84,0x24, +0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00, +0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30, +0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac, +0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14, +0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,0x01,0x80,0x02,0x3c,0x1c,0x75,0x44,0x24, +0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00, +0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30, +0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac, +0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c, +0x02,0x80,0x05,0x3c,0x30,0x60,0x42,0x24,0x02,0x80,0x03,0x3c,0x04,0x3e,0xa2,0xac, +0x00,0x80,0x02,0x3c,0xa4,0x3e,0x60,0xac,0x04,0x3e,0xa4,0x24,0x02,0x80,0x03,0x3c, +0x78,0x06,0x42,0x24,0xa8,0x3e,0x60,0xa4,0x08,0x00,0x82,0xac,0x02,0x80,0x03,0x3c, +0x00,0x80,0x02,0x3c,0xaa,0x3e,0x60,0xa4,0x02,0x80,0x06,0x3c,0x54,0x0a,0x42,0x24, +0x00,0x80,0x03,0x3c,0xac,0x3e,0xc7,0x24,0x14,0x00,0x82,0xac,0x04,0x08,0x63,0x24, +0x02,0x80,0x02,0x3c,0xac,0x3e,0xc0,0xac,0x10,0x00,0x83,0xac,0x04,0x00,0xe0,0xac, +0x02,0x80,0x03,0x3c,0xb4,0x3e,0x40,0xa0,0x02,0x80,0x02,0x3c,0xb8,0x3e,0x60,0xac, +0xbc,0x3e,0x40,0xac,0x00,0x80,0x02,0x3c,0x00,0x80,0x03,0x3c,0xb4,0x1e,0x42,0x24, +0xe8,0x0c,0x63,0x24,0x40,0x00,0x82,0xac,0x1c,0x00,0x83,0xac,0x00,0x80,0x02,0x3c, +0x00,0x80,0x03,0x3c,0x58,0x11,0x42,0x24,0xc4,0x15,0x63,0x24,0x20,0x00,0x82,0xac, +0x24,0x00,0x83,0xac,0x00,0x80,0x02,0x3c,0x00,0x80,0x03,0x3c,0x3c,0x1a,0x42,0x24, +0xa0,0x26,0x63,0x24,0x28,0x00,0x82,0xac,0x2c,0x00,0x83,0xac,0x00,0x80,0x02,0x3c, +0x00,0x80,0x03,0x3c,0x10,0x1f,0x42,0x24,0x00,0x03,0x63,0x24,0x3c,0x00,0x82,0xac, +0x08,0x00,0xe0,0x03,0x50,0x00,0x83,0xac,0x25,0xb0,0x02,0x3c,0x08,0x00,0x42,0x34, +0x00,0x00,0x43,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x0e,0x3c, +0x02,0x80,0x08,0x3c,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0xf8,0x03,0x4d,0x24, +0x00,0x14,0x6c,0x24,0x01,0x00,0x07,0x24,0x00,0x00,0xcb,0x25,0xff,0xff,0x0a,0x24, +0x00,0x04,0x09,0x25,0x80,0x1a,0x07,0x00,0x21,0x10,0x6b,0x00,0x00,0x00,0x42,0xac, +0x90,0x00,0x4a,0xac,0x00,0x04,0x04,0x8d,0x01,0x00,0xe7,0x24,0x08,0x00,0x45,0x24, +0x21,0x18,0x6d,0x00,0x05,0x00,0xe6,0x28,0x04,0x00,0x82,0xac,0x00,0x00,0x44,0xac, +0x04,0x00,0x49,0xac,0x00,0x04,0x02,0xad,0x8c,0x00,0x40,0xac,0x6c,0x00,0xa3,0xac, +0xf0,0xff,0xc0,0x14,0x68,0x00,0xac,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0xc9,0xad, +0x05,0x00,0xa2,0x2c,0x13,0x00,0x40,0x10,0xff,0xff,0x07,0x24,0x02,0x80,0x02,0x3c, +0x80,0x1a,0x05,0x00,0x00,0x00,0x42,0x24,0x0e,0x00,0xa0,0x10,0x21,0x30,0x62,0x00, +0x90,0x00,0xc3,0x8c,0xff,0xff,0x02,0x24,0x0a,0x00,0x62,0x14,0x00,0x00,0x00,0x00, +0x8c,0x00,0xc2,0x8c,0x00,0x00,0x00,0x00,0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x01,0x00,0x02,0x24,0x88,0x00,0xc4,0xac,0x8c,0x00,0xc2,0xac,0x90,0x00,0xc5,0xac, +0x21,0x38,0xa0,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,0x25,0xb0,0x04,0x3c, +0x01,0x80,0x02,0x3c,0x18,0x03,0x85,0x34,0x14,0x61,0x42,0x24,0xe0,0xff,0xbd,0x27, +0x00,0x00,0xa2,0xac,0x1b,0x00,0x86,0x34,0xdb,0xff,0x03,0x24,0x27,0x00,0x84,0x34, +0x07,0x00,0x02,0x24,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x83,0xa0, +0x18,0x00,0xbf,0xaf,0x00,0x00,0xc2,0xa0,0x01,0x00,0x11,0x24,0x21,0x80,0x00,0x00, +0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x02,0x01,0x00,0x02,0x26,0xff,0x00,0x50,0x30, +0x2b,0x18,0x30,0x02,0xfa,0xff,0x60,0x10,0x00,0x00,0x00,0x00,0x2a,0x42,0x00,0x0c, +0x21,0x20,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c, +0x2d,0x0a,0x84,0x34,0x00,0x00,0x83,0x90,0x02,0x80,0x06,0x3c,0x78,0x93,0xc5,0x24, +0x02,0x00,0x02,0x24,0xcf,0x00,0x63,0x30,0x14,0x00,0xa2,0xa0,0x20,0x00,0x63,0x34, +0x20,0x4e,0x02,0x24,0x00,0x00,0x83,0xa0,0x0c,0x00,0xa2,0xac,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x93,0xc4,0x24,0x02,0x80,0x05,0x3c,0x00,0x80,0x06,0x3c, +0x64,0x89,0xa5,0x24,0xe1,0x1c,0x00,0x08,0x30,0x6d,0xc6,0x24,0x03,0x80,0x03,0x3c, +0x00,0x80,0x63,0x24,0x40,0x10,0x04,0x3c,0xff,0xff,0x63,0x30,0x02,0x80,0x02,0x3c, +0x38,0x15,0x42,0x24,0x25,0xc0,0x64,0x00,0x1c,0x25,0x58,0xac,0x80,0x00,0x18,0x27, +0x28,0x25,0x58,0xac,0x80,0x00,0x18,0x27,0x34,0x25,0x58,0xac,0x80,0x00,0x18,0x27, +0x40,0x25,0x58,0xac,0x80,0x00,0x18,0x27,0xe0,0xff,0xbd,0x27,0x4c,0x25,0x58,0xac, +0x80,0x00,0x18,0x27,0x1c,0x00,0xb7,0xaf,0x18,0x00,0xb6,0xaf,0x14,0x00,0xb5,0xaf, +0x10,0x00,0xb4,0xaf,0x0c,0x00,0xb3,0xaf,0x08,0x00,0xb2,0xaf,0x04,0x00,0xb1,0xaf, +0x00,0x00,0xb0,0xaf,0x58,0x25,0x58,0xac,0x28,0x25,0x45,0x8c,0x34,0x25,0x46,0x8c, +0x40,0x25,0x47,0x8c,0x4c,0x25,0x48,0x8c,0x58,0x25,0x49,0x8c,0x80,0x00,0x18,0x27, +0x64,0x25,0x58,0xac,0x21,0x50,0x00,0x03,0x25,0x18,0x64,0x00,0x25,0xb0,0x0e,0x3c, +0x20,0x10,0x04,0x3c,0x80,0x00,0x18,0x27,0x18,0x25,0x43,0xac,0x24,0x25,0x45,0xac, +0x30,0x25,0x46,0xac,0x3c,0x25,0x47,0xac,0x48,0x25,0x48,0xac,0x54,0x25,0x49,0xac, +0xac,0x00,0xc3,0x35,0xb0,0x24,0x44,0xac,0xac,0x24,0x44,0xac,0xbc,0x24,0x44,0xac, +0xb8,0x24,0x44,0xac,0xc8,0x24,0x44,0xac,0xc4,0x24,0x44,0xac,0xd4,0x24,0x44,0xac, +0xd0,0x24,0x44,0xac,0x70,0x25,0x58,0xac,0x60,0x25,0x4a,0xac,0xe0,0x24,0x44,0xac, +0xdc,0x24,0x44,0xac,0xec,0x24,0x44,0xac,0xe8,0x24,0x44,0xac,0xf8,0x24,0x44,0xac, +0xf4,0x24,0x44,0xac,0x00,0x02,0x18,0x27,0x00,0x00,0x68,0x8c,0xe4,0x0a,0x46,0x94, +0x88,0x25,0x58,0xac,0xb0,0x00,0xc3,0x35,0x00,0x00,0x76,0x8c,0x21,0x10,0x05,0x3c, +0x70,0x25,0x52,0x8c,0x23,0x10,0x0c,0x3c,0x22,0x10,0x0d,0x3c,0x02,0x80,0x11,0x3c, +0x02,0x80,0x14,0x3c,0x02,0x80,0x15,0x3c,0x02,0x80,0x17,0x3c,0x00,0x80,0xa3,0x34, +0x24,0x10,0x07,0x3c,0x21,0x98,0x00,0x03,0x23,0x18,0x66,0x00,0x00,0x02,0x18,0x27, +0x54,0x3b,0x26,0x26,0x5c,0x3b,0x8a,0x26,0x64,0x3b,0xa9,0x26,0x6c,0x3b,0xeb,0x26, +0x00,0x04,0x8f,0x35,0x01,0x00,0x08,0x25,0x00,0x40,0xb0,0x35,0x00,0x01,0xce,0x35, +0x6c,0x25,0x52,0xac,0x84,0x25,0x53,0xac,0xe0,0x25,0x4f,0xac,0xa4,0x25,0x48,0xac, +0xb0,0x25,0x43,0xac,0xd4,0x25,0x50,0xac,0xc8,0x25,0x56,0xac,0x00,0x00,0xc7,0xad, +0xc4,0x25,0x47,0xac,0xe4,0x25,0x44,0xac,0x04,0x25,0x44,0xac,0x00,0x25,0x44,0xac, +0x8e,0x25,0x40,0xa4,0x8d,0x25,0x40,0xa0,0x8c,0x25,0x40,0xa0,0xd8,0x25,0x4c,0xac, +0xdc,0x25,0x4c,0xac,0x9c,0x25,0x45,0xac,0xa0,0x25,0x45,0xac,0xa8,0x25,0x45,0xac, +0xac,0x25,0x45,0xac,0xcc,0x25,0x4d,0xac,0xd0,0x25,0x4d,0xac,0xc0,0x25,0x47,0xac, +0xe8,0x25,0x44,0xac,0xf4,0x25,0x58,0xac,0xf0,0x25,0x58,0xac,0x04,0x00,0x29,0xad, +0x5c,0x3b,0x8a,0xae,0x04,0x00,0x6b,0xad,0x64,0x3b,0xa9,0xae,0x04,0x00,0xc6,0xac, +0x6c,0x3b,0xeb,0xae,0x54,0x3b,0x26,0xae,0x04,0x00,0x4a,0xad,0x02,0x80,0x03,0x3c, +0x00,0x14,0x62,0x24,0x00,0x14,0x66,0xac,0x04,0x00,0xc2,0xac,0x54,0x3b,0x22,0xae, +0x04,0x00,0x46,0xac,0x08,0x00,0x58,0xac,0x10,0x00,0x40,0xac,0x00,0x01,0x18,0x27, +0x21,0x48,0x40,0x00,0x18,0x00,0x48,0x24,0x01,0x00,0x07,0x24,0x21,0x18,0x40,0x01, +0x21,0x28,0x00,0x00,0x07,0x00,0x06,0x24,0x21,0x20,0xa8,0x00,0x21,0x10,0xa9,0x00, +0xff,0xff,0xc6,0x24,0x20,0x00,0x58,0xac,0x28,0x00,0x47,0xac,0x18,0x00,0xa5,0x24, +0x00,0x00,0x8a,0xac,0x04,0x00,0x83,0xac,0x00,0x00,0x64,0xac,0x00,0x01,0x18,0x27, +0xf5,0xff,0xc1,0x04,0x21,0x18,0x80,0x00,0x02,0x80,0x02,0x3c,0x64,0x3b,0x49,0x24, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x04,0x00,0x27,0x8d,0xd8,0x14,0x4b,0x24, +0x04,0x00,0x44,0xad,0x02,0x00,0x08,0x24,0x00,0x14,0x6a,0x24,0x21,0x28,0x00,0x00, +0x01,0x00,0x06,0x24,0x21,0x20,0xab,0x00,0x21,0x10,0xaa,0x00,0xff,0xff,0xc6,0x24, +0xe0,0x00,0x58,0xac,0xe8,0x00,0x48,0xac,0x18,0x00,0xa5,0x24,0x00,0x00,0x89,0xac, +0x04,0x00,0x87,0xac,0x00,0x00,0xe4,0xac,0x00,0x02,0x18,0x27,0xf5,0xff,0xc1,0x04, +0x21,0x38,0x80,0x00,0x02,0x80,0x02,0x3c,0x6c,0x3b,0x48,0x24,0x02,0x80,0x03,0x3c, +0x02,0x80,0x02,0x3c,0x04,0x00,0x07,0x8d,0x08,0x15,0x4b,0x24,0x04,0x00,0x24,0xad, +0x00,0x14,0x6a,0x24,0x03,0x00,0x09,0x24,0x21,0x28,0x00,0x00,0x01,0x00,0x06,0x24, +0x21,0x20,0xab,0x00,0x21,0x10,0xaa,0x00,0xff,0xff,0xc6,0x24,0x10,0x01,0x58,0xac, +0x18,0x01,0x49,0xac,0x18,0x00,0xa5,0x24,0x00,0x00,0x88,0xac,0x04,0x00,0x87,0xac, +0x00,0x00,0xe4,0xac,0x00,0x08,0x18,0x27,0xf5,0xff,0xc1,0x04,0x21,0x38,0x80,0x00, +0x1c,0x00,0xb7,0x8f,0x18,0x00,0xb6,0x8f,0x14,0x00,0xb5,0x8f,0x10,0x00,0xb4,0x8f, +0x0c,0x00,0xb3,0x8f,0x08,0x00,0xb2,0x8f,0x04,0x00,0xb1,0x8f,0x00,0x00,0xb0,0x8f, +0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x04,0x00,0x04,0xad,0xc8,0xff,0xbd,0x27, +0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf, +0x68,0x8d,0x73,0x24,0xdc,0x8d,0x52,0x24,0x02,0x80,0x03,0x3c,0xff,0xff,0x02,0x3c, +0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x30,0x00,0xbf,0xaf,0xff,0x1f,0x54,0x34,0x38,0x15,0x70,0x24,0x21,0x88,0x00,0x00, +0x02,0x80,0x15,0x3c,0x63,0x49,0x00,0x0c,0x21,0x20,0x20,0x02,0x90,0x11,0x05,0x8e, +0x6c,0x00,0x66,0x8e,0x6c,0x00,0x43,0x8e,0x48,0x8d,0xa2,0x26,0x1b,0x00,0x44,0x90, +0x21,0x18,0x66,0x00,0x24,0x28,0xb4,0x00,0x00,0x21,0x04,0x00,0x42,0x18,0x03,0x00, +0x00,0x20,0xa5,0x34,0x5c,0x11,0x03,0xae,0x80,0x11,0x04,0xae,0x90,0x11,0x05,0xae, +0x84,0x11,0x04,0xae,0x21,0x30,0x00,0x00,0x21,0x10,0x06,0x02,0x01,0x00,0xc6,0x24, +0x1d,0x00,0xc3,0x28,0xb1,0x11,0x40,0xa0,0x94,0x11,0x40,0xa0,0xfa,0xff,0x60,0x14, +0xce,0x11,0x40,0xa0,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xec,0x11,0x00,0xae, +0xe4,0xff,0x40,0x14,0x94,0x00,0x10,0x26,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c, +0x38,0x15,0x4b,0x24,0x02,0x80,0x02,0x3c,0xdc,0x8d,0x6f,0x24,0x68,0x8d,0x4d,0x24, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x48,0x8d,0x6e,0x24,0x28,0x8d,0x4c,0x24, +0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x20,0x6d,0x00,0x21,0x10,0x6f,0x00, +0x21,0x28,0x2e,0x02,0x21,0x30,0x2c,0x02,0x00,0x00,0x88,0x8c,0x00,0x00,0xa9,0x90, +0x00,0x00,0xc7,0x90,0x00,0x00,0x4a,0x8c,0x21,0x10,0x2b,0x02,0x01,0x00,0x31,0x26, +0x21,0x18,0x6b,0x00,0x1d,0x00,0x24,0x2a,0xf8,0x04,0x68,0xac,0xce,0x04,0x47,0xa0, +0x6c,0x05,0x6a,0xac,0xef,0xff,0x80,0x14,0x94,0x04,0x49,0xa0,0x02,0x80,0x02,0x3c, +0x38,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x04,0x8c,0x6b,0x24, +0xa4,0x8a,0x4c,0x24,0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00, +0x21,0x40,0x2a,0x01,0x21,0x38,0x2b,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90, +0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28, +0xc9,0x03,0x64,0xa0,0xf8,0xff,0x40,0x14,0x38,0x03,0x65,0xa0,0x21,0x10,0x2c,0x02, +0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26, +0x1d,0x00,0x22,0x2a,0x77,0x04,0x64,0xa0,0x5a,0x04,0x65,0xa0,0xeb,0xff,0x40,0x14, +0x05,0x00,0x29,0x25,0x30,0x00,0xbf,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x29,0xb0,0x02,0x3c,0xf8,0xff,0xbd,0x27, +0x00,0x00,0x40,0xac,0x08,0x00,0x44,0x34,0x0c,0x00,0x45,0x34,0x10,0x00,0x46,0x34, +0x04,0x00,0x43,0x34,0x14,0x00,0x47,0x34,0x18,0x00,0x48,0x34,0x1c,0x00,0x49,0x34, +0x20,0x00,0x4a,0x34,0x24,0x00,0x4b,0x34,0x28,0x00,0x4c,0x34,0x2c,0x00,0x4d,0x34, +0x30,0x00,0x4e,0x34,0x34,0x00,0x4f,0x34,0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf, +0x3c,0x00,0x51,0x34,0x38,0x00,0x50,0x34,0x02,0x80,0x02,0x3c,0x00,0x00,0x60,0xac, +0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac,0x21,0x20,0x00,0x00,0x00,0x00,0xc0,0xac, +0xff,0xff,0x05,0x24,0x00,0x00,0xe0,0xac,0x38,0x15,0x46,0x24,0x00,0x00,0x00,0xad, +0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad,0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad, +0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad,0x00,0x00,0xe0,0xad,0x00,0x00,0x00,0xae, +0x00,0x00,0x20,0xae,0x21,0x18,0x86,0x00,0x01,0x00,0x84,0x24,0x08,0x00,0x82,0x28, +0xfc,0xff,0x40,0x14,0xf0,0x04,0x65,0xa0,0x02,0x80,0x02,0x3c,0x38,0x15,0x43,0x24, +0x1f,0x00,0x04,0x24,0x90,0x11,0x62,0x8c,0xff,0xff,0x84,0x24,0xf0,0x00,0x42,0x34, +0x90,0x11,0x62,0xac,0xfb,0xff,0x81,0x04,0x94,0x00,0x63,0x24,0x04,0x00,0xb1,0x8f, +0x00,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x08,0x00,0xbd,0x27,0x48,0xfd,0xbd,0x27, +0xb4,0x02,0xb3,0xaf,0x02,0x80,0x02,0x3c,0x02,0x80,0x13,0x3c,0xf4,0x8e,0x46,0x24, +0x38,0x15,0x63,0x26,0xb0,0x02,0xb2,0xaf,0xac,0x02,0xb1,0xaf,0xa8,0x02,0xb0,0xaf, +0x03,0x00,0x60,0xa0,0x21,0x38,0xa0,0x03,0x90,0x00,0xc8,0x24,0x00,0x00,0xc2,0x8c, +0x04,0x00,0xc3,0x8c,0x08,0x00,0xc4,0x8c,0x0c,0x00,0xc5,0x8c,0x10,0x00,0xc6,0x24, +0x00,0x00,0xe2,0xac,0x04,0x00,0xe3,0xac,0x08,0x00,0xe4,0xac,0x0c,0x00,0xe5,0xac, +0xf6,0xff,0xc8,0x14,0x10,0x00,0xe7,0x24,0x00,0x00,0xc3,0x8c,0x02,0x80,0x02,0x3c, +0x88,0x8f,0x58,0x24,0x00,0x00,0xe3,0xac,0x98,0x00,0xb9,0x27,0x00,0x01,0x12,0x27, +0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x09,0x00,0x04,0x93,0x0d,0x00,0x05,0x93, +0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,0x04,0x00,0x10,0x93,0x06,0x00,0x0c,0x93, +0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,0x0c,0x00,0x0e,0x93,0x0e,0x00,0x06,0x93, +0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,0x0b,0x00,0x0a,0x93,0x0f,0x00,0x0b,0x93, +0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x00,0x22,0x04,0x00,0x00,0x2a,0x05,0x00, +0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,0x25,0x20,0x8f,0x00,0x25,0x28,0xae,0x00, +0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,0x00,0x3c,0x07,0x00,0x00,0x34,0x06,0x00, +0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00, +0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,0x00,0x56,0x0a,0x00,0x00,0x5e,0x0b,0x00, +0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,0x25,0x50,0x47,0x01,0x25,0x58,0x66,0x01, +0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,0x04,0x00,0x29,0xaf,0x08,0x00,0x2a,0xaf, +0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,0x10,0x00,0x39,0x27,0x01,0x00,0x02,0x93, +0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,0x02,0x00,0x04,0x93,0x04,0x00,0x08,0x93, +0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,0x03,0x00,0x07,0x93,0x00,0x12,0x02,0x00, +0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,0x25,0x18,0x68,0x00,0x00,0x24,0x04,0x00, +0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,0x25,0x28,0xa3,0x00,0x00,0x3e,0x07,0x00, +0x00,0x36,0x06,0x00,0x02,0x80,0x02,0x3c,0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00, +0x90,0x90,0x58,0x24,0x04,0x00,0x26,0xaf,0x00,0x00,0x27,0xaf,0x00,0x01,0x12,0x27, +0xa0,0x01,0xb9,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x09,0x00,0x04,0x93, +0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,0x04,0x00,0x10,0x93, +0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,0x0c,0x00,0x0e,0x93, +0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,0x0b,0x00,0x0a,0x93, +0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x00,0x22,0x04,0x00, +0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,0x25,0x20,0x8f,0x00, +0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,0x00,0x3c,0x07,0x00, +0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,0x25,0x38,0xe4,0x00, +0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,0x00,0x56,0x0a,0x00, +0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,0x25,0x50,0x47,0x01, +0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,0x04,0x00,0x29,0xaf, +0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,0x10,0x00,0x39,0x27, +0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,0x02,0x00,0x04,0x93, +0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,0x03,0x00,0x07,0x93, +0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,0x25,0x18,0x68,0x00, +0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,0x25,0x28,0xa3,0x00, +0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,0x25,0x30,0xc5,0x00,0x25,0x38,0xe4,0x00, +0x02,0x80,0x02,0x3c,0x04,0x00,0x26,0xaf,0x00,0x00,0x27,0xaf,0x38,0x15,0x46,0x24, +0x21,0x50,0x00,0x00,0x80,0x20,0x0a,0x00,0x21,0x10,0x9d,0x00,0x00,0x00,0x45,0x8c, +0x01,0x00,0x43,0x25,0xff,0x00,0x6a,0x30,0x21,0x20,0x86,0x00,0x25,0x00,0x42,0x2d, +0xf8,0xff,0x40,0x14,0x18,0x00,0x85,0xac,0x02,0x80,0x02,0x3c,0x38,0x15,0x4b,0x24, +0x21,0x50,0x00,0x00,0xc0,0x10,0x0a,0x00,0x21,0x48,0x5d,0x00,0x21,0x38,0x00,0x00, +0x21,0x40,0x4b,0x00,0x21,0x10,0x27,0x01,0xa0,0x01,0x46,0x90,0x98,0x00,0x45,0x90, +0x01,0x00,0xe4,0x24,0x21,0x18,0x07,0x01,0xff,0x00,0x87,0x30,0x08,0x00,0xe2,0x2c, +0xb4,0x01,0x66,0xa0,0xf7,0xff,0x40,0x14,0xac,0x00,0x65,0xa0,0x01,0x00,0x42,0x25, +0xff,0x00,0x4a,0x30,0x21,0x00,0x43,0x2d,0xef,0xff,0x60,0x14,0xc0,0x10,0x0a,0x00, +0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00, +0x20,0x00,0x63,0x30,0x4f,0x00,0x60,0x10,0x38,0x15,0x64,0x26,0x33,0x00,0x02,0x24, +0xc1,0x02,0x62,0xa1,0x1c,0x00,0x03,0x24,0x0f,0x00,0x02,0x24,0xbc,0x02,0x63,0xa1, +0xbd,0x02,0x62,0xa1,0x38,0x15,0x65,0x26,0x08,0x00,0xa4,0x8c,0xff,0x7f,0x09,0x3c, +0xff,0xff,0x29,0x35,0xc0,0xff,0x02,0x24,0x24,0x20,0x89,0x00,0x24,0x20,0x82,0x00, +0x0c,0x00,0x84,0x34,0xff,0xc0,0x02,0x24,0xc8,0x02,0xa0,0xa0,0x24,0x20,0x82,0x00, +0xc0,0xff,0x02,0x3c,0xc8,0x02,0xa6,0x8c,0xff,0xff,0x42,0x34,0x00,0x18,0x84,0x34, +0x24,0x20,0x82,0x00,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0xbf,0xff,0x03,0x3c, +0x24,0x30,0xc2,0x00,0xff,0xff,0x63,0x34,0x7f,0xff,0x02,0x3c,0x24,0x20,0x83,0x00, +0xff,0xff,0x42,0x34,0x24,0x20,0x82,0x00,0x7f,0xff,0x03,0x24,0x40,0x40,0x84,0x34, +0xff,0xff,0x02,0x3c,0x24,0x20,0x83,0x00,0xff,0x7f,0x42,0x34,0xc8,0x02,0xa6,0xac, +0x24,0x20,0x82,0x00,0xc9,0x02,0xa0,0xa0,0x0c,0x00,0xa6,0x8c,0xff,0x9f,0x02,0x3c, +0xc8,0x02,0xa7,0x8c,0xff,0xff,0x42,0x34,0xff,0xbf,0x03,0x3c,0x10,0x00,0xa8,0x8c, +0xff,0xff,0x63,0x34,0x24,0x20,0x82,0x00,0xff,0xf0,0x02,0x3c,0x24,0x30,0xc3,0x00, +0xff,0xff,0x42,0x34,0xff,0x3f,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x38,0xe2,0x00, +0xb4,0x02,0xb3,0x8f,0x1f,0x00,0x02,0x24,0xb0,0x02,0xb2,0x8f,0xac,0x02,0xb1,0x8f, +0xa8,0x02,0xb0,0x8f,0x24,0x40,0x03,0x01,0xbe,0x02,0xa2,0xa0,0x01,0x00,0x03,0x24, +0xff,0xff,0x02,0x24,0x24,0x30,0xc9,0x00,0xc0,0x02,0xa3,0xa0,0xc2,0x02,0xa2,0xa0, +0xff,0x00,0x03,0x24,0x12,0x00,0x02,0x24,0xb8,0x02,0xbd,0x27,0xc8,0x02,0xa7,0xac, +0x08,0x00,0xa4,0xac,0x10,0x00,0xa8,0xac,0x0c,0x00,0xa6,0xac,0xc4,0x02,0xa3,0xa4, +0xc7,0x02,0xa2,0xa0,0xca,0x02,0xa0,0xa0,0xbf,0x02,0xa0,0xa0,0x08,0x00,0xe0,0x03, +0xc6,0x02,0xa0,0xa0,0x33,0x00,0x02,0x24,0xc1,0x02,0x82,0xa0,0x0d,0x00,0x03,0x24, +0x03,0x00,0x02,0x24,0xbc,0x02,0x83,0xa0,0xd7,0x5a,0x00,0x08,0xbd,0x02,0x82,0xa0, +0x02,0x80,0x18,0x3c,0x38,0x15,0x02,0x27,0xff,0xff,0x03,0x34,0xe0,0xff,0xbd,0x27, +0x18,0x00,0xbf,0xaf,0x21,0x78,0x40,0x00,0x04,0x24,0x43,0xac,0xea,0x02,0x40,0xa0, +0xf4,0x23,0x43,0xac,0xfc,0x23,0x43,0xac,0x00,0x24,0x43,0xac,0x08,0x24,0x40,0xac, +0x0c,0x24,0x40,0xac,0x1f,0x00,0x0e,0x24,0xff,0xff,0xce,0x25,0x80,0x11,0x43,0xac, +0x84,0x11,0x43,0xac,0xfc,0xff,0xc1,0x05,0x94,0x00,0x42,0x24,0x38,0x15,0x04,0x8f, +0xd8,0x02,0xe5,0x8d,0xf0,0xff,0x02,0x3c,0xe8,0x02,0xe7,0x8d,0xfd,0xff,0x03,0x24, +0xff,0xff,0x42,0x34,0x20,0x00,0x0e,0x24,0x24,0x20,0x83,0x00,0x24,0x28,0xa2,0x00, +0xff,0xff,0x0d,0x24,0xff,0xef,0x02,0x3c,0x38,0x15,0x04,0xaf,0xff,0xff,0x42,0x34, +0xd8,0x02,0xe5,0xad,0x02,0x00,0xed,0xa1,0xdb,0x02,0xee,0xa1,0xd8,0x02,0xe0,0xa1, +0xff,0xbf,0x03,0x3c,0x38,0x15,0x08,0x8f,0xd8,0x02,0xe9,0x8d,0x24,0x38,0xe2,0x00, +0xff,0xff,0x63,0x34,0x24,0x38,0xe3,0x00,0xff,0x7f,0x02,0x3c,0x0f,0xff,0x03,0x3c, +0xfe,0xff,0x04,0x24,0xff,0xff,0x42,0x34,0xff,0xff,0x63,0x34,0x24,0x40,0x04,0x01, +0x24,0x38,0xe2,0x00,0x24,0x48,0x23,0x01,0xff,0xdf,0x02,0x3c,0xdf,0xff,0x03,0x24, +0x24,0x40,0x03,0x01,0xff,0xff,0x42,0x34,0x10,0x00,0x03,0x3c,0x24,0x38,0xe2,0x00, +0x25,0x48,0x23,0x01,0x0a,0x00,0x02,0x24,0x00,0x02,0x03,0x24,0x38,0x15,0x08,0xaf, +0x02,0x80,0x0a,0x3c,0xd6,0x02,0xe2,0xa1,0xd0,0x02,0xe3,0xa5,0x00,0x01,0x02,0x24, +0x49,0x00,0x03,0x24,0xe8,0x02,0xe7,0xad,0xd8,0x02,0xe9,0xad,0x04,0x94,0x4a,0x25, +0x3e,0x00,0x0c,0x24,0x01,0x00,0x0b,0x24,0x11,0x00,0xa3,0xa3,0xce,0x02,0xe2,0xa5, +0xd0,0x07,0x03,0x24,0x44,0x00,0x02,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa2,0xa3, +0x10,0x00,0xa5,0x27,0x47,0x00,0x02,0x24,0x21,0x20,0x40,0x01,0xe0,0x86,0xc6,0x24, +0xd4,0x02,0xec,0xa1,0xcc,0x02,0xee,0xa5,0x01,0x00,0xeb,0xa1,0x0c,0x00,0x43,0xad, +0x14,0x00,0x4b,0xa1,0x05,0x00,0xed,0xa1,0xd2,0x02,0xec,0xa1,0xd3,0x02,0xee,0xa1, +0xd5,0x02,0xee,0xa1,0x12,0x00,0xa2,0xa3,0xe1,0x1c,0x00,0x0c,0x13,0x00,0xa0,0xa3, +0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x50,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3, +0x12,0x22,0x40,0xa0,0x41,0x00,0x03,0x24,0x52,0x00,0x02,0x24,0x02,0x80,0x07,0x3c, +0xac,0x94,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,0xd0,0x07,0x02,0x24, +0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00, +0xd4,0x4e,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf, +0xe1,0x1c,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27,0x24,0x00,0xb1,0xaf, +0x02,0x80,0x11,0x3c,0x38,0x15,0x23,0x8e,0xef,0xff,0x02,0x24,0x02,0x80,0x07,0x3c, +0x24,0x18,0x62,0x00,0xf7,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x44,0x00,0x02,0x24, +0x1c,0x95,0xe7,0x24,0x2c,0x00,0xb3,0xaf,0x10,0x00,0xa2,0xa3,0x01,0x00,0x13,0x24, +0x64,0x00,0x02,0x24,0x01,0x80,0x06,0x3c,0x38,0x15,0x23,0xae,0x28,0x00,0xb2,0xaf, +0x20,0x00,0xb0,0xaf,0x21,0x20,0xe0,0x00,0x38,0x15,0x30,0x26,0x47,0x00,0x12,0x24, +0x10,0x00,0xa5,0x27,0x49,0x00,0x03,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xf3,0xa0, +0x00,0x96,0xc6,0x24,0x30,0x00,0xbf,0xaf,0x11,0x00,0xa3,0xa3,0x12,0x00,0xb2,0xa3, +0x06,0x00,0x00,0xa6,0xe1,0x1c,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x38,0x15,0x23,0x8e, +0xff,0xff,0x02,0x24,0xff,0x00,0x4a,0x30,0xfb,0xff,0x02,0x24,0x24,0x18,0x62,0x00, +0x3f,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x02,0x80,0x08,0x3c,0x3b,0x00,0x02,0x24, +0xc8,0x94,0x08,0x25,0x19,0x00,0xa2,0xa3,0x01,0x00,0x07,0x3c,0xd0,0x07,0x02,0x24, +0x01,0x80,0x06,0x3c,0x38,0x15,0x23,0xae,0x56,0x30,0xe9,0x34,0x08,0x03,0x0a,0xae, +0x43,0x00,0x03,0x24,0xf4,0x98,0xe7,0x34,0x18,0x00,0xa5,0x27,0x0c,0x00,0x02,0xad, +0x14,0x00,0x13,0xa1,0x21,0x20,0x00,0x01,0xec,0x96,0xc6,0x24,0x18,0x00,0xb2,0xa3, +0x1a,0x00,0xa3,0xa3,0x10,0x03,0x07,0xae,0x14,0x03,0x09,0xae,0x1b,0x00,0xa0,0xa3, +0x0c,0x03,0x00,0xae,0x18,0x03,0x00,0xae,0xe1,0x1c,0x00,0x0c,0x1c,0x03,0x00,0xae, +0x1e,0x00,0x02,0x24,0x4a,0x00,0x03,0x24,0x25,0x03,0x02,0xa2,0x20,0x03,0x03,0xa2, +0x45,0x00,0x02,0x24,0x46,0x00,0x03,0x24,0x21,0x03,0x02,0xa2,0x22,0x03,0x03,0xa2, +0x40,0x00,0x02,0x24,0x23,0x00,0x03,0x24,0x23,0x03,0x02,0xa2,0x24,0x03,0x03,0xa2, +0x30,0x00,0xbf,0x8f,0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f, +0x20,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27, +0x3b,0x00,0x02,0x24,0x43,0x00,0x03,0x24,0x10,0x00,0xa2,0xa3,0x11,0x00,0xa3,0xa3, +0x36,0x00,0x02,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x07,0x3c,0xe4,0x94,0xe7,0x24, +0x12,0x00,0xa2,0xa3,0x0f,0x18,0x60,0xa0,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24, +0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xec,0x9b,0xc6,0x24, +0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0xe1,0x1c,0x00,0x0c, +0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x52,0x00,0x03,0x24, +0x10,0x00,0xa3,0xa3,0x94,0x39,0x40,0xa4,0x54,0x00,0x03,0x24,0x53,0x00,0x02,0x24, +0x02,0x80,0x07,0x3c,0x38,0x95,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3, +0xf4,0x01,0x02,0x24,0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27, +0x21,0x20,0xe0,0x00,0x18,0x50,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0, +0x18,0x00,0xbf,0xaf,0xe1,0x1c,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x02,0x80,0x04,0x3c, +0xd8,0xff,0xbd,0x27,0x4c,0x39,0x84,0x24,0x21,0x28,0x00,0x00,0x20,0x00,0xbf,0xaf, +0x58,0x45,0x00,0x0c,0x0a,0x00,0x06,0x24,0x02,0x80,0x07,0x3c,0x38,0x15,0xe7,0x24, +0x10,0x24,0xe3,0x8c,0xfd,0xff,0x02,0x24,0x02,0x80,0x08,0x3c,0x24,0x18,0x62,0x00, +0xfe,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x05,0x00,0x02,0x24,0x10,0x24,0xe3,0xac, +0x14,0x24,0xe2,0xa0,0x28,0x00,0x03,0x24,0x46,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3, +0x15,0x24,0xe3,0xa0,0x4b,0x00,0x02,0x24,0x42,0x00,0x03,0x24,0x54,0x95,0x08,0x25, +0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0xd0,0x07,0x03,0x24,0x01,0x00,0x02,0x24, +0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0x00,0x01,0xe0,0x50,0xc6,0x24, +0x12,0x24,0xe0,0xa4,0x0c,0x00,0x03,0xad,0x14,0x00,0x02,0xa1,0xe1,0x1c,0x00,0x0c, +0x13,0x00,0xa0,0xa3,0x20,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x28,0x00,0xbd,0x27,0xd8,0xff,0xbd,0x27,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x20,0x00,0xbf,0xaf,0x21,0x80,0x80,0x00, +0x21,0x98,0xa0,0x00,0x21,0x88,0xc0,0x00,0x21,0x90,0x00,0x00,0x00,0x00,0x04,0x82, +0x99,0x48,0x00,0x0c,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x01,0x00,0x10,0x26, +0xff,0xff,0x10,0x26,0x00,0x00,0x04,0x92,0x2b,0x00,0x02,0x24,0x00,0x1e,0x04,0x00, +0x03,0x1e,0x03,0x00,0x41,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0x02,0x24, +0x30,0x00,0x22,0x12,0x00,0x1e,0x04,0x00,0x07,0x00,0x20,0x16,0x21,0x18,0x80,0x00, +0x00,0x1e,0x04,0x00,0x03,0x1e,0x03,0x00,0x30,0x00,0x02,0x24,0x3b,0x00,0x62,0x10, +0x0a,0x00,0x11,0x24,0x21,0x18,0x80,0x00,0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00, +0x1a,0x00,0x40,0x10,0xff,0x00,0x64,0x30,0xa9,0xff,0x82,0x24,0x61,0x00,0x83,0x2c, +0xff,0x00,0x45,0x30,0x09,0x00,0x60,0x10,0x41,0x00,0x86,0x2c,0xc9,0xff,0x82,0x24, +0xff,0x00,0x45,0x30,0x05,0x00,0xc0,0x10,0x3a,0x00,0x87,0x2c,0xd0,0xff,0x82,0x24, +0x02,0x00,0xe0,0x10,0xff,0x00,0x05,0x24,0xff,0x00,0x45,0x30,0x2a,0x10,0xb1,0x00, +0x0a,0x00,0x40,0x10,0x18,0x00,0x51,0x02,0x01,0x00,0x10,0x26,0x12,0x10,0x00,0x00, +0x2b,0x18,0x52,0x00,0x23,0x00,0x60,0x14,0x21,0x90,0xa2,0x00,0x00,0x00,0x03,0x92, +0x00,0x00,0x00,0x00,0xe8,0xff,0x60,0x14,0xff,0x00,0x64,0x30,0x02,0x00,0x60,0x12, +0x21,0x10,0x40,0x02,0x00,0x00,0x70,0xae,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x28,0x00,0xbd,0x27,0x03,0x1e,0x03,0x00,0x30,0x00,0x02,0x24,0xce,0xff,0x62,0x14, +0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x82,0x78,0x00,0x02,0x24,0x03,0x00,0x62,0x10, +0x58,0x00,0x02,0x24,0xd0,0xff,0x62,0x14,0x21,0x18,0x80,0x00,0x02,0x00,0x10,0x26, +0x00,0x00,0x04,0x92,0x73,0x5c,0x00,0x08,0x10,0x00,0x11,0x24,0x01,0x00,0x10,0x26, +0x00,0x00,0x04,0x92,0x6a,0x5c,0x00,0x08,0x10,0x00,0x02,0x24,0x9f,0x5c,0x00,0x08, +0x08,0x00,0x11,0x24,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0x02,0x24,0x08,0x00,0xe0,0x03, +0x28,0x00,0xbd,0x27,0x21,0x48,0x80,0x00,0x31,0x00,0xc0,0x14,0x21,0x50,0x00,0x00, +0x00,0x00,0x87,0x90,0x30,0x00,0x02,0x24,0x00,0x1e,0x07,0x00,0x03,0x1e,0x03,0x00, +0x2e,0x00,0x62,0x10,0x0a,0x00,0x06,0x24,0x02,0x80,0x02,0x3c,0x40,0x92,0x4b,0x24, +0xff,0x00,0xe8,0x30,0x21,0x10,0x0b,0x01,0x00,0x00,0x44,0x90,0x00,0x1e,0x07,0x00, +0x03,0x1e,0x03,0x00,0x44,0x00,0x82,0x30,0x02,0x00,0x87,0x30,0xd0,0xff,0x63,0x24, +0x1a,0x00,0x40,0x10,0x04,0x00,0x84,0x30,0x07,0x00,0x80,0x14,0x2b,0x10,0x66,0x00, +0x21,0x10,0x00,0x01,0x02,0x00,0xe0,0x10,0xe0,0xff,0x03,0x25,0xff,0x00,0x62,0x30, +0xc9,0xff,0x43,0x24,0x2b,0x10,0x66,0x00,0x10,0x00,0x40,0x10,0x18,0x00,0x46,0x01, +0x01,0x00,0x29,0x25,0x00,0x00,0x27,0x91,0x00,0x00,0x00,0x00,0xff,0x00,0xe8,0x30, +0x12,0x10,0x00,0x00,0x21,0x50,0x43,0x00,0x21,0x10,0x0b,0x01,0x00,0x00,0x44,0x90, +0x00,0x1e,0x07,0x00,0x03,0x1e,0x03,0x00,0x44,0x00,0x82,0x30,0x02,0x00,0x87,0x30, +0xd0,0xff,0x63,0x24,0xe8,0xff,0x40,0x14,0x04,0x00,0x84,0x30,0x02,0x00,0xa0,0x10, +0x00,0x00,0x00,0x00,0x00,0x00,0xa9,0xac,0x08,0x00,0xe0,0x03,0x21,0x10,0x40,0x01, +0x00,0x00,0x87,0x90,0xc1,0x5c,0x00,0x08,0x02,0x80,0x02,0x3c,0x01,0x00,0x89,0x24, +0x00,0x00,0x27,0x91,0x78,0x00,0x02,0x24,0x00,0x1e,0x07,0x00,0x03,0x1e,0x03,0x00, +0xcd,0xff,0x62,0x14,0x08,0x00,0x06,0x24,0x01,0x00,0x22,0x91,0x02,0x80,0x03,0x3c, +0x40,0x92,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x90,0x00,0x00,0x00,0x00, +0x44,0x00,0x84,0x30,0xc5,0xff,0x80,0x10,0x02,0x80,0x02,0x3c,0x01,0x00,0x29,0x25, +0x00,0x00,0x27,0x91,0xc1,0x5c,0x00,0x08,0x10,0x00,0x06,0x24,0xe8,0xff,0xbd,0x27, +0x10,0x00,0xbf,0xaf,0x00,0x00,0x83,0x80,0x2d,0x00,0x02,0x24,0x04,0x00,0x62,0x10, +0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,0xb7,0x5c,0x00,0x08,0x18,0x00,0xbd,0x27, +0xb7,0x5c,0x00,0x0c,0x01,0x00,0x84,0x24,0x10,0x00,0xbf,0x8f,0x23,0x10,0x02,0x00, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xd8,0xff,0xbd,0x27,0x1c,0x00,0xb3,0xaf, +0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x20,0x00,0xbf,0xaf, +0x21,0x80,0x80,0x00,0x21,0x90,0xa0,0x00,0x21,0x98,0xc0,0x00,0x21,0x88,0x00,0x00, +0x00,0x00,0x04,0x82,0x99,0x48,0x00,0x0c,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14, +0x01,0x00,0x10,0x26,0xff,0xff,0x10,0x26,0x00,0x00,0x03,0x82,0x2d,0x00,0x02,0x24, +0x0f,0x00,0x62,0x10,0x21,0x20,0x00,0x02,0x21,0x28,0x40,0x02,0x53,0x5c,0x00,0x0c, +0x21,0x30,0x60,0x02,0x12,0x00,0x40,0x04,0x21,0x18,0x40,0x00,0x23,0x10,0x02,0x00, +0x0a,0x10,0x71,0x00,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27, +0x01,0x00,0x10,0x26,0x21,0x20,0x00,0x02,0x21,0x28,0x40,0x02,0x53,0x5c,0x00,0x0c, +0x21,0x30,0x60,0x02,0xff,0xff,0x11,0x24,0xf0,0xff,0x41,0x04,0x21,0x18,0x40,0x00, +0xf0,0xff,0x20,0x16,0x00,0x80,0x02,0x3c,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0x7f,0x02,0x3c, +0xff,0xff,0x42,0x34,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x78,0x0c,0x00,0x00,0x01,0x00,0x00,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x01,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x02,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x03,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x04,0x5d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x05,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x06,0x59,0x78,0x0c,0x00,0x00, +0x01,0x00,0x07,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x08,0x55,0x78,0x0c,0x00,0x00, +0x01,0x00,0x09,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x0a,0x51,0x78,0x0c,0x00,0x00, +0x01,0x00,0x0b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x0c,0x4d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x0d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x0e,0x49,0x78,0x0c,0x00,0x00, +0x01,0x00,0x0f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x10,0x45,0x78,0x0c,0x00,0x00, +0x01,0x00,0x11,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x12,0x41,0x78,0x0c,0x00,0x00, +0x01,0x00,0x13,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x14,0x3d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x15,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x16,0x39,0x78,0x0c,0x00,0x00, +0x01,0x00,0x17,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x18,0x35,0x78,0x0c,0x00,0x00, +0x01,0x00,0x19,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x1a,0x31,0x78,0x0c,0x00,0x00, +0x01,0x00,0x1b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x1c,0x2d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x1d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x1e,0x29,0x78,0x0c,0x00,0x00, +0x01,0x00,0x1f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x20,0x25,0x78,0x0c,0x00,0x00, +0x01,0x00,0x21,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x22,0x21,0x78,0x0c,0x00,0x00, +0x01,0x00,0x23,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x24,0x1d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x25,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x26,0x19,0x78,0x0c,0x00,0x00, +0x01,0x00,0x27,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x28,0x15,0x78,0x0c,0x00,0x00, +0x01,0x00,0x29,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x2a,0x11,0x78,0x0c,0x00,0x00, +0x01,0x00,0x2b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x2c,0x0d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x2d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x2e,0x09,0x78,0x0c,0x00,0x00, +0x01,0x00,0x2f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x30,0x05,0x78,0x0c,0x00,0x00, +0x01,0x00,0x31,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x32,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x33,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x34,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x35,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x36,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x37,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x38,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x39,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3a,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x3b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3c,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x3d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3e,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x3f,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x40,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x41,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x42,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x43,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x44,0x5d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x45,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x46,0x59,0x78,0x0c,0x00,0x00, +0x01,0x00,0x47,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x48,0x55,0x78,0x0c,0x00,0x00, +0x01,0x00,0x49,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x4a,0x51,0x78,0x0c,0x00,0x00, +0x01,0x00,0x4b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x4c,0x4d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x4d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x4e,0x49,0x78,0x0c,0x00,0x00, +0x01,0x00,0x4f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x50,0x45,0x78,0x0c,0x00,0x00, +0x01,0x00,0x51,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x52,0x41,0x78,0x0c,0x00,0x00, +0x01,0x00,0x53,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x54,0x3d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x55,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x56,0x39,0x78,0x0c,0x00,0x00, +0x01,0x00,0x57,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x58,0x35,0x78,0x0c,0x00,0x00, +0x01,0x00,0x59,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x5a,0x31,0x78,0x0c,0x00,0x00, +0x01,0x00,0x5b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x5c,0x2d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x5d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x5e,0x29,0x78,0x0c,0x00,0x00, +0x01,0x00,0x5f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x60,0x25,0x78,0x0c,0x00,0x00, +0x01,0x00,0x61,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x62,0x21,0x78,0x0c,0x00,0x00, +0x01,0x00,0x63,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x64,0x1d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x65,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x66,0x19,0x78,0x0c,0x00,0x00, +0x01,0x00,0x67,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x68,0x15,0x78,0x0c,0x00,0x00, +0x01,0x00,0x69,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x6a,0x11,0x78,0x0c,0x00,0x00, +0x01,0x00,0x6b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x6c,0x0d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x6d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x6e,0x09,0x78,0x0c,0x00,0x00, +0x01,0x00,0x6f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x70,0x05,0x78,0x0c,0x00,0x00, +0x01,0x00,0x71,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x72,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x73,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x74,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x75,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x76,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x77,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x78,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x79,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7a,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x7b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7c,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x7d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7e,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x7f,0x01,0x78,0x0c,0x00,0x00,0x1e,0x00,0x00,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x01,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x02,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x03,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x04,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x05,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x06,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x07,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x08,0x3e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x09,0x40,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0a,0x42,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x0b,0x44,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0c,0x46,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x0d,0x48,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0e,0x48,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x0f,0x4a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x10,0x4a,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x11,0x4c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x12,0x4c,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x13,0x4e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x14,0x50,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x15,0x50,0x78,0x0c,0x00,0x00,0x1e,0x00,0x16,0x50,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x17,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x18,0x52,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x19,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1a,0x54,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x1b,0x54,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1c,0x54,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x1d,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1e,0x56,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x1f,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x20,0x56,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x21,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x22,0x58,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x23,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x24,0x58,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x25,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x26,0x5a,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x27,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x28,0x5c,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x29,0x5c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2a,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x2b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2c,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x2d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2e,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x2f,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x30,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x31,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x32,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x33,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x34,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x35,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x36,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x37,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x38,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x39,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3a,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x3b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3c,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x3d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3e,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x3f,0x5e,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x08,0x00,0x00, +0x00,0x00,0x04,0x03,0x04,0x08,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x08,0x00,0x00, +0x00,0xfc,0x00,0x00,0x0c,0x08,0x00,0x00,0x0a,0x00,0x00,0x04,0x10,0x08,0x00,0x00, +0xff,0x10,0x10,0x80,0x14,0x08,0x00,0x00,0x10,0x3d,0x0c,0x02,0x18,0x08,0x00,0x00, +0xc5,0x03,0x00,0x00,0x1c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x24,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x28,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x2c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x30,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x34,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x38,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x3c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x40,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x44,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x4c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x54,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x08,0x00,0x00, +0x65,0xa9,0x65,0xa9,0x5c,0x08,0x00,0x00,0x65,0xa9,0x65,0xa9,0x60,0x08,0x00,0x00, +0x30,0x01,0x7f,0x0f,0x64,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x68,0x08,0x00,0x00, +0x30,0x01,0x7f,0x0f,0x6c,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x70,0x08,0x00,0x00, +0x00,0x03,0x00,0x03,0x74,0x08,0x00,0x00,0x00,0x03,0x00,0x03,0x78,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x7c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x94,0x08,0x00,0x00,0xfe,0xff,0xff,0xff,0x98,0x08,0x00,0x00, +0x10,0x20,0x30,0x40,0x9c,0x08,0x00,0x00,0x50,0x60,0x70,0x00,0xb0,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0xe0,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x04,0x0e,0x00,0x00, +0x03,0x03,0x03,0x03,0x08,0x0e,0x00,0x00,0x03,0x03,0x00,0x00,0x0c,0x0e,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x14,0x0e,0x00,0x00, +0x03,0x03,0x03,0x03,0x18,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x1c,0x0e,0x00,0x00, +0x03,0x03,0x03,0x03,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x09,0x00,0x00, +0x23,0x00,0x00,0x00,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x09,0x00,0x00, +0x33,0x13,0x32,0x03,0x08,0x0a,0x00,0x00,0x00,0x86,0x88,0x8f,0x2c,0x0a,0x00,0x00, +0x00,0x00,0x92,0x00,0x00,0x0c,0x00,0x00,0x80,0x00,0x00,0x00,0x04,0x0c,0x00,0x00, +0x33,0x54,0x00,0x00,0x08,0x0c,0x00,0x00,0xe4,0x00,0x00,0x00,0x0c,0x0c,0x00,0x00, +0x6c,0x6c,0x6c,0x6c,0x10,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x20,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x24,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x28,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x2c,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x30,0x0c,0x00,0x00,0x44,0x6a,0xe9,0x8d,0x34,0x0c,0x00,0x00, +0xcd,0x52,0x96,0x46,0x38,0x0c,0x00,0x00,0x90,0x5a,0x01,0x48,0x3c,0x0c,0x00,0x00, +0x64,0x97,0x97,0x1a,0x40,0x0c,0x00,0x00,0x3f,0x42,0x7c,0x1f,0x44,0x0c,0x00,0x00, +0xb7,0x00,0x01,0x00,0x48,0x0c,0x00,0x00,0x00,0x00,0x02,0xec,0x4c,0x0c,0x00,0x00, +0x03,0x03,0xfc,0x00,0x50,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x54,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x58,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x5c,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x60,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x64,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x68,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x6c,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x70,0x0c,0x00,0x00,0x0d,0x00,0x5a,0x2c,0x74,0x0c,0x00,0x00, +0x1b,0x15,0x86,0x01,0x78,0x0c,0x00,0x00,0x1f,0x00,0x00,0x00,0x7c,0x0c,0x00,0x00, +0x12,0x16,0xb9,0x00,0x80,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x84,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0x88,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x8c,0x0c,0x00,0x00, +0x00,0x00,0x20,0x08,0x90,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x94,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0x98,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x9c,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xa0,0x0c,0x00,0x00,0x92,0x24,0x49,0x00,0xa4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xa8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xb0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xb8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x0c,0x00,0x00, +0x92,0x24,0x49,0x00,0xc0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xc4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xc8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xcc,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xd0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xd8,0x0c,0x00,0x00,0x27,0x24,0xb2,0x64,0xdc,0x0c,0x00,0x00, +0x32,0x69,0x76,0x00,0xe0,0x0c,0x00,0x00,0x22,0x22,0x22,0x00,0xe4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xe8,0x0c,0x00,0x00,0x02,0x43,0x64,0x07,0x00,0x0d,0x00,0x00, +0x80,0x07,0x00,0x00,0x04,0x0d,0x00,0x00,0x03,0x04,0x00,0x00,0x08,0x0d,0x00,0x00, +0x7f,0x90,0x00,0x00,0x0c,0x0d,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x0d,0x00,0x00, +0x99,0x99,0x69,0xa0,0x14,0x0d,0x00,0x00,0x67,0x3c,0x99,0x99,0x18,0x0d,0x00,0x00, +0x6b,0x5b,0x8f,0x6a,0x1c,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x24,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x2c,0x0d,0x00,0x00,0x75,0x19,0x97,0xcc,0x30,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x34,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x3c,0x0d,0x00,0x00,0x93,0x72,0x02,0x00,0x40,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x44,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x50,0x0d,0x00,0x00,0x0a,0x14,0x37,0x64,0x54,0x0d,0x00,0x00, +0x02,0xbd,0x4d,0x02,0x58,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x0d,0x00,0x00, +0x64,0x20,0x03,0x30,0x60,0x0d,0x00,0x00,0x68,0xde,0x53,0x46,0x64,0x0d,0x00,0x00, +0x3c,0x8a,0x51,0x00,0x68,0x0d,0x00,0x00,0x06,0x01,0x00,0x00,0xff,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x74,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x34,0x01,0x00,0x00, +0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x34,0x01,0x00,0x00, +0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x30,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x13,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x17,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x06,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x06,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x08,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x0c,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x1f,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x01,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x38,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x02,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x01,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x01,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x04,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0xd4,0x29,0x00,0x80,0x00,0xb7,0x00,0x00,0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00, +0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00, +0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00, +0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00, +0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00, +0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00, +0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00, +0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00, +0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00, +0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00, +0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00, +0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00, +0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00, +0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00, +0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00, +0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00, +0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00, +0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00, +0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00, +0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00, +0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00, +0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00, +0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00, +0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00, +0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00, +0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00, +0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00, +0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00, +0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00, +0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00, +0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00, +0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00, +0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00, +0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00, +0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00, +0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00, +0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00, +0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00, +0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00, +0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00, +0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00, +0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00, +0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00, +0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00, +0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00, +0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00, +0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00, +0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00, +0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00, +0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00, +0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00, +0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00, +0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00, +0xff,0xff,0xff,0x00,0x00,0xb7,0x00,0x00,0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00, +0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00, +0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00, +0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00, +0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00, +0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00, +0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00, +0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00, +0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00, +0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00, +0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00, +0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00, +0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00, +0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00, +0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00, +0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00, +0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00, +0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00, +0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00, +0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00, +0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00, +0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00, +0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00, +0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00, +0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00, +0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00, +0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00, +0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00, +0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00, +0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00, +0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00, +0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00, +0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00, +0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00, +0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00, +0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00, +0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00, +0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00, +0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00, +0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00, +0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00, +0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00, +0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00, +0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00, +0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00, +0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00, +0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00, +0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00, +0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00, +0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00, +0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00, +0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00, +0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00, +0xff,0xff,0xff,0x00,0x0a,0x00,0x00,0x00,0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52, +0x65,0x71,0x00,0x00,0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00, +0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,0x63,0x52,0x65,0x71,0x00,0x00,0x00,0x00, +0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00,0x00,0x00, +0x4f,0x6e,0x50,0x72,0x6f,0x62,0x65,0x52,0x65,0x71,0x00,0x00,0x4f,0x6e,0x50,0x72, +0x6f,0x62,0x65,0x52,0x73,0x70,0x00,0x00,0x44,0x6f,0x52,0x65,0x73,0x65,0x72,0x76, +0x65,0x64,0x00,0x00,0x44,0x6f,0x52,0x65,0x73,0x65,0x72,0x76,0x65,0x64,0x00,0x00, +0x4f,0x6e,0x42,0x65,0x61,0x63,0x6f,0x6e,0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x54, +0x49,0x4d,0x00,0x00,0x4f,0x6e,0x44,0x69,0x73,0x61,0x73,0x73,0x6f,0x63,0x00,0x00, +0x4f,0x6e,0x41,0x75,0x74,0x68,0x00,0x00,0x4f,0x6e,0x44,0x65,0x41,0x75,0x74,0x68, +0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x63,0x74,0x69,0x6f,0x6e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xf0,0x87,0x01,0x80,0x2c,0x13,0x01,0x80,0x10,0x00,0x00,0x00, +0xfc,0x87,0x01,0x80,0x34,0x13,0x01,0x80,0x20,0x00,0x00,0x00,0x08,0x88,0x01,0x80, +0x2c,0x13,0x01,0x80,0x30,0x00,0x00,0x00,0x18,0x88,0x01,0x80,0x34,0x13,0x01,0x80, +0x40,0x00,0x00,0x00,0x28,0x88,0x01,0x80,0x3c,0x13,0x01,0x80,0x50,0x00,0x00,0x00, +0x34,0x88,0x01,0x80,0x44,0x13,0x01,0x80,0x00,0x00,0x00,0x00,0x40,0x88,0x01,0x80, +0xac,0x13,0x01,0x80,0x00,0x00,0x00,0x00,0x4c,0x88,0x01,0x80,0xac,0x13,0x01,0x80, +0x80,0x00,0x00,0x00,0x58,0x88,0x01,0x80,0x4c,0x13,0x01,0x80,0x90,0x00,0x00,0x00, +0x64,0x88,0x01,0x80,0x54,0x13,0x01,0x80,0xa0,0x00,0x00,0x00,0x6c,0x88,0x01,0x80, +0x5c,0x13,0x01,0x80,0xb0,0x00,0x00,0x00,0x78,0x88,0x01,0x80,0x94,0x13,0x01,0x80, +0xc0,0x00,0x00,0x00,0x80,0x88,0x01,0x80,0x9c,0x13,0x01,0x80,0xd0,0x00,0x00,0x00, +0x8c,0x88,0x01,0x80,0xa4,0x13,0x01,0x80,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, +0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46,0x00,0x00,0x00,0x00,0x25,0x64,0x2e,0x00, +0x25,0x68,0x68,0x58,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x5f,0x57, +0x44,0x4f,0x47,0x00,0x6c,0x89,0x01,0x80,0x6c,0x89,0x01,0x80,0x31,0x10,0x10,0x00, +0x00,0x30,0x00,0x00,0x31,0x20,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x28,0x10,0x00, +0x00,0x30,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x30,0x00,0x00,0x31,0x2f,0x10,0x10, +0x00,0x30,0x00,0x00,0x31,0x30,0x18,0x00,0x00,0x30,0x00,0x00,0x31,0x30,0x20,0x10, +0x00,0x30,0x00,0x00,0x22,0x20,0x18,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x14,0x08, +0x00,0x20,0x00,0x00,0x22,0x21,0x1c,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x08, +0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x18, +0x00,0x20,0x00,0x00,0x1a,0x19,0x18,0x10,0x00,0x18,0x00,0x00,0x12,0x11,0x10,0x08, +0x00,0x10,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x02, +0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x06, +0x00,0x08,0x00,0x00,0x08,0x07,0x06,0x04,0x00,0x06,0x00,0x00,0x06,0x05,0x04,0x02, +0x00,0x04,0x00,0x00,0x06,0x05,0x04,0x03,0x00,0x04,0x00,0x00,0x05,0x04,0x03,0x02, +0x00,0x03,0x00,0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05,0x05,0x04,0x04,0x03, +0x06,0x05,0x05,0x04,0x04,0x03,0x03,0x03,0x05,0x04,0x04,0x03,0x03,0x02,0x02,0x02, +0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05,0x05,0x04,0x04,0x03,0x05,0x04,0x04, +0x03,0x03,0x02,0x02,0x02,0x04,0x03,0x03,0x02,0x02,0x01,0x01,0x01,0x00,0x00,0x00, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08, +0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x18,0x20,0x20,0x20,0x30,0x08,0x08,0x08, +0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20,0x20,0x20,0x20,0x30, +0x30,0x08,0x10,0x20,0x20,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20, +0x08,0x08,0x08,0x08,0x18,0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x18,0x18,0x18, +0x18,0x18,0x20,0x30,0x30,0x08,0x08,0x08,0x08,0x20,0x20,0x30,0x30,0x08,0x10,0x20, +0x20,0x20,0x30,0x30,0x30,0x30,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08, +0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x00, +0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00, +0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11,0x10,0x08,0x00,0x22, +0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09, +0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20, +0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x0a,0x09,0x08,0x02, +0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00, +0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x22, +0x21,0x1c,0x08,0x00,0x31,0x30,0x18,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09, +0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x1a,0x19,0x18, +0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10, +0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31,0x2c,0x10,0x10,0x00, +0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22, +0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,0x21, +0x14,0x08,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2c,0x10,0x10,0x00,0x0a,0x09,0x08, +0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x20,0x18,0x08, +0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x2f,0x10,0x10,0x00, +0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00,0x0a,0x09,0x08,0x04, +0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00, +0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a, +0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11, +0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08, +0x04,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00, +0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,0x21,0x14,0x08,0x00, +0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a, +0x09,0x08,0x00,0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21, +0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x0a,0x09,0x08, +0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04, +0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00, +0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31, +0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09, +0x08,0x04,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20, +0x18,0x00,0x22,0x20,0x18,0x08,0x00,0x31,0x30,0x18,0x00,0x00,0x31,0x2c,0x10,0x10, +0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00, +0x22,0x21,0x1c,0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00,0x31, +0x30,0x18,0x00,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00, +0x01,0x02,0x04,0x08,0x02,0x04,0x08,0x0c,0x10,0x18,0x20,0x30,0x02,0x04,0x08,0x0c, +0x10,0x18,0x20,0x30,0x06,0x0c,0x10,0x18,0x24,0x30,0x3c,0x48,0x48,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x26,0x2a,0x00,0x00,0x00,0x00, +0x21,0x27,0x29,0x2a,0x00,0x00,0x00,0x1f,0x23,0x28,0x2a,0x2c,0x2d,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00, +0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00, +0x60,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xd8,0x00,0x00,0x00, +0x50,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00, +0x40,0x01,0x00,0x00,0x90,0x01,0x00,0x00,0xe0,0x01,0x00,0x00,0x30,0x02,0x00,0x00, +0x2c,0x01,0x00,0x00,0x40,0x01,0x00,0x00,0xe0,0x01,0x00,0x00,0x48,0x03,0x00,0x00, +0x60,0x09,0x00,0x00,0x60,0x09,0x00,0x00,0x80,0x0c,0x00,0x00,0xa0,0x0f,0x00,0x00, +0xa0,0x0f,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00, +0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x18,0x00,0x00,0x00, +0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x60,0x00,0x00,0x00, +0x6c,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x50,0x00,0x00,0x00, +0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0xf0,0x00,0x00,0x00, +0x18,0x01,0x00,0x00,0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xf0,0x00,0x00,0x00, +0xa4,0x01,0x00,0x00,0xb0,0x04,0x00,0x00,0xb0,0x04,0x00,0x00,0x40,0x06,0x00,0x00, +0xd0,0x07,0x00,0x00,0xd0,0x07,0x00,0x00,0x2c,0x05,0x00,0x80,0x20,0x05,0x00,0x80, +0x14,0x05,0x00,0x80,0x08,0x05,0x00,0x80,0xfc,0x04,0x00,0x80,0xf0,0x04,0x00,0x80, +0xe4,0x04,0x00,0x80,0xd8,0x04,0x00,0x80,0xcc,0x04,0x00,0x80,0xc0,0x04,0x00,0x80, +0x78,0x04,0x00,0x80,0x2c,0x00,0x2a,0xb0,0x40,0x89,0x01,0x80,0x67,0x66,0x66,0x66, +0xb4,0x65,0x00,0x80,0x18,0x66,0x00,0x80,0xe8,0x65,0x00,0x80,0xdc,0x66,0x00,0x80, +0xac,0x66,0x00,0x80,0x7c,0x66,0x00,0x80,0x4c,0x66,0x00,0x80,0xd4,0x77,0x00,0x80, +0xe0,0x77,0x00,0x80,0xec,0x77,0x00,0x80,0xf8,0x77,0x00,0x80,0xd4,0x77,0x00,0x80, +0xd4,0x77,0x00,0x80,0xd4,0x77,0x00,0x80,0xd4,0x77,0x00,0x80,0x04,0x78,0x00,0x80, +0x10,0x78,0x00,0x80,0x1c,0x78,0x00,0x80,0x28,0x78,0x00,0x80,0x38,0x15,0x02,0x80, +0x38,0x15,0x02,0x80,0x84,0x0e,0x25,0xb0,0x88,0x0e,0x25,0xb0,0x8c,0x0e,0x25,0xb0, +0xd0,0x0e,0x25,0xb0,0xd8,0x0e,0x25,0xb0,0x20,0x08,0x25,0xb0,0xfe,0x01,0x80,0x7f, +0xe2,0x01,0x80,0x78,0xc7,0x01,0xc0,0x71,0xae,0x01,0x80,0x6b,0x95,0x01,0x40,0x65, +0x7f,0x01,0xc0,0x5f,0x69,0x01,0x40,0x5a,0x55,0x01,0x40,0x55,0x42,0x01,0x80,0x50, +0x30,0x01,0x00,0x4c,0x1f,0x01,0xc0,0x47,0x0f,0x01,0xc0,0x43,0x00,0x01,0x00,0x40, +0xf2,0x00,0x80,0x3c,0xe4,0x00,0x00,0x39,0xd7,0x00,0xc0,0x35,0xcb,0x00,0xc0,0x32, +0xc0,0x00,0x00,0x30,0xb5,0x00,0x40,0x2d,0xab,0x00,0xc0,0x2a,0xa2,0x00,0x80,0x28, +0x98,0x00,0x00,0x26,0x90,0x00,0x00,0x24,0x88,0x00,0x00,0x22,0x80,0x00,0x00,0x20, +0x79,0x00,0x40,0x1e,0x72,0x00,0x80,0x1c,0x6c,0x00,0x00,0x1b,0x66,0x00,0x80,0x19, +0x60,0x00,0x00,0x18,0x5b,0x00,0xc0,0x16,0x56,0x00,0x80,0x15,0x51,0x00,0x40,0x14, +0x4c,0x00,0x00,0x13,0x48,0x00,0x00,0x12,0x44,0x00,0x00,0x11,0x40,0x00,0x00,0x10, +0x36,0x35,0x2e,0x25,0x1c,0x12,0x09,0x04,0x33,0x32,0x2b,0x23,0x1a,0x11,0x08,0x04, +0x30,0x2f,0x29,0x21,0x19,0x10,0x08,0x03,0x2d,0x2d,0x27,0x1f,0x18,0x0f,0x08,0x03, +0x2b,0x2a,0x25,0x1e,0x16,0x0e,0x07,0x03,0x28,0x28,0x22,0x1c,0x15,0x0d,0x07,0x03, +0x26,0x25,0x21,0x1b,0x14,0x0d,0x06,0x03,0x24,0x23,0x1f,0x19,0x13,0x0c,0x06,0x03, +0x22,0x21,0x1d,0x18,0x11,0x0b,0x06,0x02,0x20,0x20,0x1b,0x16,0x11,0x08,0x05,0x02, +0x1f,0x1e,0x1a,0x15,0x10,0x0a,0x05,0x02,0x1d,0x1c,0x18,0x14,0x0f,0x0a,0x05,0x02, +0x1b,0x1a,0x17,0x13,0x0e,0x09,0x04,0x02,0x1a,0x19,0x16,0x12,0x0d,0x09,0x04,0x02, +0x18,0x17,0x15,0x11,0x0c,0x08,0x04,0x02,0x17,0x16,0x13,0x10,0x0c,0x08,0x04,0x02, +0x16,0x15,0x12,0x0f,0x0b,0x07,0x04,0x01,0x14,0x14,0x11,0x0e,0x0b,0x07,0x03,0x02, +0x13,0x13,0x10,0x0d,0x0a,0x06,0x03,0x01,0x12,0x12,0x0f,0x0c,0x09,0x06,0x03,0x01, +0x11,0x11,0x0f,0x0c,0x09,0x06,0x03,0x01,0x10,0x10,0x0e,0x0b,0x08,0x05,0x03,0x01, +0x0f,0x0f,0x0d,0x0b,0x08,0x05,0x03,0x01,0x0e,0x0e,0x0c,0x0a,0x08,0x05,0x02,0x01, +0x0d,0x0d,0x0c,0x0a,0x07,0x05,0x02,0x01,0x0d,0x0c,0x0b,0x09,0x07,0x04,0x02,0x01, +0x0c,0x0c,0x0a,0x09,0x06,0x04,0x02,0x01,0x0b,0x0b,0x0a,0x08,0x06,0x04,0x02,0x01, +0x0b,0x0a,0x09,0x08,0x06,0x04,0x02,0x01,0x0a,0x0a,0x09,0x07,0x05,0x03,0x02,0x01, +0x0a,0x09,0x08,0x07,0x05,0x03,0x02,0x01,0x09,0x09,0x08,0x06,0x05,0x03,0x01,0x01, +0x09,0x08,0x07,0x06,0x04,0x03,0x01,0x01,0x36,0x35,0x2e,0x1b,0x00,0x00,0x00,0x00, +0x33,0x32,0x2b,0x19,0x00,0x00,0x00,0x00,0x30,0x2f,0x29,0x18,0x00,0x00,0x00,0x00, +0x2d,0x2d,0x17,0x17,0x00,0x00,0x00,0x00,0x2b,0x2a,0x25,0x15,0x00,0x00,0x00,0x00, +0x28,0x28,0x24,0x14,0x00,0x00,0x00,0x00,0x26,0x25,0x21,0x13,0x00,0x00,0x00,0x00, +0x24,0x23,0x1f,0x12,0x00,0x00,0x00,0x00,0x22,0x21,0x1d,0x11,0x00,0x00,0x00,0x00, +0x20,0x20,0x1b,0x10,0x00,0x00,0x00,0x00,0x1f,0x1e,0x1a,0x0f,0x00,0x00,0x00,0x00, +0x1d,0x1c,0x18,0x0e,0x00,0x00,0x00,0x00,0x1b,0x1a,0x17,0x0e,0x00,0x00,0x00,0x00, +0x1a,0x19,0x16,0x0d,0x00,0x00,0x00,0x00,0x18,0x17,0x15,0x0c,0x00,0x00,0x00,0x00, +0x17,0x16,0x13,0x0b,0x00,0x00,0x00,0x00,0x16,0x15,0x12,0x0b,0x00,0x00,0x00,0x00, +0x14,0x14,0x11,0x0a,0x00,0x00,0x00,0x00,0x13,0x13,0x10,0x0a,0x00,0x00,0x00,0x00, +0x12,0x12,0x0f,0x09,0x00,0x00,0x00,0x00,0x11,0x11,0x0f,0x09,0x00,0x00,0x00,0x00, +0x10,0x10,0x0e,0x08,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0d,0x08,0x00,0x00,0x00,0x00, +0x0e,0x0e,0x0c,0x07,0x00,0x00,0x00,0x00,0x0d,0x0d,0x0c,0x07,0x00,0x00,0x00,0x00, +0x0d,0x0c,0x0b,0x06,0x00,0x00,0x00,0x00,0x0c,0x0c,0x0a,0x06,0x00,0x00,0x00,0x00, +0x0b,0x0b,0x0a,0x06,0x00,0x00,0x00,0x00,0x0b,0x0a,0x09,0x05,0x00,0x00,0x00,0x00, +0x0a,0x0a,0x09,0x05,0x00,0x00,0x00,0x00,0x0a,0x09,0x08,0x05,0x00,0x00,0x00,0x00, +0x09,0x09,0x08,0x05,0x00,0x00,0x00,0x00,0x09,0x08,0x07,0x04,0x00,0x00,0x00,0x00, +0x06,0x00,0x2a,0xb0,0x05,0x00,0x2a,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x28,0x28,0x28,0x28,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x41,0x41,0x41,0x41,0x41,0x41,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x01,0x01,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x42,0x42,0x42,0x42,0x42,0x42,0x02, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, +0x02,0x02,0x02,0x10,0x10,0x10,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x2d,0x5c,0x7c,0x2f,0x00,0x00,0x00,0x00, +0xaa,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6b,0x34,0xf0,0x00,0x6b,0x34,0xf0, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6b,0x25,0x60, +0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x09,0x66,0xd0,0xb8,0xff,0xff,0xff,0xff,}; + +u8 Rtl8192SEFwMainArray[MainArrayLength] = { +0x0, }; + +u8 Rtl8192SEFwDataArray[DataArrayLength] = { +0x0, }; + +u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength] = { +0x01c,0x07000000, +0x800,0x00040000, +0x804,0x00008003, +0x808,0x0000fc00, +0x80c,0x0000000a, +0x810,0x10005088, +0x814,0x020c3d10, +0x818,0x00200185, +0x81c,0x00000000, +0x820,0x01000000, +0x824,0x00390004, +0x828,0x01000000, +0x82c,0x00390004, +0x830,0x00000004, +0x834,0x00690200, +0x838,0x00000004, +0x83c,0x00690200, +0x840,0x00010000, +0x844,0x00010000, +0x848,0x00000000, +0x84c,0x00000000, +0x850,0x00000000, +0x854,0x00000000, +0x858,0x48484848, +0x85c,0x65a965a9, +0x860,0x0f7f0130, +0x864,0x0f7f0130, +0x868,0x0f7f0130, +0x86c,0x0f7f0130, +0x870,0x03000700, +0x874,0x03000300, +0x878,0x00020002, +0x87c,0x004f0201, +0x880,0xa8300ac1, +0x884,0x00000058, +0x888,0x00000008, +0x88c,0x00000004, +0x890,0x00000000, +0x894,0xfffffffe, +0x898,0x40302010, +0x89c,0x00706050, +0x8b0,0x00000000, +0x8e0,0x00000000, +0x8e4,0x00000000, +0xe00,0x30333333, +0xe04,0x2a2d2e2f, +0xe08,0x00003232, +0xe10,0x30333333, +0xe14,0x2a2d2e2f, +0xe18,0x30333333, +0xe1c,0x2a2d2e2f, +0xe30,0x01007c00, +0xe34,0x01004800, +0xe38,0x1000dc1f, +0xe3c,0x10008c1f, +0xe40,0x021400a0, +0xe44,0x281600a0, +0xe48,0xf8000001, +0xe4c,0x00002910, +0xe50,0x01007c00, +0xe54,0x01004800, +0xe58,0x1000dc1f, +0xe5c,0x10008c1f, +0xe60,0x021400a0, +0xe64,0x281600a0, +0xe6c,0x00002910, +0xe70,0x31ed92fb, +0xe74,0x361536fb, +0xe78,0x361536fb, +0xe7c,0x361536fb, +0xe80,0x361536fb, +0xe84,0x000d92fb, +0xe88,0x000d92fb, +0xe8c,0x31ed92fb, +0xed0,0x31ed92fb, +0xed4,0x31ed92fb, +0xed8,0x000d92fb, +0xedc,0x000d92fb, +0xee0,0x000d92fb, +0xee4,0x015e5448, +0xee8,0x21555448, +0x900,0x00000000, +0x904,0x00000023, +0x908,0x00000000, +0x90c,0x01121313, +0xa00,0x00d047c8, +0xa04,0x80ff0008, +0xa08,0x8ccd8300, +0xa0c,0x2e62120f, +0xa10,0x9500bb78, +0xa14,0x11144028, +0xa18,0x00881117, +0xa1c,0x89140f00, +0xa20,0x1a1b0000, +0xa24,0x090e1317, +0xa28,0x00000204, +0xa2c,0x10d30000, +0xc00,0x40071d40, +0xc04,0x00a05633, +0xc08,0x000000e4, +0xc0c,0x6c6c6c6c, +0xc10,0x08800000, +0xc14,0x40000100, +0xc18,0x08000000, +0xc1c,0x40000100, +0xc20,0x08000000, +0xc24,0x40000100, +0xc28,0x08000000, +0xc2c,0x40000100, +0xc30,0x6de9ac44, +0xc34,0x469652cf, +0xc38,0x49795994, +0xc3c,0x0a979764, +0xc40,0x1f7c403f, +0xc44,0x000100b7, +0xc48,0xec020000, +0xc4c,0x007f037f, +0xc50,0x69543420, +0xc54,0x433c0094, +0xc58,0x69543420, +0xc5c,0x433c0094, +0xc60,0x69543420, +0xc64,0x433c0094, +0xc68,0x69543420, +0xc6c,0x433c0094, +0xc70,0x2c7f000d, +0xc74,0x0186155b, +0xc78,0x0000001f, +0xc7c,0x00b91612, +0xc80,0x40000100, +0xc84,0x20f60000, +0xc88,0x20000080, +0xc8c,0x20200000, +0xc90,0x40000100, +0xc94,0x00000000, +0xc98,0x40000100, +0xc9c,0x00000000, +0xca0,0x00492492, +0xca4,0x00000000, +0xca8,0x00000000, +0xcac,0x00000000, +0xcb0,0x00000000, +0xcb4,0x00000000, +0xcb8,0x00000000, +0xcbc,0x28000000, +0xcc0,0x00000000, +0xcc4,0x00000000, +0xcc8,0x00000000, +0xccc,0x00000000, +0xcd0,0x00000000, +0xcd4,0x00000000, +0xcd8,0x64b22427, +0xcdc,0x00766932, +0xce0,0x00222222, +0xce4,0x00000000, +0xce8,0x37644302, +0xcec,0x2f97d40c, +0xd00,0x00000750, +0xd04,0x00000403, +0xd08,0x0000907f, +0xd0c,0x00000001, +0xd10,0xa0633333, +0xd14,0x33333c63, +0xd18,0x6a8f5b6b, +0xd1c,0x00000000, +0xd20,0x00000000, +0xd24,0x00000000, +0xd28,0x00000000, +0xd2c,0xcc979975, +0xd30,0x00000000, +0xd34,0x00000000, +0xd38,0x00000000, +0xd3c,0x00027293, +0xd40,0x00000000, +0xd44,0x00000000, +0xd48,0x00000000, +0xd50,0x6437140a, +0xd54,0x024dbd02, +0xd58,0x00000000, +0xd5c,0x30032064, +0xd60,0x4653de68, +0xd64,0x00518a3c, +0xd68,0x00002101, +0xf14,0x00000003, +0xf4c,0x00000000, +0xf00,0x00000300, +}; + +u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength] = { +0x0, }; + +u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength] = { +0x844,0xffffffff,0x00010000, +0x804,0x0000000f,0x00000001, +0x824,0x00f0000f,0x00300004, +0x82c,0x00f0000f,0x00100002, +0x870,0x04000000,0x00000001, +0x864,0x00000400,0x00000000, +0x878,0x000f000f,0x00000002, +0xe74,0x0f000000,0x00000002, +0xe78,0x0f000000,0x00000002, +0xe7c,0x0f000000,0x00000002, +0xe80,0x0f000000,0x00000002, +0x90c,0x000000ff,0x00000011, +0xc04,0x000000ff,0x00000011, +0xd04,0x0000000f,0x00000001, +0x1f4,0xffff0000,0x00007777, +0x234,0xf8000000,0x0000000a, +}; + +u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength] = { +0x804,0x0000000f,0x00000003, +0x824,0x00f0000f,0x00300004, +0x82c,0x00f0000f,0x00300002, +0x870,0x04000000,0x00000001, +0x864,0x00000400,0x00000000, +0x878,0x000f000f,0x00000002, +0xe74,0x0f000000,0x00000002, +0xe78,0x0f000000,0x00000002, +0xe7c,0x0f000000,0x00000002, +0xe80,0x0f000000,0x00000002, +0x90c,0x000000ff,0x00000011, +0xc04,0x000000ff,0x00000033, +0xd04,0x0000000f,0x00000003, +0x1f4,0xffff0000,0x00007777, +0x234,0xf8000000,0x0000000a, +}; + +u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength] = { +0x804,0x0000000f,0x00000003, +0x824,0x00f0000f,0x00300004, +0x82c,0x00f0000f,0x00300004, +0x870,0x04000000,0x00000001, +0x864,0x00000400,0x00000001, +0x878,0x000f000f,0x00020002, +0xe74,0x0f000000,0x00000006, +0xe78,0x0f000000,0x00000006, +0xe7c,0x0f000000,0x00000006, +0xe80,0x0f000000,0x00000006, +0x90c,0x000000ff,0x00000033, +0xc04,0x000000ff,0x00000033, +0xd04,0x0000000f,0x00000003, +0x1f4,0xffff0000,0x0000ffff, +0x234,0xf8000000,0x00000013, +}; + +u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength] = { +0xe00,0xffffffff,0x06090909, +0xe04,0xffffffff,0x00030406, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x0a0c0d0e, +0xe14,0xffffffff,0x04070809, +0xe18,0xffffffff,0x0a0c0d0e, +0xe1c,0xffffffff,0x04070809, +0xe00,0xffffffff,0x04040404, +0xe04,0xffffffff,0x00020204, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x02040404, +0xe14,0xffffffff,0x00000002, +0xe18,0xffffffff,0x02040404, +0xe1c,0xffffffff,0x00000002, +0xe00,0xffffffff,0x04040404, +0xe04,0xffffffff,0x00020204, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x02040404, +0xe14,0xffffffff,0x00000002, +0xe18,0xffffffff,0x02040404, +0xe1c,0xffffffff,0x00000002, +0xe00,0xffffffff,0x02020202, +0xe04,0xffffffff,0x00020202, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x02020202, +0xe14,0xffffffff,0x00000002, +0xe18,0xffffffff,0x02020202, +0xe1c,0xffffffff,0x00000002, +}; + +u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength] = { +0x000,0x00030159, +0x001,0x00030250, +0x002,0x00010000, +0x010,0x0008000f, +0x011,0x000231fc, +0x010,0x000c000f, +0x011,0x0003f9f8, +0x010,0x0002000f, +0x011,0x00020101, +0x014,0x0001093e, +0x014,0x0009093e, +0x015,0x0000f8f4, +0x017,0x000f6500, +0x01a,0x00013056, +0x01b,0x00060000, +0x01c,0x00000300, +0x01e,0x00031059, +0x021,0x00054000, +0x022,0x0000083c, +0x023,0x00001558, +0x024,0x00000060, +0x025,0x00022583, +0x026,0x0000f200, +0x027,0x000eacf1, +0x028,0x0009bd54, +0x029,0x00004582, +0x02a,0x00000001, +0x02b,0x00021334, +0x02a,0x00000000, +0x02b,0x0000000a, +0x02a,0x00000001, +0x02b,0x00000808, +0x02b,0x00053333, +0x02c,0x0000000c, +0x02a,0x00000002, +0x02b,0x00000808, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000003, +0x02b,0x00000808, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000004, +0x02b,0x00000808, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000005, +0x02b,0x00000709, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x00000006, +0x02b,0x00000709, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000007, +0x02b,0x00000709, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000008, +0x02b,0x00000709, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000009, +0x02b,0x0000060a, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000a, +0x02b,0x0000060a, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x0000000b, +0x02b,0x0000060a, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x0000000c, +0x02b,0x0000060a, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x0000000d, +0x02b,0x0000050b, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000e, +0x02b,0x0000050b, +0x02b,0x00066623, +0x02c,0x0000001a, +0x02a,0x000e4000, +0x030,0x00020000, +0x031,0x000b9631, +0x032,0x0000130d, +0x033,0x00000187, +0x013,0x00019e6c, +0x013,0x00015e94, +0x000,0x00010159, +0x018,0x0000f401, +0x0fe,0x00000000, +0x01e,0x0003105b, +0x0fe,0x00000000, +0x000,0x00030159, +0x010,0x0004000f, +0x011,0x000203f9, +}; + +u32 Rtl8192SERadioB_Array[RadioB_ArrayLength] = { +0x000,0x00030159, +0x001,0x00001041, +0x002,0x00011000, +0x005,0x00080fc0, +0x007,0x000fc803, +0x013,0x00017cb0, +0x013,0x00011cc0, +0x013,0x0000dc60, +0x013,0x00008c60, +0x013,0x00004450, +0x013,0x00000020, +}; + +u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength] = { +0x000,0x00030159, +0x001,0x00030250, +0x002,0x00010000, +0x010,0x0008000f, +0x011,0x000231fc, +0x010,0x000c000f, +0x011,0x0003f9f8, +0x014,0x0001093e, +0x014,0x0009093e, +0x015,0x000198f4, +0x017,0x000f6500, +0x01a,0x00013056, +0x01b,0x00060000, +0x01c,0x00000300, +0x01e,0x00031059, +0x021,0x00054000, +0x022,0x0000083c, +0x023,0x00001558, +0x024,0x00000060, +0x025,0x00022583, +0x026,0x0000f200, +0x027,0x000eacf1, +0x028,0x000dbd54, +0x029,0x00004582, +0x02a,0x00000001, +0x02b,0x00021334, +0x02a,0x00000000, +0x02b,0x0000000a, +0x02a,0x00000001, +0x02b,0x00000808, +0x02b,0x00053333, +0x02c,0x0000000c, +0x02a,0x00000002, +0x02b,0x00000808, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000003, +0x02b,0x00000808, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000004, +0x02b,0x00000808, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000005, +0x02b,0x00000709, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x00000006, +0x02b,0x00000709, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000007, +0x02b,0x00000709, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000008, +0x02b,0x00000709, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000009, +0x02b,0x0000060a, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000a, +0x02b,0x0000060a, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x0000000b, +0x02b,0x0000060a, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x0000000c, +0x02b,0x0000060a, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x0000000d, +0x02b,0x0000050b, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000e, +0x02b,0x0000050b, +0x02b,0x00066623, +0x02c,0x0000001a, +0x02a,0x000e4000, +0x030,0x00020000, +0x031,0x000b9631, +0x033,0x00000187, +0x013,0x00019e6c, +0x013,0x00015e94, +0x000,0x00010159, +0x018,0x0000f401, +0x0fe,0x00000000, +0x01e,0x0003105b, +0x0fe,0x00000000, +0x000,0x00030159, +0x010,0x0004000f, +0x011,0x000203f9, +}; + +u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength] = { +0x000,0x00030159, +0x001,0x00030250, +0x002,0x00010000, +0x010,0x0008000f, +0x011,0x000231fc, +0x010,0x000c000f, +0x011,0x0003f9f8, +0x014,0x0001093e, +0x014,0x0009093e, +0x015,0x000198f4, +0x017,0x000f6500, +0x01a,0x00013056, +0x01b,0x00060000, +0x01c,0x00000300, +0x01e,0x00031059, +0x021,0x00054000, +0x022,0x0000083c, +0x023,0x00001558, +0x024,0x00000060, +0x025,0x00022583, +0x026,0x0000f200, +0x027,0x000eacf1, +0x028,0x000dbd54, +0x029,0x00004582, +0x02a,0x00000001, +0x02b,0x00021334, +0x02a,0x00000000, +0x02b,0x0000000a, +0x02a,0x00000001, +0x02b,0x00000808, +0x02b,0x00053333, +0x02c,0x0000000c, +0x02a,0x00000002, +0x02b,0x00000808, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000003, +0x02b,0x00000808, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000004, +0x02b,0x00000808, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000005, +0x02b,0x00000709, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x00000006, +0x02b,0x00000709, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000007, +0x02b,0x00000709, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000008, +0x02b,0x00000709, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000009, +0x02b,0x0000060a, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000a, +0x02b,0x0000060a, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x0000000b, +0x02b,0x0000060a, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x0000000c, +0x02b,0x0000060a, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x0000000d, +0x02b,0x0000050b, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000e, +0x02b,0x0000050b, +0x02b,0x00066623, +0x02c,0x0000001a, +0x02a,0x000e4000, +0x030,0x00020000, +0x031,0x000b9631, +0x033,0x00000187, +0x013,0x00019e6c, +0x013,0x00015e94, +0x000,0x00010159, +0x018,0x0000f401, +0x0fe,0x00000000, +0x01e,0x0003105b, +0x0fe,0x00000000, +0x000,0x00030159, +0x010,0x0004000f, +0x011,0x000203f9, +}; + +u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength] = { +0x000,0x00030159, +0x001,0x00001041, +0x002,0x00011000, +0x005,0x00080fc0, +0x007,0x000fc803, +}; + +u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength] = { +0x020,0x00000035, +0x048,0x0000000e, +0x049,0x000000f0, +0x04a,0x00000077, +0x04b,0x00000083, +0x0b5,0x00000021, +0x0dc,0x000000ff, +0x0dd,0x000000ff, +0x0de,0x000000ff, +0x0df,0x000000ff, +0x116,0x00000000, +0x117,0x00000000, +0x118,0x00000000, +0x119,0x00000000, +0x11a,0x00000000, +0x11b,0x00000000, +0x11c,0x00000000, +0x11d,0x00000000, +0x160,0x0000000b, +0x161,0x0000000b, +0x162,0x0000000b, +0x163,0x0000000b, +0x164,0x0000000b, +0x165,0x0000000b, +0x166,0x0000000b, +0x167,0x0000000b, +0x168,0x0000000b, +0x169,0x0000000b, +0x16a,0x0000000b, +0x16b,0x0000000b, +0x16c,0x0000000b, +0x16d,0x0000000b, +0x16e,0x0000000b, +0x16f,0x0000000b, +0x170,0x0000000b, +0x171,0x0000000b, +0x172,0x0000000b, +0x173,0x0000000b, +0x174,0x0000000b, +0x175,0x0000000b, +0x176,0x0000000b, +0x177,0x0000000b, +0x178,0x0000000b, +0x179,0x0000000b, +0x17a,0x0000000b, +0x17b,0x0000000b, +0x17c,0x0000000b, +0x17d,0x0000000b, +0x17e,0x0000000b, +0x17f,0x0000000b, +0x236,0x0000000c, +0x503,0x00000022, +0x560,0x00000000, +}; + +u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength] = { +0x0, }; + +u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength] = { +0xc78,0x7f000001, +0xc78,0x7f010001, +0xc78,0x7e020001, +0xc78,0x7d030001, +0xc78,0x7c040001, +0xc78,0x7b050001, +0xc78,0x7a060001, +0xc78,0x79070001, +0xc78,0x78080001, +0xc78,0x77090001, +0xc78,0x760a0001, +0xc78,0x750b0001, +0xc78,0x740c0001, +0xc78,0x730d0001, +0xc78,0x720e0001, +0xc78,0x710f0001, +0xc78,0x70100001, +0xc78,0x6f110001, +0xc78,0x6f120001, +0xc78,0x6e130001, +0xc78,0x6d140001, +0xc78,0x6d150001, +0xc78,0x6c160001, +0xc78,0x6b170001, +0xc78,0x6a180001, +0xc78,0x6a190001, +0xc78,0x691a0001, +0xc78,0x681b0001, +0xc78,0x671c0001, +0xc78,0x661d0001, +0xc78,0x651e0001, +0xc78,0x641f0001, +0xc78,0x63200001, +0xc78,0x4c210001, +0xc78,0x4b220001, +0xc78,0x4a230001, +0xc78,0x49240001, +0xc78,0x48250001, +0xc78,0x47260001, +0xc78,0x46270001, +0xc78,0x45280001, +0xc78,0x44290001, +0xc78,0x2c2a0001, +0xc78,0x2b2b0001, +0xc78,0x2a2c0001, +0xc78,0x292d0001, +0xc78,0x282e0001, +0xc78,0x272f0001, +0xc78,0x26300001, +0xc78,0x25310001, +0xc78,0x24320001, +0xc78,0x23330001, +0xc78,0x22340001, +0xc78,0x09350001, +0xc78,0x08360001, +0xc78,0x07370001, +0xc78,0x06380001, +0xc78,0x05390001, +0xc78,0x043a0001, +0xc78,0x033b0001, +0xc78,0x023c0001, +0xc78,0x013d0001, +0xc78,0x003e0001, +0xc78,0x003f0001, +0xc78,0x7f400001, +0xc78,0x7f410001, +0xc78,0x7e420001, +0xc78,0x7d430001, +0xc78,0x7c440001, +0xc78,0x7b450001, +0xc78,0x7a460001, +0xc78,0x79470001, +0xc78,0x78480001, +0xc78,0x77490001, +0xc78,0x764a0001, +0xc78,0x754b0001, +0xc78,0x744c0001, +0xc78,0x734d0001, +0xc78,0x724e0001, +0xc78,0x714f0001, +0xc78,0x70500001, +0xc78,0x6f510001, +0xc78,0x6f520001, +0xc78,0x6e530001, +0xc78,0x6d540001, +0xc78,0x6d550001, +0xc78,0x6c560001, +0xc78,0x6b570001, +0xc78,0x6a580001, +0xc78,0x6a590001, +0xc78,0x695a0001, +0xc78,0x685b0001, +0xc78,0x675c0001, +0xc78,0x665d0001, +0xc78,0x655e0001, +0xc78,0x645f0001, +0xc78,0x63600001, +0xc78,0x4c610001, +0xc78,0x4b620001, +0xc78,0x4a630001, +0xc78,0x49640001, +0xc78,0x48650001, +0xc78,0x47660001, +0xc78,0x46670001, +0xc78,0x45680001, +0xc78,0x44690001, +0xc78,0x2c6a0001, +0xc78,0x2b6b0001, +0xc78,0x2a6c0001, +0xc78,0x296d0001, +0xc78,0x286e0001, +0xc78,0x276f0001, +0xc78,0x26700001, +0xc78,0x25710001, +0xc78,0x24720001, +0xc78,0x23730001, +0xc78,0x22740001, +0xc78,0x09750001, +0xc78,0x08760001, +0xc78,0x07770001, +0xc78,0x06780001, +0xc78,0x05790001, +0xc78,0x047a0001, +0xc78,0x037b0001, +0xc78,0x027c0001, +0xc78,0x017d0001, +0xc78,0x007e0001, +0xc78,0x007f0001, +0xc78,0x3000001e, +0xc78,0x3001001e, +0xc78,0x3002001e, +0xc78,0x3003001e, +0xc78,0x3004001e, +0xc78,0x3405001e, +0xc78,0x3806001e, +0xc78,0x3e07001e, +0xc78,0x3e08001e, +0xc78,0x4409001e, +0xc78,0x460a001e, +0xc78,0x480b001e, +0xc78,0x480c001e, +0xc78,0x4e0d001e, +0xc78,0x560e001e, +0xc78,0x5a0f001e, +0xc78,0x5e10001e, +0xc78,0x6211001e, +0xc78,0x6c12001e, +0xc78,0x7213001e, +0xc78,0x7214001e, +0xc78,0x7215001e, +0xc78,0x7216001e, +0xc78,0x7217001e, +0xc78,0x7218001e, +0xc78,0x7219001e, +0xc78,0x721a001e, +0xc78,0x721b001e, +0xc78,0x721c001e, +0xc78,0x721d001e, +0xc78,0x721e001e, +0xc78,0x721f001e, +}; + +u32 Rtl8192SEAGCTAB_1TArray[AGCTAB_1TArrayLength] = { +0x0, }; + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg.h @@ -0,0 +1,63 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef __INC_HAL8192SE_FW_IMG_H +#define __INC_HAL8192SE_FW_IMG_H + +#include + +/*Created on 2010/ 4/12, 5:56*/ + +#define ImgArrayLength 87000 +extern u8 Rtl8192SEFwImgArray[ImgArrayLength]; +#define MainArrayLength 1 +extern u8 Rtl8192SEFwMainArray[MainArrayLength]; +#define DataArrayLength 1 +extern u8 Rtl8192SEFwDataArray[DataArrayLength]; +#define PHY_REG_2T2RArrayLength 372 +extern u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength]; +#define PHY_REG_1T2RArrayLength 1 +extern u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength]; +#define PHY_ChangeTo_1T1RArrayLength 48 +extern u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength]; +#define PHY_ChangeTo_1T2RArrayLength 45 +extern u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength]; +#define PHY_ChangeTo_2T2RArrayLength 45 +extern u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength]; +#define PHY_REG_Array_PGLength 84 +extern u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength]; +#define RadioA_1T_ArrayLength 202 +extern u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength]; +#define RadioB_ArrayLength 22 +extern u32 Rtl8192SERadioB_Array[RadioB_ArrayLength]; +#define RadioA_to1T_ArrayLength 196 +extern u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength]; +#define RadioA_to2T_ArrayLength 196 +extern u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength]; +#define RadioB_GM_ArrayLength 10 +extern u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength]; +#define MAC_2T_ArrayLength 106 +extern u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength]; +#define MACPHY_Array_PGLength 1 +extern u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength]; +#define AGCTAB_ArrayLength 320 +extern u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength]; +#define AGCTAB_1TArrayLength 1 +extern u32 Rtl8192SEAGCTAB_1TArray[AGCTAB_1TArrayLength]; + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg492.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg492.c @@ -0,0 +1,5610 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +/*Created on 2009/ 7/23, 5: 4*/ + +#ifdef RTL8192SE +#include "r8192S_hwimg.h" + +u8 Rtl8192SEFwImgArray[ImgArrayLength] = { +0x92,0x81,0x31,0x70,0x30,0x00,0x00,0x00,0x08,0x84,0x00,0x00,0x48,0xa4,0x00,0x00, +0x30,0x00,0x00,0x00,0xc0,0xa2,0x00,0x00,0x31,0x00,0x02,0x00,0x07,0x20,0x16,0x06, +0x92,0x81,0x01,0x01,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x25,0xb0,0x1a,0x3c,0x80,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,0x80,0x00,0x7b,0x37, +0x00,0x00,0x5b,0xaf,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c, +0x80,0x00,0x7b,0x37,0x00,0x00,0x5b,0xaf,0x00,0x80,0x1a,0x3c,0x44,0x7c,0x5a,0x27, +0x08,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x04,0x00,0xa1,0xaf,0x08,0x00,0xa2,0xaf,0x0c,0x00,0xa3,0xaf,0x10,0x00,0xa4,0xaf, +0x14,0x00,0xa5,0xaf,0x18,0x00,0xa6,0xaf,0x1c,0x00,0xa7,0xaf,0x20,0x00,0xa8,0xaf, +0x24,0x00,0xa9,0xaf,0x28,0x00,0xaa,0xaf,0x2c,0x00,0xab,0xaf,0x30,0x00,0xac,0xaf, +0x34,0x00,0xad,0xaf,0x38,0x00,0xae,0xaf,0x3c,0x00,0xaf,0xaf,0x12,0x40,0x00,0x00, +0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0xb0,0xaf,0x44,0x00,0xb1,0xaf, +0x48,0x00,0xb2,0xaf,0x4c,0x00,0xb3,0xaf,0x50,0x00,0xb4,0xaf,0x54,0x00,0xb5,0xaf, +0x58,0x00,0xb6,0xaf,0x5c,0x00,0xb7,0xaf,0x60,0x00,0xb8,0xaf,0x64,0x00,0xb9,0xaf, +0x68,0x00,0xbc,0xaf,0x6c,0x00,0xbd,0xaf,0x70,0x00,0xbe,0xaf,0x74,0x00,0xbf,0xaf, +0x78,0x00,0xa8,0xaf,0x7c,0x00,0xa9,0xaf,0x80,0x00,0xaa,0xaf,0xac,0x1e,0x00,0x08, +0x21,0x20,0xa0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x25,0xb0,0x06,0x3c,0x00,0x80,0x02,0x3c,0xe8,0xff,0xbd,0x27,0x18,0x03,0xc3,0x34, +0x00,0x03,0x42,0x24,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x42,0xb0,0x03,0x3c, +0x03,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x02,0x80,0x0a,0x3c,0x02,0x80,0x10,0x3c, +0xff,0x00,0x42,0x30,0x00,0x46,0x02,0x00,0x10,0x00,0x42,0x30,0x13,0x00,0x40,0x10, +0x03,0x46,0x08,0x00,0x24,0x7e,0x42,0x8d,0x68,0x15,0x05,0x26,0xe0,0x63,0xa4,0x94, +0x01,0x00,0x47,0x24,0x10,0x00,0x02,0x24,0xb0,0x03,0xc9,0x34,0x00,0x00,0x62,0xa0, +0x07,0x00,0x80,0x10,0x1c,0x03,0xc6,0x34,0xe4,0x63,0xa2,0x94,0xe0,0x63,0xa0,0xa4, +0xe4,0x63,0xa0,0xa4,0x00,0x00,0x04,0x24,0x00,0x00,0xc2,0xac,0x00,0x00,0x20,0xad, +0x01,0x00,0x82,0x24,0x24,0x7e,0x47,0xad,0xe0,0x63,0xa2,0xa4,0x12,0x00,0x00,0x05, +0x42,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x68,0x15,0x04,0x26,0x0c,0x4b,0x83,0x94,0x08,0x4b,0x85,0x94, +0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c, +0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4, +0x08,0x00,0xe0,0x03,0x08,0x4b,0x83,0xa4,0x80,0xff,0x03,0x24,0x03,0x00,0x42,0x34, +0x00,0x00,0x43,0xa0,0x64,0x10,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0x04,0x26, +0x0c,0x4b,0x83,0x94,0x08,0x4b,0x85,0x94,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f, +0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34, +0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,0x08,0x00,0xe0,0x03,0x08,0x4b,0x83,0xa4, +0xff,0x00,0x84,0x30,0x0b,0x00,0x82,0x2c,0xff,0xff,0xe7,0x30,0x10,0x00,0xa8,0x93, +0x19,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00, +0x58,0x9f,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00, +0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x43,0xb0,0x02,0x3c,0x78,0x00,0x44,0x34, +0x07,0x00,0xe2,0x30,0x00,0x00,0x85,0xac,0x04,0x00,0x86,0xac,0x04,0x00,0x40,0x18, +0x00,0x00,0x00,0x00,0xf8,0xff,0xe2,0x30,0x08,0x00,0x42,0x24,0xff,0xff,0x47,0x30, +0x21,0x10,0xe8,0x00,0x00,0x80,0x03,0x3c,0x08,0x00,0x82,0xac,0x25,0x10,0x43,0x00, +0x08,0x00,0x82,0xac,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x6c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c, +0x20,0x01,0x00,0x08,0x60,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08, +0x54,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x48,0x00,0x44,0x34, +0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x3c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c, +0x20,0x01,0x00,0x08,0x30,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08, +0x24,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x18,0x00,0x44,0x34, +0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x0c,0x00,0x44,0x34,0x20,0x01,0x00,0x08, +0x43,0xb0,0x04,0x3c,0x01,0x00,0x02,0x24,0x25,0xb0,0x03,0x3c,0x04,0x20,0x82,0x00, +0x18,0x03,0x67,0x34,0x00,0x80,0x02,0x3c,0x43,0xb0,0x03,0x3c,0x34,0x05,0x46,0x24, +0x88,0x00,0x65,0x34,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0xff,0x42,0x30, +0x05,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x00,0x00,0xe6,0xac, +0x00,0x00,0xa2,0x94,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x30,0x24,0x10,0x44,0x00, +0xf4,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x25,0xb0,0x08,0x3c,0x00,0x80,0x02,0x3c,0xc8,0xff,0xbd,0x27,0x18,0x03,0x03,0x35, +0x90,0x05,0x42,0x24,0x00,0x00,0x62,0xac,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x34,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf, +0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0x0c,0x00,0xf2,0x84,0x08,0x00,0xf5,0x8c, +0xff,0x00,0xc6,0x30,0x00,0x01,0x02,0x24,0x23,0x10,0x46,0x00,0xff,0xff,0x51,0x30, +0xd0,0x03,0x08,0x35,0xff,0x00,0x96,0x30,0x00,0x00,0x12,0xad,0x21,0xa0,0xa0,0x00, +0x21,0x30,0xc5,0x00,0x00,0x00,0x15,0xad,0x21,0x20,0xc0,0x02,0x21,0x28,0xa0,0x02, +0x21,0x38,0x20,0x02,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x23,0x18,0x51,0x02, +0xff,0xff,0x82,0x32,0x00,0x94,0x03,0x00,0x03,0x94,0x12,0x00,0xa6,0x01,0x00,0x08, +0x02,0x9a,0x02,0x00,0x28,0xb0,0x03,0x3c,0xc0,0x10,0x13,0x00,0x21,0x10,0x43,0x00, +0x00,0x00,0x44,0x90,0x25,0xb0,0x10,0x3c,0x20,0x10,0x02,0x3c,0xff,0x00,0x93,0x30, +0x00,0x22,0x13,0x00,0xff,0xff,0x43,0x32,0x01,0x01,0x45,0x2a,0x21,0xa0,0x82,0x00, +0x21,0xa8,0xb1,0x02,0xd0,0x03,0x02,0x36,0x00,0x01,0x11,0x24,0x0b,0x88,0x65,0x00, +0x21,0x20,0xc0,0x02,0x00,0x00,0x53,0xac,0x4d,0x01,0x00,0x0c,0xb0,0x03,0x10,0x36, +0x21,0x30,0x80,0x02,0x21,0x20,0xc0,0x02,0x21,0x28,0xa0,0x02,0x21,0x38,0x20,0x02, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x23,0x18,0x51,0x02,0x00,0x94,0x03,0x00, +0x03,0x94,0x12,0x00,0x00,0x00,0x12,0xae,0xe2,0xff,0x40,0x1e,0x00,0x00,0x00,0x00, +0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c, +0x25,0xb0,0x04,0x3c,0x20,0x00,0xb2,0xaf,0x68,0x15,0x52,0x24,0x00,0x80,0x02,0x3c, +0x18,0x03,0x83,0x34,0xc8,0x06,0x42,0x24,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf, +0x30,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x00,0x00,0x62,0xac,0xb0,0x03,0x93,0x34,0x21,0xa0,0x40,0x02,0xb4,0x64,0x42,0x8e, +0x20,0x65,0x50,0x8e,0x21,0x20,0x00,0x00,0x00,0x00,0x62,0xae,0xb8,0x64,0x42,0xae, +0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x20,0x65,0x44,0x8e, +0x24,0x65,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00, +0x0a,0x18,0x82,0x00,0x20,0x65,0x43,0xae,0x20,0x65,0x85,0x8e,0x00,0x00,0x00,0x00, +0x00,0x00,0x65,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02, +0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0xff,0x00,0x15,0x24,0x21,0x20,0x00,0x00, +0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0x20,0x10,0x02,0x3c,0x20,0x00,0x07,0x24, +0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,0x05,0x00,0x35,0x12,0x21,0x30,0x60,0x00, +0x68,0x64,0x91,0xa2,0xb4,0x64,0x83,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x00,0x00,0x05,0x96,0x18,0x64,0x83,0x8e,0x2a,0xb0,0x02,0x3c,0x27,0x20,0x05,0x00, +0x01,0x00,0x46,0x34,0x21,0x10,0x65,0x00,0x2b,0x18,0x64,0x00,0x02,0x00,0x60,0x10, +0x00,0x00,0x00,0x00,0x18,0x64,0x82,0xae,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e, +0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00, +0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0xc0,0xff,0x02,0x24,0x25,0x18,0x64,0x00, +0x24,0x18,0x62,0x00,0x08,0x00,0x03,0xae,0x01,0x00,0x02,0x24,0x02,0x00,0x03,0x24, +0x00,0x00,0xc2,0xa0,0x00,0x00,0xc3,0xa0,0xbc,0xff,0x35,0x16,0x41,0xb0,0x03,0x3c, +0xfc,0x4a,0x82,0x8e,0x30,0x00,0xbf,0x8f,0x00,0x38,0x42,0x34,0x00,0x00,0x62,0xac, +0x2c,0x00,0xb5,0x8f,0xfc,0x4a,0x82,0xae,0x24,0x00,0xb3,0x8f,0x28,0x00,0xb4,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x38,0x00,0xbd,0x27,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27, +0x18,0x03,0x83,0x34,0x54,0x08,0x42,0x24,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf, +0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x02,0x80,0x02,0x3c,0x68,0x15,0x52,0x24,0xb0,0x03,0x95,0x34,0x39,0x02,0x00,0x08, +0x21,0xf0,0x40,0x02,0x08,0x00,0x04,0xae,0x76,0x4b,0x82,0x92,0x00,0x00,0x00,0x00, +0x45,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,0x09,0x00,0x42,0x34,0x01,0x00,0x03,0x24, +0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0,0x5a,0x00,0x36,0x12, +0x00,0x00,0x00,0x00,0xcc,0x64,0x42,0x8e,0x38,0x65,0x53,0x8e,0x01,0x00,0x04,0x24, +0x00,0x00,0xa2,0xae,0xd0,0x64,0x42,0xae,0x00,0x00,0xb3,0xae,0x4d,0x01,0x00,0x0c, +0x21,0xa0,0xc0,0x03,0x38,0x65,0x44,0x8e,0x3c,0x65,0x43,0x8e,0x20,0x00,0x84,0x24, +0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x38,0x65,0x43,0xae, +0x38,0x65,0xc5,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0xa5,0xae,0x02,0x80,0x17,0x3c, +0xff,0xff,0x62,0x32,0x25,0x80,0x57,0x00,0x00,0x00,0xb0,0xae,0x0c,0x00,0x02,0x92, +0xff,0x00,0x16,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0xa2,0xae,0x0c,0x00,0x11,0x92, +0x20,0x10,0x02,0x3c,0x20,0x00,0x07,0x24,0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00, +0x05,0x00,0x36,0x12,0x21,0x30,0x60,0x00,0xcc,0x64,0xc3,0xaf,0x70,0x64,0xd1,0xa3, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e, +0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00, +0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0xc0,0xff,0x05,0x24, +0x82,0x11,0x03,0x00,0x24,0x20,0x65,0x00,0x01,0x00,0x42,0x30,0xbd,0xff,0x40,0x10, +0x04,0x00,0x84,0x34,0x08,0x00,0x03,0xae,0x76,0x4b,0x82,0x92,0x00,0x00,0x00,0x00, +0xbd,0xff,0x40,0x14,0x2a,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x01,0x00,0x03,0x24,0x76,0x4b,0x83,0xa2, +0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30, +0x25,0x10,0x57,0x00,0x02,0x00,0x43,0x94,0x00,0x00,0x00,0x00,0xff,0xc0,0x64,0x30, +0x00,0xc0,0x84,0x34,0xe3,0x18,0x00,0x0c,0x77,0x4b,0x83,0xa2,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,0x09,0x00,0x42,0x34, +0x01,0x00,0x03,0x24,0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0, +0xa8,0xff,0x36,0x16,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x68,0x15,0x62,0x24, +0xfc,0x4a,0x43,0x8c,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x38,0x63,0x34, +0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x83,0xac,0x08,0x00,0xe0,0x03, +0xfc,0x4a,0x43,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27, +0x18,0x03,0x83,0x34,0xa4,0x0a,0x42,0x24,0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf, +0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf, +0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c, +0x68,0x15,0xd3,0x26,0xb0,0x03,0x94,0x34,0x02,0x80,0x15,0x3c,0x21,0xb8,0x60,0x02, +0xc0,0x64,0x62,0x8e,0x2c,0x65,0x70,0x8e,0x01,0x00,0x04,0x24,0x00,0x00,0x82,0xae, +0xc4,0x64,0x62,0xae,0x00,0x00,0x90,0xae,0x4d,0x01,0x00,0x0c,0x21,0x88,0xe0,0x02, +0x2c,0x65,0x64,0x8e,0x30,0x65,0x63,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24, +0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x2c,0x65,0x63,0xae,0x2c,0x65,0xe5,0x8e, +0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32, +0x25,0x80,0x02,0x02,0x00,0x00,0x90,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00, +0x00,0x00,0x82,0xae,0x0c,0x00,0x12,0x92,0xff,0x00,0x02,0x24,0x0a,0x00,0x42,0x12, +0x00,0x1a,0x12,0x00,0x20,0x10,0x02,0x3c,0x21,0x18,0x62,0x00,0xc0,0x64,0xe3,0xae, +0x6c,0x64,0xf2,0xa2,0x21,0x30,0x60,0x00,0x01,0x00,0x04,0x24,0x20,0x00,0x07,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xf8,0x63,0x22,0x8e,0x04,0x00,0x03,0x8e, +0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x5d,0x00,0x40,0x14,0x1f,0x00,0x64,0x30, +0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00, +0x00,0x26,0x04,0x00,0x25,0x28,0x44,0x00,0x08,0x00,0x05,0xae,0xc2,0x11,0x05,0x00, +0x01,0x00,0x43,0x30,0x47,0x00,0x60,0x14,0x01,0x00,0x02,0x24,0x00,0x00,0x04,0x96, +0x1c,0x64,0x23,0x8e,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0x05,0x00,0x40,0x10, +0xff,0xdf,0x02,0x3c,0x21,0x10,0x64,0x00,0x1c,0x64,0x22,0xae,0x08,0x00,0x05,0x8e, +0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x28,0xa2,0x00,0x00,0x40,0x03,0x3c, +0x25,0x28,0xa3,0x00,0x82,0x11,0x05,0x00,0x01,0x00,0x42,0x30,0x03,0x00,0x40,0x14, +0xc0,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,0x04,0x00,0x45,0x34,0x08,0x00,0x05,0xae, +0x68,0x15,0xc2,0x26,0x76,0x4b,0x44,0x90,0x01,0x00,0x03,0x24,0x3b,0x00,0x83,0x10, +0x7f,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,0x08,0x00,0x02,0xae,0x68,0x15,0xc5,0x26, +0xc4,0x64,0xa2,0x8c,0x20,0x00,0x10,0x8e,0x00,0x80,0x03,0x3c,0x25,0x10,0x43,0x00, +0x2a,0xb0,0x03,0x3c,0x08,0x00,0x50,0xac,0x05,0x00,0x70,0x34,0x01,0x00,0x02,0x24, +0x02,0x00,0x03,0x24,0x00,0x00,0x02,0xa2,0x00,0x00,0x03,0xa2,0x2a,0x7e,0xa2,0x96, +0xff,0x00,0x03,0x24,0x01,0x00,0x42,0x24,0x2a,0x7e,0xa2,0xa6,0x2a,0x7e,0xa4,0x96, +0x25,0xb0,0x02,0x3c,0x66,0x03,0x42,0x34,0x00,0x00,0x44,0xa4,0x98,0xff,0x43,0x16, +0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x38,0x42,0x34, +0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x62,0xac,0x08,0x00,0xe0,0x03, +0xfc,0x4a,0xa2,0xac,0xc3,0xff,0x62,0x14,0xff,0xdf,0x02,0x3c,0x00,0x00,0x04,0x96, +0x18,0x64,0x23,0x8e,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0xbd,0xff,0x40,0x10, +0xff,0xdf,0x02,0x3c,0x21,0x10,0x64,0x00,0xff,0x02,0x00,0x08,0x18,0x64,0x22,0xae, +0x08,0x00,0x05,0x8e,0xf4,0x02,0x00,0x08,0xc2,0x11,0x05,0x00,0x80,0x00,0xa5,0x34, +0x13,0x03,0x00,0x08,0x08,0x00,0x05,0xae,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf, +0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x02,0x80,0x06,0x3c,0xdc,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x18,0x03,0x42,0x34,0x38,0x0d,0x63,0x24,0x40,0x00,0xa4,0x30,0x00,0x00,0x43,0xac, +0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0x7f,0x00,0xa2,0x30,0xbf,0x00,0xa2,0x30, +0x01,0x00,0x16,0x24,0xdc,0x7e,0xc2,0xa0,0xdc,0x7e,0xc2,0x90,0x25,0xb0,0x04,0x3c, +0x88,0x02,0x83,0x34,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x02,0x80,0x15,0x3c,0x68,0x15,0xb2,0x26,0xb0,0x03,0x93,0x34, +0x02,0x80,0x14,0x3c,0xc0,0x03,0x00,0x08,0x21,0xb8,0x40,0x02,0x4c,0x64,0xf1,0xa2, +0x68,0x15,0xa2,0x26,0x84,0x64,0x46,0x8c,0xf0,0x64,0x45,0x8c,0x03,0x00,0x04,0x24, +0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x68,0x15,0xa5,0x26, +0xf8,0x63,0xa2,0x8c,0x04,0x00,0x03,0x8e,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30, +0x08,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c, +0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,0x00,0x26,0x04,0x00,0x25,0x18,0x44,0x00, +0x08,0x00,0x03,0xae,0x00,0x00,0x04,0x96,0x1c,0x64,0xa3,0x8c,0x27,0x10,0x04,0x00, +0x2b,0x10,0x62,0x00,0x02,0x00,0x40,0x10,0x21,0x10,0x64,0x00,0x1c,0x64,0xa2,0xac, +0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0x53,0x00,0x80,0x04,0x00,0x00,0x00,0x00, +0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30, +0x0c,0x00,0x42,0x28,0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x96, +0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x44,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x18,0x43,0x00, +0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x08,0x00,0x03,0xae,0x82,0x11,0x03,0x00, +0x01,0x00,0x42,0x30,0x05,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24, +0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,0x08,0x00,0x02,0xae,0x0d,0x00,0xe2,0x34, +0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24, +0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0x2a,0x7e,0x84,0x96,0x25,0xb0,0x06,0x3c, +0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0x2a,0x7e,0x84,0xa6,0x2a,0x7e,0x82,0x96, +0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x33,0x00,0x23,0x12,0x00,0x00,0x00,0x00, +0x84,0x64,0x42,0x8e,0xf0,0x64,0x50,0x8e,0x03,0x00,0x04,0x24,0x00,0x00,0x62,0xae, +0x88,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00, +0xf0,0x64,0x44,0x8e,0xf4,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24, +0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0xf0,0x64,0x43,0xae,0xf0,0x64,0xe2,0x8e, +0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32, +0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00, +0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x9f,0xff,0x22,0x12, +0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x93,0xff,0xc0,0x16, +0x84,0x64,0xe2,0xae,0x74,0x03,0x00,0x08,0x48,0x64,0xf1,0xa2,0x08,0x00,0x03,0x8e, +0xa8,0x03,0x00,0x08,0x82,0x11,0x03,0x00,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00, +0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,0xab,0xff,0x40,0x14, +0x42,0x12,0x03,0x00,0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00, +0x96,0x03,0x00,0x08,0x10,0x00,0x02,0xae,0x20,0x00,0xc0,0x12,0x68,0x15,0xa2,0x26, +0x4c,0x64,0x43,0x90,0x41,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0, +0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa4,0x8c,0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f, +0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x00,0x80,0x42,0x34,0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27, +0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa4,0xac,0x48,0x64,0x43,0x90, +0x40,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xa5,0x26, +0xfc,0x4a,0xa4,0x8c,0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34, +0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac, +0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa4,0xac,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf, +0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x02,0x80,0x06,0x3c,0xdc,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x18,0x03,0x42,0x34,0xc8,0x10,0x63,0x24,0x10,0x00,0xa4,0x30,0x00,0x00,0x43,0xac, +0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0xdf,0x00,0xa2,0x30,0xef,0x00,0xa2,0x30, +0x01,0x00,0x16,0x24,0xdc,0x7e,0xc2,0xa0,0xdc,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c, +0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x15,0x3c,0x68,0x15,0xb2,0x26, +0x21,0x98,0x40,0x00,0x02,0x80,0x14,0x3c,0xa5,0x04,0x00,0x08,0x21,0xb8,0x40,0x02, +0x54,0x64,0xf1,0xa2,0x68,0x15,0xa2,0x26,0x90,0x64,0x46,0x8c,0xfc,0x64,0x45,0x8c, +0x04,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x68,0x15,0xa5,0x26,0xf8,0x63,0xa2,0x8c,0x04,0x00,0x03,0x8e,0x42,0x10,0x02,0x00, +0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,0x08,0x00,0x02,0x8e, +0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,0x00,0x26,0x04,0x00, +0x25,0x18,0x44,0x00,0x08,0x00,0x03,0xae,0x00,0x00,0x04,0x96,0x1c,0x64,0xa3,0x8c, +0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0x02,0x00,0x40,0x10,0x21,0x10,0x64,0x00, +0x1c,0x64,0xa2,0xac,0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0x53,0x00,0x80,0x04, +0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00, +0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x00,0x00,0x02,0x96,0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x44,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34, +0x24,0x18,0x43,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x08,0x00,0x03,0xae, +0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30,0x05,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c, +0xc0,0xff,0x02,0x24,0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,0x08,0x00,0x02,0xae, +0x15,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24, +0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0x2a,0x7e,0x84,0x96, +0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0x2a,0x7e,0x84,0xa6, +0x2a,0x7e,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x33,0x00,0x23,0x12, +0x00,0x00,0x00,0x00,0x90,0x64,0x42,0x8e,0xfc,0x64,0x50,0x8e,0x04,0x00,0x04,0x24, +0x00,0x00,0x62,0xae,0x94,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c, +0x00,0x00,0x00,0x00,0xfc,0x64,0x44,0x8e,0x00,0x65,0x43,0x8e,0x20,0x00,0x84,0x24, +0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0xfc,0x64,0x43,0xae, +0xfc,0x64,0xe2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c, +0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92, +0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24, +0x9f,0xff,0x22,0x12,0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00, +0x93,0xff,0xc0,0x16,0x90,0x64,0xe2,0xae,0x59,0x04,0x00,0x08,0x50,0x64,0xf1,0xa2, +0x08,0x00,0x03,0x8e,0x8d,0x04,0x00,0x08,0x82,0x11,0x03,0x00,0x14,0x00,0x03,0x8e, +0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28, +0xab,0xff,0x40,0x14,0x42,0x12,0x03,0x00,0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x10,0x82,0x00,0x7b,0x04,0x00,0x08,0x10,0x00,0x02,0xae,0x1f,0x00,0xc0,0x12, +0x68,0x15,0xa2,0x26,0x54,0x64,0x43,0x90,0x43,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34, +0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f, +0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x06,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27, +0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x50,0x64,0x43,0x90, +0x42,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xa5,0x26, +0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f, +0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f, +0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,0x25,0x10,0x43,0x00, +0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03, +0xfc,0x4a,0xa2,0xac,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf,0x38,0x00,0xbf,0xaf, +0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf, +0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c, +0xdc,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34, +0x54,0x14,0x63,0x24,0x01,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,0x21,0xb0,0x00,0x00, +0x03,0x00,0x80,0x10,0xf7,0x00,0xa2,0x30,0xfe,0x00,0xa2,0x30,0x01,0x00,0x16,0x24, +0xdc,0x7e,0xc2,0xa0,0xdc,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34, +0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x02,0x80,0x15,0x3c,0x68,0x15,0xb2,0x26,0x21,0x98,0x40,0x00,0x02,0x80,0x14,0x3c, +0x5c,0x05,0x00,0x08,0x21,0xb8,0x40,0x02,0x00,0x00,0x02,0x96,0x00,0x00,0x00,0x00, +0xfd,0x0f,0x42,0x28,0x67,0x00,0x40,0x10,0x00,0x20,0x02,0x3c,0x08,0x00,0x03,0x8e, +0x00,0x00,0x00,0x00,0x25,0x18,0x62,0x00,0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30, +0x6b,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24,0x24,0x10,0x62,0x00, +0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,0x1d,0x00,0xe2,0x34, +0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24, +0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0x2a,0x7e,0x84,0x96,0x25,0xb0,0x06,0x3c, +0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0x2a,0x7e,0x84,0xa6,0x2a,0x7e,0x82,0x96, +0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x67,0x00,0x23,0x12,0x00,0x00,0x00,0x00, +0x9c,0x64,0x42,0x8e,0x08,0x65,0x50,0x8e,0x05,0x00,0x04,0x24,0x00,0x00,0x62,0xae, +0xa0,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00, +0x08,0x65,0x44,0x8e,0x0c,0x65,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24, +0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x08,0x65,0x43,0xae,0x08,0x65,0xe2,0x8e, +0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32, +0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00, +0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x0d,0x00,0x22,0x12, +0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x66,0x00,0xc0,0x12, +0x9c,0x64,0xe2,0xae,0x64,0x64,0xf1,0xa2,0x68,0x15,0xa2,0x26,0x9c,0x64,0x46,0x8c, +0x08,0x65,0x45,0x8c,0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c, +0x10,0x00,0xa0,0xaf,0x68,0x15,0xa5,0x26,0xf8,0x63,0xa2,0x8c,0x04,0x00,0x03,0x8e, +0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14,0x1f,0x00,0x64,0x30, +0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00, +0x00,0x26,0x04,0x00,0x25,0x10,0x44,0x00,0x08,0x00,0x02,0xae,0x00,0x00,0x04,0x96, +0x1c,0x64,0xa3,0x8c,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00,0x02,0x00,0x40,0x10, +0x21,0x10,0x64,0x00,0x1c,0x64,0xa2,0xac,0x10,0x00,0x04,0x8e,0x00,0x00,0x00,0x00, +0x47,0x00,0x80,0x04,0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00, +0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x96,0xff,0x40,0x10, +0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c,0xff,0xff,0x63,0x34, +0x24,0x10,0x43,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x44,0x00,0x82,0x11,0x03,0x00, +0x01,0x00,0x42,0x30,0x99,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,0x2a,0xb0,0x07,0x3c, +0x1d,0x00,0xe2,0x34,0x08,0x00,0x03,0xae,0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00, +0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0, +0x2a,0x7e,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24, +0x2a,0x7e,0x84,0xa6,0x2a,0x7e,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4, +0x9b,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x2d,0x00,0xc0,0x12,0x68,0x15,0xa2,0x26, +0x64,0x64,0x43,0x90,0x45,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0, +0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c, +0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac, +0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x7e,0x05,0x00,0x08,0x58,0x64,0xf1,0xa2, +0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30, +0x14,0x00,0x42,0x28,0xb7,0xff,0x40,0x14,0x42,0x12,0x03,0x00,0x9f,0xff,0x02,0x3c, +0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,0xa0,0x05,0x00,0x08,0x10,0x00,0x02,0xae, +0x58,0x64,0x43,0x90,0x44,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0, +0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c, +0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac, +0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0xc0,0xff,0xbd,0x27,0x30,0x00,0xb6,0xaf, +0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x02,0x80,0x06,0x3c,0xdc,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x18,0x03,0x42,0x34,0x38,0x18,0x63,0x24,0x02,0x00,0xa4,0x30,0x00,0x00,0x43,0xac, +0x21,0xb0,0x00,0x00,0x03,0x00,0x80,0x10,0xfb,0x00,0xa2,0x30,0xfd,0x00,0xa2,0x30, +0x01,0x00,0x16,0x24,0xdc,0x7e,0xc2,0xa0,0xdc,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c, +0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x02,0x80,0x15,0x3c,0x68,0x15,0xb2,0x26,0x21,0x98,0x40,0x00, +0x02,0x80,0x14,0x3c,0x55,0x06,0x00,0x08,0x21,0xb8,0x40,0x02,0x00,0x00,0x02,0x96, +0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x67,0x00,0x40,0x10,0x00,0x20,0x02,0x3c, +0x08,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x25,0x18,0x62,0x00,0x82,0x11,0x03,0x00, +0x01,0x00,0x42,0x30,0x6b,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24, +0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae, +0x25,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24, +0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0x2a,0x7e,0x84,0x96, +0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0x2a,0x7e,0x84,0xa6, +0x2a,0x7e,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x67,0x00,0x23,0x12, +0x00,0x00,0x00,0x00,0xa8,0x64,0x42,0x8e,0x14,0x65,0x50,0x8e,0x06,0x00,0x04,0x24, +0x00,0x00,0x62,0xae,0xac,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c, +0x00,0x00,0x00,0x00,0x14,0x65,0x44,0x8e,0x18,0x65,0x43,0x8e,0x20,0x00,0x84,0x24, +0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x14,0x65,0x43,0xae, +0x14,0x65,0xe2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c, +0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92, +0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24, +0x0d,0x00,0x22,0x12,0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00, +0x66,0x00,0xc0,0x12,0xa8,0x64,0xe2,0xae,0x60,0x64,0xf1,0xa2,0x68,0x15,0xa2,0x26, +0xa8,0x64,0x46,0x8c,0x14,0x65,0x45,0x8c,0x06,0x00,0x04,0x24,0x20,0x00,0x07,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x68,0x15,0xa5,0x26,0xf8,0x63,0xa2,0x8c, +0x04,0x00,0x03,0x8e,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14, +0x1f,0x00,0x64,0x30,0x08,0x00,0x02,0x8e,0xff,0xe0,0x03,0x3c,0xff,0xff,0x63,0x34, +0x24,0x10,0x43,0x00,0x00,0x26,0x04,0x00,0x25,0x10,0x44,0x00,0x08,0x00,0x02,0xae, +0x00,0x00,0x04,0x96,0x1c,0x64,0xa3,0x8c,0x27,0x10,0x04,0x00,0x2b,0x10,0x62,0x00, +0x02,0x00,0x40,0x10,0x21,0x10,0x64,0x00,0x1c,0x64,0xa2,0xac,0x10,0x00,0x04,0x8e, +0x00,0x00,0x00,0x00,0x47,0x00,0x80,0x04,0x00,0x00,0x00,0x00,0x14,0x00,0x03,0x8e, +0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00,0x3f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28, +0x96,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0xff,0xdf,0x03,0x3c, +0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x44,0x00, +0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30,0x99,0xff,0x40,0x10,0xc0,0xff,0x02,0x24, +0x2a,0xb0,0x07,0x3c,0x25,0x00,0xe2,0x34,0x08,0x00,0x03,0xae,0x04,0x00,0x43,0x24, +0x0b,0x10,0x76,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0, +0x00,0x00,0x43,0xa0,0x2a,0x7e,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34, +0x01,0x00,0x84,0x24,0x2a,0x7e,0x84,0xa6,0x2a,0x7e,0x82,0x96,0xff,0x00,0x03,0x24, +0x00,0x00,0xa2,0xa4,0x9b,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x2d,0x00,0xc0,0x12, +0x68,0x15,0xa2,0x26,0x60,0x64,0x43,0x90,0x47,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34, +0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f, +0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x60,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27, +0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x77,0x06,0x00,0x08, +0x5c,0x64,0xf1,0xa2,0x14,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x42,0x12,0x03,0x00, +0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,0xb7,0xff,0x40,0x14,0x42,0x12,0x03,0x00, +0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,0x99,0x06,0x00,0x08, +0x10,0x00,0x02,0xae,0x5c,0x64,0x43,0x90,0x46,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34, +0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x68,0x15,0xa5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f, +0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x60,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27, +0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x00,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x1c,0x1c,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x05,0x3c, +0x68,0x15,0xa5,0x24,0x04,0x4b,0xa2,0x8c,0xfc,0x4a,0xa4,0x8c,0x00,0x08,0x03,0x3c, +0x24,0x10,0x43,0x00,0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac, +0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa4,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c, +0xc0,0xff,0xbd,0x27,0x18,0x03,0x83,0x34,0x78,0x1c,0x42,0x24,0x3c,0x00,0xbf,0xaf, +0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf, +0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x2a,0xb0,0x03,0x3c,0x68,0x15,0x51,0x24, +0xb0,0x03,0x93,0x34,0x2c,0x00,0x77,0x34,0x02,0x80,0x15,0x3c,0x02,0x80,0x16,0x3c, +0x41,0x07,0x00,0x08,0x02,0x80,0x1e,0x3c,0x74,0x64,0x26,0x92,0x44,0x65,0x25,0x8e, +0x00,0x32,0x06,0x00,0x21,0x30,0xc2,0x00,0xd8,0x64,0x26,0xae,0x10,0x01,0x00,0x0c, +0x10,0x00,0xa0,0xaf,0x44,0x65,0x30,0x8e,0x0a,0x00,0x04,0x24,0x21,0x90,0x00,0x00, +0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0xff,0xff,0x10,0x32,0x02,0x80,0x02,0x3c, +0x25,0x80,0x02,0x02,0x0c,0x00,0x05,0x92,0x02,0x00,0x04,0x92,0xff,0x00,0x02,0x24, +0xff,0x00,0xa3,0x30,0x04,0x00,0x62,0x10,0x21,0x80,0x04,0x02,0x00,0x00,0x63,0xae, +0x01,0x00,0x12,0x24,0x74,0x64,0x25,0xa2,0x48,0xa4,0xb0,0xae,0x21,0x28,0x00,0x02, +0x02,0x00,0xa2,0x90,0x08,0x00,0x10,0x26,0x21,0x20,0x00,0x02,0xff,0x00,0x42,0x30, +0x00,0x00,0x62,0xae,0x03,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x7f,0x00,0x63,0x30, +0x00,0x00,0x63,0xae,0x00,0x00,0x72,0xae,0x03,0x00,0xa2,0x90,0x44,0xa4,0xc3,0x92, +0x02,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,0x2f,0x00,0x42,0x28, +0x11,0x00,0x40,0x10,0x08,0x00,0x02,0x24,0x03,0x00,0xa2,0x90,0x00,0x00,0x00,0x00, +0x7f,0x00,0x42,0x30,0x44,0xa4,0xc2,0xa2,0x02,0x00,0xa3,0x90,0x02,0x80,0x02,0x3c, +0xf4,0x91,0x42,0x24,0xff,0x00,0x63,0x30,0xc0,0x18,0x03,0x00,0x21,0x18,0x62,0x00, +0x04,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x09,0xf8,0x40,0x00,0x40,0xa4,0xc2,0xaf, +0x21,0xa0,0x40,0x00,0x08,0x00,0x02,0x24,0x0a,0x00,0x04,0x24,0x05,0x00,0x82,0x12, +0x00,0x01,0x07,0x24,0x01,0x00,0x02,0x24,0x02,0x00,0x03,0x24,0x01,0x00,0xe2,0xa2, +0x01,0x00,0xe3,0xa2,0xbc,0xff,0x40,0x16,0x20,0x10,0x02,0x3c,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xfc,0x4a,0x22,0x8e, +0x00,0x04,0x03,0x3c,0x41,0xb0,0x04,0x3c,0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac, +0x3c,0x00,0xbf,0x8f,0xfc,0x4a,0x22,0xae,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x40,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27,0xff,0xff,0xa8,0x30,0x02,0x80,0x02,0x3c, +0x25,0x40,0x02,0x01,0x30,0x00,0xb6,0xaf,0x20,0x00,0xb2,0xaf,0x34,0x00,0xbf,0xaf, +0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0x00,0x00,0x03,0x8d,0xff,0xff,0xd2,0x30,0x21,0xb0,0xa0,0x00, +0x00,0xc0,0x02,0x24,0x08,0x00,0x45,0x26,0x04,0x00,0x06,0x8d,0x24,0x18,0x62,0x00, +0xff,0x3f,0xa5,0x30,0xf0,0xff,0x02,0x3c,0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x00,0x80,0x05,0x3c,0x25,0x18,0x65,0x00,0xff,0x01,0xc6,0x34, +0x00,0x00,0x03,0xad,0x04,0x00,0x06,0xad,0x21,0x48,0x80,0x00,0xff,0xff,0xe7,0x30, +0x18,0x00,0x12,0xa5,0x1a,0x00,0x07,0xa1,0x18,0x00,0x03,0x8d,0xff,0x7f,0x02,0x3c, +0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x02,0x80,0x15,0x3c,0x18,0x00,0x03,0xad, +0x68,0x15,0xa5,0x26,0xe2,0x63,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x24, +0xe2,0x63,0xa2,0xa0,0x18,0x00,0x04,0x8d,0xff,0x80,0x02,0x3c,0x20,0x00,0x45,0x26, +0xff,0xff,0x42,0x34,0x7f,0x00,0x63,0x30,0xff,0xff,0xb2,0x30,0x24,0x20,0x82,0x00, +0x00,0x1e,0x03,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x00,0x42,0x34,0x25,0x20,0x83,0x00, +0x07,0x00,0x45,0x32,0x18,0x00,0x04,0xad,0x00,0x00,0x52,0xa4,0x03,0x00,0xa0,0x10, +0xff,0xff,0x42,0x32,0x08,0x00,0x42,0x26,0xff,0xff,0x42,0x30,0x68,0x15,0xb4,0x26, +0xb4,0x65,0x86,0x8e,0xb8,0x65,0x90,0x8e,0xf8,0xff,0x52,0x30,0x21,0x10,0xd2,0x00, +0x2b,0x10,0x02,0x02,0x31,0x00,0x40,0x10,0xff,0x00,0x33,0x31,0x23,0x80,0x06,0x02, +0x21,0x28,0xc0,0x02,0xff,0xff,0x07,0x32,0x01,0x00,0x11,0x24,0x21,0x20,0x60,0x02, +0x10,0x01,0x00,0x0c,0x10,0x00,0xb1,0xaf,0x23,0x18,0x50,0x02,0xff,0xff,0x72,0x30, +0x22,0x10,0x02,0x3c,0x21,0x10,0x42,0x02,0x21,0x20,0x60,0x02,0x4d,0x01,0x00,0x0c, +0xb4,0x65,0x82,0xae,0x21,0x28,0xd0,0x02,0x21,0x38,0x40,0x02,0x21,0x20,0x60,0x02, +0x10,0x00,0xb1,0xaf,0x22,0x10,0x06,0x3c,0x10,0x01,0x00,0x0c,0x68,0x15,0xb1,0x26, +0xb4,0x65,0x23,0x8e,0x25,0xb0,0x10,0x3c,0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02, +0x00,0x00,0x43,0xac,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0xb4,0x65,0x25,0x8e, +0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac,0x00,0x00,0x83,0x90, +0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34,0x00,0x00,0x83,0xa0, +0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x21,0x28,0xc0,0x02, +0x21,0x20,0x60,0x02,0x21,0x38,0x40,0x02,0x01,0x00,0x02,0x24,0x10,0x01,0x00,0x0c, +0x10,0x00,0xa2,0xaf,0xb4,0x65,0x83,0x8e,0x68,0x15,0xb1,0x26,0x25,0xb0,0x10,0x3c, +0x21,0x18,0x72,0x00,0xb4,0x65,0x83,0xae,0xb4,0x65,0x23,0x8e,0xb0,0x03,0x02,0x36, +0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00, +0xb4,0x65,0x25,0x8e,0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac, +0x00,0x00,0x83,0x90,0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34, +0x00,0x00,0x83,0xa0,0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f, +0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f, +0x18,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27, +0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf, +0x10,0x00,0xb0,0xaf,0xbf,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x21,0x28,0x00,0x00, +0x08,0x00,0x06,0x24,0x04,0x00,0x63,0x2c,0x12,0x00,0x60,0x14,0x21,0x88,0x80,0x00, +0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x02,0x80,0x03,0x3c,0x60,0x7b,0x63,0x24,0x04,0x00,0x64,0x8c,0x00,0x00,0x23,0xae, +0x04,0x00,0x71,0xac,0x00,0x00,0x91,0xac,0x04,0x00,0x24,0xae,0x00,0x60,0x82,0x40, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x08,0x00,0x82,0x94,0x02,0x80,0x04,0x3c,0x58,0x45,0x00,0x0c, +0x25,0x20,0x44,0x00,0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x08,0x00,0x25,0x8e,0x0c,0x00,0x26,0x96,0x14,0x00,0x27,0x96, +0x95,0x07,0x00,0x0c,0x09,0x00,0x04,0x24,0x04,0x00,0x23,0x8e,0x00,0x00,0x22,0x8e, +0x21,0x20,0x20,0x02,0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,0x00,0x00,0x31,0xae, +0x70,0x4f,0x00,0x0c,0x04,0x00,0x31,0xae,0x00,0x60,0x90,0x40,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0x02,0x80,0x02,0x3c,0x68,0x15,0x47,0x24,0xec,0x64,0xe3,0x90,0xff,0xff,0xa5,0x30, +0x09,0x00,0xa3,0x10,0x21,0x20,0xc0,0x00,0x5c,0x65,0xe2,0x8c,0x00,0x00,0x00,0x00, +0x08,0x00,0xc2,0xac,0x66,0x65,0xe3,0x94,0x0e,0x00,0x02,0x24,0x14,0x00,0xc2,0xac, +0x30,0x08,0x00,0x08,0x0c,0x00,0xc3,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x2a,0xb0,0x04,0x3c,0x28,0x00,0x85,0x34,0x03,0x00,0x82,0x90,0x04,0x00,0x84,0x24, +0x05,0x00,0x40,0x14,0x2b,0x18,0xa4,0x00,0xfb,0xff,0x60,0x10,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x10,0x22,0x63,0x24,0x18,0x03,0x42,0x34, +0xd0,0xff,0xbd,0x27,0x00,0x00,0x43,0xac,0x24,0x00,0xb3,0xaf,0x28,0x00,0xbf,0xaf, +0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x78,0x08,0x00,0x0c,0x18,0x00,0xb0,0xaf, +0x06,0x00,0x40,0x10,0x02,0x80,0x13,0x3c,0x68,0x15,0x63,0x26,0x76,0x4b,0x62,0x90, +0x00,0x00,0x00,0x00,0x9b,0x00,0x40,0x14,0x00,0xc0,0x04,0x34,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,0x36,0x00,0x42,0x34, +0x00,0x00,0x43,0x90,0x68,0x15,0x66,0x26,0xbc,0x65,0xc5,0x8c,0xc0,0x18,0x03,0x00, +0x23,0xb0,0x04,0x3c,0xf0,0x07,0x63,0x30,0xff,0x1f,0x02,0x3c,0x21,0x18,0x64,0x00, +0xff,0xff,0x42,0x34,0x24,0x20,0x62,0x00,0x23,0x88,0x85,0x00,0x2b,0x38,0x85,0x00, +0x00,0x04,0x22,0x26,0x60,0x65,0xc3,0x8c,0x0b,0x88,0x47,0x00,0x01,0x04,0x25,0x2e, +0x5c,0x65,0xc3,0xac,0xc0,0x65,0xc4,0xac,0x66,0x65,0xc0,0xa4,0x11,0x00,0xa0,0x14, +0x65,0x65,0xc0,0xa0,0x00,0xfc,0x83,0x24,0x23,0x10,0x02,0x3c,0x0b,0x18,0x87,0x00, +0xff,0x03,0x42,0x34,0x2b,0x10,0x43,0x00,0x33,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x23,0x88,0x83,0x00,0x2b,0x10,0x83,0x00,0xbc,0x65,0xc3,0xac,0x03,0x00,0x40,0x10, +0x01,0x04,0x25,0x2e,0x00,0x04,0x31,0x26,0x01,0x04,0x25,0x2e,0x0e,0x00,0xa0,0x10, +0x68,0x15,0x70,0x26,0x68,0x15,0x70,0x26,0xc0,0x65,0x03,0x8e,0xbc,0x65,0x04,0x8e, +0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x25,0x00,0x40,0x14,0x2b,0x10,0x64,0x00, +0x51,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,0x80,0x00,0x03,0x24,0xd0,0x03,0x42,0x34, +0x00,0x00,0x43,0xac,0x68,0x15,0x70,0x26,0xbc,0x65,0x03,0x96,0x2a,0xb0,0x02,0x3c, +0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,0x00,0x00,0x51,0xa0,0x8e,0x12,0x00,0x0c, +0x00,0x00,0x00,0x00,0x66,0x65,0x03,0x96,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34, +0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0xfc,0x4a,0x02,0x8e,0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c, +0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x28,0x00,0xbf,0x8f,0xfc,0x4a,0x02,0xae, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0xb8,0x08,0x00,0x08,0x00,0xfc,0x63,0x24, +0x5c,0x65,0x05,0x8e,0x21,0x30,0x80,0x00,0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x5c,0x65,0x03,0x8e,0x66,0x65,0x05,0x96, +0xbc,0x65,0x02,0x8e,0x21,0x18,0x71,0x00,0x21,0x28,0x25,0x02,0x21,0x10,0x51,0x00, +0x09,0x00,0x04,0x24,0xbc,0x65,0x02,0xae,0x5c,0x65,0x03,0xae,0x4d,0x01,0x00,0x0c, +0x66,0x65,0x05,0xa6,0x68,0x15,0x70,0x26,0xbc,0x65,0x03,0x96,0x2a,0xb0,0x02,0x3c, +0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,0x00,0x00,0x51,0xa0,0x8e,0x12,0x00,0x0c, +0x00,0x00,0x00,0x00,0x66,0x65,0x03,0x96,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34, +0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0xfc,0x4a,0x02,0x8e,0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c, +0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x28,0x00,0xbf,0x8f,0xfc,0x4a,0x02,0xae, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0xc4,0x65,0x02,0x8e,0x5c,0x65,0x05,0x8e, +0x21,0x30,0x80,0x00,0x23,0x88,0x44,0x00,0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x5c,0x65,0x03,0x8e,0x66,0x65,0x02,0x96, +0xc0,0x65,0x12,0x96,0x21,0x18,0x71,0x00,0x21,0x10,0x22,0x02,0x23,0x10,0x11,0x3c, +0x5c,0x65,0x03,0xae,0x66,0x65,0x02,0xa6,0x0c,0x00,0x40,0x16,0xbc,0x65,0x11,0xae, +0x09,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,0x68,0x15,0x70,0x26,0xfe,0x08,0x00,0x08, +0x00,0x00,0x00,0x00,0x44,0x67,0x62,0x94,0x76,0x4b,0x60,0xa0,0xe3,0x18,0x00,0x0c, +0x21,0x20,0x44,0x00,0x97,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x4d,0x01,0x00,0x0c, +0x09,0x00,0x04,0x24,0x5c,0x65,0x05,0x8e,0x09,0x00,0x04,0x24,0x23,0x10,0x06,0x3c, +0x21,0x38,0x40,0x02,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x5c,0x65,0x03,0x8e, +0x66,0x65,0x02,0x96,0x21,0x20,0x51,0x02,0x21,0x18,0x72,0x00,0x21,0x10,0x42,0x02, +0xbc,0x65,0x04,0xae,0x09,0x00,0x04,0x24,0x5c,0x65,0x03,0xae,0x2d,0x09,0x00,0x08, +0x66,0x65,0x02,0xa6,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x05,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x02,0x80,0x09,0x3c, +0x68,0x15,0x28,0x25,0xe8,0x63,0x06,0x8d,0xff,0xff,0x02,0x34,0x3f,0x00,0xc2,0x10, +0x21,0x38,0x80,0x00,0x2b,0x10,0xc7,0x00,0x30,0x00,0x40,0x10,0x02,0x19,0x06,0x00, +0x21,0x10,0xc7,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0xe8,0x63,0x06,0xad, +0x68,0x15,0x26,0x25,0x04,0x40,0xc4,0x8c,0xec,0x63,0x02,0xad,0xff,0xff,0x02,0x34, +0x2f,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x87,0x00,0x1f,0x00,0x40,0x10, +0x02,0x19,0x04,0x00,0x21,0x10,0x87,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x44,0x24, +0x04,0x40,0xc4,0xac,0xec,0x63,0xc2,0xac,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x68,0x15,0x23,0x25,0x80,0x10,0x02,0x00, +0x21,0x28,0x43,0x00,0x74,0x51,0xa6,0x8c,0x00,0x21,0x07,0x00,0xff,0xff,0xc2,0x38, +0x0a,0x30,0x82,0x00,0x2b,0x18,0xc7,0x00,0x07,0x00,0x60,0x10,0x21,0x10,0xc7,0x00, +0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0x74,0x51,0xa6,0xac, +0x08,0x00,0xe0,0x03,0x78,0x51,0xa2,0xac,0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00, +0x74,0x51,0xa2,0xac,0x08,0x00,0xe0,0x03,0x78,0x51,0xa2,0xac,0x21,0x10,0x87,0x00, +0x23,0x10,0x43,0x00,0x69,0x09,0x00,0x08,0x04,0x40,0xc2,0xac,0x21,0x10,0xc7,0x00, +0x68,0x15,0x26,0x25,0x04,0x40,0xc4,0x8c,0x23,0x10,0x43,0x00,0xe8,0x63,0x02,0xad, +0xec,0x63,0x02,0xad,0xff,0xff,0x02,0x34,0xd4,0xff,0x82,0x14,0x2b,0x10,0x87,0x00, +0x00,0x21,0x07,0x00,0x62,0x09,0x00,0x08,0x04,0x40,0xc4,0xac,0x00,0x31,0x04,0x00, +0x55,0x09,0x00,0x08,0xe8,0x63,0x06,0xad,0x63,0x00,0x82,0x24,0x77,0x00,0x42,0x2c, +0x00,0x00,0x85,0x28,0x04,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x64,0x00,0x82,0x24, +0x64,0x00,0x03,0x24,0x0b,0x18,0x45,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x0c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0x04,0x00,0x42,0x28, +0x17,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,0x24,0x08,0x42,0x34,0x00,0x00,0x43,0x8c, +0x00,0x00,0x00,0x00,0x00,0x02,0x63,0x30,0x16,0x00,0x60,0x14,0x01,0x00,0x02,0x24, +0x05,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x82,0x21,0x03,0x00,0x28,0x00,0x82,0x10, +0xf5,0xff,0x02,0x24,0x02,0x00,0x82,0x28,0x39,0x00,0x40,0x14,0x02,0x00,0x02,0x24, +0x2e,0x00,0x82,0x10,0xe9,0xff,0x02,0x24,0x03,0x00,0x02,0x24,0x24,0x00,0x82,0x10, +0x3e,0x00,0x63,0x30,0x05,0x00,0xc4,0x24,0x96,0x09,0x00,0x08,0x00,0x00,0x00,0x00, +0x04,0x00,0xa4,0x90,0x00,0x00,0x00,0x00,0x42,0x20,0x04,0x00,0x96,0x09,0x00,0x08, +0x96,0xff,0x84,0x24,0x05,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x60,0x00,0x64,0x30, +0x42,0x21,0x04,0x00,0x0e,0x00,0x82,0x10,0x1f,0x00,0x62,0x30,0x02,0x00,0x82,0x28, +0x1d,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x14,0x00,0x82,0x10,0x1f,0x00,0x62,0x30, +0x03,0x00,0x02,0x24,0xeb,0xff,0x82,0x14,0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00, +0xdd,0xff,0x03,0x24,0x23,0x30,0x62,0x00,0xba,0x09,0x00,0x08,0x05,0x00,0xc4,0x24, +0x40,0x10,0x02,0x00,0xf5,0xff,0x03,0x24,0xd2,0x09,0x00,0x08,0x23,0x30,0x62,0x00, +0x3e,0x00,0x63,0x30,0x23,0x30,0x43,0x00,0xba,0x09,0x00,0x08,0x05,0x00,0xc4,0x24, +0xdd,0xff,0x02,0x24,0xda,0x09,0x00,0x08,0x23,0x30,0x43,0x00,0x40,0x10,0x02,0x00, +0xe9,0xff,0x03,0x24,0xd2,0x09,0x00,0x08,0x23,0x30,0x62,0x00,0x3e,0x00,0x63,0x30, +0xda,0x09,0x00,0x08,0x23,0x30,0x43,0x00,0xd2,0xff,0x80,0x14,0x1f,0x00,0x62,0x30, +0x40,0x10,0x02,0x00,0xf8,0xff,0x03,0x24,0xd2,0x09,0x00,0x08,0x23,0x30,0x62,0x00, +0xcc,0xff,0x80,0x14,0x3e,0x00,0x63,0x30,0xf8,0xff,0x02,0x24,0xda,0x09,0x00,0x08, +0x23,0x30,0x43,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf, +0x14,0x00,0xb1,0xaf,0x0c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30, +0x04,0x00,0x42,0x28,0x29,0x00,0x40,0x14,0x21,0x80,0xa0,0x00,0x00,0x00,0xa4,0x8c, +0x02,0x80,0x11,0x3c,0x3f,0x00,0x84,0x30,0x40,0x20,0x04,0x00,0x96,0x09,0x00,0x0c, +0x96,0xff,0x84,0x24,0x68,0x15,0x25,0x26,0xf0,0x63,0xa4,0x8c,0x21,0x18,0x40,0x00, +0xff,0xff,0x02,0x34,0x3c,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00, +0x27,0x00,0x40,0x10,0x21,0x10,0x83,0x00,0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00, +0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24,0xf0,0x63,0xa4,0xac,0x00,0x00,0x04,0x8e, +0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00,0x7e,0x00,0x84,0x30,0x96,0x09,0x00,0x0c, +0x96,0xff,0x84,0x24,0x68,0x15,0x25,0x26,0xf4,0x63,0xa4,0x8c,0x21,0x18,0x40,0x00, +0xff,0xff,0x02,0x34,0x25,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00, +0x0b,0x00,0x40,0x10,0x21,0x10,0x83,0x00,0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00, +0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24,0xf4,0x63,0xa4,0xac,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x19,0x04,0x00, +0x23,0x10,0x43,0x00,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0xf4,0x63,0xa2,0xac, +0x02,0x19,0x04,0x00,0x23,0x10,0x43,0x00,0xf0,0x63,0xa2,0xac,0x00,0x00,0x04,0x8e, +0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00,0x7e,0x00,0x84,0x30,0x96,0x09,0x00,0x0c, +0x96,0xff,0x84,0x24,0x68,0x15,0x25,0x26,0xf4,0x63,0xa4,0x8c,0x21,0x18,0x40,0x00, +0xff,0xff,0x02,0x34,0xde,0xff,0x82,0x14,0x2b,0x10,0x83,0x00,0x00,0x21,0x03,0x00, +0x1b,0x0a,0x00,0x08,0xf4,0x63,0xa4,0xac,0x00,0x21,0x03,0x00,0x07,0x0a,0x00,0x08, +0xf0,0x63,0xa4,0xac,0x98,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x58,0x00,0xb6,0xaf, +0x64,0x00,0xbf,0xaf,0x60,0x00,0xbe,0xaf,0x5c,0x00,0xb7,0xaf,0x54,0x00,0xb5,0xaf, +0x50,0x00,0xb4,0xaf,0x4c,0x00,0xb3,0xaf,0x48,0x00,0xb2,0xaf,0x44,0x00,0xb1,0xaf, +0x40,0x00,0xb0,0xaf,0x68,0x15,0x56,0x24,0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34, +0x00,0x00,0x43,0x8c,0xa4,0x65,0xc7,0x8e,0x00,0x00,0x00,0x00,0x34,0x00,0xe3,0x10, +0xa8,0x65,0xc3,0xae,0x2b,0x10,0x67,0x00,0xaa,0x00,0x40,0x14,0x2b,0x10,0xe3,0x00, +0xd4,0x00,0x40,0x14,0x02,0x80,0x02,0x3c,0x68,0x15,0x44,0x24,0x78,0x65,0x83,0x94, +0x02,0x80,0x02,0x3c,0x21,0x88,0x00,0x00,0x19,0x00,0x40,0x1a,0x25,0x98,0x62,0x00, +0x21,0xf0,0x80,0x00,0x21,0xb8,0x80,0x00,0x01,0x00,0x15,0x24,0x21,0x20,0x00,0x00, +0x21,0x80,0x93,0x00,0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00,0x07,0x00,0xa0,0x10, +0x01,0x00,0x22,0x26,0x04,0x00,0x02,0x8e,0x00,0xf0,0x03,0x3c,0x00,0x20,0x04,0x3c, +0x24,0x10,0x43,0x00,0x1f,0x00,0x44,0x10,0x06,0x00,0x22,0x26,0xff,0xff,0x51,0x30, +0x82,0x16,0x05,0x00,0x01,0x00,0x42,0x30,0x35,0x00,0x55,0x10,0x00,0x00,0x00,0x00, +0x80,0x20,0x11,0x00,0x2a,0x10,0x92,0x00,0xed,0xff,0x40,0x14,0x00,0x00,0x00,0x00, +0x38,0x00,0xa4,0x8f,0x70,0x4f,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c, +0x08,0x04,0x44,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0xfe,0x1f,0x00,0x0c, +0x21,0x38,0x00,0x00,0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34,0x00,0x00,0x43,0x8c, +0xa4,0x65,0xc7,0x8e,0x00,0x00,0x00,0x00,0xce,0xff,0xe3,0x14,0xa8,0x65,0xc3,0xae, +0x25,0xb0,0x03,0x3c,0x00,0x01,0x62,0x34,0x00,0x00,0x47,0xac,0x7f,0x0a,0x00,0x08, +0xa4,0x65,0xc7,0xae,0xbc,0x4c,0xc2,0x8f,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24, +0xbc,0x4c,0xc2,0xaf,0x0c,0x00,0x04,0x8e,0x0c,0x00,0x02,0x24,0x3f,0x00,0x83,0x30, +0x65,0x00,0x62,0x10,0x21,0x28,0xc0,0x03,0x3f,0x00,0x83,0x30,0x0d,0x00,0x02,0x24, +0x5a,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x3f,0x00,0x83,0x30,0x0e,0x00,0x02,0x24, +0x04,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x8e,0x73,0x0a,0x00,0x08, +0x06,0x00,0x22,0x26,0xc8,0x4c,0xc2,0x8f,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24, +0xc8,0x4c,0xc2,0xaf,0x00,0x00,0x05,0x8e,0x73,0x0a,0x00,0x08,0x06,0x00,0x22,0x26, +0x00,0x40,0xe2,0x8e,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x0f,0x00,0x42,0x30, +0x05,0x00,0x55,0x10,0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,0x21,0x10,0x51,0x00, +0x78,0x0a,0x00,0x08,0xff,0xff,0x51,0x30,0x02,0x40,0xe2,0x92,0x00,0x00,0x00,0x00, +0x1f,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,0x04,0x00,0x03,0x8e,0x00,0x00,0x00,0x00, +0x02,0x14,0x03,0x00,0x0f,0x00,0x42,0x30,0x18,0x00,0x40,0x14,0x02,0x17,0x03,0x00, +0x03,0x00,0x44,0x30,0x08,0x00,0x80,0x10,0x00,0xc0,0x02,0x3c,0x24,0x10,0x62,0x00, +0x12,0x00,0x40,0x14,0x03,0x00,0x02,0x24,0x11,0x00,0x82,0x10,0x02,0x80,0x03,0x3c, +0x10,0x00,0x80,0x10,0x68,0x15,0x63,0x24,0x80,0x10,0x11,0x00,0x21,0xa0,0x53,0x00, +0xec,0xff,0x83,0x8e,0x25,0xb0,0x02,0x3c,0xd4,0x02,0x42,0x34,0x21,0x28,0x80,0x02, +0x21,0x20,0x00,0x02,0x00,0x00,0x43,0xac,0xa0,0x09,0x00,0x0c,0x00,0x00,0x00,0x00, +0x21,0x20,0x40,0x00,0x4f,0x09,0x00,0x0c,0x21,0x28,0x00,0x00,0x02,0x80,0x03,0x3c, +0x68,0x15,0x63,0x24,0x02,0x40,0x62,0x90,0x00,0x00,0x00,0x00,0x88,0x00,0x55,0x10, +0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0x02,0x40,0x83,0x90, +0x02,0x00,0x02,0x24,0x6a,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c, +0x4c,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30, +0x08,0x00,0x55,0x10,0x02,0x80,0x04,0x3c,0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00, +0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,0x21,0x10,0x51,0x00,0x78,0x0a,0x00,0x08, +0xff,0xff,0x51,0x30,0xd0,0x02,0x02,0x24,0x68,0x15,0x84,0x24,0xe8,0x63,0x82,0xac, +0x00,0x00,0x05,0x8e,0xed,0x0a,0x00,0x08,0xc2,0x13,0x05,0x00,0xc4,0x4c,0xa2,0x8c, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xc4,0x4c,0xa2,0xac,0x0c,0x00,0x04,0x8e, +0x9f,0x0a,0x00,0x08,0x3f,0x00,0x83,0x30,0xc0,0x4c,0xc2,0x8f,0x00,0x00,0x00,0x00, +0x01,0x00,0x42,0x24,0xc0,0x4c,0xc2,0xaf,0x0c,0x00,0x04,0x8e,0x9b,0x0a,0x00,0x08, +0x3f,0x00,0x83,0x30,0xac,0x65,0xc2,0x8e,0xff,0xff,0x71,0x30,0x23,0x10,0x47,0x00, +0xff,0xff,0x50,0x30,0x21,0x18,0x11,0x02,0xff,0xff,0x72,0x30,0x54,0x4f,0x00,0x0c, +0x21,0x20,0x40,0x02,0x7d,0x00,0x40,0x10,0x38,0x00,0xa2,0xaf,0x38,0x00,0xa3,0x8f, +0xa4,0x65,0xc6,0x8e,0x21,0x38,0x00,0x02,0x08,0x00,0x62,0x8c,0x08,0x00,0x04,0x24, +0x10,0x00,0xa0,0xaf,0x21,0x18,0x52,0x00,0x21,0x28,0x40,0x00,0x74,0x65,0xc3,0xae, +0x10,0x01,0x00,0x0c,0x78,0x65,0xc2,0xae,0x4d,0x01,0x00,0x0c,0x08,0x00,0x04,0x24, +0x78,0x65,0xc5,0x8e,0x25,0xb0,0x04,0x3c,0x24,0x10,0x02,0x3c,0x21,0x28,0xb0,0x00, +0x00,0x01,0x90,0x34,0x00,0x00,0x02,0xae,0x21,0x38,0x20,0x02,0x08,0x00,0x04,0x24, +0x24,0x10,0x06,0x3c,0xa4,0x65,0xc2,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0xa8,0x65,0xc3,0x8e,0x08,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,0xa4,0x65,0xc3,0xae, +0xa4,0x65,0xc2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xae,0x5e,0x0a,0x00,0x08, +0x02,0x80,0x02,0x3c,0x23,0x10,0x67,0x00,0xff,0xff,0x52,0x30,0x54,0x4f,0x00,0x0c, +0x21,0x20,0x40,0x02,0x5c,0x00,0x40,0x10,0x38,0x00,0xa2,0xaf,0x38,0x00,0xa3,0x8f, +0xa4,0x65,0xc6,0x8e,0x08,0x00,0x04,0x24,0x08,0x00,0x62,0x8c,0x21,0x38,0x40,0x02, +0x10,0x00,0xa0,0xaf,0x21,0x18,0x52,0x00,0x21,0x28,0x40,0x00,0x74,0x65,0xc3,0xae, +0x10,0x01,0x00,0x0c,0x78,0x65,0xc2,0xae,0xa8,0x65,0xc3,0x8e,0x08,0x00,0x04,0x24, +0x4d,0x01,0x00,0x0c,0xa4,0x65,0xc3,0xae,0xa4,0x65,0xc3,0x8e,0x25,0xb0,0x04,0x3c, +0x00,0x01,0x82,0x34,0x00,0x00,0x43,0xac,0x5e,0x0a,0x00,0x08,0x02,0x80,0x02,0x3c, +0x04,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x03,0x00,0x0f,0x00,0x42,0x30, +0x08,0x00,0x42,0x28,0x91,0xff,0x40,0x10,0x02,0x17,0x03,0x00,0x03,0x00,0x42,0x30, +0x8e,0xff,0x40,0x14,0x80,0x10,0x11,0x00,0x21,0xa0,0x53,0x00,0xec,0xff,0x83,0x8e, +0x25,0xb0,0x02,0x3c,0xd4,0x02,0x42,0x34,0x21,0x28,0x80,0x02,0x21,0x20,0x00,0x02, +0x00,0x00,0x43,0xac,0xa0,0x09,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00, +0x4f,0x09,0x00,0x0c,0x21,0x28,0x00,0x00,0xe4,0x0a,0x00,0x08,0x25,0xb0,0x03,0x3c, +0x04,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x03,0x00,0x0f,0x00,0x42,0x30, +0x08,0x00,0x42,0x28,0x06,0x00,0x40,0x10,0x00,0xc0,0x02,0x3c,0x02,0x17,0x03,0x00, +0x03,0x00,0x42,0x30,0x0c,0x00,0x40,0x10,0x80,0x10,0x11,0x00,0x00,0xc0,0x02,0x3c, +0x24,0x10,0x62,0x00,0x6c,0xff,0x40,0x14,0x02,0x80,0x04,0x3c,0x02,0x17,0x03,0x00, +0x03,0x00,0x42,0x30,0x03,0x00,0x03,0x24,0x68,0xff,0x43,0x10,0x68,0x15,0x84,0x24, +0x64,0xff,0x40,0x10,0x80,0x10,0x11,0x00,0x21,0xa0,0x53,0x00,0xec,0xff,0x83,0x8e, +0x25,0xb0,0x02,0x3c,0xd4,0x02,0x42,0x34,0x21,0x20,0x00,0x02,0x21,0x28,0x80,0x02, +0x00,0x00,0x43,0xac,0xa0,0x09,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00, +0x4f,0x09,0x00,0x0c,0x21,0x28,0x00,0x00,0x21,0x20,0x00,0x02,0xf1,0x09,0x00,0x0c, +0x21,0x28,0x80,0x02,0xde,0x0a,0x00,0x08,0x02,0x80,0x04,0x3c,0x25,0xb0,0x04,0x3c, +0x44,0x44,0x02,0x3c,0xbc,0x02,0x83,0x34,0x44,0x44,0x42,0x34,0x00,0x00,0x62,0xac, +0x80,0x0a,0x00,0x08,0x02,0x80,0x02,0x3c,0xa8,0x65,0xc5,0x8e,0x25,0xb0,0x02,0x3c, +0x00,0x01,0x43,0x34,0xbc,0x02,0x44,0x34,0x66,0x66,0x02,0x3c,0x66,0x66,0x42,0x34, +0x00,0x00,0x65,0xac,0x00,0x00,0x82,0xac,0x7f,0x0a,0x00,0x08,0xa4,0x65,0xc5,0xae, +0x25,0xb0,0x06,0x3c,0x00,0x80,0x02,0x3c,0x2a,0xb0,0x04,0x3c,0x18,0x03,0xc5,0x34, +0x70,0x2e,0x42,0x24,0x00,0x00,0xa2,0xac,0x22,0x00,0x83,0x34,0x1a,0x00,0x85,0x34, +0x00,0x00,0x67,0x94,0x06,0x00,0x84,0x34,0x00,0x00,0xa2,0x94,0x00,0x00,0x83,0x94, +0xff,0x00,0xed,0x30,0xff,0x00,0x42,0x30,0x21,0x68,0x4d,0x00,0xff,0x00,0x63,0x30, +0x21,0x68,0x6d,0x00,0x68,0x03,0xc2,0x34,0x02,0x80,0x07,0x3c,0x00,0x00,0x4d,0xa4, +0x68,0x15,0xe7,0x24,0xc6,0x00,0xc3,0x34,0xca,0x00,0xc4,0x34,0x00,0x00,0x6b,0x90, +0x60,0x4b,0xe5,0x8c,0x00,0x00,0x82,0x90,0xcc,0x00,0xc3,0x34,0x00,0x00,0x68,0x90, +0xd4,0x00,0xc4,0x34,0x64,0x4b,0xe3,0x8c,0x00,0x00,0x8a,0x90,0x61,0x4b,0xec,0x90, +0xff,0x00,0x04,0x3c,0x00,0x4a,0x0d,0x00,0x23,0x48,0x2d,0x01,0x24,0x28,0xa4,0x00, +0xff,0x00,0x6d,0x31,0xff,0x00,0x42,0x30,0x21,0x10,0xa2,0x01,0x24,0x18,0x64,0x00, +0x02,0x2c,0x05,0x00,0x69,0x4b,0xe4,0x90,0xff,0x00,0x08,0x31,0x21,0x60,0x85,0x01, +0x02,0x1c,0x03,0x00,0x21,0x10,0x48,0x00,0xff,0x00,0x4a,0x31,0x21,0x10,0x4a,0x00, +0x21,0x60,0x83,0x01,0x21,0x60,0x84,0x01,0xff,0xff,0x4d,0x30,0x23,0x18,0x8d,0x01, +0xff,0xff,0x6c,0x30,0xff,0xff,0x29,0x31,0x6a,0x03,0xc2,0x34,0x6c,0x03,0xc3,0x34, +0x1f,0x03,0xc5,0x34,0x2b,0x20,0x2c,0x01,0x6e,0x03,0xc6,0x34,0x00,0x00,0x49,0xa4, +0x00,0x00,0x6d,0xa4,0x00,0x00,0xcc,0xa4,0x05,0x00,0x80,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x00,0x00,0xa3,0xa0, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x70,0x9a,0x64,0xac, +0x00,0x60,0x82,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c, +0x70,0x9a,0x45,0x8c,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34, +0xac,0x2f,0x63,0x24,0x00,0x00,0x43,0xac,0x04,0x00,0x02,0x24,0x1e,0x00,0xa2,0x10, +0x05,0x00,0xa2,0x2c,0x10,0x00,0x40,0x10,0x05,0x00,0x02,0x24,0x03,0x00,0x02,0x24, +0x08,0x00,0xa2,0x10,0x00,0x19,0x04,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00, +0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,0x21,0x10,0x44,0x00, +0x40,0x19,0x02,0x00,0xff,0xff,0x63,0x24,0xfe,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf3,0xff,0xa2,0x10,0x06,0x00,0x02,0x24, +0xf2,0xff,0xa2,0x14,0x80,0x10,0x04,0x00,0x40,0x11,0x04,0x00,0x23,0x10,0x44,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x00,0x19,0x02,0x00,0x23,0x18,0x62,0x00, +0x01,0x0c,0x00,0x08,0x00,0x19,0x03,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00, +0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,0x21,0x10,0x44,0x00, +0x01,0x0c,0x00,0x08,0x00,0x19,0x02,0x00,0x02,0x80,0x02,0x3c,0x70,0x9a,0x45,0x8c, +0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,0x68,0x30,0x63,0x24, +0x00,0x00,0x43,0xac,0x05,0x00,0x02,0x24,0x10,0x00,0xa2,0x10,0x06,0x00,0xa2,0x2c, +0x09,0x00,0x40,0x14,0x04,0x00,0x02,0x24,0x06,0x00,0x02,0x24,0x0f,0x00,0xa2,0x10, +0x00,0x11,0x04,0x00,0xff,0xff,0x84,0x24,0xfe,0xff,0x80,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xfa,0xff,0xa2,0x14,0x80,0x10,0x04,0x00, +0x21,0x10,0x44,0x00,0x29,0x0c,0x00,0x08,0x40,0x20,0x02,0x00,0x80,0x10,0x04,0x00, +0x21,0x10,0x44,0x00,0x29,0x0c,0x00,0x08,0x80,0x20,0x02,0x00,0x23,0x10,0x44,0x00, +0x29,0x0c,0x00,0x08,0x40,0x20,0x02,0x00,0xff,0xff,0x85,0x30,0x21,0x30,0x00,0x00, +0x25,0xb0,0x03,0x3c,0x2a,0xb0,0x04,0x3c,0xb4,0x00,0x63,0x34,0x01,0x00,0xa2,0x24, +0x31,0x00,0x84,0x34,0x00,0x00,0x65,0xa0,0x00,0x00,0x85,0xa0,0xff,0xff,0x45,0x30, +0x12,0x00,0xa0,0x10,0x01,0x00,0x03,0x24,0x28,0xb0,0x07,0x3c,0x4f,0x0c,0x00,0x08, +0xff,0xff,0x08,0x24,0x00,0x00,0x83,0xa0,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30, +0x2b,0x10,0xa3,0x00,0x09,0x00,0x40,0x14,0x08,0x00,0xc6,0x24,0xf9,0xff,0x65,0x14, +0x21,0x20,0xc7,0x00,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,0x2b,0x10,0xa3,0x00, +0x00,0x00,0x88,0xa0,0xf9,0xff,0x40,0x10,0x08,0x00,0xc6,0x24,0x00,0x01,0xa2,0x2c, +0x13,0x00,0x40,0x10,0x21,0x18,0xa0,0x00,0xff,0x00,0x08,0x24,0x28,0xb0,0x07,0x3c, +0x63,0x0c,0x00,0x08,0xff,0xff,0x09,0x24,0xff,0xff,0x43,0x30,0x00,0x00,0xa2,0xa0, +0x00,0x01,0x62,0x2c,0x0a,0x00,0x40,0x10,0x08,0x00,0xc6,0x24,0x01,0x00,0x62,0x24, +0xf9,0xff,0x68,0x14,0x21,0x28,0xc7,0x00,0x00,0x01,0x02,0x24,0xff,0xff,0x43,0x30, +0x00,0x01,0x62,0x2c,0x00,0x00,0xa9,0xa0,0xf8,0xff,0x40,0x14,0x08,0x00,0xc6,0x24, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x28,0x00,0xbf,0xaf, +0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x12,0x40,0x01,0x00,0x41,0x36, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x42,0x00,0x15,0x36, +0xff,0xff,0x02,0x24,0x00,0x00,0xa2,0xa2,0xd8,0x00,0x05,0x36,0x40,0x00,0x11,0x36, +0xa8,0x00,0x14,0x36,0xa0,0x00,0x13,0x36,0x00,0x10,0x03,0x24,0xa4,0x00,0x10,0x36, +0x00,0x80,0x02,0x3c,0x00,0x00,0x23,0xa6,0x00,0x00,0xa0,0xa0,0x00,0x00,0x60,0xae, +0x00,0x00,0x00,0xae,0x00,0x00,0x82,0xae,0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24, +0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00,0xfc,0x17,0x02,0x24,0x00,0x00,0xa3,0xa0, +0x00,0x00,0x22,0xa6,0x3a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c, +0x68,0x15,0x42,0x24,0x68,0x4b,0x45,0x8c,0x60,0x4b,0x43,0x8c,0x64,0x4b,0x44,0x8c, +0xfc,0x37,0x02,0x24,0x00,0x00,0x63,0xae,0x00,0x00,0x04,0xae,0x00,0x00,0x85,0xae, +0x00,0x00,0x22,0xa6,0x00,0x00,0xa0,0xa2,0x00,0x60,0x92,0x40,0x28,0x00,0xbf,0x8f, +0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27, +0xc8,0xff,0xbd,0x27,0x34,0x00,0xbf,0xaf,0x30,0x00,0xbe,0xaf,0x2c,0x00,0xb7,0xaf, +0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf, +0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x16,0x40, +0x01,0x00,0xc1,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x11,0x3c, +0x40,0x00,0x30,0x36,0xff,0xff,0x02,0x24,0x42,0x00,0x3e,0x36,0xfc,0x77,0x13,0x24, +0x00,0x00,0xc2,0xa3,0xfc,0x57,0x12,0x24,0x00,0x00,0x13,0xa6,0x1a,0x0c,0x00,0x0c, +0x32,0x00,0x04,0x24,0xfc,0x37,0x17,0x24,0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6, +0x1a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x32,0x00,0x04,0x24,0x00,0x00,0x17,0xa6, +0x1a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xa6,0x1a,0x0c,0x00,0x0c, +0x32,0x00,0x04,0x24,0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6,0x1a,0x0c,0x00,0x0c, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x96,0x24,0xfa,0x03,0x24,0xd8,0x00,0x25,0x36, +0x24,0x10,0x43,0x00,0x00,0x00,0x02,0xa6,0x00,0x00,0xa3,0x90,0xa0,0x00,0x34,0x36, +0xa4,0x00,0x35,0x36,0xa8,0x00,0x33,0x36,0x7f,0x00,0x63,0x30,0x00,0x80,0x02,0x3c, +0x00,0x00,0xa3,0xa0,0x00,0x00,0x80,0xae,0x00,0x00,0xa0,0xae,0x00,0x00,0x62,0xae, +0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00, +0x00,0x00,0xa3,0xa0,0x00,0x00,0x12,0xa6,0x3a,0x0c,0x00,0x0c,0x56,0x01,0x31,0x36, +0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x68,0x4b,0x45,0x8c,0x60,0x4b,0x43,0x8c, +0x64,0x4b,0x44,0x8c,0xff,0x0f,0x02,0x24,0x00,0x00,0x83,0xae,0x00,0x00,0xa4,0xae, +0x00,0x00,0x65,0xae,0x00,0x00,0x17,0xa6,0x00,0x00,0x22,0xa6,0x00,0x00,0xc0,0xa3, +0x00,0x60,0x96,0x40,0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f, +0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x38,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf, +0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x40,0x00,0x05,0x36, +0x00,0x00,0xa2,0x94,0xaf,0xff,0x03,0x24,0xa8,0x00,0x13,0x36,0x24,0x10,0x43,0x00, +0x00,0x00,0xa2,0xa4,0xa0,0x00,0x12,0x36,0xa4,0x00,0x10,0x36,0x00,0x00,0x55,0x8e, +0x00,0x00,0x16,0x8e,0x00,0x00,0x71,0x8e,0x00,0x80,0x14,0x3c,0xfc,0x37,0x02,0x24, +0x00,0x00,0x40,0xae,0xfd,0x00,0x04,0x24,0x00,0x00,0x00,0xae,0x21,0x88,0x34,0x02, +0x00,0x00,0x74,0xae,0x00,0x00,0xa2,0xa4,0x3a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x00,0x55,0xae,0x00,0x00,0x16,0xae,0x00,0x00,0x71,0xae,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f, +0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x25,0xb0,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0xd8,0xfd,0x03,0x24, +0x24,0x10,0x43,0x00,0xfc,0x37,0x03,0x24,0x00,0x00,0x82,0xa4,0x00,0x00,0x83,0xa4, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xff,0xff,0xc6,0x30,0x10,0x00,0x02,0x24,0x0c,0x00,0xc2,0x10,0x11,0x00,0xc3,0x28, +0x06,0x00,0x60,0x10,0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24,0x0d,0x00,0xc2,0x10, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x06,0x00,0xc2,0x10, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xa4, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0xff,0xff,0xa5,0x24, +0x00,0x2c,0x05,0x00,0xfd,0x00,0x63,0x30,0x03,0x2c,0x05,0x00,0xff,0xff,0x87,0x30, +0x00,0x00,0x43,0xa0,0x1a,0x00,0xa0,0x04,0x00,0x00,0x00,0x00,0x21,0x30,0x40,0x00, +0x07,0x10,0xa7,0x00,0x01,0x00,0x42,0x30,0xfd,0x00,0x64,0x30,0x00,0x00,0x42,0x38, +0x02,0x00,0x63,0x34,0x0a,0x18,0x82,0x00,0x00,0x00,0xc3,0xa0,0x04,0x00,0x63,0x34, +0x00,0x00,0xc3,0xa0,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04, +0xff,0xff,0x42,0x24,0xfb,0x00,0x63,0x30,0x00,0x00,0xc3,0xa0,0x04,0x00,0x02,0x24, +0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xff,0xff,0xa2,0x24, +0x00,0x2c,0x02,0x00,0x03,0x2c,0x05,0x00,0xea,0xff,0xa1,0x04,0x07,0x10,0xa7,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34, +0x00,0x00,0x43,0x90,0xff,0xff,0x84,0x24,0x00,0x24,0x04,0x00,0x03,0x24,0x04,0x00, +0xff,0x00,0x65,0x30,0x1d,0x00,0x80,0x04,0x21,0x38,0x00,0x00,0x21,0x30,0x40,0x00, +0x01,0x00,0x08,0x24,0x04,0x00,0xa5,0x34,0x00,0x00,0xc5,0xa0,0x00,0x00,0xc2,0x90, +0x00,0x00,0x00,0x00,0xff,0x00,0x45,0x30,0x01,0x00,0xa3,0x30,0x05,0x00,0x60,0x10, +0x04,0x00,0x02,0x24,0x04,0x10,0x88,0x00,0x25,0x10,0x47,0x00,0xff,0xff,0x47,0x30, +0x04,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24, +0xfb,0x00,0xa5,0x30,0x00,0x00,0xc5,0xa0,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24, +0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xff,0xff,0x82,0x24,0x00,0x24,0x02,0x00, +0x03,0x24,0x04,0x00,0xe7,0xff,0x81,0x04,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0xe0,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x25,0xb0,0x10,0x3c, +0x0a,0x00,0x10,0x36,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x00,0x00,0x02,0x92, +0xff,0xff,0x91,0x30,0x03,0x00,0x05,0x24,0xc0,0x00,0x42,0x30,0x80,0x00,0x43,0x34, +0x00,0x00,0x03,0xa2,0x04,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,0xfb,0x00,0x63,0x30, +0x00,0x00,0x03,0xa2,0x08,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,0x04,0x00,0x63,0x34, +0x00,0x00,0x03,0xa2,0xfb,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,0x64,0x0d,0x00,0x0c, +0x06,0x00,0x04,0x24,0x42,0x20,0x11,0x00,0x64,0x0d,0x00,0x0c,0x06,0x00,0x05,0x24, +0x8a,0x0d,0x00,0x0c,0x10,0x00,0x04,0x24,0x00,0x00,0x03,0x92,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0xc0,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf, +0xff,0xff,0xb1,0x30,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf, +0x21,0x90,0xc0,0x00,0x0a,0x00,0x20,0x12,0xff,0xff,0x90,0x30,0xb1,0x0d,0x00,0x0c, +0x21,0x20,0x00,0x02,0xfe,0xff,0x23,0x26,0x02,0x00,0x04,0x26,0x00,0x00,0x42,0xa6, +0xff,0xff,0x71,0x30,0xff,0xff,0x90,0x30,0xf8,0xff,0x20,0x16,0x02,0x00,0x52,0x26, +0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x25,0xb0,0x03,0x3c,0x0a,0x00,0x68,0x34, +0x00,0x00,0x02,0x91,0xff,0xff,0xa5,0x30,0xff,0x00,0x84,0x30,0x1f,0x00,0xa0,0x10, +0xff,0x00,0x47,0x30,0x21,0x48,0x00,0x01,0x0c,0x00,0x6c,0x34,0x0b,0x00,0x6b,0x34, +0xc0,0xff,0x0a,0x24,0x21,0x68,0x00,0x01,0x25,0x10,0xea,0x00,0xff,0x00,0x47,0x30, +0x00,0x00,0x64,0xa1,0x00,0x00,0x27,0xa1,0x00,0x00,0x22,0x91,0x00,0x00,0x00,0x00, +0xff,0x00,0x47,0x30,0xc0,0x00,0xe3,0x30,0x08,0x00,0x60,0x10,0x00,0x00,0x00,0x00, +0x21,0x40,0xa0,0x01,0x00,0x00,0x02,0x91,0x00,0x00,0x00,0x00,0xff,0x00,0x47,0x30, +0xc0,0x00,0xe3,0x30,0xfb,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x8d, +0xfc,0xff,0xa3,0x24,0x04,0x00,0x84,0x24,0xff,0xff,0x65,0x30,0x00,0x00,0xc2,0xac, +0xff,0x00,0x84,0x30,0xe8,0xff,0xa0,0x14,0x04,0x00,0xc6,0x24,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xff,0x00,0x84,0x30,0x21,0x68,0xe0,0x00,0xff,0xff,0xa5,0x30, +0xc0,0x50,0x04,0x00,0x00,0x60,0x0c,0x40,0x01,0x00,0x81,0x35,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x00,0x00,0xc2,0x90,0x01,0x00,0xc3,0x90,0x25,0xb0,0x07,0x3c, +0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,0x00,0x1e,0x03,0x00,0x01,0x80,0x08,0x3c, +0x25,0x20,0xa3,0x00,0x40,0x02,0xe9,0x34,0x25,0x18,0x48,0x01,0x44,0x02,0xe7,0x34, +0x00,0x00,0xe4,0xac,0x00,0x00,0x23,0xad,0x03,0x00,0xc2,0x90,0x02,0x00,0xc4,0x90, +0x04,0x00,0xc3,0x90,0x05,0x00,0xc5,0x90,0x00,0x12,0x02,0x00,0x25,0x20,0x82,0x00, +0x00,0x1c,0x03,0x00,0x01,0x00,0x4a,0x25,0x25,0x20,0x83,0x00,0x00,0x2e,0x05,0x00, +0x25,0x40,0x48,0x01,0x25,0x20,0x85,0x00,0x00,0x00,0xe4,0xac,0x01,0x00,0x4a,0x25, +0x00,0x00,0x28,0xad,0x01,0x80,0x0b,0x3c,0x21,0x40,0x00,0x00,0x21,0x10,0xa8,0x01, +0x01,0x00,0x43,0x90,0x00,0x00,0x45,0x90,0x02,0x00,0x44,0x90,0x03,0x00,0x46,0x90, +0x00,0x1a,0x03,0x00,0x25,0x28,0xa3,0x00,0x00,0x24,0x04,0x00,0x25,0x28,0xa4,0x00, +0x00,0x36,0x06,0x00,0x04,0x00,0x08,0x25,0x25,0x10,0x4b,0x01,0x25,0x20,0xa6,0x00, +0x10,0x00,0x03,0x2d,0x00,0x00,0xe4,0xac,0x01,0x00,0x4a,0x25,0x00,0x00,0x22,0xad, +0xee,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x8c,0x40,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xff,0xff,0x84,0x30,0x42,0xb0,0x08,0x3c,0x80,0x10,0x04,0x00, +0x21,0x10,0x48,0x00,0x04,0x00,0x46,0xac,0x00,0x00,0x07,0x91,0x40,0x18,0x04,0x00, +0x03,0x00,0x06,0x24,0xff,0x00,0xe7,0x30,0x04,0x30,0x66,0x00,0x01,0x00,0x02,0x24, +0x04,0x10,0x62,0x00,0x25,0x30,0xc7,0x00,0xff,0xff,0xa5,0x30,0x25,0x10,0x47,0x00, +0x02,0x00,0xa0,0x14,0xff,0x00,0xc7,0x30,0xff,0x00,0x47,0x30,0x42,0xb0,0x02,0x3c, +0x00,0x00,0x47,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x42,0xb0,0x02,0x3c, +0x03,0x00,0x47,0x34,0x00,0x00,0xe3,0x90,0xff,0x00,0x84,0x30,0x04,0x00,0x84,0x24, +0xff,0x00,0x65,0x30,0x01,0x00,0x02,0x24,0x04,0x30,0x82,0x00,0x07,0x18,0x85,0x00, +0x25,0xb0,0x02,0x3c,0xe8,0x03,0x42,0x34,0x01,0x00,0x63,0x30,0x21,0x20,0xc0,0x00, +0x00,0x00,0x45,0xa0,0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0xa0, +0x08,0x00,0xe0,0x03,0x24,0x10,0x85,0x00,0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x74,0x9a,0x42,0x24, +0x04,0x00,0x45,0x8c,0x00,0x00,0x82,0xac,0x04,0x00,0x44,0xac,0x00,0x00,0xa4,0xac, +0x04,0x00,0x85,0xac,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x14,0x00,0x83,0x90,0x01,0x00,0x02,0x24,0x08,0x00,0x86,0xac,0x18,0x00,0x85,0xac, +0x00,0x00,0x84,0xac,0x03,0x00,0x62,0x10,0x04,0x00,0x84,0xac,0x7a,0x0e,0x00,0x08, +0x0c,0x00,0x80,0xac,0x0c,0x00,0x82,0x8c,0x7a,0x0e,0x00,0x08,0x10,0x00,0x82,0xac, +0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x04,0x00,0x85,0x8c,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac, +0x04,0x00,0x45,0xac,0x00,0x00,0x84,0xac,0x04,0x00,0x84,0xac,0x00,0x60,0x83,0x40, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x28,0x00,0xb6,0xaf, +0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x14,0x00,0xb1,0xaf,0x2c,0x00,0xbf,0xaf, +0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x80,0x16,0x3c, +0x02,0x80,0x14,0x3c,0x02,0x80,0x11,0x3c,0x02,0x80,0x15,0x3c,0x24,0x7e,0x24,0x8e, +0x25,0xb0,0x02,0x3c,0x88,0x3a,0xc3,0x26,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x74,0x9a,0x90,0x8e,0x18,0x00,0x80,0x10,0x74,0x9a,0x82,0x26,0x15,0x00,0x02,0x12, +0x00,0x00,0x00,0x00,0x21,0x98,0x40,0x00,0x01,0x00,0x12,0x24,0x14,0x00,0x02,0x92, +0x00,0x00,0x00,0x00,0x1d,0x00,0x52,0x10,0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0x8e,0x24,0x7e,0x22,0x8e,0x00,0x00,0x00,0x00, +0x23,0x20,0x62,0x00,0x2b,0x10,0x43,0x00,0x0e,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x0c,0x00,0x04,0xae,0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0xef,0xff,0x13,0x16, +0x00,0x00,0x00,0x00,0x24,0x7e,0x20,0xae,0x08,0x0c,0xa4,0x26,0x21,0x28,0x00,0x00, +0x21,0x30,0x00,0x00,0xfe,0x1f,0x00,0x0c,0x21,0x38,0x00,0x00,0xaf,0x0e,0x00,0x08, +0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00, +0x00,0x00,0x00,0x00,0xc9,0x0e,0x00,0x08,0x0c,0x00,0x02,0xae,0x0c,0x00,0x03,0x8e, +0x24,0x7e,0x22,0x8e,0x00,0x00,0x00,0x00,0x23,0x20,0x62,0x00,0x2b,0x10,0x43,0x00, +0xe7,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e, +0x09,0xf8,0x40,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,0x8e,0xc9,0x0e,0x00,0x08, +0x0c,0x00,0x03,0xae,0x02,0x80,0x02,0x3c,0x60,0x79,0x43,0x8c,0xff,0x00,0xa5,0x30, +0x25,0xb0,0x02,0x3c,0x42,0x18,0x03,0x00,0x21,0x30,0xa2,0x00,0x01,0x00,0x63,0x30, +0x01,0x00,0x02,0x24,0x10,0x00,0xa7,0x2c,0x04,0x00,0x62,0x10,0xff,0x00,0x84,0x30, +0x60,0x01,0xc4,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c, +0x10,0x00,0xa2,0x34,0xfa,0xff,0xe0,0x10,0x21,0x40,0x43,0x00,0x60,0x01,0xc4,0xa0, +0x60,0x01,0x04,0xa1,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x84,0x30, +0x01,0x00,0x03,0x24,0x10,0x00,0x02,0x3c,0x04,0x18,0x83,0x00,0xf0,0x70,0x42,0x34, +0x15,0x00,0x84,0x2c,0x06,0x00,0x80,0x10,0x24,0x28,0x62,0x00,0x0f,0x00,0x63,0x30, +0x04,0x00,0xa0,0x14,0x01,0x00,0x02,0x24,0x02,0x00,0x60,0x14,0x02,0x00,0x02,0x24, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0xa5,0x30, +0x04,0x00,0xa2,0x2c,0x14,0x00,0x40,0x10,0xff,0x00,0x84,0x30,0x02,0x80,0x03,0x3c, +0xee,0x7d,0x62,0x90,0x00,0x00,0x00,0x00,0xef,0xff,0x42,0x24,0xff,0x00,0x42,0x30, +0x02,0x00,0x42,0x2c,0x0e,0x00,0x40,0x10,0x02,0x00,0x03,0x24,0x24,0x00,0x83,0x10, +0x0f,0x10,0x02,0x3c,0x03,0x00,0x82,0x28,0x14,0x00,0x40,0x10,0x03,0x00,0x02,0x24, +0x01,0x00,0x02,0x24,0x2f,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x02,0x3c, +0x08,0x00,0xe0,0x03,0xff,0xff,0x42,0x34,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x35,0x00,0x83,0x10,0x0f,0x1f,0x02,0x3c,0x03,0x00,0x82,0x28,0x16,0x00,0x40,0x10, +0x03,0x00,0x02,0x24,0x01,0x00,0x02,0x24,0xf4,0xff,0x82,0x14,0x00,0x00,0x00,0x00, +0x0f,0x1f,0x02,0x3c,0x08,0x00,0xe0,0x03,0x00,0x80,0x42,0x34,0xf0,0xff,0x82,0x14, +0xff,0x1f,0x02,0x3c,0x01,0x00,0x02,0x24,0x29,0x00,0xa2,0x10,0x0f,0x10,0x02,0x3c, +0x02,0x00,0xa2,0x28,0x1f,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x28,0x00,0xa3,0x10, +0x00,0x00,0x00,0x00,0xe5,0xff,0xa4,0x14,0x00,0x00,0x00,0x00,0x0f,0x10,0x02,0x3c, +0x08,0x00,0xe0,0x03,0x00,0xf0,0x42,0x34,0xe1,0xff,0x82,0x14,0xff,0x1f,0x02,0x3c, +0x01,0x00,0x02,0x24,0x1c,0x00,0xa2,0x10,0x0f,0x00,0x02,0x3c,0x02,0x00,0xa2,0x28, +0x0b,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x1c,0x00,0xa3,0x10,0x00,0x00,0x00,0x00, +0xd6,0xff,0xa4,0x14,0x00,0x00,0x00,0x00,0x0f,0x00,0x02,0x3c,0x08,0x00,0xe0,0x03, +0x00,0xf0,0x42,0x34,0x0f,0x10,0x02,0x3c,0x08,0x00,0xe0,0x03,0x00,0x80,0x42,0x34, +0xce,0xff,0xa0,0x14,0x00,0x00,0x00,0x00,0x0f,0x00,0x02,0x3c,0x08,0x00,0xe0,0x03, +0x15,0xf0,0x42,0x34,0xc9,0xff,0xa0,0x14,0x00,0x00,0x00,0x00,0x0f,0x10,0x02,0x3c, +0x08,0x00,0xe0,0x03,0x15,0xf0,0x42,0x34,0x08,0x00,0xe0,0x03,0x00,0xf0,0x42,0x34, +0x08,0x00,0xe0,0x03,0x10,0xf0,0x42,0x34,0x08,0x00,0xe0,0x03,0x10,0xf0,0x42,0x34, +0x0f,0x10,0x02,0x3c,0x08,0x00,0xe0,0x03,0x05,0xf0,0x42,0x34,0x0f,0x00,0x02,0x3c, +0x08,0x00,0xe0,0x03,0x05,0xf0,0x42,0x34,0xc0,0x40,0x04,0x00,0x21,0x18,0x04,0x01, +0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,0x80,0x18,0x03,0x00, +0x68,0x15,0x42,0x24,0x21,0x18,0x62,0x00,0x80,0x51,0x66,0x8c,0x21,0x38,0x60,0x00, +0x86,0x51,0x60,0xa0,0x87,0x51,0x60,0xa0,0x1c,0x00,0x05,0x24,0x7b,0x0f,0x00,0x08, +0x01,0x00,0x03,0x24,0x08,0x00,0xa0,0x04,0x21,0x10,0x04,0x01,0x04,0x10,0xa3,0x00, +0x24,0x10,0xc2,0x00,0xfb,0xff,0x40,0x10,0xff,0xff,0xa5,0x24,0x01,0x00,0xa5,0x24, +0x86,0x51,0xe5,0xa0,0x21,0x10,0x04,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00, +0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x68,0x15,0x63,0x24,0x21,0x18,0x43,0x00, +0x80,0x51,0x66,0x8c,0x21,0x28,0x00,0x00,0x8f,0x0f,0x00,0x08,0x01,0x00,0x07,0x24, +0x1d,0x00,0xa2,0x28,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x04,0x10,0xa7,0x00, +0x24,0x10,0xc2,0x00,0xfa,0xff,0x40,0x10,0x01,0x00,0xa5,0x24,0xff,0xff,0xa5,0x24, +0x08,0x00,0xe0,0x03,0x87,0x51,0x65,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xc8,0xff,0xbd,0x27,0x28,0x00,0xb6,0xaf,0x02,0x80,0x16,0x3c,0x30,0x00,0xbe,0xaf, +0x2c,0x00,0xb7,0xaf,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x18,0x00,0xb2,0xaf, +0x14,0x00,0xb1,0xaf,0x01,0x00,0x15,0x24,0x21,0x88,0x00,0x00,0x68,0x15,0xde,0x26, +0x21,0xa0,0x00,0x00,0x21,0x90,0x00,0x00,0x25,0xb0,0x17,0x3c,0x34,0x00,0xbf,0xaf, +0x1c,0x00,0xb3,0xaf,0xb0,0x0f,0x00,0x08,0x10,0x00,0xb0,0xaf,0x01,0x00,0x31,0x26, +0x20,0x00,0x22,0x2e,0x94,0x00,0x52,0x26,0x2e,0x00,0x40,0x10,0x94,0x00,0x94,0x26, +0x68,0x15,0xc2,0x26,0x21,0x30,0x42,0x02,0x84,0x51,0xc5,0x8c,0x00,0x00,0x00,0x00, +0x02,0x13,0x05,0x00,0x01,0x00,0x42,0x30,0xf4,0xff,0x55,0x14,0x42,0x1a,0x05,0x00, +0x74,0x51,0xc2,0x8c,0x07,0x00,0x64,0x30,0x02,0x11,0x02,0x00,0x7f,0x00,0x43,0x30, +0x2d,0x00,0x95,0x10,0x07,0x00,0xb3,0x30,0x02,0x00,0x82,0x28,0x3a,0x00,0x40,0x14, +0x02,0x00,0x02,0x24,0x30,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0x3c,0x00,0x82,0x10, +0x1a,0x00,0x62,0x2c,0x21,0x80,0x9e,0x02,0x84,0x51,0x02,0x8e,0x04,0x00,0x63,0x2e, +0x42,0x12,0x02,0x00,0x0a,0x00,0x60,0x10,0x07,0x00,0x44,0x30,0x0f,0x0f,0x00,0x0c, +0x21,0x28,0x60,0x02,0x80,0x20,0x13,0x00,0x7c,0x51,0x02,0xae,0x21,0x20,0x97,0x00, +0x84,0x01,0x83,0x8c,0x00,0x00,0x00,0x00,0x24,0x18,0x62,0x00,0x80,0x51,0x03,0xae, +0x6a,0x0f,0x00,0x0c,0x21,0x20,0x20,0x02,0x21,0x10,0x37,0x02,0x01,0x00,0x31,0x26, +0x60,0x01,0x43,0x90,0x20,0x00,0x22,0x2e,0x94,0x00,0x52,0x26,0xd4,0xff,0x40,0x14, +0x94,0x00,0x94,0x26,0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f, +0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x32,0x00,0x62,0x2c,0xda,0xff,0x40,0x10, +0x21,0x80,0x9e,0x02,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x04,0x42,0x34, +0xc5,0x0f,0x00,0x08,0x84,0x51,0xc2,0xac,0x38,0x00,0x62,0x2c,0x12,0x00,0x40,0x14, +0x14,0x00,0x62,0x2c,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x02,0x42,0x34, +0xc5,0x0f,0x00,0x08,0x84,0x51,0xc2,0xac,0xcb,0xff,0x80,0x14,0x21,0x80,0x9e,0x02, +0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0xc6,0x0f,0x00,0x08,0x84,0x51,0xc2,0xac, +0xc5,0xff,0x40,0x14,0x21,0x80,0x9e,0x02,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00, +0xf0,0x0f,0x00,0x08,0x00,0x04,0x42,0x34,0xbf,0xff,0x40,0x10,0x21,0x80,0x9e,0x02, +0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x06,0x42,0x34,0xc6,0x0f,0x00,0x08, +0x84,0x51,0xc2,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd8,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,0x80,0x80,0x10,0x00, +0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x80,0x80,0x10,0x00, +0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x21,0x80,0x02,0x02, +0x14,0x00,0xb1,0xaf,0x84,0x51,0x03,0x8e,0x25,0xb0,0x02,0x3c,0x80,0x01,0x53,0x34, +0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x71,0x92, +0x7c,0x51,0x05,0x8e,0x84,0x01,0x62,0x8c,0x21,0x90,0x80,0x00,0xff,0x00,0x31,0x32, +0x24,0x10,0x45,0x00,0x6a,0x0f,0x00,0x0c,0x80,0x51,0x02,0xae,0x86,0x51,0x04,0x92, +0xe9,0x0e,0x00,0x0c,0xff,0x00,0x45,0x32,0x86,0x51,0x04,0x92,0xff,0x0e,0x00,0x0c, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x88,0x62,0x00, +0x00,0x00,0x71,0xa2,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27, +0xff,0xff,0x84,0x30,0x00,0x02,0x82,0x30,0x07,0x00,0x03,0x24,0x0d,0x00,0x40,0x14, +0x0b,0x00,0x84,0x30,0x0c,0x00,0x82,0x2c,0x0a,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,0xa0,0x9f,0x63,0x24,0x21,0x10,0x43,0x00, +0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00, +0x07,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x06,0x00,0x03,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x05,0x00,0x03,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x04,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x03,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x02,0x00,0x03,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x21,0x18,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x90,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x68,0x00,0xbe,0xaf,0x64,0x00,0xb7,0xaf, +0x60,0x00,0xb6,0xaf,0x5c,0x00,0xb5,0xaf,0x54,0x00,0xb3,0xaf,0x50,0x00,0xb2,0xaf, +0x6c,0x00,0xbf,0xaf,0x58,0x00,0xb4,0xaf,0x4c,0x00,0xb1,0xaf,0x48,0x00,0xb0,0xaf, +0xd0,0x9f,0x42,0x24,0x00,0x00,0x54,0x8c,0x08,0x00,0x03,0x24,0x10,0x00,0xa3,0xaf, +0x21,0x98,0x00,0x00,0x21,0xa8,0x00,0x00,0x21,0xb8,0x00,0x00,0x21,0xf0,0x00,0x00, +0x14,0x00,0xa0,0xaf,0x18,0x00,0xa0,0xaf,0x1c,0x00,0xa0,0xaf,0x20,0x00,0xa0,0xaf, +0x21,0xb0,0x00,0x00,0x24,0x00,0xa0,0xaf,0x28,0x00,0xa0,0xaf,0x2c,0x00,0xa0,0xaf, +0x30,0x00,0xa0,0xaf,0x34,0x00,0xa0,0xaf,0x38,0x00,0xa0,0xaf,0x3c,0x00,0xa0,0xaf, +0x40,0x00,0xa0,0xaf,0x21,0x90,0x80,0x02,0x84,0x51,0x42,0x8e,0x00,0x00,0x00,0x00, +0x02,0x13,0x02,0x00,0x01,0x00,0x42,0x30,0x6c,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c, +0x21,0x10,0x62,0x02,0x60,0x01,0x44,0x90,0x6c,0x51,0x43,0x8e,0x68,0x51,0x46,0x8e, +0xff,0x00,0x91,0x30,0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0x21,0x10,0x24,0x02, +0x73,0x44,0x44,0x90,0x56,0x44,0x45,0x90,0x50,0x51,0x47,0x8e,0x18,0x00,0x64,0x00, +0x12,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xc5,0x00, +0x12,0x30,0x00,0x00,0x21,0x30,0xc3,0x00,0x2b,0x10,0xe6,0x00,0x25,0x01,0x40,0x14, +0x23,0x10,0xe6,0x00,0x50,0x51,0x42,0xae,0x6c,0x51,0x44,0x8e,0x68,0x51,0x47,0x8e, +0x54,0x51,0x48,0x8e,0x58,0x51,0x45,0x8e,0x60,0x51,0x46,0x8e,0x64,0x51,0x43,0x8e, +0x21,0x38,0xe4,0x00,0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0x21,0x10,0x24,0x02, +0x21,0x40,0x05,0x01,0x21,0x30,0xc3,0x00,0xca,0x44,0x42,0x90,0x50,0x51,0x4a,0x8e, +0x0c,0x00,0xe0,0x10,0x21,0x48,0x00,0x00,0x2b,0x48,0x47,0x00,0x0b,0x00,0x20,0x15, +0x02,0x80,0x02,0x3c,0x07,0x00,0x22,0x2e,0x93,0x01,0x40,0x14,0xc0,0x10,0x07,0x00, +0x0c,0x00,0x02,0x24,0x8f,0x01,0x22,0x12,0x0d,0x00,0x02,0x24,0x8e,0x01,0x22,0x12, +0xc0,0x10,0x07,0x00,0x81,0x00,0x20,0x11,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24, +0x80,0x18,0x11,0x00,0x21,0x18,0x62,0x00,0x21,0x20,0x51,0x02,0xc2,0x51,0x85,0x90, +0xec,0x44,0x62,0x8c,0x00,0x00,0x00,0x00,0x04,0x10,0xa2,0x00,0x2b,0x10,0x4a,0x00, +0x76,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xe0,0x51,0x42,0x8e,0x01,0x00,0x07,0x24, +0x04,0x18,0x27,0x02,0x24,0x10,0x43,0x00,0x04,0x01,0x40,0x10,0x1c,0x00,0x22,0x2e, +0x21,0x28,0x51,0x02,0x88,0x51,0xa6,0x90,0xc2,0x51,0xa2,0x90,0x0a,0x00,0x04,0x24, +0xff,0x00,0xc3,0x30,0x04,0x20,0x44,0x00,0x2a,0x18,0x64,0x00,0xfb,0x00,0x60,0x10, +0x1c,0x00,0x22,0x2e,0x01,0x00,0xc2,0x24,0xff,0x00,0x43,0x30,0x8c,0x01,0x64,0x10, +0x88,0x51,0xa2,0xa0,0x02,0x80,0x04,0x3c,0x68,0x15,0x85,0x24,0x80,0x10,0x11,0x00, +0x21,0x10,0x45,0x00,0x60,0x45,0x44,0x8c,0xec,0x44,0x43,0x8c,0x21,0x30,0xc5,0x02, +0x40,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x21,0x18,0x62,0x00,0x82,0x50,0x03,0x00, +0x50,0x51,0xca,0xac,0xec,0x65,0xa3,0x8c,0xff,0xff,0x02,0x34,0x03,0x00,0x62,0x10, +0x21,0x20,0x20,0x02,0xe9,0x0e,0x00,0x0c,0xff,0x00,0x65,0x32,0xff,0x0e,0x00,0x0c, +0x21,0x20,0x20,0x02,0x10,0x00,0xa4,0x8f,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24, +0x0a,0x20,0x62,0x00,0xbc,0x00,0x60,0x12,0x10,0x00,0xa4,0xaf,0x02,0x80,0x03,0x3c, +0x68,0x15,0x62,0x24,0x21,0x10,0xa2,0x02,0x64,0x51,0x40,0xac,0x68,0x51,0x40,0xac, +0x6c,0x51,0x40,0xac,0x54,0x51,0x40,0xac,0x58,0x51,0x40,0xac,0x5c,0x51,0x40,0xac, +0x60,0x51,0x40,0xac,0x40,0x00,0xa4,0x8f,0x3c,0x00,0xa2,0x8f,0x01,0x00,0x73,0x26, +0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x40,0x00,0xa4,0xaf,0x3c,0x00,0xa2,0xaf, +0x38,0x00,0xa4,0x8f,0x34,0x00,0xa2,0x8f,0x20,0x00,0x63,0x2a,0x94,0x00,0x84,0x24, +0x94,0x00,0x42,0x24,0x38,0x00,0xa4,0xaf,0x34,0x00,0xa2,0xaf,0x30,0x00,0xa4,0x8f, +0x2c,0x00,0xa2,0x8f,0x94,0x00,0x52,0x26,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24, +0x30,0x00,0xa4,0xaf,0x2c,0x00,0xa2,0xaf,0x28,0x00,0xa4,0x8f,0x24,0x00,0xa2,0x8f, +0x94,0x00,0xd6,0x26,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x28,0x00,0xa4,0xaf, +0x24,0x00,0xa2,0xaf,0x20,0x00,0xa4,0x8f,0x1c,0x00,0xa2,0x8f,0x94,0x00,0xde,0x27, +0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x20,0x00,0xa4,0xaf,0x1c,0x00,0xa2,0xaf, +0x18,0x00,0xa4,0x8f,0x14,0x00,0xa2,0x8f,0x94,0x00,0x94,0x26,0x94,0x00,0x84,0x24, +0x94,0x00,0x42,0x24,0x18,0x00,0xa4,0xaf,0x14,0x00,0xa2,0xaf,0x94,0x00,0xf7,0x26, +0x59,0xff,0x60,0x14,0x94,0x00,0xb5,0x26,0x10,0x00,0xa3,0x8f,0x6c,0x00,0xbf,0x8f, +0x68,0x00,0xbe,0x8f,0x64,0x00,0xb7,0x8f,0x60,0x00,0xb6,0x8f,0x5c,0x00,0xb5,0x8f, +0x58,0x00,0xb4,0x8f,0x54,0x00,0xb3,0x8f,0x50,0x00,0xb2,0x8f,0x4c,0x00,0xb1,0x8f, +0x48,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x70,0x00,0xbd,0x27, +0x00,0x00,0x43,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x87,0x00,0xe0,0x10, +0x00,0x00,0x00,0x00,0x87,0x00,0x20,0x15,0x02,0x80,0x03,0x3c,0x40,0x10,0x07,0x00, +0x21,0x10,0x47,0x00,0x82,0x10,0x02,0x00,0x2b,0x10,0x46,0x00,0xa7,0xff,0x40,0x10, +0x00,0x00,0x00,0x00,0x20,0x00,0xa2,0x8f,0x02,0x80,0x04,0x3c,0x68,0x15,0x88,0x24, +0x21,0x20,0x48,0x00,0x21,0x30,0x91,0x00,0xe0,0x51,0x83,0x8c,0x01,0x00,0x05,0x24, +0x04,0x10,0x25,0x02,0xa5,0x51,0xc7,0x90,0x27,0x10,0x02,0x00,0x24,0x18,0x62,0x00, +0xe0,0x51,0x83,0xac,0x09,0x00,0xe5,0x10,0x88,0x51,0xc0,0xa0,0x1c,0x00,0xa3,0x8f, +0x21,0x38,0x00,0x00,0x21,0x20,0x68,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24, +0x1d,0x00,0xe2,0x28,0xfc,0xff,0x40,0x14,0xc2,0x51,0x60,0xa0,0x02,0x80,0x04,0x3c, +0x68,0x15,0x83,0x24,0x18,0x00,0xa4,0x8f,0x21,0x50,0x60,0x00,0x21,0x38,0x00,0x00, +0x21,0x10,0x83,0x00,0x21,0x10,0x51,0x00,0xa5,0x51,0x40,0xa0,0x02,0x80,0x03,0x3c, +0x02,0x80,0x02,0x3c,0xe4,0x9e,0x49,0x24,0x70,0x9e,0x68,0x24,0x80,0x18,0x07,0x00, +0x21,0x10,0x69,0x00,0x21,0x20,0x68,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c, +0x01,0x00,0xe7,0x24,0x21,0x18,0x6a,0x00,0x1d,0x00,0xe2,0x28,0xec,0x44,0x65,0xac, +0xf6,0xff,0x40,0x14,0x60,0x45,0x66,0xac,0x15,0x00,0x20,0x12,0x02,0x80,0x05,0x3c, +0x87,0x51,0x82,0x92,0xff,0xff,0x27,0x26,0x2a,0x10,0xe2,0x00,0x10,0x00,0x40,0x14, +0x02,0x80,0x03,0x3c,0x14,0x00,0xa4,0x8f,0x68,0x15,0x62,0x24,0x21,0x10,0x82,0x00, +0x87,0x51,0x45,0x90,0x80,0x51,0x44,0x8c,0x01,0x00,0x06,0x24,0x04,0x18,0xe6,0x00, +0x24,0x10,0x83,0x00,0x06,0x01,0x43,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0xe7,0x24, +0x2a,0x10,0xe5,0x00,0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x02,0x80,0x05,0x3c, +0xee,0x7d,0xa3,0x90,0x22,0x00,0x02,0x24,0xe8,0x00,0x62,0x10,0x02,0x80,0x03,0x3c, +0x02,0x80,0x04,0x3c,0x68,0x15,0x83,0x24,0x80,0x10,0x11,0x00,0x21,0x10,0x43,0x00, +0x60,0x45,0x44,0x8c,0xec,0x44,0x43,0x8c,0xee,0x7d,0xa5,0x90,0x40,0x10,0x04,0x00, +0x21,0x10,0x44,0x00,0x21,0x18,0x62,0x00,0x22,0x00,0x02,0x24,0xd6,0x00,0xa2,0x10, +0x82,0x50,0x03,0x00,0xe0,0x51,0x83,0x8e,0x01,0x00,0x02,0x24,0x04,0x10,0x22,0x02, +0x25,0x18,0x62,0x00,0xe0,0x51,0x83,0xae,0x02,0x80,0x02,0x3c,0x68,0x15,0x43,0x24, +0x21,0x10,0xe3,0x02,0x50,0x51,0x4a,0xac,0xec,0x65,0x64,0x8c,0xff,0xff,0x02,0x34, +0x44,0xff,0x82,0x14,0x21,0x20,0x20,0x02,0xff,0x0e,0x00,0x0c,0x21,0x20,0x20,0x02, +0x10,0x00,0xa4,0x8f,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x20,0x62,0x00, +0x46,0xff,0x60,0x16,0x10,0x00,0xa4,0xaf,0x02,0x80,0x02,0x3c,0x68,0x15,0x50,0x24, +0x58,0x51,0x05,0x96,0x54,0x51,0x02,0x96,0x25,0xb0,0x11,0x3c,0x00,0x2c,0x05,0x00, +0x21,0x28,0x45,0x00,0x82,0x4f,0x00,0x0c,0x68,0x0c,0x24,0x36,0x64,0x51,0x02,0x8e, +0x60,0x51,0x05,0x8e,0x5c,0x51,0x03,0x96,0x6c,0x0c,0x24,0x36,0x21,0x28,0xa2,0x00, +0x00,0x2c,0x05,0x00,0x82,0x4f,0x00,0x0c,0x21,0x28,0x65,0x00,0xf8,0x10,0x00,0x08, +0x02,0x80,0x03,0x3c,0xa2,0x10,0x00,0x08,0x50,0x51,0x40,0xae,0x27,0xff,0x20,0x11, +0x02,0x80,0x03,0x3c,0x68,0x15,0x62,0x24,0x80,0x18,0x11,0x00,0x21,0x18,0x62,0x00, +0x60,0x45,0x64,0x8c,0x00,0x00,0x00,0x00,0x2b,0x20,0x44,0x01,0x1f,0xff,0x80,0x10, +0x00,0x00,0x00,0x00,0x49,0x11,0x00,0x08,0x00,0x00,0x00,0x00,0x0a,0xff,0x40,0x10, +0x02,0x80,0x04,0x3c,0x21,0x20,0x51,0x02,0xa5,0x51,0x83,0x90,0x01,0x00,0x02,0x24, +0x78,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x40,0x00,0xa3,0x8f,0x68,0x15,0x42,0x24, +0x21,0x20,0x62,0x00,0x21,0x38,0x00,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24, +0x1d,0x00,0xe2,0x28,0xfc,0xff,0x40,0x14,0xc2,0x51,0x60,0xa0,0x3c,0x00,0xa2,0x8f, +0x02,0x80,0x04,0x3c,0x68,0x15,0x85,0x24,0x21,0x30,0x45,0x00,0xe0,0x51,0xc2,0x8c, +0x01,0x00,0x03,0x24,0x04,0x18,0x23,0x02,0x27,0x18,0x03,0x00,0x21,0x20,0xd1,0x00, +0x24,0x10,0x43,0x00,0xa5,0x51,0x80,0xa0,0xe0,0x51,0xc2,0xac,0x12,0x00,0x20,0x16, +0x88,0x51,0x80,0xa0,0x86,0x51,0xc2,0x90,0x00,0x00,0x00,0x00,0x0e,0x00,0x40,0x10, +0x01,0x00,0x07,0x24,0x38,0x00,0xa3,0x8f,0x01,0x00,0x06,0x24,0x21,0x10,0x65,0x00, +0x86,0x51,0x44,0x90,0x80,0x51,0x45,0x8c,0x04,0x18,0xe6,0x00,0x24,0x10,0xa3,0x00, +0x8d,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,0x2a,0x10,0x87,0x00, +0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x02,0x80,0x02,0x3c,0x68,0x15,0x44,0x24, +0x34,0x00,0xa2,0x8f,0x01,0x00,0x27,0x26,0x21,0x18,0x44,0x00,0x86,0x51,0x62,0x90, +0x00,0x00,0x00,0x00,0x2a,0x10,0x47,0x00,0x0f,0x00,0x40,0x14,0x02,0x80,0x05,0x3c, +0x30,0x00,0xa3,0x8f,0x01,0x00,0x06,0x24,0x21,0x10,0x64,0x00,0x86,0x51,0x45,0x90, +0x80,0x51,0x44,0x8c,0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00,0x73,0x00,0x43,0x10, +0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,0x2a,0x10,0xa7,0x00,0xfa,0xff,0x40,0x10, +0x04,0x18,0xe6,0x00,0x02,0x80,0x05,0x3c,0xee,0x7d,0xa3,0x90,0x22,0x00,0x02,0x24, +0x3e,0x00,0x62,0x10,0xee,0xff,0x22,0x26,0xee,0x7d,0xa3,0x90,0x22,0x00,0x02,0x24, +0xbd,0xfe,0x62,0x14,0x02,0x80,0x04,0x3c,0x28,0x00,0xa2,0x8f,0x68,0x15,0x86,0x24, +0x21,0x20,0x46,0x00,0x84,0x51,0x85,0x8c,0x01,0x00,0x03,0x24,0x42,0x13,0x05,0x00, +0x07,0x00,0x42,0x30,0xb3,0xfe,0x43,0x10,0x14,0x00,0x22,0x2e,0xb1,0xfe,0x40,0x14, +0x1c,0x00,0x22,0x2e,0xaf,0xfe,0x40,0x10,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34, +0x24,0x10,0xa2,0x00,0x00,0x20,0x42,0x34,0x84,0x51,0x82,0xac,0x87,0x51,0x83,0x90, +0xff,0xff,0x27,0x26,0x2a,0x18,0xe3,0x00,0xa6,0xfe,0x60,0x14,0x00,0x00,0x00,0x00, +0x24,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x21,0x10,0x66,0x00,0x87,0x51,0x45,0x90, +0x80,0x51,0x44,0x8c,0x42,0x12,0x00,0x08,0x01,0x00,0x06,0x24,0x2a,0x10,0xe5,0x00, +0x9c,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00, +0xfa,0xff,0x43,0x14,0xff,0xff,0xe7,0x24,0x01,0x00,0xe7,0x24,0xdd,0x10,0x00,0x08, +0xff,0x00,0xf1,0x30,0xc0,0x10,0x07,0x00,0x23,0x10,0x47,0x00,0xc2,0x10,0x02,0x00, +0x2b,0x10,0x48,0x00,0x7c,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0xbd,0x10,0x00,0x08, +0x00,0x00,0x00,0x00,0x18,0x00,0x22,0x2e,0x17,0x00,0x40,0x14,0x05,0x00,0x22,0x2e, +0xc2,0x51,0x83,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x62,0x2c,0x8b,0xff,0x40,0x10, +0x01,0x00,0x62,0x24,0xe3,0x11,0x00,0x08,0xc2,0x51,0x82,0xa0,0xff,0x00,0x42,0x30, +0x02,0x00,0x42,0x2c,0xc0,0xff,0x40,0x10,0x02,0x80,0x04,0x3c,0x2c,0x00,0xa3,0x8f, +0x68,0x15,0x82,0x24,0x21,0x10,0x62,0x00,0x80,0x51,0x43,0x8c,0x00,0x01,0x04,0x3c, +0x18,0x00,0x02,0x24,0x24,0x18,0x64,0x00,0x1e,0x12,0x00,0x08,0x0b,0x88,0x43,0x00, +0xdd,0x10,0x00,0x08,0xa5,0x51,0xa7,0xa0,0x04,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0xc2,0x51,0x83,0x90,0x57,0x12,0x00,0x08,0x03,0x00,0x62,0x2c,0xc2,0x51,0x83,0x90, +0x57,0x12,0x00,0x08,0x04,0x00,0x62,0x2c,0x13,0x00,0x02,0x24,0x29,0xff,0x22,0x16, +0x02,0x80,0x02,0x3c,0xa4,0x11,0x00,0x08,0x68,0x15,0x43,0x24,0x68,0x15,0x62,0x24, +0x21,0x20,0xc2,0x03,0x84,0x51,0x83,0x8c,0x00,0x00,0x00,0x00,0x42,0x13,0x03,0x00, +0x07,0x00,0x42,0x30,0x12,0xff,0x40,0x10,0x14,0x00,0x22,0x2e,0x10,0xff,0x40,0x10, +0x0c,0x00,0x22,0x2e,0x0e,0xff,0x40,0x14,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34, +0x24,0x10,0x62,0x00,0x90,0x11,0x00,0x08,0x84,0x51,0x82,0xac,0xff,0x00,0xf1,0x30, +0x1a,0x12,0x00,0x08,0x02,0x80,0x05,0x3c,0x02,0x12,0x00,0x08,0xff,0x00,0xf1,0x30, +0x8b,0x11,0x00,0x08,0xff,0x00,0xf1,0x30,0xa8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c, +0x38,0x00,0xb2,0xaf,0x54,0x00,0xbf,0xaf,0x50,0x00,0xbe,0xaf,0x4c,0x00,0xb7,0xaf, +0x48,0x00,0xb6,0xaf,0x44,0x00,0xb5,0xaf,0x40,0x00,0xb4,0xaf,0x3c,0x00,0xb3,0xaf, +0x34,0x00,0xb1,0xaf,0x30,0x00,0xb0,0xaf,0x68,0x15,0x46,0x24,0x65,0x65,0xc4,0x90, +0x60,0x65,0xc3,0x8c,0x5c,0x65,0xc2,0x8c,0x21,0x90,0x64,0x00,0x2b,0x10,0x42,0x02, +0x7e,0x00,0x40,0x10,0x21,0x88,0xc0,0x00,0x02,0x80,0x1e,0x3c,0x02,0x80,0x17,0x3c, +0x21,0xa8,0xc0,0x00,0x21,0xb0,0xc0,0x00,0xad,0x12,0x00,0x08,0x01,0x00,0x14,0x24, +0x5c,0x65,0xc2,0x8e,0x10,0x00,0x52,0x26,0x2b,0x10,0x42,0x02,0x73,0x00,0x40,0x10, +0x21,0x88,0xc0,0x02,0x65,0x65,0x22,0x92,0xff,0xff,0x45,0x32,0x25,0x28,0xb7,0x00, +0x10,0x00,0x42,0x24,0x65,0x65,0x22,0xa2,0x38,0x79,0xc4,0x27,0x60,0x45,0x00,0x0c, +0x10,0x00,0x06,0x24,0xf8,0x63,0x23,0x8e,0x00,0x00,0x00,0x00,0x42,0x18,0x03,0x00, +0x01,0x00,0x63,0x30,0x71,0x00,0x74,0x10,0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24, +0xd4,0x63,0x62,0x8c,0x00,0x00,0x00,0x00,0x42,0x84,0x02,0x00,0x1f,0x00,0x10,0x32, +0xc0,0x48,0x10,0x00,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x55,0x00,0x84,0x51,0x45,0x8c,0x00,0x00,0x00,0x00, +0x02,0x1b,0x05,0x00,0x01,0x00,0x63,0x30,0xdd,0xff,0x60,0x10,0x21,0x30,0xa0,0x02, +0x25,0xb0,0x02,0x3c,0x21,0x40,0x02,0x02,0xd0,0x63,0xa7,0x8e,0xf8,0x63,0xa2,0x8e, +0x60,0x01,0x03,0x91,0x82,0x25,0x07,0x00,0x01,0x00,0x42,0x30,0xff,0x00,0x6b,0x30, +0x9a,0x00,0x54,0x10,0x3f,0x00,0x8a,0x30,0x02,0x80,0x04,0x3c,0xd4,0x9f,0x84,0x24, +0x00,0x00,0x86,0x8c,0x04,0x00,0x04,0x24,0xd0,0x63,0xc3,0x8c,0x00,0x00,0x00,0x00, +0x82,0x15,0x03,0x00,0x3f,0x00,0x42,0x30,0x05,0x00,0x42,0x28,0x0a,0x00,0x60,0x04, +0x0a,0x50,0x82,0x00,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x70,0x51,0x43,0x8c,0x04,0x00,0x0a,0x24, +0x01,0x00,0x63,0x24,0x70,0x51,0x43,0xac,0xd4,0x63,0xc2,0x8c,0x00,0x00,0x00,0x00, +0x02,0x13,0x02,0x00,0x1f,0x00,0x42,0x30,0x08,0x00,0x42,0x28,0xb8,0xff,0x40,0x10, +0x00,0x00,0x00,0x00,0xd0,0x63,0xc2,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30, +0xb3,0xff,0x4b,0x14,0x00,0x00,0x00,0x00,0x9f,0x00,0x40,0x11,0x21,0x10,0x30,0x01, +0xa8,0x00,0x54,0x11,0x80,0x10,0x02,0x00,0x02,0x00,0x02,0x24,0xb0,0x00,0x42,0x11, +0x21,0x10,0x30,0x01,0x03,0x00,0x02,0x24,0xb8,0x00,0x42,0x11,0x21,0x10,0x30,0x01, +0xc0,0x00,0x44,0x11,0x21,0x10,0x30,0x01,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00, +0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x28,0x46,0x00,0x74,0x51,0xa3,0x8c, +0x21,0x10,0x66,0x01,0x90,0x44,0x44,0x90,0x02,0x19,0x03,0x00,0x2b,0x18,0x64,0x00, +0xc8,0x00,0x60,0x14,0x00,0x00,0x00,0x00,0x68,0x51,0xa3,0x8c,0x80,0x10,0x0b,0x00, +0x21,0x10,0x4b,0x00,0x01,0x00,0x63,0x24,0x21,0x10,0x46,0x00,0x68,0x51,0xa3,0xac, +0x21,0x10,0x4a,0x00,0x34,0x43,0x44,0x90,0x50,0x51,0xa3,0x8c,0x00,0x00,0x00,0x00, +0x21,0x18,0x64,0x00,0x50,0x51,0xa3,0xac,0x5c,0x65,0xc2,0x8e,0x10,0x00,0x52,0x26, +0x2b,0x10,0x42,0x02,0x8f,0xff,0x40,0x14,0x21,0x88,0xc0,0x02,0x54,0x00,0xbf,0x8f, +0x50,0x00,0xbe,0x8f,0x4c,0x00,0xb7,0x8f,0x48,0x00,0xb6,0x8f,0x44,0x00,0xb5,0x8f, +0x40,0x00,0xb4,0x8f,0x3c,0x00,0xb3,0x8f,0x38,0x00,0xb2,0x8f,0x34,0x00,0xb1,0x8f, +0x30,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x58,0x00,0xbd,0x27,0xd4,0x63,0x22,0x8e, +0x00,0x00,0x00,0x00,0x42,0x14,0x02,0x00,0x10,0x00,0x43,0x30,0x90,0xff,0x60,0x10, +0x0f,0x00,0x50,0x30,0x54,0x4f,0x00,0x0c,0x48,0x00,0x04,0x24,0x74,0xff,0x40,0x10, +0x21,0x98,0x40,0x00,0x14,0x00,0x02,0x24,0x28,0x00,0x04,0x24,0x14,0x00,0x62,0xae, +0x0c,0x00,0x64,0xae,0x14,0x00,0xa3,0x8f,0xe0,0xff,0x04,0x24,0x08,0x00,0x07,0x24, +0x80,0x00,0x63,0x34,0x14,0x00,0xa3,0xaf,0xd4,0x63,0x26,0x8e,0x24,0x18,0x64,0x00, +0xff,0xe0,0x04,0x24,0x42,0x14,0x06,0x00,0x1f,0x00,0x42,0x30,0x25,0x18,0x62,0x00, +0x14,0x00,0xa3,0xaf,0xd0,0x63,0x25,0x8e,0x24,0x18,0x64,0x00,0x02,0x23,0x06,0x00, +0x82,0x13,0x05,0x00,0x00,0x1f,0x42,0x30,0x25,0x18,0x62,0x00,0xff,0xff,0x02,0x3c, +0xff,0x7f,0x42,0x34,0xc2,0x2f,0x05,0x00,0x24,0x18,0x62,0x00,0xc0,0x2b,0x05,0x00, +0x0f,0x00,0x02,0x3c,0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x00,0x35,0x06,0x00,0xf0,0xff,0x02,0x3c,0x25,0x18,0x66,0x00,0xff,0xff,0x42,0x34, +0x0f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00, +0x02,0x80,0x04,0x3c,0x10,0x00,0xa5,0x27,0x8c,0x79,0x84,0x24,0x02,0x00,0x06,0x24, +0x04,0x00,0x02,0x24,0x11,0x00,0xa7,0xa3,0x14,0x00,0xa3,0xaf,0x6c,0x45,0x00,0x0c, +0x10,0x00,0xa2,0xa3,0x08,0x00,0x64,0x96,0x10,0x00,0xa5,0x27,0x02,0x00,0x06,0x24, +0x25,0x20,0x97,0x00,0x6c,0x45,0x00,0x0c,0x20,0x00,0x84,0x24,0x30,0x08,0x00,0x0c, +0x21,0x20,0x60,0x02,0xc1,0x12,0x00,0x08,0xc0,0x48,0x10,0x00,0x02,0x12,0x05,0x00, +0x01,0x00,0x42,0x30,0x14,0x00,0x54,0x10,0xc2,0x10,0x05,0x00,0x01,0x00,0x42,0x30, +0x76,0x00,0x54,0x10,0x00,0x00,0x00,0x00,0x04,0x64,0xa2,0x96,0x60,0x01,0x03,0x91, +0xc2,0x27,0x07,0x00,0x21,0x10,0x42,0x01,0x20,0x64,0xa3,0xa2,0x13,0x00,0x80,0x10, +0x04,0x64,0xa2,0xa6,0x59,0xff,0x94,0x14,0x02,0x80,0x04,0x3c,0x00,0x64,0xa2,0x96, +0x0a,0x64,0xa3,0x96,0x01,0x00,0x42,0x24,0x01,0x00,0x63,0x24,0x00,0x64,0xa2,0xa6, +0xd7,0x12,0x00,0x08,0x0a,0x64,0xa3,0xa6,0x5d,0x00,0xe0,0x04,0x00,0x00,0x00,0x00, +0x02,0x64,0xa3,0x96,0x0e,0x64,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24, +0x0e,0x64,0xa2,0xa6,0xd6,0x12,0x00,0x08,0x02,0x64,0xc3,0xa4,0x02,0x64,0xa3,0x96, +0x10,0x64,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x10,0x64,0xa2,0xa6, +0xd6,0x12,0x00,0x08,0x02,0x64,0xc3,0xa4,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x54,0x51,0x43,0x8c,0x00,0x00,0x00,0x00, +0x01,0x00,0x63,0x24,0x5c,0xff,0x54,0x15,0x54,0x51,0x43,0xac,0x21,0x10,0x30,0x01, +0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00, +0x58,0x51,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x58,0x51,0x43,0xac, +0x02,0x00,0x02,0x24,0x54,0xff,0x42,0x15,0x03,0x00,0x02,0x24,0x21,0x10,0x30,0x01, +0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00, +0x5c,0x51,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x5c,0x51,0x43,0xac, +0x03,0x00,0x02,0x24,0x4a,0xff,0x42,0x15,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00, +0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x60,0x51,0x43,0x8c, +0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x43,0xff,0x44,0x15,0x60,0x51,0x43,0xac, +0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x46,0x00,0x64,0x51,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24, +0x64,0x51,0x43,0xac,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00, +0x80,0x10,0x02,0x00,0x21,0x28,0x46,0x00,0x74,0x51,0xa3,0x8c,0x21,0x10,0x66,0x01, +0x90,0x44,0x44,0x90,0x02,0x19,0x03,0x00,0x2b,0x18,0x64,0x00,0x3a,0xff,0x60,0x10, +0x00,0x00,0x00,0x00,0x6c,0x51,0xa3,0x8c,0x80,0x10,0x0b,0x00,0x02,0x80,0x04,0x3c, +0x68,0x15,0x84,0x24,0x21,0x10,0x4b,0x00,0x01,0x00,0x63,0x24,0x21,0x10,0x44,0x00, +0x6c,0x51,0xa3,0xac,0x21,0x10,0x4a,0x00,0xc5,0x43,0x44,0x90,0x50,0x51,0xa3,0x8c, +0x00,0x00,0x00,0x00,0x21,0x18,0x64,0x00,0x1a,0x13,0x00,0x08,0x50,0x51,0xa3,0xac, +0x00,0x64,0xa3,0x96,0x08,0x64,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24, +0x08,0x64,0xa2,0xa6,0xd6,0x12,0x00,0x08,0x00,0x64,0xc3,0xa4,0x08,0x00,0xe0,0x04, +0x00,0x00,0x00,0x00,0x02,0x64,0xa3,0x96,0x0c,0x64,0xa2,0x96,0x01,0x00,0x63,0x24, +0x01,0x00,0x42,0x24,0x0c,0x64,0xa2,0xa6,0xd6,0x12,0x00,0x08,0x02,0x64,0xc3,0xa4, +0x00,0x64,0xa3,0x96,0x06,0x64,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24, +0x06,0x64,0xa2,0xa6,0xd6,0x12,0x00,0x08,0x00,0x64,0xc3,0xa4,0x25,0xb0,0x05,0x3c, +0x4c,0x00,0xa2,0x34,0x02,0x80,0x07,0x3c,0x00,0x00,0x43,0x90,0x68,0x15,0xe4,0x24, +0xed,0x4a,0x82,0x90,0x03,0x00,0x66,0x30,0x24,0x00,0x46,0x10,0x00,0x00,0x00,0x00, +0x18,0x00,0xc0,0x14,0x25,0xb0,0x03,0x3c,0xe6,0x42,0x82,0x90,0x00,0x00,0x00,0x00, +0x15,0x00,0x40,0x14,0x58,0x00,0x62,0x34,0x1c,0x00,0x02,0x24,0x50,0x0c,0xa3,0x34, +0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c, +0x58,0x0c,0x42,0x34,0x1c,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x25,0xb0,0x03,0x3c,0x58,0x00,0x62,0x34,0x00,0x00,0x45,0x8c,0x29,0xb0,0x04,0x3c, +0x5c,0x00,0x63,0x34,0x00,0x00,0x85,0xac,0x00,0x00,0x65,0x8c,0x68,0x15,0xe2,0x24, +0x04,0x00,0x84,0x34,0xed,0x4a,0x46,0xa0,0x00,0x00,0x85,0xac,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x25,0xb0,0x02,0x3c,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf, +0x2d,0x0a,0x46,0x34,0xa2,0x0d,0x43,0x34,0xa4,0x0d,0x44,0x34,0xa6,0x0d,0x45,0x34, +0xa8,0x0d,0x42,0x34,0x00,0x00,0x67,0x94,0x00,0x00,0x88,0x94,0x00,0x00,0xa9,0x94, +0x00,0x00,0x44,0x94,0x00,0x00,0xc3,0x90,0x02,0x80,0x0a,0x3c,0x68,0x15,0x42,0x25, +0x40,0x00,0x63,0x34,0xff,0x00,0x63,0x30,0xde,0x42,0x44,0xa4,0x00,0x00,0xc3,0xa0, +0xd8,0x42,0x47,0xa4,0xda,0x42,0x48,0xa4,0xdc,0x42,0x49,0xa4,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x25,0xb0,0x07,0x3c,0x5b,0x0a,0xe2,0x34,0x00,0x00,0x44,0x90, +0x68,0x15,0x46,0x25,0x5c,0x0a,0xe2,0x34,0x00,0x00,0x45,0x90,0xd8,0x42,0xc3,0x94, +0xda,0x42,0xc2,0x94,0xdc,0x42,0xc9,0x94,0xde,0x42,0xc8,0x94,0xff,0x00,0x84,0x30, +0x21,0x18,0x62,0x00,0x00,0x22,0x04,0x00,0xff,0x00,0xa5,0x30,0x21,0x20,0x85,0x00, +0x21,0x18,0x69,0x00,0xff,0xff,0x82,0x30,0x21,0x18,0x68,0x00,0x21,0x18,0x62,0x00, +0x64,0x0c,0xe7,0x34,0xff,0xff,0x42,0x30,0xe0,0x42,0xc3,0xac,0x00,0x00,0xe2,0xa4, +0xe4,0x42,0xc4,0xa4,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x45,0x25, +0x00,0x40,0xa2,0x8c,0x01,0x00,0x03,0x24,0x0f,0x00,0x44,0x30,0x07,0x00,0x83,0x10, +0x00,0x00,0x00,0x00,0x88,0x59,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xe4,0x42,0xa2,0x8c, +0x00,0x00,0x00,0x00,0x02,0x17,0x02,0x00,0x01,0x00,0x42,0x30,0xf5,0xff,0x40,0x14, +0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00, +0x03,0x00,0x63,0x30,0x3f,0x00,0x64,0x10,0x68,0x15,0x44,0x25,0xe6,0x42,0x82,0x90, +0x00,0x00,0x00,0x00,0x07,0x00,0x40,0x14,0x01,0x00,0x03,0x24,0x00,0x40,0x82,0x8c, +0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x0f,0x00,0x42,0x30,0x3c,0x00,0x43,0x10, +0x25,0xb0,0x02,0x3c,0x68,0x15,0x45,0x25,0xe6,0x42,0xa3,0x90,0xff,0x00,0x02,0x24, +0xe0,0xff,0x62,0x14,0x25,0xb0,0x03,0x3c,0xc8,0x42,0xa2,0x94,0xe0,0x42,0xa6,0x8c, +0x50,0x0c,0x63,0x34,0x00,0x00,0x64,0x90,0x2b,0x10,0xc2,0x00,0x85,0x00,0x40,0x10, +0x7f,0x00,0x84,0x30,0xff,0xff,0x82,0x24,0xff,0x00,0x44,0x30,0x68,0x15,0x45,0x25, +0xd0,0x42,0xa3,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x64,0x00,0x78,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x21,0x20,0x60,0x00,0x68,0x15,0x43,0x25,0xe0,0x42,0x62,0x8c, +0x00,0x00,0x00,0x00,0x11,0x27,0x42,0x2c,0x6d,0x00,0x40,0x14,0x3a,0x00,0x82,0x2c, +0x32,0x00,0x04,0x24,0x44,0x00,0x03,0x24,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34, +0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34,0x00,0x00,0x44,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x42,0x34, +0x00,0x00,0x44,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x69,0x14,0x00,0x08, +0x00,0x00,0x00,0x00,0xe6,0x42,0xa2,0x90,0x00,0x00,0x00,0x00,0xbf,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x24,0x7b,0x14,0x00,0x08,0xe6,0x42,0xa2,0xa0, +0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30, +0xa4,0xff,0x60,0x10,0xff,0xff,0x02,0x34,0xe8,0x63,0x83,0x8c,0x00,0x00,0x00,0x00, +0xa0,0xff,0x62,0x10,0x00,0x00,0x00,0x00,0xe0,0x42,0x83,0x8c,0x00,0x00,0x00,0x00, +0x65,0x00,0x62,0x2c,0x59,0x00,0x40,0x14,0x28,0x00,0x62,0x2c,0xd2,0x42,0x83,0x90, +0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00,0xfe,0xff,0x42,0x24, +0xfc,0xff,0x42,0x28,0x02,0x00,0x40,0x10,0xfe,0xff,0x62,0x24,0xfc,0xff,0x02,0x24, +0xd2,0x42,0x82,0xa0,0x68,0x15,0x45,0x25,0xe8,0x63,0xa2,0x8c,0xd2,0x42,0xa3,0x90, +0xce,0x42,0xa6,0x90,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30,0x0a,0x00,0x44,0x24, +0x23,0x18,0x83,0x00,0x00,0x26,0x03,0x00,0x03,0x26,0x04,0x00,0xff,0x00,0xc2,0x30, +0x2a,0x10,0x44,0x00,0x4d,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x26,0x06,0x00, +0x03,0x26,0x04,0x00,0x68,0x15,0x43,0x25,0xe0,0x42,0x62,0x8c,0x00,0x00,0x00,0x00, +0x11,0x27,0x42,0x2c,0x33,0x00,0x40,0x14,0x3a,0x00,0x82,0x28,0x32,0x00,0x82,0x28, +0x30,0x00,0x40,0x10,0x3a,0x00,0x82,0x28,0x32,0x00,0x04,0x24,0x44,0x00,0x03,0x24, +0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c, +0x50,0x0c,0x42,0x34,0xff,0x00,0x84,0x30,0x00,0x00,0x44,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x42,0x34,0x00,0x00,0x44,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x69,0x14,0x00,0x08,0x00,0x00,0x00,0x00, +0x95,0xff,0x40,0x10,0x48,0x00,0x03,0x24,0xa2,0x14,0x00,0x08,0x44,0x00,0x03,0x24, +0xd1,0x42,0xa3,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x9a,0x14,0x00,0x08, +0x0b,0x20,0x62,0x00,0xca,0x42,0xa2,0x94,0x00,0x00,0x00,0x00,0x2b,0x10,0xc2,0x00, +0x7a,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0xcc,0x42,0xa2,0x94,0x00,0x00,0x00,0x00, +0x2b,0x10,0xc2,0x00,0x07,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x92,0x14,0x00,0x08, +0x01,0x00,0x82,0x24,0xd2,0xff,0x40,0x10,0x48,0x00,0x03,0x24,0xf4,0x14,0x00,0x08, +0x44,0x00,0x03,0x24,0x92,0x14,0x00,0x08,0x02,0x00,0x82,0x24,0xb2,0xff,0x40,0x10, +0x68,0x15,0x45,0x25,0xd2,0x42,0x83,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00, +0x03,0x16,0x02,0x00,0x02,0x00,0x42,0x24,0x0d,0x00,0x42,0x28,0x09,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0xd8,0x14,0x00,0x08,0x0c,0x00,0x02,0x24,0xcf,0x42,0xa3,0x80, +0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x2a,0x10,0x82,0x00,0xe9,0x14,0x00,0x08, +0x0b,0x20,0x62,0x00,0xd8,0x14,0x00,0x08,0x02,0x00,0x62,0x24,0xc0,0xff,0xbd,0x27, +0x28,0x00,0xb4,0xaf,0x25,0xb0,0x14,0x3c,0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf, +0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x20,0x00,0xb2,0xaf,0xd8,0x00,0x86,0x36, +0x00,0x00,0xc3,0x90,0x02,0x80,0x02,0x3c,0x68,0x15,0x51,0x24,0x2a,0xb0,0x10,0x3c, +0xa0,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x34,0x00,0x05,0x36,0xfe,0xff,0x02,0x24, +0xbc,0x42,0x32,0x92,0x40,0x00,0x04,0x24,0x00,0x00,0xc3,0xa0,0x00,0x00,0xa2,0xa0, +0x54,0x4f,0x00,0x0c,0x00,0x96,0x12,0x00,0x21,0x98,0x40,0x00,0x8d,0x00,0x60,0x12, +0x00,0x40,0x02,0x3c,0x08,0x00,0x63,0x8e,0xb0,0x03,0x82,0x36,0x25,0xb0,0x1e,0x3c, +0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,0xfb,0x44,0x00,0x0c,0x21,0xb8,0x20,0x02, +0x42,0x00,0xd5,0x37,0x03,0x0c,0xd1,0x37,0x17,0x0e,0xd6,0x37,0x04,0x00,0x14,0x24, +0x2a,0xb0,0x03,0x3c,0x06,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00, +0x00,0xff,0x42,0x30,0x0a,0x00,0x40,0x18,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c, +0x94,0xa2,0x84,0x24,0x00,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x94, +0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30,0xfc,0xff,0x40,0x1c,0x00,0x00,0x00,0x00, +0x08,0x00,0x65,0x8e,0x20,0x10,0x06,0x3c,0x01,0x00,0x04,0x24,0x00,0xfe,0xc6,0x34, +0x40,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa4,0xaf,0x4d,0x01,0x00,0x0c, +0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,0x98,0xa2,0x42,0x24,0x00,0x00,0x45,0x8c, +0x01,0x00,0x03,0x24,0x21,0x20,0x00,0x00,0x00,0x00,0xa3,0xa0,0xff,0xff,0x03,0x24, +0x00,0x00,0xa3,0xa2,0x00,0x00,0x22,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30, +0x40,0x00,0x42,0x34,0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30, +0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x02,0x00,0x02,0x24, +0x02,0x80,0x04,0x3c,0x00,0x00,0xa2,0xa0,0x68,0x15,0x83,0x24,0xc1,0x42,0x62,0x90, +0x00,0x00,0xc4,0x92,0x21,0x28,0x00,0x00,0x00,0x00,0xc2,0xa2,0xff,0x00,0x90,0x30, +0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30,0x06,0x00,0xa3,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0xa2,0x24,0xef,0xff,0x02,0x24,0x64,0x00,0x04,0x24,0x00,0x00,0xa2,0xa2, +0x1a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x92,0x21,0x20,0x00,0x00, +0xbf,0x00,0x42,0x30,0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30, +0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x1a,0x0c,0x00,0x0c, +0x84,0x03,0x04,0x24,0xf4,0x08,0xc2,0x37,0x00,0x00,0x43,0x8c,0x00,0x80,0x04,0x3c, +0xdf,0x07,0x84,0x34,0x00,0x00,0xd0,0xa2,0x21,0x10,0x00,0x00,0x24,0x28,0x64,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x00,0x00,0xa0,0xa2,0x00,0x00,0x22,0x92,0x21,0x20,0x00,0x00, +0xff,0x00,0x42,0x30,0x40,0x00,0x42,0x34,0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24, +0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24, +0xbe,0x42,0xe2,0x92,0x1f,0x00,0xa3,0x30,0x2b,0x10,0x62,0x00,0x0a,0x00,0x40,0x10, +0x02,0x80,0x02,0x3c,0xbf,0x42,0xe2,0x92,0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x00, +0x05,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x01,0x00,0x02,0x3c,0x25,0x10,0x62,0x00, +0x21,0x90,0x42,0x02,0x02,0x80,0x02,0x3c,0xee,0x7d,0x43,0x90,0x22,0x00,0x02,0x24, +0x1c,0x00,0x62,0x10,0x92,0x00,0x02,0x24,0x1b,0x00,0x62,0x10,0x02,0x80,0x03,0x3c, +0xff,0xff,0x94,0x26,0x1a,0x0c,0x00,0x0c,0xf4,0x01,0x04,0x24,0x89,0xff,0x81,0x06, +0x2a,0xb0,0x03,0x3c,0x04,0x00,0x60,0x12,0x25,0xb0,0x02,0x3c,0x70,0x4f,0x00,0x0c, +0x21,0x20,0x60,0x02,0x25,0xb0,0x02,0x3c,0xd8,0x02,0x42,0x34,0x00,0x00,0x52,0xac, +0x21,0x10,0x40,0x02,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x40,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0xbe,0x42,0x62,0x90, +0xc0,0x07,0xa3,0x30,0x82,0x19,0x03,0x00,0x2b,0x10,0x62,0x00,0xe0,0xff,0x40,0x10, +0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0xbf,0x42,0x82,0x90,0x00,0x00,0x00,0x00, +0x2b,0x10,0x43,0x00,0xda,0xff,0x40,0x10,0x00,0x12,0x03,0x00,0x10,0x00,0x03,0x3c, +0x25,0x10,0x43,0x00,0xd8,0x15,0x00,0x08,0x21,0x90,0x42,0x02,0xe0,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34, +0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x6a,0x44,0x00,0x0c, +0x14,0x00,0xb1,0xaf,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x02,0x80,0x12,0x3c, +0xff,0xff,0x05,0x36,0x56,0x30,0x06,0x24,0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24, +0x68,0x15,0x51,0x26,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x04,0x43,0x23,0x92, +0x04,0x00,0x02,0x24,0x20,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0x14,0x43,0x25,0x8e, +0x25,0xb0,0x10,0x3c,0x15,0x5a,0x00,0x0c,0x00,0x0e,0x04,0x36,0x14,0x43,0x25,0x8e, +0x15,0x5a,0x00,0x0c,0x04,0x0e,0x04,0x36,0x18,0x43,0x25,0x8e,0x15,0x5a,0x00,0x0c, +0x08,0x0e,0x04,0x36,0x14,0x43,0x25,0x8e,0x15,0x5a,0x00,0x0c,0x10,0x0e,0x04,0x36, +0x14,0x43,0x25,0x8e,0x15,0x5a,0x00,0x0c,0x14,0x0e,0x04,0x36,0x14,0x43,0x25,0x8e, +0x15,0x5a,0x00,0x0c,0x18,0x0e,0x04,0x36,0x14,0x43,0x25,0x8e,0x15,0x5a,0x00,0x0c, +0x1c,0x0e,0x04,0x36,0x68,0x15,0x43,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x04,0x00,0x02,0x24,0x20,0x00,0xbd,0x27, +0x08,0x00,0xe0,0x03,0x04,0x43,0x62,0xa0,0x00,0x0e,0x42,0x34,0x00,0x00,0x43,0x8c, +0x14,0x43,0x25,0x8e,0x00,0x00,0x00,0x00,0xde,0xff,0x65,0x14,0x25,0xb0,0x10,0x3c, +0x32,0x16,0x00,0x08,0x68,0x15,0x43,0x26,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf, +0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,0x15,0x00,0x04,0x24, +0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x6a,0x44,0x00,0x0c,0x14,0x00,0xb1,0xaf, +0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x56,0x30,0x06,0x24, +0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x02,0x80,0x10,0x3c,0x1a,0x0c,0x00,0x0c, +0x64,0x00,0x04,0x24,0x68,0x15,0x02,0x26,0x04,0x43,0x46,0x90,0x25,0xb0,0x11,0x3c, +0x10,0x10,0x12,0x3c,0x01,0x00,0x03,0x24,0x00,0x0e,0x24,0x36,0x1e,0x00,0xc3,0x10, +0x10,0x10,0x45,0x36,0x15,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x04,0x0e,0x24,0x36, +0x15,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,0x08,0x0e,0x24,0x36,0x15,0x5a,0x00,0x0c, +0x10,0x10,0x05,0x24,0x10,0x0e,0x24,0x36,0x15,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36, +0x14,0x0e,0x24,0x36,0x15,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,0x18,0x0e,0x24,0x36, +0x15,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,0x1c,0x0e,0x24,0x36,0x15,0x5a,0x00,0x0c, +0x10,0x10,0x45,0x36,0x68,0x15,0x03,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x20,0x00,0xbd,0x27, +0x08,0x00,0xe0,0x03,0x04,0x43,0x62,0xa0,0x00,0x00,0x86,0x8c,0x00,0x00,0x00,0x00, +0xe0,0xff,0xc5,0x14,0x68,0x15,0x03,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x20,0x00,0xbd,0x27, +0x08,0x00,0xe0,0x03,0x04,0x43,0x62,0xa0,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf, +0x10,0x00,0xb0,0xaf,0x0f,0x00,0x11,0x3c,0x01,0x00,0x10,0x3c,0xff,0xff,0x25,0x36, +0xf4,0x98,0x06,0x36,0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf,0x6a,0x44,0x00,0x0c, +0x18,0x00,0xb2,0xaf,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x56,0x30,0x06,0x36, +0xff,0xff,0x25,0x36,0x1a,0x00,0x04,0x24,0x6a,0x44,0x00,0x0c,0x02,0x80,0x11,0x3c, +0x68,0x15,0x30,0x26,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x04,0x43,0x02,0x92, +0x25,0xb0,0x12,0x3c,0x08,0x00,0x40,0x14,0x08,0x0e,0x44,0x36,0x25,0xb0,0x02,0x3c, +0x00,0x0e,0x42,0x34,0x00,0x00,0x45,0x8c,0xec,0x42,0x03,0x8e,0x00,0x00,0x00,0x00, +0x17,0x00,0xa3,0x10,0x68,0x15,0x22,0x26,0xe8,0x42,0x05,0x8e,0x15,0x5a,0x00,0x0c, +0x00,0x00,0x00,0x00,0xec,0x42,0x05,0x8e,0x15,0x5a,0x00,0x0c,0x00,0x0e,0x44,0x36, +0xf0,0x42,0x05,0x8e,0x15,0x5a,0x00,0x0c,0x04,0x0e,0x44,0x36,0xf4,0x42,0x05,0x8e, +0x15,0x5a,0x00,0x0c,0x10,0x0e,0x44,0x36,0xf8,0x42,0x05,0x8e,0x15,0x5a,0x00,0x0c, +0x14,0x0e,0x44,0x36,0xfc,0x42,0x05,0x8e,0x15,0x5a,0x00,0x0c,0x18,0x0e,0x44,0x36, +0x00,0x43,0x05,0x8e,0x15,0x5a,0x00,0x0c,0x1c,0x0e,0x44,0x36,0x68,0x15,0x22,0x26, +0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x04,0x43,0x40,0xa0,0xe0,0xff,0xbd,0x27, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x11,0x3c,0x01,0x00,0x10,0x3c, +0xff,0xff,0x25,0x36,0xf4,0x98,0x06,0x36,0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf, +0x6a,0x44,0x00,0x0c,0x18,0x00,0xb2,0xaf,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24, +0x02,0x80,0x12,0x3c,0xff,0xff,0x25,0x36,0x56,0x30,0x06,0x36,0x6a,0x44,0x00,0x0c, +0x1a,0x00,0x04,0x24,0x68,0x15,0x51,0x26,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24, +0x04,0x43,0x23,0x92,0x03,0x00,0x02,0x24,0x2c,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c, +0xec,0x42,0x25,0x8e,0x25,0xb0,0x10,0x3c,0x15,0x5a,0x00,0x0c,0x00,0x0e,0x04,0x36, +0xf0,0x42,0x25,0x8e,0x15,0x5a,0x00,0x0c,0x04,0x0e,0x04,0x36,0xf4,0x42,0x25,0x8e, +0x15,0x5a,0x00,0x0c,0x10,0x0e,0x04,0x36,0xf8,0x42,0x25,0x8e,0x15,0x5a,0x00,0x0c, +0x14,0x0e,0x04,0x36,0xfc,0x42,0x25,0x8e,0x15,0x5a,0x00,0x0c,0x18,0x0e,0x04,0x36, +0x00,0x43,0x25,0x8e,0x15,0x5a,0x00,0x0c,0x1c,0x0e,0x04,0x36,0x08,0x43,0x24,0x8e, +0xe8,0x42,0x22,0x8e,0x00,0x00,0x00,0x00,0x21,0x28,0x44,0x00,0x00,0xff,0xa3,0x30, +0xff,0xff,0x02,0x3c,0xff,0x00,0x42,0x34,0x01,0x3f,0x63,0x2c,0x24,0x10,0xa2,0x00, +0x0c,0x00,0x60,0x10,0x08,0x0e,0x04,0x36,0x15,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00, +0x68,0x15,0x43,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x03,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03, +0x04,0x43,0x62,0xa0,0xfa,0x16,0x00,0x08,0x00,0x3f,0x45,0x34,0x00,0x0e,0x42,0x34, +0x00,0x00,0x43,0x8c,0xec,0x42,0x25,0x8e,0x00,0x00,0x00,0x00,0xd2,0xff,0x65,0x14, +0x25,0xb0,0x10,0x3c,0xfd,0x16,0x00,0x08,0x68,0x15,0x43,0x26,0xd0,0xff,0xbd,0x27, +0x18,0x00,0xb2,0xaf,0x02,0x80,0x12,0x3c,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf, +0x68,0x15,0x42,0x26,0x28,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf, +0x10,0x00,0xb0,0xaf,0xe8,0x63,0x43,0x8c,0x02,0x80,0x15,0x3c,0xee,0x7d,0xa4,0x92, +0x04,0x43,0x53,0x90,0x25,0xb0,0x02,0x3c,0x0f,0x0c,0x42,0x34,0x02,0x19,0x03,0x00, +0x00,0x00,0x44,0xa0,0x7f,0x00,0x74,0x30,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x68,0x15,0x42,0x26,0x00,0x40,0x43,0x8c,0x00,0x10,0x02,0x24,0xf0,0xf0,0x63,0x30, +0x98,0x00,0x62,0x10,0x01,0x00,0x02,0x24,0x25,0xb0,0x09,0x3c,0x4c,0x00,0x23,0x35, +0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x3f,0x00,0x40,0x10, +0x68,0x15,0x45,0x26,0x68,0x15,0x4a,0x26,0x00,0x40,0x42,0x8d,0x00,0x00,0x00,0x00, +0x02,0x13,0x02,0x00,0x0f,0x00,0x42,0x30,0x38,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x00,0x0e,0x25,0x35,0x00,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x8c,0x00,0x40,0x10, +0x10,0x0e,0x26,0x35,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x08,0x0e,0x22,0x35,0x04,0x0e,0x24,0x35,0x00,0x00,0x43,0x8c, +0x00,0x00,0xa5,0x8c,0x00,0x00,0x82,0x8c,0xe8,0x42,0x43,0xad,0xec,0x42,0x45,0xad, +0xf0,0x42,0x42,0xad,0x14,0x0e,0x24,0x35,0x18,0x0e,0x22,0x35,0x1c,0x0e,0x25,0x35, +0x00,0x00,0xc6,0x8c,0x00,0x00,0x87,0x8c,0x00,0x00,0x48,0x8c,0x00,0x00,0xa4,0x8c, +0x00,0xff,0x63,0x30,0x9a,0x0c,0x22,0x35,0x02,0x1a,0x03,0x00,0x00,0x43,0x44,0xad, +0x00,0x00,0x43,0xa0,0xf4,0x42,0x46,0xad,0xf8,0x42,0x47,0xad,0xfc,0x42,0x48,0xad, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0xee,0x7d,0xa3,0x92,0x22,0x00,0x02,0x24, +0xac,0x00,0x62,0x10,0x92,0x00,0x02,0x24,0xab,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x68,0x15,0x44,0x26, +0x00,0x40,0x83,0x8c,0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,0x24,0x18,0x62,0x00, +0x00,0x10,0x63,0x34,0x00,0x40,0x83,0xac,0x68,0x15,0x45,0x26,0x04,0x43,0xa2,0x8c, +0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x0f,0x00,0x40,0x14,0x68,0x15,0x42,0x26, +0x25,0xb0,0x02,0x3c,0x84,0x01,0x42,0x34,0x00,0x00,0x44,0x8c,0x0d,0x00,0x03,0x24, +0x8c,0x00,0x83,0x10,0x3e,0x00,0x02,0x24,0x4a,0x00,0x03,0x24,0x1f,0x43,0xa2,0xa0, +0x45,0x00,0x02,0x24,0x1c,0x43,0xa3,0xa0,0x1d,0x43,0xa2,0xa0,0x43,0x00,0x03,0x24, +0x1e,0x43,0xa3,0xa0,0x68,0x15,0x42,0x26,0xe8,0x63,0x43,0x8c,0x25,0xb0,0x02,0x3c, +0x60,0x0c,0x42,0x34,0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30,0x00,0x00,0x43,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x42,0x26,0x04,0x40,0x43,0x8c, +0x25,0xb0,0x02,0x3c,0x98,0x0c,0x42,0x34,0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30, +0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x42,0x26, +0x1e,0x43,0x44,0x90,0x25,0xb0,0x03,0x3c,0x66,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x42,0x26,0x1c,0x43,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x67,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x68,0x15,0x44,0x26,0x00,0x40,0x85,0x8c,0x10,0x10,0x02,0x24, +0xf0,0xf0,0xa3,0x30,0x2b,0x00,0x62,0x10,0xff,0xff,0x02,0x34,0x28,0x00,0xbf,0x8f, +0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x30,0x00,0xbd,0x27,0x0d,0x00,0x62,0x12,0x04,0x00,0x02,0x24,0x0b,0x00,0x62,0x12, +0x68,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0x2e,0x17,0x00,0x08,0x04,0x43,0x62,0xa0, +0x00,0x00,0xc3,0x8c,0x3f,0x3f,0x02,0x3c,0x3f,0x3f,0x42,0x34,0x71,0xff,0x62,0x14, +0x00,0x00,0x00,0x00,0x73,0x17,0x00,0x08,0x68,0x15,0x45,0x26,0x0f,0x00,0x10,0x3c, +0x01,0x00,0x11,0x3c,0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0x6a,0x44,0x00,0x0c, +0x15,0x00,0x04,0x24,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36, +0x56,0x30,0x26,0x36,0x6a,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x1a,0x0c,0x00,0x0c, +0x64,0x00,0x04,0x24,0x68,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0x2e,0x17,0x00,0x08, +0x04,0x43,0x62,0xa0,0xe8,0x63,0x83,0x8c,0x00,0x00,0x00,0x00,0xd3,0xff,0x62,0x10, +0x02,0x12,0x05,0x00,0x0f,0x00,0x45,0x30,0x01,0x00,0x03,0x24,0xcf,0xff,0xa3,0x14, +0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00, +0x03,0x00,0x63,0x30,0xc9,0xff,0x60,0x10,0x03,0x00,0x02,0x24,0x4d,0x00,0x62,0x12, +0x04,0x00,0x62,0x2a,0x2f,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x52,0x00,0x60,0x12, +0x00,0x00,0x00,0x00,0xc1,0xff,0x65,0x16,0x00,0x00,0x00,0x00,0x1c,0x43,0x82,0x90, +0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x3e,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x1f,0x43,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,0x30,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x86,0x16,0x00,0x0c,0x00,0x00,0x00,0x00,0xbb,0x17,0x00,0x08, +0x00,0x00,0x00,0x00,0x3b,0x00,0x02,0x24,0x46,0x00,0x03,0x24,0x1f,0x43,0xa2,0xa0, +0x1c,0x43,0xa3,0xa0,0x41,0x00,0x02,0x24,0x40,0x00,0x03,0x24,0x84,0x17,0x00,0x08, +0x1d,0x43,0xa2,0xa0,0x25,0xb0,0x02,0x3c,0x0d,0x08,0x42,0x34,0x00,0x00,0x43,0x90, +0x00,0x00,0x00,0x00,0x0f,0x00,0x63,0x30,0x08,0x00,0x62,0x2c,0x0f,0x00,0x63,0x38, +0x4f,0xff,0x40,0x14,0x01,0x00,0x65,0x24,0x00,0x1c,0x05,0x00,0x00,0x16,0x05,0x00, +0x25,0x10,0x43,0x00,0x00,0x22,0x05,0x00,0x25,0x10,0x44,0x00,0x68,0x15,0x43,0x26, +0x25,0x20,0x85,0x00,0x25,0x10,0x45,0x00,0x18,0x43,0x64,0xac,0x68,0x17,0x00,0x08, +0x14,0x43,0x62,0xac,0x04,0x00,0x02,0x24,0x11,0x00,0x62,0x12,0xff,0x00,0x02,0x24, +0x92,0xff,0x62,0x16,0x00,0x00,0x00,0x00,0x1e,0x43,0x82,0x90,0x00,0x00,0x00,0x00, +0x2b,0x10,0x82,0x02,0x21,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x1c,0x43,0x82,0x90, +0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x0a,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x42,0x16,0x00,0x0c,0x00,0x00,0x00,0x00,0xbb,0x17,0x00,0x08,0x00,0x00,0x00,0x00, +0x1d,0x43,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,0xf8,0xff,0x40,0x10, +0x00,0x00,0x00,0x00,0x03,0x16,0x00,0x0c,0x00,0x00,0x00,0x00,0xbb,0x17,0x00,0x08, +0x00,0x00,0x00,0x00,0x20,0x43,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02, +0xc0,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xc3,0x16,0x00,0x0c,0x00,0x00,0x00,0x00, +0xbb,0x17,0x00,0x08,0x00,0x00,0x00,0x00,0x1e,0x43,0x82,0x90,0x00,0x00,0x00,0x00, +0x2b,0x10,0x82,0x02,0xe6,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x21,0x43,0x82,0x90, +0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,0xb2,0xff,0x40,0x14,0x00,0x00,0x00,0x00, +0xc3,0x16,0x00,0x0c,0x00,0x00,0x00,0x00,0xbb,0x17,0x00,0x08,0x00,0x00,0x00,0x00, +0x02,0x80,0x08,0x3c,0x68,0x15,0x05,0x25,0xe8,0x63,0xa4,0x8c,0xe6,0x42,0xa3,0x90, +0x02,0x11,0x04,0x00,0x26,0x00,0x60,0x14,0x7f,0x00,0x46,0x30,0x25,0xb0,0x07,0x3c, +0x4c,0x00,0xe2,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x60,0x10, +0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34,0x1d,0x00,0x82,0x10,0x00,0x00,0x00,0x00, +0x00,0x08,0xe3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30, +0x19,0x00,0x40,0x10,0x4b,0x00,0xc2,0x2c,0x3e,0x00,0x40,0x10,0x01,0x00,0x04,0x24, +0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x49,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c, +0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x00,0x00,0x00,0x00,0x44,0x00,0x40,0x10, +0x23,0x00,0xc2,0x2c,0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34,0x20,0x00,0x03,0x24, +0x00,0x00,0x43,0xa0,0xd3,0x42,0x80,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x17,0x00,0x40,0x10,0x01,0x00,0x04,0x24, +0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x44,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c, +0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x00,0x00,0x00,0x00,0x3f,0x00,0x40,0x10, +0x23,0x00,0xc2,0x2c,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34,0x44,0x00,0x03,0x24, +0x00,0x00,0x43,0xa0,0xd3,0x42,0x80,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xd3,0x42,0xa2,0x90,0x00,0x00,0x00,0x00, +0xe7,0xff,0x44,0x10,0x43,0x00,0x02,0x24,0x30,0x0c,0xe3,0x34,0xd3,0x42,0xa4,0xa0, +0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0xd3,0x42,0xa2,0x90,0x00,0x00,0x00,0x00,0xc0,0xff,0x44,0x10, +0x10,0x00,0x02,0x24,0x87,0x0c,0xe3,0x34,0xd3,0x42,0xa4,0xa0,0x00,0x00,0x62,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0xc7,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90, +0x02,0x00,0x03,0x24,0xc2,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c, +0x87,0x0c,0x42,0x34,0xd3,0x42,0x83,0xa0,0x00,0x00,0x40,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xb4,0xff,0x40,0x10, +0x00,0x00,0x00,0x00,0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x02,0x00,0x03,0x24, +0xaf,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xd3,0x42,0x83,0xa0, +0x30,0x0c,0x42,0x34,0x42,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xff,0xff,0x8d,0x30, +0x00,0x60,0x0f,0x40,0x01,0x00,0xe1,0x35,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x02,0x80,0x06,0x3c,0x68,0x15,0xce,0x24,0x76,0x4b,0xc2,0x91,0x00,0x00,0x00,0x00, +0x1d,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,0x38,0x02,0x64,0x34,0x80,0xff,0x02,0x24, +0x00,0x00,0x82,0xa0,0x34,0x02,0x6a,0x34,0xd2,0x01,0x65,0x34,0xd6,0x01,0x66,0x34, +0xda,0x01,0x67,0x34,0xde,0x01,0x63,0x34,0x00,0x00,0xa8,0x94,0x00,0x00,0xc9,0x94, +0x00,0x00,0xeb,0x94,0x00,0x00,0x6c,0x94,0x00,0x00,0x44,0x95,0xb0,0xfe,0xa2,0x25, +0xff,0xff,0x4d,0x30,0x74,0x4b,0xc4,0xa5,0x00,0x00,0xa0,0xa4,0x6c,0x4b,0xc8,0xa5, +0x00,0x00,0xc0,0xa4,0x6e,0x4b,0xc9,0xa5,0x00,0x00,0xe0,0xa4,0x70,0x4b,0xcb,0xa5, +0x00,0x00,0x60,0xa4,0x00,0x00,0x4d,0xa5,0x72,0x4b,0xcc,0xa5,0x00,0x60,0x8f,0x40, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x2a,0xb0,0x02,0x3c,0x0a,0x00,0x45,0x34, +0x63,0x00,0x03,0x24,0xff,0xff,0x04,0x34,0x00,0x00,0xa2,0x90,0x00,0x00,0x00,0x00, +0x0a,0x00,0x40,0x10,0x68,0x15,0xc2,0x24,0x64,0x00,0x02,0x24,0xff,0xff,0x42,0x24, +0xff,0xff,0x42,0x30,0xfe,0xff,0x40,0x14,0xff,0xff,0x42,0x24,0xff,0xff,0x62,0x24, +0xff,0xff,0x43,0x30,0xf4,0xff,0x64,0x14,0x68,0x15,0xc2,0x24,0x74,0x4b,0x48,0x94, +0x72,0x4b,0x47,0x94,0x6c,0x4b,0x49,0x94,0x6e,0x4b,0x4a,0x94,0x70,0x4b,0x4b,0x94, +0x25,0xb0,0x03,0x3c,0x38,0x02,0x6c,0x34,0x34,0x02,0x62,0x34,0xd2,0x01,0x64,0x34, +0xd6,0x01,0x65,0x34,0xda,0x01,0x66,0x34,0xde,0x01,0x63,0x34,0x00,0x00,0x48,0xa4, +0x00,0x00,0x89,0xa4,0x00,0x00,0xaa,0xa4,0x00,0x00,0xcb,0xa4,0x00,0x00,0x67,0xa4, +0x00,0x00,0x80,0xa1,0x00,0x60,0x8f,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x25,0xb0,0x02,0x3c,0x08,0x00,0x43,0x34,0x00,0x00,0x64,0x94,0x03,0x00,0x49,0x34, +0x40,0x00,0x45,0x34,0x00,0x24,0x04,0x00,0x03,0x24,0x04,0x00,0xfc,0x77,0x0a,0x24, +0x00,0x03,0x46,0x34,0x04,0x03,0x47,0x34,0x0f,0x00,0x80,0x04,0x23,0x00,0x48,0x34, +0x00,0x00,0x22,0x91,0xfe,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x00,0x00,0x22,0xa1, +0x22,0x00,0x02,0x24,0x00,0x00,0xc0,0xac,0x00,0x00,0xe0,0xac,0x00,0x00,0x02,0xa1, +0xfc,0x37,0x02,0x24,0x00,0x00,0xaa,0xa4,0x00,0x00,0xa2,0xa4,0x00,0x00,0xaa,0xa4, +0x00,0x00,0xa0,0xa4,0x00,0x00,0xa0,0xa4,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xd0,0xff,0xbd,0x27,0x1c,0x00,0xb1,0xaf,0x28,0x00,0xbf,0xaf,0x24,0x00,0xb3,0xaf, +0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0xff,0xff,0x11,0x24,0x02,0x80,0x13,0x3c, +0x41,0xb0,0x02,0x3c,0x68,0x15,0x66,0x26,0x04,0x00,0x42,0x34,0x00,0x00,0x47,0x8c, +0x00,0x4b,0xc5,0x8c,0x02,0x80,0x03,0x3c,0xf6,0x7d,0x64,0x90,0xfc,0x4a,0xc8,0x8c, +0x02,0x80,0x02,0x3c,0x18,0x7e,0x49,0x90,0x25,0xb0,0x0a,0x3c,0x25,0x90,0xa7,0x00, +0xb0,0x03,0x42,0x35,0x00,0x00,0x52,0xac,0x00,0x24,0x04,0x00,0x00,0x00,0x48,0xac, +0x84,0x02,0x43,0x35,0x8c,0x02,0x45,0x35,0x01,0x00,0x02,0x24,0x00,0x00,0x72,0xac, +0x00,0x00,0xa4,0xac,0x88,0x04,0x22,0x11,0x00,0x4b,0xd2,0xac,0x68,0x15,0x64,0x26, +0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x01,0x00,0x42,0x30, +0x0e,0x00,0x40,0x10,0x68,0x15,0x66,0x26,0x25,0xb0,0x0b,0x3c,0xb0,0x03,0x63,0x35, +0x01,0x00,0x06,0x24,0x00,0x00,0x66,0xac,0x04,0x00,0x62,0x35,0x00,0x00,0x4a,0x8c, +0x00,0x4b,0x83,0x8c,0x40,0x00,0x02,0x3c,0x24,0x10,0x42,0x01,0x01,0x00,0x63,0x38, +0x47,0x04,0x40,0x10,0x00,0x4b,0x83,0xac,0x68,0x15,0x66,0x26,0xfc,0x4a,0xc2,0x8c, +0x00,0x00,0x00,0x00,0x24,0x28,0x52,0x00,0x04,0x00,0xa3,0x30,0x09,0x00,0x60,0x10, +0x08,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x25,0xb0,0x03,0x3c,0x04,0x00,0x04,0x24, +0x04,0x00,0x42,0x38,0xb0,0x03,0x63,0x34,0x00,0x00,0x64,0xac,0x00,0x4b,0xc2,0xac, +0x08,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,0x10,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c, +0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x38,0x00,0x4b,0xc2,0xac,0x10,0x00,0xa2,0x30, +0x06,0x00,0x40,0x10,0x20,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00, +0x10,0x00,0x42,0x38,0x00,0x4b,0xc2,0xac,0x20,0x00,0xa2,0x30,0x06,0x00,0x40,0x10, +0x40,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x38, +0x00,0x4b,0xc2,0xac,0x40,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,0x80,0x00,0xa2,0x30, +0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x38,0x00,0x4b,0xc2,0xac, +0x80,0x00,0xa2,0x30,0x06,0x00,0x40,0x10,0x00,0x01,0xa2,0x30,0x00,0x4b,0xc2,0x8c, +0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x38,0x00,0x4b,0xc2,0xac,0x00,0x01,0xa2,0x30, +0x06,0x00,0x40,0x10,0x00,0x02,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00, +0x00,0x01,0x42,0x38,0x00,0x4b,0xc2,0xac,0x00,0x02,0xa2,0x30,0x06,0x00,0x40,0x10, +0x00,0x04,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x38, +0x00,0x4b,0xc2,0xac,0x00,0x04,0xa2,0x30,0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x00,0x4b,0xc2,0x8c,0x00,0x00,0x00,0x00,0x00,0x04,0x42,0x38,0x00,0x4b,0xc2,0xac, +0x00,0x08,0xa2,0x30,0x36,0x00,0x40,0x10,0x2a,0xb0,0x03,0x3c,0x00,0x00,0x6a,0x8c, +0xff,0x00,0x02,0x24,0xff,0x00,0x44,0x31,0x2c,0x00,0x82,0x10,0x00,0x80,0x42,0x31, +0x35,0x04,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01, +0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x68,0x64,0xc2,0x90,0x20,0xb0,0x03,0x3c, +0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x4a,0x8c,0x25,0xb0,0x03,0x3c, +0xb0,0x03,0x63,0x34,0x00,0x00,0x6a,0xac,0xff,0x00,0x44,0x31,0xff,0x00,0x02,0x24, +0x1a,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x20,0x65,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0xb4,0x64,0x03,0xae,0x21,0x20,0x00,0x00,0x68,0x64,0x0a,0xa2,0x20,0x00,0x07,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x4a,0x05,0x8e,0x02,0x80,0x06,0x3c, +0xcc,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c, +0x04,0x00,0x84,0x34,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac, +0x00,0x00,0x65,0xac,0xcc,0x7e,0xc4,0xac,0xfc,0x4a,0x05,0xae,0x68,0x15,0x63,0x26, +0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x08,0x42,0x38,0x00,0x4b,0x62,0xac, +0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00, +0x00,0x10,0x42,0x30,0x38,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,0x08,0x00,0x43,0x34, +0x00,0x00,0x6a,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x44,0x31,0x2c,0x00,0x82,0x10, +0x00,0x80,0x42,0x31,0xfb,0x03,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c, +0x24,0x10,0x42,0x01,0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x70,0x64,0xa2,0x90, +0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x4a,0x8c, +0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x6a,0xac,0xff,0x00,0x44,0x31, +0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31, +0x38,0x65,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x21,0x30,0x60,0x00,0xcc,0x64,0x03,0xae,0x01,0x00,0x04,0x24,0x70,0x64,0x0a,0xa2, +0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x4a,0x05,0x8e, +0x02,0x80,0x06,0x3c,0xcc,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00, +0x25,0xb0,0x02,0x3c,0x10,0x00,0x84,0x34,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c, +0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,0xcc,0x7e,0xc4,0xac,0xfc,0x4a,0x05,0xae, +0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38, +0x00,0x4b,0x62,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x00,0x00,0x00,0x00, +0x24,0x10,0x52,0x00,0x00,0x20,0x42,0x30,0x37,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c, +0x04,0x00,0x43,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x44,0x31, +0xe9,0x03,0x82,0x10,0x00,0x80,0x42,0x31,0xc1,0x03,0x40,0x14,0x00,0x80,0x02,0x3c, +0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24, +0x6c,0x64,0xa2,0x90,0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00, +0x0c,0x00,0x4a,0x8c,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x6a,0xac, +0xff,0x00,0x44,0x31,0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,0x68,0x15,0x70,0x26, +0xff,0x00,0x43,0x31,0x2c,0x65,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00, +0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xc0,0x64,0x03,0xae,0x01,0x00,0x04,0x24, +0x6c,0x64,0x0a,0xa2,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0xfc,0x4a,0x05,0x8e,0x02,0x80,0x06,0x3c,0xcc,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24, +0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c,0x20,0x00,0x84,0x34,0x80,0x03,0x42,0x34, +0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,0xcc,0x7e,0xc4,0xac, +0xfc,0x4a,0x05,0xae,0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00, +0x00,0x20,0x42,0x38,0x00,0x4b,0x62,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c, +0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x00,0x80,0x42,0x30,0x58,0x00,0x40,0x10, +0x2a,0xb0,0x06,0x3c,0x0c,0x00,0xc3,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24, +0xff,0x00,0x44,0x31,0x9d,0x03,0x87,0x10,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14, +0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10, +0xff,0x00,0x02,0x24,0x40,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00, +0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0x48,0x64,0xa4,0xa0, +0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10, +0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00, +0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x48,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26, +0x48,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31, +0x00,0x00,0x4a,0xac,0xa9,0x1a,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac, +0xff,0x00,0x02,0x24,0x24,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31, +0xf0,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x21,0x30,0x60,0x00,0x48,0x64,0x0a,0xa2,0x84,0x64,0x03,0xae,0x03,0x00,0x04,0x24, +0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c, +0xdc,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,0xcc,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e, +0x01,0x00,0x08,0x3c,0x80,0xff,0x02,0x24,0x25,0x38,0xe2,0x00,0x00,0x80,0x03,0x35, +0x80,0x00,0xa5,0x34,0x27,0x18,0x03,0x00,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c, +0x24,0x30,0xc3,0x00,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c, +0x00,0x00,0x44,0xac,0x27,0x88,0x08,0x00,0x00,0x00,0x66,0xac,0xcc,0x7e,0x25,0xad, +0xdc,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c, +0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,0x00,0x4b,0x62,0xac,0x68,0x15,0x65,0x26, +0xfc,0x4a,0xa2,0x8c,0x01,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00, +0x24,0x10,0x43,0x00,0x56,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x10,0x00,0xc3,0x34, +0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0x49,0x03,0x87,0x10, +0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c, +0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24, +0x41,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30, +0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0x4c,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90, +0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00, +0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14, +0xff,0x00,0x44,0x30,0x4c,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26,0x4c,0x64,0x43,0x90, +0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac, +0x08,0x1b,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24, +0x22,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0xf0,0x64,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0x84,0x64,0x03,0xae,0x03,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x4c,0x64,0x0a,0xa2, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0xdc,0x7e,0x27,0x91, +0x02,0x80,0x08,0x3c,0xcc,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,0x01,0x00,0x02,0x3c, +0x00,0x80,0x42,0x34,0x40,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00, +0x80,0x00,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00, +0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac, +0xcc,0x7e,0x05,0xad,0xdc,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26, +0x00,0x4b,0x43,0x8c,0x01,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac, +0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x02,0x00,0x03,0x3c,0x24,0x10,0x52,0x00, +0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x14,0x00,0xc3,0x34, +0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0xcf,0x02,0x87,0x10, +0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c, +0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24, +0x42,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30, +0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0x50,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90, +0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00, +0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14, +0xff,0x00,0x44,0x30,0x50,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26,0x50,0x64,0x43,0x90, +0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac, +0x64,0x1b,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24, +0x25,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0xfc,0x64,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0x50,0x64,0x0a,0xa2,0x90,0x64,0x03,0xae,0x04,0x00,0x04,0x24,0x20,0x00,0x07,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,0xdc,0x7e,0x47,0x91, +0x02,0x80,0x09,0x3c,0xcc,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e,0x06,0x00,0x02,0x3c, +0x20,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x01,0xa5,0x34, +0x25,0xb0,0x03,0x3c,0x04,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02, +0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c, +0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,0xcc,0x7e,0x25,0xad,0xdc,0x7e,0x47,0xa1, +0xfc,0x4a,0x06,0xae,0x00,0x00,0x11,0xad,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c, +0x02,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26, +0xfc,0x4a,0xa2,0x8c,0x04,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00, +0x24,0x10,0x43,0x00,0x58,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x62,0x34, +0x2a,0xb0,0x08,0x3c,0x00,0x00,0x51,0xac,0x18,0x00,0x06,0x35,0x00,0x00,0xca,0x8c, +0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0xa1,0x02,0x87,0x10,0x04,0x00,0x02,0x24, +0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c, +0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x43,0x00,0x06,0x35, +0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10, +0x68,0x15,0x62,0x26,0x54,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30, +0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00, +0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30, +0x54,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26,0x54,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c, +0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c, +0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0xc7,0x1b,0x00,0x08, +0xff,0x00,0x02,0x24,0x00,0x00,0xc2,0xac,0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10, +0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0xfc,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c, +0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x90,0x64,0x03,0xae, +0x04,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x54,0x64,0x0a,0xa2,0x10,0x01,0x00,0x0c, +0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0xdc,0x7e,0x27,0x91,0x02,0x80,0x08,0x3c, +0xcc,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,0x06,0x00,0x02,0x3c,0x10,0x00,0xe7,0x34, +0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x01,0xa5,0x34,0x00,0x26,0x07,0x00, +0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c, +0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,0xcc,0x7e,0x05,0xad,0xdc,0x7e,0x27,0xa1, +0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x04,0x00,0x04,0x3c, +0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c, +0x08,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10, +0x2a,0xb0,0x06,0x3c,0x1c,0x00,0xc3,0x34,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24, +0xff,0x00,0x44,0x31,0x3e,0x02,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31, +0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01, +0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x44,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90, +0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26, +0x58,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30, +0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90, +0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x58,0x64,0xe3,0xa0, +0x68,0x15,0x62,0x26,0x58,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00, +0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34, +0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac,0x22,0x1c,0x00,0x08,0xff,0x00,0x02,0x24, +0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x25,0x00,0x82,0x10,0x68,0x15,0x70,0x26, +0xff,0x00,0x43,0x31,0x08,0x65,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00, +0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x58,0x64,0x0a,0xa2,0x9c,0x64,0x03,0xae, +0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x02,0x80,0x0a,0x3c,0xdc,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,0xcc,0x7e,0x25,0x8d, +0xfc,0x4a,0x06,0x8e,0x18,0x00,0x02,0x3c,0x08,0x00,0xe7,0x34,0x27,0x10,0x02,0x00, +0x24,0x30,0xc2,0x00,0x00,0x02,0xa5,0x34,0x25,0xb0,0x03,0x3c,0x10,0x00,0x02,0x3c, +0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02,0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00, +0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c,0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac, +0xcc,0x7e,0x25,0xad,0xdc,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,0x00,0x00,0x11,0xad, +0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x08,0x00,0x04,0x3c,0x26,0x18,0x64,0x00, +0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x10,0x00,0x03,0x3c, +0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x58,0x00,0x40,0x10, +0x25,0xb0,0x06,0x3c,0xb0,0x03,0xc2,0x34,0x2a,0xb0,0x08,0x3c,0x00,0x00,0x51,0xac, +0x20,0x00,0x03,0x35,0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31, +0xe0,0x01,0x87,0x10,0x90,0x03,0xc2,0x34,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14, +0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10, +0xff,0x00,0x02,0x24,0x45,0x00,0x06,0x35,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00, +0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0x64,0x64,0xa4,0xa0, +0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10, +0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00, +0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x64,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26, +0x64,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x0c,0x00,0x6a,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31, +0x00,0x00,0x4a,0xac,0x85,0x1c,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac, +0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31, +0x08,0x65,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x21,0x30,0x60,0x00,0x9c,0x64,0x03,0xae,0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24, +0x64,0x64,0x0a,0xa2,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c, +0xdc,0x7e,0x27,0x91,0x02,0x80,0x08,0x3c,0xcc,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e, +0x18,0x00,0x02,0x3c,0x01,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00, +0x00,0x02,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00, +0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac, +0xcc,0x7e,0x05,0xad,0xdc,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26, +0x00,0x4b,0x43,0x8c,0x10,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac, +0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x20,0x00,0x03,0x3c,0x24,0x10,0x52,0x00, +0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x24,0x00,0xc3,0x34, +0x00,0x00,0x6a,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x44,0x31,0x58,0x01,0x87,0x10, +0x25,0xb0,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c, +0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24, +0x46,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30, +0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0x5c,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90, +0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00, +0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14, +0xff,0x00,0x44,0x30,0x5c,0x64,0xe3,0xa0,0x68,0x15,0x62,0x26,0x5c,0x64,0x43,0x90, +0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac, +0xe0,0x1c,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24, +0x25,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x14,0x65,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0x5c,0x64,0x0a,0xa2,0xa8,0x64,0x03,0xae,0x06,0x00,0x04,0x24,0x20,0x00,0x07,0x24, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,0xdc,0x7e,0x47,0x91, +0x02,0x80,0x09,0x3c,0xcc,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e,0x60,0x00,0x02,0x3c, +0x04,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x04,0xa5,0x34, +0x25,0xb0,0x03,0x3c,0x40,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02, +0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c, +0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,0xcc,0x7e,0x25,0xad,0xdc,0x7e,0x47,0xa1, +0xfc,0x4a,0x06,0xae,0x00,0x00,0x11,0xad,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c, +0x20,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26, +0xfc,0x4a,0xa2,0x8c,0x40,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00, +0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x68,0x15,0x70,0x26,0x25,0xb0,0x02,0x3c, +0x2a,0xb0,0x07,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x51,0xac,0x28,0x00,0xe3,0x34, +0x00,0x00,0x6a,0x8c,0xff,0x00,0x06,0x24,0xff,0x00,0x44,0x31,0xfe,0x00,0x86,0x10, +0x25,0xbd,0x02,0x3c,0x00,0x80,0x42,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c, +0x00,0xff,0x02,0x3c,0x24,0x10,0x42,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24, +0x47,0x00,0xe7,0x34,0x00,0x00,0xe2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30, +0x0e,0x00,0x86,0x10,0x68,0x15,0x62,0x26,0x60,0x64,0xa4,0xa0,0x00,0x00,0xe2,0x90, +0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x30,0xa0,0x00, +0x21,0x28,0xe0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14, +0xff,0x00,0x44,0x30,0x60,0x64,0xc3,0xa0,0x68,0x15,0x62,0x26,0x60,0x64,0x43,0x90, +0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x6a,0x8c, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x44,0x31,0x00,0x00,0x4a,0xac, +0x44,0x1d,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24, +0x21,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x43,0x31,0x14,0x65,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0xa8,0x64,0x03,0xae,0x06,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x60,0x64,0x0a,0xa2, +0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0xdc,0x7e,0x27,0x91, +0x02,0x80,0x08,0x3c,0xcc,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,0x60,0x00,0x02,0x3c, +0x02,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x04,0xa5,0x34, +0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34, +0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,0xcc,0x7e,0x05,0xad, +0xdc,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c, +0x40,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x70,0x26, +0xfc,0x4a,0x06,0x8e,0x00,0x04,0x11,0x3c,0x24,0x10,0xd2,0x00,0x24,0x10,0x51,0x00, +0x77,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x24,0x28,0xd2,0x00,0x00,0x08,0x04,0x3c, +0x24,0x10,0xa4,0x00,0x08,0x00,0x40,0x10,0x80,0x00,0x07,0x3c,0x00,0x4b,0x03,0x8e, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,0x00,0x00,0x44,0xac, +0x00,0x4b,0x03,0xae,0x80,0x00,0x07,0x3c,0x24,0x10,0xa7,0x00,0x21,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x00,0x4b,0x03,0x8e,0x25,0xb0,0x08,0x3c,0xb0,0x03,0x09,0x35, +0x2a,0xb0,0x02,0x3c,0x00,0x00,0x23,0xad,0x36,0x00,0x42,0x34,0x00,0x00,0x43,0x90, +0x23,0xb0,0x04,0x3c,0xff,0x1f,0x02,0x3c,0xc0,0x18,0x03,0x00,0xf0,0x07,0x63,0x30, +0xbc,0x65,0x05,0x8e,0x21,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x84,0x00,0x65,0x10,0xc0,0x65,0x03,0xae,0x02,0x80,0x05,0x3c,0xcc,0x7e,0xa3,0x8c, +0x27,0x20,0x07,0x00,0x24,0x20,0xc4,0x00,0x00,0x08,0x63,0x34,0x41,0xb0,0x02,0x3c, +0x00,0x00,0x23,0xad,0x00,0x00,0x44,0xac,0xcc,0x7e,0xa3,0xac,0xfc,0x4a,0x04,0xae, +0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x80,0x00,0x04,0x3c,0x26,0x18,0x64,0x00, +0x00,0x4b,0x43,0xac,0x68,0x15,0x66,0x26,0xfc,0x4a,0xc3,0x8c,0x00,0x01,0x04,0x3c, +0x24,0x28,0x72,0x00,0x24,0x10,0xa4,0x00,0x06,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c, +0x00,0x4b,0xc3,0x8c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,0x00,0x00,0x44,0xac, +0x00,0x4b,0xc3,0xac,0x00,0x02,0x04,0x3c,0x24,0x10,0xa4,0x00,0x08,0x00,0x40,0x10, +0x02,0x80,0x02,0x3c,0x00,0x4b,0xc2,0x8c,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34, +0x26,0x10,0x44,0x00,0x00,0x4b,0xc2,0xac,0x00,0x00,0x64,0xac,0x02,0x80,0x02,0x3c, +0xea,0x7d,0x43,0x90,0x01,0x00,0x02,0x24,0x0f,0x00,0x63,0x30,0x3f,0x00,0x62,0x10, +0x00,0x00,0x00,0x00,0x28,0x00,0xbf,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f, +0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27, +0x20,0xbd,0x02,0x3c,0xec,0x02,0x65,0x35,0x4d,0x00,0x68,0x35,0xf1,0x02,0x69,0x35, +0x08,0x00,0x07,0x24,0x78,0x02,0x42,0x34,0x00,0x00,0x46,0xa4,0x00,0x00,0x00,0xa1, +0x00,0x00,0x27,0xa1,0x00,0x00,0xa0,0xac,0x00,0x00,0xa2,0x8c,0xff,0x00,0x03,0x3c, +0x80,0x00,0x04,0x3c,0xff,0x00,0x4a,0x30,0x25,0x50,0x43,0x01,0x24,0x20,0x44,0x01, +0xf2,0x02,0x66,0x35,0x0a,0x00,0x6a,0x35,0x80,0xff,0x02,0x24,0x00,0x00,0x00,0xa1, +0x00,0x00,0x27,0xa1,0x00,0x00,0xa3,0xac,0x00,0x00,0xa3,0xac,0x00,0x00,0xc0,0xa0, +0x00,0x00,0x42,0xa1,0x04,0x00,0x80,0x10,0x02,0x00,0x62,0x35,0x84,0xff,0x02,0x24, +0x00,0x00,0x42,0xa1,0x02,0x00,0x62,0x35,0x00,0x00,0x43,0x94,0xff,0xbf,0x04,0x24, +0x24,0x18,0x64,0x00,0x00,0x00,0x43,0xa4,0x7f,0x19,0x00,0x08,0x68,0x15,0x66,0x26, +0x0e,0x4f,0x00,0x0c,0x07,0x00,0x04,0x24,0x00,0x4b,0x03,0x8e,0xfc,0x4a,0x06,0x8e, +0x25,0xb0,0x02,0x3c,0x26,0x18,0x71,0x00,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x72,0x1d,0x00,0x08,0x00,0x4b,0x03,0xae,0x56,0x01,0x42,0x35,0x00,0x00,0x43,0x94, +0x00,0x00,0x00,0x00,0x75,0xfb,0x60,0x10,0x00,0x00,0x00,0x00,0x0e,0x4f,0x00,0x0c, +0x07,0x00,0x04,0x24,0x6c,0x19,0x00,0x08,0x68,0x15,0x64,0x26,0x28,0x00,0xbf,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x30,0x19,0x00,0x08,0x30,0x00,0xbd,0x27,0x00,0x00,0x62,0xac,0xdc,0x19,0x00,0x08, +0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0x19,0x1a,0x00,0x08,0xff,0x00,0x02,0x24, +0x00,0x00,0x62,0xac,0x56,0x1a,0x00,0x08,0xff,0x00,0x02,0x24,0x05,0x00,0x03,0x24, +0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x8b,0x1b,0x00,0x08,0x68,0x15,0x62,0x26, +0x02,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x07,0x1d,0x00,0x08, +0x68,0x15,0x62,0x26,0xd0,0x03,0x03,0x35,0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac, +0x9d,0x1d,0x00,0x08,0x68,0x15,0x62,0x26,0x01,0x00,0x03,0x24,0x90,0x03,0x42,0x34, +0x00,0x00,0x43,0xac,0x67,0x1d,0x00,0x08,0x68,0x15,0x62,0x26,0x25,0xb0,0x02,0x3c, +0x07,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x68,0x15,0x63,0x26, +0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,0xd3,0x1a,0x00,0x08, +0x00,0x4b,0x62,0xac,0x06,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x2c,0x1b,0x00,0x08,0x68,0x15,0x62,0x26,0x25,0xb0,0x02,0x3c,0x07,0x00,0x03,0x24, +0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c, +0x00,0x00,0x00,0x00,0x00,0x20,0x42,0x38,0x76,0x1a,0x00,0x08,0x00,0x4b,0x62,0xac, +0x03,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x49,0x1c,0x00,0x08, +0x68,0x15,0x62,0x26,0x00,0x00,0x40,0xac,0xa8,0x1c,0x00,0x08,0x68,0x15,0x62,0x26, +0x90,0x03,0x63,0x34,0x00,0x00,0x62,0xac,0xea,0x1b,0x00,0x08,0x68,0x15,0x62,0x26, +0x25,0xb0,0x0d,0x3c,0x00,0x80,0x02,0x3c,0x18,0x03,0xa4,0x35,0x10,0x79,0x42,0x24, +0x02,0x80,0x03,0x3c,0x41,0xb0,0x08,0x3c,0x00,0x00,0x82,0xac,0x68,0x15,0x6a,0x24, +0x0a,0x00,0x02,0x35,0x00,0x00,0x44,0x94,0x0a,0x4b,0x43,0x95,0x08,0x4b,0x4b,0x95, +0x25,0x18,0x64,0x00,0xff,0xff,0x6c,0x30,0x24,0x10,0x8b,0x01,0x02,0x00,0x42,0x30, +0x53,0x00,0x40,0x10,0x02,0x00,0x64,0x38,0x02,0x00,0x02,0x24,0xc0,0x03,0xa3,0x35, +0x00,0x00,0x62,0xac,0x0a,0x4b,0x44,0xa5,0x24,0x38,0x8b,0x01,0x04,0x00,0xe2,0x30, +0x0a,0x00,0x40,0x10,0x08,0x00,0xe2,0x30,0x0a,0x4b,0x43,0x95,0x0c,0x00,0x04,0x35, +0xc0,0x03,0xa5,0x35,0x04,0x00,0x63,0x38,0x04,0x00,0x02,0x24,0x00,0x00,0x86,0x8c, +0x00,0x00,0xa2,0xac,0x0a,0x4b,0x43,0xa5,0x08,0x00,0xe2,0x30,0x08,0x00,0x40,0x10, +0x10,0x00,0xe2,0x30,0x0a,0x4b,0x42,0x95,0xc0,0x03,0xa4,0x35,0x08,0x00,0x03,0x24, +0x08,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x0a,0x4b,0x42,0xa5,0x10,0x00,0xe2,0x30, +0x08,0x00,0x40,0x10,0x20,0x00,0xe2,0x30,0x0a,0x4b,0x42,0x95,0xc0,0x03,0xa4,0x35, +0x10,0x00,0x03,0x24,0x10,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x0a,0x4b,0x42,0xa5, +0x20,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,0x80,0x00,0xe2,0x30,0x0a,0x4b,0x42,0x95, +0xc0,0x03,0xa4,0x35,0x20,0x00,0x03,0x24,0x20,0x00,0x42,0x38,0x00,0x00,0x83,0xac, +0x0a,0x4b,0x42,0xa5,0x80,0x00,0xe2,0x30,0x15,0x00,0x40,0x10,0x24,0x10,0x8b,0x01, +0x02,0x80,0x09,0x3c,0x0a,0x4b,0x46,0x95,0xcc,0x7e,0x25,0x8d,0x08,0x00,0x02,0x3c, +0x7f,0xff,0x04,0x24,0x24,0x20,0x64,0x01,0x25,0x28,0xa2,0x00,0x80,0x00,0xc6,0x38, +0xb0,0x03,0xa7,0x35,0x08,0x00,0x08,0x35,0xc0,0x03,0xa3,0x35,0x80,0x00,0x02,0x24, +0x00,0x00,0x62,0xac,0x21,0x58,0x80,0x00,0x00,0x00,0xe5,0xac,0x0a,0x4b,0x46,0xa5, +0xcc,0x7e,0x25,0xad,0x00,0x00,0x04,0xa5,0x08,0x4b,0x44,0xa5,0x24,0x10,0x8b,0x01, +0x00,0x30,0x42,0x30,0x07,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x0a,0x4b,0x42,0x95, +0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38,0x00,0x20,0x42,0x34,0x0a,0x4b,0x42,0xa5, +0x02,0x80,0x02,0x3c,0xea,0x7d,0x43,0x90,0x01,0x00,0x02,0x24,0x0f,0x00,0x63,0x30, +0x05,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x5a,0x1e,0x00,0x08,0x0a,0x4b,0x43,0xa5,0x30,0x19,0x00,0x08,0x00,0x00,0x00,0x00, +0xf8,0xff,0xbd,0x27,0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,0x00,0x40,0x02,0x40, +0x00,0x68,0x08,0x40,0x00,0x70,0x02,0x40,0x00,0x60,0x09,0x40,0x25,0xb0,0x05,0x3c, +0x00,0x80,0x02,0x3c,0x18,0x03,0xa3,0x34,0xb0,0x7a,0x42,0x24,0x00,0x00,0x62,0xac, +0x80,0x00,0x87,0x8c,0x7c,0x02,0xa2,0x34,0x84,0x02,0xa3,0x34,0x88,0x02,0xa6,0x34, +0x00,0x00,0x47,0xac,0x00,0x00,0x68,0xac,0x00,0x00,0xc9,0xac,0x74,0x00,0x83,0x8c, +0x8c,0x02,0xa2,0x34,0x90,0x02,0xa7,0x34,0x00,0x00,0x43,0xac,0x08,0x00,0x86,0x8c, +0x94,0x02,0xa8,0x34,0x98,0x02,0xa9,0x34,0x00,0x00,0xe6,0xac,0x0c,0x00,0x82,0x8c, +0x9c,0x02,0xa6,0x34,0xa0,0x02,0xa7,0x34,0x00,0x00,0x02,0xad,0x10,0x00,0x83,0x8c, +0xa4,0x02,0xa8,0x34,0xa8,0x02,0xaa,0x34,0x00,0x00,0x23,0xad,0x14,0x00,0x82,0x8c, +0xac,0x02,0xa9,0x34,0xb0,0x02,0xab,0x34,0x00,0x00,0xc2,0xac,0x18,0x00,0x83,0x8c, +0xb4,0x02,0xa6,0x34,0xb8,0x02,0xac,0x34,0x00,0x00,0xe3,0xac,0x1c,0x00,0x82,0x8c, +0xbc,0x02,0xa7,0x34,0xc0,0x02,0xad,0x34,0x00,0x00,0x02,0xad,0x20,0x00,0x83,0x8c, +0xc4,0x02,0xa8,0x34,0xc8,0x02,0xae,0x34,0x00,0x00,0x43,0xad,0x24,0x00,0x82,0x8c, +0xcc,0x02,0xaa,0x34,0xd0,0x02,0xaf,0x34,0x00,0x00,0x22,0xad,0x28,0x00,0x83,0x8c, +0xd4,0x02,0xa9,0x34,0xd8,0x02,0xb0,0x34,0x00,0x00,0x63,0xad,0x2c,0x00,0x82,0x8c, +0x70,0x02,0xab,0x34,0x74,0x02,0xb1,0x34,0x00,0x00,0xc2,0xac,0x30,0x00,0x83,0x8c, +0x78,0x02,0xa5,0x34,0x00,0x00,0x83,0xad,0x34,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0xe2,0xac,0x38,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xad, +0x3c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xad,0x40,0x00,0x83,0x8c, +0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0xad,0x44,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0x42,0xad,0x48,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe3,0xad, +0x4c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xad,0x50,0x00,0x83,0x8c, +0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xae,0x54,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0x62,0xad,0x58,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xae, +0x5c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,0x0f,0x1f,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x80,0x1b,0x3c,0x44,0x7c,0x7b,0x27,0x25,0xb0,0x1a,0x3c, +0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00, +0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf, +0x0c,0x00,0x63,0xaf,0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf, +0x1c,0x00,0x67,0xaf,0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf, +0x2c,0x00,0x6b,0xaf,0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf, +0x3c,0x00,0x6f,0xaf,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40, +0x40,0x00,0x70,0xaf,0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf, +0x50,0x00,0x74,0xaf,0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf, +0x60,0x00,0x78,0xaf,0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf, +0x70,0x00,0x7e,0xaf,0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf, +0x80,0x00,0x6a,0xaf,0x00,0x68,0x1a,0x40,0x25,0xb0,0x1b,0x3c,0x1c,0x03,0x7b,0x37, +0x00,0x00,0x00,0x00,0x00,0x00,0x7a,0xaf,0x7f,0x00,0x5b,0x33,0x30,0x00,0x60,0x13, +0x00,0x00,0x00,0x00,0x25,0xb0,0x1b,0x3c,0x30,0x03,0x7b,0x37,0x00,0x00,0x00,0x00, +0x00,0x00,0x7a,0xaf,0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00, +0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf, +0x0c,0x00,0x63,0xaf,0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf, +0x1c,0x00,0x67,0xaf,0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf, +0x2c,0x00,0x6b,0xaf,0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf, +0x3c,0x00,0x6f,0xaf,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40, +0x40,0x00,0x70,0xaf,0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf, +0x50,0x00,0x74,0xaf,0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf, +0x60,0x00,0x78,0xaf,0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf, +0x70,0x00,0x7e,0xaf,0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf, +0x80,0x00,0x6a,0xaf,0xac,0x1e,0x00,0x08,0x21,0x20,0x60,0x03,0x00,0x00,0x00,0x00, +0x25,0xb0,0x08,0x3c,0x20,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0xad, +0x00,0x04,0x5b,0x33,0x0a,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x00,0x80,0x08,0x3c, +0x30,0x65,0x08,0x25,0x00,0x00,0x00,0x00,0x25,0xb0,0x1b,0x3c,0x24,0x03,0x7b,0x37, +0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xaf,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00, +0x00,0x08,0x5b,0x33,0x25,0xb0,0x08,0x3c,0x28,0x03,0x08,0x35,0x00,0x00,0x00,0x00, +0x00,0x00,0x1b,0xad,0x06,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x00,0x80,0x08,0x3c, +0x10,0x79,0x08,0x25,0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00, +0x02,0x80,0x1a,0x3c,0xcc,0x7e,0x5a,0x27,0x04,0x00,0x5b,0x97,0x25,0xb0,0x08,0x3c, +0x30,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad,0x18,0x00,0x60,0x13, +0x00,0x00,0x00,0x00,0x08,0xec,0x9b,0x27,0x00,0x00,0x00,0x00,0x04,0x00,0x61,0x8f, +0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b, +0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b, +0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b, +0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b, +0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,0xfc,0x1f,0x00,0x08,0x00,0x00,0x00,0x00, +0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27, +0x08,0x00,0x5b,0xaf,0xfc,0xef,0x9d,0x27,0x00,0x00,0x4a,0x8f,0x00,0x00,0x00,0x00, +0x21,0x00,0x40,0x11,0x00,0x00,0x00,0x00,0x02,0x80,0x08,0x3c,0x2c,0x7e,0x08,0x25, +0x21,0x48,0x00,0x00,0x21,0x58,0x00,0x00,0x01,0x00,0x6b,0x25,0x1a,0x00,0x40,0x11, +0x24,0x70,0x4b,0x01,0x14,0x00,0xc0,0x11,0x01,0x00,0x04,0x24,0x00,0x00,0x00,0x00, +0x04,0x00,0x44,0xa3,0x26,0x50,0x4b,0x01,0x00,0x00,0x4a,0xaf,0x80,0x80,0x09,0x00, +0x21,0x80,0x08,0x02,0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x02, +0x00,0x00,0x00,0x00,0x00,0x80,0x1b,0x3c,0x1c,0x7f,0x7b,0x27,0x25,0xb0,0x1a,0x3c, +0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0xcc,0x7e,0x5a,0x27, +0xe1,0xff,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x29,0x25,0x40,0x58,0x0b,0x00, +0xbf,0x1f,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x1b,0x3c,0xcc,0x7e,0x7b,0x27, +0x21,0x60,0x00,0x00,0x04,0x00,0x6c,0xa7,0x08,0x00,0x7a,0x8f,0x00,0x00,0x00,0x00, +0xf8,0xff,0x5a,0x27,0x00,0x00,0x5a,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x5a,0x27, +0x84,0x00,0x44,0x8f,0x00,0x00,0x00,0x00,0xf9,0xff,0x80,0x10,0x00,0x00,0x00,0x00, +0x04,0x00,0x41,0x8f,0xfc,0x03,0x50,0x7b,0x7c,0x00,0x42,0x7b,0xbc,0x00,0x44,0x7b, +0xfc,0x00,0x46,0x7b,0x3c,0x01,0x48,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02, +0x7c,0x01,0x4a,0x7b,0xbc,0x01,0x4c,0x7b,0xfc,0x01,0x4e,0x7b,0x3c,0x02,0x50,0x7b, +0x7c,0x02,0x52,0x7b,0xbc,0x02,0x54,0x7b,0xfc,0x02,0x56,0x7b,0x3c,0x03,0x58,0x7b, +0x7c,0x03,0x5c,0x7b,0xbc,0x03,0x5e,0x7b,0x80,0x00,0x5b,0x8f,0x00,0x00,0x00,0x00, +0x08,0x00,0x60,0x03,0x10,0x00,0x00,0x42,0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00, +0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac, +0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac, +0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac, +0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac, +0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac, +0x54,0x00,0x95,0xac,0x58,0x00,0x96,0xac,0x5c,0x00,0x97,0xac,0x60,0x00,0x98,0xac, +0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac, +0x74,0x00,0x9f,0xac,0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac, +0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24, +0x84,0x00,0x86,0x8c,0x00,0x00,0x00,0x00,0xf9,0xff,0xc0,0x10,0x00,0x00,0x00,0x00, +0x21,0xd8,0x80,0x00,0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b, +0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b, +0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b, +0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b, +0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b, +0x80,0x00,0x7b,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40, +0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40, +0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac, +0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac, +0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00, +0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac, +0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac,0x54,0x00,0x94,0xac,0x58,0x00,0x96,0xac, +0x5c,0x00,0x96,0xac,0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac, +0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac,0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac, +0x80,0x00,0x9f,0xac,0x84,0x00,0x80,0xac,0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c, +0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c,0xfa,0xff,0xc0,0x10, +0x00,0x00,0x00,0x00,0x21,0xd8,0x80,0x00,0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f, +0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b, +0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b, +0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b, +0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b, +0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x60,0xb9,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,0x00,0x00,0x7b,0x27, +0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x00,0x00,0x05,0x24, +0x03,0x00,0xa4,0x24,0x00,0xa0,0x80,0x40,0x00,0xa0,0x84,0x40,0x01,0x80,0x04,0x3c, +0x98,0x03,0x84,0x24,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x01,0x80,0x1b,0x3c,0x98,0x03,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27, +0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x00,0x00,0x5a,0x27,0xfc,0x03,0x5d,0x27, +0x02,0x80,0x1c,0x3c,0x00,0x14,0x9c,0x27,0x00,0xf0,0x08,0x3c,0x00,0x0c,0x08,0x35, +0x00,0x60,0x88,0x40,0x02,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,0xff,0x7f,0x05,0x3c, +0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x20,0x84,0x4c,0xff,0xff,0x05,0x34, +0x21,0x28,0xa4,0x00,0x00,0x28,0x85,0x4c,0x00,0x80,0x04,0x3c,0x00,0x00,0x84,0x24, +0xff,0x7f,0x05,0x3c,0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x00,0x84,0x4c, +0xff,0xff,0x06,0x34,0x21,0x30,0xc4,0x00,0x24,0x30,0xc5,0x00,0x00,0x08,0x86,0x4c, +0x00,0xa0,0x04,0x40,0x10,0x00,0x84,0x34,0x00,0xa0,0x84,0x40,0x01,0x80,0x1b,0x3c, +0x24,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf, +0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x84, +0x20,0x00,0x06,0x24,0x25,0x28,0xa6,0x00,0x00,0x00,0x85,0xa4,0x01,0x80,0x1b,0x3c, +0x54,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf, +0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x8c,0x00,0x00,0x00,0x00, +0x10,0x00,0xa5,0x30,0xfc,0xff,0xa0,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x07,0x3c, +0xff,0xff,0xe7,0x34,0x02,0x80,0x05,0x3c,0xe8,0x7d,0xa5,0x24,0xff,0xff,0xa5,0x30, +0x40,0xb0,0x04,0x3c,0x25,0x28,0xa4,0x00,0x24,0x28,0xa7,0x00,0x21,0x30,0x00,0x00, +0x43,0xb0,0x02,0x3c,0x00,0x80,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x45,0xac, +0x04,0x00,0x46,0xac,0x08,0x00,0x44,0xac,0x8b,0x5b,0x00,0x08,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24, +0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x42,0x24, +0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x21,0x18,0x40,0x00,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x44,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x04,0x00,0x85,0x8c,0x00,0x80,0x03,0x3c,0x01,0x00,0x02,0x24,0x25,0x28,0xa3,0x00, +0x00,0x00,0xa4,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x74,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x04,0x00,0x82,0x8c,0x02,0x00,0x83,0x94,0x00,0x80,0x07,0x3c,0x25,0x28,0x47,0x00, +0x00,0x00,0xa2,0x8c,0x10,0x00,0x02,0x24,0x13,0x00,0x62,0x10,0x11,0x00,0x66,0x28, +0x06,0x00,0xc0,0x10,0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24,0x17,0x00,0x62,0x10, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0xfd,0xff,0x62,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xac, +0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x25,0x10,0x47,0x00,0x00,0x00,0x42,0x8c, +0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0xa2,0xa4,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x25,0x18,0x67,0x00, +0x00,0x00,0x62,0x94,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c, +0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xa0,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00, +0x25,0x18,0x67,0x00,0x00,0x00,0x62,0x90,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24, +0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x1c,0x00,0xbf,0xaf, +0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x68,0x15,0x31,0x26,0x44,0x65,0x30,0x96, +0x02,0x80,0x02,0x3c,0x01,0x80,0x03,0x3c,0x25,0x80,0x02,0x02,0x25,0xb0,0x02,0x3c, +0x38,0x06,0x63,0x24,0x18,0x03,0x42,0x34,0x60,0x00,0x04,0x26,0x80,0x00,0x05,0x26, +0x00,0x00,0x43,0xac,0x6c,0x45,0x00,0x0c,0x03,0x00,0x06,0x24,0x21,0x20,0x00,0x02, +0x21,0x28,0x00,0x00,0x58,0x45,0x00,0x0c,0x08,0x00,0x06,0x24,0x44,0x65,0x22,0x8e, +0x0c,0x00,0x03,0x24,0x0c,0x00,0x43,0xae,0x08,0x00,0x42,0xae,0x12,0x00,0x02,0x24, +0x14,0x00,0x42,0xae,0x21,0x20,0x40,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x30,0x08,0x00,0x08,0x20,0x00,0xbd,0x27, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x02,0x80,0x02,0x3c,0x21,0x48,0x80,0x00, +0x68,0x15,0x48,0x24,0x21,0x38,0x00,0x00,0x21,0x28,0x27,0x01,0x00,0x00,0xa2,0x90, +0x21,0x20,0xe8,0x00,0x01,0x00,0xe7,0x24,0x44,0x4c,0x82,0xa0,0x1e,0x00,0xa3,0x90, +0x1e,0x00,0xe6,0x28,0x62,0x4c,0x83,0xa0,0x3c,0x00,0xa2,0x90,0x00,0x00,0x00,0x00, +0x80,0x4c,0x82,0xa0,0x5a,0x00,0xa3,0x90,0xf3,0xff,0xc0,0x14,0x9e,0x4c,0x83,0xa0, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24, +0x20,0xbd,0x03,0x3c,0x58,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x0f,0x27,0x07,0x24, +0x20,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0xff,0xff,0xe7,0x24,0xff,0xff,0xe1,0x04, +0xff,0xff,0xe7,0x24,0x62,0xbd,0x04,0x3c,0x24,0x10,0x82,0x34,0x00,0x00,0x40,0xa0, +0x28,0x10,0x83,0x34,0x0c,0x11,0x86,0x34,0x0e,0x00,0x02,0x24,0x00,0x00,0x60,0xa0, +0x00,0x11,0x85,0x34,0x00,0x00,0xc2,0xa0,0x00,0x00,0xa7,0x8c,0xdf,0xff,0x02,0x24, +0x10,0x00,0x86,0x34,0x24,0x38,0xe2,0x00,0x49,0x0c,0x03,0x24,0xcf,0xff,0x02,0x24, +0x00,0x00,0xc3,0xac,0x04,0x00,0x84,0x34,0x00,0x00,0xa7,0xac,0x24,0x38,0xe2,0x00, +0x41,0x0c,0x02,0x24,0x00,0x00,0xa7,0xac,0x00,0x00,0x80,0xac,0x00,0x00,0xc2,0xac, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x25,0xb0,0x05,0x3c,0x01,0x80,0x03,0x3c,0x21,0x38,0x80,0x00,0x18,0x03,0xa2,0x34, +0xa8,0x08,0x63,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0x35,0x00,0xe4,0x10, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x10,0x20,0x08,0xa2,0x34,0x02,0x00,0x02,0x24, +0x83,0x00,0xe2,0x10,0x03,0x00,0x02,0x24,0x5a,0x00,0xe2,0x10,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c, +0x68,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x80,0x4b,0xc2,0xac, +0x40,0x08,0x02,0x24,0x84,0x4b,0xc3,0xac,0x90,0x4b,0xc2,0xac,0x78,0x08,0x03,0x24, +0x0c,0x08,0x02,0x24,0x94,0x4b,0xc3,0xac,0x98,0x4b,0xc2,0xac,0x10,0x08,0x03,0x24, +0x20,0x08,0x02,0x24,0x9c,0x4b,0xc3,0xac,0xa0,0x4b,0xc2,0xac,0x24,0x08,0x03,0x24, +0x58,0x08,0x02,0x24,0xa4,0x4b,0xc3,0xac,0xa8,0x4b,0xc2,0xac,0x50,0x0c,0x03,0x24, +0x54,0x0c,0x02,0x24,0xac,0x4b,0xc3,0xac,0xb0,0x4b,0xc2,0xac,0x14,0x0c,0x03,0x24, +0x10,0x0c,0x02,0x24,0x60,0x08,0x05,0x24,0xb4,0x4b,0xc3,0xac,0xb8,0x4b,0xc2,0xac, +0x80,0x0c,0x03,0x24,0x84,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xc0,0x4b,0xc2,0xac, +0x8c,0x4b,0xc5,0xac,0xbc,0x4b,0xc3,0xac,0x7d,0x4b,0xc0,0xa0,0x88,0x4b,0xc5,0xac, +0x02,0x00,0x80,0x10,0xa0,0x08,0x02,0x24,0xb8,0x08,0x02,0x24,0x08,0x00,0xe0,0x03, +0xc4,0x4b,0xc2,0xac,0x28,0x08,0xa2,0x34,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c, +0x68,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x80,0x4b,0xc2,0xac, +0x44,0x08,0x02,0x24,0x84,0x4b,0xc3,0xac,0x90,0x4b,0xc2,0xac,0x78,0x08,0x03,0x24, +0x0c,0x08,0x02,0x24,0x94,0x4b,0xc3,0xac,0x98,0x4b,0xc2,0xac,0x14,0x08,0x03,0x24, +0x28,0x08,0x02,0x24,0x9c,0x4b,0xc3,0xac,0xa0,0x4b,0xc2,0xac,0x2c,0x08,0x03,0x24, +0x58,0x08,0x02,0x24,0xa4,0x4b,0xc3,0xac,0xa8,0x4b,0xc2,0xac,0x58,0x0c,0x03,0x24, +0x5c,0x0c,0x02,0x24,0xac,0x4b,0xc3,0xac,0xb0,0x4b,0xc2,0xac,0x1c,0x0c,0x03,0x24, +0x18,0x0c,0x02,0x24,0x64,0x08,0x05,0x24,0xb4,0x4b,0xc3,0xac,0xb8,0x4b,0xc2,0xac, +0x88,0x0c,0x03,0x24,0x8c,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xc0,0x4b,0xc2,0xac, +0x7d,0x4b,0xc7,0xa0,0x8c,0x4b,0xc5,0xac,0xbc,0x4b,0xc3,0xac,0x88,0x4b,0xc5,0xac, +0xd6,0xff,0x80,0x10,0xa4,0x08,0x02,0x24,0xbc,0x08,0x02,0x24,0x08,0x00,0xe0,0x03, +0xc4,0x4b,0xc2,0xac,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0xac,0x08,0x03,0x24, +0xc4,0x4b,0x43,0xac,0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x80,0x4b,0x43,0xac, +0x4c,0x08,0x03,0x24,0x84,0x4b,0x44,0xac,0x90,0x4b,0x43,0xac,0x7c,0x08,0x04,0x24, +0x0c,0x08,0x03,0x24,0x94,0x4b,0x44,0xac,0x98,0x4b,0x43,0xac,0x1c,0x08,0x04,0x24, +0x38,0x08,0x03,0x24,0x9c,0x4b,0x44,0xac,0xa0,0x4b,0x43,0xac,0x3c,0x08,0x04,0x24, +0x5c,0x08,0x03,0x24,0xa4,0x4b,0x44,0xac,0xa8,0x4b,0x43,0xac,0x68,0x0c,0x04,0x24, +0x6c,0x0c,0x03,0x24,0xac,0x4b,0x44,0xac,0xb0,0x4b,0x43,0xac,0x2c,0x0c,0x04,0x24, +0x28,0x0c,0x03,0x24,0x6c,0x08,0x05,0x24,0xb4,0x4b,0x44,0xac,0xb8,0x4b,0x43,0xac, +0x98,0x0c,0x04,0x24,0x9c,0x0c,0x03,0x24,0x7d,0x4b,0x47,0xa0,0x8c,0x4b,0x45,0xac, +0xbc,0x4b,0x44,0xac,0xc0,0x4b,0x43,0xac,0x08,0x00,0xe0,0x03,0x88,0x4b,0x45,0xac, +0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0xa8,0x08,0x03,0x24,0xc4,0x4b,0x43,0xac, +0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x80,0x4b,0x43,0xac,0x48,0x08,0x03,0x24, +0x84,0x4b,0x44,0xac,0x90,0x4b,0x43,0xac,0x7c,0x08,0x04,0x24,0x0c,0x08,0x03,0x24, +0x94,0x4b,0x44,0xac,0x98,0x4b,0x43,0xac,0x18,0x08,0x04,0x24,0x30,0x08,0x03,0x24, +0x9c,0x4b,0x44,0xac,0xa0,0x4b,0x43,0xac,0x34,0x08,0x04,0x24,0x5c,0x08,0x03,0x24, +0xa4,0x4b,0x44,0xac,0xa8,0x4b,0x43,0xac,0x60,0x0c,0x04,0x24,0x64,0x0c,0x03,0x24, +0xac,0x4b,0x44,0xac,0xb0,0x4b,0x43,0xac,0x24,0x0c,0x04,0x24,0x20,0x0c,0x03,0x24, +0x68,0x08,0x05,0x24,0xb4,0x4b,0x44,0xac,0xb8,0x4b,0x43,0xac,0x90,0x0c,0x04,0x24, +0x94,0x0c,0x03,0x24,0x7d,0x4b,0x47,0xa0,0x8c,0x4b,0x45,0xac,0xbc,0x4b,0x44,0xac, +0xc0,0x4b,0x43,0xac,0x08,0x00,0xe0,0x03,0x88,0x4b,0x45,0xac,0xe6,0x42,0x00,0x08, +0x21,0x18,0x00,0x00,0x20,0x00,0x62,0x2c,0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x06,0x10,0x64,0x00,0x01,0x00,0x42,0x30,0xfa,0xff,0x40,0x10,0x01,0x00,0x63,0x24, +0xff,0xff,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xd8,0xff,0xbd,0x27, +0x25,0xb0,0x02,0x3c,0x18,0x00,0xb2,0xaf,0x21,0x90,0x82,0x00,0xff,0xff,0x02,0x24, +0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf, +0x21,0x88,0xa0,0x00,0x21,0x20,0xa0,0x00,0x21,0x18,0x40,0x02,0x10,0x00,0xa2,0x10, +0x21,0x98,0xc0,0x00,0x00,0x00,0x50,0x8e,0xe1,0x42,0x00,0x0c,0x00,0x00,0x00,0x00, +0x04,0x10,0x53,0x00,0x27,0x18,0x11,0x00,0x25,0x18,0x62,0x00,0x24,0x18,0x70,0x00, +0x00,0x00,0x43,0xae,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27, +0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x28,0x00,0xbd,0x27,0x00,0x00,0x66,0xac,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x21,0x30,0x80,0x00,0xf8,0x60,0x44,0x8c, +0xed,0x42,0x00,0x08,0xff,0xff,0x05,0x24,0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c, +0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x20,0x82,0x00, +0x00,0x00,0x90,0x8c,0x21,0x88,0xa0,0x00,0xe1,0x42,0x00,0x0c,0x21,0x20,0xa0,0x00, +0x24,0x80,0x11,0x02,0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27, +0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x28,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf, +0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x24,0x00,0xb5,0xaf,0x10,0x00,0xb0,0xaf, +0x68,0x15,0x31,0x26,0xa4,0x4b,0x22,0x8e,0x25,0xb0,0x12,0x3c,0x24,0x08,0x53,0x36, +0x21,0x10,0x52,0x00,0x00,0x00,0x70,0x8e,0x00,0x00,0x55,0x8c,0x7f,0x80,0x03,0x3c, +0xff,0x7f,0x02,0x3c,0xff,0xff,0x63,0x34,0xff,0xff,0x42,0x34,0x24,0x10,0x02,0x02, +0x24,0x18,0xa3,0x02,0xc0,0x25,0x04,0x00,0x25,0x18,0x64,0x00,0x00,0x80,0x14,0x3c, +0x00,0x00,0x62,0xae,0x01,0x00,0x04,0x24,0xeb,0x0b,0x00,0x0c,0x25,0xa8,0x74,0x00, +0xa4,0x4b,0x22,0x8e,0x25,0x80,0x14,0x02,0x01,0x00,0x04,0x24,0x21,0x10,0x52,0x00, +0x00,0x00,0x55,0xac,0xeb,0x0b,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xae, +0xeb,0x0b,0x00,0x0c,0x01,0x00,0x04,0x24,0xc4,0x4b,0x24,0x8e,0x0f,0x00,0x05,0x3c, +0x28,0x00,0xbf,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0xa5,0x34, +0x18,0x43,0x00,0x08,0x30,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf, +0x02,0x80,0x11,0x3c,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x68,0x15,0x27,0x26, +0x7f,0x4b,0xe5,0x90,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x70,0x0d,0x63,0x24, +0x18,0x03,0x42,0x34,0x02,0x00,0x06,0x24,0x00,0x00,0x43,0xac,0x34,0x00,0xa6,0x10, +0x21,0x80,0x80,0x00,0x03,0x00,0x03,0x24,0x3a,0x00,0xa3,0x10,0x2e,0x00,0x02,0x2e, +0x10,0x00,0x02,0x2e,0x07,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0x00,0x04,0x32, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x29,0x43,0x00,0x08, +0x20,0x00,0xbd,0x27,0xfa,0xff,0xa6,0x14,0xff,0x00,0x04,0x32,0x7d,0x4b,0xe4,0x90, +0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x38,0x00,0x85,0x10,0x68,0x15,0x22,0x26,0x2e,0x00,0x83,0x10, +0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,0x18,0x43,0x00,0x0c,0xff,0xff,0x05,0x24, +0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24, +0xed,0x42,0x00,0x0c,0xff,0xff,0x05,0x24,0x68,0x15,0x22,0x26,0x7d,0x4b,0x44,0x90, +0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14, +0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0xdb,0xff,0x82,0x14, +0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c, +0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00,0x72,0x43,0x00,0x08,0xff,0x00,0x04,0x32, +0x25,0x00,0x82,0x2c,0xcc,0xff,0x40,0x14,0x03,0x00,0x03,0x24,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0xc7,0xff,0x40,0x14,0x10,0x00,0x02,0x2e,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x68,0x15,0x22,0x26,0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c, +0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,0x84,0x43,0x00,0x08,0x00,0x08,0x04,0x24, +0xcc,0xff,0x80,0x14,0x68,0x15,0x22,0x26,0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24, +0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24,0x84,0x43,0x00,0x08,0x00,0x08,0x04,0x24, +0xb2,0xff,0x80,0x14,0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,0x80,0x4b,0x44,0x8c, +0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00,0x72,0x43,0x00,0x08, +0xff,0x00,0x04,0x32,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c, +0x68,0x15,0x28,0x26,0x7f,0x4b,0x06,0x91,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x1c,0x0f,0x63,0x24,0x18,0x03,0x42,0x34,0x02,0x00,0x07,0x24,0x18,0x00,0xb2,0xaf, +0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00, +0x39,0x00,0xc7,0x10,0xff,0x00,0x90,0x30,0x03,0x00,0x03,0x24,0x3f,0x00,0xc3,0x10, +0x2e,0x00,0x02,0x2e,0x10,0x00,0x02,0x2e,0x0c,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x0f,0x00,0x04,0x3c,0xff,0xff,0x84,0x34,0x24,0x20,0x44,0x02,0x00,0x15,0x10,0x00, +0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x25,0x20,0x44,0x00,0x13,0x43,0x00,0x08,0x20,0x00,0xbd,0x27,0xf5,0xff,0xc7,0x14, +0x0f,0x00,0x04,0x3c,0x7d,0x4b,0x04,0x91,0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10, +0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x38,0x00,0x86,0x10, +0x68,0x15,0x22,0x26,0x2e,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24, +0x18,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34, +0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,0xed,0x42,0x00,0x0c,0xff,0xff,0x05,0x24, +0x68,0x15,0x22,0x26,0x7d,0x4b,0x44,0x90,0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10, +0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10, +0x03,0x00,0x02,0x24,0xd6,0xff,0x82,0x14,0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26, +0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0xed,0x42,0x00,0x0c,0x21,0x30,0x00,0x00, +0xdf,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0x25,0x00,0x02,0x2e,0xc7,0xff,0x40,0x14, +0x03,0x00,0x03,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xc1,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x68,0x15,0x22,0x26, +0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24, +0xf6,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xcc,0xff,0x80,0x14,0x68,0x15,0x22,0x26, +0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c,0x0f,0x00,0x06,0x24, +0xf6,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xad,0xff,0x80,0x14,0x00,0x00,0x00,0x00, +0x68,0x15,0x22,0x26,0x80,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24,0xed,0x42,0x00,0x0c, +0x21,0x30,0x00,0x00,0xdf,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0xe8,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00,0x14,0x00,0xbf,0xaf,0x29,0x43,0x00,0x0c, +0x21,0x20,0x00,0x00,0x40,0x01,0x44,0x34,0x21,0x18,0x40,0x00,0x1f,0x00,0x02,0x2e, +0x00,0x23,0x04,0x00,0x10,0x00,0x40,0x10,0x10,0x00,0x05,0x2e,0x00,0x01,0x64,0x34, +0x06,0x00,0xa0,0x10,0x00,0x23,0x04,0x00,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x13,0x43,0x00,0x0c, +0xf1,0xff,0x10,0x26,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x13,0x43,0x00,0x0c,0xe2,0xff,0x10,0x26, +0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x27,0x38,0x05,0x00,0x21,0x40,0x82,0x00, +0xff,0xff,0x02,0x24,0x07,0x00,0xa2,0x10,0x25,0x38,0xe6,0x00,0x00,0x00,0x02,0x8d, +0x00,0x00,0x00,0x00,0x24,0x10,0xe2,0x00,0x00,0x00,0x02,0xad,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xad,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xd8,0xff,0xbd,0x27,0xa8,0x11,0x42,0x24, +0x18,0x03,0x63,0x34,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf, +0x24,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac, +0x21,0x88,0xa0,0x00,0x21,0x98,0xc0,0x00,0x21,0xa0,0x80,0x00,0x00,0x60,0x12,0x40, +0x01,0x00,0x41,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x02,0x3c, +0xff,0xff,0x42,0x34,0x0a,0x00,0x22,0x12,0x21,0x28,0xc0,0x00,0x5c,0x43,0x00,0x0c, +0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02,0xe1,0x42,0x00,0x0c,0x21,0x80,0x40,0x00, +0x04,0x10,0x53,0x00,0x27,0x28,0x11,0x00,0x25,0x28,0xa2,0x00,0x24,0x28,0xb0,0x00, +0xc7,0x43,0x00,0x0c,0xff,0x00,0x84,0x32,0x00,0x60,0x92,0x40,0x24,0x00,0xbf,0x8f, +0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x01,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xe0,0xff,0xbd,0x27,0x54,0x12,0x63,0x24,0x18,0x03,0x42,0x34, +0x18,0x00,0xb2,0xaf,0x1c,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf, +0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00,0x00,0x60,0x11,0x40,0x01,0x00,0x21,0x36, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x5c,0x43,0x00,0x0c,0x00,0x00,0x00,0x00, +0x21,0x80,0x40,0x00,0xe1,0x42,0x00,0x0c,0x21,0x20,0x40,0x02,0x24,0x80,0x12,0x02, +0x06,0x80,0x50,0x00,0x00,0x60,0x91,0x40,0x21,0x10,0x00,0x02,0x1c,0x00,0xbf,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xc8,0xff,0xbd,0x27,0x2c,0x00,0xb1,0xaf,0xff,0xff,0x05,0x24, +0x21,0x88,0x80,0x00,0x02,0x00,0x06,0x24,0x10,0x00,0xa4,0x27,0x34,0x00,0xbf,0xaf, +0x30,0x00,0xb2,0xaf,0x58,0x45,0x00,0x0c,0x28,0x00,0xb0,0xaf,0x08,0x00,0x30,0x96, +0x02,0x80,0x02,0x3c,0x21,0x28,0x00,0x00,0x25,0x80,0x02,0x02,0x21,0x20,0x00,0x02, +0x58,0x45,0x00,0x0c,0x10,0x00,0x06,0x24,0x20,0x00,0x02,0x96,0x24,0x00,0x04,0x26, +0x10,0x00,0xa5,0x27,0x03,0xff,0x42,0x30,0xc8,0x00,0x42,0x34,0x20,0x00,0x02,0xa6, +0x60,0x45,0x00,0x0c,0x06,0x00,0x06,0x24,0x25,0xb0,0x03,0x3c,0x50,0x00,0x62,0x34, +0x00,0x00,0x44,0x8c,0x54,0x00,0x65,0x34,0x58,0x00,0x66,0x34,0x18,0x00,0xa4,0xaf, +0x00,0x00,0xa2,0x8c,0x5c,0x00,0x63,0x34,0x2a,0x00,0x04,0x26,0x1c,0x00,0xa2,0xaf, +0x00,0x00,0xc7,0x8c,0x18,0x00,0xa5,0x27,0x06,0x00,0x06,0x24,0x20,0x00,0xa7,0xaf, +0x00,0x00,0x62,0x8c,0x1a,0x00,0x12,0x24,0x60,0x45,0x00,0x0c,0x24,0x00,0xa2,0xaf, +0x30,0x00,0x04,0x26,0x20,0x00,0xa5,0x27,0x60,0x45,0x00,0x0c,0x06,0x00,0x06,0x24, +0x13,0x00,0x03,0x24,0x14,0x00,0x23,0xae,0x0c,0x00,0x32,0xae,0x08,0x00,0x05,0x8e, +0x04,0x00,0x04,0x8e,0xff,0xdf,0x02,0x3c,0x14,0x00,0x06,0x8e,0xff,0xff,0x42,0x34, +0x10,0x00,0x07,0x8e,0xff,0xe0,0x03,0x24,0x24,0x28,0xa2,0x00,0x00,0x40,0x02,0x3c, +0x24,0x20,0x83,0x00,0x25,0x28,0xa2,0x00,0xff,0x81,0x03,0x24,0xfe,0xff,0x02,0x3c, +0x24,0x30,0xc3,0x00,0xff,0xff,0x42,0x34,0x00,0x12,0x84,0x34,0x00,0x80,0x03,0x3c, +0x24,0x20,0x82,0x00,0x25,0x38,0xe3,0x00,0x00,0x26,0xc6,0x34,0x80,0x00,0xa5,0x34, +0x20,0x00,0x02,0x24,0x00,0x00,0x12,0xa6,0x10,0x00,0x07,0xae,0x02,0x00,0x02,0xa2, +0x14,0x00,0x06,0xae,0x04,0x00,0x04,0xae,0x08,0x00,0x05,0xae,0x34,0x00,0xbf,0x8f, +0x30,0x00,0xb2,0x8f,0x2c,0x00,0xb1,0x8f,0x28,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x38,0x00,0xbd,0x27,0x54,0x45,0x00,0x08,0xff,0x00,0xa5,0x30,0x00,0x00,0x85,0xa0, +0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24,0xfc,0xff,0xc0,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x05,0x00,0xc0,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0x85,0xac,0xff,0xff,0xc6,0x24,0xfd,0xff,0xc0,0x14,0x04,0x00,0x84,0x24, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10, +0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24, +0x01,0x00,0xa5,0x24,0x00,0x00,0xe2,0xa0,0xfb,0xff,0x66,0x14,0x01,0x00,0xe7,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10, +0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x8c,0xff,0xff,0x63,0x24, +0x04,0x00,0xa5,0x24,0x00,0x00,0xe2,0xac,0xfb,0xff,0x66,0x14,0x04,0x00,0xe7,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x2b,0x10,0xa4,0x00,0x0d,0x00,0x40,0x14, +0xff,0xff,0x02,0x24,0xff,0xff,0xc6,0x24,0x08,0x00,0xc2,0x10,0x21,0x18,0x80,0x00, +0xff,0xff,0x07,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0xa5,0x24, +0x00,0x00,0x62,0xa0,0xfb,0xff,0xc7,0x14,0x01,0x00,0x63,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x80,0x00,0x21,0x28,0xa6,0x00,0x21,0x18,0x86,0x00,0xff,0xff,0xc6,0x24, +0xfa,0xff,0xc2,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0x07,0x24,0xff,0xff,0xa5,0x24, +0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24,0xff,0xff,0xc6,0x24,0xfb,0xff,0xc7,0x14, +0x00,0x00,0x62,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x0c,0x00,0xc0,0x10, +0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0xa3,0x90,0x01,0x00,0x84,0x24, +0x23,0x10,0x43,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x04,0x00,0x40,0x14, +0x01,0x00,0xa5,0x24,0xff,0xff,0xc6,0x24,0xf6,0xff,0xc0,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0xc0,0x00,0xab,0x45,0x00,0x08,0x21,0x18,0x86,0x00, +0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x45,0x10,0x00,0x00,0x00,0x00, +0x01,0x00,0x84,0x24,0xfa,0xff,0x83,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x80,0x00,0x09,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,0xff,0x00,0xa5,0x30, +0xff,0xff,0x06,0x24,0x00,0x00,0x82,0x90,0xff,0xff,0x63,0x24,0x05,0x00,0x45,0x10, +0x01,0x00,0x84,0x24,0xfb,0xff,0x66,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0xff,0xff,0x82,0x24,0x21,0x38,0x00,0x00, +0x1f,0x00,0xc0,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x02,0x3c,0x40,0xa3,0x4b,0x24, +0x00,0x00,0x87,0x90,0x00,0x00,0xa3,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24, +0x21,0x10,0xeb,0x00,0x16,0x00,0xe0,0x10,0x01,0x00,0xa5,0x24,0x14,0x00,0x60,0x10, +0x21,0x48,0x6b,0x00,0x10,0x00,0xe3,0x10,0x20,0x00,0xe8,0x24,0x00,0x00,0x42,0x90, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x02,0x00,0x40,0x10,0x20,0x00,0x6a,0x24, +0xff,0x00,0x07,0x31,0x00,0x00,0x22,0x91,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30, +0x02,0x00,0x40,0x10,0xff,0x00,0xe7,0x30,0xff,0x00,0x43,0x31,0xff,0x00,0x63,0x30, +0x03,0x00,0xe3,0x14,0x00,0x00,0x00,0x00,0xe5,0xff,0xc0,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x23,0x10,0xe3,0x00,0x21,0x18,0x80,0x00,0x00,0x00,0xa2,0x90, +0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x21,0x38,0x80,0x00,0xff,0xff,0x03,0x24, +0xff,0xff,0xc6,0x24,0x06,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90, +0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0xf9,0xff,0x40,0x14,0x01,0x00,0x84,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,0x00,0x00,0x82,0x80,0xfa,0x45,0x00,0x08, +0x21,0x18,0x80,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00, +0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24, +0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x12,0x00,0xc0,0x10,0x21,0x18,0x80,0x00,0x00,0x00,0x82,0x80, +0x0b,0x46,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80, +0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90, +0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0x05,0x00,0x40,0x10,0x01,0x00,0x84,0x24, +0xff,0xff,0xc6,0x24,0xf9,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xa0, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x00,0x00,0x83,0x90,0x00,0x00,0xa2,0x90, +0x01,0x00,0x84,0x24,0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00, +0x03,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,0xf7,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x0b,0x00,0xc0,0x10, +0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x00,0x00,0x83,0x90,0xff,0xff,0xc6,0x24, +0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14, +0x01,0x00,0xa5,0x24,0xf5,0xff,0x60,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x80,0x00,0x2e,0x05,0x00,0x21,0x10,0x80,0x00, +0x3c,0x46,0x00,0x08,0x03,0x2e,0x05,0x00,0x07,0x00,0x60,0x10,0x01,0x00,0x42,0x24, +0x00,0x00,0x43,0x80,0x00,0x00,0x00,0x00,0xfb,0xff,0x65,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x00,0x00,0x82,0x80,0x48,0x46,0x00,0x08,0x21,0x18,0x80,0x00,0x01,0x00,0x63,0x24, +0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x23,0x10,0x64,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf, +0x21,0x80,0xa0,0x00,0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,0x21,0x88,0x80,0x00, +0x42,0x46,0x00,0x0c,0x00,0x86,0x10,0x00,0x21,0x18,0x51,0x00,0x03,0x86,0x10,0x00, +0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00,0x0a,0x00,0x50,0x10,0x21,0x10,0x60,0x00, +0xff,0xff,0x63,0x24,0x2b,0x10,0x71,0x00,0xf9,0xff,0x40,0x10,0x21,0x10,0x00,0x00, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x21,0x30,0x80,0x00,0x0d,0x00,0xa0,0x10, +0xff,0xff,0xa3,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x24,0xff,0xff,0x63,0x24,0x05,0x00,0x65,0x10, +0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x80,0x00,0x00,0x00,0x00,0xfa,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x23,0x10,0xc4,0x00,0x00,0x00,0x82,0x90, +0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10,0x21,0x40,0x00,0x00,0x00,0x00,0xa9,0x80, +0x00,0x00,0x00,0x00,0x17,0x00,0x20,0x11,0x21,0x30,0xa0,0x00,0x00,0x3e,0x02,0x00, +0x03,0x3e,0x07,0x00,0x21,0x18,0x20,0x01,0x15,0x00,0xe3,0x10,0x00,0x00,0x00,0x00, +0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0x00,0x1e,0x02,0x00, +0x03,0x1e,0x03,0x00,0xf8,0xff,0x60,0x14,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00, +0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x90, +0x00,0x00,0x00,0x00,0xeb,0xff,0x40,0x14,0x01,0x00,0x08,0x25,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x01,0x00,0x00,0xa2,0x90,0x8d,0x46,0x00,0x08,0x00,0x16,0x02,0x00, +0x00,0x00,0xc2,0x90,0x8d,0x46,0x00,0x08,0x00,0x16,0x02,0x00,0x00,0x00,0x87,0x90, +0x00,0x00,0x00,0x00,0x14,0x00,0xe0,0x10,0x21,0x10,0x80,0x00,0x00,0x00,0xa4,0x90, +0x00,0x00,0x00,0x00,0x00,0x1e,0x04,0x00,0x03,0x1e,0x03,0x00,0x09,0x00,0x60,0x10, +0x21,0x30,0xa0,0x00,0x00,0x3e,0x07,0x00,0x03,0x3e,0x07,0x00,0x0b,0x00,0xe3,0x10, +0x01,0x00,0xc6,0x24,0x00,0x00,0xc3,0x80,0x00,0x00,0x00,0x00,0xfb,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0x00,0x00,0x47,0x90,0x00,0x00,0x00,0x00, +0xf0,0xff,0xe0,0x14,0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf, +0x18,0x00,0xbf,0xaf,0x21,0x80,0x80,0x00,0x1d,0x00,0x80,0x10,0x21,0x88,0xa0,0x00, +0x79,0x46,0x00,0x0c,0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82, +0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0x22,0x00,0x40,0x10,0x21,0x18,0x00,0x00, +0x9d,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x10,0x21,0x18,0x40,0x00, +0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00,0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x02,0x80,0x02,0x3c,0x68,0xa4,0x43,0xac,0x21,0x18,0x00,0x02,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x00,0x00,0x60,0xa0,0xce,0x46,0x00,0x08,0x01,0x00,0x63,0x24, +0x02,0x80,0x02,0x3c,0x68,0xa4,0x50,0x8c,0x00,0x00,0x00,0x00,0xf3,0xff,0x00,0x12, +0x21,0x18,0x00,0x00,0x79,0x46,0x00,0x0c,0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02, +0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0xe0,0xff,0x40,0x14, +0x21,0x18,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x02,0x80,0x02,0x3c,0x68,0xa4,0x40,0xac,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0xe0,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf, +0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x90,0x8c,0x21,0x90,0x80,0x00, +0x21,0x88,0xa0,0x00,0x21,0x18,0x00,0x00,0x0f,0x00,0x00,0x12,0x21,0x20,0x00,0x02, +0x79,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82, +0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0x07,0x00,0x40,0x10,0x21,0x18,0x00,0x00, +0x9d,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x18,0x40,0x00,0x09,0x00,0x40,0x14, +0x00,0x00,0x42,0xae,0x21,0x18,0x00,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00,0xf5,0xff,0x40,0x10, +0x01,0x00,0x64,0x24,0x00,0x00,0x60,0xa0,0x07,0x47,0x00,0x08,0x00,0x00,0x44,0xae, +0xd8,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x21,0x88,0x80,0x00,0x21,0x20,0xa0,0x00, +0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf, +0x42,0x46,0x00,0x0c,0x21,0x98,0xa0,0x00,0x21,0x90,0x40,0x00,0x08,0x00,0x40,0x16, +0x21,0x10,0x20,0x02,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27, +0x42,0x46,0x00,0x0c,0x21,0x20,0x20,0x02,0x21,0x80,0x40,0x00,0x2a,0x10,0x52,0x00, +0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x02, +0x21,0x30,0x40,0x02,0x95,0x45,0x00,0x0c,0xff,0xff,0x10,0x26,0x0b,0x00,0x40,0x10, +0x2a,0x18,0x12,0x02,0xf8,0xff,0x60,0x10,0x01,0x00,0x31,0x26,0x20,0x00,0xbf,0x8f, +0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x23,0x47,0x00,0x08, +0x21,0x10,0x20,0x02,0x01,0x80,0x02,0x3c,0x0c,0x1d,0x43,0x24,0x25,0xb0,0x02,0x3c, +0xc0,0xff,0xbd,0x27,0x18,0x03,0x42,0x34,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf, +0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x3c,0x00,0xbf,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x00,0x00,0x43,0xac,0x21,0xf0,0x00,0x00,0x02,0x80,0x15,0x3c,0x02,0x80,0x17,0x3c, +0x02,0x80,0x16,0x3c,0x25,0xb0,0x05,0x3c,0x01,0x80,0x04,0x3c,0x0c,0x1d,0x82,0x24, +0x18,0x03,0xa3,0x34,0x00,0x00,0x62,0xac,0xa0,0x02,0xa8,0x34,0x68,0x15,0xae,0x26, +0x00,0x00,0x04,0x8d,0xe4,0x63,0xc3,0x95,0xff,0x0f,0x02,0x3c,0xff,0xff,0x47,0x34, +0x24,0x98,0x87,0x00,0x01,0x00,0x06,0x3c,0x01,0x00,0x63,0x24,0x2b,0x10,0xd3,0x00, +0x07,0x00,0x40,0x10,0xe4,0x63,0xc3,0xa5,0xa4,0x02,0xa2,0x34,0x00,0x00,0x54,0x8c, +0x00,0xb0,0x03,0x3c,0x25,0x98,0x63,0x02,0x00,0x00,0x74,0xae,0x00,0x00,0x00,0xad, +0xb0,0x02,0xa4,0x34,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x98,0x47,0x00, +0x2b,0x18,0xd3,0x00,0x08,0x00,0x60,0x10,0x25,0xb0,0x02,0x3c,0x00,0xb0,0x02,0x3c, +0x25,0x98,0x62,0x02,0x00,0x00,0x74,0x8e,0xb4,0x02,0xa2,0x34,0x00,0x00,0x54,0xac, +0x00,0x00,0x80,0xac,0x25,0xb0,0x02,0x3c,0xc0,0x02,0x4a,0x34,0x00,0x00,0x53,0x8d, +0xff,0x00,0x05,0x3c,0xff,0xff,0xa2,0x34,0x2b,0x10,0x53,0x00,0x4f,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x25,0xb0,0x11,0x3c,0x00,0x00,0x23,0x8e,0x00,0xff,0x09,0x3c, +0xff,0x00,0x22,0x35,0x00,0xfd,0x08,0x3c,0x01,0x00,0x66,0x24,0x24,0x38,0x62,0x02, +0xac,0x02,0x24,0x36,0xbc,0x02,0x23,0x36,0x05,0x00,0x02,0x35,0x00,0x00,0x86,0xac, +0x2b,0x10,0x47,0x00,0x00,0x00,0x73,0xac,0x00,0x00,0x86,0x8c,0xb7,0x00,0x40,0x14, +0xa6,0x00,0x02,0x35,0x04,0x00,0x02,0x35,0x2b,0x10,0xe2,0x00,0x39,0x00,0x40,0x10, +0x25,0xb0,0x02,0x3c,0x00,0xf8,0x03,0x3c,0x15,0x00,0x62,0x34,0x1d,0x04,0xe2,0x10, +0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x1e,0x01,0x40,0x14,0x00,0xf9,0x04,0x3c, +0x00,0xf1,0x04,0x3c,0x20,0x04,0xe4,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x87,0x00, +0x82,0x01,0x40,0x14,0x10,0x00,0x62,0x34,0x00,0xf0,0x03,0x3c,0x01,0x00,0x62,0x34, +0x5b,0x04,0xe2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x59,0x02,0x40,0x14, +0x03,0x00,0x62,0x34,0x00,0xd0,0x02,0x3c,0x36,0x04,0xe2,0x10,0x2b,0x10,0x47,0x00, +0x71,0x03,0x40,0x14,0x00,0xe0,0x02,0x3c,0x00,0xc0,0x02,0x3c,0x4b,0x05,0xe2,0x10, +0x00,0x00,0x00,0x00,0x00,0xf0,0x02,0x3c,0x24,0x38,0x62,0x02,0x18,0x00,0xe2,0x10, +0x0f,0x00,0x03,0x3c,0x00,0x70,0x09,0x3c,0x24,0x10,0x69,0x02,0x02,0x25,0x13,0x00, +0xff,0xff,0x63,0x34,0x00,0x50,0x08,0x3c,0x24,0x28,0x63,0x02,0x02,0x57,0x02,0x00, +0xff,0x00,0x84,0x30,0xa7,0x01,0xe8,0x10,0xff,0x00,0x66,0x32,0x2b,0x10,0x07,0x01, +0x9b,0x01,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0x20,0x02,0x3c,0xb5,0x03,0xe2,0x10, +0x2b,0x10,0x47,0x00,0xa3,0x02,0x40,0x14,0x00,0x30,0x02,0x3c,0xb2,0x03,0xe0,0x10, +0x80,0x10,0x04,0x00,0x00,0x10,0x02,0x3c,0xaf,0x03,0xe2,0x10,0x80,0x10,0x04,0x00, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x00,0x00,0x40,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x07,0x3c, +0x64,0x03,0xe2,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x28,0x7e,0xe3,0xa2, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x28,0x7e,0xe2,0x92, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x55,0x00,0x40,0x10,0x68,0x15,0xa5,0x26, +0x68,0x15,0xa6,0x26,0x00,0x40,0xc4,0x8c,0xe4,0x42,0xc5,0x8c,0xf0,0xff,0x02,0x24, +0x24,0x20,0x82,0x00,0x00,0x50,0x03,0x3c,0x01,0x00,0x84,0x34,0x24,0x28,0xa3,0x00, +0x00,0x10,0x02,0x3c,0x00,0x40,0xc4,0xac,0x95,0x03,0xa2,0x10,0xd6,0x42,0xc0,0xa0, +0x28,0x7e,0xe2,0x92,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,0x40,0x00,0x40,0x10, +0x68,0x15,0xa2,0x26,0x00,0x40,0x43,0x8c,0x0f,0xff,0x04,0x24,0x24,0x18,0x64,0x00, +0x10,0x00,0x63,0x34,0x00,0x40,0x43,0xac,0x28,0x7e,0xe2,0x92,0x00,0x00,0x00,0x00, +0x04,0x00,0x42,0x30,0x32,0x00,0x40,0x10,0x68,0x15,0xa2,0x26,0x00,0x40,0x43,0x8c, +0xff,0xf0,0x04,0x24,0x24,0x18,0x64,0x00,0x00,0x01,0x63,0x34,0x25,0xb0,0x05,0x3c, +0x00,0x40,0x43,0xac,0x4c,0x00,0xa3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00, +0x03,0x00,0x42,0x30,0x06,0x00,0x40,0x14,0x68,0x15,0xa4,0x26,0x00,0x40,0x83,0x8c, +0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x40,0x83,0xac, +0x60,0x7b,0xc4,0x8e,0x01,0x80,0x06,0x3c,0x0c,0x1e,0xc2,0x24,0x18,0x03,0xa3,0x34, +0x60,0x7b,0xc6,0x26,0x00,0x00,0x62,0xac,0x11,0x00,0x86,0x10,0x02,0x80,0x02,0x3c, +0xbf,0x00,0xb2,0x34,0x68,0x15,0x51,0x24,0x21,0x80,0xc0,0x00,0x21,0xf0,0x00,0x00, +0x00,0x00,0x42,0x92,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x2c,0x09,0x00,0x40,0x10, +0x02,0x80,0x02,0x3c,0xf8,0x65,0x24,0x8e,0x30,0x08,0x00,0x0c,0x00,0x00,0x00,0x00, +0x60,0x7b,0xc2,0x8e,0x00,0x00,0x00,0x00,0xf5,0xff,0x50,0x14,0x00,0x00,0x00,0x00, +0x02,0x80,0x02,0x3c,0x08,0x08,0x44,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00, +0xfe,0x1f,0x00,0x0c,0x21,0x38,0x00,0x00,0x58,0x47,0x00,0x08,0x25,0xb0,0x05,0x3c, +0x00,0x40,0x43,0x8c,0xff,0xf0,0x04,0x24,0x01,0x48,0x00,0x08,0x24,0x18,0x64,0x00, +0x00,0x40,0x43,0x8c,0x0f,0xff,0x04,0x24,0xf7,0x47,0x00,0x08,0x24,0x18,0x64,0x00, +0x00,0x40,0xa4,0x8c,0xe4,0x42,0xa6,0x8c,0xf0,0xff,0x02,0x24,0x00,0x90,0x03,0x3c, +0x24,0x20,0x82,0x00,0x24,0x18,0xc3,0x00,0x00,0x10,0x02,0x3c,0xb0,0xff,0x62,0x14, +0x00,0x40,0xa4,0xac,0x50,0x0c,0xe3,0x34,0xff,0xbf,0x02,0x3c,0x00,0x00,0x64,0x90, +0xff,0xff,0x42,0x34,0x24,0x10,0xc2,0x00,0x00,0x80,0x03,0x3c,0x25,0x10,0x43,0x00, +0xe4,0x42,0xa2,0xac,0xee,0x47,0x00,0x08,0xd7,0x42,0xa4,0xa0,0x55,0x03,0xe2,0x10, +0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x18,0x00,0x40,0x14,0x00,0xfe,0x03,0x3c, +0x20,0x00,0x02,0x35,0x53,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,0x85,0x00,0x40,0x14, +0xa0,0x00,0x02,0x35,0x15,0x00,0x02,0x35,0x9d,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00, +0x17,0x01,0x40,0x14,0x17,0x00,0x02,0x35,0x08,0x00,0x02,0x35,0x16,0x04,0xe2,0x10, +0x64,0x03,0x23,0x36,0x2b,0x10,0x47,0x00,0x24,0x02,0x40,0x14,0x09,0x00,0x02,0x35, +0x07,0x00,0x02,0x35,0x53,0xff,0xe2,0x14,0x00,0x00,0x00,0x00,0xd9,0x58,0x00,0x0c, +0x21,0x20,0x60,0x02,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x18,0x00,0x62,0x34, +0x42,0x03,0xe2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x95,0x00,0x40,0x14, +0x07,0x00,0x22,0x35,0xad,0x00,0x02,0x35,0x8c,0x03,0xe2,0x10,0x00,0x00,0x00,0x00, +0x2b,0x10,0x47,0x00,0xd2,0x00,0x40,0x14,0x10,0x00,0x62,0x34,0xaa,0x00,0x02,0x35, +0x75,0x04,0xe2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x6e,0x01,0x40,0x14, +0xab,0x00,0x02,0x35,0xa7,0x00,0x02,0x35,0x3b,0xff,0xe2,0x14,0x00,0xf0,0x02,0x3c, +0x00,0xff,0x62,0x32,0x02,0xa2,0x02,0x00,0x02,0x1c,0x13,0x00,0x01,0x00,0x02,0x24, +0xbd,0x05,0x82,0x12,0xff,0x00,0x65,0x30,0x02,0x00,0x02,0x24,0xae,0x05,0x82,0x12, +0xc0,0x10,0x05,0x00,0x03,0x00,0x02,0x24,0x9e,0x05,0x82,0x12,0xc0,0x10,0x05,0x00, +0x04,0x00,0x02,0x24,0xc5,0x05,0x82,0x12,0xc0,0x10,0x05,0x00,0x08,0x00,0x02,0x24, +0x29,0x06,0x82,0x12,0xc0,0x10,0x05,0x00,0x09,0x00,0x02,0x24,0x19,0x06,0x82,0x12, +0xc0,0x10,0x05,0x00,0x0a,0x00,0x02,0x24,0x09,0x06,0x82,0x12,0xc0,0x10,0x05,0x00, +0x0b,0x00,0x02,0x24,0xf9,0x05,0x82,0x12,0xc0,0x10,0x05,0x00,0x0c,0x00,0x02,0x24, +0xe9,0x05,0x82,0x12,0xc0,0x10,0x05,0x00,0x0d,0x00,0x02,0x24,0xd9,0x05,0x82,0x12, +0xc0,0x10,0x05,0x00,0x0e,0x00,0x02,0x24,0xc9,0x05,0x82,0x12,0xc0,0x10,0x05,0x00, +0x0f,0x00,0x02,0x24,0xb9,0x05,0x82,0x12,0xc0,0x10,0x05,0x00,0x10,0x00,0x02,0x24, +0x2b,0xff,0x82,0x16,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x45,0x00,0x68,0x15,0xa3,0x26,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00, +0x58,0x51,0x44,0x94,0x54,0x51,0x45,0x94,0x25,0xb0,0x06,0x3c,0x00,0x24,0x04,0x00, +0xc4,0x02,0xc3,0x34,0x21,0x28,0xa4,0x00,0x00,0x00,0x65,0xac,0x64,0x51,0x47,0x8c, +0x60,0x51,0x43,0x8c,0x5c,0x51,0x44,0x94,0xc8,0x02,0xc6,0x34,0x21,0x18,0x67,0x00, +0x00,0x1c,0x03,0x00,0x21,0x20,0x83,0x00,0x00,0x00,0xc4,0xac,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x06,0x00,0x82,0x34,0xfe,0x02,0xe2,0x10,0x00,0x00,0x00,0x00, +0x2b,0x10,0x47,0x00,0x52,0x00,0x40,0x14,0x01,0x00,0x82,0x34,0x3b,0x03,0xe2,0x10, +0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x6a,0x01,0x40,0x14,0x03,0x00,0x82,0x34, +0x17,0x00,0x62,0x34,0xaa,0x04,0xe2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x00, +0x7d,0x04,0x40,0x14,0x00,0x00,0x00,0x00,0x18,0x00,0x62,0x34,0x40,0x05,0xe2,0x10, +0x00,0x00,0x00,0x00,0xe3,0xfe,0xe4,0x14,0x68,0x15,0xa2,0x26,0x64,0x64,0x44,0x90, +0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x0b,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,0xf8,0x00,0x40,0x14, +0xa3,0x00,0x02,0x35,0x22,0x00,0x02,0x35,0x8b,0x03,0xe2,0x10,0x2b,0x10,0xe2,0x00, +0xbb,0x01,0x40,0x14,0x68,0x15,0xa4,0x26,0x28,0x00,0x02,0x35,0xe7,0x04,0xe2,0x10, +0x0f,0x00,0x10,0x3c,0x29,0x00,0x02,0x35,0xcf,0xfe,0xe2,0x14,0x00,0xf0,0x02,0x3c, +0x02,0x1c,0x13,0x00,0x00,0x1f,0x62,0x32,0x68,0x15,0xb0,0x26,0x02,0xa2,0x02,0x00, +0x3f,0x00,0x66,0x30,0xc1,0x42,0x06,0xa2,0xbc,0x42,0x14,0xa2,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x3b,0x15,0x00,0x0c, +0x00,0x00,0x00,0x00,0x21,0xa0,0x40,0x00,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x00,0x00,0x54,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x03,0x40,0x02,0x92,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xce,0x47,0x00,0x08, +0x03,0x40,0x02,0xa2,0xf5,0x02,0xe2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00, +0x4d,0x00,0x40,0x14,0x0e,0x00,0x22,0x35,0x1a,0x00,0x62,0x34,0x43,0x03,0xe2,0x10, +0x2b,0x10,0xe2,0x00,0x38,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0xf0,0x04,0xe9,0x10, +0x00,0x00,0x00,0x00,0x01,0x00,0x22,0x35,0xa6,0xfe,0xe2,0x14,0x00,0x00,0x00,0x00, +0x0e,0x4f,0x00,0x0c,0x01,0x00,0x04,0x24,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x00,0xfb,0x03,0x3c,0x02,0x00,0x62,0x34,0x14,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00, +0xd6,0x00,0x40,0x14,0x01,0x00,0x02,0x35,0x20,0x00,0x82,0x34,0xd2,0x03,0xe2,0x10, +0x2b,0x10,0x47,0x00,0x25,0x02,0x40,0x14,0x07,0x00,0x82,0x34,0x95,0xfe,0xe2,0x14, +0x68,0x15,0xa2,0x26,0x48,0x64,0x44,0x90,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34, +0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xea,0x02,0xe2,0x10, +0x2b,0x10,0x47,0x00,0xef,0x00,0x40,0x14,0x12,0x00,0x62,0x34,0x02,0x00,0x82,0x34, +0xa3,0xfe,0xe2,0x10,0x2b,0x10,0xe2,0x00,0xa4,0x01,0x40,0x14,0x00,0xff,0x62,0x32, +0x03,0x00,0x82,0x34,0xd6,0x04,0xe2,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x82,0x34, +0x81,0xfe,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x02,0x14,0x13,0x00,0xff,0x00,0x54,0x30, +0x00,0xff,0x63,0x32,0x07,0x00,0x82,0x2e,0x95,0xfe,0x40,0x10,0x02,0xf2,0x03,0x00, +0x02,0x80,0x04,0x3c,0x84,0x9f,0x83,0x24,0x80,0x10,0x14,0x00,0x21,0x10,0x43,0x00, +0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00, +0xec,0x02,0xe2,0x10,0x2b,0x10,0x47,0x00,0x12,0x01,0x40,0x14,0x11,0x00,0x62,0x34, +0xae,0x00,0x02,0x35,0x9e,0x04,0xe2,0x10,0x02,0x24,0x13,0x00,0xaf,0x00,0x02,0x35, +0x68,0xfe,0xe2,0x14,0x00,0x00,0x00,0x00,0x76,0x50,0x00,0x0c,0x00,0x00,0x00,0x00, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x0d,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00, +0xfa,0x00,0x40,0x14,0x0f,0x00,0x22,0x35,0x0c,0x00,0x22,0x35,0xf6,0x03,0xe2,0x10, +0x68,0x15,0xa2,0x26,0x0d,0x00,0x22,0x35,0x5b,0xfe,0xe2,0x14,0x00,0xf0,0x02,0x3c, +0x68,0x15,0xa3,0x26,0x01,0x00,0x02,0x24,0xce,0x47,0x00,0x08,0x46,0x64,0x62,0xa4, +0x02,0x03,0xe2,0x10,0x2b,0x10,0x47,0x00,0x15,0x01,0x40,0x14,0x00,0xa0,0x02,0x3c, +0x00,0x60,0x02,0x3c,0x04,0x00,0xe2,0x10,0x80,0x10,0x04,0x00,0x69,0xfe,0xe9,0x14, +0x25,0xb0,0x02,0x3c,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x68,0x15,0xa3,0x26, +0x21,0x10,0x43,0x00,0x21,0x10,0x4a,0x00,0xce,0x47,0x00,0x08,0xc1,0x43,0x46,0xa0, +0x07,0x03,0xe2,0x10,0x2b,0x10,0xe2,0x00,0x37,0x01,0x40,0x14,0x00,0xff,0x62,0x32, +0x18,0x00,0x02,0x35,0xe3,0x03,0xe2,0x10,0x19,0x00,0x02,0x35,0x3e,0xfe,0xe2,0x14, +0x00,0xf0,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xc0,0x02,0x62,0x34,0x00,0x00,0x40,0xac, +0x94,0x0e,0x64,0x34,0x9c,0x0e,0x62,0x34,0xa4,0x0e,0x65,0x34,0xac,0x0e,0x66,0x34, +0x00,0x00,0x89,0x8c,0x68,0x15,0xaf,0x26,0x00,0x00,0x4b,0x8c,0x00,0x00,0xac,0x8c, +0x00,0x00,0xc4,0x8c,0xb4,0x0e,0x62,0x34,0x0c,0x40,0xe5,0x8d,0x10,0x40,0xe6,0x8d, +0x00,0x00,0x4a,0x8c,0xff,0x03,0x07,0x3c,0x00,0xfc,0x08,0x24,0xbc,0x0e,0x62,0x34, +0x24,0x48,0x27,0x01,0x24,0x20,0x87,0x00,0x00,0x00,0x4d,0x8c,0x24,0x30,0xc8,0x00, +0x02,0x4c,0x09,0x00,0x24,0x28,0xa8,0x00,0x02,0x24,0x04,0x00,0xcc,0x0e,0x68,0x34, +0xf0,0xff,0x02,0x3c,0xc4,0x0e,0x63,0x34,0xff,0x03,0x42,0x34,0x25,0x28,0xa9,0x00, +0x25,0x30,0xc4,0x00,0x00,0x00,0x69,0x8c,0x08,0x40,0xe4,0x8d,0x00,0x00,0x0e,0x8d, +0x24,0x58,0x67,0x01,0x24,0x50,0x47,0x01,0x24,0x30,0xc2,0x00,0x24,0x28,0xa2,0x00, +0x82,0x59,0x0b,0x00,0x82,0x51,0x0a,0x00,0x0f,0xc0,0x03,0x3c,0xff,0x9f,0x02,0x3c, +0xff,0xff,0x63,0x34,0xff,0xff,0x42,0x34,0x25,0x28,0xab,0x00,0x25,0x30,0xca,0x00, +0x24,0x60,0x87,0x01,0x24,0x68,0xa7,0x01,0xff,0x00,0x08,0x3c,0x24,0x20,0x82,0x00, +0x24,0x30,0xc3,0x00,0x24,0x28,0xa3,0x00,0x24,0x70,0xc7,0x01,0x00,0x61,0x0c,0x00, +0x00,0x69,0x0d,0x00,0x24,0x48,0x27,0x01,0x00,0xff,0x03,0x35,0x00,0x20,0x02,0x3c, +0x25,0x20,0x82,0x00,0x25,0x28,0xac,0x00,0x25,0x30,0xcd,0x00,0x02,0x4c,0x09,0x00, +0x02,0x74,0x0e,0x00,0x24,0x18,0x63,0x02,0x08,0x40,0xe4,0xad,0x0c,0x40,0xe5,0xad, +0x10,0x40,0xe6,0xad,0x14,0x40,0xe9,0xa5,0x4d,0x04,0x60,0x10,0x16,0x40,0xee,0xa5, +0x24,0x10,0x68,0x02,0x02,0x14,0x02,0x00,0x02,0x1a,0x13,0x00,0xc7,0x42,0xe2,0xa1, +0xc3,0x42,0xe3,0xa1,0x68,0x15,0xa2,0x26,0xc3,0x42,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x61,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0xfd,0x55,0x00,0x0c,0x10,0x00,0xa4,0x27,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x92,0x02,0xe2,0x10,0x2b,0x10,0x47,0x00,0xda,0x00,0x40,0x14,0xa4,0x00,0x02,0x35, +0xa1,0x00,0x02,0x35,0x26,0x03,0xe2,0x10,0x02,0x24,0x13,0x00,0xa2,0x00,0x02,0x35, +0xd8,0xfd,0xe2,0x14,0xc4,0x02,0x22,0x36,0x00,0xff,0xa3,0x34,0x24,0x18,0x63,0x02, +0x00,0x00,0x45,0x8c,0x02,0xf2,0x03,0x00,0xb2,0x51,0x00,0x0c,0x21,0x20,0xc0,0x03, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x11,0x04,0xe2,0x10,0x00,0x00,0x00,0x00, +0xac,0x00,0x02,0x35,0xcb,0xfd,0xe2,0x14,0x00,0x00,0x00,0x00,0x8b,0x4f,0x00,0x0c, +0x21,0x20,0x60,0x02,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x46,0x03,0xe2,0x10, +0x00,0x00,0x00,0x00,0x2b,0x10,0x47,0x00,0x3e,0x01,0x40,0x14,0x02,0x00,0x02,0x35, +0x03,0x00,0x62,0x34,0xfb,0x03,0xe2,0x10,0x68,0x15,0xa3,0x26,0xbe,0xfd,0xe8,0x14, +0x00,0xf0,0x02,0x3c,0xcc,0x58,0x00,0x0c,0x21,0x20,0x60,0x02,0x00,0xff,0x63,0x32, +0x00,0xcc,0x02,0x34,0xd3,0xfd,0x62,0x14,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26, +0xe4,0x42,0x43,0x8c,0x00,0x10,0x04,0x3c,0x25,0x18,0x64,0x00,0xce,0x47,0x00,0x08, +0xe4,0x42,0x43,0xac,0x04,0x03,0xe2,0x10,0x2b,0x10,0xe2,0x00,0x04,0x01,0x40,0x14, +0x24,0x10,0x65,0x02,0x08,0x00,0x62,0x34,0x7b,0x03,0xe2,0x10,0x20,0x00,0x62,0x34, +0xa8,0xfd,0xe2,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x07,0x52,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x0c,0x03,0xe2,0x10,0x2b,0x10,0xe2,0x00,0x9e,0x00,0x40,0x14, +0x00,0xff,0x62,0x32,0x13,0x00,0x62,0x34,0x75,0x03,0xe2,0x10,0x14,0x00,0x62,0x34, +0x94,0xfd,0xe2,0x14,0x00,0x00,0x00,0x00,0x3a,0x0c,0x00,0x0c,0xfd,0x00,0x04,0x24, +0x25,0xb0,0x03,0x3c,0x10,0x10,0x02,0x3c,0xa0,0x00,0x64,0x34,0x10,0x10,0x42,0x34, +0x00,0x00,0x82,0xac,0x00,0xc0,0x02,0x3c,0xa8,0x00,0x65,0x34,0x00,0xa1,0x42,0x34, +0xa4,0x00,0x63,0x34,0x00,0x00,0x60,0xac,0x00,0x00,0xa2,0xac,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0xd2,0x02,0xe2,0x10,0xc4,0x02,0x23,0x36,0x2b,0x10,0xe2,0x00, +0x09,0x01,0x40,0x14,0x68,0x15,0xa2,0x26,0x04,0x00,0x82,0x34,0xaa,0x03,0xe2,0x10, +0x68,0x15,0xa2,0x26,0x05,0x00,0x82,0x34,0x7a,0xfd,0xe2,0x14,0x68,0x15,0xa2,0x26, +0x50,0x64,0x44,0x90,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xa2,0x26,0x76,0x4b,0x44,0x90, +0xc4,0x02,0x23,0x36,0x00,0x00,0x64,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xf2,0x02,0xe2,0x10, +0x10,0x00,0x22,0x35,0x64,0xfd,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x00,0xff,0x63,0x32, +0x00,0xff,0x02,0x34,0xbe,0x03,0x62,0x10,0x68,0x15,0xa2,0x26,0xce,0x47,0x00,0x08, +0xec,0x65,0x40,0xac,0x5c,0x03,0xe2,0x10,0x00,0x00,0x00,0x00,0x12,0x00,0x62,0x34, +0x58,0xfd,0xe2,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34, +0x24,0x10,0x62,0x02,0x02,0xf2,0x02,0x00,0x68,0x15,0xa3,0x26,0x77,0x4b,0x7e,0xa0, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x0f,0x01,0xe2,0x10,0x00,0x40,0x02,0x3c,0x61,0xfd,0xe2,0x14, +0x25,0xb0,0x02,0x3c,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x68,0x15,0xa3,0x26, +0x21,0x10,0x43,0x00,0x21,0x10,0x4a,0x00,0xce,0x47,0x00,0x08,0xc1,0x43,0x46,0xa0, +0xc4,0x02,0xe2,0x10,0x2b,0x10,0x47,0x00,0xd3,0x00,0x40,0x14,0x00,0xb0,0x02,0x3c, +0x00,0x90,0x02,0x3c,0x53,0xfd,0xe2,0x14,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26, +0x21,0x10,0x82,0x00,0xce,0x47,0x00,0x08,0x73,0x44,0x46,0xa0,0xe0,0x02,0xe2,0x10, +0x25,0xb0,0x02,0x3c,0x14,0x00,0x02,0x35,0x2f,0xfd,0xe2,0x14,0x00,0xf0,0x02,0x3c, +0xff,0x00,0x04,0x3c,0x00,0xff,0x82,0x34,0x24,0x10,0x62,0x02,0x45,0xfd,0x40,0x10, +0x25,0xb0,0x02,0x3c,0x68,0x15,0xa3,0x26,0x04,0x43,0x66,0x90,0x24,0x20,0x64,0x02, +0x00,0xff,0x65,0x32,0x02,0x24,0x04,0x00,0x02,0x2a,0x05,0x00,0x00,0x01,0xc6,0x34, +0xfb,0xff,0x87,0x24,0xfb,0xff,0xa2,0x24,0x1f,0x43,0x62,0xa0,0x04,0x43,0x66,0xac, +0x1d,0x43,0x67,0xa0,0x1c,0x43,0x64,0xa0,0xce,0x47,0x00,0x08,0x1e,0x43,0x65,0xa0, +0x08,0x40,0x83,0x8c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x02,0x34,0x13,0x00,0x00,0x1f,0x65,0x32,0x00,0x20,0x02,0x3c,0x25,0x18,0x62,0x00, +0x02,0xa2,0x05,0x00,0x3f,0x00,0xc6,0x30,0xc1,0x42,0x86,0xa0,0x08,0x40,0x83,0xac, +0xce,0x47,0x00,0x08,0xbc,0x42,0x94,0xa0,0x02,0x22,0x02,0x00,0x03,0x00,0x83,0x2c, +0x24,0xfd,0x60,0x10,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26,0xce,0x47,0x00,0x08, +0x02,0x40,0x44,0xa0,0xae,0x02,0xe2,0x10,0xa5,0x00,0x02,0x35,0x01,0xfd,0xe2,0x14, +0x00,0x00,0x00,0x00,0x02,0x24,0x13,0x00,0xec,0x51,0x00,0x0c,0xff,0x00,0x84,0x30, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x02,0x22,0x02,0x00,0x21,0xa0,0x00,0x00, +0xbf,0x4a,0x00,0x08,0x27,0xb0,0x07,0x3c,0x00,0x01,0x82,0x2e,0x0b,0x00,0x40,0x10, +0x08,0x00,0xe7,0x24,0x00,0x00,0xe2,0x94,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x30, +0xff,0x00,0xc3,0x33,0xf8,0xff,0x64,0x14,0x01,0x00,0x94,0x26,0xff,0xff,0x94,0x26, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x54,0xa4,0xff,0x00,0x82,0x2e, +0x03,0xfd,0x40,0x14,0x25,0xb0,0x02,0x3c,0x12,0x87,0x03,0x3c,0xc4,0x02,0x42,0x34, +0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x02,0xf2,0x02,0x00, +0x80,0x00,0xc0,0x13,0x00,0x00,0x00,0x00,0x94,0x00,0x22,0x36,0x00,0x00,0x43,0x94, +0xb0,0x03,0x25,0x36,0x68,0x15,0xa6,0x26,0xff,0xff,0x74,0x30,0x1b,0x00,0x9e,0x02, +0x02,0x00,0xc0,0x17,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x00,0x00,0xb4,0xac, +0xe6,0x4a,0xc7,0x94,0xff,0xff,0xc3,0x27,0x01,0x00,0x02,0x24,0xe3,0x4a,0xc2,0xa0, +0x80,0xff,0x02,0x24,0x6a,0x03,0x2a,0x36,0x4f,0x00,0x2b,0x36,0x9e,0x00,0x2c,0x36, +0x44,0x00,0x28,0x36,0xd8,0x00,0x2d,0x36,0x12,0xa0,0x00,0x00,0x80,0x22,0x14,0x00, +0x00,0xf8,0x84,0x24,0x18,0x00,0xd4,0x03,0xff,0xff,0x7e,0x30,0x00,0x19,0x1e,0x00, +0x25,0x18,0x62,0x00,0x26,0xb0,0x02,0x3c,0x7c,0x00,0x42,0x34,0x12,0x48,0x00,0x00, +0x23,0x38,0xe9,0x00,0x00,0x00,0x47,0xa5,0x00,0x00,0xbe,0xac,0x00,0x00,0x63,0xa1, +0x00,0x00,0xb4,0xac,0x00,0x00,0x94,0xa5,0x42,0xa1,0x04,0x00,0x00,0x00,0xb4,0xac, +0x00,0x00,0x54,0xa4,0x00,0x00,0x03,0x95,0xff,0xfd,0x02,0x24,0xe8,0x4a,0xc7,0xa4, +0x24,0x18,0x62,0x00,0x00,0x00,0x03,0xa5,0x00,0x00,0x02,0x95,0x00,0x00,0x00,0x00, +0x00,0x02,0x42,0x34,0x00,0x00,0x02,0xa5,0x00,0x00,0xa3,0x91,0x00,0x00,0x00,0x00, +0x40,0x00,0x63,0x34,0x00,0x00,0xa3,0xa1,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0xcc,0x02,0x23,0x36,0x00,0xff,0x64,0x32,0x02,0xf4,0x02,0x00,0x00,0x00,0x73,0xac, +0x04,0x00,0xc0,0x13,0x02,0x9a,0x04,0x00,0x01,0x00,0x02,0x24,0x02,0x00,0xc2,0x13, +0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x2a,0x42,0x00,0x0c,0x0f,0x00,0x10,0x3c, +0xff,0xff,0x05,0x36,0x95,0x44,0x00,0x0c,0x21,0x20,0x60,0x02,0xff,0xff,0x10,0x36, +0x24,0xa0,0x50,0x00,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x54,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xd6,0xfe,0xe2,0x10,0x00,0x00,0x00,0x00, +0x90,0xfc,0xe3,0x14,0x00,0xff,0xa2,0x34,0x24,0x10,0x62,0x02,0x02,0x9a,0x02,0x00, +0xcc,0x02,0x23,0x36,0x00,0x00,0x73,0xac,0x21,0x20,0x71,0x02,0x00,0x00,0x94,0x8c, +0xc4,0x02,0x22,0x36,0x00,0x00,0x54,0xac,0x00,0x00,0x94,0x8c,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x7c,0x02,0xe2,0x10,0x25,0xb0,0x02,0x3c,0x03,0x00,0x02,0x35, +0x81,0xfc,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x68,0x15,0xa4,0x26,0xe4,0x42,0x83,0x8c, +0xff,0xef,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0xe4,0x42,0x83,0xac, +0xce,0x47,0x00,0x08,0xe6,0x42,0x80,0xa0,0x5c,0x64,0x44,0x90,0xc4,0x02,0x23,0x36, +0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x28,0x02,0xe3,0x10, +0x01,0x00,0x62,0x34,0x70,0xfc,0xe2,0x14,0x00,0xf0,0x02,0x3c,0x68,0x15,0xa2,0x26, +0xf8,0x63,0x43,0x8c,0xfd,0xff,0x04,0x24,0x24,0x18,0x64,0x00,0x01,0x00,0x63,0x34, +0xce,0x47,0x00,0x08,0xf8,0x63,0x43,0xac,0x82,0xfc,0xe2,0x14,0x25,0xb0,0x02,0x3c, +0x80,0x10,0x04,0x00,0x68,0x15,0xa3,0x26,0x21,0x10,0x43,0x00,0xce,0x47,0x00,0x08, +0x60,0x45,0x45,0xac,0x25,0xb0,0x05,0x3c,0x4f,0x00,0xa2,0x34,0x9e,0x00,0xa3,0x34, +0x00,0x00,0x40,0xa0,0x00,0x00,0x60,0xa4,0x94,0x00,0xa2,0x34,0x00,0x00,0x43,0x94, +0x9a,0x00,0xa4,0x34,0x98,0x00,0xa6,0x34,0xff,0xff,0x74,0x30,0x80,0x12,0x14,0x00, +0x00,0xf8,0x42,0x24,0x42,0xa1,0x02,0x00,0x00,0x14,0x02,0x24,0x00,0x00,0x82,0xa4, +0x26,0xb0,0x02,0x3c,0xb0,0x03,0xa7,0x34,0xa0,0x80,0x03,0x24,0x7c,0x00,0x42,0x34, +0x00,0x00,0xc3,0xa4,0x44,0x00,0xa4,0x34,0x00,0x00,0xf4,0xac,0x00,0x00,0x54,0xa4, +0x00,0x00,0x83,0x94,0xff,0xfd,0x02,0x24,0xd8,0x00,0xa5,0x34,0x24,0x18,0x62,0x00, +0x00,0x00,0x83,0xa4,0x00,0x00,0x82,0x94,0x68,0x15,0xa6,0x26,0x00,0x02,0x42,0x34, +0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,0xbf,0xff,0x02,0x24,0xe8,0x4a,0xc0,0xa4, +0x24,0x18,0x62,0x00,0xe3,0x4a,0xc0,0xa0,0x00,0x00,0xa3,0xa0,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x68,0x15,0xa3,0x26, +0x21,0x10,0x43,0x00,0x21,0x10,0x4a,0x00,0xce,0x47,0x00,0x08,0x34,0x43,0x46,0xa0, +0xd7,0x42,0xc3,0x90,0x50,0x0c,0xe2,0x34,0x21,0x20,0x00,0x00,0x00,0x00,0x43,0xa0, +0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x82,0x24,0x68,0x15,0xa2,0x26,0xd7,0x42,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x58,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x68,0x15,0xa5,0x26,0xe4,0x42,0xa3,0x8c,0x00,0x40,0x04,0x3c,0xff,0x7f,0x02,0x3c, +0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0xee,0x47,0x00,0x08, +0xe4,0x42,0xa3,0xac,0xee,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x08,0x40,0xc3,0x8d,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0xce,0x47,0x00,0x08,0x08,0x40,0xc3,0xad,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x77,0x4b,0xc4,0x91, +0xc4,0x02,0x23,0x36,0xcc,0x02,0x22,0x36,0x00,0x00,0x53,0xac,0x00,0x00,0x64,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x6e,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x4c,0x64,0xc3,0x91,0xc4,0x02,0x22,0x36,0x00,0x00,0x43,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0xa5,0x34,0x24,0x28,0x65,0x02, +0x02,0x2a,0x05,0x00,0x40,0x11,0x05,0x00,0x26,0xb0,0x04,0x3c,0x94,0x00,0x23,0x36, +0x00,0x00,0x65,0xa4,0xc0,0xff,0x54,0x24,0x7c,0x00,0x8b,0x34,0x04,0x00,0x07,0x24, +0x7a,0x00,0x84,0x34,0x00,0x04,0x02,0x24,0xa0,0x80,0x03,0x24,0x9a,0x00,0x26,0x36, +0x98,0x00,0x28,0x36,0x96,0x00,0x29,0x36,0xb0,0x03,0x2a,0x36,0x00,0x00,0xc2,0xa4, +0x00,0x00,0x03,0xa5,0x00,0x00,0x27,0xa5,0x00,0x00,0x87,0xa0,0x00,0x00,0x54,0xad, +0x44,0x00,0x24,0x36,0x00,0x00,0x74,0xa5,0x00,0x00,0x83,0x94,0xff,0xfd,0x02,0x24, +0xe6,0x4a,0xc5,0xa5,0x24,0x18,0x62,0x00,0x00,0x00,0x83,0xa4,0x00,0x00,0x82,0x94, +0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x34,0x00,0x00,0x82,0xa4,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x00,0x0f,0x62,0x32,0x02,0x22,0x02,0x00,0x01,0x00,0x03,0x24, +0xda,0x02,0x83,0x10,0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x24,0xdb,0x02,0x82,0x10, +0x00,0x00,0x00,0x00,0x03,0x00,0x02,0x24,0xf7,0x00,0x82,0x10,0x00,0x00,0x00,0x00, +0xa6,0x50,0x00,0x0c,0x21,0x20,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x04,0x43,0xc2,0x91,0xce,0x47,0x00,0x08,0x04,0x43,0xc2,0xad,0x0e,0x4f,0x00,0x0c, +0x07,0x00,0x04,0x24,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x9a,0x4f,0x00,0x0c, +0x21,0x20,0x60,0x02,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x60,0x64,0xc3,0x91, +0xc4,0x02,0x22,0x36,0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x00,0xff,0xa2,0x34,0x24,0x10,0x62,0x02,0x02,0x9a,0x02,0x00,0xcc,0x02,0x23,0x36, +0x00,0x00,0x73,0xac,0xc4,0x02,0x24,0x36,0x00,0x00,0x94,0x8c,0x21,0x10,0x71,0x02, +0x00,0x00,0x54,0xac,0x00,0x00,0x54,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x94,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0xa0,0x00,0x00,0x16,0x4c,0x00,0x08, +0x27,0xb0,0x04,0x3c,0x00,0x01,0x82,0x2e,0x0c,0x00,0x40,0x10,0x08,0x00,0x84,0x24, +0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0xff,0x7e,0x30,0xff,0x00,0xc2,0x33, +0xf0,0x00,0x42,0x28,0xf7,0xff,0x40,0x14,0x01,0x00,0x94,0x26,0xff,0xff,0x94,0x26, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x5e,0xa4,0xff,0x00,0x82,0x2e, +0xab,0xfb,0x40,0x14,0x25,0xb0,0x02,0x3c,0x12,0x87,0x03,0x3c,0xc4,0x02,0x42,0x34, +0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xf8,0x63,0xc2,0x8d, +0xfe,0xff,0x03,0x24,0x02,0x00,0x42,0x34,0x24,0x10,0x43,0x00,0xce,0x47,0x00,0x08, +0xf8,0x63,0xc2,0xad,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x68,0x15,0xae,0x26,0x76,0x4b,0xc2,0x91,0x00,0x00,0x00,0x00, +0x97,0xfb,0x40,0x14,0x00,0xff,0xa2,0x34,0x24,0x10,0x62,0x02,0x02,0xf2,0x02,0x00, +0xcc,0x02,0x22,0x36,0x00,0x00,0x5e,0xac,0xc8,0x02,0x25,0x36,0xff,0x00,0xc3,0x33, +0x01,0x00,0x02,0x24,0x00,0x00,0xa3,0xac,0x21,0x20,0xc0,0x03,0x76,0x4b,0xc2,0xa1, +0xe3,0x18,0x00,0x0c,0x77,0x4b,0xde,0xa1,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0xa2,0x34, +0x24,0x10,0x62,0x02,0x25,0xb0,0x05,0x3c,0x02,0xf2,0x02,0x00,0xcc,0x02,0xa3,0x34, +0x01,0x00,0x02,0x24,0x00,0x00,0x7e,0xac,0x01,0x01,0xc2,0x13,0x68,0x15,0xa2,0x26, +0x02,0x00,0xc2,0x2b,0x28,0x01,0x40,0x14,0x03,0x00,0x02,0x24,0x20,0x01,0xc2,0x13, +0xc4,0x02,0xa3,0x34,0x68,0x15,0xa2,0x26,0x70,0x4b,0x44,0x94,0x25,0xb0,0x03,0x3c, +0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x68,0x15,0xa2,0x26,0xce,0x47,0x00,0x08,0x46,0x64,0x40,0xa4,0x68,0x15,0xa2,0x26, +0x21,0x10,0x82,0x00,0xce,0x47,0x00,0x08,0x56,0x44,0x46,0xa0,0x68,0x15,0xa2,0x26, +0xce,0x47,0x00,0x08,0xec,0x65,0x40,0xac,0x00,0x1f,0x63,0x32,0x02,0x14,0x13,0x00, +0x02,0xa2,0x03,0x00,0x3f,0x00,0x46,0x30,0x68,0x15,0xa3,0x26,0xc1,0x42,0x66,0xa0, +0xce,0x47,0x00,0x08,0xbc,0x42,0x74,0xa0,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00, +0xfd,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x68,0x15,0xae,0x26,0x08,0x40,0xc7,0x8d,0x00,0x00,0x40,0xad,0x42,0x17,0x07,0x00, +0x03,0x00,0x42,0x30,0x5c,0x00,0x40,0x14,0x68,0x15,0xa2,0x26,0x03,0x0d,0x22,0x36, +0x00,0x00,0x45,0x90,0x10,0x40,0xc6,0x8d,0xff,0x9f,0x03,0x3c,0xff,0xff,0x63,0x34, +0xff,0x3f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0xe3,0x00,0x00,0x20,0x04,0x3c, +0x24,0x60,0xc2,0x00,0x25,0x18,0x64,0x00,0x00,0x40,0x02,0x3c,0x70,0x00,0xa5,0x30, +0x25,0x60,0x82,0x01,0x93,0x01,0xa0,0x10,0x08,0x40,0xc3,0xad,0x94,0x0e,0x22,0x36, +0x9c,0x0e,0x23,0x36,0xa4,0x0e,0x24,0x36,0xac,0x0e,0x27,0x36,0x00,0x00,0x45,0x8c, +0x00,0x00,0x69,0x8c,0x00,0x00,0x8b,0x8c,0x00,0x00,0xe6,0x8c,0x0c,0x40,0xc3,0x8d, +0xb4,0x0e,0x22,0x36,0x00,0x00,0x4a,0x8c,0xff,0x03,0x07,0x3c,0x00,0xfc,0x08,0x24, +0xbc,0x0e,0x22,0x36,0x24,0x28,0xa7,0x00,0x24,0x30,0xc7,0x00,0x24,0x20,0x88,0x01, +0x02,0x2c,0x05,0x00,0x00,0x00,0x4c,0x8c,0x24,0x18,0x68,0x00,0x02,0x34,0x06,0x00, +0xcc,0x0e,0x2d,0x36,0xc4,0x0e,0x28,0x36,0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34, +0x25,0x18,0x65,0x00,0x25,0x20,0x86,0x00,0x00,0x00,0x05,0x8d,0x24,0x48,0x27,0x01, +0x00,0x00,0xa6,0x8d,0x24,0x50,0x47,0x01,0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00, +0x82,0x49,0x09,0x00,0x82,0x51,0x0a,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34, +0x25,0x18,0x69,0x00,0x25,0x20,0x8a,0x00,0x24,0x58,0x67,0x01,0x24,0x60,0x87,0x01, +0x24,0x20,0x82,0x00,0x24,0x30,0xc7,0x00,0x00,0x59,0x0b,0x00,0x24,0x18,0x62,0x00, +0x00,0x61,0x0c,0x00,0x24,0x28,0xa7,0x00,0x25,0x18,0x6b,0x00,0x25,0x20,0x8c,0x00, +0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,0x16,0x40,0xc6,0xa5,0x0c,0x40,0xc3,0xad, +0x10,0x40,0xc4,0xad,0x14,0x40,0xc5,0xa5,0x68,0x15,0xa3,0x26,0x0c,0x40,0x62,0x8c, +0x00,0x00,0x00,0x00,0x53,0x01,0x40,0x04,0x00,0x00,0x00,0x00,0x00,0xff,0x62,0x32, +0x29,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0xc3,0x42,0x62,0xa0, +0xfd,0x55,0x00,0x0c,0x10,0x00,0xa4,0x27,0x38,0x55,0x00,0x0c,0x00,0x00,0x00,0x00, +0x68,0x15,0xa2,0x26,0x0c,0x40,0x43,0x8c,0x00,0x80,0x04,0x3c,0x25,0x18,0x64,0x00, +0x0c,0x40,0x43,0xac,0x68,0x15,0xa2,0x26,0xc3,0x42,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x61,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xa6,0x50,0x00,0x0c,0x03,0x00,0x04,0x24, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xd2,0x59,0x00,0x0c,0x00,0x00,0x00,0x00, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0xa2,0x34,0x24,0x10,0x62,0x02, +0x02,0xf2,0x02,0x00,0x07,0x00,0x03,0x24,0x25,0x01,0xc3,0x13,0x02,0x80,0x04,0x3c, +0x08,0x00,0xc2,0x2b,0x0a,0x01,0x40,0x10,0x20,0x00,0x02,0x24,0xd8,0xfa,0xc0,0x17, +0x02,0x80,0x02,0x3c,0xe8,0x7d,0x43,0x94,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x02,0x24,0x13,0x00, +0x0f,0x10,0x00,0x0c,0xff,0x00,0x84,0x30,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x68,0x15,0xa2,0x26,0x58,0x64,0x44,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x24,0x10,0x65,0x02,0xcc,0x02,0x23,0x36, +0x00,0xff,0x64,0x32,0x02,0xf4,0x02,0x00,0x00,0x00,0x73,0xac,0x04,0x00,0xc0,0x13, +0x02,0x9a,0x04,0x00,0x01,0x00,0x02,0x24,0x02,0x00,0xc2,0x13,0x01,0x00,0x04,0x24, +0x21,0x20,0x00,0x00,0x25,0xb0,0x10,0x3c,0x2a,0x42,0x00,0x0c,0xc4,0x02,0x12,0x36, +0x00,0x00,0x54,0x8e,0x0f,0x00,0x11,0x3c,0x21,0x20,0x60,0x02,0x21,0x30,0x80,0x02, +0x6a,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x20,0x60,0x02,0x95,0x44,0x00,0x0c, +0xff,0xff,0x25,0x36,0xc8,0x02,0x10,0x36,0x00,0x00,0x42,0xae,0x00,0x00,0x02,0xae, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x28,0xb0,0x02,0x3c,0x00,0x00,0x43,0x90, +0xff,0x00,0x02,0x24,0xff,0x00,0x73,0x30,0xa5,0xfa,0x62,0x12,0xff,0x00,0x04,0x24, +0x28,0xb0,0x05,0x3c,0xc0,0x10,0x13,0x00,0x21,0x10,0x45,0x00,0x00,0x00,0x43,0x90, +0x00,0x00,0x00,0x00,0xff,0x00,0x73,0x30,0xfa,0xff,0x64,0x16,0x25,0xb0,0x02,0x3c, +0xd0,0x47,0x00,0x08,0xc0,0x02,0x42,0x34,0x64,0x03,0x23,0x36,0x00,0x00,0x62,0x90, +0x00,0x00,0x00,0x00,0xfa,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x80,0x10,0x04,0x00,0x68,0x15,0xa3,0x26,0x21,0x10,0x43,0x00, +0xce,0x47,0x00,0x08,0xec,0x44,0x45,0xac,0x25,0xb0,0x03,0x3c,0xff,0x00,0x02,0x24, +0x56,0x01,0x63,0x34,0x01,0x00,0x04,0x24,0x02,0x80,0x06,0x3c,0x00,0x00,0x62,0xa4, +0xce,0x47,0x00,0x08,0x18,0x7e,0xc4,0xa0,0xa8,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x44,0x64,0x44,0x94,0x25,0xb0,0x03,0x3c, +0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xa4,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x6e,0x4b,0x44,0x94,0xc4,0x02,0xa3,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x68,0x15,0xa4,0x26,0x08,0x40,0x83,0x8c,0xff,0x9f,0x02,0x3c, +0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0xce,0x47,0x00,0x08,0x08,0x40,0x83,0xac, +0x68,0x15,0xa3,0x26,0xff,0xff,0x02,0x34,0xce,0x47,0x00,0x08,0xec,0x65,0x62,0xac, +0x64,0x03,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x74,0x30, +0x02,0x00,0x84,0x36,0x00,0x00,0x44,0xa0,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x68,0x15,0xa5,0x26,0xf8,0x63,0xa2,0x8c,0xfd,0xff,0x03,0x24,0xfe,0xff,0x04,0x24, +0x24,0x10,0x43,0x00,0x24,0x10,0x44,0x00,0xce,0x47,0x00,0x08,0xf8,0x63,0xa2,0xac, +0x34,0x0d,0x00,0x0c,0x00,0x00,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x68,0x15,0xa2,0x26,0x72,0x4b,0x44,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xda,0xfe,0xc0,0x17,0xc4,0x02,0xa3,0x34, +0x68,0x15,0xa2,0x26,0x6c,0x4b,0x44,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0x64,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0x63,0x32,0x25,0xb0,0x02,0x3c, +0x02,0x9a,0x03,0x00,0xcc,0x02,0x42,0x34,0x00,0x00,0x53,0xac,0xbf,0x00,0x60,0x12, +0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x24,0x59,0x01,0x62,0x12,0x00,0x00,0x00,0x00, +0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x28,0xb0,0x14,0x3c,0x00,0x00,0x82,0x96,0x02,0x1c,0x13,0x00,0xff,0x00,0x64,0x30, +0xff,0xff,0x5e,0x30,0xff,0x00,0xc3,0x33,0x0c,0x00,0x83,0x10,0xff,0x7f,0x03,0x3c, +0x08,0x00,0x94,0x26,0x00,0x00,0x82,0x96,0x00,0x00,0x00,0x00,0xff,0xff,0x5e,0x30, +0xff,0x00,0xc3,0x33,0x05,0x00,0x83,0x10,0xff,0x7f,0x03,0x3c,0xff,0xff,0x82,0x32, +0x00,0x08,0x42,0x2c,0xf6,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0xff,0xff,0x63,0x34, +0x25,0xb0,0x02,0x3c,0x24,0x18,0x83,0x02,0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,0x00,0x00,0x43,0x90, +0x00,0x00,0x00,0x00,0xff,0x00,0x74,0x30,0x05,0x00,0x84,0x36,0x00,0x00,0x44,0xa0, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34, +0x24,0x10,0x62,0x02,0x02,0xf2,0x02,0x00,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa3,0x26, +0xcc,0x02,0x42,0x34,0x76,0x4b,0x60,0xa0,0x21,0x20,0xc0,0x03,0x00,0x00,0x5e,0xac, +0xe3,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xff,0xff,0x05,0x36, +0x60,0x00,0x06,0x24,0x6a,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0xeb,0x0b,0x00,0x0c, +0xe8,0x03,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x24,0x00,0x04,0x24,0x95,0x44,0x00,0x0c,0xff,0xff,0x05,0x36, +0x1f,0x00,0x54,0x30,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0xc4,0x02,0x22,0x36,0x00,0x00,0x54,0xa0, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x54,0x64,0x44,0x90,0x25,0xb0,0x03,0x3c, +0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x00,0xff,0x65,0x32,0xff,0x00,0x84,0x30,0x28,0x50,0x00,0x0c,0x02,0x2a,0x05,0x00, +0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x62,0xa0,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0xf8,0x63,0x62,0x8c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x34, +0xce,0x47,0x00,0x08,0xf8,0x63,0x62,0xac,0xcd,0x4c,0x00,0x08,0x12,0x00,0x02,0x24, +0xb8,0x59,0x00,0x0c,0x21,0x20,0x60,0x02,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x0e,0x4f,0x00,0x0c,0x21,0x20,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0xcf,0xf9,0xc2,0x17,0x02,0x80,0x06,0x3c,0x08,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x49,0x09,0x00,0x0c,0x21,0x20,0xc0,0x03,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x12,0x00,0x02,0x24,0xc7,0x42,0xe2,0xa1,0xc3,0x49,0x00,0x08,0xc3,0x42,0xe2,0xa1, +0x01,0x0d,0x00,0x0c,0x00,0x00,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x68,0x15,0xa3,0x26,0xff,0xff,0x02,0x34,0xce,0x47,0x00,0x08,0xec,0x65,0x62,0xac, +0xef,0x7d,0x83,0x90,0xc4,0x02,0x22,0x36,0x00,0x00,0x43,0xac,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0xfd,0x55,0x00,0x0c,0x10,0x00,0xa4,0x27,0xd8,0x4c,0x00,0x08, +0x68,0x15,0xa2,0x26,0x07,0x52,0x00,0x0c,0x10,0x40,0xcc,0xad,0xc5,0x4c,0x00,0x08, +0x68,0x15,0xa3,0x26,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c, +0x21,0x10,0x45,0x00,0xec,0x66,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00, +0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x45,0x00,0x68,0x15,0xa3,0x26,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00, +0x80,0x51,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x68,0x15,0xa3,0x26,0x80,0x10,0x02,0x00, +0x21,0x10,0x43,0x00,0x7c,0x51,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34, +0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x2a,0x42,0x00,0x0c, +0x21,0x20,0x00,0x00,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x68,0x15,0xa3,0x26,0x80,0x10,0x02,0x00, +0x21,0x10,0x43,0x00,0xe0,0x51,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34, +0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00, +0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,0x21,0x10,0x45,0x00,0x0c,0x67,0x83,0x24, +0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c, +0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x02,0x80,0x06,0x3c, +0x08,0x67,0xc3,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c, +0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c, +0x21,0x10,0x45,0x00,0x04,0x67,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00, +0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x45,0x00,0x02,0x80,0x06,0x3c,0x00,0x67,0xc3,0x24,0x80,0x10,0x02,0x00, +0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34, +0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00, +0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,0x21,0x10,0x45,0x00,0xfc,0x66,0x83,0x24, +0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c, +0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x02,0x80,0x06,0x3c, +0xf8,0x66,0xc3,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c, +0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c, +0x21,0x10,0x45,0x00,0xf4,0x66,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00, +0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x45,0x00,0x02,0x80,0x06,0x3c,0xf0,0x66,0xc3,0x24,0x80,0x10,0x02,0x00, +0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34, +0x00,0x00,0x64,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xa6,0x50,0x00,0x0c, +0x01,0x00,0x04,0x24,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0xa6,0x50,0x00,0x0c, +0x02,0x00,0x04,0x24,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26, +0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,0x2c,0x43,0x64,0x94,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x00,0x11,0x1e,0x00,0x68,0x15,0xa3,0x26,0x21,0x10,0x43,0x00,0x28,0x43,0x44,0x8c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x42,0x26,0x04,0x00,0x00,0x00,0x44,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x11,0x1e,0x00,0x68,0x15,0xa3,0x26, +0x21,0x10,0x43,0x00,0x2b,0x43,0x44,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x01,0x00,0x84,0x30,0x00,0x00,0x44,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x68,0x15,0xa2,0x26,0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,0x32,0x43,0x64,0x94, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0xcf,0x47,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26,0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00, +0x31,0x43,0x64,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac, +0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26,0x00,0x19,0x1e,0x00, +0x21,0x18,0x62,0x00,0x30,0x43,0x64,0x90,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x00,0x00,0x44,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c,0x68,0x15,0xa2,0x26, +0x00,0x19,0x1e,0x00,0x21,0x18,0x62,0x00,0x2e,0x43,0x64,0x94,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0xcf,0x47,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x25,0xb0,0x05,0x3c,0x01,0x00,0x06,0x24,0x01,0x80,0x02,0x3c,0x04,0x30,0x86,0x00, +0xf1,0x02,0xa7,0x34,0xed,0x02,0xa4,0x34,0x38,0x3c,0x42,0x24,0x18,0x03,0xa5,0x34, +0x08,0x00,0x03,0x24,0x00,0x00,0xa2,0xac,0x00,0x00,0xe3,0xa0,0x00,0x00,0x80,0xa0, +0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0, +0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0, +0x00,0x00,0xe0,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c, +0x25,0xb0,0x03,0x3c,0x94,0x3c,0x42,0x24,0x18,0x03,0x63,0x34,0x00,0x00,0x62,0xac, +0x00,0x00,0x83,0x90,0x30,0x00,0x02,0x24,0x05,0x00,0x62,0x10,0x21,0x20,0x00,0x00, +0x31,0x00,0x02,0x24,0x02,0x00,0x62,0x10,0x01,0x00,0x04,0x24,0x07,0x00,0x04,0x24, +0x0e,0x4f,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c, +0xd0,0x3c,0x42,0x24,0x18,0x03,0x63,0x34,0x02,0x80,0x04,0x3c,0x00,0x00,0x62,0xac, +0x08,0x00,0xe0,0x03,0x24,0x7e,0x80,0xac,0x02,0x80,0x02,0x3c,0x68,0x7b,0x42,0x24, +0xc0,0x20,0x04,0x00,0x21,0x20,0x82,0x00,0x21,0x28,0x00,0x00,0x00,0x60,0x06,0x40, +0x01,0x00,0xc1,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0x00,0x82,0x8c, +0x00,0x00,0x00,0x00,0x09,0x00,0x44,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x43,0x8c, +0x21,0x28,0x40,0x00,0x00,0x00,0x42,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xac, +0x04,0x00,0x43,0xac,0x00,0x00,0xa5,0xac,0x04,0x00,0xa5,0xac,0x00,0x60,0x86,0x40, +0x08,0x00,0xe0,0x03,0x21,0x10,0xa0,0x00,0x21,0x18,0x80,0x00,0xe8,0xff,0xbd,0x27, +0x01,0x01,0x62,0x2c,0x10,0x00,0xbf,0xaf,0x01,0x00,0x04,0x24,0x01,0x02,0x65,0x2c, +0x0a,0x00,0x40,0x14,0x21,0x30,0x00,0x00,0x02,0x00,0x04,0x24,0x07,0x00,0xa0,0x14, +0x01,0x08,0x62,0x2c,0x05,0x00,0x40,0x14,0x03,0x00,0x04,0x24,0x10,0x00,0xbf,0x8f, +0x21,0x10,0xc0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x3c,0x4f,0x00,0x0c, +0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,0x21,0x30,0x40,0x00,0x21,0x10,0xc0,0x00, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,0x80,0x7b,0x62,0x8c, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x10,0x00,0x83,0x8c,0x02,0x80,0x02,0x3c, +0x68,0x7b,0x42,0x24,0xc0,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x65,0x8c, +0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x04,0x00,0xa4,0xac,0x00,0x00,0x64,0xac, +0x04,0x00,0x83,0xac,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,0xc0,0x18,0x04,0x00, +0x21,0x18,0x64,0x00,0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c, +0x68,0x15,0x42,0x24,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x84,0x51,0x64,0x8c, +0xff,0xf1,0x02,0x24,0x24,0x20,0x82,0x00,0x08,0x00,0xe0,0x03,0x84,0x51,0x64,0xac, +0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,0xc0,0x18,0x04,0x00,0x21,0x18,0x64,0x00, +0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24, +0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x84,0x51,0x64,0x8c,0xff,0xf1,0x02,0x24, +0x24,0x20,0x82,0x00,0x00,0x02,0x84,0x34,0x08,0x00,0xe0,0x03,0x84,0x51,0x64,0xac, +0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02, +0x80,0x80,0x10,0x00,0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24, +0x80,0x80,0x10,0x00,0x21,0x80,0x02,0x02,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf, +0x14,0x00,0xb1,0xaf,0x84,0x51,0x05,0x8e,0xff,0x1f,0x02,0x3c,0x25,0xb0,0x12,0x3c, +0xff,0xff,0x42,0x34,0xf8,0xff,0x03,0x24,0x7c,0x51,0x02,0xae,0x84,0x01,0x46,0x36, +0x24,0x28,0xa3,0x00,0xff,0xfe,0x02,0x24,0x00,0x00,0xc7,0x8c,0x24,0x28,0xa2,0x00, +0xff,0xef,0x03,0x24,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,0x24,0x28,0xa3,0x00, +0x24,0x28,0xa2,0x00,0x80,0x51,0x07,0xae,0x84,0x51,0x05,0xae,0x6a,0x0f,0x00,0x0c, +0x21,0x88,0x80,0x00,0x86,0x51,0x02,0x92,0x21,0x88,0x32,0x02,0x1c,0x00,0xbf,0x8f, +0x60,0x01,0x22,0xa2,0x18,0x00,0xb2,0x8f,0x70,0x51,0x00,0xae,0x54,0x51,0x00,0xae, +0x58,0x51,0x00,0xae,0x5c,0x51,0x00,0xae,0x60,0x51,0x00,0xae,0x64,0x51,0x00,0xae, +0x68,0x51,0x00,0xae,0x6c,0x51,0x00,0xae,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xff,0x00,0xa5,0x30,0xc0,0x10,0x05,0x00, +0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x02,0x80,0x03,0x3c, +0x68,0x15,0x63,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x84,0x51,0x43,0x8c, +0x25,0xb0,0x05,0x3c,0xff,0x00,0xc6,0x30,0x21,0x30,0xc5,0x00,0xaf,0x01,0xc2,0x90, +0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x65,0x00,0xff,0x00,0x88,0x30, +0xff,0x00,0x49,0x30,0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,0x21,0x58,0x00,0x00, +0x2b,0x00,0x20,0x11,0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,0x2b,0x10,0x09,0x01, +0x21,0x28,0x00,0x00,0xfd,0x4f,0x00,0x08,0x01,0x00,0x07,0x24,0xff,0x00,0x65,0x30, +0x1d,0x00,0xa2,0x2c,0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,0x04,0x10,0xa7,0x00, +0x24,0x10,0x46,0x00,0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,0x21,0x58,0xa0,0x00, +0xff,0xff,0x02,0x25,0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,0x0f,0x00,0x60,0x14, +0x2b,0x10,0x49,0x01,0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,0x24,0x10,0x46,0x00, +0xff,0xff,0xa7,0x24,0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,0x17,0x00,0x49,0x11, +0xff,0x00,0x6a,0x30,0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,0x2b,0x10,0xab,0x00, +0xf6,0xff,0x40,0x10,0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,0x08,0x00,0x40,0x10, +0x21,0x20,0x00,0x01,0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,0x04,0x00,0x40,0x14, +0x21,0x20,0x00,0x00,0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,0xff,0x00,0x44,0x30, +0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,0x21,0x20,0x00,0x00, +0x23,0x10,0x09,0x01,0x1e,0x50,0x00,0x08,0xff,0x00,0x44,0x30,0x21,0x20,0x00,0x01, +0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xff,0x00,0x84,0x30,0xc0,0x10,0x04,0x00, +0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c, +0x68,0x15,0x63,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x25,0xb0,0x06,0x3c, +0x84,0x51,0x43,0x8c,0xff,0x00,0xa5,0x30,0x21,0x20,0x86,0x00,0x21,0x28,0xa6,0x00, +0x60,0x01,0x82,0x90,0xaf,0x01,0xa4,0x90,0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00, +0x21,0x18,0x66,0x00,0xff,0x00,0x48,0x30,0xff,0x00,0x89,0x30,0x84,0x01,0x66,0x8c, +0x21,0x50,0x00,0x00,0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,0x21,0x20,0x00,0x01, +0x2b,0x00,0xc0,0x10,0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,0x4b,0x50,0x00,0x08, +0x01,0x00,0x07,0x24,0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,0x07,0x00,0x40,0x10, +0xff,0xff,0x02,0x25,0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,0xf9,0xff,0x40,0x10, +0x01,0x00,0xa3,0x24,0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,0xff,0x00,0x45,0x30, +0x2b,0x18,0xab,0x00,0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,0x01,0x00,0x04,0x24, +0x04,0x10,0xa4,0x00,0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,0x04,0x00,0x40,0x10, +0x01,0x00,0x43,0x25,0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,0x21,0x40,0xa0,0x00, +0xff,0x00,0xe5,0x30,0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,0x04,0x10,0xa4,0x00, +0x2b,0x10,0x49,0x01,0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,0x23,0x10,0x2a,0x01, +0x2a,0x10,0x62,0x01,0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x69,0x01, +0x21,0x10,0x4a,0x00,0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00, +0xfd,0xff,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,0x6c,0x50,0x00,0x08, +0xff,0x00,0x44,0x30,0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00, +0xd8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x18,0x00,0xb2,0xaf,0xff,0xff,0x03,0x3c, +0x68,0x15,0x52,0x24,0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf, +0x20,0x00,0xbf,0xaf,0xff,0x1f,0x73,0x34,0x21,0x88,0x00,0x00,0x21,0x80,0x40,0x02, +0xaa,0x4f,0x00,0x0c,0x21,0x20,0x20,0x02,0x84,0x51,0x02,0x8e,0x21,0x28,0x00,0x00, +0x24,0x10,0x53,0x00,0x00,0x20,0x42,0x34,0x84,0x51,0x02,0xae,0x86,0x51,0x03,0x92, +0x00,0x00,0x00,0x00,0x80,0x18,0x03,0x00,0x21,0x18,0x72,0x00,0xec,0x44,0x64,0x8c, +0x60,0x45,0x62,0x8c,0x00,0x00,0x00,0x00,0x21,0x10,0x44,0x00,0x42,0x10,0x02,0x00, +0x50,0x51,0x02,0xae,0x21,0x10,0x05,0x02,0x01,0x00,0xa5,0x24,0x1d,0x00,0xa3,0x28, +0xc2,0x51,0x40,0xa0,0x88,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,0xa5,0x51,0x40,0xa0, +0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xe0,0x51,0x00,0xae,0xe4,0xff,0x40,0x14, +0x94,0x00,0x10,0x26,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27, +0xc0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x2c,0x00,0xb5,0xaf,0x68,0x15,0x46,0x24, +0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf, +0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0xec,0x65,0xc2,0x8c,0xff,0x00,0x03,0x24,0xff,0x00,0x8d,0x30, +0xff,0xff,0x42,0x38,0x0b,0x18,0x02,0x00,0xff,0xff,0x04,0x34,0x10,0x00,0xa3,0xaf, +0xec,0x65,0xc4,0xac,0xb9,0x00,0xa0,0x11,0x08,0x00,0x15,0x24,0x02,0x80,0x02,0x3c, +0x50,0x9e,0x45,0x24,0x90,0x44,0xc4,0x24,0xc7,0x50,0x00,0x08,0x21,0x88,0x00,0x00, +0x01,0x00,0x31,0x26,0x00,0x00,0x82,0xa0,0x1d,0x00,0x22,0x2a,0x0b,0x00,0x40,0x10, +0x01,0x00,0x84,0x24,0x21,0x10,0x25,0x02,0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00, +0xf7,0xff,0x40,0x10,0xfd,0xff,0x43,0x24,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a, +0x00,0x00,0x83,0xa0,0xf7,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c, +0x68,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xe8,0x9b,0x6c,0x24, +0x70,0x9b,0x4b,0x24,0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00, +0x21,0x40,0x2a,0x01,0x21,0x38,0x2c,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90, +0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28, +0xc5,0x43,0x64,0xa0,0xf8,0xff,0x40,0x14,0x34,0x43,0x65,0xa0,0x21,0x10,0x2b,0x02, +0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26, +0x1d,0x00,0x22,0x2a,0x73,0x44,0x64,0xa0,0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14, +0x05,0x00,0x29,0x25,0xaf,0x00,0xa0,0x11,0x02,0x80,0x02,0x3c,0x68,0x15,0x48,0x24, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xe4,0x9e,0x69,0x24,0x70,0x9e,0x47,0x24, +0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x10,0x69,0x00,0x21,0x20,0x67,0x00, +0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,0x21,0x18,0x68,0x00, +0x04,0x00,0x22,0x2a,0xec,0x44,0x65,0xac,0xf6,0xff,0x40,0x14,0x60,0x45,0x66,0xac, +0x02,0x80,0x02,0x3c,0x68,0x15,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c, +0xe4,0x9e,0x68,0x24,0x70,0x9e,0x47,0x24,0x04,0x00,0x11,0x24,0x80,0x20,0x11,0x00, +0x21,0x10,0x88,0x00,0x21,0x30,0x87,0x00,0x00,0x00,0x45,0x8c,0x00,0x00,0xc3,0x8c, +0x01,0x00,0x31,0x26,0x21,0x20,0x89,0x00,0x82,0x28,0x05,0x00,0x82,0x18,0x03,0x00, +0x1d,0x00,0x22,0x2a,0xec,0x44,0x83,0xac,0xf4,0xff,0x40,0x14,0x60,0x45,0x85,0xac, +0x02,0x80,0x02,0x3c,0x68,0x15,0x56,0x24,0xff,0xff,0x02,0x3c,0x21,0xf0,0xc0,0x02, +0xff,0x1f,0x57,0x34,0x21,0x88,0x00,0x00,0x21,0xa0,0x00,0x00,0x24,0x51,0x00,0x08, +0x21,0x90,0xc0,0x02,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0x94,0x00,0x52,0x26, +0x3d,0x00,0x40,0x10,0x94,0x00,0x94,0x26,0x84,0x51,0x44,0x8e,0x01,0x00,0x03,0x24, +0x02,0x13,0x04,0x00,0x01,0x00,0x53,0x30,0xf6,0xff,0x63,0x16,0x07,0x00,0x82,0x30, +0x25,0xb0,0x03,0x3c,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x84,0x01,0x45,0x8c, +0x7c,0x51,0x43,0x8e,0x21,0x20,0x20,0x02,0x24,0x28,0xa3,0x00,0x6a,0x0f,0x00,0x0c, +0x80,0x51,0x45,0xae,0x86,0x51,0x44,0x92,0xe9,0x0e,0x00,0x0c,0xff,0x00,0x25,0x32, +0x84,0x51,0x42,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x57,0x00,0x00,0x20,0x42,0x34, +0x84,0x51,0x42,0xae,0x86,0x51,0x50,0x92,0x00,0x00,0x00,0x00,0x21,0x20,0x00,0x02, +0xff,0x0e,0x00,0x0c,0x80,0x80,0x10,0x00,0x21,0x80,0x16,0x02,0x54,0x51,0x40,0xae, +0x58,0x51,0x40,0xae,0x5c,0x51,0x40,0xae,0x60,0x51,0x40,0xae,0x64,0x51,0x40,0xae, +0x68,0x51,0x40,0xae,0x6c,0x51,0x40,0xae,0x70,0x51,0x40,0xae,0xec,0x44,0x04,0x8e, +0x60,0x45,0x03,0x8e,0x26,0x10,0x53,0x00,0x21,0x30,0x00,0x00,0x21,0x18,0x64,0x00, +0x42,0x18,0x03,0x00,0x04,0x00,0x04,0x24,0x0a,0xa8,0x82,0x00,0x50,0x51,0x43,0xae, +0x21,0x20,0x9e,0x02,0x21,0x10,0x86,0x00,0x01,0x00,0xc6,0x24,0x1d,0x00,0xc3,0x28, +0xc2,0x51,0x40,0xa0,0x88,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,0xa5,0x51,0x40,0xa0, +0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xe0,0x51,0x80,0xac,0x94,0x00,0x52,0x26, +0xc5,0xff,0x40,0x14,0x94,0x00,0x94,0x26,0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34, +0x00,0x00,0x55,0xa0,0x10,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x03,0x00,0x60,0x14, +0x02,0x80,0x03,0x3c,0x68,0x15,0x62,0x24,0xec,0x65,0x40,0xac,0x3c,0x00,0xbf,0x8f, +0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f, +0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f, +0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c, +0x50,0x9e,0x45,0x24,0x90,0x44,0xc4,0x24,0x21,0x88,0x00,0x00,0x21,0x10,0x25,0x02, +0x00,0x00,0x43,0x90,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0, +0xfa,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,0x68,0x15,0x4a,0x24, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x0c,0x9d,0x6c,0x24,0xac,0x9b,0x4b,0x24, +0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01, +0x21,0x38,0x2c,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90, +0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc5,0x43,0x64,0xa0, +0xf8,0xff,0x40,0x14,0x34,0x43,0x65,0xa0,0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90, +0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a, +0x73,0x44,0x64,0xa0,0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25, +0x02,0x80,0x02,0x3c,0x68,0x15,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c, +0xe4,0x9e,0x68,0x24,0x70,0x9e,0x47,0x24,0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00, +0x21,0x10,0x68,0x00,0x21,0x20,0x67,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c, +0x01,0x00,0x31,0x26,0x21,0x18,0x69,0x00,0x1d,0x00,0x22,0x2a,0xec,0x44,0x65,0xac, +0xf6,0xff,0x40,0x14,0x60,0x45,0x66,0xac,0x17,0x51,0x00,0x08,0x02,0x80,0x02,0x3c, +0xd8,0xff,0xbd,0x27,0xff,0xff,0x84,0x30,0x18,0x00,0xb2,0xaf,0xf0,0x01,0x92,0x30, +0x02,0x91,0x12,0x00,0x14,0x00,0xb1,0xaf,0xc0,0x88,0x12,0x00,0x21,0x88,0x32,0x02, +0x80,0x88,0x11,0x00,0x21,0x88,0x32,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24, +0x80,0x88,0x11,0x00,0x21,0x88,0x22,0x02,0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf, +0x10,0x00,0xb0,0xaf,0x84,0x51,0x30,0x8e,0x00,0x02,0x83,0x30,0xff,0xfe,0x02,0x24, +0x2b,0x18,0x03,0x00,0x00,0x10,0x10,0x36,0x24,0x80,0x02,0x02,0x00,0x1a,0x03,0x00, +0x00,0x04,0x82,0x30,0x25,0x80,0x03,0x02,0x2b,0x10,0x02,0x00,0xf7,0xff,0x03,0x24, +0x24,0x80,0x03,0x02,0xc0,0x10,0x02,0x00,0x25,0x80,0x02,0x02,0x7c,0x51,0x25,0xae, +0x84,0x51,0x30,0xae,0x3c,0x10,0x00,0x0c,0x21,0x98,0xa0,0x00,0xf8,0xff,0x03,0x24, +0x24,0x80,0x03,0x02,0x07,0x00,0x42,0x30,0x25,0x80,0x02,0x02,0x07,0x00,0x03,0x32, +0x25,0xb0,0x02,0x3c,0x80,0x18,0x03,0x00,0x84,0x51,0x30,0xae,0x21,0x18,0x62,0x00, +0x84,0x01,0x62,0x8c,0x21,0x20,0x40,0x02,0x24,0x10,0x53,0x00,0x6a,0x0f,0x00,0x0c, +0x80,0x51,0x22,0xae,0x86,0x51,0x24,0x92,0x21,0x28,0x40,0x02,0x20,0x00,0xbf,0x8f, +0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0xe9,0x0e,0x00,0x08,0x28,0x00,0xbd,0x27,0xaa,0x4f,0x00,0x08,0xff,0x00,0x84,0x30, +0x02,0x80,0x02,0x3c,0x68,0x15,0x43,0x24,0x1f,0x00,0x04,0x24,0x84,0x51,0x62,0x8c, +0xff,0xff,0x84,0x24,0x00,0x10,0x42,0x34,0x84,0x51,0x62,0xac,0xfb,0xff,0x81,0x04, +0x94,0x00,0x63,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x23,0x10,0xa4,0x00,0x2b,0x18,0xa4,0x00,0x23,0x20,0x85,0x00,0x08,0x00,0xe0,0x03, +0x0b,0x10,0x83,0x00,0x20,0xff,0xbd,0x27,0xcc,0x00,0xb5,0xaf,0xdc,0x00,0xbf,0xaf, +0xd8,0x00,0xbe,0xaf,0xd4,0x00,0xb7,0xaf,0xd0,0x00,0xb6,0xaf,0xc8,0x00,0xb4,0xaf, +0xc4,0x00,0xb3,0xaf,0xc0,0x00,0xb2,0xaf,0xbc,0x00,0xb1,0xaf,0xb8,0x00,0xb0,0xaf, +0x21,0xa8,0x00,0x00,0x40,0x11,0x15,0x00,0x10,0x00,0xa3,0x27,0x21,0x10,0x43,0x00, +0x07,0x00,0x16,0x24,0xff,0xff,0xd6,0x26,0x00,0x00,0x40,0xac,0xfd,0xff,0xc1,0x06, +0x04,0x00,0x42,0x24,0x01,0x00,0xb5,0x26,0x03,0x00,0xa2,0x2e,0xf6,0xff,0x40,0x14, +0x40,0x11,0x15,0x00,0x25,0xb0,0x10,0x3c,0xc4,0x02,0x02,0x36,0x00,0x00,0x40,0xac, +0x04,0x00,0x03,0x36,0x00,0x00,0x62,0x8c,0x04,0x0c,0x03,0x36,0x00,0x00,0x63,0x8c, +0x08,0x0c,0x04,0x36,0x0f,0x00,0x11,0x3c,0xac,0x00,0xa3,0xaf,0x00,0x00,0x84,0x8c, +0x24,0x10,0x51,0x00,0x02,0xf4,0x02,0x00,0xb0,0x00,0xa4,0xaf,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00, +0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x70,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24, +0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c, +0xff,0xff,0x25,0x36,0x74,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c, +0x21,0x20,0x00,0x00,0xe0,0x0e,0x02,0x36,0x21,0x20,0x40,0x00,0x00,0x00,0x42,0x8c, +0xdc,0x0e,0x12,0x36,0x70,0x0e,0x13,0x36,0x78,0x00,0xa2,0xaf,0x00,0x00,0x42,0x8e, +0x74,0x0e,0x14,0x36,0x78,0x0e,0x15,0x36,0x7c,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8e, +0x7c,0x0e,0x16,0x36,0x80,0x0e,0x17,0x36,0x80,0x00,0xa3,0xaf,0x00,0x00,0x82,0x8e, +0xd4,0x0e,0x10,0x36,0xed,0x3f,0x11,0x3c,0x84,0x00,0xa2,0xaf,0x00,0x00,0xa3,0x8e, +0xfb,0x92,0x25,0x36,0x88,0x00,0xa3,0xaf,0x00,0x00,0xc2,0x8e,0x00,0x00,0x00,0x00, +0x8c,0x00,0xa2,0xaf,0x00,0x00,0xe3,0x8e,0x25,0xb0,0x02,0x3c,0x84,0x0e,0x42,0x34, +0x90,0x00,0xa3,0xaf,0x00,0x00,0x42,0x8c,0x25,0xb0,0x03,0x3c,0x88,0x0e,0x63,0x34, +0x94,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8c,0x25,0xb0,0x02,0x3c,0x8c,0x0e,0x42,0x34, +0x98,0x00,0xa3,0xaf,0x00,0x00,0x42,0x8c,0x25,0xb0,0x03,0x3c,0xd0,0x0e,0x63,0x34, +0x9c,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8c,0x00,0x00,0x00,0x00,0xa0,0x00,0xa3,0xaf, +0x00,0x00,0x02,0x8e,0x25,0xb0,0x03,0x3c,0xd8,0x0e,0x63,0x34,0xa4,0x00,0xa2,0xaf, +0x00,0x00,0x63,0x8c,0xf9,0x51,0x00,0x0c,0xa8,0x00,0xa3,0xaf,0x21,0x20,0x40,0x02, +0xf9,0x51,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0x60,0x02,0xf9,0x51,0x00,0x0c, +0xfb,0x92,0x25,0x36,0x21,0x20,0x80,0x02,0xf9,0x51,0x00,0x0c,0xfb,0x92,0x25,0x36, +0x21,0x20,0xa0,0x02,0xf9,0x51,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0xc0,0x02, +0xf9,0x51,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0xe0,0x02,0xf9,0x51,0x00,0x0c, +0xfb,0x92,0x25,0x36,0x02,0x80,0x02,0x3c,0xd8,0x9f,0x42,0x24,0x00,0x00,0x44,0x8c, +0xfb,0x92,0x25,0x36,0xf9,0x51,0x00,0x0c,0x25,0xb0,0x13,0x3c,0x02,0x80,0x03,0x3c, +0xdc,0x9f,0x63,0x24,0x00,0x00,0x64,0x8c,0xfb,0x92,0x25,0x36,0xf9,0x51,0x00,0x0c, +0x21,0xb0,0x00,0x00,0x02,0x80,0x02,0x3c,0xe0,0x9f,0x42,0x24,0x00,0x00,0x44,0x8c, +0xfb,0x92,0x25,0x36,0xf9,0x51,0x00,0x0c,0xff,0x03,0x14,0x3c,0x02,0x80,0x03,0x3c, +0xe4,0x9f,0x63,0x24,0x00,0x00,0x64,0x8c,0xfb,0x92,0x25,0x36,0xf9,0x51,0x00,0x0c, +0x10,0x00,0xb7,0x27,0x21,0x20,0x00,0x02,0xf9,0x51,0x00,0x0c,0xfb,0x92,0x25,0x36, +0x02,0x80,0x02,0x3c,0xe8,0x9f,0x42,0x24,0x00,0x00,0x44,0x8c,0xf9,0x51,0x00,0x0c, +0xfb,0x92,0x25,0x36,0xe5,0x52,0x00,0x08,0x21,0xa8,0x00,0x00,0x6e,0x00,0xc2,0x13, +0x02,0x80,0x02,0x3c,0xac,0x0e,0x62,0x36,0x94,0x0e,0x63,0x36,0x00,0x00,0x48,0x8c, +0x00,0x00,0x64,0x8c,0xb4,0x0e,0x62,0x36,0x9c,0x0e,0x63,0x36,0x00,0x00,0x45,0x8c, +0x00,0x00,0x66,0x8c,0x25,0xb0,0x03,0x3c,0xbc,0x0e,0x63,0x34,0x00,0x00,0x67,0x8c, +0x24,0x20,0x94,0x00,0x00,0xd8,0x02,0x3c,0x24,0x10,0x02,0x01,0x24,0x28,0xb4,0x00, +0x24,0x30,0xd4,0x00,0x24,0x38,0xf4,0x00,0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24, +0x01,0x00,0x42,0x2c,0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,0xe8,0x00,0x83,0x10, +0x02,0x3c,0x07,0x00,0xe6,0x00,0xa3,0x10,0x20,0x00,0x03,0x24,0xe4,0x00,0xc3,0x10, +0x00,0x00,0x00,0x00,0xe2,0x00,0xe3,0x10,0x01,0x00,0x08,0x24,0x80,0x00,0x03,0x24, +0x08,0x00,0x83,0x10,0x21,0x20,0x00,0x00,0x06,0x00,0xa3,0x10,0x21,0x20,0x00,0x00, +0xe0,0x03,0x03,0x24,0x03,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0xdb,0x00,0xe3,0x10, +0x01,0x00,0x04,0x24,0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x11, +0x00,0x00,0x00,0x00,0xd7,0x00,0x80,0x14,0x94,0x0e,0x63,0x36,0x01,0x00,0xb5,0x26, +0x0a,0x00,0xa2,0x2e,0x01,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xcb,0xff,0xc0,0x17, +0x01,0x00,0x02,0x24,0xa0,0x00,0x03,0x3c,0x30,0x54,0x65,0x34,0xf9,0x51,0x00,0x0c, +0x04,0x0c,0x64,0x36,0x08,0x00,0x05,0x3c,0xe4,0x00,0xa5,0x34,0xf9,0x51,0x00,0x0c, +0x08,0x0c,0x64,0x36,0x28,0x0e,0x64,0x36,0xf9,0x51,0x00,0x0c,0x80,0x80,0x05,0x3c, +0x14,0x02,0x02,0x3c,0x48,0x01,0x45,0x34,0xf9,0x51,0x00,0x0c,0x40,0x0e,0x64,0x36, +0x16,0x68,0x05,0x3c,0xa2,0x04,0xa5,0x34,0xf9,0x51,0x00,0x0c,0x44,0x0e,0x64,0x36, +0x4c,0x0e,0x64,0x36,0xf9,0x51,0x00,0x0c,0xd1,0x28,0x05,0x24,0x14,0x02,0x03,0x3c, +0x4d,0x01,0x65,0x34,0xf9,0x51,0x00,0x0c,0x60,0x0e,0x64,0x36,0x16,0x28,0x05,0x3c, +0xba,0x08,0xa5,0x34,0xf9,0x51,0x00,0x0c,0x64,0x0e,0x64,0x36,0x6c,0x0e,0x64,0x36, +0xf9,0x51,0x00,0x0c,0xd1,0x28,0x05,0x24,0x00,0xfb,0x05,0x3c,0x01,0x00,0xa5,0x34, +0xf9,0x51,0x00,0x0c,0x48,0x0e,0x64,0x36,0x00,0xf8,0x05,0x3c,0x01,0x00,0xa5,0x34, +0xf9,0x51,0x00,0x0c,0x48,0x0e,0x64,0x36,0xeb,0x0b,0x00,0x0c,0x03,0x00,0x04,0x24, +0xa0,0x00,0x02,0x3c,0x33,0x54,0x45,0x34,0xf9,0x51,0x00,0x0c,0x04,0x0c,0x64,0x36, +0x08,0x0c,0x64,0x36,0xf9,0x51,0x00,0x0c,0xe4,0x00,0x05,0x24,0x28,0x0e,0x64,0x36, +0xf9,0x51,0x00,0x0c,0x21,0x28,0x00,0x00,0x01,0x00,0x02,0x24,0x96,0xff,0xc2,0x17, +0xac,0x0e,0x62,0x36,0x02,0x80,0x02,0x3c,0xec,0x9f,0x42,0x24,0x25,0xb0,0x03,0x3c, +0x00,0x00,0x44,0x8c,0x20,0x08,0x63,0x34,0x00,0x00,0x71,0x8c,0x00,0x01,0x03,0x3c, +0x00,0x01,0x65,0x34,0xf9,0x51,0x00,0x0c,0x25,0xb0,0x12,0x3c,0x00,0x01,0x02,0x3c, +0x00,0x01,0x45,0x34,0xf9,0x51,0x00,0x0c,0x28,0x08,0x44,0x36,0xa0,0x00,0x03,0x3c, +0x30,0x54,0x65,0x34,0xf9,0x51,0x00,0x0c,0x04,0x0c,0x44,0x36,0x08,0x00,0x05,0x3c, +0xe4,0x00,0xa5,0x34,0xf9,0x51,0x00,0x0c,0x08,0x0c,0x44,0x36,0x28,0x0e,0x44,0x36, +0xf9,0x51,0x00,0x0c,0x80,0x80,0x05,0x3c,0x00,0x01,0x02,0x3c,0x00,0x7c,0x45,0x34, +0xf9,0x51,0x00,0x0c,0x30,0x0e,0x44,0x36,0x00,0x01,0x03,0x3c,0x00,0x48,0x65,0x34, +0xf9,0x51,0x00,0x0c,0x34,0x0e,0x44,0x36,0x00,0x10,0x02,0x3c,0x1f,0xdc,0x45,0x34, +0xf9,0x51,0x00,0x0c,0x38,0x0e,0x44,0x36,0x00,0x10,0x03,0x3c,0x1f,0x8c,0x65,0x34, +0xf9,0x51,0x00,0x0c,0x3c,0x0e,0x44,0x36,0x14,0x02,0x02,0x3c,0x02,0x01,0x45,0x34, +0xf9,0x51,0x00,0x0c,0x40,0x0e,0x44,0x36,0x16,0x68,0x05,0x3c,0xc7,0x04,0xa5,0x34, +0xf9,0x51,0x00,0x0c,0x44,0x0e,0x44,0x36,0x4c,0x0e,0x44,0x36,0xf9,0x51,0x00,0x0c, +0xd1,0x28,0x05,0x24,0x6c,0x0e,0x44,0x36,0xf9,0x51,0x00,0x0c,0xd1,0x28,0x05,0x24, +0x00,0x01,0x03,0x3c,0x00,0x7c,0x65,0x34,0xf9,0x51,0x00,0x0c,0x50,0x0e,0x44,0x36, +0x00,0x01,0x02,0x3c,0x00,0x48,0x45,0x34,0xf9,0x51,0x00,0x0c,0x54,0x0e,0x44,0x36, +0x00,0x10,0x03,0x3c,0x23,0xdc,0x65,0x34,0xf9,0x51,0x00,0x0c,0x58,0x0e,0x44,0x36, +0x00,0x10,0x02,0x3c,0x23,0x8c,0x45,0x34,0xf9,0x51,0x00,0x0c,0x5c,0x0e,0x44,0x36, +0x14,0x02,0x03,0x3c,0x02,0x01,0x65,0x34,0xf9,0x51,0x00,0x0c,0x60,0x0e,0x44,0x36, +0x16,0x28,0x05,0x3c,0x07,0x0d,0xa5,0x34,0xf9,0x51,0x00,0x0c,0x64,0x0e,0x44,0x36, +0x48,0x0e,0x44,0x36,0xf9,0x51,0x00,0x0c,0x00,0xfb,0x05,0x3c,0x00,0xf8,0x05,0x3c, +0xf9,0x51,0x00,0x0c,0x48,0x0e,0x44,0x36,0x00,0x02,0x10,0x3c,0xeb,0x0b,0x00,0x0c, +0x03,0x00,0x04,0x24,0x4c,0x0e,0x44,0x36,0xf9,0x51,0x00,0x0c,0xd1,0x28,0x05,0x36, +0xd1,0x28,0x05,0x36,0xf9,0x51,0x00,0x0c,0x6c,0x0e,0x44,0x36,0x48,0x0e,0x44,0x36, +0xf9,0x51,0x00,0x0c,0x00,0xfb,0x05,0x3c,0x00,0xf8,0x05,0x3c,0xf9,0x51,0x00,0x0c, +0x48,0x0e,0x44,0x36,0xeb,0x0b,0x00,0x0c,0x03,0x00,0x04,0x24,0xac,0x00,0xa5,0x8f, +0x04,0x0c,0x44,0x36,0xf9,0x51,0x00,0x0c,0x00,0x01,0x31,0x32,0xb0,0x00,0xa5,0x8f, +0x08,0x0c,0x44,0x36,0xf9,0x51,0x00,0x0c,0x2b,0x88,0x11,0x00,0x28,0x0e,0x44,0x36, +0xf9,0x51,0x00,0x0c,0x21,0x28,0x00,0x00,0x23,0xff,0x20,0x16,0xac,0x0e,0x62,0x36, +0x02,0x80,0x02,0x3c,0xec,0x9f,0x42,0x24,0x00,0x00,0x44,0x8c,0xf9,0x51,0x00,0x0c, +0x00,0x01,0x05,0x3c,0x28,0x08,0x44,0x36,0xf9,0x51,0x00,0x0c,0x00,0x01,0x05,0x3c, +0xac,0x0e,0x62,0x36,0x94,0x0e,0x63,0x36,0x00,0x00,0x48,0x8c,0x00,0x00,0x64,0x8c, +0xb4,0x0e,0x62,0x36,0x9c,0x0e,0x63,0x36,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c, +0x25,0xb0,0x03,0x3c,0xbc,0x0e,0x63,0x34,0x00,0x00,0x67,0x8c,0x24,0x20,0x94,0x00, +0x00,0xd8,0x02,0x3c,0x24,0x10,0x02,0x01,0x24,0x28,0xb4,0x00,0x24,0x30,0xd4,0x00, +0x24,0x38,0xf4,0x00,0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c, +0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,0x1a,0xff,0x83,0x14,0x02,0x3c,0x07,0x00, +0x80,0x00,0x03,0x24,0x20,0xff,0x83,0x14,0x21,0x40,0x00,0x00,0xdb,0x52,0x00,0x08, +0x21,0x20,0x00,0x00,0x00,0x00,0x62,0x8c,0x9c,0x0e,0x65,0x36,0xa4,0x0e,0x66,0x36, +0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00,0x00,0x00,0xe2,0xae,0x00,0x00,0xa4,0x8c, +0xac,0x0e,0x67,0x36,0xb4,0x0e,0x65,0x36,0x24,0x20,0x94,0x00,0x02,0x24,0x04,0x00, +0x04,0x00,0xe4,0xae,0x00,0x00,0xc3,0x8c,0xc4,0x0e,0x64,0x36,0x24,0x18,0x74,0x00, +0x02,0x1c,0x03,0x00,0x08,0x00,0xe3,0xae,0x00,0x00,0xe2,0x8c,0x00,0x00,0x00,0x00, +0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00,0x0c,0x00,0xe2,0xae,0x00,0x00,0xa3,0x8c, +0x00,0x00,0x00,0x00,0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,0x10,0x00,0xe3,0xae, +0x25,0xb0,0x03,0x3c,0xbc,0x0e,0x63,0x34,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00, +0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00,0x14,0x00,0xe2,0xae,0x00,0x00,0x83,0x8c, +0x00,0x00,0x00,0x00,0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,0x18,0x00,0xe3,0xae, +0x25,0xb0,0x03,0x3c,0xcc,0x0e,0x63,0x34,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00, +0x24,0x10,0x54,0x00,0x02,0x14,0x02,0x00,0x1c,0x00,0xe2,0xae,0x01,0x00,0xd6,0x26, +0x03,0x00,0xc2,0x2e,0xc7,0xfe,0x40,0x14,0x20,0x00,0xf7,0x26,0x10,0x00,0xb0,0x8f, +0x00,0x00,0x00,0x00,0x49,0x01,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x00,0xb1,0x8f, +0x00,0x00,0x00,0x00,0x06,0x00,0x20,0x16,0x21,0x20,0x00,0x02,0x50,0x00,0xa2,0x8f, +0x00,0x00,0x00,0x00,0x29,0x00,0x40,0x10,0xff,0x00,0x05,0x24,0x21,0x20,0x00,0x02, +0x02,0x52,0x00,0x0c,0x21,0x28,0x20,0x02,0x03,0x00,0x42,0x2c,0x08,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x34,0x00,0xa5,0x8f,0x14,0x00,0xa4,0x8f,0x02,0x52,0x00,0x0c, +0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c,0x1c,0x00,0x40,0x14,0x21,0x28,0x00,0x00, +0x50,0x00,0xb2,0x8f,0x21,0x20,0x00,0x02,0x02,0x52,0x00,0x0c,0x21,0x28,0x40,0x02, +0x03,0x00,0x42,0x2c,0x09,0x00,0x40,0x10,0x21,0x20,0x20,0x02,0x54,0x00,0xa5,0x8f, +0x14,0x00,0xa4,0x8f,0x02,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c, +0x0e,0x00,0x40,0x14,0x21,0x28,0x00,0x00,0x21,0x20,0x20,0x02,0x02,0x52,0x00,0x0c, +0x21,0x28,0x40,0x02,0x03,0x00,0x42,0x2c,0xe0,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x54,0x00,0xa5,0x8f,0x34,0x00,0xa4,0x8f,0x02,0x52,0x00,0x0c,0x00,0x00,0x00,0x00, +0x03,0x00,0x42,0x2c,0xd9,0x00,0x40,0x10,0x01,0x00,0x05,0x24,0xff,0x00,0x02,0x24, +0xdb,0x00,0xa2,0x10,0x25,0xb0,0x03,0x3c,0x10,0x00,0xa2,0x27,0x40,0x29,0x05,0x00, +0x02,0x80,0x0f,0x3c,0x21,0x28,0xa2,0x00,0x68,0x15,0xec,0x25,0x00,0x00,0xa6,0x8c, +0x0c,0x00,0xa7,0x8c,0x0c,0x40,0x83,0x8d,0x10,0x40,0x84,0x8d,0x04,0x00,0xa8,0x8c, +0x10,0x00,0xa9,0x8c,0x00,0xfc,0x02,0x24,0x08,0x00,0xaa,0x8c,0x14,0x00,0xab,0x8c, +0x24,0x20,0x82,0x00,0xff,0x03,0xc6,0x30,0x24,0x18,0x62,0x00,0xff,0x03,0xe7,0x30, +0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x18,0x66,0x00,0x25,0x20,0x87,0x00, +0xff,0x03,0x08,0x31,0xff,0x03,0x29,0x31,0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00, +0x80,0x42,0x08,0x00,0x80,0x4a,0x09,0x00,0x0f,0xc0,0x02,0x3c,0x1c,0x00,0xa6,0x8c, +0x18,0x00,0xa7,0x8c,0xff,0xff,0x42,0x34,0x25,0x18,0x68,0x00,0x25,0x20,0x89,0x00, +0xff,0x03,0x4a,0x31,0xff,0x03,0x6b,0x31,0x24,0x20,0x82,0x00,0x00,0x55,0x0a,0x00, +0x24,0x18,0x62,0x00,0x00,0x5d,0x0b,0x00,0x25,0x18,0x6a,0x00,0x25,0x20,0x8b,0x00, +0x16,0x40,0x86,0xa5,0x0c,0x40,0x83,0xad,0x10,0x40,0x84,0xad,0x14,0x40,0x87,0xa5, +0x68,0x15,0xf1,0x25,0x10,0x40,0x22,0x8e,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00, +0x4d,0x00,0x43,0x10,0x25,0xb0,0x12,0x3c,0x0c,0x40,0x23,0x8e,0x80,0x0c,0x44,0x36, +0x00,0x00,0x88,0x8c,0x00,0x02,0x62,0x30,0xc0,0xff,0x13,0x3c,0x82,0x6d,0x08,0x00, +0x03,0x00,0x40,0x10,0xff,0x03,0x65,0x30,0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00, +0x18,0x00,0xad,0x00,0x82,0x62,0x03,0x00,0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31, +0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30, +0x00,0xfc,0x02,0x24,0x25,0x60,0x82,0x01,0x18,0x00,0x8d,0x01,0x00,0xfc,0x74,0x36, +0x24,0x28,0x14,0x01,0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32, +0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,0xf9,0x51,0x00,0x0c,0x25,0x28,0xa6,0x00, +0x94,0x0c,0x44,0x36,0x00,0x00,0x85,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x55,0x34, +0xc0,0x03,0x10,0x32,0x24,0x28,0xb5,0x00,0x80,0x85,0x10,0x00,0xf9,0x51,0x00,0x0c, +0x25,0x28,0xb0,0x00,0x10,0x40,0x2c,0x8e,0x88,0x0c,0x44,0x36,0x00,0x00,0x88,0x8c, +0x82,0x2a,0x0c,0x00,0xff,0x03,0xa5,0x30,0x24,0x10,0x13,0x01,0x00,0x02,0xa3,0x30, +0x03,0x00,0x60,0x10,0x82,0x6d,0x02,0x00,0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00, +0x18,0x00,0xad,0x00,0x02,0x65,0x0c,0x00,0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31, +0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30, +0x00,0xfc,0x02,0x24,0x25,0x60,0x82,0x01,0x18,0x00,0x8d,0x01,0x24,0x28,0x14,0x01, +0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00, +0x25,0x28,0xa2,0x00,0xf9,0x51,0x00,0x0c,0x25,0x28,0xa6,0x00,0x9c,0x0c,0x44,0x36, +0x00,0x00,0x85,0x8c,0xc0,0x03,0x10,0x32,0x80,0x85,0x10,0x00,0x24,0x28,0xb5,0x00, +0xf9,0x51,0x00,0x0c,0x25,0x28,0xb0,0x00,0x78,0x00,0xa5,0x8f,0x25,0xb0,0x10,0x3c, +0xf9,0x51,0x00,0x0c,0xe0,0x0e,0x04,0x36,0x7c,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c, +0xdc,0x0e,0x04,0x36,0x80,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0x70,0x0e,0x04,0x36, +0x84,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0x74,0x0e,0x04,0x36,0x88,0x00,0xa5,0x8f, +0xf9,0x51,0x00,0x0c,0x78,0x0e,0x04,0x36,0x8c,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c, +0x7c,0x0e,0x04,0x36,0x90,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0x80,0x0e,0x04,0x36, +0x94,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0x84,0x0e,0x04,0x36,0x98,0x00,0xa5,0x8f, +0xf9,0x51,0x00,0x0c,0x88,0x0e,0x04,0x36,0x9c,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c, +0x8c,0x0e,0x04,0x36,0xa0,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0xd0,0x0e,0x04,0x36, +0xa4,0x00,0xa5,0x8f,0xf9,0x51,0x00,0x0c,0xd4,0x0e,0x04,0x36,0xa8,0x00,0xa5,0x8f, +0x88,0x0e,0x04,0x36,0xf9,0x51,0x00,0x0c,0x0f,0x00,0x10,0x3c,0x70,0x00,0xa6,0x8f, +0xff,0xff,0x05,0x36,0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0x1a,0x0c,0x00,0x0c, +0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x74,0x00,0xa6,0x8f, +0xff,0xff,0x05,0x36,0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0x1a,0x0c,0x00,0x0c, +0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0xff,0xff,0x05,0x36, +0x95,0x44,0x00,0x0c,0x1e,0x00,0x04,0x24,0x21,0x88,0x40,0x00,0xfd,0xff,0x06,0x24, +0x01,0x00,0x42,0x34,0x24,0x30,0x46,0x00,0xff,0xff,0x05,0x36,0x6a,0x44,0x00,0x0c, +0x1e,0x00,0x04,0x24,0xeb,0x0b,0x00,0x0c,0x03,0x00,0x04,0x24,0xff,0xff,0x05,0x36, +0x03,0x00,0x26,0x36,0x6a,0x44,0x00,0x0c,0x1e,0x00,0x04,0x24,0xdc,0x00,0xbf,0x8f, +0xd8,0x00,0xbe,0x8f,0xd4,0x00,0xb7,0x8f,0xd0,0x00,0xb6,0x8f,0xcc,0x00,0xb5,0x8f, +0xc8,0x00,0xb4,0x8f,0xc4,0x00,0xb3,0x8f,0xc0,0x00,0xb2,0x8f,0xbc,0x00,0xb1,0x8f, +0xb8,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0xe0,0x00,0xbd,0x27,0xff,0x00,0x05,0x24, +0xff,0x00,0x02,0x24,0x29,0xff,0xa2,0x14,0x10,0x00,0xa2,0x27,0x25,0xb0,0x03,0x3c, +0x94,0x0e,0x62,0x34,0x9c,0x0e,0x64,0x34,0xa4,0x0e,0x65,0x34,0xac,0x0e,0x66,0x34, +0x02,0x80,0x0f,0x3c,0x00,0x00,0x49,0x8c,0x68,0x15,0xed,0x25,0x00,0x00,0x8c,0x8c, +0x00,0x00,0xae,0x8c,0x00,0x00,0xc7,0x8c,0xb4,0x0e,0x62,0x34,0x0c,0x40,0xa4,0x8d, +0x10,0x40,0xa5,0x8d,0x00,0x00,0x4a,0x8c,0xff,0x03,0x06,0x3c,0x00,0xfc,0x08,0x24, +0xbc,0x0e,0x62,0x34,0x24,0x48,0x26,0x01,0x24,0x38,0xe6,0x00,0x00,0x00,0x4b,0x8c, +0x24,0x28,0xa8,0x00,0x24,0x20,0x88,0x00,0x02,0x3c,0x07,0x00,0xcc,0x0e,0x68,0x34, +0x02,0x4c,0x09,0x00,0xc4,0x0e,0x63,0x34,0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34, +0x25,0x28,0xa7,0x00,0x25,0x20,0x89,0x00,0x00,0x00,0x67,0x8c,0x24,0x60,0x86,0x01, +0x00,0x00,0x03,0x8d,0x24,0x50,0x46,0x01,0x24,0x28,0xa2,0x00,0x24,0x20,0x82,0x00, +0x82,0x61,0x0c,0x00,0x82,0x51,0x0a,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34, +0x25,0x20,0x8c,0x00,0x25,0x28,0xaa,0x00,0x24,0x70,0xc6,0x01,0x24,0x58,0x66,0x01, +0x24,0x28,0xa2,0x00,0x24,0x18,0x66,0x00,0x00,0x71,0x0e,0x00,0x24,0x20,0x82,0x00, +0x00,0x59,0x0b,0x00,0x24,0x38,0xe6,0x00,0x25,0x20,0x8e,0x00,0x25,0x28,0xab,0x00, +0x02,0x3c,0x07,0x00,0x02,0x1c,0x03,0x00,0x16,0x40,0xa3,0xa5,0x0c,0x40,0xa4,0xad, +0x10,0x40,0xa5,0xad,0x4e,0x54,0x00,0x08,0x14,0x40,0xa7,0xa5,0x30,0x00,0xb1,0x8f, +0xf6,0x53,0x00,0x08,0x21,0x20,0x00,0x02,0xe0,0xff,0xbd,0x27,0x44,0x00,0x02,0x24, +0x10,0x00,0xa2,0xa3,0x49,0x00,0x03,0x24,0x47,0x00,0x02,0x24,0x02,0x80,0x07,0x3c, +0x68,0xa5,0xe7,0x24,0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0x10,0x27,0x03,0x24, +0x01,0x00,0x02,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00, +0xf4,0x57,0xc6,0x24,0x0c,0x00,0xe3,0xac,0x14,0x00,0xe2,0xa0,0x18,0x00,0xbf,0xaf, +0x88,0x0e,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x25,0xb0,0x03,0x3c, +0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf, +0x24,0x00,0xb5,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf, +0x03,0x0d,0x64,0x34,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x54,0x30, +0x70,0x00,0x93,0x32,0x63,0x00,0x60,0x12,0x42,0x00,0x63,0x34,0x8f,0x00,0x82,0x32, +0x00,0x00,0x82,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x5b,0x00,0x60,0x12, +0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c, +0xff,0xff,0x25,0x36,0x21,0xa8,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c, +0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36, +0x21,0xb0,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x64,0x00,0x04,0x24,0x1a,0x0c,0x00,0x0c,0x08,0x00,0x10,0x3c,0xff,0xff,0x10,0x36, +0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x01,0x00,0x12,0x3c,0x24,0x30,0xb0,0x02, +0x25,0x30,0xd2,0x00,0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00, +0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x24,0x80,0xd0,0x02,0x2a,0x42,0x00,0x0c, +0x01,0x00,0x04,0x24,0x25,0x30,0x12,0x02,0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c, +0x21,0x20,0x00,0x00,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x2a,0x42,0x00,0x0c, +0x21,0x20,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x18,0x00,0x04,0x24,0x95,0x44,0x00,0x0c, +0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24,0x18,0x00,0x04,0x24, +0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c,0x00,0x80,0x06,0x36,0xeb,0x0b,0x00,0x0c, +0x03,0x00,0x04,0x24,0x27,0x00,0x60,0x16,0x25,0xb0,0x02,0x3c,0x2c,0x00,0xbf,0x8f, +0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c, +0x42,0x00,0x42,0x34,0x30,0x00,0xbd,0x27,0x00,0x00,0x40,0xa0,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x24,0x00,0x00,0x62,0xa0,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c, +0x18,0x00,0x04,0x24,0x95,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c, +0x64,0x00,0x04,0x24,0x18,0x00,0x04,0x24,0xff,0xff,0x25,0x36,0x6a,0x44,0x00,0x0c, +0x00,0x80,0x06,0x36,0xeb,0x0b,0x00,0x0c,0x03,0x00,0x04,0x24,0xdb,0xff,0x60,0x12, +0x25,0xb0,0x02,0x3c,0x03,0x0d,0x42,0x34,0x00,0x00,0x54,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x0f,0x00,0x10,0x3c,0x21,0x30,0xa0,0x02,0xff,0xff,0x05,0x36, +0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24, +0x2a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x21,0x30,0xc0,0x02, +0x6a,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0x1a,0x0c,0x00,0x0c,0x64,0x00,0x04,0x24, +0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f, +0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x21,0x20,0x00,0x00,0x2a,0x42,0x00,0x08,0x30,0x00,0xbd,0x27,0xc0,0xff,0xbd,0x27, +0x28,0x00,0xb4,0xaf,0x02,0x80,0x14,0x3c,0x30,0x00,0xb6,0xaf,0x38,0x00,0xbf,0xaf, +0x34,0x00,0xb7,0xaf,0x2c,0x00,0xb5,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf, +0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x68,0x15,0x85,0x26,0x0c,0x40,0xa2,0x8c, +0x00,0x00,0x00,0x00,0x82,0x17,0x02,0x00,0x01,0x00,0x42,0x30,0x08,0x00,0x40,0x14, +0x06,0x00,0x16,0x24,0x08,0x40,0xa2,0x8c,0x01,0x00,0x03,0x24,0x42,0x17,0x02,0x00, +0x03,0x00,0x42,0x30,0x5d,0x01,0x43,0x10,0x25,0xb0,0x02,0x3c,0x68,0x15,0x85,0x26, +0x0c,0x40,0xa2,0x8c,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,0x01,0x00,0x44,0x30, +0x0d,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x08,0x40,0xa2,0x8c,0x00,0x00,0x00,0x00, +0x42,0x17,0x02,0x00,0x03,0x00,0x42,0x30,0xef,0xff,0x44,0x14,0x25,0xb0,0x02,0x3c, +0x0e,0x0c,0x44,0x34,0x00,0x00,0x83,0x90,0x00,0x01,0x02,0x24,0xff,0x00,0x63,0x30, +0x01,0x00,0x63,0x24,0x59,0x02,0x62,0x10,0xff,0x00,0x62,0x30,0x00,0x00,0x82,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x84,0x26,0x10,0x40,0x82,0x8c, +0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,0x73,0x02,0x43,0x10,0x0f,0x00,0x10,0x3c, +0xc7,0x42,0x93,0x90,0x25,0xb0,0x02,0x3c,0x62,0x0c,0x42,0x34,0xff,0x00,0x63,0x32, +0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x90,0x26, +0xc6,0x42,0x02,0x92,0x00,0x00,0x00,0x00,0x79,0x01,0x40,0x10,0x01,0x00,0x02,0x24, +0x25,0xb0,0x11,0x3c,0x03,0x0d,0x23,0x36,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00, +0x70,0x00,0x42,0x30,0x9f,0x01,0x40,0x14,0xcc,0x00,0x02,0x24,0xc4,0x42,0x02,0x96, +0x00,0x00,0x00,0x00,0x23,0x20,0x53,0x00,0x2b,0x18,0x53,0x00,0x23,0x10,0x62,0x02, +0x0a,0x10,0x83,0x00,0x03,0x00,0x42,0x2c,0x6c,0x01,0x40,0x10,0x00,0x00,0x00,0x00, +0xc4,0x42,0x03,0x92,0x63,0x0c,0x22,0x36,0x21,0x20,0x00,0x00,0x00,0x00,0x43,0xa0, +0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x82,0x24,0x68,0x15,0x83,0x26,0xc3,0x42,0x62,0x90,0x08,0x40,0x66,0x8c, +0xc2,0x42,0x73,0xa0,0x23,0x20,0x53,0x00,0x2b,0x38,0x62,0x02,0x23,0x90,0x62,0x02, +0x02,0x2c,0x06,0x00,0x0b,0x90,0x87,0x00,0x3f,0x00,0xa5,0x30,0x3f,0x00,0xc4,0x30, +0x24,0x00,0x02,0x24,0x20,0x00,0x03,0x24,0x23,0x10,0x44,0x00,0x8a,0x01,0x40,0x16, +0x23,0x18,0x65,0x00,0x21,0x40,0x80,0x00,0x21,0xa8,0xa0,0x00,0x02,0x80,0x17,0x3c, +0x2b,0x28,0xc8,0x02,0x81,0x01,0xa0,0x10,0x68,0x15,0x82,0x26,0x80,0x10,0x08,0x00, +0x68,0x15,0x83,0x26,0x21,0x10,0x43,0x00,0x18,0x40,0x44,0x8c,0x00,0x00,0x00,0x00, +0x82,0x25,0x04,0x00,0x68,0x15,0x86,0x26,0x0c,0x40,0xc3,0x8c,0x00,0x00,0x00,0x00, +0xff,0x03,0x67,0x30,0xe9,0x01,0xe0,0x10,0x00,0x02,0x62,0x30,0x04,0x00,0x40,0x10, +0x18,0x00,0xe4,0x00,0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00,0x18,0x00,0xe4,0x00, +0x82,0x82,0x03,0x00,0xff,0x03,0x10,0x32,0x00,0x02,0x03,0x32,0x12,0x10,0x00,0x00, +0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x45,0x30,0x00,0xfc,0x02,0x24, +0x25,0x80,0x02,0x02,0x18,0x00,0x04,0x02,0x80,0x1d,0x04,0x00,0x25,0xb0,0x11,0x3c, +0x80,0x0c,0x24,0x36,0x94,0x0c,0x31,0x36,0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00, +0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x18,0x62,0x00,0x25,0x18,0x65,0x00, +0x21,0x28,0x60,0x00,0xf9,0x51,0x00,0x0c,0x10,0x00,0xa3,0xaf,0x00,0x00,0x23,0x8e, +0xff,0x0f,0x02,0x3c,0xc0,0x03,0x10,0x32,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x80,0x85,0x10,0x00,0x25,0x18,0x70,0x00,0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x00, +0x10,0x00,0xa3,0xaf,0xf9,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0x68,0x15,0x83,0x26, +0x08,0x40,0x62,0x8c,0x00,0x00,0x00,0x00,0x5b,0x01,0x40,0x04,0xc0,0x28,0x15,0x00, +0x21,0x10,0xa3,0x00,0xac,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x22,0x0a,0x63,0x34, +0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26, +0x21,0x10,0xa2,0x00,0xad,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x23,0x0a,0x63,0x34, +0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26, +0x21,0x10,0xa2,0x00,0xae,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x24,0x0a,0x63,0x34, +0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26, +0x21,0x10,0xa2,0x00,0xaf,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x25,0x0a,0x63,0x34, +0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26, +0x21,0x10,0xa2,0x00,0xb0,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x26,0x0a,0x63,0x34, +0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26, +0x21,0x10,0xa2,0x00,0xb1,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x27,0x0a,0x63,0x34, +0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26, +0x21,0x10,0xa2,0x00,0xb2,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x28,0x0a,0x63,0x34, +0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26, +0x21,0x10,0xa2,0x00,0xb3,0x40,0x44,0x90,0x25,0xb0,0x03,0x3c,0x29,0x0a,0x63,0x34, +0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0xee,0x7d,0xe3,0x92, +0x22,0x00,0x02,0x24,0x03,0x00,0x62,0x10,0x92,0x00,0x02,0x24,0xfe,0xfe,0x62,0x14, +0x00,0x00,0x00,0x00,0x68,0x15,0x82,0x26,0x08,0x40,0x43,0x8c,0x01,0x00,0x44,0x3a, +0x24,0x00,0x02,0x24,0x02,0x1a,0x03,0x00,0x3f,0x00,0x63,0x30,0x01,0x00,0x84,0x30, +0x87,0x01,0x80,0x10,0x23,0x28,0x43,0x00,0x42,0x18,0x12,0x00,0x40,0x10,0x03,0x00, +0x21,0x90,0x43,0x00,0x68,0x15,0x83,0x26,0xc3,0x42,0x62,0x90,0x00,0x00,0x00,0x00, +0x2b,0x10,0x62,0x02,0x50,0x01,0x40,0x10,0x2b,0x10,0x45,0x02,0x06,0x00,0x40,0x10, +0x24,0x00,0x06,0x24,0x08,0x40,0x62,0x8c,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00, +0x3f,0x00,0x42,0x30,0x21,0x30,0x52,0x00,0x2b,0x28,0xc6,0x02,0x50,0x01,0xa0,0x10, +0x68,0x15,0x82,0x26,0x80,0x10,0x06,0x00,0x68,0x15,0x83,0x26,0x21,0x10,0x43,0x00, +0x18,0x40,0x44,0x8c,0x00,0x00,0x00,0x00,0x82,0x25,0x04,0x00,0x68,0x15,0x83,0x26, +0x10,0x40,0x70,0x8c,0x00,0x00,0x00,0x00,0x82,0x3a,0x10,0x00,0xff,0x03,0xe7,0x30, +0x5a,0x01,0xe0,0x10,0x00,0x02,0xe2,0x30,0x04,0x00,0x40,0x10,0x18,0x00,0xe4,0x00, +0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00,0x18,0x00,0xe4,0x00,0x02,0x85,0x10,0x00, +0xff,0x03,0x10,0x32,0x00,0x02,0x03,0x32,0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00, +0x03,0x00,0x60,0x10,0xff,0x03,0x45,0x30,0x00,0xfc,0x02,0x24,0x25,0x80,0x02,0x02, +0x18,0x00,0x04,0x02,0x80,0x1d,0x04,0x00,0x25,0xb0,0x11,0x3c,0x88,0x0c,0x24,0x36, +0x9c,0x0c,0x31,0x36,0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32, +0x00,0x14,0x02,0x00,0x25,0x18,0x62,0x00,0x25,0x18,0x65,0x00,0x21,0x28,0x60,0x00, +0xf9,0x51,0x00,0x0c,0x10,0x00,0xa3,0xaf,0x00,0x00,0x23,0x8e,0xff,0x0f,0x02,0x3c, +0xff,0xff,0x42,0x34,0xc0,0x03,0x10,0x32,0x24,0x18,0x62,0x00,0x80,0x85,0x10,0x00, +0x25,0x18,0x70,0x00,0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x00,0xf9,0x51,0x00,0x0c, +0x10,0x00,0xa3,0xaf,0x1c,0x56,0x00,0x08,0x00,0x00,0x00,0x00,0x80,0x0c,0x42,0x34, +0x00,0x00,0x43,0x8c,0x21,0x30,0xa0,0x00,0xc0,0xff,0x02,0x3c,0x24,0x20,0x62,0x00, +0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c,0x7e,0x57,0x00,0x08,0x18,0x40,0xc3,0x24, +0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,0x0d,0x00,0x40,0x10,0x02,0x80,0x17,0x3c, +0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x45,0x00,0xf8,0xff,0x44,0x14, +0x04,0x00,0x63,0x24,0x08,0x40,0xc2,0x8c,0xc0,0xff,0x03,0x24,0x3f,0x00,0x24,0x32, +0x24,0x10,0x43,0x00,0x25,0x10,0x44,0x00,0x08,0x40,0xc2,0xac,0x02,0x80,0x17,0x3c, +0xee,0x7d,0xe3,0x92,0x22,0x00,0x02,0x24,0x44,0x00,0x62,0x10,0x92,0x00,0x02,0x24, +0x43,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0x25,0xb0,0x02,0x3c,0x24,0x0a,0x42,0x34, +0x00,0x00,0x44,0x8c,0x3f,0x3f,0x03,0x3c,0x3f,0x3f,0x63,0x34,0x24,0x20,0x83,0x00, +0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x16,0x56,0x53,0x24,0x1e,0x57,0x72,0x24, +0x21,0x88,0x00,0x00,0xa5,0x57,0x00,0x08,0x10,0x00,0xa4,0xaf,0x95,0x45,0x00,0x0c, +0x00,0x00,0x00,0x00,0x4d,0x00,0x40,0x10,0x68,0x15,0x85,0x26,0x01,0x00,0x31,0x26, +0x21,0x00,0x22,0x2e,0x17,0x00,0x40,0x10,0x68,0x15,0x84,0x26,0xc0,0x80,0x11,0x00, +0x10,0x00,0xa4,0x27,0x21,0x28,0x13,0x02,0x95,0x45,0x00,0x0c,0x04,0x00,0x06,0x24, +0x21,0x28,0x12,0x02,0x10,0x00,0xa4,0x27,0xf0,0xff,0x40,0x14,0x04,0x00,0x06,0x24, +0x68,0x15,0x85,0x26,0x08,0x40,0xa3,0x8c,0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34, +0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00,0xff,0x7f,0x02,0x3c, +0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x08,0x40,0xa3,0xac, +0x68,0x15,0x84,0x26,0x0c,0x40,0x83,0x8c,0x00,0x40,0x02,0x3c,0x25,0x18,0x62,0x00, +0x25,0xb0,0x02,0x3c,0x0e,0x0c,0x42,0x34,0x0c,0x40,0x83,0xac,0x00,0x00,0x40,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x16,0x56,0x00,0x08,0x68,0x15,0x85,0x26, +0xc6,0x42,0x02,0xa2,0x52,0x56,0x00,0x08,0xc4,0x42,0x13,0xa6,0x50,0x55,0x00,0x0c, +0x00,0x00,0x00,0x00,0x62,0x56,0x00,0x08,0xc4,0x42,0x13,0xa6,0x25,0xb0,0x02,0x3c, +0x88,0x0c,0x42,0x34,0x00,0x00,0x44,0x8c,0x02,0x80,0x03,0x3c,0x68,0x15,0x66,0x24, +0xc0,0xff,0x02,0x3c,0x24,0x20,0x82,0x00,0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c, +0xe0,0x57,0x00,0x08,0x18,0x40,0xc3,0x24,0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e, +0xb2,0xff,0x40,0x10,0x25,0xb0,0x02,0x3c,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00, +0x24,0x10,0x45,0x00,0xf8,0xff,0x44,0x14,0x04,0x00,0x63,0x24,0x08,0x40,0xc2,0x8c, +0x3f,0x00,0x23,0x32,0xff,0xc0,0x04,0x24,0x24,0x10,0x44,0x00,0x00,0x1a,0x03,0x00, +0x25,0x10,0x43,0x00,0x90,0x57,0x00,0x08,0x08,0x40,0xc2,0xac,0x08,0x40,0xa3,0x8c, +0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00, +0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00,0x00,0x80,0x02,0x3c,0xb9,0x57,0x00,0x08, +0x25,0x18,0x62,0x00,0x63,0x0c,0x23,0x36,0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x6c,0x56,0x00,0x08,0x68,0x15,0x83,0x26,0x30,0x40,0x43,0x8c, +0x87,0x56,0x00,0x08,0x82,0x25,0x03,0x00,0x91,0x00,0xe0,0x10,0x21,0x40,0x00,0x00, +0x2b,0x10,0x42,0x02,0x21,0x20,0x92,0x00,0x00,0x00,0x42,0x38,0x24,0x00,0x08,0x24, +0x2b,0x18,0x43,0x02,0x0b,0x40,0x82,0x00,0x70,0xfe,0x60,0x10,0x20,0x00,0x15,0x24, +0x68,0x15,0x83,0x26,0x0a,0x40,0x62,0x94,0x02,0x80,0x17,0x3c,0x3f,0x00,0x42,0x30, +0x7e,0x56,0x00,0x08,0x21,0xa8,0x52,0x00,0x21,0x10,0xa3,0x00,0xb4,0x41,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x22,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb5,0x41,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x23,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb6,0x41,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x24,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb7,0x41,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x25,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb8,0x41,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x26,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xb9,0x41,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x27,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xba,0x41,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x28,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x68,0x15,0x82,0x26,0x21,0x10,0xa2,0x00,0xbb,0x41,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x29,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x19,0x57,0x00,0x08,0x00,0x00,0x00,0x00,0x28,0x00,0xa0,0x10, +0x80,0x10,0x08,0x00,0x21,0x10,0x46,0x00,0x18,0x40,0x45,0x8c,0x25,0xb0,0x04,0x3c, +0xf9,0x51,0x00,0x0c,0x80,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,0x94,0x0c,0x84,0x34, +0xb3,0x56,0x00,0x08,0x21,0x28,0x00,0x00,0x08,0x40,0x62,0x8c,0x00,0x00,0x00,0x00, +0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x2b,0x18,0x42,0x02,0xb2,0xfe,0x60,0x14, +0x23,0x30,0x52,0x00,0x21,0x30,0x00,0x00,0x21,0x28,0x00,0x00,0x68,0x15,0x82,0x26, +0x30,0x40,0x43,0x8c,0x41,0x57,0x00,0x08,0x82,0x25,0x03,0x00,0x00,0x00,0x80,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x3d,0x56,0x00,0x08,0x68,0x15,0x84,0x26, +0x23,0x10,0x92,0x00,0x2b,0x18,0x44,0x02,0x2b,0x20,0x45,0x02,0x0b,0x40,0x43,0x00, +0xe2,0xfd,0x80,0x14,0x23,0xa8,0xb2,0x00,0x7d,0x56,0x00,0x08,0x21,0xa8,0x00,0x00, +0x30,0x40,0xc5,0x8c,0x7a,0x58,0x00,0x08,0x25,0xb0,0x04,0x3c,0x27,0x00,0xa0,0x10, +0x80,0x10,0x06,0x00,0x21,0x10,0x43,0x00,0x18,0x40,0x45,0x8c,0x25,0xb0,0x04,0x3c, +0xf9,0x51,0x00,0x0c,0x88,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,0x9c,0x0c,0x84,0x34, +0xf9,0x51,0x00,0x0c,0x21,0x28,0x00,0x00,0x1c,0x56,0x00,0x08,0x00,0x00,0x00,0x00, +0xff,0xff,0x43,0x26,0x42,0x18,0x03,0x00,0x40,0x10,0x03,0x00,0x21,0x10,0x43,0x00, +0x2b,0x57,0x00,0x08,0x01,0x00,0x52,0x24,0xff,0xff,0x05,0x36,0x60,0x00,0x06,0x24, +0x6a,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0xeb,0x0b,0x00,0x0c,0xe8,0x03,0x04,0x24, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x24,0x00,0x04,0x24,0x95,0x44,0x00,0x0c,0xff,0xff,0x05,0x36,0x1f,0x00,0x53,0x30, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x1a,0x0c,0x00,0x0c, +0x64,0x00,0x04,0x24,0x44,0x56,0x00,0x08,0x25,0xb0,0x02,0x3c,0x30,0x40,0x65,0x8c, +0xa6,0x58,0x00,0x08,0x25,0xb0,0x04,0x3c,0x00,0xff,0x84,0x30,0x02,0x22,0x04,0x00, +0x08,0x00,0x80,0x10,0x02,0x80,0x02,0x3c,0xff,0x00,0x02,0x24,0x04,0x00,0x82,0x10, +0xcc,0xff,0x03,0x24,0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,0x4e,0x58,0x43,0xa0, +0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,0x4e,0x58,0x44,0xa0,0x02,0x24,0x04,0x00, +0xff,0x00,0x84,0x30,0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x68,0x15,0x63,0x24, +0x20,0x00,0x84,0x2c,0x09,0x00,0x80,0x10,0x21,0x10,0x43,0x00,0x74,0x51,0x43,0x8c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30, +0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c, +0x50,0x79,0x43,0x8c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00, +0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xff,0x00,0x85,0x30,0xd2,0xff,0xa3,0x24,0xfe,0xff,0xa2,0x24,0xda,0xff,0xa4,0x24, +0x04,0x00,0x63,0x2c,0x08,0x00,0x84,0x2c,0x06,0x00,0x60,0x14,0xff,0x00,0x42,0x30, +0xf0,0xff,0xa2,0x24,0xfc,0xff,0xa3,0x24,0x16,0x00,0x46,0x2c,0x03,0x00,0x80,0x10, +0xff,0x00,0x62,0x30,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xfa,0xff,0xa3,0x24, +0xfc,0xff,0xc0,0x10,0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,0xff,0x00,0x62,0x30, +0xe0,0xff,0xbd,0x27,0x44,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,0x49,0x00,0x03,0x24, +0x47,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x02,0x80,0x08,0x3c,0x30,0xa5,0xe7,0x24, +0x68,0x15,0x08,0x25,0xff,0xff,0x09,0x34,0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3, +0xf4,0x01,0x03,0x24,0x01,0x00,0x02,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27, +0x21,0x20,0xe0,0x00,0x9c,0x64,0xc6,0x24,0xf4,0x63,0x09,0xad,0x0c,0x00,0xe3,0xac, +0x14,0x00,0xe2,0xa0,0xf0,0x63,0x09,0xad,0x18,0x00,0xbf,0xaf,0x88,0x0e,0x00,0x0c, +0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf, +0x10,0x00,0xb0,0xaf,0x02,0x80,0x02,0x3c,0xee,0x7d,0x44,0x90,0x22,0x00,0x03,0x24, +0x07,0x00,0x83,0x10,0x25,0xb0,0x04,0x3c,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0x4c,0x00,0x83,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30, +0xf5,0xff,0x40,0x10,0x02,0x80,0x11,0x3c,0x68,0x15,0x22,0x26,0xf0,0x63,0x43,0x8c, +0x98,0x0c,0x84,0x34,0x21,0x10,0x00,0x00,0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30, +0x00,0x00,0x83,0xa0,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x22,0x26,0xf4,0x63,0x43,0x8c, +0x25,0xb0,0x02,0x3c,0x99,0x0c,0x42,0x34,0x02,0x19,0x03,0x00,0xff,0x00,0x63,0x30, +0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x68,0x15,0x30,0x26, +0xf0,0x63,0x04,0x8e,0xff,0xff,0x02,0x34,0xd7,0xff,0x82,0x10,0x00,0x00,0x00,0x00, +0xe8,0x63,0x02,0x8e,0x00,0x00,0x00,0x00,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30, +0x3f,0x00,0x43,0x2c,0x12,0x00,0x60,0x14,0x3b,0x00,0x42,0x2c,0xf4,0x63,0x02,0x8e, +0x02,0x19,0x04,0x00,0x02,0x11,0x02,0x00,0x23,0x18,0x62,0x00,0x1e,0x00,0x60,0x18, +0x25,0xb0,0x04,0x3c,0x12,0x01,0x05,0x3c,0x0c,0x09,0x84,0x34,0x13,0x13,0xa5,0x34, +0xf9,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,0xe4,0x42,0x43,0x8c, +0x00,0x20,0x04,0x3c,0x25,0x18,0x64,0x00,0x30,0x59,0x00,0x08,0xe4,0x42,0x43,0xac, +0xbd,0xff,0x40,0x10,0x01,0x00,0x03,0x24,0xe4,0x42,0x02,0x8e,0x00,0x00,0x00,0x00, +0x42,0x17,0x02,0x00,0x01,0x00,0x42,0x30,0xb7,0xff,0x43,0x14,0x25,0xb0,0x04,0x3c, +0x32,0x03,0x05,0x3c,0x0c,0x09,0x84,0x34,0xf9,0x51,0x00,0x0c,0x33,0x13,0xa5,0x34, +0xe4,0x42,0x03,0x8e,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x30,0x59,0x00,0x08,0xe4,0x42,0x03,0xae,0x22,0x02,0x05,0x3c,0x0c,0x09,0x84,0x34, +0x6a,0x59,0x00,0x08,0x23,0x13,0xa5,0x34,0x25,0xb0,0x03,0x3c,0x03,0x0d,0x63,0x34, +0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x08,0x00,0x42,0x34, +0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x03,0x0d,0x63,0x34, +0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xf7,0x00,0x42,0x30,0x00,0x00,0x62,0xa0, +0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,0x00,0x00,0x62,0x90, +0x21,0x20,0x00,0x00,0x3f,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24, +0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24, +0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00, +0xff,0x00,0x42,0x30,0x80,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24, +0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xff,0x00,0x03,0x3c, +0x82,0x01,0x49,0x34,0x81,0x01,0x48,0x34,0x24,0x10,0x83,0x00,0x02,0x3c,0x02,0x00, +0x00,0xff,0x63,0x34,0x02,0x80,0x02,0x3c,0x68,0x15,0x45,0x24,0x02,0x32,0x04,0x00, +0x01,0x00,0x02,0x24,0x24,0x20,0x83,0x00,0xce,0x4c,0xa2,0xa0,0xbc,0x4c,0xa0,0xac, +0xc0,0x4c,0xa0,0xac,0xc4,0x4c,0xa0,0xac,0x06,0x00,0x80,0x14,0xc8,0x4c,0xa0,0xac, +0x00,0x00,0x02,0x91,0x00,0x00,0x23,0x91,0xcc,0x4c,0xa2,0xa0,0x08,0x00,0xe0,0x03, +0xcd,0x4c,0xa3,0xa0,0xcd,0x4c,0xa7,0xa0,0x08,0x00,0xe0,0x03,0xcc,0x4c,0xa6,0xa0, +0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0xcd,0x4c,0x66,0x90,0xcc,0x4c,0x65,0x90, +0x25,0xb0,0x02,0x3c,0x82,0x01,0x44,0x34,0x81,0x01,0x42,0x34,0x00,0x00,0x45,0xa0, +0x00,0x00,0x86,0xa0,0x08,0x00,0xe0,0x03,0xce,0x4c,0x60,0xa0,0x02,0x80,0x08,0x3c, +0x68,0x15,0x04,0x25,0xce,0x4c,0x82,0x90,0x00,0x00,0x00,0x00,0x15,0x00,0x40,0x10, +0x21,0x18,0x00,0x00,0xc0,0x4c,0x82,0x8c,0xbc,0x4c,0x85,0x8c,0x25,0xb0,0x03,0x3c, +0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x82,0x01,0x67,0x34,0x0f,0x00,0x40,0x10, +0x81,0x01,0x66,0x34,0xcd,0x4c,0x83,0x90,0xcc,0x4c,0x82,0x90,0xf0,0x00,0x63,0x30, +0x1f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0,0x00,0x00,0xe3,0xa0,0x68,0x15,0x02,0x25, +0x01,0x00,0x03,0x24,0xc8,0x4c,0x40,0xac,0xbc,0x4c,0x40,0xac,0xc0,0x4c,0x40,0xac, +0xc4,0x4c,0x40,0xac,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xc4,0x4c,0x82,0x8c, +0x25,0xb0,0x03,0x3c,0x82,0x01,0x69,0x34,0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00, +0x0e,0x00,0x40,0x14,0x81,0x01,0x66,0x34,0xc8,0x4c,0x82,0x8c,0x00,0x00,0x00,0x00, +0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x08,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0xcd,0x4c,0x83,0x90,0xcc,0x4c,0x82,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa0, +0x00,0x00,0x23,0xa1,0xf2,0x59,0x00,0x08,0x68,0x15,0x02,0x25,0xcd,0x4c,0x83,0x90, +0xcc,0x4c,0x82,0x90,0xf0,0x00,0x63,0x30,0x7f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0, +0x00,0x00,0x23,0xa1,0xf2,0x59,0x00,0x08,0x68,0x15,0x02,0x25,0x00,0x00,0x85,0xac, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x25,0xb0,0x03,0x3c,0x33,0x02,0x65,0x34,0x00,0x11,0x04,0x00,0x00,0x00,0xa2,0xa0, +0x30,0x02,0x63,0x34,0x00,0x00,0x65,0x8c,0x0f,0x00,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x28,0xa2,0x00,0x01,0x00,0x03,0x24,0x04,0x18,0x83,0x00,0x02,0x00,0xa0,0x10, +0x21,0x10,0x00,0x00,0xff,0xff,0x62,0x30,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x25,0xb0,0x11,0x3c,0x18,0x00,0xb2,0xaf, +0x4c,0x00,0x22,0x36,0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x44,0x90, +0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x24,0xff,0x00,0x84,0x30,0x07,0x00,0x82,0x10, +0x68,0x15,0x72,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x46,0x64,0x43,0x96, +0x01,0x00,0x02,0x24,0xf7,0xff,0x62,0x14,0x21,0x20,0x00,0x00,0x1e,0x5a,0x00,0x0c, +0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x24,0x1e,0x5a,0x00,0x0c,0x21,0x80,0x40,0x00, +0x25,0x80,0x02,0x02,0x33,0x02,0x23,0x36,0x08,0x00,0x02,0x24,0xff,0xff,0x10,0x32, +0x40,0x00,0x25,0x36,0x00,0x00,0x62,0xa0,0xea,0xff,0x00,0x16,0x00,0x00,0x00,0x00, +0x00,0x00,0xa2,0x94,0x44,0x64,0x43,0x96,0xff,0xdf,0x42,0x30,0x00,0x20,0x44,0x34, +0x01,0x00,0x63,0x24,0x44,0x64,0x43,0xa6,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa4,0xa4, +0x3b,0x5a,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xb8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c, +0x3c,0x00,0xb1,0xaf,0x38,0x00,0xb0,0xaf,0x40,0x00,0xbf,0xaf,0x68,0x15,0x50,0x24, +0xf8,0x63,0x03,0x8e,0x02,0x80,0x11,0x3c,0x01,0x00,0x02,0x24,0x01,0x00,0x63,0x30, +0x10,0x00,0xa4,0x27,0x64,0x79,0x25,0x26,0x07,0x00,0x62,0x10,0x0a,0x00,0x06,0x24, +0x40,0x00,0xbf,0x8f,0x3c,0x00,0xb1,0x8f,0x38,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,0x6c,0x45,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x21,0x28,0x00,0x00,0x64,0x79,0x24,0x26,0x58,0x45,0x00,0x0c,0x0a,0x00,0x06,0x24, +0x28,0x00,0x03,0x24,0x05,0x00,0x02,0x24,0xfd,0x63,0x03,0xa2,0xfc,0x63,0x02,0xa2, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x54,0x4f,0x00,0x0c, +0x48,0x00,0x04,0x24,0x21,0x80,0x40,0x00,0x10,0x00,0xa5,0x27,0xe4,0xff,0x40,0x10, +0x0a,0x00,0x06,0x24,0x08,0x00,0x44,0x94,0x14,0x00,0x02,0x24,0x14,0x00,0x02,0xae, +0x02,0x80,0x02,0x3c,0x28,0x00,0x03,0x24,0x25,0x20,0x82,0x00,0x0c,0x00,0x03,0xae, +0x6c,0x45,0x00,0x0c,0x20,0x00,0x84,0x24,0x30,0x08,0x00,0x0c,0x21,0x20,0x00,0x02, +0x6e,0x5a,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x18,0x03,0x42,0x34,0x60,0x6a,0x63,0x24,0x00,0x00,0x43,0xac,0x63,0x00,0x02,0x24, +0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x02,0x80,0x02,0x3c, +0xe8,0x7d,0x45,0x94,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xeb,0x7d,0x66,0x90, +0xf8,0x7d,0x47,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x03,0x7e,0x69,0x90, +0x05,0x7e,0x4a,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x08,0x7e,0x6b,0x90, +0x0a,0x7e,0x4c,0x90,0x07,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x25,0xb0,0x04,0x3c, +0xf5,0x7d,0x43,0xa0,0xb0,0x03,0x84,0x34,0x02,0x80,0x02,0x3c,0x02,0x80,0x18,0x3c, +0xea,0x7d,0x08,0x93,0x00,0x00,0x85,0xac,0xf6,0x7d,0x40,0xa0,0x02,0x80,0x02,0x3c, +0x00,0x00,0x86,0xac,0x02,0x80,0x0f,0x3c,0xf7,0x7d,0x40,0xa0,0x02,0x80,0x02,0x3c, +0x00,0x00,0x87,0xac,0x68,0x15,0xee,0x25,0x18,0x7e,0x40,0xa0,0xfd,0xff,0x02,0x24, +0xd5,0x4a,0xc2,0xa1,0x01,0x00,0x03,0x24,0x00,0x78,0x02,0x24,0xd4,0x4a,0xc3,0xa1, +0xd8,0x4a,0xc2,0xa5,0xff,0x07,0x03,0x24,0x0f,0x00,0x0d,0x31,0x02,0x00,0x02,0x24, +0xda,0x4a,0xc3,0xa5,0x00,0x00,0x88,0xac,0x00,0x00,0x89,0xac,0x00,0x00,0x8a,0xac, +0x00,0x00,0x8b,0xac,0x00,0x00,0x8c,0xac,0x17,0x00,0xa2,0x11,0x02,0x80,0x02,0x3c, +0xea,0x7d,0x02,0x93,0x01,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x05,0x00,0x43,0x10, +0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x2a,0x7e,0x40,0xa4,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x3c,0x68,0x15,0xe4,0x25,0x02,0xbc,0x42,0x34, +0x68,0x4b,0x82,0xac,0x15,0x15,0x03,0x3c,0x02,0x02,0x02,0x3c,0x07,0x07,0x63,0x34, +0x64,0x4b,0x82,0xac,0x02,0x80,0x02,0x3c,0x60,0x4b,0x83,0xac,0x2a,0x7e,0x40,0xa4, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xef,0x7d,0x44,0x90,0x06,0x00,0x03,0x24, +0x15,0x00,0x83,0x10,0x0b,0x00,0x02,0x24,0x0a,0x00,0x82,0x10,0x00,0xe0,0x02,0x3c, +0x68,0x15,0xe4,0x25,0x00,0xb2,0x42,0x34,0x00,0x1c,0x03,0x3c,0x68,0x4b,0x82,0xac, +0x00,0x1c,0x63,0x34,0x00,0x04,0x02,0x24,0x60,0x4b,0x83,0xac,0xd2,0x5a,0x00,0x08, +0x64,0x4b,0x82,0xac,0x00,0x80,0x02,0x3c,0x00,0xbc,0x42,0x34,0x15,0x15,0x03,0x3c, +0x68,0x4b,0xc2,0xad,0x07,0x07,0x63,0x34,0x03,0x03,0x02,0x3c,0x60,0x4b,0xc3,0xad, +0xd2,0x5a,0x00,0x08,0x64,0x4b,0xc2,0xad,0x00,0xc0,0x02,0x3c,0x00,0xb2,0x42,0x34, +0x1c,0x1c,0x03,0x3c,0x68,0x4b,0xc2,0xad,0x07,0x07,0x63,0x34,0x00,0x04,0x02,0x24, +0x60,0x4b,0xc3,0xad,0xd2,0x5a,0x00,0x08,0x64,0x4b,0xc2,0xad,0x25,0xb0,0x02,0x3c, +0x4d,0x00,0x44,0x34,0xff,0x00,0x03,0x3c,0xec,0x02,0x42,0x34,0x00,0x00,0x43,0xac, +0x00,0x00,0x80,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x44,0x6c,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x7f,0x00,0x02,0x3c,0xfd,0xbf,0x45,0x34, +0x80,0x04,0x03,0x3c,0x25,0x28,0xa3,0x00,0x00,0x08,0x04,0x3c,0x02,0x80,0x02,0x3c, +0x68,0x15,0x42,0x24,0x25,0x28,0xa4,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x65,0xac, +0x04,0x4b,0x45,0xac,0xfc,0x4a,0x45,0xac,0x08,0x00,0x63,0x34,0x86,0x00,0x05,0x24, +0x00,0x00,0x65,0xa4,0x08,0x4b,0x45,0xa4,0x00,0x4b,0x40,0xac,0x0a,0x4b,0x40,0xa4, +0x0c,0x4b,0x45,0xa4,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x30,0x5b,0x00,0x08,0x00,0x00,0x00,0x00, +0x42,0xb0,0x02,0x3c,0xa0,0xff,0x03,0x24,0x01,0x00,0x42,0x34,0xe8,0xff,0xbd,0x27, +0x21,0x20,0x00,0x00,0x01,0x00,0x05,0x24,0x00,0x01,0x06,0x24,0x00,0x00,0x43,0xa0, +0x10,0x00,0xbf,0xaf,0x51,0x0e,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f, +0x03,0x00,0x04,0x24,0x01,0x00,0x05,0x24,0x40,0x1f,0x06,0x24,0x51,0x0e,0x00,0x08, +0x18,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x02,0x80,0x10,0x3c, +0x68,0x15,0x10,0x26,0x76,0x4b,0x00,0xa2,0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf, +0x5e,0x5e,0x00,0x0c,0x21,0x88,0x00,0x02,0x48,0x01,0x02,0x24,0xec,0x63,0x02,0xae, +0xe8,0x63,0x02,0xae,0x21,0x10,0x00,0x02,0x1f,0x00,0x03,0x24,0xff,0xff,0x63,0x24, +0xd0,0x4c,0x40,0xa4,0xd2,0x4c,0x40,0xa4,0xd4,0x4c,0x40,0xa4,0xd6,0x4c,0x40,0xa4, +0xd8,0x4c,0x40,0xa4,0xda,0x4c,0x40,0xa4,0xdc,0x4c,0x40,0xa4,0xde,0x4c,0x40,0xa4, +0xe0,0x4c,0x40,0xa4,0xf5,0xff,0x61,0x04,0x24,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c, +0x10,0x00,0x03,0x24,0xb0,0x03,0x42,0x34,0x02,0x80,0x04,0x3c,0x8c,0x58,0x84,0x24, +0x00,0x00,0x43,0xac,0x21,0x28,0x00,0x00,0x58,0x45,0x00,0x0c,0x04,0x00,0x06,0x24, +0x2c,0x5f,0x00,0x0c,0x00,0x00,0x00,0x00,0xb4,0x5f,0x00,0x0c,0xec,0x65,0x20,0xae, +0xea,0x60,0x00,0x0c,0x00,0x00,0x00,0x00,0x0a,0x59,0x00,0x0c,0x00,0x00,0x00,0x00, +0x02,0x80,0x03,0x3c,0xee,0x7d,0x64,0x90,0x92,0x00,0x02,0x24,0x03,0x00,0x82,0x10, +0x00,0x00,0x00,0x00,0x49,0x61,0x00,0x0c,0x00,0x00,0x00,0x00,0x2f,0x61,0x00,0x0c, +0x00,0x00,0x00,0x00,0xce,0x5f,0x00,0x0c,0x00,0x00,0x00,0x00,0xb7,0x61,0x00,0x0c, +0x00,0x00,0x00,0x00,0x44,0x64,0x20,0xa6,0x9d,0x61,0x00,0x0c,0x46,0x64,0x20,0xa6, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x80,0x04,0x3c, +0x02,0x80,0x05,0x3c,0x58,0x7b,0x82,0x24,0x60,0x7b,0xa3,0x24,0x20,0x00,0xbd,0x27, +0x04,0x00,0x42,0xac,0x58,0x7b,0x82,0xac,0x60,0x7b,0xa3,0xac,0x08,0x00,0xe0,0x03, +0x04,0x00,0x63,0xac,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x01,0x80,0x02,0x3c, +0x25,0xb0,0x10,0x3c,0x18,0x03,0x03,0x36,0x2c,0x6e,0x42,0x24,0x00,0x00,0x62,0xac, +0x14,0x00,0xbf,0xaf,0x98,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x12,0x5c,0x00,0x0c, +0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x3a,0x5e,0x00,0x0c, +0xe7,0x60,0x43,0xa0,0x09,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x32,0x41,0x00,0x0c, +0x00,0x00,0x00,0x00,0x43,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x00,0x03,0x36, +0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x34,0x00,0x00,0x62,0xa4, +0x11,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x32,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00, +0x06,0x5e,0x00,0x0c,0x00,0x00,0x00,0x00,0xcb,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x80,0x04,0x3c,0x14,0x29,0x84,0x24,0x23,0x5e,0x00,0x0c,0x01,0x00,0x05,0x24, +0x01,0x80,0x04,0x3c,0x0c,0x1d,0x84,0x24,0x23,0x5e,0x00,0x0c,0x02,0x00,0x05,0x24, +0x34,0x4f,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c,0x88,0x3a,0x84,0x24, +0x23,0x5e,0x00,0x0c,0x03,0x00,0x05,0x24,0x02,0x80,0x02,0x3c,0xf8,0x7d,0x43,0x90, +0x43,0x00,0x04,0x36,0x29,0x00,0x60,0x10,0xd8,0x00,0x10,0x36,0x07,0x00,0x02,0x24, +0x2b,0x00,0x62,0x10,0x25,0xb0,0x04,0x3c,0x10,0x02,0x86,0x34,0x43,0x00,0x85,0x34, +0x03,0x00,0x02,0x24,0x10,0x00,0x03,0x24,0x00,0x00,0xa2,0xa0,0xd8,0x00,0x84,0x34, +0x00,0x00,0xc3,0xa0,0x00,0x00,0x82,0x90,0x80,0xff,0x03,0x24,0x42,0xb0,0x05,0x3c, +0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xa0,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34, +0x00,0x00,0x82,0x94,0x00,0x00,0x00,0x00,0xc0,0x00,0x42,0x34,0x00,0x00,0x82,0xa4, +0x00,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x34,0x00,0x00,0xa3,0xa0, +0x18,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24, +0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0xfe,0x1f,0x00,0x0c,0x21,0x38,0x00,0x00, +0x30,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f, +0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x00,0x00,0x80,0xa0, +0x00,0x00,0x03,0x92,0x80,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x00,0x00,0x03,0xa2, +0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0x42,0xb0,0x05,0x3c, +0xc0,0x00,0x42,0x34,0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,0x00,0x00,0x00,0x00, +0x01,0x00,0x63,0x34,0x00,0x00,0xa3,0xa0,0x18,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00, +0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00, +0xfe,0x1f,0x00,0x0c,0x21,0x38,0x00,0x00,0x30,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00, +0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0x21,0x20,0x00,0x00,0x20,0xb0,0x06,0x3c,0xff,0xff,0x05,0x34, +0x21,0x18,0x86,0x00,0x04,0x00,0x84,0x24,0x2a,0x10,0xa4,0x00,0x00,0x00,0x60,0xac, +0xfb,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xb8,0xff,0xbd,0x27,0x25,0xb0,0x04,0x3c,0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf, +0x3c,0x00,0xb7,0xaf,0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf, +0x2c,0x00,0xb3,0xaf,0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf, +0x0a,0x00,0x83,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x30, +0x0c,0x00,0x40,0x10,0x4c,0x87,0x02,0x3c,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00, +0x10,0x00,0x42,0x30,0x66,0x01,0x40,0x10,0x4c,0x87,0x02,0x3c,0x54,0x00,0x83,0x34, +0x50,0x00,0x82,0x34,0x00,0x00,0x45,0xac,0x00,0x00,0x65,0xa4,0x36,0x5c,0x00,0x08, +0x02,0x80,0x03,0x3c,0x54,0x00,0x85,0x34,0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34, +0x12,0x01,0x03,0x24,0x00,0x00,0x82,0xac,0x00,0x00,0xa3,0xac,0x02,0x80,0x03,0x3c, +0x68,0x15,0x62,0x24,0xd5,0x4a,0x43,0x90,0xda,0x4a,0x45,0x94,0x25,0xb0,0x1e,0x3c, +0x1c,0x00,0xa3,0xa3,0x60,0x4b,0x43,0x8c,0x58,0x00,0xc6,0x37,0xff,0xff,0x04,0x24, +0x10,0x00,0xa3,0xaf,0x64,0x4b,0x43,0x8c,0x5c,0x00,0xc7,0x37,0x60,0x00,0xc8,0x37, +0x14,0x00,0xa3,0xaf,0x68,0x4b,0x42,0x8c,0x64,0x00,0xc9,0x37,0x8a,0x00,0xca,0x37, +0x18,0x00,0xa2,0xaf,0x24,0x10,0x02,0x3c,0x21,0x28,0xa2,0x00,0x4c,0x81,0x02,0x3c, +0x00,0xe0,0x42,0x34,0x00,0x00,0xc2,0xac,0x96,0x01,0x03,0x24,0x28,0x28,0x02,0x24, +0x00,0x00,0xe3,0xac,0x89,0x00,0xcb,0x37,0x00,0x00,0x04,0xad,0x8c,0x00,0xcc,0x37, +0x00,0x00,0x24,0xad,0x09,0x00,0x03,0x24,0x00,0x00,0x42,0xa5,0x10,0x10,0x02,0x24, +0x00,0x00,0x63,0xa1,0x8e,0x00,0xcd,0x37,0x00,0x00,0x82,0xa5,0x0a,0x0a,0x03,0x24, +0x13,0x00,0x02,0x24,0x90,0x00,0xce,0x37,0x00,0x00,0xa3,0xa5,0x00,0x00,0xc2,0xa1, +0x25,0xb0,0x02,0x3c,0x40,0x00,0x03,0x24,0x91,0x00,0x42,0x34,0x00,0x00,0x43,0xa0, +0x25,0xb0,0x03,0x3c,0x3a,0x01,0x02,0x24,0x92,0x00,0x63,0x34,0x00,0x00,0x62,0xa4, +0xb5,0x00,0xd1,0x37,0x21,0x00,0x03,0x24,0x00,0x00,0x23,0xa2,0x10,0x00,0xa2,0x8f, +0xa0,0x00,0xd2,0x37,0xa4,0x00,0xd3,0x37,0x00,0x00,0x42,0xae,0x14,0x00,0xa3,0x8f, +0xa8,0x00,0xd4,0x37,0xac,0x00,0xd5,0x37,0x00,0x00,0x63,0xae,0x18,0x00,0xa2,0x8f, +0x25,0xb0,0x03,0x3c,0xb0,0x00,0x63,0x34,0x00,0x00,0x82,0xae,0x21,0x10,0x02,0x3c, +0xff,0x77,0x42,0x34,0x00,0x00,0xa2,0xae,0x25,0xb0,0x02,0x3c,0xd8,0x00,0x42,0x34, +0x00,0x00,0x65,0xac,0x00,0x00,0x40,0xa0,0x1c,0x00,0xa2,0x93,0x25,0xb0,0x03,0x3c, +0xb4,0x00,0x63,0x34,0x00,0x00,0x62,0xa0,0x25,0xb0,0x03,0x3c,0x04,0x00,0x02,0x24, +0xb6,0x00,0x63,0x34,0x00,0x00,0x62,0xa0,0x25,0xb0,0x03,0x3c,0x0f,0x00,0x02,0x24, +0xba,0x00,0x63,0x34,0xb9,0x00,0xdf,0x37,0x00,0x00,0xe4,0xa3,0x00,0x00,0x62,0xa4, +0x25,0xb0,0x02,0x3c,0x1a,0x01,0x42,0x34,0x16,0x01,0xd0,0x37,0x18,0x01,0xcf,0x37, +0x00,0x00,0x00,0xa6,0x25,0xb0,0x03,0x3c,0x00,0x00,0xe0,0xa5,0x00,0x00,0x40,0xa4, +0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,0xdc,0x00,0x63,0x34,0x00,0x00,0x62,0xac, +0x2f,0x00,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x32,0x32,0x63,0x34,0xd0,0x01,0x42,0x34, +0x00,0x00,0x43,0xac,0x5e,0x00,0x02,0x3c,0x25,0xb0,0x03,0x3c,0x32,0x43,0x42,0x34, +0xd4,0x01,0x63,0x34,0x00,0x00,0x62,0xac,0x08,0x00,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x30,0xa5,0x63,0x34,0xd8,0x01,0x42,0x34,0x00,0x00,0x43,0xac,0xdc,0x01,0xc4,0x37, +0x02,0x80,0x03,0x3c,0x49,0xa5,0x02,0x34,0xee,0x7d,0x6d,0x90,0x00,0x00,0x82,0xac, +0xc2,0x00,0x02,0x3c,0x1a,0x06,0x03,0x24,0x51,0x10,0x42,0x34,0xe0,0x01,0xc5,0x37, +0xf4,0x01,0xc6,0x37,0xf8,0x01,0xc7,0x37,0x07,0x07,0x04,0x24,0x00,0x00,0xa3,0xa4, +0x00,0x02,0xc8,0x37,0x00,0x00,0xc4,0xa4,0x26,0x00,0x03,0x24,0x00,0x00,0xe2,0xac, +0x03,0x02,0xc9,0x37,0x04,0x00,0x02,0x24,0x00,0x00,0x03,0xa5,0x36,0x02,0xca,0x37, +0x00,0x00,0x22,0xa1,0xc0,0x01,0x03,0x24,0x0c,0x00,0x02,0x24,0x34,0x02,0xcb,0x37, +0x00,0x00,0x42,0xa1,0x37,0x02,0xcc,0x37,0x00,0x00,0x63,0xa5,0x03,0x00,0x02,0x24, +0x22,0x00,0x03,0x24,0x00,0x00,0x82,0xa1,0xd6,0x00,0xa3,0x11,0x1b,0x1b,0x02,0x3c, +0x13,0x13,0x02,0x3c,0x13,0x13,0x42,0x34,0x60,0x01,0xc3,0x37,0x64,0x01,0xc4,0x37, +0x68,0x01,0xc5,0x37,0x7c,0x01,0xca,0x37,0x6c,0x01,0xc6,0x37,0x70,0x01,0xc7,0x37, +0x74,0x01,0xc8,0x37,0x78,0x01,0xc9,0x37,0x00,0x00,0x62,0xac,0x00,0x00,0x82,0xac, +0x02,0x80,0x03,0x3c,0x00,0x00,0xa2,0xac,0x00,0x00,0xc2,0xac,0x00,0x00,0xe2,0xac, +0x00,0x00,0x02,0xad,0x00,0x00,0x22,0xad,0x00,0x00,0x42,0xad,0xee,0x7d,0x65,0x90, +0x25,0xb0,0x0c,0x3c,0x01,0x70,0x03,0x3c,0x80,0x01,0x82,0x35,0x08,0x5f,0x63,0x34, +0x22,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0xb5,0x00,0xa4,0x10,0x0f,0x1f,0x02,0x3c, +0x92,0x00,0x02,0x24,0xb2,0x00,0xa2,0x10,0x0f,0x1f,0x02,0x3c,0x0f,0x10,0x02,0x3c, +0x00,0xf0,0x51,0x34,0xf7,0x01,0x92,0x35,0x15,0xf0,0x4d,0x34,0x77,0x00,0x0e,0x24, +0x84,0x01,0x87,0x35,0x88,0x01,0x88,0x35,0x10,0xf0,0x44,0x34,0x8c,0x01,0x85,0x35, +0x05,0xf0,0x42,0x34,0x00,0x00,0xed,0xac,0x90,0x01,0x83,0x35,0x00,0x00,0x04,0xad, +0x94,0x01,0x86,0x35,0x00,0x00,0xa2,0xac,0xf5,0x0f,0x02,0x24,0x00,0x00,0x71,0xac, +0x25,0xb0,0x05,0x3c,0x00,0x00,0xc2,0xac,0x98,0x01,0x89,0x35,0x9c,0x01,0x8a,0x35, +0xf0,0x0f,0x03,0x24,0x0d,0x00,0x02,0x24,0x00,0x00,0x23,0xad,0xa0,0x01,0x8b,0x35, +0x00,0x00,0x42,0xad,0xa7,0x01,0xb7,0x34,0xf6,0x01,0x8c,0x35,0xff,0xff,0x02,0x24, +0x00,0x00,0x6d,0xad,0x00,0x00,0x8e,0xa1,0x00,0x00,0x4e,0xa2,0x00,0x00,0xe2,0xa2, +0x25,0xb0,0x02,0x3c,0xa8,0x01,0xb6,0x34,0xff,0xff,0x09,0x24,0xac,0x01,0x42,0x34, +0x00,0x00,0xc9,0xae,0x03,0x04,0x04,0x3c,0x00,0x00,0x49,0xac,0x07,0x08,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x01,0x02,0x84,0x34,0x05,0x06,0x63,0x34,0xb4,0x01,0xb1,0x34, +0xb8,0x01,0xb2,0x34,0xbc,0x01,0xb3,0x34,0xb0,0x01,0x42,0x34,0x00,0x00,0x44,0xac, +0x00,0x00,0x23,0xae,0x25,0xb0,0x02,0x3c,0x00,0x00,0x44,0xae,0x00,0x00,0x63,0xae, +0x25,0xb0,0x03,0x3c,0x0c,0x00,0x06,0x24,0xc0,0x01,0xb4,0x34,0xc1,0x01,0xb5,0x34, +0x0d,0x00,0x08,0x24,0xc2,0x01,0x63,0x34,0xc3,0x01,0x42,0x34,0x00,0x00,0x86,0xa2, +0xc4,0x01,0xab,0x34,0x00,0x00,0xa6,0xa2,0xc5,0x01,0xac,0x34,0x00,0x00,0x66,0xa0, +0x0e,0x00,0x07,0x24,0x00,0x00,0x48,0xa0,0xc6,0x01,0xaa,0x34,0xc7,0x01,0xad,0x34, +0x0f,0x00,0x02,0x24,0x00,0x00,0x68,0xa1,0x00,0x00,0x87,0xa1,0x00,0x00,0x47,0xa1, +0x00,0x00,0xa2,0xa1,0x57,0x01,0x02,0x3c,0x48,0x00,0xbf,0x34,0x46,0x00,0xae,0x34, +0x0e,0xe2,0x42,0x34,0x00,0x00,0xc0,0xa5,0x4c,0x00,0xbe,0x34,0x00,0x00,0xe2,0xaf, +0x4d,0x00,0xb9,0x34,0x80,0xff,0x02,0x24,0x00,0x00,0xc0,0xa3,0x00,0x00,0x22,0xa3, +0x25,0xb0,0x02,0x3c,0xbc,0x00,0x03,0x24,0x40,0x00,0x42,0x34,0x00,0x00,0x43,0xa4, +0x25,0xb0,0x03,0x3c,0x64,0x03,0xb8,0x34,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34, +0x00,0x00,0x00,0xa3,0xd8,0x00,0xa7,0x34,0x00,0x00,0x62,0xa4,0x00,0x00,0xe3,0x90, +0x80,0xff,0x02,0x24,0x2a,0xb0,0x04,0x3c,0x25,0x18,0x62,0x00,0x00,0x00,0xe3,0xa0, +0x26,0xb0,0x06,0x3c,0x30,0x00,0x89,0x34,0x20,0x20,0x02,0x24,0x38,0x00,0x84,0x34, +0x40,0x00,0x03,0x24,0x00,0x00,0x82,0xa4,0x79,0x00,0xc8,0x34,0x00,0x00,0x23,0xa1, +0x94,0x00,0xaa,0x34,0x16,0x00,0x02,0x24,0x64,0x00,0x03,0x24,0x00,0x00,0x02,0xa1, +0x7c,0x00,0xd2,0x34,0x00,0x00,0x43,0xa5,0x98,0x00,0xab,0x34,0x7a,0x00,0xc6,0x34, +0x22,0x00,0x02,0x24,0x04,0x00,0x03,0x24,0x00,0x00,0x62,0xa5,0x9c,0x00,0xac,0x34, +0x00,0x00,0xc3,0xa0,0x20,0x0c,0x02,0x24,0x0a,0x00,0x03,0x24,0x00,0x00,0x42,0xa6, +0x9a,0x00,0xad,0x34,0x00,0x00,0x83,0xa1,0x96,0x00,0xae,0x34,0xff,0x03,0x02,0x24, +0x02,0x00,0x03,0x24,0x00,0x00,0xa2,0xa5,0x00,0x00,0xc3,0xa5,0x25,0xb0,0x03,0x3c, +0x20,0x00,0x02,0x24,0xb7,0x00,0x63,0x34,0x00,0x00,0x62,0xa0,0x89,0x00,0xb1,0x34, +0x09,0x00,0x03,0x24,0x00,0x00,0x23,0xa2,0x44,0x00,0xa5,0x34,0x00,0x00,0xa3,0x94, +0x02,0x80,0x02,0x3c,0x68,0x15,0x46,0x24,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00, +0x00,0x00,0xa3,0xa4,0x00,0x00,0xa2,0x94,0xd5,0x4a,0xc4,0x90,0x04,0x02,0x03,0x24, +0x00,0x02,0x42,0x34,0x00,0x00,0xa2,0xa4,0x29,0xb0,0x02,0x3c,0x40,0x00,0x42,0x34, +0x00,0x00,0x43,0xa4,0x3a,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x00,0xbf,0x8f, +0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f, +0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f, +0x20,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27, +0x54,0x00,0x85,0x34,0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34,0x12,0x01,0x03,0x24, +0x00,0x00,0x82,0xac,0x00,0x00,0xa3,0xa4,0x36,0x5c,0x00,0x08,0x02,0x80,0x03,0x3c, +0x00,0xf0,0x51,0x34,0xf7,0x01,0x92,0x35,0x15,0xf0,0x4d,0x34,0xea,0x5c,0x00,0x08, +0xff,0xff,0x0e,0x24,0xc8,0x5c,0x00,0x08,0x1b,0x1b,0x42,0x34,0x25,0xb0,0x03,0x3c, +0x25,0xb0,0x08,0x3c,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,0x02,0x80,0x04,0x3c, +0x00,0x00,0x62,0xa4,0x94,0x8d,0x84,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35, +0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00, +0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24, +0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c, +0x02,0x80,0x02,0x3c,0x8c,0x87,0x44,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35, +0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00, +0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24, +0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,0x02,0x80,0x05,0x3c,0x04,0x78,0x42,0x24, +0x02,0x80,0x03,0x3c,0x2c,0x7e,0xa2,0xac,0x00,0x80,0x02,0x3c,0xcc,0x7e,0x60,0xac, +0x2c,0x7e,0xa4,0x24,0x02,0x80,0x03,0x3c,0xc8,0x06,0x42,0x24,0xd0,0x7e,0x60,0xa4, +0x08,0x00,0x82,0xac,0x02,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0xd2,0x7e,0x60,0xa4, +0x02,0x80,0x06,0x3c,0xa4,0x0a,0x42,0x24,0x00,0x80,0x03,0x3c,0xd4,0x7e,0xc7,0x24, +0x14,0x00,0x82,0xac,0x54,0x08,0x63,0x24,0x02,0x80,0x02,0x3c,0xd4,0x7e,0xc0,0xac, +0x10,0x00,0x83,0xac,0x04,0x00,0xe0,0xac,0xdc,0x7e,0x40,0xa0,0x00,0x80,0x02,0x3c, +0x1c,0x1c,0x42,0x24,0x3c,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c, +0x38,0x0d,0x63,0x24,0xc8,0x10,0x42,0x24,0x1c,0x00,0x83,0xac,0x20,0x00,0x82,0xac, +0x00,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0x54,0x14,0x63,0x24,0x38,0x18,0x42,0x24, +0x24,0x00,0x83,0xac,0x28,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,0x01,0x80,0x02,0x3c, +0x10,0x22,0x63,0x24,0xd0,0x04,0x42,0x24,0x2c,0x00,0x83,0xac,0x30,0x00,0x82,0xac, +0x00,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0x78,0x1c,0x63,0x24,0x00,0x03,0x42,0x24, +0x38,0x00,0x83,0xac,0x08,0x00,0xe0,0x03,0x4c,0x00,0x82,0xac,0x25,0xb0,0x02,0x3c, +0x08,0x00,0x42,0x34,0x00,0x00,0x43,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x02,0x80,0x0e,0x3c,0x02,0x80,0x08,0x3c,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c, +0xf8,0x03,0x4d,0x24,0x00,0x14,0x6c,0x24,0x01,0x00,0x07,0x24,0x00,0x00,0xcb,0x25, +0xff,0xff,0x0a,0x24,0x00,0x04,0x09,0x25,0x80,0x1a,0x07,0x00,0x21,0x10,0x6b,0x00, +0x00,0x00,0x42,0xac,0x90,0x00,0x4a,0xac,0x00,0x04,0x04,0x8d,0x01,0x00,0xe7,0x24, +0x08,0x00,0x45,0x24,0x21,0x18,0x6d,0x00,0x05,0x00,0xe6,0x28,0x04,0x00,0x82,0xac, +0x00,0x00,0x44,0xac,0x04,0x00,0x49,0xac,0x00,0x04,0x02,0xad,0x8c,0x00,0x40,0xac, +0x6c,0x00,0xa3,0xac,0xf0,0xff,0xc0,0x14,0x68,0x00,0xac,0xac,0x08,0x00,0xe0,0x03, +0x00,0x00,0xc9,0xad,0x05,0x00,0xa2,0x2c,0x13,0x00,0x40,0x10,0xff,0xff,0x07,0x24, +0x02,0x80,0x02,0x3c,0x80,0x1a,0x05,0x00,0x00,0x00,0x42,0x24,0x0e,0x00,0xa0,0x10, +0x21,0x30,0x62,0x00,0x90,0x00,0xc3,0x8c,0xff,0xff,0x02,0x24,0x0a,0x00,0x62,0x14, +0x00,0x00,0x00,0x00,0x8c,0x00,0xc2,0x8c,0x00,0x00,0x00,0x00,0x06,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x24,0x88,0x00,0xc4,0xac,0x8c,0x00,0xc2,0xac, +0x90,0x00,0xc5,0xac,0x21,0x38,0xa0,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00, +0x25,0xb0,0x04,0x3c,0x01,0x80,0x02,0x3c,0x18,0x03,0x85,0x34,0xe8,0x78,0x42,0x24, +0xe0,0xff,0xbd,0x27,0x00,0x00,0xa2,0xac,0x1b,0x00,0x86,0x34,0xdb,0xff,0x03,0x24, +0x27,0x00,0x84,0x34,0x07,0x00,0x02,0x24,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf, +0x00,0x00,0x83,0xa0,0x18,0x00,0xbf,0xaf,0x00,0x00,0xc2,0xa0,0x01,0x00,0x11,0x24, +0x21,0x80,0x00,0x00,0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x02,0x01,0x00,0x02,0x26, +0xff,0x00,0x50,0x30,0x2b,0x18,0x30,0x02,0xfa,0xff,0x60,0x10,0x00,0x00,0x00,0x00, +0x2a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x40,0x10,0x03,0x3c,0xff,0xff,0x44,0x30, +0x25,0xc0,0x83,0x00,0xf4,0x64,0x58,0xac,0x40,0x00,0x18,0x27,0x00,0x65,0x58,0xac, +0x40,0x00,0x18,0x27,0x0c,0x65,0x58,0xac,0x40,0x00,0x18,0x27,0x18,0x65,0x58,0xac, +0x40,0x00,0x18,0x27,0xe0,0xff,0xbd,0x27,0x24,0x65,0x58,0xac,0x40,0x00,0x18,0x27, +0x1c,0x00,0xb7,0xaf,0x18,0x00,0xb6,0xaf,0x14,0x00,0xb5,0xaf,0x10,0x00,0xb4,0xaf, +0x0c,0x00,0xb3,0xaf,0x08,0x00,0xb2,0xaf,0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf, +0x30,0x65,0x58,0xac,0x00,0x65,0x45,0x8c,0x0c,0x65,0x46,0x8c,0x18,0x65,0x47,0x8c, +0x24,0x65,0x48,0x8c,0x30,0x65,0x49,0x8c,0x40,0x00,0x18,0x27,0x3c,0x65,0x58,0xac, +0x21,0x50,0x00,0x03,0x25,0x20,0x83,0x00,0x40,0x00,0x18,0x27,0x20,0x10,0x03,0x3c, +0xf0,0x64,0x44,0xac,0xfc,0x64,0x45,0xac,0x08,0x65,0x46,0xac,0x14,0x65,0x47,0xac, +0x20,0x65,0x48,0xac,0x2c,0x65,0x49,0xac,0x25,0xb0,0x06,0x3c,0x88,0x64,0x43,0xac, +0x84,0x64,0x43,0xac,0x94,0x64,0x43,0xac,0x90,0x64,0x43,0xac,0xa0,0x64,0x43,0xac, +0x9c,0x64,0x43,0xac,0xac,0x64,0x43,0xac,0xa8,0x64,0x43,0xac,0x48,0x65,0x58,0xac, +0x00,0x02,0x18,0x27,0x38,0x65,0x4a,0xac,0x60,0x65,0x58,0xac,0xb8,0x64,0x43,0xac, +0xb4,0x64,0x43,0xac,0xc4,0x64,0x43,0xac,0xc0,0x64,0x43,0xac,0xd0,0x64,0x43,0xac, +0xcc,0x64,0x43,0xac,0xac,0x00,0xc4,0x34,0xb0,0x00,0xc5,0x34,0x00,0x00,0x92,0x8c, +0x48,0x65,0x50,0x8c,0x00,0x00,0xb3,0x8c,0x21,0x10,0x04,0x3c,0x23,0x10,0x09,0x3c, +0x22,0x10,0x0c,0x3c,0x02,0x80,0x14,0x3c,0x02,0x80,0x15,0x3c,0x02,0x80,0x16,0x3c, +0x02,0x80,0x17,0x3c,0x24,0x10,0x05,0x3c,0x21,0x88,0x00,0x03,0x68,0x7b,0x87,0x26, +0x00,0x04,0x18,0x27,0x70,0x7b,0xa8,0x26,0x78,0x7b,0xca,0x26,0x80,0x7b,0xeb,0x26, +0x00,0x04,0x2d,0x35,0x00,0x40,0x8e,0x34,0x00,0x80,0x8f,0x35,0x00,0x01,0xc6,0x34, +0x44,0x65,0x50,0xac,0x5c,0x65,0x51,0xac,0xc4,0x65,0x4d,0xac,0x88,0x65,0x52,0xac, +0x94,0x65,0x4e,0xac,0xb8,0x65,0x4f,0xac,0xac,0x65,0x53,0xac,0x00,0x00,0xc5,0xac, +0xa8,0x65,0x45,0xac,0xc8,0x65,0x43,0xac,0xd4,0x65,0x58,0xac,0xdc,0x64,0x43,0xac, +0xd8,0x64,0x43,0xac,0x66,0x65,0x40,0xa4,0x65,0x65,0x40,0xa0,0x64,0x65,0x40,0xa0, +0xbc,0x65,0x49,0xac,0xc0,0x65,0x49,0xac,0x80,0x65,0x44,0xac,0x84,0x65,0x44,0xac, +0x8c,0x65,0x44,0xac,0x90,0x65,0x44,0xac,0xb0,0x65,0x4c,0xac,0xb4,0x65,0x4c,0xac, +0xa4,0x65,0x45,0xac,0xcc,0x65,0x43,0xac,0xd8,0x65,0x58,0xac,0x04,0x00,0x08,0xad, +0x68,0x7b,0x87,0xae,0x04,0x00,0x4a,0xad,0x70,0x7b,0xa8,0xae,0x04,0x00,0x6b,0xad, +0x78,0x7b,0xca,0xae,0x80,0x7b,0xeb,0xae,0x04,0x00,0xe7,0xac,0x02,0x80,0x02,0x3c, +0x00,0x14,0x43,0x24,0x21,0x20,0xe0,0x00,0x03,0x00,0x06,0x24,0x21,0x10,0x80,0x00, +0xff,0xff,0xc6,0x24,0x08,0x00,0x78,0xac,0x00,0x00,0x63,0xac,0x10,0x00,0x60,0xac, +0x00,0x00,0x67,0xac,0x21,0x20,0x60,0x00,0x04,0x00,0x62,0xac,0x00,0x00,0x43,0xac, +0x00,0x01,0x18,0x27,0xf5,0xff,0xc1,0x04,0x18,0x00,0x63,0x24,0x02,0x80,0x02,0x3c, +0x70,0x7b,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x04,0x00,0x28,0x8d, +0x60,0x14,0x4b,0x24,0x04,0x00,0xe4,0xac,0x00,0x14,0x6a,0x24,0x01,0x00,0x07,0x24, +0x21,0x28,0x00,0x00,0x07,0x00,0x06,0x24,0x21,0x20,0xab,0x00,0x21,0x10,0xaa,0x00, +0xff,0xff,0xc6,0x24,0x68,0x00,0x58,0xac,0x70,0x00,0x47,0xac,0x18,0x00,0xa5,0x24, +0x00,0x00,0x89,0xac,0x04,0x00,0x88,0xac,0x00,0x00,0x04,0xad,0x00,0x01,0x18,0x27, +0xf5,0xff,0xc1,0x04,0x21,0x40,0x80,0x00,0x02,0x80,0x02,0x3c,0x78,0x7b,0x4a,0x24, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x04,0x00,0x45,0x8d,0x20,0x15,0x4b,0x24, +0x04,0x00,0x24,0xad,0x02,0x00,0x07,0x24,0x00,0x14,0x69,0x24,0x21,0x20,0x00,0x00, +0x01,0x00,0x06,0x24,0x21,0x40,0x8b,0x00,0x21,0x10,0x89,0x00,0xff,0xff,0xc6,0x24, +0x28,0x01,0x58,0xac,0x30,0x01,0x47,0xac,0x18,0x00,0x84,0x24,0x00,0x00,0x0a,0xad, +0x04,0x00,0x05,0xad,0x00,0x00,0xa8,0xac,0x00,0x02,0x18,0x27,0xf5,0xff,0xc1,0x04, +0x21,0x28,0x00,0x01,0x02,0x80,0x05,0x3c,0x80,0x7b,0xa5,0x24,0x04,0x00,0xa6,0x8c, +0x1c,0x00,0xb7,0x8f,0x18,0x00,0xb6,0x8f,0x14,0x00,0xb5,0x8f,0x10,0x00,0xb4,0x8f, +0x0c,0x00,0xb3,0x8f,0x08,0x00,0xb2,0x8f,0x04,0x00,0xb1,0x8f,0x00,0x00,0xb0,0x8f, +0x02,0x80,0x07,0x3c,0x02,0x80,0x03,0x3c,0x50,0x15,0xe4,0x24,0x00,0x14,0x63,0x24, +0x03,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x58,0x01,0x78,0xac,0x04,0x00,0x48,0xad, +0x04,0x00,0xa4,0xac,0x60,0x01,0x62,0xac,0x50,0x15,0xe5,0xac,0x04,0x00,0x86,0xac, +0x08,0x00,0xe0,0x03,0x00,0x00,0xc4,0xac,0xc8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c, +0x02,0x80,0x03,0x3c,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x70,0x9e,0x74,0x24, +0xe4,0x9e,0x53,0x24,0x02,0x80,0x03,0x3c,0xff,0xff,0x02,0x3c,0x2c,0x00,0xb5,0xaf, +0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x30,0x00,0xbf,0xaf, +0xff,0x1f,0x55,0x34,0x68,0x15,0x70,0x24,0x21,0x88,0x00,0x00,0x02,0x80,0x12,0x3c, +0xaa,0x4f,0x00,0x0c,0x21,0x20,0x20,0x02,0x84,0x51,0x02,0x8e,0x6c,0x00,0x86,0x8e, +0x50,0x9e,0x43,0x26,0x6c,0x00,0x64,0x8e,0x1b,0x00,0x65,0x90,0x24,0x10,0x55,0x00, +0x00,0x20,0x42,0x34,0xff,0xf1,0x03,0x24,0x21,0x20,0x86,0x00,0x24,0x10,0x43,0x00, +0x00,0x29,0x05,0x00,0x42,0x20,0x04,0x00,0x00,0x02,0x42,0x34,0x50,0x51,0x04,0xae, +0x74,0x51,0x05,0xae,0x84,0x51,0x02,0xae,0x78,0x51,0x05,0xae,0x21,0x30,0x00,0x00, +0x21,0x10,0x06,0x02,0x01,0x00,0xc6,0x24,0x1d,0x00,0xc3,0x28,0xa5,0x51,0x40,0xa0, +0x88,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,0xc2,0x51,0x40,0xa0,0x01,0x00,0x31,0x26, +0x20,0x00,0x22,0x2a,0xe0,0x51,0x00,0xae,0xe1,0xff,0x40,0x14,0x94,0x00,0x10,0x26, +0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x68,0x15,0x4b,0x24,0x02,0x80,0x02,0x3c, +0xe4,0x9e,0x6f,0x24,0x70,0x9e,0x4d,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c, +0x50,0x9e,0x6e,0x24,0x30,0x9e,0x4c,0x24,0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00, +0x21,0x20,0x6d,0x00,0x21,0x10,0x6f,0x00,0x21,0x28,0x2e,0x02,0x21,0x30,0x2c,0x02, +0x00,0x00,0x88,0x8c,0x00,0x00,0xa9,0x90,0x00,0x00,0xc7,0x90,0x00,0x00,0x4a,0x8c, +0x21,0x10,0x2b,0x02,0x01,0x00,0x31,0x26,0x21,0x18,0x6b,0x00,0x1d,0x00,0x24,0x2a, +0xec,0x44,0x68,0xac,0xca,0x44,0x47,0xa0,0x60,0x45,0x6a,0xac,0xef,0xff,0x80,0x14, +0x90,0x44,0x49,0xa0,0x02,0x80,0x02,0x3c,0x68,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c, +0x02,0x80,0x02,0x3c,0x0c,0x9d,0x6b,0x24,0xac,0x9b,0x4c,0x24,0x21,0x88,0x00,0x00, +0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,0x21,0x38,0x2b,0x01, +0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01, +0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc5,0x43,0x64,0xa0,0xf8,0xff,0x40,0x14, +0x34,0x43,0x65,0xa0,0x21,0x10,0x2c,0x02,0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90, +0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x73,0x44,0x64,0xa0, +0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,0x52,0x00,0x02,0x24, +0x10,0x00,0xa2,0xa3,0x41,0x00,0x03,0x24,0x4d,0x00,0x02,0x24,0x02,0x80,0x07,0x3c, +0xdc,0xa4,0xe7,0x24,0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0xe8,0x03,0x03,0x24, +0x01,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00, +0x60,0x3e,0xc6,0x24,0x0c,0x00,0xe3,0xac,0x14,0x00,0xe2,0xa0,0x88,0x0e,0x00,0x0c, +0x13,0x00,0xa0,0xa3,0x30,0x00,0xbf,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c, +0x42,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3,0x55,0x60,0x40,0xa0,0x4e,0x00,0x03,0x24, +0x43,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x14,0xa5,0xe7,0x24,0x11,0x00,0xa2,0xa3, +0x12,0x00,0xa3,0xa3,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,0x00,0x80,0x06,0x3c, +0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xec,0x4f,0xc6,0x24,0x0c,0x00,0xe2,0xac, +0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0x88,0x0e,0x00,0x0c,0x13,0x00,0xa0,0xa3, +0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0x48,0xfd,0xbd,0x27,0xb4,0x02,0xb3,0xaf,0x02,0x80,0x02,0x3c,0x02,0x80,0x13,0x3c, +0xf0,0x9f,0x46,0x24,0x68,0x15,0x63,0x26,0xb0,0x02,0xb2,0xaf,0xac,0x02,0xb1,0xaf, +0xa8,0x02,0xb0,0xaf,0x03,0x40,0x60,0xa0,0x21,0x38,0xa0,0x03,0x90,0x00,0xc8,0x24, +0x00,0x00,0xc2,0x8c,0x04,0x00,0xc3,0x8c,0x08,0x00,0xc4,0x8c,0x0c,0x00,0xc5,0x8c, +0x10,0x00,0xc6,0x24,0x00,0x00,0xe2,0xac,0x04,0x00,0xe3,0xac,0x08,0x00,0xe4,0xac, +0x0c,0x00,0xe5,0xac,0xf6,0xff,0xc8,0x14,0x10,0x00,0xe7,0x24,0x00,0x00,0xc3,0x8c, +0x02,0x80,0x02,0x3c,0x84,0xa0,0x58,0x24,0x00,0x00,0xe3,0xac,0x98,0x00,0xb9,0x27, +0x00,0x01,0x12,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x09,0x00,0x04,0x93, +0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,0x04,0x00,0x10,0x93, +0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,0x0c,0x00,0x0e,0x93, +0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,0x0b,0x00,0x0a,0x93, +0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x00,0x22,0x04,0x00, +0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,0x25,0x20,0x8f,0x00, +0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,0x00,0x3c,0x07,0x00, +0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,0x25,0x38,0xe4,0x00, +0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,0x00,0x56,0x0a,0x00, +0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,0x25,0x50,0x47,0x01, +0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,0x04,0x00,0x29,0xaf, +0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,0x10,0x00,0x39,0x27, +0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,0x02,0x00,0x04,0x93, +0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,0x03,0x00,0x07,0x93, +0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,0x25,0x18,0x68,0x00, +0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,0x25,0x28,0xa3,0x00, +0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,0x02,0x80,0x02,0x3c,0x25,0x38,0xe4,0x00, +0x25,0x30,0xc5,0x00,0x8c,0xa1,0x58,0x24,0x04,0x00,0x26,0xaf,0x00,0x00,0x27,0xaf, +0x00,0x01,0x12,0x27,0xa0,0x01,0xb9,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93, +0x09,0x00,0x04,0x93,0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93, +0x04,0x00,0x10,0x93,0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93, +0x0c,0x00,0x0e,0x93,0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93, +0x0b,0x00,0x0a,0x93,0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00, +0x00,0x22,0x04,0x00,0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00, +0x25,0x20,0x8f,0x00,0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00, +0x00,0x3c,0x07,0x00,0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01, +0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00, +0x00,0x56,0x0a,0x00,0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01, +0x25,0x50,0x47,0x01,0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf, +0x04,0x00,0x29,0xaf,0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17, +0x10,0x00,0x39,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93, +0x02,0x00,0x04,0x93,0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93, +0x03,0x00,0x07,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00, +0x25,0x18,0x68,0x00,0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00, +0x25,0x28,0xa3,0x00,0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,0x25,0x30,0xc5,0x00, +0x25,0x38,0xe4,0x00,0x02,0x80,0x02,0x3c,0x04,0x00,0x26,0xaf,0x00,0x00,0x27,0xaf, +0x68,0x15,0x46,0x24,0x21,0x50,0x00,0x00,0x80,0x20,0x0a,0x00,0x21,0x10,0x9d,0x00, +0x00,0x00,0x45,0x8c,0x01,0x00,0x43,0x25,0xff,0x00,0x6a,0x30,0x21,0x20,0x86,0x00, +0x25,0x00,0x42,0x2d,0xf8,0xff,0x40,0x14,0x18,0x40,0x85,0xac,0x02,0x80,0x02,0x3c, +0x68,0x15,0x4b,0x24,0x21,0x50,0x00,0x00,0xc0,0x10,0x0a,0x00,0x21,0x48,0x5d,0x00, +0x21,0x38,0x00,0x00,0x21,0x40,0x4b,0x00,0x21,0x10,0x27,0x01,0xa0,0x01,0x46,0x90, +0x98,0x00,0x45,0x90,0x01,0x00,0xe4,0x24,0x21,0x18,0x07,0x01,0xff,0x00,0x87,0x30, +0x08,0x00,0xe2,0x2c,0xb4,0x41,0x66,0xa0,0xf7,0xff,0x40,0x14,0xac,0x40,0x65,0xa0, +0x01,0x00,0x42,0x25,0xff,0x00,0x4a,0x30,0x21,0x00,0x43,0x2d,0xef,0xff,0x60,0x14, +0xc0,0x10,0x0a,0x00,0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90, +0x00,0x00,0x00,0x00,0x20,0x00,0x63,0x30,0x42,0x00,0x60,0x10,0x68,0x15,0x64,0x26, +0x33,0x00,0x02,0x24,0xc1,0x42,0x62,0xa1,0x1c,0x00,0x03,0x24,0x0f,0x00,0x02,0x24, +0xbc,0x42,0x63,0xa1,0xbd,0x42,0x62,0xa1,0x68,0x15,0x65,0x26,0x08,0x40,0xa4,0x8c, +0xff,0x7f,0x08,0x3c,0xff,0xff,0x08,0x35,0xc0,0xff,0x02,0x24,0x24,0x20,0x88,0x00, +0x24,0x20,0x82,0x00,0x0c,0x00,0x84,0x34,0xff,0xc0,0x02,0x24,0x24,0x20,0x82,0x00, +0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x00,0x18,0x84,0x34,0xbf,0xff,0x03,0x3c, +0x24,0x20,0x82,0x00,0xff,0xff,0x63,0x34,0x7f,0xff,0x02,0x3c,0x24,0x20,0x83,0x00, +0xff,0xff,0x42,0x34,0x24,0x20,0x82,0x00,0x0c,0x40,0xa6,0x8c,0x7f,0xff,0x03,0x24, +0x40,0x40,0x84,0x34,0xff,0xff,0x02,0x3c,0x24,0x20,0x83,0x00,0xff,0x7f,0x42,0x34, +0xff,0xbf,0x03,0x3c,0x10,0x40,0xa7,0x8c,0x24,0x20,0x82,0x00,0xff,0xff,0x63,0x34, +0xff,0x9f,0x02,0x3c,0x24,0x30,0xc3,0x00,0xff,0xff,0x42,0x34,0xff,0x3f,0x03,0x3c, +0x24,0x20,0x82,0x00,0xff,0xff,0x63,0x34,0x12,0x00,0x02,0x24,0xb4,0x02,0xb3,0x8f, +0xb0,0x02,0xb2,0x8f,0xac,0x02,0xb1,0x8f,0xa8,0x02,0xb0,0x8f,0x24,0x38,0xe3,0x00, +0xc7,0x42,0xa2,0xa0,0x1f,0x00,0x03,0x24,0x01,0x00,0x02,0x24,0x24,0x30,0xc8,0x00, +0xbe,0x42,0xa3,0xa0,0xc0,0x42,0xa2,0xa0,0xff,0x00,0x03,0x24,0xff,0xff,0x02,0x24, +0xb8,0x02,0xbd,0x27,0x08,0x40,0xa4,0xac,0x10,0x40,0xa7,0xac,0x0c,0x40,0xa6,0xac, +0xc2,0x42,0xa2,0xa0,0xc4,0x42,0xa3,0xa4,0xbf,0x42,0xa0,0xa0,0x08,0x00,0xe0,0x03, +0xc6,0x42,0xa0,0xa0,0x33,0x00,0x02,0x24,0xc1,0x42,0x82,0xa0,0x0d,0x00,0x03,0x24, +0x03,0x00,0x02,0x24,0xbc,0x42,0x83,0xa0,0xa8,0x60,0x00,0x08,0xbd,0x42,0x82,0xa0, +0x02,0x80,0x07,0x3c,0x68,0x15,0xe7,0x24,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf, +0xe6,0x42,0xe0,0xa0,0xe4,0x42,0xe8,0x8c,0xff,0xef,0x02,0x3c,0xff,0xff,0x42,0x34, +0xff,0xbf,0x03,0x3c,0x00,0x40,0xe9,0x8c,0x24,0x40,0x02,0x01,0xff,0xff,0x63,0x34, +0xff,0x7f,0x02,0x3c,0x24,0x40,0x03,0x01,0xff,0xff,0x42,0x34,0xf0,0xff,0x04,0x24, +0x24,0x40,0x02,0x01,0xff,0xdf,0x02,0x3c,0x24,0x48,0x24,0x01,0xff,0xf0,0x03,0x24, +0xff,0xff,0x42,0x34,0x24,0x48,0x23,0x01,0x24,0x40,0x02,0x01,0x20,0x00,0x03,0x24, +0x0a,0x00,0x02,0x24,0xd2,0x42,0xe2,0xa0,0xd7,0x42,0xe3,0xa0,0x20,0x00,0x02,0x24, +0x00,0x01,0x03,0x24,0xc8,0x42,0xe2,0xa4,0xca,0x42,0xe3,0xa4,0x00,0x02,0x02,0x24, +0x49,0x00,0x03,0x24,0x02,0x80,0x0a,0x3c,0x00,0x40,0xe9,0xac,0xe4,0x42,0xe8,0xac, +0xf8,0xa4,0x4a,0x25,0xff,0xff,0x0c,0x34,0x3e,0x00,0x0d,0x24,0x1c,0x00,0x0e,0x24, +0x01,0x00,0x0b,0x24,0x11,0x00,0xa3,0xa3,0xcc,0x42,0xe2,0xa4,0xd0,0x07,0x03,0x24, +0x44,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,0x10,0x00,0xa2,0xa3,0x10,0x00,0xa5,0x27, +0x47,0x00,0x02,0x24,0x21,0x20,0x40,0x01,0xa4,0x50,0xc6,0x24,0x04,0x40,0xec,0xac, +0xd0,0x42,0xed,0xa0,0xd1,0x42,0xee,0xa0,0x02,0x40,0xeb,0xa0,0x0c,0x00,0x43,0xad, +0x14,0x00,0x4b,0xa1,0xe8,0x63,0xec,0xac,0xce,0x42,0xed,0xa0,0xcf,0x42,0xee,0xa0, +0xd6,0x42,0xe0,0xa0,0xd4,0x42,0xe0,0xa0,0x12,0x00,0xa2,0xa3,0x88,0x0e,0x00,0x0c, +0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x50,0x00,0x03,0x24, +0x10,0x00,0xa3,0xa3,0x36,0x62,0x40,0xa0,0x41,0x00,0x03,0x24,0x52,0x00,0x02,0x24, +0x02,0x80,0x07,0x3c,0xa0,0xa5,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3, +0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27, +0x21,0x20,0xe0,0x00,0x74,0x67,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0, +0x18,0x00,0xbf,0xaf,0x88,0x0e,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd8,0xff,0xbd,0x27, +0x18,0x00,0xb0,0xaf,0x02,0x80,0x10,0x3c,0x68,0x15,0x10,0x26,0x20,0x00,0xbf,0xaf, +0x1c,0x00,0xb1,0xaf,0x00,0x40,0x09,0x8e,0xff,0xff,0x02,0x24,0xff,0x00,0x4b,0x30, +0x0f,0xff,0x02,0x24,0x24,0x48,0x22,0x01,0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34, +0x24,0x48,0x22,0x01,0x01,0x00,0x07,0x3c,0x47,0x00,0x02,0x24,0x3b,0x00,0x03,0x24, +0x02,0x80,0x08,0x3c,0x10,0x00,0xa2,0xa3,0x11,0x00,0xa3,0xa3,0xbc,0xa5,0x08,0x25, +0x56,0x30,0xea,0x34,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,0xf4,0x98,0xe7,0x34, +0x00,0x80,0x06,0x3c,0x04,0x43,0x0b,0xae,0x00,0x40,0x09,0xae,0x43,0x00,0x11,0x24, +0x10,0x00,0xa5,0x27,0x0c,0x43,0x07,0xae,0x10,0x43,0x0a,0xae,0x0c,0x00,0x02,0xad, +0x14,0x00,0x03,0xa1,0x08,0x43,0x00,0xae,0x14,0x43,0x00,0xae,0x18,0x43,0x00,0xae, +0x21,0x20,0x00,0x01,0x3c,0x5c,0xc6,0x24,0x12,0x00,0xb1,0xa3,0x88,0x0e,0x00,0x0c, +0x13,0x00,0xa0,0xa3,0x1e,0x00,0x02,0x24,0x21,0x43,0x02,0xa2,0x4a,0x00,0x03,0x24, +0x45,0x00,0x02,0x24,0x1c,0x43,0x03,0xa2,0x1d,0x43,0x02,0xa2,0x23,0x00,0x03,0x24, +0x3e,0x00,0x02,0x24,0x1e,0x43,0x11,0xa2,0x1f,0x43,0x02,0xa2,0x20,0x43,0x03,0xa2, +0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x28,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x3b,0x00,0x02,0x24,0x43,0x00,0x03,0x24, +0x10,0x00,0xa2,0xa3,0x11,0x00,0xa3,0xa3,0x36,0x00,0x02,0x24,0x02,0x80,0x03,0x3c, +0x02,0x80,0x07,0x3c,0xd8,0xa5,0xe7,0x24,0x12,0x00,0xa2,0xa3,0x3b,0x58,0x60,0xa0, +0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27, +0x21,0x20,0xe0,0x00,0x60,0x61,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0, +0x18,0x00,0xbf,0xaf,0x88,0x0e,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27, +0x02,0x80,0x02,0x3c,0x52,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3,0xac,0x79,0x40,0xa4, +0x54,0x00,0x03,0x24,0x53,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x10,0xa6,0xe7,0x24, +0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,0xf4,0x01,0x02,0x24,0x01,0x00,0x03,0x24, +0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xb8,0x68,0xc6,0x24, +0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0x88,0x0e,0x00,0x0c, +0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x02,0x80,0x04,0x3c,0xd8,0xff,0xbd,0x27,0x64,0x79,0x84,0x24, +0x21,0x28,0x00,0x00,0x20,0x00,0xbf,0xaf,0x58,0x45,0x00,0x0c,0x0a,0x00,0x06,0x24, +0x02,0x80,0x07,0x3c,0x68,0x15,0xe7,0x24,0xf8,0x63,0xe3,0x8c,0xfd,0xff,0x02,0x24, +0x02,0x80,0x08,0x3c,0x24,0x18,0x62,0x00,0xfe,0xff,0x02,0x24,0x24,0x18,0x62,0x00, +0x05,0x00,0x02,0x24,0xf8,0x63,0xe3,0xac,0xfc,0x63,0xe2,0xa0,0x28,0x00,0x03,0x24, +0x46,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,0xfd,0x63,0xe3,0xa0,0x4b,0x00,0x02,0x24, +0x42,0x00,0x03,0x24,0x2c,0xa6,0x08,0x25,0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3, +0xd0,0x07,0x03,0x24,0x01,0x00,0x02,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27, +0x21,0x20,0x00,0x01,0x80,0x69,0xc6,0x24,0xfa,0x63,0xe0,0xa4,0x0c,0x00,0x03,0xad, +0x14,0x00,0x02,0xa1,0x88,0x0e,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x20,0x00,0xbf,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x78,0x0c,0x00,0x00,0x01,0x00,0x00,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x01,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x02,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x03,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x04,0x5d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x05,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x06,0x59,0x78,0x0c,0x00,0x00, +0x01,0x00,0x07,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x08,0x55,0x78,0x0c,0x00,0x00, +0x01,0x00,0x09,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x0a,0x51,0x78,0x0c,0x00,0x00, +0x01,0x00,0x0b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x0c,0x4d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x0d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x0e,0x49,0x78,0x0c,0x00,0x00, +0x01,0x00,0x0f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x10,0x45,0x78,0x0c,0x00,0x00, +0x01,0x00,0x11,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x12,0x41,0x78,0x0c,0x00,0x00, +0x01,0x00,0x13,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x14,0x3d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x15,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x16,0x39,0x78,0x0c,0x00,0x00, +0x01,0x00,0x17,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x18,0x35,0x78,0x0c,0x00,0x00, +0x01,0x00,0x19,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x1a,0x31,0x78,0x0c,0x00,0x00, +0x01,0x00,0x1b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x1c,0x2d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x1d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x1e,0x29,0x78,0x0c,0x00,0x00, +0x01,0x00,0x1f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x20,0x25,0x78,0x0c,0x00,0x00, +0x01,0x00,0x21,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x22,0x21,0x78,0x0c,0x00,0x00, +0x01,0x00,0x23,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x24,0x1d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x25,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x26,0x19,0x78,0x0c,0x00,0x00, +0x01,0x00,0x27,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x28,0x15,0x78,0x0c,0x00,0x00, +0x01,0x00,0x29,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x2a,0x11,0x78,0x0c,0x00,0x00, +0x01,0x00,0x2b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x2c,0x0d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x2d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x2e,0x09,0x78,0x0c,0x00,0x00, +0x01,0x00,0x2f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x30,0x05,0x78,0x0c,0x00,0x00, +0x01,0x00,0x31,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x32,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x33,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x34,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x35,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x36,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x37,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x38,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x39,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3a,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x3b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3c,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x3d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3e,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x3f,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x40,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x41,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x42,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x43,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x44,0x5d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x45,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x46,0x59,0x78,0x0c,0x00,0x00, +0x01,0x00,0x47,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x48,0x55,0x78,0x0c,0x00,0x00, +0x01,0x00,0x49,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x4a,0x51,0x78,0x0c,0x00,0x00, +0x01,0x00,0x4b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x4c,0x4d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x4d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x4e,0x49,0x78,0x0c,0x00,0x00, +0x01,0x00,0x4f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x50,0x45,0x78,0x0c,0x00,0x00, +0x01,0x00,0x51,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x52,0x41,0x78,0x0c,0x00,0x00, +0x01,0x00,0x53,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x54,0x3d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x55,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x56,0x39,0x78,0x0c,0x00,0x00, +0x01,0x00,0x57,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x58,0x35,0x78,0x0c,0x00,0x00, +0x01,0x00,0x59,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x5a,0x31,0x78,0x0c,0x00,0x00, +0x01,0x00,0x5b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x5c,0x2d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x5d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x5e,0x29,0x78,0x0c,0x00,0x00, +0x01,0x00,0x5f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x60,0x25,0x78,0x0c,0x00,0x00, +0x01,0x00,0x61,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x62,0x21,0x78,0x0c,0x00,0x00, +0x01,0x00,0x63,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x64,0x1d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x65,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x66,0x19,0x78,0x0c,0x00,0x00, +0x01,0x00,0x67,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x68,0x15,0x78,0x0c,0x00,0x00, +0x01,0x00,0x69,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x6a,0x11,0x78,0x0c,0x00,0x00, +0x01,0x00,0x6b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x6c,0x0d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x6d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x6e,0x09,0x78,0x0c,0x00,0x00, +0x01,0x00,0x6f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x70,0x05,0x78,0x0c,0x00,0x00, +0x01,0x00,0x71,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x72,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x73,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x74,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x75,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x76,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x77,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x78,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x79,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7a,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x7b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7c,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x7d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7e,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x7f,0x01,0x78,0x0c,0x00,0x00,0x1e,0x00,0x00,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x01,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x02,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x03,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x04,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x05,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x06,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x07,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x08,0x3e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x09,0x40,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0a,0x42,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x0b,0x44,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0c,0x46,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x0d,0x48,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0e,0x48,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x0f,0x4a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x10,0x4a,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x11,0x4c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x12,0x4c,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x13,0x4e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x14,0x50,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x15,0x50,0x78,0x0c,0x00,0x00,0x1e,0x00,0x16,0x50,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x17,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x18,0x52,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x19,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1a,0x54,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x1b,0x54,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1c,0x54,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x1d,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1e,0x56,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x1f,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x20,0x56,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x21,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x22,0x58,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x23,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x24,0x58,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x25,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x26,0x5a,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x27,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x28,0x5c,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x29,0x5c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2a,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x2b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2c,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x2d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2e,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x2f,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x30,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x31,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x32,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x33,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x34,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x35,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x36,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x37,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x38,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x39,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3a,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x3b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3c,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x3d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3e,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x3f,0x5e,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x08,0x00,0x00, +0x00,0x00,0x04,0x03,0x04,0x08,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x08,0x00,0x00, +0x00,0xfc,0x00,0x00,0x0c,0x08,0x00,0x00,0x0a,0x00,0x00,0x04,0x10,0x08,0x00,0x00, +0xff,0x10,0x10,0x80,0x14,0x08,0x00,0x00,0x10,0x3d,0x0c,0x02,0x18,0x08,0x00,0x00, +0xc5,0x03,0x00,0x00,0x1c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x24,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x28,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x2c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x30,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x34,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x38,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x3c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x40,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x44,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x4c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x54,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x08,0x00,0x00, +0x65,0xa9,0x65,0xa9,0x5c,0x08,0x00,0x00,0x65,0xa9,0x65,0xa9,0x60,0x08,0x00,0x00, +0x30,0x01,0x7f,0x0f,0x64,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x68,0x08,0x00,0x00, +0x30,0x01,0x7f,0x0f,0x6c,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x70,0x08,0x00,0x00, +0x00,0x03,0x00,0x03,0x74,0x08,0x00,0x00,0x00,0x03,0x00,0x03,0x78,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x7c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x94,0x08,0x00,0x00,0xfe,0xff,0xff,0xff,0x98,0x08,0x00,0x00, +0x10,0x20,0x30,0x40,0x9c,0x08,0x00,0x00,0x50,0x60,0x70,0x00,0xb0,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0xe0,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x04,0x0e,0x00,0x00, +0x03,0x03,0x03,0x03,0x08,0x0e,0x00,0x00,0x03,0x03,0x00,0x00,0x0c,0x0e,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x14,0x0e,0x00,0x00, +0x03,0x03,0x03,0x03,0x18,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x1c,0x0e,0x00,0x00, +0x03,0x03,0x03,0x03,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x09,0x00,0x00, +0x23,0x00,0x00,0x00,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x09,0x00,0x00, +0x33,0x13,0x32,0x03,0x08,0x0a,0x00,0x00,0x00,0x86,0x88,0x8f,0x2c,0x0a,0x00,0x00, +0x00,0x00,0x92,0x00,0x00,0x0c,0x00,0x00,0x80,0x00,0x00,0x00,0x04,0x0c,0x00,0x00, +0x33,0x54,0x00,0x00,0x08,0x0c,0x00,0x00,0xe4,0x00,0x00,0x00,0x0c,0x0c,0x00,0x00, +0x6c,0x6c,0x6c,0x6c,0x10,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x20,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x24,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x28,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x2c,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x30,0x0c,0x00,0x00,0x44,0x6a,0xe9,0x8d,0x34,0x0c,0x00,0x00, +0xcd,0x52,0x96,0x46,0x38,0x0c,0x00,0x00,0x90,0x5a,0x01,0x48,0x3c,0x0c,0x00,0x00, +0x64,0x97,0x97,0x1a,0x40,0x0c,0x00,0x00,0x3f,0x42,0x7c,0x1f,0x44,0x0c,0x00,0x00, +0xb7,0x00,0x01,0x00,0x48,0x0c,0x00,0x00,0x00,0x00,0x02,0xec,0x4c,0x0c,0x00,0x00, +0x03,0x03,0xfc,0x00,0x50,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x54,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x58,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x5c,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x60,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x64,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x68,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x6c,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x70,0x0c,0x00,0x00,0x0d,0x00,0x5a,0x2c,0x74,0x0c,0x00,0x00, +0x1b,0x15,0x86,0x01,0x78,0x0c,0x00,0x00,0x1f,0x00,0x00,0x00,0x7c,0x0c,0x00,0x00, +0x12,0x16,0xb9,0x00,0x80,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x84,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0x88,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x8c,0x0c,0x00,0x00, +0x00,0x00,0x20,0x08,0x90,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x94,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0x98,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x9c,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xa0,0x0c,0x00,0x00,0x92,0x24,0x49,0x00,0xa4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xa8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xb0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xb8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x0c,0x00,0x00, +0x92,0x24,0x49,0x00,0xc0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xc4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xc8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xcc,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xd0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xd8,0x0c,0x00,0x00,0x27,0x24,0xb2,0x64,0xdc,0x0c,0x00,0x00, +0x32,0x69,0x76,0x00,0xe0,0x0c,0x00,0x00,0x22,0x22,0x22,0x00,0xe4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xe8,0x0c,0x00,0x00,0x02,0x43,0x64,0x07,0x00,0x0d,0x00,0x00, +0x80,0x07,0x00,0x00,0x04,0x0d,0x00,0x00,0x03,0x04,0x00,0x00,0x08,0x0d,0x00,0x00, +0x7f,0x90,0x00,0x00,0x0c,0x0d,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x0d,0x00,0x00, +0x99,0x99,0x69,0xa0,0x14,0x0d,0x00,0x00,0x67,0x3c,0x99,0x99,0x18,0x0d,0x00,0x00, +0x6b,0x5b,0x8f,0x6a,0x1c,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x24,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x2c,0x0d,0x00,0x00,0x75,0x19,0x97,0xcc,0x30,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x34,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x3c,0x0d,0x00,0x00,0x93,0x72,0x02,0x00,0x40,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x44,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x50,0x0d,0x00,0x00,0x0a,0x14,0x37,0x64,0x54,0x0d,0x00,0x00, +0x02,0xbd,0x4d,0x02,0x58,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x0d,0x00,0x00, +0x64,0x20,0x03,0x30,0x60,0x0d,0x00,0x00,0x68,0xde,0x53,0x46,0x64,0x0d,0x00,0x00, +0x3c,0x8a,0x51,0x00,0x68,0x0d,0x00,0x00,0x06,0x01,0x00,0x00,0xff,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00, +0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x74,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x14,0x35,0x00,0x80,0x10,0x00,0x00,0x00,0x20,0x35,0x00,0x80,0x10,0x00,0x00,0x00, +0xa0,0x08,0x01,0x80,0x10,0x00,0x00,0x00,0x2c,0x25,0x00,0x80,0x10,0x00,0x00,0x00, +0x24,0x25,0x00,0x80,0x10,0x00,0x00,0x00,0x34,0x25,0x00,0x80,0x08,0x00,0x00,0x00, +0x38,0x06,0x01,0x80,0x00,0xb7,0x00,0x00,0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00, +0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00, +0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00, +0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00, +0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00, +0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00, +0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00, +0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00, +0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00, +0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00, +0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00, +0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00, +0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00, +0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00, +0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00, +0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00, +0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00, +0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00, +0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00, +0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00, +0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00, +0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00, +0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00, +0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00, +0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00, +0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00, +0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00, +0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00, +0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00, +0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00, +0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00, +0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00, +0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00, +0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00, +0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00, +0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00, +0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00, +0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00, +0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00, +0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00, +0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00, +0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00, +0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00, +0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00, +0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00, +0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00, +0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00, +0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00, +0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00, +0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00, +0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00, +0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00, +0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00, +0xff,0xff,0xff,0x00,0x00,0xb7,0x00,0x00,0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00, +0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00, +0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00, +0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00, +0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00, +0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00, +0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00, +0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00, +0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00, +0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00, +0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00, +0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00, +0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00, +0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00, +0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00, +0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00, +0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00, +0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00, +0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00, +0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00, +0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00, +0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00, +0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00, +0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00, +0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00, +0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00, +0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00, +0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00, +0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00, +0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00, +0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00, +0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00, +0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00, +0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00, +0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00, +0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00, +0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00, +0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00, +0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00, +0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00, +0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00, +0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00, +0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00, +0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00, +0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00, +0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00, +0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00, +0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00, +0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00, +0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00, +0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00, +0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00, +0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00, +0xff,0xff,0xff,0x00,0x0a,0x00,0x00,0x00,0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52, +0x65,0x71,0x00,0x00,0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00, +0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,0x63,0x52,0x65,0x71,0x00,0x00,0x00,0x00, +0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00,0x00,0x00, +0x4f,0x6e,0x50,0x72,0x6f,0x62,0x65,0x52,0x65,0x71,0x00,0x00,0x4f,0x6e,0x50,0x72, +0x6f,0x62,0x65,0x52,0x73,0x70,0x00,0x00,0x44,0x6f,0x52,0x65,0x73,0x65,0x72,0x76, +0x65,0x64,0x00,0x00,0x44,0x6f,0x52,0x65,0x73,0x65,0x72,0x76,0x65,0x64,0x00,0x00, +0x4f,0x6e,0x42,0x65,0x61,0x63,0x6f,0x6e,0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x54, +0x49,0x4d,0x00,0x00,0x4f,0x6e,0x44,0x69,0x73,0x61,0x73,0x73,0x6f,0x63,0x00,0x00, +0x4f,0x6e,0x41,0x75,0x74,0x68,0x00,0x00,0x4f,0x6e,0x44,0x65,0x41,0x75,0x74,0x68, +0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x63,0x74,0x69,0x6f,0x6e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x20,0x99,0x01,0x80,0x2c,0x13,0x01,0x80,0x10,0x00,0x00,0x00, +0x2c,0x99,0x01,0x80,0x34,0x13,0x01,0x80,0x20,0x00,0x00,0x00,0x38,0x99,0x01,0x80, +0x2c,0x13,0x01,0x80,0x30,0x00,0x00,0x00,0x48,0x99,0x01,0x80,0x34,0x13,0x01,0x80, +0x40,0x00,0x00,0x00,0x58,0x99,0x01,0x80,0x3c,0x13,0x01,0x80,0x50,0x00,0x00,0x00, +0x64,0x99,0x01,0x80,0x44,0x13,0x01,0x80,0x00,0x00,0x00,0x00,0x70,0x99,0x01,0x80, +0xac,0x13,0x01,0x80,0x00,0x00,0x00,0x00,0x7c,0x99,0x01,0x80,0xac,0x13,0x01,0x80, +0x80,0x00,0x00,0x00,0x88,0x99,0x01,0x80,0x4c,0x13,0x01,0x80,0x90,0x00,0x00,0x00, +0x94,0x99,0x01,0x80,0x54,0x13,0x01,0x80,0xa0,0x00,0x00,0x00,0x9c,0x99,0x01,0x80, +0x5c,0x13,0x01,0x80,0xb0,0x00,0x00,0x00,0xa8,0x99,0x01,0x80,0x94,0x13,0x01,0x80, +0xc0,0x00,0x00,0x00,0xb0,0x99,0x01,0x80,0x9c,0x13,0x01,0x80,0xd0,0x00,0x00,0x00, +0xbc,0x99,0x01,0x80,0xa4,0x13,0x01,0x80,0x00,0x00,0x00,0x00,0x74,0x9a,0x01,0x80, +0x74,0x9a,0x01,0x80,0x31,0x10,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x20,0x10,0x00, +0x00,0x30,0x00,0x00,0x31,0x28,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x2c,0x10,0x10, +0x00,0x30,0x00,0x00,0x31,0x2f,0x10,0x10,0x00,0x30,0x00,0x00,0x31,0x30,0x18,0x00, +0x00,0x30,0x00,0x00,0x31,0x30,0x20,0x10,0x00,0x30,0x00,0x00,0x22,0x20,0x18,0x08, +0x00,0x20,0x00,0x00,0x22,0x21,0x14,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x1c,0x08, +0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x10, +0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x18,0x00,0x20,0x00,0x00,0x1a,0x19,0x18,0x10, +0x00,0x18,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x10,0x00,0x00,0x0a,0x09,0x08,0x00, +0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x02,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x04, +0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x06,0x00,0x08,0x00,0x00,0x08,0x07,0x06,0x04, +0x00,0x06,0x00,0x00,0x06,0x05,0x04,0x02,0x00,0x04,0x00,0x00,0x06,0x05,0x04,0x03, +0x00,0x04,0x00,0x00,0x05,0x04,0x03,0x02,0x00,0x03,0x00,0x00,0x09,0x08,0x07,0x06, +0x07,0x06,0x06,0x05,0x05,0x04,0x04,0x03,0x06,0x05,0x05,0x04,0x04,0x03,0x03,0x03, +0x05,0x04,0x04,0x03,0x03,0x02,0x02,0x02,0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06, +0x05,0x05,0x04,0x04,0x03,0x05,0x04,0x04,0x03,0x03,0x02,0x02,0x02,0x04,0x03,0x03, +0x02,0x02,0x01,0x01,0x01,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08, +0x08,0x20,0x20,0x20,0x30,0x08,0x08,0x08,0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30, +0x30,0x10,0x20,0x20,0x20,0x20,0x20,0x30,0x30,0x08,0x10,0x20,0x30,0x30,0x30,0x30, +0x30,0x30,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20, +0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20, +0x20,0x08,0x08,0x08,0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20, +0x20,0x20,0x20,0x30,0x30,0x08,0x10,0x20,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00, +0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a, +0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09, +0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10, +0x08,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x00, +0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00, +0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22, +0x20,0x18,0x08,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09, +0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20, +0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x1c,0x08,0x00,0x31,0x30,0x18,0x00, +0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00, +0x0a,0x09,0x08,0x04,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a, +0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21, +0x20,0x08,0x00,0x31,0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10, +0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08, +0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00, +0x31,0x2c,0x10,0x10,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22, +0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f, +0x10,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10, +0x10,0x00,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09, +0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08, +0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00, +0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00, +0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a, +0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21, +0x1c,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08, +0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00, +0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00, +0x22,0x21,0x14,0x08,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a, +0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19, +0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18, +0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31,0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00, +0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00, +0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31, +0x30,0x20,0x10,0x00,0x31,0x2c,0x10,0x10,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11, +0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x31,0x30,0x20, +0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x10,0x10,0x00, +0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00,0x01,0x02,0x04,0x08,0x02,0x04,0x08,0x0c, +0x10,0x18,0x20,0x30,0x02,0x04,0x08,0x0c,0x10,0x18,0x20,0x30,0x06,0x0c,0x10,0x18, +0x24,0x30,0x3c,0x48,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x25,0x27,0x2c,0x19,0x1b,0x1e,0x20,0x23,0x29,0x2a,0x2b,0x00,0x00,0x00,0x00, +0x25,0x29,0x2b,0x2e,0x2e,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00, +0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00, +0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x90,0x00,0x00,0x00, +0xc0,0x00,0x00,0x00,0xd8,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x78,0x00,0x00,0x00, +0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x90,0x01,0x00,0x00, +0xe0,0x01,0x00,0x00,0x30,0x02,0x00,0x00,0x2c,0x01,0x00,0x00,0x40,0x01,0x00,0x00, +0xe0,0x01,0x00,0x00,0xd0,0x02,0x00,0x00,0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00, +0x80,0x0c,0x00,0x00,0xa0,0x0f,0x00,0x00,0xa0,0x0f,0x00,0x00,0x02,0x00,0x00,0x00, +0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, +0x12,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00, +0x48,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x28,0x00,0x00,0x00, +0x3c,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00, +0xc8,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x18,0x01,0x00,0x00,0x64,0x00,0x00,0x00, +0xa0,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,0x68,0x01,0x00,0x00,0x40,0x06,0x00,0x00, +0x40,0x06,0x00,0x00,0x40,0x06,0x00,0x00,0xd0,0x07,0x00,0x00,0xd0,0x07,0x00,0x00, +0x2c,0x05,0x00,0x80,0x20,0x05,0x00,0x80,0x14,0x05,0x00,0x80,0x08,0x05,0x00,0x80, +0xfc,0x04,0x00,0x80,0xf0,0x04,0x00,0x80,0xe4,0x04,0x00,0x80,0xd8,0x04,0x00,0x80, +0xcc,0x04,0x00,0x80,0xc0,0x04,0x00,0x80,0x78,0x04,0x00,0x80,0x70,0x3b,0x01,0x80, +0x48,0x3b,0x01,0x80,0x24,0x3b,0x01,0x80,0x14,0x3c,0x01,0x80,0xf0,0x3b,0x01,0x80, +0xcc,0x3b,0x01,0x80,0xa8,0x3b,0x01,0x80,0x30,0x41,0x00,0x80,0x3c,0x41,0x00,0x80, +0x48,0x41,0x00,0x80,0x54,0x41,0x00,0x80,0x30,0x41,0x00,0x80,0x30,0x41,0x00,0x80, +0x30,0x41,0x00,0x80,0x30,0x41,0x00,0x80,0x60,0x41,0x00,0x80,0x6c,0x41,0x00,0x80, +0x78,0x41,0x00,0x80,0x84,0x41,0x00,0x80,0x68,0x15,0x02,0x80,0x68,0x15,0x02,0x80, +0x84,0x0e,0x25,0xb0,0x88,0x0e,0x25,0xb0,0x8c,0x0e,0x25,0xb0,0xd0,0x0e,0x25,0xb0, +0xd8,0x0e,0x25,0xb0,0x20,0x08,0x25,0xb0,0xfe,0x01,0x80,0x7f,0xe2,0x01,0x80,0x78, +0xc7,0x01,0xc0,0x71,0xae,0x01,0x80,0x6b,0x95,0x01,0x40,0x65,0x7f,0x01,0xc0,0x5f, +0x69,0x01,0x40,0x5a,0x55,0x01,0x40,0x55,0x42,0x01,0x80,0x50,0x30,0x01,0x00,0x4c, +0x1f,0x01,0xc0,0x47,0x0f,0x01,0xc0,0x43,0x00,0x01,0x00,0x40,0xf2,0x00,0x80,0x3c, +0xe4,0x00,0x00,0x39,0xd7,0x00,0xc0,0x35,0xcb,0x00,0xc0,0x32,0xc0,0x00,0x00,0x30, +0xb5,0x00,0x40,0x2d,0xab,0x00,0xc0,0x2a,0xa2,0x00,0x80,0x28,0x98,0x00,0x00,0x26, +0x90,0x00,0x00,0x24,0x88,0x00,0x00,0x22,0x80,0x00,0x00,0x20,0x79,0x00,0x40,0x1e, +0x72,0x00,0x80,0x1c,0x6c,0x00,0x00,0x1b,0x66,0x00,0x80,0x19,0x60,0x00,0x00,0x18, +0x5b,0x00,0xc0,0x16,0x56,0x00,0x80,0x15,0x51,0x00,0x40,0x14,0x4c,0x00,0x00,0x13, +0x48,0x00,0x00,0x12,0x44,0x00,0x00,0x11,0x40,0x00,0x00,0x10,0x36,0x35,0x2e,0x25, +0x1c,0x12,0x09,0x04,0x33,0x32,0x2b,0x23,0x1a,0x11,0x08,0x04,0x30,0x2f,0x29,0x21, +0x19,0x10,0x08,0x03,0x2d,0x2d,0x27,0x1f,0x18,0x0f,0x08,0x03,0x2b,0x2a,0x25,0x1e, +0x16,0x0e,0x07,0x03,0x28,0x28,0x22,0x1c,0x15,0x0d,0x07,0x03,0x26,0x25,0x21,0x1b, +0x14,0x0d,0x06,0x03,0x24,0x23,0x1f,0x19,0x13,0x0c,0x06,0x03,0x22,0x21,0x1d,0x18, +0x11,0x0b,0x06,0x02,0x20,0x20,0x1b,0x16,0x11,0x08,0x05,0x02,0x1f,0x1e,0x1a,0x15, +0x10,0x0a,0x05,0x02,0x1d,0x1c,0x18,0x14,0x0f,0x0a,0x05,0x02,0x1b,0x1a,0x17,0x13, +0x0e,0x09,0x04,0x02,0x1a,0x19,0x16,0x12,0x0d,0x09,0x04,0x02,0x18,0x17,0x15,0x11, +0x0c,0x08,0x04,0x02,0x17,0x16,0x13,0x10,0x0c,0x08,0x04,0x02,0x16,0x15,0x12,0x0f, +0x0b,0x07,0x04,0x01,0x14,0x14,0x11,0x0e,0x0b,0x07,0x03,0x02,0x13,0x13,0x10,0x0d, +0x0a,0x06,0x03,0x01,0x12,0x12,0x0f,0x0c,0x09,0x06,0x03,0x01,0x11,0x11,0x0f,0x0c, +0x09,0x06,0x03,0x01,0x10,0x10,0x0e,0x0b,0x08,0x05,0x03,0x01,0x0f,0x0f,0x0d,0x0b, +0x08,0x05,0x03,0x01,0x0e,0x0e,0x0c,0x0a,0x08,0x05,0x02,0x01,0x0d,0x0d,0x0c,0x0a, +0x07,0x05,0x02,0x01,0x0d,0x0c,0x0b,0x09,0x07,0x04,0x02,0x01,0x0c,0x0c,0x0a,0x09, +0x06,0x04,0x02,0x01,0x0b,0x0b,0x0a,0x08,0x06,0x04,0x02,0x01,0x0b,0x0a,0x09,0x08, +0x06,0x04,0x02,0x01,0x0a,0x0a,0x09,0x07,0x05,0x03,0x02,0x01,0x0a,0x09,0x08,0x07, +0x05,0x03,0x02,0x01,0x09,0x09,0x08,0x06,0x05,0x03,0x01,0x01,0x09,0x08,0x07,0x06, +0x04,0x03,0x01,0x01,0x36,0x35,0x2e,0x1b,0x00,0x00,0x00,0x00,0x33,0x32,0x2b,0x19, +0x00,0x00,0x00,0x00,0x30,0x2f,0x29,0x18,0x00,0x00,0x00,0x00,0x2d,0x2d,0x17,0x17, +0x00,0x00,0x00,0x00,0x2b,0x2a,0x25,0x15,0x00,0x00,0x00,0x00,0x28,0x28,0x24,0x14, +0x00,0x00,0x00,0x00,0x26,0x25,0x21,0x13,0x00,0x00,0x00,0x00,0x24,0x23,0x1f,0x12, +0x00,0x00,0x00,0x00,0x22,0x21,0x1d,0x11,0x00,0x00,0x00,0x00,0x20,0x20,0x1b,0x10, +0x00,0x00,0x00,0x00,0x1f,0x1e,0x1a,0x0f,0x00,0x00,0x00,0x00,0x1d,0x1c,0x18,0x0e, +0x00,0x00,0x00,0x00,0x1b,0x1a,0x17,0x0e,0x00,0x00,0x00,0x00,0x1a,0x19,0x16,0x0d, +0x00,0x00,0x00,0x00,0x18,0x17,0x15,0x0c,0x00,0x00,0x00,0x00,0x17,0x16,0x13,0x0b, +0x00,0x00,0x00,0x00,0x16,0x15,0x12,0x0b,0x00,0x00,0x00,0x00,0x14,0x14,0x11,0x0a, +0x00,0x00,0x00,0x00,0x13,0x13,0x10,0x0a,0x00,0x00,0x00,0x00,0x12,0x12,0x0f,0x09, +0x00,0x00,0x00,0x00,0x11,0x11,0x0f,0x09,0x00,0x00,0x00,0x00,0x10,0x10,0x0e,0x08, +0x00,0x00,0x00,0x00,0x0f,0x0f,0x0d,0x08,0x00,0x00,0x00,0x00,0x0e,0x0e,0x0c,0x07, +0x00,0x00,0x00,0x00,0x0d,0x0d,0x0c,0x07,0x00,0x00,0x00,0x00,0x0d,0x0c,0x0b,0x06, +0x00,0x00,0x00,0x00,0x0c,0x0c,0x0a,0x06,0x00,0x00,0x00,0x00,0x0b,0x0b,0x0a,0x06, +0x00,0x00,0x00,0x00,0x0b,0x0a,0x09,0x05,0x00,0x00,0x00,0x00,0x0a,0x0a,0x09,0x05, +0x00,0x00,0x00,0x00,0x0a,0x09,0x08,0x05,0x00,0x00,0x00,0x00,0x09,0x09,0x08,0x05, +0x00,0x00,0x00,0x00,0x09,0x08,0x07,0x04,0x00,0x00,0x00,0x00,0x06,0x00,0x2a,0xb0, +0x05,0x00,0x2a,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x28,0x28,0x28,0x28,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x41,0x41,0x41,0x41,0x41,0x41,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x01,0x01,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x42,0x42,0x42,0x42,0x42,0x42,0x02, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, +0x02,0x02,0x02,0x10,0x10,0x10,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0xa5,0x76,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x26,0x72,0xb0,0x00,0x26,0x72,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x26,0x65,0x60,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x02, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x5a,0x00,0xb8,0xff,0xff,0xff,0xff, +}; + +u8 Rtl8192SEFwMainArray[MainArrayLength] = { +0x0, }; + +u8 Rtl8192SEFwDataArray[DataArrayLength] = { +0x0, }; + +u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength] = { +0x01c,0x07000000, +0x800,0x00040000, +0x804,0x00008003, +0x808,0x0000fc00, +0x80c,0x0000000a, +0x810,0x10005088, +0x814,0x020c3d10, +0x818,0x00200185, +0x81c,0x00000000, +0x820,0x01000000, +0x824,0x00390004, +0x828,0x01000000, +0x82c,0x00390004, +0x830,0x00000004, +0x834,0x00690200, +0x838,0x00000004, +0x83c,0x00690200, +0x840,0x00010000, +0x844,0x00010000, +0x848,0x00000000, +0x84c,0x00000000, +0x850,0x00000000, +0x854,0x00000000, +0x858,0x48484848, +0x85c,0x65a965a9, +0x860,0x0f7f0130, +0x864,0x0f7f0130, +0x868,0x0f7f0130, +0x86c,0x0f7f0130, +0x870,0x03000700, +0x874,0x03000300, +0x878,0x00020002, +0x87c,0x004f0201, +0x880,0xa8300ac1, +0x884,0x00000058, +0x888,0x00000008, +0x88c,0x00000004, +0x890,0x00000000, +0x894,0xfffffffe, +0x898,0x40302010, +0x89c,0x00706050, +0x8b0,0x00000000, +0x8e0,0x00000000, +0x8e4,0x00000000, +0xe00,0x30333333, +0xe04,0x2a2d2e2f, +0xe08,0x00003232, +0xe10,0x30333333, +0xe14,0x2a2d2e2f, +0xe18,0x30333333, +0xe1c,0x2a2d2e2f, +0xe30,0x01007c00, +0xe34,0x01004800, +0xe38,0x1000dc1f, +0xe3c,0x10008c1f, +0xe40,0x021400a0, +0xe44,0x281600a0, +0xe48,0xf8000001, +0xe4c,0x00002910, +0xe50,0x01007c00, +0xe54,0x01004800, +0xe58,0x1000dc1f, +0xe5c,0x10008c1f, +0xe60,0x021400a0, +0xe64,0x281600a0, +0xe6c,0x00002910, +0xe70,0x31ed92fb, +0xe74,0x361536fb, +0xe78,0x361536fb, +0xe7c,0x361536fb, +0xe80,0x361536fb, +0xe84,0x000d92fb, +0xe88,0x000d92fb, +0xe8c,0x31ed92fb, +0xed0,0x31ed92fb, +0xed4,0x31ed92fb, +0xed8,0x000d92fb, +0xedc,0x000d92fb, +0xee0,0x000d92fb, +0xee4,0x015e5448, +0xee8,0x21555448, +0x900,0x00000000, +0x904,0x00000023, +0x908,0x00000000, +0x90c,0x01121313, +0xa00,0x00d047c8, +0xa04,0x80ff0008, +0xa08,0x8ccd8300, +0xa0c,0x2e62120f, +0xa10,0x9500bb78, +0xa14,0x11144028, +0xa18,0x00881117, +0xa1c,0x89140f00, +0xa20,0x1a1b0000, +0xa24,0x090e1317, +0xa28,0x00000204, +0xa2c,0x10d30000, +0xc00,0x40071d40, +0xc04,0x00a05633, +0xc08,0x000000e4, +0xc0c,0x6c6c6c6c, +0xc10,0x08800000, +0xc14,0x40000100, +0xc18,0x08000000, +0xc1c,0x40000100, +0xc20,0x08000000, +0xc24,0x40000100, +0xc28,0x08000000, +0xc2c,0x40000100, +0xc30,0x6de9ac44, +0xc34,0x469652cf, +0xc38,0x49795994, +0xc3c,0x0a979764, +0xc40,0x1f7c403f, +0xc44,0x000100b7, +0xc48,0xec020000, +0xc4c,0x007f037f, +0xc50,0x69543420, +0xc54,0x433c0094, +0xc58,0x69543420, +0xc5c,0x433c0094, +0xc60,0x69543420, +0xc64,0x433c0094, +0xc68,0x69543420, +0xc6c,0x433c0094, +0xc70,0x2c7f000d, +0xc74,0x0186155b, +0xc78,0x0000001f, +0xc7c,0x00b91612, +0xc80,0x40000100, +0xc84,0x20f60000, +0xc88,0x20000080, +0xc8c,0x20200000, +0xc90,0x40000100, +0xc94,0x00000000, +0xc98,0x40000100, +0xc9c,0x00000000, +0xca0,0x00492492, +0xca4,0x00000000, +0xca8,0x00000000, +0xcac,0x00000000, +0xcb0,0x00000000, +0xcb4,0x00000000, +0xcb8,0x00000000, +0xcbc,0x28000000, +0xcc0,0x00000000, +0xcc4,0x00000000, +0xcc8,0x00000000, +0xccc,0x00000000, +0xcd0,0x00000000, +0xcd4,0x00000000, +0xcd8,0x64b22427, +0xcdc,0x00766932, +0xce0,0x00222222, +0xce4,0x00000000, +0xce8,0x37644302, +0xcec,0x2f97d40c, +0xd00,0x00000750, +0xd04,0x00000403, +0xd08,0x0000907f, +0xd0c,0x00000001, +0xd10,0xa0633333, +0xd14,0x33333c63, +0xd18,0x6a8f5b6b, +0xd1c,0x00000000, +0xd20,0x00000000, +0xd24,0x00000000, +0xd28,0x00000000, +0xd2c,0xcc979975, +0xd30,0x00000000, +0xd34,0x00000000, +0xd38,0x00000000, +0xd3c,0x00027293, +0xd40,0x00000000, +0xd44,0x00000000, +0xd48,0x00000000, +0xd50,0x6437140a, +0xd54,0x024dbd02, +0xd58,0x00000000, +0xd5c,0x30032064, +0xd60,0x4653de68, +0xd64,0x00518a3c, +0xd68,0x00002101, +0xf14,0x00000003, +0xf4c,0x00000000, +0xf00,0x00000300, +}; + +u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength] = { +0x0, }; + +u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength] = { +0x844,0xffffffff,0x00010000, +0x804,0x0000000f,0x00000001, +0x824,0x00f0000f,0x00300004, +0x82c,0x00f0000f,0x00100002, +0x870,0x04000000,0x00000001, +0x864,0x00000400,0x00000000, +0x878,0x000f000f,0x00000002, +0xe74,0x0f000000,0x00000002, +0xe78,0x0f000000,0x00000002, +0xe7c,0x0f000000,0x00000002, +0xe80,0x0f000000,0x00000002, +0x90c,0x000000ff,0x00000011, +0xc04,0x000000ff,0x00000011, +0xd04,0x0000000f,0x00000001, +0x1f4,0xffff0000,0x00007777, +0x234,0xf8000000,0x0000000a, +}; + +u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength] = { +0x804,0x0000000f,0x00000003, +0x824,0x00f0000f,0x00300004, +0x82c,0x00f0000f,0x00300002, +0x870,0x04000000,0x00000001, +0x864,0x00000400,0x00000000, +0x878,0x000f000f,0x00000002, +0xe74,0x0f000000,0x00000002, +0xe78,0x0f000000,0x00000002, +0xe7c,0x0f000000,0x00000002, +0xe80,0x0f000000,0x00000002, +0x90c,0x000000ff,0x00000011, +0xc04,0x000000ff,0x00000033, +0xd04,0x0000000f,0x00000003, +0x1f4,0xffff0000,0x00007777, +0x234,0xf8000000,0x0000000a, +}; + +u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength] = { +0x804,0x0000000f,0x00000003, +0x824,0x00f0000f,0x00300004, +0x82c,0x00f0000f,0x00300004, +0x870,0x04000000,0x00000001, +0x864,0x00000400,0x00000001, +0x878,0x000f000f,0x00020002, +0xe74,0x0f000000,0x00000006, +0xe78,0x0f000000,0x00000006, +0xe7c,0x0f000000,0x00000006, +0xe80,0x0f000000,0x00000006, +0x90c,0x000000ff,0x00000033, +0xc04,0x000000ff,0x00000033, +0xd04,0x0000000f,0x00000003, +0x1f4,0xffff0000,0x0000ffff, +0x234,0xf8000000,0x00000013, +}; + +u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength] = { +0xe00,0xffffffff,0x06090909, +0xe04,0xffffffff,0x00030406, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x0a0c0d0e, +0xe14,0xffffffff,0x04070809, +0xe18,0xffffffff,0x0a0c0d0e, +0xe1c,0xffffffff,0x04070809, +0xe00,0xffffffff,0x04040404, +0xe04,0xffffffff,0x00020204, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x02040404, +0xe14,0xffffffff,0x00000002, +0xe18,0xffffffff,0x02040404, +0xe1c,0xffffffff,0x00000002, +0xe00,0xffffffff,0x04040404, +0xe04,0xffffffff,0x00020204, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x02040404, +0xe14,0xffffffff,0x00000002, +0xe18,0xffffffff,0x02040404, +0xe1c,0xffffffff,0x00000002, +0xe00,0xffffffff,0x02020202, +0xe04,0xffffffff,0x00020202, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x02020202, +0xe14,0xffffffff,0x00000002, +0xe18,0xffffffff,0x02020202, +0xe1c,0xffffffff,0x00000002, +}; + +u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength] = { +0x000,0x00030159, +0x001,0x00030250, +0x002,0x00010000, +0x010,0x0008000f, +0x011,0x000231fc, +0x010,0x000c000f, +0x011,0x0003f9f8, +0x010,0x0002000f, +0x011,0x00020101, +0x014,0x0001093e, +0x014,0x0009093e, +0x015,0x0000f8f4, +0x017,0x000f6500, +0x01a,0x00013056, +0x01b,0x00060000, +0x01c,0x00000300, +0x01e,0x00031059, +0x021,0x00054000, +0x022,0x0000083c, +0x023,0x00001558, +0x024,0x00000060, +0x025,0x00022583, +0x026,0x0000f200, +0x027,0x000eacf1, +0x028,0x0009bd54, +0x029,0x00004582, +0x02a,0x00000001, +0x02b,0x00021334, +0x02a,0x00000000, +0x02b,0x0000000a, +0x02a,0x00000001, +0x02b,0x00000808, +0x02b,0x00053333, +0x02c,0x0000000c, +0x02a,0x00000002, +0x02b,0x00000808, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000003, +0x02b,0x00000808, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000004, +0x02b,0x00000808, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000005, +0x02b,0x00000709, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x00000006, +0x02b,0x00000709, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000007, +0x02b,0x00000709, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000008, +0x02b,0x00000709, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000009, +0x02b,0x0000060a, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000a, +0x02b,0x0000060a, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x0000000b, +0x02b,0x0000060a, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x0000000c, +0x02b,0x0000060a, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x0000000d, +0x02b,0x0000050b, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000e, +0x02b,0x0000050b, +0x02b,0x00066623, +0x02c,0x0000001a, +0x02a,0x000e4000, +0x030,0x00020000, +0x031,0x000b9631, +0x032,0x0000130d, +0x033,0x00000187, +0x013,0x00019e6c, +0x013,0x00015e94, +0x000,0x00010159, +0x018,0x0000f401, +0x0fe,0x00000000, +0x01e,0x0003105b, +0x0fe,0x00000000, +0x000,0x00030159, +0x010,0x0004000f, +0x011,0x000203f9, +}; + +u32 Rtl8192SERadioB_Array[RadioB_ArrayLength] = { +0x000,0x00030159, +0x001,0x00001041, +0x002,0x00011000, +0x005,0x00080fc0, +0x007,0x000fc803, +0x013,0x00017cb0, +0x013,0x00011cc0, +0x013,0x0000dc60, +0x013,0x00008c60, +0x013,0x00004450, +0x013,0x00000020, +}; + +u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength] = { +0x000,0x00030159, +0x001,0x00030250, +0x002,0x00010000, +0x010,0x0008000f, +0x011,0x000231fc, +0x010,0x000c000f, +0x011,0x0003f9f8, +0x014,0x0001093e, +0x014,0x0009093e, +0x015,0x000198f4, +0x017,0x000f6500, +0x01a,0x00013056, +0x01b,0x00060000, +0x01c,0x00000300, +0x01e,0x00031059, +0x021,0x00054000, +0x022,0x0000083c, +0x023,0x00001558, +0x024,0x00000060, +0x025,0x00022583, +0x026,0x0000f200, +0x027,0x000eacf1, +0x028,0x000dbd54, +0x029,0x00004582, +0x02a,0x00000001, +0x02b,0x00021334, +0x02a,0x00000000, +0x02b,0x0000000a, +0x02a,0x00000001, +0x02b,0x00000808, +0x02b,0x00053333, +0x02c,0x0000000c, +0x02a,0x00000002, +0x02b,0x00000808, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000003, +0x02b,0x00000808, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000004, +0x02b,0x00000808, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000005, +0x02b,0x00000709, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x00000006, +0x02b,0x00000709, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000007, +0x02b,0x00000709, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000008, +0x02b,0x00000709, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000009, +0x02b,0x0000060a, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000a, +0x02b,0x0000060a, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x0000000b, +0x02b,0x0000060a, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x0000000c, +0x02b,0x0000060a, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x0000000d, +0x02b,0x0000050b, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000e, +0x02b,0x0000050b, +0x02b,0x00066623, +0x02c,0x0000001a, +0x02a,0x000e4000, +0x030,0x00020000, +0x031,0x000b9631, +0x033,0x00000187, +0x013,0x00019e6c, +0x013,0x00015e94, +0x000,0x00010159, +0x018,0x0000f401, +0x0fe,0x00000000, +0x01e,0x0003105b, +0x0fe,0x00000000, +0x000,0x00030159, +0x010,0x0004000f, +0x011,0x000203f9, +}; + +u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength] = { +0x000,0x00030159, +0x001,0x00030250, +0x002,0x00010000, +0x010,0x0008000f, +0x011,0x000231fc, +0x010,0x000c000f, +0x011,0x0003f9f8, +0x014,0x0001093e, +0x014,0x0009093e, +0x015,0x000198f4, +0x017,0x000f6500, +0x01a,0x00013056, +0x01b,0x00060000, +0x01c,0x00000300, +0x01e,0x00031059, +0x021,0x00054000, +0x022,0x0000083c, +0x023,0x00001558, +0x024,0x00000060, +0x025,0x00022583, +0x026,0x0000f200, +0x027,0x000eacf1, +0x028,0x000dbd54, +0x029,0x00004582, +0x02a,0x00000001, +0x02b,0x00021334, +0x02a,0x00000000, +0x02b,0x0000000a, +0x02a,0x00000001, +0x02b,0x00000808, +0x02b,0x00053333, +0x02c,0x0000000c, +0x02a,0x00000002, +0x02b,0x00000808, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000003, +0x02b,0x00000808, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000004, +0x02b,0x00000808, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000005, +0x02b,0x00000709, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x00000006, +0x02b,0x00000709, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000007, +0x02b,0x00000709, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000008, +0x02b,0x00000709, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000009, +0x02b,0x0000060a, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000a, +0x02b,0x0000060a, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x0000000b, +0x02b,0x0000060a, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x0000000c, +0x02b,0x0000060a, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x0000000d, +0x02b,0x0000050b, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000e, +0x02b,0x0000050b, +0x02b,0x00066623, +0x02c,0x0000001a, +0x02a,0x000e4000, +0x030,0x00020000, +0x031,0x000b9631, +0x033,0x00000187, +0x013,0x00019e6c, +0x013,0x00015e94, +0x000,0x00010159, +0x018,0x0000f401, +0x0fe,0x00000000, +0x01e,0x0003105b, +0x0fe,0x00000000, +0x000,0x00030159, +0x010,0x0004000f, +0x011,0x000203f9, +}; + +u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength] = { +0x000,0x00030159, +0x001,0x00001041, +0x002,0x00011000, +0x005,0x00080fc0, +0x007,0x000fc803, +}; + +u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength] = { +0x020,0x00000035, +0x048,0x0000000e, +0x049,0x000000f0, +0x04a,0x00000077, +0x04b,0x00000083, +0x0b5,0x00000021, +0x0dc,0x000000ff, +0x0dd,0x000000ff, +0x0de,0x000000ff, +0x0df,0x000000ff, +0x116,0x00000000, +0x117,0x00000000, +0x118,0x00000000, +0x119,0x00000000, +0x11a,0x00000000, +0x11b,0x00000000, +0x11c,0x00000000, +0x11d,0x00000000, +0x160,0x0000000b, +0x161,0x0000000b, +0x162,0x0000000b, +0x163,0x0000000b, +0x164,0x0000000b, +0x165,0x0000000b, +0x166,0x0000000b, +0x167,0x0000000b, +0x168,0x0000000b, +0x169,0x0000000b, +0x16a,0x0000000b, +0x16b,0x0000000b, +0x16c,0x0000000b, +0x16d,0x0000000b, +0x16e,0x0000000b, +0x16f,0x0000000b, +0x170,0x0000000b, +0x171,0x0000000b, +0x172,0x0000000b, +0x173,0x0000000b, +0x174,0x0000000b, +0x175,0x0000000b, +0x176,0x0000000b, +0x177,0x0000000b, +0x178,0x0000000b, +0x179,0x0000000b, +0x17a,0x0000000b, +0x17b,0x0000000b, +0x17c,0x0000000b, +0x17d,0x0000000b, +0x17e,0x0000000b, +0x17f,0x0000000b, +0x236,0x0000000c, +0x503,0x00000022, +0x560,0x00000000, +}; + +u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength] = { +0x0, }; + +u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength] = { +0xc78,0x7f000001, +0xc78,0x7f010001, +0xc78,0x7e020001, +0xc78,0x7d030001, +0xc78,0x7c040001, +0xc78,0x7b050001, +0xc78,0x7a060001, +0xc78,0x79070001, +0xc78,0x78080001, +0xc78,0x77090001, +0xc78,0x760a0001, +0xc78,0x750b0001, +0xc78,0x740c0001, +0xc78,0x730d0001, +0xc78,0x720e0001, +0xc78,0x710f0001, +0xc78,0x70100001, +0xc78,0x6f110001, +0xc78,0x6f120001, +0xc78,0x6e130001, +0xc78,0x6d140001, +0xc78,0x6d150001, +0xc78,0x6c160001, +0xc78,0x6b170001, +0xc78,0x6a180001, +0xc78,0x6a190001, +0xc78,0x691a0001, +0xc78,0x681b0001, +0xc78,0x671c0001, +0xc78,0x661d0001, +0xc78,0x651e0001, +0xc78,0x641f0001, +0xc78,0x63200001, +0xc78,0x4c210001, +0xc78,0x4b220001, +0xc78,0x4a230001, +0xc78,0x49240001, +0xc78,0x48250001, +0xc78,0x47260001, +0xc78,0x46270001, +0xc78,0x45280001, +0xc78,0x44290001, +0xc78,0x2c2a0001, +0xc78,0x2b2b0001, +0xc78,0x2a2c0001, +0xc78,0x292d0001, +0xc78,0x282e0001, +0xc78,0x272f0001, +0xc78,0x26300001, +0xc78,0x25310001, +0xc78,0x24320001, +0xc78,0x23330001, +0xc78,0x22340001, +0xc78,0x09350001, +0xc78,0x08360001, +0xc78,0x07370001, +0xc78,0x06380001, +0xc78,0x05390001, +0xc78,0x043a0001, +0xc78,0x033b0001, +0xc78,0x023c0001, +0xc78,0x013d0001, +0xc78,0x003e0001, +0xc78,0x003f0001, +0xc78,0x7f400001, +0xc78,0x7f410001, +0xc78,0x7e420001, +0xc78,0x7d430001, +0xc78,0x7c440001, +0xc78,0x7b450001, +0xc78,0x7a460001, +0xc78,0x79470001, +0xc78,0x78480001, +0xc78,0x77490001, +0xc78,0x764a0001, +0xc78,0x754b0001, +0xc78,0x744c0001, +0xc78,0x734d0001, +0xc78,0x724e0001, +0xc78,0x714f0001, +0xc78,0x70500001, +0xc78,0x6f510001, +0xc78,0x6f520001, +0xc78,0x6e530001, +0xc78,0x6d540001, +0xc78,0x6d550001, +0xc78,0x6c560001, +0xc78,0x6b570001, +0xc78,0x6a580001, +0xc78,0x6a590001, +0xc78,0x695a0001, +0xc78,0x685b0001, +0xc78,0x675c0001, +0xc78,0x665d0001, +0xc78,0x655e0001, +0xc78,0x645f0001, +0xc78,0x63600001, +0xc78,0x4c610001, +0xc78,0x4b620001, +0xc78,0x4a630001, +0xc78,0x49640001, +0xc78,0x48650001, +0xc78,0x47660001, +0xc78,0x46670001, +0xc78,0x45680001, +0xc78,0x44690001, +0xc78,0x2c6a0001, +0xc78,0x2b6b0001, +0xc78,0x2a6c0001, +0xc78,0x296d0001, +0xc78,0x286e0001, +0xc78,0x276f0001, +0xc78,0x26700001, +0xc78,0x25710001, +0xc78,0x24720001, +0xc78,0x23730001, +0xc78,0x22740001, +0xc78,0x09750001, +0xc78,0x08760001, +0xc78,0x07770001, +0xc78,0x06780001, +0xc78,0x05790001, +0xc78,0x047a0001, +0xc78,0x037b0001, +0xc78,0x027c0001, +0xc78,0x017d0001, +0xc78,0x007e0001, +0xc78,0x007f0001, +0xc78,0x3000001e, +0xc78,0x3001001e, +0xc78,0x3002001e, +0xc78,0x3003001e, +0xc78,0x3004001e, +0xc78,0x3405001e, +0xc78,0x3806001e, +0xc78,0x3e07001e, +0xc78,0x3e08001e, +0xc78,0x4409001e, +0xc78,0x460a001e, +0xc78,0x480b001e, +0xc78,0x480c001e, +0xc78,0x4e0d001e, +0xc78,0x560e001e, +0xc78,0x5a0f001e, +0xc78,0x5e10001e, +0xc78,0x6211001e, +0xc78,0x6c12001e, +0xc78,0x7213001e, +0xc78,0x7214001e, +0xc78,0x7215001e, +0xc78,0x7216001e, +0xc78,0x7217001e, +0xc78,0x7218001e, +0xc78,0x7219001e, +0xc78,0x721a001e, +0xc78,0x721b001e, +0xc78,0x721c001e, +0xc78,0x721d001e, +0xc78,0x721e001e, +0xc78,0x721f001e, +}; + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg492.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg492.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef __INC_HAL8192SE_FW_IMG_H +#define __INC_HAL8192SE_FW_IMG_H + +/*Created on 2009/ 7/23, 5: 4*/ + +#include +#define ImgArrayLength 75984 +extern u8 Rtl8192SEFwImgArray[ImgArrayLength]; +#define MainArrayLength 1 +extern u8 Rtl8192SEFwMainArray[MainArrayLength]; +#define DataArrayLength 1 +extern u8 Rtl8192SEFwDataArray[DataArrayLength]; +#define PHY_REG_2T2RArrayLength 372 +extern u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength]; +#define PHY_REG_1T2RArrayLength 1 +extern u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength]; +#define PHY_ChangeTo_1T1RArrayLength 48 +extern u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength]; +#define PHY_ChangeTo_1T2RArrayLength 45 +extern u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength]; +#define PHY_ChangeTo_2T2RArrayLength 45 +extern u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength]; +#define PHY_REG_Array_PGLength 84 +extern u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength]; +#define RadioA_1T_ArrayLength 202 +extern u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength]; +#define RadioB_ArrayLength 22 +extern u32 Rtl8192SERadioB_Array[RadioB_ArrayLength]; +#define RadioA_to1T_ArrayLength 196 +extern u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength]; +#define RadioA_to2T_ArrayLength 196 +extern u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength]; +#define RadioB_GM_ArrayLength 10 +extern u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength]; +#define MAC_2T_ArrayLength 106 +extern u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength]; +#define MACPHY_Array_PGLength 1 +extern u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength]; +#define AGCTAB_ArrayLength 320 +extern u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength]; + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg74.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg74.c @@ -0,0 +1,6398 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +/*Created on 2009/11/17, 16:15*/ + +#ifdef RTL8192SE +#include "r8192S_hwimg.h" + +u8 Rtl8192SEFwImgArray[ImgArrayLength] = { +0x92,0x81,0x4a,0x70,0x30,0x00,0x00,0x00,0x08,0xa4,0x00,0x00,0x88,0xb5,0x00,0x00, +0x30,0x00,0x00,0x00,0x00,0xb4,0x00,0x00,0x4a,0x00,0x00,0x00,0x11,0x17,0x13,0x29, +0x92,0x81,0x01,0x01,0x00,0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x7f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x1f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x25,0xb0,0x1a,0x3c,0x80,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,0x80,0x00,0x7b,0x37, +0x00,0x00,0x5b,0xaf,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c, +0x80,0x00,0x7b,0x37,0x00,0x00,0x5b,0xaf,0x01,0x80,0x1a,0x3c,0x10,0x9d,0x5a,0x27, +0x08,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x04,0x00,0xa1,0xaf,0x08,0x00,0xa2,0xaf,0x0c,0x00,0xa3,0xaf,0x10,0x00,0xa4,0xaf, +0x14,0x00,0xa5,0xaf,0x18,0x00,0xa6,0xaf,0x1c,0x00,0xa7,0xaf,0x20,0x00,0xa8,0xaf, +0x24,0x00,0xa9,0xaf,0x28,0x00,0xaa,0xaf,0x2c,0x00,0xab,0xaf,0x30,0x00,0xac,0xaf, +0x34,0x00,0xad,0xaf,0x38,0x00,0xae,0xaf,0x3c,0x00,0xaf,0xaf,0x12,0x40,0x00,0x00, +0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0xb0,0xaf,0x44,0x00,0xb1,0xaf, +0x48,0x00,0xb2,0xaf,0x4c,0x00,0xb3,0xaf,0x50,0x00,0xb4,0xaf,0x54,0x00,0xb5,0xaf, +0x58,0x00,0xb6,0xaf,0x5c,0x00,0xb7,0xaf,0x60,0x00,0xb8,0xaf,0x64,0x00,0xb9,0xaf, +0x68,0x00,0xbc,0xaf,0x6c,0x00,0xbd,0xaf,0x70,0x00,0xbe,0xaf,0x74,0x00,0xbf,0xaf, +0x78,0x00,0xa8,0xaf,0x7c,0x00,0xa9,0xaf,0x80,0x00,0xaa,0xaf,0xda,0x26,0x00,0x08, +0x21,0x20,0xa0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0x88,0x30,0x80,0x28,0x08,0x00,0x2a,0xb0,0x0a,0x3c,0x21,0x38,0xaa,0x00, +0x0c,0x00,0xe6,0x8c,0x02,0x80,0x03,0x3c,0xcc,0x3f,0x63,0x24,0x25,0xb0,0x02,0x3c, +0xb0,0x03,0x42,0x34,0x21,0x28,0xa3,0x00,0xff,0x00,0xc4,0x30,0xff,0x00,0x09,0x24, +0x00,0x00,0x45,0xac,0x00,0x00,0x43,0xac,0x05,0x00,0x89,0x10,0x00,0x00,0x00,0x00, +0x00,0x80,0xc2,0x30,0x04,0x00,0x40,0x10,0x00,0x80,0x02,0x3c,0x0c,0x00,0xe2,0xac, +0x08,0x00,0xe0,0x03,0x21,0x10,0xc0,0x00,0x00,0xff,0x02,0x3c,0x24,0x10,0xc2,0x00, +0xfb,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x21,0x20,0x0a,0x01,0x40,0x00,0x82,0x90, +0x00,0x00,0x00,0x00,0xff,0x00,0x43,0x30,0x12,0x00,0x69,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0xa3,0xa0,0x40,0x00,0x83,0x90,0x00,0x00,0xa6,0x90,0xff,0x00,0x63,0x30, +0xff,0x00,0xc2,0x30,0xfa,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x20,0xb0,0x03,0x3c, +0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x46,0x8c,0x25,0xb0,0x03,0x3c, +0xb0,0x03,0x63,0x34,0x21,0x10,0xc0,0x00,0x00,0x00,0x66,0xac,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0xa6,0x90,0xe7,0x00,0x00,0x08,0xff,0x00,0xc2,0x30, +0xff,0xff,0x84,0x30,0x80,0x20,0x04,0x00,0x2a,0xb0,0x02,0x3c,0x21,0x48,0x82,0x00, +0x00,0x00,0x25,0x8d,0x02,0x80,0x02,0x3c,0xec,0x3f,0x42,0x24,0x21,0x40,0x82,0x00, +0x25,0xb0,0x03,0x3c,0x02,0x80,0x02,0x3c,0xb0,0x03,0x67,0x34,0xcc,0x3f,0x42,0x24, +0xff,0x00,0xa4,0x30,0xff,0x00,0x03,0x24,0x00,0x00,0xe8,0xac,0x00,0x80,0xa6,0x30, +0x00,0x00,0xe2,0xac,0x06,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x00,0xff,0x02,0x3c, +0x05,0x00,0xc0,0x10,0x24,0x10,0xa2,0x00,0x00,0x80,0x02,0x3c,0x00,0x00,0x22,0xad, +0x08,0x00,0xe0,0x03,0x21,0x10,0xa0,0x00,0xfd,0xff,0x40,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0x03,0x91,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x0c,0x00,0x65,0x8c,0x00,0x00,0x00,0x00,0x21,0x10,0xa0,0x00,0x00,0x00,0xe5,0xac, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x05,0x3c,0x00,0x80,0x02,0x3c, +0xe0,0xff,0xbd,0x27,0x18,0x03,0xa3,0x34,0x68,0x04,0x42,0x24,0x18,0x00,0xbf,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x42,0xb0,0x02,0x3c,0x03,0x00,0x46,0x34, +0x00,0x00,0xc3,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x70,0x30,0x10,0x00,0x02,0x32, +0x18,0x00,0x40,0x10,0x02,0x80,0x11,0x3c,0x78,0x1b,0x27,0x26,0xec,0x23,0xe4,0x94, +0x10,0x00,0x02,0x24,0x00,0x00,0xc2,0xa0,0x08,0x00,0x80,0x10,0x1c,0x03,0xa3,0x34, +0xf0,0x23,0xe2,0x94,0xb0,0x03,0xa4,0x34,0x00,0x00,0x62,0xa0,0x00,0x00,0x80,0xac, +0xec,0x23,0xe0,0xa4,0xf0,0x23,0xe0,0xa4,0x00,0x00,0x04,0x24,0x02,0x80,0x05,0x3c, +0x02,0x80,0x06,0x3c,0x8c,0x43,0xa2,0x8c,0xbc,0x44,0xc3,0x8c,0x01,0x00,0x84,0x24, +0x01,0x00,0x42,0x24,0x01,0x00,0x63,0x24,0xec,0x23,0xe4,0xa4,0x8c,0x43,0xa2,0xac, +0xbc,0x44,0xc3,0xac,0x00,0x16,0x10,0x00,0x03,0x16,0x02,0x00,0x71,0x00,0x40,0x04, +0x42,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x40,0x00,0x02,0x32,0x16,0x00,0x40,0x10,0x78,0x1b,0x24,0x26, +0x42,0xb0,0x03,0x3c,0x40,0x00,0x02,0x24,0x03,0x00,0x63,0x34,0x00,0x00,0x62,0xa0, +0x02,0x80,0x03,0x3c,0xb6,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x1a,0x00,0x40,0x10, +0x02,0x80,0x04,0x3c,0xb6,0x44,0x60,0xa0,0x02,0x80,0x04,0x3c,0xb2,0x44,0x83,0x90, +0xfd,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0xb2,0x44,0x83,0xa0,0xb2,0x44,0x82,0x90, +0x00,0x00,0x00,0x00,0x07,0x00,0x42,0x30,0x2c,0x00,0x40,0x10,0x02,0x80,0x02,0x3c, +0x78,0x1b,0x24,0x26,0x18,0x0b,0x83,0x94,0x14,0x0b,0x85,0x94,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c, +0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,0x20,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4, +0x08,0x00,0xe0,0x03,0x14,0x0b,0x83,0xa4,0x9e,0x44,0x82,0x90,0x02,0x80,0x05,0x3c, +0x01,0x00,0x42,0x24,0x9e,0x44,0x82,0xa0,0xb2,0x44,0xa3,0x90,0xef,0xff,0x02,0x24, +0x24,0x18,0x62,0x00,0xb2,0x44,0xa3,0xa0,0x9e,0x44,0x82,0x90,0x00,0x00,0x00,0x00, +0x02,0x00,0x42,0x2c,0x24,0x00,0x40,0x14,0x78,0x1b,0x23,0x26,0xe8,0x0a,0x62,0x90, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x3d,0x00,0x40,0x10,0x02,0x80,0x02,0x3c, +0x02,0x80,0x03,0x3c,0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0xdc,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24, +0xb9,0x44,0x62,0xa0,0x65,0x01,0x00,0x08,0x78,0x1b,0x24,0x26,0xb0,0x44,0x40,0xa0, +0x02,0x80,0x03,0x3c,0x99,0x44,0x64,0x90,0xf9,0x1f,0x00,0x0c,0xff,0x00,0x84,0x30, +0x78,0x1b,0x24,0x26,0x18,0x0b,0x83,0x94,0x14,0x0b,0x85,0x94,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c, +0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,0x20,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4, +0x08,0x00,0xe0,0x03,0x14,0x0b,0x83,0xa4,0x02,0x80,0x05,0x3c,0x02,0x80,0x03,0x3c, +0xac,0x44,0xa2,0x8c,0xa4,0x44,0x64,0x8c,0x02,0x80,0x03,0x3c,0x21,0x10,0x44,0x00, +0xac,0x44,0xa2,0xac,0xac,0x44,0xa4,0x8c,0x25,0xb0,0x02,0x3c,0xe4,0x02,0x42,0x34, +0x00,0x00,0x44,0xac,0xa0,0x44,0x62,0x94,0x02,0x80,0x05,0x3c,0x99,0x44,0xa4,0x90, +0xff,0xff,0x42,0x30,0x40,0x10,0x02,0x00,0xf6,0xff,0x42,0x24,0x02,0x80,0x03,0x3c, +0xff,0x00,0x84,0x30,0xf9,0x1f,0x00,0x0c,0x88,0x44,0x62,0xac,0x95,0x01,0x00,0x08, +0x78,0x1b,0x24,0x26,0x80,0xff,0x03,0x24,0x03,0x00,0x42,0x34,0x00,0x00,0x43,0xa0, +0x1b,0x16,0x00,0x0c,0x00,0x00,0x00,0x00,0x49,0x01,0x00,0x08,0x00,0x00,0x00,0x00, +0xb9,0x44,0x40,0xa0,0x65,0x01,0x00,0x08,0x78,0x1b,0x24,0x26,0xff,0x00,0x84,0x30, +0x0b,0x00,0x82,0x2c,0xff,0xff,0xe7,0x30,0x10,0x00,0xa8,0x93,0x19,0x00,0x40,0x10, +0x21,0x18,0x00,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,0x48,0xaf,0x63,0x24, +0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00, +0x00,0x00,0x00,0x00,0x43,0xb0,0x02,0x3c,0x78,0x00,0x44,0x34,0x07,0x00,0xe2,0x30, +0x00,0x00,0x85,0xac,0x04,0x00,0x86,0xac,0x04,0x00,0x40,0x18,0x00,0x00,0x00,0x00, +0xf8,0xff,0xe2,0x30,0x08,0x00,0x42,0x24,0xff,0xff,0x47,0x30,0x21,0x10,0xe8,0x00, +0x00,0x80,0x03,0x3c,0x08,0x00,0x82,0xac,0x25,0x10,0x43,0x00,0x08,0x00,0x82,0xac, +0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x43,0xb0,0x02,0x3c, +0xd3,0x01,0x00,0x08,0x6c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08, +0x60,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08,0x54,0x00,0x44,0x34, +0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08,0x48,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c, +0xd3,0x01,0x00,0x08,0x3c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08, +0x30,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08,0x24,0x00,0x44,0x34, +0x43,0xb0,0x02,0x3c,0xd3,0x01,0x00,0x08,0x18,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c, +0xd3,0x01,0x00,0x08,0x0c,0x00,0x44,0x34,0xd3,0x01,0x00,0x08,0x43,0xb0,0x04,0x3c, +0x01,0x00,0x02,0x24,0x43,0xb0,0x03,0x3c,0x04,0x20,0x82,0x00,0x88,0x00,0x65,0x34, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0xff,0x42,0x30,0x05,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x00,0x00,0xa2,0x94,0x00,0x00,0x00,0x00, +0xff,0xff,0x42,0x30,0x24,0x10,0x44,0x00,0xf5,0xff,0x40,0x1c,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,0x00,0x80,0x02,0x3c, +0xd0,0xff,0xbd,0x27,0x18,0x03,0x03,0x35,0x48,0x08,0x42,0x24,0x00,0x00,0x62,0xac, +0x28,0x00,0xb4,0xaf,0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0x2c,0x00,0xbf,0xaf, +0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x08,0x00,0xf3,0x8c,0xff,0x00,0xc6,0x30, +0x00,0x01,0x02,0x24,0x0c,0x00,0xf1,0x84,0x23,0x10,0x46,0x00,0xff,0xff,0xa3,0x30, +0xff,0xff,0x50,0x30,0xff,0x00,0x94,0x30,0xd0,0x03,0x08,0x35,0x21,0x30,0xc5,0x00, +0x21,0x20,0x80,0x02,0x21,0x28,0x60,0x02,0x21,0x38,0x00,0x02,0x02,0x92,0x03,0x00, +0x00,0x00,0x11,0xad,0x00,0x00,0x13,0xad,0x42,0x02,0x00,0x08,0x00,0x00,0x00,0x00, +0x01,0x01,0x23,0x2a,0xff,0xff,0x22,0x32,0x21,0x98,0x70,0x02,0x21,0x20,0x80,0x02, +0x00,0x01,0x10,0x24,0x00,0x02,0x00,0x0c,0x0b,0x80,0x43,0x00,0xc0,0x10,0x12,0x00, +0x28,0xb0,0x03,0x3c,0x21,0x10,0x43,0x00,0x00,0x00,0x45,0x90,0x20,0x10,0x06,0x3c, +0x21,0x20,0x80,0x02,0xff,0x00,0xb2,0x30,0x00,0x12,0x12,0x00,0x21,0x30,0x46,0x00, +0x21,0x28,0x60,0x02,0x21,0x38,0x00,0x02,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x23,0x18,0x30,0x02,0x00,0x8c,0x03,0x00,0x03,0x8c,0x11,0x00,0xe8,0xff,0x20,0x1e, +0x00,0x00,0x00,0x00,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x30,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x18,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf, +0x21,0x38,0x80,0x00,0x02,0x80,0x02,0x3c,0x78,0x1b,0x44,0x24,0x00,0x00,0xe8,0x94, +0x28,0x24,0x83,0x8c,0x21,0x80,0xa0,0x00,0x27,0x10,0x08,0x00,0x2b,0x10,0x62,0x00, +0x03,0x00,0x40,0x10,0x21,0x28,0xc0,0x00,0x21,0x10,0x68,0x00,0x28,0x24,0x82,0xac, +0x04,0x24,0x82,0x8c,0x04,0x00,0xe3,0x8c,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30, +0x20,0x00,0x40,0x14,0x1f,0x00,0x64,0x30,0x08,0x00,0xe2,0x8c,0xff,0xe0,0x03,0x3c, +0xff,0xff,0x63,0x34,0x00,0x26,0x04,0x00,0x24,0x10,0x43,0x00,0x25,0x18,0x44,0x00, +0x10,0x00,0xe4,0x8c,0x00,0x00,0x00,0x00,0x1a,0x00,0x80,0x04,0x08,0x00,0xe3,0xac, +0x82,0x11,0x03,0x00,0x01,0x00,0x42,0x30,0x05,0x00,0x40,0x14,0x02,0x00,0x04,0x24, +0xc0,0xff,0x02,0x24,0x24,0x10,0x62,0x00,0x0f,0x00,0x42,0x34,0x08,0x00,0xe2,0xac, +0x21,0x30,0x00,0x02,0x01,0x00,0x02,0x24,0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c, +0x10,0x00,0xa2,0xaf,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x50,0xac, +0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb0,0x8f,0x02,0x00,0x04,0x24,0x00,0x02,0x00,0x08, +0x20,0x00,0xbd,0x27,0x10,0x00,0xe4,0x8c,0x08,0x00,0xe3,0x8c,0xe9,0xff,0x81,0x04, +0x82,0x11,0x03,0x00,0x14,0x00,0xe2,0x8c,0x00,0x00,0x00,0x00,0x42,0x12,0x02,0x00, +0x3f,0x00,0x42,0x30,0x14,0x00,0x42,0x28,0xe2,0xff,0x40,0x14,0x82,0x11,0x03,0x00, +0x9f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x82,0x00,0x70,0x02,0x00,0x08, +0x10,0x00,0xe2,0xac,0xff,0xff,0x84,0x30,0x2a,0xb0,0x02,0x3c,0x0d,0x00,0x42,0x34, +0x80,0x20,0x04,0x00,0x21,0x20,0x82,0x00,0x04,0x00,0x82,0x24,0xff,0xff,0xa5,0x30, +0x0b,0x20,0x45,0x00,0x01,0x00,0x03,0x24,0x02,0x00,0x02,0x24,0x00,0x00,0x83,0xa0, +0x00,0x00,0x82,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xc0,0xff,0xbd,0x27, +0x02,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0x24,0x00,0xb3,0xaf,0x78,0x1b,0x53,0x24, +0x00,0x80,0x02,0x3c,0x38,0x00,0xbe,0xaf,0x8c,0x0a,0x42,0x24,0xb0,0x03,0x7e,0x34, +0x18,0x03,0x63,0x34,0x2c,0x00,0xb5,0xaf,0x3c,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf, +0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x21,0xa8,0x60,0x02,0xc0,0x24,0x62,0x8e, +0x2c,0x25,0x72,0x8e,0x21,0x20,0x00,0x00,0x00,0x00,0xc2,0xaf,0xc4,0x24,0x62,0xae, +0x00,0x00,0xd2,0xaf,0x00,0x02,0x00,0x0c,0x21,0xa0,0xa0,0x02,0x2c,0x25,0x64,0x8e, +0x30,0x25,0x63,0x8e,0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00, +0x0a,0x18,0x82,0x00,0x02,0x80,0x02,0x3c,0x2c,0x25,0x63,0xae,0x74,0xaf,0x42,0x24, +0x2c,0x25,0xa5,0x8e,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac, +0x02,0x80,0x02,0x3c,0xff,0xff,0x43,0x32,0x25,0x80,0x62,0x00,0x00,0x00,0x90,0xac, +0x0c,0x00,0x02,0x92,0xff,0x00,0x16,0x24,0x01,0x00,0x17,0x24,0x00,0x00,0x82,0xac, +0x0c,0x00,0x11,0x92,0x20,0x10,0x02,0x3c,0x21,0x20,0x00,0x00,0x00,0x1a,0x11,0x00, +0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x05,0x00,0x36,0x12,0x40,0x00,0x07,0x24, +0xc0,0x24,0xa3,0xae,0x74,0x24,0xb1,0xa2,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x00,0x00,0x02,0x96,0x24,0x24,0x83,0x8e,0x21,0x28,0x40,0x02,0x27,0x30,0x02,0x00, +0x21,0x10,0x62,0x00,0x2b,0x18,0x66,0x00,0x21,0x20,0x00,0x00,0x02,0x00,0x60,0x10, +0x40,0x00,0x07,0x24,0x24,0x24,0x82,0xae,0x04,0x00,0x06,0x8e,0x08,0x00,0x03,0x8e, +0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0xc6,0x30,0x24,0x18,0x62,0x00, +0x00,0x36,0x06,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x66,0x00,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x00,0x40,0x06,0x3c,0x25,0x18,0x66,0x00,0xc0,0xff,0x02,0x24, +0x24,0x18,0x62,0x00,0x08,0x00,0x03,0xae,0xc4,0x24,0xa6,0x8e,0xc3,0x01,0x00,0x0c, +0x10,0x00,0xb7,0xaf,0xc4,0x24,0xa3,0x8e,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34, +0x00,0x00,0x43,0xac,0x00,0x02,0x00,0x0c,0x21,0x20,0x00,0x00,0x2a,0xb0,0x02,0x3c, +0x01,0x00,0x42,0x34,0x02,0x00,0x03,0x24,0x00,0x00,0x57,0xa0,0x00,0x00,0x43,0xa0, +0xae,0xff,0x36,0x16,0x41,0xb0,0x03,0x3c,0x08,0x0b,0xa2,0x8e,0x3c,0x00,0xbf,0x8f, +0x00,0x38,0x42,0x34,0x00,0x00,0x62,0xac,0x38,0x00,0xbe,0x8f,0x08,0x0b,0xa2,0xae, +0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c, +0xc0,0xff,0xbd,0x27,0x18,0x03,0x83,0x34,0x68,0x0c,0x42,0x24,0x3c,0x00,0xbf,0xaf, +0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf, +0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x78,0x1b,0x55,0x24,0xb0,0x03,0x96,0x34, +0x4e,0x03,0x00,0x08,0x21,0xf0,0xa0,0x02,0x24,0x10,0x62,0x00,0x04,0x00,0x42,0x34, +0x02,0x80,0x03,0x3c,0x78,0x1b,0x71,0x24,0x08,0x00,0x02,0xae,0xdc,0x24,0x26,0x8e, +0x01,0x00,0x04,0x24,0x21,0x28,0x80,0x02,0x40,0x00,0x07,0x24,0x01,0x00,0x12,0x24, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xb2,0xaf,0xdc,0x24,0x23,0x8e,0x25,0xb0,0x02,0x3c, +0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x02,0x00,0x0c,0x01,0x00,0x04,0x24, +0x82,0x0b,0x22,0x92,0x00,0x00,0x00,0x00,0x88,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c, +0x09,0x00,0x42,0x34,0x02,0x00,0x03,0x24,0x00,0x00,0x52,0xa0,0x00,0x00,0x43,0xa0, +0x9d,0x00,0x77,0x12,0x00,0x00,0x00,0x00,0xd8,0x24,0xa2,0x8e,0x44,0x25,0xb4,0x8e, +0x01,0x00,0x04,0x24,0x00,0x00,0xc2,0xae,0xdc,0x24,0xa2,0xae,0x00,0x00,0xd4,0xae, +0x00,0x02,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x25,0xa4,0x8e,0x48,0x25,0xa3,0x8e, +0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00, +0x44,0x25,0xa3,0xae,0x44,0x25,0xc2,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xae, +0x02,0x80,0x11,0x3c,0xff,0xff,0x82,0x32,0x25,0x80,0x51,0x00,0x00,0x00,0xd0,0xae, +0x0c,0x00,0x03,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc3,0xae,0x02,0x00,0x02,0x92, +0x06,0x00,0x03,0x96,0x21,0x10,0x54,0x00,0xff,0xff,0x42,0x30,0x01,0x00,0x63,0x30, +0x12,0x00,0x60,0x10,0x25,0x30,0x51,0x00,0xec,0x0c,0xc3,0x97,0x00,0x00,0x00,0x00, +0x01,0x00,0x62,0x24,0xec,0x0c,0xc2,0xa7,0x0c,0x00,0x04,0x8e,0x00,0xf0,0x02,0x3c, +0xff,0x0f,0x63,0x30,0xff,0xff,0x42,0x34,0x00,0x2c,0x03,0x00,0x24,0x20,0x82,0x00, +0x25,0x20,0x85,0x00,0x0c,0x00,0x04,0xae,0x16,0x00,0xc2,0x94,0x00,0x19,0x03,0x00, +0x0f,0x00,0x42,0x30,0x25,0x10,0x43,0x00,0x16,0x00,0xc2,0xa4,0x02,0x80,0x03,0x3c, +0x98,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x17,0x00,0x40,0x10,0x02,0x80,0x03,0x3c, +0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,0x77,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00, +0x0f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x0b,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x21,0x10,0x54,0x00,0xff,0xff,0x42,0x30, +0x25,0x28,0x51,0x00,0x00,0x00,0xa4,0x94,0x08,0x00,0x02,0x24,0x0c,0x00,0x83,0x30, +0x6a,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x0c,0x00,0x13,0x92,0xff,0x00,0x17,0x24, +0x0d,0x00,0x77,0x12,0x02,0x80,0x02,0x3c,0x78,0x1b,0x48,0x24,0x00,0x1a,0x13,0x00, +0x20,0x10,0x02,0x3c,0x44,0x25,0x05,0x8d,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0x01,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0xd8,0x24,0x03,0xad,0x78,0x24,0x13,0xa1, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e, +0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00, +0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x82,0x11,0x03,0x00, +0x01,0x00,0x42,0x30,0x78,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,0x08,0x00,0x03,0xae, +0x02,0x80,0x03,0x3c,0x78,0x1b,0x71,0x24,0xdc,0x24,0x26,0x8e,0x01,0x00,0x04,0x24, +0x21,0x28,0x80,0x02,0x40,0x00,0x07,0x24,0x01,0x00,0x12,0x24,0xc3,0x01,0x00,0x0c, +0x10,0x00,0xb2,0xaf,0xdc,0x24,0x23,0x8e,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34, +0x00,0x00,0x43,0xac,0x00,0x02,0x00,0x0c,0x01,0x00,0x04,0x24,0x82,0x0b,0x22,0x92, +0x00,0x00,0x00,0x00,0x7a,0xff,0x40,0x14,0x2a,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x82,0x0b,0x32,0xa2, +0x02,0x00,0x02,0x92,0x02,0x80,0x03,0x3c,0x21,0x10,0x54,0x00,0xff,0xff,0x42,0x30, +0x25,0x10,0x43,0x00,0x02,0x00,0x45,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0xa4,0x30, +0x00,0xc0,0x84,0x24,0xff,0xff,0x84,0x30,0x2c,0x22,0x00,0x0c,0x83,0x0b,0x25,0xa2, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c, +0x09,0x00,0x42,0x34,0x02,0x00,0x03,0x24,0x00,0x00,0x52,0xa0,0x00,0x00,0x43,0xa0, +0x65,0xff,0x77,0x16,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x08,0x0b,0x22,0x8e,0x41,0xb0,0x03,0x3c, +0x3c,0x00,0xbf,0x8f,0x00,0x38,0x42,0x34,0x00,0x00,0x62,0xac,0x38,0x00,0xbe,0x8f, +0x08,0x0b,0x22,0xae,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f, +0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f, +0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x55,0x1f,0x00,0x0c, +0x01,0x00,0x04,0x24,0x8a,0x03,0x00,0x08,0x02,0x80,0x03,0x3c,0xb1,0x44,0x43,0x90, +0x00,0x00,0x00,0x00,0x94,0xff,0x60,0x14,0x00,0x10,0x82,0x34,0x9a,0x03,0x00,0x08, +0x00,0x00,0xa2,0xa4,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x24,0x10,0x63,0x24, +0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xc0,0xff,0xbd,0x27,0x2c,0x00,0xb5,0xaf,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf, +0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf, +0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c, +0x54,0x44,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34, +0x40,0x10,0x63,0x24,0x40,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,0x21,0xa8,0x00,0x00, +0x03,0x00,0x80,0x10,0x7f,0x00,0xa2,0x30,0xbf,0x00,0xa2,0x30,0x01,0x00,0x15,0x24, +0x54,0x44,0xc2,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x02,0x80,0x02,0x3c,0x78,0x1b,0x52,0x24,0x02,0x80,0x17,0x3c,0x02,0x80,0x14,0x3c, +0x21,0xf0,0x40,0x02,0x4c,0x04,0x00,0x08,0x21,0xb0,0x40,0x02,0x58,0x24,0xd0,0xa3, +0xfc,0x24,0x45,0x8e,0x90,0x24,0x46,0x8e,0x03,0x00,0x04,0x24,0x40,0x00,0x07,0x24, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x94,0x24,0xc5,0x8e,0x21,0x20,0x20,0x02, +0x51,0x02,0x00,0x0c,0x21,0x30,0x60,0x02,0x21,0x20,0x00,0x00,0x21,0x28,0xa0,0x02, +0x95,0x02,0x00,0x0c,0x21,0x30,0x00,0x02,0x9c,0x43,0x82,0x96,0x25,0xb0,0x05,0x3c, +0x66,0x03,0xa4,0x34,0x01,0x00,0x42,0x24,0x9c,0x43,0x82,0xa6,0x9c,0x43,0x83,0x96, +0xff,0x00,0x02,0x24,0x00,0x00,0x83,0xa4,0x5f,0x00,0x02,0x12,0x00,0x00,0x00,0x00, +0x90,0x24,0x42,0x8e,0x03,0x00,0x04,0x24,0xfc,0x24,0x53,0x8e,0x00,0x02,0x00,0x0c, +0x94,0x24,0x42,0xae,0xfc,0x24,0x44,0x8e,0x00,0x25,0x43,0x8e,0x02,0x80,0x10,0x3c, +0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00, +0xff,0xff,0x65,0x32,0x25,0x88,0xb0,0x00,0xfc,0x24,0x43,0xae,0x02,0x00,0x22,0x92, +0x06,0x00,0x23,0x96,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,0x01,0x00,0x63,0x30, +0x11,0x00,0x60,0x10,0x25,0x28,0x50,0x00,0xec,0x0c,0x44,0x96,0x00,0xf0,0x06,0x3c, +0xff,0xff,0xc6,0x34,0x01,0x00,0x82,0x24,0xec,0x0c,0x42,0xa6,0x0c,0x00,0x23,0x8e, +0xff,0x0f,0x84,0x30,0x00,0x14,0x04,0x00,0x24,0x18,0x66,0x00,0x25,0x18,0x62,0x00, +0x0c,0x00,0x23,0xae,0x16,0x00,0xa2,0x94,0x00,0x21,0x04,0x00,0x0f,0x00,0x42,0x30, +0x25,0x10,0x44,0x00,0x16,0x00,0xa2,0xa4,0x98,0x44,0xe2,0x92,0x00,0x00,0x00,0x00, +0x1c,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00, +0x02,0x00,0x42,0x30,0x21,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c, +0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28, +0x0b,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x00,0x22,0x92,0x00,0x00,0x00,0x00, +0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,0x25,0x28,0x50,0x00,0x00,0x00,0xa4,0x94, +0x08,0x00,0x02,0x24,0x0c,0x00,0x83,0x30,0x43,0x00,0x62,0x10,0x02,0x80,0x02,0x3c, +0x98,0x44,0xe2,0x92,0x05,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x0f,0x00,0x43,0x10, +0x02,0x80,0x03,0x3c,0x0c,0x00,0x30,0x92,0xff,0x00,0x02,0x24,0xa6,0xff,0x02,0x12, +0x00,0x12,0x10,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x9b,0xff,0xa0,0x16, +0x90,0x24,0xc2,0xaf,0x34,0x04,0x00,0x08,0x54,0x24,0xd0,0xa3,0x55,0x1f,0x00,0x0c, +0x01,0x00,0x04,0x24,0x7c,0x04,0x00,0x08,0x02,0x80,0x03,0x3c,0xb3,0x44,0x62,0x90, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0xee,0xff,0x40,0x10,0x02,0x80,0x03,0x3c, +0xb2,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x34,0xb2,0x44,0x62,0xa0, +0x91,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x29,0x00,0xa0,0x12,0x2a,0xb0,0x02,0x3c, +0x58,0x24,0xc3,0x92,0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00,0x41,0x00,0x42,0x34, +0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x78,0x1b,0x45,0x24,0x08,0x0b,0xa4,0x8c, +0x01,0x00,0x02,0x3c,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34, +0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac, +0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,0xb1,0x44,0x43,0x90,0x00,0x00,0x00,0x00, +0xbb,0xff,0x60,0x14,0x00,0x10,0x82,0x34,0x8c,0x04,0x00,0x08,0x00,0x00,0xa2,0xa4, +0x54,0x24,0xc3,0x92,0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00,0x40,0x00,0x42,0x34, +0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x78,0x1b,0x45,0x24,0x08,0x0b,0xa4,0x8c, +0x01,0x00,0x02,0x3c,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f, +0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34, +0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac, +0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,0xb8,0xff,0xbd,0x27,0x44,0x00,0xbf,0xaf, +0x40,0x00,0xbe,0xaf,0x3c,0x00,0xb7,0xaf,0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf, +0x30,0x00,0xb4,0xaf,0x2c,0x00,0xb3,0xaf,0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf, +0x20,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c,0x54,0x44,0xc5,0x90,0x00,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,0xd8,0x13,0x63,0x24,0x10,0x00,0xa4,0x30, +0x00,0x00,0x43,0xac,0x18,0x00,0xa0,0xaf,0x04,0x00,0x80,0x10,0xdf,0x00,0xa2,0x30, +0x01,0x00,0x03,0x24,0xef,0x00,0xa2,0x30,0x18,0x00,0xa3,0xaf,0x54,0x44,0xc2,0xa0, +0x54,0x44,0xc3,0x90,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x02,0x80,0x17,0x3c,0x78,0x1b,0xf4,0x26,0x21,0xa8,0x40,0x00,0x02,0x80,0x16,0x3c, +0x39,0x05,0x00,0x08,0x21,0xf0,0x80,0x02,0x60,0x24,0x71,0xa0,0x78,0x1b,0xe2,0x26, +0x9c,0x24,0x46,0x8c,0x08,0x25,0x45,0x8c,0x04,0x00,0x04,0x24,0x40,0x00,0x07,0x24, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x78,0x1b,0xf2,0x26,0xa0,0x24,0x45,0x8e, +0x21,0x20,0x00,0x02,0x51,0x02,0x00,0x0c,0x21,0x30,0x60,0x02,0x18,0x00,0xa5,0x8f, +0x02,0x00,0x04,0x24,0x95,0x02,0x00,0x0c,0x21,0x30,0x20,0x02,0x9c,0x43,0xc2,0x96, +0x25,0xb0,0x05,0x3c,0x66,0x03,0xa4,0x34,0x01,0x00,0x42,0x24,0x9c,0x43,0xc2,0xa6, +0x9c,0x43,0xc3,0x96,0xff,0x00,0x02,0x24,0x00,0x00,0x83,0xa4,0x71,0x00,0x22,0x12, +0x00,0x00,0x00,0x00,0x9c,0x24,0x82,0x8e,0x08,0x25,0x93,0x8e,0x04,0x00,0x04,0x24, +0x00,0x00,0xa2,0xae,0xa0,0x24,0x82,0xae,0x00,0x00,0xb3,0xae,0x00,0x02,0x00,0x0c, +0x00,0x00,0x00,0x00,0x08,0x25,0x84,0x8e,0x0c,0x25,0x83,0x8e,0x40,0x00,0x84,0x24, +0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x08,0x25,0x83,0xae, +0x08,0x25,0xc2,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xae,0x02,0x80,0x11,0x3c, +0xff,0xff,0x62,0x32,0x25,0x80,0x51,0x00,0x00,0x00,0xb0,0xae,0x0c,0x00,0x03,0x92, +0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xae,0x02,0x00,0x02,0x92,0x06,0x00,0x03,0x96, +0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,0x01,0x00,0x63,0x30,0x12,0x00,0x60,0x10, +0x25,0x30,0x51,0x00,0xec,0x0c,0xc3,0x97,0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x24, +0xec,0x0c,0xc2,0xa7,0x0c,0x00,0x04,0x8e,0x00,0xf0,0x02,0x3c,0xff,0x0f,0x63,0x30, +0xff,0xff,0x42,0x34,0x00,0x2c,0x03,0x00,0x24,0x20,0x82,0x00,0x25,0x20,0x85,0x00, +0x0c,0x00,0x04,0xae,0x16,0x00,0xc2,0x94,0x00,0x19,0x03,0x00,0x0f,0x00,0x42,0x30, +0x25,0x10,0x43,0x00,0x16,0x00,0xc2,0xa4,0x02,0x80,0x03,0x3c,0x98,0x44,0x62,0x90, +0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c, +0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,0x31,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00, +0x0f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x0c,0x00,0x40,0x10,0x02,0x80,0x03,0x3c, +0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30, +0x25,0x28,0x51,0x00,0x00,0x00,0xa4,0x94,0x08,0x00,0x02,0x24,0x0c,0x00,0x83,0x30, +0x48,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x98,0x44,0x62,0x90, +0x05,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x0f,0x00,0x43,0x10,0x02,0x80,0x03,0x3c, +0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x97,0xff,0x22,0x12,0x20,0x10,0x03,0x3c, +0x00,0x12,0x11,0x00,0x21,0x10,0x43,0x00,0x78,0x1b,0xe3,0x26,0x9c,0x24,0x62,0xac, +0x18,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00,0x87,0xff,0x40,0x14,0x00,0x00,0x00,0x00, +0x1f,0x05,0x00,0x08,0x5c,0x24,0x71,0xa0,0xb3,0x44,0x62,0x90,0x00,0x00,0x00,0x00, +0x02,0x00,0x42,0x30,0xee,0xff,0x40,0x10,0x02,0x80,0x03,0x3c,0xb2,0x44,0x62,0x90, +0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x34,0xb2,0x44,0x62,0xa0,0x8c,0x05,0x00,0x08, +0x00,0x00,0x00,0x00,0x55,0x1f,0x00,0x0c,0x01,0x00,0x04,0x24,0x76,0x05,0x00,0x08, +0x02,0x80,0x03,0x3c,0x18,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x28,0x00,0x60,0x10, +0x2a,0xb0,0x02,0x3c,0x60,0x24,0x43,0x92,0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00, +0x43,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x78,0x1b,0xe5,0x26,0x08,0x0b,0xa2,0x8c, +0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f, +0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f, +0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,0x25,0x10,0x43,0x00, +0x41,0xb0,0x04,0x3c,0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03, +0x08,0x0b,0xa2,0xac,0xb1,0x44,0x43,0x90,0x00,0x00,0x00,0x00,0xb7,0xff,0x60,0x14, +0x02,0x80,0x03,0x3c,0x00,0x10,0x82,0x34,0x87,0x05,0x00,0x08,0x00,0x00,0xa2,0xa4, +0x5c,0x24,0x43,0x92,0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00,0x42,0x00,0x42,0x34, +0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x78,0x1b,0xe5,0x26,0x08,0x0b,0xa2,0x8c,0x44,0x00,0xbf,0x8f, +0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f, +0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f, +0x20,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c, +0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac, +0xb8,0xff,0xbd,0x27,0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf,0x3c,0x00,0xb7,0xaf, +0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf,0x2c,0x00,0xb3,0xaf, +0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c, +0x54,0x44,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34, +0xd0,0x17,0x63,0x24,0x01,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,0x18,0x00,0xa0,0xaf, +0x04,0x00,0x80,0x10,0xf7,0x00,0xa2,0x30,0x01,0x00,0x03,0x24,0xfe,0x00,0xa2,0x30, +0x18,0x00,0xa3,0xaf,0x54,0x44,0xc2,0xa0,0x54,0x44,0xc3,0x90,0x25,0xb0,0x02,0x3c, +0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x02,0x80,0x17,0x3c,0x78,0x1b,0xf4,0x26,0x21,0xa8,0x40,0x00, +0x02,0x80,0x16,0x3c,0x36,0x06,0x00,0x08,0x21,0xf0,0x80,0x02,0x68,0x24,0x71,0xa0, +0x78,0x1b,0xe2,0x26,0xa8,0x24,0x46,0x8c,0x14,0x25,0x45,0x8c,0x05,0x00,0x04,0x24, +0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x78,0x1b,0xf2,0x26, +0xac,0x24,0x45,0x8e,0x21,0x20,0x00,0x02,0x51,0x02,0x00,0x0c,0x21,0x30,0x60,0x02, +0x18,0x00,0xa5,0x8f,0x04,0x00,0x04,0x24,0x95,0x02,0x00,0x0c,0x21,0x30,0x20,0x02, +0x9c,0x43,0xc2,0x96,0x25,0xb0,0x05,0x3c,0x66,0x03,0xa4,0x34,0x01,0x00,0x42,0x24, +0x9c,0x43,0xc2,0xa6,0x9c,0x43,0xc3,0x96,0xff,0x00,0x02,0x24,0x00,0x00,0x83,0xa4, +0x71,0x00,0x22,0x12,0x00,0x00,0x00,0x00,0xa8,0x24,0x82,0x8e,0x14,0x25,0x93,0x8e, +0x05,0x00,0x04,0x24,0x00,0x00,0xa2,0xae,0xac,0x24,0x82,0xae,0x00,0x00,0xb3,0xae, +0x00,0x02,0x00,0x0c,0x00,0x00,0x00,0x00,0x14,0x25,0x84,0x8e,0x18,0x25,0x83,0x8e, +0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00, +0x14,0x25,0x83,0xae,0x14,0x25,0xc2,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xae, +0x02,0x80,0x11,0x3c,0xff,0xff,0x62,0x32,0x25,0x80,0x51,0x00,0x00,0x00,0xb0,0xae, +0x0c,0x00,0x03,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xae,0x02,0x00,0x02,0x92, +0x06,0x00,0x03,0x96,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,0x01,0x00,0x63,0x30, +0x12,0x00,0x60,0x10,0x25,0x30,0x51,0x00,0xec,0x0c,0xc3,0x97,0x00,0x00,0x00,0x00, +0x01,0x00,0x62,0x24,0xec,0x0c,0xc2,0xa7,0x0c,0x00,0x04,0x8e,0x00,0xf0,0x02,0x3c, +0xff,0x0f,0x63,0x30,0xff,0xff,0x42,0x34,0x00,0x2c,0x03,0x00,0x24,0x20,0x82,0x00, +0x25,0x20,0x85,0x00,0x0c,0x00,0x04,0xae,0x16,0x00,0xc2,0x94,0x00,0x19,0x03,0x00, +0x0f,0x00,0x42,0x30,0x25,0x10,0x43,0x00,0x16,0x00,0xc2,0xa4,0x02,0x80,0x03,0x3c, +0x98,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x02,0x80,0x03,0x3c,0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30, +0x31,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90, +0x00,0x00,0x00,0x00,0x0f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28,0x0c,0x00,0x40,0x10, +0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x21,0x10,0x53,0x00, +0xff,0xff,0x42,0x30,0x25,0x28,0x51,0x00,0x00,0x00,0xa4,0x94,0x08,0x00,0x02,0x24, +0x0c,0x00,0x83,0x30,0x48,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c, +0x98,0x44,0x62,0x90,0x05,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x0f,0x00,0x43,0x10, +0x02,0x80,0x03,0x3c,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x97,0xff,0x22,0x12, +0x20,0x10,0x03,0x3c,0x00,0x12,0x11,0x00,0x21,0x10,0x43,0x00,0x78,0x1b,0xe3,0x26, +0xa8,0x24,0x62,0xac,0x18,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00,0x87,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0x1c,0x06,0x00,0x08,0x64,0x24,0x71,0xa0,0xb3,0x44,0x62,0x90, +0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30,0xee,0xff,0x40,0x10,0x02,0x80,0x03,0x3c, +0xb2,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x34,0xb2,0x44,0x62,0xa0, +0x89,0x06,0x00,0x08,0x00,0x00,0x00,0x00,0x55,0x1f,0x00,0x0c,0x01,0x00,0x04,0x24, +0x73,0x06,0x00,0x08,0x02,0x80,0x03,0x3c,0x18,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00, +0x28,0x00,0x60,0x10,0x2a,0xb0,0x02,0x3c,0x68,0x24,0x43,0x92,0xb0,0x03,0xa5,0x34, +0x21,0x20,0x60,0x00,0x45,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x78,0x1b,0xe5,0x26, +0x08,0x0b,0xa2,0x8c,0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f, +0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f, +0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c, +0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0xac, +0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0xb1,0x44,0x43,0x90,0x00,0x00,0x00,0x00, +0xb7,0xff,0x60,0x14,0x02,0x80,0x03,0x3c,0x00,0x10,0x82,0x34,0x84,0x06,0x00,0x08, +0x00,0x00,0xa2,0xa4,0x64,0x24,0x43,0x92,0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00, +0x44,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x78,0x1b,0xe5,0x26,0x08,0x0b,0xa2,0x8c, +0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f, +0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f, +0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,0x25,0x10,0x43,0x00, +0x41,0xb0,0x04,0x3c,0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03, +0x08,0x0b,0xa2,0xac,0xb8,0xff,0xbd,0x27,0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf, +0x3c,0x00,0xb7,0xaf,0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf, +0x2c,0x00,0xb3,0xaf,0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf, +0x02,0x80,0x06,0x3c,0x54,0x44,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x18,0x03,0x42,0x34,0xc4,0x1b,0x63,0x24,0x02,0x00,0xa4,0x30,0x00,0x00,0x43,0xac, +0x18,0x00,0xa0,0xaf,0x04,0x00,0x80,0x10,0xfb,0x00,0xa2,0x30,0x01,0x00,0x03,0x24, +0xfd,0x00,0xa2,0x30,0x18,0x00,0xa3,0xaf,0x54,0x44,0xc2,0xa0,0x54,0x44,0xc3,0x90, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x17,0x3c,0x78,0x1b,0xf4,0x26, +0x21,0xa8,0x40,0x00,0x02,0x80,0x16,0x3c,0x33,0x07,0x00,0x08,0x21,0xf0,0x80,0x02, +0x70,0x24,0x71,0xa0,0x78,0x1b,0xe2,0x26,0xb4,0x24,0x46,0x8c,0x20,0x25,0x45,0x8c, +0x06,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x78,0x1b,0xf2,0x26,0xb8,0x24,0x45,0x8e,0x21,0x20,0x00,0x02,0x51,0x02,0x00,0x0c, +0x21,0x30,0x60,0x02,0x18,0x00,0xa5,0x8f,0x06,0x00,0x04,0x24,0x95,0x02,0x00,0x0c, +0x21,0x30,0x20,0x02,0x9c,0x43,0xc2,0x96,0x25,0xb0,0x05,0x3c,0x66,0x03,0xa4,0x34, +0x01,0x00,0x42,0x24,0x9c,0x43,0xc2,0xa6,0x9c,0x43,0xc3,0x96,0xff,0x00,0x02,0x24, +0x00,0x00,0x83,0xa4,0x71,0x00,0x22,0x12,0x00,0x00,0x00,0x00,0xb4,0x24,0x82,0x8e, +0x20,0x25,0x93,0x8e,0x06,0x00,0x04,0x24,0x00,0x00,0xa2,0xae,0xb8,0x24,0x82,0xae, +0x00,0x00,0xb3,0xae,0x00,0x02,0x00,0x0c,0x00,0x00,0x00,0x00,0x20,0x25,0x84,0x8e, +0x24,0x25,0x83,0x8e,0x40,0x00,0x84,0x24,0x7f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00, +0x0a,0x18,0x82,0x00,0x20,0x25,0x83,0xae,0x20,0x25,0xc2,0x8f,0x00,0x00,0x00,0x00, +0x00,0x00,0xa2,0xae,0x02,0x80,0x11,0x3c,0xff,0xff,0x62,0x32,0x25,0x80,0x51,0x00, +0x00,0x00,0xb0,0xae,0x0c,0x00,0x03,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xae, +0x02,0x00,0x02,0x92,0x06,0x00,0x03,0x96,0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30, +0x01,0x00,0x63,0x30,0x12,0x00,0x60,0x10,0x25,0x30,0x51,0x00,0xec,0x0c,0xc3,0x97, +0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x24,0xec,0x0c,0xc2,0xa7,0x0c,0x00,0x04,0x8e, +0x00,0xf0,0x02,0x3c,0xff,0x0f,0x63,0x30,0xff,0xff,0x42,0x34,0x00,0x2c,0x03,0x00, +0x24,0x20,0x82,0x00,0x25,0x20,0x85,0x00,0x0c,0x00,0x04,0xae,0x16,0x00,0xc2,0x94, +0x00,0x19,0x03,0x00,0x0f,0x00,0x42,0x30,0x25,0x10,0x43,0x00,0x16,0x00,0xc2,0xa4, +0x02,0x80,0x03,0x3c,0x98,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00, +0x02,0x00,0x42,0x30,0x31,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c, +0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x42,0x30,0x0c,0x00,0x42,0x28, +0x0c,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x92,0x00,0x00,0x00,0x00, +0x21,0x10,0x53,0x00,0xff,0xff,0x42,0x30,0x25,0x28,0x51,0x00,0x00,0x00,0xa4,0x94, +0x08,0x00,0x02,0x24,0x0c,0x00,0x83,0x30,0x48,0x00,0x62,0x10,0x02,0x80,0x02,0x3c, +0x02,0x80,0x03,0x3c,0x98,0x44,0x62,0x90,0x05,0x00,0x03,0x24,0xff,0x00,0x42,0x30, +0x0f,0x00,0x43,0x10,0x02,0x80,0x03,0x3c,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24, +0x97,0xff,0x22,0x12,0x20,0x10,0x03,0x3c,0x00,0x12,0x11,0x00,0x21,0x10,0x43,0x00, +0x78,0x1b,0xe3,0x26,0xb4,0x24,0x62,0xac,0x18,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00, +0x87,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x19,0x07,0x00,0x08,0x6c,0x24,0x71,0xa0, +0xb3,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x30,0xee,0xff,0x40,0x10, +0x02,0x80,0x03,0x3c,0xb2,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x34, +0xb2,0x44,0x62,0xa0,0x86,0x07,0x00,0x08,0x00,0x00,0x00,0x00,0x55,0x1f,0x00,0x0c, +0x01,0x00,0x04,0x24,0x70,0x07,0x00,0x08,0x02,0x80,0x03,0x3c,0x18,0x00,0xa3,0x8f, +0x00,0x00,0x00,0x00,0x28,0x00,0x60,0x10,0x2a,0xb0,0x02,0x3c,0x70,0x24,0x43,0x92, +0xb0,0x03,0xa5,0x34,0x21,0x20,0x60,0x00,0x47,0x00,0x42,0x34,0x00,0x00,0x43,0xa0, +0x00,0x00,0xa4,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x78,0x1b,0xe5,0x26,0x08,0x0b,0xa2,0x8c,0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f, +0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f, +0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f, +0x60,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x48,0x00,0xbd,0x27, +0x00,0x00,0x82,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0xb1,0x44,0x43,0x90, +0x00,0x00,0x00,0x00,0xb7,0xff,0x60,0x14,0x02,0x80,0x03,0x3c,0x00,0x10,0x82,0x34, +0x81,0x07,0x00,0x08,0x00,0x00,0xa2,0xa4,0x6c,0x24,0x43,0x92,0xb0,0x03,0xa5,0x34, +0x21,0x20,0x60,0x00,0x46,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x00,0x00,0xa4,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x78,0x1b,0xe5,0x26, +0x08,0x0b,0xa2,0x8c,0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,0x3c,0x00,0xb7,0x8f, +0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,0x2c,0x00,0xb3,0x8f, +0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,0x60,0x00,0x03,0x3c, +0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0xac, +0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0xb8,0x1f,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x05,0x3c,0x78,0x1b,0xa5,0x24, +0x10,0x0b,0xa2,0x8c,0x08,0x0b,0xa4,0x8c,0x00,0x08,0x03,0x3c,0x24,0x10,0x43,0x00, +0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03, +0x08,0x0b,0xa4,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc8,0xff,0xbd,0x27, +0x18,0x03,0x83,0x34,0x14,0x20,0x42,0x24,0x30,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf, +0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x02,0x80,0x14,0x3c,0x78,0x1b,0x93,0x26,0xfc,0x00,0x82,0x34, +0x00,0x00,0x45,0x8c,0xe4,0x0a,0x66,0x96,0x94,0x25,0x63,0x96,0x8c,0x25,0x67,0x8e, +0x23,0x28,0xa6,0x00,0x21,0x10,0xa3,0x00,0x23,0x88,0x47,0x00,0xb0,0x03,0x84,0x34, +0x23,0x30,0x23,0x02,0x2b,0x10,0x71,0x00,0x00,0x00,0x83,0xac,0x00,0x00,0x91,0xac, +0x0b,0x88,0xc2,0x00,0x21,0x20,0x20,0x02,0x39,0x15,0x00,0x0c,0x90,0x25,0x65,0xae, +0x4b,0x00,0x40,0x10,0x21,0x90,0x40,0x00,0x0c,0x00,0x51,0xac,0x8c,0x25,0x68,0x8e, +0x90,0x25,0x62,0x8e,0x08,0x00,0x45,0x8e,0x20,0xbd,0x03,0x3c,0x88,0x03,0x63,0x34, +0x2b,0x10,0x48,0x00,0x40,0x10,0x15,0x3c,0x21,0x20,0x00,0x00,0xff,0xff,0x27,0x32, +0x00,0x00,0x65,0xac,0x28,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xe4,0x0a,0x66,0x96, +0x08,0x00,0x42,0x96,0x40,0x10,0x05,0x3c,0x21,0x20,0x00,0x00,0x21,0x30,0x06,0x01, +0x25,0x28,0x45,0x00,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x02,0x3c, +0x68,0x41,0x42,0x24,0x78,0x1b,0x84,0x26,0x90,0x25,0x83,0x8c,0x04,0x00,0x45,0x8c, +0x8c,0x25,0x83,0xac,0x00,0x00,0x42,0xae,0x04,0x00,0x52,0xac,0x00,0x00,0xb2,0xac, +0x04,0x00,0x45,0xae,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x78,0x1b,0x85,0x26,0x10,0x0b,0xa2,0x8c,0x08,0x0b,0xa3,0x8c, +0x30,0x00,0xbf,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f, +0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x04,0x00,0x42,0x30, +0x25,0x18,0x62,0x00,0x41,0xb0,0x04,0x3c,0x38,0x00,0xbd,0x27,0x00,0x00,0x83,0xac, +0x08,0x00,0xe0,0x03,0x08,0x0b,0xa3,0xac,0x94,0x25,0x70,0x8e,0x08,0x00,0x45,0x96, +0xe4,0x0a,0x66,0x96,0x23,0x80,0x08,0x02,0xff,0xff,0x10,0x32,0x21,0x30,0x06,0x01, +0x25,0x28,0xb5,0x00,0x21,0x38,0x00,0x02,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x00,0x02,0x00,0x0c,0x21,0x20,0x00,0x00,0x08,0x00,0x45,0x96,0xe4,0x0a,0x62,0x96, +0x23,0x38,0x30,0x02,0x25,0x28,0xb5,0x00,0x21,0xb0,0x06,0x3c,0x21,0x28,0xb0,0x00, +0x21,0x30,0x46,0x00,0xff,0xff,0xe7,0x30,0x3d,0x08,0x00,0x08,0x21,0x20,0x00,0x00, +0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x02,0x80,0x04,0x3c,0x58,0x44,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x10,0x63,0x34, +0x58,0x44,0x83,0xac,0x00,0x60,0x82,0x40,0x49,0x08,0x00,0x08,0x00,0x00,0x00,0x00, +0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xc0,0xff,0xbd,0x27,0x00,0x22,0x63,0x24, +0x18,0x03,0x42,0x34,0x2a,0xb0,0x04,0x3c,0x00,0x00,0x43,0xac,0x3c,0x00,0xbf,0xaf, +0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf, +0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf, +0x18,0x00,0xb0,0xaf,0x2c,0x00,0x84,0x34,0x00,0x00,0x88,0x8c,0xff,0x00,0x02,0x24, +0xff,0x00,0x03,0x31,0x9e,0x00,0x62,0x10,0x00,0x80,0x02,0x31,0x33,0x00,0x40,0x10, +0x00,0xff,0x02,0x3c,0x00,0x80,0x02,0x3c,0x00,0x00,0x82,0xac,0xff,0x00,0x02,0x24, +0x10,0x00,0x62,0x10,0x02,0x80,0x02,0x3c,0x78,0x1b,0x50,0x24,0xff,0x00,0x03,0x31, +0x50,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0xe4,0x24,0x03,0xae,0x21,0x30,0x60,0x00,0x80,0x24,0x08,0xa2,0x0a,0x00,0x04,0x24, +0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x01,0x00,0x03,0x24, +0x58,0x25,0x03,0xa2,0x02,0x80,0x02,0x3c,0x78,0x1b,0x44,0x24,0x58,0x25,0x83,0x90, +0x01,0x00,0x02,0x24,0x25,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,0x78,0x1b,0x70,0x24, +0x59,0x25,0x02,0x92,0x00,0x00,0x00,0x00,0x08,0x00,0x40,0x10,0x00,0x04,0x03,0x3c, +0x10,0x0b,0x02,0x8e,0x08,0x0b,0x04,0x8e,0x24,0x10,0x43,0x00,0x25,0x20,0x82,0x00, +0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x0b,0x04,0xae,0x3c,0x00,0xbf,0x8f, +0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f, +0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f, +0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x24,0x10,0x02,0x01, +0xcf,0xff,0x40,0x10,0xff,0x00,0x02,0x24,0x02,0x80,0x03,0x3c,0x78,0x1b,0x62,0x24, +0x80,0x24,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x0c,0x00,0x68,0x8c,0x9b,0x08,0x00,0x08,0xff,0x00,0x03,0x31,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0x21,0x88,0x80,0x00, +0x7c,0x03,0x57,0x34,0x1e,0x03,0x5e,0x34,0x21,0x98,0x80,0x00,0xb0,0x03,0x56,0x34, +0x01,0x00,0x15,0x24,0x07,0x09,0x00,0x08,0x01,0x00,0x14,0x24,0xf2,0x23,0x22,0x96, +0x59,0x25,0x35,0xa2,0x01,0x00,0x42,0x34,0x00,0x00,0xc2,0xa7,0xf2,0x23,0x22,0xa6, +0x30,0x00,0x02,0x24,0x06,0x00,0x42,0x12,0x02,0x80,0x02,0x3c,0x78,0xaf,0x42,0x24, +0x00,0x00,0x48,0x8c,0x02,0x00,0x02,0x24,0x01,0x00,0x15,0xa1,0x01,0x00,0x02,0xa1, +0x59,0x25,0x62,0x92,0x00,0x00,0x00,0x00,0x45,0x00,0x54,0x14,0xff,0x00,0x02,0x24, +0x0c,0x00,0x03,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x69,0x30,0x40,0x00,0x22,0x11, +0x20,0x10,0x02,0x3c,0x80,0x24,0x63,0xa2,0x80,0x24,0x28,0x92,0x50,0x25,0x25,0x8e, +0xff,0x00,0x03,0x31,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0xc9,0xae, +0x21,0x30,0x60,0x00,0x00,0x00,0xe8,0xa6,0x0a,0x00,0x04,0x24,0xe4,0x24,0x23,0xae, +0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x50,0x25,0x30,0x8e, +0x00,0x02,0x00,0x0c,0x0a,0x00,0x04,0x24,0xff,0xff,0x10,0x32,0x02,0x80,0x02,0x3c, +0x25,0x80,0x02,0x02,0x02,0x00,0x03,0x92,0x20,0x00,0x02,0x24,0xd3,0xff,0x62,0x14, +0x21,0x20,0x03,0x02,0x02,0x80,0x02,0x3c,0x88,0xb5,0x44,0xac,0x20,0x00,0x03,0x26, +0x02,0x00,0x62,0x90,0x59,0x25,0x25,0x92,0x03,0x00,0x64,0x90,0xff,0x00,0x52,0x30, +0x7f,0x00,0x83,0x30,0x10,0x00,0xb4,0x14,0x28,0x00,0x04,0x26,0x02,0x80,0x05,0x3c, +0x91,0x43,0xa2,0x90,0x00,0x00,0x00,0x00,0x7f,0x00,0x42,0x30,0x08,0x00,0x62,0x10, +0x32,0x00,0x42,0x2e,0xf2,0x23,0x22,0x96,0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x34, +0x00,0x00,0xc2,0xa7,0x91,0x43,0xa3,0xa0,0xf2,0x23,0x22,0xa6,0x32,0x00,0x42,0x2e, +0xbf,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0xc0,0x18,0x12,0x00, +0x94,0x9f,0x42,0x24,0x21,0x18,0x62,0x00,0x04,0x00,0x62,0x8c,0x02,0x80,0x03,0x3c, +0x09,0xf8,0x40,0x00,0x84,0xb5,0x62,0xac,0xe9,0x08,0x00,0x08,0x30,0x00,0x02,0x24, +0x02,0x80,0x03,0x3c,0x78,0x1b,0x62,0x24,0xad,0x08,0x00,0x08,0x58,0x25,0x40,0xa0, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0xb3,0x08,0x00,0x08,0x02,0x80,0x03,0x3c,0xc8,0xff,0xbd,0x27,0xff,0xff,0xa8,0x30, +0x02,0x80,0x02,0x3c,0x25,0x40,0x02,0x01,0x30,0x00,0xb6,0xaf,0x20,0x00,0xb2,0xaf, +0x34,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf, +0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x03,0x8d,0xff,0xff,0xd2,0x30, +0x21,0xb0,0xa0,0x00,0x00,0xc0,0x02,0x24,0x08,0x00,0x45,0x26,0x04,0x00,0x06,0x8d, +0x24,0x18,0x62,0x00,0xff,0x3f,0xa5,0x30,0xf0,0xff,0x02,0x3c,0x25,0x18,0x65,0x00, +0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x80,0x05,0x3c,0x25,0x18,0x65,0x00, +0xff,0x01,0xc6,0x34,0x00,0x00,0x03,0xad,0x04,0x00,0x06,0xad,0x21,0x48,0x80,0x00, +0xff,0xff,0xe7,0x30,0x18,0x00,0x12,0xa5,0x1a,0x00,0x07,0xa1,0x18,0x00,0x03,0x8d, +0xff,0x7f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x02,0x80,0x15,0x3c, +0x18,0x00,0x03,0xad,0x78,0x1b,0xa5,0x26,0xee,0x23,0xa3,0x90,0x00,0x00,0x00,0x00, +0x01,0x00,0x62,0x24,0xee,0x23,0xa2,0xa0,0x18,0x00,0x04,0x8d,0xff,0x80,0x02,0x3c, +0x20,0x00,0x45,0x26,0xff,0xff,0x42,0x34,0x7f,0x00,0x63,0x30,0xff,0xff,0xb2,0x30, +0x24,0x20,0x82,0x00,0x00,0x1e,0x03,0x00,0x25,0xb0,0x02,0x3c,0xc0,0x00,0x42,0x34, +0x25,0x20,0x83,0x00,0x07,0x00,0x45,0x32,0x18,0x00,0x04,0xad,0x00,0x00,0x52,0xa4, +0x03,0x00,0xa0,0x10,0xff,0xff,0x42,0x32,0x08,0x00,0x42,0x26,0xff,0xff,0x42,0x30, +0x78,0x1b,0xb4,0x26,0xb4,0x25,0x86,0x8e,0xb8,0x25,0x90,0x8e,0xf8,0xff,0x52,0x30, +0x21,0x10,0xd2,0x00,0x2b,0x10,0x02,0x02,0x31,0x00,0x40,0x10,0xff,0x00,0x33,0x31, +0x23,0x80,0x06,0x02,0x21,0x28,0xc0,0x02,0xff,0xff,0x07,0x32,0x01,0x00,0x11,0x24, +0x21,0x20,0x60,0x02,0xc3,0x01,0x00,0x0c,0x10,0x00,0xb1,0xaf,0x23,0x18,0x50,0x02, +0xff,0xff,0x72,0x30,0x22,0x10,0x02,0x3c,0x21,0x10,0x42,0x02,0x21,0x20,0x60,0x02, +0x00,0x02,0x00,0x0c,0xb4,0x25,0x82,0xae,0x21,0x28,0xd0,0x02,0x21,0x38,0x40,0x02, +0x21,0x20,0x60,0x02,0x10,0x00,0xb1,0xaf,0x22,0x10,0x06,0x3c,0xc3,0x01,0x00,0x0c, +0x78,0x1b,0xb1,0x26,0xb4,0x25,0x23,0x8e,0x25,0xb0,0x10,0x3c,0xb0,0x03,0x02,0x36, +0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,0x00,0x02,0x00,0x0c,0x00,0x00,0x00,0x00, +0xb4,0x25,0x25,0x8e,0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac, +0x00,0x00,0x83,0x90,0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34, +0x00,0x00,0x83,0xa0,0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f, +0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f, +0x18,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27, +0x21,0x28,0xc0,0x02,0x21,0x20,0x60,0x02,0x21,0x38,0x40,0x02,0x01,0x00,0x02,0x24, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xa2,0xaf,0xb4,0x25,0x83,0x8e,0x78,0x1b,0xb1,0x26, +0x25,0xb0,0x10,0x3c,0x21,0x18,0x72,0x00,0xb4,0x25,0x83,0xae,0xb4,0x25,0x23,0x8e, +0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,0x00,0x02,0x00,0x0c, +0x00,0x00,0x00,0x00,0xb4,0x25,0x25,0x8e,0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36, +0x00,0x00,0x45,0xac,0x00,0x00,0x83,0x90,0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f, +0x10,0x00,0x63,0x34,0x00,0x00,0x83,0xa0,0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6, +0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f, +0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03, +0x38,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27,0x1c,0x00,0xb1,0xaf,0x34,0x00,0xbf,0xaf, +0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf, +0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0x21,0x88,0x80,0x00,0x00,0x60,0x14,0x40, +0x01,0x00,0x81,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x14,0x00,0x83,0x8c, +0x02,0x80,0x15,0x3c,0x15,0x00,0x02,0x24,0x78,0x1b,0xb3,0x26,0x21,0x28,0x00,0x00, +0x1d,0x00,0x62,0x10,0x08,0x00,0x06,0x24,0x08,0x00,0x82,0x94,0x02,0x80,0x04,0x3c, +0x3e,0x46,0x00,0x0c,0x25,0x20,0x44,0x00,0x08,0x00,0x25,0x8e,0x0c,0x00,0x26,0x96, +0x14,0x00,0x27,0x96,0x3e,0x09,0x00,0x0c,0x09,0x00,0x04,0x24,0x04,0x00,0x22,0x8e, +0x00,0x00,0x23,0x8e,0x21,0x20,0x20,0x02,0x00,0x00,0x43,0xac,0x04,0x00,0x62,0xac, +0x00,0x00,0x31,0xae,0x56,0x15,0x00,0x0c,0x04,0x00,0x31,0xae,0x00,0x60,0x94,0x40, +0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x0c,0x00,0x90,0x8c,0x25,0xb0,0x02,0x3c, +0xc0,0x00,0x42,0x34,0xb4,0x25,0x68,0x8e,0x07,0x00,0x07,0x32,0x00,0x00,0x50,0xa4, +0x08,0x00,0x05,0x26,0x0b,0x80,0xa7,0x00,0xb8,0x25,0x63,0x8e,0xf8,0xff,0x10,0x32, +0x21,0x10,0x10,0x01,0x23,0x90,0x68,0x00,0x2b,0x18,0x62,0x00,0x01,0x00,0x16,0x24, +0x09,0x00,0x04,0x24,0x21,0x30,0x00,0x01,0x33,0x00,0x60,0x10,0xff,0xff,0x07,0x32, +0x08,0x00,0x25,0x8e,0xff,0xff,0x47,0x32,0x23,0x80,0x12,0x02,0xc3,0x01,0x00,0x0c, +0x10,0x00,0xb6,0xaf,0x22,0x10,0x03,0x3c,0x21,0x18,0x03,0x02,0x09,0x00,0x04,0x24, +0x00,0x02,0x00,0x0c,0xb4,0x25,0x63,0xae,0x08,0x00,0x25,0x8e,0xff,0xff,0x07,0x32, +0x09,0x00,0x04,0x24,0x21,0x28,0xb2,0x00,0x22,0x10,0x06,0x3c,0xc3,0x01,0x00,0x0c, +0x10,0x00,0xb6,0xaf,0x00,0x02,0x00,0x0c,0x09,0x00,0x04,0x24,0x78,0x1b,0xa2,0x26, +0xb4,0x25,0x46,0x8c,0x25,0xb0,0x03,0x3c,0xec,0x00,0x64,0x34,0x00,0x00,0x86,0xac, +0xbd,0x00,0x65,0x34,0x00,0x00,0xa2,0x90,0xc2,0x00,0x63,0x34,0x21,0x20,0x20,0x02, +0x10,0x00,0x42,0x34,0x00,0x00,0xa2,0xa0,0x00,0x00,0x66,0xa4,0x04,0x00,0x22,0x8e, +0x00,0x00,0x23,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x43,0xac,0x04,0x00,0x62,0xac, +0x00,0x00,0x31,0xae,0x56,0x15,0x00,0x0c,0x04,0x00,0x31,0xae,0x00,0x60,0x94,0x40, +0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x08,0x00,0x25,0x8e,0x01,0x00,0x02,0x24, +0x21,0x30,0x00,0x01,0x09,0x00,0x04,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa2,0xaf, +0xb4,0x25,0x63,0x8e,0x00,0x00,0x00,0x00,0x21,0x18,0x70,0x00,0x2d,0x0a,0x00,0x08, +0xb4,0x25,0x63,0xae,0xe8,0xff,0xbd,0x27,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf, +0x21,0x28,0x80,0x00,0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0xbf,0x00,0x42,0x34,0x00,0x00,0x43,0x90, +0x00,0x00,0x00,0x00,0x04,0x00,0x63,0x2c,0x05,0x00,0x60,0x10,0x02,0x80,0x06,0x3c, +0x70,0x41,0xc3,0x8c,0x70,0x41,0xc2,0x24,0x0c,0x00,0x62,0x10,0x00,0x00,0x00,0x00, +0x70,0x41,0xc2,0x24,0x04,0x00,0x43,0x8c,0x00,0x00,0xa2,0xac,0x04,0x00,0x45,0xac, +0x00,0x00,0x65,0xac,0x04,0x00,0xa3,0xac,0x00,0x60,0x90,0x40,0x14,0x00,0xbf,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xd9,0x09,0x00,0x0c, +0x00,0x00,0x00,0x00,0x00,0x60,0x90,0x40,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0xd0,0xff,0xbd,0x27,0x18,0x03,0x42,0x34,0xf8,0x29,0x63,0x24,0x28,0x00,0xbf,0xaf, +0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x00,0x00,0x43,0xac,0x02,0x80,0x04,0x3c,0x98,0x44,0x82,0x90,0x00,0x00,0x00,0x00, +0x09,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x02,0x80,0x02,0x3c,0xb1,0x44,0x43,0x90, +0x00,0x00,0x00,0x00,0x61,0x00,0x60,0x10,0x02,0x80,0x02,0x3c,0x9c,0x1e,0x00,0x0c, +0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x78,0x41,0x43,0x8c,0x78,0x41,0x42,0x24, +0x66,0x00,0x62,0x10,0x02,0x80,0x13,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,0x36,0x00,0x42,0x34,0x00,0x00,0x43,0x90, +0x78,0x1b,0x66,0x26,0xbc,0x25,0xc5,0x8c,0xc0,0x18,0x03,0x00,0x23,0xb0,0x04,0x3c, +0xf0,0x07,0x63,0x30,0xff,0x1f,0x02,0x3c,0x21,0x18,0x64,0x00,0xff,0xff,0x42,0x34, +0x24,0x20,0x62,0x00,0x23,0x88,0x85,0x00,0x00,0x04,0x22,0x26,0x2b,0x28,0x85,0x00, +0x6c,0x25,0xc3,0x8c,0x0b,0x88,0x45,0x00,0xe1,0x01,0x22,0x2e,0x68,0x25,0xc3,0xac, +0xc0,0x25,0xc4,0xac,0x72,0x25,0xc0,0xa4,0x14,0x00,0x40,0x14,0x71,0x25,0xc0,0xa0, +0x20,0xfe,0x82,0x24,0x20,0x02,0x83,0x24,0x0a,0x18,0x45,0x00,0x23,0x10,0x02,0x3c, +0xff,0x03,0x42,0x34,0x2b,0x10,0x43,0x00,0x21,0x28,0x60,0x00,0x34,0x00,0x40,0x14, +0xbc,0x25,0xc3,0xac,0xc0,0x25,0xc2,0x8c,0x00,0x00,0x00,0x00,0x2b,0x18,0x45,0x00, +0x23,0x88,0x45,0x00,0x03,0x00,0x60,0x10,0xe1,0x01,0x22,0x2e,0x00,0x04,0x31,0x26, +0xe1,0x01,0x22,0x2e,0x0e,0x00,0x40,0x10,0x78,0x1b,0x70,0x26,0x78,0x1b,0x70,0x26, +0xc0,0x25,0x03,0x8e,0xbc,0x25,0x04,0x8e,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00, +0x41,0x00,0x40,0x14,0x2b,0x10,0x64,0x00,0x6d,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c, +0x80,0x00,0x03,0x24,0xd0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x78,0x1b,0x70,0x26, +0xbc,0x25,0x03,0x96,0x2a,0xb0,0x02,0x3c,0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00, +0x00,0x00,0x51,0xa0,0x45,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,0x72,0x25,0x03,0x96, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x08,0x0b,0x02,0x8e, +0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac, +0x28,0x00,0xbf,0x8f,0x08,0x0b,0x02,0xae,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f, +0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27, +0x00,0xfc,0xa5,0x24,0xbd,0x0a,0x00,0x08,0xbc,0x25,0xc5,0xac,0x01,0x00,0x04,0x24, +0xba,0x44,0x44,0xa0,0x02,0x80,0x03,0x3c,0x99,0x44,0x64,0x90,0x02,0x80,0x13,0x3c, +0xf9,0x1f,0x00,0x0c,0xff,0x00,0x84,0x30,0x02,0x80,0x02,0x3c,0x78,0x41,0x43,0x8c, +0x78,0x41,0x42,0x24,0x9c,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x90,0x1e,0x00,0x0c, +0x00,0x00,0x00,0x00,0x98,0xff,0x40,0x10,0x78,0x1b,0x63,0x26,0x82,0x0b,0x62,0x90, +0x00,0x00,0x00,0x00,0x94,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x98,0x26,0x64,0x94, +0x82,0x0b,0x60,0xa0,0x00,0xc0,0x84,0x24,0x2c,0x22,0x00,0x0c,0xff,0xff,0x84,0x30, +0x9a,0x0a,0x00,0x08,0x00,0x00,0x00,0x00,0x68,0x25,0x05,0x8e,0x21,0x30,0x80,0x00, +0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x68,0x25,0x03,0x8e,0x72,0x25,0x05,0x96,0xbc,0x25,0x02,0x8e,0x21,0x18,0x71,0x00, +0x21,0x28,0x25,0x02,0x21,0x10,0x51,0x00,0x09,0x00,0x04,0x24,0xbc,0x25,0x02,0xae, +0x68,0x25,0x03,0xae,0x00,0x02,0x00,0x0c,0x72,0x25,0x05,0xa6,0x78,0x1b,0x70,0x26, +0xbc,0x25,0x03,0x96,0x2a,0xb0,0x02,0x3c,0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00, +0x00,0x00,0x51,0xa0,0x45,0x18,0x00,0x0c,0x00,0x00,0x00,0x00,0x72,0x25,0x03,0x96, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x08,0x0b,0x02,0x8e, +0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac, +0x28,0x00,0xbf,0x8f,0x08,0x0b,0x02,0xae,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f, +0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27, +0xc4,0x25,0x02,0x8e,0x68,0x25,0x05,0x8e,0x21,0x30,0x80,0x00,0x23,0x88,0x44,0x00, +0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x68,0x25,0x03,0x8e,0x72,0x25,0x02,0x96,0xc0,0x25,0x12,0x96,0x21,0x18,0x71,0x00, +0x21,0x10,0x22,0x02,0x23,0x10,0x11,0x3c,0x68,0x25,0x03,0xae,0x72,0x25,0x02,0xa6, +0x06,0x00,0x40,0x16,0xbc,0x25,0x11,0xae,0x09,0x00,0x04,0x24,0x00,0x02,0x00,0x0c, +0x78,0x1b,0x70,0x26,0x20,0x0b,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x0c, +0x09,0x00,0x04,0x24,0x68,0x25,0x05,0x8e,0x09,0x00,0x04,0x24,0x23,0x10,0x06,0x3c, +0x21,0x38,0x40,0x02,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x68,0x25,0x03,0x8e, +0x72,0x25,0x02,0x96,0x21,0x20,0x51,0x02,0x21,0x18,0x72,0x00,0x21,0x10,0x42,0x02, +0xbc,0x25,0x04,0xae,0x09,0x00,0x04,0x24,0x68,0x25,0x03,0xae,0x4f,0x0b,0x00,0x08, +0x72,0x25,0x02,0xa6,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x08,0x00,0x02,0x24,0xfc,0x00,0x84,0x30, +0x50,0x00,0x02,0x24,0x11,0x00,0x82,0x10,0x05,0x00,0x03,0x24,0x51,0x00,0x82,0x28, +0x10,0x00,0x40,0x10,0xa0,0x00,0x02,0x24,0x20,0x00,0x02,0x24,0x0b,0x00,0x82,0x10, +0x02,0x00,0x03,0x24,0x21,0x00,0x82,0x28,0x15,0x00,0x40,0x14,0x30,0x00,0x02,0x24, +0x06,0x00,0x82,0x10,0x03,0x00,0x03,0x24,0x04,0x00,0x03,0x24,0x40,0x00,0x02,0x24, +0x02,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0xfd,0xff,0x82,0x10,0x08,0x00,0x03,0x24,0xa1,0x00,0x82,0x28, +0x0c,0x00,0x40,0x10,0xc0,0x00,0x02,0x24,0x80,0x00,0x02,0x24,0xf7,0xff,0x82,0x10, +0x06,0x00,0x03,0x24,0x07,0x00,0x03,0x24,0x84,0x0b,0x00,0x08,0x90,0x00,0x02,0x24, +0xf2,0xff,0x80,0x10,0x21,0x18,0x00,0x00,0x01,0x00,0x03,0x24,0x84,0x0b,0x00,0x08, +0x10,0x00,0x02,0x24,0xed,0xff,0x82,0x10,0x0a,0x00,0x03,0x24,0xc1,0x00,0x82,0x28, +0x04,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x09,0x00,0x03,0x24,0x84,0x0b,0x00,0x08, +0xb0,0x00,0x02,0x24,0x0b,0x00,0x03,0x24,0x84,0x0b,0x00,0x08,0xd0,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x3c,0x25,0xb0,0x04,0x3c, +0x98,0x2e,0x63,0x24,0x18,0x03,0x84,0x34,0x00,0x00,0x83,0xac,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x00,0x80,0x03,0x3c, +0x25,0xb0,0x04,0x3c,0xdc,0x2e,0x63,0x24,0x18,0x03,0x84,0x34,0x00,0x00,0x83,0xac, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x3c,0x25,0xb0,0x04,0x3c, +0xf8,0x2e,0x63,0x24,0x18,0x03,0x84,0x34,0x00,0x00,0x83,0xac,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x00,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x7c,0x2f,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x25,0xb0,0x03,0x3c,0x00,0x80,0x02,0x3c, +0xb0,0x03,0x65,0x34,0x98,0x2f,0x42,0x24,0x18,0x03,0x63,0x34,0x00,0x00,0x62,0xac, +0x00,0x00,0xa4,0xac,0x00,0x00,0x83,0x8c,0x21,0x10,0x00,0x00,0xff,0x3f,0x63,0x30, +0x00,0x00,0xa3,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x98,0xff,0xbd,0x27,0x60,0x00,0xbe,0xaf,0x5c,0x00,0xb7,0xaf, +0x48,0x00,0xb2,0xaf,0x44,0x00,0xb1,0xaf,0x64,0x00,0xbf,0xaf,0x58,0x00,0xb6,0xaf, +0x54,0x00,0xb5,0xaf,0x50,0x00,0xb4,0xaf,0x4c,0x00,0xb3,0xaf,0x40,0x00,0xb0,0xaf, +0x21,0x88,0x80,0x00,0x02,0x00,0x84,0x90,0x21,0xf0,0x00,0x00,0x21,0xb8,0x00,0x00, +0x0f,0x00,0x84,0x30,0xc0,0x20,0x04,0x00,0x21,0x20,0x91,0x00,0x18,0x00,0x92,0x24, +0x00,0x60,0x13,0x40,0x01,0x00,0x61,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x02,0x80,0x05,0x3c,0x28,0x00,0x84,0x24,0x18,0x42,0xa5,0x24,0x7b,0x46,0x00,0x0c, +0x06,0x00,0x06,0x24,0xa6,0x00,0x40,0x14,0x02,0x80,0x14,0x3c,0x98,0x44,0x82,0x92, +0x00,0x00,0x00,0x00,0xb0,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24, +0xe8,0x0a,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0xaa,0x00,0x40,0x10, +0x02,0x80,0x09,0x3c,0xb9,0x44,0x22,0x91,0x00,0x00,0x00,0x00,0x06,0x00,0x40,0x10, +0x02,0x80,0x02,0x3c,0xb9,0x44,0x22,0x91,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x24, +0xb9,0x44,0x22,0xa1,0x02,0x80,0x02,0x3c,0x9e,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c, +0xb2,0x44,0x62,0x90,0xfd,0xff,0x03,0x24,0x42,0xb0,0x04,0x3c,0x24,0x10,0x43,0x00, +0x02,0x80,0x03,0x3c,0xb2,0x44,0x62,0xa0,0x00,0x00,0x83,0x90,0xef,0xff,0x02,0x24, +0x03,0x00,0x85,0x34,0x24,0x18,0x62,0x00,0x40,0x00,0x02,0x24,0x00,0x00,0x83,0xa0, +0x02,0x80,0x16,0x3c,0x00,0x00,0xa2,0xa0,0xa0,0x44,0xc2,0x96,0x20,0x00,0x43,0x96, +0xff,0xff,0x42,0x30,0x0a,0x00,0x43,0x10,0x02,0x80,0x15,0x3c,0x25,0xb0,0x02,0x3c, +0x94,0x00,0x42,0x34,0xa0,0x44,0xc3,0xa6,0x00,0x00,0x43,0xa4,0xa0,0x44,0xc3,0x96, +0x00,0x00,0x00,0x00,0xff,0xff,0x63,0x30,0x80,0x1a,0x03,0x00,0xa4,0x44,0xa3,0xae, +0x25,0xb0,0x10,0x3c,0x84,0x00,0x02,0x36,0x00,0x00,0x44,0x8c,0x80,0x00,0x10,0x36, +0x00,0x00,0x02,0x8e,0xa4,0x44,0xa6,0x8e,0x21,0x18,0x00,0x00,0x00,0x28,0x04,0x00, +0x21,0x20,0x00,0x00,0x25,0x28,0xa3,0x00,0x25,0x20,0x82,0x00,0x24,0x22,0x00,0x0c, +0x38,0x00,0xa9,0xaf,0x02,0x80,0x05,0x3c,0x00,0x00,0x04,0x8e,0xa4,0x44,0xa6,0x8e, +0xa8,0x44,0xa3,0x94,0x23,0x20,0x82,0x00,0x21,0x20,0x86,0x00,0xff,0xff,0x63,0x30, +0x80,0x1a,0x03,0x00,0x23,0x20,0x83,0x00,0x02,0x80,0x08,0x3c,0xac,0x44,0x04,0xad, +0x00,0x00,0x02,0x8e,0x21,0x18,0x00,0x00,0x21,0x38,0x00,0x00,0x00,0x50,0x42,0x24, +0x00,0x50,0x45,0x2c,0x21,0x18,0x65,0x00,0x2b,0x20,0xe3,0x00,0xac,0x44,0x06,0x8d, +0x38,0x00,0xa9,0x8f,0x8f,0x00,0x80,0x14,0x00,0x00,0x00,0x00,0x8b,0x00,0x67,0x10, +0x2b,0x10,0xc2,0x00,0xac,0x44,0x04,0x8d,0x25,0xb0,0x02,0x3c,0xe4,0x02,0x42,0x34, +0x00,0x00,0x44,0xac,0xa0,0x44,0xc3,0x96,0x02,0x80,0x02,0x3c,0x05,0x00,0x05,0x24, +0xff,0xff,0x63,0x30,0x40,0x18,0x03,0x00,0xf6,0xff,0x63,0x24,0x88,0x44,0x43,0xac, +0x00,0x00,0x27,0x8e,0x24,0x00,0x44,0x26,0x30,0x00,0xa6,0x27,0xff,0x3f,0xe7,0x30, +0x8a,0x11,0x00,0x0c,0xdc,0xff,0xe7,0x24,0x2c,0x00,0x40,0x10,0x21,0x28,0x40,0x00, +0x98,0x44,0x82,0x92,0x02,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x7f,0x00,0x43,0x10, +0x02,0x80,0x04,0x3c,0x02,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,0x08,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x04,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x30, +0x04,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x01,0x00,0x17,0x24,0xb6,0x44,0x57,0xa0, +0x04,0x00,0xa3,0x90,0x30,0x00,0xa7,0x8f,0x00,0x00,0x00,0x00,0x04,0x00,0xe2,0x28, +0x16,0x00,0x40,0x14,0xfe,0x00,0x66,0x30,0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24, +0x98,0x26,0x64,0x94,0xc0,0x10,0x06,0x00,0x2a,0x10,0x82,0x00,0x10,0x00,0x40,0x14, +0x02,0x80,0x03,0x3c,0x21,0x10,0xc7,0x00,0xfd,0xff,0x42,0x24,0xc0,0x10,0x02,0x00, +0x2a,0x10,0x44,0x00,0x0a,0x00,0x40,0x14,0xc2,0x10,0x04,0x00,0x23,0x30,0x46,0x00, +0x21,0x18,0xa6,0x00,0x05,0x00,0x62,0x90,0x07,0x00,0x84,0x30,0x01,0x00,0x03,0x24, +0x07,0x10,0x82,0x00,0x01,0x00,0x42,0x30,0x0b,0xf0,0x62,0x00,0x02,0x80,0x03,0x3c, +0xb2,0x44,0x62,0x90,0xef,0xff,0x03,0x24,0x21,0x20,0xe0,0x02,0x24,0x10,0x43,0x00, +0x02,0x80,0x03,0x3c,0xb2,0x44,0x62,0xa0,0x98,0x44,0x83,0x92,0x02,0x80,0x02,0x3c, +0x10,0xaf,0x42,0x24,0xff,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00, +0x00,0x00,0x66,0x8c,0x00,0x00,0x00,0x00,0x09,0xf8,0xc0,0x00,0x21,0x28,0xc0,0x03, +0x00,0x60,0x93,0x40,0x64,0x00,0xbf,0x8f,0x60,0x00,0xbe,0x8f,0x5c,0x00,0xb7,0x8f, +0x58,0x00,0xb6,0x8f,0x54,0x00,0xb5,0x8f,0x50,0x00,0xb4,0x8f,0x4c,0x00,0xb3,0x8f, +0x48,0x00,0xb2,0x8f,0x44,0x00,0xb1,0x8f,0x40,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x68,0x00,0xbd,0x27,0x98,0x44,0x82,0x92,0x00,0x00,0x00,0x00, +0xef,0xff,0x40,0x14,0x02,0x80,0x03,0x3c,0x78,0x1b,0x70,0x24,0xe8,0x0a,0x02,0x92, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0xe9,0xff,0x40,0x10,0x24,0x00,0x44,0x26, +0x00,0x00,0x27,0x8e,0x05,0x00,0x05,0x24,0xff,0x3f,0xe7,0x30,0xdc,0xff,0xe7,0x24, +0x8a,0x11,0x00,0x0c,0x30,0x00,0xa6,0x27,0xe1,0xff,0x40,0x10,0x21,0x28,0x40,0x00, +0x30,0x00,0xa7,0x8f,0x04,0x00,0x42,0x90,0x04,0x00,0xe3,0x28,0xdc,0xff,0x60,0x14, +0xfe,0x00,0x46,0x30,0x98,0x26,0x04,0x96,0xc0,0x10,0x06,0x00,0x2a,0x10,0x82,0x00, +0xd7,0xff,0x40,0x14,0x21,0x10,0xc7,0x00,0xfd,0xff,0x42,0x24,0xc0,0x10,0x02,0x00, +0x2a,0x10,0x44,0x00,0xd2,0xff,0x40,0x14,0xc2,0x10,0x04,0x00,0x23,0x30,0x46,0x00, +0x21,0x18,0xa6,0x00,0x05,0x00,0x62,0x90,0x07,0x00,0x84,0x30,0x07,0x10,0x82,0x00, +0x01,0x00,0x42,0x30,0xca,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x0e,0x46,0x00,0x0c, +0x21,0x20,0x00,0x00,0xc4,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x75,0xff,0x40,0x10, +0x00,0x00,0x00,0x00,0xb9,0x44,0x22,0x91,0x00,0x00,0x00,0x00,0x71,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0xb9,0x44,0x22,0x91,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24, +0xb9,0x44,0x22,0xa1,0x75,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x03,0x00,0xa2,0x90, +0x02,0x80,0x07,0x3c,0xb4,0x44,0xe2,0xa0,0x02,0x00,0xa3,0x90,0x21,0x30,0x80,0x00, +0xb5,0x44,0x83,0xa0,0xb5,0x44,0x82,0x90,0x00,0x00,0x00,0x00,0x06,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0xb4,0x44,0xe2,0x90,0x00,0x00,0x00,0x00,0xb5,0x44,0xc2,0xa0, +0x8d,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0xb5,0x44,0x82,0x90,0x00,0x00,0x00,0x00, +0xb5,0x44,0xc2,0xa0,0x8d,0x0c,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x09,0x3c, +0x78,0x1b,0x28,0x25,0xf4,0x23,0x06,0x8d,0xff,0xff,0x02,0x34,0x44,0x00,0xc2,0x10, +0x21,0x38,0x80,0x00,0x2b,0x10,0xc7,0x00,0x34,0x00,0x40,0x10,0x02,0x19,0x06,0x00, +0x21,0x10,0xc7,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0xf4,0x23,0x06,0xad, +0xf8,0x23,0x02,0xad,0x78,0x1b,0x26,0x25,0x06,0x00,0xc4,0x94,0xff,0xff,0x02,0x34, +0xff,0xff,0x83,0x30,0x33,0x00,0x62,0x10,0x00,0x11,0x07,0x00,0xff,0xff,0x84,0x30, +0x2b,0x10,0x87,0x00,0x20,0x00,0x40,0x10,0x03,0x19,0x04,0x00,0x03,0x11,0x04,0x00, +0x21,0x18,0x87,0x00,0x23,0x18,0x62,0x00,0x10,0x00,0x64,0x24,0x06,0x00,0xc4,0xa4, +0xf8,0x23,0xc3,0xac,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x45,0x00,0x78,0x1b,0x23,0x25,0x80,0x10,0x02,0x00,0x21,0x28,0x43,0x00, +0x80,0x11,0xa6,0x8c,0x00,0x21,0x07,0x00,0xff,0xff,0xc2,0x38,0x0a,0x30,0x82,0x00, +0x2b,0x18,0xc7,0x00,0x07,0x00,0x60,0x10,0x21,0x10,0xc7,0x00,0x02,0x19,0x06,0x00, +0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0x80,0x11,0xa6,0xac,0x08,0x00,0xe0,0x03, +0x84,0x11,0xa2,0xac,0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00,0x80,0x11,0xa2,0xac, +0x08,0x00,0xe0,0x03,0x84,0x11,0xa2,0xac,0x21,0x10,0x87,0x00,0x23,0x10,0x43,0x00, +0x06,0x00,0xc2,0xa4,0x3d,0x0d,0x00,0x08,0xf8,0x23,0xc2,0xac,0x21,0x10,0xc7,0x00, +0x23,0x10,0x43,0x00,0xf4,0x23,0x02,0xad,0xf8,0x23,0x02,0xad,0x78,0x1b,0x26,0x25, +0x06,0x00,0xc4,0x94,0xff,0xff,0x02,0x34,0xff,0xff,0x83,0x30,0xcf,0xff,0x62,0x14, +0x00,0x11,0x07,0x00,0x21,0x20,0x40,0x00,0x33,0x0d,0x00,0x08,0x06,0x00,0xc2,0xa4, +0x00,0x31,0x04,0x00,0x25,0x0d,0x00,0x08,0xf4,0x23,0x06,0xad,0x63,0x00,0x82,0x24, +0x77,0x00,0x42,0x2c,0x00,0x00,0x85,0x28,0x04,0x00,0x40,0x10,0x21,0x18,0x00,0x00, +0x64,0x00,0x82,0x24,0x64,0x00,0x03,0x24,0x0b,0x18,0x45,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,0x0c,0x00,0x82,0x8c, +0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,0x07,0x00,0x40,0x14, +0x25,0xb0,0x02,0x3c,0x04,0x00,0xa4,0x90,0x10,0x00,0xbf,0x8f,0x18,0x00,0xbd,0x27, +0x42,0x20,0x04,0x00,0x6b,0x0d,0x00,0x08,0x96,0xff,0x84,0x24,0x24,0x08,0x42,0x34, +0x00,0x00,0x43,0x8c,0x00,0x00,0x00,0x00,0x00,0x02,0x63,0x30,0x1b,0x00,0x60,0x14, +0x01,0x00,0x02,0x24,0x05,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x82,0x21,0x03,0x00, +0x3c,0x00,0x82,0x10,0x02,0x00,0x82,0x28,0x57,0x00,0x40,0x14,0x02,0x00,0x02,0x24, +0x46,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0x2e,0x00,0x82,0x10,0x3e,0x00,0x63,0x30, +0x6b,0x0d,0x00,0x0c,0x21,0x20,0xc0,0x00,0x06,0x00,0x45,0x24,0x65,0x00,0xa4,0x2c, +0x64,0x00,0x03,0x24,0x0a,0x28,0x64,0x00,0xdd,0xff,0xa2,0x24,0x08,0x00,0x42,0x2c, +0x1f,0x00,0x40,0x10,0xe5,0xff,0xa2,0x24,0xfe,0xff,0xa5,0x24,0x10,0x00,0xbf,0x8f, +0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x05,0x00,0xa3,0x90, +0x00,0x00,0x00,0x00,0x60,0x00,0x64,0x30,0x42,0x21,0x04,0x00,0x25,0x00,0x82,0x10, +0x02,0x00,0x82,0x28,0x36,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x2f,0x00,0x82,0x10, +0x03,0x00,0x02,0x24,0xe6,0xff,0x82,0x14,0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00, +0xd8,0xff,0x03,0x24,0x23,0x30,0x62,0x00,0x6b,0x0d,0x00,0x0c,0x21,0x20,0xc0,0x00, +0x06,0x00,0x45,0x24,0x65,0x00,0xa4,0x2c,0x64,0x00,0x03,0x24,0x0a,0x28,0x64,0x00, +0xdd,0xff,0xa2,0x24,0x08,0x00,0x42,0x2c,0xe3,0xff,0x40,0x14,0xe5,0xff,0xa2,0x24, +0x08,0x00,0x42,0x2c,0x06,0x00,0x40,0x10,0xf1,0xff,0xa2,0x24,0x9f,0x0d,0x00,0x08, +0xfa,0xff,0xa5,0x24,0xd8,0xff,0x02,0x24,0x94,0x0d,0x00,0x08,0x23,0x30,0x43,0x00, +0x0c,0x00,0x42,0x2c,0x0c,0x00,0x40,0x10,0xfb,0xff,0xa2,0x24,0x9f,0x0d,0x00,0x08, +0xf8,0xff,0xa5,0x24,0x3e,0x00,0x63,0x30,0xfe,0xff,0x02,0x24,0x94,0x0d,0x00,0x08, +0x23,0x30,0x43,0x00,0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00,0xfe,0xff,0x03,0x24, +0xb2,0x0d,0x00,0x08,0x23,0x30,0x62,0x00,0x0a,0x00,0x42,0x2c,0xcb,0xff,0x40,0x10, +0x00,0x00,0x00,0x00,0x9f,0x0d,0x00,0x08,0xfc,0xff,0xa5,0x24,0x3e,0x00,0x63,0x30, +0xec,0xff,0x02,0x24,0x94,0x0d,0x00,0x08,0x23,0x30,0x43,0x00,0x1f,0x00,0x62,0x30, +0x40,0x10,0x02,0x00,0xec,0xff,0x03,0x24,0xb2,0x0d,0x00,0x08,0x23,0x30,0x62,0x00, +0xb3,0xff,0x80,0x14,0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00,0x0e,0x00,0x03,0x24, +0xb2,0x0d,0x00,0x08,0x23,0x30,0x62,0x00,0xad,0xff,0x80,0x14,0x3e,0x00,0x63,0x30, +0x0e,0x00,0x02,0x24,0x94,0x0d,0x00,0x08,0x23,0x30,0x43,0x00,0xa0,0xff,0xbd,0x27, +0x5c,0x00,0xbf,0xaf,0x58,0x00,0xbe,0xaf,0x54,0x00,0xb7,0xaf,0x50,0x00,0xb6,0xaf, +0x4c,0x00,0xb5,0xaf,0x48,0x00,0xb4,0xaf,0x44,0x00,0xb3,0xaf,0x40,0x00,0xb2,0xaf, +0x3c,0x00,0xb1,0xaf,0x38,0x00,0xb0,0xaf,0x02,0x80,0x02,0x3c,0x68,0x41,0x45,0x8c, +0x00,0x80,0x04,0x3c,0xac,0x37,0x83,0x24,0x68,0x41,0x44,0x24,0x25,0xb0,0x02,0x3c, +0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0xbb,0x00,0xa4,0x10,0x02,0x80,0x02,0x3c, +0x02,0x80,0x03,0x3c,0x7c,0xaf,0x42,0x24,0x80,0xaf,0x63,0x24,0x00,0x00,0x5e,0x8c, +0x00,0x00,0x75,0x8c,0xf0,0x25,0xd6,0x8f,0x21,0x20,0x00,0x00,0x21,0xb8,0x00,0x00, +0x08,0x00,0xc2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xae,0x08,0x00,0xc3,0x96, +0x02,0x80,0x02,0x3c,0x00,0x02,0x00,0x0c,0x25,0xa0,0x62,0x00,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xe4,0x0a,0xc3,0x97, +0x8c,0x25,0xc2,0x8f,0x25,0xb0,0x04,0x3c,0xf8,0x00,0x84,0x34,0x21,0x10,0x43,0x00, +0x00,0x00,0x82,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0x23,0x0e,0x00,0x08,0x00,0x00,0x00,0x00,0x0c,0x00,0xc2,0x8e,0x00,0x00,0x00,0x00, +0x2b,0x10,0xe2,0x02,0x86,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x8e, +0x21,0x98,0x80,0x02,0x42,0x1b,0x02,0x00,0x78,0x00,0x63,0x30,0x02,0x26,0x02,0x00, +0xff,0x3f,0x42,0x30,0x21,0x10,0x43,0x00,0x03,0x00,0x84,0x30,0x21,0x10,0x44,0x00, +0x18,0x00,0x42,0x24,0xff,0xff,0x52,0x30,0x7f,0x00,0x43,0x32,0x00,0x00,0xb2,0xae, +0x03,0x00,0x60,0x10,0x80,0xff,0x42,0x32,0x80,0x00,0x42,0x26,0x80,0xff,0x42,0x30, +0x00,0x00,0xa2,0xae,0x21,0x90,0x40,0x00,0x02,0x00,0x62,0x96,0x21,0x18,0xf2,0x02, +0xff,0xff,0x77,0x30,0x0f,0x00,0x42,0x30,0x00,0x00,0xa2,0xae,0x00,0x00,0x63,0x8e, +0x21,0xa0,0x92,0x02,0x42,0x13,0x03,0x00,0x78,0x00,0x42,0x30,0x02,0x1e,0x03,0x00, +0x03,0x00,0x63,0x30,0x21,0x10,0x53,0x00,0x21,0x88,0x43,0x00,0x18,0x00,0x25,0x26, +0x00,0x00,0xa5,0xae,0x01,0x00,0xa4,0x90,0x18,0x00,0x22,0x92,0x00,0x22,0x04,0x00, +0x73,0x0b,0x00,0x0c,0x25,0x20,0x82,0x00,0x40,0x18,0x02,0x00,0x21,0x18,0x62,0x00, +0x02,0x80,0x04,0x3c,0x21,0x80,0x40,0x00,0x80,0x18,0x03,0x00,0x98,0xa8,0x82,0x24, +0x21,0x18,0x62,0x00,0x08,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x09,0xf8,0x40,0x00, +0x21,0x20,0x60,0x02,0x06,0x00,0x03,0x24,0xc7,0xff,0x03,0x16,0x00,0x00,0x00,0x00, +0xe8,0x0a,0xc2,0x93,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0xc2,0xff,0x40,0x10, +0x02,0x80,0x02,0x3c,0x28,0x00,0x24,0x26,0x18,0x42,0x45,0x24,0x7b,0x46,0x00,0x0c, +0x06,0x00,0x06,0x24,0xbc,0xff,0x40,0x14,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c, +0xbc,0x44,0x64,0x8c,0x9c,0x44,0x43,0x90,0x02,0x80,0x02,0x3c,0x38,0xa9,0x45,0x8c, +0xff,0x00,0x63,0x30,0x40,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0xc0,0x10,0x02,0x00, +0x21,0x10,0x43,0x00,0x23,0x20,0x85,0x00,0x80,0x10,0x02,0x00,0x2b,0x20,0x82,0x00, +0xad,0xff,0x80,0x14,0x02,0x80,0x03,0x3c,0xbc,0x44,0x62,0x8c,0x21,0x20,0x40,0x02, +0x02,0x80,0x03,0x3c,0x39,0x15,0x00,0x0c,0x38,0xa9,0x62,0xac,0x1d,0x01,0x40,0x10, +0x21,0x88,0x40,0x00,0x00,0x00,0x65,0x8e,0x08,0x00,0x50,0x94,0x04,0x00,0x64,0x8e, +0xf0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0xe0,0xff,0x03,0x24,0x24,0x28,0xa2,0x00, +0xff,0xfb,0x02,0x3c,0x24,0x20,0x83,0x00,0xff,0xff,0x42,0x34,0x02,0x80,0x03,0x3c, +0x25,0x80,0x03,0x02,0x24,0x28,0xa2,0x00,0x1e,0x00,0x84,0x34,0x04,0x00,0x64,0xae, +0x00,0x00,0x65,0xae,0x21,0x20,0x00,0x02,0x21,0x28,0x60,0x02,0x52,0x46,0x00,0x0c, +0x06,0x00,0x06,0x24,0xc8,0xff,0x46,0x26,0xcb,0xff,0x43,0x26,0x00,0x00,0xc2,0x28, +0x0b,0x30,0x62,0x00,0x18,0x00,0x04,0x26,0x83,0x30,0x06,0x00,0x52,0x46,0x00,0x0c, +0x38,0x00,0x65,0x26,0x15,0x00,0x03,0x24,0x14,0x00,0x23,0xae,0x00,0x00,0x62,0x8e, +0x21,0x20,0x20,0x02,0x42,0x1b,0x02,0x00,0x78,0x00,0x63,0x30,0x02,0x2e,0x02,0x00, +0xff,0x3f,0x42,0x30,0x21,0x10,0x43,0x00,0x03,0x00,0xa5,0x30,0x21,0x10,0x45,0x00, +0x18,0x00,0x42,0x24,0x59,0x0a,0x00,0x0c,0x0c,0x00,0x22,0xae,0x0c,0x00,0xc2,0x8e, +0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x02,0x7c,0xff,0x40,0x14,0x00,0x00,0x00,0x00, +0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x04,0x00,0xc3,0x8e,0x00,0x00,0xc2,0x8e,0x21,0x20,0xc0,0x02,0x00,0x00,0x62,0xac, +0x04,0x00,0x43,0xac,0x00,0x00,0xd6,0xae,0x56,0x15,0x00,0x0c,0x04,0x00,0xd6,0xae, +0x00,0x60,0x90,0x40,0x02,0x80,0x04,0x3c,0x68,0x41,0x83,0x8c,0x68,0x41,0x82,0x24, +0x4c,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x7c,0xaf,0x42,0x24, +0x00,0x00,0x51,0x8c,0x25,0xb0,0x10,0x3c,0x04,0x01,0x02,0x36,0x00,0x00,0x43,0x8c, +0xa4,0x25,0x27,0x8e,0x00,0x00,0x00,0x00,0xc5,0x00,0xe3,0x10,0xa8,0x25,0x23,0xae, +0x2b,0x10,0x67,0x00,0xe4,0x00,0x40,0x14,0x2b,0x10,0xe3,0x00,0x0c,0x01,0x40,0x14, +0x23,0x10,0x67,0x00,0x02,0x80,0x03,0x3c,0x78,0x1b,0x64,0x24,0x78,0x25,0x83,0x94, +0x02,0x80,0x02,0x3c,0x21,0x90,0x00,0x00,0x22,0x00,0xe0,0x1a,0x25,0x88,0x62,0x00, +0x21,0xa8,0x80,0x00,0x21,0xf0,0x80,0x00,0x21,0x80,0x00,0x00,0x01,0x00,0x14,0x24, +0x21,0x98,0x11,0x02,0x04,0x00,0x62,0x8e,0x02,0x00,0x03,0x24,0x02,0x17,0x02,0x00, +0x03,0x00,0x42,0x30,0x31,0x00,0x43,0x10,0x02,0x80,0x04,0x3c,0x21,0x10,0x11,0x02, +0x00,0x00,0x43,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x10,0x01,0x00,0x42,0x26, +0x04,0x00,0x62,0x8e,0x00,0xf0,0x03,0x3c,0x00,0x20,0x04,0x3c,0x24,0x10,0x43,0x00, +0x10,0x00,0x44,0x10,0x00,0x00,0x00,0x00,0x06,0x00,0x42,0x26,0x00,0x00,0x65,0x8e, +0xff,0xff,0x52,0x30,0x82,0x16,0x05,0x00,0x01,0x00,0x42,0x30,0x4a,0x00,0x54,0x10, +0x02,0x80,0x03,0x3c,0x80,0x80,0x12,0x00,0x2a,0x10,0x17,0x02,0xe4,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0x56,0x15,0x00,0x0c,0x21,0x20,0xc0,0x02,0x8e,0x0f,0x00,0x08, +0x02,0x80,0x02,0x3c,0xc8,0x0c,0xa2,0x8e,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24, +0xc8,0x0c,0xa2,0xae,0x0c,0x00,0x64,0x8e,0x0c,0x00,0x02,0x24,0x3f,0x00,0x83,0x30, +0xa6,0x00,0x62,0x10,0x21,0x28,0xa0,0x02,0x3f,0x00,0x83,0x30,0x0d,0x00,0x02,0x24, +0x9b,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x3f,0x00,0x83,0x30,0x0e,0x00,0x02,0x24, +0xe2,0xff,0x62,0x14,0x06,0x00,0x42,0x26,0xd4,0x0c,0xa2,0x8e,0x00,0x00,0x00,0x00, +0x01,0x00,0x42,0x24,0xe6,0x0e,0x00,0x08,0xd4,0x0c,0xa2,0xae,0x98,0x44,0x82,0x90, +0x00,0x00,0x00,0x00,0xce,0xff,0x40,0x10,0x21,0x10,0x11,0x02,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x98,0x44,0x82,0x90, +0x02,0x80,0x03,0x3c,0xe4,0xae,0x65,0x24,0xff,0x00,0x42,0x30,0x80,0x10,0x02,0x00, +0x21,0x10,0x45,0x00,0x00,0x00,0x43,0x8c,0x00,0x00,0x64,0x8e,0x04,0x00,0x65,0x8e, +0x09,0xf8,0x60,0x00,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0x9a,0x44,0x82,0x90, +0x0c,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x10,0x02,0x80,0x03,0x3c, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xdc,0x0e,0x00,0x08, +0x21,0x10,0x11,0x02,0xb1,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0xf8,0xff,0x40,0x10, +0x02,0x80,0x04,0x3c,0xb7,0x44,0x82,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24, +0xb7,0x44,0x82,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0xdc,0x0e,0x00,0x08,0x21,0x10,0x11,0x02,0x78,0x1b,0x62,0x8c,0x00,0x00,0x00,0x00, +0x02,0x11,0x02,0x00,0x03,0x00,0x42,0x30,0x05,0x00,0x54,0x10,0xc2,0x13,0x05,0x00, +0x1e,0x00,0x42,0x30,0x21,0x10,0x52,0x00,0xed,0x0e,0x00,0x08,0xff,0xff,0x52,0x30, +0x01,0x00,0xc2,0x93,0x00,0x00,0x00,0x00,0x1c,0x00,0x40,0x14,0x02,0x80,0x04,0x3c, +0x04,0x00,0x64,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x04,0x00,0x0f,0x00,0x45,0x30, +0x08,0x00,0xa3,0x28,0x14,0x00,0x60,0x10,0x02,0x17,0x04,0x00,0x03,0x00,0x43,0x30, +0x08,0x00,0x60,0x10,0x00,0xc0,0x02,0x3c,0x24,0x10,0x82,0x00,0x0e,0x00,0x40,0x14, +0x03,0x00,0x02,0x24,0x0d,0x00,0x62,0x10,0x02,0x80,0x04,0x3c,0x0c,0x00,0x60,0x10, +0x78,0x1b,0x82,0x24,0x21,0x10,0xbe,0x00,0xf0,0x04,0x50,0x90,0x80,0x28,0x12,0x00, +0x21,0x28,0xb1,0x00,0x75,0x0d,0x00,0x0c,0x21,0x20,0x60,0x02,0x21,0x20,0x40,0x00, +0x1f,0x0d,0x00,0x0c,0x21,0x28,0x00,0x02,0x02,0x80,0x04,0x3c,0x78,0x1b,0x82,0x24, +0x01,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x89,0x00,0x74,0x10,0x00,0x00,0x00,0x00, +0x02,0x80,0x04,0x3c,0x78,0x1b,0x84,0x24,0x01,0x00,0x83,0x90,0x02,0x00,0x02,0x24, +0x08,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x8e,0x00,0x00,0x00,0x00, +0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,0x21,0x10,0x52,0x00,0xed,0x0e,0x00,0x08, +0xff,0xff,0x52,0x30,0x04,0x00,0x64,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x04,0x00, +0x0f,0x00,0x45,0x30,0x08,0x00,0xa3,0x28,0xf3,0xff,0x60,0x10,0x02,0x17,0x04,0x00, +0x03,0x00,0x42,0x30,0xf0,0xff,0x40,0x14,0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24, +0x21,0x10,0xa3,0x00,0xf0,0x04,0x50,0x90,0x80,0x28,0x12,0x00,0x21,0x28,0xb1,0x00, +0x75,0x0d,0x00,0x0c,0x21,0x20,0x60,0x02,0x21,0x20,0x40,0x00,0x1f,0x0d,0x00,0x0c, +0x21,0x28,0x00,0x02,0x00,0x00,0x65,0x8e,0x6d,0x0f,0x00,0x08,0xc2,0x13,0x05,0x00, +0x02,0x80,0x04,0x3c,0x00,0x01,0x02,0x36,0x78,0x1b,0x84,0x24,0x00,0x00,0x47,0xac, +0xa4,0x25,0x87,0xac,0x02,0x80,0x02,0x3c,0x08,0x04,0x44,0x24,0x21,0x28,0x00,0x00, +0x21,0x30,0x00,0x00,0x2d,0x28,0x00,0x0c,0x21,0x38,0x00,0x00,0xf7,0x0d,0x00,0x08, +0x02,0x80,0x02,0x3c,0x99,0x99,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x96,0x99,0x63,0x34, +0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x1e,0x0e,0x00,0x08,0x00,0x00,0x00,0x00, +0xd0,0x0c,0xa2,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xd0,0x0c,0xa2,0xac, +0x0c,0x00,0x64,0x8e,0x03,0x0f,0x00,0x08,0x3f,0x00,0x83,0x30,0xcc,0x0c,0xa2,0x8e, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xcc,0x0c,0xa2,0xae,0x0c,0x00,0x64,0x8e, +0xff,0x0e,0x00,0x08,0x3f,0x00,0x83,0x30,0xac,0x25,0x22,0x8e,0xff,0xff,0x73,0x30, +0x23,0x10,0x47,0x00,0xff,0xff,0x52,0x30,0x21,0x18,0x53,0x02,0xff,0xff,0x77,0x30, +0x39,0x15,0x00,0x0c,0x21,0x20,0xe0,0x02,0xda,0xff,0x40,0x10,0x21,0xb0,0x40,0x00, +0x08,0x00,0x42,0x8c,0xa4,0x25,0x26,0x8e,0x21,0x38,0x40,0x02,0x21,0x18,0x57,0x00, +0x74,0x25,0x23,0xae,0x21,0x28,0x40,0x00,0x08,0x00,0x04,0x24,0x78,0x25,0x22,0xae, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x00,0x02,0x00,0x0c,0x08,0x00,0x04,0x24, +0x78,0x25,0x25,0x8e,0x24,0x10,0x02,0x3c,0x00,0x01,0x10,0x36,0x00,0x00,0x02,0xae, +0x21,0x38,0x60,0x02,0x21,0x28,0xb2,0x00,0x08,0x00,0x04,0x24,0x24,0x10,0x06,0x3c, +0xa4,0x25,0x22,0xae,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xa8,0x25,0x23,0x8e, +0x08,0x00,0x04,0x24,0x00,0x02,0x00,0x0c,0xa4,0x25,0x23,0xae,0xa4,0x25,0x22,0x8e, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xae,0xca,0x0e,0x00,0x08,0x02,0x80,0x03,0x3c, +0xff,0xff,0x57,0x30,0x39,0x15,0x00,0x0c,0x21,0x20,0xe0,0x02,0x42,0x00,0x40,0x10, +0x21,0xb0,0x40,0x00,0x08,0x00,0x42,0x8c,0xa4,0x25,0x26,0x8e,0x08,0x00,0x04,0x24, +0x21,0x18,0x57,0x00,0x74,0x25,0x23,0xae,0x21,0x28,0x40,0x00,0x21,0x38,0xe0,0x02, +0x78,0x25,0x22,0xae,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xa8,0x25,0x23,0x8e, +0x08,0x00,0x04,0x24,0x00,0x02,0x00,0x0c,0xa4,0x25,0x23,0xae,0xa4,0x25,0x23,0x8e, +0x00,0x01,0x02,0x36,0x00,0x00,0x43,0xac,0xca,0x0e,0x00,0x08,0x02,0x80,0x03,0x3c, +0x04,0x00,0x64,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x04,0x00,0x0f,0x00,0x42,0x30, +0x08,0x00,0x42,0x28,0x06,0x00,0x40,0x10,0x00,0xc0,0x02,0x3c,0x02,0x17,0x04,0x00, +0x03,0x00,0x42,0x30,0x0b,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,0x00,0xc0,0x02,0x3c, +0x24,0x10,0x82,0x00,0x6a,0xff,0x40,0x14,0x02,0x17,0x04,0x00,0x03,0x00,0x42,0x30, +0x03,0x00,0x03,0x24,0x66,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x64,0xff,0x40,0x10, +0x02,0x80,0x03,0x3c,0x78,0x1b,0x62,0x8c,0x00,0x00,0x00,0x00,0x42,0x10,0x02,0x00, +0x01,0x00,0x42,0x30,0x06,0x00,0x54,0x14,0x21,0x80,0x00,0x00,0x02,0x14,0x04,0x00, +0x0f,0x00,0x42,0x30,0x78,0x1b,0x63,0x24,0x21,0x10,0x43,0x00,0xf0,0x04,0x50,0x90, +0x80,0x28,0x12,0x00,0x21,0x28,0xb1,0x00,0xec,0xff,0xa2,0x8c,0x25,0xb0,0x03,0x3c, +0xd4,0x02,0x63,0x34,0x21,0x20,0x60,0x02,0x00,0x00,0x62,0xac,0x75,0x0d,0x00,0x0c, +0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,0x1f,0x0d,0x00,0x0c,0x21,0x28,0x00,0x02, +0x65,0x0f,0x00,0x08,0x02,0x80,0x04,0x3c,0xa8,0x25,0x23,0x8e,0x00,0x01,0x02,0x36, +0x00,0x00,0x43,0xac,0x8d,0x0f,0x00,0x08,0xa4,0x25,0x23,0xae,0xe0,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x0c,0x00,0x82,0x8c, +0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,0x29,0x00,0x40,0x14, +0x21,0x80,0xa0,0x00,0x00,0x00,0xa4,0x8c,0x02,0x80,0x11,0x3c,0x3f,0x00,0x84,0x30, +0x40,0x20,0x04,0x00,0x6b,0x0d,0x00,0x0c,0x96,0xff,0x84,0x24,0x78,0x1b,0x25,0x26, +0xfc,0x23,0xa4,0x8c,0x21,0x18,0x40,0x00,0xff,0xff,0x02,0x34,0x3c,0x00,0x82,0x10, +0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x27,0x00,0x40,0x10,0x21,0x10,0x83,0x00, +0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00,0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24, +0xfc,0x23,0xa4,0xac,0x00,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00, +0x7e,0x00,0x84,0x30,0x6b,0x0d,0x00,0x0c,0x96,0xff,0x84,0x24,0x78,0x1b,0x25,0x26, +0x00,0x24,0xa4,0x8c,0x21,0x18,0x40,0x00,0xff,0xff,0x02,0x34,0x25,0x00,0x82,0x10, +0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x0b,0x00,0x40,0x10,0x21,0x10,0x83,0x00, +0x21,0x18,0x83,0x00,0x02,0x11,0x04,0x00,0x23,0x20,0x62,0x00,0x10,0x00,0x84,0x24, +0x00,0x24,0xa4,0xac,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x02,0x19,0x04,0x00,0x23,0x10,0x43,0x00,0x20,0x00,0xbd,0x27, +0x08,0x00,0xe0,0x03,0x00,0x24,0xa2,0xac,0x02,0x19,0x04,0x00,0x23,0x10,0x43,0x00, +0xfc,0x23,0xa2,0xac,0x00,0x00,0x04,0x8e,0x00,0x00,0x00,0x00,0xc2,0x21,0x04,0x00, +0x7e,0x00,0x84,0x30,0x6b,0x0d,0x00,0x0c,0x96,0xff,0x84,0x24,0x78,0x1b,0x25,0x26, +0x00,0x24,0xa4,0x8c,0x21,0x18,0x40,0x00,0xff,0xff,0x02,0x34,0xde,0xff,0x82,0x14, +0x2b,0x10,0x83,0x00,0x00,0x21,0x03,0x00,0x49,0x10,0x00,0x08,0x00,0x24,0xa4,0xac, +0x00,0x21,0x03,0x00,0x35,0x10,0x00,0x08,0xfc,0x23,0xa4,0xac,0xb8,0xff,0xbd,0x27, +0x25,0xb0,0x03,0x3c,0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf,0x3c,0x00,0xb7,0xaf, +0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf,0x2c,0x00,0xb3,0xaf, +0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf,0x44,0x00,0x63,0x34, +0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00, +0x0e,0x00,0x40,0x04,0x18,0x00,0xa0,0xaf,0x21,0x20,0x60,0x00,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0xff,0x42,0x30,0x64,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x02,0x00, +0x03,0x16,0x02,0x00,0xf6,0xff,0x41,0x04,0x21,0x10,0x00,0x00,0x02,0x80,0x02,0x3c, +0x78,0x41,0x43,0x8c,0x00,0x80,0x06,0x3c,0xcc,0x41,0xc2,0x24,0x25,0xb0,0x05,0x3c, +0x02,0x80,0x06,0x3c,0x18,0x03,0xa4,0x34,0x78,0x41,0xd1,0x24,0x00,0x00,0x82,0xac, +0x5d,0x00,0x71,0x10,0x01,0x00,0x15,0x24,0x2a,0xb0,0x02,0x3c,0x02,0x80,0x03,0x3c, +0x06,0x00,0x56,0x34,0x78,0x1b,0x74,0x24,0xb0,0x03,0xb7,0x34,0x21,0xf0,0x80,0x00, +0x05,0x00,0x53,0x34,0x01,0x00,0x12,0x24,0x1b,0x00,0xa0,0x12,0x02,0x80,0x03,0x3c, +0x98,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x17,0x00,0x40,0x10,0x21,0xa8,0x00,0x00, +0x01,0x00,0x06,0x24,0x18,0x00,0xa6,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90, +0x00,0x00,0x00,0x00,0x0f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,0x57,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x02,0x80,0x06,0x3c,0x56,0x43,0xc2,0x90,0x00,0x00,0x00,0x00, +0x02,0x00,0x42,0x30,0x4d,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x00,0xc2,0x96,0x00,0x26,0x90,0x8e, +0x00,0xff,0x42,0x30,0x00,0x00,0xf0,0xae,0x0d,0x00,0x40,0x18,0x02,0x80,0x02,0x3c, +0x84,0xaf,0x42,0x24,0x21,0x28,0xc0,0x03,0x00,0x00,0x44,0x8c,0x02,0x80,0x06,0x3c, +0x88,0xaf,0xc6,0x24,0x00,0x00,0xc3,0x8c,0x00,0x00,0xa4,0xac,0x00,0x00,0x62,0x94, +0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30,0xfb,0xff,0x40,0x1c,0x00,0x00,0x00,0x00, +0x0c,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x07,0x00,0x62,0x30,0x48,0x00,0x40,0x14, +0x08,0x00,0x62,0x24,0xc2,0x10,0x03,0x00,0x08,0x00,0x05,0x8e,0xcc,0x24,0x86,0x8e, +0xc0,0x10,0x02,0x00,0x20,0x00,0x42,0x24,0xff,0xff,0x47,0x30,0x01,0x00,0x04,0x24, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xb2,0xaf,0x00,0x02,0x00,0x0c,0x01,0x00,0x04,0x24, +0x02,0x00,0x02,0x24,0x00,0x00,0x72,0xa2,0x00,0x00,0x62,0xa2,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x04,0x00,0x03,0x8e, +0x00,0x00,0x02,0x8e,0x21,0x20,0x00,0x02,0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac, +0x00,0x00,0x10,0xae,0x56,0x15,0x00,0x0c,0x04,0x00,0x10,0xae,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x00,0x22,0x8e,0x00,0x00,0x00,0x00, +0xad,0xff,0x51,0x14,0x00,0x00,0x00,0x00,0x18,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00, +0x07,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x98,0x44,0x62,0x90, +0x00,0x00,0x00,0x00,0x11,0x00,0x40,0x14,0x18,0x00,0xa0,0xaf,0x02,0x80,0x02,0x3c, +0x08,0x08,0x44,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0x2d,0x28,0x00,0x0c, +0x21,0x38,0x00,0x00,0x94,0x10,0x00,0x08,0x02,0x80,0x02,0x3c,0x55,0x1f,0x00,0x0c, +0x01,0x00,0x04,0x24,0xbf,0x10,0x00,0x08,0x00,0x00,0x00,0x00,0xf9,0x1f,0x00,0x0c, +0x04,0x00,0x04,0x24,0xba,0x10,0x00,0x08,0x02,0x80,0x06,0x3c,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x06,0x3c, +0x99,0x44,0xc4,0x90,0xf9,0x1f,0x00,0x0c,0xff,0x00,0x84,0x30,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x04,0x11,0x00,0x08,0x02,0x80,0x02,0x3c, +0xda,0x10,0x00,0x08,0xc2,0x10,0x02,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00, +0x08,0x00,0xe0,0x03,0x08,0x00,0x82,0x24,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf, +0x24,0x11,0x00,0x0c,0x74,0x00,0x84,0x24,0x21,0x28,0x40,0x00,0x10,0x00,0xa4,0x27, +0x46,0x46,0x00,0x0c,0x02,0x00,0x06,0x24,0x10,0x00,0xa2,0x97,0x18,0x00,0xbf,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27, +0x18,0x00,0xbf,0xaf,0x24,0x11,0x00,0x0c,0x10,0x00,0xa5,0xa7,0x21,0x20,0x40,0x00, +0x10,0x00,0xa5,0x27,0x46,0x46,0x00,0x0c,0x02,0x00,0x06,0x24,0x18,0x00,0xbf,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03, +0x0a,0x00,0x82,0x24,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf,0x3f,0x11,0x00,0x0c, +0x74,0x00,0x84,0x24,0x21,0x28,0x40,0x00,0x10,0x00,0xa4,0x27,0x46,0x46,0x00,0x0c, +0x02,0x00,0x06,0x24,0x10,0x00,0xa2,0x97,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf, +0x21,0x80,0x80,0x00,0x00,0x00,0x05,0xa2,0x01,0x00,0x06,0xa2,0x18,0x00,0xb2,0xaf, +0x14,0x00,0xb1,0xaf,0x1c,0x00,0xbf,0xaf,0x21,0x88,0xc0,0x00,0x02,0x00,0x84,0x24, +0x30,0x00,0xb2,0x8f,0x0d,0x00,0xc0,0x14,0x21,0x28,0xe0,0x00,0x00,0x00,0x43,0x8e, +0x21,0x10,0x11,0x02,0x1c,0x00,0xbf,0x8f,0x21,0x18,0x71,0x00,0x02,0x00,0x63,0x24, +0x00,0x00,0x43,0xae,0x14,0x00,0xb1,0x8f,0x18,0x00,0xb2,0x8f,0x10,0x00,0xb0,0x8f, +0x02,0x00,0x42,0x24,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x46,0x46,0x00,0x0c, +0x00,0x00,0x00,0x00,0x00,0x00,0x43,0x8e,0x21,0x10,0x11,0x02,0x1c,0x00,0xbf,0x8f, +0x21,0x18,0x71,0x00,0x02,0x00,0x63,0x24,0x00,0x00,0x43,0xae,0x14,0x00,0xb1,0x8f, +0x18,0x00,0xb2,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x00,0x42,0x24,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x21,0x80,0xa0,0x00, +0x18,0x00,0xb2,0xaf,0x21,0x28,0xc0,0x00,0x21,0x90,0xe0,0x00,0x21,0x30,0x00,0x02, +0x1c,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x46,0x46,0x00,0x0c,0x21,0x88,0x80,0x00, +0x00,0x00,0x43,0x8e,0x21,0x10,0x30,0x02,0x1c,0x00,0xbf,0x8f,0x21,0x18,0x70,0x00, +0x00,0x00,0x43,0xae,0x14,0x00,0xb1,0x8f,0x18,0x00,0xb2,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x10,0x00,0xe0,0x18,0x21,0x18,0x00,0x00, +0x00,0x00,0xc0,0xac,0x21,0x40,0x00,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00, +0x0c,0x00,0x45,0x10,0x21,0x18,0x80,0x00,0x01,0x00,0x82,0x90,0x00,0x00,0x00,0x00, +0x21,0x18,0x48,0x00,0x02,0x00,0x68,0x24,0x21,0x10,0x82,0x00,0x2b,0x18,0x07,0x01, +0xf5,0xff,0x60,0x14,0x02,0x00,0x44,0x24,0x21,0x18,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x01,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xac, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x7f,0x00,0x84,0x30,0x0c,0x00,0x82,0x2c, +0x0a,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00, +0x8c,0xaf,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00, +0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x6c,0x00,0x03,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x60,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x48,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x30,0x00,0x03,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x24,0x00,0x03,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x18,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x12,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x0c,0x00,0x03,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x16,0x00,0x03,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x0b,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x04,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x02,0x00,0x03,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xc8,0xff,0xbd,0x27,0x24,0x00,0xb5,0xaf, +0x02,0x80,0x15,0x3c,0x2c,0x00,0xb7,0xaf,0x28,0x00,0xb6,0xaf,0x20,0x00,0xb4,0xaf, +0x1c,0x00,0xb3,0xaf,0x30,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf, +0x10,0x00,0xb0,0xaf,0x21,0xb8,0x80,0x00,0x21,0xa0,0x00,0x00,0x21,0x98,0x00,0x00, +0x78,0x1b,0xb6,0x26,0x78,0x1b,0xa2,0x26,0x21,0x10,0x62,0x02,0x44,0x0b,0x51,0x90, +0xfe,0x00,0x03,0x24,0x1e,0x00,0x23,0x12,0xff,0x00,0x02,0x24,0x21,0x00,0x22,0x12, +0x21,0x10,0x80,0x02,0xa2,0x11,0x00,0x0c,0x21,0x20,0x20,0x02,0x21,0x88,0x40,0x00, +0x21,0x80,0x00,0x00,0x21,0x90,0xc0,0x02,0x21,0x10,0x12,0x02,0x26,0x0b,0x44,0x90, +0x00,0x00,0x00,0x00,0x02,0x00,0x82,0x24,0xff,0x00,0x42,0x30,0x02,0x00,0x42,0x2c, +0x05,0x00,0x40,0x14,0x01,0x00,0x10,0x26,0xa2,0x11,0x00,0x0c,0x00,0x00,0x00,0x00, +0x05,0x00,0x51,0x10,0x01,0x00,0x03,0x24,0x1e,0x00,0x02,0x2a,0xf3,0xff,0x40,0x14, +0x21,0x10,0x12,0x02,0x21,0x18,0x00,0x00,0x01,0x00,0x02,0x24,0x14,0x00,0x62,0x10, +0xff,0x00,0x22,0x32,0x21,0x10,0xf4,0x02,0x00,0x00,0x51,0xa0,0x01,0x00,0x94,0x26, +0x01,0x00,0x73,0x26,0x1e,0x00,0x62,0x2a,0xdb,0xff,0x40,0x14,0x78,0x1b,0xa2,0x26, +0x21,0x10,0x80,0x02,0x30,0x00,0xbf,0x8f,0x2c,0x00,0xb7,0x8f,0x28,0x00,0xb6,0x8f, +0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27, +0x01,0x12,0x00,0x08,0x80,0x00,0x51,0x34,0xb8,0xff,0xbd,0x27,0x3c,0x00,0xb3,0xaf, +0x38,0x00,0xb2,0xaf,0x30,0x00,0xb0,0xaf,0x21,0x90,0xc0,0x00,0x21,0x98,0xa0,0x00, +0x1e,0x00,0x06,0x24,0x21,0x28,0x00,0x00,0x21,0x80,0x80,0x00,0x10,0x00,0xa4,0x27, +0x40,0x00,0xbf,0xaf,0x35,0x46,0x00,0x0c,0x34,0x00,0xb1,0xaf,0x10,0x00,0xa4,0x27, +0xd2,0x11,0x00,0x0c,0x00,0x00,0x40,0xae,0x21,0x88,0x40,0x00,0x09,0x00,0x43,0x28, +0x21,0x38,0x40,0x00,0x08,0x00,0x02,0x24,0x0a,0x88,0x43,0x00,0x01,0x00,0x02,0x24, +0x21,0x20,0x60,0x02,0x10,0x00,0xa5,0x27,0x0e,0x00,0x02,0x12,0x21,0x30,0x20,0x02, +0x05,0x00,0x60,0x14,0xf8,0xff,0xf1,0x24,0x21,0x20,0x60,0x02,0x18,0x00,0xa5,0x27, +0x08,0x00,0x20,0x16,0x21,0x30,0x20,0x02,0x40,0x00,0xbf,0x8f,0x3c,0x00,0xb3,0x8f, +0x38,0x00,0xb2,0x8f,0x34,0x00,0xb1,0x8f,0x30,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x48,0x00,0xbd,0x27,0x46,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0xae, +0x40,0x00,0xbf,0x8f,0x3c,0x00,0xb3,0x8f,0x38,0x00,0xb2,0x8f,0x34,0x00,0xb1,0x8f, +0x30,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,0x00,0x00,0x82,0x94, +0x21,0x30,0x80,0x00,0x10,0x00,0x85,0x24,0x42,0x1a,0x02,0x00,0xc2,0x11,0x02,0x00, +0x02,0x00,0x42,0x30,0x01,0x00,0x63,0x30,0x25,0x18,0x43,0x00,0x01,0x00,0x04,0x24, +0x07,0x00,0x64,0x10,0x00,0x00,0x00,0x00,0x05,0x00,0x60,0x10,0x0a,0x00,0xc5,0x24, +0x02,0x00,0x02,0x24,0x02,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x18,0x00,0xc5,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0xa0,0x00,0x00,0x00,0x82,0x94,0x21,0x30,0x80,0x00, +0x04,0x00,0x85,0x24,0x42,0x1a,0x02,0x00,0xc2,0x11,0x02,0x00,0x02,0x00,0x42,0x30, +0x01,0x00,0x63,0x30,0x25,0x18,0x43,0x00,0x01,0x00,0x04,0x24,0x04,0x00,0x64,0x10, +0x00,0x00,0x00,0x00,0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x10,0x00,0xc5,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0xa0,0x00,0x13,0x00,0xa0,0x18,0x21,0x30,0x00,0x00, +0x02,0x00,0x07,0x24,0x04,0x00,0x08,0x24,0x0b,0x00,0x09,0x24,0x16,0x00,0x0a,0x24, +0x21,0x10,0x86,0x00,0x00,0x00,0x43,0x90,0x01,0x00,0xc6,0x24,0x7f,0x00,0x63,0x30, +0x07,0x00,0x67,0x10,0x2a,0x10,0xc5,0x00,0x05,0x00,0x68,0x10,0x00,0x00,0x00,0x00, +0x03,0x00,0x69,0x10,0x00,0x00,0x00,0x00,0x05,0x00,0x6a,0x14,0x00,0x00,0x00,0x00, +0xf3,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf, +0x6a,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,0x01,0x00,0x44,0x38, +0x03,0x00,0x03,0x24,0x01,0x00,0x02,0x24,0x0b,0x10,0x64,0x00,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x60,0x02,0x40, +0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c, +0xfc,0xa9,0x64,0xac,0x00,0x60,0x82,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x02,0x80,0x02,0x3c,0xfc,0xa9,0x45,0x8c,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x18,0x03,0x42,0x34,0x70,0x4a,0x63,0x24,0x00,0x00,0x43,0xac,0x04,0x00,0x02,0x24, +0x1e,0x00,0xa2,0x10,0x05,0x00,0xa2,0x2c,0x10,0x00,0x40,0x10,0x05,0x00,0x02,0x24, +0x03,0x00,0x02,0x24,0x08,0x00,0xa2,0x10,0x00,0x19,0x04,0x00,0x80,0x10,0x04,0x00, +0x21,0x10,0x44,0x00,0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00, +0x21,0x10,0x44,0x00,0x40,0x19,0x02,0x00,0xff,0xff,0x63,0x24,0xfe,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf3,0xff,0xa2,0x10, +0x06,0x00,0x02,0x24,0xf2,0xff,0xa2,0x14,0x80,0x10,0x04,0x00,0x40,0x11,0x04,0x00, +0x23,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x00,0x19,0x02,0x00, +0x23,0x18,0x62,0x00,0xb2,0x12,0x00,0x08,0x00,0x19,0x03,0x00,0x80,0x10,0x04,0x00, +0x21,0x10,0x44,0x00,0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00, +0x21,0x10,0x44,0x00,0xb2,0x12,0x00,0x08,0x00,0x19,0x02,0x00,0x02,0x80,0x02,0x3c, +0xfc,0xa9,0x45,0x8c,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34, +0x2c,0x4b,0x63,0x24,0x00,0x00,0x43,0xac,0x05,0x00,0x02,0x24,0x06,0x00,0xa2,0x10, +0x06,0x00,0xa2,0x2c,0x0c,0x00,0x40,0x10,0x06,0x00,0x02,0x24,0x04,0x00,0x02,0x24, +0x0e,0x00,0xa2,0x10,0x80,0x10,0x04,0x00,0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00, +0x80,0x10,0x02,0x00,0xff,0xff,0x42,0x24,0xfe,0xff,0x40,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf7,0xff,0xa2,0x14,0x00,0x11,0x04,0x00, +0x23,0x10,0x44,0x00,0xdd,0x12,0x00,0x08,0x40,0x10,0x02,0x00,0x21,0x10,0x44,0x00, +0xdd,0x12,0x00,0x08,0x40,0x10,0x02,0x00,0xff,0xff,0x85,0x30,0x21,0x30,0x00,0x00, +0x25,0xb0,0x03,0x3c,0x2a,0xb0,0x04,0x3c,0xb4,0x00,0x63,0x34,0x01,0x00,0xa2,0x24, +0x31,0x00,0x84,0x34,0x00,0x00,0x65,0xa0,0x00,0x00,0x85,0xa0,0xff,0xff,0x45,0x30, +0x12,0x00,0xa0,0x10,0x01,0x00,0x03,0x24,0x28,0xb0,0x07,0x3c,0xff,0x12,0x00,0x08, +0xff,0xff,0x08,0x24,0x00,0x00,0x83,0xa0,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30, +0x2b,0x10,0xa3,0x00,0x09,0x00,0x40,0x14,0x08,0x00,0xc6,0x24,0xf9,0xff,0x65,0x14, +0x21,0x20,0xc7,0x00,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,0x2b,0x10,0xa3,0x00, +0x00,0x00,0x88,0xa0,0xf9,0xff,0x40,0x10,0x08,0x00,0xc6,0x24,0x00,0x01,0xa2,0x2c, +0x13,0x00,0x40,0x10,0x21,0x18,0xa0,0x00,0xff,0x00,0x08,0x24,0x28,0xb0,0x07,0x3c, +0x13,0x13,0x00,0x08,0xff,0xff,0x09,0x24,0xff,0xff,0x43,0x30,0x00,0x00,0xa2,0xa0, +0x00,0x01,0x62,0x2c,0x0a,0x00,0x40,0x10,0x08,0x00,0xc6,0x24,0x01,0x00,0x62,0x24, +0xf9,0xff,0x68,0x14,0x21,0x28,0xc7,0x00,0x00,0x01,0x02,0x24,0xff,0xff,0x43,0x30, +0x00,0x01,0x62,0x2c,0x00,0x00,0xa9,0xa0,0xf8,0xff,0x40,0x14,0x08,0x00,0xc6,0x24, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x28,0x00,0xbf,0xaf, +0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x12,0x40,0x01,0x00,0x41,0x36, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x42,0x00,0x15,0x36, +0xff,0xff,0x02,0x24,0x00,0x00,0xa2,0xa2,0xd8,0x00,0x05,0x36,0x40,0x00,0x11,0x36, +0xa8,0x00,0x14,0x36,0xa0,0x00,0x13,0x36,0x00,0x10,0x03,0x24,0xa4,0x00,0x10,0x36, +0x00,0x80,0x02,0x3c,0x00,0x00,0x23,0xa6,0x00,0x00,0xa0,0xa0,0x00,0x00,0x60,0xae, +0x00,0x00,0x00,0xae,0x00,0x00,0x82,0xae,0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24, +0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00,0xfc,0x17,0x02,0x24,0x00,0x00,0xa3,0xa0, +0x00,0x00,0x22,0xa6,0xea,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c, +0x78,0x1b,0x42,0x24,0x74,0x0b,0x45,0x8c,0x6c,0x0b,0x43,0x8c,0x70,0x0b,0x44,0x8c, +0xfc,0x37,0x02,0x24,0x00,0x00,0x63,0xae,0x00,0x00,0x04,0xae,0x00,0x00,0x85,0xae, +0x00,0x00,0x22,0xa6,0x00,0x00,0xa0,0xa2,0x00,0x60,0x92,0x40,0x28,0x00,0xbf,0x8f, +0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27, +0xc8,0xff,0xbd,0x27,0x34,0x00,0xbf,0xaf,0x30,0x00,0xbe,0xaf,0x2c,0x00,0xb7,0xaf, +0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf, +0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x16,0x40, +0x01,0x00,0xc1,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x11,0x3c, +0x40,0x00,0x30,0x36,0xff,0xff,0x02,0x24,0x42,0x00,0x3e,0x36,0xfc,0x77,0x13,0x24, +0x00,0x00,0xc2,0xa3,0xfc,0x57,0x12,0x24,0x00,0x00,0x13,0xa6,0xcb,0x12,0x00,0x0c, +0x32,0x00,0x04,0x24,0xfc,0x37,0x17,0x24,0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6, +0xcb,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x32,0x00,0x04,0x24,0x00,0x00,0x17,0xa6, +0xcb,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xa6,0xcb,0x12,0x00,0x0c, +0x32,0x00,0x04,0x24,0x32,0x00,0x04,0x24,0x00,0x00,0x12,0xa6,0xcb,0x12,0x00,0x0c, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x96,0x24,0xfa,0x03,0x24,0xd8,0x00,0x25,0x36, +0x24,0x10,0x43,0x00,0x00,0x00,0x02,0xa6,0x00,0x00,0xa3,0x90,0xa0,0x00,0x34,0x36, +0xa4,0x00,0x35,0x36,0xa8,0x00,0x33,0x36,0x7f,0x00,0x63,0x30,0x00,0x80,0x02,0x3c, +0x00,0x00,0xa3,0xa0,0x00,0x00,0x80,0xae,0x00,0x00,0xa0,0xae,0x00,0x00,0x62,0xae, +0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00, +0x00,0x00,0xa3,0xa0,0x00,0x00,0x12,0xa6,0xea,0x12,0x00,0x0c,0x56,0x01,0x31,0x36, +0x02,0x80,0x02,0x3c,0x78,0x1b,0x42,0x24,0x74,0x0b,0x45,0x8c,0x6c,0x0b,0x43,0x8c, +0x70,0x0b,0x44,0x8c,0xff,0x0f,0x02,0x24,0x00,0x00,0x83,0xae,0x00,0x00,0xa4,0xae, +0x00,0x00,0x65,0xae,0x00,0x00,0x17,0xa6,0x00,0x00,0x22,0xa6,0x00,0x00,0xc0,0xa3, +0x00,0x60,0x96,0x40,0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f, +0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x38,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf, +0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x40,0x00,0x05,0x36, +0x00,0x00,0xa2,0x94,0xaf,0xff,0x03,0x24,0xa8,0x00,0x13,0x36,0x24,0x10,0x43,0x00, +0x00,0x00,0xa2,0xa4,0xa0,0x00,0x12,0x36,0xa4,0x00,0x10,0x36,0x00,0x00,0x55,0x8e, +0x00,0x00,0x16,0x8e,0x00,0x00,0x71,0x8e,0x00,0x80,0x14,0x3c,0xfc,0x37,0x02,0x24, +0x00,0x00,0x40,0xae,0xfd,0x00,0x04,0x24,0x00,0x00,0x00,0xae,0x21,0x88,0x34,0x02, +0x00,0x00,0x74,0xae,0x00,0x00,0xa2,0xa4,0xea,0x12,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x00,0x55,0xae,0x00,0x00,0x16,0xae,0x00,0x00,0x71,0xae,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f, +0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x25,0xb0,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0xd8,0xfd,0x03,0x24, +0x24,0x10,0x43,0x00,0xfc,0x37,0x03,0x24,0x00,0x00,0x82,0xa4,0x00,0x00,0x83,0xa4, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xc8,0xff,0xbd,0x27,0x25,0xb0,0x03,0x3c,0x1c,0x00,0xb3,0xaf, +0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x34,0x00,0xbf,0xaf, +0x30,0x00,0xbe,0xaf,0x2c,0x00,0xb7,0xaf,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf, +0x20,0x00,0xb4,0xaf,0x0a,0x00,0x67,0x34,0x00,0x00,0xe2,0x90,0xff,0xff,0xb2,0x30, +0x21,0x98,0xc0,0x00,0xff,0x00,0x91,0x30,0x20,0x00,0x40,0x12,0xff,0x00,0x50,0x30, +0x21,0xa0,0xe0,0x00,0x0c,0x00,0x77,0x34,0x0b,0x00,0x76,0x34,0x21,0xf0,0xe0,0x00, +0xc0,0xff,0x15,0x24,0x25,0x10,0x15,0x02,0xff,0x00,0x50,0x30,0x00,0x00,0xd1,0xa2, +0x00,0x00,0x90,0xa2,0x00,0x00,0x82,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x50,0x30, +0xc0,0x00,0x03,0x32,0x07,0x00,0x60,0x10,0x21,0x20,0xc0,0x03,0x00,0x00,0x82,0x90, +0x00,0x00,0x00,0x00,0xff,0x00,0x50,0x30,0xc0,0x00,0x03,0x32,0xfb,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0x8e,0x04,0x00,0x23,0x26,0x64,0x00,0x04,0x24, +0x00,0x00,0x62,0xae,0x9c,0x12,0x00,0x0c,0xff,0x00,0x71,0x30,0xfc,0xff,0x42,0x26, +0xff,0xff,0x52,0x30,0xe7,0xff,0x40,0x16,0x04,0x00,0x73,0x26,0x34,0x00,0xbf,0x8f, +0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f, +0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xff,0x00,0x84,0x30, +0xff,0xff,0xac,0x30,0xc0,0x48,0x04,0x00,0x00,0x60,0x0e,0x40,0x01,0x00,0xc1,0x35, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x02,0x3c,0x40,0x02,0x4d,0x34, +0xf8,0xff,0xe7,0x24,0x21,0x40,0x00,0x00,0x01,0x00,0x0f,0x24,0x44,0x02,0x4b,0x34, +0x57,0x14,0x00,0x08,0x01,0x80,0x0a,0x3c,0x28,0x00,0x0f,0x11,0x00,0x00,0x00,0x00, +0x01,0x00,0xe2,0x90,0x00,0x00,0xe4,0x90,0x02,0x00,0xe3,0x90,0x03,0x00,0xe5,0x90, +0x00,0x12,0x02,0x00,0x25,0x20,0x82,0x00,0x00,0x1c,0x03,0x00,0x25,0x20,0x83,0x00, +0x21,0x10,0x28,0x01,0x00,0x2e,0x05,0x00,0x01,0x00,0x08,0x25,0x25,0x20,0x85,0x00, +0x25,0x10,0x4a,0x00,0x06,0x00,0x03,0x2d,0x00,0x00,0x64,0xad,0x04,0x00,0xe7,0x24, +0x00,0x00,0xa2,0xad,0x12,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0xea,0xff,0x00,0x15, +0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0x90,0x01,0x00,0xc3,0x90,0x04,0x00,0xe7,0x24, +0x00,0x14,0x02,0x00,0x25,0x10,0x82,0x01,0x00,0x1e,0x03,0x00,0x25,0x20,0x43,0x00, +0x21,0x10,0x28,0x01,0x01,0x00,0x08,0x25,0x25,0x10,0x4a,0x00,0x06,0x00,0x03,0x2d, +0x00,0x00,0x64,0xad,0x00,0x00,0xa2,0xad,0xf0,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x00,0x60,0x8e,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x03,0x00,0xc2,0x90, +0x02,0x00,0xc4,0x90,0x04,0x00,0xc3,0x90,0x05,0x00,0xc5,0x90,0x49,0x14,0x00,0x08, +0x00,0x12,0x02,0x00,0xff,0xff,0x84,0x30,0x42,0xb0,0x08,0x3c,0x80,0x10,0x04,0x00, +0x21,0x10,0x48,0x00,0x04,0x00,0x46,0xac,0x00,0x00,0x07,0x91,0x40,0x18,0x04,0x00, +0x03,0x00,0x06,0x24,0xff,0x00,0xe7,0x30,0x04,0x30,0x66,0x00,0x01,0x00,0x02,0x24, +0x04,0x10,0x62,0x00,0x25,0x30,0xc7,0x00,0xff,0xff,0xa5,0x30,0x25,0x10,0x47,0x00, +0x02,0x00,0xa0,0x14,0xff,0x00,0xc7,0x30,0xff,0x00,0x47,0x30,0x42,0xb0,0x02,0x3c, +0x00,0x00,0x47,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x42,0xb0,0x02,0x3c, +0x03,0x00,0x47,0x34,0x00,0x00,0xe3,0x90,0xff,0x00,0x84,0x30,0x04,0x00,0x84,0x24, +0xff,0x00,0x65,0x30,0x01,0x00,0x02,0x24,0x04,0x30,0x82,0x00,0x07,0x18,0x85,0x00, +0x25,0xb0,0x02,0x3c,0xe8,0x03,0x42,0x34,0x01,0x00,0x63,0x30,0x21,0x20,0xc0,0x00, +0x00,0x00,0x45,0xa0,0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0xa0, +0x08,0x00,0xe0,0x03,0x24,0x10,0x85,0x00,0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x00,0xaa,0x42,0x24, +0x04,0x00,0x45,0x8c,0x00,0x00,0x82,0xac,0x04,0x00,0x44,0xac,0x00,0x00,0xa4,0xac, +0x04,0x00,0x85,0xac,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x14,0x00,0x83,0x90,0x01,0x00,0x02,0x24,0x08,0x00,0x86,0xac,0x18,0x00,0x85,0xac, +0x00,0x00,0x84,0xac,0x03,0x00,0x62,0x10,0x04,0x00,0x84,0xac,0x9a,0x14,0x00,0x08, +0x0c,0x00,0x80,0xac,0x0c,0x00,0x82,0x8c,0x9a,0x14,0x00,0x08,0x10,0x00,0x82,0xac, +0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x04,0x00,0x85,0x8c,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac, +0x04,0x00,0x45,0xac,0x00,0x00,0x84,0xac,0x04,0x00,0x84,0xac,0x00,0x60,0x83,0x40, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xc8,0xff,0xbd,0x27,0x28,0x00,0xb6,0xaf, +0x25,0xb0,0x02,0x3c,0x02,0x80,0x16,0x3c,0x2c,0x00,0xb7,0xaf,0x24,0x00,0xb5,0xaf, +0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x30,0x00,0xbf,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x18,0x03,0x55,0x34,0x00,0x80,0x17,0x3c, +0x02,0x80,0x13,0x3c,0x02,0x80,0x14,0x3c,0x00,0xaa,0xd2,0x26,0x08,0x53,0xe2,0x26, +0x00,0x00,0xa2,0xae,0x00,0xaa,0xd0,0x8e,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x8c,0x43,0x71,0x8e,0x00,0x00,0x00,0x00, +0x25,0x00,0x20,0x12,0x00,0x00,0x00,0x00,0x8c,0x43,0x60,0xae,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x23,0x00,0x12,0x12,0x08,0x0c,0x84,0x26, +0x14,0x00,0x03,0x92,0x01,0x00,0x02,0x24,0x2b,0x00,0x62,0x10,0x00,0x00,0x00,0x00, +0x0a,0x00,0x60,0x14,0x02,0x00,0x02,0x24,0x0c,0x00,0x03,0x8e,0x00,0x00,0x00,0x00, +0x2b,0x10,0x23,0x02,0x1e,0x00,0x40,0x10,0x23,0x10,0x71,0x00,0x0c,0x00,0x02,0xae, +0x00,0x00,0x10,0x8e,0xe2,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0xfc,0xff,0x62,0x14, +0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0xf8,0xff,0x60,0x10, +0x2b,0x10,0x23,0x02,0xf5,0xff,0x40,0x14,0x23,0x10,0x71,0x00,0x08,0x00,0x02,0x8e, +0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,0x0c,0x00,0x00,0xae,0x00,0x00,0x10,0x8e, +0xe2,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x08,0x0c,0x84,0x26,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00, +0x2d,0x28,0x00,0x0c,0x21,0x38,0x00,0x00,0xd4,0x14,0x00,0x08,0x08,0x53,0xe2,0x26, +0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,0x00,0x00,0x00,0x00, +0xf0,0x14,0x00,0x08,0x0c,0x00,0x02,0xae,0x0c,0x00,0x03,0x8e,0x00,0x00,0x00,0x00, +0x2b,0x10,0x23,0x02,0xd9,0xff,0x40,0x14,0x23,0x10,0x71,0x00,0x08,0x00,0x02,0x8e, +0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x03,0x8e, +0x00,0x00,0x00,0x00,0x0c,0x00,0x03,0xae,0x00,0x00,0x10,0x8e,0xe2,0x14,0x00,0x08, +0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x80,0x41,0x42,0x24,0xc0,0x20,0x04,0x00, +0x21,0x20,0x82,0x00,0x21,0x28,0x00,0x00,0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x09,0x00,0x44,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x43,0x8c,0x21,0x28,0x40,0x00, +0x00,0x00,0x42,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac, +0x00,0x00,0xa5,0xac,0x04,0x00,0xa5,0xac,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03, +0x21,0x10,0xa0,0x00,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00, +0x01,0x01,0x02,0x2e,0x14,0x00,0xbf,0xaf,0x01,0x00,0x04,0x24,0x01,0x02,0x03,0x2e, +0x0b,0x00,0x40,0x14,0x21,0x28,0x00,0x00,0x02,0x00,0x04,0x24,0x08,0x00,0x60,0x14, +0x01,0x08,0x02,0x2e,0x06,0x00,0x40,0x14,0x03,0x00,0x04,0x24,0x14,0x00,0xbf,0x8f, +0x10,0x00,0xb0,0x8f,0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27, +0x21,0x15,0x00,0x0c,0x00,0x00,0x00,0x00,0xf8,0xff,0x40,0x10,0x21,0x28,0x40,0x00, +0x0c,0x00,0x50,0xac,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0xa0,0x00, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x10,0x00,0x83,0x8c,0x02,0x80,0x02,0x3c, +0x80,0x41,0x42,0x24,0xc0,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x65,0x8c, +0x02,0x80,0x07,0x3c,0x02,0x80,0x08,0x3c,0x00,0x00,0x85,0xac,0x04,0x00,0xa4,0xac, +0x04,0x00,0x83,0xac,0x58,0x44,0xe5,0x8c,0x00,0x00,0x00,0x00,0x05,0x00,0xa0,0x10, +0x00,0x00,0x64,0xac,0x44,0x44,0x02,0x8d,0x58,0x44,0xe0,0xac,0x25,0x10,0x45,0x00, +0x44,0x44,0x02,0xad,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x02,0x80,0x02,0x3c,0x7c,0x3f,0x43,0x8c,0xff,0x00,0xa5,0x30,0x25,0xb0,0x02,0x3c, +0x42,0x18,0x03,0x00,0x21,0x30,0xa2,0x00,0x01,0x00,0x63,0x30,0x01,0x00,0x02,0x24, +0x10,0x00,0xa7,0x2c,0x04,0x00,0x62,0x10,0xff,0x00,0x84,0x30,0x60,0x01,0xc4,0xa0, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,0x10,0x00,0xa2,0x34, +0xfa,0xff,0xe0,0x10,0x21,0x40,0x43,0x00,0x60,0x01,0xc4,0xa0,0x60,0x01,0x04,0xa1, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x84,0x30,0x01,0x00,0x03,0x24, +0x10,0x00,0x02,0x3c,0x04,0x18,0x83,0x00,0xf0,0x70,0x42,0x34,0x15,0x00,0x84,0x2c, +0x06,0x00,0x80,0x10,0x24,0x28,0x62,0x00,0x0f,0x00,0x63,0x30,0x04,0x00,0xa0,0x14, +0x01,0x00,0x02,0x24,0x02,0x00,0x60,0x14,0x02,0x00,0x02,0x24,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xc0,0x40,0x04,0x00,0x21,0x18,0x04,0x01, +0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,0x80,0x18,0x03,0x00, +0x78,0x1b,0x42,0x24,0x21,0x18,0x62,0x00,0x8c,0x11,0x66,0x8c,0x21,0x38,0x60,0x00, +0x92,0x11,0x60,0xa0,0x93,0x11,0x60,0xa0,0x1c,0x00,0x05,0x24,0xa7,0x15,0x00,0x08, +0x01,0x00,0x03,0x24,0x08,0x00,0xa0,0x04,0x21,0x10,0x04,0x01,0x04,0x10,0xa3,0x00, +0x24,0x10,0xc2,0x00,0xfb,0xff,0x40,0x10,0xff,0xff,0xa5,0x24,0x01,0x00,0xa5,0x24, +0x92,0x11,0xe5,0xa0,0x21,0x10,0x04,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00, +0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x78,0x1b,0x63,0x24,0x21,0x18,0x43,0x00, +0x8c,0x11,0x66,0x8c,0x21,0x28,0x00,0x00,0xbb,0x15,0x00,0x08,0x01,0x00,0x07,0x24, +0x1d,0x00,0xa2,0x28,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x04,0x10,0xa7,0x00, +0x24,0x10,0xc2,0x00,0xfa,0xff,0x40,0x10,0x01,0x00,0xa5,0x24,0xff,0xff,0xa5,0x24, +0x08,0x00,0xe0,0x03,0x93,0x11,0x65,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf, +0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,0x80,0x80,0x10,0x00,0x21,0x80,0x04,0x02, +0x02,0x80,0x02,0x3c,0x78,0x1b,0x42,0x24,0x80,0x80,0x10,0x00,0x20,0x00,0xbf,0xaf, +0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x21,0x80,0x02,0x02,0x14,0x00,0xb1,0xaf, +0x90,0x11,0x03,0x8e,0x25,0xb0,0x02,0x3c,0x80,0x01,0x53,0x34,0x07,0x00,0x63,0x30, +0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x71,0x92,0x88,0x11,0x05,0x8e, +0x84,0x01,0x62,0x8c,0x21,0x90,0x80,0x00,0xff,0x00,0x31,0x32,0x24,0x10,0x45,0x00, +0x96,0x15,0x00,0x0c,0x8c,0x11,0x02,0xae,0x92,0x11,0x04,0x92,0x70,0x15,0x00,0x0c, +0xff,0x00,0x45,0x32,0x92,0x11,0x04,0x92,0x86,0x15,0x00,0x0c,0x00,0x00,0x00,0x00, +0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x88,0x62,0x00,0x00,0x00,0x71,0xa2, +0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xff,0xff,0x84,0x30, +0x00,0x02,0x82,0x30,0x07,0x00,0x03,0x24,0x0d,0x00,0x40,0x14,0x0b,0x00,0x84,0x30, +0x0c,0x00,0x82,0x2c,0x0a,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c, +0x80,0x10,0x04,0x00,0xe0,0xaf,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c, +0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x03,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x06,0x00,0x03,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x05,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x04,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x03,0x00,0x03,0x24, +0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x02,0x00,0x03,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x60,0x00,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x21,0x18,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x90,0xff,0xbd,0x27, +0x02,0x80,0x02,0x3c,0x68,0x00,0xbe,0xaf,0x64,0x00,0xb7,0xaf,0x60,0x00,0xb6,0xaf, +0x5c,0x00,0xb5,0xaf,0x54,0x00,0xb3,0xaf,0x50,0x00,0xb2,0xaf,0x6c,0x00,0xbf,0xaf, +0x58,0x00,0xb4,0xaf,0x4c,0x00,0xb1,0xaf,0x48,0x00,0xb0,0xaf,0x10,0xb0,0x42,0x24, +0x00,0x00,0x54,0x8c,0x08,0x00,0x03,0x24,0x10,0x00,0xa3,0xaf,0x21,0x98,0x00,0x00, +0x21,0xa8,0x00,0x00,0x21,0xb8,0x00,0x00,0x21,0xf0,0x00,0x00,0x14,0x00,0xa0,0xaf, +0x18,0x00,0xa0,0xaf,0x1c,0x00,0xa0,0xaf,0x20,0x00,0xa0,0xaf,0x21,0xb0,0x00,0x00, +0x24,0x00,0xa0,0xaf,0x28,0x00,0xa0,0xaf,0x2c,0x00,0xa0,0xaf,0x30,0x00,0xa0,0xaf, +0x34,0x00,0xa0,0xaf,0x38,0x00,0xa0,0xaf,0x3c,0x00,0xa0,0xaf,0x40,0x00,0xa0,0xaf, +0x21,0x90,0x80,0x02,0x90,0x11,0x42,0x8e,0x00,0x00,0x00,0x00,0x02,0x13,0x02,0x00, +0x01,0x00,0x42,0x30,0x6c,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,0x21,0x10,0x62,0x02, +0x60,0x01,0x44,0x90,0x78,0x11,0x43,0x8e,0x74,0x11,0x46,0x8e,0xff,0x00,0x91,0x30, +0x02,0x80,0x04,0x3c,0x78,0x1b,0x84,0x24,0x21,0x10,0x24,0x02,0x77,0x04,0x44,0x90, +0x5a,0x04,0x45,0x90,0x5c,0x11,0x47,0x8e,0x18,0x00,0x64,0x00,0x12,0x18,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xc5,0x00,0x12,0x30,0x00,0x00, +0x21,0x30,0xc3,0x00,0x2b,0x10,0xe6,0x00,0x25,0x01,0x40,0x14,0x23,0x10,0xe6,0x00, +0x5c,0x11,0x42,0xae,0x78,0x11,0x44,0x8e,0x74,0x11,0x47,0x8e,0x60,0x11,0x48,0x8e, +0x64,0x11,0x45,0x8e,0x6c,0x11,0x46,0x8e,0x70,0x11,0x43,0x8e,0x21,0x38,0xe4,0x00, +0x02,0x80,0x04,0x3c,0x78,0x1b,0x84,0x24,0x21,0x10,0x24,0x02,0x21,0x40,0x05,0x01, +0x21,0x30,0xc3,0x00,0xce,0x04,0x42,0x90,0x5c,0x11,0x4a,0x8e,0x0c,0x00,0xe0,0x10, +0x21,0x48,0x00,0x00,0x2b,0x48,0x47,0x00,0x0b,0x00,0x20,0x15,0x02,0x80,0x02,0x3c, +0x07,0x00,0x22,0x2e,0x93,0x01,0x40,0x14,0xc0,0x10,0x07,0x00,0x0c,0x00,0x02,0x24, +0x8f,0x01,0x22,0x12,0x0d,0x00,0x02,0x24,0x8e,0x01,0x22,0x12,0xc0,0x10,0x07,0x00, +0x81,0x00,0x20,0x11,0x02,0x80,0x02,0x3c,0x78,0x1b,0x42,0x24,0x80,0x18,0x11,0x00, +0x21,0x18,0x62,0x00,0x21,0x20,0x51,0x02,0xce,0x11,0x85,0x90,0xf8,0x04,0x62,0x8c, +0x00,0x00,0x00,0x00,0x04,0x10,0xa2,0x00,0x2b,0x10,0x4a,0x00,0x76,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0xec,0x11,0x42,0x8e,0x01,0x00,0x07,0x24,0x04,0x18,0x27,0x02, +0x24,0x10,0x43,0x00,0x04,0x01,0x40,0x10,0x1c,0x00,0x22,0x2e,0x21,0x28,0x51,0x02, +0x94,0x11,0xa6,0x90,0xce,0x11,0xa2,0x90,0x0a,0x00,0x04,0x24,0xff,0x00,0xc3,0x30, +0x04,0x20,0x44,0x00,0x2a,0x18,0x64,0x00,0xfb,0x00,0x60,0x10,0x1c,0x00,0x22,0x2e, +0x01,0x00,0xc2,0x24,0xff,0x00,0x43,0x30,0x8c,0x01,0x64,0x10,0x94,0x11,0xa2,0xa0, +0x02,0x80,0x04,0x3c,0x78,0x1b,0x85,0x24,0x80,0x10,0x11,0x00,0x21,0x10,0x45,0x00, +0x6c,0x05,0x44,0x8c,0xf8,0x04,0x43,0x8c,0x21,0x30,0xc5,0x02,0x40,0x10,0x04,0x00, +0x21,0x10,0x44,0x00,0x21,0x18,0x62,0x00,0x82,0x50,0x03,0x00,0x5c,0x11,0xca,0xac, +0xec,0x25,0xa3,0x8c,0xff,0xff,0x02,0x34,0x03,0x00,0x62,0x10,0x21,0x20,0x20,0x02, +0x70,0x15,0x00,0x0c,0xff,0x00,0x65,0x32,0x86,0x15,0x00,0x0c,0x21,0x20,0x20,0x02, +0x10,0x00,0xa4,0x8f,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x20,0x62,0x00, +0xbc,0x00,0x60,0x12,0x10,0x00,0xa4,0xaf,0x02,0x80,0x03,0x3c,0x78,0x1b,0x62,0x24, +0x21,0x10,0xa2,0x02,0x70,0x11,0x40,0xac,0x74,0x11,0x40,0xac,0x78,0x11,0x40,0xac, +0x60,0x11,0x40,0xac,0x64,0x11,0x40,0xac,0x68,0x11,0x40,0xac,0x6c,0x11,0x40,0xac, +0x40,0x00,0xa4,0x8f,0x3c,0x00,0xa2,0x8f,0x01,0x00,0x73,0x26,0x94,0x00,0x84,0x24, +0x94,0x00,0x42,0x24,0x40,0x00,0xa4,0xaf,0x3c,0x00,0xa2,0xaf,0x38,0x00,0xa4,0x8f, +0x34,0x00,0xa2,0x8f,0x20,0x00,0x63,0x2a,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24, +0x38,0x00,0xa4,0xaf,0x34,0x00,0xa2,0xaf,0x30,0x00,0xa4,0x8f,0x2c,0x00,0xa2,0x8f, +0x94,0x00,0x52,0x26,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x30,0x00,0xa4,0xaf, +0x2c,0x00,0xa2,0xaf,0x28,0x00,0xa4,0x8f,0x24,0x00,0xa2,0x8f,0x94,0x00,0xd6,0x26, +0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24,0x28,0x00,0xa4,0xaf,0x24,0x00,0xa2,0xaf, +0x20,0x00,0xa4,0x8f,0x1c,0x00,0xa2,0x8f,0x94,0x00,0xde,0x27,0x94,0x00,0x84,0x24, +0x94,0x00,0x42,0x24,0x20,0x00,0xa4,0xaf,0x1c,0x00,0xa2,0xaf,0x18,0x00,0xa4,0x8f, +0x14,0x00,0xa2,0x8f,0x94,0x00,0x94,0x26,0x94,0x00,0x84,0x24,0x94,0x00,0x42,0x24, +0x18,0x00,0xa4,0xaf,0x14,0x00,0xa2,0xaf,0x94,0x00,0xf7,0x26,0x59,0xff,0x60,0x14, +0x94,0x00,0xb5,0x26,0x10,0x00,0xa3,0x8f,0x6c,0x00,0xbf,0x8f,0x68,0x00,0xbe,0x8f, +0x64,0x00,0xb7,0x8f,0x60,0x00,0xb6,0x8f,0x5c,0x00,0xb5,0x8f,0x58,0x00,0xb4,0x8f, +0x54,0x00,0xb3,0x8f,0x50,0x00,0xb2,0x8f,0x4c,0x00,0xb1,0x8f,0x48,0x00,0xb0,0x8f, +0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x70,0x00,0xbd,0x27,0x00,0x00,0x43,0xa0, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x87,0x00,0xe0,0x10,0x00,0x00,0x00,0x00, +0x87,0x00,0x20,0x15,0x02,0x80,0x03,0x3c,0x40,0x10,0x07,0x00,0x21,0x10,0x47,0x00, +0x82,0x10,0x02,0x00,0x2b,0x10,0x46,0x00,0xa7,0xff,0x40,0x10,0x00,0x00,0x00,0x00, +0x20,0x00,0xa2,0x8f,0x02,0x80,0x04,0x3c,0x78,0x1b,0x88,0x24,0x21,0x20,0x48,0x00, +0x21,0x30,0x91,0x00,0xec,0x11,0x83,0x8c,0x01,0x00,0x05,0x24,0x04,0x10,0x25,0x02, +0xb1,0x11,0xc7,0x90,0x27,0x10,0x02,0x00,0x24,0x18,0x62,0x00,0xec,0x11,0x83,0xac, +0x09,0x00,0xe5,0x10,0x94,0x11,0xc0,0xa0,0x1c,0x00,0xa3,0x8f,0x21,0x38,0x00,0x00, +0x21,0x20,0x68,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,0x1d,0x00,0xe2,0x28, +0xfc,0xff,0x40,0x14,0xce,0x11,0x60,0xa0,0x02,0x80,0x04,0x3c,0x78,0x1b,0x83,0x24, +0x18,0x00,0xa4,0x8f,0x21,0x50,0x60,0x00,0x21,0x38,0x00,0x00,0x21,0x10,0x83,0x00, +0x21,0x10,0x51,0x00,0xb1,0x11,0x40,0xa0,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c, +0x70,0xae,0x49,0x24,0xfc,0xad,0x68,0x24,0x80,0x18,0x07,0x00,0x21,0x10,0x69,0x00, +0x21,0x20,0x68,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0xe7,0x24, +0x21,0x18,0x6a,0x00,0x1d,0x00,0xe2,0x28,0xf8,0x04,0x65,0xac,0xf6,0xff,0x40,0x14, +0x6c,0x05,0x66,0xac,0x15,0x00,0x20,0x12,0x02,0x80,0x05,0x3c,0x93,0x11,0x82,0x92, +0xff,0xff,0x27,0x26,0x2a,0x10,0xe2,0x00,0x10,0x00,0x40,0x14,0x02,0x80,0x03,0x3c, +0x14,0x00,0xa4,0x8f,0x78,0x1b,0x62,0x24,0x21,0x10,0x82,0x00,0x93,0x11,0x45,0x90, +0x8c,0x11,0x44,0x8c,0x01,0x00,0x06,0x24,0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00, +0x06,0x01,0x43,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0xe7,0x24,0x2a,0x10,0xe5,0x00, +0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x02,0x80,0x05,0x3c,0x56,0x43,0xa3,0x90, +0x22,0x00,0x02,0x24,0xe8,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,0x02,0x80,0x04,0x3c, +0x78,0x1b,0x83,0x24,0x80,0x10,0x11,0x00,0x21,0x10,0x43,0x00,0x6c,0x05,0x44,0x8c, +0xf8,0x04,0x43,0x8c,0x56,0x43,0xa5,0x90,0x40,0x10,0x04,0x00,0x21,0x10,0x44,0x00, +0x21,0x18,0x62,0x00,0x22,0x00,0x02,0x24,0xd6,0x00,0xa2,0x10,0x82,0x50,0x03,0x00, +0xec,0x11,0x83,0x8e,0x01,0x00,0x02,0x24,0x04,0x10,0x22,0x02,0x25,0x18,0x62,0x00, +0xec,0x11,0x83,0xae,0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24,0x21,0x10,0xe3,0x02, +0x5c,0x11,0x4a,0xac,0xec,0x25,0x64,0x8c,0xff,0xff,0x02,0x34,0x44,0xff,0x82,0x14, +0x21,0x20,0x20,0x02,0x86,0x15,0x00,0x0c,0x21,0x20,0x20,0x02,0x10,0x00,0xa4,0x8f, +0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x20,0x62,0x00,0x46,0xff,0x60,0x16, +0x10,0x00,0xa4,0xaf,0x02,0x80,0x02,0x3c,0x78,0x1b,0x50,0x24,0x64,0x11,0x05,0x96, +0x60,0x11,0x02,0x96,0x25,0xb0,0x11,0x3c,0x00,0x2c,0x05,0x00,0x21,0x28,0x45,0x00, +0x10,0x50,0x00,0x0c,0x68,0x0c,0x24,0x36,0x70,0x11,0x02,0x8e,0x6c,0x11,0x05,0x8e, +0x68,0x11,0x03,0x96,0x6c,0x0c,0x24,0x36,0x21,0x28,0xa2,0x00,0x00,0x2c,0x05,0x00, +0x10,0x50,0x00,0x0c,0x21,0x28,0x65,0x00,0xaf,0x16,0x00,0x08,0x02,0x80,0x03,0x3c, +0x59,0x16,0x00,0x08,0x5c,0x11,0x40,0xae,0x27,0xff,0x20,0x11,0x02,0x80,0x03,0x3c, +0x78,0x1b,0x62,0x24,0x80,0x18,0x11,0x00,0x21,0x18,0x62,0x00,0x6c,0x05,0x64,0x8c, +0x00,0x00,0x00,0x00,0x2b,0x20,0x44,0x01,0x1f,0xff,0x80,0x10,0x00,0x00,0x00,0x00, +0x00,0x17,0x00,0x08,0x00,0x00,0x00,0x00,0x0a,0xff,0x40,0x10,0x02,0x80,0x04,0x3c, +0x21,0x20,0x51,0x02,0xb1,0x11,0x83,0x90,0x01,0x00,0x02,0x24,0x78,0x00,0x62,0x10, +0x02,0x80,0x02,0x3c,0x40,0x00,0xa3,0x8f,0x78,0x1b,0x42,0x24,0x21,0x20,0x62,0x00, +0x21,0x38,0x00,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,0x1d,0x00,0xe2,0x28, +0xfc,0xff,0x40,0x14,0xce,0x11,0x60,0xa0,0x3c,0x00,0xa2,0x8f,0x02,0x80,0x04,0x3c, +0x78,0x1b,0x85,0x24,0x21,0x30,0x45,0x00,0xec,0x11,0xc2,0x8c,0x01,0x00,0x03,0x24, +0x04,0x18,0x23,0x02,0x27,0x18,0x03,0x00,0x21,0x20,0xd1,0x00,0x24,0x10,0x43,0x00, +0xb1,0x11,0x80,0xa0,0xec,0x11,0xc2,0xac,0x12,0x00,0x20,0x16,0x94,0x11,0x80,0xa0, +0x92,0x11,0xc2,0x90,0x00,0x00,0x00,0x00,0x0e,0x00,0x40,0x10,0x01,0x00,0x07,0x24, +0x38,0x00,0xa3,0x8f,0x01,0x00,0x06,0x24,0x21,0x10,0x65,0x00,0x92,0x11,0x44,0x90, +0x8c,0x11,0x45,0x8c,0x04,0x18,0xe6,0x00,0x24,0x10,0xa3,0x00,0x8d,0x00,0x43,0x10, +0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,0x2a,0x10,0x87,0x00,0xfa,0xff,0x40,0x10, +0x04,0x18,0xe6,0x00,0x02,0x80,0x02,0x3c,0x78,0x1b,0x44,0x24,0x34,0x00,0xa2,0x8f, +0x01,0x00,0x27,0x26,0x21,0x18,0x44,0x00,0x92,0x11,0x62,0x90,0x00,0x00,0x00,0x00, +0x2a,0x10,0x47,0x00,0x0f,0x00,0x40,0x14,0x02,0x80,0x05,0x3c,0x30,0x00,0xa3,0x8f, +0x01,0x00,0x06,0x24,0x21,0x10,0x64,0x00,0x92,0x11,0x45,0x90,0x8c,0x11,0x44,0x8c, +0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00,0x73,0x00,0x43,0x10,0x00,0x00,0x00,0x00, +0x01,0x00,0xe7,0x24,0x2a,0x10,0xa7,0x00,0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00, +0x02,0x80,0x05,0x3c,0x56,0x43,0xa3,0x90,0x22,0x00,0x02,0x24,0x3e,0x00,0x62,0x10, +0xee,0xff,0x22,0x26,0x56,0x43,0xa3,0x90,0x22,0x00,0x02,0x24,0xbd,0xfe,0x62,0x14, +0x02,0x80,0x04,0x3c,0x28,0x00,0xa2,0x8f,0x78,0x1b,0x86,0x24,0x21,0x20,0x46,0x00, +0x90,0x11,0x85,0x8c,0x01,0x00,0x03,0x24,0x42,0x13,0x05,0x00,0x07,0x00,0x42,0x30, +0xb3,0xfe,0x43,0x10,0x14,0x00,0x22,0x2e,0xb1,0xfe,0x40,0x14,0x1c,0x00,0x22,0x2e, +0xaf,0xfe,0x40,0x10,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,0x24,0x10,0xa2,0x00, +0x00,0x20,0x42,0x34,0x90,0x11,0x82,0xac,0x93,0x11,0x83,0x90,0xff,0xff,0x27,0x26, +0x2a,0x18,0xe3,0x00,0xa6,0xfe,0x60,0x14,0x00,0x00,0x00,0x00,0x24,0x00,0xa3,0x8f, +0x00,0x00,0x00,0x00,0x21,0x10,0x66,0x00,0x93,0x11,0x45,0x90,0x8c,0x11,0x44,0x8c, +0xf9,0x17,0x00,0x08,0x01,0x00,0x06,0x24,0x2a,0x10,0xe5,0x00,0x9c,0xfe,0x40,0x14, +0x00,0x00,0x00,0x00,0x04,0x18,0xe6,0x00,0x24,0x10,0x83,0x00,0xfa,0xff,0x43,0x14, +0xff,0xff,0xe7,0x24,0x01,0x00,0xe7,0x24,0x94,0x16,0x00,0x08,0xff,0x00,0xf1,0x30, +0xc0,0x10,0x07,0x00,0x23,0x10,0x47,0x00,0xc2,0x10,0x02,0x00,0x2b,0x10,0x48,0x00, +0x7c,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0x74,0x16,0x00,0x08,0x00,0x00,0x00,0x00, +0x18,0x00,0x22,0x2e,0x17,0x00,0x40,0x14,0x05,0x00,0x22,0x2e,0xce,0x11,0x83,0x90, +0x00,0x00,0x00,0x00,0x05,0x00,0x62,0x2c,0x8b,0xff,0x40,0x10,0x01,0x00,0x62,0x24, +0x9a,0x17,0x00,0x08,0xce,0x11,0x82,0xa0,0xff,0x00,0x42,0x30,0x02,0x00,0x42,0x2c, +0xc0,0xff,0x40,0x10,0x02,0x80,0x04,0x3c,0x2c,0x00,0xa3,0x8f,0x78,0x1b,0x82,0x24, +0x21,0x10,0x62,0x00,0x8c,0x11,0x43,0x8c,0x00,0x01,0x04,0x3c,0x18,0x00,0x02,0x24, +0x24,0x18,0x64,0x00,0xd5,0x17,0x00,0x08,0x0b,0x88,0x43,0x00,0x94,0x16,0x00,0x08, +0xb1,0x11,0xa7,0xa0,0x04,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xce,0x11,0x83,0x90, +0x0e,0x18,0x00,0x08,0x03,0x00,0x62,0x2c,0xce,0x11,0x83,0x90,0x0e,0x18,0x00,0x08, +0x04,0x00,0x62,0x2c,0x13,0x00,0x02,0x24,0x29,0xff,0x22,0x16,0x02,0x80,0x02,0x3c, +0x5b,0x17,0x00,0x08,0x78,0x1b,0x43,0x24,0x78,0x1b,0x62,0x24,0x21,0x20,0xc2,0x03, +0x90,0x11,0x83,0x8c,0x00,0x00,0x00,0x00,0x42,0x13,0x03,0x00,0x07,0x00,0x42,0x30, +0x12,0xff,0x40,0x10,0x14,0x00,0x22,0x2e,0x10,0xff,0x40,0x10,0x0c,0x00,0x22,0x2e, +0x0e,0xff,0x40,0x14,0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,0x24,0x10,0x62,0x00, +0x47,0x17,0x00,0x08,0x90,0x11,0x82,0xac,0xff,0x00,0xf1,0x30,0xd1,0x17,0x00,0x08, +0x02,0x80,0x05,0x3c,0xb9,0x17,0x00,0x08,0xff,0x00,0xf1,0x30,0x42,0x17,0x00,0x08, +0xff,0x00,0xf1,0x30,0xa8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x38,0x00,0xb2,0xaf, +0x54,0x00,0xbf,0xaf,0x50,0x00,0xbe,0xaf,0x4c,0x00,0xb7,0xaf,0x48,0x00,0xb6,0xaf, +0x44,0x00,0xb5,0xaf,0x40,0x00,0xb4,0xaf,0x3c,0x00,0xb3,0xaf,0x34,0x00,0xb1,0xaf, +0x30,0x00,0xb0,0xaf,0x78,0x1b,0x46,0x24,0x71,0x25,0xc4,0x90,0x6c,0x25,0xc3,0x8c, +0x68,0x25,0xc2,0x8c,0x21,0x90,0x64,0x00,0x2b,0x10,0x42,0x02,0x7e,0x00,0x40,0x10, +0x21,0x88,0xc0,0x00,0x02,0x80,0x1e,0x3c,0x02,0x80,0x17,0x3c,0x21,0xa8,0xc0,0x00, +0x21,0xb0,0xc0,0x00,0x64,0x18,0x00,0x08,0x01,0x00,0x14,0x24,0x68,0x25,0xc2,0x8e, +0x10,0x00,0x52,0x26,0x2b,0x10,0x42,0x02,0x73,0x00,0x40,0x10,0x21,0x88,0xc0,0x02, +0x71,0x25,0x22,0x92,0xff,0xff,0x45,0x32,0x25,0x28,0xb7,0x00,0x10,0x00,0x42,0x24, +0x71,0x25,0x22,0xa2,0x54,0x3f,0xc4,0x27,0x46,0x46,0x00,0x0c,0x10,0x00,0x06,0x24, +0x04,0x24,0x23,0x8e,0x00,0x00,0x00,0x00,0x42,0x18,0x03,0x00,0x01,0x00,0x63,0x30, +0x71,0x00,0x74,0x10,0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24,0xe0,0x23,0x62,0x8c, +0x00,0x00,0x00,0x00,0x42,0x84,0x02,0x00,0x1f,0x00,0x10,0x32,0xc0,0x48,0x10,0x00, +0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x55,0x00,0x90,0x11,0x45,0x8c,0x00,0x00,0x00,0x00,0x02,0x1b,0x05,0x00, +0x01,0x00,0x63,0x30,0xdd,0xff,0x60,0x10,0x21,0x30,0xa0,0x02,0x25,0xb0,0x02,0x3c, +0x21,0x40,0x02,0x02,0xdc,0x23,0xa7,0x8e,0x04,0x24,0xa2,0x8e,0x60,0x01,0x03,0x91, +0x82,0x25,0x07,0x00,0x01,0x00,0x42,0x30,0xff,0x00,0x6b,0x30,0x9a,0x00,0x54,0x10, +0x3f,0x00,0x8a,0x30,0x02,0x80,0x04,0x3c,0x14,0xb0,0x84,0x24,0x00,0x00,0x86,0x8c, +0x04,0x00,0x04,0x24,0xdc,0x23,0xc3,0x8c,0x00,0x00,0x00,0x00,0x82,0x15,0x03,0x00, +0x3f,0x00,0x42,0x30,0x05,0x00,0x42,0x28,0x0a,0x00,0x60,0x04,0x0a,0x50,0x82,0x00, +0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x46,0x00,0x7c,0x11,0x43,0x8c,0x04,0x00,0x0a,0x24,0x01,0x00,0x63,0x24, +0x7c,0x11,0x43,0xac,0xe0,0x23,0xc2,0x8c,0x00,0x00,0x00,0x00,0x02,0x13,0x02,0x00, +0x1f,0x00,0x42,0x30,0x08,0x00,0x42,0x28,0xb8,0xff,0x40,0x10,0x00,0x00,0x00,0x00, +0xdc,0x23,0xc2,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0xb3,0xff,0x4b,0x14, +0x00,0x00,0x00,0x00,0x9f,0x00,0x40,0x11,0x21,0x10,0x30,0x01,0xa8,0x00,0x54,0x11, +0x80,0x10,0x02,0x00,0x02,0x00,0x02,0x24,0xb0,0x00,0x42,0x11,0x21,0x10,0x30,0x01, +0x03,0x00,0x02,0x24,0xb8,0x00,0x42,0x11,0x21,0x10,0x30,0x01,0xc0,0x00,0x44,0x11, +0x21,0x10,0x30,0x01,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00, +0x80,0x10,0x02,0x00,0x21,0x28,0x46,0x00,0x80,0x11,0xa3,0x8c,0x21,0x10,0x66,0x01, +0x94,0x04,0x44,0x90,0x02,0x19,0x03,0x00,0x2b,0x18,0x64,0x00,0xc8,0x00,0x60,0x14, +0x00,0x00,0x00,0x00,0x74,0x11,0xa3,0x8c,0x80,0x10,0x0b,0x00,0x21,0x10,0x4b,0x00, +0x01,0x00,0x63,0x24,0x21,0x10,0x46,0x00,0x74,0x11,0xa3,0xac,0x21,0x10,0x4a,0x00, +0x38,0x03,0x44,0x90,0x5c,0x11,0xa3,0x8c,0x00,0x00,0x00,0x00,0x21,0x18,0x64,0x00, +0x5c,0x11,0xa3,0xac,0x68,0x25,0xc2,0x8e,0x10,0x00,0x52,0x26,0x2b,0x10,0x42,0x02, +0x8f,0xff,0x40,0x14,0x21,0x88,0xc0,0x02,0x54,0x00,0xbf,0x8f,0x50,0x00,0xbe,0x8f, +0x4c,0x00,0xb7,0x8f,0x48,0x00,0xb6,0x8f,0x44,0x00,0xb5,0x8f,0x40,0x00,0xb4,0x8f, +0x3c,0x00,0xb3,0x8f,0x38,0x00,0xb2,0x8f,0x34,0x00,0xb1,0x8f,0x30,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x58,0x00,0xbd,0x27,0xe0,0x23,0x22,0x8e,0x00,0x00,0x00,0x00, +0x42,0x14,0x02,0x00,0x10,0x00,0x43,0x30,0x90,0xff,0x60,0x10,0x0f,0x00,0x50,0x30, +0x39,0x15,0x00,0x0c,0x48,0x00,0x04,0x24,0x74,0xff,0x40,0x10,0x21,0x98,0x40,0x00, +0x14,0x00,0x02,0x24,0x28,0x00,0x04,0x24,0x14,0x00,0x62,0xae,0x0c,0x00,0x64,0xae, +0x14,0x00,0xa3,0x8f,0xe0,0xff,0x04,0x24,0x08,0x00,0x07,0x24,0x80,0x00,0x63,0x34, +0x14,0x00,0xa3,0xaf,0xe0,0x23,0x26,0x8e,0x24,0x18,0x64,0x00,0xff,0xe0,0x04,0x24, +0x42,0x14,0x06,0x00,0x1f,0x00,0x42,0x30,0x25,0x18,0x62,0x00,0x14,0x00,0xa3,0xaf, +0xdc,0x23,0x25,0x8e,0x24,0x18,0x64,0x00,0x02,0x23,0x06,0x00,0x82,0x13,0x05,0x00, +0x00,0x1f,0x42,0x30,0x25,0x18,0x62,0x00,0xff,0xff,0x02,0x3c,0xff,0x7f,0x42,0x34, +0xc2,0x2f,0x05,0x00,0x24,0x18,0x62,0x00,0xc0,0x2b,0x05,0x00,0x0f,0x00,0x02,0x3c, +0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x35,0x06,0x00, +0xf0,0xff,0x02,0x3c,0x25,0x18,0x66,0x00,0xff,0xff,0x42,0x34,0x0f,0x00,0x84,0x30, +0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00,0x02,0x80,0x04,0x3c, +0x10,0x00,0xa5,0x27,0xa8,0x3f,0x84,0x24,0x02,0x00,0x06,0x24,0x04,0x00,0x02,0x24, +0x11,0x00,0xa7,0xa3,0x14,0x00,0xa3,0xaf,0x52,0x46,0x00,0x0c,0x10,0x00,0xa2,0xa3, +0x08,0x00,0x64,0x96,0x10,0x00,0xa5,0x27,0x02,0x00,0x06,0x24,0x25,0x20,0x97,0x00, +0x52,0x46,0x00,0x0c,0x20,0x00,0x84,0x24,0x59,0x0a,0x00,0x0c,0x21,0x20,0x60,0x02, +0x78,0x18,0x00,0x08,0xc0,0x48,0x10,0x00,0x02,0x12,0x05,0x00,0x01,0x00,0x42,0x30, +0x14,0x00,0x54,0x10,0xc2,0x10,0x05,0x00,0x01,0x00,0x42,0x30,0x76,0x00,0x54,0x10, +0x00,0x00,0x00,0x00,0x10,0x24,0xa2,0x96,0x60,0x01,0x03,0x91,0xc2,0x27,0x07,0x00, +0x21,0x10,0x42,0x01,0x2c,0x24,0xa3,0xa2,0x13,0x00,0x80,0x10,0x10,0x24,0xa2,0xa6, +0x59,0xff,0x94,0x14,0x02,0x80,0x04,0x3c,0x0c,0x24,0xa2,0x96,0x16,0x24,0xa3,0x96, +0x01,0x00,0x42,0x24,0x01,0x00,0x63,0x24,0x0c,0x24,0xa2,0xa6,0x8e,0x18,0x00,0x08, +0x16,0x24,0xa3,0xa6,0x5d,0x00,0xe0,0x04,0x00,0x00,0x00,0x00,0x0e,0x24,0xa3,0x96, +0x1a,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x1a,0x24,0xa2,0xa6, +0x8d,0x18,0x00,0x08,0x0e,0x24,0xc3,0xa4,0x0e,0x24,0xa3,0x96,0x1c,0x24,0xa2,0x96, +0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x1c,0x24,0xa2,0xa6,0x8d,0x18,0x00,0x08, +0x0e,0x24,0xc3,0xa4,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x46,0x00,0x60,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24, +0x5c,0xff,0x54,0x15,0x60,0x11,0x43,0xac,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00, +0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x64,0x11,0x43,0x8c, +0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x64,0x11,0x43,0xac,0x02,0x00,0x02,0x24, +0x54,0xff,0x42,0x15,0x03,0x00,0x02,0x24,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00, +0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x68,0x11,0x43,0x8c, +0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x68,0x11,0x43,0xac,0x03,0x00,0x02,0x24, +0x4a,0xff,0x42,0x15,0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00,0x6c,0x11,0x43,0x8c,0x00,0x00,0x00,0x00, +0x01,0x00,0x63,0x24,0x43,0xff,0x44,0x15,0x6c,0x11,0x43,0xac,0x21,0x10,0x30,0x01, +0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x46,0x00, +0x70,0x11,0x43,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x24,0x70,0x11,0x43,0xac, +0x21,0x10,0x30,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x50,0x00,0x80,0x10,0x02,0x00, +0x21,0x28,0x46,0x00,0x80,0x11,0xa3,0x8c,0x21,0x10,0x66,0x01,0x94,0x04,0x44,0x90, +0x02,0x19,0x03,0x00,0x2b,0x18,0x64,0x00,0x3a,0xff,0x60,0x10,0x00,0x00,0x00,0x00, +0x78,0x11,0xa3,0x8c,0x80,0x10,0x0b,0x00,0x02,0x80,0x04,0x3c,0x78,0x1b,0x84,0x24, +0x21,0x10,0x4b,0x00,0x01,0x00,0x63,0x24,0x21,0x10,0x44,0x00,0x78,0x11,0xa3,0xac, +0x21,0x10,0x4a,0x00,0xc9,0x03,0x44,0x90,0x5c,0x11,0xa3,0x8c,0x00,0x00,0x00,0x00, +0x21,0x18,0x64,0x00,0xd1,0x18,0x00,0x08,0x5c,0x11,0xa3,0xac,0x0c,0x24,0xa3,0x96, +0x14,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x14,0x24,0xa2,0xa6, +0x8d,0x18,0x00,0x08,0x0c,0x24,0xc3,0xa4,0x08,0x00,0xe0,0x04,0x00,0x00,0x00,0x00, +0x0e,0x24,0xa3,0x96,0x18,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24, +0x18,0x24,0xa2,0xa6,0x8d,0x18,0x00,0x08,0x0e,0x24,0xc3,0xa4,0x0c,0x24,0xa3,0x96, +0x12,0x24,0xa2,0x96,0x01,0x00,0x63,0x24,0x01,0x00,0x42,0x24,0x12,0x24,0xa2,0xa6, +0x8d,0x18,0x00,0x08,0x0c,0x24,0xc3,0xa4,0x02,0x80,0x0a,0x3c,0x78,0x1b,0x42,0x8d, +0xe8,0xff,0xbd,0x27,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30,0x11,0x00,0x40,0x14, +0x10,0x00,0xbf,0xaf,0x25,0xb0,0x05,0x3c,0x4c,0x00,0xa2,0x34,0x00,0x00,0x43,0x90, +0x78,0x1b,0x46,0x25,0xf9,0x0a,0xc2,0x90,0x03,0x00,0x67,0x30,0x09,0x00,0x47,0x10, +0x58,0x00,0xa2,0x34,0x00,0x00,0x44,0x8c,0x29,0xb0,0x03,0x3c,0x5c,0x00,0xa2,0x34, +0x00,0x00,0x64,0xac,0x00,0x00,0x44,0x8c,0x04,0x00,0x63,0x34,0xf9,0x0a,0xc7,0xa0, +0x00,0x00,0x64,0xac,0x78,0x1b,0x42,0x25,0xcb,0x02,0x43,0x90,0x25,0xb0,0x02,0x3c, +0x90,0x0c,0x42,0x34,0x0f,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x42,0x25,0xc9,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x91,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x78,0x1b,0x42,0x25,0xca,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,0x92,0x0c,0x63,0x34, +0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x78,0x1b,0x42,0x25, +0xc8,0x02,0x43,0x8c,0x25,0xb0,0x02,0x3c,0x93,0x0c,0x42,0x34,0x02,0x1f,0x03,0x00, +0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x78,0x1b,0x42,0x25, +0xea,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,0x98,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x2d,0x0a,0x46,0x34, +0xa2,0x0d,0x43,0x34,0xa4,0x0d,0x44,0x34,0xa6,0x0d,0x45,0x34,0xa8,0x0d,0x42,0x34, +0x00,0x00,0x67,0x94,0x00,0x00,0x88,0x94,0x00,0x00,0xa9,0x94,0x00,0x00,0x44,0x94, +0x00,0x00,0xc3,0x90,0x78,0x1b,0x42,0x25,0xe2,0x02,0x44,0xa4,0x40,0x00,0x63,0x34, +0xff,0x00,0x63,0x30,0x00,0x00,0xc3,0xa0,0xdc,0x02,0x47,0xa4,0xde,0x02,0x48,0xa4, +0xe0,0x02,0x49,0xa4,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x07,0x3c, +0x5b,0x0a,0xe2,0x34,0x00,0x00,0x44,0x90,0x78,0x1b,0x46,0x25,0x5c,0x0a,0xe2,0x34, +0x00,0x00,0x45,0x90,0xdc,0x02,0xc3,0x94,0xde,0x02,0xc2,0x94,0xe0,0x02,0xc9,0x94, +0xe2,0x02,0xc8,0x94,0xff,0x00,0x84,0x30,0x21,0x18,0x62,0x00,0x00,0x22,0x04,0x00, +0xff,0x00,0xa5,0x30,0x21,0x20,0x85,0x00,0x21,0x18,0x69,0x00,0xff,0xff,0x82,0x30, +0x21,0x18,0x68,0x00,0x21,0x18,0x62,0x00,0x64,0x0c,0xe7,0x34,0xff,0xff,0x42,0x30, +0xe4,0x02,0xc3,0xac,0x00,0x00,0xe2,0xa4,0xe8,0x02,0xc4,0xa4,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x42,0x8d,0x01,0x00,0x03,0x24,0x01,0x00,0x44,0x30, +0x07,0x00,0x83,0x10,0x78,0x1b,0x45,0x25,0x24,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00, +0x10,0x00,0xbf,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27, +0xe8,0x02,0xa2,0x8c,0x00,0x00,0x00,0x00,0x02,0x17,0x02,0x00,0x01,0x00,0x42,0x30, +0xf5,0xff,0x40,0x14,0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90, +0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,0x4e,0x00,0x64,0x10,0x00,0x00,0x00,0x00, +0x78,0x1b,0x45,0x25,0xea,0x02,0xa2,0x90,0x00,0x00,0x00,0x00,0x07,0x00,0x40,0x14, +0x78,0x1b,0x46,0x25,0x78,0x1b,0x42,0x8d,0x01,0x00,0x03,0x24,0x02,0x11,0x02,0x00, +0x03,0x00,0x42,0x30,0x49,0x00,0x43,0x10,0x3e,0x00,0x02,0x24,0xea,0x02,0xc3,0x90, +0xff,0x00,0x02,0x24,0xe0,0xff,0x62,0x14,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34, +0x00,0x00,0x45,0x90,0xcc,0x02,0xc4,0x94,0xe4,0x02,0xc7,0x8c,0x32,0x00,0x02,0x24, +0x20,0x00,0x03,0x24,0x7f,0x00,0xa5,0x30,0x2b,0x20,0xe4,0x00,0xd4,0x02,0xc2,0xa0, +0xd5,0x02,0xc3,0xa0,0x0c,0x00,0x80,0x14,0xff,0xff,0xa2,0x24,0xce,0x02,0xc2,0x94, +0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x00,0x09,0x00,0x40,0x14,0x78,0x1b,0x44,0x25, +0xd0,0x02,0xc2,0x94,0x00,0x00,0x00,0x00,0x2b,0x10,0xe2,0x00,0x02,0x00,0x40,0x10, +0x02,0x00,0xa2,0x24,0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30,0x78,0x1b,0x44,0x25, +0xd4,0x02,0x83,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x65,0x00,0x7e,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x21,0x28,0x60,0x00,0x78,0x1b,0x43,0x25,0xe4,0x02,0x62,0x8c, +0x00,0x00,0x00,0x00,0x11,0x27,0x42,0x2c,0x73,0x00,0x40,0x14,0x3a,0x00,0xa2,0x2c, +0x32,0x00,0x05,0x24,0x44,0x00,0x03,0x24,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34, +0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34,0x00,0x00,0x45,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x42,0x34, +0x00,0x00,0x45,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x3e,0x1a,0x00,0x08, +0x00,0x00,0x00,0x00,0xea,0x02,0xa2,0x90,0x00,0x00,0x00,0x00,0xb0,0xff,0x40,0x14, +0xff,0xff,0x02,0x24,0x50,0x1a,0x00,0x08,0xea,0x02,0xa2,0xa0,0x02,0x00,0xa4,0x90, +0xd4,0x02,0xa2,0xa0,0x1c,0x00,0x03,0x24,0x06,0x00,0x02,0x24,0x57,0x00,0x82,0x10, +0xd5,0x02,0xa3,0xa0,0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90, +0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,0x8f,0xff,0x60,0x10,0x78,0x1b,0x44,0x25, +0x80,0x11,0x83,0x8c,0xff,0xff,0x02,0x34,0x8b,0xff,0x62,0x10,0x00,0x00,0x00,0x00, +0xe4,0x02,0x83,0x8c,0x00,0x00,0x00,0x00,0xe9,0x03,0x62,0x2c,0x5c,0x00,0x40,0x14, +0x90,0x01,0x62,0x2c,0xd6,0x02,0x83,0x90,0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00, +0x03,0x16,0x02,0x00,0xfe,0xff,0x42,0x24,0xfc,0xff,0x42,0x28,0x02,0x00,0x40,0x10, +0xfe,0xff,0x62,0x24,0xfc,0xff,0x02,0x24,0xd6,0x02,0x82,0xa0,0x78,0x1b,0x44,0x25, +0x80,0x11,0x82,0x8c,0xd6,0x02,0x83,0x90,0xd2,0x02,0x85,0x90,0x02,0x11,0x02,0x00, +0x7f,0x00,0x42,0x30,0x0a,0x00,0x47,0x24,0x23,0x18,0xe3,0x00,0x00,0x3e,0x03,0x00, +0x03,0x3e,0x07,0x00,0xff,0x00,0xa2,0x30,0x2a,0x10,0x47,0x00,0x3e,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x00,0x3e,0x05,0x00,0x03,0x3e,0x07,0x00,0x78,0x1b,0x43,0x25, +0xe4,0x02,0x62,0x8c,0x00,0x00,0x00,0x00,0x11,0x27,0x42,0x2c,0x32,0x00,0x40,0x14, +0x3a,0x00,0xe2,0x28,0x32,0x00,0xe2,0x28,0x2f,0x00,0x40,0x10,0x3a,0x00,0xe2,0x28, +0x32,0x00,0x07,0x24,0x44,0x00,0x03,0x24,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34, +0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c,0x50,0x0c,0x42,0x34,0xff,0x00,0xe4,0x30, +0x00,0x00,0x44,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c, +0x58,0x0c,0x42,0x34,0x00,0x00,0x44,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x3e,0x1a,0x00,0x08,0x00,0x00,0x00,0x00,0x8f,0xff,0x40,0x10,0x48,0x00,0x03,0x24, +0x86,0x1a,0x00,0x08,0x44,0x00,0x03,0x24,0xd5,0x02,0x83,0x90,0x00,0x00,0x00,0x00, +0x2b,0x10,0xa3,0x00,0x7e,0x1a,0x00,0x08,0x0b,0x28,0x62,0x00,0x25,0xb0,0x02,0x3c, +0x00,0x08,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x27,0x18,0x03,0x00, +0x01,0x00,0x63,0x30,0xa4,0xff,0x60,0x10,0x25,0xb0,0x02,0x3c,0x36,0x00,0x02,0x24, +0xa9,0x1a,0x00,0x08,0xd2,0x02,0xa2,0xa0,0xd3,0xff,0x40,0x10,0x48,0x00,0x03,0x24, +0xde,0x1a,0x00,0x08,0x44,0x00,0x03,0x24,0xd3,0x02,0x83,0x80,0x00,0x00,0x00,0x00, +0xff,0x00,0x62,0x30,0x2a,0x10,0xe2,0x00,0xd3,0x1a,0x00,0x08,0x0b,0x38,0x62,0x00, +0xae,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xd6,0x02,0x83,0x90,0x00,0x00,0x00,0x00, +0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00,0x02,0x00,0x42,0x24,0x0d,0x00,0x42,0x28, +0x03,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xc2,0x1a,0x00,0x08,0x0c,0x00,0x02,0x24, +0xc2,0x1a,0x00,0x08,0x02,0x00,0x62,0x24,0xc0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf, +0x25,0xb0,0x14,0x3c,0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf, +0x2c,0x00,0xb5,0xaf,0x20,0x00,0xb2,0xaf,0xd8,0x00,0x86,0x36,0x00,0x00,0xc3,0x90, +0x02,0x80,0x02,0x3c,0x78,0x1b,0x51,0x24,0x2a,0xb0,0x10,0x3c,0xa0,0xff,0x02,0x24, +0x25,0x18,0x62,0x00,0x34,0x00,0x05,0x36,0xfe,0xff,0x02,0x24,0xbc,0x02,0x32,0x92, +0x40,0x00,0x04,0x24,0x00,0x00,0xc3,0xa0,0x00,0x00,0xa2,0xa0,0x39,0x15,0x00,0x0c, +0x00,0x96,0x12,0x00,0x21,0x98,0x40,0x00,0x8d,0x00,0x60,0x12,0x00,0x40,0x02,0x3c, +0x08,0x00,0x63,0x8e,0xb0,0x03,0x82,0x36,0x25,0xb0,0x1e,0x3c,0x21,0x20,0x60,0x02, +0x00,0x00,0x43,0xac,0x02,0x45,0x00,0x0c,0x21,0xb8,0x20,0x02,0x42,0x00,0xd5,0x37, +0x03,0x0c,0xd1,0x37,0x17,0x0e,0xd6,0x37,0x04,0x00,0x14,0x24,0x2a,0xb0,0x03,0x3c, +0x06,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30, +0x0a,0x00,0x40,0x18,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0xd4,0xb2,0x84,0x24, +0x00,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00, +0x00,0xff,0x42,0x30,0xfc,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,0x08,0x00,0x65,0x8e, +0x20,0x10,0x06,0x3c,0x01,0x00,0x04,0x24,0x00,0xfe,0xc6,0x34,0x40,0x00,0x07,0x24, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xa4,0xaf,0x00,0x02,0x00,0x0c,0x01,0x00,0x04,0x24, +0x02,0x80,0x02,0x3c,0xd8,0xb2,0x42,0x24,0x00,0x00,0x45,0x8c,0x01,0x00,0x03,0x24, +0x21,0x20,0x00,0x00,0x00,0x00,0xa3,0xa0,0xff,0xff,0x03,0x24,0x00,0x00,0xa3,0xa2, +0x00,0x00,0x22,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,0x40,0x00,0x42,0x34, +0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x02,0x00,0x02,0x24,0x02,0x80,0x04,0x3c, +0x00,0x00,0xa2,0xa0,0x78,0x1b,0x83,0x24,0xc1,0x02,0x62,0x90,0x00,0x00,0xc4,0x92, +0x21,0x28,0x00,0x00,0x00,0x00,0xc2,0xa2,0xff,0x00,0x90,0x30,0x01,0x00,0xa2,0x24, +0xff,0x00,0x45,0x30,0x06,0x00,0xa3,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0xa2,0x24, +0xef,0xff,0x02,0x24,0x64,0x00,0x04,0x24,0x00,0x00,0xa2,0xa2,0xcb,0x12,0x00,0x0c, +0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x92,0x21,0x20,0x00,0x00,0xbf,0x00,0x42,0x30, +0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0xcb,0x12,0x00,0x0c,0x84,0x03,0x04,0x24, +0xf4,0x08,0xc2,0x37,0x00,0x00,0x43,0x8c,0x00,0x80,0x04,0x3c,0xdf,0x07,0x84,0x34, +0x00,0x00,0xd0,0xa2,0x21,0x10,0x00,0x00,0x24,0x28,0x64,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x00,0x00,0xa0,0xa2,0x00,0x00,0x22,0x92,0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30, +0x40,0x00,0x42,0x34,0x00,0x00,0x22,0xa2,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30, +0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0xbe,0x02,0xe2,0x92, +0x1f,0x00,0xa3,0x30,0x2b,0x10,0x62,0x00,0x0a,0x00,0x40,0x10,0x02,0x80,0x02,0x3c, +0xbf,0x02,0xe2,0x92,0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x00,0x05,0x00,0x40,0x10, +0x02,0x80,0x02,0x3c,0x01,0x00,0x02,0x3c,0x25,0x10,0x62,0x00,0x21,0x90,0x42,0x02, +0x02,0x80,0x02,0x3c,0x56,0x43,0x43,0x90,0x22,0x00,0x02,0x24,0x1c,0x00,0x62,0x10, +0x92,0x00,0x02,0x24,0x1b,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,0xff,0xff,0x94,0x26, +0xcb,0x12,0x00,0x0c,0xf4,0x01,0x04,0x24,0x89,0xff,0x81,0x06,0x2a,0xb0,0x03,0x3c, +0x04,0x00,0x60,0x12,0x25,0xb0,0x02,0x3c,0x56,0x15,0x00,0x0c,0x21,0x20,0x60,0x02, +0x25,0xb0,0x02,0x3c,0xd8,0x02,0x42,0x34,0x00,0x00,0x52,0xac,0x21,0x10,0x40,0x02, +0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f, +0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f, +0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27, +0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24,0xbe,0x02,0x62,0x90,0xc0,0x07,0xa3,0x30, +0x82,0x19,0x03,0x00,0x2b,0x10,0x62,0x00,0xe0,0xff,0x40,0x10,0x02,0x80,0x04,0x3c, +0x78,0x1b,0x84,0x24,0xbf,0x02,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x00, +0xda,0xff,0x40,0x10,0x00,0x12,0x03,0x00,0x10,0x00,0x03,0x3c,0x25,0x10,0x43,0x00, +0xbf,0x1b,0x00,0x08,0x21,0x90,0x42,0x02,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf, +0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,0x15,0x00,0x04,0x24, +0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0xb8,0x44,0x00,0x0c,0x14,0x00,0xb1,0xaf, +0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x02,0x80,0x12,0x3c,0xff,0xff,0x05,0x36, +0x56,0x30,0x06,0x24,0xb8,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x78,0x1b,0x51,0x26, +0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x08,0x03,0x23,0x92,0x04,0x00,0x02,0x24, +0x20,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0x18,0x03,0x25,0x8e,0x25,0xb0,0x10,0x3c, +0xb1,0x5a,0x00,0x0c,0x00,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c, +0x04,0x0e,0x04,0x36,0x1c,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x08,0x0e,0x04,0x36, +0x18,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x10,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e, +0xb1,0x5a,0x00,0x0c,0x14,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c, +0x18,0x0e,0x04,0x36,0x18,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x1c,0x0e,0x04,0x36, +0x78,0x1b,0x43,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x04,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03, +0x08,0x03,0x62,0xa0,0x00,0x0e,0x42,0x34,0x00,0x00,0x43,0x8c,0x18,0x03,0x25,0x8e, +0x00,0x00,0x00,0x00,0xde,0xff,0x65,0x14,0x25,0xb0,0x10,0x3c,0x19,0x1c,0x00,0x08, +0x78,0x1b,0x43,0x26,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c, +0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,0x15,0x00,0x04,0x24,0x1c,0x00,0xbf,0xaf, +0x18,0x00,0xb2,0xaf,0xb8,0x44,0x00,0x0c,0x14,0x00,0xb1,0xaf,0xcb,0x12,0x00,0x0c, +0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x56,0x30,0x06,0x24,0xb8,0x44,0x00,0x0c, +0x1a,0x00,0x04,0x24,0x02,0x80,0x10,0x3c,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24, +0x78,0x1b,0x02,0x26,0x08,0x03,0x46,0x90,0x25,0xb0,0x11,0x3c,0x10,0x10,0x12,0x3c, +0x01,0x00,0x03,0x24,0x00,0x0e,0x24,0x36,0x1e,0x00,0xc3,0x10,0x10,0x10,0x45,0x36, +0xb1,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x04,0x0e,0x24,0x36,0xb1,0x5a,0x00,0x0c, +0x10,0x10,0x45,0x36,0x08,0x0e,0x24,0x36,0xb1,0x5a,0x00,0x0c,0x10,0x10,0x05,0x24, +0x10,0x0e,0x24,0x36,0xb1,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,0x14,0x0e,0x24,0x36, +0xb1,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36,0x18,0x0e,0x24,0x36,0xb1,0x5a,0x00,0x0c, +0x10,0x10,0x45,0x36,0x1c,0x0e,0x24,0x36,0xb1,0x5a,0x00,0x0c,0x10,0x10,0x45,0x36, +0x78,0x1b,0x03,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03, +0x08,0x03,0x62,0xa0,0x00,0x00,0x86,0x8c,0x00,0x00,0x00,0x00,0xe0,0xff,0xc5,0x14, +0x78,0x1b,0x03,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03, +0x08,0x03,0x62,0xa0,0xd8,0xff,0xbd,0x27,0x1c,0x00,0xb3,0xaf,0x02,0x80,0x13,0x3c, +0x14,0x00,0xb1,0xaf,0x78,0x1b,0x71,0x26,0x10,0x03,0x26,0x8e,0x10,0x00,0xb0,0xaf, +0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0x15,0x00,0x04,0x24,0x20,0x00,0xbf,0xaf, +0xb8,0x44,0x00,0x0c,0x18,0x00,0xb2,0xaf,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24, +0x14,0x03,0x26,0x8e,0xff,0xff,0x05,0x36,0xb8,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24, +0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x08,0x03,0x22,0x92,0x25,0xb0,0x12,0x3c, +0x08,0x00,0x40,0x14,0x08,0x0e,0x44,0x36,0x25,0xb0,0x02,0x3c,0x00,0x0e,0x42,0x34, +0x00,0x00,0x45,0x8c,0xf0,0x02,0x23,0x8e,0x00,0x00,0x00,0x00,0x17,0x00,0xa3,0x10, +0x78,0x1b,0x62,0x26,0xec,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00, +0xf0,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x00,0x0e,0x44,0x36,0xf4,0x02,0x25,0x8e, +0xb1,0x5a,0x00,0x0c,0x04,0x0e,0x44,0x36,0xf8,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c, +0x10,0x0e,0x44,0x36,0xfc,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x14,0x0e,0x44,0x36, +0x00,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x18,0x0e,0x44,0x36,0x04,0x03,0x25,0x8e, +0xb1,0x5a,0x00,0x0c,0x1c,0x0e,0x44,0x36,0x78,0x1b,0x62,0x26,0x20,0x00,0xbf,0x8f, +0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x28,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x40,0xa0,0xe0,0xff,0xbd,0x27, +0x18,0x00,0xb2,0xaf,0x02,0x80,0x12,0x3c,0x14,0x00,0xb1,0xaf,0x78,0x1b,0x51,0x26, +0x10,0x03,0x26,0x8e,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36, +0x1c,0x00,0xbf,0xaf,0xb8,0x44,0x00,0x0c,0x15,0x00,0x04,0x24,0xcb,0x12,0x00,0x0c, +0x64,0x00,0x04,0x24,0x14,0x03,0x26,0x8e,0xff,0xff,0x05,0x36,0xb8,0x44,0x00,0x0c, +0x1a,0x00,0x04,0x24,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x08,0x03,0x23,0x92, +0x03,0x00,0x02,0x24,0x2c,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0xf0,0x02,0x25,0x8e, +0x25,0xb0,0x10,0x3c,0xb1,0x5a,0x00,0x0c,0x00,0x0e,0x04,0x36,0xf4,0x02,0x25,0x8e, +0xb1,0x5a,0x00,0x0c,0x04,0x0e,0x04,0x36,0xf8,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c, +0x10,0x0e,0x04,0x36,0xfc,0x02,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x14,0x0e,0x04,0x36, +0x00,0x03,0x25,0x8e,0xb1,0x5a,0x00,0x0c,0x18,0x0e,0x04,0x36,0x04,0x03,0x25,0x8e, +0xb1,0x5a,0x00,0x0c,0x1c,0x0e,0x04,0x36,0x0c,0x03,0x24,0x8e,0xec,0x02,0x22,0x8e, +0x00,0x00,0x00,0x00,0x21,0x28,0x44,0x00,0x00,0xff,0xa3,0x30,0xff,0xff,0x02,0x3c, +0xff,0x00,0x42,0x34,0x01,0x3f,0x63,0x2c,0x24,0x10,0xa2,0x00,0x0c,0x00,0x60,0x10, +0x08,0x0e,0x04,0x36,0xb1,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x78,0x1b,0x43,0x26, +0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x03,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x08,0x03,0x62,0xa0, +0xe1,0x1c,0x00,0x08,0x00,0x3f,0x45,0x34,0x00,0x0e,0x42,0x34,0x00,0x00,0x43,0x8c, +0xf0,0x02,0x25,0x8e,0x00,0x00,0x00,0x00,0xd2,0xff,0x65,0x14,0x25,0xb0,0x10,0x3c, +0xe4,0x1c,0x00,0x08,0x78,0x1b,0x43,0x26,0xd8,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf, +0x02,0x80,0x12,0x3c,0x20,0x00,0xb4,0xaf,0x24,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x78,0x1b,0x44,0x26,0x80,0x11,0x82,0x8c, +0x78,0x1b,0x43,0x8e,0x08,0x03,0x93,0x90,0x02,0x11,0x02,0x00,0x7f,0x00,0x54,0x30, +0xcc,0x00,0x63,0x30,0x40,0x00,0x02,0x24,0x68,0x00,0x62,0x10,0x01,0x00,0x02,0x24, +0x25,0xb0,0x08,0x3c,0x4c,0x00,0x03,0x35,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00, +0x03,0x00,0x42,0x30,0x07,0x00,0x40,0x10,0x78,0x1b,0x45,0x26,0x78,0x1b,0x42,0x92, +0x00,0x00,0x00,0x00,0x82,0x11,0x02,0x00,0x2f,0x00,0x40,0x10,0x00,0x0e,0x05,0x35, +0x78,0x1b,0x45,0x26,0x08,0x03,0xa2,0x8c,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00, +0x0f,0x00,0x40,0x14,0x78,0x1b,0x42,0x26,0x25,0xb0,0x02,0x3c,0x84,0x01,0x42,0x34, +0x00,0x00,0x44,0x8c,0x0d,0x00,0x03,0x24,0x7b,0x00,0x83,0x10,0x3e,0x00,0x02,0x24, +0x4a,0x00,0x03,0x24,0x23,0x03,0xa2,0xa0,0x20,0x03,0xa3,0xa0,0x45,0x00,0x02,0x24, +0x43,0x00,0x03,0x24,0x21,0x03,0xa2,0xa0,0x22,0x03,0xa3,0xa0,0x78,0x1b,0x42,0x26, +0x80,0x11,0x43,0x8c,0x25,0xb0,0x02,0x3c,0x60,0x0c,0x42,0x34,0x02,0x19,0x03,0x00, +0xff,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x78,0x1b,0x45,0x8e,0x44,0x00,0x02,0x24,0xcc,0x00,0xa3,0x30,0x3e,0x00,0x62,0x10, +0x78,0x1b,0x44,0x26,0x24,0x00,0xbf,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x00,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00, +0x5e,0x00,0x40,0x10,0x10,0x0e,0x07,0x35,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x08,0x0e,0x02,0x35,0x04,0x0e,0x03,0x35, +0x00,0x00,0x44,0x8c,0x00,0x00,0xa5,0x8c,0x00,0x00,0x66,0x8c,0x02,0x80,0x02,0x3c, +0x78,0x1b,0x49,0x24,0xec,0x02,0x24,0xad,0xf0,0x02,0x25,0xad,0xf4,0x02,0x26,0xad, +0x14,0x0e,0x04,0x35,0x02,0x80,0x02,0x3c,0x18,0x0e,0x05,0x35,0x00,0x00,0xe7,0x8c, +0x1c,0x0e,0x06,0x35,0x00,0x00,0x83,0x8c,0x56,0x43,0x4a,0x90,0x00,0x00,0xa2,0x8c, +0x00,0x00,0xc4,0x8c,0xf8,0x02,0x27,0xad,0x00,0x03,0x22,0xad,0x22,0x00,0x02,0x24, +0xfc,0x02,0x23,0xad,0x5a,0x00,0x42,0x11,0x04,0x03,0x24,0xad,0x92,0x00,0x02,0x24, +0x58,0x00,0x42,0x11,0x0d,0x08,0x02,0x35,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x78,0x1b,0x42,0x8e,0x3f,0xff,0x03,0x24,0x24,0x10,0x43,0x00, +0x40,0x00,0x42,0x34,0x14,0x1d,0x00,0x08,0x78,0x1b,0x42,0xae,0x3a,0x00,0x62,0x12, +0x04,0x00,0x02,0x24,0x38,0x00,0x62,0x12,0x78,0x1b,0x43,0x26,0xff,0xff,0x02,0x24, +0x08,0x1d,0x00,0x08,0x08,0x03,0x62,0xa0,0x80,0x11,0x83,0x8c,0xff,0xff,0x02,0x34, +0xc0,0xff,0x62,0x10,0x02,0x11,0x05,0x00,0x03,0x00,0x45,0x30,0x01,0x00,0x03,0x24, +0xbc,0xff,0xa3,0x14,0x25,0xb0,0x02,0x3c,0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90, +0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,0xb6,0xff,0x60,0x10,0x03,0x00,0x02,0x24, +0x65,0x00,0x62,0x12,0x04,0x00,0x62,0x2a,0x47,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x6a,0x00,0x60,0x12,0x00,0x00,0x00,0x00,0xae,0xff,0x65,0x16,0x00,0x00,0x00,0x00, +0x20,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x56,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x23,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00, +0x48,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x6d,0x1c,0x00,0x0c,0x00,0x00,0x00,0x00, +0x39,0x1d,0x00,0x08,0x00,0x00,0x00,0x00,0x3b,0x00,0x02,0x24,0x46,0x00,0x03,0x24, +0x23,0x03,0xa2,0xa0,0x20,0x03,0xa3,0xa0,0x41,0x00,0x02,0x24,0x40,0x00,0x03,0x24, +0x21,0x03,0xa2,0xa0,0x27,0x1d,0x00,0x08,0x22,0x03,0xa3,0xa0,0x00,0x00,0xe3,0x8c, +0x3f,0x3f,0x02,0x3c,0x3f,0x3f,0x42,0x34,0x9f,0xff,0x62,0x14,0x00,0x00,0x00,0x00, +0x15,0x1d,0x00,0x08,0x78,0x1b,0x45,0x26,0x0f,0x00,0x10,0x3c,0x01,0x00,0x11,0x3c, +0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0xb8,0x44,0x00,0x0c,0x15,0x00,0x04,0x24, +0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x56,0x30,0x26,0x36, +0xb8,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24, +0x78,0x1b,0x43,0x26,0xff,0xff,0x02,0x24,0x08,0x1d,0x00,0x08,0x08,0x03,0x62,0xa0, +0x0d,0x08,0x02,0x35,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x63,0x30, +0x08,0x00,0x62,0x2c,0x0f,0x00,0x63,0x38,0xa3,0xff,0x40,0x14,0x01,0x00,0x65,0x24, +0x00,0x16,0x05,0x00,0x00,0x24,0x05,0x00,0x00,0x1a,0x05,0x00,0x25,0x10,0x44,0x00, +0x25,0x10,0x43,0x00,0x25,0x10,0x45,0x00,0x25,0x18,0x65,0x00,0x1c,0x03,0x23,0xad, +0x66,0x1d,0x00,0x08,0x18,0x03,0x22,0xad,0x04,0x00,0x02,0x24,0x11,0x00,0x62,0x12, +0xff,0x00,0x02,0x24,0x67,0xff,0x62,0x16,0x00,0x00,0x00,0x00,0x22,0x03,0x82,0x90, +0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x21,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x20,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0x0a,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x29,0x1c,0x00,0x0c,0x00,0x00,0x00,0x00,0x39,0x1d,0x00,0x08, +0x00,0x00,0x00,0x00,0x21,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00, +0xf8,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xea,0x1b,0x00,0x0c,0x00,0x00,0x00,0x00, +0x39,0x1d,0x00,0x08,0x00,0x00,0x00,0x00,0x24,0x03,0x82,0x90,0x00,0x00,0x00,0x00, +0x2b,0x10,0x82,0x02,0xa8,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xab,0x1c,0x00,0x0c, +0x00,0x00,0x00,0x00,0x39,0x1d,0x00,0x08,0x00,0x00,0x00,0x00,0x22,0x03,0x82,0x90, +0x00,0x00,0x00,0x00,0x2b,0x10,0x82,0x02,0xe6,0xff,0x40,0x10,0x00,0x00,0x00,0x00, +0x25,0x03,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x54,0x00,0x9a,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0xab,0x1c,0x00,0x0c,0x00,0x00,0x00,0x00,0x39,0x1d,0x00,0x08, +0x00,0x00,0x00,0x00,0x02,0x80,0x08,0x3c,0x78,0x1b,0x05,0x25,0x80,0x11,0xa4,0x8c, +0xea,0x02,0xa3,0x90,0x02,0x11,0x04,0x00,0x26,0x00,0x60,0x14,0x7f,0x00,0x46,0x30, +0x25,0xb0,0x07,0x3c,0x4c,0x00,0xe2,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00, +0x20,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34,0x1d,0x00,0x82,0x10, +0x00,0x00,0x00,0x00,0x00,0x08,0xe3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00, +0x01,0x00,0x42,0x30,0x19,0x00,0x40,0x10,0x4b,0x00,0xc2,0x2c,0x3e,0x00,0x40,0x10, +0x01,0x00,0x04,0x24,0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x49,0x00,0x40,0x10, +0x23,0x00,0xc2,0x2c,0x78,0x1b,0x04,0x25,0xd7,0x02,0x82,0x90,0x00,0x00,0x00,0x00, +0x44,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34, +0x20,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,0xd7,0x02,0x80,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x17,0x00,0x40,0x10, +0x01,0x00,0x04,0x24,0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x44,0x00,0x40,0x10, +0x23,0x00,0xc2,0x2c,0x78,0x1b,0x04,0x25,0xd7,0x02,0x82,0x90,0x00,0x00,0x00,0x00, +0x3f,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,0x25,0xb0,0x02,0x3c,0x30,0x0c,0x42,0x34, +0x44,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,0xd7,0x02,0x80,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xd7,0x02,0xa2,0x90, +0x00,0x00,0x00,0x00,0xe7,0xff,0x44,0x10,0x43,0x00,0x02,0x24,0x30,0x0c,0xe3,0x34, +0xd7,0x02,0xa4,0xa0,0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xd7,0x02,0xa2,0x90,0x00,0x00,0x00,0x00, +0xc0,0xff,0x44,0x10,0x10,0x00,0x02,0x24,0x87,0x0c,0xe3,0x34,0xd7,0x02,0xa4,0xa0, +0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0xc7,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x78,0x1b,0x04,0x25, +0xd7,0x02,0x82,0x90,0x02,0x00,0x03,0x24,0xc2,0xff,0x43,0x10,0x00,0x00,0x00,0x00, +0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34,0xd7,0x02,0x83,0xa0,0x00,0x00,0x40,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0xb4,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x78,0x1b,0x04,0x25,0xd7,0x02,0x82,0x90, +0x02,0x00,0x03,0x24,0xaf,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c, +0xd7,0x02,0x83,0xa0,0x30,0x0c,0x42,0x34,0x42,0x00,0x03,0x24,0x00,0x00,0x43,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x2a,0xb0,0x04,0x3c,0x28,0x00,0x85,0x34,0x02,0x00,0x82,0x94,0x04,0x00,0x84,0x24, +0x05,0x00,0x40,0x14,0x2b,0x18,0xa4,0x00,0xfb,0xff,0x60,0x10,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,0x90,0x1e,0x00,0x0c,0x00,0x00,0x00,0x00, +0x08,0x00,0x40,0x10,0x01,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0xb8,0x44,0x43,0xa0, +0x14,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x6c,0x44,0x44,0xac, +0xb7,0x44,0x60,0xa0,0x10,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0x9e,0x44,0x40,0xa0,0xff,0x00,0x85,0x30, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xb0,0x44,0x60,0xa0,0x08,0x00,0xa4,0x2c, +0xb2,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xba,0x44,0x60,0xa0, +0x98,0x44,0x45,0xa0,0x11,0x00,0x80,0x10,0x02,0x80,0x03,0x3c,0x80,0x10,0x05,0x00, +0xdc,0xb2,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00, +0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x02,0x80,0x05,0x3c,0x78,0x1b,0xa5,0x24, +0x08,0x0b,0xa4,0x8c,0x00,0x70,0x02,0x3c,0x08,0x00,0x42,0x34,0x25,0x20,0x82,0x00, +0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x0b,0xa4,0xac,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x02,0x80,0x05,0x3c,0x78,0x1b,0xa5,0x24,0x08,0x0b,0xa4,0x8c, +0x00,0x70,0x02,0x3c,0x08,0x00,0x42,0x34,0x27,0x10,0x02,0x00,0x24,0x20,0x82,0x00, +0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac, +0x02,0x80,0x05,0x3c,0x78,0x1b,0xa5,0x24,0x08,0x0b,0xa2,0x8c,0x14,0x0b,0xa6,0x94, +0x00,0x70,0x04,0x3c,0x41,0xb0,0x03,0x3c,0x08,0x00,0x42,0x34,0x27,0x20,0x04,0x00, +0x00,0x00,0x62,0xac,0x24,0x20,0x44,0x00,0x10,0x00,0xc6,0x34,0x08,0x00,0x67,0x34, +0x02,0x80,0x08,0x3c,0x01,0x00,0x02,0x24,0x00,0x00,0x64,0xac,0x00,0x00,0xe6,0xa4, +0xb4,0x44,0x02,0xa1,0xb4,0x44,0x03,0x91,0x02,0x80,0x02,0x3c,0x14,0x0b,0xa6,0xa4, +0xb5,0x44,0x43,0xa0,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa4,0xac,0x02,0x80,0x05,0x3c, +0x78,0x1b,0xa5,0x24,0x08,0x0b,0xa3,0x8c,0x14,0x0b,0xa6,0x94,0x00,0x70,0x02,0x3c, +0x41,0xb0,0x04,0x3c,0x08,0x00,0x63,0x34,0x27,0x10,0x02,0x00,0x24,0x10,0x62,0x00, +0x10,0x00,0xc6,0x34,0x08,0x00,0x87,0x34,0x14,0x0b,0xa6,0xa4,0x00,0x00,0x83,0xac, +0x00,0x00,0x82,0xac,0x00,0x00,0xe6,0xa4,0x08,0x00,0xe0,0x03,0x08,0x0b,0xa2,0xac, +0x25,0xb0,0x03,0x3c,0xbe,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x08,0x00,0xe0,0x03, +0x01,0x00,0x42,0x2c,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,0x90,0x1e,0x00,0x0c, +0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x15,0x00,0x40,0x10,0x78,0x41,0x64,0x24, +0x78,0x41,0x62,0x8c,0x00,0x00,0x00,0x00,0x11,0x00,0x44,0x14,0x02,0x80,0x02,0x3c, +0xb8,0x44,0x43,0x90,0x01,0x00,0x02,0x24,0xff,0x00,0x63,0x30,0x0c,0x00,0x62,0x10, +0x01,0x00,0x04,0x24,0x02,0x80,0x03,0x3c,0x99,0x44,0x62,0x90,0x00,0x00,0x00,0x00, +0x0f,0x00,0x42,0x30,0x05,0x00,0x42,0x28,0x05,0x00,0x40,0x10,0x21,0x10,0x80,0x00, +0x10,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27, +0x10,0x00,0xbf,0x8f,0x21,0x20,0x00,0x00,0x21,0x10,0x80,0x00,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,0x90,0x1e,0x00,0x0c, +0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x25,0x00,0x40,0x10,0x78,0x41,0x64,0x24, +0x78,0x41,0x62,0x8c,0x00,0x00,0x00,0x00,0x21,0x00,0x44,0x14,0x01,0x00,0x05,0x24, +0x02,0x80,0x03,0x3c,0xb0,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30, +0x1b,0x00,0x45,0x10,0x02,0x80,0x03,0x3c,0x99,0x44,0x62,0x90,0x00,0x00,0x00,0x00, +0x0f,0x00,0x42,0x30,0x03,0x00,0x42,0x28,0x15,0x00,0x40,0x10,0x02,0x80,0x03,0x3c, +0xb2,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x30,0x10,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0xb2,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x30, +0x0b,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,0xb8,0x44,0x62,0x90,0x00,0x00,0x00,0x00, +0xff,0x00,0x42,0x30,0x06,0x00,0x45,0x10,0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c, +0xb9,0x44,0x43,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00, +0x21,0x20,0x00,0x00,0x10,0x00,0xbf,0x8f,0x21,0x10,0x80,0x00,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0xff,0x00,0x84,0x30,0x18,0x00,0xbf,0xaf, +0x14,0x00,0xb1,0xaf,0x29,0x00,0x80,0x10,0x10,0x00,0xb0,0xaf,0x25,0xb0,0x03,0x3c, +0x04,0x0c,0x62,0x90,0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x02,0x00,0x42,0x34, +0x04,0x0c,0x62,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x04,0x0d,0x62,0x90, +0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x02,0x00,0x42,0x34,0x04,0x0d,0x62,0xa0, +0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x82,0x24,0x25,0xb0,0x10,0x3c,0x70,0x0e,0x05,0x8e,0x80,0x01,0x11,0x3c, +0x70,0x0e,0x04,0x24,0x34,0x5b,0x00,0x0c,0x25,0x28,0xb1,0x00,0x8c,0x0e,0x05,0x8e, +0x8c,0x0e,0x04,0x24,0x34,0x5b,0x00,0x0c,0x25,0x28,0xb1,0x00,0x03,0x00,0x05,0x3c, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x59,0x01,0xa5,0x34, +0x44,0x08,0x04,0x24,0x34,0x5b,0x00,0x08,0x20,0x00,0xbd,0x27,0x44,0x08,0x04,0x24, +0x34,0x5b,0x00,0x0c,0x21,0x28,0x00,0x00,0x25,0xb0,0x03,0x3c,0x04,0x0c,0x62,0x90, +0x21,0x20,0x00,0x00,0xfd,0x00,0x42,0x30,0x04,0x0c,0x62,0xa0,0x01,0x00,0x82,0x24, +0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24, +0x25,0xb0,0x03,0x3c,0x04,0x0d,0x62,0x90,0x21,0x20,0x00,0x00,0xfd,0x00,0x42,0x30, +0x04,0x0d,0x62,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x25,0xb0,0x11,0x3c,0x70,0x0e,0x25,0x8e, +0x7f,0xfe,0x10,0x3c,0xff,0xff,0x10,0x36,0x24,0x28,0xb0,0x00,0x34,0x5b,0x00,0x0c, +0x70,0x0e,0x04,0x24,0x8c,0x0e,0x25,0x8e,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f, +0x24,0x28,0xb0,0x00,0x8c,0x0e,0x04,0x24,0x10,0x00,0xb0,0x8f,0x34,0x5b,0x00,0x08, +0x20,0x00,0xbd,0x27,0x25,0xb0,0x03,0x3c,0xfc,0x37,0x02,0x24,0x40,0x00,0x64,0x34, +0x00,0x00,0x82,0xa4,0x42,0x00,0x65,0x34,0x03,0x00,0x02,0x24,0x00,0x00,0xa0,0xa0, +0x03,0x08,0x62,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf, +0x10,0x00,0xb0,0xaf,0x02,0x80,0x02,0x3c,0x98,0x44,0x43,0x90,0x00,0x00,0x00,0x00, +0x07,0x00,0x60,0x10,0x25,0xb0,0x10,0x3c,0x02,0x80,0x03,0x3c,0x56,0x43,0x62,0x90, +0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,0x2e,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x21,0x00,0x06,0x36,0x00,0x00,0xc2,0x90,0x18,0x00,0x03,0x36,0x42,0x00,0x05,0x36, +0x01,0x00,0x42,0x34,0x00,0x00,0xc2,0xa0,0x40,0x00,0x11,0x36,0x00,0x00,0x60,0xa0, +0xff,0xff,0x02,0x24,0xfc,0x57,0x03,0x24,0x00,0x00,0xa2,0xa0,0x64,0x00,0x04,0x24, +0x00,0x00,0x23,0xa6,0xcb,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0xfc,0x77,0x02,0x24, +0x00,0x00,0x22,0xa6,0xcb,0x12,0x00,0x0c,0x0a,0x00,0x04,0x24,0x03,0x08,0x00,0xa2, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x0a,0x00,0x04,0x24,0xcb,0x12,0x00,0x0c, +0x25,0xb0,0x10,0x3c,0x40,0x00,0x10,0x36,0xfc,0x37,0x02,0x24,0x00,0x00,0x02,0xa6, +0xcb,0x12,0x00,0x0c,0x0a,0x00,0x04,0x24,0xfc,0x77,0x02,0x24,0x00,0x00,0x02,0xa6, +0xcb,0x12,0x00,0x0c,0x0a,0x00,0x04,0x24,0xfc,0x57,0x02,0x24,0x00,0x00,0x02,0xa6, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x55,0x1f,0x00,0x0c,0x21,0x20,0x00,0x00,0xc8,0x1f,0x00,0x08, +0x25,0xb0,0x10,0x3c,0xd8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x20,0x00,0xbf,0xaf, +0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0xff,0x00,0x90,0x30, +0x00,0x60,0x13,0x40,0x01,0x00,0x61,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x02,0x80,0x11,0x3c,0x9a,0x44,0x22,0x92,0x0f,0x00,0x12,0x32,0x0f,0x00,0x42,0x30, +0x0d,0x00,0x52,0x10,0x04,0x00,0x02,0x32,0x13,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x9a,0x44,0x22,0x92,0x0c,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x2f,0x00,0x43,0x10, +0x08,0x00,0x02,0x32,0x9a,0x44,0x22,0x92,0x04,0x00,0x03,0x24,0x0f,0x00,0x42,0x30, +0x5a,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x00,0x60,0x93,0x40,0x20,0x00,0xbf,0x8f, +0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x9a,0x44,0x22,0x92,0x00,0x00,0x00,0x00, +0x04,0x00,0x42,0x30,0x33,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x9a,0x44,0x22,0x92, +0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30,0x32,0x00,0x40,0x10,0x08,0x00,0x02,0x32, +0x30,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,0x60,0x26,0x62,0x90,0x00,0x00,0x00,0x00, +0x01,0x00,0x42,0x30,0x3d,0x00,0x40,0x14,0x01,0x00,0x04,0x24,0x9a,0x44,0x22,0x92, +0xf0,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x9a,0x44,0x22,0xa2,0x9a,0x44,0x23,0x92, +0x00,0x00,0x00,0x00,0x25,0x18,0x43,0x02,0x9a,0x44,0x23,0xa2,0x00,0x60,0x93,0x40, +0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xd1,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0x05,0x1f,0x00,0x0c,0x00,0x00,0x00,0x00,0xd2,0xff,0x40,0x10, +0x00,0x00,0x00,0x00,0x9a,0x44,0x22,0x92,0xf0,0xff,0x03,0x24,0x24,0x10,0x43,0x00, +0x9a,0x44,0x22,0xa2,0x02,0x80,0x03,0x3c,0x9a,0x44,0x22,0x92,0x60,0x26,0x64,0x90, +0x04,0x00,0x42,0x34,0x01,0x00,0x84,0x30,0x9a,0x44,0x22,0xa2,0xc1,0xff,0x80,0x10, +0x00,0x00,0x00,0x00,0x0e,0x46,0x00,0x0c,0x01,0x00,0x04,0x24,0x11,0x20,0x00,0x08, +0x00,0x00,0x00,0x00,0xa9,0x1f,0x00,0x0c,0x00,0x00,0x00,0x00,0x23,0x20,0x00,0x08, +0x00,0x00,0x00,0x00,0x9a,0x44,0x22,0x92,0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30, +0xd2,0xff,0x40,0x14,0x08,0x00,0x02,0x32,0xd0,0xff,0x40,0x10,0x02,0x80,0x02,0x3c, +0xb1,0x44,0x43,0x90,0x01,0x00,0x02,0x24,0xff,0x00,0x63,0x30,0x1b,0x00,0x62,0x10, +0x02,0x80,0x03,0x3c,0x60,0x26,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30, +0xc6,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x21,0x20,0x00,0x00,0x0e,0x46,0x00,0x0c, +0x00,0x00,0x00,0x00,0x2f,0x20,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0x1f,0x00,0x0c, +0x00,0x00,0x00,0x00,0xa4,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xb9,0x1f,0x00,0x0c, +0x00,0x00,0x00,0x00,0x9a,0x44,0x22,0x92,0xf0,0xff,0x03,0x24,0x24,0x10,0x43,0x00, +0x9a,0x44,0x22,0xa2,0x9a,0x44,0x23,0x92,0x00,0x00,0x00,0x00,0x02,0x00,0x63,0x34, +0x9a,0x44,0x23,0xa2,0x37,0x20,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c, +0x98,0x44,0x43,0x90,0x00,0x00,0x00,0x00,0xac,0xff,0x60,0x14,0x02,0x80,0x03,0x3c, +0x65,0x20,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x98,0x44,0x43,0x90, +0x00,0x00,0x00,0x00,0x0c,0x00,0x60,0x10,0x02,0x80,0x02,0x3c,0xb1,0x44,0x43,0x90, +0x00,0x00,0x00,0x00,0x0a,0x00,0x60,0x14,0x0c,0x00,0x04,0x24,0x02,0x80,0x03,0x3c, +0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x42,0x30,0x04,0x00,0x42,0x28, +0x03,0x00,0x40,0x14,0x04,0x00,0x04,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xf9,0x1f,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0xe8,0xff,0xbd,0x27,0x68,0x82,0x63,0x24,0x18,0x03,0x42,0x34,0x14,0x00,0xbf,0xaf, +0x10,0x00,0xb0,0xaf,0x00,0x00,0x43,0xac,0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,0x60,0x26,0x62,0x90, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x17,0x00,0x40,0x10,0x02,0x80,0x02,0x3c, +0x02,0x80,0x02,0x3c,0x9a,0x44,0x43,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x63,0x30, +0x04,0x00,0x63,0x28,0x17,0x00,0x60,0x14,0x04,0x00,0x04,0x24,0x02,0x80,0x03,0x3c, +0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x0c,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xb9,0x44,0x62,0xa0, +0x00,0x60,0x90,0x40,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xb9,0x44,0x40,0xa0,0x00,0x60,0x90,0x40, +0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0xf9,0x1f,0x00,0x0c,0x00,0x00,0x00,0x00,0xb4,0x20,0x00,0x08, +0x02,0x80,0x03,0x3c,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xe8,0xff,0xbd,0x27, +0x34,0x83,0x42,0x24,0x18,0x03,0x63,0x34,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf, +0x00,0x00,0x62,0xac,0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x02,0x80,0x04,0x3c,0xb7,0x44,0x82,0x90,0x00,0x00,0x00,0x00, +0x0a,0x00,0x40,0x10,0x14,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x6c,0x44,0x43,0xac, +0xb7,0x44,0x80,0xa0,0x00,0x60,0x90,0x40,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c, +0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,0xba,0x44,0x44,0xa0,0xb8,0x44,0x60,0xa0, +0x02,0x80,0x02,0x3c,0x99,0x44,0x44,0x90,0xf9,0x1f,0x00,0x0c,0xff,0x00,0x84,0x30, +0x00,0x60,0x90,0x40,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x42,0x11,0x05,0x00,0x0f,0x00,0x46,0x30, +0xe8,0xff,0xbd,0x27,0x09,0x00,0xc3,0x28,0x14,0x00,0xbf,0xaf,0x15,0x00,0x60,0x10, +0x10,0x00,0xb0,0xaf,0x82,0x16,0x05,0x00,0x01,0x00,0x42,0x30,0x15,0x00,0x40,0x10, +0x00,0xc0,0x02,0x3c,0x24,0x10,0xa2,0x00,0x47,0x00,0x40,0x14,0xc2,0x15,0x04,0x00, +0x01,0x00,0x42,0x30,0x54,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c, +0x3c,0xaf,0x63,0x24,0x21,0x18,0xc3,0x00,0x02,0x80,0x04,0x3c,0xb3,0x44,0x85,0x90, +0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x24,0x10,0x45,0x00,0x4a,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0x24,0x10,0xa2,0x00,0x1f,0x00,0x40,0x14,0xc2,0x15,0x04,0x00, +0x01,0x00,0x42,0x30,0x0b,0x00,0x40,0x10,0x02,0x80,0x04,0x3c,0x02,0x80,0x03,0x3c, +0x3c,0xaf,0x63,0x24,0x21,0x18,0xc3,0x00,0x02,0x80,0x04,0x3c,0xb3,0x44,0x85,0x90, +0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x24,0x10,0x45,0x00,0x3b,0x00,0x40,0x14, +0x02,0x80,0x04,0x3c,0xb2,0x44,0x82,0x90,0xfe,0xff,0x03,0x24,0x24,0x10,0x43,0x00, +0xb2,0x44,0x82,0xa0,0xb2,0x44,0x82,0x90,0x00,0x00,0x00,0x00,0x07,0x00,0x42,0x30, +0xe4,0xff,0x40,0x14,0x02,0x80,0x02,0x3c,0xb0,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c, +0x99,0x44,0x64,0x90,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0xff,0x00,0x84,0x30, +0xf9,0x1f,0x00,0x08,0x18,0x00,0xbd,0x27,0x02,0x80,0x04,0x3c,0xb2,0x44,0x82,0x90, +0xfd,0xff,0x03,0x24,0x14,0x00,0xbf,0x8f,0x24,0x10,0x43,0x00,0x02,0x80,0x03,0x3c, +0xb2,0x44,0x82,0xa0,0xb6,0x44,0x60,0xa0,0x42,0xb0,0x04,0x3c,0x00,0x00,0x82,0x90, +0x10,0x00,0xb0,0x8f,0xef,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x03,0x00,0x85,0x34, +0x40,0x00,0x03,0x24,0x18,0x00,0xbd,0x27,0x00,0x00,0x82,0xa0,0x00,0x00,0xa3,0xa0, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x42,0xb0,0x07,0x3c,0x00,0x00,0xe3,0x90, +0xef,0xff,0x02,0x24,0x03,0x00,0xf0,0x34,0x24,0x18,0x62,0x00,0x40,0x00,0x02,0x24, +0x00,0x00,0xe3,0xa0,0x02,0x00,0x04,0x24,0x00,0x00,0x02,0xa2,0x21,0x28,0x00,0x00, +0x71,0x14,0x00,0x0c,0x00,0x03,0x06,0x24,0x44,0x00,0x02,0x24,0x00,0x00,0x02,0xa2, +0x11,0x21,0x00,0x08,0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f, +0x01,0x00,0x04,0x24,0x1c,0x46,0x00,0x08,0x18,0x00,0xbd,0x27,0xb2,0x44,0x82,0x90, +0x27,0x21,0x00,0x08,0xfb,0xff,0x03,0x24,0x82,0x26,0x05,0x00,0xe8,0xff,0xbd,0x27, +0x00,0xc0,0x02,0x3c,0x01,0x00,0x84,0x30,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf, +0x0c,0x00,0x80,0x10,0x24,0x10,0xa2,0x00,0x42,0xb0,0x07,0x3c,0x03,0x00,0xf0,0x34, +0x02,0x00,0x04,0x24,0x21,0x28,0x00,0x00,0x31,0x00,0x40,0x14,0x00,0x03,0x06,0x24, +0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x04,0x24,0x1c,0x46,0x00,0x08, +0x18,0x00,0xbd,0x27,0x42,0xb0,0x04,0x3c,0x02,0x80,0x06,0x3c,0x0f,0x00,0x40,0x14, +0x03,0x00,0x87,0x34,0x02,0x80,0x06,0x3c,0xb2,0x44,0xc3,0x90,0xfe,0xff,0x02,0x24, +0x24,0x18,0x62,0x00,0xb2,0x44,0xc3,0xa0,0xb2,0x44,0xc2,0x90,0x00,0x00,0x00,0x00, +0x07,0x00,0x42,0x30,0x16,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x14,0x00,0xbf,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xb2,0x44,0xc3,0x90, +0xfd,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x02,0x80,0x02,0x3c,0xb2,0x44,0xc3,0xa0, +0xb6,0x44,0x40,0xa0,0x00,0x00,0x83,0x90,0xef,0xff,0x02,0x24,0x24,0x18,0x62,0x00, +0x40,0x00,0x02,0x24,0x00,0x00,0x83,0xa0,0x00,0x00,0xe2,0xa0,0xb2,0x44,0xc2,0x90, +0x00,0x00,0x00,0x00,0x07,0x00,0x42,0x30,0xec,0xff,0x40,0x14,0x02,0x80,0x02,0x3c, +0xb0,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c,0x99,0x44,0x64,0x90,0x14,0x00,0xbf,0x8f, +0x10,0x00,0xb0,0x8f,0xff,0x00,0x84,0x30,0xf9,0x1f,0x00,0x08,0x18,0x00,0xbd,0x27, +0x00,0x00,0xe3,0x90,0xef,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x40,0x00,0x02,0x24, +0x00,0x00,0xe3,0xa0,0x00,0x00,0x02,0xa2,0x71,0x14,0x00,0x0c,0x00,0x00,0x00,0x00, +0x44,0x00,0x02,0x24,0x00,0x00,0x02,0xa2,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0xff,0x00,0xa5,0x30, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x02,0x80,0x10,0x3c, +0x03,0x00,0xa0,0x14,0xff,0x00,0x91,0x30,0x19,0x00,0x20,0x12,0x02,0x80,0x02,0x3c, +0xb2,0x44,0x03,0x92,0xfb,0xff,0x02,0x24,0x01,0x00,0x04,0x24,0x24,0x18,0x62,0x00, +0xb2,0x44,0x03,0xa2,0x2e,0x00,0xa0,0x14,0x01,0x00,0x02,0x24,0xb2,0x44,0x02,0x92, +0xfe,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0xb2,0x44,0x02,0xa2,0x02,0x00,0x04,0x24, +0x21,0x28,0x00,0x00,0x13,0x00,0x20,0x16,0x00,0x03,0x06,0x24,0xb2,0x44,0x02,0x92, +0xfd,0xff,0x03,0x24,0x18,0x00,0xbf,0x8f,0x24,0x10,0x43,0x00,0xb2,0x44,0x02,0xa2, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0xb0,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c,0x99,0x44,0x64,0x90,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0x00,0x84,0x30,0xf9,0x1f,0x00,0x08, +0x20,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0x01,0x00,0x07,0x24,0xb0,0x44,0x47,0xa0, +0xb2,0x44,0x03,0x92,0x00,0x00,0x00,0x00,0x02,0x00,0x63,0x34,0xb2,0x44,0x03,0xa2, +0x71,0x14,0x00,0x0c,0x00,0x00,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x42,0xb0,0x02,0x3c,0x44,0x00,0x03,0x24,0x03,0x00,0x42,0x34, +0x20,0x00,0xbd,0x27,0x00,0x00,0x43,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x02,0x80,0x03,0x3c,0xb0,0x44,0x62,0xa0,0xb2,0x44,0x05,0x92,0x00,0x00,0x00,0x00, +0x01,0x00,0xa5,0x34,0xb2,0x44,0x05,0xa2,0x1c,0x46,0x00,0x0c,0x00,0x00,0x00,0x00, +0xc4,0x21,0x00,0x08,0x02,0x00,0x04,0x24,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c, +0xe8,0xff,0xbd,0x27,0xd8,0x87,0x42,0x24,0x18,0x03,0x63,0x34,0x10,0x00,0xb0,0xaf, +0x00,0x00,0x62,0xac,0x02,0x80,0x10,0x3c,0x99,0x44,0x02,0x92,0x00,0x00,0x00,0x00, +0x0f,0x00,0x42,0x30,0x03,0x00,0x42,0x28,0x05,0x00,0x40,0x10,0x14,0x00,0xbf,0xaf, +0x25,0x1f,0x00,0x0c,0x00,0x00,0x00,0x00,0x04,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x99,0x44,0x04,0x92,0xf9,0x1f,0x00,0x0c,0xff,0x00,0x84,0x30,0x02,0x80,0x04,0x3c, +0x78,0x1b,0x84,0x24,0x18,0x0b,0x83,0x94,0x14,0x0b,0x85,0x94,0x14,0x00,0xbf,0x8f, +0x10,0x00,0xb0,0x8f,0x02,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,0x25,0x18,0x65,0x00, +0x08,0x00,0x42,0x34,0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,0x08,0x00,0xe0,0x03, +0x14,0x0b,0x83,0xa4,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x14,0x00,0xbf,0xaf, +0x02,0x80,0x10,0x3c,0x08,0x14,0x04,0x26,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00, +0x2d,0x28,0x00,0x0c,0x21,0x38,0x00,0x00,0x1e,0x22,0x00,0x08,0x08,0x14,0x04,0x26, +0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,0x82,0x5b,0x00,0x0c,0x21,0x38,0x00,0x00, +0x10,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27, +0xff,0xff,0x8d,0x30,0x00,0x60,0x0f,0x40,0x01,0x00,0xe1,0x35,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x02,0x80,0x06,0x3c,0x78,0x1b,0xce,0x24,0x82,0x0b,0xc2,0x91, +0x00,0x00,0x00,0x00,0x1d,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,0x38,0x02,0x64,0x34, +0x80,0xff,0x02,0x24,0x00,0x00,0x82,0xa0,0x34,0x02,0x6a,0x34,0xd2,0x01,0x65,0x34, +0xd6,0x01,0x66,0x34,0xda,0x01,0x67,0x34,0xde,0x01,0x63,0x34,0x00,0x00,0xa8,0x94, +0x00,0x00,0xc9,0x94,0x00,0x00,0xeb,0x94,0x00,0x00,0x6c,0x94,0x00,0x00,0x44,0x95, +0xb0,0xfe,0xa2,0x25,0xff,0xff,0x4d,0x30,0x80,0x0b,0xc4,0xa5,0x00,0x00,0xa0,0xa4, +0x78,0x0b,0xc8,0xa5,0x00,0x00,0xc0,0xa4,0x7a,0x0b,0xc9,0xa5,0x00,0x00,0xe0,0xa4, +0x7c,0x0b,0xcb,0xa5,0x00,0x00,0x60,0xa4,0x00,0x00,0x4d,0xa5,0x7e,0x0b,0xcc,0xa5, +0x00,0x60,0x8f,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x2a,0xb0,0x02,0x3c, +0x0a,0x00,0x45,0x34,0x63,0x00,0x03,0x24,0xff,0xff,0x04,0x34,0x00,0x00,0xa2,0x90, +0x00,0x00,0x00,0x00,0x0a,0x00,0x40,0x10,0x78,0x1b,0xc2,0x24,0x64,0x00,0x02,0x24, +0xff,0xff,0x42,0x24,0xff,0xff,0x42,0x30,0xfe,0xff,0x40,0x14,0xff,0xff,0x42,0x24, +0xff,0xff,0x62,0x24,0xff,0xff,0x43,0x30,0xf4,0xff,0x64,0x14,0x78,0x1b,0xc2,0x24, +0x80,0x0b,0x48,0x94,0x7e,0x0b,0x47,0x94,0x78,0x0b,0x49,0x94,0x7a,0x0b,0x4a,0x94, +0x7c,0x0b,0x4b,0x94,0x25,0xb0,0x03,0x3c,0x38,0x02,0x6c,0x34,0x34,0x02,0x62,0x34, +0xd2,0x01,0x64,0x34,0xd6,0x01,0x65,0x34,0xda,0x01,0x66,0x34,0xde,0x01,0x63,0x34, +0x00,0x00,0x48,0xa4,0x00,0x00,0x89,0xa4,0x00,0x00,0xaa,0xa4,0x00,0x00,0xcb,0xa4, +0x00,0x00,0x67,0xa4,0x00,0x00,0x80,0xa1,0x00,0x60,0x8f,0x40,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c,0x08,0x00,0x83,0x34,0x00,0x00,0x62,0x94, +0x00,0x00,0x00,0x00,0x00,0x14,0x02,0x00,0x03,0x14,0x02,0x00,0x1a,0x00,0x40,0x04, +0x60,0x02,0x85,0x34,0x00,0x00,0xa3,0x90,0x05,0x00,0x02,0x24,0x00,0x03,0x8b,0x34, +0xff,0x00,0x63,0x30,0x04,0x03,0x8c,0x34,0xbd,0x00,0x8a,0x34,0x03,0x00,0x86,0x34, +0x40,0x00,0x85,0x34,0xfc,0x77,0x09,0x24,0x11,0x00,0x62,0x10,0x23,0x00,0x84,0x34, +0x00,0x00,0xc2,0x90,0xfe,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0x00,0x00,0xc2,0xa0, +0x22,0x00,0x02,0x24,0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,0x00,0x00,0x82,0xa0, +0xfc,0x37,0x02,0x24,0x00,0x00,0xa9,0xa4,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa9,0xa4, +0x00,0x00,0xa0,0xa4,0x00,0x00,0xa0,0xa4,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,0x00,0x00,0x42,0x91,0x00,0x00,0x00,0x00, +0x08,0x00,0x42,0x34,0x00,0x00,0x42,0xa1,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xd0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,0x2c,0x00,0xbf,0xaf,0x24,0x00,0xb3,0xaf, +0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0xff,0xff,0x14,0x24, +0x02,0x80,0x13,0x3c,0x41,0xb0,0x02,0x3c,0x78,0x1b,0x66,0x26,0x04,0x00,0x42,0x34, +0x00,0x00,0x47,0x8c,0x0c,0x0b,0xc5,0x8c,0x02,0x80,0x03,0x3c,0x5e,0x43,0x64,0x90, +0x08,0x0b,0xc8,0x8c,0x02,0x80,0x02,0x3c,0x80,0x43,0x49,0x90,0x25,0xb0,0x0a,0x3c, +0x25,0x88,0xa7,0x00,0xb0,0x03,0x42,0x35,0x00,0x00,0x51,0xac,0x00,0x24,0x04,0x00, +0x00,0x00,0x48,0xac,0x84,0x02,0x43,0x35,0x8c,0x02,0x45,0x35,0x01,0x00,0x02,0x24, +0x00,0x00,0x71,0xac,0x00,0x00,0xa4,0xac,0x0a,0x03,0x22,0x11,0x0c,0x0b,0xd1,0xac, +0x78,0x1b,0x64,0x26,0x08,0x0b,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x51,0x00, +0x01,0x00,0x42,0x30,0x0e,0x00,0x40,0x10,0x78,0x1b,0x67,0x26,0x25,0xb0,0x0b,0x3c, +0xb0,0x03,0x63,0x35,0x01,0x00,0x06,0x24,0x00,0x00,0x66,0xac,0x04,0x00,0x62,0x35, +0x00,0x00,0x4a,0x8c,0x0c,0x0b,0x83,0x8c,0x40,0x00,0x02,0x3c,0x24,0x10,0x42,0x01, +0x01,0x00,0x63,0x38,0x18,0x01,0x40,0x10,0x0c,0x0b,0x83,0xac,0x78,0x1b,0x67,0x26, +0x08,0x0b,0xe8,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x11,0x01,0x04,0x00,0x42,0x30, +0x18,0x00,0x40,0x10,0x78,0x1b,0x70,0x26,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x64,0x34, +0x04,0x00,0x02,0x24,0x00,0x00,0x82,0xac,0x0c,0x0b,0xe2,0x8c,0xfc,0x00,0x63,0x34, +0xe4,0x0a,0xe5,0x94,0x8c,0x25,0xe4,0x8c,0x00,0x00,0x66,0x8c,0x04,0x00,0x42,0x38, +0x21,0x50,0x85,0x00,0x0a,0x00,0xca,0x10,0x0c,0x0b,0xe2,0xac,0x02,0x80,0x05,0x3c, +0x44,0x44,0xa2,0x8c,0xfb,0xff,0x04,0x24,0x24,0x20,0x04,0x01,0x00,0x10,0x42,0x34, +0x41,0xb0,0x03,0x3c,0x44,0x44,0xa2,0xac,0x00,0x00,0x64,0xac,0x08,0x0b,0xe4,0xac, +0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x24,0x20,0x51,0x00, +0x08,0x00,0x83,0x30,0x06,0x00,0x60,0x10,0x10,0x00,0x82,0x30,0x0c,0x0b,0x02,0x8e, +0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x38,0x0c,0x0b,0x02,0xae,0x10,0x00,0x82,0x30, +0x06,0x00,0x40,0x10,0x20,0x00,0x82,0x30,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00, +0x10,0x00,0x42,0x38,0x0c,0x0b,0x02,0xae,0x20,0x00,0x82,0x30,0x06,0x00,0x40,0x10, +0x40,0x00,0x82,0x30,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x38, +0x0c,0x0b,0x02,0xae,0x40,0x00,0x82,0x30,0x06,0x00,0x40,0x10,0x80,0x00,0x82,0x30, +0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x38,0x0c,0x0b,0x02,0xae, +0x80,0x00,0x82,0x30,0x06,0x00,0x40,0x10,0x00,0x01,0x82,0x30,0x0c,0x0b,0x02,0x8e, +0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x38,0x0c,0x0b,0x02,0xae,0x00,0x01,0x82,0x30, +0x06,0x00,0x40,0x10,0x00,0x02,0x82,0x30,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00, +0x00,0x01,0x42,0x38,0x0c,0x0b,0x02,0xae,0x00,0x02,0x82,0x30,0x06,0x00,0x40,0x10, +0x00,0x04,0x82,0x30,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x38, +0x0c,0x0b,0x02,0xae,0x00,0x04,0x82,0x30,0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x00,0x04,0x42,0x38,0x0c,0x0b,0x02,0xae, +0x00,0x08,0x82,0x30,0x7a,0x02,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26, +0x08,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x51,0x00,0x00,0x10,0x42,0x30, +0x50,0x02,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26,0x08,0x0b,0x03,0x8e, +0x00,0x00,0x00,0x00,0x24,0x10,0x71,0x00,0x00,0x20,0x42,0x30,0x42,0x02,0x40,0x14, +0x00,0x00,0x00,0x00,0x24,0x10,0x71,0x00,0x00,0x80,0x42,0x30,0xf6,0x00,0x40,0x14, +0x01,0x00,0x12,0x3c,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00, +0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00,0x24,0x10,0x52,0x00,0x20,0x01,0x40,0x14, +0x00,0x00,0x00,0x00,0x08,0x0b,0x02,0x8e,0x02,0x00,0x12,0x3c,0x24,0x10,0x51,0x00, +0x24,0x10,0x52,0x00,0x48,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26, +0x08,0x0b,0x02,0x8e,0x04,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00, +0x24,0x10,0x52,0x00,0x71,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26, +0x08,0x0b,0x02,0x8e,0x08,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x52,0x00, +0x98,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e, +0x10,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00,0x24,0x10,0x52,0x00, +0xc1,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e, +0x20,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x52,0x00,0xe8,0x01,0x40,0x14, +0x00,0x00,0x00,0x00,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,0x40,0x00,0x12,0x3c, +0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00,0x24,0x10,0x52,0x00,0x9a,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x78,0x1b,0x68,0x26,0x08,0x0b,0x07,0x8d,0x00,0x04,0x05,0x3c, +0x24,0x10,0xf1,0x00,0x24,0x10,0x45,0x00,0x1b,0x00,0x40,0x10,0x78,0x1b,0x66,0x26, +0x2a,0xb0,0x02,0x3c,0x2c,0x00,0x42,0x34,0x00,0x00,0x4a,0x8c,0xff,0x00,0x02,0x24, +0xff,0x00,0x43,0x31,0x58,0x02,0x62,0x10,0x02,0x80,0x06,0x3c,0x44,0x44,0xc4,0x8c, +0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x00,0x80,0x84,0x34,0x27,0x28,0x05,0x00, +0x00,0x00,0x44,0xac,0x24,0x28,0xe5,0x00,0x41,0xb0,0x03,0x3c,0x02,0x80,0x02,0x3c, +0x00,0x00,0x65,0xac,0x44,0x44,0xc4,0xac,0x08,0x0b,0x05,0xad,0x9a,0x43,0x40,0xa4, +0x78,0x1b,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x00,0x04,0x04,0x3c,0x26,0x18,0x64,0x00, +0x0c,0x0b,0x43,0xac,0x78,0x1b,0x66,0x26,0x08,0x0b,0xc7,0x8c,0x00,0x08,0x04,0x3c, +0x24,0x28,0xf1,0x00,0x24,0x10,0xa4,0x00,0x08,0x00,0x40,0x10,0x80,0x00,0x08,0x3c, +0x0c,0x0b,0xc3,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00, +0x00,0x00,0x44,0xac,0x0c,0x0b,0xc3,0xac,0x80,0x00,0x08,0x3c,0x24,0x10,0xa8,0x00, +0x21,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x0c,0x0b,0xc3,0x8c,0x25,0xb0,0x09,0x3c, +0xb0,0x03,0x2a,0x35,0x2a,0xb0,0x02,0x3c,0x00,0x00,0x43,0xad,0x36,0x00,0x42,0x34, +0x00,0x00,0x43,0x90,0x23,0xb0,0x04,0x3c,0xff,0x1f,0x02,0x3c,0xc0,0x18,0x03,0x00, +0xf0,0x07,0x63,0x30,0xbc,0x25,0xc5,0x8c,0x21,0x18,0x64,0x00,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x2a,0x02,0x65,0x10,0xc0,0x25,0xc3,0xac,0x02,0x80,0x05,0x3c, +0x44,0x44,0xa3,0x8c,0x27,0x20,0x08,0x00,0x24,0x20,0xe4,0x00,0x00,0x08,0x63,0x34, +0x41,0xb0,0x02,0x3c,0x00,0x00,0x43,0xad,0x00,0x00,0x44,0xac,0x44,0x44,0xa3,0xac, +0x08,0x0b,0xc4,0xac,0x78,0x1b,0x62,0x26,0x0c,0x0b,0x43,0x8c,0x80,0x00,0x04,0x3c, +0x26,0x18,0x64,0x00,0x0c,0x0b,0x43,0xac,0x78,0x1b,0x66,0x26,0x08,0x0b,0xc3,0x8c, +0x00,0x01,0x04,0x3c,0x24,0x28,0x71,0x00,0x24,0x10,0xa4,0x00,0x06,0x00,0x40,0x10, +0x25,0xb0,0x02,0x3c,0x0c,0x0b,0xc3,0x8c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00, +0x00,0x00,0x44,0xac,0x0c,0x0b,0xc3,0xac,0x00,0x02,0x04,0x3c,0x24,0x10,0xa4,0x00, +0x08,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,0x0c,0x0b,0xc2,0x8c,0x25,0xb0,0x03,0x3c, +0xb0,0x03,0x63,0x34,0x26,0x10,0x44,0x00,0x0c,0x0b,0xc2,0xac,0x00,0x00,0x64,0xac, +0x02,0x80,0x02,0x3c,0x52,0x43,0x43,0x90,0x01,0x00,0x02,0x24,0x0f,0x00,0x63,0x30, +0xf1,0x01,0x62,0x10,0x00,0x00,0x00,0x00,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x20,0xbd,0x02,0x3c,0xec,0x02,0x65,0x35, +0x4d,0x00,0x68,0x35,0xf1,0x02,0x69,0x35,0x08,0x00,0x07,0x24,0x78,0x02,0x42,0x34, +0x00,0x00,0x46,0xa4,0x00,0x00,0x00,0xa1,0x00,0x00,0x27,0xa1,0x00,0x00,0xa0,0xac, +0x00,0x00,0xa2,0x8c,0xff,0x00,0x03,0x3c,0x80,0x00,0x04,0x3c,0xff,0x00,0x4a,0x30, +0x25,0x50,0x43,0x01,0x24,0x20,0x44,0x01,0xf2,0x02,0x66,0x35,0x0a,0x00,0x6a,0x35, +0x80,0xff,0x02,0x24,0x00,0x00,0x00,0xa1,0x00,0x00,0x27,0xa1,0x00,0x00,0xa3,0xac, +0x00,0x00,0xa3,0xac,0x00,0x00,0xc0,0xa0,0x00,0x00,0x42,0xa1,0x04,0x00,0x80,0x10, +0x02,0x00,0x62,0x35,0x84,0xff,0x02,0x24,0x00,0x00,0x42,0xa1,0x02,0x00,0x62,0x35, +0x00,0x00,0x43,0x94,0xff,0xbf,0x04,0x24,0x24,0x18,0x64,0x00,0x00,0x00,0x43,0xa4, +0xd8,0x22,0x00,0x08,0x78,0x1b,0x67,0x26,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00, +0xc0,0x00,0x00,0x0c,0x07,0x00,0x04,0x24,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30, +0xff,0x00,0x02,0x24,0x1b,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x20,0x25,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0xb4,0x24,0x03,0xae,0x06,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x70,0x24,0x0a,0xa2, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x06,0x3c,0x02,0x80,0x07,0x3c, +0x44,0x44,0xc3,0x8c,0x54,0x44,0xe4,0x90,0x08,0x0b,0x05,0x8e,0x60,0x00,0x02,0x3c, +0x27,0x10,0x02,0x00,0x24,0x28,0xa2,0x00,0x00,0x04,0x63,0x34,0x02,0x00,0x84,0x34, +0x41,0xb0,0x02,0x3c,0x44,0x44,0xc3,0xac,0x54,0x44,0xe4,0xa0,0x00,0x00,0x45,0xac, +0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x26,0x10,0x52,0x00, +0x79,0x23,0x00,0x08,0x0c,0x0b,0x02,0xae,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00, +0xc0,0x00,0x00,0x0c,0x21,0x20,0x00,0x00,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30, +0xff,0x00,0x02,0x24,0x1e,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0xfc,0x24,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0x90,0x24,0x03,0xae,0x03,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x54,0x24,0x0a,0xa2, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x07,0x3c,0x02,0x80,0x08,0x3c, +0x44,0x44,0xe5,0x8c,0x54,0x44,0x06,0x91,0x08,0x0b,0x04,0x8e,0x01,0x00,0x09,0x3c, +0x00,0x80,0x22,0x35,0x27,0x10,0x02,0x00,0x80,0xff,0x03,0x24,0x24,0x20,0x82,0x00, +0x25,0x30,0xc3,0x00,0x80,0x00,0xa5,0x34,0x41,0xb0,0x02,0x3c,0x44,0x44,0xe5,0xac, +0x54,0x44,0x06,0xa1,0x27,0xa0,0x09,0x00,0x00,0x00,0x44,0xac,0x08,0x0b,0x04,0xae, +0x0c,0x0b,0x02,0x8e,0x01,0x00,0x12,0x3c,0x00,0x80,0x42,0x38,0x0c,0x0b,0x02,0xae, +0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x51,0x00, +0x24,0x10,0x54,0x00,0x24,0x10,0x52,0x00,0xe2,0xfe,0x40,0x10,0x00,0x00,0x00,0x00, +0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x0c,0x01,0x00,0x04,0x24, +0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,0xff,0x00,0x02,0x24,0x1b,0x00,0x62,0x10, +0xff,0x00,0x43,0x31,0xfc,0x24,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00, +0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x90,0x24,0x03,0xae,0x03,0x00,0x04,0x24, +0x40,0x00,0x07,0x24,0x58,0x24,0x0a,0xa2,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x02,0x80,0x06,0x3c,0x02,0x80,0x07,0x3c,0x44,0x44,0xc3,0x8c,0x54,0x44,0xe4,0x90, +0x08,0x0b,0x05,0x8e,0x00,0x80,0x42,0x36,0x27,0x10,0x02,0x00,0x24,0x28,0xa2,0x00, +0x80,0x00,0x63,0x34,0x40,0x00,0x84,0x34,0x41,0xb0,0x02,0x3c,0x44,0x44,0xc3,0xac, +0x54,0x44,0xe4,0xa0,0x00,0x00,0x45,0xac,0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e, +0x00,0x00,0x00,0x00,0x26,0x10,0x52,0x00,0x0c,0x0b,0x02,0xae,0x78,0x1b,0x70,0x26, +0x08,0x0b,0x02,0x8e,0x02,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x52,0x00, +0xbb,0xfe,0x40,0x10,0x00,0x00,0x00,0x00,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00, +0xc0,0x00,0x00,0x0c,0x02,0x00,0x04,0x24,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30, +0xff,0x00,0x02,0x24,0x1d,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x08,0x25,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0x9c,0x24,0x03,0xae,0x04,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x5c,0x24,0x0a,0xa2, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x06,0x3c,0x44,0x44,0xc3,0x8c, +0x02,0x80,0x07,0x3c,0x54,0x44,0xe4,0x90,0x08,0x0b,0x05,0x8e,0x06,0x00,0x02,0x3c, +0x27,0x10,0x02,0x00,0x00,0x01,0x63,0x34,0x24,0x28,0xa2,0x00,0x44,0x44,0xc3,0xac, +0x20,0x00,0x84,0x34,0x41,0xb0,0x02,0x3c,0x04,0x00,0x03,0x3c,0x54,0x44,0xe4,0xa0, +0x26,0xa0,0x83,0x02,0x00,0x00,0x45,0xac,0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e, +0x00,0x00,0x00,0x00,0x26,0x10,0x52,0x00,0x0c,0x0b,0x02,0xae,0x78,0x1b,0x70,0x26, +0x08,0x0b,0x02,0x8e,0x04,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00, +0x24,0x10,0x52,0x00,0x92,0xfe,0x40,0x10,0x00,0x00,0x00,0x00,0x86,0x20,0x00,0x0c, +0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x0c,0x03,0x00,0x04,0x24,0x21,0x50,0x40,0x00, +0xff,0x00,0x43,0x30,0xff,0x00,0x02,0x24,0x1b,0x00,0x62,0x10,0xff,0x00,0x43,0x31, +0x08,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00, +0x21,0x30,0x60,0x00,0x9c,0x24,0x03,0xae,0x04,0x00,0x04,0x24,0x40,0x00,0x07,0x24, +0x60,0x24,0x0a,0xa2,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x06,0x3c, +0x02,0x80,0x07,0x3c,0x44,0x44,0xc3,0x8c,0x54,0x44,0xe4,0x90,0x08,0x0b,0x05,0x8e, +0x06,0x00,0x02,0x3c,0x27,0x10,0x02,0x00,0x24,0x28,0xa2,0x00,0x00,0x01,0x63,0x34, +0x10,0x00,0x84,0x34,0x41,0xb0,0x02,0x3c,0x44,0x44,0xc3,0xac,0x54,0x44,0xe4,0xa0, +0x00,0x00,0x45,0xac,0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00, +0x26,0x10,0x52,0x00,0x0c,0x0b,0x02,0xae,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e, +0x08,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x52,0x00,0x6b,0xfe,0x40,0x10, +0x00,0x00,0x00,0x00,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x0c, +0x04,0x00,0x04,0x24,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,0xff,0x00,0x02,0x24, +0x1d,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x14,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c, +0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xa8,0x24,0x03,0xae, +0x05,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x64,0x24,0x0a,0xa2,0xc3,0x01,0x00,0x0c, +0x10,0x00,0xa0,0xaf,0x02,0x80,0x06,0x3c,0x44,0x44,0xc3,0x8c,0x02,0x80,0x07,0x3c, +0x54,0x44,0xe4,0x90,0x08,0x0b,0x05,0x8e,0x18,0x00,0x02,0x3c,0x27,0x10,0x02,0x00, +0x00,0x02,0x63,0x34,0x24,0x28,0xa2,0x00,0x44,0x44,0xc3,0xac,0x08,0x00,0x84,0x34, +0x41,0xb0,0x02,0x3c,0x10,0x00,0x03,0x3c,0x54,0x44,0xe4,0xa0,0x26,0xa0,0x83,0x02, +0x00,0x00,0x45,0xac,0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00, +0x26,0x10,0x52,0x00,0x0c,0x0b,0x02,0xae,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e, +0x10,0x00,0x12,0x3c,0x24,0x10,0x51,0x00,0x24,0x10,0x54,0x00,0x24,0x10,0x52,0x00, +0x42,0xfe,0x40,0x10,0x00,0x00,0x00,0x00,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00, +0xc0,0x00,0x00,0x0c,0x05,0x00,0x04,0x24,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30, +0xff,0x00,0x02,0x24,0x1b,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x14,0x25,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00, +0xa8,0x24,0x03,0xae,0x05,0x00,0x04,0x24,0x40,0x00,0x07,0x24,0x68,0x24,0x0a,0xa2, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x06,0x3c,0x02,0x80,0x07,0x3c, +0x44,0x44,0xc3,0x8c,0x54,0x44,0xe4,0x90,0x08,0x0b,0x05,0x8e,0x18,0x00,0x02,0x3c, +0x27,0x10,0x02,0x00,0x24,0x28,0xa2,0x00,0x00,0x02,0x63,0x34,0x01,0x00,0x84,0x34, +0x41,0xb0,0x02,0x3c,0x44,0x44,0xc3,0xac,0x54,0x44,0xe4,0xa0,0x00,0x00,0x45,0xac, +0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x26,0x10,0x52,0x00, +0x0c,0x0b,0x02,0xae,0x78,0x1b,0x70,0x26,0x08,0x0b,0x02,0x8e,0x20,0x00,0x12,0x3c, +0x24,0x10,0x51,0x00,0x24,0x10,0x52,0x00,0x1b,0xfe,0x40,0x10,0x00,0x00,0x00,0x00, +0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x0c,0x06,0x00,0x04,0x24, +0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,0xff,0x00,0x02,0x24,0x1d,0x00,0x62,0x10, +0xff,0x00,0x43,0x31,0x20,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00, +0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xb4,0x24,0x03,0xae,0x06,0x00,0x04,0x24, +0x40,0x00,0x07,0x24,0x6c,0x24,0x0a,0xa2,0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf, +0x02,0x80,0x06,0x3c,0x44,0x44,0xc3,0x8c,0x02,0x80,0x07,0x3c,0x54,0x44,0xe4,0x90, +0x08,0x0b,0x05,0x8e,0x60,0x00,0x02,0x3c,0x27,0x10,0x02,0x00,0x00,0x04,0x63,0x34, +0x24,0x28,0xa2,0x00,0x44,0x44,0xc3,0xac,0x04,0x00,0x84,0x34,0x41,0xb0,0x02,0x3c, +0x40,0x00,0x03,0x3c,0x54,0x44,0xe4,0xa0,0x26,0xa0,0x83,0x02,0x00,0x00,0x45,0xac, +0x08,0x0b,0x05,0xae,0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x26,0x10,0x52,0x00, +0x71,0x23,0x00,0x08,0x0c,0x0b,0x02,0xae,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00, +0x0c,0x0b,0x02,0x8e,0x08,0x0b,0x03,0x8e,0x00,0x20,0x42,0x38,0x41,0x23,0x00,0x08, +0x0c,0x0b,0x02,0xae,0x86,0x20,0x00,0x0c,0x00,0x00,0x00,0x00,0xf4,0x00,0x00,0x0c, +0x01,0x00,0x04,0x24,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30,0xff,0x00,0x02,0x24, +0x16,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x44,0x25,0x05,0x8e,0x20,0x10,0x02,0x3c, +0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0xd8,0x24,0x03,0xae,0x21,0x30,0x60,0x00, +0x01,0x00,0x04,0x24,0x78,0x24,0x0a,0xa2,0x40,0x00,0x07,0x24,0xc3,0x01,0x00,0x0c, +0x10,0x00,0xa0,0xaf,0x02,0x80,0x05,0x3c,0x44,0x44,0xa3,0x8c,0x08,0x0b,0x04,0x8e, +0xff,0xc7,0x02,0x24,0x10,0x00,0x63,0x34,0x24,0x20,0x82,0x00,0x41,0xb0,0x02,0x3c, +0x44,0x44,0xa3,0xac,0x00,0x00,0x44,0xac,0x08,0x0b,0x04,0xae,0x0c,0x0b,0x02,0x8e, +0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38,0x3a,0x23,0x00,0x08,0x0c,0x0b,0x02,0xae, +0xf4,0x00,0x00,0x0c,0x21,0x20,0x00,0x00,0x21,0x50,0x40,0x00,0xff,0x00,0x43,0x30, +0xff,0x00,0x02,0x24,0x16,0x00,0x62,0x10,0xff,0x00,0x43,0x31,0x2c,0x25,0x05,0x8e, +0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0xc0,0x24,0x03,0xae, +0x21,0x30,0x60,0x00,0x21,0x20,0x00,0x00,0x74,0x24,0x0a,0xa2,0x40,0x00,0x07,0x24, +0xc3,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x05,0x3c,0x44,0x44,0xa3,0x8c, +0x08,0x0b,0x04,0x8e,0xff,0xc7,0x02,0x24,0x04,0x00,0x63,0x34,0x24,0x20,0x82,0x00, +0x41,0xb0,0x02,0x3c,0x44,0x44,0xa3,0xac,0x00,0x00,0x44,0xac,0x08,0x0b,0x04,0xae, +0x0c,0x0b,0x02,0x8e,0x00,0x00,0x00,0x00,0x00,0x08,0x42,0x38,0x33,0x23,0x00,0x08, +0x0c,0x0b,0x02,0xae,0x56,0x01,0x42,0x35,0x00,0x00,0x43,0x94,0x00,0x00,0x00,0x00, +0xf3,0xfc,0x60,0x10,0x00,0x00,0x00,0x00,0xde,0x4f,0x00,0x0c,0x07,0x00,0x04,0x24, +0xc5,0x22,0x00,0x08,0x78,0x1b,0x64,0x26,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x79,0x22,0x00,0x08,0x30,0x00,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x01,0x00,0x03,0x24, +0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x95,0x23,0x00,0x08,0x78,0x1b,0x62,0x26, +0xd0,0x03,0x23,0x35,0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xc6,0x23,0x00,0x08, +0x78,0x1b,0x62,0x26,0xe0,0xff,0xbd,0x27,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf, +0x10,0x00,0xb0,0xaf,0x25,0xb0,0x0c,0x3c,0x01,0x80,0x02,0x3c,0x18,0x03,0x83,0x35, +0xa4,0x97,0x42,0x24,0x02,0x80,0x11,0x3c,0x41,0xb0,0x0b,0x3c,0x00,0x00,0x62,0xac, +0x78,0x1b,0x2a,0x26,0x0a,0x00,0x62,0x35,0x00,0x00,0x44,0x94,0x16,0x0b,0x43,0x95, +0x14,0x0b,0x49,0x95,0x25,0x30,0x64,0x00,0xff,0xff,0xd0,0x30,0x24,0x10,0x09,0x02, +0x02,0x00,0x42,0x30,0x9e,0x00,0x40,0x10,0xc0,0x03,0x83,0x35,0x02,0x00,0x02,0x24, +0x00,0x00,0x62,0xac,0x02,0x80,0x08,0x3c,0x44,0x44,0x04,0x8d,0xdc,0x02,0x82,0x35, +0x00,0x00,0x47,0x90,0xfd,0xff,0x03,0x24,0x00,0x80,0x02,0x3c,0x24,0x18,0x23,0x01, +0x25,0x20,0x82,0x00,0x02,0x00,0xc6,0x38,0x08,0x00,0x65,0x35,0x02,0x80,0x02,0x3c, +0x99,0x44,0x47,0xa0,0x44,0x44,0x04,0xad,0x16,0x0b,0x46,0xa5,0x21,0x48,0x60,0x00, +0x00,0x00,0xa3,0xa4,0x14,0x0b,0x43,0xa5,0x24,0x38,0x09,0x02,0x04,0x00,0xe2,0x30, +0x0a,0x00,0x40,0x10,0x08,0x00,0xe2,0x30,0x16,0x0b,0x43,0x95,0x0c,0x00,0x64,0x35, +0xc0,0x03,0x85,0x35,0x04,0x00,0x63,0x38,0x04,0x00,0x02,0x24,0x00,0x00,0x86,0x8c, +0x00,0x00,0xa2,0xac,0x16,0x0b,0x43,0xa5,0x08,0x00,0xe2,0x30,0x08,0x00,0x40,0x10, +0x10,0x00,0xe2,0x30,0x16,0x0b,0x42,0x95,0xc0,0x03,0x84,0x35,0x08,0x00,0x03,0x24, +0x08,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x16,0x0b,0x42,0xa5,0x10,0x00,0xe2,0x30, +0x3a,0x00,0x40,0x10,0x78,0x1b,0x29,0x26,0xc0,0x03,0x84,0x35,0x10,0x00,0x02,0x24, +0x00,0x00,0x82,0xac,0x16,0x0b,0x43,0x95,0x02,0x80,0x05,0x3c,0xba,0x44,0xa4,0x90, +0x10,0x00,0x63,0x38,0x02,0x80,0x02,0x3c,0x16,0x0b,0x43,0xa5,0x7c,0x44,0x47,0x24, +0x69,0x00,0x80,0x14,0x21,0x30,0x00,0x00,0xe8,0x0a,0x42,0x91,0x00,0x00,0x00,0x00, +0x01,0x00,0x42,0x30,0x69,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c, +0x98,0x44,0x82,0x90,0x00,0x00,0x00,0x00,0x64,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x98,0x44,0x82,0x90,0x02,0x00,0x03,0x24,0xff,0x00,0x42,0x30,0x66,0x00,0x43,0x10, +0x00,0x00,0x00,0x00,0x98,0x44,0x82,0x90,0x03,0x00,0x03,0x24,0xff,0x00,0x42,0x30, +0x61,0x00,0x43,0x10,0x02,0x80,0x05,0x3c,0xb2,0x44,0xa2,0x90,0x02,0x80,0x03,0x3c, +0x02,0x00,0x04,0x24,0x10,0x00,0x42,0x34,0xb2,0x44,0xa2,0xa0,0x9d,0x44,0x66,0x90, +0x21,0x28,0x00,0x00,0x0c,0x00,0xe0,0xac,0xff,0x00,0xc6,0x30,0x71,0x14,0x00,0x0c, +0x00,0x32,0x06,0x00,0x42,0xb0,0x02,0x3c,0x03,0x00,0x42,0x34,0x44,0x00,0x04,0x24, +0x00,0x00,0x44,0xa0,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00, +0x0f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,0x04,0x00,0x40,0x10,0x78,0x1b,0x29,0x26, +0xf9,0x1f,0x00,0x0c,0x04,0x00,0x04,0x24,0x78,0x1b,0x29,0x26,0x14,0x0b,0x27,0x95, +0x00,0x00,0x00,0x00,0x24,0x28,0x07,0x02,0x20,0x00,0xa2,0x30,0x09,0x00,0x40,0x10, +0x80,0x00,0xa2,0x30,0x16,0x0b,0x22,0x95,0x25,0xb0,0x03,0x3c,0x20,0x00,0x04,0x24, +0x20,0x00,0x42,0x38,0xc0,0x03,0x63,0x34,0x00,0x00,0x64,0xac,0x16,0x0b,0x22,0xa5, +0x80,0x00,0xa2,0x30,0x17,0x00,0x40,0x10,0x24,0x10,0x07,0x02,0x02,0x80,0x08,0x3c, +0x44,0x44,0x04,0x8d,0x16,0x0b,0x26,0x95,0x25,0xb0,0x03,0x3c,0x10,0x00,0x02,0x3c, +0x7f,0xff,0x05,0x24,0x24,0x28,0xe5,0x00,0x25,0x20,0x82,0x00,0xb0,0x03,0x67,0x34, +0x80,0x00,0x02,0x24,0xc0,0x03,0x63,0x34,0x00,0x00,0x62,0xac,0x41,0xb0,0x02,0x3c, +0x80,0x00,0xc6,0x38,0x08,0x00,0x42,0x34,0x00,0x00,0xe4,0xac,0x16,0x0b,0x26,0xa5, +0x44,0x44,0x04,0xad,0x21,0x38,0xa0,0x00,0x00,0x00,0x45,0xa4,0x14,0x0b,0x25,0xa5, +0x24,0x10,0x07,0x02,0x00,0x30,0x42,0x30,0x07,0x00,0x40,0x10,0x02,0x80,0x02,0x3c, +0x16,0x0b,0x22,0x95,0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38,0x00,0x20,0x42,0x34, +0x16,0x0b,0x22,0xa5,0x02,0x80,0x02,0x3c,0x52,0x43,0x43,0x90,0x01,0x00,0x02,0x24, +0x0f,0x00,0x63,0x30,0x0f,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0x12,0x26,0x00,0x08,0x16,0x0b,0x46,0xa5,0xe8,0x0a,0x42,0x91,0xba,0x44,0xa0,0xa0, +0x01,0x00,0x42,0x30,0x99,0xff,0x40,0x14,0x01,0x00,0x06,0x24,0x62,0x26,0x00,0x08, +0x0c,0x00,0xe0,0xac,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x79,0x22,0x00,0x08,0x20,0x00,0xbd,0x27,0x02,0x80,0x04,0x3c,0xb5,0x44,0x82,0x90, +0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x24,0xb5,0x44,0x82,0xa0,0xb5,0x44,0x83,0x90, +0x00,0x00,0x00,0x00,0x07,0x00,0x60,0x10,0x02,0x80,0x02,0x3c,0x9e,0x44,0x43,0x90, +0x00,0x00,0x00,0x00,0x03,0x00,0x60,0x14,0x00,0x00,0x00,0x00,0x12,0x00,0xc0,0x10, +0x02,0x80,0x02,0x3c,0xb5,0x44,0x82,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x14, +0x0c,0x00,0xe0,0xac,0x02,0x80,0x02,0x3c,0xb4,0x44,0x43,0x90,0x00,0x00,0x00,0x00, +0xb5,0x44,0x83,0xa0,0x02,0x80,0x05,0x3c,0xb2,0x44,0xa2,0x90,0x02,0x80,0x03,0x3c, +0x02,0x00,0x04,0x24,0x10,0x00,0x42,0x34,0xb2,0x44,0xa2,0xa0,0x9d,0x44,0x66,0x90, +0x52,0x26,0x00,0x08,0x21,0x28,0x00,0x00,0x02,0x80,0x04,0x3c,0xac,0x44,0x83,0x8c, +0xa4,0x44,0x45,0x8c,0xe4,0x02,0x86,0x35,0x21,0x18,0x65,0x00,0xac,0x44,0x83,0xac, +0xac,0x44,0x82,0x8c,0x02,0x80,0x03,0x3c,0x00,0x00,0xc2,0xac,0xa0,0x44,0x62,0x94, +0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x30,0x40,0x10,0x02,0x00,0xf6,0xff,0x42,0x24, +0x62,0x26,0x00,0x08,0x0c,0x00,0xe2,0xac,0xf8,0xff,0xbd,0x27,0x04,0x00,0xb1,0xaf, +0x00,0x00,0xb0,0xaf,0x00,0x40,0x09,0x40,0x00,0x68,0x0a,0x40,0x00,0x70,0x02,0x40, +0x00,0x60,0x0b,0x40,0x25,0xb0,0x05,0x3c,0x18,0x03,0xa7,0x34,0x00,0x00,0xe6,0x8c, +0x01,0x80,0x02,0x3c,0x1c,0x03,0xa3,0x34,0x68,0x9b,0x42,0x24,0x00,0x00,0x66,0xac, +0x00,0x00,0xe2,0xac,0x80,0x00,0x83,0x8c,0x7c,0x02,0xa2,0x34,0x80,0x02,0xa6,0x34, +0x84,0x02,0xa7,0x34,0x88,0x02,0xa8,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0xc9,0xac, +0x00,0x00,0xea,0xac,0x00,0x00,0x0b,0xad,0x74,0x00,0x83,0x8c,0x8c,0x02,0xa2,0x34, +0x90,0x02,0xa7,0x34,0x00,0x00,0x43,0xac,0x08,0x00,0x86,0x8c,0x94,0x02,0xa8,0x34, +0x98,0x02,0xa9,0x34,0x00,0x00,0xe6,0xac,0x0c,0x00,0x82,0x8c,0x9c,0x02,0xa6,0x34, +0xa0,0x02,0xa7,0x34,0x00,0x00,0x02,0xad,0x10,0x00,0x83,0x8c,0xa4,0x02,0xa8,0x34, +0xa8,0x02,0xaa,0x34,0x00,0x00,0x23,0xad,0x14,0x00,0x82,0x8c,0xac,0x02,0xa9,0x34, +0xb0,0x02,0xab,0x34,0x00,0x00,0xc2,0xac,0x18,0x00,0x83,0x8c,0xb4,0x02,0xa6,0x34, +0xb8,0x02,0xac,0x34,0x00,0x00,0xe3,0xac,0x1c,0x00,0x82,0x8c,0xbc,0x02,0xa7,0x34, +0xc0,0x02,0xad,0x34,0x00,0x00,0x02,0xad,0x20,0x00,0x83,0x8c,0xc4,0x02,0xa8,0x34, +0xc8,0x02,0xae,0x34,0x00,0x00,0x43,0xad,0x24,0x00,0x82,0x8c,0xcc,0x02,0xaa,0x34, +0xd0,0x02,0xaf,0x34,0x00,0x00,0x22,0xad,0x28,0x00,0x83,0x8c,0xd4,0x02,0xa9,0x34, +0xd8,0x02,0xb0,0x34,0x00,0x00,0x63,0xad,0x2c,0x00,0x82,0x8c,0x70,0x02,0xab,0x34, +0x74,0x02,0xb1,0x34,0x00,0x00,0xc2,0xac,0x30,0x00,0x83,0x8c,0x78,0x02,0xa5,0x34, +0x00,0x00,0x83,0xad,0x34,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0xac, +0x38,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xad,0x3c,0x00,0x82,0x8c, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xad,0x40,0x00,0x83,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xad,0x44,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0xad, +0x48,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe3,0xad,0x4c,0x00,0x82,0x8c, +0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xad,0x50,0x00,0x83,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0x03,0xae,0x54,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xad, +0x58,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xae,0x5c,0x00,0x82,0x8c, +0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,0x42,0x27,0x00,0x08,0x00,0x00,0x00,0x00, +0x01,0x80,0x1b,0x3c,0x10,0x9d,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27, +0x00,0x00,0x5b,0xaf,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00, +0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,0x0c,0x00,0x63,0xaf, +0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,0x1c,0x00,0x67,0xaf, +0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,0x2c,0x00,0x6b,0xaf, +0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,0x3c,0x00,0x6f,0xaf, +0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0x70,0xaf, +0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,0x50,0x00,0x74,0xaf, +0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,0x60,0x00,0x78,0xaf, +0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,0x70,0x00,0x7e,0xaf, +0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,0x80,0x00,0x6a,0xaf, +0x00,0x68,0x1a,0x40,0x7f,0x00,0x5b,0x33,0x30,0x00,0x60,0x13,0x00,0x00,0x00,0x00, +0x25,0xb0,0x1b,0x3c,0x30,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x7a,0xaf, +0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00, +0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,0x0c,0x00,0x63,0xaf, +0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,0x1c,0x00,0x67,0xaf, +0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,0x2c,0x00,0x6b,0xaf, +0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,0x3c,0x00,0x6f,0xaf, +0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0x70,0xaf, +0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,0x50,0x00,0x74,0xaf, +0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,0x60,0x00,0x78,0xaf, +0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,0x70,0x00,0x7e,0xaf, +0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,0x80,0x00,0x6a,0xaf, +0xda,0x26,0x00,0x08,0x21,0x20,0x60,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c, +0x20,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0xad,0x00,0x04,0x5b,0x33, +0x0a,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x01,0x80,0x08,0x3c,0x90,0x8a,0x08,0x25, +0x00,0x00,0x00,0x00,0x25,0xb0,0x1b,0x3c,0x24,0x03,0x7b,0x37,0x00,0x00,0x00,0x00, +0x00,0x00,0x68,0xaf,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x08,0x5b,0x33, +0x25,0xb0,0x08,0x3c,0x28,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad, +0x06,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x01,0x80,0x08,0x3c,0xa4,0x97,0x08,0x25, +0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x80,0x1a,0x3c, +0x44,0x44,0x5a,0x27,0x04,0x00,0x5b,0x97,0x25,0xb0,0x08,0x3c,0x30,0x03,0x08,0x35, +0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad,0x18,0x00,0x60,0x13,0x00,0x00,0x00,0x00, +0x08,0xe8,0x9b,0x27,0x00,0x00,0x00,0x00,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b, +0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b, +0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b, +0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b, +0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b, +0x80,0x00,0x7b,0x8f,0x2b,0x28,0x00,0x08,0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03, +0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,0x08,0x00,0x5b,0xaf, +0xfc,0xeb,0x9d,0x27,0x00,0x00,0x4a,0x8f,0x00,0x00,0x00,0x00,0x21,0x00,0x40,0x11, +0x00,0x00,0x00,0x00,0x02,0x80,0x08,0x3c,0xa4,0x43,0x08,0x25,0x21,0x48,0x00,0x00, +0x21,0x58,0x00,0x00,0x01,0x00,0x6b,0x25,0x1a,0x00,0x40,0x11,0x24,0x70,0x4b,0x01, +0x14,0x00,0xc0,0x11,0x01,0x00,0x04,0x24,0x00,0x00,0x00,0x00,0x04,0x00,0x44,0xa3, +0x26,0x50,0x4b,0x01,0x00,0x00,0x4a,0xaf,0x80,0x80,0x09,0x00,0x21,0x80,0x08,0x02, +0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x02,0x00,0x00,0x00,0x00, +0x01,0x80,0x1b,0x3c,0xd8,0x9f,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27, +0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x44,0x44,0x5a,0x27,0xe1,0xff,0x00,0x10, +0x00,0x00,0x00,0x00,0x01,0x00,0x29,0x25,0x40,0x58,0x0b,0x00,0xee,0x27,0x00,0x08, +0x00,0x00,0x00,0x00,0x02,0x80,0x1b,0x3c,0x44,0x44,0x7b,0x27,0x21,0x60,0x00,0x00, +0x04,0x00,0x6c,0xa7,0x08,0x00,0x7a,0x8f,0x00,0x00,0x00,0x00,0xf8,0xff,0x5a,0x27, +0x00,0x00,0x5a,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x5a,0x27,0x84,0x00,0x44,0x8f, +0x00,0x00,0x00,0x00,0xf9,0xff,0x80,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x41,0x8f, +0xfc,0x03,0x50,0x7b,0x7c,0x00,0x42,0x7b,0xbc,0x00,0x44,0x7b,0xfc,0x00,0x46,0x7b, +0x3c,0x01,0x48,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x4a,0x7b, +0xbc,0x01,0x4c,0x7b,0xfc,0x01,0x4e,0x7b,0x3c,0x02,0x50,0x7b,0x7c,0x02,0x52,0x7b, +0xbc,0x02,0x54,0x7b,0xfc,0x02,0x56,0x7b,0x3c,0x03,0x58,0x7b,0x7c,0x03,0x5c,0x7b, +0xbc,0x03,0x5e,0x7b,0x80,0x00,0x5b,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03, +0x10,0x00,0x00,0x42,0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00, +0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac, +0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac, +0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac, +0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac, +0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac,0x54,0x00,0x95,0xac, +0x58,0x00,0x96,0xac,0x5c,0x00,0x97,0xac,0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac, +0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac,0x74,0x00,0x9f,0xac, +0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac,0xf8,0xff,0x84,0x24, +0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c, +0x00,0x00,0x00,0x00,0xf9,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,0x21,0xd8,0x80,0x00, +0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b, +0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02, +0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b, +0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b, +0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,0x00,0x60,0x05,0x40, +0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac, +0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac, +0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac, +0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00, +0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac, +0x50,0x00,0x94,0xac,0x54,0x00,0x94,0xac,0x58,0x00,0x96,0xac,0x5c,0x00,0x96,0xac, +0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac, +0x70,0x00,0x9e,0xac,0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac, +0x84,0x00,0x80,0xac,0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00, +0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c,0xfa,0xff,0xc0,0x10,0x00,0x00,0x00,0x00, +0x21,0xd8,0x80,0x00,0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b, +0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b, +0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b, +0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b, +0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b, +0x80,0x00,0x7b,0x8f,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xd7,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,0x00,0x00,0x7b,0x27, +0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x00,0x00,0x05,0x24, +0x03,0x00,0xa4,0x24,0x00,0xa0,0x80,0x40,0x00,0xa0,0x84,0x40,0x01,0x80,0x04,0x3c, +0x98,0x03,0x84,0x24,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x01,0x80,0x1b,0x3c,0x98,0x03,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27, +0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x00,0x00,0x5a,0x27,0xfc,0x03,0x5d,0x27, +0x02,0x80,0x1c,0x3c,0x00,0x18,0x9c,0x27,0x00,0xf0,0x08,0x3c,0x00,0x0c,0x08,0x35, +0x00,0x60,0x88,0x40,0x02,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,0xff,0x7f,0x05,0x3c, +0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x20,0x84,0x4c,0xff,0xff,0x05,0x34, +0x21,0x28,0xa4,0x00,0x00,0x28,0x85,0x4c,0x02,0x80,0x08,0x3c,0x00,0x00,0x08,0x25, +0x00,0x00,0x00,0xad,0x03,0x80,0x09,0x3c,0x7c,0xc3,0x29,0x25,0x04,0x00,0x08,0x25, +0xfe,0xff,0x09,0x15,0x00,0x00,0x00,0xad,0x00,0x80,0x04,0x3c,0x00,0x00,0x84,0x24, +0xff,0x7f,0x05,0x3c,0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x00,0x84,0x4c, +0xff,0xff,0x06,0x34,0x21,0x30,0xc4,0x00,0x24,0x30,0xc5,0x00,0x00,0x08,0x86,0x4c, +0x00,0xa0,0x04,0x40,0x10,0x00,0x84,0x34,0x00,0xa0,0x84,0x40,0x01,0x80,0x1b,0x3c, +0x44,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf, +0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x84, +0x20,0x00,0x06,0x24,0x25,0x28,0xa6,0x00,0x00,0x00,0x85,0xa4,0x01,0x80,0x1b,0x3c, +0x74,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf, +0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x8c,0x00,0x00,0x00,0x00, +0x10,0x00,0xa5,0x30,0xfc,0xff,0xa0,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x07,0x3c, +0xff,0xff,0xe7,0x34,0x02,0x80,0x05,0x3c,0x50,0x43,0xa5,0x24,0xff,0xff,0xa5,0x30, +0x40,0xb0,0x04,0x3c,0x25,0x28,0xa4,0x00,0x24,0x28,0xa7,0x00,0x21,0x30,0x00,0x00, +0x43,0xb0,0x02,0x3c,0x00,0x80,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x45,0xac, +0x04,0x00,0x46,0xac,0x08,0x00,0x44,0xac,0x7e,0x5e,0x00,0x08,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24, +0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x42,0x24, +0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x21,0x18,0x40,0x00,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03, +0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03, +0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03, +0x21,0x10,0x00,0x00,0xe0,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,0x1c,0x00,0xbf,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x30,0x80,0x00,0x21,0x90,0x00,0x00, +0x00,0x60,0x11,0x40,0x01,0x00,0x21,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x0d,0x00,0x83,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x60,0x14,0x02,0x80,0x02,0x3c, +0x01,0x00,0x03,0x24,0x9c,0x44,0x43,0xa0,0x0c,0x00,0xc2,0x90,0x02,0x80,0x05,0x3c, +0xb1,0x44,0xa2,0xa0,0x00,0x00,0xc4,0x90,0x05,0x00,0x02,0x24,0xff,0x00,0x83,0x30, +0x4b,0x00,0x62,0x10,0x00,0x00,0x00,0x00,0x03,0x00,0x02,0x24,0x3b,0x00,0x62,0x10, +0xff,0x00,0x84,0x30,0x09,0x00,0x82,0x2c,0x2f,0x00,0x40,0x10,0x02,0x80,0x10,0x3c, +0x98,0x44,0x02,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,0x2b,0x00,0x82,0x10, +0x00,0x00,0x00,0x00,0xad,0x1e,0x00,0x0c,0x00,0x00,0x00,0x00,0x98,0x44,0x02,0x92, +0x00,0x00,0x00,0x00,0x3e,0x00,0x40,0x10,0x02,0x80,0x03,0x3c,0x60,0x26,0x62,0x90, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x5a,0x00,0x40,0x10,0x02,0x80,0x02,0x3c, +0x02,0x80,0x03,0x3c,0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x0f,0x00,0x40,0x14, +0x25,0xb0,0x02,0x3c,0xb9,0x44,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24, +0xb9,0x44,0x62,0xa0,0x02,0x80,0x03,0x3c,0x9a,0x44,0x62,0x90,0x00,0x00,0x00,0x00, +0x0f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,0x04,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c, +0xf9,0x1f,0x00,0x0c,0x04,0x00,0x04,0x24,0x25,0xb0,0x02,0x3c,0x00,0x01,0x03,0x24, +0x16,0x01,0x42,0x34,0x00,0x00,0x43,0xa4,0x00,0x60,0x91,0x40,0x21,0x10,0x40,0x02, +0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x04,0x00,0x12,0x24,0x00,0x60,0x91,0x40, +0x21,0x10,0x40,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x0b,0x00,0xc2,0x90, +0x00,0x00,0x00,0x00,0x03,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,0x02,0x80,0x03,0x3c, +0x01,0x00,0x02,0x24,0xb4,0x44,0x62,0xa0,0xb4,0x44,0x63,0x90,0x02,0x80,0x02,0x3c, +0xb5,0x44,0x43,0xa0,0x00,0x00,0xc4,0x90,0xb7,0x41,0x00,0x08,0xff,0x00,0x84,0x30, +0xb1,0x44,0xa0,0xa0,0x00,0x00,0xc4,0x90,0xb4,0x41,0x00,0x08,0xff,0x00,0x83,0x30, +0x42,0xb0,0x05,0x3c,0x00,0x00,0xa3,0x90,0xef,0xff,0x02,0x24,0x03,0x00,0xa6,0x34, +0x24,0x18,0x62,0x00,0x40,0x00,0x02,0x24,0x00,0x00,0xa3,0xa0,0x0c,0x00,0x04,0x24, +0x00,0x00,0xc2,0xa0,0x02,0x80,0x03,0x3c,0xf9,0x1f,0x00,0x0c,0x88,0x44,0x60,0xac, +0x02,0x80,0x03,0x3c,0x56,0x43,0x62,0x90,0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30, +0x17,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x78,0x1b,0x45,0x24, +0x82,0x0b,0xa3,0x90,0x25,0xb0,0x02,0x3c,0x16,0x01,0x42,0x34,0x00,0x00,0x40,0xa4, +0xce,0xff,0x60,0x10,0x00,0x00,0x00,0x00,0x98,0x26,0xa4,0x94,0x82,0x0b,0xa0,0xa0, +0x00,0xc0,0x84,0x24,0x2c,0x22,0x00,0x0c,0xff,0xff,0x84,0x30,0xe9,0x41,0x00,0x08, +0x00,0x00,0x00,0x00,0xb9,0x44,0x40,0xa0,0x25,0xb0,0x02,0x3c,0x00,0x01,0x03,0x24, +0x16,0x01,0x42,0x34,0x00,0x00,0x43,0xa4,0xe0,0x41,0x00,0x08,0x00,0x00,0x00,0x00, +0x55,0x1f,0x00,0x0c,0x01,0x00,0x04,0x24,0x15,0x42,0x00,0x08,0x02,0x80,0x02,0x3c, +0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf, +0x14,0x00,0xb1,0xaf,0x21,0x80,0x80,0x00,0x00,0x60,0x11,0x40,0x01,0x00,0x21,0x36, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0x00,0x02,0x92,0x02,0x80,0x04,0x3c, +0x25,0xb0,0x05,0x3c,0x02,0x80,0x07,0x3c,0x98,0x26,0x84,0x24,0x50,0x00,0xa5,0x34, +0x06,0x00,0x06,0x24,0x13,0x00,0x40,0x14,0x78,0x1b,0xe3,0x24,0xe8,0x0a,0x62,0x90, +0x78,0x1b,0xf2,0x24,0x02,0x80,0x04,0x3c,0xfe,0x00,0x42,0x30,0xe8,0x0a,0x62,0xa0, +0xe8,0x0a,0x42,0x92,0x18,0x42,0x84,0x24,0x01,0x00,0x42,0x30,0x18,0x00,0x40,0x14, +0x02,0x00,0x05,0x26,0x00,0x60,0x91,0x40,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x46,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x07,0x3c, +0x78,0x1b,0xe3,0x24,0xe8,0x0a,0x62,0x90,0x78,0x1b,0xf2,0x24,0x02,0x80,0x04,0x3c, +0x01,0x00,0x42,0x34,0xe8,0x0a,0x62,0xa0,0xe8,0x0a,0x42,0x92,0x18,0x42,0x84,0x24, +0x02,0x00,0x05,0x26,0x01,0x00,0x42,0x30,0xea,0xff,0x40,0x10,0x06,0x00,0x06,0x24, +0x01,0x00,0x03,0x92,0x02,0x80,0x02,0x3c,0xb3,0x44,0x43,0xa0,0x46,0x46,0x00,0x0c, +0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x96,0x02,0x80,0x03,0x3c,0xa0,0x44,0x64,0xa4, +0xa0,0x44,0x62,0x94,0x02,0x80,0x03,0x3c,0xff,0xff,0x42,0x30,0x80,0x12,0x02,0x00, +0xa4,0x44,0x62,0xac,0x0a,0x00,0x04,0x96,0x14,0x00,0x03,0x24,0x02,0x80,0x02,0x3c, +0xb9,0x44,0x43,0xa0,0x98,0x26,0x44,0xa6,0x00,0x60,0x91,0x40,0x1c,0x00,0xbf,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00, +0x25,0xb0,0x02,0x3c,0x21,0x20,0x82,0x00,0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c, +0x25,0xb0,0x06,0x3c,0x78,0x1b,0x45,0x24,0x01,0x80,0x02,0x3c,0x18,0x03,0xc3,0x34, +0x54,0x0a,0x42,0x24,0x20,0x08,0xc8,0x34,0x21,0x38,0x80,0x00,0x60,0x08,0x09,0x24, +0x00,0x00,0x62,0xac,0x07,0x00,0x80,0x10,0x70,0x08,0x02,0x24,0x01,0x00,0x02,0x24, +0x28,0x08,0xc3,0x34,0x2a,0x00,0x82,0x10,0x64,0x08,0x06,0x24,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x8d,0xe0,0x08,0x03,0x24,0x8c,0x0b,0xa2,0xac, +0x40,0x08,0x02,0x24,0x90,0x0b,0xa3,0xac,0x9c,0x0b,0xa2,0xac,0x78,0x08,0x03,0x24, +0x0c,0x08,0x02,0x24,0xa0,0x0b,0xa3,0xac,0xa4,0x0b,0xa2,0xac,0x10,0x08,0x03,0x24, +0x20,0x08,0x02,0x24,0xa8,0x0b,0xa3,0xac,0xac,0x0b,0xa2,0xac,0x24,0x08,0x03,0x24, +0x58,0x08,0x02,0x24,0xb0,0x0b,0xa3,0xac,0xb4,0x0b,0xa2,0xac,0x50,0x0c,0x03,0x24, +0x54,0x0c,0x02,0x24,0xb8,0x0b,0xa3,0xac,0xbc,0x0b,0xa2,0xac,0x14,0x0c,0x03,0x24, +0x10,0x0c,0x02,0x24,0xc0,0x0b,0xa3,0xac,0xc4,0x0b,0xa2,0xac,0x80,0x0c,0x03,0x24, +0x84,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xcc,0x0b,0xa2,0xac,0x98,0x0b,0xa9,0xac, +0xc8,0x0b,0xa3,0xac,0x89,0x0b,0xa0,0xa0,0x94,0x0b,0xa9,0xac,0x02,0x00,0x80,0x10, +0xa0,0x08,0x02,0x24,0xb8,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,0xd0,0x0b,0xa2,0xac, +0x70,0x08,0x02,0x24,0x00,0x00,0x64,0x8c,0xe0,0x08,0x03,0x24,0x8c,0x0b,0xa2,0xac, +0x44,0x08,0x02,0x24,0x90,0x0b,0xa3,0xac,0x9c,0x0b,0xa2,0xac,0x78,0x08,0x03,0x24, +0x0c,0x08,0x02,0x24,0xa0,0x0b,0xa3,0xac,0xa4,0x0b,0xa2,0xac,0x14,0x08,0x03,0x24, +0x28,0x08,0x02,0x24,0xa8,0x0b,0xa3,0xac,0xac,0x0b,0xa2,0xac,0x2c,0x08,0x03,0x24, +0x58,0x08,0x02,0x24,0xb0,0x0b,0xa3,0xac,0xb4,0x0b,0xa2,0xac,0x58,0x0c,0x03,0x24, +0x5c,0x0c,0x02,0x24,0xb8,0x0b,0xa3,0xac,0xbc,0x0b,0xa2,0xac,0x1c,0x0c,0x03,0x24, +0x18,0x0c,0x02,0x24,0xc0,0x0b,0xa3,0xac,0xc4,0x0b,0xa2,0xac,0x88,0x0c,0x03,0x24, +0x8c,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xcc,0x0b,0xa2,0xac,0x89,0x0b,0xa7,0xa0, +0x98,0x0b,0xa6,0xac,0xc8,0x0b,0xa3,0xac,0x94,0x0b,0xa6,0xac,0xda,0xff,0x80,0x10, +0xa4,0x08,0x02,0x24,0xbc,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,0xd0,0x0b,0xa2,0xac, +0xfb,0x42,0x00,0x08,0x21,0x18,0x00,0x00,0x20,0x00,0x62,0x2c,0x06,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0x06,0x10,0x64,0x00,0x01,0x00,0x42,0x30,0xfa,0xff,0x40,0x10, +0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0xd8,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x25,0xb0,0x02,0x3c,0x21,0x88,0xa0,0x00, +0xff,0xff,0x03,0x24,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf, +0x20,0x00,0xbf,0xaf,0x21,0x98,0xc0,0x00,0x21,0x28,0xc0,0x00,0x21,0x90,0x80,0x00, +0x09,0x00,0x23,0x12,0x21,0x80,0x82,0x00,0x00,0x00,0x10,0x8e,0xf6,0x42,0x00,0x0c, +0x21,0x20,0x20,0x02,0x27,0x28,0x11,0x00,0x24,0x28,0xb0,0x00,0x04,0x10,0x53,0x00, +0x25,0x28,0xa2,0x00,0x21,0x20,0x40,0x02,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x8a,0x42,0x00,0x08, +0x28,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0x21,0x30,0x80,0x00,0x14,0x27,0x44,0x8c, +0x02,0x43,0x00,0x08,0xff,0xff,0x05,0x24,0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c, +0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x20,0x82,0x00, +0x00,0x00,0x90,0x8c,0x21,0x88,0xa0,0x00,0xf6,0x42,0x00,0x0c,0x21,0x20,0xa0,0x00, +0x24,0x80,0x11,0x02,0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd8,0xff,0xbd,0x27, +0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x20,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf, +0x1c,0x00,0xb3,0xaf,0x10,0x00,0xb0,0xaf,0x78,0x1b,0x31,0x26,0xb0,0x0b,0x23,0x8e, +0x25,0xb0,0x02,0x3c,0x24,0x08,0x53,0x8c,0x21,0x18,0x62,0x00,0x00,0x00,0x70,0x8c, +0x7f,0x80,0x02,0x3c,0xff,0xff,0x42,0x34,0xff,0x7f,0x05,0x3c,0x24,0x80,0x02,0x02, +0xc0,0x25,0x04,0x00,0xff,0xff,0xa5,0x34,0x24,0x28,0x65,0x02,0x25,0x80,0x04,0x02, +0x8a,0x42,0x00,0x0c,0x24,0x08,0x04,0x24,0x9c,0x12,0x00,0x0c,0x01,0x00,0x04,0x24, +0x00,0x80,0x12,0x3c,0xb0,0x0b,0x24,0x8e,0x25,0x80,0x12,0x02,0x8a,0x42,0x00,0x0c, +0x21,0x28,0x00,0x02,0x9c,0x12,0x00,0x0c,0x01,0x00,0x04,0x24,0x25,0x28,0x72,0x02, +0x8a,0x42,0x00,0x0c,0x24,0x08,0x04,0x24,0x9c,0x12,0x00,0x0c,0x01,0x00,0x04,0x24, +0xd0,0x0b,0x24,0x8e,0x0f,0x00,0x05,0x3c,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0xa5,0x34, +0x24,0x43,0x00,0x08,0x28,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf, +0x02,0x80,0x11,0x3c,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x78,0x1b,0x27,0x26, +0x8b,0x0b,0xe5,0x90,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x90,0x0d,0x63,0x24, +0x18,0x03,0x42,0x34,0x02,0x00,0x06,0x24,0x00,0x00,0x43,0xac,0x34,0x00,0xa6,0x10, +0x21,0x80,0x80,0x00,0x03,0x00,0x03,0x24,0x3a,0x00,0xa3,0x10,0x2e,0x00,0x02,0x2e, +0x10,0x00,0x02,0x2e,0x07,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0x00,0x04,0x32, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x35,0x43,0x00,0x08, +0x20,0x00,0xbd,0x27,0xfa,0xff,0xa6,0x14,0xff,0x00,0x04,0x32,0x89,0x0b,0xe4,0x90, +0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14, +0x00,0x00,0x00,0x00,0x38,0x00,0x85,0x10,0x78,0x1b,0x22,0x26,0x2e,0x00,0x83,0x10, +0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,0x24,0x43,0x00,0x0c,0xff,0xff,0x05,0x24, +0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24, +0x02,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0x78,0x1b,0x22,0x26,0x89,0x0b,0x44,0x90, +0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14, +0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0xdb,0xff,0x82,0x14, +0x00,0x00,0x00,0x00,0x78,0x1b,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c, +0x02,0x43,0x00,0x0c,0x21,0x30,0x00,0x00,0x7a,0x43,0x00,0x08,0xff,0x00,0x04,0x32, +0x25,0x00,0x82,0x2c,0xcc,0xff,0x40,0x14,0x03,0x00,0x03,0x24,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0xc7,0xff,0x40,0x14,0x10,0x00,0x02,0x2e,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x78,0x1b,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c, +0x02,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,0x8c,0x43,0x00,0x08,0x00,0x08,0x04,0x24, +0xcc,0xff,0x80,0x14,0x78,0x1b,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24, +0x02,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,0x8c,0x43,0x00,0x08,0x00,0x08,0x04,0x24, +0xb2,0xff,0x80,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x22,0x26,0x8c,0x0b,0x44,0x8c, +0x0f,0x00,0x05,0x24,0x02,0x43,0x00,0x0c,0x21,0x30,0x00,0x00,0x7a,0x43,0x00,0x08, +0xff,0x00,0x04,0x32,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c, +0x78,0x1b,0x28,0x26,0x8b,0x0b,0x06,0x91,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0x3c,0x0f,0x63,0x24,0x18,0x03,0x42,0x34,0x02,0x00,0x07,0x24,0x18,0x00,0xb2,0xaf, +0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00, +0x39,0x00,0xc7,0x10,0xff,0x00,0x90,0x30,0x03,0x00,0x03,0x24,0x3f,0x00,0xc3,0x10, +0x2e,0x00,0x02,0x2e,0x10,0x00,0x02,0x2e,0x0c,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x0f,0x00,0x04,0x3c,0xff,0xff,0x84,0x34,0x24,0x20,0x44,0x02,0x00,0x15,0x10,0x00, +0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x25,0x20,0x44,0x00,0x1f,0x43,0x00,0x08,0x20,0x00,0xbd,0x27,0xf5,0xff,0xc7,0x14, +0x0f,0x00,0x04,0x3c,0x89,0x0b,0x04,0x91,0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10, +0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x38,0x00,0x86,0x10, +0x78,0x1b,0x22,0x26,0x2e,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24, +0x24,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34, +0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,0x02,0x43,0x00,0x0c,0xff,0xff,0x05,0x24, +0x78,0x1b,0x22,0x26,0x89,0x0b,0x44,0x90,0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10, +0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10, +0x03,0x00,0x02,0x24,0xd6,0xff,0x82,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x22,0x26, +0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0x02,0x43,0x00,0x0c,0x21,0x30,0x00,0x00, +0xe7,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0x25,0x00,0x02,0x2e,0xc7,0xff,0x40,0x14, +0x03,0x00,0x03,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xc1,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x78,0x1b,0x22,0x26, +0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0x02,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24, +0xfe,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xcc,0xff,0x80,0x14,0x78,0x1b,0x22,0x26, +0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24,0x02,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24, +0xfe,0x43,0x00,0x08,0x00,0x08,0x04,0x24,0xad,0xff,0x80,0x14,0x00,0x00,0x00,0x00, +0x78,0x1b,0x22,0x26,0x8c,0x0b,0x44,0x8c,0x0f,0x00,0x05,0x24,0x02,0x43,0x00,0x0c, +0x21,0x30,0x00,0x00,0xe7,0x43,0x00,0x08,0x0f,0x00,0x04,0x3c,0xe8,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00,0x14,0x00,0xbf,0xaf,0x35,0x43,0x00,0x0c, +0x21,0x20,0x00,0x00,0x40,0x01,0x44,0x34,0x21,0x18,0x40,0x00,0x1f,0x00,0x02,0x2e, +0x00,0x23,0x04,0x00,0x10,0x00,0x40,0x10,0x10,0x00,0x05,0x2e,0x00,0x01,0x64,0x34, +0x06,0x00,0xa0,0x10,0x00,0x23,0x04,0x00,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x1f,0x43,0x00,0x0c, +0xf1,0xff,0x10,0x26,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x1f,0x43,0x00,0x0c,0xe2,0xff,0x10,0x26, +0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x18,0x00,0xbf,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x20,0x82,0x00,0x00,0x00,0x90,0x8c, +0x21,0x88,0xa0,0x00,0xf6,0x42,0x00,0x0c,0x21,0x20,0xa0,0x00,0x24,0x80,0x11,0x02, +0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd8,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c, +0x18,0x00,0xb2,0xaf,0x21,0x90,0x82,0x00,0xff,0xff,0x02,0x24,0x1c,0x00,0xb3,0xaf, +0x14,0x00,0xb1,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x88,0xa0,0x00, +0x21,0x20,0xa0,0x00,0x21,0x18,0x40,0x02,0x10,0x00,0xa2,0x10,0x21,0x98,0xc0,0x00, +0x00,0x00,0x50,0x8e,0xf6,0x42,0x00,0x0c,0x00,0x00,0x00,0x00,0x27,0x18,0x11,0x00, +0x24,0x18,0x70,0x00,0x04,0x10,0x53,0x00,0x25,0x18,0x62,0x00,0x00,0x00,0x43,0xae, +0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x20,0x00,0xbf,0x8f, +0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x28,0x00,0xbd,0x27,0x00,0x00,0x66,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x25,0xb0,0x02,0x3c,0x21,0x38,0x82,0x00,0xff,0xff,0x02,0x24,0x27,0x40,0x05,0x00, +0x08,0x00,0xa2,0x10,0x24,0x18,0xc5,0x00,0x00,0x00,0xe2,0x8c,0x00,0x00,0x00,0x00, +0x24,0x10,0x02,0x01,0x25,0x10,0x43,0x00,0x00,0x00,0xe2,0xac,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x21,0x38,0xa0,0x00,0x25,0xb0,0x02,0x3c,0xff,0xff,0x03,0x24,0x27,0x48,0x05,0x00, +0x24,0x40,0xc7,0x00,0x21,0x28,0xc0,0x00,0x05,0x00,0xe3,0x10,0x21,0x30,0x82,0x00, +0x00,0x00,0xc5,0x8c,0x00,0x00,0x00,0x00,0x24,0x28,0x25,0x01,0x25,0x28,0xa8,0x00, +0x8a,0x42,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c, +0xd8,0xff,0xbd,0x27,0xe0,0x12,0x42,0x24,0x18,0x03,0x63,0x34,0x20,0x00,0xb4,0xaf, +0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x24,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf, +0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,0x21,0x88,0xa0,0x00,0x21,0x98,0xc0,0x00, +0x21,0xa0,0x80,0x00,0x00,0x60,0x12,0x40,0x01,0x00,0x41,0x36,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x0f,0x00,0x02,0x3c,0xff,0xff,0x42,0x34,0x0a,0x00,0x22,0x12, +0x21,0x28,0xc0,0x00,0x64,0x43,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02, +0xf6,0x42,0x00,0x0c,0x21,0x80,0x40,0x00,0x27,0x28,0x11,0x00,0x24,0x28,0xb0,0x00, +0x04,0x10,0x53,0x00,0x25,0x28,0xa2,0x00,0xcf,0x43,0x00,0x0c,0xff,0x00,0x84,0x32, +0x00,0x60,0x92,0x40,0x24,0x00,0xbf,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x28,0x00,0xbd,0x27,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x8c,0x13,0x63,0x24, +0x18,0x03,0x42,0x34,0xe0,0xff,0xbd,0x27,0x00,0x00,0x43,0xac,0x18,0x00,0xbf,0xaf, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x64,0x43,0x00,0x0c,0x21,0x88,0xa0,0x00, +0x21,0x80,0x40,0x00,0xf6,0x42,0x00,0x0c,0x21,0x20,0x20,0x02,0x24,0x80,0x11,0x02, +0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf, +0x95,0x42,0x00,0x0c,0xff,0x00,0x84,0x30,0x10,0x00,0xbf,0x8f,0x01,0x00,0x02,0x24, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xc8,0xff,0xbd,0x27,0x2c,0x00,0xb1,0xaf,0xff,0xff,0x05,0x24,0x21,0x88,0x80,0x00, +0x02,0x00,0x06,0x24,0x10,0x00,0xa4,0x27,0x34,0x00,0xbf,0xaf,0x30,0x00,0xb2,0xaf, +0x3e,0x46,0x00,0x0c,0x28,0x00,0xb0,0xaf,0x08,0x00,0x30,0x96,0x02,0x80,0x02,0x3c, +0x21,0x28,0x00,0x00,0x25,0x80,0x02,0x02,0x21,0x20,0x00,0x02,0x3e,0x46,0x00,0x0c, +0x10,0x00,0x06,0x24,0x20,0x00,0x02,0x96,0x24,0x00,0x04,0x26,0x10,0x00,0xa5,0x27, +0x03,0xff,0x42,0x30,0xc8,0x00,0x42,0x34,0x20,0x00,0x02,0xa6,0x46,0x46,0x00,0x0c, +0x06,0x00,0x06,0x24,0x25,0xb0,0x03,0x3c,0x50,0x00,0x62,0x34,0x00,0x00,0x44,0x8c, +0x54,0x00,0x65,0x34,0x58,0x00,0x66,0x34,0x18,0x00,0xa4,0xaf,0x00,0x00,0xa2,0x8c, +0x5c,0x00,0x63,0x34,0x2a,0x00,0x04,0x26,0x1c,0x00,0xa2,0xaf,0x00,0x00,0xc7,0x8c, +0x18,0x00,0xa5,0x27,0x06,0x00,0x06,0x24,0x20,0x00,0xa7,0xaf,0x00,0x00,0x62,0x8c, +0x1a,0x00,0x12,0x24,0x46,0x46,0x00,0x0c,0x24,0x00,0xa2,0xaf,0x30,0x00,0x04,0x26, +0x20,0x00,0xa5,0x27,0x46,0x46,0x00,0x0c,0x06,0x00,0x06,0x24,0x13,0x00,0x03,0x24, +0x14,0x00,0x23,0xae,0x0c,0x00,0x32,0xae,0x08,0x00,0x05,0x8e,0x04,0x00,0x04,0x8e, +0xff,0xdf,0x02,0x3c,0x14,0x00,0x06,0x8e,0xff,0xff,0x42,0x34,0x10,0x00,0x07,0x8e, +0xff,0xe0,0x03,0x24,0x24,0x28,0xa2,0x00,0x00,0x40,0x02,0x3c,0x24,0x20,0x83,0x00, +0x25,0x28,0xa2,0x00,0xff,0x81,0x03,0x24,0xfe,0xff,0x02,0x3c,0x24,0x30,0xc3,0x00, +0xff,0xff,0x42,0x34,0x00,0x12,0x84,0x34,0x00,0x80,0x03,0x3c,0x24,0x20,0x82,0x00, +0x25,0x38,0xe3,0x00,0x00,0x26,0xc6,0x34,0x80,0x00,0xa5,0x34,0x20,0x00,0x02,0x24, +0x00,0x00,0x12,0xa6,0x10,0x00,0x07,0xae,0x02,0x00,0x02,0xa2,0x14,0x00,0x06,0xae, +0x04,0x00,0x04,0xae,0x08,0x00,0x05,0xae,0x34,0x00,0xbf,0x8f,0x30,0x00,0xb2,0x8f, +0x2c,0x00,0xb1,0x8f,0x28,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27, +0xc8,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,0x18,0x00,0xb0,0xaf,0xff,0xff,0xf4,0x30, +0x25,0xb0,0x10,0x3c,0x01,0x80,0x02,0x3c,0x1c,0x00,0xb1,0xaf,0x18,0x03,0x03,0x36, +0x58,0x15,0x42,0x24,0x20,0x00,0x91,0x26,0x30,0x00,0xb6,0xaf,0x24,0x00,0xb3,0xaf, +0x21,0xb0,0x80,0x00,0x48,0x00,0xb3,0x93,0x21,0x20,0x20,0x02,0x00,0x00,0x62,0xac, +0x2c,0x00,0xb5,0xaf,0x20,0x00,0xb2,0xaf,0x34,0x00,0xbf,0xaf,0xff,0x00,0xb5,0x30, +0x39,0x15,0x00,0x0c,0xff,0x00,0xd2,0x30,0x0b,0x00,0x40,0x14,0x10,0x00,0xa2,0xaf, +0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x08,0x00,0x43,0x8c,0xb0,0x03,0x02,0x36, +0x02,0x80,0x10,0x3c,0x00,0x00,0x43,0xac,0x10,0x00,0xa2,0x8f,0x21,0x30,0x20,0x02, +0x21,0x28,0x00,0x00,0x08,0x00,0x44,0x94,0x35,0x46,0x00,0x0c,0x25,0x20,0x90,0x00, +0x10,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x62,0x94,0x00,0x00,0x00,0x00, +0x25,0x88,0x50,0x00,0x50,0x00,0x60,0x16,0x20,0x00,0x30,0x26,0x20,0x00,0x32,0xa6, +0x48,0x00,0x02,0x24,0x6b,0x00,0x42,0x12,0x00,0x00,0x00,0x00,0x04,0x00,0x02,0x24, +0x4c,0x00,0xa2,0x16,0x21,0x28,0xc0,0x02,0xa4,0x00,0x02,0x24,0x6a,0x00,0x42,0x12, +0x02,0x80,0x02,0x3c,0x10,0x00,0xa2,0x8f,0x25,0xb0,0x10,0x3c,0xb0,0x03,0x10,0x36, +0x0c,0x00,0x54,0xac,0x10,0x00,0xa2,0x8f,0x12,0x00,0x03,0x24,0x21,0x28,0x00,0x00, +0x14,0x00,0x43,0xac,0x00,0x00,0x14,0xae,0x10,0x00,0xa2,0x8f,0x08,0x00,0x06,0x24, +0x08,0x00,0x43,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xae,0x10,0x00,0xa2,0x8f, +0x02,0x80,0x03,0x3c,0x08,0x00,0x44,0x94,0x00,0x00,0x00,0x00,0x25,0x88,0x83,0x00, +0x3e,0x46,0x00,0x0c,0x21,0x20,0x20,0x02,0x04,0x00,0x25,0x8e,0x08,0x00,0x26,0x8e, +0x14,0x00,0x27,0x8e,0x10,0x00,0x24,0x8e,0xff,0xe0,0x03,0x24,0xff,0xdf,0x02,0x3c, +0x24,0x28,0xa3,0x00,0xff,0xff,0x42,0x34,0xff,0x81,0x03,0x24,0x24,0x38,0xe3,0x00, +0x24,0x30,0xc2,0x00,0x00,0x80,0x03,0x3c,0x00,0x40,0x02,0x3c,0x25,0x30,0xc2,0x00, +0x25,0x20,0x83,0x00,0x00,0x12,0xa5,0x34,0x20,0x00,0x02,0x24,0x10,0x00,0x24,0xae, +0x00,0x00,0x34,0xa6,0x02,0x00,0x22,0xa2,0x04,0x00,0x25,0xae,0x14,0x00,0x27,0xae, +0x08,0x00,0x26,0xae,0x00,0x60,0x05,0x40,0x01,0x00,0xa1,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0x10,0x00,0xa3,0x8f,0x78,0x41,0x42,0x24, +0x04,0x00,0x44,0x8c,0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,0x10,0x00,0xa2,0x27, +0x00,0x00,0x83,0xac,0x04,0x00,0x64,0xac,0x00,0x00,0x02,0xae,0x00,0x60,0x85,0x40, +0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x00,0x10,0x42,0x36,0x8a,0x45,0x00,0x08, +0x20,0x00,0x22,0xa6,0x24,0x00,0x24,0x26,0x46,0x46,0x00,0x0c,0x06,0x00,0x06,0x24, +0x02,0x80,0x05,0x3c,0x98,0x26,0xa5,0x24,0x2a,0x00,0x24,0x26,0x46,0x46,0x00,0x0c, +0x06,0x00,0x06,0x24,0x02,0x80,0x05,0x3c,0x30,0x00,0x24,0x26,0x18,0x42,0xa5,0x24, +0x46,0x46,0x00,0x0c,0x06,0x00,0x06,0x24,0x02,0x80,0x05,0x3c,0x78,0x1b,0xa5,0x24, +0xec,0x0c,0xa6,0x94,0x00,0x00,0x00,0x00,0x01,0x00,0xc2,0x24,0x00,0x21,0x06,0x00, +0xff,0xff,0x46,0x30,0xff,0xff,0x84,0x30,0x00,0x10,0xc2,0x2c,0x0a,0x30,0x02,0x00, +0x02,0x1a,0x04,0x00,0x17,0x00,0x03,0xa2,0x16,0x00,0x04,0xa2,0x93,0x45,0x00,0x08, +0xec,0x0c,0xa6,0xa4,0x20,0x00,0x22,0x96,0x00,0x00,0x00,0x00,0x00,0x01,0x42,0x34, +0x8d,0x45,0x00,0x08,0x20,0x00,0x22,0xa6,0x10,0x42,0x43,0x94,0x02,0x80,0x05,0x3c, +0x24,0x00,0x24,0x26,0x00,0xc0,0x63,0x24,0xff,0xff,0x63,0x30,0x02,0x12,0x03,0x00, +0x18,0x42,0xa5,0x24,0x03,0x00,0x02,0xa2,0x02,0x00,0x03,0xa2,0x46,0x46,0x00,0x0c, +0x06,0x00,0x06,0x24,0x02,0x80,0x05,0x3c,0x2a,0x00,0x24,0x26,0x98,0x26,0xa5,0x24, +0x46,0x46,0x00,0x0c,0x06,0x00,0x06,0x24,0x93,0x45,0x00,0x08,0x00,0x00,0x00,0x00, +0xff,0x00,0x82,0x30,0x02,0x80,0x04,0x3c,0xe0,0xff,0xbd,0x27,0x18,0x42,0x84,0x24, +0x08,0x00,0x05,0x24,0x48,0x00,0x06,0x24,0x18,0x00,0x07,0x24,0x18,0x00,0xbf,0xaf, +0x56,0x45,0x00,0x0c,0x10,0x00,0xa2,0xaf,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x05,0x3c, +0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb0,0xaf,0x78,0x1b,0xa5,0x24,0x98,0x26,0xa2,0x94, +0x01,0x00,0x03,0x24,0xff,0x00,0x90,0x30,0x00,0xc0,0x42,0x24,0xff,0xff,0x44,0x30, +0x2c,0x22,0x00,0x0c,0x82,0x0b,0xa3,0xa0,0x02,0x80,0x04,0x3c,0x18,0x42,0x84,0x24, +0x04,0x00,0x05,0x24,0xa4,0x00,0x06,0x24,0x10,0x00,0x07,0x24,0x56,0x45,0x00,0x0c, +0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x3a,0x46,0x00,0x08, +0xff,0x00,0xa5,0x30,0x00,0x00,0x85,0xa0,0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24, +0xfc,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x05,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0xff,0xff,0xc6,0x24, +0xfd,0xff,0xc0,0x14,0x04,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24, +0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24,0x01,0x00,0xa5,0x24,0x00,0x00,0xe2,0xa0, +0xfb,0xff,0x66,0x14,0x01,0x00,0xe7,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00, +0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,0xff,0xff,0x06,0x24, +0x00,0x00,0xa2,0x8c,0xff,0xff,0x63,0x24,0x04,0x00,0xa5,0x24,0x00,0x00,0xe2,0xac, +0xfb,0xff,0x66,0x14,0x04,0x00,0xe7,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00, +0x2b,0x10,0xa4,0x00,0x0d,0x00,0x40,0x14,0xff,0xff,0x02,0x24,0xff,0xff,0xc6,0x24, +0x08,0x00,0xc2,0x10,0x21,0x18,0x80,0x00,0xff,0xff,0x07,0x24,0x00,0x00,0xa2,0x90, +0xff,0xff,0xc6,0x24,0x01,0x00,0xa5,0x24,0x00,0x00,0x62,0xa0,0xfb,0xff,0xc7,0x14, +0x01,0x00,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x21,0x28,0xa6,0x00, +0x21,0x18,0x86,0x00,0xff,0xff,0xc6,0x24,0xfa,0xff,0xc2,0x10,0x00,0x00,0x00,0x00, +0xff,0xff,0x07,0x24,0xff,0xff,0xa5,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24, +0xff,0xff,0xc6,0x24,0xfb,0xff,0xc7,0x14,0x00,0x00,0x62,0xa0,0x08,0x00,0xe0,0x03, +0x21,0x10,0x80,0x00,0x0c,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x90, +0x00,0x00,0xa3,0x90,0x01,0x00,0x84,0x24,0x23,0x10,0x43,0x00,0x00,0x16,0x02,0x00, +0x03,0x16,0x02,0x00,0x04,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,0xff,0xff,0xc6,0x24, +0xf6,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0xc0,0x00, +0x91,0x46,0x00,0x08,0x21,0x18,0x86,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00, +0x04,0x00,0x45,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0xfa,0xff,0x83,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x09,0x00,0xc0,0x10, +0xff,0xff,0xc3,0x24,0xff,0x00,0xa5,0x30,0xff,0xff,0x06,0x24,0x00,0x00,0x82,0x90, +0xff,0xff,0x63,0x24,0x05,0x00,0x45,0x10,0x01,0x00,0x84,0x24,0xfb,0xff,0x66,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0xff,0xff,0x82,0x24,0x21,0x38,0x00,0x00,0x1f,0x00,0xc0,0x10,0x21,0x18,0x00,0x00, +0x02,0x80,0x02,0x3c,0x80,0xb4,0x4b,0x24,0x00,0x00,0x87,0x90,0x00,0x00,0xa3,0x90, +0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24,0x21,0x10,0xeb,0x00,0x16,0x00,0xe0,0x10, +0x01,0x00,0xa5,0x24,0x14,0x00,0x60,0x10,0x21,0x48,0x6b,0x00,0x10,0x00,0xe3,0x10, +0x20,0x00,0xe8,0x24,0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30, +0x02,0x00,0x40,0x10,0x20,0x00,0x6a,0x24,0xff,0x00,0x07,0x31,0x00,0x00,0x22,0x91, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x02,0x00,0x40,0x10,0xff,0x00,0xe7,0x30, +0xff,0x00,0x43,0x31,0xff,0x00,0x63,0x30,0x03,0x00,0xe3,0x14,0x00,0x00,0x00,0x00, +0xe5,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x23,0x10,0xe3,0x00, +0x21,0x18,0x80,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0, +0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x21,0x38,0x80,0x00,0xff,0xff,0x03,0x24,0xff,0xff,0xc6,0x24,0x06,0x00,0xc3,0x10, +0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0, +0xf9,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00, +0x00,0x00,0x82,0x80,0xe0,0x46,0x00,0x08,0x21,0x18,0x80,0x00,0x01,0x00,0x84,0x24, +0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00, +0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14, +0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x12,0x00,0xc0,0x10, +0x21,0x18,0x80,0x00,0x00,0x00,0x82,0x80,0xf1,0x46,0x00,0x08,0x00,0x00,0x00,0x00, +0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14, +0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0, +0x05,0x00,0x40,0x10,0x01,0x00,0x84,0x24,0xff,0xff,0xc6,0x24,0xf9,0xff,0xc0,0x14, +0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00, +0x00,0x00,0x83,0x90,0x00,0x00,0xa2,0x90,0x01,0x00,0x84,0x24,0x23,0x10,0x62,0x00, +0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14,0x01,0x00,0xa5,0x24, +0xf7,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x21,0x10,0x00,0x00,0x0b,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90, +0x00,0x00,0x83,0x90,0xff,0xff,0xc6,0x24,0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00, +0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,0xf5,0xff,0x60,0x14, +0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x80, +0x00,0x2e,0x05,0x00,0x21,0x10,0x80,0x00,0x22,0x47,0x00,0x08,0x03,0x2e,0x05,0x00, +0x07,0x00,0x60,0x10,0x01,0x00,0x42,0x24,0x00,0x00,0x43,0x80,0x00,0x00,0x00,0x00, +0xfb,0xff,0x65,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x00,0x00,0x82,0x80,0x2e,0x47,0x00,0x08, +0x21,0x18,0x80,0x00,0x01,0x00,0x63,0x24,0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00, +0xfc,0xff,0x40,0x14,0x23,0x10,0x64,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x21,0x80,0xa0,0x00,0x14,0x00,0xb1,0xaf, +0x18,0x00,0xbf,0xaf,0x21,0x88,0x80,0x00,0x28,0x47,0x00,0x0c,0x00,0x86,0x10,0x00, +0x21,0x18,0x51,0x00,0x03,0x86,0x10,0x00,0x00,0x00,0x62,0x80,0x00,0x00,0x00,0x00, +0x0a,0x00,0x50,0x10,0x21,0x10,0x60,0x00,0xff,0xff,0x63,0x24,0x2b,0x10,0x71,0x00, +0xf9,0xff,0x40,0x10,0x21,0x10,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0x21,0x30,0x80,0x00,0x0d,0x00,0xa0,0x10,0xff,0xff,0xa3,0x24,0x00,0x00,0x82,0x80, +0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0x05,0x24, +0xff,0xff,0x63,0x24,0x05,0x00,0x65,0x10,0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x80, +0x00,0x00,0x00,0x00,0xfa,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x23,0x10,0xc4,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0x19,0x00,0x40,0x10, +0x21,0x40,0x00,0x00,0x00,0x00,0xa9,0x80,0x00,0x00,0x00,0x00,0x17,0x00,0x20,0x11, +0x21,0x30,0xa0,0x00,0x00,0x3e,0x02,0x00,0x03,0x3e,0x07,0x00,0x21,0x18,0x20,0x01, +0x15,0x00,0xe3,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xc6,0x24,0x00,0x00,0xc2,0x90, +0x00,0x00,0x00,0x00,0x00,0x1e,0x02,0x00,0x03,0x1e,0x03,0x00,0xf8,0xff,0x60,0x14, +0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0xeb,0xff,0x40,0x14, +0x01,0x00,0x08,0x25,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x01,0x00,0x00,0xa2,0x90, +0x73,0x47,0x00,0x08,0x00,0x16,0x02,0x00,0x00,0x00,0xc2,0x90,0x73,0x47,0x00,0x08, +0x00,0x16,0x02,0x00,0x00,0x00,0x87,0x90,0x00,0x00,0x00,0x00,0x14,0x00,0xe0,0x10, +0x21,0x10,0x80,0x00,0x00,0x00,0xa4,0x90,0x00,0x00,0x00,0x00,0x00,0x1e,0x04,0x00, +0x03,0x1e,0x03,0x00,0x09,0x00,0x60,0x10,0x21,0x30,0xa0,0x00,0x00,0x3e,0x07,0x00, +0x03,0x3e,0x07,0x00,0x0b,0x00,0xe3,0x10,0x01,0x00,0xc6,0x24,0x00,0x00,0xc3,0x80, +0x00,0x00,0x00,0x00,0xfb,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24, +0x00,0x00,0x47,0x90,0x00,0x00,0x00,0x00,0xf0,0xff,0xe0,0x14,0x00,0x00,0x00,0x00, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27, +0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x21,0x80,0x80,0x00, +0x1d,0x00,0x80,0x10,0x21,0x88,0xa0,0x00,0x5f,0x47,0x00,0x0c,0x21,0x20,0x00,0x02, +0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02, +0x22,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x83,0x47,0x00,0x0c,0x00,0x00,0x00,0x00, +0x05,0x00,0x40,0x10,0x21,0x18,0x40,0x00,0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00, +0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0xa8,0xb5,0x43,0xac, +0x21,0x18,0x00,0x02,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x00,0x00,0x60,0xa0, +0xb4,0x47,0x00,0x08,0x01,0x00,0x63,0x24,0x02,0x80,0x02,0x3c,0xa8,0xb5,0x50,0x8c, +0x00,0x00,0x00,0x00,0xf3,0xff,0x00,0x12,0x21,0x18,0x00,0x00,0x5f,0x47,0x00,0x0c, +0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02, +0x21,0x20,0x00,0x02,0xe0,0xff,0x40,0x14,0x21,0x18,0x00,0x00,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x80,0x02,0x3c,0xa8,0xb5,0x40,0xac, +0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xe0,0xff,0xbd,0x27, +0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf, +0x00,0x00,0x90,0x8c,0x21,0x90,0x80,0x00,0x21,0x88,0xa0,0x00,0x21,0x18,0x00,0x00, +0x0f,0x00,0x00,0x12,0x21,0x20,0x00,0x02,0x5f,0x47,0x00,0x0c,0x00,0x00,0x00,0x00, +0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02, +0x07,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x83,0x47,0x00,0x0c,0x00,0x00,0x00,0x00, +0x21,0x18,0x40,0x00,0x09,0x00,0x40,0x14,0x00,0x00,0x42,0xae,0x21,0x18,0x00,0x02, +0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x00,0x00,0x42,0x80, +0x00,0x00,0x00,0x00,0xf5,0xff,0x40,0x10,0x01,0x00,0x64,0x24,0x00,0x00,0x60,0xa0, +0xed,0x47,0x00,0x08,0x00,0x00,0x44,0xae,0xd8,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf, +0x21,0x88,0x80,0x00,0x21,0x20,0xa0,0x00,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf, +0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x28,0x47,0x00,0x0c,0x21,0x98,0xa0,0x00, +0x21,0x90,0x40,0x00,0x08,0x00,0x40,0x16,0x21,0x10,0x20,0x02,0x20,0x00,0xbf,0x8f, +0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x28,0x47,0x00,0x0c,0x21,0x20,0x20,0x02, +0x21,0x80,0x40,0x00,0x2a,0x10,0x52,0x00,0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x02,0x21,0x30,0x40,0x02,0x7b,0x46,0x00,0x0c, +0xff,0xff,0x10,0x26,0x0b,0x00,0x40,0x10,0x2a,0x18,0x12,0x02,0xf8,0xff,0x60,0x10, +0x01,0x00,0x31,0x26,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x28,0x00,0xbd,0x27,0x09,0x48,0x00,0x08,0x21,0x10,0x20,0x02,0x01,0x80,0x02,0x3c, +0xa4,0x20,0x43,0x24,0x25,0xb0,0x02,0x3c,0xc0,0xff,0xbd,0x27,0x18,0x03,0x42,0x34, +0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,0x20,0x00,0xb2,0xaf, +0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x43,0xac,0x21,0xa0,0x00,0x00, +0x02,0x80,0x13,0x3c,0x02,0x80,0x15,0x3c,0x02,0x80,0x17,0x3c,0x02,0x80,0x16,0x3c, +0x78,0x1b,0x67,0x26,0xf0,0x23,0xe3,0x94,0x25,0xb0,0x11,0x3c,0x01,0x80,0x05,0x3c, +0x18,0x03,0x24,0x36,0x01,0x00,0x63,0x24,0xa4,0x20,0xa2,0x24,0x00,0x00,0x82,0xac, +0xf0,0x23,0xe3,0xa4,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0xc6,0x00,0x23,0x36,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00, +0x11,0x00,0x42,0x2c,0x08,0x00,0x40,0x14,0x02,0x80,0x03,0x3c,0x02,0x80,0x04,0x3c, +0x44,0x44,0x62,0x8c,0x5c,0x44,0x83,0x8c,0x02,0x80,0x05,0x3c,0x5c,0x44,0x80,0xac, +0x25,0x10,0x43,0x00,0x44,0x44,0xa2,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0xc0,0x02,0x26,0x36,0x00,0x00,0xd2,0x8c,0x00,0x00,0x00,0x00, +0x03,0x00,0x40,0x12,0xff,0x00,0x03,0x3c,0x01,0x00,0x82,0x26,0xff,0xff,0x54,0x30, +0xff,0xff,0x62,0x34,0x2b,0x10,0x52,0x00,0x1d,0x02,0x40,0x10,0x00,0x50,0x82,0x2e, +0x00,0xff,0x02,0x3c,0xff,0x00,0x42,0x34,0x00,0xfd,0x06,0x3c,0x24,0x28,0x42,0x02, +0x14,0x00,0xc2,0x34,0xf7,0x04,0xa2,0x10,0x2b,0x10,0x45,0x00,0x33,0x02,0x40,0x14, +0x00,0xfd,0x04,0x3c,0x00,0xf2,0x08,0x3c,0x01,0x00,0x02,0x35,0x0b,0x05,0xa2,0x10, +0x2b,0x10,0x45,0x00,0xd3,0x02,0x40,0x14,0x00,0xfb,0x04,0x3c,0x00,0xf0,0x04,0x3c, +0x20,0x00,0x82,0x34,0x59,0x05,0xa2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00, +0xfe,0x02,0x40,0x14,0x01,0x00,0x82,0x34,0x68,0x05,0xa2,0x10,0x00,0x00,0x00,0x00, +0x2b,0x10,0x45,0x00,0x07,0x04,0x40,0x14,0x03,0x00,0x82,0x34,0x00,0xe0,0x02,0x3c, +0xb7,0x05,0xa2,0x10,0x00,0xff,0x48,0x32,0xb3,0x04,0xa4,0x10,0xff,0x00,0x02,0x3c, +0x25,0xb0,0x02,0x3c,0xc0,0x02,0x42,0x34,0x21,0xa0,0x00,0x00,0x00,0x00,0x40,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x25,0xb0,0x08,0x3c,0x64,0x03,0x02,0x35,0x00,0x00,0x43,0x94,0x68,0x03,0x04,0x35, +0x90,0x43,0xa3,0xa6,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0xa0,0x43,0xe2,0xae, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x90,0x43,0xa2,0x96, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0xd2,0x01,0x40,0x10,0x78,0x1b,0x66,0x26, +0x78,0x1b,0x67,0x26,0x78,0x1b,0x64,0x8e,0xd8,0x02,0xe5,0x8c,0xe8,0x02,0xe6,0x8c, +0xf0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x00,0x50,0x03,0x3c,0x24,0x28,0xa2,0x00, +0x01,0x00,0x84,0x34,0x24,0x30,0xc3,0x00,0x00,0x10,0x02,0x3c,0x78,0x1b,0x64,0xae, +0x9b,0x04,0xc2,0x10,0xd8,0x02,0xe5,0xac,0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00, +0x02,0x00,0x42,0x30,0xbc,0x01,0x40,0x10,0xf3,0xff,0x03,0x24,0x78,0x1b,0x62,0x8e, +0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,0x04,0x00,0x42,0x34,0x78,0x1b,0x62,0xae, +0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x30,0x49,0x01,0x40,0x10, +0xcf,0xff,0x03,0x24,0x78,0x1b,0x62,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00, +0x10,0x00,0x42,0x34,0x78,0x1b,0x62,0xae,0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00, +0x08,0x00,0x42,0x30,0x48,0x01,0x40,0x14,0x00,0x00,0x00,0x00,0x90,0x43,0xa2,0x96, +0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x30,0x26,0x00,0x40,0x10,0x78,0x1b,0x64,0x26, +0xc9,0x02,0x82,0x90,0xa0,0x43,0xe3,0x8e,0x01,0x00,0x42,0x24,0xc9,0x02,0x82,0xa0, +0x0f,0x00,0x63,0x30,0x01,0x00,0x02,0x24,0xa6,0x04,0x62,0x10,0x02,0x80,0x04,0x3c, +0xa0,0x43,0x82,0x8c,0x02,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0xa5,0x04,0x43,0x10, +0x00,0x00,0x00,0x00,0xa0,0x43,0x82,0x8c,0x03,0x00,0x03,0x24,0x0f,0x00,0x42,0x30, +0x02,0x00,0x43,0x10,0x03,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x15,0x51,0x00,0x0c, +0x00,0x00,0x00,0x00,0xa0,0x43,0xe3,0x8e,0x90,0x43,0xa5,0x96,0x25,0xb0,0x02,0x3c, +0xf0,0x00,0x63,0x30,0x64,0x03,0x42,0x34,0x02,0x19,0x03,0x00,0xef,0x00,0xa5,0x30, +0x78,0x1b,0x64,0x26,0x02,0x00,0x83,0xa0,0x00,0x00,0x45,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x30, +0x26,0x00,0x40,0x10,0x78,0x1b,0x64,0x26,0xca,0x02,0x82,0x90,0xa0,0x43,0xe3,0x8e, +0x01,0x00,0x42,0x24,0xca,0x02,0x82,0xa0,0x0f,0x00,0x63,0x30,0x01,0x00,0x02,0x24, +0x7a,0x04,0x62,0x10,0x02,0x80,0x04,0x3c,0xa0,0x43,0x82,0x8c,0x02,0x00,0x03,0x24, +0x0f,0x00,0x42,0x30,0x79,0x04,0x43,0x10,0x00,0x00,0x00,0x00,0xa0,0x43,0x82,0x8c, +0x03,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x02,0x00,0x43,0x10,0x03,0x00,0x04,0x24, +0x21,0x20,0x00,0x00,0x15,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0xa0,0x43,0xe3,0x8e, +0x90,0x43,0xa5,0x96,0x25,0xb0,0x02,0x3c,0xf0,0x00,0x63,0x30,0x64,0x03,0x42,0x34, +0x02,0x19,0x03,0x00,0xdf,0x00,0xa5,0x30,0x78,0x1b,0x64,0x26,0x02,0x00,0x83,0xa0, +0x00,0x00,0x45,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x90,0x43,0xa2,0x96, +0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x30,0xc4,0x00,0x40,0x10,0x78,0x1b,0x64,0x26, +0x78,0x1b,0x6f,0x26,0x08,0x00,0xe4,0x8d,0x00,0x00,0x00,0x00,0x42,0x17,0x04,0x00, +0x03,0x00,0x42,0x30,0x71,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xa0,0x43,0xe2,0x8e, +0xff,0x9f,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x18,0x83,0x00,0x00,0xff,0x11,0x3c, +0x00,0x20,0x04,0x3c,0x25,0x18,0x64,0x00,0x24,0x10,0x51,0x00,0x08,0x00,0xe3,0xad, +0x98,0x01,0x40,0x14,0x02,0x80,0x10,0x3c,0x25,0xb0,0x0e,0x3c,0x03,0x0d,0xc2,0x35, +0x00,0x00,0x43,0x90,0x10,0x00,0xe4,0x8d,0xff,0x3f,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x58,0x82,0x00,0x70,0x00,0x63,0x30,0x00,0x40,0x02,0x3c,0x56,0x04,0x60,0x10, +0x25,0x58,0x62,0x01,0x94,0x0e,0xc2,0x35,0x9c,0x0e,0xc3,0x35,0xa4,0x0e,0xc4,0x35, +0xac,0x0e,0xc5,0x35,0x00,0x00,0x47,0x8c,0x00,0x00,0x6a,0x8c,0x00,0x00,0x8c,0x8c, +0x00,0x00,0xa6,0x8c,0x0c,0x00,0xe4,0x8d,0xb4,0x0e,0xc2,0x35,0x00,0x00,0x49,0x8c, +0xff,0x03,0x05,0x3c,0x00,0xfc,0x08,0x24,0xbc,0x0e,0xc2,0x35,0x24,0x38,0xe5,0x00, +0x24,0x30,0xc5,0x00,0x24,0x18,0x68,0x01,0x02,0x3c,0x07,0x00,0x00,0x00,0x4b,0x8c, +0x24,0x20,0x88,0x00,0x02,0x34,0x06,0x00,0xcc,0x0e,0xcd,0x35,0xc4,0x0e,0xc8,0x35, +0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x20,0x87,0x00,0x25,0x18,0x66,0x00, +0x00,0x00,0x07,0x8d,0x24,0x50,0x45,0x01,0x00,0x00,0xa6,0x8d,0x24,0x48,0x25,0x01, +0x24,0x18,0x62,0x00,0x24,0x20,0x82,0x00,0x82,0x51,0x0a,0x00,0x82,0x49,0x09,0x00, +0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,0x25,0x20,0x8a,0x00,0x25,0x18,0x69,0x00, +0x24,0x60,0x85,0x01,0x24,0x58,0x65,0x01,0x24,0x18,0x62,0x00,0x24,0x30,0xc5,0x00, +0x00,0x61,0x0c,0x00,0x24,0x20,0x82,0x00,0x00,0x59,0x0b,0x00,0x24,0x38,0xe5,0x00, +0x25,0x20,0x8c,0x00,0x25,0x18,0x6b,0x00,0x02,0x3c,0x07,0x00,0x02,0x34,0x06,0x00, +0x16,0x00,0xe6,0xa5,0x0c,0x00,0xe4,0xad,0x10,0x00,0xe3,0xad,0x14,0x00,0xe7,0xa5, +0x78,0x1b,0x63,0x26,0x0c,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x16,0x04,0x40,0x04, +0x00,0x00,0x00,0x00,0xa0,0x43,0xe2,0x8e,0xff,0x00,0x04,0x3c,0x24,0x10,0x44,0x00, +0x05,0x00,0x40,0x10,0x12,0x00,0x02,0x24,0xa0,0x43,0xe2,0x8e,0x00,0x00,0x00,0x00, +0x24,0x10,0x44,0x00,0x02,0x14,0x02,0x00,0xc3,0x02,0x62,0xa0,0x6c,0x56,0x00,0x0c, +0x10,0x00,0xa4,0x27,0xa7,0x55,0x00,0x0c,0x00,0x00,0x00,0x00,0x78,0x1b,0x62,0x26, +0x0c,0x00,0x43,0x8c,0x00,0x80,0x04,0x3c,0x25,0x18,0x64,0x00,0x0c,0x00,0x43,0xac, +0x78,0x1b,0x62,0x26,0xc3,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,0x61,0x0c,0x63,0x34, +0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x90,0x43,0xa2,0x96, +0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x30,0x52,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x78,0x1b,0x62,0x8e,0x00,0x00,0x00,0x00,0x42,0x10,0x02,0x00,0x01,0x00,0x42,0x30, +0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00, +0x00,0x01,0x42,0x30,0xe6,0x00,0x40,0x14,0x02,0x80,0x02,0x3c,0x78,0x1b,0x62,0x26, +0xea,0x02,0x40,0xa0,0x90,0x43,0xa2,0x96,0x01,0x00,0x03,0x24,0x00,0x02,0x42,0x30, +0xe7,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x78,0x1b,0x62,0x8e,0xfd,0xff,0x03,0x24, +0x24,0x10,0x43,0x00,0x78,0x1b,0x62,0xae,0x25,0xb0,0x04,0x3c,0x4c,0x00,0x83,0x34, +0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x05,0x00,0x40,0x14, +0x01,0x80,0x05,0x3c,0x78,0x1b,0x62,0x8e,0x3f,0xff,0x03,0x24,0x24,0x10,0x43,0x00, +0x78,0x1b,0x62,0xae,0x18,0x03,0x82,0x34,0xa4,0x21,0xa3,0x24,0x00,0x00,0x43,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x70,0x41,0xc2,0x8e,0x70,0x41,0xc3,0x26,0x11,0x00,0x43,0x10,0x02,0x80,0x02,0x3c, +0xbf,0x00,0x92,0x34,0x78,0x1b,0x51,0x24,0x21,0x80,0x60,0x00,0x21,0xf0,0x00,0x00, +0x00,0x00,0x42,0x92,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x2c,0x08,0x00,0x40,0x10, +0x00,0x00,0x00,0x00,0xf8,0x25,0x24,0x8e,0xd9,0x09,0x00,0x0c,0x00,0x00,0x00,0x00, +0x70,0x41,0xc3,0x8e,0x00,0x00,0x00,0x00,0xf5,0xff,0x70,0x14,0x00,0x00,0x00,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c, +0x21,0x28,0x00,0x00,0x08,0x10,0x44,0x24,0x21,0x30,0x00,0x00,0x2d,0x28,0x00,0x0c, +0x21,0x38,0x00,0x00,0x3f,0x48,0x00,0x08,0x78,0x1b,0x67,0x26,0x08,0x00,0x83,0x8c, +0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x08,0x00,0x83,0xac, +0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x30,0xb0,0xff,0x40,0x10, +0x00,0x00,0x00,0x00,0x78,0x1b,0x65,0x26,0xc8,0x02,0xa4,0x8c,0xff,0x0f,0x02,0x3c, +0xff,0xff,0x42,0x34,0x02,0x1f,0x04,0x00,0x01,0x00,0x63,0x24,0x24,0x20,0x82,0x00, +0x00,0x1f,0x03,0x00,0x25,0x20,0x83,0x00,0x76,0x52,0x00,0x0c,0xc8,0x02,0xa4,0xac, +0x90,0x43,0xa3,0x96,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34,0x7f,0x00,0x63,0x30, +0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x9a,0x49,0x00,0x08, +0x00,0x00,0x00,0x00,0x78,0x1b,0x62,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00, +0x78,0x1b,0x62,0xae,0x90,0x43,0xa2,0x96,0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x30, +0xba,0xfe,0x40,0x10,0x00,0x00,0x00,0x00,0x78,0x1b,0x65,0x26,0xc8,0x02,0xa4,0x8c, +0xff,0xf0,0x02,0x3c,0xff,0xff,0x42,0x34,0x02,0x1e,0x04,0x00,0x0f,0x00,0x63,0x30, +0x01,0x00,0x63,0x24,0x0f,0x00,0x63,0x30,0x24,0x20,0x82,0x00,0x00,0x1e,0x03,0x00, +0x25,0x20,0x83,0x00,0xe5,0x50,0x00,0x0c,0xc8,0x02,0xa4,0xac,0x5d,0x52,0x00,0x0c, +0x00,0x00,0x00,0x00,0xa0,0x43,0xe2,0x8e,0x01,0x00,0x03,0x24,0x0f,0x00,0x42,0x30, +0x86,0x05,0x43,0x10,0x02,0x80,0x04,0x3c,0xa0,0x43,0x82,0x8c,0x02,0x00,0x03,0x24, +0x0f,0x00,0x42,0x30,0x83,0x05,0x43,0x10,0x00,0x00,0x00,0x00,0xa0,0x43,0x82,0x8c, +0x03,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x02,0x00,0x43,0x10,0x03,0x00,0x04,0x24, +0x21,0x20,0x00,0x00,0x15,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0x29,0xb0,0x02,0x3c, +0x00,0x00,0x40,0xac,0x08,0x00,0x44,0x34,0x0c,0x00,0x45,0x34,0x10,0x00,0x46,0x34, +0x3c,0x00,0x51,0x34,0x04,0x00,0x43,0x34,0x14,0x00,0x47,0x34,0x18,0x00,0x48,0x34, +0x1c,0x00,0x49,0x34,0x20,0x00,0x4a,0x34,0x24,0x00,0x4b,0x34,0x28,0x00,0x4c,0x34, +0x2c,0x00,0x4d,0x34,0x30,0x00,0x4e,0x34,0x34,0x00,0x4f,0x34,0x38,0x00,0x50,0x34, +0x02,0x80,0x02,0x3c,0x00,0x00,0x60,0xac,0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac, +0xff,0xff,0x04,0x24,0x00,0x00,0xc0,0xac,0x21,0x28,0x00,0x00,0x00,0x00,0xe0,0xac, +0x78,0x1b,0x46,0x24,0x00,0x00,0x00,0xad,0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad, +0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad,0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad, +0x00,0x00,0xe0,0xad,0x00,0x00,0x00,0xae,0x00,0x00,0x20,0xae,0x21,0x18,0xa6,0x00, +0x01,0x00,0xa5,0x24,0x08,0x00,0xa2,0x28,0xfc,0xff,0x40,0x14,0xf0,0x04,0x64,0xa0, +0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24,0x1f,0x00,0x05,0x24,0x90,0x11,0x62,0x8c, +0xff,0xff,0xa5,0x24,0xf0,0x00,0x42,0x34,0x90,0x11,0x62,0xac,0xfb,0xff,0xa1,0x04, +0x94,0x00,0x63,0x24,0x90,0x43,0xa3,0x96,0x25,0xb0,0x02,0x3c,0x64,0x03,0x42,0x34, +0xf7,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0xc5,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x78,0x1b,0x62,0x8e,0xb5,0x48,0x00,0x08, +0x24,0x10,0x43,0x00,0x78,0x1b,0x64,0x8e,0xe8,0x02,0xc5,0x8c,0xfe,0xff,0x02,0x24, +0x00,0x90,0x03,0x3c,0x24,0x20,0x82,0x00,0x24,0x18,0xa3,0x00,0x00,0x10,0x02,0x3c, +0x35,0xfe,0x62,0x14,0x78,0x1b,0x64,0xae,0x50,0x0c,0x03,0x35,0xff,0xbf,0x02,0x3c, +0x00,0x00,0x64,0x90,0xff,0xff,0x42,0x34,0x24,0x10,0xa2,0x00,0x00,0x80,0x03,0x3c, +0x25,0x10,0x43,0x00,0xe8,0x02,0xc2,0xac,0xac,0x48,0x00,0x08,0xdb,0x02,0xc4,0xa0, +0x07,0xfe,0x40,0x14,0xc4,0x02,0x23,0x36,0xff,0xff,0x02,0x24,0x21,0xa0,0x00,0x00, +0x00,0x00,0xc0,0xac,0x00,0x00,0x62,0xac,0x8a,0x48,0x00,0x08,0x00,0x00,0x00,0x00, +0xff,0xff,0x03,0x24,0x78,0x1b,0x42,0x24,0xea,0x02,0x43,0xa0,0x90,0x43,0xa2,0x96, +0x01,0x00,0x03,0x24,0x00,0x02,0x42,0x30,0x1b,0xff,0x43,0x14,0x00,0x00,0x00,0x00, +0x78,0x1b,0x62,0x8e,0x25,0xb0,0x03,0x3c,0x77,0x00,0x04,0x24,0x02,0x00,0x42,0x34, +0x99,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x78,0x1b,0x62,0xae,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0xb1,0x49,0x00,0x08,0x25,0xb0,0x04,0x3c,0xa5,0x00,0x82,0x34, +0xf1,0x02,0xa2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00,0x77,0x00,0x40,0x14, +0x00,0xfe,0x06,0x3c,0x28,0x00,0x82,0x34,0x0b,0x03,0xa2,0x10,0x0f,0x00,0x10,0x3c, +0x2b,0x10,0x45,0x00,0xb4,0x00,0x40,0x14,0xa1,0x00,0x82,0x34,0x18,0x00,0x82,0x34, +0x1c,0x03,0xa2,0x10,0x2b,0x10,0x45,0x00,0x41,0x01,0x40,0x14,0x23,0x00,0x82,0x34, +0x16,0x00,0x82,0x34,0xf2,0x03,0xa2,0x10,0x02,0x14,0x12,0x00,0x17,0x00,0x82,0x34, +0xcf,0xfd,0xa2,0x14,0x25,0xb0,0x04,0x3c,0x68,0x03,0x85,0x34,0x00,0x00,0xa3,0x8c, +0x00,0xff,0x42,0x32,0x00,0x12,0x02,0x00,0xff,0xff,0x74,0x30,0x25,0x10,0x54,0x00, +0x00,0x00,0xa2,0xac,0x64,0x03,0x84,0x34,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00, +0xff,0x00,0x54,0x30,0x40,0x00,0x83,0x36,0x00,0x00,0x83,0xa0,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x25,0xb0,0x04,0x3c,0x94,0x0e,0x82,0x34,0x9c,0x0e,0x83,0x34, +0xa4,0x0e,0x85,0x34,0xac,0x0e,0x86,0x34,0x00,0x00,0x49,0x8c,0x00,0x00,0x6c,0x8c, +0xb4,0x0e,0x82,0x34,0x00,0x00,0xae,0x8c,0x10,0x00,0xe3,0x8d,0x00,0x00,0xc8,0x8c, +0x0c,0x00,0xe5,0x8d,0x00,0x00,0x4a,0x8c,0xff,0x3f,0x02,0x3c,0xff,0x03,0x06,0x3c, +0xff,0xff,0x42,0x34,0x00,0xfc,0x07,0x24,0x24,0x18,0x62,0x00,0x24,0x48,0x26,0x01, +0xbc,0x0e,0x82,0x34,0x24,0x40,0x06,0x01,0x00,0x00,0x4b,0x8c,0x24,0x18,0x67,0x00, +0x24,0x28,0xa7,0x00,0x02,0x44,0x08,0x00,0xcc,0x0e,0x8d,0x34,0x02,0x4c,0x09,0x00, +0xc4,0x0e,0x84,0x34,0xf0,0xff,0x02,0x3c,0x00,0x00,0x87,0x8c,0xff,0x03,0x42,0x34, +0x00,0x00,0xa4,0x8d,0x25,0x18,0x68,0x00,0x25,0x28,0xa9,0x00,0x24,0x60,0x86,0x01, +0x24,0x50,0x46,0x01,0xa0,0x43,0x08,0x8e,0x24,0x18,0x62,0x00,0x24,0x28,0xa2,0x00, +0x82,0x61,0x0c,0x00,0x82,0x51,0x0a,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34, +0x25,0x28,0xac,0x00,0x25,0x18,0x6a,0x00,0x24,0x70,0xc6,0x01,0x24,0x58,0x66,0x01, +0x24,0x18,0x62,0x00,0x24,0x28,0xa2,0x00,0x24,0x20,0x86,0x00,0x00,0x71,0x0e,0x00, +0x00,0x59,0x0b,0x00,0x24,0x38,0xe6,0x00,0xff,0xff,0x02,0x3c,0x25,0x28,0xae,0x00, +0x25,0x18,0x6b,0x00,0x02,0x3c,0x07,0x00,0x02,0x24,0x04,0x00,0x24,0x40,0x02,0x01, +0x0c,0x00,0xe5,0xad,0x10,0x00,0xe3,0xad,0x14,0x00,0xe7,0xa5,0x56,0x00,0x00,0x11, +0x16,0x00,0xe4,0xa5,0xa0,0x43,0x03,0x8e,0xa0,0x43,0x02,0x8e,0x02,0x1c,0x03,0x00, +0x24,0x10,0x51,0x00,0x02,0x16,0x02,0x00,0xc7,0x02,0xe2,0xa1,0xc3,0x02,0xe3,0xa1, +0x6c,0x56,0x00,0x0c,0x10,0x00,0xa4,0x27,0x90,0x43,0xa3,0x96,0x25,0xb0,0x02,0x3c, +0x64,0x03,0x42,0x34,0xbf,0x00,0x63,0x30,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x8b,0x49,0x00,0x08,0x78,0x1b,0x62,0x26,0x10,0x00,0xc2,0x34, +0x7a,0x02,0xa2,0x10,0x2b,0x10,0x45,0x00,0x9a,0x00,0x40,0x14,0x19,0x00,0xc2,0x34, +0xaa,0x00,0x82,0x34,0x12,0x03,0xa2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00, +0x2d,0x01,0x40,0x14,0xae,0x00,0x82,0x34,0xa6,0x00,0x82,0x34,0xdf,0x03,0xa2,0x10, +0x00,0x00,0x00,0x00,0xa7,0x00,0x82,0x34,0x5a,0xfd,0xa2,0x14,0x25,0xb0,0x02,0x3c, +0x00,0xff,0x42,0x32,0x02,0xa2,0x02,0x00,0x02,0x1c,0x12,0x00,0x01,0x00,0x02,0x24, +0x50,0x04,0x82,0x12,0xff,0x00,0x68,0x30,0x02,0x00,0x02,0x24,0x41,0x04,0x82,0x12, +0xc0,0x10,0x08,0x00,0x03,0x00,0x02,0x24,0x4d,0xfd,0x82,0x16,0xc0,0x10,0x08,0x00, +0x21,0x10,0x48,0x00,0x80,0x10,0x02,0x00,0x02,0x80,0x04,0x3c,0x21,0x10,0x48,0x00, +0x08,0x2d,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c, +0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x02,0x00,0x82,0x34,0x65,0x02,0xa2,0x10,0x2b,0x10,0x45,0x00, +0x8b,0x00,0x40,0x14,0x10,0x00,0xc2,0x34,0x00,0xf8,0x03,0x3c,0x17,0x00,0x62,0x34, +0x4b,0x03,0xa2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00,0x0e,0x01,0x40,0x14, +0x15,0x00,0x62,0x34,0x3c,0x04,0xa2,0x10,0x00,0x00,0x00,0x00,0x16,0x00,0x62,0x34, +0x2f,0xfd,0xa2,0x14,0x00,0x00,0x00,0x00,0x58,0x13,0x00,0x0c,0x00,0x00,0x00,0x00, +0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x12,0x00,0x02,0x24,0xc7,0x02,0xe2,0xa1, +0x0e,0x4b,0x00,0x08,0xc3,0x02,0xe2,0xa1,0xd0,0x02,0xa2,0x10,0x00,0x00,0x00,0x00, +0x2b,0x10,0x45,0x00,0x7f,0x00,0x40,0x14,0xa3,0x00,0x82,0x34,0x29,0x00,0x82,0x34, +0xa6,0x03,0xa2,0x10,0xa0,0x00,0x82,0x34,0x1e,0xfd,0xa2,0x14,0x25,0xb0,0x02,0x3c, +0x00,0x0f,0x42,0x32,0x02,0x22,0x02,0x00,0x01,0x00,0x03,0x24,0x3b,0x04,0x83,0x10, +0x00,0x00,0x00,0x00,0x02,0x00,0x02,0x24,0x45,0x04,0x82,0x10,0x00,0x00,0x00,0x00, +0x03,0x00,0x02,0x24,0xff,0x03,0x82,0x10,0x00,0x00,0x00,0x00,0x15,0x51,0x00,0x0c, +0x21,0x20,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xf1,0x04,0x3c, +0x02,0x00,0x82,0x34,0x0a,0xfd,0xa2,0x10,0x2b,0x10,0x45,0x00,0x1c,0x01,0x40,0x14, +0x04,0x00,0x82,0x34,0x44,0x03,0xa4,0x10,0x26,0xb0,0x06,0x3c,0x01,0x00,0x82,0x34, +0x04,0xfd,0xa2,0x14,0x25,0xb0,0x02,0x3c,0x00,0xff,0x42,0x32,0x02,0xf2,0x02,0x00, +0xba,0x03,0xc0,0x13,0x25,0xb0,0x05,0x3c,0x94,0x00,0xa2,0x34,0x00,0x00,0x43,0x94, +0xb0,0x03,0xa6,0x34,0xff,0xff,0xca,0x27,0xff,0xff,0x74,0x30,0x1b,0x00,0x9e,0x02, +0x02,0x00,0xc0,0x17,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x00,0x00,0xd4,0xac, +0x78,0x1b,0x68,0x26,0x01,0x00,0x02,0x24,0xef,0x0a,0x02,0xa1,0x80,0xff,0x02,0x24, +0x4f,0x00,0xab,0x34,0x9e,0x00,0xac,0x34,0xf2,0x0a,0x09,0x95,0x44,0x00,0xa7,0x34, +0xd8,0x00,0xa5,0x34,0x12,0xa0,0x00,0x00,0x80,0x22,0x14,0x00,0x00,0xf8,0x84,0x24, +0x18,0x00,0xd4,0x03,0xff,0xff,0x5e,0x31,0x00,0x19,0x1e,0x00,0x25,0x18,0x62,0x00, +0x26,0xb0,0x02,0x3c,0x00,0x00,0xde,0xac,0x7c,0x00,0x42,0x34,0x00,0x00,0x63,0xa1, +0x00,0x00,0xd4,0xac,0x00,0x00,0x94,0xa5,0x42,0xa1,0x04,0x00,0x00,0x00,0xd4,0xac, +0x00,0x00,0x54,0xa4,0x00,0x00,0xe3,0x94,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00, +0x00,0x00,0xe3,0xa4,0x00,0x00,0xe4,0x94,0x12,0x68,0x00,0x00,0x23,0x48,0x2d,0x01, +0x00,0x02,0x84,0x34,0xf4,0x0a,0x09,0xa5,0x00,0x00,0xe4,0xa4,0x00,0x00,0xa2,0x90, +0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x34,0x00,0x00,0xa2,0xa0,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x35,0x02,0xa2,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00, +0xac,0x00,0x40,0x14,0x12,0x00,0xc2,0x34,0xac,0x02,0xa2,0x10,0x00,0x00,0x00,0x00, +0x2b,0x10,0xa2,0x00,0x2d,0x03,0x40,0x14,0x00,0x00,0x00,0x00,0x18,0x00,0xc2,0x34, +0xbf,0xfc,0xa2,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x78,0x1b,0x62,0x26,0x83,0x0b,0x44,0x90, +0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x26,0x02,0xa2,0x10,0x2b,0x10,0x45,0x00,0xd7,0x00,0x40,0x14,0x12,0x00,0xc2,0x34, +0x03,0x00,0x82,0x34,0x23,0x03,0xa2,0x10,0x07,0x00,0xc2,0x34,0xa8,0xfc,0xa2,0x14, +0x00,0x00,0x00,0x00,0x34,0x59,0x00,0x0c,0x21,0x20,0x40,0x02,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x5f,0x01,0xa2,0x10,0x2b,0x10,0x45,0x00,0x01,0x01,0x40,0x14, +0x78,0x1b,0x63,0x26,0x25,0xb0,0x02,0x3c,0xff,0x00,0x03,0x3c,0xc4,0x02,0x42,0x34, +0x00,0xff,0x63,0x34,0x24,0x18,0x43,0x02,0x00,0x00,0x45,0x8c,0x02,0xf2,0x03,0x00, +0x21,0x52,0x00,0x0c,0x21,0x20,0xc0,0x03,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x9e,0x02,0xa2,0x10,0x2b,0x10,0x45,0x00,0xfb,0x00,0x40,0x14,0x24,0x00,0x82,0x34, +0x19,0x00,0x82,0x34,0x8f,0xfc,0xa2,0x14,0x25,0xb0,0x02,0x3c,0x25,0xb0,0x03,0x3c, +0xc0,0x02,0x62,0x34,0x00,0x00,0x40,0xac,0x94,0x0e,0x64,0x34,0x9c,0x0e,0x62,0x34, +0xa4,0x0e,0x65,0x34,0xac,0x0e,0x66,0x34,0x00,0x00,0x89,0x8c,0x78,0x1b,0x6f,0x26, +0x00,0x00,0x4b,0x8c,0x00,0x00,0xac,0x8c,0x00,0x00,0xc4,0x8c,0xb4,0x0e,0x62,0x34, +0x0c,0x00,0xe5,0x8d,0x10,0x00,0xe6,0x8d,0x00,0x00,0x4a,0x8c,0xff,0x03,0x07,0x3c, +0x00,0xfc,0x08,0x24,0xbc,0x0e,0x62,0x34,0x24,0x48,0x27,0x01,0x24,0x20,0x87,0x00, +0x00,0x00,0x4d,0x8c,0x24,0x30,0xc8,0x00,0x02,0x4c,0x09,0x00,0x24,0x28,0xa8,0x00, +0x02,0x24,0x04,0x00,0xcc,0x0e,0x68,0x34,0xf0,0xff,0x02,0x3c,0xc4,0x0e,0x63,0x34, +0xff,0x03,0x42,0x34,0x25,0x28,0xa9,0x00,0x25,0x30,0xc4,0x00,0x00,0x00,0x69,0x8c, +0x08,0x00,0xe4,0x8d,0x00,0x00,0x0e,0x8d,0x24,0x58,0x67,0x01,0x24,0x50,0x47,0x01, +0x24,0x30,0xc2,0x00,0x24,0x28,0xa2,0x00,0x82,0x59,0x0b,0x00,0x82,0x51,0x0a,0x00, +0x0f,0xc0,0x03,0x3c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x63,0x34,0xff,0xff,0x42,0x34, +0x25,0x28,0xab,0x00,0x25,0x30,0xca,0x00,0x24,0x60,0x87,0x01,0x24,0x68,0xa7,0x01, +0xff,0x00,0x08,0x3c,0x24,0x20,0x82,0x00,0x24,0x30,0xc3,0x00,0x24,0x28,0xa3,0x00, +0x24,0x70,0xc7,0x01,0x00,0x61,0x0c,0x00,0x00,0x69,0x0d,0x00,0x24,0x48,0x27,0x01, +0x00,0xff,0x03,0x35,0x00,0x20,0x02,0x3c,0x25,0x20,0x82,0x00,0x25,0x28,0xac,0x00, +0x25,0x30,0xcd,0x00,0x02,0x4c,0x09,0x00,0x02,0x74,0x0e,0x00,0x24,0x18,0x43,0x02, +0x08,0x00,0xe4,0xad,0x0c,0x00,0xe5,0xad,0x10,0x00,0xe6,0xad,0x14,0x00,0xe9,0xa5, +0x55,0x03,0x60,0x10,0x16,0x00,0xee,0xa5,0x24,0x10,0x48,0x02,0x02,0x14,0x02,0x00, +0x02,0x1a,0x12,0x00,0xc7,0x02,0xe2,0xa1,0xc3,0x02,0xe3,0xa1,0x78,0x1b,0x62,0x26, +0xc3,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c,0x61,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x6c,0x56,0x00,0x0c,0x10,0x00,0xa4,0x27, +0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x92,0x02,0xa2,0x10,0x00,0x00,0x00,0x00, +0x2b,0x10,0x45,0x00,0x82,0x00,0x40,0x14,0xaf,0x00,0x82,0x34,0xab,0x00,0x82,0x34, +0x2b,0xfc,0xa2,0x14,0x00,0x00,0x00,0x00,0x54,0x5a,0x00,0x0c,0x21,0x20,0x40,0x02, +0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x3d,0x02,0xa4,0x10,0x2b,0x10,0x85,0x00, +0x87,0x00,0x40,0x14,0x78,0x1b,0x62,0x26,0x18,0x00,0x62,0x34,0x20,0xfc,0xa2,0x14, +0x00,0x00,0x00,0x00,0xb1,0x13,0x00,0x0c,0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x00,0xff,0x03,0x3c,0x0f,0x00,0x62,0x34,0x0d,0x02,0xa2,0x10, +0x2b,0x10,0x45,0x00,0x70,0x00,0x40,0x14,0x10,0x00,0x62,0x34,0x1a,0x00,0xc2,0x34, +0x14,0xfc,0xa2,0x14,0x25,0xb0,0x02,0x3c,0xff,0x00,0x02,0x3c,0x00,0xff,0x42,0x34, +0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,0x01,0x00,0x03,0x24,0x28,0x03,0xc3,0x13, +0x78,0x1b,0x62,0x26,0x02,0x00,0xc2,0x2b,0x1f,0x03,0x40,0x14,0x03,0x00,0x02,0x24, +0x19,0x03,0xc2,0x13,0x00,0x00,0x00,0x00,0x78,0x1b,0x62,0x26,0x7c,0x0b,0x44,0x94, +0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0xcd,0x01,0xa2,0x10,0x2b,0x10,0xa2,0x00,0x7b,0x00,0x40,0x14, +0x02,0x14,0x12,0x00,0x08,0x00,0x82,0x34,0xfa,0xfb,0xa2,0x14,0x25,0xb0,0x02,0x3c, +0x00,0xff,0x42,0x32,0x02,0x92,0x02,0x00,0x05,0x00,0x40,0x12,0x21,0x20,0x00,0x00, +0x01,0x00,0x02,0x24,0x02,0x00,0x42,0x12,0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00, +0x95,0x42,0x00,0x0c,0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c, +0xe8,0x01,0xa2,0x10,0x2b,0x10,0xa2,0x00,0x68,0x02,0x40,0x14,0x00,0x00,0x00,0x00, +0xe8,0xfb,0xa8,0x14,0x25,0xb0,0x02,0x3c,0x25,0xb0,0x05,0x3c,0xc4,0x02,0xa3,0x34, +0x00,0x00,0x64,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x90,0x82,0x00, +0x01,0x00,0x03,0x3c,0x2b,0x18,0x72,0x00,0xdd,0xfb,0x60,0x10,0x00,0xb0,0x02,0x3c, +0x25,0x90,0x42,0x02,0x00,0x00,0x54,0x8e,0xc8,0x02,0xa2,0x34,0x00,0x00,0x54,0xac, +0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x75,0x02,0xa2,0x10,0x2b,0x10,0x45,0x00, +0x66,0x00,0x40,0x14,0x02,0x1c,0x12,0x00,0x1f,0x00,0x68,0x30,0xc0,0x10,0x08,0x00, +0x21,0x10,0x48,0x00,0x80,0x10,0x02,0x00,0x25,0xb0,0x04,0x3c,0x21,0x10,0x48,0x00, +0x02,0x80,0x03,0x3c,0xc8,0x02,0x85,0x34,0x78,0x1b,0x63,0x24,0xc4,0x02,0x84,0x34, +0x80,0x10,0x02,0x00,0x00,0x00,0x94,0x8c,0x21,0x48,0x43,0x00,0x00,0x00,0xa7,0x8c, +0x21,0x58,0x80,0x00,0x21,0x28,0x00,0x00,0xff,0x00,0x0a,0x24,0x29,0xb0,0x06,0x3c, +0x21,0x20,0xa3,0x00,0xf0,0x04,0x82,0x90,0x00,0x00,0x00,0x00,0x6a,0x02,0x4a,0x10, +0x00,0x00,0x00,0x00,0x68,0x02,0x48,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xa5,0x24, +0x08,0x00,0xa2,0x28,0xf6,0xff,0x40,0x14,0x08,0x00,0xc6,0x24,0x08,0x00,0x02,0x24, +0xb3,0xfb,0xa2,0x14,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xff,0xff,0x03,0x24, +0xc4,0x02,0x42,0x34,0x00,0x00,0x43,0xac,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c, +0xab,0xfb,0xa2,0x14,0x00,0x00,0x00,0x00,0xe5,0x50,0x00,0x0c,0x00,0x00,0x00,0x00, +0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0xa6,0xfb,0xa2,0x14,0x25,0xb0,0x02,0x3c, +0x00,0xff,0x43,0x32,0x00,0xff,0x02,0x34,0x5f,0x00,0x62,0x14,0x78,0x1b,0x62,0x26, +0x78,0x1b,0x63,0x26,0xff,0xff,0x02,0x34,0x86,0x48,0x00,0x08,0xec,0x25,0x62,0xac, +0x04,0x24,0x43,0x8c,0xfd,0xff,0x04,0x24,0x24,0x18,0x64,0x00,0x01,0x00,0x63,0x34, +0x86,0x48,0x00,0x08,0x04,0x24,0x43,0xac,0x96,0xfb,0xa2,0x14,0x25,0xb0,0x02,0x3c, +0x78,0x1b,0x65,0x26,0xd8,0x02,0xa3,0x8c,0x0f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x12,0x01,0x04,0x3c,0x25,0xb0,0x02,0x3c,0x0c,0x09,0x42,0x34, +0x13,0x13,0x84,0x34,0xd8,0x02,0xa3,0xac,0x00,0x00,0x44,0xac,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0x43,0x32, +0xff,0x00,0x5e,0x30,0x04,0x00,0xc0,0x13,0x02,0x92,0x03,0x00,0x01,0x00,0x02,0x24, +0x02,0x00,0xc2,0x13,0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x95,0x42,0x00,0x0c, +0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xe3,0x44,0x00,0x0c,0x21,0x20,0x40,0x02, +0xff,0xff,0x10,0x36,0x24,0xa0,0x50,0x00,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34, +0x00,0x00,0x54,0xac,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x1f,0x00,0x68,0x30, +0xc0,0x10,0x08,0x00,0x21,0x10,0x48,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x48,0x00, +0x80,0x10,0x02,0x00,0x78,0x1b,0x64,0x26,0x21,0x30,0x44,0x00,0x90,0x11,0xc3,0x90, +0x0f,0x00,0x02,0x24,0x02,0x29,0x03,0x00,0xaf,0xff,0xa2,0x10,0x21,0x18,0xa4,0x00, +0xf0,0x04,0x62,0x90,0x00,0x00,0x00,0x00,0xab,0xff,0x48,0x14,0xc0,0x20,0x05,0x00, +0xff,0xff,0x02,0x24,0xf0,0x04,0x62,0xa0,0x90,0x11,0xc3,0x8c,0x29,0xb0,0x02,0x3c, +0x21,0x20,0x82,0x00,0x25,0xb0,0x02,0x3c,0xf0,0x00,0x63,0x34,0xc4,0x02,0x42,0x34, +0x90,0x11,0xc3,0xac,0x00,0x00,0x80,0xac,0x04,0x00,0x80,0xac,0x00,0x00,0x45,0xac, +0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0x42,0x34,0x24,0x10,0x42,0x02, +0x25,0xb0,0x03,0x3c,0x02,0x92,0x02,0x00,0x21,0x10,0x43,0x02,0x00,0x00,0x54,0x8c, +0xc4,0x02,0x63,0x34,0x00,0x00,0x74,0xac,0x00,0x00,0x54,0x8c,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x78,0x1b,0x62,0x26,0x86,0x48,0x00,0x08,0xec,0x25,0x40,0xac, +0xdb,0x02,0xe3,0x90,0x50,0x0c,0x02,0x35,0x21,0x28,0x00,0x00,0x00,0x00,0x43,0xa0, +0x01,0x00,0xa2,0x24,0xff,0x00,0x45,0x30,0x06,0x00,0xa3,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0xa2,0x24,0x78,0x1b,0x62,0x26,0xdb,0x02,0x44,0x90,0x25,0xb0,0x03,0x3c, +0x58,0x0c,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x78,0x1b,0x65,0x26,0xe8,0x02,0xa3,0x8c,0x00,0x40,0x04,0x3c,0xff,0x7f,0x02,0x3c, +0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0xac,0x48,0x00,0x08, +0xe8,0x02,0xa3,0xac,0x00,0xff,0x62,0x34,0x24,0x10,0x42,0x02,0x21,0xfb,0x40,0x10, +0x25,0xb0,0x02,0x3c,0x08,0x03,0xe5,0x90,0x24,0x18,0x43,0x02,0x00,0xff,0x44,0x32, +0x02,0x1c,0x03,0x00,0x02,0x22,0x04,0x00,0x00,0x01,0xa5,0x34,0xfb,0xff,0x66,0x24, +0xfb,0xff,0x82,0x24,0x23,0x03,0xe2,0xa0,0x08,0x03,0xe5,0xac,0x21,0x03,0xe6,0xa0, +0x20,0x03,0xe3,0xa0,0x86,0x48,0x00,0x08,0x22,0x03,0xe4,0xa0,0x07,0x49,0x00,0x08, +0x01,0x00,0x04,0x24,0xdd,0x48,0x00,0x08,0x01,0x00,0x04,0x24,0x07,0x49,0x00,0x08, +0x02,0x00,0x04,0x24,0xdd,0x48,0x00,0x08,0x02,0x00,0x04,0x24,0xc4,0x02,0x23,0x36, +0x00,0x00,0x64,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x90,0x82,0x00, +0x01,0x00,0x03,0x3c,0x2b,0x18,0x72,0x00,0x01,0xfb,0x60,0x10,0xc8,0x02,0x22,0x36, +0x00,0x00,0x54,0x8c,0x00,0xb0,0x03,0x3c,0x25,0x90,0x43,0x02,0x00,0x00,0x54,0xae, +0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x6c,0x56,0x00,0x0c,0x10,0x00,0xa4,0x27, +0x8b,0x49,0x00,0x08,0x78,0x1b,0x62,0x26,0x76,0x52,0x00,0x0c,0x10,0x00,0xeb,0xad, +0x73,0x49,0x00,0x08,0x78,0x1b,0x63,0x26,0x24,0x20,0x43,0x02,0x5b,0x52,0x00,0x0c, +0x02,0x24,0x04,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x82,0x0b,0xe2,0x90, +0x00,0x00,0x00,0x00,0x31,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0xff,0x62,0x34, +0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,0x01,0x00,0x02,0x24,0x21,0x20,0xc0,0x03, +0x82,0x0b,0xe2,0xa0,0x2c,0x22,0x00,0x0c,0x83,0x0b,0xfe,0xa0,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x04,0x24,0xe2,0x8c,0xfe,0xff,0x03,0x24,0x02,0x00,0x42,0x34,0x24,0x10,0x43,0x00, +0x86,0x48,0x00,0x08,0x04,0x24,0xe2,0xac,0xff,0xff,0x05,0x36,0x60,0x00,0x06,0x24, +0xb8,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0x9c,0x12,0x00,0x0c,0xe8,0x03,0x04,0x24, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x24,0x00,0x04,0x24,0xe3,0x44,0x00,0x0c,0xff,0xff,0x05,0x36,0x1f,0x00,0x54,0x30, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcb,0x12,0x00,0x0c, +0x64,0x00,0x04,0x24,0xc4,0x02,0x22,0x36,0x00,0x00,0x54,0xa0,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x08,0x00,0xe3,0x8c,0xff,0x9f,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x86,0x48,0x00,0x08,0x08,0x00,0xe3,0xac,0xc8,0x02,0xe4,0x8c, +0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0x02,0x1f,0x04,0x00,0x01,0x00,0x63,0x24, +0x24,0x20,0x82,0x00,0x00,0x1f,0x03,0x00,0x25,0x20,0x83,0x00,0xc8,0x02,0xe4,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x76,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0x62,0x34, +0xc4,0x02,0x24,0x36,0x00,0x00,0x94,0x8c,0x24,0x10,0x42,0x02,0x02,0x92,0x02,0x00, +0x21,0x18,0x51,0x02,0x00,0x00,0x74,0xac,0x00,0x00,0x74,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0x94,0xac,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x82,0x0b,0xe3,0x90, +0xc4,0x02,0x22,0x36,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x29,0xb0,0x02,0x3c, +0x00,0x00,0x40,0xac,0x04,0x00,0x44,0x34,0x08,0x00,0x45,0x34,0x0c,0x00,0x46,0x34, +0x3c,0x00,0x43,0x34,0x10,0x00,0x47,0x34,0x14,0x00,0x48,0x34,0x18,0x00,0x49,0x34, +0x1c,0x00,0x4a,0x34,0x20,0x00,0x4b,0x34,0x24,0x00,0x4c,0x34,0x28,0x00,0x4d,0x34, +0x2c,0x00,0x4e,0x34,0x30,0x00,0x4f,0x34,0x34,0x00,0x50,0x34,0x38,0x00,0x51,0x34, +0x02,0x80,0x02,0x3c,0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac,0xff,0xff,0x04,0x24, +0x00,0x00,0xc0,0xac,0x21,0x28,0x00,0x00,0x00,0x00,0xe0,0xac,0x78,0x1b,0x46,0x24, +0x00,0x00,0x00,0xad,0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad,0x00,0x00,0x60,0xad, +0x00,0x00,0x80,0xad,0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad,0x00,0x00,0xe0,0xad, +0x00,0x00,0x00,0xae,0x00,0x00,0x20,0xae,0x00,0x00,0x60,0xac,0x21,0x18,0xa6,0x00, +0x01,0x00,0xa5,0x24,0x08,0x00,0xa2,0x28,0xfc,0xff,0x40,0x14,0xf0,0x04,0x64,0xa0, +0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24,0x1f,0x00,0x05,0x24,0x90,0x11,0x62,0x8c, +0xff,0xff,0xa5,0x24,0xf0,0x00,0x42,0x34,0x90,0x11,0x62,0xac,0xfb,0xff,0xa1,0x04, +0x94,0x00,0x63,0x24,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x24,0x20,0x43,0x02, +0xc6,0x15,0x00,0x0c,0x02,0x24,0x04,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x6e,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x02,0x1a,0x08,0x00,0xff,0x00,0x02,0x24,0x2b,0x01,0x62,0x10,0x25,0xb0,0x05,0x3c, +0x0e,0x00,0x60,0x14,0x00,0xcc,0x02,0x34,0x25,0xb0,0x04,0x3c,0x64,0x03,0x84,0x34, +0x78,0x1b,0x67,0x26,0x00,0x00,0x85,0x94,0xe8,0x02,0xe6,0x8c,0xff,0xef,0x02,0x3c, +0xff,0xfe,0x03,0x24,0xff,0xff,0x42,0x34,0x24,0x28,0xa3,0x00,0x24,0x30,0xc2,0x00, +0x00,0x00,0x85,0xa4,0xe8,0x02,0xe6,0xac,0x00,0xcc,0x02,0x34,0x39,0xfa,0x02,0x15, +0x25,0xb0,0x02,0x3c,0x78,0x1b,0x62,0x26,0xe8,0x02,0x43,0x8c,0x00,0x10,0x04,0x3c, +0x25,0x18,0x64,0x00,0x86,0x48,0x00,0x08,0xe8,0x02,0x43,0xac,0x24,0x10,0x43,0x02, +0x02,0xf4,0x02,0x00,0x00,0xff,0x43,0x32,0x04,0x00,0xc0,0x13,0x02,0x92,0x03,0x00, +0x01,0x00,0x02,0x24,0x02,0x00,0xc2,0x13,0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00, +0x25,0xb0,0x10,0x3c,0x95,0x42,0x00,0x0c,0xc4,0x02,0x10,0x36,0x00,0x00,0x14,0x8e, +0x0f,0x00,0x11,0x3c,0x21,0x20,0x40,0x02,0x21,0x30,0x80,0x02,0xb8,0x44,0x00,0x0c, +0xff,0xff,0x25,0x36,0x21,0x20,0x40,0x02,0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36, +0x00,0x00,0x02,0xae,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0xff,0x62,0x34, +0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,0x78,0x1b,0x63,0x26,0x83,0x0b,0x7e,0xa0, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xff,0x00,0x02,0x24,0x56,0x01,0x63,0x34, +0x00,0x00,0x62,0xa4,0x01,0x00,0x04,0x24,0x02,0x80,0x02,0x3c,0x86,0x48,0x00,0x08, +0x80,0x43,0x44,0xa0,0x24,0x10,0x43,0x02,0x02,0xa4,0x02,0x00,0x00,0xff,0x43,0x32, +0x07,0x00,0x82,0x2e,0xfe,0xf9,0x40,0x10,0x02,0xf2,0x03,0x00,0x02,0x80,0x04,0x3c, +0xbc,0xaf,0x83,0x24,0x80,0x10,0x14,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c, +0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x78,0x1b,0x65,0x26, +0xd8,0x02,0xa3,0x8c,0x0f,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x10,0x00,0x04,0x3c,0x25,0x18,0x64,0x00,0x86,0x48,0x00,0x08,0xd8,0x02,0xa3,0xac, +0xe4,0x13,0x00,0x0c,0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x78,0x1b,0x65,0x26,0x04,0x24,0xa2,0x8c,0xfd,0xff,0x03,0x24,0xfe,0xff,0x04,0x24, +0x24,0x10,0x43,0x00,0x24,0x10,0x44,0x00,0x86,0x48,0x00,0x08,0x04,0x24,0xa2,0xac, +0x1f,0x00,0x48,0x30,0xc0,0x18,0x08,0x00,0x21,0x18,0x68,0x00,0x00,0x0f,0x45,0x32, +0x80,0x18,0x03,0x00,0x02,0x2a,0x05,0x00,0x78,0x1b,0x64,0x26,0x25,0xb0,0x02,0x3c, +0x21,0x18,0x68,0x00,0x21,0x30,0xa4,0x00,0xc8,0x02,0x47,0x34,0x80,0x18,0x03,0x00, +0xc4,0x02,0x42,0x34,0x00,0x00,0x54,0x8c,0x21,0x18,0x64,0x00,0x00,0x00,0xe7,0x8c, +0xf0,0x04,0xc8,0xa0,0x90,0x11,0x64,0x8c,0x0f,0xff,0x02,0x24,0xc0,0x30,0x05,0x00, +0x24,0x20,0x82,0x00,0x00,0x29,0x05,0x00,0x29,0xb0,0x02,0x3c,0x21,0x30,0xc2,0x00, +0x25,0x20,0x85,0x00,0x90,0x11,0x64,0xac,0x00,0x00,0xd4,0xac,0x04,0x00,0xc7,0xac, +0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0xff,0x65,0x34,0x24,0x28,0x45,0x02, +0x25,0xb0,0x04,0x3c,0x02,0x2a,0x05,0x00,0x94,0x00,0x83,0x34,0x40,0x11,0x05,0x00, +0x00,0x00,0x65,0xa4,0xc0,0xff,0x54,0x24,0x7c,0x00,0xcc,0x34,0x04,0x00,0x07,0x24, +0x9a,0x00,0x88,0x34,0x98,0x00,0x89,0x34,0x96,0x00,0x8a,0x34,0x7a,0x00,0xc6,0x34, +0xb0,0x03,0x8b,0x34,0x00,0x04,0x02,0x24,0xa0,0x00,0x03,0x24,0x00,0x00,0x02,0xa5, +0x44,0x00,0x84,0x34,0x00,0x00,0x23,0xa5,0x00,0x00,0x47,0xa5,0x00,0x00,0xc7,0xa0, +0x00,0x00,0x74,0xad,0x00,0x00,0x94,0xa5,0x00,0x00,0x83,0x94,0xff,0xfd,0x02,0x24, +0x78,0x1b,0x66,0x26,0x24,0x18,0x62,0x00,0x00,0x00,0x83,0xa4,0x00,0x00,0x82,0x94, +0xf2,0x0a,0xc5,0xa4,0x00,0x02,0x42,0x34,0x00,0x00,0x82,0xa4,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x24,0x20,0x43,0x02,0x00,0xff,0x45,0x32,0x02,0x24,0x04,0x00, +0x97,0x50,0x00,0x0c,0x02,0x2a,0x05,0x00,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34, +0x00,0x00,0x62,0xa0,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xff,0x00,0x02,0x3c, +0x00,0xff,0x42,0x34,0x24,0x10,0x42,0x02,0x02,0xf2,0x02,0x00,0x78,0x1b,0x63,0x26, +0x21,0x20,0xc0,0x03,0x2c,0x22,0x00,0x0c,0x82,0x0b,0x60,0xa0,0xa9,0x4d,0x00,0x08, +0x00,0x00,0x00,0x00,0x78,0x1b,0x63,0x26,0x04,0x24,0x62,0x8c,0x00,0x00,0x00,0x00, +0x03,0x00,0x42,0x34,0x86,0x48,0x00,0x08,0x04,0x24,0x62,0xac,0x6f,0x0b,0x00,0x0c, +0x21,0x20,0xc0,0x03,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x5d,0x52,0x00,0x0c, +0x00,0x00,0x00,0x00,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x02,0x1c,0x12,0x00, +0x00,0x1f,0x42,0x32,0x78,0x1b,0x70,0x26,0x02,0xa2,0x02,0x00,0x3f,0x00,0x67,0x30, +0xc1,0x02,0x07,0xa2,0xbc,0x02,0x14,0xa2,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x22,0x1b,0x00,0x0c,0x00,0x00,0x00,0x00, +0x21,0xa0,0x40,0x00,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x00,0x00,0x54,0xac, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x03,0x00,0x02,0x92, +0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0x86,0x48,0x00,0x08,0x03,0x00,0x02,0xa2, +0x24,0x18,0x43,0x02,0x02,0x44,0x03,0x00,0xc0,0x10,0x08,0x00,0x21,0x10,0x48,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x48,0x00,0x00,0xff,0x44,0x32,0x80,0x10,0x02,0x00, +0x78,0x1b,0x63,0x26,0x21,0x10,0x43,0x00,0x02,0xa1,0x04,0x00,0x80,0x11,0x54,0xac, +0x86,0x48,0x00,0x08,0x84,0x11,0x54,0xac,0xf0,0x04,0x88,0xa0,0x90,0x11,0x22,0x8d, +0x0f,0x00,0xa3,0x30,0x0f,0xff,0x04,0x24,0x00,0x19,0x03,0x00,0x24,0x10,0x44,0x00, +0x25,0x10,0x43,0x00,0x90,0x11,0x22,0xad,0x00,0x00,0xd4,0xac,0x04,0x00,0xc7,0xac, +0x00,0x00,0x65,0xad,0xd2,0x4c,0x00,0x08,0x08,0x00,0x02,0x24,0x4f,0x00,0xa2,0x34, +0x9e,0x00,0xa3,0x34,0x00,0x00,0x40,0xa0,0x00,0x00,0x60,0xa4,0x94,0x00,0xa2,0x34, +0x00,0x00,0x43,0x94,0x9a,0x00,0xa4,0x34,0x98,0x00,0xa6,0x34,0xff,0xff,0x74,0x30, +0x80,0x12,0x14,0x00,0x00,0xf8,0x42,0x24,0x42,0xa1,0x02,0x00,0x00,0x14,0x02,0x24, +0x00,0x00,0x82,0xa4,0x26,0xb0,0x02,0x3c,0xb0,0x03,0xa7,0x34,0xa0,0x80,0x03,0x24, +0x7c,0x00,0x42,0x34,0x00,0x00,0xc3,0xa4,0x44,0x00,0xa4,0x34,0x00,0x00,0xf4,0xac, +0x00,0x00,0x54,0xa4,0x00,0x00,0x83,0x94,0xff,0xfd,0x02,0x24,0xd8,0x00,0xa5,0x34, +0x24,0x18,0x62,0x00,0x00,0x00,0x83,0xa4,0x00,0x00,0x82,0x94,0x78,0x1b,0x66,0x26, +0x00,0x02,0x42,0x34,0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,0xbf,0xff,0x02,0x24, +0xf4,0x0a,0xc0,0xa4,0x24,0x18,0x62,0x00,0xef,0x0a,0xc0,0xa0,0x00,0x00,0xa3,0xa0, +0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x64,0x03,0xa5,0x34,0x78,0x1b,0x66,0x26, +0x00,0x00,0xa3,0x94,0xe8,0x02,0xc4,0x8c,0xff,0xef,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x20,0x82,0x00,0x00,0x01,0x63,0x34,0x00,0x00,0xa3,0xa4,0x4c,0x4e,0x00,0x08, +0xe8,0x02,0xc4,0xac,0x15,0x51,0x00,0x0c,0x03,0x00,0x04,0x24,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0x21,0x10,0x48,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x48,0x00, +0x78,0x1b,0x63,0x26,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x8c,0x11,0x44,0x8c, +0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac,0x87,0x48,0x00,0x08, +0x25,0xb0,0x02,0x3c,0xc0,0x10,0x08,0x00,0x21,0x10,0x48,0x00,0x80,0x10,0x02,0x00, +0x21,0x10,0x48,0x00,0x78,0x1b,0x63,0x26,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00, +0x88,0x11,0x44,0x8c,0x25,0xb0,0x03,0x3c,0xc4,0x02,0x63,0x34,0x00,0x00,0x64,0xac, +0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x1e,0x13,0x00,0x0c,0x00,0x00,0x00,0x00, +0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x12,0x00,0x02,0x24,0xc7,0x02,0xe2,0xa1, +0x45,0x4c,0x00,0x08,0xc3,0x02,0xe2,0xa1,0x78,0x1b,0x62,0x26,0x7e,0x0b,0x44,0x94, +0x43,0x4b,0x00,0x08,0x25,0xb0,0x03,0x3c,0xe3,0xfc,0xc0,0x17,0x25,0xb0,0x03,0x3c, +0x78,0x1b,0x62,0x26,0x78,0x0b,0x44,0x94,0x44,0x4b,0x00,0x08,0xc4,0x02,0x63,0x34, +0x7a,0x0b,0x44,0x94,0x43,0x4b,0x00,0x08,0x25,0xb0,0x03,0x3c,0x2b,0x4a,0x00,0x08, +0x01,0x00,0x04,0x24,0x2b,0x4a,0x00,0x08,0x02,0x00,0x04,0x24,0x15,0x51,0x00,0x0c, +0x01,0x00,0x04,0x24,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x19,0x1e,0x00, +0x78,0x1b,0x62,0x26,0x21,0x18,0x62,0x00,0x36,0x03,0x64,0x94,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x00,0x00,0x44,0xac,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x15,0x51,0x00,0x0c,0x02,0x00,0x04,0x24,0x87,0x48,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x00,0x19,0x1e,0x00,0x78,0x1b,0x62,0x26,0x21,0x18,0x62,0x00,0x35,0x03,0x64,0x90, +0xb2,0x4f,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x19,0x1e,0x00,0x78,0x1b,0x62,0x26, +0x21,0x18,0x62,0x00,0x34,0x03,0x64,0x90,0xb2,0x4f,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x00,0x19,0x1e,0x00,0x78,0x1b,0x62,0x26,0x21,0x18,0x62,0x00,0x32,0x03,0x64,0x94, +0xb2,0x4f,0x00,0x08,0x25,0xb0,0x02,0x3c,0x00,0x19,0x1e,0x00,0x78,0x1b,0x62,0x26, +0x21,0x18,0x62,0x00,0x30,0x03,0x64,0x94,0xb2,0x4f,0x00,0x08,0x25,0xb0,0x02,0x3c, +0x00,0x11,0x1e,0x00,0x78,0x1b,0x63,0x26,0x21,0x10,0x43,0x00,0x2c,0x03,0x44,0x8c, +0xb1,0x4f,0x00,0x08,0x42,0x26,0x04,0x00,0x00,0x11,0x1e,0x00,0x78,0x1b,0x63,0x26, +0x21,0x10,0x43,0x00,0x2f,0x03,0x44,0x90,0xb1,0x4f,0x00,0x08,0x01,0x00,0x84,0x30, +0x25,0xb0,0x05,0x3c,0x01,0x00,0x06,0x24,0x01,0x80,0x02,0x3c,0x04,0x30,0x86,0x00, +0xf1,0x02,0xa7,0x34,0xed,0x02,0xa4,0x34,0x78,0x3f,0x42,0x24,0x18,0x03,0xa5,0x34, +0x08,0x00,0x03,0x24,0x00,0x00,0xa2,0xac,0x00,0x00,0xe3,0xa0,0x00,0x00,0x80,0xa0, +0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0, +0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0, +0x00,0x00,0xe0,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c, +0x25,0xb0,0x03,0x3c,0xd4,0x3f,0x42,0x24,0x18,0x03,0x63,0x34,0x00,0x00,0x62,0xac, +0x00,0x00,0x83,0x90,0x30,0x00,0x02,0x24,0x05,0x00,0x62,0x10,0x21,0x20,0x00,0x00, +0x31,0x00,0x02,0x24,0x02,0x00,0x62,0x10,0x01,0x00,0x04,0x24,0x07,0x00,0x04,0x24, +0xde,0x4f,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c, +0x10,0x40,0x42,0x24,0x18,0x03,0x63,0x34,0x02,0x80,0x04,0x3c,0x00,0x00,0x62,0xac, +0x08,0x00,0xe0,0x03,0x8c,0x43,0x80,0xac,0x02,0x80,0x03,0x3c,0x98,0x41,0x62,0x8c, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,0x80,0x80,0x10,0x00, +0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x78,0x1b,0x42,0x24,0x80,0x80,0x10,0x00, +0x21,0x80,0x02,0x02,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf, +0x90,0x11,0x05,0x8e,0xff,0x1f,0x02,0x3c,0x25,0xb0,0x12,0x3c,0xff,0xff,0x42,0x34, +0xf8,0xff,0x03,0x24,0x88,0x11,0x02,0xae,0x84,0x01,0x46,0x36,0x24,0x28,0xa3,0x00, +0xff,0xfe,0x02,0x24,0x00,0x00,0xc7,0x8c,0x24,0x28,0xa2,0x00,0xff,0xef,0x03,0x24, +0xff,0xff,0x02,0x3c,0xff,0x1f,0x42,0x34,0x24,0x28,0xa3,0x00,0x24,0x28,0xa2,0x00, +0x8c,0x11,0x07,0xae,0x90,0x11,0x05,0xae,0x96,0x15,0x00,0x0c,0x21,0x88,0x80,0x00, +0x92,0x11,0x02,0x92,0x21,0x88,0x32,0x02,0x1c,0x00,0xbf,0x8f,0x60,0x01,0x22,0xa2, +0x18,0x00,0xb2,0x8f,0x7c,0x11,0x00,0xae,0x60,0x11,0x00,0xae,0x64,0x11,0x00,0xae, +0x68,0x11,0x00,0xae,0x6c,0x11,0x00,0xae,0x70,0x11,0x00,0xae,0x74,0x11,0x00,0xae, +0x78,0x11,0x00,0xae,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0xff,0x00,0xa5,0x30,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24, +0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x90,0x11,0x43,0x8c,0x25,0xb0,0x05,0x3c, +0xff,0x00,0xc6,0x30,0x21,0x30,0xc5,0x00,0xaf,0x01,0xc2,0x90,0x07,0x00,0x63,0x30, +0x80,0x18,0x03,0x00,0x21,0x18,0x65,0x00,0xff,0x00,0x88,0x30,0xff,0x00,0x49,0x30, +0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11, +0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00, +0x6c,0x50,0x00,0x08,0x01,0x00,0x07,0x24,0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c, +0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00, +0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25, +0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01, +0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24, +0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30, +0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10, +0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01, +0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00, +0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03, +0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01, +0x8d,0x50,0x00,0x08,0xff,0x00,0x44,0x30,0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03, +0x21,0x10,0x80,0x00,0xff,0x00,0x84,0x30,0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00, +0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24, +0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x25,0xb0,0x06,0x3c,0x90,0x11,0x43,0x8c, +0xff,0x00,0xa5,0x30,0x21,0x20,0x86,0x00,0x21,0x28,0xa6,0x00,0x60,0x01,0x82,0x90, +0xaf,0x01,0xa4,0x90,0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x66,0x00, +0xff,0x00,0x48,0x30,0xff,0x00,0x89,0x30,0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00, +0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10, +0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,0xba,0x50,0x00,0x08,0x01,0x00,0x07,0x24, +0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25, +0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24, +0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00, +0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00, +0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25, +0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30, +0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01, +0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01, +0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00, +0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14, +0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,0xdb,0x50,0x00,0x08,0xff,0x00,0x44,0x30, +0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xd8,0xff,0xbd,0x27, +0x02,0x80,0x02,0x3c,0x18,0x00,0xb2,0xaf,0xff,0xff,0x03,0x3c,0x78,0x1b,0x52,0x24, +0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x20,0x00,0xbf,0xaf, +0xff,0x1f,0x73,0x34,0x21,0x88,0x00,0x00,0x21,0x80,0x40,0x02,0x19,0x50,0x00,0x0c, +0x21,0x20,0x20,0x02,0x90,0x11,0x02,0x8e,0x21,0x28,0x00,0x00,0x24,0x10,0x53,0x00, +0x00,0x20,0x42,0x34,0x90,0x11,0x02,0xae,0x92,0x11,0x03,0x92,0x00,0x00,0x00,0x00, +0x80,0x18,0x03,0x00,0x21,0x18,0x72,0x00,0xf8,0x04,0x64,0x8c,0x6c,0x05,0x62,0x8c, +0x00,0x00,0x00,0x00,0x21,0x10,0x44,0x00,0x42,0x10,0x02,0x00,0x5c,0x11,0x02,0xae, +0x21,0x10,0x05,0x02,0x01,0x00,0xa5,0x24,0x1d,0x00,0xa3,0x28,0xce,0x11,0x40,0xa0, +0x94,0x11,0x40,0xa0,0xfa,0xff,0x60,0x14,0xb1,0x11,0x40,0xa0,0x01,0x00,0x31,0x26, +0x20,0x00,0x22,0x2a,0xec,0x11,0x00,0xae,0xe4,0xff,0x40,0x14,0x94,0x00,0x10,0x26, +0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xc0,0xff,0xbd,0x27, +0x02,0x80,0x02,0x3c,0x2c,0x00,0xb5,0xaf,0x78,0x1b,0x46,0x24,0x3c,0x00,0xbf,0xaf, +0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf, +0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0xec,0x25,0xc2,0x8c,0xff,0x00,0x03,0x24,0xff,0x00,0x8d,0x30,0xff,0xff,0x42,0x38, +0x0b,0x18,0x02,0x00,0xff,0xff,0x04,0x34,0x10,0x00,0xa3,0xaf,0xec,0x25,0xc4,0xac, +0xb9,0x00,0xa0,0x11,0x08,0x00,0x15,0x24,0x02,0x80,0x02,0x3c,0xdc,0xad,0x45,0x24, +0x94,0x04,0xc4,0x24,0x36,0x51,0x00,0x08,0x21,0x88,0x00,0x00,0x01,0x00,0x31,0x26, +0x00,0x00,0x82,0xa0,0x1d,0x00,0x22,0x2a,0x0b,0x00,0x40,0x10,0x01,0x00,0x84,0x24, +0x21,0x10,0x25,0x02,0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00,0xf7,0xff,0x40,0x10, +0xfd,0xff,0x43,0x24,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0, +0xf7,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,0x78,0x1b,0x4a,0x24, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x74,0xab,0x6c,0x24,0xfc,0xaa,0x4b,0x24, +0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01, +0x21,0x38,0x2c,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90, +0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc9,0x03,0x64,0xa0, +0xf8,0xff,0x40,0x14,0x38,0x03,0x65,0xa0,0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90, +0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a, +0x77,0x04,0x64,0xa0,0x5a,0x04,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25, +0xaf,0x00,0xa0,0x11,0x02,0x80,0x02,0x3c,0x78,0x1b,0x48,0x24,0x02,0x80,0x03,0x3c, +0x02,0x80,0x02,0x3c,0x70,0xae,0x69,0x24,0xfc,0xad,0x47,0x24,0x21,0x88,0x00,0x00, +0x80,0x18,0x11,0x00,0x21,0x10,0x69,0x00,0x21,0x20,0x67,0x00,0x00,0x00,0x46,0x8c, +0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,0x21,0x18,0x68,0x00,0x04,0x00,0x22,0x2a, +0xf8,0x04,0x65,0xac,0xf6,0xff,0x40,0x14,0x6c,0x05,0x66,0xac,0x02,0x80,0x02,0x3c, +0x78,0x1b,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x70,0xae,0x68,0x24, +0xfc,0xad,0x47,0x24,0x04,0x00,0x11,0x24,0x80,0x20,0x11,0x00,0x21,0x10,0x88,0x00, +0x21,0x30,0x87,0x00,0x00,0x00,0x45,0x8c,0x00,0x00,0xc3,0x8c,0x01,0x00,0x31,0x26, +0x21,0x20,0x89,0x00,0x82,0x28,0x05,0x00,0x82,0x18,0x03,0x00,0x1d,0x00,0x22,0x2a, +0xf8,0x04,0x83,0xac,0xf4,0xff,0x40,0x14,0x6c,0x05,0x85,0xac,0x02,0x80,0x02,0x3c, +0x78,0x1b,0x56,0x24,0xff,0xff,0x02,0x3c,0x21,0xf0,0xc0,0x02,0xff,0x1f,0x57,0x34, +0x21,0x88,0x00,0x00,0x21,0xa0,0x00,0x00,0x93,0x51,0x00,0x08,0x21,0x90,0xc0,0x02, +0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0x94,0x00,0x52,0x26,0x3d,0x00,0x40,0x10, +0x94,0x00,0x94,0x26,0x90,0x11,0x44,0x8e,0x01,0x00,0x03,0x24,0x02,0x13,0x04,0x00, +0x01,0x00,0x53,0x30,0xf6,0xff,0x63,0x16,0x07,0x00,0x82,0x30,0x25,0xb0,0x03,0x3c, +0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x84,0x01,0x45,0x8c,0x88,0x11,0x43,0x8e, +0x21,0x20,0x20,0x02,0x24,0x28,0xa3,0x00,0x96,0x15,0x00,0x0c,0x8c,0x11,0x45,0xae, +0x92,0x11,0x44,0x92,0x70,0x15,0x00,0x0c,0xff,0x00,0x25,0x32,0x90,0x11,0x42,0x8e, +0x00,0x00,0x00,0x00,0x24,0x10,0x57,0x00,0x00,0x20,0x42,0x34,0x90,0x11,0x42,0xae, +0x92,0x11,0x50,0x92,0x00,0x00,0x00,0x00,0x21,0x20,0x00,0x02,0x86,0x15,0x00,0x0c, +0x80,0x80,0x10,0x00,0x21,0x80,0x16,0x02,0x60,0x11,0x40,0xae,0x64,0x11,0x40,0xae, +0x68,0x11,0x40,0xae,0x6c,0x11,0x40,0xae,0x70,0x11,0x40,0xae,0x74,0x11,0x40,0xae, +0x78,0x11,0x40,0xae,0x7c,0x11,0x40,0xae,0xf8,0x04,0x04,0x8e,0x6c,0x05,0x03,0x8e, +0x26,0x10,0x53,0x00,0x21,0x30,0x00,0x00,0x21,0x18,0x64,0x00,0x42,0x18,0x03,0x00, +0x04,0x00,0x04,0x24,0x0a,0xa8,0x82,0x00,0x5c,0x11,0x43,0xae,0x21,0x20,0x9e,0x02, +0x21,0x10,0x86,0x00,0x01,0x00,0xc6,0x24,0x1d,0x00,0xc3,0x28,0xce,0x11,0x40,0xa0, +0x94,0x11,0x40,0xa0,0xfa,0xff,0x60,0x14,0xb1,0x11,0x40,0xa0,0x01,0x00,0x31,0x26, +0x20,0x00,0x22,0x2a,0xec,0x11,0x80,0xac,0x94,0x00,0x52,0x26,0xc5,0xff,0x40,0x14, +0x94,0x00,0x94,0x26,0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x00,0x00,0x55,0xa0, +0x10,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,0x03,0x00,0x60,0x14,0x02,0x80,0x03,0x3c, +0x78,0x1b,0x62,0x24,0xec,0x25,0x40,0xac,0x3c,0x00,0xbf,0x8f,0x38,0x00,0xbe,0x8f, +0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0xdc,0xad,0x45,0x24, +0x94,0x04,0xc4,0x24,0x21,0x88,0x00,0x00,0x21,0x10,0x25,0x02,0x00,0x00,0x43,0x90, +0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0,0xfa,0xff,0x40,0x14, +0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,0x78,0x1b,0x4a,0x24,0x02,0x80,0x03,0x3c, +0x02,0x80,0x02,0x3c,0x98,0xac,0x6c,0x24,0x38,0xab,0x4b,0x24,0x21,0x88,0x00,0x00, +0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,0x21,0x38,0x2c,0x01, +0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01, +0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc9,0x03,0x64,0xa0,0xf8,0xff,0x40,0x14, +0x38,0x03,0x65,0xa0,0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90, +0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x77,0x04,0x64,0xa0, +0x5a,0x04,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,0x02,0x80,0x02,0x3c, +0x78,0x1b,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x70,0xae,0x68,0x24, +0xfc,0xad,0x47,0x24,0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x10,0x68,0x00, +0x21,0x20,0x67,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26, +0x21,0x18,0x69,0x00,0x1d,0x00,0x22,0x2a,0xf8,0x04,0x65,0xac,0xf6,0xff,0x40,0x14, +0x6c,0x05,0x66,0xac,0x86,0x51,0x00,0x08,0x02,0x80,0x02,0x3c,0xd8,0xff,0xbd,0x27, +0xff,0xff,0x84,0x30,0x18,0x00,0xb2,0xaf,0xf0,0x01,0x92,0x30,0x02,0x91,0x12,0x00, +0x14,0x00,0xb1,0xaf,0xc0,0x88,0x12,0x00,0x21,0x88,0x32,0x02,0x80,0x88,0x11,0x00, +0x21,0x88,0x32,0x02,0x02,0x80,0x02,0x3c,0x78,0x1b,0x42,0x24,0x80,0x88,0x11,0x00, +0x21,0x88,0x22,0x02,0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x10,0x00,0xb0,0xaf, +0x90,0x11,0x30,0x8e,0x00,0x02,0x83,0x30,0xff,0xfe,0x02,0x24,0x2b,0x18,0x03,0x00, +0x00,0x10,0x10,0x36,0x24,0x80,0x02,0x02,0x00,0x1a,0x03,0x00,0x00,0x04,0x82,0x30, +0x25,0x80,0x03,0x02,0x2b,0x10,0x02,0x00,0xf7,0xff,0x03,0x24,0x24,0x80,0x03,0x02, +0xc0,0x10,0x02,0x00,0x25,0x80,0x02,0x02,0x88,0x11,0x25,0xae,0x90,0x11,0x30,0xae, +0xf3,0x15,0x00,0x0c,0x21,0x98,0xa0,0x00,0xf8,0xff,0x03,0x24,0x24,0x80,0x03,0x02, +0x07,0x00,0x42,0x30,0x25,0x80,0x02,0x02,0x07,0x00,0x03,0x32,0x25,0xb0,0x02,0x3c, +0x80,0x18,0x03,0x00,0x90,0x11,0x30,0xae,0x21,0x18,0x62,0x00,0x84,0x01,0x62,0x8c, +0x21,0x20,0x40,0x02,0x24,0x10,0x53,0x00,0x96,0x15,0x00,0x0c,0x8c,0x11,0x22,0xae, +0x92,0x11,0x24,0x92,0x21,0x28,0x40,0x02,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x70,0x15,0x00,0x08, +0x28,0x00,0xbd,0x27,0x19,0x50,0x00,0x08,0xff,0x00,0x84,0x30,0x02,0x80,0x02,0x3c, +0x78,0x1b,0x43,0x24,0x1f,0x00,0x04,0x24,0x90,0x11,0x62,0x8c,0xff,0xff,0x84,0x24, +0x00,0x10,0x42,0x34,0x90,0x11,0x62,0xac,0xfb,0xff,0x81,0x04,0x94,0x00,0x63,0x24, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x23,0x10,0xa4,0x00, +0x2b,0x18,0xa4,0x00,0x23,0x20,0x85,0x00,0x08,0x00,0xe0,0x03,0x0b,0x10,0x83,0x00, +0x20,0xff,0xbd,0x27,0xcc,0x00,0xb5,0xaf,0xdc,0x00,0xbf,0xaf,0xd8,0x00,0xbe,0xaf, +0xd4,0x00,0xb7,0xaf,0xd0,0x00,0xb6,0xaf,0xc8,0x00,0xb4,0xaf,0xc4,0x00,0xb3,0xaf, +0xc0,0x00,0xb2,0xaf,0xbc,0x00,0xb1,0xaf,0xb8,0x00,0xb0,0xaf,0x21,0xa8,0x00,0x00, +0x40,0x11,0x15,0x00,0x10,0x00,0xa3,0x27,0x21,0x10,0x43,0x00,0x07,0x00,0x16,0x24, +0xff,0xff,0xd6,0x26,0x00,0x00,0x40,0xac,0xfd,0xff,0xc1,0x06,0x04,0x00,0x42,0x24, +0x01,0x00,0xb5,0x26,0x03,0x00,0xa2,0x2e,0xf6,0xff,0x40,0x14,0x40,0x11,0x15,0x00, +0x25,0xb0,0x10,0x3c,0xc4,0x02,0x02,0x36,0x00,0x00,0x40,0xac,0x04,0x00,0x03,0x36, +0x00,0x00,0x62,0x8c,0x04,0x0c,0x03,0x36,0x00,0x00,0x63,0x8c,0x08,0x0c,0x04,0x36, +0x0f,0x00,0x11,0x3c,0xac,0x00,0xa3,0xaf,0x00,0x00,0x84,0x8c,0x24,0x10,0x51,0x00, +0x02,0xf4,0x02,0x00,0xb0,0x00,0xa4,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0xe3,0x44,0x00,0x0c, +0xff,0xff,0x25,0x36,0x70,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x00,0x60,0x81,0x40,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x95,0x42,0x00,0x0c, +0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38, +0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36, +0x74,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x95,0x42,0x00,0x0c,0x21,0x20,0x00,0x00, +0xe0,0x0e,0x02,0x36,0x21,0x20,0x40,0x00,0x00,0x00,0x42,0x8c,0xdc,0x0e,0x12,0x36, +0x70,0x0e,0x13,0x36,0x78,0x00,0xa2,0xaf,0x00,0x00,0x42,0x8e,0x74,0x0e,0x14,0x36, +0x78,0x0e,0x15,0x36,0x7c,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8e,0x7c,0x0e,0x16,0x36, +0x80,0x0e,0x17,0x36,0x80,0x00,0xa3,0xaf,0x00,0x00,0x82,0x8e,0xd4,0x0e,0x10,0x36, +0xed,0x3f,0x11,0x3c,0x84,0x00,0xa2,0xaf,0x00,0x00,0xa3,0x8e,0xfb,0x92,0x25,0x36, +0x88,0x00,0xa3,0xaf,0x00,0x00,0xc2,0x8e,0x00,0x00,0x00,0x00,0x8c,0x00,0xa2,0xaf, +0x00,0x00,0xe3,0x8e,0x25,0xb0,0x02,0x3c,0x84,0x0e,0x42,0x34,0x90,0x00,0xa3,0xaf, +0x00,0x00,0x42,0x8c,0x25,0xb0,0x03,0x3c,0x88,0x0e,0x63,0x34,0x94,0x00,0xa2,0xaf, +0x00,0x00,0x63,0x8c,0x25,0xb0,0x02,0x3c,0x8c,0x0e,0x42,0x34,0x98,0x00,0xa3,0xaf, +0x00,0x00,0x42,0x8c,0x25,0xb0,0x03,0x3c,0xd0,0x0e,0x63,0x34,0x9c,0x00,0xa2,0xaf, +0x00,0x00,0x63,0x8c,0x00,0x00,0x00,0x00,0xa0,0x00,0xa3,0xaf,0x00,0x00,0x02,0x8e, +0x25,0xb0,0x03,0x3c,0xd8,0x0e,0x63,0x34,0xa4,0x00,0xa2,0xaf,0x00,0x00,0x63,0x8c, +0x68,0x52,0x00,0x0c,0xa8,0x00,0xa3,0xaf,0x21,0x20,0x40,0x02,0x68,0x52,0x00,0x0c, +0xfb,0x92,0x25,0x36,0x21,0x20,0x60,0x02,0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36, +0x21,0x20,0x80,0x02,0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0xa0,0x02, +0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36,0x21,0x20,0xc0,0x02,0x68,0x52,0x00,0x0c, +0xfb,0x92,0x25,0x36,0x21,0x20,0xe0,0x02,0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36, +0x02,0x80,0x02,0x3c,0x18,0xb0,0x42,0x24,0x00,0x00,0x44,0x8c,0xfb,0x92,0x25,0x36, +0x68,0x52,0x00,0x0c,0x25,0xb0,0x13,0x3c,0x02,0x80,0x03,0x3c,0x1c,0xb0,0x63,0x24, +0x00,0x00,0x64,0x8c,0xfb,0x92,0x25,0x36,0x68,0x52,0x00,0x0c,0x21,0xb0,0x00,0x00, +0x02,0x80,0x02,0x3c,0x20,0xb0,0x42,0x24,0x00,0x00,0x44,0x8c,0xfb,0x92,0x25,0x36, +0x68,0x52,0x00,0x0c,0xff,0x03,0x14,0x3c,0x02,0x80,0x03,0x3c,0x24,0xb0,0x63,0x24, +0x00,0x00,0x64,0x8c,0xfb,0x92,0x25,0x36,0x68,0x52,0x00,0x0c,0x10,0x00,0xb7,0x27, +0x21,0x20,0x00,0x02,0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36,0x02,0x80,0x02,0x3c, +0x28,0xb0,0x42,0x24,0x00,0x00,0x44,0x8c,0x68,0x52,0x00,0x0c,0xfb,0x92,0x25,0x36, +0x54,0x53,0x00,0x08,0x21,0xa8,0x00,0x00,0x6e,0x00,0xc2,0x13,0x02,0x80,0x02,0x3c, +0xac,0x0e,0x62,0x36,0x94,0x0e,0x63,0x36,0x00,0x00,0x48,0x8c,0x00,0x00,0x64,0x8c, +0xb4,0x0e,0x62,0x36,0x9c,0x0e,0x63,0x36,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c, +0x25,0xb0,0x03,0x3c,0xbc,0x0e,0x63,0x34,0x00,0x00,0x67,0x8c,0x24,0x20,0x94,0x00, +0x00,0xd8,0x02,0x3c,0x24,0x10,0x02,0x01,0x24,0x28,0xb4,0x00,0x24,0x30,0xd4,0x00, +0x24,0x38,0xf4,0x00,0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c, +0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,0xe8,0x00,0x83,0x10,0x02,0x3c,0x07,0x00, +0xe6,0x00,0xa3,0x10,0x20,0x00,0x03,0x24,0xe4,0x00,0xc3,0x10,0x00,0x00,0x00,0x00, +0xe2,0x00,0xe3,0x10,0x01,0x00,0x08,0x24,0x80,0x00,0x03,0x24,0x08,0x00,0x83,0x10, +0x21,0x20,0x00,0x00,0x06,0x00,0xa3,0x10,0x21,0x20,0x00,0x00,0xe0,0x03,0x03,0x24, +0x03,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0xdb,0x00,0xe3,0x10,0x01,0x00,0x04,0x24, +0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x11,0x00,0x00,0x00,0x00, +0xd7,0x00,0x80,0x14,0x94,0x0e,0x63,0x36,0x01,0x00,0xb5,0x26,0x0a,0x00,0xa2,0x2e, +0x01,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xcb,0xff,0xc0,0x17,0x01,0x00,0x02,0x24, +0xa0,0x00,0x03,0x3c,0x30,0x54,0x65,0x34,0x68,0x52,0x00,0x0c,0x04,0x0c,0x64,0x36, +0x08,0x00,0x05,0x3c,0xe4,0x00,0xa5,0x34,0x68,0x52,0x00,0x0c,0x08,0x0c,0x64,0x36, +0x28,0x0e,0x64,0x36,0x68,0x52,0x00,0x0c,0x80,0x80,0x05,0x3c,0x14,0x02,0x02,0x3c, +0x48,0x01,0x45,0x34,0x68,0x52,0x00,0x0c,0x40,0x0e,0x64,0x36,0x16,0x68,0x05,0x3c, +0xa2,0x04,0xa5,0x34,0x68,0x52,0x00,0x0c,0x44,0x0e,0x64,0x36,0x4c,0x0e,0x64,0x36, +0x68,0x52,0x00,0x0c,0xd1,0x28,0x05,0x24,0x14,0x02,0x03,0x3c,0x4d,0x01,0x65,0x34, +0x68,0x52,0x00,0x0c,0x60,0x0e,0x64,0x36,0x16,0x28,0x05,0x3c,0xba,0x08,0xa5,0x34, +0x68,0x52,0x00,0x0c,0x64,0x0e,0x64,0x36,0x6c,0x0e,0x64,0x36,0x68,0x52,0x00,0x0c, +0xd1,0x28,0x05,0x24,0x00,0xfb,0x05,0x3c,0x01,0x00,0xa5,0x34,0x68,0x52,0x00,0x0c, +0x48,0x0e,0x64,0x36,0x00,0xf8,0x05,0x3c,0x01,0x00,0xa5,0x34,0x68,0x52,0x00,0x0c, +0x48,0x0e,0x64,0x36,0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24,0xa0,0x00,0x02,0x3c, +0x33,0x54,0x45,0x34,0x68,0x52,0x00,0x0c,0x04,0x0c,0x64,0x36,0x08,0x0c,0x64,0x36, +0x68,0x52,0x00,0x0c,0xe4,0x00,0x05,0x24,0x28,0x0e,0x64,0x36,0x68,0x52,0x00,0x0c, +0x21,0x28,0x00,0x00,0x01,0x00,0x02,0x24,0x96,0xff,0xc2,0x17,0xac,0x0e,0x62,0x36, +0x02,0x80,0x02,0x3c,0x2c,0xb0,0x42,0x24,0x25,0xb0,0x03,0x3c,0x00,0x00,0x44,0x8c, +0x20,0x08,0x63,0x34,0x00,0x00,0x71,0x8c,0x00,0x01,0x03,0x3c,0x00,0x01,0x65,0x34, +0x68,0x52,0x00,0x0c,0x25,0xb0,0x12,0x3c,0x00,0x01,0x02,0x3c,0x00,0x01,0x45,0x34, +0x68,0x52,0x00,0x0c,0x28,0x08,0x44,0x36,0xa0,0x00,0x03,0x3c,0x30,0x54,0x65,0x34, +0x68,0x52,0x00,0x0c,0x04,0x0c,0x44,0x36,0x08,0x00,0x05,0x3c,0xe4,0x00,0xa5,0x34, +0x68,0x52,0x00,0x0c,0x08,0x0c,0x44,0x36,0x28,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c, +0x80,0x80,0x05,0x3c,0x00,0x01,0x02,0x3c,0x00,0x7c,0x45,0x34,0x68,0x52,0x00,0x0c, +0x30,0x0e,0x44,0x36,0x00,0x01,0x03,0x3c,0x00,0x48,0x65,0x34,0x68,0x52,0x00,0x0c, +0x34,0x0e,0x44,0x36,0x00,0x10,0x02,0x3c,0x1f,0xdc,0x45,0x34,0x68,0x52,0x00,0x0c, +0x38,0x0e,0x44,0x36,0x00,0x10,0x03,0x3c,0x1f,0x8c,0x65,0x34,0x68,0x52,0x00,0x0c, +0x3c,0x0e,0x44,0x36,0x14,0x02,0x02,0x3c,0x02,0x01,0x45,0x34,0x68,0x52,0x00,0x0c, +0x40,0x0e,0x44,0x36,0x16,0x68,0x05,0x3c,0xc7,0x04,0xa5,0x34,0x68,0x52,0x00,0x0c, +0x44,0x0e,0x44,0x36,0x4c,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c,0xd1,0x28,0x05,0x24, +0x6c,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c,0xd1,0x28,0x05,0x24,0x00,0x01,0x03,0x3c, +0x00,0x7c,0x65,0x34,0x68,0x52,0x00,0x0c,0x50,0x0e,0x44,0x36,0x00,0x01,0x02,0x3c, +0x00,0x48,0x45,0x34,0x68,0x52,0x00,0x0c,0x54,0x0e,0x44,0x36,0x00,0x10,0x03,0x3c, +0x23,0xdc,0x65,0x34,0x68,0x52,0x00,0x0c,0x58,0x0e,0x44,0x36,0x00,0x10,0x02,0x3c, +0x23,0x8c,0x45,0x34,0x68,0x52,0x00,0x0c,0x5c,0x0e,0x44,0x36,0x14,0x02,0x03,0x3c, +0x02,0x01,0x65,0x34,0x68,0x52,0x00,0x0c,0x60,0x0e,0x44,0x36,0x16,0x28,0x05,0x3c, +0x07,0x0d,0xa5,0x34,0x68,0x52,0x00,0x0c,0x64,0x0e,0x44,0x36,0x48,0x0e,0x44,0x36, +0x68,0x52,0x00,0x0c,0x00,0xfb,0x05,0x3c,0x00,0xf8,0x05,0x3c,0x68,0x52,0x00,0x0c, +0x48,0x0e,0x44,0x36,0x00,0x02,0x10,0x3c,0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24, +0x4c,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c,0xd1,0x28,0x05,0x36,0xd1,0x28,0x05,0x36, +0x68,0x52,0x00,0x0c,0x6c,0x0e,0x44,0x36,0x48,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c, +0x00,0xfb,0x05,0x3c,0x00,0xf8,0x05,0x3c,0x68,0x52,0x00,0x0c,0x48,0x0e,0x44,0x36, +0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24,0xac,0x00,0xa5,0x8f,0x04,0x0c,0x44,0x36, +0x68,0x52,0x00,0x0c,0x00,0x01,0x31,0x32,0xb0,0x00,0xa5,0x8f,0x08,0x0c,0x44,0x36, +0x68,0x52,0x00,0x0c,0x2b,0x88,0x11,0x00,0x28,0x0e,0x44,0x36,0x68,0x52,0x00,0x0c, +0x21,0x28,0x00,0x00,0x23,0xff,0x20,0x16,0xac,0x0e,0x62,0x36,0x02,0x80,0x02,0x3c, +0x2c,0xb0,0x42,0x24,0x00,0x00,0x44,0x8c,0x68,0x52,0x00,0x0c,0x00,0x01,0x05,0x3c, +0x28,0x08,0x44,0x36,0x68,0x52,0x00,0x0c,0x00,0x01,0x05,0x3c,0xac,0x0e,0x62,0x36, +0x94,0x0e,0x63,0x36,0x00,0x00,0x48,0x8c,0x00,0x00,0x64,0x8c,0xb4,0x0e,0x62,0x36, +0x9c,0x0e,0x63,0x36,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,0x25,0xb0,0x03,0x3c, +0xbc,0x0e,0x63,0x34,0x00,0x00,0x67,0x8c,0x24,0x20,0x94,0x00,0x00,0xd8,0x02,0x3c, +0x24,0x10,0x02,0x01,0x24,0x28,0xb4,0x00,0x24,0x30,0xd4,0x00,0x24,0x38,0xf4,0x00, +0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c,0x02,0x2c,0x05,0x00, +0x02,0x34,0x06,0x00,0x1a,0xff,0x83,0x14,0x02,0x3c,0x07,0x00,0x80,0x00,0x03,0x24, +0x20,0xff,0x83,0x14,0x21,0x40,0x00,0x00,0x4a,0x53,0x00,0x08,0x21,0x20,0x00,0x00, +0x00,0x00,0x62,0x8c,0x9c,0x0e,0x65,0x36,0xa4,0x0e,0x66,0x36,0x24,0x10,0x54,0x00, +0x02,0x14,0x02,0x00,0x00,0x00,0xe2,0xae,0x00,0x00,0xa4,0x8c,0xac,0x0e,0x67,0x36, +0xb4,0x0e,0x65,0x36,0x24,0x20,0x94,0x00,0x02,0x24,0x04,0x00,0x04,0x00,0xe4,0xae, +0x00,0x00,0xc3,0x8c,0xc4,0x0e,0x64,0x36,0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00, +0x08,0x00,0xe3,0xae,0x00,0x00,0xe2,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00, +0x02,0x14,0x02,0x00,0x0c,0x00,0xe2,0xae,0x00,0x00,0xa3,0x8c,0x00,0x00,0x00,0x00, +0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,0x10,0x00,0xe3,0xae,0x25,0xb0,0x03,0x3c, +0xbc,0x0e,0x63,0x34,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00, +0x02,0x14,0x02,0x00,0x14,0x00,0xe2,0xae,0x00,0x00,0x83,0x8c,0x00,0x00,0x00,0x00, +0x24,0x18,0x74,0x00,0x02,0x1c,0x03,0x00,0x18,0x00,0xe3,0xae,0x25,0xb0,0x03,0x3c, +0xcc,0x0e,0x63,0x34,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x54,0x00, +0x02,0x14,0x02,0x00,0x1c,0x00,0xe2,0xae,0x01,0x00,0xd6,0x26,0x03,0x00,0xc2,0x2e, +0xc7,0xfe,0x40,0x14,0x20,0x00,0xf7,0x26,0x10,0x00,0xb0,0x8f,0x00,0x00,0x00,0x00, +0x49,0x01,0x00,0x16,0x00,0x00,0x00,0x00,0x30,0x00,0xb1,0x8f,0x00,0x00,0x00,0x00, +0x06,0x00,0x20,0x16,0x21,0x20,0x00,0x02,0x50,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00, +0x29,0x00,0x40,0x10,0xff,0x00,0x05,0x24,0x21,0x20,0x00,0x02,0x71,0x52,0x00,0x0c, +0x21,0x28,0x20,0x02,0x03,0x00,0x42,0x2c,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00, +0x34,0x00,0xa5,0x8f,0x14,0x00,0xa4,0x8f,0x71,0x52,0x00,0x0c,0x00,0x00,0x00,0x00, +0x03,0x00,0x42,0x2c,0x1c,0x00,0x40,0x14,0x21,0x28,0x00,0x00,0x50,0x00,0xb2,0x8f, +0x21,0x20,0x00,0x02,0x71,0x52,0x00,0x0c,0x21,0x28,0x40,0x02,0x03,0x00,0x42,0x2c, +0x09,0x00,0x40,0x10,0x21,0x20,0x20,0x02,0x54,0x00,0xa5,0x8f,0x14,0x00,0xa4,0x8f, +0x71,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c,0x0e,0x00,0x40,0x14, +0x21,0x28,0x00,0x00,0x21,0x20,0x20,0x02,0x71,0x52,0x00,0x0c,0x21,0x28,0x40,0x02, +0x03,0x00,0x42,0x2c,0xe0,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x54,0x00,0xa5,0x8f, +0x34,0x00,0xa4,0x8f,0x71,0x52,0x00,0x0c,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x2c, +0xd9,0x00,0x40,0x10,0x01,0x00,0x05,0x24,0xff,0x00,0x02,0x24,0xdb,0x00,0xa2,0x10, +0x25,0xb0,0x03,0x3c,0x10,0x00,0xa2,0x27,0x40,0x29,0x05,0x00,0x02,0x80,0x0f,0x3c, +0x21,0x28,0xa2,0x00,0x78,0x1b,0xec,0x25,0x00,0x00,0xa6,0x8c,0x0c,0x00,0xa7,0x8c, +0x0c,0x00,0x83,0x8d,0x10,0x00,0x84,0x8d,0x04,0x00,0xa8,0x8c,0x10,0x00,0xa9,0x8c, +0x00,0xfc,0x02,0x24,0x08,0x00,0xaa,0x8c,0x14,0x00,0xab,0x8c,0x24,0x20,0x82,0x00, +0xff,0x03,0xc6,0x30,0x24,0x18,0x62,0x00,0xff,0x03,0xe7,0x30,0xf0,0xff,0x02,0x3c, +0xff,0x03,0x42,0x34,0x25,0x18,0x66,0x00,0x25,0x20,0x87,0x00,0xff,0x03,0x08,0x31, +0xff,0x03,0x29,0x31,0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00,0x80,0x42,0x08,0x00, +0x80,0x4a,0x09,0x00,0x0f,0xc0,0x02,0x3c,0x1c,0x00,0xa6,0x8c,0x18,0x00,0xa7,0x8c, +0xff,0xff,0x42,0x34,0x25,0x18,0x68,0x00,0x25,0x20,0x89,0x00,0xff,0x03,0x4a,0x31, +0xff,0x03,0x6b,0x31,0x24,0x20,0x82,0x00,0x00,0x55,0x0a,0x00,0x24,0x18,0x62,0x00, +0x00,0x5d,0x0b,0x00,0x25,0x18,0x6a,0x00,0x25,0x20,0x8b,0x00,0x16,0x00,0x86,0xa5, +0x0c,0x00,0x83,0xad,0x10,0x00,0x84,0xad,0x14,0x00,0x87,0xa5,0x78,0x1b,0xf1,0x25, +0x10,0x00,0x22,0x8e,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,0x4d,0x00,0x43,0x10, +0x25,0xb0,0x12,0x3c,0x0c,0x00,0x23,0x8e,0x80,0x0c,0x44,0x36,0x00,0x00,0x88,0x8c, +0x00,0x02,0x62,0x30,0xc0,0xff,0x13,0x3c,0x82,0x6d,0x08,0x00,0x03,0x00,0x40,0x10, +0xff,0x03,0x65,0x30,0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00,0x18,0x00,0xad,0x00, +0x82,0x62,0x03,0x00,0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31,0x12,0x10,0x00,0x00, +0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30,0x00,0xfc,0x02,0x24, +0x25,0x60,0x82,0x01,0x18,0x00,0x8d,0x01,0x00,0xfc,0x74,0x36,0x24,0x28,0x14,0x01, +0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00, +0x25,0x28,0xa2,0x00,0x68,0x52,0x00,0x0c,0x25,0x28,0xa6,0x00,0x94,0x0c,0x44,0x36, +0x00,0x00,0x85,0x8c,0xff,0x0f,0x02,0x3c,0xff,0xff,0x55,0x34,0xc0,0x03,0x10,0x32, +0x24,0x28,0xb5,0x00,0x80,0x85,0x10,0x00,0x68,0x52,0x00,0x0c,0x25,0x28,0xb0,0x00, +0x10,0x00,0x2c,0x8e,0x88,0x0c,0x44,0x36,0x00,0x00,0x88,0x8c,0x82,0x2a,0x0c,0x00, +0xff,0x03,0xa5,0x30,0x24,0x10,0x13,0x01,0x00,0x02,0xa3,0x30,0x03,0x00,0x60,0x10, +0x82,0x6d,0x02,0x00,0x00,0xfc,0x02,0x24,0x25,0x28,0xa2,0x00,0x18,0x00,0xad,0x00, +0x02,0x65,0x0c,0x00,0xff,0x03,0x8c,0x31,0x00,0x02,0x83,0x31,0x12,0x10,0x00,0x00, +0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x46,0x30,0x00,0xfc,0x02,0x24, +0x25,0x60,0x82,0x01,0x18,0x00,0x8d,0x01,0x24,0x28,0x14,0x01,0x12,0x80,0x00,0x00, +0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00, +0x68,0x52,0x00,0x0c,0x25,0x28,0xa6,0x00,0x9c,0x0c,0x44,0x36,0x00,0x00,0x85,0x8c, +0xc0,0x03,0x10,0x32,0x80,0x85,0x10,0x00,0x24,0x28,0xb5,0x00,0x68,0x52,0x00,0x0c, +0x25,0x28,0xb0,0x00,0x78,0x00,0xa5,0x8f,0x25,0xb0,0x10,0x3c,0x68,0x52,0x00,0x0c, +0xe0,0x0e,0x04,0x36,0x7c,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0xdc,0x0e,0x04,0x36, +0x80,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0x70,0x0e,0x04,0x36,0x84,0x00,0xa5,0x8f, +0x68,0x52,0x00,0x0c,0x74,0x0e,0x04,0x36,0x88,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c, +0x78,0x0e,0x04,0x36,0x8c,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0x7c,0x0e,0x04,0x36, +0x90,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0x80,0x0e,0x04,0x36,0x94,0x00,0xa5,0x8f, +0x68,0x52,0x00,0x0c,0x84,0x0e,0x04,0x36,0x98,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c, +0x88,0x0e,0x04,0x36,0x9c,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0x8c,0x0e,0x04,0x36, +0xa0,0x00,0xa5,0x8f,0x68,0x52,0x00,0x0c,0xd0,0x0e,0x04,0x36,0xa4,0x00,0xa5,0x8f, +0x68,0x52,0x00,0x0c,0xd4,0x0e,0x04,0x36,0xa8,0x00,0xa5,0x8f,0x88,0x0e,0x04,0x36, +0x68,0x52,0x00,0x0c,0x0f,0x00,0x10,0x3c,0x70,0x00,0xa6,0x8f,0xff,0xff,0x05,0x36, +0xb8,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24, +0x95,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x74,0x00,0xa6,0x8f,0xff,0xff,0x05,0x36, +0xb8,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24, +0x95,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0xff,0xff,0x05,0x36,0xe3,0x44,0x00,0x0c, +0x1e,0x00,0x04,0x24,0x21,0x88,0x40,0x00,0xfd,0xff,0x06,0x24,0x01,0x00,0x42,0x34, +0x24,0x30,0x46,0x00,0xff,0xff,0x05,0x36,0xb8,0x44,0x00,0x0c,0x1e,0x00,0x04,0x24, +0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x03,0x00,0x26,0x36, +0xb8,0x44,0x00,0x0c,0x1e,0x00,0x04,0x24,0xdc,0x00,0xbf,0x8f,0xd8,0x00,0xbe,0x8f, +0xd4,0x00,0xb7,0x8f,0xd0,0x00,0xb6,0x8f,0xcc,0x00,0xb5,0x8f,0xc8,0x00,0xb4,0x8f, +0xc4,0x00,0xb3,0x8f,0xc0,0x00,0xb2,0x8f,0xbc,0x00,0xb1,0x8f,0xb8,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0xe0,0x00,0xbd,0x27,0xff,0x00,0x05,0x24,0xff,0x00,0x02,0x24, +0x29,0xff,0xa2,0x14,0x10,0x00,0xa2,0x27,0x25,0xb0,0x03,0x3c,0x94,0x0e,0x62,0x34, +0x9c,0x0e,0x64,0x34,0xa4,0x0e,0x65,0x34,0xac,0x0e,0x66,0x34,0x02,0x80,0x0f,0x3c, +0x00,0x00,0x49,0x8c,0x78,0x1b,0xed,0x25,0x00,0x00,0x8c,0x8c,0x00,0x00,0xae,0x8c, +0x00,0x00,0xc7,0x8c,0xb4,0x0e,0x62,0x34,0x0c,0x00,0xa4,0x8d,0x10,0x00,0xa5,0x8d, +0x00,0x00,0x4a,0x8c,0xff,0x03,0x06,0x3c,0x00,0xfc,0x08,0x24,0xbc,0x0e,0x62,0x34, +0x24,0x48,0x26,0x01,0x24,0x38,0xe6,0x00,0x00,0x00,0x4b,0x8c,0x24,0x28,0xa8,0x00, +0x24,0x20,0x88,0x00,0x02,0x3c,0x07,0x00,0xcc,0x0e,0x68,0x34,0x02,0x4c,0x09,0x00, +0xc4,0x0e,0x63,0x34,0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x28,0xa7,0x00, +0x25,0x20,0x89,0x00,0x00,0x00,0x67,0x8c,0x24,0x60,0x86,0x01,0x00,0x00,0x03,0x8d, +0x24,0x50,0x46,0x01,0x24,0x28,0xa2,0x00,0x24,0x20,0x82,0x00,0x82,0x61,0x0c,0x00, +0x82,0x51,0x0a,0x00,0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,0x25,0x20,0x8c,0x00, +0x25,0x28,0xaa,0x00,0x24,0x70,0xc6,0x01,0x24,0x58,0x66,0x01,0x24,0x28,0xa2,0x00, +0x24,0x18,0x66,0x00,0x00,0x71,0x0e,0x00,0x24,0x20,0x82,0x00,0x00,0x59,0x0b,0x00, +0x24,0x38,0xe6,0x00,0x25,0x20,0x8e,0x00,0x25,0x28,0xab,0x00,0x02,0x3c,0x07,0x00, +0x02,0x1c,0x03,0x00,0x16,0x00,0xa3,0xa5,0x0c,0x00,0xa4,0xad,0x10,0x00,0xa5,0xad, +0xbd,0x54,0x00,0x08,0x14,0x00,0xa7,0xa5,0x30,0x00,0xb1,0x8f,0x65,0x54,0x00,0x08, +0x21,0x20,0x00,0x02,0xe0,0xff,0xbd,0x27,0x44,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3, +0x49,0x00,0x03,0x24,0x47,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x1c,0xb6,0xe7,0x24, +0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0x10,0x27,0x03,0x24,0x01,0x00,0x02,0x24, +0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xb0,0x59,0xc6,0x24, +0x0c,0x00,0xe3,0xac,0x14,0x00,0xe2,0xa0,0x18,0x00,0xbf,0xaf,0xa8,0x14,0x00,0x0c, +0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x25,0xb0,0x03,0x3c,0x20,0x00,0xb4,0xaf, +0x1c,0x00,0xb3,0xaf,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf, +0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x03,0x0d,0x64,0x34, +0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x54,0x30,0x70,0x00,0x93,0x32, +0x63,0x00,0x60,0x12,0x42,0x00,0x63,0x34,0x8f,0x00,0x82,0x32,0x00,0x00,0x82,0xa0, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x5b,0x00,0x60,0x12,0x00,0x00,0x00,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x0f,0x00,0x11,0x3c,0x21,0x20,0x00,0x00,0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36, +0x21,0xa8,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x95,0x42,0x00,0x0c,0x01,0x00,0x04,0x24, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x21,0x20,0x00,0x00,0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0xb0,0x40,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x64,0x00,0x04,0x24, +0xcb,0x12,0x00,0x0c,0x08,0x00,0x10,0x3c,0xff,0xff,0x10,0x36,0x95,0x42,0x00,0x0c, +0x21,0x20,0x00,0x00,0x01,0x00,0x12,0x3c,0x24,0x30,0xb0,0x02,0x25,0x30,0xd2,0x00, +0xff,0xff,0x25,0x36,0xb8,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xcb,0x12,0x00,0x0c, +0x64,0x00,0x04,0x24,0x24,0x80,0xd0,0x02,0x95,0x42,0x00,0x0c,0x01,0x00,0x04,0x24, +0x25,0x30,0x12,0x02,0xff,0xff,0x25,0x36,0xb8,0x44,0x00,0x0c,0x21,0x20,0x00,0x00, +0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x95,0x42,0x00,0x0c,0x21,0x20,0x00,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x0f,0x00,0x11,0x3c,0x18,0x00,0x04,0x24,0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36, +0x21,0x80,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40, +0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x18,0x00,0x04,0x24,0xff,0xff,0x25,0x36, +0xb8,0x44,0x00,0x0c,0x00,0x80,0x06,0x36,0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24, +0x27,0x00,0x60,0x16,0x25,0xb0,0x02,0x3c,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f, +0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,0x42,0x00,0x42,0x34, +0x30,0x00,0xbd,0x27,0x00,0x00,0x40,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xff,0xff,0x02,0x24,0x00,0x00,0x62,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34, +0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x18,0x00,0x04,0x24, +0xe3,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24, +0x18,0x00,0x04,0x24,0xff,0xff,0x25,0x36,0xb8,0x44,0x00,0x0c,0x00,0x80,0x06,0x36, +0x9c,0x12,0x00,0x0c,0x03,0x00,0x04,0x24,0xdb,0xff,0x60,0x12,0x25,0xb0,0x02,0x3c, +0x03,0x0d,0x42,0x34,0x00,0x00,0x54,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24, +0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24, +0x0f,0x00,0x10,0x3c,0x21,0x30,0xa0,0x02,0xff,0xff,0x05,0x36,0xb8,0x44,0x00,0x0c, +0x21,0x20,0x00,0x00,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x95,0x42,0x00,0x0c, +0x01,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x21,0x30,0xc0,0x02,0xb8,0x44,0x00,0x0c, +0x21,0x20,0x00,0x00,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24,0x2c,0x00,0xbf,0x8f, +0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f, +0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x20,0x00,0x00, +0x95,0x42,0x00,0x08,0x30,0x00,0xbd,0x27,0xc0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf, +0x02,0x80,0x14,0x3c,0x78,0x1b,0x85,0x26,0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf, +0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf, +0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0xc8,0x02,0xa3,0x90,0x25,0xb0,0x02,0x3c, +0x9a,0x0c,0x42,0x34,0x01,0x00,0x63,0x24,0xff,0x00,0x64,0x30,0x00,0x00,0x44,0xa0, +0xc8,0x02,0xa3,0xa0,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x78,0x1b,0x85,0x26, +0x0c,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x82,0x17,0x02,0x00,0x01,0x00,0x42,0x30, +0x08,0x00,0x40,0x14,0x06,0x00,0x16,0x24,0x08,0x00,0xa2,0x8c,0x01,0x00,0x03,0x24, +0x42,0x17,0x02,0x00,0x03,0x00,0x42,0x30,0x4e,0x01,0x43,0x10,0x25,0xb0,0x02,0x3c, +0x78,0x1b,0x85,0x26,0x0c,0x00,0xa2,0x8c,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00, +0x01,0x00,0x44,0x30,0x0d,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x38,0x00,0xbf,0x8f, +0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x08,0x00,0xa2,0x8c, +0x00,0x00,0x00,0x00,0x42,0x17,0x02,0x00,0x03,0x00,0x43,0x30,0xef,0xff,0x64,0x14, +0x00,0x00,0x00,0x00,0x10,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x82,0x17,0x02,0x00, +0x60,0x02,0x43,0x10,0x0f,0x00,0x10,0x3c,0xc7,0x02,0xb3,0x90,0x25,0xb0,0x02,0x3c, +0x62,0x0c,0x42,0x34,0xff,0x00,0x63,0x32,0x00,0x00,0x43,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x90,0x26,0xc6,0x02,0x02,0x92,0x00,0x00,0x00,0x00, +0x6f,0x01,0x40,0x10,0x01,0x00,0x02,0x24,0x25,0xb0,0x11,0x3c,0x03,0x0d,0x23,0x36, +0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x70,0x00,0x42,0x30,0x95,0x01,0x40,0x14, +0xcc,0x00,0x02,0x24,0xc4,0x02,0x02,0x96,0x00,0x00,0x00,0x00,0x23,0x20,0x53,0x00, +0x2b,0x18,0x53,0x00,0x23,0x10,0x62,0x02,0x0a,0x10,0x83,0x00,0x03,0x00,0x42,0x2c, +0x62,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xc4,0x02,0x03,0x92,0x63,0x0c,0x22,0x36, +0x21,0x20,0x00,0x00,0x00,0x00,0x43,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30, +0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x78,0x1b,0x83,0x26, +0xc3,0x02,0x62,0x90,0x08,0x00,0x66,0x8c,0xc2,0x02,0x73,0xa0,0x23,0x20,0x53,0x00, +0x2b,0x38,0x62,0x02,0x23,0x90,0x62,0x02,0x02,0x2c,0x06,0x00,0x0b,0x90,0x87,0x00, +0x3f,0x00,0xa5,0x30,0x3f,0x00,0xc4,0x30,0x24,0x00,0x02,0x24,0x20,0x00,0x03,0x24, +0x23,0x10,0x44,0x00,0x7d,0x01,0x40,0x16,0x23,0x18,0x65,0x00,0x21,0x40,0x80,0x00, +0x21,0xa8,0xa0,0x00,0x02,0x80,0x17,0x3c,0x2b,0x28,0xc8,0x02,0xf3,0x01,0xa0,0x10, +0x78,0x1b,0x82,0x26,0x80,0x10,0x08,0x00,0x78,0x1b,0x83,0x26,0x21,0x10,0x43,0x00, +0x18,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x82,0x25,0x04,0x00,0x78,0x1b,0x86,0x26, +0x0c,0x00,0xc3,0x8c,0x00,0x00,0x00,0x00,0xff,0x03,0x67,0x30,0x7b,0x01,0xe0,0x10, +0x00,0x02,0x62,0x30,0x04,0x00,0x40,0x10,0x18,0x00,0xe4,0x00,0x00,0xfc,0x02,0x24, +0x25,0x38,0xe2,0x00,0x18,0x00,0xe4,0x00,0x82,0x82,0x03,0x00,0xff,0x03,0x10,0x32, +0x00,0x02,0x03,0x32,0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10, +0xff,0x03,0x45,0x30,0x00,0xfc,0x02,0x24,0x25,0x80,0x02,0x02,0x18,0x00,0x04,0x02, +0x80,0x1d,0x04,0x00,0x25,0xb0,0x11,0x3c,0x80,0x0c,0x24,0x36,0x94,0x0c,0x31,0x36, +0x12,0x80,0x00,0x00,0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00, +0x25,0x18,0x62,0x00,0x25,0x18,0x65,0x00,0x21,0x28,0x60,0x00,0x68,0x52,0x00,0x0c, +0x10,0x00,0xa3,0xaf,0x00,0x00,0x23,0x8e,0xff,0x0f,0x02,0x3c,0xc0,0x03,0x10,0x32, +0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x80,0x85,0x10,0x00,0x25,0x18,0x70,0x00, +0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x00,0x10,0x00,0xa3,0xaf,0x68,0x52,0x00,0x0c, +0x00,0x00,0x00,0x00,0x78,0x1b,0x83,0x26,0x08,0x00,0x62,0x8c,0x00,0x00,0x00,0x00, +0x59,0x01,0x40,0x04,0xc0,0x28,0x15,0x00,0x21,0x10,0xa3,0x00,0xac,0x00,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x22,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xad,0x00,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x23,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xae,0x00,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x24,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xaf,0x00,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x25,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb0,0x00,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x26,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb1,0x00,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x27,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb2,0x00,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x28,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb3,0x00,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x29,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x56,0x43,0xe3,0x92,0x22,0x00,0x02,0x24,0x03,0x00,0x62,0x10, +0x92,0x00,0x02,0x24,0x0d,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x78,0x1b,0x82,0x26, +0x08,0x00,0x43,0x8c,0x01,0x00,0x44,0x3a,0x24,0x00,0x02,0x24,0x02,0x1a,0x03,0x00, +0x3f,0x00,0x63,0x30,0x01,0x00,0x84,0x30,0x71,0x01,0x80,0x10,0x23,0x28,0x43,0x00, +0x42,0x18,0x12,0x00,0x40,0x10,0x03,0x00,0x21,0x90,0x43,0x00,0x78,0x1b,0x83,0x26, +0xc3,0x02,0x62,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x62,0x02,0x46,0x01,0x40,0x10, +0x2b,0x10,0x45,0x02,0x06,0x00,0x40,0x10,0x24,0x00,0x06,0x24,0x08,0x00,0x62,0x8c, +0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x21,0x30,0x52,0x00, +0x2b,0x28,0xc6,0x02,0x46,0x01,0xa0,0x10,0x78,0x1b,0x82,0x26,0x80,0x10,0x06,0x00, +0x78,0x1b,0x83,0x26,0x21,0x10,0x43,0x00,0x18,0x00,0x44,0x8c,0x00,0x00,0x00,0x00, +0x82,0x25,0x04,0x00,0x78,0x1b,0x83,0x26,0x10,0x00,0x70,0x8c,0x00,0x00,0x00,0x00, +0x82,0x3a,0x10,0x00,0xff,0x03,0xe7,0x30,0x3c,0x01,0xe0,0x10,0x00,0x02,0xe2,0x30, +0x04,0x00,0x40,0x10,0x18,0x00,0xe4,0x00,0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00, +0x18,0x00,0xe4,0x00,0x02,0x85,0x10,0x00,0xff,0x03,0x10,0x32,0x00,0x02,0x03,0x32, +0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,0x03,0x00,0x60,0x10,0xff,0x03,0x45,0x30, +0x00,0xfc,0x02,0x24,0x25,0x80,0x02,0x02,0x18,0x00,0x04,0x02,0x80,0x1d,0x04,0x00, +0x25,0xb0,0x11,0x3c,0x88,0x0c,0x24,0x36,0x9c,0x0c,0x31,0x36,0x12,0x80,0x00,0x00, +0x02,0x82,0x10,0x00,0x3f,0x00,0x02,0x32,0x00,0x14,0x02,0x00,0x25,0x18,0x62,0x00, +0x25,0x18,0x65,0x00,0x21,0x28,0x60,0x00,0x68,0x52,0x00,0x0c,0x10,0x00,0xa3,0xaf, +0x00,0x00,0x23,0x8e,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0xc0,0x03,0x10,0x32, +0x24,0x18,0x62,0x00,0x80,0x85,0x10,0x00,0x25,0x18,0x70,0x00,0x21,0x20,0x20,0x02, +0x21,0x28,0x60,0x00,0x68,0x52,0x00,0x0c,0x10,0x00,0xa3,0xaf,0x99,0x56,0x00,0x08, +0x00,0x00,0x00,0x00,0x80,0x0c,0x42,0x34,0x00,0x00,0x43,0x8c,0x21,0x30,0xa0,0x00, +0xc0,0xff,0x02,0x3c,0x24,0x20,0x62,0x00,0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c, +0xec,0x57,0x00,0x08,0x18,0x00,0xc3,0x24,0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e, +0x0d,0x00,0x40,0x10,0x02,0x80,0x17,0x3c,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00, +0x24,0x10,0x45,0x00,0xf8,0xff,0x44,0x14,0x04,0x00,0x63,0x24,0x08,0x00,0xc2,0x8c, +0xc0,0xff,0x03,0x24,0x3f,0x00,0x24,0x32,0x24,0x10,0x43,0x00,0x25,0x10,0x44,0x00, +0x08,0x00,0xc2,0xac,0x02,0x80,0x17,0x3c,0x56,0x43,0xe3,0x92,0x22,0x00,0x02,0x24, +0x3a,0x00,0x62,0x10,0x92,0x00,0x02,0x24,0x39,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c, +0x25,0xb0,0x02,0x3c,0x24,0x0a,0x42,0x34,0x00,0x00,0x44,0x8c,0x3f,0x3f,0x03,0x3c, +0x3f,0x3f,0x63,0x34,0x24,0x20,0x83,0x00,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c, +0x26,0x1c,0x53,0x24,0x2e,0x1d,0x72,0x24,0x21,0x88,0x00,0x00,0x13,0x58,0x00,0x08, +0x10,0x00,0xa4,0xaf,0x7b,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0x43,0x00,0x40,0x10, +0x78,0x1b,0x85,0x26,0x01,0x00,0x31,0x26,0x21,0x00,0x22,0x2e,0x17,0x00,0x40,0x10, +0x78,0x1b,0x82,0x26,0xc0,0x80,0x11,0x00,0x10,0x00,0xa4,0x27,0x21,0x28,0x13,0x02, +0x7b,0x46,0x00,0x0c,0x04,0x00,0x06,0x24,0x21,0x28,0x12,0x02,0x10,0x00,0xa4,0x27, +0xf0,0xff,0x40,0x14,0x04,0x00,0x06,0x24,0x78,0x1b,0x85,0x26,0x08,0x00,0xa3,0x8c, +0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00, +0x00,0x24,0x04,0x00,0xff,0x7f,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x08,0x00,0xa3,0xac,0x78,0x1b,0x82,0x26,0x0c,0x00,0x43,0x8c, +0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0x92,0x56,0x00,0x08,0x0c,0x00,0x43,0xac, +0xc6,0x02,0x02,0xa2,0xc0,0x56,0x00,0x08,0xc4,0x02,0x13,0xa6,0xbf,0x55,0x00,0x0c, +0x00,0x00,0x00,0x00,0xd0,0x56,0x00,0x08,0xc4,0x02,0x13,0xa6,0x25,0xb0,0x02,0x3c, +0x88,0x0c,0x42,0x34,0x00,0x00,0x44,0x8c,0x02,0x80,0x03,0x3c,0x78,0x1b,0x66,0x24, +0xc0,0xff,0x02,0x3c,0x24,0x20,0x82,0x00,0x21,0x88,0x00,0x00,0xc0,0xff,0x05,0x3c, +0x44,0x58,0x00,0x08,0x18,0x00,0xc3,0x24,0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e, +0xbc,0xff,0x40,0x10,0x25,0xb0,0x02,0x3c,0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00, +0x24,0x10,0x45,0x00,0xf8,0xff,0x44,0x14,0x04,0x00,0x63,0x24,0x08,0x00,0xc2,0x8c, +0x3f,0x00,0x23,0x32,0xff,0xc0,0x04,0x24,0x24,0x10,0x44,0x00,0x00,0x1a,0x03,0x00, +0x25,0x10,0x43,0x00,0xfe,0x57,0x00,0x08,0x08,0x00,0xc2,0xac,0x08,0x00,0xa3,0x8c, +0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00, +0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00,0x00,0x80,0x02,0x3c,0x27,0x58,0x00,0x08, +0x25,0x18,0x62,0x00,0x63,0x0c,0x23,0x36,0x00,0x00,0x62,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0xda,0x56,0x00,0x08,0x78,0x1b,0x83,0x26,0x98,0x00,0xe0,0x10, +0x21,0x40,0x00,0x00,0x2b,0x10,0x42,0x02,0x21,0x20,0x92,0x00,0x00,0x00,0x42,0x38, +0x24,0x00,0x08,0x24,0x2b,0x18,0x43,0x02,0x0b,0x40,0x82,0x00,0x7d,0xfe,0x60,0x10, +0x20,0x00,0x15,0x24,0x78,0x1b,0x83,0x26,0x0a,0x00,0x62,0x94,0x02,0x80,0x17,0x3c, +0x3f,0x00,0x42,0x30,0xec,0x56,0x00,0x08,0x21,0xa8,0x52,0x00,0x96,0x00,0xa0,0x10, +0x80,0x10,0x08,0x00,0x21,0x10,0x46,0x00,0x18,0x00,0x45,0x8c,0x25,0xb0,0x04,0x3c, +0x68,0x52,0x00,0x0c,0x80,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,0x94,0x0c,0x84,0x34, +0x21,0x57,0x00,0x08,0x21,0x28,0x00,0x00,0x21,0x10,0xa3,0x00,0xb4,0x01,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x22,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb5,0x01,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x23,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb6,0x01,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x24,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb7,0x01,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x25,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb8,0x01,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x26,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xb9,0x01,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x27,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xba,0x01,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x28,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x78,0x1b,0x82,0x26,0x21,0x10,0xa2,0x00,0xbb,0x01,0x44,0x90, +0x25,0xb0,0x03,0x3c,0x29,0x0a,0x63,0x34,0x00,0x00,0x64,0xa0,0x21,0x10,0x00,0x00, +0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x42,0x24,0x87,0x57,0x00,0x08,0x00,0x00,0x00,0x00,0x30,0x00,0x43,0x8c, +0xf5,0x56,0x00,0x08,0x82,0x25,0x03,0x00,0x08,0x00,0x62,0x8c,0x00,0x00,0x00,0x00, +0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x2b,0x18,0x42,0x02,0xbc,0xfe,0x60,0x14, +0x23,0x30,0x52,0x00,0x21,0x30,0x00,0x00,0x21,0x28,0x00,0x00,0x78,0x1b,0x82,0x26, +0x30,0x00,0x43,0x8c,0xaf,0x57,0x00,0x08,0x82,0x25,0x03,0x00,0x32,0x00,0xa0,0x10, +0x80,0x10,0x06,0x00,0x21,0x10,0x43,0x00,0x18,0x00,0x45,0x8c,0x25,0xb0,0x04,0x3c, +0x68,0x52,0x00,0x0c,0x88,0x0c,0x84,0x34,0x25,0xb0,0x04,0x3c,0x9c,0x0c,0x84,0x34, +0x68,0x52,0x00,0x0c,0x21,0x28,0x00,0x00,0x99,0x56,0x00,0x08,0x00,0x00,0x00,0x00, +0x23,0x10,0x92,0x00,0x2b,0x18,0x44,0x02,0x2b,0x20,0x45,0x02,0x0b,0x40,0x43,0x00, +0xe8,0xfd,0x80,0x14,0x23,0xa8,0xb2,0x00,0xeb,0x56,0x00,0x08,0x21,0xa8,0x00,0x00, +0xff,0xff,0x43,0x26,0x42,0x18,0x03,0x00,0x40,0x10,0x03,0x00,0x21,0x10,0x43,0x00, +0x99,0x57,0x00,0x08,0x01,0x00,0x52,0x24,0x30,0x00,0xc5,0x8c,0x7a,0x58,0x00,0x08, +0x25,0xb0,0x04,0x3c,0xff,0xff,0x05,0x36,0x60,0x00,0x06,0x24,0xb8,0x44,0x00,0x0c, +0x24,0x00,0x04,0x24,0x9c,0x12,0x00,0x0c,0xe8,0x03,0x04,0x24,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x24,0x00,0x04,0x24, +0xe3,0x44,0x00,0x0c,0xff,0xff,0x05,0x36,0x1f,0x00,0x53,0x30,0x00,0x60,0x01,0x40, +0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xcb,0x12,0x00,0x0c,0x64,0x00,0x04,0x24, +0xb2,0x56,0x00,0x08,0x25,0xb0,0x02,0x3c,0x30,0x00,0x65,0x8c,0xf6,0x58,0x00,0x08, +0x25,0xb0,0x04,0x3c,0x00,0xff,0x84,0x30,0x02,0x22,0x04,0x00,0x08,0x00,0x80,0x10, +0x02,0x80,0x02,0x3c,0xff,0x00,0x02,0x24,0x04,0x00,0x82,0x10,0xcc,0xff,0x03,0x24, +0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,0x62,0x1e,0x43,0xa0,0x02,0x80,0x02,0x3c, +0x08,0x00,0xe0,0x03,0x62,0x1e,0x44,0xa0,0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30, +0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00, +0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x78,0x1b,0x63,0x24,0x20,0x00,0x84,0x2c, +0x09,0x00,0x80,0x10,0x21,0x10,0x43,0x00,0x80,0x11,0x43,0x8c,0x25,0xb0,0x02,0x3c, +0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xac, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x6c,0x3f,0x43,0x8c, +0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30, +0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x85,0x30, +0xd2,0xff,0xa3,0x24,0xfe,0xff,0xa2,0x24,0xda,0xff,0xa4,0x24,0x04,0x00,0x63,0x2c, +0x08,0x00,0x84,0x2c,0x06,0x00,0x60,0x14,0xff,0x00,0x42,0x30,0xf0,0xff,0xa2,0x24, +0xfc,0xff,0xa3,0x24,0x16,0x00,0x46,0x2c,0x03,0x00,0x80,0x10,0xff,0x00,0x62,0x30, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xfa,0xff,0xa3,0x24,0xfc,0xff,0xc0,0x10, +0x21,0x10,0xa0,0x00,0x08,0x00,0xe0,0x03,0xff,0x00,0x62,0x30,0xe0,0xff,0xbd,0x27, +0x02,0x80,0x08,0x3c,0x78,0x1b,0x08,0x25,0x18,0x00,0xbf,0xaf,0xe8,0x02,0x07,0x8d, +0x02,0x80,0x02,0x3c,0x56,0x43,0x49,0x90,0x00,0x03,0x02,0x3c,0x25,0x38,0xe2,0x00, +0xff,0xf3,0x02,0x3c,0x02,0x80,0x03,0x3c,0xff,0xff,0x42,0x34,0xe4,0xb5,0x6a,0x24, +0x24,0x38,0xe2,0x00,0xff,0xff,0x03,0x34,0x01,0x80,0x06,0x3c,0x22,0x00,0x02,0x24, +0x21,0x20,0x40,0x01,0x44,0x66,0xc6,0x24,0x10,0x00,0xa5,0x27,0xe8,0x02,0x07,0xad, +0x00,0x24,0x03,0xad,0x05,0x00,0x22,0x11,0xfc,0x23,0x03,0xad,0x18,0x00,0xbf,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x44,0x00,0x02,0x24, +0x10,0x00,0xa2,0xa3,0x49,0x00,0x03,0x24,0x47,0x00,0x02,0x24,0x11,0x00,0xa3,0xa3, +0x12,0x00,0xa2,0xa3,0xd0,0x07,0x03,0x24,0x01,0x00,0x02,0x24,0x13,0x00,0xa0,0xa3, +0x0c,0x00,0x43,0xad,0xa8,0x14,0x00,0x0c,0x14,0x00,0x42,0xa1,0x18,0x00,0xbf,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27, +0x10,0x00,0xb0,0xaf,0x02,0x80,0x10,0x3c,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf, +0x78,0x1b,0x04,0x26,0xd8,0x02,0x82,0x8c,0x01,0x00,0x03,0x24,0x02,0x15,0x02,0x00, +0x0f,0x00,0x42,0x30,0x07,0x00,0x43,0x10,0x25,0xb0,0x06,0x3c,0x18,0x00,0xbf,0x8f, +0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0x4c,0x00,0xc3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00, +0x03,0x00,0x42,0x30,0x45,0x00,0x40,0x10,0xff,0xf3,0x02,0x3c,0xe8,0x02,0x85,0x8c, +0x00,0x00,0x00,0x00,0x82,0x16,0x05,0x00,0x03,0x00,0x42,0x30,0x17,0x00,0x40,0x14, +0x78,0x1b,0x11,0x26,0x0c,0x09,0xc3,0x34,0x00,0x00,0x63,0x8c,0x12,0x01,0x02,0x3c, +0x13,0x13,0x42,0x34,0x6b,0x00,0x62,0x10,0xff,0xfc,0x02,0x3c,0x22,0x02,0x02,0x3c, +0x23,0x13,0x42,0x34,0x52,0x00,0x62,0x10,0xff,0xfc,0x02,0x3c,0x00,0x03,0x02,0x3c, +0x25,0x10,0xa2,0x00,0xe8,0x02,0x82,0xac,0x78,0x1b,0x05,0x26,0xe8,0x02,0xa3,0x8c, +0xff,0xf3,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x04,0x04,0x3c, +0x25,0x18,0x64,0x00,0xe8,0x02,0xa3,0xac,0x78,0x1b,0x11,0x26,0xfc,0x23,0x24,0x8e, +0xff,0xff,0x02,0x34,0xd5,0xff,0x82,0x10,0x00,0x00,0x00,0x00,0x80,0x11,0x22,0x8e, +0x00,0x00,0x00,0x00,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30,0x3f,0x00,0x43,0x2c, +0x28,0x00,0x60,0x14,0x3b,0x00,0x42,0x2c,0x00,0x24,0x22,0x8e,0x02,0x19,0x04,0x00, +0x02,0x11,0x02,0x00,0x23,0x18,0x62,0x00,0x3a,0x00,0x60,0x18,0x01,0x00,0x03,0x24, +0xeb,0x02,0x22,0x92,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x0e,0x00,0x43,0x10, +0x78,0x1b,0x02,0x26,0x25,0xb0,0x04,0x3c,0x12,0x01,0x05,0x3c,0x0c,0x09,0x84,0x34, +0x68,0x52,0x00,0x0c,0x13,0x13,0xa5,0x34,0xe8,0x02,0x23,0x8e,0xff,0xfc,0x02,0x3c, +0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x01,0x04,0x3c,0x25,0x18,0x64,0x00, +0xe8,0x02,0x23,0xae,0x78,0x1b,0x02,0x26,0xe8,0x02,0x43,0x8c,0x00,0x20,0x04,0x3c, +0x25,0x18,0x64,0x00,0x9d,0x59,0x00,0x08,0xe8,0x02,0x43,0xac,0xe8,0x02,0x83,0x8c, +0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0x42,0x34, +0x24,0x18,0x62,0x00,0x20,0x00,0xbd,0x27,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03, +0xe8,0x02,0x83,0xac,0xa5,0xff,0x40,0x10,0x03,0x00,0x03,0x24,0xeb,0x02,0x22,0x92, +0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0xa0,0xff,0x43,0x10,0x32,0x03,0x05,0x3c, +0x25,0xb0,0x04,0x3c,0x0c,0x09,0x84,0x34,0x68,0x52,0x00,0x0c,0x33,0x13,0xa5,0x34, +0xe8,0x02,0x23,0x8e,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00, +0x00,0x03,0x04,0x3c,0x25,0x18,0x64,0x00,0x9d,0x59,0x00,0x08,0xe8,0x02,0x23,0xae, +0xff,0xff,0x42,0x34,0x24,0x10,0xa2,0x00,0x00,0x02,0x03,0x3c,0xbb,0x59,0x00,0x08, +0x25,0x10,0x43,0x00,0xeb,0x02,0x22,0x92,0x02,0x00,0x03,0x24,0x03,0x00,0x42,0x30, +0xd5,0xff,0x43,0x10,0x78,0x1b,0x02,0x26,0x25,0xb0,0x04,0x3c,0x22,0x02,0x05,0x3c, +0x0c,0x09,0x84,0x34,0x68,0x52,0x00,0x0c,0x23,0x13,0xa5,0x34,0xe8,0x02,0x23,0x8e, +0xff,0xfc,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0xe5,0x59,0x00,0x08, +0x00,0x02,0x04,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0xa2,0x00,0x00,0x01,0x03,0x3c, +0xbb,0x59,0x00,0x08,0x25,0x10,0x43,0x00,0x25,0xb0,0x03,0x3c,0x03,0x0d,0x63,0x34, +0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xff,0x00,0x42,0x30,0x08,0x00,0x42,0x34, +0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c, +0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x03,0x0d,0x63,0x34, +0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00,0xf7,0x00,0x42,0x30,0x00,0x00,0x62,0xa0, +0x01,0x00,0x82,0x24,0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14, +0x01,0x00,0x82,0x24,0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,0x00,0x00,0x62,0x90, +0x21,0x20,0x00,0x00,0x3f,0x00,0x42,0x30,0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24, +0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24, +0x25,0xb0,0x03,0x3c,0x2d,0x0a,0x63,0x34,0x00,0x00,0x62,0x90,0x21,0x20,0x00,0x00, +0xff,0x00,0x42,0x30,0x80,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0x01,0x00,0x82,0x24, +0xff,0x00,0x44,0x30,0x06,0x00,0x83,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0xff,0x00,0x03,0x3c, +0x82,0x01,0x49,0x34,0x81,0x01,0x48,0x34,0x24,0x10,0x83,0x00,0x02,0x3c,0x02,0x00, +0x00,0xff,0x63,0x34,0x02,0x80,0x02,0x3c,0x78,0x1b,0x45,0x24,0x02,0x32,0x04,0x00, +0x01,0x00,0x02,0x24,0x24,0x20,0x83,0x00,0xda,0x0c,0xa2,0xa0,0xc8,0x0c,0xa0,0xac, +0xcc,0x0c,0xa0,0xac,0xd0,0x0c,0xa0,0xac,0x06,0x00,0x80,0x14,0xd4,0x0c,0xa0,0xac, +0x00,0x00,0x02,0x91,0x00,0x00,0x23,0x91,0xd8,0x0c,0xa2,0xa0,0x08,0x00,0xe0,0x03, +0xd9,0x0c,0xa3,0xa0,0xd9,0x0c,0xa7,0xa0,0x08,0x00,0xe0,0x03,0xd8,0x0c,0xa6,0xa0, +0x02,0x80,0x03,0x3c,0x78,0x1b,0x63,0x24,0xd9,0x0c,0x66,0x90,0xd8,0x0c,0x65,0x90, +0x25,0xb0,0x02,0x3c,0x82,0x01,0x44,0x34,0x81,0x01,0x42,0x34,0x00,0x00,0x45,0xa0, +0x00,0x00,0x86,0xa0,0x08,0x00,0xe0,0x03,0xda,0x0c,0x60,0xa0,0x02,0x80,0x08,0x3c, +0x78,0x1b,0x04,0x25,0xda,0x0c,0x82,0x90,0x00,0x00,0x00,0x00,0x15,0x00,0x40,0x10, +0x21,0x18,0x00,0x00,0xcc,0x0c,0x82,0x8c,0xc8,0x0c,0x85,0x8c,0x25,0xb0,0x03,0x3c, +0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x82,0x01,0x67,0x34,0x0f,0x00,0x40,0x10, +0x81,0x01,0x66,0x34,0xd9,0x0c,0x83,0x90,0xd8,0x0c,0x82,0x90,0xf0,0x00,0x63,0x30, +0x1f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0,0x00,0x00,0xe3,0xa0,0x78,0x1b,0x02,0x25, +0x01,0x00,0x03,0x24,0xd4,0x0c,0x40,0xac,0xc8,0x0c,0x40,0xac,0xcc,0x0c,0x40,0xac, +0xd0,0x0c,0x40,0xac,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xd0,0x0c,0x82,0x8c, +0x25,0xb0,0x03,0x3c,0x82,0x01,0x69,0x34,0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00, +0x0e,0x00,0x40,0x14,0x81,0x01,0x66,0x34,0xd4,0x0c,0x82,0x8c,0x00,0x00,0x00,0x00, +0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x08,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0xd9,0x0c,0x83,0x90,0xd8,0x0c,0x82,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa0, +0x00,0x00,0x23,0xa1,0x8e,0x5a,0x00,0x08,0x78,0x1b,0x02,0x25,0xd9,0x0c,0x83,0x90, +0xd8,0x0c,0x82,0x90,0xf0,0x00,0x63,0x30,0x7f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0, +0x00,0x00,0x23,0xa1,0x8e,0x5a,0x00,0x08,0x78,0x1b,0x02,0x25,0x00,0x00,0x85,0xac, +0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30,0x06,0x00,0x43,0x2c, +0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x25,0xb0,0x03,0x3c,0x33,0x02,0x65,0x34,0x00,0x11,0x04,0x00,0x00,0x00,0xa2,0xa0, +0x30,0x02,0x63,0x34,0x00,0x00,0x65,0x8c,0x0f,0x00,0x02,0x3c,0xff,0xff,0x42,0x34, +0x24,0x28,0xa2,0x00,0x01,0x00,0x03,0x24,0x04,0x18,0x83,0x00,0x02,0x00,0xa0,0x10, +0x21,0x10,0x00,0x00,0xff,0xff,0x62,0x30,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x25,0xb0,0x11,0x3c,0x18,0x00,0xb2,0xaf, +0x4c,0x00,0x22,0x36,0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x44,0x90, +0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x24,0xff,0x00,0x84,0x30,0x07,0x00,0x82,0x10, +0x78,0x1b,0x72,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f, +0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x52,0x24,0x43,0x96, +0x01,0x00,0x02,0x24,0xf7,0xff,0x62,0x14,0x21,0x20,0x00,0x00,0xba,0x5a,0x00,0x0c, +0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x24,0xba,0x5a,0x00,0x0c,0x21,0x80,0x40,0x00, +0x25,0x80,0x02,0x02,0x33,0x02,0x23,0x36,0x08,0x00,0x02,0x24,0xff,0xff,0x10,0x32, +0x40,0x00,0x25,0x36,0x00,0x00,0x62,0xa0,0xea,0xff,0x00,0x16,0x00,0x00,0x00,0x00, +0x00,0x00,0xa2,0x94,0x50,0x24,0x43,0x96,0xff,0xdf,0x42,0x30,0x00,0x20,0x44,0x34, +0x01,0x00,0x63,0x24,0x50,0x24,0x43,0xa6,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa4,0xa4, +0xd7,0x5a,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xb8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c, +0x3c,0x00,0xb1,0xaf,0x38,0x00,0xb0,0xaf,0x40,0x00,0xbf,0xaf,0x78,0x1b,0x50,0x24, +0x04,0x24,0x03,0x8e,0x02,0x80,0x11,0x3c,0x01,0x00,0x02,0x24,0x01,0x00,0x63,0x30, +0x10,0x00,0xa4,0x27,0x80,0x3f,0x25,0x26,0x07,0x00,0x62,0x10,0x0a,0x00,0x06,0x24, +0x40,0x00,0xbf,0x8f,0x3c,0x00,0xb1,0x8f,0x38,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00, +0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,0x52,0x46,0x00,0x0c,0x00,0x00,0x00,0x00, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40, +0x21,0x28,0x00,0x00,0x80,0x3f,0x24,0x26,0x3e,0x46,0x00,0x0c,0x0a,0x00,0x06,0x24, +0x28,0x00,0x03,0x24,0x05,0x00,0x02,0x24,0x09,0x24,0x03,0xa2,0x08,0x24,0x02,0xa2, +0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x39,0x15,0x00,0x0c, +0x48,0x00,0x04,0x24,0x21,0x80,0x40,0x00,0x10,0x00,0xa5,0x27,0xe4,0xff,0x40,0x10, +0x0a,0x00,0x06,0x24,0x08,0x00,0x44,0x94,0x14,0x00,0x02,0x24,0x14,0x00,0x02,0xae, +0x02,0x80,0x02,0x3c,0x28,0x00,0x03,0x24,0x25,0x20,0x82,0x00,0x0c,0x00,0x03,0xae, +0x52,0x46,0x00,0x0c,0x20,0x00,0x84,0x24,0x59,0x0a,0x00,0x0c,0x21,0x20,0x00,0x02, +0x0a,0x5b,0x00,0x08,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x21,0x20,0x82,0x00, +0x00,0x00,0x85,0xac,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0x00,0x42,0x30, +0x06,0x00,0x43,0x2c,0xfc,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0xe8,0xff,0xbd,0x27,0xff,0x00,0xa5,0x30,0x10,0x00,0xb0,0xaf, +0x14,0x00,0xbf,0xaf,0x18,0x00,0xa0,0x14,0xff,0x00,0x90,0x30,0x2c,0x00,0x00,0x12, +0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x01,0x00,0x07,0x24,0xb0,0x44,0x67,0xa0, +0x02,0x80,0x08,0x3c,0xb2,0x44,0x02,0x91,0x02,0x00,0x04,0x24,0x21,0x28,0x00,0x00, +0x02,0x00,0x42,0x34,0x00,0x03,0x06,0x24,0xb2,0x44,0x02,0xa1,0x71,0x14,0x00,0x0c, +0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x42,0xb0,0x02,0x3c, +0x44,0x00,0x03,0x24,0x03,0x00,0x42,0x34,0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa0, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x00,0x03,0x24,0x02,0x80,0x02,0x3c, +0xb0,0x44,0x43,0xa0,0x02,0x80,0x02,0x3c,0xb3,0x44,0x43,0x90,0x0f,0x00,0x02,0x24, +0x02,0x80,0x05,0x3c,0x0f,0x00,0x63,0x30,0x07,0x00,0x62,0x10,0x01,0x00,0x04,0x24, +0xb2,0x44,0xa2,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x34,0xb2,0x44,0xa2,0xa0, +0x1c,0x46,0x00,0x0c,0x00,0x00,0x00,0x00,0xdb,0xff,0x00,0x16,0x02,0x80,0x03,0x3c, +0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27, +0xb0,0x44,0x40,0xa0,0x02,0x80,0x03,0x3c,0x99,0x44,0x64,0x90,0x14,0x00,0xbf,0x8f, +0x10,0x00,0xb0,0x8f,0xff,0x00,0x84,0x30,0xf9,0x1f,0x00,0x08,0x18,0x00,0xbd,0x27, +0xe8,0xff,0xbd,0x27,0x10,0x00,0xb2,0xaf,0x0c,0x00,0xb1,0xaf,0x08,0x00,0xb0,0xaf, +0x21,0x40,0xe0,0x00,0x21,0x90,0xa0,0x03,0x21,0x60,0xc0,0x00,0x21,0x78,0x80,0x00, +0x45,0x00,0xe0,0x14,0x21,0x50,0xa0,0x00,0x2b,0x10,0xa6,0x00,0x78,0x00,0x40,0x10, +0xff,0xff,0x02,0x34,0x2b,0x10,0x46,0x00,0x8f,0x01,0x40,0x10,0x21,0x28,0xc0,0x00, +0xff,0x00,0x02,0x3c,0xff,0xff,0x42,0x34,0x10,0x00,0x03,0x24,0x2b,0x10,0x46,0x00, +0x18,0x00,0x04,0x24,0x21,0x30,0x60,0x00,0x0b,0x30,0x82,0x00,0x02,0x80,0x03,0x3c, +0x06,0x10,0xc5,0x00,0xfc,0xb2,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x90, +0x20,0x00,0x02,0x24,0x21,0x20,0x86,0x00,0x23,0x30,0x44,0x00,0x08,0x00,0xc0,0x10, +0x02,0x4c,0x0c,0x00,0x23,0x10,0x46,0x00,0x06,0x10,0x4f,0x00,0x04,0x18,0xca,0x00, +0x25,0x50,0x62,0x00,0x04,0x60,0xcc,0x00,0x04,0x78,0xcf,0x00,0x02,0x4c,0x0c,0x00, +0x1b,0x00,0x49,0x01,0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00, +0xff,0xff,0x87,0x31,0x02,0x24,0x0f,0x00,0x12,0x18,0x00,0x00,0x10,0x28,0x00,0x00, +0x00,0x14,0x05,0x00,0x25,0x28,0x44,0x00,0x18,0x00,0x67,0x00,0x12,0x58,0x00,0x00, +0x2b,0x18,0xab,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x49,0x01,0x02,0x00,0x20,0x15, +0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x08,0x00,0x60,0x10,0x00,0x00,0x00,0x00, +0x21,0x28,0xac,0x00,0x2b,0x10,0xac,0x00,0x04,0x00,0x40,0x14,0x2b,0x10,0xab,0x00, +0x00,0x00,0x42,0x38,0x21,0x18,0xac,0x00,0x0b,0x28,0x62,0x00,0x23,0x28,0xab,0x00, +0x1b,0x00,0xa9,0x00,0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00, +0xff,0xff,0xe4,0x31,0x12,0x18,0x00,0x00,0x10,0x40,0x00,0x00,0x00,0x00,0x00,0x00, +0x42,0x5c,0x00,0x08,0x18,0x00,0x67,0x00,0x2b,0x10,0xa7,0x00,0x0a,0x00,0x40,0x10, +0xff,0xff,0x02,0x34,0x10,0x00,0xb2,0x8f,0x0c,0x00,0xb1,0x8f,0x08,0x00,0xb0,0x8f, +0x21,0x10,0x80,0x00,0x21,0x18,0xa0,0x00,0x00,0x00,0xa4,0xaf,0x04,0x00,0xa5,0xaf, +0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x2b,0x10,0x47,0x00,0xd2,0x00,0x40,0x10, +0x00,0x01,0xe3,0x2c,0xff,0x00,0x02,0x3c,0x10,0x00,0x03,0x24,0xff,0xff,0x42,0x34, +0x2b,0x10,0x47,0x00,0x18,0x00,0x04,0x24,0x21,0x28,0x60,0x00,0x0b,0x28,0x82,0x00, +0x06,0x10,0xa8,0x00,0x02,0x80,0x03,0x3c,0xfc,0xb2,0x63,0x24,0x21,0x10,0x43,0x00, +0x00,0x00,0x44,0x90,0x20,0x00,0x02,0x24,0x21,0x20,0x85,0x00,0x23,0x30,0x44,0x00, +0xce,0x00,0xc0,0x14,0x23,0x38,0x46,0x00,0x2b,0x10,0x0a,0x01,0x04,0x00,0x40,0x14, +0x23,0x20,0xec,0x01,0x2b,0x10,0xec,0x01,0x05,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x2b,0x10,0xe4,0x01,0x23,0x18,0x48,0x01,0x23,0x50,0x62,0x00,0x21,0x78,0x80,0x00, +0x04,0x00,0x40,0x12,0x21,0xc0,0xe0,0x01,0x21,0xc8,0x40,0x01,0x00,0x00,0x58,0xae, +0x04,0x00,0x59,0xae,0x00,0x00,0xa2,0x8f,0x04,0x00,0xa3,0x8f,0x10,0x00,0xb2,0x8f, +0x0c,0x00,0xb1,0x8f,0x08,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27, +0x53,0x00,0xc0,0x10,0x01,0x00,0x02,0x24,0xff,0xff,0x02,0x34,0x2b,0x10,0x4c,0x00, +0x59,0x00,0x40,0x14,0xff,0x00,0x02,0x3c,0x00,0x01,0x83,0x2d,0x08,0x00,0x02,0x24, +0x21,0x28,0x00,0x00,0x0a,0x28,0x43,0x00,0x06,0x10,0xac,0x00,0x02,0x80,0x03,0x3c, +0xfc,0xb2,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x90,0x20,0x00,0x02,0x24, +0x21,0x20,0x85,0x00,0x23,0x30,0x44,0x00,0x5b,0x00,0xc0,0x14,0x00,0x00,0x00,0x00, +0x23,0x50,0x4c,0x01,0x02,0x4c,0x0c,0x00,0xff,0xff,0x8d,0x31,0x1b,0x00,0x49,0x01, +0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x02,0x24,0x0f,0x00, +0x12,0x18,0x00,0x00,0x10,0x28,0x00,0x00,0x00,0x14,0x05,0x00,0x25,0x28,0x44,0x00, +0x18,0x00,0x6d,0x00,0x12,0x58,0x00,0x00,0x2b,0x18,0xab,0x00,0x00,0x00,0x00,0x00, +0x1b,0x00,0x49,0x01,0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00, +0x08,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x21,0x28,0xac,0x00,0x2b,0x10,0xac,0x00, +0x04,0x00,0x40,0x14,0x2b,0x10,0xab,0x00,0x00,0x00,0x42,0x38,0x21,0x18,0xac,0x00, +0x0b,0x28,0x62,0x00,0x23,0x28,0xab,0x00,0x1b,0x00,0xa9,0x00,0x02,0x00,0x20,0x15, +0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0xff,0xff,0xe4,0x31,0x12,0x18,0x00,0x00, +0x10,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x6d,0x00, +0x00,0x14,0x08,0x00,0x12,0x58,0x00,0x00,0x25,0x40,0x44,0x00,0x2b,0x18,0x0b,0x01, +0x1b,0x00,0xa9,0x00,0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00, +0x08,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x21,0x40,0x0c,0x01,0x2b,0x10,0x0c,0x01, +0x04,0x00,0x40,0x14,0x2b,0x10,0x0b,0x01,0x21,0x18,0x0c,0x01,0x00,0x00,0x42,0x38, +0x0b,0x40,0x62,0x00,0xab,0xff,0x40,0x12,0x23,0x78,0x0b,0x01,0x06,0xc0,0xcf,0x00, +0x21,0xc8,0x00,0x00,0x00,0x00,0x58,0xae,0xff,0x5b,0x00,0x08,0x04,0x00,0x59,0xae, +0x1b,0x00,0x47,0x00,0x02,0x00,0xe0,0x14,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00, +0xff,0xff,0x02,0x34,0x12,0x60,0x00,0x00,0x2b,0x10,0x4c,0x00,0xab,0xff,0x40,0x10, +0x00,0x01,0x83,0x2d,0xff,0x00,0x02,0x3c,0x10,0x00,0x03,0x24,0xff,0xff,0x42,0x34, +0x2b,0x10,0x4c,0x00,0x18,0x00,0x04,0x24,0x21,0x28,0x60,0x00,0x0b,0x28,0x82,0x00, +0x02,0x80,0x03,0x3c,0x06,0x10,0xac,0x00,0xfc,0xb2,0x63,0x24,0x21,0x10,0x43,0x00, +0x00,0x00,0x44,0x90,0x20,0x00,0x02,0x24,0x21,0x20,0x85,0x00,0x23,0x30,0x44,0x00, +0xa7,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,0x23,0x38,0x46,0x00,0x04,0x60,0xcc,0x00, +0x06,0x58,0xea,0x00,0x02,0x4c,0x0c,0x00,0x1b,0x00,0x69,0x01,0x02,0x00,0x20,0x15, +0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0xff,0xff,0x8d,0x31,0x06,0x18,0xef,0x00, +0x04,0x10,0xca,0x00,0x25,0x50,0x43,0x00,0x02,0x24,0x0a,0x00,0x12,0x28,0x00,0x00, +0x10,0x40,0x00,0x00,0x00,0x14,0x08,0x00,0x25,0x40,0x44,0x00,0x18,0x00,0xad,0x00, +0x12,0x28,0x00,0x00,0x2b,0x18,0x05,0x01,0x00,0x00,0x00,0x00,0x1b,0x00,0x69,0x01, +0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x05,0x00,0x60,0x10, +0x04,0x78,0xcf,0x00,0x21,0x40,0x0c,0x01,0x2b,0x10,0x0c,0x01,0x93,0x00,0x40,0x10, +0x2b,0x10,0x05,0x01,0x23,0x40,0x05,0x01,0x1b,0x00,0x09,0x01,0x02,0x00,0x20,0x15, +0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0xff,0xff,0x44,0x31,0x12,0x18,0x00,0x00, +0x10,0x58,0x00,0x00,0x00,0x14,0x0b,0x00,0x25,0x58,0x44,0x00,0x18,0x00,0x6d,0x00, +0x12,0x28,0x00,0x00,0x2b,0x18,0x65,0x01,0x00,0x00,0x00,0x00,0x1b,0x00,0x09,0x01, +0x02,0x00,0x20,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x77,0xff,0x60,0x10, +0x23,0x50,0x65,0x01,0x21,0x58,0x6c,0x01,0x2b,0x10,0x6c,0x01,0x04,0x00,0x40,0x14, +0x2b,0x10,0x65,0x01,0x00,0x00,0x42,0x38,0x21,0x18,0x6c,0x01,0x0b,0x58,0x62,0x00, +0x1d,0x5c,0x00,0x08,0x23,0x50,0x65,0x01,0x08,0x00,0x02,0x24,0x21,0x28,0x00,0x00, +0x0a,0x28,0x43,0x00,0x02,0x80,0x03,0x3c,0x06,0x10,0xa8,0x00,0xfc,0xb2,0x63,0x24, +0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x90,0x20,0x00,0x02,0x24,0x21,0x20,0x85,0x00, +0x23,0x30,0x44,0x00,0x34,0xff,0xc0,0x10,0x23,0x38,0x46,0x00,0x06,0x10,0xec,0x00, +0x04,0x18,0xc8,0x00,0x25,0x40,0x62,0x00,0x06,0x58,0xea,0x00,0x02,0x6c,0x08,0x00, +0x1b,0x00,0x6d,0x01,0x02,0x00,0xa0,0x15,0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00, +0xff,0xff,0x11,0x31,0x06,0x10,0xef,0x00,0x04,0x18,0xca,0x00,0x25,0x50,0x62,0x00, +0x02,0x24,0x0a,0x00,0x04,0x60,0xcc,0x00,0x12,0x80,0x00,0x00,0x10,0x48,0x00,0x00, +0x00,0x14,0x09,0x00,0x25,0x48,0x44,0x00,0x12,0x28,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x00,0x11,0x02,0x12,0x70,0x00,0x00,0x2b,0x18,0x2e,0x01, +0x00,0x00,0x00,0x00,0x1b,0x00,0x6d,0x01,0x02,0x00,0xa0,0x15,0x00,0x00,0x00,0x00, +0x0d,0x00,0x07,0x00,0x0a,0x00,0x60,0x10,0x04,0x78,0xcf,0x00,0x21,0x48,0x28,0x01, +0x2b,0x10,0x28,0x01,0x06,0x00,0x40,0x14,0xff,0xff,0xb0,0x24,0x2b,0x10,0x2e,0x01, +0x03,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0x10,0x26,0x21,0x48,0x28,0x01, +0x23,0x48,0x2e,0x01,0x1b,0x00,0x2d,0x01,0x02,0x00,0xa0,0x15,0x00,0x00,0x00,0x00, +0x0d,0x00,0x07,0x00,0xff,0xff,0x44,0x31,0x12,0x28,0x00,0x00,0x10,0x58,0x00,0x00, +0x00,0x14,0x0b,0x00,0x25,0x58,0x44,0x00,0x18,0x00,0xb1,0x00,0x12,0x70,0x00,0x00, +0x2b,0x18,0x6e,0x01,0x00,0x00,0x00,0x00,0x1b,0x00,0x2d,0x01,0x02,0x00,0xa0,0x15, +0x00,0x00,0x00,0x00,0x0d,0x00,0x07,0x00,0x0b,0x00,0x60,0x10,0x00,0x14,0x10,0x00, +0x21,0x58,0x68,0x01,0x2b,0x10,0x68,0x01,0x06,0x00,0x40,0x14,0xff,0xff,0xa5,0x24, +0x2b,0x10,0x6e,0x01,0x04,0x00,0x40,0x10,0x00,0x14,0x10,0x00,0xff,0xff,0xa5,0x24, +0x21,0x58,0x68,0x01,0x00,0x14,0x10,0x00,0x25,0x10,0x45,0x00,0x23,0x58,0x6e,0x01, +0x19,0x00,0x4c,0x00,0x10,0x28,0x00,0x00,0x2b,0x18,0x65,0x01,0x12,0x48,0x00,0x00, +0x05,0x00,0x60,0x14,0x23,0x20,0x2c,0x01,0x07,0x00,0xab,0x14,0x2b,0x10,0xe9,0x01, +0x05,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x24,0x01,0x23,0x18,0xa8,0x00, +0x23,0x28,0x62,0x00,0x21,0x48,0x80,0x00,0xea,0xfe,0x40,0x12,0x23,0x18,0xe9,0x01, +0x23,0x20,0x65,0x01,0x2b,0x10,0xe3,0x01,0x23,0x50,0x82,0x00,0x04,0x28,0xea,0x00, +0x06,0x18,0xc3,0x00,0x25,0xc0,0xa3,0x00,0x06,0xc8,0xca,0x00,0x00,0x00,0x58,0xae, +0xff,0x5b,0x00,0x08,0x04,0x00,0x59,0xae,0x00,0x01,0xc3,0x2c,0x08,0x00,0x02,0x24, +0x21,0x30,0x00,0x00,0x99,0x5b,0x00,0x08,0x0a,0x30,0x43,0x00,0x00,0x00,0x42,0x38, +0x21,0x18,0x0c,0x01,0x93,0x5c,0x00,0x08,0x0b,0x40,0x62,0x00,0x25,0xb0,0x02,0x3c, +0x4d,0x00,0x44,0x34,0xff,0x00,0x03,0x3c,0xec,0x02,0x42,0x34,0x00,0x00,0x43,0xac, +0x00,0x00,0x80,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0xc4,0x74,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x7f,0x00,0x02,0x3c,0x0d,0xb8,0x46,0x34, +0x80,0x00,0x03,0x3c,0x25,0x30,0xc3,0x00,0x00,0x04,0x02,0x3c,0x25,0x30,0xc2,0x00, +0x00,0x08,0x03,0x3c,0x25,0x30,0xc3,0x00,0x02,0x80,0x04,0x3c,0x01,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x78,0x1b,0x84,0x24,0x41,0xb0,0x05,0x3c,0xe0,0x74,0x63,0x24, +0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0xa6,0xac,0x10,0x0b,0x86,0xac, +0x08,0x0b,0x86,0xac,0x08,0x00,0xa5,0x34,0x86,0x00,0x06,0x24,0x00,0x00,0xa6,0xa4, +0x14,0x0b,0x86,0xa4,0x0c,0x0b,0x80,0xac,0x16,0x0b,0x80,0xa4,0x08,0x00,0xe0,0x03, +0x18,0x0b,0x86,0xa4,0x53,0x5d,0x00,0x08,0x00,0x00,0x00,0x00,0x42,0xb0,0x02,0x3c, +0xa0,0xff,0x03,0x24,0x01,0x00,0x42,0x34,0xe8,0xff,0xbd,0x27,0x21,0x20,0x00,0x00, +0x01,0x00,0x05,0x24,0x00,0x01,0x06,0x24,0x00,0x00,0x43,0xa0,0x10,0x00,0xbf,0xaf, +0x71,0x14,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,0x03,0x00,0x04,0x24, +0x01,0x00,0x05,0x24,0x40,0x1f,0x06,0x24,0x71,0x14,0x00,0x08,0x18,0x00,0xbd,0x27, +0x25,0xb0,0x03,0x3c,0x01,0x80,0x02,0x3c,0xe0,0xff,0xbd,0x27,0x18,0x03,0x64,0x34, +0x98,0x75,0x42,0x24,0x00,0x00,0x82,0xac,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf, +0x18,0x00,0xbf,0xaf,0xb6,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x02,0x80,0x10,0x3c, +0x78,0x1b,0x10,0x26,0xe3,0x0a,0x02,0xa2,0x34,0x61,0x00,0x0c,0xee,0x23,0x00,0xa2, +0xff,0xff,0x02,0x34,0x21,0x88,0x00,0x02,0xf8,0x23,0x02,0xae,0xf0,0x23,0x00,0xa6, +0xf2,0x23,0x00,0xa6,0xf4,0x23,0x02,0xae,0x21,0x28,0x00,0x00,0x21,0x20,0x00,0x02, +0x04,0x00,0xa2,0x24,0x01,0x00,0xa5,0x24,0x20,0x00,0xa3,0x28,0xee,0x0c,0x82,0xa4, +0xdc,0x0c,0x80,0xa4,0xde,0x0c,0x80,0xa4,0xe0,0x0c,0x80,0xa4,0xe2,0x0c,0x80,0xa4, +0xe4,0x0c,0x80,0xa4,0xe6,0x0c,0x80,0xa4,0xe8,0x0c,0x80,0xa4,0xea,0x0c,0x80,0xa4, +0xec,0x0c,0x80,0xa4,0xf0,0x0c,0x80,0xa0,0xf1,0xff,0x60,0x14,0x24,0x00,0x84,0x24, +0x25,0xb0,0x02,0x3c,0x10,0x00,0x03,0x24,0xb0,0x03,0x42,0x34,0x02,0x80,0x04,0x3c, +0xa0,0x1e,0x84,0x24,0x00,0x00,0x43,0xac,0x21,0x28,0x00,0x00,0x3e,0x46,0x00,0x0c, +0x04,0x00,0x06,0x24,0x11,0x62,0x00,0x0c,0x00,0x00,0x00,0x00,0x84,0x62,0x00,0x0c, +0xec,0x25,0x20,0xae,0xe6,0x63,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c, +0x56,0x43,0x64,0x90,0x92,0x00,0x02,0x24,0x03,0x00,0x82,0x10,0x00,0x00,0x00,0x00, +0x5c,0x64,0x00,0x0c,0x00,0x00,0x00,0x00,0x42,0x64,0x00,0x0c,0x00,0x00,0x00,0x00, +0xbd,0x62,0x00,0x0c,0x00,0x00,0x00,0x00,0xc9,0x64,0x00,0x0c,0x00,0x00,0x00,0x00, +0x50,0x24,0x20,0xa6,0xaf,0x64,0x00,0x0c,0x52,0x24,0x20,0xa6,0xf3,0x64,0x00,0x0c, +0x00,0x00,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f, +0x02,0x80,0x05,0x3c,0x02,0x80,0x06,0x3c,0x02,0x80,0x07,0x3c,0x68,0x41,0xa2,0x24, +0x70,0x41,0xc3,0x24,0x78,0x41,0xe4,0x24,0x20,0x00,0xbd,0x27,0x04,0x00,0x42,0xac, +0x68,0x41,0xa2,0xac,0x04,0x00,0x63,0xac,0x70,0x41,0xc3,0xac,0x78,0x41,0xe4,0xac, +0x08,0x00,0xe0,0x03,0x04,0x00,0x84,0xac,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c, +0xe8,0xff,0xbd,0x27,0x00,0x77,0x63,0x24,0x18,0x03,0x42,0x34,0x14,0x00,0xbf,0xaf, +0x10,0x00,0xb0,0xaf,0x00,0x00,0x43,0xac,0x21,0x20,0x00,0x00,0x01,0x00,0x82,0x24, +0xff,0xff,0x44,0x30,0x64,0x00,0x83,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x82,0x24, +0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x52,0x43,0x48,0x90,0x50,0x43,0x65,0x94, +0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x53,0x43,0x46,0x90,0x60,0x43,0x67,0x90, +0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x6b,0x43,0x49,0x90,0x6d,0x43,0x6a,0x90, +0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x70,0x43,0x4b,0x90,0x72,0x43,0x6c,0x90, +0x02,0x80,0x02,0x3c,0x07,0x00,0x03,0x24,0x25,0xb0,0x04,0x3c,0x5d,0x43,0x43,0xa0, +0xb0,0x03,0x84,0x34,0x02,0x80,0x02,0x3c,0x00,0x00,0x85,0xac,0x5e,0x43,0x40,0xa0, +0x02,0x80,0x02,0x3c,0x00,0x00,0x86,0xac,0x5f,0x43,0x40,0xa0,0x02,0x80,0x02,0x3c, +0x00,0x00,0x87,0xac,0x02,0x80,0x03,0x3c,0x80,0x43,0x40,0xa0,0x02,0x80,0x10,0x3c, +0x02,0x80,0x02,0x3c,0x78,0x1b,0x0d,0x26,0x7e,0x43,0x60,0xa4,0x7c,0x43,0x40,0xa4, +0x01,0x00,0x03,0x24,0xfd,0xff,0x02,0x24,0xe0,0x0a,0xa3,0xa1,0xe2,0x0a,0xa2,0xa1, +0xff,0x07,0x03,0x24,0x00,0x78,0x02,0x24,0xe6,0x0a,0xa3,0xa5,0xe4,0x0a,0xa2,0xa5, +0xff,0xff,0x03,0x24,0x02,0x80,0x02,0x3c,0x00,0x00,0x88,0xac,0x0f,0x00,0x0e,0x31, +0x00,0x00,0x89,0xac,0x00,0x00,0x8a,0xac,0x00,0x00,0x8b,0xac,0x00,0x00,0x8c,0xac, +0x91,0x43,0x43,0xa0,0x02,0x00,0x02,0x24,0xe8,0x0a,0xa0,0xa1,0x31,0x00,0xc2,0x11, +0x82,0x0b,0xa0,0xa1,0x00,0x80,0x02,0x3c,0x15,0x15,0x03,0x3c,0x02,0xbc,0x42,0x34, +0x07,0x07,0x63,0x34,0x74,0x0b,0xa2,0xad,0x6c,0x0b,0xa3,0xad,0x02,0x02,0x02,0x3c, +0x70,0x0b,0xa2,0xad,0x02,0x80,0x02,0x3c,0x25,0xb0,0x04,0x3c,0x9c,0x43,0x40,0xa4, +0x0a,0x00,0x83,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x30, +0x12,0x00,0x40,0x10,0x4c,0x87,0x02,0x3c,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00, +0x10,0x00,0x42,0x30,0x38,0x00,0x40,0x14,0x21,0x20,0x00,0x00,0x08,0x00,0x82,0x24, +0xff,0xff,0x44,0x30,0x80,0x00,0x83,0x2c,0xfc,0xff,0x60,0x14,0x78,0x1b,0x03,0x26, +0x01,0x00,0x02,0x24,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x05,0x00,0x04,0x24, +0x8b,0x0b,0x62,0xa0,0x93,0x12,0x00,0x08,0x18,0x00,0xbd,0x27,0x54,0x00,0x85,0x34, +0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34,0x12,0x01,0x03,0x24,0x00,0x00,0x82,0xac, +0x00,0x00,0xa3,0xac,0x01,0x00,0x02,0x24,0x78,0x1b,0x03,0x26,0x14,0x00,0xbf,0x8f, +0x10,0x00,0xb0,0x8f,0x05,0x00,0x04,0x24,0x8b,0x0b,0x62,0xa0,0x93,0x12,0x00,0x08, +0x18,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0x57,0x43,0x44,0x90,0x06,0x00,0x03,0x24, +0x25,0x00,0x83,0x10,0x0b,0x00,0x02,0x24,0x10,0x00,0x82,0x10,0x00,0x80,0x02,0x3c, +0x02,0x80,0x02,0x3c,0x6a,0x43,0x43,0x90,0x00,0x00,0x00,0x00,0x2c,0x00,0x60,0x10, +0x00,0xe0,0x02,0x3c,0x04,0xe0,0x02,0x3c,0x78,0x1b,0x04,0x26,0x00,0x8e,0x42,0x34, +0x00,0x15,0x03,0x3c,0x74,0x0b,0x82,0xac,0x00,0x15,0x63,0x34,0x00,0x42,0x02,0x24, +0x6c,0x0b,0x83,0xac,0x0f,0x5e,0x00,0x08,0x70,0x0b,0x82,0xac,0x00,0xbc,0x42,0x34, +0x15,0x15,0x03,0x3c,0x74,0x0b,0xa2,0xad,0x07,0x07,0x63,0x34,0x03,0x03,0x02,0x3c, +0x0e,0x5e,0x00,0x08,0x6c,0x0b,0xa3,0xad,0x02,0x80,0x06,0x3c,0x00,0xb4,0xc6,0x24, +0xf5,0x13,0x00,0x0c,0x80,0x00,0x05,0x24,0x78,0x1b,0x03,0x26,0x01,0x00,0x02,0x24, +0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x05,0x00,0x04,0x24,0x8b,0x0b,0x62,0xa0, +0x93,0x12,0x00,0x08,0x18,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0x6a,0x43,0x43,0x90, +0x00,0x00,0x00,0x00,0x13,0x00,0x60,0x10,0x1c,0x1c,0x03,0x3c,0x04,0xc0,0x02,0x3c, +0x00,0xb8,0x42,0x34,0x74,0x0b,0xa2,0xad,0x00,0x15,0x03,0x3c,0x02,0x02,0x02,0x3c, +0x00,0x07,0x63,0x34,0x00,0x22,0x42,0x34,0x0e,0x5e,0x00,0x08,0x6c,0x0b,0xa3,0xad, +0x78,0x1b,0x04,0x26,0x00,0xb2,0x42,0x34,0x00,0x1c,0x03,0x3c,0x74,0x0b,0x82,0xac, +0x00,0x1c,0x63,0x34,0x00,0x04,0x02,0x24,0x6c,0x0b,0x83,0xac,0x0f,0x5e,0x00,0x08, +0x70,0x0b,0x82,0xac,0x00,0xc0,0x02,0x3c,0x00,0xb2,0x42,0x34,0x74,0x0b,0xa2,0xad, +0x07,0x07,0x63,0x34,0x00,0x04,0x02,0x24,0x0e,0x5e,0x00,0x08,0x6c,0x0b,0xa3,0xad, +0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x01,0x80,0x02,0x3c,0x25,0xb0,0x10,0x3c, +0x18,0x03,0x03,0x36,0xf8,0x79,0x42,0x24,0x00,0x00,0x62,0xac,0x14,0x00,0xbf,0xaf, +0xc0,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,0xff,0x5e,0x00,0x0c,0x00,0x00,0x00,0x00, +0x25,0x61,0x00,0x0c,0x00,0x00,0x00,0x00,0x29,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00, +0x3a,0x41,0x00,0x0c,0x00,0x00,0x00,0x00,0x66,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00, +0x44,0x00,0x03,0x36,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x34, +0x00,0x00,0x62,0xa4,0x31,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,0x55,0x5d,0x00,0x0c, +0x00,0x00,0x00,0x00,0xf1,0x60,0x00,0x0c,0x00,0x00,0x00,0x00,0xaf,0x60,0x00,0x0c, +0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c,0xac,0x37,0x84,0x24,0x0e,0x61,0x00,0x0c, +0x01,0x00,0x05,0x24,0x00,0x80,0x04,0x3c,0xcc,0x41,0x84,0x24,0x0e,0x61,0x00,0x0c, +0x02,0x00,0x05,0x24,0x01,0x80,0x04,0x3c,0xa4,0x20,0x84,0x24,0x0e,0x61,0x00,0x0c, +0x04,0x00,0x05,0x24,0x04,0x50,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c, +0x08,0x53,0x84,0x24,0x0e,0x61,0x00,0x0c,0x03,0x00,0x05,0x24,0x02,0x80,0x02,0x3c, +0x60,0x43,0x43,0x90,0x43,0x00,0x04,0x36,0x2a,0x00,0x60,0x10,0xd8,0x00,0x10,0x36, +0x07,0x00,0x02,0x24,0x2c,0x00,0x62,0x10,0x25,0xb0,0x04,0x3c,0x43,0x00,0x85,0x34, +0x10,0x02,0x86,0x34,0x03,0x00,0x02,0x24,0x10,0x00,0x03,0x24,0x00,0x00,0xa2,0xa0, +0xd8,0x00,0x84,0x34,0x00,0x00,0xc3,0xa0,0x00,0x00,0x82,0x90,0x80,0xff,0x03,0x24, +0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xa0,0x32,0x61,0x00,0x0c,0x00,0x00,0x00,0x00, +0x42,0xb0,0x03,0x3c,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x34, +0x00,0x00,0x62,0xa0,0x38,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c, +0x44,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24, +0xc0,0x00,0x42,0x34,0x00,0x00,0x62,0xa4,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00, +0x2d,0x28,0x00,0x0c,0x21,0x38,0x00,0x00,0x53,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00, +0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0x00,0x00,0x80,0xa0,0x00,0x00,0x03,0x92,0x80,0xff,0x02,0x24, +0x25,0x18,0x62,0x00,0x00,0x00,0x03,0xa2,0x32,0x61,0x00,0x0c,0x00,0x00,0x00,0x00, +0x42,0xb0,0x03,0x3c,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x34, +0x00,0x00,0x62,0xa0,0x38,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c, +0x44,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24, +0xc0,0x00,0x42,0x34,0x00,0x00,0x62,0xa4,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00, +0x2d,0x28,0x00,0x0c,0x21,0x38,0x00,0x00,0x53,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00, +0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03, +0x18,0x00,0xbd,0x27,0xb0,0xff,0xbd,0x27,0x02,0x80,0x03,0x3c,0x4c,0x00,0xbf,0xaf, +0x48,0x00,0xbe,0xaf,0x3c,0x00,0xb5,0xaf,0x38,0x00,0xb4,0xaf,0x34,0x00,0xb3,0xaf, +0x30,0x00,0xb2,0xaf,0x2c,0x00,0xb1,0xaf,0x28,0x00,0xb0,0xaf,0x44,0x00,0xb7,0xaf, +0x40,0x00,0xb6,0xaf,0x78,0x1b,0x62,0x24,0xe2,0x0a,0x43,0x90,0xe4,0x0a,0x45,0x94, +0xe6,0x0a,0x46,0x94,0x1c,0x00,0xa3,0xa3,0x6c,0x0b,0x43,0x8c,0x24,0xb0,0x04,0x3c, +0x21,0xb0,0x07,0x3c,0x10,0x00,0xa3,0xaf,0x70,0x0b,0x43,0x8c,0x25,0xb0,0x1e,0x3c, +0x01,0x00,0x88,0x34,0x14,0x00,0xa3,0xaf,0x74,0x0b,0x42,0x8c,0x21,0x38,0xa7,0x00, +0xff,0x1f,0x03,0x3c,0x18,0x00,0xa2,0xaf,0x20,0xb0,0x02,0x3c,0xff,0xff,0x42,0x34, +0x21,0x28,0xa2,0x00,0x4c,0x81,0x02,0x3c,0xff,0xff,0x63,0x34,0x21,0x40,0xc8,0x00, +0x58,0x00,0xc9,0x37,0x21,0x30,0xc4,0x00,0x00,0xe0,0x42,0x34,0x00,0x00,0x22,0xad, +0xff,0xff,0x04,0x24,0x24,0x40,0x03,0x01,0x24,0x28,0xa3,0x00,0x24,0x38,0xe3,0x00, +0x24,0x30,0xc3,0x00,0x5c,0x00,0xca,0x37,0x60,0x00,0xcb,0x37,0x64,0x00,0xcc,0x37, +0x8a,0x00,0xcd,0x37,0x96,0x01,0x03,0x24,0x28,0x28,0x02,0x24,0x00,0x00,0x43,0xad, +0x89,0x00,0xce,0x37,0x00,0x00,0x64,0xad,0x8c,0x00,0xcf,0x37,0x00,0x00,0x84,0xad, +0x09,0x00,0x03,0x24,0x00,0x00,0xa2,0xa5,0x0a,0x0a,0x02,0x24,0x00,0x00,0xc3,0xa1, +0x00,0x00,0xe2,0xa5,0x25,0xb0,0x02,0x3c,0x0e,0x0e,0x03,0x24,0x8e,0x00,0x42,0x34, +0x00,0x00,0x43,0xa4,0x90,0x00,0xd1,0x37,0x13,0x00,0x02,0x24,0x00,0x00,0x22,0xa2, +0x40,0x00,0x03,0x24,0x3a,0x01,0x02,0x24,0x91,0x00,0xd2,0x37,0x92,0x00,0xd3,0x37, +0x00,0x00,0x43,0xa2,0x00,0x00,0x62,0xa6,0x25,0xb0,0x02,0x3c,0x21,0x00,0x03,0x24, +0xb5,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x10,0x00,0xa3,0x8f,0xa0,0x00,0xd5,0x37, +0x25,0xb0,0x02,0x3c,0x00,0x00,0xa3,0xae,0x14,0x00,0xa3,0x8f,0xa4,0x00,0x42,0x34, +0xb0,0x00,0xdf,0x37,0x00,0x00,0x43,0xac,0x18,0x00,0xa3,0x8f,0x25,0xb0,0x02,0x3c, +0xa8,0x00,0x42,0x34,0x00,0x00,0x43,0xac,0x25,0xb0,0x02,0x3c,0x25,0xb0,0x03,0x3c, +0xac,0x00,0x42,0x34,0xf8,0x00,0x63,0x34,0x00,0x00,0x45,0xac,0x00,0x00,0x67,0xac, +0x25,0xb0,0x02,0x3c,0x25,0xb0,0x03,0x3c,0x08,0x01,0x42,0x34,0xd8,0x00,0x63,0x34, +0x00,0x00,0xe6,0xaf,0x00,0x00,0x48,0xac,0x00,0x00,0x60,0xa0,0x1c,0x00,0xa3,0x93, +0x25,0xb0,0x02,0x3c,0xb4,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c, +0x04,0x00,0x03,0x24,0xb6,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x25,0xb0,0x02,0x3c, +0xb9,0x00,0x42,0x34,0x25,0xb0,0x03,0x3c,0x00,0x00,0x44,0xa0,0xba,0x00,0x63,0x34, +0x0f,0x00,0x02,0x24,0x00,0x00,0x62,0xa4,0x25,0xb0,0x02,0x3c,0x1a,0x01,0x42,0x34, +0x16,0x01,0xd4,0x37,0x18,0x01,0xd0,0x37,0x25,0xb0,0x03,0x3c,0x00,0x00,0x80,0xa6, +0xdc,0x00,0x63,0x34,0x00,0x00,0x00,0xa6,0x00,0x00,0x40,0xa4,0xff,0xcf,0x02,0x24, +0x00,0x00,0x62,0xac,0x02,0x80,0x02,0x3c,0x56,0x43,0x42,0x90,0xd0,0x01,0xc4,0x37, +0x5e,0x00,0x03,0x3c,0x20,0x00,0xa2,0xaf,0x2f,0x00,0x02,0x3c,0x32,0x32,0x42,0x34, +0x00,0x00,0x82,0xac,0x08,0x00,0x02,0x3c,0x32,0x43,0x63,0x34,0x30,0xa5,0x42,0x34, +0xd4,0x01,0xc5,0x37,0xd8,0x01,0xc6,0x37,0x00,0x00,0xa3,0xac,0xdc,0x01,0xc7,0x37, +0x00,0x00,0xc2,0xac,0x49,0xa5,0x03,0x34,0x1a,0x06,0x02,0x24,0xe0,0x01,0xc8,0x37, +0x00,0x00,0xe3,0xac,0xf4,0x01,0xc9,0x37,0x00,0x00,0x02,0xa5,0x07,0x07,0x03,0x24, +0xc2,0x00,0x02,0x3c,0x00,0x00,0x23,0xa5,0x51,0x10,0x42,0x34,0x26,0x00,0x03,0x24, +0xf8,0x01,0xca,0x37,0x00,0x02,0xcb,0x37,0x00,0x00,0x42,0xad,0x03,0x02,0xcc,0x37, +0x00,0x00,0x63,0xa5,0x0c,0x00,0x02,0x24,0x04,0x00,0x03,0x24,0x36,0x02,0xcd,0x37, +0x00,0x00,0x83,0xa1,0x34,0x02,0xce,0x37,0x00,0x00,0xa2,0xa1,0xc0,0x01,0x03,0x24, +0x03,0x00,0x02,0x24,0x37,0x02,0xcf,0x37,0x00,0x00,0xc3,0xa5,0x00,0x00,0xe2,0xa1, +0x20,0x00,0xa2,0x8f,0x22,0x00,0x03,0x24,0xd2,0x00,0x43,0x10,0x1b,0x1b,0x02,0x3c, +0x13,0x13,0x02,0x3c,0x13,0x13,0x42,0x34,0x60,0x01,0xc3,0x37,0x64,0x01,0xc4,0x37, +0x68,0x01,0xc5,0x37,0x7c,0x01,0xca,0x37,0x6c,0x01,0xc6,0x37,0x70,0x01,0xc7,0x37, +0x74,0x01,0xc8,0x37,0x78,0x01,0xc9,0x37,0x00,0x00,0x62,0xac,0x00,0x00,0x82,0xac, +0x02,0x80,0x03,0x3c,0x00,0x00,0xa2,0xac,0x00,0x00,0xc2,0xac,0x00,0x00,0xe2,0xac, +0x00,0x00,0x02,0xad,0x00,0x00,0x22,0xad,0x00,0x00,0x42,0xad,0x56,0x43,0x65,0x90, +0x25,0xb0,0x0c,0x3c,0x01,0x70,0x03,0x3c,0x80,0x01,0x82,0x35,0x08,0x5f,0x63,0x34, +0x22,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0xb1,0x00,0xa4,0x10,0x0f,0x1f,0x02,0x3c, +0x92,0x00,0x02,0x24,0xae,0x00,0xa2,0x10,0x0f,0x1f,0x02,0x3c,0x0f,0x10,0x02,0x3c, +0x00,0xf0,0x4f,0x34,0xf7,0x01,0x91,0x35,0x15,0xf0,0x4d,0x34,0x77,0x00,0x0e,0x24, +0x84,0x01,0x87,0x35,0x88,0x01,0x88,0x35,0x10,0xf0,0x44,0x34,0x8c,0x01,0x85,0x35, +0x05,0xf0,0x42,0x34,0x00,0x00,0xed,0xac,0x90,0x01,0x83,0x35,0x00,0x00,0x04,0xad, +0x94,0x01,0x86,0x35,0x00,0x00,0xa2,0xac,0xf5,0x0f,0x02,0x24,0x00,0x00,0x6f,0xac, +0x25,0xb0,0x05,0x3c,0x00,0x00,0xc2,0xac,0x98,0x01,0x89,0x35,0x9c,0x01,0x8a,0x35, +0xf0,0x0f,0x03,0x24,0x0d,0x00,0x02,0x24,0x00,0x00,0x23,0xad,0xa0,0x01,0x8b,0x35, +0x00,0x00,0x42,0xad,0xa7,0x01,0xb7,0x34,0xf6,0x01,0x8c,0x35,0xff,0xff,0x02,0x24, +0x00,0x00,0x6d,0xad,0x03,0x04,0x04,0x3c,0x00,0x00,0x8e,0xa1,0x07,0x08,0x03,0x3c, +0x00,0x00,0x2e,0xa2,0x00,0x00,0xe2,0xa2,0x25,0xb0,0x02,0x3c,0x01,0x02,0x84,0x34, +0x05,0x06,0x63,0x34,0xa8,0x01,0xb6,0x34,0xff,0xff,0x09,0x24,0xac,0x01,0xaf,0x34, +0xb4,0x01,0xb1,0x34,0xb8,0x01,0xb2,0x34,0xbc,0x01,0xb3,0x34,0xb0,0x01,0x42,0x34, +0x00,0x00,0xc9,0xae,0x00,0x00,0xe9,0xad,0x00,0x00,0x44,0xac,0x00,0x00,0x23,0xae, +0x00,0x00,0x44,0xae,0x00,0x00,0x63,0xae,0x25,0xb0,0x03,0x3c,0x0c,0x00,0x06,0x24, +0xc0,0x01,0x63,0x34,0x25,0xb0,0x02,0x3c,0x00,0x00,0x66,0xa0,0xc1,0x01,0xb5,0x34, +0xc2,0x01,0x42,0x34,0x25,0xb0,0x03,0x3c,0x00,0x00,0xa6,0xa2,0x0d,0x00,0x08,0x24, +0x00,0x00,0x46,0xa0,0xc4,0x01,0xab,0x34,0xc5,0x01,0xac,0x34,0x0e,0x00,0x07,0x24, +0xc6,0x01,0xaa,0x34,0xc7,0x01,0xad,0x34,0xc3,0x01,0x63,0x34,0x0f,0x00,0x02,0x24, +0x00,0x00,0x68,0xa0,0x00,0x00,0x68,0xa1,0x00,0x00,0x87,0xa1,0x00,0x00,0x47,0xa1, +0x00,0x00,0xa2,0xa1,0x57,0x01,0x02,0x3c,0x48,0x00,0xbf,0x34,0x46,0x00,0xae,0x34, +0x0e,0xe2,0x42,0x34,0x00,0x00,0xc0,0xa5,0x4c,0x00,0xbe,0x34,0x00,0x00,0xe2,0xaf, +0x4d,0x00,0xb9,0x34,0x80,0xff,0x02,0x24,0x00,0x00,0xc0,0xa3,0x00,0x00,0x22,0xa3, +0x25,0xb0,0x02,0x3c,0xbc,0x00,0x03,0x24,0x40,0x00,0x42,0x34,0x00,0x00,0x43,0xa4, +0x25,0xb0,0x03,0x3c,0x64,0x03,0xb8,0x34,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34, +0x00,0x00,0x00,0xa3,0x00,0x00,0x62,0xa4,0x02,0x80,0x02,0x3c,0xd8,0x00,0xaa,0x34, +0x78,0x1b,0x43,0x24,0xe2,0x0a,0x64,0x90,0x00,0x00,0x47,0x91,0x2a,0xb0,0x06,0x3c, +0xa0,0xff,0x02,0x24,0x25,0x38,0xe2,0x00,0x34,0x00,0xc9,0x34,0x01,0x00,0x83,0x24, +0x00,0x00,0x47,0xa1,0x26,0xb0,0x08,0x3c,0x00,0x00,0x23,0xa1,0x30,0x00,0xce,0x34, +0x20,0x20,0x02,0x24,0x38,0x00,0xc6,0x34,0x40,0x00,0x03,0x24,0x00,0x00,0xc2,0xa4, +0x79,0x00,0x0b,0x35,0x00,0x00,0xc3,0xa1,0x94,0x00,0xac,0x34,0x16,0x00,0x02,0x24, +0x64,0x00,0x03,0x24,0x00,0x00,0x62,0xa1,0x7c,0x00,0x15,0x35,0x00,0x00,0x83,0xa5, +0x98,0x00,0xad,0x34,0x7a,0x00,0x08,0x35,0x22,0x00,0x02,0x24,0x04,0x00,0x03,0x24, +0x00,0x00,0xa2,0xa5,0x9c,0x00,0xaf,0x34,0x00,0x00,0x03,0xa1,0x20,0x0c,0x02,0x24, +0x0a,0x00,0x03,0x24,0x00,0x00,0xa2,0xa6,0x00,0x00,0xe3,0xa1,0x25,0xb0,0x03,0x3c, +0xff,0x03,0x02,0x24,0x9a,0x00,0x63,0x34,0x00,0x00,0x62,0xa4,0x96,0x00,0xb1,0x34, +0x02,0x00,0x03,0x24,0x00,0x00,0x23,0xa6,0xb7,0x00,0xb2,0x34,0x89,0x00,0xb3,0x34, +0x20,0x00,0x02,0x24,0x09,0x00,0x03,0x24,0x00,0x00,0x42,0xa2,0x44,0x00,0xa5,0x34, +0x00,0x00,0x63,0xa2,0x00,0x00,0xa2,0x94,0xff,0xfd,0x03,0x24,0x04,0x02,0x06,0x24, +0x24,0x10,0x43,0x00,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa3,0x94,0x29,0xb0,0x02,0x3c, +0x40,0x00,0x42,0x34,0x00,0x02,0x63,0x34,0x00,0x00,0xa3,0xa4,0xff,0x00,0x84,0x30, +0x00,0x00,0x46,0xa4,0xea,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x4c,0x00,0xbf,0x8f, +0x48,0x00,0xbe,0x8f,0x44,0x00,0xb7,0x8f,0x40,0x00,0xb6,0x8f,0x3c,0x00,0xb5,0x8f, +0x38,0x00,0xb4,0x8f,0x34,0x00,0xb3,0x8f,0x30,0x00,0xb2,0x8f,0x2c,0x00,0xb1,0x8f, +0x28,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x50,0x00,0xbd,0x27, +0x00,0xf0,0x4f,0x34,0xf7,0x01,0x91,0x35,0x15,0xf0,0x4d,0x34,0xd2,0x5f,0x00,0x08, +0xff,0xff,0x0e,0x24,0xb0,0x5f,0x00,0x08,0x1b,0x1b,0x42,0x34,0x25,0xb0,0x03,0x3c, +0x25,0xb0,0x08,0x3c,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,0x02,0x80,0x04,0x3c, +0x00,0x00,0x62,0xa4,0x34,0x9b,0x84,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35, +0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00, +0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24, +0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c, +0x02,0x80,0x02,0x3c,0x2c,0x95,0x44,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35, +0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00, +0x0a,0x00,0x47,0x10,0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00, +0x00,0x00,0x62,0xac,0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24, +0x00,0x00,0xc2,0xac,0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x02,0x80,0x05,0x3c,0xb0,0x83,0x42,0x24, +0x02,0x80,0x03,0x3c,0xa4,0x43,0xa2,0xac,0x00,0x80,0x02,0x3c,0x44,0x44,0x60,0xac, +0xa4,0x43,0xa4,0x24,0x02,0x80,0x03,0x3c,0x8c,0x0a,0x42,0x24,0x48,0x44,0x60,0xa4, +0x08,0x00,0x82,0xac,0x02,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0x4a,0x44,0x60,0xa4, +0x02,0x80,0x06,0x3c,0x24,0x10,0x42,0x24,0x00,0x80,0x03,0x3c,0x4c,0x44,0xc7,0x24, +0x14,0x00,0x82,0xac,0x68,0x0c,0x63,0x24,0x02,0x80,0x02,0x3c,0x4c,0x44,0xc0,0xac, +0x10,0x00,0x83,0xac,0x04,0x00,0xe0,0xac,0x02,0x80,0x03,0x3c,0x54,0x44,0x40,0xa0, +0x02,0x80,0x02,0x3c,0x58,0x44,0x60,0xac,0x5c,0x44,0x40,0xac,0x01,0x80,0x02,0x3c, +0x00,0x80,0x03,0x3c,0xd8,0x87,0x42,0x24,0x40,0x10,0x63,0x24,0x7c,0x00,0x82,0xac, +0x1c,0x00,0x83,0xac,0x00,0x80,0x02,0x3c,0x00,0x80,0x03,0x3c,0xd8,0x13,0x42,0x24, +0xd0,0x17,0x63,0x24,0x20,0x00,0x82,0xac,0x24,0x00,0x83,0xac,0x00,0x80,0x02,0x3c, +0x00,0x80,0x03,0x3c,0xc4,0x1b,0x42,0x24,0xf8,0x29,0x63,0x24,0x28,0x00,0x82,0xac, +0x2c,0x00,0x83,0xac,0x00,0x80,0x02,0x3c,0x00,0x80,0x03,0x3c,0x14,0x20,0x42,0x24, +0x00,0x22,0x63,0x24,0x30,0x00,0x82,0xac,0x3c,0x00,0x83,0xac,0x00,0x80,0x02,0x3c, +0x00,0x80,0x03,0x3c,0x68,0x04,0x42,0x24,0xb8,0x1f,0x63,0x24,0x50,0x00,0x82,0xac, +0x08,0x00,0xe0,0x03,0x40,0x00,0x83,0xac,0x25,0xb0,0x02,0x3c,0x08,0x00,0x42,0x34, +0x00,0x00,0x43,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x0e,0x3c, +0x02,0x80,0x08,0x3c,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0xf8,0x03,0x4d,0x24, +0x00,0x18,0x6c,0x24,0x01,0x00,0x07,0x24,0x00,0x00,0xcb,0x25,0xff,0xff,0x0a,0x24, +0x00,0x04,0x09,0x25,0x80,0x1a,0x07,0x00,0x21,0x10,0x6b,0x00,0x00,0x00,0x42,0xac, +0x90,0x00,0x4a,0xac,0x00,0x04,0x04,0x8d,0x01,0x00,0xe7,0x24,0x08,0x00,0x45,0x24, +0x21,0x18,0x6d,0x00,0x06,0x00,0xe6,0x28,0x04,0x00,0x82,0xac,0x00,0x00,0x44,0xac, +0x04,0x00,0x49,0xac,0x00,0x04,0x02,0xad,0x8c,0x00,0x40,0xac,0x6c,0x00,0xa3,0xac, +0xf0,0xff,0xc0,0x14,0x68,0x00,0xac,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0xc9,0xad, +0x06,0x00,0xa2,0x2c,0x13,0x00,0x40,0x10,0xff,0xff,0x07,0x24,0x02,0x80,0x02,0x3c, +0x80,0x1a,0x05,0x00,0x00,0x00,0x42,0x24,0x0e,0x00,0xa0,0x10,0x21,0x30,0x62,0x00, +0x90,0x00,0xc3,0x8c,0xff,0xff,0x02,0x24,0x0a,0x00,0x62,0x14,0x00,0x00,0x00,0x00, +0x8c,0x00,0xc2,0x8c,0x00,0x00,0x00,0x00,0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00, +0x01,0x00,0x02,0x24,0x88,0x00,0xc4,0xac,0x8c,0x00,0xc2,0xac,0x90,0x00,0xc5,0xac, +0x21,0x38,0xa0,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,0x02,0x80,0x03,0x3c, +0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,0x94,0x84,0x63,0x24,0xe8,0xff,0xbd,0x27, +0x00,0x00,0x43,0xac,0x10,0x00,0xbf,0xaf,0x95,0x42,0x00,0x0c,0x21,0x20,0x00,0x00, +0x10,0x00,0xbf,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x03,0x80,0x05,0x3c,0x00,0x80,0xa5,0x24, +0x40,0x10,0x0c,0x3c,0xff,0xff,0xa5,0x30,0x02,0x80,0x04,0x3c,0x78,0x1b,0x84,0x24, +0x25,0xc8,0xac,0x00,0x00,0x25,0x99,0xac,0x80,0x00,0x39,0x27,0xe0,0xff,0xbd,0x27, +0x0c,0x25,0x99,0xac,0x80,0x00,0x39,0x27,0x1c,0x00,0xb7,0xaf,0x18,0x00,0xb6,0xaf, +0x14,0x00,0xb5,0xaf,0x10,0x00,0xb4,0xaf,0x0c,0x00,0xb3,0xaf,0x08,0x00,0xb2,0xaf, +0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,0x18,0x25,0x99,0xac,0x80,0x00,0x39,0x27, +0x24,0x25,0x99,0xac,0xe2,0x0a,0x86,0x90,0x80,0x00,0x39,0x27,0x30,0x25,0x99,0xac, +0x80,0x00,0x39,0x27,0x3c,0x25,0x99,0xac,0x20,0xb0,0x02,0x3c,0x0c,0x25,0x87,0x8c, +0x18,0x25,0x88,0x8c,0x24,0x25,0x89,0x8c,0x30,0x25,0x8a,0x8c,0x3c,0x25,0x8b,0x8c, +0x00,0x01,0x42,0x34,0x00,0x32,0x06,0x00,0xff,0x1f,0x03,0x3c,0x80,0x00,0x39,0x27, +0x21,0x30,0xc2,0x00,0xff,0xff,0x63,0x34,0x24,0x30,0xc3,0x00,0x48,0x25,0x99,0xac, +0x20,0x10,0x03,0x3c,0x21,0x68,0x20,0x03,0x25,0x28,0xac,0x00,0x25,0xb0,0x0e,0x3c, +0x80,0x00,0x39,0x27,0xfc,0x24,0x85,0xac,0x08,0x25,0x87,0xac,0x14,0x25,0x88,0xac, +0x20,0x25,0x89,0xac,0x2c,0x25,0x8a,0xac,0xcc,0x24,0x86,0xac,0x38,0x25,0x8b,0xac, +0xac,0x00,0xc2,0x35,0x94,0x24,0x83,0xac,0x90,0x24,0x83,0xac,0xa0,0x24,0x83,0xac, +0x9c,0x24,0x83,0xac,0xac,0x24,0x83,0xac,0xa8,0x24,0x83,0xac,0x54,0x25,0x99,0xac, +0xd0,0x24,0x86,0xac,0x44,0x25,0x8d,0xac,0xb8,0x24,0x83,0xac,0xb4,0x24,0x83,0xac, +0xc4,0x24,0x83,0xac,0xc0,0x24,0x83,0xac,0xdc,0x24,0x83,0xac,0xd8,0x24,0x83,0xac, +0x00,0x02,0x39,0x27,0x00,0x00,0x48,0x8c,0xe4,0x0a,0x87,0x94,0x6c,0x25,0x99,0xac, +0xb0,0x00,0xc2,0x35,0x00,0x00,0x56,0x8c,0x21,0x10,0x06,0x3c,0x54,0x25,0x92,0x8c, +0x23,0x10,0x0b,0x3c,0x22,0x10,0x0f,0x3c,0x02,0x80,0x14,0x3c,0x02,0x80,0x15,0x3c, +0x02,0x80,0x17,0x3c,0x02,0x80,0x18,0x3c,0x00,0x80,0xc5,0x34,0x21,0x98,0x20,0x03, +0x23,0x28,0xa7,0x00,0x00,0x02,0x39,0x27,0x24,0x10,0x07,0x3c,0x80,0x41,0x89,0x26, +0x88,0x41,0xaa,0x26,0x90,0x41,0xec,0x26,0x98,0x41,0x0d,0x27,0x00,0x04,0x70,0x35, +0x01,0x00,0x08,0x25,0x00,0x40,0xf1,0x35,0x00,0x01,0xce,0x35,0x01,0x00,0x02,0x24, +0x50,0x25,0x92,0xac,0x59,0x25,0x82,0xa0,0x68,0x25,0x93,0xac,0xc4,0x25,0x90,0xac, +0x88,0x25,0x88,0xac,0x94,0x25,0x85,0xac,0xb8,0x25,0x91,0xac,0xac,0x25,0x96,0xac, +0x00,0x00,0xc7,0xad,0xa8,0x25,0x87,0xac,0xc8,0x25,0x83,0xac,0xe8,0x24,0x83,0xac, +0xe4,0x24,0x83,0xac,0x72,0x25,0x80,0xa4,0x71,0x25,0x80,0xa0,0x70,0x25,0x80,0xa0, +0xbc,0x25,0x8b,0xac,0xc0,0x25,0x8b,0xac,0x80,0x25,0x86,0xac,0x84,0x25,0x86,0xac, +0x8c,0x25,0x86,0xac,0x90,0x25,0x86,0xac,0xb0,0x25,0x8f,0xac,0xb4,0x25,0x8f,0xac, +0xa4,0x25,0x87,0xac,0xcc,0x25,0x83,0xac,0xd8,0x25,0x99,0xac,0xd4,0x25,0x99,0xac, +0x04,0x00,0x4a,0xad,0x80,0x41,0x89,0xae,0x04,0x00,0x8c,0xad,0x88,0x41,0xaa,0xae, +0x04,0x00,0xad,0xad,0x90,0x41,0xec,0xae,0x98,0x41,0x0d,0xaf,0x04,0x00,0x29,0xad, +0x02,0x80,0x02,0x3c,0x00,0x18,0x43,0x24,0x21,0x20,0x20,0x01,0x03,0x00,0x06,0x24, +0x21,0x10,0x80,0x00,0xff,0xff,0xc6,0x24,0x08,0x00,0x79,0xac,0x00,0x00,0x63,0xac, +0x10,0x00,0x60,0xac,0x00,0x00,0x69,0xac,0x21,0x20,0x60,0x00,0x04,0x00,0x62,0xac, +0x00,0x00,0x43,0xac,0x00,0x01,0x39,0x27,0xf5,0xff,0xc1,0x04,0x18,0x00,0x63,0x24, +0x02,0x80,0x02,0x3c,0x88,0x41,0x48,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c, +0x04,0x00,0x07,0x8d,0x60,0x18,0x4b,0x24,0x04,0x00,0x24,0xad,0x00,0x18,0x6a,0x24, +0x01,0x00,0x09,0x24,0x21,0x28,0x00,0x00,0x0f,0x00,0x06,0x24,0x21,0x20,0xab,0x00, +0x21,0x10,0xaa,0x00,0xff,0xff,0xc6,0x24,0x68,0x00,0x59,0xac,0x70,0x00,0x49,0xac, +0x18,0x00,0xa5,0x24,0x00,0x00,0x88,0xac,0x04,0x00,0x87,0xac,0x00,0x00,0xe4,0xac, +0x00,0x01,0x39,0x27,0xf5,0xff,0xc1,0x04,0x21,0x38,0x80,0x00,0x02,0x80,0x02,0x3c, +0x90,0x41,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x04,0x00,0x25,0x8d, +0xe0,0x19,0x4b,0x24,0x04,0x00,0x04,0xad,0x00,0x18,0x6a,0x24,0x02,0x00,0x07,0x24, +0x21,0x20,0x00,0x00,0x0f,0x00,0x06,0x24,0x21,0x40,0x8b,0x00,0x21,0x10,0x8a,0x00, +0xff,0xff,0xc6,0x24,0xe8,0x01,0x59,0xac,0xf0,0x01,0x47,0xac,0x18,0x00,0x84,0x24, +0x00,0x00,0x09,0xad,0x04,0x00,0x05,0xad,0x00,0x00,0xa8,0xac,0x00,0x02,0x39,0x27, +0xf5,0xff,0xc1,0x04,0x21,0x28,0x00,0x01,0x02,0x80,0x05,0x3c,0x98,0x41,0xa5,0x24, +0x04,0x00,0xa6,0x8c,0x1c,0x00,0xb7,0x8f,0x18,0x00,0xb6,0x8f,0x14,0x00,0xb5,0x8f, +0x10,0x00,0xb4,0x8f,0x0c,0x00,0xb3,0x8f,0x08,0x00,0xb2,0x8f,0x04,0x00,0xb1,0x8f, +0x00,0x00,0xb0,0x8f,0x02,0x80,0x07,0x3c,0x02,0x80,0x03,0x3c,0x60,0x1b,0xe4,0x24, +0x00,0x18,0x63,0x24,0x03,0x00,0x02,0x24,0x20,0x00,0xbd,0x27,0x68,0x03,0x79,0xac, +0x04,0x00,0x28,0xad,0x04,0x00,0xa4,0xac,0x70,0x03,0x62,0xac,0x60,0x1b,0xe5,0xac, +0x04,0x00,0x86,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0xc4,0xac,0xc8,0xff,0xbd,0x27, +0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf, +0xfc,0xad,0x73,0x24,0x70,0xae,0x52,0x24,0x02,0x80,0x03,0x3c,0xff,0xff,0x02,0x3c, +0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf, +0x30,0x00,0xbf,0xaf,0xff,0x1f,0x54,0x34,0x78,0x1b,0x70,0x24,0x21,0x88,0x00,0x00, +0x02,0x80,0x15,0x3c,0x19,0x50,0x00,0x0c,0x21,0x20,0x20,0x02,0x90,0x11,0x05,0x8e, +0x6c,0x00,0x66,0x8e,0x6c,0x00,0x43,0x8e,0xdc,0xad,0xa2,0x26,0x1b,0x00,0x44,0x90, +0x21,0x18,0x66,0x00,0x24,0x28,0xb4,0x00,0x00,0x21,0x04,0x00,0x42,0x18,0x03,0x00, +0x00,0x20,0xa5,0x34,0x5c,0x11,0x03,0xae,0x80,0x11,0x04,0xae,0x90,0x11,0x05,0xae, +0x84,0x11,0x04,0xae,0x21,0x30,0x00,0x00,0x21,0x10,0x06,0x02,0x01,0x00,0xc6,0x24, +0x1d,0x00,0xc3,0x28,0xb1,0x11,0x40,0xa0,0x94,0x11,0x40,0xa0,0xfa,0xff,0x60,0x14, +0xce,0x11,0x40,0xa0,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xec,0x11,0x00,0xae, +0xe4,0xff,0x40,0x14,0x94,0x00,0x10,0x26,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c, +0x78,0x1b,0x4b,0x24,0x02,0x80,0x02,0x3c,0x70,0xae,0x6f,0x24,0xfc,0xad,0x4d,0x24, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xdc,0xad,0x6e,0x24,0xbc,0xad,0x4c,0x24, +0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x20,0x6d,0x00,0x21,0x10,0x6f,0x00, +0x21,0x28,0x2e,0x02,0x21,0x30,0x2c,0x02,0x00,0x00,0x88,0x8c,0x00,0x00,0xa9,0x90, +0x00,0x00,0xc7,0x90,0x00,0x00,0x4a,0x8c,0x21,0x10,0x2b,0x02,0x01,0x00,0x31,0x26, +0x21,0x18,0x6b,0x00,0x1d,0x00,0x24,0x2a,0xf8,0x04,0x68,0xac,0xce,0x04,0x47,0xa0, +0x6c,0x05,0x6a,0xac,0xef,0xff,0x80,0x14,0x94,0x04,0x49,0xa0,0x02,0x80,0x02,0x3c, +0x78,0x1b,0x4a,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x98,0xac,0x6b,0x24, +0x38,0xab,0x4c,0x24,0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00, +0x21,0x40,0x2a,0x01,0x21,0x38,0x2b,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90, +0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28, +0xc9,0x03,0x64,0xa0,0xf8,0xff,0x40,0x14,0x38,0x03,0x65,0xa0,0x21,0x10,0x2c,0x02, +0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26, +0x1d,0x00,0x22,0x2a,0x77,0x04,0x64,0xa0,0x5a,0x04,0x65,0xa0,0xeb,0xff,0x40,0x14, +0x05,0x00,0x29,0x25,0x30,0x00,0xbf,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f, +0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f, +0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x29,0xb0,0x02,0x3c,0xf8,0xff,0xbd,0x27, +0x00,0x00,0x40,0xac,0x08,0x00,0x44,0x34,0x0c,0x00,0x45,0x34,0x10,0x00,0x46,0x34, +0x04,0x00,0x43,0x34,0x14,0x00,0x47,0x34,0x18,0x00,0x48,0x34,0x1c,0x00,0x49,0x34, +0x20,0x00,0x4a,0x34,0x24,0x00,0x4b,0x34,0x28,0x00,0x4c,0x34,0x2c,0x00,0x4d,0x34, +0x30,0x00,0x4e,0x34,0x34,0x00,0x4f,0x34,0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf, +0x3c,0x00,0x51,0x34,0x38,0x00,0x50,0x34,0x02,0x80,0x02,0x3c,0x00,0x00,0x60,0xac, +0x00,0x00,0x80,0xac,0x00,0x00,0xa0,0xac,0x21,0x20,0x00,0x00,0x00,0x00,0xc0,0xac, +0xff,0xff,0x05,0x24,0x00,0x00,0xe0,0xac,0x78,0x1b,0x46,0x24,0x00,0x00,0x00,0xad, +0x00,0x00,0x20,0xad,0x00,0x00,0x40,0xad,0x00,0x00,0x60,0xad,0x00,0x00,0x80,0xad, +0x00,0x00,0xa0,0xad,0x00,0x00,0xc0,0xad,0x00,0x00,0xe0,0xad,0x00,0x00,0x00,0xae, +0x00,0x00,0x20,0xae,0x21,0x18,0x86,0x00,0x01,0x00,0x84,0x24,0x08,0x00,0x82,0x28, +0xfc,0xff,0x40,0x14,0xf0,0x04,0x65,0xa0,0x02,0x80,0x02,0x3c,0x78,0x1b,0x43,0x24, +0x1f,0x00,0x04,0x24,0x90,0x11,0x62,0x8c,0xff,0xff,0x84,0x24,0xf0,0x00,0x42,0x34, +0x90,0x11,0x62,0xac,0xfb,0xff,0x81,0x04,0x94,0x00,0x63,0x24,0x04,0x00,0xb1,0x8f, +0x00,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x08,0x00,0xbd,0x27,0x48,0xfd,0xbd,0x27, +0xb4,0x02,0xb3,0xaf,0x02,0x80,0x02,0x3c,0x02,0x80,0x13,0x3c,0x30,0xb0,0x46,0x24, +0x78,0x1b,0x63,0x26,0xb0,0x02,0xb2,0xaf,0xac,0x02,0xb1,0xaf,0xa8,0x02,0xb0,0xaf, +0x03,0x00,0x60,0xa0,0x21,0x38,0xa0,0x03,0x90,0x00,0xc8,0x24,0x00,0x00,0xc2,0x8c, +0x04,0x00,0xc3,0x8c,0x08,0x00,0xc4,0x8c,0x0c,0x00,0xc5,0x8c,0x10,0x00,0xc6,0x24, +0x00,0x00,0xe2,0xac,0x04,0x00,0xe3,0xac,0x08,0x00,0xe4,0xac,0x0c,0x00,0xe5,0xac, +0xf6,0xff,0xc8,0x14,0x10,0x00,0xe7,0x24,0x00,0x00,0xc3,0x8c,0x02,0x80,0x02,0x3c, +0xc4,0xb0,0x58,0x24,0x00,0x00,0xe3,0xac,0x98,0x00,0xb9,0x27,0x00,0x01,0x12,0x27, +0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x09,0x00,0x04,0x93,0x0d,0x00,0x05,0x93, +0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,0x04,0x00,0x10,0x93,0x06,0x00,0x0c,0x93, +0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,0x0c,0x00,0x0e,0x93,0x0e,0x00,0x06,0x93, +0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,0x0b,0x00,0x0a,0x93,0x0f,0x00,0x0b,0x93, +0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x00,0x22,0x04,0x00,0x00,0x2a,0x05,0x00, +0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,0x25,0x20,0x8f,0x00,0x25,0x28,0xae,0x00, +0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,0x00,0x3c,0x07,0x00,0x00,0x34,0x06,0x00, +0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00, +0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,0x00,0x56,0x0a,0x00,0x00,0x5e,0x0b,0x00, +0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,0x25,0x50,0x47,0x01,0x25,0x58,0x66,0x01, +0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,0x04,0x00,0x29,0xaf,0x08,0x00,0x2a,0xaf, +0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,0x10,0x00,0x39,0x27,0x01,0x00,0x02,0x93, +0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,0x02,0x00,0x04,0x93,0x04,0x00,0x08,0x93, +0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,0x03,0x00,0x07,0x93,0x00,0x12,0x02,0x00, +0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,0x25,0x18,0x68,0x00,0x00,0x24,0x04,0x00, +0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,0x25,0x28,0xa3,0x00,0x00,0x3e,0x07,0x00, +0x00,0x36,0x06,0x00,0x02,0x80,0x02,0x3c,0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00, +0xcc,0xb1,0x58,0x24,0x04,0x00,0x26,0xaf,0x00,0x00,0x27,0xaf,0x00,0x01,0x12,0x27, +0xa0,0x01,0xb9,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x09,0x00,0x04,0x93, +0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,0x04,0x00,0x10,0x93, +0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,0x0c,0x00,0x0e,0x93, +0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,0x0b,0x00,0x0a,0x93, +0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x00,0x22,0x04,0x00, +0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,0x25,0x20,0x8f,0x00, +0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,0x00,0x3c,0x07,0x00, +0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,0x25,0x38,0xe4,0x00, +0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,0x00,0x56,0x0a,0x00, +0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,0x25,0x50,0x47,0x01, +0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,0x04,0x00,0x29,0xaf, +0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,0x10,0x00,0x39,0x27, +0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,0x02,0x00,0x04,0x93, +0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,0x03,0x00,0x07,0x93, +0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,0x25,0x18,0x68,0x00, +0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,0x25,0x28,0xa3,0x00, +0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,0x25,0x30,0xc5,0x00,0x25,0x38,0xe4,0x00, +0x02,0x80,0x02,0x3c,0x04,0x00,0x26,0xaf,0x00,0x00,0x27,0xaf,0x78,0x1b,0x46,0x24, +0x21,0x50,0x00,0x00,0x80,0x20,0x0a,0x00,0x21,0x10,0x9d,0x00,0x00,0x00,0x45,0x8c, +0x01,0x00,0x43,0x25,0xff,0x00,0x6a,0x30,0x21,0x20,0x86,0x00,0x25,0x00,0x42,0x2d, +0xf8,0xff,0x40,0x14,0x18,0x00,0x85,0xac,0x02,0x80,0x02,0x3c,0x78,0x1b,0x4b,0x24, +0x21,0x50,0x00,0x00,0xc0,0x10,0x0a,0x00,0x21,0x48,0x5d,0x00,0x21,0x38,0x00,0x00, +0x21,0x40,0x4b,0x00,0x21,0x10,0x27,0x01,0xa0,0x01,0x46,0x90,0x98,0x00,0x45,0x90, +0x01,0x00,0xe4,0x24,0x21,0x18,0x07,0x01,0xff,0x00,0x87,0x30,0x08,0x00,0xe2,0x2c, +0xb4,0x01,0x66,0xa0,0xf7,0xff,0x40,0x14,0xac,0x00,0x65,0xa0,0x01,0x00,0x42,0x25, +0xff,0x00,0x4a,0x30,0x21,0x00,0x43,0x2d,0xef,0xff,0x60,0x14,0xc0,0x10,0x0a,0x00, +0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00, +0x20,0x00,0x63,0x30,0x4f,0x00,0x60,0x10,0x78,0x1b,0x64,0x26,0x33,0x00,0x02,0x24, +0xc1,0x02,0x62,0xa1,0x1c,0x00,0x03,0x24,0x0f,0x00,0x02,0x24,0xbc,0x02,0x63,0xa1, +0xbd,0x02,0x62,0xa1,0x78,0x1b,0x65,0x26,0x08,0x00,0xa4,0x8c,0xff,0x7f,0x09,0x3c, +0xff,0xff,0x29,0x35,0xc0,0xff,0x02,0x24,0x24,0x20,0x89,0x00,0x24,0x20,0x82,0x00, +0x0c,0x00,0x84,0x34,0xff,0xc0,0x02,0x24,0xc8,0x02,0xa0,0xa0,0x24,0x20,0x82,0x00, +0xc0,0xff,0x02,0x3c,0xc8,0x02,0xa6,0x8c,0xff,0xff,0x42,0x34,0x00,0x18,0x84,0x34, +0x24,0x20,0x82,0x00,0xff,0x0f,0x02,0x3c,0xff,0xff,0x42,0x34,0xbf,0xff,0x03,0x3c, +0x24,0x30,0xc2,0x00,0xff,0xff,0x63,0x34,0x7f,0xff,0x02,0x3c,0x24,0x20,0x83,0x00, +0xff,0xff,0x42,0x34,0x24,0x20,0x82,0x00,0x7f,0xff,0x03,0x24,0x40,0x40,0x84,0x34, +0xff,0xff,0x02,0x3c,0x24,0x20,0x83,0x00,0xff,0x7f,0x42,0x34,0xc8,0x02,0xa6,0xac, +0x24,0x20,0x82,0x00,0xc9,0x02,0xa0,0xa0,0x0c,0x00,0xa6,0x8c,0xff,0x9f,0x02,0x3c, +0xc8,0x02,0xa7,0x8c,0xff,0xff,0x42,0x34,0xff,0xbf,0x03,0x3c,0x10,0x00,0xa8,0x8c, +0xff,0xff,0x63,0x34,0x24,0x20,0x82,0x00,0xff,0xf0,0x02,0x3c,0x24,0x30,0xc3,0x00, +0xff,0xff,0x42,0x34,0xff,0x3f,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x38,0xe2,0x00, +0xb4,0x02,0xb3,0x8f,0x1f,0x00,0x02,0x24,0xb0,0x02,0xb2,0x8f,0xac,0x02,0xb1,0x8f, +0xa8,0x02,0xb0,0x8f,0x24,0x40,0x03,0x01,0xbe,0x02,0xa2,0xa0,0x01,0x00,0x03,0x24, +0xff,0xff,0x02,0x24,0x24,0x30,0xc9,0x00,0xc0,0x02,0xa3,0xa0,0xc2,0x02,0xa2,0xa0, +0xff,0x00,0x03,0x24,0x12,0x00,0x02,0x24,0xb8,0x02,0xbd,0x27,0xc8,0x02,0xa7,0xac, +0x08,0x00,0xa4,0xac,0x10,0x00,0xa8,0xac,0x0c,0x00,0xa6,0xac,0xc4,0x02,0xa3,0xa4, +0xc7,0x02,0xa2,0xa0,0xca,0x02,0xa0,0xa0,0xbf,0x02,0xa0,0xa0,0x08,0x00,0xe0,0x03, +0xc6,0x02,0xa0,0xa0,0x33,0x00,0x02,0x24,0xc1,0x02,0x82,0xa0,0x0d,0x00,0x03,0x24, +0x03,0x00,0x02,0x24,0xbc,0x02,0x83,0xa0,0x97,0x63,0x00,0x08,0xbd,0x02,0x82,0xa0, +0x02,0x80,0x19,0x3c,0x78,0x1b,0x22,0x27,0xe0,0xff,0xbd,0x27,0xff,0xff,0x03,0x34, +0x18,0x00,0xbf,0xaf,0x21,0xc0,0x40,0x00,0xf4,0x23,0x43,0xac,0xea,0x02,0x40,0xa0, +0x1f,0x00,0x0f,0x24,0xff,0xff,0xef,0x25,0x80,0x11,0x43,0xac,0x84,0x11,0x43,0xac, +0xfc,0xff,0xe1,0x05,0x94,0x00,0x42,0x24,0x78,0x1b,0x24,0x8f,0xd8,0x02,0x05,0x8f, +0xf0,0xff,0x02,0x3c,0xe8,0x02,0x07,0x8f,0xfd,0xff,0x03,0x24,0xff,0xff,0x42,0x34, +0x24,0x20,0x83,0x00,0x24,0x28,0xa2,0x00,0x20,0x00,0x0f,0x24,0xff,0xff,0x0e,0x24, +0xff,0xef,0x02,0x3c,0x78,0x1b,0x24,0xaf,0xff,0xff,0x42,0x34,0xd8,0x02,0x05,0xaf, +0x02,0x00,0x0e,0xa3,0xdb,0x02,0x0f,0xa3,0xd8,0x02,0x00,0xa3,0xff,0xbf,0x03,0x3c, +0x78,0x1b,0x28,0x8f,0xd8,0x02,0x09,0x8f,0x24,0x38,0xe2,0x00,0xff,0xff,0x63,0x34, +0x24,0x38,0xe3,0x00,0xff,0x7f,0x02,0x3c,0x0f,0xff,0x03,0x3c,0xfe,0xff,0x04,0x24, +0xff,0xff,0x42,0x34,0xff,0xff,0x63,0x34,0x24,0x40,0x04,0x01,0x24,0x38,0xe2,0x00, +0x24,0x48,0x23,0x01,0xff,0xdf,0x02,0x3c,0xcf,0xff,0x03,0x24,0x24,0x40,0x03,0x01, +0xff,0xff,0x42,0x34,0x10,0x00,0x03,0x3c,0x24,0x38,0xe2,0x00,0x25,0x48,0x23,0x01, +0x0a,0x00,0x02,0x24,0x00,0x02,0x03,0x24,0x78,0x1b,0x28,0xaf,0x02,0x80,0x0a,0x3c, +0xd6,0x02,0x02,0xa3,0xd0,0x02,0x03,0xa7,0x00,0x01,0x02,0x24,0x49,0x00,0x03,0x24, +0xe8,0x02,0x07,0xaf,0xd8,0x02,0x09,0xaf,0xac,0xb5,0x4a,0x25,0x3e,0x00,0x0c,0x24, +0x1c,0x00,0x0d,0x24,0x01,0x00,0x0b,0x24,0x11,0x00,0xa3,0xa3,0xce,0x02,0x02,0xa7, +0xd0,0x07,0x03,0x24,0x44,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,0x10,0x00,0xa2,0xa3, +0x10,0x00,0xa5,0x27,0x47,0x00,0x02,0x24,0x21,0x20,0x40,0x01,0xc8,0x66,0xc6,0x24, +0xd4,0x02,0x0c,0xa3,0xd5,0x02,0x0d,0xa3,0xcc,0x02,0x0f,0xa7,0x01,0x00,0x0b,0xa3, +0x0c,0x00,0x43,0xad,0x14,0x00,0x4b,0xa1,0x06,0x00,0x0e,0xa7,0xd2,0x02,0x0c,0xa3, +0xd3,0x02,0x0d,0xa3,0x12,0x00,0xa2,0xa3,0xa8,0x14,0x00,0x0c,0x13,0x00,0xa0,0xa3, +0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27, +0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x50,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3, +0x52,0x28,0x40,0xa0,0x41,0x00,0x03,0x24,0x52,0x00,0x02,0x24,0x02,0x80,0x07,0x3c, +0x54,0xb6,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,0xd0,0x07,0x02,0x24, +0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00, +0xe4,0x69,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf, +0xa8,0x14,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00, +0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x02,0x80,0x09,0x3c,0x78,0x1b,0x23,0x8d, +0xff,0xff,0x02,0x24,0xff,0x00,0x4b,0x30,0xf3,0xff,0x02,0x24,0x24,0x18,0x62,0x00, +0x3f,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0xd8,0xff,0xbd,0x27,0x78,0x1b,0x23,0xad, +0x47,0x00,0x02,0x24,0x3b,0x00,0x03,0x24,0x02,0x80,0x08,0x3c,0x70,0xb6,0x08,0x25, +0x18,0x00,0xb0,0xaf,0x10,0x00,0xa2,0xa3,0x78,0x1b,0x30,0x25,0x11,0x00,0xa3,0xa3, +0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,0x01,0x00,0x07,0x3c,0x00,0x80,0x06,0x3c, +0x08,0x03,0x0b,0xae,0x1c,0x00,0xb1,0xaf,0x56,0x30,0xea,0x34,0x43,0x00,0x11,0x24, +0xf4,0x98,0xe7,0x34,0x10,0x00,0xa5,0x27,0x0c,0x00,0x02,0xad,0x14,0x00,0x03,0xa1, +0x21,0x20,0x00,0x01,0xd8,0x73,0xc6,0x24,0x20,0x00,0xbf,0xaf,0x12,0x00,0xb1,0xa3, +0x10,0x03,0x07,0xae,0x14,0x03,0x0a,0xae,0x13,0x00,0xa0,0xa3,0x0c,0x03,0x00,0xae, +0x18,0x03,0x00,0xae,0xa8,0x14,0x00,0x0c,0x1c,0x03,0x00,0xae,0x1e,0x00,0x02,0x24, +0x25,0x03,0x02,0xa2,0x4a,0x00,0x03,0x24,0x45,0x00,0x02,0x24,0x20,0x03,0x03,0xa2, +0x21,0x03,0x02,0xa2,0x23,0x00,0x03,0x24,0x3e,0x00,0x02,0x24,0x22,0x03,0x11,0xa2, +0x23,0x03,0x02,0xa2,0x24,0x03,0x03,0xa2,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb1,0x8f, +0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27, +0x3b,0x00,0x02,0x24,0x43,0x00,0x03,0x24,0x10,0x00,0xa2,0xa3,0x11,0x00,0xa3,0xa3, +0x36,0x00,0x02,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x07,0x3c,0x8c,0xb6,0xe7,0x24, +0x12,0x00,0xa2,0xa3,0x4f,0x1e,0x60,0xa0,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24, +0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0x04,0x78,0xc6,0x24, +0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0xa8,0x14,0x00,0x0c, +0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x52,0x00,0x03,0x24, +0x10,0x00,0xa3,0xa3,0xc8,0x3f,0x40,0xa4,0x54,0x00,0x03,0x24,0x53,0x00,0x02,0x24, +0x02,0x80,0x07,0x3c,0xc4,0xb6,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3, +0xf4,0x01,0x02,0x24,0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27, +0x21,0x20,0xe0,0x00,0x28,0x6b,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0, +0x18,0x00,0xbf,0xaf,0xa8,0x14,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f, +0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x02,0x80,0x04,0x3c, +0xd8,0xff,0xbd,0x27,0x80,0x3f,0x84,0x24,0x21,0x28,0x00,0x00,0x20,0x00,0xbf,0xaf, +0x3e,0x46,0x00,0x0c,0x0a,0x00,0x06,0x24,0x02,0x80,0x07,0x3c,0x78,0x1b,0xe7,0x24, +0x04,0x24,0xe3,0x8c,0xfd,0xff,0x02,0x24,0x02,0x80,0x08,0x3c,0x24,0x18,0x62,0x00, +0xfe,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x05,0x00,0x02,0x24,0x04,0x24,0xe3,0xac, +0x08,0x24,0xe2,0xa0,0x28,0x00,0x03,0x24,0x46,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3, +0x09,0x24,0xe3,0xa0,0x4b,0x00,0x02,0x24,0x42,0x00,0x03,0x24,0xe0,0xb6,0x08,0x25, +0x11,0x00,0xa3,0xa3,0x12,0x00,0xa2,0xa3,0xd0,0x07,0x03,0x24,0x01,0x00,0x02,0x24, +0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0x00,0x01,0xf0,0x6b,0xc6,0x24, +0x06,0x24,0xe0,0xa4,0x0c,0x00,0x03,0xad,0x14,0x00,0x02,0xa1,0xa8,0x14,0x00,0x0c, +0x13,0x00,0xa0,0xa3,0x20,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03, +0x28,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x03,0x3c,0x1c,0x00,0xbf,0xaf, +0x18,0x00,0xb0,0xaf,0x44,0xaf,0x62,0x24,0x02,0x00,0x48,0x90,0x44,0xaf,0x67,0x94, +0x02,0x80,0x02,0x3c,0x60,0x44,0x42,0x24,0x02,0x00,0x10,0x24,0x01,0x80,0x06,0x3c, +0x21,0x20,0x40,0x00,0x10,0x00,0xa5,0x27,0x14,0x00,0x50,0xa0,0x34,0x83,0xc6,0x24, +0x10,0x00,0xa7,0xa7,0x12,0x00,0xa8,0xa3,0xa8,0x14,0x00,0x0c,0x13,0x00,0xa0,0xa3, +0x02,0x80,0x02,0x3c,0x7c,0x44,0x42,0x24,0x01,0x80,0x06,0x3c,0x21,0x20,0x40,0x00, +0x10,0x00,0xa5,0x27,0x14,0x00,0x50,0xa0,0xa8,0x14,0x00,0x0c,0x68,0x82,0xc6,0x24, +0x02,0x80,0x02,0x3c,0x98,0x44,0x40,0xa0,0x0c,0x00,0x04,0x24,0x02,0x80,0x03,0x3c, +0x02,0x80,0x02,0x3c,0x99,0x44,0x64,0xa0,0x9a,0x44,0x44,0xa0,0x02,0x80,0x03,0x3c, +0x02,0x80,0x02,0x3c,0xb1,0x44,0x60,0xa0,0x01,0x00,0x06,0x24,0xb7,0x44,0x40,0xa0, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xb8,0x44,0x60,0xa0,0x9c,0x44,0x46,0xa0, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xb9,0x44,0x60,0xa0,0x08,0x00,0x04,0x24, +0x9b,0x44,0x46,0xa0,0x02,0x80,0x02,0x3c,0x9d,0x44,0x44,0xa0,0x01,0x00,0x05,0x24, +0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x9e,0x44,0x60,0xa0,0x64,0x00,0x04,0x24, +0xa8,0x44,0x45,0xa4,0x02,0x80,0x03,0x3c,0x01,0x00,0x02,0x3c,0xa0,0x44,0x64,0xa4, +0x00,0x90,0x42,0x34,0x02,0x80,0x03,0x3c,0xa4,0x44,0x62,0xac,0x02,0x80,0x04,0x3c, +0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0xac,0x44,0x80,0xac,0x1c,0x00,0xbf,0x8f, +0xb0,0x44,0x40,0xa0,0x18,0x00,0xb0,0x8f,0xb2,0x44,0x60,0xa0,0x02,0x80,0x02,0x3c, +0x02,0x80,0x03,0x3c,0xba,0x44,0x40,0xa0,0xb3,0x44,0x60,0xa0,0x02,0x80,0x02,0x3c, +0x02,0x80,0x03,0x3c,0xb4,0x44,0x45,0xa0,0x20,0x00,0xbd,0x27,0xb5,0x44,0x65,0xa0, +0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0xb6,0x44,0x40,0xa0,0xbc,0x44,0x60,0xac, +0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x78,0x0c,0x00,0x00,0x01,0x00,0x00,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x01,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x02,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x03,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x04,0x5d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x05,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x06,0x59,0x78,0x0c,0x00,0x00, +0x01,0x00,0x07,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x08,0x55,0x78,0x0c,0x00,0x00, +0x01,0x00,0x09,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x0a,0x51,0x78,0x0c,0x00,0x00, +0x01,0x00,0x0b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x0c,0x4d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x0d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x0e,0x49,0x78,0x0c,0x00,0x00, +0x01,0x00,0x0f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x10,0x45,0x78,0x0c,0x00,0x00, +0x01,0x00,0x11,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x12,0x41,0x78,0x0c,0x00,0x00, +0x01,0x00,0x13,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x14,0x3d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x15,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x16,0x39,0x78,0x0c,0x00,0x00, +0x01,0x00,0x17,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x18,0x35,0x78,0x0c,0x00,0x00, +0x01,0x00,0x19,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x1a,0x31,0x78,0x0c,0x00,0x00, +0x01,0x00,0x1b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x1c,0x2d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x1d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x1e,0x29,0x78,0x0c,0x00,0x00, +0x01,0x00,0x1f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x20,0x25,0x78,0x0c,0x00,0x00, +0x01,0x00,0x21,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x22,0x21,0x78,0x0c,0x00,0x00, +0x01,0x00,0x23,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x24,0x1d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x25,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x26,0x19,0x78,0x0c,0x00,0x00, +0x01,0x00,0x27,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x28,0x15,0x78,0x0c,0x00,0x00, +0x01,0x00,0x29,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x2a,0x11,0x78,0x0c,0x00,0x00, +0x01,0x00,0x2b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x2c,0x0d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x2d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x2e,0x09,0x78,0x0c,0x00,0x00, +0x01,0x00,0x2f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x30,0x05,0x78,0x0c,0x00,0x00, +0x01,0x00,0x31,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x32,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x33,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x34,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x35,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x36,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x37,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x38,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x39,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3a,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x3b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3c,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x3d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3e,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x3f,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x40,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x41,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x42,0x5e,0x78,0x0c,0x00,0x00, +0x01,0x00,0x43,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x44,0x5d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x45,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x46,0x59,0x78,0x0c,0x00,0x00, +0x01,0x00,0x47,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x48,0x55,0x78,0x0c,0x00,0x00, +0x01,0x00,0x49,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x4a,0x51,0x78,0x0c,0x00,0x00, +0x01,0x00,0x4b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x4c,0x4d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x4d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x4e,0x49,0x78,0x0c,0x00,0x00, +0x01,0x00,0x4f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x50,0x45,0x78,0x0c,0x00,0x00, +0x01,0x00,0x51,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x52,0x41,0x78,0x0c,0x00,0x00, +0x01,0x00,0x53,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x54,0x3d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x55,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x56,0x39,0x78,0x0c,0x00,0x00, +0x01,0x00,0x57,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x58,0x35,0x78,0x0c,0x00,0x00, +0x01,0x00,0x59,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x5a,0x31,0x78,0x0c,0x00,0x00, +0x01,0x00,0x5b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x5c,0x2d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x5d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x5e,0x29,0x78,0x0c,0x00,0x00, +0x01,0x00,0x5f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x60,0x25,0x78,0x0c,0x00,0x00, +0x01,0x00,0x61,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x62,0x21,0x78,0x0c,0x00,0x00, +0x01,0x00,0x63,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x64,0x1d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x65,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x66,0x19,0x78,0x0c,0x00,0x00, +0x01,0x00,0x67,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x68,0x15,0x78,0x0c,0x00,0x00, +0x01,0x00,0x69,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x6a,0x11,0x78,0x0c,0x00,0x00, +0x01,0x00,0x6b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x6c,0x0d,0x78,0x0c,0x00,0x00, +0x01,0x00,0x6d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x6e,0x09,0x78,0x0c,0x00,0x00, +0x01,0x00,0x6f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x70,0x05,0x78,0x0c,0x00,0x00, +0x01,0x00,0x71,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x72,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x73,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x74,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x75,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x76,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x77,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x78,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x79,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7a,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x7b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7c,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x7d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7e,0x01,0x78,0x0c,0x00,0x00, +0x01,0x00,0x7f,0x01,0x78,0x0c,0x00,0x00,0x1e,0x00,0x00,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x01,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x02,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x03,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x04,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x05,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x06,0x30,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x07,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x08,0x3e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x09,0x40,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0a,0x42,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x0b,0x44,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0c,0x46,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x0d,0x48,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0e,0x48,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x0f,0x4a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x10,0x4a,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x11,0x4c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x12,0x4c,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x13,0x4e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x14,0x50,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x15,0x50,0x78,0x0c,0x00,0x00,0x1e,0x00,0x16,0x50,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x17,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x18,0x52,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x19,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1a,0x54,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x1b,0x54,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1c,0x54,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x1d,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1e,0x56,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x1f,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x20,0x56,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x21,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x22,0x58,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x23,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x24,0x58,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x25,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x26,0x5a,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x27,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x28,0x5c,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x29,0x5c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2a,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x2b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2c,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x2d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2e,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x2f,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x30,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x31,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x32,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x33,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x34,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x35,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x36,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x37,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x38,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x39,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3a,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x3b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3c,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x3d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3e,0x5e,0x78,0x0c,0x00,0x00, +0x1e,0x00,0x3f,0x5e,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x08,0x00,0x00, +0x00,0x00,0x04,0x03,0x04,0x08,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x08,0x00,0x00, +0x00,0xfc,0x00,0x00,0x0c,0x08,0x00,0x00,0x0a,0x00,0x00,0x04,0x10,0x08,0x00,0x00, +0xff,0x10,0x10,0x80,0x14,0x08,0x00,0x00,0x10,0x3d,0x0c,0x02,0x18,0x08,0x00,0x00, +0xc5,0x03,0x00,0x00,0x1c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x24,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x28,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x2c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x30,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x34,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x38,0x08,0x00,0x00, +0x04,0x00,0x00,0x00,0x3c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x40,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x44,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x4c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x54,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x08,0x00,0x00, +0x65,0xa9,0x65,0xa9,0x5c,0x08,0x00,0x00,0x65,0xa9,0x65,0xa9,0x60,0x08,0x00,0x00, +0x30,0x01,0x7f,0x0f,0x64,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x68,0x08,0x00,0x00, +0x30,0x01,0x7f,0x0f,0x6c,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x70,0x08,0x00,0x00, +0x00,0x03,0x00,0x03,0x74,0x08,0x00,0x00,0x00,0x03,0x00,0x03,0x78,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x7c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x94,0x08,0x00,0x00,0xfe,0xff,0xff,0xff,0x98,0x08,0x00,0x00, +0x10,0x20,0x30,0x40,0x9c,0x08,0x00,0x00,0x50,0x60,0x70,0x00,0xb0,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0xe0,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x08,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x04,0x0e,0x00,0x00, +0x03,0x03,0x03,0x03,0x08,0x0e,0x00,0x00,0x03,0x03,0x00,0x00,0x0c,0x0e,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x14,0x0e,0x00,0x00, +0x03,0x03,0x03,0x03,0x18,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x1c,0x0e,0x00,0x00, +0x03,0x03,0x03,0x03,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x09,0x00,0x00, +0x23,0x00,0x00,0x00,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x09,0x00,0x00, +0x33,0x13,0x32,0x03,0x08,0x0a,0x00,0x00,0x00,0x86,0x88,0x8f,0x2c,0x0a,0x00,0x00, +0x00,0x00,0x92,0x00,0x00,0x0c,0x00,0x00,0x80,0x00,0x00,0x00,0x04,0x0c,0x00,0x00, +0x33,0x54,0x00,0x00,0x08,0x0c,0x00,0x00,0xe4,0x00,0x00,0x00,0x0c,0x0c,0x00,0x00, +0x6c,0x6c,0x6c,0x6c,0x10,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x20,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x24,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x28,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x2c,0x0c,0x00,0x00, +0x00,0x01,0x00,0x40,0x30,0x0c,0x00,0x00,0x44,0x6a,0xe9,0x8d,0x34,0x0c,0x00,0x00, +0xcd,0x52,0x96,0x46,0x38,0x0c,0x00,0x00,0x90,0x5a,0x01,0x48,0x3c,0x0c,0x00,0x00, +0x64,0x97,0x97,0x1a,0x40,0x0c,0x00,0x00,0x3f,0x42,0x7c,0x1f,0x44,0x0c,0x00,0x00, +0xb7,0x00,0x01,0x00,0x48,0x0c,0x00,0x00,0x00,0x00,0x02,0xec,0x4c,0x0c,0x00,0x00, +0x03,0x03,0xfc,0x00,0x50,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x54,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x58,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x5c,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x60,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x64,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x68,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x6c,0x0c,0x00,0x00, +0x94,0x00,0x3c,0x43,0x70,0x0c,0x00,0x00,0x0d,0x00,0x5a,0x2c,0x74,0x0c,0x00,0x00, +0x1b,0x15,0x86,0x01,0x78,0x0c,0x00,0x00,0x1f,0x00,0x00,0x00,0x7c,0x0c,0x00,0x00, +0x12,0x16,0xb9,0x00,0x80,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x84,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0x88,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x8c,0x0c,0x00,0x00, +0x00,0x00,0x20,0x08,0x90,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x94,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0x98,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x9c,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xa0,0x0c,0x00,0x00,0x92,0x24,0x49,0x00,0xa4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xa8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xb0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xb8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x0c,0x00,0x00, +0x92,0x24,0x49,0x00,0xc0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xc4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xc8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xcc,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xd0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xd8,0x0c,0x00,0x00,0x27,0x24,0xb2,0x64,0xdc,0x0c,0x00,0x00, +0x32,0x69,0x76,0x00,0xe0,0x0c,0x00,0x00,0x22,0x22,0x22,0x00,0xe4,0x0c,0x00,0x00, +0x00,0x00,0x00,0x00,0xe8,0x0c,0x00,0x00,0x02,0x43,0x64,0x07,0x00,0x0d,0x00,0x00, +0x80,0x07,0x00,0x00,0x04,0x0d,0x00,0x00,0x03,0x04,0x00,0x00,0x08,0x0d,0x00,0x00, +0x7f,0x90,0x00,0x00,0x0c,0x0d,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x0d,0x00,0x00, +0x99,0x99,0x69,0xa0,0x14,0x0d,0x00,0x00,0x67,0x3c,0x99,0x99,0x18,0x0d,0x00,0x00, +0x6b,0x5b,0x8f,0x6a,0x1c,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x24,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x2c,0x0d,0x00,0x00,0x75,0x19,0x97,0xcc,0x30,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x34,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x3c,0x0d,0x00,0x00,0x93,0x72,0x02,0x00,0x40,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x44,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x0d,0x00,0x00, +0x00,0x00,0x00,0x00,0x50,0x0d,0x00,0x00,0x0a,0x14,0x37,0x64,0x54,0x0d,0x00,0x00, +0x02,0xbd,0x4d,0x02,0x58,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x0d,0x00,0x00, +0x64,0x20,0x03,0x30,0x60,0x0d,0x00,0x00,0x68,0xde,0x53,0x46,0x64,0x0d,0x00,0x00, +0x3c,0x8a,0x51,0x00,0x68,0x0d,0x00,0x00,0x06,0x01,0x00,0x00,0xff,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00, +0x64,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x6c,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x74,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x7c,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x84,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x8c,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x94,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x9c,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0xa4,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0xac,0x05,0x01,0x80,0x10,0x00,0x00,0x00, +0x9c,0x2d,0x00,0x80,0x10,0x00,0x00,0x00,0x94,0x2d,0x00,0x80,0x10,0x00,0x00,0x00, +0xb4,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0xbc,0x05,0x01,0x80,0x34,0x01,0x00,0x00, +0xc4,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0xcc,0x05,0x01,0x80,0x34,0x01,0x00,0x00, +0xc4,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0xd4,0x05,0x01,0x80,0x30,0x00,0x00,0x00, +0xdc,0x05,0x01,0x80,0x04,0x00,0x00,0x00,0xe4,0x05,0x01,0x80,0x13,0x00,0x00,0x00, +0xec,0x05,0x01,0x80,0x17,0x00,0x00,0x00,0xf4,0x05,0x01,0x80,0x06,0x00,0x00,0x00, +0xfc,0x05,0x01,0x80,0x06,0x00,0x00,0x00,0x04,0x06,0x01,0x80,0x08,0x00,0x00,0x00, +0x0c,0x06,0x01,0x80,0x0c,0x00,0x00,0x00,0x14,0x06,0x01,0x80,0x04,0x00,0x00,0x00, +0x1c,0x06,0x01,0x80,0x1f,0x00,0x00,0x00,0x24,0x06,0x01,0x80,0x01,0x00,0x00,0x00, +0x2c,0x06,0x01,0x80,0x38,0x00,0x00,0x00,0x34,0x06,0x01,0x80,0x04,0x00,0x00,0x00, +0x3c,0x06,0x01,0x80,0x02,0x00,0x00,0x00,0x44,0x06,0x01,0x80,0x04,0x00,0x00,0x00, +0x4c,0x06,0x01,0x80,0x01,0x00,0x00,0x00,0x54,0x06,0x01,0x80,0x01,0x00,0x00,0x00, +0x5c,0x06,0x01,0x80,0x0c,0x00,0x00,0x00,0x64,0x06,0x01,0x80,0x0e,0x00,0x00,0x00, +0x6c,0x06,0x01,0x80,0x0c,0x00,0x00,0x00,0xb8,0x08,0x01,0x80,0x78,0x00,0x00,0x00, +0xf0,0x09,0x01,0x80,0x04,0x00,0x00,0x00,0xf8,0x09,0x01,0x80,0x04,0x00,0x00,0x00, +0xa4,0x2d,0x00,0x80,0x04,0x00,0x00,0x00,0xac,0x2d,0x00,0x80,0x04,0x00,0x00,0x00, +0xb4,0x2d,0x00,0x80,0x04,0x00,0x00,0x00,0x00,0x0a,0x01,0x80,0x08,0x00,0x00,0x00, +0x08,0x0a,0x01,0x80,0x10,0x00,0x00,0x00,0x10,0x0a,0x01,0x80,0x01,0x00,0x00,0x00, +0x18,0x0a,0x01,0x80,0x01,0x00,0x00,0x00,0x20,0x0a,0x01,0x80,0x10,0x00,0x00,0x00, +0xc4,0x2d,0x00,0x80,0x00,0xb7,0x00,0x00,0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00, +0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00, +0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00, +0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00, +0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00, +0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00, +0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00, +0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00, +0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00, +0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00, +0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00, +0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00, +0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00, +0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00, +0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00, +0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00, +0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00, +0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00, +0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00, +0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00, +0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00, +0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00, +0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00, +0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00, +0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00, +0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00, +0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00, +0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00, +0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00, +0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00, +0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00, +0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00, +0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00, +0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00, +0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00, +0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00, +0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00, +0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00, +0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00, +0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00, +0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00, +0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00, +0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00, +0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00, +0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00, +0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00, +0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00, +0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00, +0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00, +0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00, +0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00, +0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00, +0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00, +0xff,0xff,0xff,0x00,0x00,0xb7,0x00,0x00,0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00, +0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00, +0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00, +0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00, +0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00, +0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00, +0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00, +0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00, +0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00, +0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00, +0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00, +0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00, +0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00, +0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00, +0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00, +0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00, +0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00, +0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00, +0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00, +0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00, +0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00, +0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00, +0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00, +0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00, +0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00, +0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00, +0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00, +0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00, +0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00, +0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00, +0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00, +0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00, +0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00, +0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00, +0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00, +0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00, +0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00, +0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00, +0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00, +0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00, +0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00, +0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00, +0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00, +0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00, +0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00, +0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00, +0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00, +0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00, +0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00, +0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00, +0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00, +0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00, +0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00, +0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00, +0xff,0xff,0xff,0x00,0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52,0x65,0x71,0x00,0x00, +0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00,0x4f,0x6e,0x52,0x65, +0x41,0x73,0x73,0x6f,0x63,0x52,0x65,0x71,0x00,0x00,0x00,0x00,0x4f,0x6e,0x52,0x65, +0x41,0x73,0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00,0x00,0x00,0x4f,0x6e,0x50,0x72, +0x6f,0x62,0x65,0x52,0x65,0x71,0x00,0x00,0x4f,0x6e,0x50,0x72,0x6f,0x62,0x65,0x52, +0x73,0x70,0x00,0x00,0x4f,0x6e,0x42,0x65,0x61,0x63,0x6f,0x6e,0x00,0x00,0x00,0x00, +0x4f,0x6e,0x41,0x54,0x49,0x4d,0x00,0x00,0x4f,0x6e,0x44,0x69,0x73,0x61,0x73,0x73, +0x6f,0x63,0x00,0x00,0x4f,0x6e,0x41,0x75,0x74,0x68,0x00,0x00,0x4f,0x6e,0x44,0x65, +0x41,0x75,0x74,0x68,0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x63,0x74,0x69,0x6f,0x6e, +0x00,0x00,0x00,0x00,0x4f,0x6e,0x45,0x78,0x63,0x65,0x70,0x74,0x69,0x6f,0x6e,0x00, +0x00,0x00,0x00,0x00,0xfc,0xa7,0x01,0x80,0x24,0x2f,0x00,0x80,0x10,0x00,0x00,0x00, +0x08,0xa8,0x01,0x80,0x2c,0x2f,0x00,0x80,0x20,0x00,0x00,0x00,0x14,0xa8,0x01,0x80, +0x24,0x2f,0x00,0x80,0x30,0x00,0x00,0x00,0x24,0xa8,0x01,0x80,0x2c,0x2f,0x00,0x80, +0x40,0x00,0x00,0x00,0x34,0xa8,0x01,0x80,0x34,0x2f,0x00,0x80,0x50,0x00,0x00,0x00, +0x40,0xa8,0x01,0x80,0x54,0x2f,0x00,0x80,0x80,0x00,0x00,0x00,0x4c,0xa8,0x01,0x80, +0x04,0x30,0x00,0x80,0x90,0x00,0x00,0x00,0x58,0xa8,0x01,0x80,0x5c,0x2f,0x00,0x80, +0xa0,0x00,0x00,0x00,0x60,0xa8,0x01,0x80,0x6c,0x2f,0x00,0x80,0xb0,0x00,0x00,0x00, +0x6c,0xa8,0x01,0x80,0x64,0x2f,0x00,0x80,0xc0,0x00,0x00,0x00,0x74,0xa8,0x01,0x80, +0x74,0x2f,0x00,0x80,0xd0,0x00,0x00,0x00,0x80,0xa8,0x01,0x80,0x7c,0x2f,0x00,0x80, +0x0c,0x00,0x00,0x00,0x8c,0xa8,0x01,0x80,0x98,0x2f,0x00,0x80,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b, +0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x04,0x05,0x06,0x07,0x08,0xff,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0x01,0x80,0x00,0xaa,0x01,0x80, +0x31,0x10,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x20,0x10,0x00,0x00,0x30,0x00,0x00, +0x31,0x28,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x30,0x00,0x00, +0x31,0x2f,0x10,0x10,0x00,0x30,0x00,0x00,0x31,0x30,0x18,0x00,0x00,0x30,0x00,0x00, +0x31,0x30,0x20,0x10,0x00,0x30,0x00,0x00,0x22,0x20,0x18,0x08,0x00,0x20,0x00,0x00, +0x22,0x21,0x14,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x1c,0x08,0x00,0x20,0x00,0x00, +0x22,0x21,0x20,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x20,0x00,0x00, +0x22,0x21,0x20,0x18,0x00,0x20,0x00,0x00,0x1a,0x19,0x18,0x10,0x00,0x18,0x00,0x00, +0x12,0x11,0x10,0x08,0x00,0x10,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x08,0x00,0x00, +0x0a,0x09,0x08,0x02,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x08,0x00,0x00, +0x0a,0x09,0x08,0x06,0x00,0x08,0x00,0x00,0x08,0x07,0x06,0x04,0x00,0x06,0x00,0x00, +0x06,0x05,0x04,0x02,0x00,0x04,0x00,0x00,0x06,0x05,0x04,0x03,0x00,0x04,0x00,0x00, +0x05,0x04,0x03,0x02,0x00,0x03,0x00,0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05, +0x05,0x04,0x04,0x03,0x06,0x05,0x05,0x04,0x04,0x03,0x03,0x03,0x05,0x04,0x04,0x03, +0x03,0x02,0x02,0x02,0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05,0x05,0x04,0x04, +0x03,0x05,0x04,0x04,0x03,0x03,0x02,0x02,0x02,0x04,0x03,0x03,0x02,0x02,0x01,0x01, +0x01,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20, +0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20, +0x30,0x08,0x08,0x08,0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20, +0x20,0x20,0x20,0x30,0x30,0x08,0x10,0x20,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08, +0x08,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x20,0x08,0x08,0x08, +0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20,0x20,0x20,0x20,0x30, +0x30,0x08,0x10,0x20,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x0a,0x09,0x08,0x04, +0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00, +0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a, +0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11, +0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08, +0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x18, +0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,0x20,0x18,0x08,0x00, +0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a, +0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21, +0x20,0x08,0x00,0x22,0x21,0x1c,0x08,0x00,0x31,0x30,0x18,0x00,0x00,0x0a,0x09,0x08, +0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04, +0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00, +0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31, +0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21, +0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14, +0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2c,0x10,0x10, +0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00, +0x22,0x21,0x20,0x18,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31, +0x2f,0x10,0x10,0x00,0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00, +0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a, +0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09, +0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10, +0x08,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x04, +0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00, +0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22, +0x21,0x14,0x08,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09, +0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20, +0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x21,0x14,0x08, +0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00, +0x0a,0x09,0x08,0x04,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a, +0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21, +0x20,0x08,0x00,0x31,0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10, +0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08, +0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00, +0x31,0x2c,0x10,0x10,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22, +0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f, +0x10,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10, +0x10,0x00,0x00,0x00,0x01,0x02,0x04,0x08,0x02,0x04,0x08,0x0c,0x10,0x18,0x20,0x30, +0x02,0x04,0x08,0x0c,0x10,0x18,0x20,0x30,0x06,0x0c,0x10,0x18,0x24,0x30,0x3c,0x48, +0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x27,0x2c, +0x19,0x1b,0x1e,0x20,0x23,0x29,0x2a,0x2b,0x00,0x00,0x00,0x00,0x25,0x29,0x2b,0x2e, +0x2e,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00, +0x10,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00, +0x48,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0xc0,0x00,0x00,0x00, +0xd8,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xa0,0x00,0x00,0x00, +0xc8,0x00,0x00,0x00,0x40,0x01,0x00,0x00,0x90,0x01,0x00,0x00,0xe0,0x01,0x00,0x00, +0x30,0x02,0x00,0x00,0x2c,0x01,0x00,0x00,0x40,0x01,0x00,0x00,0xe0,0x01,0x00,0x00, +0xd0,0x02,0x00,0x00,0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00, +0xa0,0x0f,0x00,0x00,0xa0,0x0f,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00, +0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x12,0x00,0x00,0x00, +0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00, +0x60,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x3c,0x00,0x00,0x00, +0x50,0x00,0x00,0x00,0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00, +0xf0,0x00,0x00,0x00,0x18,0x01,0x00,0x00,0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00, +0xf0,0x00,0x00,0x00,0x68,0x01,0x00,0x00,0x40,0x06,0x00,0x00,0x40,0x06,0x00,0x00, +0x40,0x06,0x00,0x00,0xd0,0x07,0x00,0x00,0xd0,0x07,0x00,0x00,0x30,0x7a,0x00,0x80, +0x88,0x85,0x00,0x80,0x88,0x85,0x00,0x80,0x88,0x85,0x00,0x80,0x88,0x85,0x00,0x80, +0xd8,0x83,0x00,0x80,0x38,0x7a,0x00,0x80,0x30,0x7a,0x00,0x80,0x30,0x7a,0x00,0x80, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb8,0x86,0x00,0x80,0xb8,0x86,0x00,0x80, +0xb8,0x86,0x00,0x80,0xb8,0x86,0x00,0x80,0xfc,0x6c,0x01,0x80,0x1c,0x6d,0x01,0x80, +0x04,0x6d,0x01,0x80,0x0c,0x6d,0x01,0x80,0x14,0x6d,0x01,0x80,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x08,0x04,0x04,0x08,0x02,0x02,0x01,0x01,0x50,0x53,0x00,0x00, +0xf8,0x07,0x00,0x80,0xec,0x07,0x00,0x80,0xe0,0x07,0x00,0x80,0xd4,0x07,0x00,0x80, +0xc8,0x07,0x00,0x80,0xbc,0x07,0x00,0x80,0xb0,0x07,0x00,0x80,0xa4,0x07,0x00,0x80, +0x98,0x07,0x00,0x80,0x8c,0x07,0x00,0x80,0x44,0x07,0x00,0x80,0xb0,0x03,0x25,0xb0, +0x2c,0x00,0x2a,0xb0,0x78,0x1b,0x02,0x80,0xb0,0x03,0x25,0xb0,0x44,0x44,0x33,0x33, +0x06,0x00,0x2a,0xb0,0x3c,0x47,0x00,0x80,0x30,0x47,0x00,0x80,0x24,0x47,0x00,0x80, +0x18,0x47,0x00,0x80,0x0c,0x47,0x00,0x80,0x00,0x47,0x00,0x80,0xf4,0x46,0x00,0x80, +0xe8,0x46,0x00,0x80,0xdc,0x46,0x00,0x80,0xd0,0x46,0x00,0x80,0xc4,0x46,0x00,0x80, +0xb8,0x46,0x00,0x80,0x60,0x3f,0x01,0x80,0x48,0x3f,0x01,0x80,0x30,0x3f,0x01,0x80, +0x18,0x3f,0x01,0x80,0x00,0x3f,0x01,0x80,0xe8,0x3e,0x01,0x80,0xb4,0x3e,0x01,0x80, +0x00,0x02,0x00,0x00,0x08,0x09,0x00,0x00,0x0c,0x58,0x00,0x80,0x18,0x58,0x00,0x80, +0x24,0x58,0x00,0x80,0x30,0x58,0x00,0x80,0x0c,0x58,0x00,0x80,0x0c,0x58,0x00,0x80, +0x0c,0x58,0x00,0x80,0x0c,0x58,0x00,0x80,0x3c,0x58,0x00,0x80,0x48,0x58,0x00,0x80, +0x54,0x58,0x00,0x80,0x60,0x58,0x00,0x80,0x78,0x1b,0x02,0x80,0x78,0x1b,0x02,0x80, +0x84,0x0e,0x25,0xb0,0x88,0x0e,0x25,0xb0,0x8c,0x0e,0x25,0xb0,0xd0,0x0e,0x25,0xb0, +0xd8,0x0e,0x25,0xb0,0x20,0x08,0x25,0xb0,0xfe,0x01,0x80,0x7f,0xe2,0x01,0x80,0x78, +0xc7,0x01,0xc0,0x71,0xae,0x01,0x80,0x6b,0x95,0x01,0x40,0x65,0x7f,0x01,0xc0,0x5f, +0x69,0x01,0x40,0x5a,0x55,0x01,0x40,0x55,0x42,0x01,0x80,0x50,0x30,0x01,0x00,0x4c, +0x1f,0x01,0xc0,0x47,0x0f,0x01,0xc0,0x43,0x00,0x01,0x00,0x40,0xf2,0x00,0x80,0x3c, +0xe4,0x00,0x00,0x39,0xd7,0x00,0xc0,0x35,0xcb,0x00,0xc0,0x32,0xc0,0x00,0x00,0x30, +0xb5,0x00,0x40,0x2d,0xab,0x00,0xc0,0x2a,0xa2,0x00,0x80,0x28,0x98,0x00,0x00,0x26, +0x90,0x00,0x00,0x24,0x88,0x00,0x00,0x22,0x80,0x00,0x00,0x20,0x79,0x00,0x40,0x1e, +0x72,0x00,0x80,0x1c,0x6c,0x00,0x00,0x1b,0x66,0x00,0x80,0x19,0x60,0x00,0x00,0x18, +0x5b,0x00,0xc0,0x16,0x56,0x00,0x80,0x15,0x51,0x00,0x40,0x14,0x4c,0x00,0x00,0x13, +0x48,0x00,0x00,0x12,0x44,0x00,0x00,0x11,0x40,0x00,0x00,0x10,0x36,0x35,0x2e,0x25, +0x1c,0x12,0x09,0x04,0x33,0x32,0x2b,0x23,0x1a,0x11,0x08,0x04,0x30,0x2f,0x29,0x21, +0x19,0x10,0x08,0x03,0x2d,0x2d,0x27,0x1f,0x18,0x0f,0x08,0x03,0x2b,0x2a,0x25,0x1e, +0x16,0x0e,0x07,0x03,0x28,0x28,0x22,0x1c,0x15,0x0d,0x07,0x03,0x26,0x25,0x21,0x1b, +0x14,0x0d,0x06,0x03,0x24,0x23,0x1f,0x19,0x13,0x0c,0x06,0x03,0x22,0x21,0x1d,0x18, +0x11,0x0b,0x06,0x02,0x20,0x20,0x1b,0x16,0x11,0x08,0x05,0x02,0x1f,0x1e,0x1a,0x15, +0x10,0x0a,0x05,0x02,0x1d,0x1c,0x18,0x14,0x0f,0x0a,0x05,0x02,0x1b,0x1a,0x17,0x13, +0x0e,0x09,0x04,0x02,0x1a,0x19,0x16,0x12,0x0d,0x09,0x04,0x02,0x18,0x17,0x15,0x11, +0x0c,0x08,0x04,0x02,0x17,0x16,0x13,0x10,0x0c,0x08,0x04,0x02,0x16,0x15,0x12,0x0f, +0x0b,0x07,0x04,0x01,0x14,0x14,0x11,0x0e,0x0b,0x07,0x03,0x02,0x13,0x13,0x10,0x0d, +0x0a,0x06,0x03,0x01,0x12,0x12,0x0f,0x0c,0x09,0x06,0x03,0x01,0x11,0x11,0x0f,0x0c, +0x09,0x06,0x03,0x01,0x10,0x10,0x0e,0x0b,0x08,0x05,0x03,0x01,0x0f,0x0f,0x0d,0x0b, +0x08,0x05,0x03,0x01,0x0e,0x0e,0x0c,0x0a,0x08,0x05,0x02,0x01,0x0d,0x0d,0x0c,0x0a, +0x07,0x05,0x02,0x01,0x0d,0x0c,0x0b,0x09,0x07,0x04,0x02,0x01,0x0c,0x0c,0x0a,0x09, +0x06,0x04,0x02,0x01,0x0b,0x0b,0x0a,0x08,0x06,0x04,0x02,0x01,0x0b,0x0a,0x09,0x08, +0x06,0x04,0x02,0x01,0x0a,0x0a,0x09,0x07,0x05,0x03,0x02,0x01,0x0a,0x09,0x08,0x07, +0x05,0x03,0x02,0x01,0x09,0x09,0x08,0x06,0x05,0x03,0x01,0x01,0x09,0x08,0x07,0x06, +0x04,0x03,0x01,0x01,0x36,0x35,0x2e,0x1b,0x00,0x00,0x00,0x00,0x33,0x32,0x2b,0x19, +0x00,0x00,0x00,0x00,0x30,0x2f,0x29,0x18,0x00,0x00,0x00,0x00,0x2d,0x2d,0x17,0x17, +0x00,0x00,0x00,0x00,0x2b,0x2a,0x25,0x15,0x00,0x00,0x00,0x00,0x28,0x28,0x24,0x14, +0x00,0x00,0x00,0x00,0x26,0x25,0x21,0x13,0x00,0x00,0x00,0x00,0x24,0x23,0x1f,0x12, +0x00,0x00,0x00,0x00,0x22,0x21,0x1d,0x11,0x00,0x00,0x00,0x00,0x20,0x20,0x1b,0x10, +0x00,0x00,0x00,0x00,0x1f,0x1e,0x1a,0x0f,0x00,0x00,0x00,0x00,0x1d,0x1c,0x18,0x0e, +0x00,0x00,0x00,0x00,0x1b,0x1a,0x17,0x0e,0x00,0x00,0x00,0x00,0x1a,0x19,0x16,0x0d, +0x00,0x00,0x00,0x00,0x18,0x17,0x15,0x0c,0x00,0x00,0x00,0x00,0x17,0x16,0x13,0x0b, +0x00,0x00,0x00,0x00,0x16,0x15,0x12,0x0b,0x00,0x00,0x00,0x00,0x14,0x14,0x11,0x0a, +0x00,0x00,0x00,0x00,0x13,0x13,0x10,0x0a,0x00,0x00,0x00,0x00,0x12,0x12,0x0f,0x09, +0x00,0x00,0x00,0x00,0x11,0x11,0x0f,0x09,0x00,0x00,0x00,0x00,0x10,0x10,0x0e,0x08, +0x00,0x00,0x00,0x00,0x0f,0x0f,0x0d,0x08,0x00,0x00,0x00,0x00,0x0e,0x0e,0x0c,0x07, +0x00,0x00,0x00,0x00,0x0d,0x0d,0x0c,0x07,0x00,0x00,0x00,0x00,0x0d,0x0c,0x0b,0x06, +0x00,0x00,0x00,0x00,0x0c,0x0c,0x0a,0x06,0x00,0x00,0x00,0x00,0x0b,0x0b,0x0a,0x06, +0x00,0x00,0x00,0x00,0x0b,0x0a,0x09,0x05,0x00,0x00,0x00,0x00,0x0a,0x0a,0x09,0x05, +0x00,0x00,0x00,0x00,0x0a,0x09,0x08,0x05,0x00,0x00,0x00,0x00,0x09,0x09,0x08,0x05, +0x00,0x00,0x00,0x00,0x09,0x08,0x07,0x04,0x00,0x00,0x00,0x00,0x06,0x00,0x2a,0xb0, +0x05,0x00,0x2a,0xb0,0x34,0x7b,0x00,0x80,0xbc,0x7b,0x00,0x80,0x60,0x7b,0x00,0x80, +0xbc,0x7b,0x00,0x80,0xbc,0x7b,0x00,0x80,0xbc,0x7b,0x00,0x80,0xbc,0x7b,0x00,0x80, +0x08,0x7b,0x00,0x80,0x00,0x01,0x02,0x02,0x03,0x03,0x03,0x03,0x04,0x04,0x04,0x04, +0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05, +0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, +0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06, +0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07, +0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x28,0x28,0x28,0x28,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08, +0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, +0x04,0x04,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x41,0x41,0x41,0x41,0x41,0x41,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x01,0x01,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x42,0x42,0x42,0x42,0x42,0x42,0x02, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, +0x02,0x02,0x02,0x10,0x10,0x10,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, +0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10, +0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10, +0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x36,0xc2,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x45,0xc4,0xf0,0x00,0x45,0xc4,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x45,0xb5,0x60,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x02, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0xc7,0x00,0xb8,0xff,0xff,0xff,0xff, +}; + +u8 Rtl8192SEFwMainArray[MainArrayLength] = { +0x0, }; + +u8 Rtl8192SEFwDataArray[DataArrayLength] = { +0x0, }; + +u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength] = { +0x01c,0x07000000, +0x800,0x00040000, +0x804,0x00008003, +0x808,0x0000fc00, +0x80c,0x0000000a, +0x810,0x10005088, +0x814,0x020c3d10, +0x818,0x00200185, +0x81c,0x00000000, +0x820,0x01000000, +0x824,0x00390004, +0x828,0x01000000, +0x82c,0x00390004, +0x830,0x00000004, +0x834,0x00690200, +0x838,0x00000004, +0x83c,0x00690200, +0x840,0x00010000, +0x844,0x00010000, +0x848,0x00000000, +0x84c,0x00000000, +0x850,0x00000000, +0x854,0x00000000, +0x858,0x48484848, +0x85c,0x65a965a9, +0x860,0x0f7f0130, +0x864,0x0f7f0130, +0x868,0x0f7f0130, +0x86c,0x0f7f0130, +0x870,0x03000700, +0x874,0x03000300, +0x878,0x00020002, +0x87c,0x004f0201, +0x880,0xa8300ac1, +0x884,0x00000058, +0x888,0x00000008, +0x88c,0x00000004, +0x890,0x00000000, +0x894,0xfffffffe, +0x898,0x40302010, +0x89c,0x00706050, +0x8b0,0x00000000, +0x8e0,0x00000000, +0x8e4,0x00000000, +0xe00,0x30333333, +0xe04,0x2a2d2e2f, +0xe08,0x00003232, +0xe10,0x30333333, +0xe14,0x2a2d2e2f, +0xe18,0x30333333, +0xe1c,0x2a2d2e2f, +0xe30,0x01007c00, +0xe34,0x01004800, +0xe38,0x1000dc1f, +0xe3c,0x10008c1f, +0xe40,0x021400a0, +0xe44,0x281600a0, +0xe48,0xf8000001, +0xe4c,0x00002910, +0xe50,0x01007c00, +0xe54,0x01004800, +0xe58,0x1000dc1f, +0xe5c,0x10008c1f, +0xe60,0x021400a0, +0xe64,0x281600a0, +0xe6c,0x00002910, +0xe70,0x31ed92fb, +0xe74,0x361536fb, +0xe78,0x361536fb, +0xe7c,0x361536fb, +0xe80,0x361536fb, +0xe84,0x000d92fb, +0xe88,0x000d92fb, +0xe8c,0x31ed92fb, +0xed0,0x31ed92fb, +0xed4,0x31ed92fb, +0xed8,0x000d92fb, +0xedc,0x000d92fb, +0xee0,0x000d92fb, +0xee4,0x015e5448, +0xee8,0x21555448, +0x900,0x00000000, +0x904,0x00000023, +0x908,0x00000000, +0x90c,0x01121313, +0xa00,0x00d047c8, +0xa04,0x80ff0008, +0xa08,0x88cd8300, +0xa0c,0x2e62120f, +0xa10,0x9500bb78, +0xa14,0x11144028, +0xa18,0x00881117, +0xa1c,0x89140f00, +0xa20,0x1a1b0000, +0xa24,0x090e1317, +0xa28,0x00000204, +0xa2c,0x10d30000, +0xc00,0x40071d40, +0xc04,0x00a05633, +0xc08,0x000000e4, +0xc0c,0x6c6c6c6c, +0xc10,0x08800000, +0xc14,0x40000100, +0xc18,0x08000000, +0xc1c,0x40000100, +0xc20,0x08000000, +0xc24,0x40000100, +0xc28,0x08000000, +0xc2c,0x40000100, +0xc30,0x6de9ac44, +0xc34,0x469652cf, +0xc38,0x49795994, +0xc3c,0x0a979764, +0xc40,0x1f7c403f, +0xc44,0x000100b7, +0xc48,0xec020000, +0xc4c,0x007f037f, +0xc50,0x69543420, +0xc54,0x433c0094, +0xc58,0x69543420, +0xc5c,0x433c0094, +0xc60,0x69543420, +0xc64,0x433c0094, +0xc68,0x69543420, +0xc6c,0x433c0094, +0xc70,0x2c7f000d, +0xc74,0x0186175b, +0xc78,0x0000001f, +0xc7c,0x00b91612, +0xc80,0x40000100, +0xc84,0x20f60000, +0xc88,0x20000080, +0xc8c,0x20200000, +0xc90,0x40000100, +0xc94,0x00000000, +0xc98,0x40000100, +0xc9c,0x00000000, +0xca0,0x00492492, +0xca4,0x00000000, +0xca8,0x00000000, +0xcac,0x00000000, +0xcb0,0x00000000, +0xcb4,0x00000000, +0xcb8,0x00000000, +0xcbc,0x28000000, +0xcc0,0x00000000, +0xcc4,0x00000000, +0xcc8,0x00000000, +0xccc,0x00000000, +0xcd0,0x00000000, +0xcd4,0x00000000, +0xcd8,0x64b22427, +0xcdc,0x00766932, +0xce0,0x00222222, +0xce4,0x00000000, +0xce8,0x37644302, +0xcec,0x2f97d40c, +0xd00,0x00000750, +0xd04,0x00000403, +0xd08,0x0000907f, +0xd0c,0x00000001, +0xd10,0xa0633333, +0xd14,0x33333c63, +0xd18,0x6a8f5b6b, +0xd1c,0x00000000, +0xd20,0x00000000, +0xd24,0x00000000, +0xd28,0x00000000, +0xd2c,0xcc979975, +0xd30,0x00000000, +0xd34,0x00000000, +0xd38,0x00000000, +0xd3c,0x00027293, +0xd40,0x00000000, +0xd44,0x00000000, +0xd48,0x00000000, +0xd50,0x6437140a, +0xd54,0x024dbd02, +0xd58,0x00000000, +0xd5c,0x30032064, +0xd60,0x4653de68, +0xd64,0x00518a3c, +0xd68,0x00002101, +0xf14,0x00000003, +0xf4c,0x00000000, +0xf00,0x00000300, +}; + +u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength] = { +0x0, }; + +u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength] = { +0x844,0xffffffff,0x00010000, +0x804,0x0000000f,0x00000001, +0x824,0x00f0000f,0x00300004, +0x82c,0x00f0000f,0x00100002, +0x870,0x04000000,0x00000001, +0x864,0x00000400,0x00000000, +0x878,0x000f000f,0x00000002, +0xe74,0x0f000000,0x00000002, +0xe78,0x0f000000,0x00000002, +0xe7c,0x0f000000,0x00000002, +0xe80,0x0f000000,0x00000002, +0x90c,0x000000ff,0x00000011, +0xc04,0x000000ff,0x00000011, +0xd04,0x0000000f,0x00000001, +0x1f4,0xffff0000,0x00007777, +0x234,0xf8000000,0x0000000a, +}; + +u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength] = { +0x804,0x0000000f,0x00000003, +0x824,0x00f0000f,0x00300004, +0x82c,0x00f0000f,0x00300002, +0x870,0x04000000,0x00000001, +0x864,0x00000400,0x00000000, +0x878,0x000f000f,0x00000002, +0xe74,0x0f000000,0x00000002, +0xe78,0x0f000000,0x00000002, +0xe7c,0x0f000000,0x00000002, +0xe80,0x0f000000,0x00000002, +0x90c,0x000000ff,0x00000011, +0xc04,0x000000ff,0x00000033, +0xd04,0x0000000f,0x00000003, +0x1f4,0xffff0000,0x00007777, +0x234,0xf8000000,0x0000000a, +}; + +u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength] = { +0x804,0x0000000f,0x00000003, +0x824,0x00f0000f,0x00300004, +0x82c,0x00f0000f,0x00300004, +0x870,0x04000000,0x00000001, +0x864,0x00000400,0x00000001, +0x878,0x000f000f,0x00020002, +0xe74,0x0f000000,0x00000006, +0xe78,0x0f000000,0x00000006, +0xe7c,0x0f000000,0x00000006, +0xe80,0x0f000000,0x00000006, +0x90c,0x000000ff,0x00000033, +0xc04,0x000000ff,0x00000033, +0xd04,0x0000000f,0x00000003, +0x1f4,0xffff0000,0x0000ffff, +0x234,0xf8000000,0x00000013, +}; + +u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength] = { +0xe00,0xffffffff,0x06090909, +0xe04,0xffffffff,0x00030406, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x0a0c0d0e, +0xe14,0xffffffff,0x03040508, +0xe18,0xffffffff,0x0a0c0d0e, +0xe1c,0xffffffff,0x03040508, +0xe00,0xffffffff,0x04040404, +0xe04,0xffffffff,0x00020204, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x02040404, +0xe14,0xffffffff,0x00000002, +0xe18,0xffffffff,0x02040404, +0xe1c,0xffffffff,0x00000002, +0xe00,0xffffffff,0x04040404, +0xe04,0xffffffff,0x00020204, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x02040404, +0xe14,0xffffffff,0x00000002, +0xe18,0xffffffff,0x02040404, +0xe1c,0xffffffff,0x00000002, +0xe00,0xffffffff,0x02020202, +0xe04,0xffffffff,0x00020202, +0xe08,0x0000ff00,0x00000000, +0xe10,0xffffffff,0x02020202, +0xe14,0xffffffff,0x00000002, +0xe18,0xffffffff,0x02020202, +0xe1c,0xffffffff,0x00000002, +}; + +u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength] = { +0x000,0x00030159, +0x001,0x00030250, +0x002,0x00010000, +0x010,0x0008000f, +0x011,0x000231fc, +0x010,0x000c000f, +0x011,0x0003f9f8, +0x010,0x0002000f, +0x011,0x00020101, +0x014,0x0001093e, +0x014,0x0009093e, +0x015,0x0000f8f4, +0x017,0x000f6500, +0x01a,0x00013056, +0x01b,0x00060000, +0x01c,0x00000300, +0x01e,0x00031059, +0x021,0x00054000, +0x022,0x0000083c, +0x023,0x00001558, +0x024,0x00000060, +0x025,0x00022583, +0x026,0x0000f200, +0x027,0x000eacf1, +0x028,0x0009bd54, +0x029,0x00004582, +0x02a,0x00000001, +0x02b,0x00021334, +0x02a,0x00000000, +0x02b,0x0000000a, +0x02a,0x00000001, +0x02b,0x00000808, +0x02b,0x00053333, +0x02c,0x0000000c, +0x02a,0x00000002, +0x02b,0x00000808, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000003, +0x02b,0x00000808, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000004, +0x02b,0x00000808, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000005, +0x02b,0x00000709, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x00000006, +0x02b,0x00000709, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000007, +0x02b,0x00000709, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000008, +0x02b,0x00000709, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000009, +0x02b,0x0000060a, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000a, +0x02b,0x0000060a, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x0000000b, +0x02b,0x0000060a, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x0000000c, +0x02b,0x0000060a, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x0000000d, +0x02b,0x0000050b, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000e, +0x02b,0x0000050b, +0x02b,0x00066623, +0x02c,0x0000001a, +0x02a,0x000e4000, +0x030,0x00020000, +0x031,0x000b9631, +0x032,0x0000130d, +0x033,0x00000187, +0x013,0x00019e6c, +0x013,0x00015e94, +0x000,0x00010159, +0x018,0x0000f401, +0x0fe,0x00000000, +0x01e,0x0003105b, +0x0fe,0x00000000, +0x000,0x00030159, +0x010,0x0004000f, +0x011,0x000203f9, +}; + +u32 Rtl8192SERadioB_Array[RadioB_ArrayLength] = { +0x000,0x00030159, +0x001,0x00001041, +0x002,0x00011000, +0x005,0x00080fc0, +0x007,0x000fc803, +0x013,0x00017cb0, +0x013,0x00011cc0, +0x013,0x0000dc60, +0x013,0x00008c60, +0x013,0x00004450, +0x013,0x00000020, +}; + +u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength] = { +0x000,0x00030159, +0x001,0x00030250, +0x002,0x00010000, +0x010,0x0008000f, +0x011,0x000231fc, +0x010,0x000c000f, +0x011,0x0003f9f8, +0x014,0x0001093e, +0x014,0x0009093e, +0x015,0x000198f4, +0x017,0x000f6500, +0x01a,0x00013056, +0x01b,0x00060000, +0x01c,0x00000300, +0x01e,0x00031059, +0x021,0x00054000, +0x022,0x0000083c, +0x023,0x00001558, +0x024,0x00000060, +0x025,0x00022583, +0x026,0x0000f200, +0x027,0x000eacf1, +0x028,0x000dbd54, +0x029,0x00004582, +0x02a,0x00000001, +0x02b,0x00021334, +0x02a,0x00000000, +0x02b,0x0000000a, +0x02a,0x00000001, +0x02b,0x00000808, +0x02b,0x00053333, +0x02c,0x0000000c, +0x02a,0x00000002, +0x02b,0x00000808, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000003, +0x02b,0x00000808, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000004, +0x02b,0x00000808, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000005, +0x02b,0x00000709, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x00000006, +0x02b,0x00000709, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000007, +0x02b,0x00000709, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000008, +0x02b,0x00000709, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000009, +0x02b,0x0000060a, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000a, +0x02b,0x0000060a, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x0000000b, +0x02b,0x0000060a, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x0000000c, +0x02b,0x0000060a, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x0000000d, +0x02b,0x0000050b, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000e, +0x02b,0x0000050b, +0x02b,0x00066623, +0x02c,0x0000001a, +0x02a,0x000e4000, +0x030,0x00020000, +0x031,0x000b9631, +0x033,0x00000187, +0x013,0x00019e6c, +0x013,0x00015e94, +0x000,0x00010159, +0x018,0x0000f401, +0x0fe,0x00000000, +0x01e,0x0003105b, +0x0fe,0x00000000, +0x000,0x00030159, +0x010,0x0004000f, +0x011,0x000203f9, +}; + +u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength] = { +0x000,0x00030159, +0x001,0x00030250, +0x002,0x00010000, +0x010,0x0008000f, +0x011,0x000231fc, +0x010,0x000c000f, +0x011,0x0003f9f8, +0x014,0x0001093e, +0x014,0x0009093e, +0x015,0x000198f4, +0x017,0x000f6500, +0x01a,0x00013056, +0x01b,0x00060000, +0x01c,0x00000300, +0x01e,0x00031059, +0x021,0x00054000, +0x022,0x0000083c, +0x023,0x00001558, +0x024,0x00000060, +0x025,0x00022583, +0x026,0x0000f200, +0x027,0x000eacf1, +0x028,0x000dbd54, +0x029,0x00004582, +0x02a,0x00000001, +0x02b,0x00021334, +0x02a,0x00000000, +0x02b,0x0000000a, +0x02a,0x00000001, +0x02b,0x00000808, +0x02b,0x00053333, +0x02c,0x0000000c, +0x02a,0x00000002, +0x02b,0x00000808, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000003, +0x02b,0x00000808, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000004, +0x02b,0x00000808, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000005, +0x02b,0x00000709, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x00000006, +0x02b,0x00000709, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x00000007, +0x02b,0x00000709, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x00000008, +0x02b,0x00000709, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x00000009, +0x02b,0x0000060a, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000a, +0x02b,0x0000060a, +0x02b,0x0005b333, +0x02c,0x0000000d, +0x02a,0x0000000b, +0x02b,0x0000060a, +0x02b,0x00063333, +0x02c,0x0000000d, +0x02a,0x0000000c, +0x02b,0x0000060a, +0x02b,0x0006b333, +0x02c,0x0000000d, +0x02a,0x0000000d, +0x02b,0x0000050b, +0x02b,0x00053333, +0x02c,0x0000000d, +0x02a,0x0000000e, +0x02b,0x0000050b, +0x02b,0x00066623, +0x02c,0x0000001a, +0x02a,0x000e4000, +0x030,0x00020000, +0x031,0x000b9631, +0x033,0x00000187, +0x013,0x00019e6c, +0x013,0x00015e94, +0x000,0x00010159, +0x018,0x0000f401, +0x0fe,0x00000000, +0x01e,0x0003105b, +0x0fe,0x00000000, +0x000,0x00030159, +0x010,0x0004000f, +0x011,0x000203f9, +}; + +u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength] = { +0x000,0x00030159, +0x001,0x00001041, +0x002,0x00011000, +0x005,0x00080fc0, +0x007,0x000fc803, +}; + +u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength] = { +0x020,0x00000035, +0x048,0x0000000e, +0x049,0x000000f0, +0x04a,0x00000077, +0x04b,0x00000083, +0x0b5,0x00000021, +0x0dc,0x000000ff, +0x0dd,0x000000ff, +0x0de,0x000000ff, +0x0df,0x000000ff, +0x116,0x00000000, +0x117,0x00000000, +0x118,0x00000000, +0x119,0x00000000, +0x11a,0x00000000, +0x11b,0x00000000, +0x11c,0x00000000, +0x11d,0x00000000, +0x160,0x0000000b, +0x161,0x0000000b, +0x162,0x0000000b, +0x163,0x0000000b, +0x164,0x0000000b, +0x165,0x0000000b, +0x166,0x0000000b, +0x167,0x0000000b, +0x168,0x0000000b, +0x169,0x0000000b, +0x16a,0x0000000b, +0x16b,0x0000000b, +0x16c,0x0000000b, +0x16d,0x0000000b, +0x16e,0x0000000b, +0x16f,0x0000000b, +0x170,0x0000000b, +0x171,0x0000000b, +0x172,0x0000000b, +0x173,0x0000000b, +0x174,0x0000000b, +0x175,0x0000000b, +0x176,0x0000000b, +0x177,0x0000000b, +0x178,0x0000000b, +0x179,0x0000000b, +0x17a,0x0000000b, +0x17b,0x0000000b, +0x17c,0x0000000b, +0x17d,0x0000000b, +0x17e,0x0000000b, +0x17f,0x0000000b, +0x236,0x0000000c, +0x503,0x00000022, +0x560,0x00000000, +}; + +u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength] = { +0x0, }; + +u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength] = { +0xc78,0x7f000001, +0xc78,0x7f010001, +0xc78,0x7e020001, +0xc78,0x7d030001, +0xc78,0x7c040001, +0xc78,0x7b050001, +0xc78,0x7a060001, +0xc78,0x79070001, +0xc78,0x78080001, +0xc78,0x77090001, +0xc78,0x760a0001, +0xc78,0x750b0001, +0xc78,0x740c0001, +0xc78,0x730d0001, +0xc78,0x720e0001, +0xc78,0x710f0001, +0xc78,0x70100001, +0xc78,0x6f110001, +0xc78,0x6f120001, +0xc78,0x6e130001, +0xc78,0x6d140001, +0xc78,0x6d150001, +0xc78,0x6c160001, +0xc78,0x6b170001, +0xc78,0x6a180001, +0xc78,0x6a190001, +0xc78,0x691a0001, +0xc78,0x681b0001, +0xc78,0x671c0001, +0xc78,0x661d0001, +0xc78,0x651e0001, +0xc78,0x641f0001, +0xc78,0x63200001, +0xc78,0x4c210001, +0xc78,0x4b220001, +0xc78,0x4a230001, +0xc78,0x49240001, +0xc78,0x48250001, +0xc78,0x47260001, +0xc78,0x46270001, +0xc78,0x45280001, +0xc78,0x44290001, +0xc78,0x2c2a0001, +0xc78,0x2b2b0001, +0xc78,0x2a2c0001, +0xc78,0x292d0001, +0xc78,0x282e0001, +0xc78,0x272f0001, +0xc78,0x26300001, +0xc78,0x25310001, +0xc78,0x24320001, +0xc78,0x23330001, +0xc78,0x22340001, +0xc78,0x09350001, +0xc78,0x08360001, +0xc78,0x07370001, +0xc78,0x06380001, +0xc78,0x05390001, +0xc78,0x043a0001, +0xc78,0x033b0001, +0xc78,0x023c0001, +0xc78,0x013d0001, +0xc78,0x003e0001, +0xc78,0x003f0001, +0xc78,0x7f400001, +0xc78,0x7f410001, +0xc78,0x7e420001, +0xc78,0x7d430001, +0xc78,0x7c440001, +0xc78,0x7b450001, +0xc78,0x7a460001, +0xc78,0x79470001, +0xc78,0x78480001, +0xc78,0x77490001, +0xc78,0x764a0001, +0xc78,0x754b0001, +0xc78,0x744c0001, +0xc78,0x734d0001, +0xc78,0x724e0001, +0xc78,0x714f0001, +0xc78,0x70500001, +0xc78,0x6f510001, +0xc78,0x6f520001, +0xc78,0x6e530001, +0xc78,0x6d540001, +0xc78,0x6d550001, +0xc78,0x6c560001, +0xc78,0x6b570001, +0xc78,0x6a580001, +0xc78,0x6a590001, +0xc78,0x695a0001, +0xc78,0x685b0001, +0xc78,0x675c0001, +0xc78,0x665d0001, +0xc78,0x655e0001, +0xc78,0x645f0001, +0xc78,0x63600001, +0xc78,0x4c610001, +0xc78,0x4b620001, +0xc78,0x4a630001, +0xc78,0x49640001, +0xc78,0x48650001, +0xc78,0x47660001, +0xc78,0x46670001, +0xc78,0x45680001, +0xc78,0x44690001, +0xc78,0x2c6a0001, +0xc78,0x2b6b0001, +0xc78,0x2a6c0001, +0xc78,0x296d0001, +0xc78,0x286e0001, +0xc78,0x276f0001, +0xc78,0x26700001, +0xc78,0x25710001, +0xc78,0x24720001, +0xc78,0x23730001, +0xc78,0x22740001, +0xc78,0x09750001, +0xc78,0x08760001, +0xc78,0x07770001, +0xc78,0x06780001, +0xc78,0x05790001, +0xc78,0x047a0001, +0xc78,0x037b0001, +0xc78,0x027c0001, +0xc78,0x017d0001, +0xc78,0x007e0001, +0xc78,0x007f0001, +0xc78,0x3000001e, +0xc78,0x3001001e, +0xc78,0x3002001e, +0xc78,0x3003001e, +0xc78,0x3004001e, +0xc78,0x3405001e, +0xc78,0x3806001e, +0xc78,0x3e07001e, +0xc78,0x3e08001e, +0xc78,0x4409001e, +0xc78,0x460a001e, +0xc78,0x480b001e, +0xc78,0x480c001e, +0xc78,0x4e0d001e, +0xc78,0x560e001e, +0xc78,0x5a0f001e, +0xc78,0x5e10001e, +0xc78,0x6211001e, +0xc78,0x6c12001e, +0xc78,0x7213001e, +0xc78,0x7214001e, +0xc78,0x7215001e, +0xc78,0x7216001e, +0xc78,0x7217001e, +0xc78,0x7218001e, +0xc78,0x7219001e, +0xc78,0x721a001e, +0xc78,0x721b001e, +0xc78,0x721c001e, +0xc78,0x721d001e, +0xc78,0x721e001e, +0xc78,0x721f001e, +}; + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg74.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_hwimg74.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef __INC_HAL8192SE_FW_IMG_H +#define __INC_HAL8192SE_FW_IMG_H + +/*Created on 2009/11/17, 16:15*/ + +#include +#define ImgArrayLength 88592 +extern u8 Rtl8192SEFwImgArray[ImgArrayLength]; +#define MainArrayLength 1 +extern u8 Rtl8192SEFwMainArray[MainArrayLength]; +#define DataArrayLength 1 +extern u8 Rtl8192SEFwDataArray[DataArrayLength]; +#define PHY_REG_2T2RArrayLength 372 +extern u32 Rtl8192SEPHY_REG_2T2RArray[PHY_REG_2T2RArrayLength]; +#define PHY_REG_1T2RArrayLength 1 +extern u32 Rtl8192SEPHY_REG_1T2RArray[PHY_REG_1T2RArrayLength]; +#define PHY_ChangeTo_1T1RArrayLength 48 +extern u32 Rtl8192SEPHY_ChangeTo_1T1RArray[PHY_ChangeTo_1T1RArrayLength]; +#define PHY_ChangeTo_1T2RArrayLength 45 +extern u32 Rtl8192SEPHY_ChangeTo_1T2RArray[PHY_ChangeTo_1T2RArrayLength]; +#define PHY_ChangeTo_2T2RArrayLength 45 +extern u32 Rtl8192SEPHY_ChangeTo_2T2RArray[PHY_ChangeTo_2T2RArrayLength]; +#define PHY_REG_Array_PGLength 84 +extern u32 Rtl8192SEPHY_REG_Array_PG[PHY_REG_Array_PGLength]; +#define RadioA_1T_ArrayLength 202 +extern u32 Rtl8192SERadioA_1T_Array[RadioA_1T_ArrayLength]; +#define RadioB_ArrayLength 22 +extern u32 Rtl8192SERadioB_Array[RadioB_ArrayLength]; +#define RadioA_to1T_ArrayLength 196 +extern u32 Rtl8192SERadioA_to1T_Array[RadioA_to1T_ArrayLength]; +#define RadioA_to2T_ArrayLength 196 +extern u32 Rtl8192SERadioA_to2T_Array[RadioA_to2T_ArrayLength]; +#define RadioB_GM_ArrayLength 10 +extern u32 Rtl8192SERadioB_GM_Array[RadioB_GM_ArrayLength]; +#define MAC_2T_ArrayLength 106 +extern u32 Rtl8192SEMAC_2T_Array[MAC_2T_ArrayLength]; +#define MACPHY_Array_PGLength 1 +extern u32 Rtl8192SEMACPHY_Array_PG[MACPHY_Array_PGLength]; +#define AGCTAB_ArrayLength 320 +extern u32 Rtl8192SEAGCTAB_Array[AGCTAB_ArrayLength]; + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_inc.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_inc.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + +#ifndef _R8192S_INC_H +#define _R8192S_INC_H + +#include "r8192S_dev.h" +#include "r8192S_led.h" +#include "r8192S_def.h" +#include "r8192S_phy.h" +#include "r8192S_phyreg.h" +#include "r8192S_firmware.h" +#include "r8192S_hwimg.h" +#include "r8192S_hw.h" +#include "r8192S_rtl6052.h" +#include "r8192S_Efuse.h" +#include "r8192S_mp.h" +#include "r8192S_scan.h" + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_led.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_led.c @@ -0,0 +1,1380 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#include "../rtl_core.h" +#ifdef RTL8192SE +#define LED_BLINK_NORMAL_INTERVAL 100 +#define LED_BLINK_SLOWLY_INTERVAL 200 + +#define LED_BLINK_NORMAL_INTERVAL_NETTRONIX 100 +#define LED_BLINK_SLOWLY_INTERVAL_NETTRONIX 2000 + +#define LED_BLINK_SLOWLY_INTERVAL_PORNET 1000 +#define LED_BLINK_NORMAL_INTERVAL_PORNET 100 + + +#define LED_CM2_BLINK_ON_INTERVAL 250 +#define LED_CM2_BLINK_OFF_INTERVAL 4750 + +#define LED_CM8_BLINK_OFF_INTERVAL 3750 + +#define LED_RunTop_BLINK_INTERVAL 300 + +#define LED_CM3_BLINK_INTERVAL 1500 + + + +static void BlinkTimerCallback(unsigned long data); + + +void InitLed8190Pci(struct net_device *dev, PLED_8190 pLed,LED_PIN_8190 LedPin) +{ + pLed->dev = dev; + pLed->LedPin = LedPin; + + pLed->CurrLedState = LED_OFF; + pLed->bLedOn = false; + pLed->bLedBlinkInProgress = false; + pLed->BlinkTimes = 0; + pLed->BlinkingLedState = LED_OFF; + + setup_timer(&pLed->BlinkTimer, + BlinkTimerCallback, + (unsigned long) pLed); +} + +void DeInitLed8190Pci(PLED_8190 pLed) +{ + del_timer_sync(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; +} + +void SwLedOn( struct net_device *dev , PLED_8190 pLed) +{ + u8 LedCfg; + + LedCfg = read_nic_byte(dev, LEDCFG); + + switch(pLed->LedPin) + { + case LED_PIN_GPIO0: + break; + + case LED_PIN_LED0: + write_nic_byte(dev, LEDCFG, LedCfg&0xf0); + break; + + case LED_PIN_LED1: + write_nic_byte(dev, LEDCFG, LedCfg&0x0f); + break; + + default: + break; + } + + pLed->bLedOn = true; +} + +void SwLedOff(struct net_device *dev, PLED_8190 pLed) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 LedCfg; + + LedCfg = read_nic_byte(dev, LEDCFG); + + switch(pLed->LedPin) + { + case LED_PIN_GPIO0: + break; + + case LED_PIN_LED0: + LedCfg &= 0xf0; + + if(priv->bLedOpenDrain == true) + write_nic_byte(dev, LEDCFG, (LedCfg|BIT1)); + else + write_nic_byte(dev, LEDCFG, (LedCfg|BIT3)); + break; + + case LED_PIN_LED1: + LedCfg &= 0x0f; + write_nic_byte(dev, LEDCFG, (LedCfg|BIT7)); + break; + + default: + break; + } + + pLed->bLedOn = false; +} + + +void InitSwLeds(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + InitLed8190Pci( + dev, + &(priv->SwLed0), + LED_PIN_LED0); + + InitLed8190Pci( + dev, + &(priv->SwLed1), + LED_PIN_LED1); +} + + +void DeInitSwLeds(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + DeInitLed8190Pci( &(priv->SwLed0) ); + DeInitLed8190Pci( &(priv->SwLed1) ); +} + +void HwLedBlink(struct net_device *dev, PLED_8190 pLed) +{ + + + switch(pLed->LedPin) + { + case LED_PIN_GPIO0: + break; + + case LED_PIN_LED0: + break; + + case LED_PIN_LED1: + break; + + default: + break; + } + + pLed->bLedOn = true; +} + + + +void SwLedBlink(PLED_8190 pLed) +{ + struct net_device *dev = (struct net_device *)pLed->dev; + struct r8192_priv *priv = rtllib_priv(dev); + bool bStopBlinking = false; + + if( pLed->BlinkingLedState == LED_ON ) + { + SwLedOn(dev, pLed); + RT_TRACE(COMP_LED, "Blinktimes (%d): turn on\n", pLed->BlinkTimes); + } + else + { + SwLedOff(dev, pLed); + RT_TRACE(COMP_LED, "Blinktimes (%d): turn off\n", pLed->BlinkTimes); + } + + pLed->BlinkTimes--; + switch(pLed->CurrLedState) + { + case LED_BLINK_NORMAL: + case LED_BLINK_TXRX: + case LED_BLINK_RUNTOP: + if(pLed->BlinkTimes == 0) + { + bStopBlinking = true; + } + break; + + case LED_SCAN_BLINK: + if( (priv->rtllib->state == RTLLIB_LINKED) && + (!rtllib_act_scanning(priv->rtllib,true))&& + (pLed->BlinkTimes % 2 == 0)) + { + bStopBlinking = true; + } + break; + + case LED_NO_LINK_BLINK: + case LED_BLINK_StartToBlink: + if( (priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_INFRA)) + { + bStopBlinking = true; + } + else if((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_ADHOC)) + { + bStopBlinking = true; + } + else if(pLed->BlinkTimes == 0) + { + bStopBlinking = true; + } + break; + + case LED_BLINK_CAMEO: + if((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_INFRA)) + { + bStopBlinking = true; + } + else if((priv->rtllib->state == RTLLIB_LINKED) && (priv->rtllib->iw_mode == IW_MODE_ADHOC) ) + { + bStopBlinking = true; + } + break; + + default: + bStopBlinking = true; + break; + } + + if(bStopBlinking) + { + if( priv->rtllib->eRFPowerState != eRfOn ) + { + SwLedOff(dev, pLed); + } + else if(pLed->CurrLedState == LED_BLINK_TXRX) + { + SwLedOff(dev, pLed); + } + else if(pLed->CurrLedState == LED_BLINK_RUNTOP) + { + SwLedOff(dev, pLed); + } + else if( (priv->rtllib->state == RTLLIB_LINKED) && (pLed->bLedOn == false)) + { + SwLedOn(dev, pLed); + } + else if( (priv->rtllib->state != RTLLIB_LINKED) && pLed->bLedOn == true) + { + SwLedOff(dev, pLed); + } + + pLed->BlinkTimes = 0; + pLed->bLedBlinkInProgress = false; + } + else + { + if( pLed->BlinkingLedState == LED_ON ) + pLed->BlinkingLedState = LED_OFF; + else + pLed->BlinkingLedState = LED_ON; + + switch( pLed->CurrLedState ) + { + case LED_BLINK_NORMAL: + case LED_BLINK_TXRX: + case LED_BLINK_StartToBlink: + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); + break; + + case LED_BLINK_SLOWLY: + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL)); + break; + + case LED_SCAN_BLINK: + case LED_NO_LINK_BLINK: + if( pLed->bLedOn ) + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL)); + else + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_OFF_INTERVAL)); + break; + + case LED_BLINK_RUNTOP: + mod_timer(&(pLed->BlinkTimer),jiffies + MSECS(LED_RunTop_BLINK_INTERVAL)); + break; + + case LED_BLINK_CAMEO: + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET)); + break; + + default: + RT_TRACE(COMP_ERR, "SwLedCm2Blink(): unexpected state!\n"); + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL)); + break; + } + } +} + +void SwLedBlink5(PLED_8190 pLed) +{ + struct net_device *dev = (struct net_device *)pLed->dev; + struct r8192_priv *priv = rtllib_priv(dev); + bool bStopBlinking = false; + + if( pLed->BlinkingLedState == LED_ON ) + { + SwLedOn(dev, pLed); + RT_TRACE(COMP_LED, "Blinktimes (%d): turn on\n", pLed->BlinkTimes); + } + else + { + SwLedOff(dev, pLed); + RT_TRACE(COMP_LED, "Blinktimes (%d): turn off\n", pLed->BlinkTimes); + } + + switch(pLed->CurrLedState) + { + case LED_OFF: + SwLedOff(dev, pLed); + break; + + case LED_BLINK_SLOWLY: + if( pLed->bLedOn ) + pLed->BlinkingLedState = LED_OFF; + else + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_NETTRONIX)); + break; + + case LED_BLINK_NORMAL: + pLed->BlinkTimes--; + if( pLed->BlinkTimes == 0 ) + { + bStopBlinking = true; + } + if(bStopBlinking) + { + if( priv->rtllib->eRFPowerState != eRfOn ) + { + SwLedOff(dev, pLed); + } + else + { + pLed->bLedSlowBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if( pLed->bLedOn ) + pLed->BlinkingLedState = LED_OFF; + else + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_NETTRONIX)); + } + pLed->BlinkTimes = 0; + pLed->bLedBlinkInProgress = false; + } + else + { + if( priv->rtllib->eRFPowerState != eRfOn ) + { + SwLedOff(dev, pLed); + } + else + { + if( pLed->bLedOn ) + pLed->BlinkingLedState = LED_OFF; + else + pLed->BlinkingLedState = LED_ON; + + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL_NETTRONIX)); + } + } + break; + + default: + break; + } + +} + + +void SwLedBlink6(PLED_8190 pLed) +{ + struct net_device *dev = (struct net_device *)pLed->dev; + struct r8192_priv *priv = rtllib_priv(dev); + bool bStopBlinking = false; + + if( pLed->BlinkingLedState == LED_ON ) + { + SwLedOn(dev, pLed); + RT_TRACE(COMP_LED, "Blinktimes (%d): turn on\n", pLed->BlinkTimes); + } + else + { + SwLedOff(dev, pLed); + RT_TRACE(COMP_LED, "Blinktimes (%d): turn off\n", pLed->BlinkTimes); + } + + switch(pLed->CurrLedState) + { + case LED_OFF: + SwLedOff(dev, pLed); + break; + + case LED_BLINK_SLOWLY: + if( pLed->bLedOn ) + pLed->BlinkingLedState = LED_OFF; + else + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET)); + break; + + case LED_BLINK_NORMAL: + pLed->BlinkTimes--; + if( pLed->BlinkTimes == 0 ) + { + bStopBlinking = true; + } + if(bStopBlinking) + { + if( priv->rtllib->eRFPowerState != eRfOn ) + { + SwLedOff(dev, pLed); + } + else + { + pLed->bLedSlowBlinkInProgress = true; + pLed->CurrLedState = LED_BLINK_SLOWLY; + if( pLed->bLedOn ) + pLed->BlinkingLedState = LED_OFF; + else + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET)); + } + pLed->BlinkTimes = 0; + pLed->bLedBlinkInProgress = false; + } + else + { + if( priv->rtllib->eRFPowerState != eRfOn ) + { + SwLedOff(dev, pLed); + } + else + { + if( pLed->bLedOn ) + pLed->BlinkingLedState = LED_OFF; + else + pLed->BlinkingLedState = LED_ON; + + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL_PORNET)); + } + } + break; + + default: + break; + } + +} + +void SwLedBlink7( PLED_8190 pLed) +{ + struct net_device *dev = (struct net_device *)pLed->dev; + + SwLedOn(dev, pLed); + RT_TRACE(COMP_LED, "Blinktimes (%d): turn on\n", pLed->BlinkTimes); +} + +void BlinkTimerCallback(unsigned long data) +{ + PLED_8190 pLed = (PLED_8190)data; + struct net_device *dev = (struct net_device *)pLed->dev; + struct r8192_priv *priv = rtllib_priv(dev); + + switch(priv->LedStrategy) + { + case SW_LED_MODE1: + break; + case SW_LED_MODE2: + break; + case SW_LED_MODE3: + break; + case SW_LED_MODE5: + break; + case SW_LED_MODE6: + break; + + case SW_LED_MODE7: + SwLedBlink7(pLed); + break; + + default: + break; + } +} + +void SwLedControlMode0(struct net_device *dev,LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed0 = &(priv->SwLed0); + PLED_8190 pLed1 = &(priv->SwLed1); + + switch(LedAction) + { + case LED_CTL_TX: + case LED_CTL_RX: + break; + + case LED_CTL_LINK: + pLed0->CurrLedState = LED_ON; + SwLedOn(dev, pLed0); + + pLed1->CurrLedState = LED_BLINK_NORMAL; + HwLedBlink(dev, pLed1); + break; + + case LED_CTL_POWER_ON: + pLed0->CurrLedState = LED_OFF; + SwLedOff(dev, pLed0); + + pLed1->CurrLedState = LED_BLINK_NORMAL; + HwLedBlink(dev, pLed1); + + break; + + case LED_CTL_POWER_OFF: + pLed0->CurrLedState = LED_OFF; + SwLedOff(dev, pLed0); + + pLed1->CurrLedState = LED_OFF; + SwLedOff(dev, pLed1); + break; + + case LED_CTL_SITE_SURVEY: + break; + + case LED_CTL_NO_LINK: + pLed0->CurrLedState = LED_OFF; + SwLedOff(dev, pLed0); + + pLed1->CurrLedState = LED_BLINK_NORMAL; + HwLedBlink(dev, pLed1); + break; + + default: + break; + } + + RT_TRACE(COMP_LED, "Led0 %d Led1 %d\n", pLed0->CurrLedState, pLed1->CurrLedState); +} + + +void SwLedControlMode1(struct net_device *dev, LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed = &(priv->SwLed1); + + switch(LedAction) + { + case LED_CTL_TX: + case LED_CTL_RX: + if( pLed->bLedBlinkInProgress == false ) + { + pLed->bLedBlinkInProgress = true; + + pLed->CurrLedState = LED_BLINK_NORMAL; + pLed->BlinkTimes = 2; + + if( pLed->bLedOn ) + pLed->BlinkingLedState = LED_OFF; + else + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); + } + break; + + case LED_CTL_SITE_SURVEY: + if( pLed->bLedBlinkInProgress == false ) + { + pLed->bLedBlinkInProgress = true; + + if(priv->rtllib->state == RTLLIB_LINKED) + { + pLed->CurrLedState = LED_SCAN_BLINK; + pLed->BlinkTimes = 4; + } + else + { + pLed->CurrLedState = LED_NO_LINK_BLINK; + pLed->BlinkTimes = 24; + } + + if( pLed->bLedOn ) + { + pLed->BlinkingLedState = LED_OFF; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL)); + } + else + { + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_OFF_INTERVAL)); + } + } + else + { + if(pLed->CurrLedState != LED_NO_LINK_BLINK) + { + if(priv->rtllib->state == RTLLIB_LINKED) + { + pLed->CurrLedState = LED_SCAN_BLINK; + } + else + { + pLed->CurrLedState = LED_NO_LINK_BLINK; + } + } + } + break; + + case LED_CTL_NO_LINK: + if( pLed->bLedBlinkInProgress == false ) + { + pLed->bLedBlinkInProgress = true; + + pLed->CurrLedState = LED_NO_LINK_BLINK; + pLed->BlinkTimes = 24; + + if( pLed->bLedOn ) + { + pLed->BlinkingLedState = LED_OFF; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL)); + } + else + { + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_OFF_INTERVAL)); + } + } + else + { + pLed->CurrLedState = LED_NO_LINK_BLINK; + } + break; + + case LED_CTL_LINK: + pLed->CurrLedState = LED_ON; + if( pLed->bLedBlinkInProgress == false ) + { + SwLedOn(dev, pLed); + } + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = LED_OFF; + if(pLed->bLedBlinkInProgress) + { + del_timer_sync(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + SwLedOff(dev, pLed); + break; + + default: + break; + } + + RT_TRACE(COMP_LED, "Led %d \n", pLed->CurrLedState); +} + +void SwLedControlMode2(struct net_device *dev, LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed0 = &(priv->SwLed0); + PLED_8190 pLed1 = &(priv->SwLed1); + + switch(LedAction) + { + case LED_CTL_POWER_ON: + pLed0->CurrLedState = LED_OFF; + SwLedOff(dev, pLed0); + + pLed1->CurrLedState = LED_BLINK_CAMEO; + if( pLed1->bLedBlinkInProgress == false ) + { + pLed1->bLedBlinkInProgress = true; + + pLed1->BlinkTimes = 6; + + if( pLed1->bLedOn ) + pLed1->BlinkingLedState = LED_OFF; + else + pLed1->BlinkingLedState = LED_ON; + mod_timer(&(pLed1->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET)); + } + break; + + case LED_CTL_TX: + case LED_CTL_RX: + if( pLed0->bLedBlinkInProgress == false ) + { + pLed0->bLedBlinkInProgress = true; + + pLed0->CurrLedState = LED_BLINK_TXRX; + pLed0->BlinkTimes = 2; + + if( pLed0->bLedOn ) + pLed0->BlinkingLedState = LED_OFF; + else + pLed0->BlinkingLedState = LED_ON; + + mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); + } + break; + + case LED_CTL_NO_LINK: + pLed1->CurrLedState = LED_BLINK_CAMEO; + if( pLed1->bLedBlinkInProgress == false ) + { + pLed1->bLedBlinkInProgress = true; + + pLed1->BlinkTimes = 6; + + if( pLed1->bLedOn ) + pLed1->BlinkingLedState = LED_OFF; + else + pLed1->BlinkingLedState = LED_ON; + mod_timer(&(pLed1->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET)); + } + break; + + case LED_CTL_LINK: + pLed1->CurrLedState = LED_ON; + if( pLed1->bLedBlinkInProgress == false ) + { + SwLedOn(dev, pLed1); + } + break; + + case LED_CTL_POWER_OFF: + pLed0->CurrLedState = LED_OFF; + pLed1->CurrLedState = LED_OFF; + if(pLed0->bLedBlinkInProgress) + { + del_timer_sync(&(pLed0->BlinkTimer)); + pLed0->bLedBlinkInProgress = false; + } + if(pLed1->bLedBlinkInProgress) + { + del_timer_sync(&(pLed1->BlinkTimer)); + pLed1->bLedBlinkInProgress = false; + } + SwLedOff(dev, pLed0); + SwLedOff(dev, pLed1); + break; + + default: + break; + } + + RT_TRACE(COMP_LED, "Led0 %d, Led1 %d \n", pLed0->CurrLedState, pLed1->CurrLedState); +} + + + +void SwLedControlMode3(struct net_device *dev, LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed0 = &(priv->SwLed0); + PLED_8190 pLed1 = &(priv->SwLed1); + + switch(LedAction) + { + case LED_CTL_POWER_ON: + pLed0->CurrLedState = LED_ON; + SwLedOn(dev, pLed0); + pLed1->CurrLedState = LED_OFF; + SwLedOff(dev, pLed1); + break; + + case LED_CTL_TX: + case LED_CTL_RX: + if( pLed1->bLedBlinkInProgress == false ) + { + pLed1->bLedBlinkInProgress = true; + + pLed1->CurrLedState = LED_BLINK_RUNTOP; + pLed1->BlinkTimes = 2; + + if( pLed1->bLedOn ) + pLed1->BlinkingLedState = LED_OFF; + else + pLed1->BlinkingLedState = LED_ON; + + mod_timer(&(pLed1->BlinkTimer), jiffies + MSECS(LED_RunTop_BLINK_INTERVAL)); + } + break; + + case LED_CTL_POWER_OFF: + pLed0->CurrLedState = LED_OFF; + pLed1->CurrLedState = LED_OFF; + if(pLed0->bLedBlinkInProgress) + { + del_timer_sync(&(pLed0->BlinkTimer)); + pLed0->bLedBlinkInProgress = false; + } + if(pLed1->bLedBlinkInProgress) + { + del_timer_sync(&(pLed1->BlinkTimer)); + pLed1->bLedBlinkInProgress = false; + } + SwLedOff(dev, pLed0); + SwLedOff(dev, pLed1); + break; + + default: + break; + } + + RT_TRACE(COMP_LED, "Led0 %d, Led1 %d \n", pLed0->CurrLedState, pLed1->CurrLedState); +} + + +void SwLedControlMode4(struct net_device *dev, LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed0 = &(priv->SwLed0); + PLED_8190 pLed1 = &(priv->SwLed1); + + switch(LedAction) + { + case LED_CTL_POWER_ON: + pLed1->CurrLedState = LED_ON; + SwLedOn(dev, pLed1); + pLed0->CurrLedState = LED_OFF; + SwLedOff(dev, pLed0); + break; + + case LED_CTL_TX: + case LED_CTL_RX: + if( pLed0->bLedBlinkInProgress == false ) + { + pLed0->bLedBlinkInProgress = true; + + pLed0->CurrLedState = LED_BLINK_RUNTOP; + pLed0->BlinkTimes = 2; + + if( pLed0->bLedOn ) + pLed0->BlinkingLedState = LED_OFF; + else + pLed0->BlinkingLedState = LED_ON; + + mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_RunTop_BLINK_INTERVAL)); + } + break; + + case LED_CTL_POWER_OFF: + pLed0->CurrLedState = LED_OFF; + pLed1->CurrLedState = LED_OFF; + if(pLed0->bLedBlinkInProgress) + { + del_timer_sync(&(pLed0->BlinkTimer)); + pLed0->bLedBlinkInProgress = false; + } + if(pLed1->bLedBlinkInProgress) + { + del_timer_sync(&(pLed1->BlinkTimer)); + pLed1->bLedBlinkInProgress = false; + } + SwLedOff(dev, pLed0); + SwLedOff(dev, pLed1); + break; + + default: + break; + } + + RT_TRACE(COMP_LED, "Led0 %d, Led1 %d \n", pLed0->CurrLedState, pLed1->CurrLedState); +} + +void SwLedControlMode5(struct net_device *dev, LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed0 = &(priv->SwLed0); + PLED_8190 pLed1 = &(priv->SwLed1); + switch(LedAction) + { + case LED_CTL_POWER_ON: + case LED_CTL_START_TO_LINK: + case LED_CTL_NO_LINK: + pLed1->CurrLedState = LED_OFF; + SwLedOff(dev, pLed1); + + + if( pLed0->bLedSlowBlinkInProgress == false ) + { + pLed0->bLedSlowBlinkInProgress = true; + pLed0->CurrLedState = LED_BLINK_SLOWLY; + if( pLed0->bLedOn ) + pLed0->BlinkingLedState = LED_OFF; + else + pLed0->BlinkingLedState = LED_ON; + mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_NETTRONIX)); + } + + break; + + case LED_CTL_TX: + case LED_CTL_RX: + pLed1->CurrLedState = LED_ON; + SwLedOn(dev, pLed1); + + if( pLed0->bLedBlinkInProgress == false ) + { + del_timer_sync(&(pLed0->BlinkTimer)); + pLed0->bLedSlowBlinkInProgress = false; + pLed0->bLedBlinkInProgress = true; + pLed0->CurrLedState = LED_BLINK_NORMAL; + pLed0->BlinkTimes = 2; + + if( pLed0->bLedOn ) + pLed0->BlinkingLedState = LED_OFF; + else + pLed0->BlinkingLedState = LED_ON; + mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL_NETTRONIX)); + } + break; + + case LED_CTL_LINK: + pLed1->CurrLedState = LED_ON; + SwLedOn(dev, pLed1); + + if( pLed0->bLedSlowBlinkInProgress == false ) + { + pLed0->bLedSlowBlinkInProgress = true; + pLed0->CurrLedState = LED_BLINK_SLOWLY; + if( pLed0->bLedOn ) + pLed0->BlinkingLedState = LED_OFF; + else + pLed0->BlinkingLedState = LED_ON; + mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_NETTRONIX)); + } + break; + + + case LED_CTL_POWER_OFF: + pLed0->CurrLedState = LED_OFF; + pLed1->CurrLedState = LED_OFF; + if( pLed0->bLedSlowBlinkInProgress == true ) + { + del_timer_sync(&(pLed0->BlinkTimer)); + pLed0->bLedSlowBlinkInProgress = false; + } + if(pLed0->bLedBlinkInProgress == true) + { + del_timer_sync(&(pLed0->BlinkTimer)); + pLed0->bLedBlinkInProgress = false; + } + SwLedOff(dev, pLed0); + SwLedOff(dev, pLed1); + break; + + default: + break; + } + + +} + +void SwLedControlMode6(struct net_device *dev, LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed0 = &(priv->SwLed0); + PLED_8190 pLed1 = &(priv->SwLed1); + + + switch(LedAction) + { + case LED_CTL_POWER_ON: + case LED_CTL_START_TO_LINK: + case LED_CTL_NO_LINK: + case LED_CTL_LINK: + case LED_CTL_SITE_SURVEY: + pLed1->CurrLedState = LED_OFF; + SwLedOff(dev, pLed1); + + if( pLed0->bLedSlowBlinkInProgress == false ) + { + pLed0->bLedSlowBlinkInProgress = true; + pLed0->CurrLedState = LED_BLINK_SLOWLY; + if( pLed0->bLedOn ) + pLed0->BlinkingLedState = LED_OFF; + else + pLed0->BlinkingLedState = LED_ON; + mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL_PORNET)); + } + break; + + case LED_CTL_TX: + case LED_CTL_RX: + pLed1->CurrLedState = LED_OFF; + SwLedOff(dev, pLed1); + if( pLed0->bLedBlinkInProgress == false ) + { + del_timer_sync(&(pLed0->BlinkTimer)); + pLed0->bLedSlowBlinkInProgress = false; + pLed0->bLedBlinkInProgress = true; + pLed0->CurrLedState = LED_BLINK_NORMAL; + pLed0->BlinkTimes = 2; + if( pLed0->bLedOn ) + pLed0->BlinkingLedState = LED_OFF; + else + pLed0->BlinkingLedState = LED_ON; + mod_timer(&(pLed0->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL_PORNET)); + } + break; + + case LED_CTL_POWER_OFF: + pLed1->CurrLedState = LED_OFF; + SwLedOff(dev, pLed1); + + pLed0->CurrLedState = LED_OFF; + if( pLed0->bLedSlowBlinkInProgress == true ) + { + del_timer_sync(&(pLed0->BlinkTimer)); + pLed0->bLedSlowBlinkInProgress = false; + } + if(pLed0->bLedBlinkInProgress == true) + { + del_timer_sync(&(pLed0->BlinkTimer)); + pLed0->bLedBlinkInProgress = false; + } + SwLedOff(dev, pLed0); + break; + + default: + break; + + } +} + + +void SwLedControlMode7(struct net_device *dev, LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed0 = &(priv->SwLed0); + + switch(LedAction) + { + case LED_CTL_POWER_ON: + case LED_CTL_LINK: + case LED_CTL_NO_LINK: + SwLedOn(dev, pLed0); + break; + + case LED_CTL_POWER_OFF: + SwLedOff(dev, pLed0); + break; + + default: + break; + + } +} + +void +SwLedControlMode8(struct net_device *dev, LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed = &(priv->SwLed0); + + switch(LedAction) + { + case LED_CTL_TX: + case LED_CTL_RX: + if( pLed->bLedBlinkInProgress == false && priv->rtllib->state == RTLLIB_LINKED) + { + pLed->bLedBlinkInProgress = true; + + pLed->CurrLedState = LED_BLINK_NORMAL; + pLed->BlinkTimes = 2; + + if( pLed->bLedOn ) + pLed->BlinkingLedState = LED_OFF; + else + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); + } + break; + + case LED_CTL_SITE_SURVEY: + if( pLed->bLedBlinkInProgress == false ) + { + pLed->bLedBlinkInProgress = true; + pLed->CurrLedState = LED_SCAN_BLINK; + pLed->BlinkTimes = 2; + + if( pLed->bLedOn ) + { + pLed->BlinkingLedState = LED_OFF; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL)); + } + else + { + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM8_BLINK_OFF_INTERVAL)); + } + } + else if(pLed->CurrLedState != LED_SCAN_BLINK) + { + del_timer_sync(&(pLed->BlinkTimer)); + pLed->CurrLedState = LED_SCAN_BLINK; + pLed->BlinkTimes = 2; + + if( pLed->bLedOn ) + { + pLed->BlinkingLedState = LED_OFF; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL)); + } + else + { + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM8_BLINK_OFF_INTERVAL)); + } + } + break; + + case LED_CTL_POWER_ON: + case LED_CTL_NO_LINK: + if( pLed->bLedBlinkInProgress == false ) + { + pLed->bLedBlinkInProgress = true; + + pLed->CurrLedState = LED_NO_LINK_BLINK; + pLed->BlinkTimes = 24; + + if( pLed->bLedOn ) + { + pLed->BlinkingLedState = LED_OFF; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL)); + } + else + { + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM8_BLINK_OFF_INTERVAL)); + } + } + else if(pLed->CurrLedState != LED_SCAN_BLINK && pLed->CurrLedState != LED_NO_LINK_BLINK) + { + pLed->CurrLedState = LED_NO_LINK_BLINK; + pLed->BlinkTimes = 24; + + if( pLed->bLedOn ) + { + pLed->BlinkingLedState = LED_OFF; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM2_BLINK_ON_INTERVAL)); + } + else + { + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_CM8_BLINK_OFF_INTERVAL)); + } + } + break; + + case LED_CTL_LINK: + pLed->CurrLedState = LED_ON; + if(pLed->bLedBlinkInProgress) + { + del_timer_sync(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + SwLedOn(dev, pLed); + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = LED_OFF; + if(pLed->bLedBlinkInProgress) + { + del_timer_sync(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + SwLedOff(dev, pLed); + break; + + default: + break; + } +} + +void +SwLedControlMode9(struct net_device *dev, LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed = &(priv->SwLed0); + + switch(LedAction) + { + case LED_CTL_TX: + case LED_CTL_RX: + if( pLed->bLedBlinkInProgress == false ) + { + pLed->bLedBlinkInProgress = true; + + pLed->CurrLedState = LED_BLINK_NORMAL; + pLed->BlinkTimes = 2; + + if( pLed->bLedOn ) + pLed->BlinkingLedState = LED_OFF; + else + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_NORMAL_INTERVAL)); + } + break; + + case LED_CTL_SITE_SURVEY: + if(priv->rtllib->LinkDetectInfo.bBusyTraffic && priv->rtllib->state == RTLLIB_LINKED) + ; + else + { + if( pLed->bLedBlinkInProgress == true ) + del_timer_sync(&(pLed->BlinkTimer)); + else + pLed->bLedBlinkInProgress = true; + + pLed->CurrLedState = LED_SCAN_BLINK; + pLed->BlinkTimes = 24; + + if( pLed->bLedOn ) + { + pLed->BlinkingLedState = LED_OFF; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL)); + } + else + { + pLed->BlinkingLedState = LED_ON; + mod_timer(&(pLed->BlinkTimer), jiffies + MSECS(LED_BLINK_SLOWLY_INTERVAL)); + } + } + break; + + case LED_CTL_POWER_ON: + case LED_CTL_NO_LINK: + case LED_CTL_LINK: + if( pLed->bLedBlinkInProgress == false ) + { + pLed->CurrLedState = LED_ON; + SwLedOn(dev, pLed); + } + break; + + case LED_CTL_POWER_OFF: + pLed->CurrLedState = LED_OFF; + if(pLed->bLedBlinkInProgress) + { + del_timer_sync(&(pLed->BlinkTimer)); + pLed->bLedBlinkInProgress = false; + } + SwLedOff(dev, pLed); + break; + + default: + break; + } + + RT_TRACE(COMP_LED, "LED9 CurrLedState %d\n", pLed->CurrLedState); + +} + +void +SwLedControlMode10(struct net_device *dev, LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PLED_8190 pLed0 = &(priv->SwLed0); + + switch(LedAction) + { + case LED_CTL_LINK: + SwLedOn(dev, pLed0); + break; + + case LED_CTL_POWER_ON: + case LED_CTL_NO_LINK: + case LED_CTL_POWER_OFF: + SwLedOff(dev, pLed0); + break; + + default: + break; + } +} + +void LedControl8192SE(struct net_device *dev, LED_CTL_MODE LedAction) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if(IS_NIC_DOWN(priv)) + return; + +#ifdef TO_DO_LIST + if(Adapter->bInHctTest) + return; +#endif + + if( priv->rtllib->eRFPowerState != eRfOn && + (LedAction == LED_CTL_TX || LedAction == LED_CTL_RX || + LedAction == LED_CTL_SITE_SURVEY || + LedAction == LED_CTL_LINK || + LedAction == LED_CTL_NO_LINK|| + LedAction == LED_CTL_START_TO_LINK || + LedAction == LED_CTL_POWER_ON) ) + { + return; + } + + RT_TRACE(COMP_LED, "LedAction %d, \n", LedAction); + + switch(priv->LedStrategy) + { + case SW_LED_MODE0: + break; + case SW_LED_MODE1: + break; + case SW_LED_MODE2: + break; + case SW_LED_MODE3: + break; + case SW_LED_MODE4: + break; + case SW_LED_MODE5: + break; + + case SW_LED_MODE6: + break; + + case SW_LED_MODE7: + SwLedControlMode7(dev, LedAction); + break; + case SW_LED_MODE8: + SwLedControlMode8(dev, LedAction); + break; + + case SW_LED_MODE9: + SwLedControlMode9(dev, LedAction); + break; + case SW_LED_MODE10: + SwLedControlMode10(dev, LedAction); + break; + + default: + break; + } +} + +#ifdef TO_DO_LIST +#ifdef NDIS50_MINIPORT +void LedBlinkTimerStallCheck(struct net_device *dev) +{ +} + + +void DoLedTimerStallCheck(PLED_8190 pLed) +{ +} +#endif +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_led.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_led.h @@ -0,0 +1,87 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef __INC_HAL8192SELED_H +#define __INC_HAL8192SELED_H + + + +typedef enum _LED_STATE_8190{ + LED_UNKNOWN = 0, + LED_ON = 1, + LED_OFF = 2, + LED_BLINK_NORMAL = 3, + LED_BLINK_SLOWLY = 4, + LED_POWER_ON_BLINK = 5, + LED_SCAN_BLINK = 6, + LED_NO_LINK_BLINK = 7, + LED_BLINK_StartToBlink = 8, + LED_BLINK_TXRX = 9, + LED_BLINK_RUNTOP = 10, + LED_BLINK_CAMEO = 11, +}LED_STATE_8190; + +typedef enum _LED_PIN_8190{ + LED_PIN_GPIO0, + LED_PIN_LED0, + LED_PIN_LED1 +}LED_PIN_8190; + +typedef struct _LED_8190{ + void * dev; + + LED_PIN_8190 LedPin; + + LED_STATE_8190 CurrLedState; + bool bLedOn; + + bool bLedBlinkInProgress; + + bool bLedSlowBlinkInProgress; + u32 BlinkTimes; + LED_STATE_8190 BlinkingLedState; + + struct timer_list BlinkTimer; +} LED_8190, *PLED_8190; + + + + +typedef enum _LED_STRATEGY_8190{ + SW_LED_MODE0, + SW_LED_MODE1, + SW_LED_MODE2, + SW_LED_MODE3, + SW_LED_MODE4, + SW_LED_MODE5, + SW_LED_MODE6, + SW_LED_MODE7, + SW_LED_MODE8, + SW_LED_MODE9, + SW_LED_MODE10, + HW_LED, +}LED_STRATEGY_8190, *PLED_STRATEGY_8190; + + +void SwLedOn(struct net_device *dev , PLED_8190 pLed); +void SwLedOff(struct net_device *dev, PLED_8190 pLed); +void InitSwLeds(struct net_device *dev); +void DeInitSwLeds(struct net_device *dev); +void LedControl8192SE(struct net_device *dev, LED_CTL_MODE LedAction); + +#endif /*__INC_HAL8190PCILED_H*/ --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_mp.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_mp.c @@ -0,0 +1,1253 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + +#ifdef CONFIG_MP +#include "../rtl_core.h" + +void rtl8192_init_mp(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + priv->chan_forced = false; + + priv->bSingleCarrier = false; + priv->RegBoard = 0; + priv->bCckContTx = false; + priv->bOfdmContTx = false; + priv->bStartContTx = false; + priv->RegPaModel = 0; + priv->btMpCckTxPower = 0; + priv->btMpOfdmTxPower = 0; +} + +static bool r8192_MgntIsRateValidForWirelessMode(u8 rate, u8 wirelessmode) +{ + bool bReturn = false; + + switch(wirelessmode) + { + case WIRELESS_MODE_A: + case WIRELESS_MODE_N_5G: + if((rate >= 12) && (rate <= 108) && (rate != 22) && (rate != 44)) + { + bReturn = true; + } + break; + + case WIRELESS_MODE_B: + if( ((rate <= 22) && (rate != 12) && (rate != 18)) || + (rate == 44) ) + { + bReturn = true; + } + break; + + case WIRELESS_MODE_G: + case WIRELESS_MODE_G | WIRELESS_MODE_B: + case WIRELESS_MODE_N_24G: + if((rate >= 2) && (rate <= 108)) + { + bReturn = true; + } + break; + + case WIRELESS_MODE_AUTO: + printk("MgntIsRateValidForWirelessMode(): wirelessmode should not be WIRELESS_MODE_AUTO\n"); + break; + + default: + printk("MgntIsRateValidForWirelessMode(): Unknown wirelessmode: %d\n", wirelessmode); + break; + } + + if(!bReturn) + { + if(wirelessmode&(WIRELESS_MODE_N_24G|WIRELESS_MODE_N_5G)) + { + if((rate>=0x80) && (rate<=MGN_MCS15_SG)) + bReturn = true; + } + } + return bReturn; +} + +inline u8 r8192_is_wireless_b_mode(u16 rate) +{ + if( ((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220) ) + return 1; + else return 0; +} + +static void r8192_XmitOnePacket(struct net_device* dev) +{ + struct r8192_priv* priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + struct sk_buff* skb = rtllib_get_beacon(ieee); + + if (unlikely(!skb)){ + printk("========>error alloc skb\n"); + return; + } + + priv->rtllib->softmac_data_hard_start_xmit(skb, dev, ieee->rate); +} + +int r8192_wx_mp_set_chan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + int ret = -1; + u8 channel; + + down(&priv->wx_sem); + + channel = *extra; + + rtllib_stop_scan(ieee); + + printk("####RTL819X MP####set channel[1-11] %d\n",channel); + + if((channel > 11) || (channel < 1)) { + up(&priv->wx_sem); + return ret; + } + + priv->rtllib->current_network.channel = channel; + priv->MptChannelToSw = channel; + + priv->chan_forced = false; + MPT_ProSwChannel(dev); + priv->chan_forced = true; + + ret = 0; + up(&priv->wx_sem); + + return ret; + +} + +int r8192_wx_mp_set_txrate(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device* ieee = priv->rtllib; + int ret = -1; + u32 data_rate_index = 0; + + down(&priv->wx_sem); + + data_rate_index = *extra; + + printk("####RTL819X MP####set tx rate index %d\n",data_rate_index); + + priv->MptRateIndex = data_rate_index; + + if((data_rate_index > 27) || (data_rate_index < 0)) { + up(&priv->wx_sem); + return ret; + } else if(data_rate_index <= 3) { + ieee->mode = WIRELESS_MODE_B; + } else if (data_rate_index <= 11) { + ieee->mode = WIRELESS_MODE_G; + } else { + ieee->mode = WIRELESS_MODE_N_24G; + } + + MPT_ProSetDataRate819x(dev); + + printk("####RTL819X MP####set tx rate %d\n",ieee->rate); + + ret = 0; + up(&priv->wx_sem); + + return ret; +} + +int r8192_wx_mp_set_txpower(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int ret = -1; + u8 power_index = 0; + + down(&priv->wx_sem); + + power_index = *extra; + + printk("####RTL819X MP####set tx power index %d\n",power_index); + + if((power_index > 0x3F) || (power_index < 0x00)) { + up(&priv->wx_sem); + return ret; + } + + mpt_ProSetTxPower(dev, power_index); + + ret = 0; + up(&priv->wx_sem); + + return ret; + +} + +int r8192_wx_mp_set_bw(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int ret = -1; + u8 bw_index = 0; + + down(&priv->wx_sem); + + bw_index = *extra; + + printk("####RTL819X MP####set bandwith index %d [0: 20MHz 1: 40MHz]\n",bw_index); + + priv->MptBandWidth = bw_index; + +#if 0 + if((bw_index > 1) || (bw_index < 0)) { + up(&priv->wx_sem); + return ret; + } else if(bw_index == 1) { + HTSetConnectBwMode(priv->rtllib, HT_CHANNEL_WIDTH_20_40, + (priv->rtllib->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + } else { + HTSetConnectBwMode(priv->rtllib, HT_CHANNEL_WIDTH_20, + (priv->rtllib->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + } +#else + MPT_ProSetBandWidth819x(dev); +#endif + + ret = 0; + up(&priv->wx_sem); + + return ret; + +} + + + +int r8192_wx_mp_set_txstart(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + int ret = -1; + u8 start_flag = 0; + + down(&priv->wx_sem); + + start_flag = *extra; + + if(start_flag == 1) { + if (priv->bCckContTx || priv->bOfdmContTx) { + printk("####RTL819X MP####continious Tx is undergoing, please close it first\n"); + ret = -EBUSY; + up(&priv->wx_sem); + return ret; + } + + if(r8192_is_wireless_b_mode(ieee->rate)) { + printk("####RTL819X MP####start cck continious TX, rate:%d\n", ieee->rate); + mpt_StartCckContTx(dev, true); + r8192_XmitOnePacket(dev); + } else { + printk("####RTL819X MP####start ofdm continious TX, rate:%d\n", ieee->rate); + mpt_StartOfdmContTx(dev); + r8192_XmitOnePacket(dev); + } + } else if(start_flag == 2) { + bool bCckContTx = priv->bCckContTx; + bool bOfdmContTx = priv->bOfdmContTx; + + if(bCckContTx && !bOfdmContTx) { + printk("####RTL819X MP####stop cck continious TX\n"); + mpt_StopCckCoNtTx(dev); + } else if (!bCckContTx && bOfdmContTx) { + printk("####RTL819X MP####stop ofdm continious TX\n"); + mpt_StopOfdmContTx(dev); + } else if(!bCckContTx && !bOfdmContTx) { + ; + } else { + printk("####RTL819X MP#### Unexpected case! bCckContTx: %d , bOfdmContTx: %d\n", + bCckContTx, bOfdmContTx); +} + } else { + ret = -1; + up(&priv->wx_sem); + return ret; + } + + + ret = 0; + up(&priv->wx_sem); + + return ret; + +} + +int r8192_wx_mp_set_singlecarrier(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + struct rtllib_device *ieee = priv->rtllib; + int ret = -1; + u8 start_flag = 0; + + if((ieee->rate > 108) || (ieee->rate < 12)) + printk("####RTL819X MP#### we did not do singlecarrier when rate not in [6M-54M] tmp, see StartTesting_SingleCarrierTx to get more\n"); + + down(&priv->wx_sem); + + start_flag = *extra; + + if(start_flag == 1){ + if (priv->bCckContTx || priv->bOfdmContTx || priv->bSingleCarrier){ + printk("####RTL819X MP#### single carrier continious Tx is undergoing, please close it first\n"); + ret = -EBUSY; + up(&priv->wx_sem); + return ret; + } + + printk("####RTL819X MP####start single carrier cck continious TX\n"); + mpt_StartOfdmContTx(dev); + r8192_XmitOnePacket(dev); + + } else if(start_flag == 2) { + if (priv->bCckContTx) { + printk("####RTL819X MP####stop single cck continious TX\n"); + mpt_StopCckCoNtTx(dev); + } + if (priv->bOfdmContTx) { + printk("####RTL819X MP####stop single ofdm continious TX\n"); + mpt_StopOfdmContTx(dev); + } + if (priv->bSingleCarrier) { + printk("####RTL819X MP####stop single carrier mode\n"); + MPT_ProSetSingleCarrier(dev, false); + } + } else { + ret = -1; + up(&priv->wx_sem); + + return ret; + } + + ret = 0; + up(&priv->wx_sem); + + return ret; + +} +int r8192_wx_mp_write_rf(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 ulIoType, INulRegOffset, INulRegValue; + u32 *info_buf = (u32*)(&wrqu->freq.m); + u32 ulRegOffset = info_buf[0]; + u32 ulRegValue = info_buf[1]; + u32 RF_PATH = info_buf[2]; + + down(&priv->wx_sem); + printk("####RTL819X MP####%s :ulRegOffset %x, ulRegValue %x, RF_PATH:%x\n", + __func__, ulRegOffset, ulRegValue, RF_PATH); + + ulIoType = MPT_WRITE_RF; + INulRegOffset = ulRegOffset & bRFRegOffsetMask; + INulRegValue = ulRegValue & bRFRegOffsetMask; + + + priv->MptIoOffset = INulRegOffset; + priv->MptIoValue = INulRegValue; + priv->MptRfPath = RF_PATH; + priv->MptActType = ulIoType; + + mpt_Pro819xIoCallback(dev); + + up(&priv->wx_sem); + return 0; + +} + +int r8192_wx_mp_write_mac(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 *info_buf = (u32*)(&wrqu->freq.m); + u32 ulRegOffset = info_buf[0]; + u32 ulRegValue = info_buf[1]; + u32 ulRegDataWidth = info_buf[2]; + u32 ulIoType = 0; + + down(&priv->wx_sem); + + printk("####RTL819X MP####%s :ulRegOffset %x, ulRegValue %x, ulRegDataWidth:%x\n", + __func__, ulRegOffset, ulRegValue, ulRegDataWidth); + + switch(ulRegDataWidth) + { + case 1: + ulIoType = MPT_WRITE_MAC_1BYTE; + break; + + case 2: + ulIoType = MPT_WRITE_MAC_2BYTE; + break; + case 4: + ulIoType = MPT_WRITE_MAC_4BYTE; + break; + default: + printk("####RTL819X MP####%s :error ulRegDataWidth:%x\n", __func__, ulRegDataWidth); + break; + } + + if(ulIoType != 0){ + priv->MptIoOffset = ulRegOffset; + priv->MptIoValue = ulRegValue; + priv->MptActType = ulIoType; + mpt_Pro819xIoCallback(dev); + } + + up(&priv->wx_sem); + + return 0; + +} + +/*----------------------------------------------------------------------------- + * Function: mpt_StartCckContTx() + * + * Overview: Start CCK Continuous Tx. + * + * Input: PADAPTER pAdapter + * BOOLEAN bScrambleOn + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/16/2007 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +void mpt_StartCckContTx(struct net_device *dev,bool bScrambleOn) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u32 cckrate; + + if(!rtl8192_QueryBBReg(dev, rFPGA0_RFMOD, bCCKEn)) + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, bEnable); + + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMContinueTx, bDisable); + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable); + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleTone, bDisable); + switch(priv->rtllib->rate) + { + case 2: + cckrate = 0; + break; + case 4: + cckrate = 1; + break; + case 11: + cckrate = 2; + break; + case 22: + cckrate = 3; + break; + default: + cckrate = 0; + break; + } + rtl8192_setBBreg(dev, rCCK0_System, bCCKTxRate, cckrate); + + rtl8192_setBBreg(dev, rCCK0_System, bCCKBBMode, 0x2); + rtl8192_setBBreg(dev, rCCK0_System, bCCKScramble, 0x1); + + priv->bCckContTx = true; + priv->bOfdmContTx = false; + +} /* mpt_StartCckContTx */ + +/*----------------------------------------------------------------------------- + * Function: mpt_StartOfdmContTx() + * + * Overview: Start OFDM Continuous Tx. + * + * Input: PADAPTER pAdapter + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/16/2007 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +void mpt_StartOfdmContTx(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + if(!rtl8192_QueryBBReg(dev, rFPGA0_RFMOD, bOFDMEn)) + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, bEnable); + + rtl8192_setBBreg(dev, rCCK0_System, bCCKBBMode, bDisable); + + rtl8192_setBBreg(dev, rCCK0_System, bCCKScramble, bEnable); + + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMContinueTx, bEnable); + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable); + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleTone, bDisable); + + priv->bCckContTx = false; + priv->bOfdmContTx = true; + +} /* mpt_StartOfdmContTx */ + +/*----------------------------------------------------------------------------- + * Function: mpt_StopCckCoNtTx() + * + * Overview: Stop CCK Continuous Tx. + * + * Input: PADAPTER pAdapter + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/16/2007 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +void mpt_StopCckCoNtTx(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + priv->bCckContTx = false; + priv->bOfdmContTx = false; + + rtl8192_setBBreg(dev, rCCK0_System, bCCKBBMode, 0x0); + rtl8192_setBBreg(dev, rCCK0_System, bCCKScramble, 0x1); + + rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x0); + rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x1); + +} /* mpt_StopCckCoNtTx */ + +/*----------------------------------------------------------------------------- + * Function: mpt_StopOfdmContTx() + * + * Overview: Stop 818xB OFDM Continuous Tx. + * + * Input: PADAPTER pAdapter + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/16/2007 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +void mpt_StopOfdmContTx(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + priv->bCckContTx = false; + priv->bOfdmContTx = false; + + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMContinueTx, bDisable); + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable); + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleTone, bDisable); + mdelay(10); + rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x0); + rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x1); + +} /* mpt_StopOfdmContTx */ + +/*----------------------------------------------------------------------------- + * Function: mpt_SwitchRfSetting92S + * + * Overview: Change RF Setting when we siwthc channel/rate/BW for 92S series MP. + * + * Input: IN PADAPTER pAdapter + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 01/08/2009 MHC Suggestion from SD3 Willis for 92S series. + * 01/09/2009 MHC Add CCK modification for 40MHZ. Suggestion from SD3. + * + *---------------------------------------------------------------------------*/ + void mpt_SwitchRfSetting92S(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u8 ChannelToSw = priv->MptChannelToSw; + u32 ulRateIdx = priv->MptRateIndex; + u32 ulbandwidth = priv->MptBandWidth; + + if (ulbandwidth == BAND_20MHZ_MODE) + { + if (ChannelToSw == 1) + { + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0A8F4); + } + else if (ChannelToSw == 11) + { + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0F8F5); + } + else + { + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0F8F4); + } + } + else + { + if (ChannelToSw == 3) + { + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0A8F4); + } + else if (ChannelToSw == 9 || ChannelToSw == 10 || ChannelToSw == 11) + { + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0F8F5); + } + else + { + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_IPA, 0xFFFFF, 0x0F8F4); + } + } + + + if (ulRateIdx < MPT_RATE_6M) + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_SYN_G2, 0xFFFFF, 0x04440); + else + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)0, RF_SYN_G2, 0xFFFFF, 0x0F200); +} + +/*----------------------------------------------------------------------------- + * Function: mpt_ProSetTxPower() + * + * Overview: Change Tx Power of current channel for + * OID_RT_PRO_SET_TX_POWER_CONTROL. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/16/2007 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +bool mpt_ProSetTxPower( struct net_device *dev, u32 ulTxPower) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u8 CurrChannel = priv->rtllib->current_network.channel; + bool bResult = true; + + CurrChannel = priv->MptChannelToSw; + + if(CurrChannel > 11 || CurrChannel < 1) + { + printk("mpt_ProSetTxPower(): CurrentChannel:%d is not valid\n", CurrChannel); + return false; + } + + if(ulTxPower > MAX_TX_PWR_INDEX_N_MODE) + { + printk("mpt_ProSetTxPower(): TxPWR:%d is invalid\n", ulTxPower); + return false; + } + + if( priv->MptRateIndex >= MPT_RATE_1M && + priv->MptRateIndex <= MPT_RATE_11M ) + { + priv->TxPowerLevelCCK[CurrChannel-1] = (u8)ulTxPower; + + priv->RfTxPwrLevelCck[0][CurrChannel-1] = (u8)ulTxPower; + } + else if(priv->MptRateIndex >= MPT_RATE_6M && + priv->MptRateIndex <= MPT_RATE_MCS15 ) + { + priv->TxPowerLevelOFDM24G[CurrChannel-1] = (u8)ulTxPower; + + priv->RfTxPwrLevelOfdm1T[0][CurrChannel-1] = (u8)ulTxPower; + priv->RfTxPwrLevelOfdm2T[0][CurrChannel-1] = (u8)ulTxPower; + } + + rtl8192_phy_setTxPower(dev,CurrChannel); + + return bResult; + +} /* mpt_ProSetTxPower */ + +/*----------------------------------------------------------------------------- + * Function: mpt_ProSetTxAGCOffset() + * + * Overview: Change Tx AGC Offset + * OID_RT_PRO_SET_TX_AGC_OFFSET. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 08/09/2007 Cosa Create Version 0. + * + *---------------------------------------------------------------------------*/ +bool mpt_ProSetTxAGCOffset(struct net_device *dev, u32 ulTxAGCOffset) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + bool bResult = true; + u32 TxAGCOffset_B, TxAGCOffset_C, TxAGCOffset_D; + + TxAGCOffset_B = (ulTxAGCOffset&0x000000ff); + TxAGCOffset_C = ((ulTxAGCOffset&0x0000ff00)>>8); + TxAGCOffset_D = ((ulTxAGCOffset&0x00ff0000)>>16); + + if( TxAGCOffset_B > TxAGC_Offset_neg1 || + TxAGCOffset_C > TxAGC_Offset_neg1 || + TxAGCOffset_D > TxAGC_Offset_neg1 ) + { + printk("mpt_ProSetTxAGCOffset(): TxAGCOffset:%d is invalid\n", ulTxAGCOffset); + return false; + } + + priv->AntennaTxPwDiff[0] = TxAGCOffset_B; + priv->AntennaTxPwDiff[1] = TxAGCOffset_C; + priv->AntennaTxPwDiff[2] = TxAGCOffset_D; + + MPT_ProSetTxAGCOffset(dev); + + return bResult; + +} /* mpt_ProSetTxPower */ + +/*----------------------------------------------------------------------------- + * Function: mpt_ProSetTxAGCOffset() + * + * Overview: Change Tx AGC Offset + * OID_RT_PRO_SET_TX_AGC_OFFSET. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 08/09/2007 Cosa Create Version 0. + * + *---------------------------------------------------------------------------*/ +bool mpt_ProSetRxFilter(struct net_device *dev, u32 RCRMode) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + if(RCRMode == 1) + { + priv->MptRCR &= ~(RCR_AAP|RCR_AM|RCR_AB); + priv->MptRCR |= RCR_APM; + write_nic_dword(dev, RCR, priv->MptRCR); + } + else + { + priv->MptRCR |= (RCR_AAP|RCR_APM|RCR_AM|RCR_AB); + write_nic_dword(dev, RCR, priv->MptRCR); + } + + return 1; +} /* mpt_ProSetTxPower */ + +/*----------------------------------------------------------------------------- + * Function: mpt_ProSetModulation() + * + * Overview: Switch wireless mode for OID_RT_PRO_SET_MODULATION. + * + * Input: PADAPTER pAdapter + * ULONG ulWirelessMode + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/16/2007 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +bool mpt_ProSetModulation(struct net_device *dev, u32 ulWirelessMode) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + WIRELESS_MODE WirelessMode; + bool bResult = false; + + switch(ulWirelessMode) + { + case WIRELESS_MODE_A: + WirelessMode = WIRELESS_MODE_A; + break; + + case WIRELESS_MODE_B: + WirelessMode = WIRELESS_MODE_B; + break; + + case WIRELESS_MODE_G: + case WIRELESS_MODE_G |WIRELESS_MODE_B: + WirelessMode = WIRELESS_MODE_G; + break; + + case WIRELESS_MODE_N_24G: + WirelessMode = WIRELESS_MODE_N_24G; + break; + + case WIRELESS_MODE_N_5G: + WirelessMode = WIRELESS_MODE_N_5G; + break; + + case WIRELESS_MODE_AUTO: + default: + bResult = false; + return bResult; + break; + } + + priv->rtllib->mode = WirelessMode; + priv->RegWirelessMode = WirelessMode; + rtl8192_SetWirelessMode(dev, priv->rtllib->mode); + HTUseDefaultSetting(priv->rtllib); + + + if (IS_HARDWARE_TYPE_8192SE(dev)) + { + mpt_SwitchRfSetting92S(dev); + } + + bResult = true; + + return bResult; + +} + +/*----------------------------------------------------------------------------- + * Function: mpt_Pro819xIoCallback() + * + * Overview: Callback function of a workitem for IO. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/16/2007 MHC Create Version 0. + * + *---------------------------------------------------------------------------*/ +void mpt_Pro819xIoCallback(struct net_device *dev) +{ + + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u32 MptActType = priv->MptActType; + + printk("####RTL819X MP####%s :ulRegOffset %x, ulRegValue %x, MptActType:%x, MptRfPath:%x\n", + __func__, priv->MptIoOffset, priv->MptIoValue, MptActType, priv->MptRfPath); + + switch(MptActType) + { + case MPT_WRITE_MAC_1BYTE: + write_nic_byte(dev, priv->MptIoOffset, (u8)(priv->MptIoValue)); + break; + + case MPT_WRITE_MAC_2BYTE: + write_nic_word(dev, priv->MptIoOffset, (u16)(priv->MptIoValue)); + break; + + case MPT_WRITE_MAC_4BYTE: + write_nic_dword(dev, priv->MptIoOffset, (u32)(priv->MptIoValue)); + break; + + case MPT_WRITE_RF: + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)priv->MptRfPath, + priv->MptIoOffset, bRFRegOffsetMask, priv->MptIoValue); + break; + + default: + break; + } +} + +void MPT_ProSetSingleCarrier(struct net_device *dev, bool ulMode) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + + if(ulMode == 1) { + priv->bSingleCarrier = true; + } else { + priv->bSingleCarrier = false; + } + + if(priv->bSingleCarrier) + { + if(!rtl8192_QueryBBReg(dev, rFPGA0_RFMOD, bOFDMEn)) + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, bEnable); + + rtl8192_setBBreg(dev, rCCK0_System, bCCKBBMode, bDisable); + + rtl8192_setBBreg(dev, rCCK0_System, bCCKScramble, bEnable); + + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMContinueTx, bDisable); + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleCarrier, bEnable); + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleTone, bDisable); + } + else + { + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMContinueTx, bDisable); + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable); + rtl8192_setBBreg(dev, rOFDM1_LSTF, bOFDMSingleTone, bDisable); + mdelay(10); + rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x0); + rtl8192_setBBreg(dev, rPMAC_Reset, bBBResetB, 0x1); + } +} + +/*----------------------------------------------------------------------------- + * Function: MPT_ProSetBandWidth819x() + * + * Overview: None + * + * Input: PADAPTER pAdapter + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 01/03/2007 Cosa Create Version 0. + * + *---------------------------------------------------------------------------*/ +void MPT_ProSetBandWidth819x(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + PRT_HIGH_THROUGHPUT pHTInfo = priv->rtllib->pHTInfo; + u32 ulbandwidth = priv->MptBandWidth; + + printk("##################MPT_ProSetBandWidth819x() is start. \n"); + /* 2007/06/07 MH Call normal driver API and set 40MHZ mode. */ + if (ulbandwidth == BAND_20MHZ_MODE) { + /* 20 MHZ sub-carrier mode --> dont care. */ + pHTInfo->bCurBW40MHz = false; + pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT; + priv->rtllib->SetBWModeHandler(dev, HT_CHANNEL_WIDTH_20, pHTInfo->CurSTAExtChnlOffset); + } else if (ulbandwidth == BAND_40MHZ_DUPLICATE_MODE) { + /* Sub-Carrier mode is defined in MAC data sheet chapter 12.3. */ + /* 40MHX sub-carrier mode --> duplicate. */ + pHTInfo->bCurBW40MHz = true; + pHTInfo->bCurTxBW40MHz = true; + pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_DEF; + + priv->rtllib->SetBWModeHandler(dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset); + } else if (ulbandwidth == BAND_40MHZ_LOWER_MODE) { + /* 40MHX sub-carrier mode --> lower mode */ + pHTInfo->bCurBW40MHz = true; + pHTInfo->bCurTxBW40MHz = true; + pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_LOWER; + + /* Extention channel is lower. Current channel must > 3. */ + /*if (pMgntInfo->dot11CurrentChannelNumber < 3) + DbgPrint("Illegal Current_Chl=%d\r\n", pMgntInfo->dot11CurrentChannelNumber); + else + pAdapter->HalFunc.SwChnlByTimerHandler(pAdapter, pMgntInfo->dot11CurrentChannelNumber-2);*/ + + priv->rtllib->SetBWModeHandler(dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset); + } else if (ulbandwidth == BAND_40MHZ_UPPER_MODE) { + /* 40MHX sub-carrier mode --> upper mode */ + pHTInfo->bCurBW40MHz = true; + pHTInfo->bCurTxBW40MHz = true; + pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_UPPER; + + /* Extention channel is upper. Current channel must < 12. */ + /*if (pMgntInfo->dot11CurrentChannelNumber > 12) + DbgPrint("Illegal Current_Chl=%d", pMgntInfo->dot11CurrentChannelNumber); + else + pAdapter->HalFunc.SwChnlByTimerHandler(pAdapter, pMgntInfo->dot11CurrentChannelNumber+2);*/ + + priv->rtllib->SetBWModeHandler(dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset); + } else if (ulbandwidth == BAND_40MHZ_DONTCARE_MODE) { + /* 40MHX sub-carrier mode --> dont care mode */ + pHTInfo->bCurBW40MHz = true; + pHTInfo->bCurTxBW40MHz = true; + pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_LOWER; + + priv->rtllib->SetBWModeHandler(dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset); + } else { + printk("##################MPT_ProSetBandWidth819x() error BW. \n"); + return; + } + +{ + mpt_SwitchRfSetting92S(dev); + return; + } + + printk("##################MPT_ProSetBandWidth819x() is finished. \n"); +} + +/*----------------------------------------------------------------------------- + * Function: MPT_ProSwChannel() + * + * Overview: Callback function of a work item to switch channel for + * OID_RT_PRO_SET_CHANNEL_DIRECT_CALL + * + * Input: PVOID Context + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 05/16/2007 MHC Create Version 0. + * 06/07/2007 MHC Normal driver change switch channel handler. + * 09/03/2008 MHC RF channel register for 92S. + * 01/08/2008 MHC For MP verification for 92S,weneed to change setting according + * to SD3 Willis's document. + * + *---------------------------------------------------------------------------*/ +void MPT_ProSwChannel(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u8 ChannelToSw = priv->MptChannelToSw; + u8 eRFPath; + + priv->rtllib->current_network.channel = ChannelToSw; + priv->MptChannelToSw = ChannelToSw; + + if (IS_HARDWARE_TYPE_8192SE(dev)) + { + for(eRFPath = 0; eRFPath NumTotalRFPath; eRFPath++) + { + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rRfChannel, 0x3FF, ChannelToSw); + } + + if (IS_HARDWARE_TYPE_8192SE(dev)) + { + mpt_SwitchRfSetting92S(dev); + } + } + +#ifdef MP_DEVELOP_READY + for(eRFPath = 0; eRFPath NumTotalRFPath; eRFPath++) + { + if (IS_HARDWARE_TYPE_8192SE(dev)) + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rRfChannel, 0x3FF, ChannelToSw); + + udelay(100); + } + + + for(eRFPath = 0; eRFPath NumTotalRFPath; eRFPath++) + { + if (IS_HARDWARE_TYPE_8192SE(dev)) + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rRfChannel, 0x3FF, ChannelToSw); + + udelay(100); + } +#endif + + /* 2007/06/07 MH Normal driver change sw channel handler. It does not + support SwChnlByDelayHandler ans replace with SwChnlByTimerHandler. */ + priv->rtllib->set_chan(dev, ChannelToSw); + +#if 0 + if(pHalData->CurrentChannel == 14 && !pHalData->bCCKinCH14){ + pHalData->bCCKinCH14 = true; + MPT_CCKTxPowerAdjust(pAdapter,pHalData->bCCKinCH14); + } + else if(pHalData->CurrentChannel != 14 && pHalData->bCCKinCH14){ + pHalData->bCCKinCH14 = false; + MPT_CCKTxPowerAdjust(pAdapter,pHalData->bCCKinCH14); + } +#endif +} /* MPT_ProSwChannel */ + +/*----------------------------------------------------------------------------- + * Function: MPT_ProSetDataRate819x() + * + * Overview: None + * + * Input: PADAPTER pAdapter + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 01/03/2007 Cosa Create Version 0. + * + *---------------------------------------------------------------------------*/ +void MPT_ProSetDataRate819x(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u8 DataRate = 0xFF; + u32 ulRateIdx = priv->MptRateIndex; + + + printk("################MPT_ProSetDataRate819x():Rate=%d\n", ulRateIdx); + switch(ulRateIdx) + { + /* CCK rate. */ + case MPT_RATE_1M: DataRate = 2; break; + case MPT_RATE_2M: DataRate = 4; break; + case MPT_RATE_55M: DataRate = 11; break; + case MPT_RATE_11M: DataRate = 22; break; + + /* OFDM rate. */ + case MPT_RATE_6M: DataRate = 12; break; + case MPT_RATE_9M: DataRate = 18; break; + case MPT_RATE_12M: DataRate = 24; break; + case MPT_RATE_18M: DataRate = 36; break; + case MPT_RATE_24M: DataRate = 48; break; + case MPT_RATE_36M: DataRate = 72; break; + case MPT_RATE_48M: DataRate = 96; break; + case MPT_RATE_54M: DataRate = 108; break; + + /* HT rate. */ + case MPT_RATE_MCS0: DataRate = 0x80; break; + case MPT_RATE_MCS1: DataRate = 0x81; break; + case MPT_RATE_MCS2: DataRate = 0x82; break; + case MPT_RATE_MCS3: DataRate = 0x83; break; + case MPT_RATE_MCS4: DataRate = 0x84; break; + case MPT_RATE_MCS5: DataRate = 0x85; break; + case MPT_RATE_MCS6: DataRate = 0x86; break; + case MPT_RATE_MCS7: DataRate = 0x87; break; + case MPT_RATE_MCS8: DataRate = 0x88; break; + case MPT_RATE_MCS9: DataRate = 0x89; break; + case MPT_RATE_MCS10: DataRate = 0x8A; break; + case MPT_RATE_MCS11: DataRate = 0x8B; break; + case MPT_RATE_MCS12: DataRate = 0x8C; break; + case MPT_RATE_MCS13: DataRate = 0x8D; break; + case MPT_RATE_MCS14: DataRate = 0x8E; break; + case MPT_RATE_MCS15: DataRate = 0x8F; break; + case MPT_RATE_LAST: + break; + + default: + break; + } + + { + mpt_SwitchRfSetting92S(dev); + } + +#ifdef MP_DEVELOP_READY + if (IS_HARDWARE_TYPE_8192SE(dev)) + { + for(eRFPath = 0; eRFPath NumTotalRFPath; eRFPath++) + { + if (ulbandwidth == BAND_20MHZ_MODE) + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rRfChannel, (BIT11|BIT10), 0x01); + else + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, rRfChannel, (BIT11|BIT10), 0x00); + + delay_us(100); + } + } +#endif + + + if(!r8192_MgntIsRateValidForWirelessMode(DataRate, priv->rtllib->mode) && DataRate != 0 ) + { + printk("[MPT]: unknow wmode=%d", priv->rtllib->mode); + } + if (DataRate != 0xFF) + { + printk("[MPT]: Force rate=0x%02x", DataRate); + priv->rtllib->rate = (int)DataRate; + } + +} + +/*----------------------------------------------------------------------------- + * Function: MPT_ProSetTxAGCOffset() + * + * Overview: Set Tx power level for + * OID_RT_PRO_SET_TX_AGC_OFFSET + * + * Input: PVOID Context + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 08/09/2007 Cosa Create Version 0. + * + *---------------------------------------------------------------------------*/ +void MPT_ProSetTxAGCOffset(struct net_device *dev) +{ + struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev); + u32 u4RegValue, TxAGCOffset_B, TxAGCOffset_C, TxAGCOffset_D; + + TxAGCOffset_B = priv->AntennaTxPwDiff[0]; + TxAGCOffset_C = priv->AntennaTxPwDiff[1]; + TxAGCOffset_D = priv->AntennaTxPwDiff[2]; + + + u4RegValue = (TxAGCOffset_D<<8 | TxAGCOffset_C<<4 | TxAGCOffset_B); + rtl8192_setBBreg(dev, rFPGA0_TxGainStage, (bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue); + printk("##################MPT_ProSetTxAGCOffset() is finished \n"); +} + +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_mp.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_mp.h @@ -0,0 +1,185 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + +#ifndef __INC_HAL8192S_MP_H +#define __INC_HAL8192S_MP_H + +/*--------------------------Define Parameters-------------------------------*/ + +#define MPT_NOOP 0 +#define MPT_READ_MAC_1BYTE 1 +#define MPT_READ_MAC_2BYTE 2 +#define MPT_READ_MAC_4BYTE 3 +#define MPT_WRITE_MAC_1BYTE 4 +#define MPT_WRITE_MAC_2BYTE 5 +#define MPT_WRITE_MAC_4BYTE 6 +#define MPT_READ_BB_CCK 7 +#define MPT_WRITE_BB_CCK 8 +#define MPT_READ_BB_OFDM 9 +#define MPT_WRITE_BB_OFDM 10 +#define MPT_READ_RF 11 +#define MPT_WRITE_RF 12 +#define MPT_READ_EEPROM_1BYTE 13 +#define MPT_WRITE_EEPROM_1BYTE 14 +#define MPT_READ_EEPROM_2BYTE 15 +#define MPT_WRITE_EEPROM_2BYTE 16 +#define MPT_SET_CSTHRESHOLD 21 +#define MPT_SET_INITGAIN 22 +#define MPT_SWITCH_BAND 23 +#define MPT_SWITCH_CHANNEL 24 +#define MPT_SET_DATARATE 25 +#define MPT_SWITCH_ANTENNA 26 +#define MPT_SET_TX_POWER 27 +#define MPT_SET_CONT_TX 28 +#define MPT_SET_SINGLE_CARRIER 29 +#define MPT_SET_CARRIER_SUPPRESSION 30 + +#define MPT_SET_ANTENNA_GAIN_OFFSET 40 +#define MPT_SET_CRYSTAL_CAP 41 +#define MPT_TRIGGER_RF_THERMAL_METER 42 +#define MPT_SET_SINGLE_TONE 43 +#define MPT_READ_RF_THERMAL_METER 44 +#define MPT_SWITCH_BAND_WIDTH 45 +#define MPT_QUERY_TSSI_VALUE 46 +#define MPT_SET_TX_POWER_ADJUST 47 +#define MPT_DO_TX_POWER_TRACK 48 +#define MPT_QUERY_NIC_TYPE 49 +#define MPT_QUERY_WPS_PUSHED 50 +#define MPT_SET_LED_CONTROL 51 +#define MPT_TX_POWER_TRACK_CONTROL 52 + +#define MPT_WRITE_EFUSE_1BYTE 53 +#define MPT_READ_EFUSE_1BYTE 54 +#define MPT_READ_EFUSE_2BYTE 55 +#define MPT_READ_EFUSE_4BYTE 56 +#define MPT_UPDATE_EFUSE 57 +#define MPT_UPDATE_EFUSE_UTILIZE 58 +#define MPT_UPDATE_AUTOLOAD_STS 59 + +#define MAX_TX_PWR_INDEX_N_MODE 64 +/*--------------------------Define Parameters-------------------------------*/ + +/*------------------------------Define structure----------------------------*/ +/* MP set force data rate base on the definition. */ +typedef enum _MPT_RATE_INDEX{ + /* CCK rate. */ + MPT_RATE_1M = 1, + MPT_RATE_2M, + MPT_RATE_55M, + MPT_RATE_11M, + + /* OFDM rate. */ + MPT_RATE_6M, + MPT_RATE_9M, + MPT_RATE_12M, + MPT_RATE_18M, + MPT_RATE_24M, + MPT_RATE_36M, + MPT_RATE_48M, + MPT_RATE_54M, + + /* HT rate. */ + MPT_RATE_MCS0, + MPT_RATE_MCS1, + MPT_RATE_MCS2, + MPT_RATE_MCS3, + MPT_RATE_MCS4, + MPT_RATE_MCS5, + MPT_RATE_MCS6, + MPT_RATE_MCS7, + MPT_RATE_MCS8, + MPT_RATE_MCS9, + MPT_RATE_MCS10, + MPT_RATE_MCS11, + MPT_RATE_MCS12, + MPT_RATE_MCS13, + MPT_RATE_MCS14, + MPT_RATE_MCS15, + MPT_RATE_LAST + +}MPT_RATE_E, *PMPT_RATE_E; + +typedef enum _MPT_Bandwidth_Switch_Mode{ + BAND_20MHZ_MODE = 0, + BAND_40MHZ_DUPLICATE_MODE = 1, + BAND_40MHZ_LOWER_MODE = 2, + BAND_40MHZ_UPPER_MODE = 3, + BAND_40MHZ_DONTCARE_MODE = 4 +}MPT_BANDWIDTH_MODE_E, *PMPT_BANDWIDTH_MODE_E; + +typedef enum _TxAGC_Offset{ + TxAGC_Offset_0 = 0x00, + TxAGC_Offset_1, + TxAGC_Offset_2, + TxAGC_Offset_3, + TxAGC_Offset_4, + TxAGC_Offset_5, + TxAGC_Offset_6, + TxAGC_Offset_7, + TxAGC_Offset_neg8, + TxAGC_Offset_neg7, + TxAGC_Offset_neg6, + TxAGC_Offset_neg5, + TxAGC_Offset_neg4, + TxAGC_Offset_neg3, + TxAGC_Offset_neg2, + TxAGC_Offset_neg1 +} TxAGC_Offset; +/*------------------------------Define structure----------------------------*/ +void rtl8192_init_mp(struct net_device* dev); +int r8192_wx_mp_set_chan(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +int r8192_wx_mp_set_txrate(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +int r8192_wx_mp_set_txpower(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +int r8192_wx_mp_set_bw(struct net_device *dev,struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +int r8192_wx_mp_set_txstart(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +int r8192_wx_mp_set_singlecarrier(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +int r8192_wx_mp_write_rf(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +int r8192_wx_mp_write_mac(struct net_device *dev, struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +void mpt_StartCckContTx(struct net_device *dev,bool bScrambleOn); +void mpt_StartOfdmContTx(struct net_device *dev); +void mpt_StopCckCoNtTx(struct net_device *dev); +void mpt_StopOfdmContTx(struct net_device *dev); +void mpt_SwitchRfSetting92S(struct net_device *dev); +bool mpt_ProSetTxPower( struct net_device *dev, u32 ulTxPower); +bool mpt_ProSetTxAGCOffset(struct net_device *dev, u32 ulTxAGCOffset); +bool mpt_ProSetRxFilter(struct net_device *dev, u32 RCRMode); +bool mpt_ProSetRxFilter(struct net_device *dev, u32 RCRMode); +bool mpt_ProSetModulation(struct net_device *dev, u32 ulWirelessMode); +void mpt_Pro819xIoCallback(struct net_device *dev); +void MPT_ProSetSingleCarrier(struct net_device *dev, bool ulMode); +void MPT_ProSetBandWidth819x(struct net_device *dev); +void MPT_ProSwChannel(struct net_device *dev); +void MPT_ProSetDataRate819x(struct net_device *dev); +void MPT_ProSetTxAGCOffset(struct net_device *dev); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_phy.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_phy.c @@ -0,0 +1,3480 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifdef RTL8192SE + +#include "../rtl_core.h" +#include "../rtl_dm.h" + +#ifdef ENABLE_DOT11D +#include "../rtllib/dot11d.h" +#endif + +/*---------------------------Define Local Constant---------------------------*/ +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 + +#define MAX_DOZE_WAITING_TIMES_9x 64 + +#define PHY_STOP_SWITCH_CLKREQ 0 +/*---------------------------Define Local Constant---------------------------*/ + +/*------------------------Define global variable-----------------------------*/ + +#define Rtl819XMAC_Array Rtl8192SEMAC_2T_Array +#define Rtl819XAGCTAB_Array Rtl8192SEAGCTAB_Array +#define Rtl819XPHY_REG_Array Rtl8192SEPHY_REG_2T2RArray +#define Rtl819XPHY_REG_to1T1R_Array Rtl8192SEPHY_ChangeTo_1T1RArray +#define Rtl819XPHY_REG_to1T2R_Array Rtl8192SEPHY_ChangeTo_1T2RArray +#define Rtl819XPHY_REG_to2T2R_Array Rtl8192SEPHY_ChangeTo_2T2RArray +#define Rtl819XPHY_REG_Array_PG Rtl8192SEPHY_REG_Array_PG +#define Rtl819XRadioA_Array Rtl8192SERadioA_1T_Array +#define Rtl819XRadioB_Array Rtl8192SERadioB_Array +#define Rtl819XRadioB_GM_Array Rtl8192SERadioB_GM_Array +#define Rtl819XRadioA_to1T_Array Rtl8192SERadioA_to1T_Array +#define Rtl819XRadioA_to2T_Array Rtl8192SERadioA_to2T_Array + +/*------------------------Define local variable------------------------------*/ +#if 0 +static u32 RF_CHANNEL_TABLE_ZEBRA[]={ + 0, + 0x085c, + 0x08dc, + 0x095c, + 0x09dc, + 0x0a5c, + 0x0adc, + 0x0b5c, + 0x0bdc, + 0x0c5c, + 0x0cdc, + 0x0d5c, + 0x0ddc, + 0x0e5c, + 0x0f72, +}; +#endif + +/*------------------------Define local variable------------------------------*/ + + +/*--------------------Define export function prototype-----------------------*/ +/*--------------------Define export function prototype-----------------------*/ + + +/*---------------------Define local function prototype-----------------------*/ + +static u32 phy_FwRFSerialRead( struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset); +static void phy_FwRFSerialWrite( struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data); + +static u32 phy_RFSerialRead(struct net_device* dev,RF90_RADIO_PATH_E eRFPath,u32 Offset); +static void phy_RFSerialWrite( struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data); +static u32 phy_CalculateBitShift(u32 BitMask); +static bool phy_BB8190_Config_HardCode(struct net_device* dev); +static bool phy_BB8192S_Config_ParaFile(struct net_device* dev); + +static bool phy_ConfigMACWithHeaderFile(struct net_device* dev); + +static bool phy_ConfigBBWithHeaderFile(struct net_device* dev,u8 ConfigType); + +static bool phy_ConfigBBWithPgHeaderFile(struct net_device* dev,u8 ConfigType); + +static bool phy_SetBBtoDiffRFWithHeaderFile(struct net_device* dev,u8 ConfigType); + +static void phy_InitBBRFRegisterDefinition(struct net_device* dev); +static bool phy_SetSwChnlCmdArray( SwChnlCmd* CmdTable, + u32 CmdTableIdx, + u32 CmdTableSz, + SwChnlCmdID CmdID, + u32 Para1, + u32 Para2, + u32 msDelay ); + +static bool phy_SwChnlStepByStep( + struct net_device* dev, + u8 channel, + u8 *stage, + u8 *step, + u32 *delay + ); + +static void phy_FinishSwChnlNow(struct net_device* dev,u8 channel); + +static u8 phy_DbmToTxPwrIdx( struct net_device* dev, WIRELESS_MODE WirelessMode, long PowerInDbm); +static bool phy_SetRFPowerState8192SE(struct net_device* dev,RT_RF_POWER_STATE eRFPowerState); +static void phy_CheckEphySwitchReady( struct net_device* dev); + +static long phy_TxPwrIdxToDbm( struct net_device* dev, WIRELESS_MODE WirelessMode, u8 TxPwrIdx); +void rtl8192_SetFwCmdIOCallback(struct net_device* dev); + + +/*---------------------Define local function prototype-----------------------*/ + + +/*----------------------------Function Body----------------------------------*/ +u32 rtl8192_QueryBBReg(struct net_device* dev, u32 RegAddr, u32 BitMask) +{ + + u32 ReturnValue = 0, OriginalValue, BitShift; + +#if (DISABLE_BB_RF == 1) + return 0; +#endif + + RT_TRACE(COMP_RF, "--->PHY_QueryBBReg(): RegAddr(%#x), BitMask(%#x)\n", RegAddr, BitMask); + + OriginalValue = read_nic_dword(dev, RegAddr); + + BitShift = phy_CalculateBitShift(BitMask); + ReturnValue = (OriginalValue & BitMask) >> BitShift; + + RT_TRACE(COMP_RF, "<---PHY_QueryBBReg(): RegAddr(%#x), BitMask(%#x), OriginalValue(%#x)\n", RegAddr, BitMask, OriginalValue); + return (ReturnValue); +} + +void rtl8192_setBBreg(struct net_device* dev, u32 RegAddr, u32 BitMask, u32 Data) +{ + u32 OriginalValue, BitShift, NewValue; + +#if (DISABLE_BB_RF == 1) + return; +#endif + + + { + if(BitMask!= bMaskDWord) + { + OriginalValue = read_nic_dword(dev, RegAddr); + BitShift = phy_CalculateBitShift(BitMask); + NewValue = (((OriginalValue) & (~BitMask)) | (Data << BitShift)); + write_nic_dword(dev, RegAddr, NewValue); + }else + write_nic_dword(dev, RegAddr, Data); + } + + return; +} + + +u32 rtl8192_phy_QueryRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask) +{ + u32 Original_Value, Readback_Value, BitShift; + struct r8192_priv *priv = rtllib_priv(dev); + unsigned long flags; + +#if (DISABLE_BB_RF == 1) + return 0; +#endif + + RT_TRACE(COMP_RF, "--->PHY_QueryRFReg(): RegAddr(%#x), eRFPath(%#x), BitMask(%#x)\n", RegAddr, eRFPath,BitMask); + + if (!((priv->rf_pathmap >> eRFPath) & 0x1)) + return 0; + + if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) + return 0; + + spin_lock_irqsave(&priv->rf_lock, flags); + if (priv->Rf_Mode == RF_OP_By_FW) + { + Original_Value = phy_FwRFSerialRead(dev, eRFPath, RegAddr); + } + else + { + Original_Value = phy_RFSerialRead(dev, eRFPath, RegAddr); + } + + BitShift = phy_CalculateBitShift(BitMask); + Readback_Value = (Original_Value & BitMask) >> BitShift; + spin_unlock_irqrestore(&priv->rf_lock, flags); + + + return (Readback_Value); +} + + +void rtl8192_phy_SetRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask, u32 Data) +{ + + struct r8192_priv *priv = rtllib_priv(dev); + u32 Original_Value, BitShift, New_Value; + unsigned long flags; +#if (DISABLE_BB_RF == 1) + return; +#endif + + RT_TRACE(COMP_RF, "--->PHY_SetRFReg(): RegAddr(%#x), BitMask(%#x), Data(%#x), eRFPath(%#x)\n", + RegAddr, BitMask, Data, eRFPath); + + if (!((priv->rf_pathmap >> eRFPath) & 0x1)) + return ; + if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) + { + return; + } + + spin_lock_irqsave(&priv->rf_lock, flags); + if (priv->Rf_Mode == RF_OP_By_FW) + { + if (BitMask != bRFRegOffsetMask) + { + Original_Value = phy_FwRFSerialRead(dev, eRFPath, RegAddr); + BitShift = phy_CalculateBitShift(BitMask); + New_Value = (((Original_Value) & (~BitMask)) | (Data<< BitShift)); + + phy_FwRFSerialWrite(dev, eRFPath, RegAddr, New_Value); + } + else + phy_FwRFSerialWrite(dev, eRFPath, RegAddr, Data); + } + else + { + if (BitMask != bRFRegOffsetMask) + { + Original_Value = phy_RFSerialRead(dev, eRFPath, RegAddr); + BitShift = phy_CalculateBitShift(BitMask); + New_Value = (((Original_Value) & (~BitMask)) | (Data<< BitShift)); + + phy_RFSerialWrite(dev, eRFPath, RegAddr, New_Value); + } + else + phy_RFSerialWrite(dev, eRFPath, RegAddr, Data); + + } + spin_unlock_irqrestore(&priv->rf_lock, flags); + RT_TRACE(COMP_RF, "<---PHY_SetRFReg(): RegAddr(%#x), BitMask(%#x), Data(%#x), eRFPath(%#x)\n", + RegAddr, BitMask, Data, eRFPath); + +} + +static u32 +phy_FwRFSerialRead( + struct net_device* dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset ) +{ + u32 retValue = 0; +#if 0 + u32 Data = 0; + u8 time = 0; + Data |= ((Offset&0xFF)<<12); + Data |= ((eRFPath&0x3)<<20); + Data |= 0x80000000; + while (PlatformIORead4Byte(dev, QPNR)&0x80000000) + { + if (time++ < 100) + { + delay_us(10); + } + else + break; + } + PlatformIOWrite4Byte(dev, QPNR, Data); + while (PlatformIORead4Byte(dev, QPNR)&0x80000000) + { + if (time++ < 100) + { + delay_us(10); + } + else + return (0); + } + retValue = PlatformIORead4Byte(dev, RF_DATA); +#endif + return (retValue); + +} /* phy_FwRFSerialRead */ + +static void +phy_FwRFSerialWrite( + struct net_device* dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset, + u32 Data ) +{ +#if 0 + u8 time = 0; + DbgPrint("N FW RF CTRL RF-%d OF%02x DATA=%03x\n\r", eRFPath, Offset, Data); + + Data |= ((Offset&0xFF)<<12); + Data |= ((eRFPath&0x3)<<20); + Data |= 0x400000; + Data |= 0x80000000; + + while (PlatformIORead4Byte(dev, QPNR)&0x80000000) + { + if (time++ < 100) + { + delay_us(10); + } + else + break; + } + PlatformIOWrite4Byte(dev, QPNR, Data); +#endif +} /* phy_FwRFSerialWrite */ + +#if (RTL92SE_FPGA_VERIFY == 1) +static u32 phy_RFSerialRead(struct net_device* dev,RF90_RADIO_PATH_E eRFPath,u32 Offset) +{ + + u32 retValue = 0; + struct r8192_priv *priv = rtllib_priv(dev); + BB_REGISTER_DEFINITION_T *pPhyReg = &priv->PHYRegDef[eRFPath]; + u32 NewOffset; + + Offset &= 0x3f; + + if( priv->rf_chip == RF_8256 || + priv->rf_chip == RF_8225 || + priv->rf_chip == RF_6052) + { + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0); + + if(Offset>=31) + { + priv->RFReadPageCnt[2]++; + priv->RfReg0Value[eRFPath] |= 0x140; + + rtl8192_setBBreg(dev, + pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16) ); + + NewOffset = Offset - 30; + + }else if(Offset>=16) + { + priv->RFReadPageCnt[1]++; + priv->RfReg0Value[eRFPath] |= 0x100; + priv->RfReg0Value[eRFPath] &= (~0x40); + + rtl8192_setBBreg(dev, + pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16) ); + + NewOffset = Offset - 15; + } + else + { + priv->RFReadPageCnt[0]++; + NewOffset = Offset; + } + } + else + NewOffset = Offset; + +#if (RTL92SE_FPGA_VERIFY == 1) + { + u32 temp1, temp2; + + temp1 = rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter2, 0xffffffff); + temp2 = rtl8192_QueryBBReg(dev, pPhyReg->rfHSSIPara2, 0xffffffff); + temp2 = temp2 & (~bLSSIReadAddress) | (NewOffset<<24) | bLSSIReadEdge; + + rtl8192_setBBreg(dev, rFPGA0_XA_HSSIParameter2, 0xffffffff, temp1&(~bLSSIReadEdge)); + msleep(1); + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, 0xffffffff, temp2); + msleep(1); + rtl8192_setBBreg(dev, rFPGA0_XA_HSSIParameter2, 0xffffffff, temp1|bLSSIReadEdge); + msleep(1); + + } +#else + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress, NewOffset); + + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x0); + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x1); +#endif + + mdelay(1); + + retValue = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack, bLSSIReadBackData); + + if( priv->rf_chip == RF_8256 || + priv->rf_chip == RF_8225 || + priv->rf_chip == RF_6052) + { + if (Offset >= 0x10) + { + priv->RfReg0Value[eRFPath] &= 0xebf; + + rtl8192_setBBreg( + dev, + pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16) ); + } + + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0xf); + } + + return retValue; +} + + +static void +phy_RFSerialWrite( + struct net_device* dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset, + u32 Data + ) +{ + u32 DataAndAddr = 0; + struct r8192_priv *priv = rtllib_priv(dev); + BB_REGISTER_DEFINITION_T *pPhyReg = &priv->PHYRegDef[eRFPath]; + u32 NewOffset; + + Offset &= 0x3f; + + PHY_RFShadowWrite(dev, eRFPath, Offset, Data); + + if( priv->rf_chip == RF_8256 || + priv->rf_chip == RF_8225 || + priv->rf_chip == RF_6052) + { + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0); + + if(Offset>=31) + { + priv->RFWritePageCnt[2]++; + priv->RfReg0Value[eRFPath] |= 0x140; + + rtl8192_setBBreg(dev, + pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16) ); + + NewOffset = Offset - 30; + + }else if(Offset>=16) + { + priv->RFWritePageCnt[1]++; + priv->RfReg0Value[eRFPath] |= 0x100; + priv->RfReg0Value[eRFPath] &= (~0x40); + + + rtl8192_setBBreg(dev, + pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16) ); + + NewOffset = Offset - 15; + } + else + { + priv->RFWritePageCnt[0]++; + NewOffset = Offset; + } + } + else + NewOffset = Offset; + + DataAndAddr = (Data<<16) | (NewOffset&0x3f); + + rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr); + + + if(Offset==0x0) + priv->RfReg0Value[eRFPath] = Data; + + if( priv->rf_chip == RF_8256 || + priv->rf_chip == RF_8225 || + priv->rf_chip == RF_6052) + { + if (Offset >= 0x10) + { + if(Offset != 0) + { + priv->RfReg0Value[eRFPath] &= 0xebf; + rtl8192_setBBreg( + dev, + pPhyReg->rf3wireOffset, + bMaskDWord, + (priv->RfReg0Value[eRFPath] << 16) ); + } + } + rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0xf); + } + +} +#else +static u32 +phy_RFSerialRead( + struct net_device* dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset + ) +{ + + u32 retValue = 0; + struct r8192_priv *priv = rtllib_priv(dev); + BB_REGISTER_DEFINITION_T *pPhyReg = &priv->PHYRegDef[eRFPath]; + u32 NewOffset; + u32 tmplong,tmplong2; + u8 RfPiEnable=0; +#if 0 + if(priv->rf_chip == RF_8225 && Offset > 0x24) + return retValue; + if(priv->rf_chip == RF_8256 && Offset > 0x2D) + return retValue; +#endif + Offset &= 0x3f; + + NewOffset = Offset; + + tmplong = rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter2, bMaskDWord); + if(eRFPath == RF90_PATH_A) + tmplong2 = tmplong; + else + tmplong2 = rtl8192_QueryBBReg(dev, pPhyReg->rfHSSIPara2, bMaskDWord); + tmplong2 = (tmplong2 & (~bLSSIReadAddress)) | (NewOffset<<23) | bLSSIReadEdge; + + rtl8192_setBBreg(dev, rFPGA0_XA_HSSIParameter2, bMaskDWord, tmplong&(~bLSSIReadEdge)); + udelay(1000); + + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bMaskDWord, tmplong2); + udelay(1000); + + rtl8192_setBBreg(dev, rFPGA0_XA_HSSIParameter2, bMaskDWord, tmplong|bLSSIReadEdge); + + if(eRFPath == RF90_PATH_A) + RfPiEnable = (u8)rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter1, BIT8); + else if(eRFPath == RF90_PATH_B) + RfPiEnable = (u8)rtl8192_QueryBBReg(dev, rFPGA0_XB_HSSIParameter1, BIT8); + + if(RfPiEnable) + { + retValue = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBackPi, bLSSIReadBackData); + } + else + { + retValue = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack, bLSSIReadBackData); + } + + retValue = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack, bLSSIReadBackData); + + return retValue; + +} + +static void +phy_RFSerialWrite( + struct net_device* dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset, + u32 Data + ) +{ + u32 DataAndAddr = 0; + struct r8192_priv *priv = rtllib_priv(dev); + BB_REGISTER_DEFINITION_T *pPhyReg = &priv->PHYRegDef[eRFPath]; + u32 NewOffset; + +#if 0 + if(priv->rf_chip == RF_8225 && Offset > 0x24) + return; + if(priv->rf_chip == RF_8256 && Offset > 0x2D) + return; +#endif + + Offset &= 0x3f; + + PHY_RFShadowWrite(dev, eRFPath, Offset, Data); + + NewOffset = Offset; + + DataAndAddr = ((NewOffset<<20) | (Data&0x000fffff)) & 0x0fffffff; + + rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr); + +} + +#endif + +static u32 phy_CalculateBitShift(u32 BitMask) +{ + u32 i; + + for(i=0; i<=31; i++) + { + if ( ((BitMask>>i) & 0x1 ) == 1) + break; + } + + return (i); +} + + +extern bool PHY_MACConfig8192S(struct net_device* dev) +{ + bool rtStatus = true; + +#if RTL8190_Download_Firmware_From_Header + rtStatus = phy_ConfigMACWithHeaderFile(dev); +#else + + RT_TRACE(COMP_INIT, "Read MACREG.txt\n"); +#endif + return (rtStatus == true) ? 1:0; + +} + +extern bool +PHY_BBConfig8192S(struct net_device* dev) +{ + bool rtStatus = true; + u8 PathMap = 0, index = 0, rf_num = 0; + struct r8192_priv *priv = rtllib_priv(dev); + u8 bRegHwParaFile = 1; + + phy_InitBBRFRegisterDefinition(dev); + + switch(bRegHwParaFile) + { + case 0: + phy_BB8190_Config_HardCode(dev); + break; + + case 1: + rtStatus = phy_BB8192S_Config_ParaFile(dev); + break; + + case 2: + phy_BB8190_Config_HardCode(dev); + phy_BB8192S_Config_ParaFile(dev); + break; + + default: + phy_BB8190_Config_HardCode(dev); + break; + } + + PathMap = (u8)(rtl8192_QueryBBReg(dev, rFPGA0_TxInfo, 0xf) | + rtl8192_QueryBBReg(dev, rOFDM0_TRxPathEnable, 0xf)); + priv->rf_pathmap = PathMap; + for(index = 0; index<4; index++) + { + if((PathMap>>index)&0x1) + rf_num++; + } + + if((priv->rf_type==RF_1T1R && rf_num!=1) || + (priv->rf_type==RF_1T2R && rf_num!=2) || + (priv->rf_type==RF_2T2R && rf_num!=2) || + (priv->rf_type==RF_2T2R_GREEN && rf_num!=2) || + (priv->rf_type==RF_2T4R && rf_num!=4)) + { + RT_TRACE( COMP_INIT, "PHY_BBConfig8192S: RF_Type(%x) does not match RF_Num(%x)!!\n", priv->rf_type, rf_num); + } + return rtStatus; +} + +extern bool +PHY_RFConfig8192S(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + bool rtStatus = true; + + + if (IS_HARDWARE_TYPE_8192SE(dev)) + priv->rf_chip = RF_6052; + + switch(priv->rf_chip) + { + case RF_8225: + case RF_6052: + rtStatus = PHY_RF6052_Config(dev); + break; + + case RF_8256: + break; + + case RF_8258: + break; + + case RF_PSEUDO_11N: + break; + default: + break; + } + + return rtStatus; +} + + +static bool +phy_BB8190_Config_HardCode(struct net_device* dev) +{ + return true; +} + + +static bool +phy_BB8192S_Config_ParaFile(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + bool rtStatus = true; + + RT_TRACE(COMP_INIT, "==>phy_BB8192S_Config_ParaFile\n"); + +#if RTL8190_Download_Firmware_From_Header + if (priv->rf_type == RF_1T2R || priv->rf_type == RF_2T2R || + priv->rf_type == RF_1T1R ||priv->rf_type == RF_2T2R_GREEN) + { + rtStatus = phy_ConfigBBWithHeaderFile(dev,BaseBand_Config_PHY_REG); + if(priv->rf_type != RF_2T2R && priv->rf_type != RF_2T2R_GREEN) + { + rtStatus = phy_SetBBtoDiffRFWithHeaderFile(dev,BaseBand_Config_PHY_REG); + } + }else + rtStatus = false; +#else + RT_TRACE(COMP_INIT, "RF_Type == %d\n", priv->rf_type); + if (priv->rf_type == RF_1T2R || priv->rf_type == RF_2T2R || + priv->rf_type == RF_1T1R ||priv->rf_type == RF_2T2R_GREEN) + { + rtStatus = phy_ConfigBBWithParaFile(dev, (char* )&szBBRegFile); + if(priv->rf_type != RF_2T2R && priv->rf_type != RF_2T2R_GREEN) + { + if(priv->rf_type == RF_1T1R) + rtStatus = phy_SetBBtoDiffRFWithParaFile(dev, (char* )&szBBRegto1T1RFile); + else if(priv->rf_type == RF_1T2R) + rtStatus = phy_SetBBtoDiffRFWithParaFile(dev, (char* )&szBBRegto1T2RFile); + } + + }else + rtStatus = false; +#endif + + if(rtStatus != true){ + RT_TRACE(COMP_INIT, "phy_BB8192S_Config_ParaFile():Write BB Reg Fail!!"); + goto phy_BB8190_Config_ParaFile_Fail; + } + + if (priv->AutoloadFailFlag == false) + { + priv->pwrGroupCnt = 0; + +#if RTL8190_Download_Firmware_From_Header + rtStatus = phy_ConfigBBWithPgHeaderFile(dev,BaseBand_Config_PHY_REG); +#else + rtStatus = phy_ConfigBBWithPgParaFile(dev, (char* )&szBBRegPgFile); +#endif + } + if(rtStatus != true){ + RT_TRACE(COMP_INIT, "phy_BB8192S_Config_ParaFile():BB_PG Reg Fail!!"); + goto phy_BB8190_Config_ParaFile_Fail; + } + +#if RTL8190_Download_Firmware_From_Header + rtStatus = phy_ConfigBBWithHeaderFile(dev,BaseBand_Config_AGC_TAB); +#else + RT_TRACE(COMP_INIT, "phy_BB8192S_Config_ParaFile AGC_TAB.txt\n"); + rtStatus = phy_ConfigBBWithParaFile(dev, (char* )&szAGCTableFile); +#endif + + if(rtStatus != true){ + printk( "phy_BB8192S_Config_ParaFile():AGC Table Fail\n"); + goto phy_BB8190_Config_ParaFile_Fail; + } + + +#if 0 + if(pHalData->VersionID > VERSION_8190_BD) + { + u4RegValue = ( pHalData->AntennaTxPwDiff[2]<<8 | + pHalData->AntennaTxPwDiff[1]<<4 | + pHalData->AntennaTxPwDiff[0]); + + PHY_SetBBReg(dev, rFPGA0_TxGainStage, + (bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue); + + u4RegValue = pHalData->CrystalCap; + PHY_SetBBReg(dev, rFPGA0_AnalogParameter1, bXtalCap92x, u4RegValue); + + } +#endif + + priv->bCckHighPower = (bool)(rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter2, 0x200)); + + +phy_BB8190_Config_ParaFile_Fail: + return rtStatus; +} + +static bool +phy_ConfigMACWithHeaderFile(struct net_device* dev) +{ + u32 i = 0; + u32 ArrayLength = 0; + u32* ptrArray; + + /*if(dev->bInHctTest) + { + RT_TRACE(COMP_INIT, DBG_LOUD, ("Rtl819XMACPHY_ArrayDTM\n")); + ArrayLength = MACPHY_ArrayLengthDTM; + ptrArray = Rtl819XMACPHY_ArrayDTM; + } + else if(pHalData->bTXPowerDataReadFromEEPORM) + { + + }else*/ + { + RT_TRACE(COMP_INIT, "Read Rtl819XMACPHY_Array\n"); + ArrayLength = MAC_2T_ArrayLength; + ptrArray = Rtl819XMAC_Array; + } + + /*for(i = 0 ;i < ArrayLength;i=i+3){ + RT_TRACE(COMP_SEND, DBG_LOUD, ("The Rtl819XMACPHY_Array[0] is %lx Rtl819XMACPHY_Array[1] is %lx Rtl819XMACPHY_Array[2] is %lx\n",ptrArray[i], ptrArray[i+1], ptrArray[i+2])); + if(ptrArray[i] == 0x318) + { + ptrArray[i+2] = 0x00000800; + } + PHY_SetBBReg(dev, ptrArray[i], ptrArray[i+1], ptrArray[i+2]); + }*/ + for(i = 0 ;i < ArrayLength;i=i+2){ + write_nic_byte(dev, ptrArray[i], (u8)ptrArray[i+1]); + } + return true; +} + + +static bool +phy_ConfigBBWithHeaderFile(struct net_device* dev,u8 ConfigType) +{ + int i; + u32* Rtl819XPHY_REGArray_Table; + u32* Rtl819XAGCTAB_Array_Table; + u16 PHY_REGArrayLen, AGCTAB_ArrayLen; + /*if(dev->bInHctTest) + { + + AGCTAB_ArrayLen = AGCTAB_ArrayLengthDTM; + Rtl819XAGCTAB_Array_Table = Rtl819XAGCTAB_ArrayDTM; + + if(pHalData->RF_Type == RF_2T4R) + { + PHY_REGArrayLen = PHY_REGArrayLengthDTM; + Rtl819XPHY_REGArray_Table = Rtl819XPHY_REGArrayDTM; + } + else if (pHalData->RF_Type == RF_1T2R) + { + PHY_REGArrayLen = PHY_REG_1T2RArrayLengthDTM; + Rtl819XPHY_REGArray_Table = Rtl819XPHY_REG_1T2RArrayDTM; + } + + } + else + */ + AGCTAB_ArrayLen = AGCTAB_ArrayLength; + Rtl819XAGCTAB_Array_Table = Rtl819XAGCTAB_Array; + PHY_REGArrayLen = PHY_REG_2T2RArrayLength; + Rtl819XPHY_REGArray_Table = Rtl819XPHY_REG_Array; + + if(ConfigType == BaseBand_Config_PHY_REG) + { + for(i=0;irf_type == RF_1T1R) + { + Rtl819XPHY_REGArraytoXTXR_Table = Rtl819XPHY_REG_to1T1R_Array; + PHY_REGArraytoXTXRLen = PHY_ChangeTo_1T1RArrayLength; + } + else if(priv->rf_type == RF_1T2R) + { + Rtl819XPHY_REGArraytoXTXR_Table = Rtl819XPHY_REG_to1T2R_Array; + PHY_REGArraytoXTXRLen = PHY_ChangeTo_1T2RArrayLength; + } + else + { + return false; + } + + if(ConfigType == BaseBand_Config_PHY_REG) + { + for(i=0;iMCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][0] = Data; + } + if(RegAddr == rTxAGC_Rate54_24) + { + priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][1] = Data; + } + if(RegAddr == rTxAGC_CCK_Mcs32) + { + priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][6] = Data; + } + if(RegAddr == rTxAGC_Mcs03_Mcs00) + { + priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][2] = Data; + } + if(RegAddr == rTxAGC_Mcs07_Mcs04) + { + priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][3] = Data; + } + if(RegAddr == rTxAGC_Mcs11_Mcs08) + { + priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][4] = Data; + } + if(RegAddr == rTxAGC_Mcs15_Mcs12) + { + priv->MCSTxPowerLevelOriginalOffset[priv->pwrGroupCnt][5] = Data; + priv->pwrGroupCnt++; + } +} + +static bool +phy_ConfigBBWithPgHeaderFile(struct net_device* dev,u8 ConfigType) +{ + int i; + u32* Rtl819XPHY_REGArray_Table_PG; + u16 PHY_REGArrayPGLen; + + PHY_REGArrayPGLen = PHY_REG_Array_PGLength; + Rtl819XPHY_REGArray_Table_PG = Rtl819XPHY_REG_Array_PG; + + if(ConfigType == BaseBand_Config_PHY_REG) + { + for(i=0;iIC_Class != IC_INFERIORITY_A) + { + tmpval = rtl8192_phy_QueryRFReg(dev, eRFPath, RF_IPA, 0xf); + rtl8192_phy_SetRFReg(dev, eRFPath, RF_IPA, 0xf, tmpval+1); + } + + return rtStatus; +} + +u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E eRFPath) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int i; + bool rtStatus = true; + u32 *Rtl819XRadioA_Array_Table; + u32 *Rtl819XRadioB_Array_Table; + u16 RadioA_ArrayLen,RadioB_ArrayLen; + + RadioA_ArrayLen = RadioA_1T_ArrayLength; + Rtl819XRadioA_Array_Table=Rtl819XRadioA_Array; + + if(priv->rf_type == RF_2T2R_GREEN) + { + Rtl819XRadioB_Array_Table = Rtl819XRadioB_GM_Array; + RadioB_ArrayLen = RadioB_GM_ArrayLength; + } + else + { + Rtl819XRadioB_Array_Table=Rtl819XRadioB_Array; + RadioB_ArrayLen = RadioB_ArrayLength; + } + + + RT_TRACE(COMP_INIT, "PHY_ConfigRFWithHeaderFile: Radio No %x\n", eRFPath); + rtStatus = true; + + switch(eRFPath){ + case RF90_PATH_A: + for(i = 0;iSetRFPowerStateInProgress == true) + return; + + priv->SetRFPowerStateInProgress = true; + + + if(RFPowerState==RF_SHUT_DOWN) + { + RFPowerState=RF_OFF; + WaitShutDown=true; + } + + + priv->RFPowerState = RFPowerState; + switch( priv->rf_chip ) + { + case RF_8225: + case RF_6052: + switch( RFPowerState ) + { + case RF_ON: + break; + + case RF_SLEEP: + break; + + case RF_OFF: + break; + } + break; + + case RF_8256: + switch( RFPowerState ) + { + case RF_ON: + break; + + case RF_SLEEP: + break; + + case RF_OFF: + for(eRFPath=(RF90_RADIO_PATH_E)RF90_PATH_A; eRFPath < RF90_PATH_MAX; eRFPath++) + { + if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath)) + continue; + + pPhyReg = &priv->PHYRegDef[eRFPath]; + rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, bRFSI_RFENV); + rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0); + } + break; + } + break; + + case RF_8258: + break; + } + + priv->SetRFPowerStateInProgress = false; +} +#endif + +void PHY_GetHWRegOriginalValue(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); +#if 0 + priv->MCSTxPowerLevelOriginalOffset[0] = + rtl8192_QueryBBReg(dev, rTxAGC_Rate18_06, bMaskDWord); + priv->MCSTxPowerLevelOriginalOffset[1] = + rtl8192_QueryBBReg(dev, rTxAGC_Rate54_24, bMaskDWord); + priv->MCSTxPowerLevelOriginalOffset[2] = + rtl8192_QueryBBReg(dev, rTxAGC_Mcs03_Mcs00, bMaskDWord); + priv->MCSTxPowerLevelOriginalOffset[3] = + rtl8192_QueryBBReg(dev, rTxAGC_Mcs07_Mcs04, bMaskDWord); + priv->MCSTxPowerLevelOriginalOffset[4] = + rtl8192_QueryBBReg(dev, rTxAGC_Mcs11_Mcs08, bMaskDWord); + priv->MCSTxPowerLevelOriginalOffset[5] = + rtl8192_QueryBBReg(dev, rTxAGC_Mcs15_Mcs12, bMaskDWord); + + priv->CCKTxPowerLevelOriginalOffset= + rtl8192_QueryBBReg(dev, rTxAGC_CCK_Mcs32, bMaskDWord); + RT_TRACE(COMP_INIT, "Legacy OFDM =%08x/%08x HT_OFDM=%08x/%08x/%08x/%08x\n", + priv->MCSTxPowerLevelOriginalOffset[0], priv->MCSTxPowerLevelOriginalOffset[1] , + priv->MCSTxPowerLevelOriginalOffset[2], priv->MCSTxPowerLevelOriginalOffset[3] , + priv->MCSTxPowerLevelOriginalOffset[4], priv->MCSTxPowerLevelOriginalOffset[5] ); +#endif + + priv->DefaultInitialGain[0] = rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bMaskByte0); + priv->DefaultInitialGain[1] = rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bMaskByte0); + priv->DefaultInitialGain[2] = rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bMaskByte0); + priv->DefaultInitialGain[3] = rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, bMaskByte0); + RT_TRACE(COMP_INIT, "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x) \n", + priv->DefaultInitialGain[0], priv->DefaultInitialGain[1], + priv->DefaultInitialGain[2], priv->DefaultInitialGain[3]); + + priv->framesync = rtl8192_QueryBBReg(dev, rOFDM0_RxDetector3, bMaskByte0); + priv->framesyncC34 = rtl8192_QueryBBReg(dev, rOFDM0_RxDetector2, bMaskDWord); + RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x \n", + rOFDM0_RxDetector3, priv->framesync); + +} + + + +static void phy_InitBBRFRegisterDefinition( struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + priv->PHYRegDef[RF90_PATH_A].rfintfs = rFPGA0_XAB_RFInterfaceSW; + priv->PHYRegDef[RF90_PATH_B].rfintfs = rFPGA0_XAB_RFInterfaceSW; + priv->PHYRegDef[RF90_PATH_C].rfintfs = rFPGA0_XCD_RFInterfaceSW; + priv->PHYRegDef[RF90_PATH_D].rfintfs = rFPGA0_XCD_RFInterfaceSW; + + priv->PHYRegDef[RF90_PATH_A].rfintfi = rFPGA0_XAB_RFInterfaceRB; + priv->PHYRegDef[RF90_PATH_B].rfintfi = rFPGA0_XAB_RFInterfaceRB; + priv->PHYRegDef[RF90_PATH_C].rfintfi = rFPGA0_XCD_RFInterfaceRB; + priv->PHYRegDef[RF90_PATH_D].rfintfi = rFPGA0_XCD_RFInterfaceRB; + + priv->PHYRegDef[RF90_PATH_A].rfintfo = rFPGA0_XA_RFInterfaceOE; + priv->PHYRegDef[RF90_PATH_B].rfintfo = rFPGA0_XB_RFInterfaceOE; + priv->PHYRegDef[RF90_PATH_C].rfintfo = rFPGA0_XC_RFInterfaceOE; + priv->PHYRegDef[RF90_PATH_D].rfintfo = rFPGA0_XD_RFInterfaceOE; + + priv->PHYRegDef[RF90_PATH_A].rfintfe = rFPGA0_XA_RFInterfaceOE; + priv->PHYRegDef[RF90_PATH_B].rfintfe = rFPGA0_XB_RFInterfaceOE; + priv->PHYRegDef[RF90_PATH_C].rfintfe = rFPGA0_XC_RFInterfaceOE; + priv->PHYRegDef[RF90_PATH_D].rfintfe = rFPGA0_XD_RFInterfaceOE; + + priv->PHYRegDef[RF90_PATH_A].rf3wireOffset = rFPGA0_XA_LSSIParameter; + priv->PHYRegDef[RF90_PATH_B].rf3wireOffset = rFPGA0_XB_LSSIParameter; + priv->PHYRegDef[RF90_PATH_C].rf3wireOffset = rFPGA0_XC_LSSIParameter; + priv->PHYRegDef[RF90_PATH_D].rf3wireOffset = rFPGA0_XD_LSSIParameter; + + priv->PHYRegDef[RF90_PATH_A].rfLSSI_Select = rFPGA0_XAB_RFParameter; + priv->PHYRegDef[RF90_PATH_B].rfLSSI_Select = rFPGA0_XAB_RFParameter; + priv->PHYRegDef[RF90_PATH_C].rfLSSI_Select = rFPGA0_XCD_RFParameter; + priv->PHYRegDef[RF90_PATH_D].rfLSSI_Select = rFPGA0_XCD_RFParameter; + + priv->PHYRegDef[RF90_PATH_A].rfTxGainStage = rFPGA0_TxGainStage; + priv->PHYRegDef[RF90_PATH_B].rfTxGainStage = rFPGA0_TxGainStage; + priv->PHYRegDef[RF90_PATH_C].rfTxGainStage = rFPGA0_TxGainStage; + priv->PHYRegDef[RF90_PATH_D].rfTxGainStage = rFPGA0_TxGainStage; + + priv->PHYRegDef[RF90_PATH_A].rfHSSIPara1 = rFPGA0_XA_HSSIParameter1; + priv->PHYRegDef[RF90_PATH_B].rfHSSIPara1 = rFPGA0_XB_HSSIParameter1; + priv->PHYRegDef[RF90_PATH_C].rfHSSIPara1 = rFPGA0_XC_HSSIParameter1; + priv->PHYRegDef[RF90_PATH_D].rfHSSIPara1 = rFPGA0_XD_HSSIParameter1; + + priv->PHYRegDef[RF90_PATH_A].rfHSSIPara2 = rFPGA0_XA_HSSIParameter2; + priv->PHYRegDef[RF90_PATH_B].rfHSSIPara2 = rFPGA0_XB_HSSIParameter2; + priv->PHYRegDef[RF90_PATH_C].rfHSSIPara2 = rFPGA0_XC_HSSIParameter2; + priv->PHYRegDef[RF90_PATH_D].rfHSSIPara2 = rFPGA0_XD_HSSIParameter2; + + priv->PHYRegDef[RF90_PATH_A].rfSwitchControl = rFPGA0_XAB_SwitchControl; + priv->PHYRegDef[RF90_PATH_B].rfSwitchControl = rFPGA0_XAB_SwitchControl; + priv->PHYRegDef[RF90_PATH_C].rfSwitchControl = rFPGA0_XCD_SwitchControl; + priv->PHYRegDef[RF90_PATH_D].rfSwitchControl = rFPGA0_XCD_SwitchControl; + + priv->PHYRegDef[RF90_PATH_A].rfAGCControl1 = rOFDM0_XAAGCCore1; + priv->PHYRegDef[RF90_PATH_B].rfAGCControl1 = rOFDM0_XBAGCCore1; + priv->PHYRegDef[RF90_PATH_C].rfAGCControl1 = rOFDM0_XCAGCCore1; + priv->PHYRegDef[RF90_PATH_D].rfAGCControl1 = rOFDM0_XDAGCCore1; + + priv->PHYRegDef[RF90_PATH_A].rfAGCControl2 = rOFDM0_XAAGCCore2; + priv->PHYRegDef[RF90_PATH_B].rfAGCControl2 = rOFDM0_XBAGCCore2; + priv->PHYRegDef[RF90_PATH_C].rfAGCControl2 = rOFDM0_XCAGCCore2; + priv->PHYRegDef[RF90_PATH_D].rfAGCControl2 = rOFDM0_XDAGCCore2; + + priv->PHYRegDef[RF90_PATH_A].rfRxIQImbalance = rOFDM0_XARxIQImbalance; + priv->PHYRegDef[RF90_PATH_B].rfRxIQImbalance = rOFDM0_XBRxIQImbalance; + priv->PHYRegDef[RF90_PATH_C].rfRxIQImbalance = rOFDM0_XCRxIQImbalance; + priv->PHYRegDef[RF90_PATH_D].rfRxIQImbalance = rOFDM0_XDRxIQImbalance; + + priv->PHYRegDef[RF90_PATH_A].rfRxAFE = rOFDM0_XARxAFE; + priv->PHYRegDef[RF90_PATH_B].rfRxAFE = rOFDM0_XBRxAFE; + priv->PHYRegDef[RF90_PATH_C].rfRxAFE = rOFDM0_XCRxAFE; + priv->PHYRegDef[RF90_PATH_D].rfRxAFE = rOFDM0_XDRxAFE; + + priv->PHYRegDef[RF90_PATH_A].rfTxIQImbalance = rOFDM0_XATxIQImbalance; + priv->PHYRegDef[RF90_PATH_B].rfTxIQImbalance = rOFDM0_XBTxIQImbalance; + priv->PHYRegDef[RF90_PATH_C].rfTxIQImbalance = rOFDM0_XCTxIQImbalance; + priv->PHYRegDef[RF90_PATH_D].rfTxIQImbalance = rOFDM0_XDTxIQImbalance; + + priv->PHYRegDef[RF90_PATH_A].rfTxAFE = rOFDM0_XATxAFE; + priv->PHYRegDef[RF90_PATH_B].rfTxAFE = rOFDM0_XBTxAFE; + priv->PHYRegDef[RF90_PATH_C].rfTxAFE = rOFDM0_XCTxAFE; + priv->PHYRegDef[RF90_PATH_D].rfTxAFE = rOFDM0_XDTxAFE; + + priv->PHYRegDef[RF90_PATH_A].rfLSSIReadBack = rFPGA0_XA_LSSIReadBack; + priv->PHYRegDef[RF90_PATH_B].rfLSSIReadBack = rFPGA0_XB_LSSIReadBack; + priv->PHYRegDef[RF90_PATH_C].rfLSSIReadBack = rFPGA0_XC_LSSIReadBack; + priv->PHYRegDef[RF90_PATH_D].rfLSSIReadBack = rFPGA0_XD_LSSIReadBack; + + priv->PHYRegDef[RF90_PATH_A].rfLSSIReadBackPi = TransceiverA_HSPI_Readback; + priv->PHYRegDef[RF90_PATH_B].rfLSSIReadBackPi = TransceiverB_HSPI_Readback; + +} + + +bool PHY_SetRFPowerState(struct net_device* dev, RT_RF_POWER_STATE eRFPowerState) +{ + struct r8192_priv *priv = rtllib_priv(dev); + bool bResult = false; + + RT_TRACE((COMP_PS | COMP_RF), "---------> PHY_SetRFPowerState(): eRFPowerState(%d)\n", eRFPowerState); + + if(eRFPowerState == priv->rtllib->eRFPowerState) + { + ; + return bResult; + } + + bResult = phy_SetRFPowerState8192SE(dev, eRFPowerState); + + RT_TRACE((COMP_PS | COMP_RF), "<--------- PHY_SetRFPowerState(): bResult(%d)\n", bResult); + + return bResult; +} + +static bool phy_SetRFPowerState8192SE(struct net_device* dev,RT_RF_POWER_STATE eRFPowerState) +{ + struct r8192_priv *priv = rtllib_priv(dev); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->rtllib->PowerSaveControl)); + bool bResult = true; + u8 i, QueueID; + struct rtl8192_tx_ring *ring = NULL; + priv->SetRFPowerStateInProgress = true; + + switch(priv->rf_chip ) + { + default: + switch( eRFPowerState ) + { + case eRfOn: + RT_TRACE(COMP_PS,"========>%s():eRfOn\n", __func__); + { + if((priv->rtllib->eRFPowerState == eRfOff) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) + { + bool rtstatus = true; + u32 InitializeCount = 0; + do + { + InitializeCount++; + rtstatus = NicIFEnableNIC(dev); + }while( (rtstatus != true) &&(InitializeCount < 10) ); + if(rtstatus != true) + { + RT_TRACE(COMP_ERR,"%s():Initialize Adapter fail,return\n",__FUNCTION__); + priv->SetRFPowerStateInProgress = false; + return false; + } + RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); + } + else + { + write_nic_word(dev, CMDR, 0x37FC); + write_nic_byte(dev, TXPAUSE, 0x00); + write_nic_byte(dev, PHY_CCA, 0x3); + } + +#if 1 + if(priv->rtllib->state == RTLLIB_LINKED) + { + LedControl8192SE(dev, LED_CTL_LINK); + } + else + { + LedControl8192SE(dev, LED_CTL_NO_LINK); + } +#endif + } + break; + case eRfOff: + RT_TRACE(COMP_PS,"========>%s():eRfOff\n", __func__); + { + for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; ) + { + if(QueueID == 5) + { + QueueID++; + continue; + } + + ring = &priv->tx_ring[QueueID]; + if(skb_queue_len(&ring->queue) == 0) + { + QueueID++; + continue; + } + #ifdef TO_DO_LIST + #if( DEV_BUS_TYPE==PCI_INTERFACE) + else if(IsLowPowerState(Adapter)) + { + RT_TRACE(COMP_PS, DBG_LOUD, + ("eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 but lower power state!\n", (i+1), QueueID)); + break; + } + #endif + #endif + else + { + RT_TRACE(COMP_PS, "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID); + udelay(10); + i++; + } + + if(i >= MAX_DOZE_WAITING_TIMES_9x) + { + RT_TRACE(COMP_PS, "\n\n\n %s(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", __FUNCTION__,MAX_DOZE_WAITING_TIMES_9x, QueueID); + break; + } + } + + if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) + { + NicIFDisableNIC(dev); + RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC); + if(priv->pwrdown && priv->rtllib->RfOffReason>= RF_CHANGE_BY_HW) + write_nic_byte(dev,0x03,0x31); + } + else if(!(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC)) + { + SET_RTL8192SE_RF_SLEEP(dev); + +#if 1 + if(priv->rtllib->RfOffReason == RF_CHANGE_BY_IPS ) + { + LedControl8192SE(dev,LED_CTL_NO_LINK); + } + else + { + LedControl8192SE(dev, LED_CTL_POWER_OFF); + } +#endif + } + } + break; + + case eRfSleep: + RT_TRACE(COMP_PS,"========>%s():eRfSleep\n", __func__); + { + if(priv->rtllib->eRFPowerState == eRfOff) + break; + + for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; ) + { + ring = &priv->tx_ring[QueueID]; + if(skb_queue_len(&ring->queue) == 0) + { + QueueID++; + continue; + } + #ifdef TO_DO_LIST + #if( DEV_BUS_TYPE==PCI_INTERFACE) + else if(IsLowPowerState(Adapter)) + { + RT_TRACE(COMP_PS, "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 but lower power state!\n", (i+1), QueueID); + break; + } + #endif + #endif + else + { + RT_TRACE(COMP_PS, "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID); + udelay(10); + i++; + } + + if(i >= MAX_DOZE_WAITING_TIMES_9x) + { + RT_TRACE(COMP_PS, "\n\n\n %s(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", __FUNCTION__,MAX_DOZE_WAITING_TIMES_9x, QueueID); + break; + } + } + + SET_RTL8192SE_RF_SLEEP(dev); + } + break; + + default: + bResult = false; + RT_TRACE(COMP_ERR, "phy_SetRFPowerState8192S(): unknow state to set: 0x%X!!!\n", eRFPowerState); + break; + } + break; + } + + if(bResult) + { + priv->rtllib->eRFPowerState = eRFPowerState; + } + + priv->SetRFPowerStateInProgress = false; + + return bResult; +} + + +void +PHY_SwitchEphyParameter(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + write_nic_dword(dev, 0x540, 0x73c11); + write_nic_dword(dev, 0x548, 0x2407c); + + write_nic_word(dev, 0x550, 0x1000); + write_nic_byte(dev, 0x554, 0x20); + phy_CheckEphySwitchReady(dev); + + write_nic_word(dev, 0x550, 0xa0eb); + write_nic_byte(dev, 0x554, 0x3e); + phy_CheckEphySwitchReady(dev); + + write_nic_word(dev, 0x550, 0xff80); + write_nic_byte(dev, 0x554, 0x39); + phy_CheckEphySwitchReady(dev); + + if(priv->bSupportASPM && !priv->bSupportBackDoor) + write_nic_byte(dev, 0x560, 0x40); + else + { + write_nic_byte(dev, 0x560, 0x00); + + if (priv->CustomerID == RT_CID_819x_SAMSUNG || + priv->CustomerID == RT_CID_819x_Lenovo) + { + if (priv->NdisAdapter.PciBridgeVendor == PCI_BRIDGE_VENDOR_AMD || + priv->NdisAdapter.PciBridgeVendor == PCI_BRIDGE_VENDOR_ATI) + { + write_nic_byte(dev, 0x560, 0x40); + } + } + } + +} + + + void +PHY_GetTxPowerLevel8192S( + struct net_device* dev, + long* powerlevel + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 TxPwrLevel = 0; + long TxPwrDbm; + + TxPwrLevel = priv->CurrentCckTxPwrIdx; + TxPwrDbm = phy_TxPwrIdxToDbm(dev, WIRELESS_MODE_B, TxPwrLevel); + + TxPwrLevel = priv->CurrentOfdm24GTxPwrIdx + priv->LegacyHTTxPowerDiff; + + if(phy_TxPwrIdxToDbm(dev, WIRELESS_MODE_G, TxPwrLevel) > TxPwrDbm) + TxPwrDbm = phy_TxPwrIdxToDbm(dev, WIRELESS_MODE_G, TxPwrLevel); + TxPwrLevel = priv->CurrentOfdm24GTxPwrIdx; + + if(phy_TxPwrIdxToDbm(dev, WIRELESS_MODE_N_24G, TxPwrLevel) > TxPwrDbm) + TxPwrDbm = phy_TxPwrIdxToDbm(dev, WIRELESS_MODE_N_24G, TxPwrLevel); + *powerlevel = TxPwrDbm; +} + +#if 1 +void getTxPowerIndex( + struct net_device* dev, + u8 channel, + u8* cckPowerLevel, + u8* ofdmPowerLevel + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 index = (channel -1); + cckPowerLevel[0] = priv->RfTxPwrLevelCck[0][index]; + cckPowerLevel[1] = priv->RfTxPwrLevelCck[1][index]; + + if (priv->rf_type == RF_1T2R || priv->rf_type == RF_1T1R) + { + ofdmPowerLevel[0] = priv->RfTxPwrLevelOfdm1T[0][index]; + ofdmPowerLevel[1] = priv->RfTxPwrLevelOfdm1T[1][index]; + } + else if (priv->rf_type == RF_2T2R) + { + ofdmPowerLevel[0] = priv->RfTxPwrLevelOfdm2T[0][index]; + ofdmPowerLevel[1] = priv->RfTxPwrLevelOfdm2T[1][index]; + } + RT_TRACE(COMP_POWER,"Channel-%d, set tx power index !!\n", channel); +} + +void ccxPowerIndexCheck( + struct net_device* dev, + u8 channel, + u8* cckPowerLevel, + u8* ofdmPowerLevel + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + +#ifdef TODO + if( priv->rtllib->iw_mode != IW_MODE_INFRA && priv->bWithCcxCellPwr && + channel == priv->rtllib->current_network.channel) + { + u8 CckCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_B, priv->CcxCellPwr); + u8 LegacyOfdmCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_G, priv->CcxCellPwr); + u8 OfdmCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_N_24G, priv->CcxCellPwr); + + RT_TRACE(COMP_TXAGC, + "CCX Cell Limit: %d dbm => CCK Tx power index : %d, Legacy OFDM Tx power index : %d, OFDM Tx power index: %d\n", + priv->CcxCellPwr, CckCellPwrIdx, LegacyOfdmCellPwrIdx, OfdmCellPwrIdx); + RT_TRACE(COMP_TXAGC, + "EEPROM channel(%d) => CCK Tx power index: %d, Legacy OFDM Tx power index : %d, OFDM Tx power index: %d\n", + channel, cckPowerLevel[0], ofdmPowerLevel[0] + priv->LegacyHTTxPowerDiff, ofdmPowerLevel[0]); + + if(cckPowerLevel[0] > CckCellPwrIdx) + cckPowerLevel[0] = CckCellPwrIdx; + if(ofdmPowerLevel[0] + priv->LegacyHTTxPowerDiff > LegacyOfdmCellPwrIdx) + { + if((OfdmCellPwrIdx - priv->LegacyHTTxPowerDiff) > 0) + { + ofdmPowerLevel[0] = OfdmCellPwrIdx - priv->LegacyHTTxPowerDiff; + } + else + { + ofdmPowerLevel[0] = 0; + } + } + + RT_TRACE(COMP_TXAGC, + "Altered CCK Tx power index : %d, Legacy OFDM Tx power index: %d, OFDM Tx power index: %d\n", + cckPowerLevel[0], ofdmPowerLevel[0] + priv->LegacyHTTxPowerDiff, ofdmPowerLevel[0]); + } + +#endif + priv->CurrentCckTxPwrIdx = cckPowerLevel[0]; + priv->CurrentOfdm24GTxPwrIdx = ofdmPowerLevel[0]; + + RT_TRACE(COMP_TXAGC, + "PHY_SetTxPowerLevel8192S(): CCK Tx power index : %d, Legacy OFDM Tx power index: %d, OFDM Tx power index: %d\n", + cckPowerLevel[0], ofdmPowerLevel[0] + priv->LegacyHTTxPowerDiff, ofdmPowerLevel[0]); + +} +/*----------------------------------------------------------------------------- + * Function: SetTxPowerLevel8190() + * + * Overview: This function is export to "HalCommon" moudule + * We must consider RF path later!!!!!!! + * + * Input: PADAPTER Adapter + * u1Byte channel + * + * Output: NONE + * + * Return: NONE + * 2008/11/04 MHC We remove EEPROM_93C56. + * We need to move CCX relative code to independet file. + * 2009/01/21 MHC Support new EEPROM format from SD3 requirement. + * + *---------------------------------------------------------------------------*/ +void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 cckPowerLevel[2], ofdmPowerLevel[2]; + + if(priv->bTXPowerDataReadFromEEPORM == false) + return; + getTxPowerIndex(dev, channel, &cckPowerLevel[0], &ofdmPowerLevel[0]); + RT_TRACE(COMP_POWER, "Channel-%d, cckPowerLevel (A / B) = 0x%x / 0x%x, ofdmPowerLevel (A / B) = 0x%x / 0x%x\n", + channel, cckPowerLevel[0], cckPowerLevel[1], ofdmPowerLevel[0], ofdmPowerLevel[1]); + + ccxPowerIndexCheck(dev, channel, &cckPowerLevel[0], &ofdmPowerLevel[0]); + + switch(priv->rf_chip) + { + case RF_8225: + break; + + case RF_8256: + ; + break; + + case RF_6052: + PHY_RF6052SetCckTxPower(dev, cckPowerLevel[0]); + PHY_RF6052SetOFDMTxPower(dev, &ofdmPowerLevel[0], channel); + break; + + case RF_8258: + break; + default: + break; + } +} +#else +void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 powerlevel = (u8)EEPROM_Default_TxPower, powerlevelOFDM24G = 0x10; + s8 ant_pwr_diff = 0; + u32 u4RegValue; + u8 index = (channel -1); + u8 pwrdiff[2] = {0}; + u8 ht20pwr[2] = {0}, ht40pwr[2] = {0}; + u8 rfpath = 0, rfpathnum = 2; + + if(priv->bTXPowerDataReadFromEEPORM == false) + return; + + + powerlevel = priv->RfTxPwrLevelCck[0][index]; + + if (priv->rf_type == RF_1T2R || priv->rf_type == RF_1T1R) + { + powerlevelOFDM24G = priv->RfTxPwrLevelOfdm1T[0][index]; + + + rfpathnum = 1; + ht20pwr[0] = ht40pwr[0] = priv->RfTxPwrLevelOfdm1T[0][index]; + } + else if (priv->rf_type == RF_2T2R) + { + powerlevelOFDM24G = priv->RfTxPwrLevelOfdm2T[0][index]; + ant_pwr_diff = priv->RfTxPwrLevelOfdm2T[1][index] - + priv->RfTxPwrLevelOfdm2T[0][index]; + + RT_TRACE(COMP_POWER, "CH-%d HT40 A/B Pwr index = %x/%x(%d/%d)\n", + channel, priv->RfTxPwrLevelOfdm2T[0][index], + priv->RfTxPwrLevelOfdm2T[1][index], + priv->RfTxPwrLevelOfdm2T[0][index], + priv->RfTxPwrLevelOfdm2T[1][index]); + + ht20pwr[0] = ht40pwr[0] = priv->RfTxPwrLevelOfdm2T[0][index]; + ht20pwr[1] = ht40pwr[1] = priv->RfTxPwrLevelOfdm2T[1][index]; + } + RT_TRACE(COMP_POWER, "Channel-%d, set tx power index\n", channel); + + if (priv->eeprom_version >= 2) + { + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + { + for (rfpath = 0; rfpath < rfpathnum; rfpath++) + { + pwrdiff[rfpath] = priv->TxPwrHt20Diff[rfpath][index]; + + if (pwrdiff[rfpath] < 8) + { + ht20pwr[rfpath] += pwrdiff[rfpath]; + } + else + { + ht20pwr[rfpath] -= (16-pwrdiff[rfpath]); + } + } + + if (priv->rf_type == RF_2T2R) + ant_pwr_diff = ht20pwr[1] - ht20pwr[0]; + + RT_TRACE(COMP_POWER, "HT20 to HT40 pwrdiff[A/B]=%d/%d, ant_pwr_diff=%d(B-A=%d-%d)\n", + pwrdiff[0], pwrdiff[1], ant_pwr_diff, ht20pwr[1], ht20pwr[0]); + } + } + + if(ant_pwr_diff > 7) + ant_pwr_diff = 7; + if(ant_pwr_diff < -8) + ant_pwr_diff = -8; + + RT_TRACE(COMP_POWER, "CCK/HT Power index = %x/%x(%d/%d), ant_pwr_diff=%d\n", + powerlevel, powerlevelOFDM24G, powerlevel, powerlevelOFDM24G, ant_pwr_diff); + + ant_pwr_diff &= 0xf; + + priv->AntennaTxPwDiff[2] = 0; + priv->AntennaTxPwDiff[1] = 0; + priv->AntennaTxPwDiff[0] = (u8)(ant_pwr_diff); + RT_TRACE(COMP_POWER, "pHalData->AntennaTxPwDiff[0]/[1]/[2] = 0x%x/0x%x/0x%x\n", + priv->AntennaTxPwDiff[0], priv->AntennaTxPwDiff[1], priv->AntennaTxPwDiff[2]); + u4RegValue = ( priv->AntennaTxPwDiff[2]<<8 | + priv->AntennaTxPwDiff[1]<<4 | + priv->AntennaTxPwDiff[0] ); + RT_TRACE(COMP_POWER, "BCD-Diff=0x%x\n", u4RegValue); + + rtl8192_setBBreg(dev, rFPGA0_TxGainStage, (bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue); + +#ifdef TODO + if( priv->rtllib->iw_mode != IW_MODE_INFRA && priv->bWithCcxCellPwr && + channel == priv->rtllib->current_network.channel) + { + u8 CckCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_B, priv->CcxCellPwr); + u8 LegacyOfdmCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_G, priv->CcxCellPwr); + u8 OfdmCellPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_N_24G, priv->CcxCellPwr); + + RT_TRACE(COMP_TXAGC, + ("CCX Cell Limit: %d dbm => CCK Tx power index : %d, Legacy OFDM Tx power index : %d, OFDM Tx power index: %d\n", + priv->CcxCellPwr, CckCellPwrIdx, LegacyOfdmCellPwrIdx, OfdmCellPwrIdx)); + RT_TRACE(COMP_TXAGC, + ("EEPROM channel(%d) => CCK Tx power index: %d, Legacy OFDM Tx power index : %d, OFDM Tx power index: %d\n", + channel, powerlevel, powerlevelOFDM24G + priv->LegacyHTTxPowerDiff, powerlevelOFDM24G)); + + if(powerlevel > CckCellPwrIdx) + powerlevel = CckCellPwrIdx; + if(powerlevelOFDM24G + priv->LegacyHTTxPowerDiff > LegacyOfdmCellPwrIdx) + { + if((OfdmCellPwrIdx - priv->LegacyHTTxPowerDiff) > 0) + { + powerlevelOFDM24G = OfdmCellPwrIdx - priv->LegacyHTTxPowerDiff; + } + else + { + powerlevelOFDM24G = 0; + } + } + + RT_TRACE(COMP_TXAGC, + ("Altered CCK Tx power index : %d, Legacy OFDM Tx power index: %d, OFDM Tx power index: %d\n", + powerlevel, powerlevelOFDM24G + priv->LegacyHTTxPowerDiff, powerlevelOFDM24G)); + } +#endif + priv->CurrentCckTxPwrIdx = powerlevel; + priv->CurrentOfdm24GTxPwrIdx = powerlevelOFDM24G; + + RT_TRACE(COMP_POWER, "PHY_SetTxPowerLevel8192S(): CCK Tx power index : %d, Legacy OFDM Tx power index: %d, OFDM Tx power index: %d\n", + powerlevel, powerlevelOFDM24G + priv->LegacyHTTxPowerDiff, powerlevelOFDM24G); + + switch(priv->rf_chip) + { + case RF_8225: + break; + + case RF_8256: + break; + + case RF_6052: + PHY_RF6052SetCckTxPower(dev, powerlevel); + PHY_RF6052SetOFDMTxPower(dev, powerlevelOFDM24G, channel); + break; + + case RF_8258: + break; + default: + break; + } + +} +#endif + +bool PHY_UpdateTxPowerDbm8192S(struct net_device* dev, long powerInDbm) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 idx; + u8 rf_path; + + u8 CckTxPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_B, powerInDbm); + u8 OfdmTxPwrIdx = phy_DbmToTxPwrIdx(dev, WIRELESS_MODE_N_24G, powerInDbm); + + if(OfdmTxPwrIdx - priv->LegacyHTTxPowerDiff > 0) + OfdmTxPwrIdx -= priv->LegacyHTTxPowerDiff; + else + OfdmTxPwrIdx = 0; + + RT_TRACE(COMP_POWER, "PHY_UpdateTxPowerDbm8192S(): %ld dBm , CckTxPwrIdx = %d, OfdmTxPwrIdx = %d\n", powerInDbm, CckTxPwrIdx, OfdmTxPwrIdx); + + for(idx = 0; idx < 14; idx++) + { + priv->TxPowerLevelCCK[idx] = CckTxPwrIdx; + priv->TxPowerLevelCCK_A[idx] = CckTxPwrIdx; + priv->TxPowerLevelCCK_C[idx] = CckTxPwrIdx; + priv->TxPowerLevelOFDM24G[idx] = OfdmTxPwrIdx; + priv->TxPowerLevelOFDM24G_A[idx] = OfdmTxPwrIdx; + priv->TxPowerLevelOFDM24G_C[idx] = OfdmTxPwrIdx; + for (rf_path = 0; rf_path < 2; rf_path++) + { + priv->RfTxPwrLevelCck[rf_path][idx] = CckTxPwrIdx; + priv->RfTxPwrLevelOfdm1T[rf_path][idx] = + priv->RfTxPwrLevelOfdm2T[rf_path][idx] = OfdmTxPwrIdx; + } + } + + rtl8192_phy_setTxPower(dev, priv->chan); + + return true; +} + +extern void PHY_SetBeaconHwReg( struct net_device* dev, u16 BeaconInterval) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 NewBeaconNum; + + if(priv->pFirmware->FirmwareVersion >= 0x33) + { + write_nic_dword(dev,WFM5,0xF1000000|(BeaconInterval<<8)); + } + else + { + NewBeaconNum = BeaconInterval *32 - 64; + write_nic_dword(dev, WFM3+4, NewBeaconNum); + write_nic_dword(dev, WFM3, 0xB026007C); +} +} + +static u8 phy_DbmToTxPwrIdx( + struct net_device* dev, + WIRELESS_MODE WirelessMode, + long PowerInDbm + ) +{ + u8 TxPwrIdx = 0; + long Offset = 0; + + + switch(WirelessMode) + { + case WIRELESS_MODE_B: + Offset = -7; + break; + + case WIRELESS_MODE_G: + Offset = -8; + break; + + case WIRELESS_MODE_N_24G: + default: + Offset = -8; + break; + } + + if((PowerInDbm - Offset) > 0) + { + TxPwrIdx = (u8)((PowerInDbm - Offset) * 2); + } + else + { + TxPwrIdx = 0; + } + + if(TxPwrIdx > MAX_TXPWR_IDX_NMODE_92S) + TxPwrIdx = MAX_TXPWR_IDX_NMODE_92S; + + return TxPwrIdx; +} + +static long phy_TxPwrIdxToDbm( + struct net_device* dev, + WIRELESS_MODE WirelessMode, + u8 TxPwrIdx + ) +{ + long Offset = 0; + long PwrOutDbm = 0; + + switch(WirelessMode) + { + case WIRELESS_MODE_B: + Offset = -7; + break; + + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + Offset = -8; + break; + default: + Offset = -8; + break; + } + + PwrOutDbm = TxPwrIdx / 2 + Offset; + + return PwrOutDbm; +} + +extern void +PHY_ScanOperationBackup8192S( + struct net_device* dev, + u8 Operation + ) +{ +#if(RTL8192S_DISABLE_FW_DM == 0) + + struct r8192_priv *priv = rtllib_priv(dev); + + if(priv->up) + { + switch(Operation) + { + case SCAN_OPT_BACKUP: + priv->rtllib->SetFwCmdHandler(dev, FW_CMD_PAUSE_DM_BY_SCAN); + break; + + case SCAN_OPT_RESTORE: + priv->rtllib->SetFwCmdHandler(dev, FW_CMD_RESUME_DM_BY_SCAN); + break; + + default: + RT_TRACE(COMP_SCAN, "Unknown Scan Backup Operation. \n"); + break; + } + } +#endif +} + +void PHY_SetBWModeCallback8192S(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 regBwOpMode, regRRSR_RSC; + + + + RT_TRACE(COMP_SWBW, "==>SetBWModeCallback8192s() Switch to %s bandwidth\n", \ + priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20?"20MHz":"40MHz"); + + if(priv->rf_chip == RF_PSEUDO_11N) + { + priv->SetBWModeInProgress= false; + return; + } + if(IS_NIC_DOWN(priv)){ + priv->SwChnlInProgress = priv->SetBWModeInProgress = false; + return; + } + + regBwOpMode = read_nic_byte(dev, BW_OPMODE); + regRRSR_RSC = read_nic_byte(dev, RRSR+2); + + switch(priv->CurrentChannelBW) + { + case HT_CHANNEL_WIDTH_20: + regBwOpMode |= BW_OPMODE_20MHZ; + write_nic_byte(dev, BW_OPMODE, regBwOpMode); + break; + + case HT_CHANNEL_WIDTH_20_40: + regBwOpMode &= ~BW_OPMODE_20MHZ; + write_nic_byte(dev, BW_OPMODE, regBwOpMode); + + break; + + default: + RT_TRACE(COMP_DBG, "SetBWModeCallback8192s():\ + unknown Bandwidth: %#X\n",priv->CurrentChannelBW); + break; + } + + switch(priv->CurrentChannelBW) + { + case HT_CHANNEL_WIDTH_20: + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x0); + rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x0); + + if(priv->card_8192_version >= VERSION_8192S_BCUT) + write_nic_byte(dev, rFPGA0_AnalogParameter2, 0x58); + break; + + case HT_CHANNEL_WIDTH_20_40: + rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x1); + rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x1); + + + rtl8192_setBBreg(dev, rCCK0_System, bCCKSideBand, (priv->nCur40MhzPrimeSC>>1)); + rtl8192_setBBreg(dev, rOFDM1_LSTF, 0xC00, priv->nCur40MhzPrimeSC); + + if(priv->card_8192_version >= VERSION_8192S_BCUT) + write_nic_byte(dev, rFPGA0_AnalogParameter2, 0x18); + break; + + default: + RT_TRACE(COMP_DBG, "SetBWModeCallback8192s(): unknown Bandwidth: %#X\n"\ + ,priv->CurrentChannelBW); + break; + + } + + + switch( priv->rf_chip ) + { + case RF_8225: + break; + + case RF_8256: + break; + + case RF_8258: + break; + + case RF_PSEUDO_11N: + break; + + case RF_6052: + PHY_RF6052SetBandwidth(dev, priv->CurrentChannelBW); + break; + default: + printk("Unknown rf_chip: %d\n", priv->rf_chip); + break; + } + + priv->SetBWModeInProgress= false; + + RT_TRACE(COMP_SWBW, "<==SetBWModeCallback8192s() \n" ); +} + + +void rtl8192_SetBWMode(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + + + + + if(priv->SetBWModeInProgress) + return; + + priv->SetBWModeInProgress= true; + + priv->CurrentChannelBW = Bandwidth; + + if(Offset==HT_EXTCHNL_OFFSET_LOWER) + priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_UPPER; + else if(Offset==HT_EXTCHNL_OFFSET_UPPER) + priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_LOWER; + else + priv->nCur40MhzPrimeSC = HAL_PRIME_CHNL_OFFSET_DONT_CARE; + +#if 0 + if(!priv->bDriverStopped) + { +#ifdef USE_WORKITEM + PlatformScheduleWorkItem(&(priv->SetBWModeWorkItem)); +#else + PlatformSetTimer(dev, &(priv->SetBWModeTimer), 0); +#endif + } +#endif + if(!IS_NIC_DOWN(priv)){ + PHY_SetBWModeCallback8192S(dev); + } else { + priv->SetBWModeInProgress= false; + } +} + +void PHY_SwChnlCallback8192S(struct net_device *dev) +{ + + struct r8192_priv *priv = rtllib_priv(dev); + u32 delay; + + RT_TRACE(COMP_CH, "==>SwChnlCallback8190Pci(), switch to channel %d\n", priv->chan); + + if(IS_NIC_DOWN(priv)) + { + printk("%s: driver is not up\n", __FUNCTION__); + priv->SwChnlInProgress = priv->SetBWModeInProgress = false; + return; + } + if(priv->rf_chip == RF_PSEUDO_11N) + { + printk("%s: rt chip is RF_PSEUDO_11N\n", __FUNCTION__); + priv->SwChnlInProgress=false; + return; + } + + do{ + if(!priv->SwChnlInProgress) + break; + + if(!phy_SwChnlStepByStep(dev, priv->chan, &priv->SwChnlStage, &priv->SwChnlStep, &delay)) + { + if(delay>0) + { + mdelay(delay); + } + else + continue; + } + else + { + priv->SwChnlInProgress=false; + break; + } + }while(true); +} + +u8 rtl8192_phy_SwChnl(struct net_device* dev, u8 channel) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + if(IS_NIC_DOWN(priv)) + { + printk("%s: driver is not up.\n",__FUNCTION__); + priv->SwChnlInProgress = priv->SetBWModeInProgress = false; + return false; + } + if(priv->SwChnlInProgress){ + printk("%s: SwChnl is in progress\n",__FUNCTION__); + return false; + } + + if(priv->SetBWModeInProgress){ + printk("%s: Set BWMode is in progress\n",__FUNCTION__); + return false; + } + if (0) + { + u8 path; + for(path=0; path<2; path++){ + printk("============>to set channel:%x\n", rtl8192_phy_QueryRFReg(dev, path, 0x18, 0x3ff)); + udelay(10); + } + } + switch(priv->rtllib->mode) + { + case WIRELESS_MODE_A: + case WIRELESS_MODE_N_5G: + if (channel<=14){ + RT_TRACE(COMP_ERR, "WIRELESS_MODE_A but channel<=14"); + return false; + } + break; + + case WIRELESS_MODE_B: + if (channel>14){ + RT_TRACE(COMP_ERR, "WIRELESS_MODE_B but channel>14"); + return false; + } + break; + + case WIRELESS_MODE_G: + case WIRELESS_MODE_N_24G: + if (channel>14){ + RT_TRACE(COMP_ERR, "WIRELESS_MODE_G but channel>14"); + return false; + } + break; + + default: + break; + } + + priv->SwChnlInProgress = true; + if( channel == 0) + channel = 1; + + priv->chan=channel; + + priv->SwChnlStage=0; + priv->SwChnlStep=0; + +#if 0 + if(!dev->bDriverStopped) + { +#ifdef USE_WORKITEM + PlatformScheduleWorkItem(&(priv->SwChnlWorkItem)); +#else + PlatformSetTimer(dev, &(priv->SwChnlTimer), 0); +#endif + } +#endif + + if(!IS_NIC_DOWN(priv)){ + PHY_SwChnlCallback8192S(dev); + } else { + priv->SwChnlInProgress = false; + } + return true; +} + + +void PHY_SwChnlPhy8192S( + struct net_device* dev, + u8 channel + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + RT_TRACE(COMP_SCAN, "==>PHY_SwChnlPhy8192S(), switch to channel %d.\n", priv->chan); + +#ifdef TO_DO_LIST + if(RT_CANNOT_IO(dev)) + return; +#endif + + if(priv->SwChnlInProgress) + return; + + if(priv->rf_chip == RF_PSEUDO_11N) + { + priv->SwChnlInProgress=false; + return; + } + + priv->SwChnlInProgress = true; + if( channel == 0) + channel = 1; + + priv->chan=channel; + + priv->SwChnlStage = 0; + priv->SwChnlStep = 0; + + phy_FinishSwChnlNow(dev,channel); + + priv->SwChnlInProgress = false; +} + +static bool +phy_SwChnlStepByStep( + struct net_device* dev, + u8 channel, + u8 *stage, + u8 *step, + u32 *delay + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + SwChnlCmd PreCommonCmd[MAX_PRECMD_CNT]; + u32 PreCommonCmdCnt; + SwChnlCmd PostCommonCmd[MAX_POSTCMD_CNT]; + u32 PostCommonCmdCnt; + SwChnlCmd RfDependCmd[MAX_RFDEPENDCMD_CNT]; + u32 RfDependCmdCnt; + SwChnlCmd *CurrentCmd = NULL; + u8 eRFPath; + u16 u2Channel = 0; + + RT_TRACE(COMP_CH, "===========>%s(), channel:%d, stage:%d, step:%d\n", __FUNCTION__, channel, *stage, *step); + if (!IsLegalChannel(priv->rtllib, channel)) + { + RT_TRACE(COMP_ERR, "=============>set to illegal channel:%d\n", channel); + return true; + } + + + PreCommonCmdCnt = 0; + phy_SetSwChnlCmdArray(PreCommonCmd, PreCommonCmdCnt++, MAX_PRECMD_CNT, + CmdID_SetTxPowerLevel, 0, 0, 0); + phy_SetSwChnlCmdArray(PreCommonCmd, PreCommonCmdCnt++, MAX_PRECMD_CNT, + CmdID_End, 0, 0, 0); + + PostCommonCmdCnt = 0; + + phy_SetSwChnlCmdArray(PostCommonCmd, PostCommonCmdCnt++, MAX_POSTCMD_CNT, + CmdID_End, 0, 0, 0); + + RfDependCmdCnt = 0; + switch( priv->rf_chip ) + { + case RF_8225: + if (channel < 1 || channel > 14) + RT_TRACE(COMP_ERR, "illegal channel for zebra:%d\n", channel); + phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, + CmdID_RF_WriteReg, rRfChannel, channel, 10); + phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, + CmdID_End, 0, 0, 0); + break; + + case RF_8256: + if (channel < 1 || channel > 14) + RT_TRACE(COMP_ERR, "illegal channel for zebra:%d\n", channel); + phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, + CmdID_RF_WriteReg, rRfChannel, channel, 10); + phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, + CmdID_End, 0, 0, 0); + break; + + case RF_6052: + if (channel < 1 || channel > 14) + RT_TRACE(COMP_ERR, "illegal channel for zebra:%d\n", channel); + + u2Channel = channel; + + switch(priv->CurrentChannelBW) + { + case HT_CHANNEL_WIDTH_20: + u2Channel |= BIT10; + break; + + case HT_CHANNEL_WIDTH_20_40: + u2Channel &= ~BIT10; + break; + default: + u2Channel |= BIT10; + break; + } + u2Channel |= BIT12|BIT13|BIT14; + + phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, + CmdID_RF_WriteReg, RF_CHNLBW, u2Channel, 10); + phy_SetSwChnlCmdArray(RfDependCmd, RfDependCmdCnt++, MAX_RFDEPENDCMD_CNT, + CmdID_End, 0, 0, 0); + break; + + case RF_8258: + break; + + default: + return false; + break; + } + + + do{ + switch(*stage) + { + case 0: + CurrentCmd=&PreCommonCmd[*step]; + break; + case 1: + CurrentCmd=&RfDependCmd[*step]; + break; + case 2: + CurrentCmd=&PostCommonCmd[*step]; + break; + } + + if(CurrentCmd->CmdID==CmdID_End) + { + if((*stage)==2) + { + return true; + } + else + { + (*stage)++; + (*step)=0; + continue; + } + } + + switch(CurrentCmd->CmdID) + { + case CmdID_SetTxPowerLevel: +#ifndef CONFIG_MP + rtl8192_phy_setTxPower(dev,channel); +#endif + break; + case CmdID_WritePortUlong: + write_nic_dword(dev, CurrentCmd->Para1, CurrentCmd->Para2); + break; + case CmdID_WritePortUshort: + write_nic_word(dev, CurrentCmd->Para1, (u16)CurrentCmd->Para2); + break; + case CmdID_WritePortUchar: + write_nic_byte(dev, CurrentCmd->Para1, (u8)CurrentCmd->Para2); + break; + case CmdID_RF_WriteReg: + for(eRFPath = 0; eRFPath NumTotalRFPath; eRFPath++) + { + if (IS_HARDWARE_TYPE_8192SE(dev)) { +#ifdef CONFIG_FW_SETCHAN + u32 rf_bw = ((priv->RfRegChnlVal[eRFPath] & 0xfffffc00) | (CurrentCmd->Para2 & 0xFF00)); +#endif + priv->RfRegChnlVal[eRFPath] = ((priv->RfRegChnlVal[eRFPath] & 0xfffffc00) | CurrentCmd->Para2); + +#ifdef CONFIG_FW_SETCHAN + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, CurrentCmd->Para1, bRFRegOffsetMask, rf_bw); +#else + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, CurrentCmd->Para1, bRFRegOffsetMask, priv->RfRegChnlVal[eRFPath]); +#endif + } else { + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, CurrentCmd->Para1, bRFRegOffsetMask, (CurrentCmd->Para2)); + } + } + break; + default: + break; + } + + break; + }while(true); + + (*delay)=CurrentCmd->msDelay; + (*step)++; + RT_TRACE(COMP_CH, "<===========%s(), channel:%d, stage:%d, step:%d\n", __FUNCTION__, channel, *stage, *step); + return false; +} + +static bool +phy_SetSwChnlCmdArray( + SwChnlCmd* CmdTable, + u32 CmdTableIdx, + u32 CmdTableSz, + SwChnlCmdID CmdID, + u32 Para1, + u32 Para2, + u32 msDelay + ) +{ + SwChnlCmd* pCmd; + + if(CmdTable == NULL) + { + return false; + } + if(CmdTableIdx >= CmdTableSz) + { + return false; + } + + pCmd = CmdTable + CmdTableIdx; + pCmd->CmdID = CmdID; + pCmd->Para1 = Para1; + pCmd->Para2 = Para2; + pCmd->msDelay = msDelay; + + return true; +} + +static void +phy_FinishSwChnlNow( + struct net_device* dev, + u8 channel + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 delay; + + while(!phy_SwChnlStepByStep(dev,channel,&priv->SwChnlStage,&priv->SwChnlStep,&delay)) + { + if(delay>0) + mdelay(delay); + if(IS_NIC_DOWN(priv)) + break; + } +} + + +u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev, u32 eRFPath) +{ + bool rtValue = true; + +#if 0 + if (priv->rf_type == RF_1T2R && eRFPath != RF90_PATH_A) + { + rtValue = false; + } + if (priv->rf_type == RF_1T2R && eRFPath != RF90_PATH_A) + { + + } +#endif + return rtValue; + +} /* PHY_CheckIsLegalRfPath8192S */ + + + +void +PHY_IQCalibrate( struct net_device* dev) +{ + u32 i, reg; + u32 old_value; + long X, Y, TX0[4]; + u32 TXA[4]; + + + for (i = 0; i < 10; i++) + { + rtl8192_setBBreg(dev, 0xc04, bMaskDWord, 0x00a05430); + udelay(5); + rtl8192_setBBreg(dev, 0xc08, bMaskDWord, 0x000800e4); + udelay(5); + rtl8192_setBBreg(dev, 0xe28, bMaskDWord, 0x80800000); + udelay(5); + rtl8192_setBBreg(dev, 0xe40, bMaskDWord, 0x02140148); + udelay(5); + rtl8192_setBBreg(dev, 0xe44, bMaskDWord, 0x681604a2); + udelay(5); + rtl8192_setBBreg(dev, 0xe4c, bMaskDWord, 0x000028d1); + udelay(5); + rtl8192_setBBreg(dev, 0xe60, bMaskDWord, 0x0214014d); + udelay(5); + rtl8192_setBBreg(dev, 0xe64, bMaskDWord, 0x281608ba); + udelay(5); + rtl8192_setBBreg(dev, 0xe6c, bMaskDWord, 0x000028d1); + udelay(5); + rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xfb000001); + udelay(5); + rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xf8000001); + udelay(2000); + rtl8192_setBBreg(dev, 0xc04, bMaskDWord, 0x00a05433); + udelay(5); + rtl8192_setBBreg(dev, 0xc08, bMaskDWord, 0x000000e4); + udelay(5); + rtl8192_setBBreg(dev, 0xe28, bMaskDWord, 0x0); + + + reg = rtl8192_QueryBBReg(dev, 0xeac, bMaskDWord); + + if (!(reg&(BIT27|BIT28|BIT30|BIT31))) + { + old_value = (rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord) & 0x3FF); + + X = (rtl8192_QueryBBReg(dev, 0xe94, bMaskDWord) & 0x03FF0000)>>16; + TXA[RF90_PATH_A] = (X * old_value)/0x100; + reg = rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord); + reg = (reg & 0xFFFFFC00) | (u32)TXA[RF90_PATH_A]; + rtl8192_setBBreg(dev, 0xc80, bMaskDWord, reg); + udelay(5); + + Y = ( rtl8192_QueryBBReg(dev, 0xe9C, bMaskDWord) & 0x03FF0000)>>16; + TX0[RF90_PATH_C] = ((Y * old_value)/0x100); + reg = rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord); + reg = (reg & 0xffc0ffff) |((u32) (TX0[RF90_PATH_C]&0x3F)<<16); + rtl8192_setBBreg(dev, 0xc80, bMaskDWord, reg); + reg = rtl8192_QueryBBReg(dev, 0xc94, bMaskDWord); + reg = (reg & 0x0fffffff) |(((Y&0x3c0)>>6)<<28); + rtl8192_setBBreg(dev, 0xc94, bMaskDWord, reg); + udelay(5); + + reg = rtl8192_QueryBBReg(dev, 0xc14, bMaskDWord); + X = (rtl8192_QueryBBReg(dev, 0xea4, bMaskDWord) & 0x03FF0000)>>16; + reg = (reg & 0xFFFFFC00) |X; + rtl8192_setBBreg(dev, 0xc14, bMaskDWord, reg); + Y = (rtl8192_QueryBBReg(dev, 0xeac, bMaskDWord) & 0x003F0000)>>16; + reg = (reg & 0xFFFF03FF) |Y<<10; + rtl8192_setBBreg(dev, 0xc14, bMaskDWord, reg); + udelay(5); + old_value = (rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord) & 0x3FF); + + X = (rtl8192_QueryBBReg(dev, 0xeb4, bMaskDWord) & 0x03FF0000)>>16; + reg = rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord); + TXA[RF90_PATH_A] = (X * old_value) / 0x100; + reg = (reg & 0xFFFFFC00) | TXA[RF90_PATH_A]; + rtl8192_setBBreg(dev, 0xc88, bMaskDWord, reg); + udelay(5); + + Y = (rtl8192_QueryBBReg(dev, 0xebc, bMaskDWord)& 0x03FF0000)>>16; + TX0[RF90_PATH_C] = ((Y * old_value)/0x100); + reg = rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord); + reg = (reg & 0xffc0ffff) |( (TX0[RF90_PATH_C]&0x3F)<<16); + rtl8192_setBBreg(dev, 0xc88, bMaskDWord, reg); + reg = rtl8192_QueryBBReg(dev, 0xc9c, bMaskDWord); + reg = (reg & 0x0fffffff) |(((Y&0x3c0)>>6)<<28); + rtl8192_setBBreg(dev, 0xc9c, bMaskDWord, reg); + udelay(5); + + reg = rtl8192_QueryBBReg(dev, 0xc1c, bMaskDWord); + X = (rtl8192_QueryBBReg(dev, 0xec4, bMaskDWord) & 0x03FF0000)>>16; + reg = (reg & 0xFFFFFC00) |X; + rtl8192_setBBreg(dev, 0xc1c, bMaskDWord, reg); + + Y = (rtl8192_QueryBBReg(dev, 0xecc, bMaskDWord) & 0x003F0000)>>16; + reg = (reg & 0xFFFF03FF) |Y<<10; + rtl8192_setBBreg(dev, 0xc1c, bMaskDWord, reg); + udelay(5); + + RT_TRACE(COMP_INIT, "PHY_IQCalibrate OK\n"); + break; + } + + } + + + + +} + +extern void PHY_IQCalibrateBcut(struct net_device* dev) +{ + u32 i, reg; + u32 old_value; + long X, Y, TX0[4]; + u32 TXA[4]; + u32 calibrate_set[13] = {0}; + u32 load_value[13]; + u8 RfPiEnable=0; + + /* + 0xee0[31:0]=0x3fed92fb; + 0xedc[31:0] =0x3fed92fb; + 0xe70[31:0] =0x3fed92fb; + 0xe74[31:0] =0x3fed92fb; + 0xe78[31:0] =0x3fed92fb; + 0xe7c[31:0]= 0x3fed92fb; + 0xe80[31:0]= 0x3fed92fb; + 0xe84[31:0]= 0x3fed92fb; + 0xe88[31:0]= 0x3fed92fb; + 0xe8c[31:0]= 0x3fed92fb; + 0xed0[31:0]= 0x3fed92fb; + 0xed4[31:0]= 0x3fed92fb; + 0xed8[31:0]= 0x3fed92fb; + */ + calibrate_set [0] = 0xee0; + calibrate_set [1] = 0xedc; + calibrate_set [2] = 0xe70; + calibrate_set [3] = 0xe74; + calibrate_set [4] = 0xe78; + calibrate_set [5] = 0xe7c; + calibrate_set [6] = 0xe80; + calibrate_set [7] = 0xe84; + calibrate_set [8] = 0xe88; + calibrate_set [9] = 0xe8c; + calibrate_set [10] = 0xed0; + calibrate_set [11] = 0xed4; + calibrate_set [12] = 0xed8; + for (i = 0; i < 13; i++) + { + load_value[i] = rtl8192_QueryBBReg(dev, calibrate_set[i], bMaskDWord); + rtl8192_setBBreg(dev, calibrate_set[i], bMaskDWord, 0x3fed92fb); + + } + + RfPiEnable = (u8)rtl8192_QueryBBReg(dev, rFPGA0_XA_HSSIParameter1, BIT8); + for (i = 0; i < 10; i++) + { + RT_TRACE(COMP_INIT, "IQK -%d\n", i); + if (!RfPiEnable) + { + rtl8192_setBBreg(dev, 0x820, bMaskDWord, 0x01000100); + rtl8192_setBBreg(dev, 0x828, bMaskDWord, 0x01000100); + } + + rtl8192_setBBreg(dev, 0xc04, bMaskDWord, 0x00a05430); + udelay(5); + rtl8192_setBBreg(dev, 0xc08, bMaskDWord, 0x000800e4); + udelay(5); + rtl8192_setBBreg(dev, 0xe28, bMaskDWord, 0x80800000); + udelay(5); + rtl8192_setBBreg(dev, 0xe40, bMaskDWord, 0x02140102); + udelay(5); + rtl8192_setBBreg(dev, 0xe44, bMaskDWord, 0x681604c2); + udelay(5); + rtl8192_setBBreg(dev, 0xe4c, bMaskDWord, 0x000028d1); + udelay(5); + rtl8192_setBBreg(dev, 0xe60, bMaskDWord, 0x02140102); + udelay(5); + rtl8192_setBBreg(dev, 0xe64, bMaskDWord, 0x28160d05); + udelay(5); + rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xfb000000); + udelay(5); + rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xf8000000); + udelay(5); + + udelay(2000); + + rtl8192_setBBreg(dev, 0xe6c, bMaskDWord, 0x020028d1); + udelay(5); + rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xfb000000); + udelay(5); + rtl8192_setBBreg(dev, 0xe48, bMaskDWord, 0xf8000000); + + udelay(2000); + + rtl8192_setBBreg(dev, 0xc04, bMaskDWord, 0x00a05433); + udelay(5); + rtl8192_setBBreg(dev, 0xc08, bMaskDWord, 0x000000e4); + udelay(5); + rtl8192_setBBreg(dev, 0xe28, bMaskDWord, 0x0); + + if (!RfPiEnable) + { + rtl8192_setBBreg(dev, 0x820, bMaskDWord, 0x01000000); + rtl8192_setBBreg(dev, 0x828, bMaskDWord, 0x01000000); + } + + + reg = rtl8192_QueryBBReg(dev, 0xeac, bMaskDWord); + + if (!(reg&(BIT27|BIT28|BIT30|BIT31))) + { + old_value = (rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord) & 0x3FF); + + X = (rtl8192_QueryBBReg(dev, 0xe94, bMaskDWord) & 0x03FF0000)>>16; + TXA[RF90_PATH_A] = (X * old_value)/0x100; + reg = rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord); + reg = (reg & 0xFFFFFC00) | (u32)TXA[RF90_PATH_A]; + rtl8192_setBBreg(dev, 0xc80, bMaskDWord, reg); + udelay(5); + + Y = ( rtl8192_QueryBBReg(dev, 0xe9C, bMaskDWord) & 0x03FF0000)>>16; + TX0[RF90_PATH_C] = ((Y * old_value)/0x100); + reg = rtl8192_QueryBBReg(dev, 0xc80, bMaskDWord); + reg = (reg & 0xffc0ffff) |((u32) (TX0[RF90_PATH_C]&0x3F)<<16); + rtl8192_setBBreg(dev, 0xc80, bMaskDWord, reg); + reg = rtl8192_QueryBBReg(dev, 0xc94, bMaskDWord); + reg = (reg & 0x0fffffff) |(((Y&0x3c0)>>6)<<28); + rtl8192_setBBreg(dev, 0xc94, bMaskDWord, reg); + udelay(5); + + reg = rtl8192_QueryBBReg(dev, 0xc14, bMaskDWord); + X = (rtl8192_QueryBBReg(dev, 0xea4, bMaskDWord) & 0x03FF0000)>>16; + reg = (reg & 0xFFFFFC00) |X; + rtl8192_setBBreg(dev, 0xc14, bMaskDWord, reg); + Y = (rtl8192_QueryBBReg(dev, 0xeac, bMaskDWord) & 0x003F0000)>>16; + reg = (reg & 0xFFFF03FF) |Y<<10; + rtl8192_setBBreg(dev, 0xc14, bMaskDWord, reg); + udelay(5); + old_value = (rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord) & 0x3FF); + + X = (rtl8192_QueryBBReg(dev, 0xeb4, bMaskDWord) & 0x03FF0000)>>16; + reg = rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord); + TXA[RF90_PATH_A] = (X * old_value) / 0x100; + reg = (reg & 0xFFFFFC00) | TXA[RF90_PATH_A]; + rtl8192_setBBreg(dev, 0xc88, bMaskDWord, reg); + udelay(5); + + Y = (rtl8192_QueryBBReg(dev, 0xebc, bMaskDWord)& 0x03FF0000)>>16; + TX0[RF90_PATH_C] = ((Y * old_value)/0x100); + reg = rtl8192_QueryBBReg(dev, 0xc88, bMaskDWord); + reg = (reg & 0xffc0ffff) |( (TX0[RF90_PATH_C]&0x3F)<<16); + rtl8192_setBBreg(dev, 0xc88, bMaskDWord, reg); + reg = rtl8192_QueryBBReg(dev, 0xc9c, bMaskDWord); + reg = (reg & 0x0fffffff) |(((Y&0x3c0)>>6)<<28); + rtl8192_setBBreg(dev, 0xc9c, bMaskDWord, reg); + udelay(5); + + reg = rtl8192_QueryBBReg(dev, 0xc1c, bMaskDWord); + X = (rtl8192_QueryBBReg(dev, 0xec4, bMaskDWord) & 0x03FF0000)>>16; + reg = (reg & 0xFFFFFC00) |X; + rtl8192_setBBreg(dev, 0xc1c, bMaskDWord, reg); + + Y = (rtl8192_QueryBBReg(dev, 0xecc, bMaskDWord) & 0x003F0000)>>16; + reg = (reg & 0xFFFF03FF) |Y<<10; + rtl8192_setBBreg(dev, 0xc1c, bMaskDWord, reg); + udelay(5); + + RT_TRACE(COMP_INIT, "PHY_IQCalibrate OK\n"); + break; + } + + } + + for (i = 0; i < 13; i++) + rtl8192_setBBreg(dev, calibrate_set[i], bMaskDWord, load_value[i]); + + + + + +} + +#define HalGetFirmwareVerison(priv) (priv->pFirmware->FirmwareVersion ) +bool rtl8192se_set_fw_cmd(struct net_device* dev, FW_CMD_IO_TYPE FwCmdIO) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 FwParam = FW_CMD_IO_PARA_QUERY(priv); + u16 FwCmdMap = FW_CMD_IO_QUERY(priv); + bool bPostProcessing = false; + + RT_TRACE(COMP_CMD, "-->HalSetFwCmd8192S(): Set FW Cmd(%#x), SetFwCmdInProgress(%d)\n", FwCmdIO, priv->SetFwCmdInProgress); + + + + + + RT_TRACE(COMP_CMD, "-->HalSetFwCmd8192S(): Set FW Cmd(%#x), SetFwCmdInProgress(%d)\n", + FwCmdIO, priv->SetFwCmdInProgress); + + do{ + + if(HalGetFirmwareVerison(priv) >= 0x35) + { + switch(FwCmdIO) + { + case FW_CMD_RA_REFRESH_N: + FwCmdIO = FW_CMD_RA_REFRESH_N_COMB; + break; + case FW_CMD_RA_REFRESH_BG: + FwCmdIO = FW_CMD_RA_REFRESH_BG_COMB; + break; + default: + break; + } + } + else + { + if((FwCmdIO == FW_CMD_IQK_ENABLE) || + (FwCmdIO == FW_CMD_RA_REFRESH_N) || + (FwCmdIO == FW_CMD_RA_REFRESH_BG)) + { + bPostProcessing = true; + break; + } + } + + if(HalGetFirmwareVerison(priv) >= 0x3E) + { + if(FwCmdIO == FW_CMD_CTRL_DM_BY_DRIVER) + FwCmdIO = FW_CMD_CTRL_DM_BY_DRIVER_NEW; + } + + + switch(FwCmdIO) + { + + case FW_CMD_RA_INIT: + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] RA init!!\n"); + FwCmdMap |= FW_RA_INIT_CTL; + FW_CMD_IO_SET(priv, FwCmdMap); + FW_CMD_IO_CLR(priv, FW_RA_INIT_CTL); + break; + + case FW_CMD_DIG_DISABLE: + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set DIG disable!!\n"); + FwCmdMap &= ~FW_DIG_ENABLE_CTL; + FW_CMD_IO_SET(priv, FwCmdMap); + break; + + case FW_CMD_DIG_ENABLE: + case FW_CMD_DIG_RESUME: + if(!(priv->DMFlag & HAL_DM_DIG_DISABLE)) + { + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set DIG enable or resume!!\n"); + FwCmdMap |= (FW_DIG_ENABLE_CTL|FW_SS_CTL); + FW_CMD_IO_SET(priv, FwCmdMap); + } + break; + + case FW_CMD_DIG_HALT: + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set DIG halt!!\n"); + FwCmdMap &= ~(FW_DIG_ENABLE_CTL|FW_SS_CTL); + FW_CMD_IO_SET(priv, FwCmdMap); + break; + + case FW_CMD_TXPWR_TRACK_THERMAL: + { + u8 ThermalVal = 0; + FwCmdMap |= FW_PWR_TRK_CTL; + FwParam &= FW_PWR_TRK_PARAM_CLR; + ThermalVal = priv->ThermalValue; + FwParam |= ((ThermalVal<<24) |(priv->ThermalMeter[0]<<16)); + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set TxPwr tracking!! FwCmdMap(%#x), FwParam(%#x)\n", FwCmdMap, FwParam); + FW_CMD_PARA_SET(priv, FwParam); + FW_CMD_IO_SET(priv, FwCmdMap); + FW_CMD_IO_CLR(priv, FW_PWR_TRK_CTL); + } + break; + + case FW_CMD_RA_REFRESH_N_COMB: + FwCmdMap |= FW_RA_N_CTL; + FwCmdMap &= ~(FW_RA_BG_CTL |FW_RA_INIT_CTL); + FwParam &= FW_RA_PARAM_CLR; + if(!(priv->rtllib->pHTInfo->IOTRaFunc & HT_IOT_RAFUNC_DISABLE_ALL)) + FwParam |= ((priv->rtllib->pHTInfo->IOTRaFunc)&0xf); + FwParam |= ((priv->rtllib->pHTInfo->IOTPeer & 0xf) <<4); + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set RA/IOT Comb in n mode!! FwCmdMap(%#x), FwParam(%#x)\n", FwCmdMap, FwParam); + FW_CMD_PARA_SET(priv, FwParam); + FW_CMD_IO_SET(priv, FwCmdMap); + FW_CMD_IO_CLR(priv, FW_RA_N_CTL); + break; + + case FW_CMD_RA_REFRESH_BG_COMB: + FwCmdMap |= FW_RA_BG_CTL; + FwCmdMap &= ~(FW_RA_N_CTL|FW_RA_INIT_CTL); + FwParam &= FW_RA_PARAM_CLR; + if(!(priv->rtllib->pHTInfo->IOTRaFunc & HT_IOT_RAFUNC_DISABLE_ALL)) + FwParam |= ((priv->rtllib->pHTInfo->IOTRaFunc)&0xf); + FwParam |= ((priv->rtllib->pHTInfo->IOTPeer & 0xf) <<4); + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set RA/IOT Comb in BG mode!! FwCmdMap(%#x), FwParam(%#x)\n", FwCmdMap, FwParam); + FW_CMD_PARA_SET(priv, FwParam); + FW_CMD_IO_SET(priv, FwCmdMap); + FW_CMD_IO_CLR(priv, FW_RA_BG_CTL); + break; + + case FW_CMD_IQK_ENABLE: + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] IQK enable.\n"); + FwCmdMap |= FW_IQK_CTL; + FW_CMD_IO_SET(priv, FwCmdMap); + FW_CMD_IO_CLR(priv, FW_IQK_CTL); + break; + + case FW_CMD_CTRL_DM_BY_DRIVER_NEW: + RT_TRACE(COMP_CMD, "[FW CMD][New Version] Inform FW driver control some DM!! FwCmdMap(%#x), FwParam(%#x)\n", FwCmdMap, FwParam); + FwCmdMap |= FW_DRIVER_CTRL_DM_CTL; + FW_CMD_IO_SET(priv, FwCmdMap); + break; + + case FW_CMD_RESUME_DM_BY_SCAN: + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Resume DM after scan.\n"); + FwCmdMap |= (FW_DIG_ENABLE_CTL|FW_HIGH_PWR_ENABLE_CTL|FW_SS_CTL); + + if(priv->DMFlag & HAL_DM_DIG_DISABLE || !dm_digtable.dig_enable_flag) + FwCmdMap &= ~FW_DIG_ENABLE_CTL; + + if((priv->DMFlag & HAL_DM_HIPWR_DISABLE) || + (priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_HIGH_POWER) || + (priv->rtllib->bdynamic_txpower_enable == true)) + FwCmdMap &= ~FW_HIGH_PWR_ENABLE_CTL; + + if( (dm_digtable.Dig_Ext_Port_Stage == DIG_EXT_PORT_STAGE_0) || + (dm_digtable.Dig_Ext_Port_Stage == DIG_EXT_PORT_STAGE_1)) + FwCmdMap &= ~FW_DIG_ENABLE_CTL; + + FW_CMD_IO_SET(priv, FwCmdMap); + bPostProcessing = true; + break; + + case FW_CMD_PAUSE_DM_BY_SCAN: + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Pause DM before scan.\n"); + FwCmdMap &= ~(FW_DIG_ENABLE_CTL|FW_HIGH_PWR_ENABLE_CTL|FW_SS_CTL); + FW_CMD_IO_SET(priv, FwCmdMap); + bPostProcessing = true; + break; + + case FW_CMD_HIGH_PWR_DISABLE: + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set HighPwr disable!!\n"); + FwCmdMap &= ~FW_HIGH_PWR_ENABLE_CTL; + FW_CMD_IO_SET(priv, FwCmdMap); + bPostProcessing = true; + break; + + case FW_CMD_HIGH_PWR_ENABLE: + if(((priv->rtllib->pHTInfo->IOTAction & HT_IOT_ACT_DISABLE_HIGH_POWER)==0) && + !(priv->DMFlag & HAL_DM_HIPWR_DISABLE) && + (priv->rtllib->bdynamic_txpower_enable != true)) + { + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set HighPwr enable!!\n"); + FwCmdMap |= (FW_HIGH_PWR_ENABLE_CTL|FW_SS_CTL); + FW_CMD_IO_SET(priv, FwCmdMap); + bPostProcessing = true; + } + break; + + case FW_CMD_DIG_MODE_FA: + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set DIG Mode to FA.\n"); + FwCmdMap |= FW_FA_CTL; + FW_CMD_IO_SET(priv, FwCmdMap); + break; + + case FW_CMD_DIG_MODE_SS: + RT_TRACE(COMP_CMD, "[FW CMD] [New Version] Set DIG Mode to SS.\n"); + FwCmdMap &= ~FW_FA_CTL; + FW_CMD_IO_SET(priv, FwCmdMap); + break; + + case FW_CMD_PAPE_CONTROL: + RT_TRACE(COMP_CMD, "[FW CMD] Set PAPE Control \n"); +#ifdef MERGE_TO_DO + if(pHalData->bt_coexist.BT_PapeCtrl) + { + RTPRINT(FBT, BT_TRACE, ("BT set PAPE Control to SW/HW dynamically. \n")); + FwCmdMap |= FW_PAPE_CTL_BY_SW_HW; + } + else +#endif + { + printk("BT set PAPE Control to SW\n"); + FwCmdMap &= ~FW_PAPE_CTL_BY_SW_HW; + } + FW_CMD_IO_SET(priv, FwCmdMap); + break; + + default: + bPostProcessing = true; + break; + } + }while(false); + + RT_TRACE(COMP_CMD, "[FW CMD] Current FwCmdMap(%#x)\n", priv->FwCmdIOMap); + RT_TRACE(COMP_CMD, "[FW CMD] Current FwCmdIOParam(%#x)\n", priv->FwCmdIOParam); + + if(bPostProcessing && !priv->SetFwCmdInProgress) + { + priv->SetFwCmdInProgress = true; + priv->CurrentFwCmdIO = FwCmdIO; + } + else + { + return false; + } + +#if 0 +#ifdef USE_WORKITEM + PlatformScheduleWorkItem(&(pHalData->FwCmdIOWorkItem)); +#else + PlatformSetTimer(Adapter, &(pHalData->SetFwCmdIOTimer), 0); +#endif +#endif + rtl8192_SetFwCmdIOCallback(dev); + return true; +} +void ChkFwCmdIoDone(struct net_device* dev) +{ + u16 PollingCnt = 10000; + u32 tmpValue; + + do + { + + udelay(10); + + tmpValue = read_nic_dword(dev, WFM5); + if(tmpValue == 0) + { + RT_TRACE(COMP_CMD, "[FW CMD] Set FW Cmd success!!\n"); + break; + } + else + { + RT_TRACE(COMP_CMD, "[FW CMD] Polling FW Cmd PollingCnt(%d)!!\n", PollingCnt); + } + }while( --PollingCnt ); + + if(PollingCnt == 0) + { + RT_TRACE(COMP_ERR, "[FW CMD] Set FW Cmd fail!!\n"); + } +} +void rtl8192_SetFwCmdIOCallback(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 input,CurrentAID = 0; + + if(IS_NIC_DOWN(priv)){ + RT_TRACE(COMP_CMD, "SetFwCmdIOTimerCallback(): driver is going to unload\n"); + return; + } + + RT_TRACE(COMP_CMD, "--->SetFwCmdIOTimerCallback(): Cmd(%#x), SetFwCmdInProgress(%d)\n", priv->CurrentFwCmdIO, priv->SetFwCmdInProgress); + + if(HalGetFirmwareVerison(priv) >= 0x34) + { + switch(priv->CurrentFwCmdIO) + { + case FW_CMD_RA_REFRESH_N: + priv->CurrentFwCmdIO = FW_CMD_RA_REFRESH_N_COMB; + break; + case FW_CMD_RA_REFRESH_BG: + priv->CurrentFwCmdIO = FW_CMD_RA_REFRESH_BG_COMB; + break; + default: + break; + } + } + + switch(priv->CurrentFwCmdIO) + { + + case FW_CMD_RA_RESET: + RT_TRACE(COMP_CMD, "[FW CMD] Set RA Reset!!\n"); + write_nic_dword(dev, WFM5, FW_RA_RESET); + ChkFwCmdIoDone(dev); + break; + + case FW_CMD_RA_ACTIVE: + RT_TRACE(COMP_CMD, "[FW CMD] Set RA Active!!\n"); + write_nic_dword(dev, WFM5, FW_RA_ACTIVE); + ChkFwCmdIoDone(dev); + break; + + case FW_CMD_RA_REFRESH_N: + RT_TRACE(COMP_CMD, "[FW CMD] Set RA n refresh!!\n"); + if(priv->rtllib->pHTInfo->IOTRaFunc & HT_IOT_RAFUNC_DISABLE_ALL) + input = FW_RA_REFRESH; + else + input = FW_RA_REFRESH | (priv->rtllib->pHTInfo->IOTRaFunc << 8); + write_nic_dword(dev, WFM5, input); + ChkFwCmdIoDone(dev); + write_nic_dword(dev, WFM5, FW_RA_ENABLE_RSSI_MASK); + ChkFwCmdIoDone(dev); + break; + + case FW_CMD_RA_REFRESH_BG: + RT_TRACE(COMP_CMD, "[FW CMD] Set RA BG refresh!!\n"); + write_nic_dword(dev, WFM5, FW_RA_REFRESH); + ChkFwCmdIoDone(dev); + write_nic_dword(dev, WFM5, FW_RA_DISABLE_RSSI_MASK); + ChkFwCmdIoDone(dev); + break; + + case FW_CMD_RA_REFRESH_N_COMB: + RT_TRACE(COMP_CMD, "[FW CMD] Set RA n Combo refresh!!\n"); + if(priv->rtllib->pHTInfo->IOTRaFunc & HT_IOT_RAFUNC_DISABLE_ALL) + input = FW_RA_IOT_N_COMB; + else + input = FW_RA_IOT_N_COMB | (((priv->rtllib->pHTInfo->IOTRaFunc)&0x0f) << 8); + input = input |((priv->rtllib->pHTInfo->IOTPeer & 0xf) <<12); + RT_TRACE(COMP_CMD, "[FW CMD] Set RA/IOT Comb in n mode!! input(%#x)\n", input); + write_nic_dword(dev, WFM5, input); + ChkFwCmdIoDone(dev); + break; + + case FW_CMD_RA_REFRESH_BG_COMB: + RT_TRACE(COMP_CMD, "[FW CMD] Set RA B/G Combo refresh!!\n"); + if(priv->rtllib->pHTInfo->IOTRaFunc & HT_IOT_RAFUNC_DISABLE_ALL) + input = FW_RA_IOT_BG_COMB; + else + input = FW_RA_IOT_BG_COMB | (((priv->rtllib->pHTInfo->IOTRaFunc)&0x0f) << 8); + input = input |((priv->rtllib->pHTInfo->IOTPeer & 0xf) <<12); + RT_TRACE(COMP_CMD, "[FW CMD] Set RA/IOT Comb in B/G mode!! input(%#x)\n", input); + write_nic_dword(dev, WFM5, input); + ChkFwCmdIoDone(dev); + break; + + case FW_CMD_IQK_ENABLE: + RT_TRACE(COMP_CMD, "[FW CMD] IQK Enable!!\n"); + write_nic_dword(dev, WFM5, FW_IQK_ENABLE); + ChkFwCmdIoDone(dev); + break; + + case FW_CMD_PAUSE_DM_BY_SCAN: + RT_TRACE(COMP_CMD, "[FW CMD] Pause DM by Scan!!\n"); + rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bMaskByte0, 0x17); + rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bMaskByte0, 0x17); + rtl8192_setBBreg(dev, rCCK0_CCA, bMaskByte2, 0x40); + break; + + case FW_CMD_RESUME_DM_BY_SCAN: + RT_TRACE(COMP_CMD, "[FW CMD] Resume DM by Scan!!\n"); + rtl8192_setBBreg(dev, rCCK0_CCA, bMaskByte2, 0xcd); + rtl8192_phy_setTxPower(dev, priv->rtllib->current_network.channel); + break; + + case FW_CMD_HIGH_PWR_DISABLE: + RT_TRACE(COMP_CMD, "[FW CMD] High Pwr Disable!!\n"); + if(priv->DMFlag & HAL_DM_HIPWR_DISABLE) + break; + rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bMaskByte0, 0x17); + rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bMaskByte0, 0x17); + rtl8192_setBBreg(dev, rCCK0_CCA, bMaskByte2, 0x40); + break; + + case FW_CMD_HIGH_PWR_ENABLE: + RT_TRACE(COMP_CMD, "[FW CMD] High Pwr Enable!!\n"); + if((priv->DMFlag & HAL_DM_HIPWR_DISABLE) || + (priv->rtllib->bdynamic_txpower_enable == true)) + break; + rtl8192_setBBreg(dev, rCCK0_CCA, bMaskByte2, 0xcd); + break; + + case FW_CMD_LPS_ENTER: + RT_TRACE(COMP_CMD, "[FW CMD] Enter LPS mode!!\n"); + CurrentAID = priv->rtllib->assoc_id; + write_nic_dword(dev, WFM5, (FW_LPS_ENTER| ((CurrentAID|0xc000)<<8)) ); + ChkFwCmdIoDone(dev); + priv->rtllib->pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_EDCA_TURBO; + break; + + case FW_CMD_LPS_LEAVE: + RT_TRACE(COMP_CMD, "[FW CMD] Leave LPS mode!!\n"); + write_nic_dword(dev, WFM5, FW_LPS_LEAVE ); + ChkFwCmdIoDone(dev); + priv->rtllib->pHTInfo->IOTAction &= (~HT_IOT_ACT_DISABLE_EDCA_TURBO); + break; + + case FW_CMD_ADD_A2_ENTRY: + RT_TRACE(COMP_CMD, "[FW CMD] ADD A2 entry!!\n"); + write_nic_dword(dev, WFM5, FW_ADD_A2_ENTRY); + ChkFwCmdIoDone(dev); + break; + + case FW_CMD_CTRL_DM_BY_DRIVER: + RT_TRACE(COMP_CMD, "[FW CMD] Inform fw driver will do some dm at driver\n"); + write_nic_dword(dev, WFM5, FW_CTRL_DM_BY_DRIVER); + ChkFwCmdIoDone(dev); + break; +#ifdef CONFIG_FW_SETCHAN + case FW_CMD_CHAN_SET: + input = FW_CHAN_SET | (((priv->chan)&0xff) << 8); + RT_TRACE(COMP_CMD, "[FW CMD] Inform fw to set channel to %x!!, input(%#x):\n", priv->chan,input); + write_nic_dword(dev, WFM5, input); + ChkFwCmdIoDone(dev); + break; +#endif + + default: + break; + } + + + ChkFwCmdIoDone(dev); + + + priv->SetFwCmdInProgress = false; + RT_TRACE(COMP_CMD, "<---SetFwCmdIOWorkItemCallback()\n"); +} + +static void +phy_CheckEphySwitchReady(struct net_device* dev) +{ + u32 delay = 100; + u8 regu1; + + regu1 = read_nic_byte(dev, 0x554); + while ((regu1 & BIT5) && (delay > 0)) + { + regu1 = read_nic_byte(dev, 0x554); + delay--; + udelay(50); + } + RT_TRACE(COMP_INIT, "regu1=%02x delay = %d\n", regu1, delay); + +} + +#ifdef TO_DO_LIST +void +HW_RadioGpioChk92SE( + IN PADAPTER pAdapter + ) +{ + PMGNT_INFO pMgntInfo = &(pAdapter->MgntInfo); + u1Byte u1Tmp = 0; + HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); + RT_RF_POWER_STATE eRfPowerStateToSet; + BOOLEAN bActuallySet = false; + +#if 0 + if (!RT_IN_PS_LEVEL(pAdapter, RT_RF_OFF_LEVL_PCI_D3) && + pMgntInfo->RfOffReason != RF_CHANGE_BY_HW) + { + return; + } + + PlatformSwitchClkReq(pAdapter, 0x00); + + if (RT_IN_PS_LEVEL(pAdapter, RT_RF_OFF_LEVL_PCI_D3)) + { + RT_LEAVE_D3(pAdapter, false); + RT_CLEAR_PS_LEVEL(pAdapter, RT_RF_OFF_LEVL_PCI_D3); + Power_DomainInit92SE(pAdapter); + } + + PlatformEFIOWrite1Byte(pAdapter, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); + + u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IO_SEL); + u1Tmp &= HAL_8192S_HW_GPIO_OFF_MASK; + PlatformEFIOWrite1Byte(pAdapter, GPIO_IO_SEL, u1Tmp); + + RT_TRACE(COMP_CMD, DBG_LOUD, + ("HW_RadioGpioChk92SE HW_RadioGpioChk92SE=%02x\n", HW_RadioGpioChk92SE)); + + u1Tmp = PlatformEFIORead1Byte(pAdapter, GPIO_IN); + + eRfPowerStateToSet = (u1Tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? eRfOn : eRfOff; + + if( (pHalData->bHwRadioOff == true) && (eRfPowerStateToSet == eRfOn)) + { + RT_TRACE(COMP_RF, DBG_LOUD, ("HW_RadioGpioChk92SE - HW Radio ON\n")); + pHalData->bHwRadioOff = false; + bActuallySet = true; + } + else if ( (pHalData->bHwRadioOff == false) && (eRfPowerStateToSet == eRfOff)) + { + RT_TRACE(COMP_RF, DBG_LOUD, ("HW_RadioGpioChk92SE - HW Radio OFF\n")); + pHalData->bHwRadioOff = true; + bActuallySet = true; + } + + if(bActuallySet) + { + pHalData->bHwRfOffAction = 1; + MgntActSet_RF_State(pAdapter, eRfPowerStateToSet, RF_CHANGE_BY_HW); + DrvIFIndicateCurrentPhyStatus(pAdapter); + + + { + PMP_ADAPTER pDevice = &(pAdapter->NdisAdapter); + if(pDevice->RegHwSwRfOffD3 == 1 || pDevice->RegHwSwRfOffD3 == 2) + (eRfPowerStateToSet == eRfOff) ? RT_ENABLE_ASPM(pAdapter) : RT_DISABLE_ASPM(pAdapter); + } + } + RT_TRACE(COMP_RF, DBG_TRACE, ("HW_RadioGpioChk92SE() <--------- \n")); +#endif +}/* HW_RadioGpioChk92SE */ +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_phy.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_phy.h @@ -0,0 +1,202 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +/* Check to see if the file has been included already. */ +#ifndef _R8192S_PHY_H +#define _R8192S_PHY_H + + +/*--------------------------Define Parameters-------------------------------*/ +#define LOOP_LIMIT 5 +#define MAX_STALL_TIME 50 +#define AntennaDiversityValue 0x80 +#define MAX_TXPWR_IDX_NMODE_92S 63 +#define Reset_Cnt_Limit 3 + + +#define MAX_PRECMD_CNT 16 +#define MAX_RFDEPENDCMD_CNT 16 +#define MAX_POSTCMD_CNT 16 +#ifdef RTL8192SE +#define SET_RTL8192SE_RF_SLEEP(dev) \ +{ \ + u8 u1bTmp; \ + u1bTmp = read_nic_byte (dev, LDOV12D_CTRL); \ + u1bTmp |= BIT0; \ + write_nic_byte(dev, LDOV12D_CTRL, u1bTmp); \ + write_nic_byte(dev, SPS1_CTRL, 0x0); \ + write_nic_byte(dev, TXPAUSE, 0xFF); \ + write_nic_word(dev, CMDR, 0x57FC); \ + udelay(100); \ + write_nic_word(dev, CMDR, 0x77FC); \ + write_nic_byte(dev, PHY_CCA, 0x0); \ + udelay(10); \ + write_nic_word(dev, CMDR, 0x37FC); \ + udelay(10); \ + write_nic_word(dev, CMDR, 0x77FC); \ + udelay(10); \ + write_nic_word(dev, CMDR, 0x57FC); \ +} + + +#endif + +/*--------------------------Define Parameters-------------------------------*/ + + +/*------------------------------Define structure----------------------------*/ +typedef enum _SwChnlCmdID{ + CmdID_End, + CmdID_SetTxPowerLevel, + CmdID_BBRegWrite10, + CmdID_WritePortUlong, + CmdID_WritePortUshort, + CmdID_WritePortUchar, + CmdID_RF_WriteReg, +}SwChnlCmdID; + + +typedef struct _SwChnlCmd{ + SwChnlCmdID CmdID; + u32 Para1; + u32 Para2; + u32 msDelay; +}__attribute__ ((packed)) SwChnlCmd; + +extern u32 rtl819XMACPHY_Array_PG[]; +extern u32 rtl819XPHY_REG_1T2RArray[]; +extern u32 rtl819XAGCTAB_Array[]; +extern u32 rtl819XRadioA_Array[]; +extern u32 rtl819XRadioB_Array[]; +extern u32 rtl819XRadioC_Array[]; +extern u32 rtl819XRadioD_Array[]; + +typedef enum _HW90_BLOCK{ + HW90_BLOCK_MAC = 0, + HW90_BLOCK_PHY0 = 1, + HW90_BLOCK_PHY1 = 2, + HW90_BLOCK_RF = 3, + HW90_BLOCK_MAXIMUM = 4, +}HW90_BLOCK_E, *PHW90_BLOCK_E; + +typedef enum _RF90_RADIO_PATH{ + RF90_PATH_A = 0, + RF90_PATH_B = 1, + RF90_PATH_C = 2, + RF90_PATH_D = 3, +#ifndef _RTL8192_EXT_PATCH_ + RF90_PATH_MAX = 4, +#endif +}RF90_RADIO_PATH_E, *PRF90_RADIO_PATH_E; +#ifdef _RTL8192_EXT_PATCH_ +#define RF90_PATH_MAX 2 +#endif + +#define bMaskByte0 0xff +#define bMaskByte1 0xff00 +#define bMaskByte2 0xff0000 +#define bMaskByte3 0xff000000 +#define bMaskHWord 0xffff0000 +#define bMaskLWord 0x0000ffff +#define bMaskDWord 0xffffffff + +typedef enum _BaseBand_Config_Type{ + BaseBand_Config_PHY_REG = 0, + BaseBand_Config_AGC_TAB = 1, +}BaseBand_Config_Type, *PBaseBand_Config_Type; + +typedef enum _VERSION_8190{ + VERSION_8190_BD=0x3, + VERSION_8190_BE +}VERSION_8190,*PVERSION_8190; + + +typedef enum _VERSION_8192S{ + VERSION_8192S_ACUT, + VERSION_8192S_BCUT, + VERSION_8192S_CCUT +}VERSION_8192S,*PVERSION_8192S; + +typedef enum _PHY_Rate_Tx_Power_Offset_Area{ + RA_OFFSET_LEGACY_OFDM1, + RA_OFFSET_LEGACY_OFDM2, + RA_OFFSET_HT_OFDM1, + RA_OFFSET_HT_OFDM2, + RA_OFFSET_HT_OFDM3, + RA_OFFSET_HT_OFDM4, + RA_OFFSET_HT_CCK, +}RA_OFFSET_AREA,*PRA_OFFSET_AREA; +#if 0 +typedef enum _RATR_TABLE_MODE_8192S{ + RATR_INX_WIRELESS_NGB = 0, + RATR_INX_WIRELESS_NG = 1, + RATR_INX_WIRELESS_NB = 2, + RATR_INX_WIRELESS_N = 3, + RATR_INX_WIRELESS_GB = 4, + RATR_INX_WIRELESS_G = 5, + RATR_INX_WIRELESS_B = 6, + RATR_INX_WIRELESS_MC = 7, + RATR_INX_WIRELESS_A = 8, +}RATR_TABLE_MODE_8192S, *PRATR_TABLE_MODE_8192S; +#endif +/*------------------------------Define structure----------------------------*/ + + +/*------------------------Export global variable----------------------------*/ +/*------------------------Export global variable----------------------------*/ + + +/*------------------------Export Marco Definition---------------------------*/ +/*------------------------Export Marco Definition---------------------------*/ + + +/*--------------------------Exported Function prototype---------------------*/ + +extern u32 rtl8192_QueryBBReg(struct net_device* dev,u32 RegAddr, u32 BitMask); +extern void rtl8192_setBBreg(struct net_device* dev,u32 RegAddr, u32 BitMask,u32 Data); +extern u32 rtl8192_phy_QueryRFReg(struct net_device* dev,RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask); +extern void rtl8192_phy_SetRFReg(struct net_device* dev,RF90_RADIO_PATH_E eRFPath, u32 RegAddr,u32 BitMask,u32 Data); + +bool rtl8192_phy_checkBBAndRF(struct net_device* dev, HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath); + + +extern bool PHY_MACConfig8192S(struct net_device* dev); +extern bool PHY_BBConfig8192S(struct net_device* dev); +extern bool PHY_RFConfig8192S(struct net_device* dev); + +extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev,RF90_RADIO_PATH_E eRFPath); +extern void rtl8192_SetBWMode(struct net_device* dev,HT_CHANNEL_WIDTH ChnlWidth,HT_EXTCHNL_OFFSET Offset ); +extern u8 rtl8192_phy_SwChnl(struct net_device* dev,u8 channel); +extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev,u32 eRFPath ); +extern void rtl8192_BBConfig(struct net_device* dev); +extern void PHY_IQCalibrateBcut(struct net_device* dev); +extern void PHY_IQCalibrate(struct net_device* dev); +extern void PHY_GetHWRegOriginalValue(struct net_device* dev); + +extern void InitialGainOperateWorkItemCallBack(void *data); +void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel); + +/*--------------------------Exported Function prototype---------------------*/ +bool rtl8192se_set_fw_cmd(struct net_device* dev, FW_CMD_IO_TYPE FwCmdIO); +extern void PHY_SetBeaconHwReg( struct net_device* dev, u16 BeaconInterval); +void ChkFwCmdIoDone(struct net_device* dev); +void PHY_SwitchEphyParameter(struct net_device* dev); +bool PHY_SetRFPowerState(struct net_device* dev, RT_RF_POWER_STATE eRFPowerState); +extern void PHY_ScanOperationBackup8192S(struct net_device* dev,u8 Operation); +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_phyreg.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_phyreg.h @@ -0,0 +1,954 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef __INC_HAL8192SPHYREG_H +#define __INC_HAL8192SPHYREG_H + + +/*--------------------------Define Parameters-------------------------------*/ + + + + +#define rPMAC_Reset 0x100 +#define rPMAC_TxStart 0x104 +#define rPMAC_TxLegacySIG 0x108 +#define rPMAC_TxHTSIG1 0x10c +#define rPMAC_TxHTSIG2 0x110 +#define rPMAC_PHYDebug 0x114 +#define rPMAC_TxPacketNum 0x118 +#define rPMAC_TxIdle 0x11c +#define rPMAC_TxMACHeader0 0x120 +#define rPMAC_TxMACHeader1 0x124 +#define rPMAC_TxMACHeader2 0x128 +#define rPMAC_TxMACHeader3 0x12c +#define rPMAC_TxMACHeader4 0x130 +#define rPMAC_TxMACHeader5 0x134 +#define rPMAC_TxDataType 0x138 +#define rPMAC_TxRandomSeed 0x13c +#define rPMAC_CCKPLCPPreamble 0x140 +#define rPMAC_CCKPLCPHeader 0x144 +#define rPMAC_CCKCRC16 0x148 +#define rPMAC_OFDMRxCRC32OK 0x170 +#define rPMAC_OFDMRxCRC32Er 0x174 +#define rPMAC_OFDMRxParityEr 0x178 +#define rPMAC_OFDMRxCRC8Er 0x17c +#define rPMAC_CCKCRxRC16Er 0x180 +#define rPMAC_CCKCRxRC32Er 0x184 +#define rPMAC_CCKCRxRC32OK 0x188 +#define rPMAC_TxStatus 0x18c + +#define RF_BB_CMD_ADDR 0x02c0 +#define RF_BB_CMD_DATA 0x02c4 + +#define rFPGA0_RFMOD 0x800 + +#define rFPGA0_TxInfo 0x804 +#define rFPGA0_PSDFunction 0x808 + +#define rFPGA0_TxGainStage 0x80c + +#define rFPGA0_RFTiming1 0x810 +#define rFPGA0_RFTiming2 0x814 + +#define rFPGA0_XA_HSSIParameter1 0x820 +#define rFPGA0_XA_HSSIParameter2 0x824 +#define rFPGA0_XB_HSSIParameter1 0x828 +#define rFPGA0_XB_HSSIParameter2 0x82c +#define rFPGA0_XC_HSSIParameter1 0x830 +#define rFPGA0_XC_HSSIParameter2 0x834 +#define rFPGA0_XD_HSSIParameter1 0x838 +#define rFPGA0_XD_HSSIParameter2 0x83c +#define rFPGA0_XA_LSSIParameter 0x840 +#define rFPGA0_XB_LSSIParameter 0x844 +#define rFPGA0_XC_LSSIParameter 0x848 +#define rFPGA0_XD_LSSIParameter 0x84c + +#define rFPGA0_RFWakeUpParameter 0x850 +#define rFPGA0_RFSleepUpParameter 0x854 + +#define rFPGA0_XAB_SwitchControl 0x858 +#define rFPGA0_XCD_SwitchControl 0x85c + +#define rFPGA0_XA_RFInterfaceOE 0x860 +#define rFPGA0_XB_RFInterfaceOE 0x864 +#define rFPGA0_XC_RFInterfaceOE 0x868 +#define rFPGA0_XD_RFInterfaceOE 0x86c + +#define rFPGA0_XAB_RFInterfaceSW 0x870 +#define rFPGA0_XCD_RFInterfaceSW 0x874 + +#define rFPGA0_XAB_RFParameter 0x878 +#define rFPGA0_XCD_RFParameter 0x87c + +#define rFPGA0_AnalogParameter1 0x880 +#define rFPGA0_AnalogParameter2 0x884 +#define rFPGA0_AnalogParameter3 0x888 +#define rFPGA0_AnalogParameter4 0x88c + +#define rFPGA0_XA_LSSIReadBack 0x8a0 +#define rFPGA0_XB_LSSIReadBack 0x8a4 +#define rFPGA0_XC_LSSIReadBack 0x8a8 +#define rFPGA0_XD_LSSIReadBack 0x8ac + +#define rFPGA0_PSDReport 0x8b4 +#define TransceiverA_HSPI_Readback 0x8b8 +#define TransceiverB_HSPI_Readback 0x8bc +#define rFPGA0_XAB_RFInterfaceRB 0x8e0 +#define rFPGA0_XCD_RFInterfaceRB 0x8e4 + +#define rFPGA1_RFMOD 0x900 + +#define rFPGA1_TxBlock 0x904 +#define rFPGA1_DebugSelect 0x908 +#define rFPGA1_TxInfo 0x90c + +#define rCCK0_System 0xa00 + +#define rCCK0_AFESetting 0xa04 +#define rCCK0_CCA 0xa08 + +#define rCCK0_RxAGC1 0xa0c +#define rCCK0_RxAGC2 0xa10 + +#define rCCK0_RxHP 0xa14 + +#define rCCK0_DSPParameter1 0xa18 +#define rCCK0_DSPParameter2 0xa1c + +#define rCCK0_TxFilter1 0xa20 +#define rCCK0_TxFilter2 0xa24 +#define rCCK0_DebugPort 0xa28 +#define rCCK0_FalseAlarmReport 0xa2c +#define rCCK0_TRSSIReport 0xa50 +#define rCCK0_RxReport 0xa54 +#define rCCK0_FACounterLower 0xa5c +#define rCCK0_FACounterUpper 0xa58 + +#define rOFDM0_LSTF 0xc00 + +#define rOFDM0_TRxPathEnable 0xc04 +#define rOFDM0_TRMuxPar 0xc08 +#define rOFDM0_TRSWIsolation 0xc0c + +#define rOFDM0_XARxAFE 0xc10 +#define rOFDM0_XARxIQImbalance 0xc14 +#define rOFDM0_XBRxAFE 0xc18 +#define rOFDM0_XBRxIQImbalance 0xc1c +#define rOFDM0_XCRxAFE 0xc20 +#define rOFDM0_XCRxIQImbalance 0xc24 +#define rOFDM0_XDRxAFE 0xc28 +#define rOFDM0_XDRxIQImbalance 0xc2c + +#define rOFDM0_RxDetector1 0xc30 +#define rOFDM0_RxDetector2 0xc34 +#define rOFDM0_RxDetector3 0xc38 +#define rOFDM0_RxDetector4 0xc3c + +#define rOFDM0_RxDSP 0xc40 +#define rOFDM0_CFOandDAGC 0xc44 +#define rOFDM0_CCADropThreshold 0xc48 +#define rOFDM0_ECCAThreshold 0xc4c + +#define rOFDM0_XAAGCCore1 0xc50 +#define rOFDM0_XAAGCCore2 0xc54 +#define rOFDM0_XBAGCCore1 0xc58 +#define rOFDM0_XBAGCCore2 0xc5c +#define rOFDM0_XCAGCCore1 0xc60 +#define rOFDM0_XCAGCCore2 0xc64 +#define rOFDM0_XDAGCCore1 0xc68 +#define rOFDM0_XDAGCCore2 0xc6c + +#define rOFDM0_AGCParameter1 0xc70 +#define rOFDM0_AGCParameter2 0xc74 +#define rOFDM0_AGCRSSITable 0xc78 +#define rOFDM0_HTSTFAGC 0xc7c + +#define rOFDM0_XATxIQImbalance 0xc80 +#define rOFDM0_XATxAFE 0xc84 +#define rOFDM0_XBTxIQImbalance 0xc88 +#define rOFDM0_XBTxAFE 0xc8c +#define rOFDM0_XCTxIQImbalance 0xc90 +#define rOFDM0_XCTxAFE 0xc94 +#define rOFDM0_XDTxIQImbalance 0xc98 +#define rOFDM0_XDTxAFE 0xc9c + +#define rOFDM0_RxHPParameter 0xce0 +#define rOFDM0_TxPseudoNoiseWgt 0xce4 +#define rOFDM0_FrameSync 0xcf0 +#define rOFDM0_DFSReport 0xcf4 +#define rOFDM0_TxCoeff1 0xca4 +#define rOFDM0_TxCoeff2 0xca8 +#define rOFDM0_TxCoeff3 0xcac +#define rOFDM0_TxCoeff4 0xcb0 +#define rOFDM0_TxCoeff5 0xcb4 +#define rOFDM0_TxCoeff6 0xcb8 + + +#define rOFDM1_LSTF 0xd00 +#define rOFDM1_TRxPathEnable 0xd04 + +#define rOFDM1_CFO 0xd08 +#define rOFDM1_CSI1 0xd10 +#define rOFDM1_SBD 0xd14 +#define rOFDM1_CSI2 0xd18 +#define rOFDM1_CFOTracking 0xd2c +#define rOFDM1_TRxMesaure1 0xd34 +#define rOFDM1_IntfDet 0xd3c +#define rOFDM1_PseudoNoiseStateAB 0xd50 +#define rOFDM1_PseudoNoiseStateCD 0xd54 +#define rOFDM1_RxPseudoNoiseWgt 0xd58 + +#define rOFDM_PHYCounter1 0xda0 +#define rOFDM_PHYCounter2 0xda4 +#define rOFDM_PHYCounter3 0xda8 + +#define rOFDM_ShortCFOAB 0xdac +#define rOFDM_ShortCFOCD 0xdb0 +#define rOFDM_LongCFOAB 0xdb4 +#define rOFDM_LongCFOCD 0xdb8 +#define rOFDM_TailCFOAB 0xdbc +#define rOFDM_TailCFOCD 0xdc0 +#define rOFDM_PWMeasure1 0xdc4 +#define rOFDM_PWMeasure2 0xdc8 +#define rOFDM_BWReport 0xdcc +#define rOFDM_AGCReport 0xdd0 +#define rOFDM_RxSNR 0xdd4 +#define rOFDM_RxEVMCSI 0xdd8 +#define rOFDM_SIGReport 0xddc + + +#define rTxAGC_Rate18_06 0xe00 +#define rTxAGC_Rate54_24 0xe04 +#define rTxAGC_CCK_Mcs32 0xe08 +#define rTxAGC_Mcs03_Mcs00 0xe10 +#define rTxAGC_Mcs07_Mcs04 0xe14 +#define rTxAGC_Mcs11_Mcs08 0xe18 +#define rTxAGC_Mcs15_Mcs12 0xe1c + +#define rZebra1_HSSIEnable 0x0 +#define rZebra1_TRxEnable1 0x1 +#define rZebra1_TRxEnable2 0x2 +#define rZebra1_AGC 0x4 +#define rZebra1_ChargePump 0x5 +#define rZebra1_Channel 0x7 + +#define rZebra1_TxGain 0x8 +#define rZebra1_TxLPF 0x9 +#define rZebra1_RxLPF 0xb +#define rZebra1_RxHPFCorner 0xc + +#define rGlobalCtrl 0 +#define rRTL8256_TxLPF 19 +#define rRTL8256_RxLPF 11 + +#define rRTL8258_TxLPF 0x11 +#define rRTL8258_RxLPF 0x13 +#define rRTL8258_RSSILPF 0xa + +#define RF_AC 0x00 + +#define RF_IQADJ_G1 0x01 +#define RF_IQADJ_G2 0x02 +#define RF_POW_TRSW 0x05 + +#define RF_GAIN_RX 0x06 +#define RF_GAIN_TX 0x07 + +#define RF_TXM_IDAC 0x08 +#define RF_BS_IQGEN 0x0F + +#define RF_MODE1 0x10 +#define RF_MODE2 0x11 + +#define RF_RX_AGC_HP 0x12 +#define RF_TX_AGC 0x13 +#define RF_BIAS 0x14 +#define RF_IPA 0x15 +#define RF_POW_ABILITY 0x17 +#define RF_MODE_AG 0x18 +#define rRfChannel 0x18 +#define RF_CHNLBW 0x18 +#define RF_TOP 0x19 + +#define RF_RX_G1 0x1A +#define RF_RX_G2 0x1B + +#define RF_RX_BB2 0x1C +#define RF_RX_BB1 0x1D + +#define RF_RCK1 0x1E +#define RF_RCK2 0x1F + +#define RF_TX_G1 0x20 +#define RF_TX_G2 0x21 +#define RF_TX_G3 0x22 + +#define RF_TX_BB1 0x23 + +#define RF_T_METER 0x24 + +#define RF_SYN_G1 0x25 +#define RF_SYN_G2 0x26 +#define RF_SYN_G3 0x27 +#define RF_SYN_G4 0x28 +#define RF_SYN_G5 0x29 +#define RF_SYN_G6 0x2A +#define RF_SYN_G7 0x2B +#define RF_SYN_G8 0x2C + +#define RF_RCK_OS 0x30 + +#define RF_TXPA_G1 0x31 +#define RF_TXPA_G2 0x32 +#define RF_TXPA_G3 0x33 + +#define bBBResetB 0x100 +#define bGlobalResetB 0x200 +#define bOFDMTxStart 0x4 +#define bCCKTxStart 0x8 +#define bCRC32Debug 0x100 +#define bPMACLoopback 0x10 +#define bTxLSIG 0xffffff +#define bOFDMTxRate 0xf +#define bOFDMTxReserved 0x10 +#define bOFDMTxLength 0x1ffe0 +#define bOFDMTxParity 0x20000 +#define bTxHTSIG1 0xffffff +#define bTxHTMCSRate 0x7f +#define bTxHTBW 0x80 +#define bTxHTLength 0xffff00 +#define bTxHTSIG2 0xffffff +#define bTxHTSmoothing 0x1 +#define bTxHTSounding 0x2 +#define bTxHTReserved 0x4 +#define bTxHTAggreation 0x8 +#define bTxHTSTBC 0x30 +#define bTxHTAdvanceCoding 0x40 +#define bTxHTShortGI 0x80 +#define bTxHTNumberHT_LTF 0x300 +#define bTxHTCRC8 0x3fc00 +#define bCounterReset 0x10000 +#define bNumOfOFDMTx 0xffff +#define bNumOfCCKTx 0xffff0000 +#define bTxIdleInterval 0xffff +#define bOFDMService 0xffff0000 +#define bTxMACHeader 0xffffffff +#define bTxDataInit 0xff +#define bTxHTMode 0x100 +#define bTxDataType 0x30000 +#define bTxRandomSeed 0xffffffff +#define bCCKTxPreamble 0x1 +#define bCCKTxSFD 0xffff0000 +#define bCCKTxSIG 0xff +#define bCCKTxService 0xff00 +#define bCCKLengthExt 0x8000 +#define bCCKTxLength 0xffff0000 +#define bCCKTxCRC16 0xffff +#define bCCKTxStatus 0x1 +#define bOFDMTxStatus 0x2 + +#define IS_BB_REG_OFFSET_92S(_Offset) ((_Offset >= 0x800) && (_Offset <= 0xfff)) + +#define bRFMOD 0x1 +#define bJapanMode 0x2 +#define bCCKTxSC 0x30 +#define bCCKEn 0x1000000 +#define bOFDMEn 0x2000000 + +#define bOFDMRxADCPhase 0x10000 +#define bOFDMTxDACPhase 0x40000 +#define bXATxAGC 0x3f + +#define bXBTxAGC 0xf00 +#define bXCTxAGC 0xf000 +#define bXDTxAGC 0xf0000 + +#define bPAStart 0xf0000000 +#define bTRStart 0x00f00000 +#define bRFStart 0x0000f000 +#define bBBStart 0x000000f0 +#define bBBCCKStart 0x0000000f +#define bPAEnd 0xf +#define bTREnd 0x0f000000 +#define bRFEnd 0x000f0000 +#define bCCAMask 0x000000f0 +#define bR2RCCAMask 0x00000f00 +#define bHSSI_R2TDelay 0xf8000000 +#define bHSSI_T2RDelay 0xf80000 +#define bContTxHSSI 0x400 +#define bIGFromCCK 0x200 +#define bAGCAddress 0x3f +#define bRxHPTx 0x7000 +#define bRxHPT2R 0x38000 +#define bRxHPCCKIni 0xc0000 +#define bAGCTxCode 0xc00000 +#define bAGCRxCode 0x300000 + +#define b3WireDataLength 0x800 +#define b3WireAddressLength 0x400 + +#define b3WireRFPowerDown 0x1 +#define b5GPAPEPolarity 0x40000000 +#define b2GPAPEPolarity 0x80000000 +#define bRFSW_TxDefaultAnt 0x3 +#define bRFSW_TxOptionAnt 0x30 +#define bRFSW_RxDefaultAnt 0x300 +#define bRFSW_RxOptionAnt 0x3000 +#define bRFSI_3WireData 0x1 +#define bRFSI_3WireClock 0x2 +#define bRFSI_3WireLoad 0x4 +#define bRFSI_3WireRW 0x8 +#define bRFSI_3Wire 0xf + +#define bRFSI_RFENV 0x10 + +#define bRFSI_TRSW 0x20 +#define bRFSI_TRSWB 0x40 +#define bRFSI_ANTSW 0x100 +#define bRFSI_ANTSWB 0x200 +#define bRFSI_PAPE 0x400 +#define bRFSI_PAPE5G 0x800 +#define bBandSelect 0x1 +#define bHTSIG2_GI 0x80 +#define bHTSIG2_Smoothing 0x01 +#define bHTSIG2_Sounding 0x02 +#define bHTSIG2_Aggreaton 0x08 +#define bHTSIG2_STBC 0x30 +#define bHTSIG2_AdvCoding 0x40 +#define bHTSIG2_NumOfHTLTF 0x300 +#define bHTSIG2_CRC8 0x3fc +#define bHTSIG1_MCS 0x7f +#define bHTSIG1_BandWidth 0x80 +#define bHTSIG1_HTLength 0xffff +#define bLSIG_Rate 0xf +#define bLSIG_Reserved 0x10 +#define bLSIG_Length 0x1fffe +#define bLSIG_Parity 0x20 +#define bCCKRxPhase 0x4 +#if (RTL92SE_FPGA_VERIFY == 1) +#define bLSSIReadAddress 0x3f000000 +#else +#define bLSSIReadAddress 0x7f800000 +#endif +#define bLSSIReadEdge 0x80000000 +#if (RTL92SE_FPGA_VERIFY == 1) +#define bLSSIReadBackData 0xfff +#else +#define bLSSIReadBackData 0xfffff +#endif +#define bLSSIReadOKFlag 0x1000 +#define bCCKSampleRate 0x8 +#define bRegulator0Standby 0x1 +#define bRegulatorPLLStandby 0x2 +#define bRegulator1Standby 0x4 +#define bPLLPowerUp 0x8 +#define bDPLLPowerUp 0x10 +#define bDA10PowerUp 0x20 +#define bAD7PowerUp 0x200 +#define bDA6PowerUp 0x2000 +#define bXtalPowerUp 0x4000 +#define b40MDClkPowerUP 0x8000 +#define bDA6DebugMode 0x20000 +#define bDA6Swing 0x380000 + +#define bADClkPhase 0x4000000 + +#define b80MClkDelay 0x18000000 +#define bAFEWatchDogEnable 0x20000000 + +#define bXtalCap01 0xc0000000 +#define bXtalCap23 0x3 +#define bXtalCap92x 0x0f000000 +#define bXtalCap 0x0f000000 + +#define bIntDifClkEnable 0x400 +#define bExtSigClkEnable 0x800 +#define bBandgapMbiasPowerUp 0x10000 +#define bAD11SHGain 0xc0000 +#define bAD11InputRange 0x700000 +#define bAD11OPCurrent 0x3800000 +#define bIPathLoopback 0x4000000 +#define bQPathLoopback 0x8000000 +#define bAFELoopback 0x10000000 +#define bDA10Swing 0x7e0 +#define bDA10Reverse 0x800 +#define bDAClkSource 0x1000 +#define bAD7InputRange 0x6000 +#define bAD7Gain 0x38000 +#define bAD7OutputCMMode 0x40000 +#define bAD7InputCMMode 0x380000 +#define bAD7Current 0xc00000 +#define bRegulatorAdjust 0x7000000 +#define bAD11PowerUpAtTx 0x1 +#define bDA10PSAtTx 0x10 +#define bAD11PowerUpAtRx 0x100 +#define bDA10PSAtRx 0x1000 +#define bCCKRxAGCFormat 0x200 +#define bPSDFFTSamplepPoint 0xc000 +#define bPSDAverageNum 0x3000 +#define bIQPathControl 0xc00 +#define bPSDFreq 0x3ff +#define bPSDAntennaPath 0x30 +#define bPSDIQSwitch 0x40 +#define bPSDRxTrigger 0x400000 +#define bPSDTxTrigger 0x80000000 +#define bPSDSineToneScale 0x7f000000 +#define bPSDReport 0xffff + +#define bOFDMTxSC 0x30000000 +#define bCCKTxOn 0x1 +#define bOFDMTxOn 0x2 +#define bDebugPage 0xfff +#define bDebugItem 0xff +#define bAntL 0x10 +#define bAntNonHT 0x100 +#define bAntHT1 0x1000 +#define bAntHT2 0x10000 +#define bAntHT1S1 0x100000 +#define bAntNonHTS1 0x1000000 + +#define bCCKBBMode 0x3 +#define bCCKTxPowerSaving 0x80 +#define bCCKRxPowerSaving 0x40 + +#define bCCKSideBand 0x10 + +#define bCCKScramble 0x8 +#define bCCKAntDiversity 0x8000 +#define bCCKCarrierRecovery 0x4000 +#define bCCKTxRate 0x3000 +#define bCCKDCCancel 0x0800 +#define bCCKISICancel 0x0400 +#define bCCKMatchFilter 0x0200 +#define bCCKEqualizer 0x0100 +#define bCCKPreambleDetect 0x800000 +#define bCCKFastFalseCCA 0x400000 +#define bCCKChEstStart 0x300000 +#define bCCKCCACount 0x080000 +#define bCCKcs_lim 0x070000 +#define bCCKBistMode 0x80000000 +#define bCCKCCAMask 0x40000000 +#define bCCKTxDACPhase 0x4 +#define bCCKRxADCPhase 0x20000000 +#define bCCKr_cp_mode0 0x0100 +#define bCCKTxDCOffset 0xf0 +#define bCCKRxDCOffset 0xf +#define bCCKCCAMode 0xc000 +#define bCCKFalseCS_lim 0x3f00 +#define bCCKCS_ratio 0xc00000 +#define bCCKCorgBit_sel 0x300000 +#define bCCKPD_lim 0x0f0000 +#define bCCKNewCCA 0x80000000 +#define bCCKRxHPofIG 0x8000 +#define bCCKRxIG 0x7f00 +#define bCCKLNAPolarity 0x800000 +#define bCCKRx1stGain 0x7f0000 +#define bCCKRFExtend 0x20000000 +#define bCCKRxAGCSatLevel 0x1f000000 +#define bCCKRxAGCSatCount 0xe0 +#define bCCKRxRFSettle 0x1f +#define bCCKFixedRxAGC 0x8000 +#define bCCKAntennaPolarity 0x2000 +#define bCCKTxFilterType 0x0c00 +#define bCCKRxAGCReportType 0x0300 +#define bCCKRxDAGCEn 0x80000000 +#define bCCKRxDAGCPeriod 0x20000000 +#define bCCKRxDAGCSatLevel 0x1f000000 +#define bCCKTimingRecovery 0x800000 +#define bCCKTxC0 0x3f0000 +#define bCCKTxC1 0x3f000000 +#define bCCKTxC2 0x3f +#define bCCKTxC3 0x3f00 +#define bCCKTxC4 0x3f0000 +#define bCCKTxC5 0x3f000000 +#define bCCKTxC6 0x3f +#define bCCKTxC7 0x3f00 +#define bCCKDebugPort 0xff0000 +#define bCCKDACDebug 0x0f000000 +#define bCCKFalseAlarmEnable 0x8000 +#define bCCKFalseAlarmRead 0x4000 +#define bCCKTRSSI 0x7f +#define bCCKRxAGCReport 0xfe +#define bCCKRxReport_AntSel 0x80000000 +#define bCCKRxReport_MFOff 0x40000000 +#define bCCKRxRxReport_SQLoss 0x20000000 +#define bCCKRxReport_Pktloss 0x10000000 +#define bCCKRxReport_Lockedbit 0x08000000 +#define bCCKRxReport_RateError 0x04000000 +#define bCCKRxReport_RxRate 0x03000000 +#define bCCKRxFACounterLower 0xff +#define bCCKRxFACounterUpper 0xff000000 +#define bCCKRxHPAGCStart 0xe000 +#define bCCKRxHPAGCFinal 0x1c00 +#define bCCKRxFalseAlarmEnable 0x8000 +#define bCCKFACounterFreeze 0x4000 +#define bCCKTxPathSel 0x10000000 +#define bCCKDefaultRxPath 0xc000000 +#define bCCKOptionRxPath 0x3000000 + +#define bNumOfSTF 0x3 +#define bShift_L 0xc0 +#define bGI_TH 0xc +#define bRxPathA 0x1 +#define bRxPathB 0x2 +#define bRxPathC 0x4 +#define bRxPathD 0x8 +#define bTxPathA 0x1 +#define bTxPathB 0x2 +#define bTxPathC 0x4 +#define bTxPathD 0x8 +#define bTRSSIFreq 0x200 +#define bADCBackoff 0x3000 +#define bDFIRBackoff 0xc000 +#define bTRSSILatchPhase 0x10000 +#define bRxIDCOffset 0xff +#define bRxQDCOffset 0xff00 +#define bRxDFIRMode 0x1800000 +#define bRxDCNFType 0xe000000 +#define bRXIQImb_A 0x3ff +#define bRXIQImb_B 0xfc00 +#define bRXIQImb_C 0x3f0000 +#define bRXIQImb_D 0xffc00000 +#define bDC_dc_Notch 0x60000 +#define bRxNBINotch 0x1f000000 +#define bPD_TH 0xf +#define bPD_TH_Opt2 0xc000 +#define bPWED_TH 0x700 +#define bIfMF_Win_L 0x800 +#define bPD_Option 0x1000 +#define bMF_Win_L 0xe000 +#define bBW_Search_L 0x30000 +#define bwin_enh_L 0xc0000 +#define bBW_TH 0x700000 +#define bED_TH2 0x3800000 +#define bBW_option 0x4000000 +#define bRatio_TH 0x18000000 +#define bWindow_L 0xe0000000 +#define bSBD_Option 0x1 +#define bFrame_TH 0x1c +#define bFS_Option 0x60 +#define bDC_Slope_check 0x80 +#define bFGuard_Counter_DC_L 0xe00 +#define bFrame_Weight_Short 0x7000 +#define bSub_Tune 0xe00000 +#define bFrame_DC_Length 0xe000000 +#define bSBD_start_offset 0x30000000 +#define bFrame_TH_2 0x7 +#define bFrame_GI2_TH 0x38 +#define bGI2_Sync_en 0x40 +#define bSarch_Short_Early 0x300 +#define bSarch_Short_Late 0xc00 +#define bSarch_GI2_Late 0x70000 +#define bCFOAntSum 0x1 +#define bCFOAcc 0x2 +#define bCFOStartOffset 0xc +#define bCFOLookBack 0x70 +#define bCFOSumWeight 0x80 +#define bDAGCEnable 0x10000 +#define bTXIQImb_A 0x3ff +#define bTXIQImb_B 0xfc00 +#define bTXIQImb_C 0x3f0000 +#define bTXIQImb_D 0xffc00000 +#define bTxIDCOffset 0xff +#define bTxQDCOffset 0xff00 +#define bTxDFIRMode 0x10000 +#define bTxPesudoNoiseOn 0x4000000 +#define bTxPesudoNoise_A 0xff +#define bTxPesudoNoise_B 0xff00 +#define bTxPesudoNoise_C 0xff0000 +#define bTxPesudoNoise_D 0xff000000 +#define bCCADropOption 0x20000 +#define bCCADropThres 0xfff00000 +#define bEDCCA_H 0xf +#define bEDCCA_L 0xf0 +#define bLambda_ED 0x300 +#define bRxInitialGain 0x7f +#define bRxAntDivEn 0x80 +#define bRxAGCAddressForLNA 0x7f00 +#define bRxHighPowerFlow 0x8000 +#define bRxAGCFreezeThres 0xc0000 +#define bRxFreezeStep_AGC1 0x300000 +#define bRxFreezeStep_AGC2 0xc00000 +#define bRxFreezeStep_AGC3 0x3000000 +#define bRxFreezeStep_AGC0 0xc000000 +#define bRxRssi_Cmp_En 0x10000000 +#define bRxQuickAGCEn 0x20000000 +#define bRxAGCFreezeThresMode 0x40000000 +#define bRxOverFlowCheckType 0x80000000 +#define bRxAGCShift 0x7f +#define bTRSW_Tri_Only 0x80 +#define bPowerThres 0x300 +#define bRxAGCEn 0x1 +#define bRxAGCTogetherEn 0x2 +#define bRxAGCMin 0x4 +#define bRxHP_Ini 0x7 +#define bRxHP_TRLNA 0x70 +#define bRxHP_RSSI 0x700 +#define bRxHP_BBP1 0x7000 +#define bRxHP_BBP2 0x70000 +#define bRxHP_BBP3 0x700000 +#define bRSSI_H 0x7f0000 +#define bRSSI_Gen 0x7f000000 +#define bRxSettle_TRSW 0x7 +#define bRxSettle_LNA 0x38 +#define bRxSettle_RSSI 0x1c0 +#define bRxSettle_BBP 0xe00 +#define bRxSettle_RxHP 0x7000 +#define bRxSettle_AntSW_RSSI 0x38000 +#define bRxSettle_AntSW 0xc0000 +#define bRxProcessTime_DAGC 0x300000 +#define bRxSettle_HSSI 0x400000 +#define bRxProcessTime_BBPPW 0x800000 +#define bRxAntennaPowerShift 0x3000000 +#define bRSSITableSelect 0xc000000 +#define bRxHP_Final 0x7000000 +#define bRxHTSettle_BBP 0x7 +#define bRxHTSettle_HSSI 0x8 +#define bRxHTSettle_RxHP 0x70 +#define bRxHTSettle_BBPPW 0x80 +#define bRxHTSettle_Idle 0x300 +#define bRxHTSettle_Reserved 0x1c00 +#define bRxHTRxHPEn 0x8000 +#define bRxHTAGCFreezeThres 0x30000 +#define bRxHTAGCTogetherEn 0x40000 +#define bRxHTAGCMin 0x80000 +#define bRxHTAGCEn 0x100000 +#define bRxHTDAGCEn 0x200000 +#define bRxHTRxHP_BBP 0x1c00000 +#define bRxHTRxHP_Final 0xe0000000 +#define bRxPWRatioTH 0x3 +#define bRxPWRatioEn 0x4 +#define bRxMFHold 0x3800 +#define bRxPD_Delay_TH1 0x38 +#define bRxPD_Delay_TH2 0x1c0 +#define bRxPD_DC_COUNT_MAX 0x600 +#define bRxPD_Delay_TH 0x8000 +#define bRxProcess_Delay 0xf0000 +#define bRxSearchrange_GI2_Early 0x700000 +#define bRxFrame_Guard_Counter_L 0x3800000 +#define bRxSGI_Guard_L 0xc000000 +#define bRxSGI_Search_L 0x30000000 +#define bRxSGI_TH 0xc0000000 +#define bDFSCnt0 0xff +#define bDFSCnt1 0xff00 +#define bDFSFlag 0xf0000 +#define bMFWeightSum 0x300000 +#define bMinIdxTH 0x7f000000 +#define bDAFormat 0x40000 +#define bTxChEmuEnable 0x01000000 +#define bTRSWIsolation_A 0x7f +#define bTRSWIsolation_B 0x7f00 +#define bTRSWIsolation_C 0x7f0000 +#define bTRSWIsolation_D 0x7f000000 +#define bExtLNAGain 0x7c00 + +#define bSTBCEn 0x4 +#define bAntennaMapping 0x10 +#define bNss 0x20 +#define bCFOAntSumD 0x200 +#define bPHYCounterReset 0x8000000 +#define bCFOReportGet 0x4000000 +#define bOFDMContinueTx 0x10000000 +#define bOFDMSingleCarrier 0x20000000 +#define bOFDMSingleTone 0x40000000 +#define bHTDetect 0x100 +#define bCFOEn 0x10000 +#define bCFOValue 0xfff00000 +#define bSigTone_Re 0x3f +#define bSigTone_Im 0x7f00 +#define bCounter_CCA 0xffff +#define bCounter_ParityFail 0xffff0000 +#define bCounter_RateIllegal 0xffff +#define bCounter_CRC8Fail 0xffff0000 +#define bCounter_MCSNoSupport 0xffff +#define bCounter_FastSync 0xffff +#define bShortCFO 0xfff +#define bShortCFOTLength 12 +#define bShortCFOFLength 11 +#define bLongCFO 0x7ff +#define bLongCFOTLength 11 +#define bLongCFOFLength 11 +#define bTailCFO 0x1fff +#define bTailCFOTLength 13 +#define bTailCFOFLength 12 +#define bmax_en_pwdB 0xffff +#define bCC_power_dB 0xffff0000 +#define bnoise_pwdB 0xffff +#define bPowerMeasTLength 10 +#define bPowerMeasFLength 3 +#define bRx_HT_BW 0x1 +#define bRxSC 0x6 +#define bRx_HT 0x8 +#define bNB_intf_det_on 0x1 +#define bIntf_win_len_cfg 0x30 +#define bNB_Intf_TH_cfg 0x1c0 +#define bRFGain 0x3f +#define bTableSel 0x40 +#define bTRSW 0x80 +#define bRxSNR_A 0xff +#define bRxSNR_B 0xff00 +#define bRxSNR_C 0xff0000 +#define bRxSNR_D 0xff000000 +#define bSNREVMTLength 8 +#define bSNREVMFLength 1 +#define bCSI1st 0xff +#define bCSI2nd 0xff00 +#define bRxEVM1st 0xff0000 +#define bRxEVM2nd 0xff000000 +#define bSIGEVM 0xff +#define bPWDB 0xff00 +#define bSGIEN 0x10000 + +#define bSFactorQAM1 0xf +#define bSFactorQAM2 0xf0 +#define bSFactorQAM3 0xf00 +#define bSFactorQAM4 0xf000 +#define bSFactorQAM5 0xf0000 +#define bSFactorQAM6 0xf0000 +#define bSFactorQAM7 0xf00000 +#define bSFactorQAM8 0xf000000 +#define bSFactorQAM9 0xf0000000 +#define bCSIScheme 0x100000 + +#define bNoiseLvlTopSet 0x3 +#define bChSmooth 0x4 +#define bChSmoothCfg1 0x38 +#define bChSmoothCfg2 0x1c0 +#define bChSmoothCfg3 0xe00 +#define bChSmoothCfg4 0x7000 +#define bMRCMode 0x800000 +#define bTHEVMCfg 0x7000000 + +#define bLoopFitType 0x1 +#define bUpdCFO 0x40 +#define bUpdCFOOffData 0x80 +#define bAdvUpdCFO 0x100 +#define bAdvTimeCtrl 0x800 +#define bUpdClko 0x1000 +#define bFC 0x6000 +#define bTrackingMode 0x8000 +#define bPhCmpEnable 0x10000 +#define bUpdClkoLTF 0x20000 +#define bComChCFO 0x40000 +#define bCSIEstiMode 0x80000 +#define bAdvUpdEqz 0x100000 +#define bUChCfg 0x7000000 +#define bUpdEqz 0x8000000 + +#define bTxAGCRate18_06 0x7f7f7f7f +#define bTxAGCRate54_24 0x7f7f7f7f +#define bTxAGCRateMCS32 0x7f +#define bTxAGCRateCCK 0x7f00 +#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f +#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f +#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f +#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f + +#define bRxPesudoNoiseOn 0x20000000 +#define bRxPesudoNoise_A 0xff +#define bRxPesudoNoise_B 0xff00 +#define bRxPesudoNoise_C 0xff0000 +#define bRxPesudoNoise_D 0xff000000 +#define bPesudoNoiseState_A 0xffff +#define bPesudoNoiseState_B 0xffff0000 +#define bPesudoNoiseState_C 0xffff +#define bPesudoNoiseState_D 0xffff0000 + +#define bZebra1_HSSIEnable 0x8 +#define bZebra1_TRxControl 0xc00 +#define bZebra1_TRxGainSetting 0x07f +#define bZebra1_RxCorner 0xc00 +#define bZebra1_TxChargePump 0x38 +#define bZebra1_RxChargePump 0x7 +#define bZebra1_ChannelNum 0xf80 +#define bZebra1_TxLPFBW 0x400 +#define bZebra1_RxLPFBW 0x600 + +#define bRTL8256RegModeCtrl1 0x100 +#define bRTL8256RegModeCtrl0 0x40 +#define bRTL8256_TxLPFBW 0x18 +#define bRTL8256_RxLPFBW 0x600 + +#define bRTL8258_TxLPFBW 0xc +#define bRTL8258_RxLPFBW 0xc00 +#define bRTL8258_RSSILPFBW 0xc0 + + + +#define bByte0 0x1 +#define bByte1 0x2 +#define bByte2 0x4 +#define bByte3 0x8 +#define bWord0 0x3 +#define bWord1 0xc +#define bDWord 0xf + +#define bMaskByte0 0xff +#define bMaskByte1 0xff00 +#define bMaskByte2 0xff0000 +#define bMaskByte3 0xff000000 +#define bMaskHWord 0xffff0000 +#define bMaskLWord 0x0000ffff +#define bMaskDWord 0xffffffff + +#if (RTL92SE_FPGA_VERIFY == 1) +#define bMask12Bits 0xfff +#define bMask20Bits 0xfff +#define bRFRegOffsetMask 0xfff +#else +#define bMask12Bits 0xfffff +#define bMask20Bits 0xfffff +#define bRFRegOffsetMask 0xfffff +#endif +#define bEnable 0x1 +#define bDisable 0x0 + +#define LeftAntenna 0x0 +#define RightAntenna 0x1 + +#define tCheckTxStatus 500 +#define tUpdateRxCounter 100 + +#define rateCCK 0 +#define rateOFDM 1 +#define rateHT 2 + +#define bPMAC_End 0x1ff +#define bFPGAPHY0_End 0x8ff +#define bFPGAPHY1_End 0x9ff +#define bCCKPHY0_End 0xaff +#define bOFDMPHY0_End 0xcff +#define bOFDMPHY1_End 0xdff + + +#define bPMACControl 0x0 +#define bWMACControl 0x1 +#define bWNICControl 0x2 + +#define PathA 0x0 +#define PathB 0x1 +#define PathC 0x2 +#define PathD 0x3 + +/*--------------------------Define Parameters-------------------------------*/ + + +#endif + + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_rtl6052.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_rtl6052.c @@ -0,0 +1,971 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + +#ifdef RTL8192SE +#include "../rtl_core.h" +#include "../rtl_dm.h" + +/*---------------------------Define Local Constant---------------------------*/ +typedef struct RF_Shadow_Compare_Map { + u32 Value; + u8 Compare; + u8 ErrorOrNot; + u8 Recorver; + u8 Driver_Write; +}RF_SHADOW_T; +/*---------------------------Define Local Constant---------------------------*/ + + +/*------------------------Define global variable-----------------------------*/ +/*------------------------Define global variable-----------------------------*/ + + + + +/*---------------------Define local function prototype-----------------------*/ +void phy_RF6052_Config_HardCode(struct net_device* dev); + +bool phy_RF6052_Config_ParaFile(struct net_device* dev); +/*---------------------Define local function prototype-----------------------*/ + +/*------------------------Define function prototype--------------------------*/ +extern void RF_ChangeTxPath(struct net_device* dev, u16 DataRate); + +/*------------------------Define function prototype--------------------------*/ + +/*------------------------Define local variable------------------------------*/ +static RF_SHADOW_T RF_Shadow[RF6052_MAX_PATH][RF6052_MAX_REG]; +/*------------------------Define local variable------------------------------*/ + +/*------------------------Define function prototype--------------------------*/ +extern void RF_ChangeTxPath(struct net_device* dev, u16 DataRate) +{ +#if 0 + static u1Byte RF_Path_Type = 2; + static u4Byte tx_gain_tbl1[6] + = {0x17f50, 0x11f40, 0x0cf30, 0x08720, 0x04310, 0x00100}; + static u4Byte tx_gain_tbl2[6] + = {0x15ea0, 0x10e90, 0x0c680, 0x08250, 0x04040, 0x00030}; + u1Byte i; + + if (RF_Path_Type == 2 && (DataRate&0xF) <= 0x7) + { + PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, + RF_TXPA_G2, bMask20Bits, 0x0f000); + PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, + RF_TXPA_G3, bMask20Bits, 0xeacf1); + + for (i = 0; i < 6; i++) + PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, + RF_TX_AGC, bMask20Bits, tx_gain_tbl1[i]); + + PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, + RF_TXPA_G2, bMask20Bits, 0x01e39); + } + else if (RF_Path_Type == 1 && (DataRate&0xF) >= 0x8) + { + PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, + RF_TXPA_G2, bMask20Bits, 0x04440); + PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, + RF_TXPA_G3, bMask20Bits, 0xea4f1); + + for (i = 0; i < 6; i++) + PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, + RF_TX_AGC, bMask20Bits, tx_gain_tbl2[i]); + + PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, + RF_TXPA_G2, bMask20Bits, 0x01e19); + } +#endif + +} /* RF_ChangeTxPath */ + + +void PHY_RF6052SetBandwidth(struct net_device* dev, HT_CHANNEL_WIDTH Bandwidth) +{ + u8 eRFPath; + struct r8192_priv *priv = rtllib_priv(dev); + + + if (IS_HARDWARE_TYPE_8192SE(dev)) + { +#if (RTL92SE_FPGA_VERIFY == 0) + switch(Bandwidth) + { + case HT_CHANNEL_WIDTH_20: +#if 1 + priv->RfRegChnlVal[0] = ((priv->RfRegChnlVal[0] & 0xfffff3ff) | 0x0400); + rtl8192_phy_SetRFReg(dev, RF90_PATH_A, RF_CHNLBW, bRFRegOffsetMask, priv->RfRegChnlVal[0]); +#else + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, RF_CHNLBW, BIT10|BIT11, 0x01); +#endif + break; + case HT_CHANNEL_WIDTH_20_40: +#if 1 + priv->RfRegChnlVal[0] = ((priv->RfRegChnlVal[0] & 0xfffff3ff)); + rtl8192_phy_SetRFReg(dev, RF90_PATH_A, RF_CHNLBW, bRFRegOffsetMask, priv->RfRegChnlVal[0]); +#else + rtl8192_phy_SetRFReg(dev, (RF90_RADIO_PATH_E)RF90_PATH_A, RF_CHNLBW, BIT10|BIT11, 0x00); +#endif + break; + default: + RT_TRACE(COMP_DBG, "PHY_SetRF6052Bandwidth(): unknown Bandwidth: %#X\n",Bandwidth); + break; + } +#endif + } + else + { + for(eRFPath = 0; eRFPath NumTotalRFPath; eRFPath++) + { + switch(Bandwidth) + { + case HT_CHANNEL_WIDTH_20: + break; + case HT_CHANNEL_WIDTH_20_40: + break; + default: + RT_TRACE(COMP_DBG, "PHY_SetRF8225Bandwidth(): unknown Bandwidth: %#X\n",Bandwidth ); + break; + + } + } + } +} + + +extern void PHY_RF6052SetCckTxPower(struct net_device* dev, u8 powerlevel) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 TxAGC=0; + bool dontIncCCKOrTurboScanOff=false; + + if (((priv->eeprom_version >= 2) && (priv->TxPwrSafetyFlag == 1)) || + ((priv->eeprom_version >= 2) && (priv->EEPROMRegulatory != 0))) { + dontIncCCKOrTurboScanOff = true; + } + + if(rtllib_act_scanning(priv->rtllib,true) == true){ + TxAGC = 0x3f; + + if(dontIncCCKOrTurboScanOff ) + TxAGC = powerlevel; + } else { + TxAGC = powerlevel; + + if(priv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) + TxAGC = 0x10; + else if(priv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2) + TxAGC = 0x0; + } + + if(TxAGC > RF6052_MAX_TX_PWR) + TxAGC = RF6052_MAX_TX_PWR; + + rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC); + +} /* PHY_RF6052SetCckTxPower */ + + +#if 0 +extern void PHY_RF6052SetOFDMTxPower(struct net_device* dev, u8 powerlevel, u8 Channel) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 writeVal, powerBase0, powerBase1; + u8 index = 0; + u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; + u8 rfa_pwr[4]; + u8 rfa_lower_bound = 0, rfa_upper_bound = 0; + u8 i; + u8 rf_pwr_diff = 0, chnlGroup = 0; + u8 Legacy_pwrdiff=0, HT20_pwrdiff=0; + + if (priv->eeprom_version < 2) + powerBase0 = powerlevel + (priv->LegacyHTTxPowerDiff & 0xf); + else if (priv->eeprom_version >= 2) + { + Legacy_pwrdiff = priv->TxPwrLegacyHtDiff[RF90_PATH_A][Channel-1]; + powerBase0 = powerlevel + Legacy_pwrdiff; + RT_TRACE(COMP_POWER, " [LagacyToHT40 pwr diff = %d]\n", Legacy_pwrdiff); + RT_TRACE(COMP_POWER, " [OFDM power base index = 0x%x]\n", powerBase0); + } + powerBase0 = (powerBase0<<24) | (powerBase0<<16) |(powerBase0<<8) |powerBase0; + + if(priv->eeprom_version >= 2) + { + + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + { + HT20_pwrdiff = priv->TxPwrHt20Diff[RF90_PATH_A][Channel-1]; + + if (HT20_pwrdiff < 8) + powerlevel += HT20_pwrdiff; + else + powerlevel -= (16-HT20_pwrdiff); + + RT_TRACE(COMP_POWER, " [HT20 to HT40 pwrdiff = %d]\n", HT20_pwrdiff); + RT_TRACE(COMP_POWER, " [MCS power base index = 0x%x]\n", powerlevel); + } + } + powerBase1 = powerlevel; + powerBase1 = (powerBase1<<24) | (powerBase1<<16) |(powerBase1<<8) |powerBase1; + + RT_TRACE(COMP_POWER, " [Legacy/HT power index= %x/%x]\n", powerBase0, powerBase1); + + for(index=0; index<6; index++) + { + + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + { + writeVal = ((index<2)?powerBase0:powerBase1); + } + else + { + if(priv->pwrGroupCnt == 0) + chnlGroup = 0; + if(priv->pwrGroupCnt >= 3) + { + if(Channel <= 3) + chnlGroup = 0; + else if(Channel >= 4 && Channel <= 9) + chnlGroup = 1; + else if(Channel >= 10) + chnlGroup = 2; + if(priv->pwrGroupCnt == 4) + chnlGroup ++; + } + else + chnlGroup = 0; + writeVal = priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index] + + ((index<2)?powerBase0:powerBase1); + } + RT_TRACE(COMP_POWER, "Reg 0x%x, chnlGroup = %d, Original=%x writeVal=%x\n", + RegOffset[index], chnlGroup, priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index], + writeVal); + + if (priv->rf_type == RF_2T2R) + { + rf_pwr_diff = priv->AntennaTxPwDiff[0]; + RT_TRACE(COMP_POWER, "2T2R RF-B to RF-A PWR DIFF=%d\n", rf_pwr_diff); + + if (rf_pwr_diff >= 8) + { + rfa_lower_bound = 0x10-rf_pwr_diff; + RT_TRACE(COMP_POWER, "rfa_lower_bound= %d\n", rfa_lower_bound); + } + else if (rf_pwr_diff >= 0) + { + rfa_upper_bound = RF6052_MAX_TX_PWR-rf_pwr_diff; + RT_TRACE(COMP_POWER, "rfa_upper_bound= %d\n", rfa_upper_bound); + } + } + + for (i= 0; i <4; i++) + { + rfa_pwr[i] = (u8)((writeVal & (0x7f<<(i*8)))>>(i*8)); + if (rfa_pwr[i] > RF6052_MAX_TX_PWR) + rfa_pwr[i] = RF6052_MAX_TX_PWR; + + if (priv->rf_type == RF_2T2R) + { + if (rf_pwr_diff >= 8) + { + if (rfa_pwr[i] = 1) + { + if (rfa_pwr[i] > rfa_upper_bound) + { + RT_TRACE(COMP_POWER, "Overflow"); + rfa_pwr[i] = rfa_upper_bound; + } + } + RT_TRACE(COMP_POWER, "rfa_pwr[%d]=%x\n", i, rfa_pwr[i]); + } + + } + +#if 1 + writeVal = (rfa_pwr[3]<<24) | (rfa_pwr[2]<<16) |(rfa_pwr[1]<<8) |rfa_pwr[0]; + RT_TRACE(COMP_POWER, "WritePower=%08x\n", writeVal); +#else + if(priv->bDynamicTxHighPower == true) + { + if(index > 1) + { + writeVal = 0x03030303; + } + else + { + writeVal = (rfa_pwr[3]<<24) | (rfa_pwr[2]<<16) |(rfa_pwr[1]<<8) |rfa_pwr[0]; + } + RT_TRACE(COMP_POWER, "HighPower=%08x\n", writeVal); + } + else + { + writeVal = (rfa_pwr[3]<<24) | (rfa_pwr[2]<<16) |(rfa_pwr[1]<<8) |rfa_pwr[0]; + RT_TRACE(COMP_POWER, "NormalPower=%08x\n", writeVal); + } +#endif + rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); + } + +} /* PHY_RF6052SetOFDMTxPower */ +#endif + +void getPowerBase( + struct net_device* dev, + u8* pPowerLevel, + u8 Channel, + u32* OfdmBase, + u32* MCSBase, + u8* pFinalPowerIndex + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u32 powerBase0, powerBase1; + u8 Legacy_pwrdiff=0, HT20_pwrdiff=0; + u8 i, powerlevel[4]; + + for(i=0; i<2; i++) + powerlevel[i] = pPowerLevel[i]; + if (priv->eeprom_version < 2) + powerBase0 = powerlevel[0] + (priv->LegacyHTTxPowerDiff & 0xf); + else if (priv->eeprom_version >= 2) + { + Legacy_pwrdiff = priv->TxPwrLegacyHtDiff[RF90_PATH_A][Channel-1]; + powerBase0 = powerlevel[0] + Legacy_pwrdiff; + } + powerBase0 = (powerBase0<<24) | (powerBase0<<16) |(powerBase0<<8) |powerBase0; + *OfdmBase = powerBase0; + RT_TRACE(COMP_POWER, " [OFDM power base index = 0x%x]\n", powerBase0); + + if(priv->eeprom_version >= 2) + { + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20) + { + for(i=0; i<2; i++) + { + HT20_pwrdiff = priv->TxPwrHt20Diff[i][Channel-1]; + if (HT20_pwrdiff < 8) + powerlevel[i] += HT20_pwrdiff; + else + powerlevel[i] -= (16-HT20_pwrdiff); + } + } + } + powerBase1 = powerlevel[0]; + powerBase1 = (powerBase1<<24) | (powerBase1<<16) |(powerBase1<<8) |powerBase1; + *MCSBase = powerBase1; + + RT_TRACE(COMP_POWER, " [MCS power base index = 0x%x]\n", powerBase1); + + pFinalPowerIndex[0] = powerlevel[0]; + pFinalPowerIndex[1] = powerlevel[1]; + switch(priv->EEPROMRegulatory) + { + case 3: + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + { + pFinalPowerIndex[0] += priv->PwrGroupHT40[RF90_PATH_A][Channel-1]; + pFinalPowerIndex[1] += priv->PwrGroupHT40[RF90_PATH_B][Channel-1]; + } + else + { + pFinalPowerIndex[0] += priv->PwrGroupHT20[RF90_PATH_A][Channel-1]; + pFinalPowerIndex[1] += priv->PwrGroupHT20[RF90_PATH_B][Channel-1]; + } + break; + default: + break; + } + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + { + RT_TRACE(COMP_POWER, "40MHz finalPowerIndex (A / B) = 0x%x / 0x%x\n", + pFinalPowerIndex[0], pFinalPowerIndex[1]); + } + else + { + RT_TRACE(COMP_POWER, "20MHz finalPowerIndex (A / B) = 0x%x / 0x%x\n", + pFinalPowerIndex[0], pFinalPowerIndex[1]); + } +} + +void getTxPowerWriteValByRegulatory( + struct net_device* dev, + u8 Channel, + u8 index, + u32 powerBase0, + u32 powerBase1, + u32* pOutWriteVal + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u8 i, chnlGroup, pwr_diff_limit[4]; + u32 writeVal, customer_limit; + + switch(priv->EEPROMRegulatory) + { + case 0: + chnlGroup = 0; + RT_TRACE(COMP_POWER,"MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n", + chnlGroup, index, priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index]); + writeVal = priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index] + + ((index<2)?powerBase0:powerBase1); + RT_TRACE(COMP_POWER,"RTK better performance, writeVal = 0x%x\n", writeVal); + break; + case 1: + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + { + writeVal = ((index<2)?powerBase0:powerBase1); + RT_TRACE(COMP_POWER,"Realtek regulatory, 40MHz, writeVal = 0x%x\n", writeVal); + } + else + { + if(priv->pwrGroupCnt == 1) + chnlGroup = 0; + if(priv->pwrGroupCnt >= 3) + { + if(Channel <= 3) + chnlGroup = 0; + else if(Channel >= 4 && Channel <= 8) + chnlGroup = 1; + else if(Channel > 8) + chnlGroup = 2; + if(priv->pwrGroupCnt == 4) + chnlGroup++; + } + RT_TRACE(COMP_POWER,"MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n", + chnlGroup, index, priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index]); + writeVal = priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index] + + ((index<2)?powerBase0:powerBase1); + RT_TRACE(COMP_POWER,"Realtek regulatory, 20MHz, writeVal = 0x%x\n", writeVal); + } + break; + case 2: + writeVal = ((index<2)?powerBase0:powerBase1); + RT_TRACE(COMP_POWER,"Better regulatory, writeVal = 0x%x\n", writeVal); + break; + case 3: + chnlGroup = 0; + RT_TRACE(COMP_POWER,"MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n", + chnlGroup, index, priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index]); + + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + { + RT_TRACE(COMP_POWER,"customer's limit, 40MHz = 0x%x\n", + priv->PwrGroupHT40[RF90_PATH_A][Channel-1]); + } + else + { + RT_TRACE(COMP_POWER,"customer's limit, 20MHz = 0x%x\n", + priv->PwrGroupHT20[RF90_PATH_A][Channel-1]); + } + for (i=0; i<4; i++) + { + pwr_diff_limit[i] = (u8)((priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index]&(0x7f<<(i*8)))>>(i*8)); + if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20_40) + { + if(pwr_diff_limit[i] > priv->PwrGroupHT40[RF90_PATH_A][Channel-1]) + { + pwr_diff_limit[i] = priv->PwrGroupHT40[RF90_PATH_A][Channel-1]; + } + } + else + { + if(pwr_diff_limit[i] > priv->PwrGroupHT20[RF90_PATH_A][Channel-1]) + { + pwr_diff_limit[i] = priv->PwrGroupHT20[RF90_PATH_A][Channel-1]; + } + } + } + customer_limit = (pwr_diff_limit[3]<<24) | (pwr_diff_limit[2]<<16) | + (pwr_diff_limit[1]<<8) | (pwr_diff_limit[0]); + RT_TRACE(COMP_POWER,"Customer's limit = 0x%x\n", customer_limit); + + writeVal = customer_limit + ((index<2)?powerBase0:powerBase1); + RT_TRACE(COMP_POWER,"Customer, writeVal = 0x%x\n", writeVal); + break; + default: + chnlGroup = 0; + writeVal = priv->MCSTxPowerLevelOriginalOffset[chnlGroup][index] + + ((index<2)?powerBase0:powerBase1); + RT_TRACE(COMP_POWER,"RTK better performance, writeVal = 0x%x\n", writeVal); + break; + } + + if(priv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level1) + writeVal = 0x10101010; + else if(priv->DynamicTxHighPowerLvl == TxHighPwrLevel_Level2) + writeVal = 0x0; + + *pOutWriteVal = writeVal; + +} + +void setAntennaDiff( + struct net_device* dev, + u8* pFinalPowerIndex + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + char ant_pwr_diff=0; + u32 u4RegValue=0; + + if (priv->rf_type == RF_2T2R) + { + ant_pwr_diff = pFinalPowerIndex[1] - pFinalPowerIndex[0]; + + if(ant_pwr_diff > 7) + ant_pwr_diff = 7; + if(ant_pwr_diff < -8) + ant_pwr_diff = -8; + RT_TRACE(COMP_POWER,"Antenna Diff from RF-B to RF-A = %d (0x%x)\n", + ant_pwr_diff, ant_pwr_diff&0xf); + ant_pwr_diff &= 0xf; + } + priv->AntennaTxPwDiff[2] = 0; + priv->AntennaTxPwDiff[1] = 0; + priv->AntennaTxPwDiff[0] = (u8)(ant_pwr_diff); + + u4RegValue = (priv->AntennaTxPwDiff[2]<<8 | + priv->AntennaTxPwDiff[1]<<4 | + priv->AntennaTxPwDiff[0] ); + + rtl8192_setBBreg(dev, rFPGA0_TxGainStage, + (bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue); + + RT_TRACE(COMP_POWER,"Write BCD-Diff(0x%x) = 0x%x\n", + rFPGA0_TxGainStage, u4RegValue); +} + +void writeOFDMPowerReg( + struct net_device* dev, + u8 index, + u32 Value + ) +{ + struct r8192_priv *priv = rtllib_priv(dev); + u16 RegOffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; + u8 i, rfa_pwr[4]; + u8 rfa_lower_bound = 0, rfa_upper_bound = 0, rf_pwr_diff = 0; + u32 writeVal=Value; + if (priv->rf_type == RF_2T2R) + { + rf_pwr_diff = priv->AntennaTxPwDiff[0]; + + if (rf_pwr_diff >= 8) + { + rfa_lower_bound = 0x10-rf_pwr_diff; + RT_TRACE(COMP_POWER,"rfa_lower_bound= %d\n", rfa_lower_bound); + } + else + { + rfa_upper_bound = RF6052_MAX_TX_PWR-rf_pwr_diff; + RT_TRACE(COMP_POWER,"rfa_upper_bound= %d\n", rfa_upper_bound); + } + } + + for (i=0; i<4; i++) + { + rfa_pwr[i] = (u8)((writeVal & (0x7f<<(i*8)))>>(i*8)); + if (rfa_pwr[i] > RF6052_MAX_TX_PWR) + rfa_pwr[i] = RF6052_MAX_TX_PWR; + + if (priv->rf_type == RF_2T2R) + { + if (rf_pwr_diff >= 8) + { + if (rfa_pwr[i] = 1) + { + if (rfa_pwr[i] > rfa_upper_bound) + { + RT_TRACE(COMP_POWER,"Overflow"); + rfa_pwr[i] = rfa_upper_bound; + } + } + RT_TRACE(COMP_POWER,"rfa_pwr[%d]=%x\n", i, rfa_pwr[i]); + } + + } + + writeVal = (rfa_pwr[3]<<24) | (rfa_pwr[2]<<16) |(rfa_pwr[1]<<8) |rfa_pwr[0]; + + rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal); + RT_TRACE(COMP_POWER,"Set 0x%x = %08x\n",RegOffset[index], writeVal); +} + +/*----------------------------------------------------------------------------- + * Function: PHY_RF6052SetOFDMTxPower + * + * Overview: For legacy and HY OFDM, we must read EEPROM TX power index for + * different channel and read original value in TX power register area from + * 0xe00. We increase offset and original value to be correct tx pwr. + * + * Input: NONE + * + * Output: NONE + * + * Return: NONE + * + * Revised History: + * When Who Remark + * 11/05/2008 MHC Simulate 8192 series method. + * 01/06/2009 MHC 1. Prevent Path B tx power overflow or underflow dure to + * A/B pwr difference or legacy/HT pwr diff. + * 2. We concern with path B legacy/HT OFDM difference. + * 01/22/2009 MHC Support new EPRO format from SD3. + * + *---------------------------------------------------------------------------*/ +extern void +PHY_RF6052SetOFDMTxPower(struct net_device* dev, u8* pPowerLevel, u8 Channel) +{ + u32 writeVal, powerBase0, powerBase1; + u8 index = 0; + u8 finalPowerIndex[4]; + + getPowerBase(dev, pPowerLevel, Channel, &powerBase0, &powerBase1, &finalPowerIndex[0]); + setAntennaDiff(dev, &finalPowerIndex[0] ); + + for(index=0; index<6; index++) + { + getTxPowerWriteValByRegulatory(dev, Channel, index, + powerBase0, powerBase1, &writeVal); + + writeOFDMPowerReg(dev, index, writeVal); + } +} + +bool PHY_RF6052_Config(struct net_device* dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + bool rtStatus = true; + u8 bRegHwParaFile = 1; + + if(priv->rf_type == RF_1T1R) + priv->NumTotalRFPath = 1; + else + priv->NumTotalRFPath = 2; + + switch(bRegHwParaFile) + { + case 0: + phy_RF6052_Config_HardCode(dev); + break; + + case 1: + rtStatus = phy_RF6052_Config_ParaFile(dev); + break; + + case 2: + phy_RF6052_Config_HardCode(dev); + phy_RF6052_Config_ParaFile(dev); + break; + + default: + phy_RF6052_Config_HardCode(dev); + break; + } + return rtStatus; + +} + +void phy_RF6052_Config_HardCode(struct net_device* dev) +{ + + + +} + +bool phy_RF6052_Config_ParaFile(struct net_device* dev) +{ + u32 u4RegValue = 0; + u8 eRFPath; + bool rtStatus = true; + struct r8192_priv *priv = rtllib_priv(dev); + BB_REGISTER_DEFINITION_T *pPhyReg; + + + for(eRFPath = 0; eRFPath NumTotalRFPath; eRFPath++) + { + + pPhyReg = &priv->PHYRegDef[eRFPath]; + + switch(eRFPath) + { + case RF90_PATH_A: + case RF90_PATH_C: + u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV); + break; + case RF90_PATH_B : + case RF90_PATH_D: + u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16); + break; + } + + rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1); + + rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1); + + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireAddressLength, 0x0); + rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, b3WireDataLength, 0x0); + + + switch(eRFPath) + { + case RF90_PATH_A: +#if RTL8190_Download_Firmware_From_Header + rtStatus= rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath); +#else + rtStatus = PHY_ConfigRFWithParaFile(dev, (char* )&szRadioAFile, (RF90_RADIO_PATH_E)eRFPath); +#endif + break; + case RF90_PATH_B: +#if RTL8190_Download_Firmware_From_Header + rtStatus= rtl8192_phy_ConfigRFWithHeaderFile(dev,(RF90_RADIO_PATH_E)eRFPath); +#else + if(priv->rf_type == RF_2T2R_GREEN) + rtStatus = PHY_ConfigRFWithParaFile(dev, (char *)&szRadioBGMFile, (RF90_RADIO_PATH_E)eRFPath); + else + rtStatus = PHY_ConfigRFWithParaFile(dev, (char* )&szRadioBFile, (RF90_RADIO_PATH_E)eRFPath); +#endif + break; + case RF90_PATH_C: + break; + case RF90_PATH_D: + break; + } + + switch(eRFPath) + { + case RF90_PATH_A: + case RF90_PATH_C: + rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV, u4RegValue); + break; + case RF90_PATH_B : + case RF90_PATH_D: + rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16, u4RegValue); + break; + } + + if(rtStatus != true){ + printk("phy_RF6052_Config_ParaFile():Radio[%d] Fail!!", eRFPath); + goto phy_RF6052_Config_ParaFile_Fail; + } + + } + + RT_TRACE(COMP_INIT, "<---phy_RF6052_Config_ParaFile()\n"); + return rtStatus; + +phy_RF6052_Config_ParaFile_Fail: + return rtStatus; +} + + +extern u32 PHY_RFShadowRead( + struct net_device * dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset) +{ + return RF_Shadow[eRFPath][Offset].Value; + +} /* PHY_RFShadowRead */ + + +extern void PHY_RFShadowWrite( + struct net_device * dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset, + u32 Data) +{ + RF_Shadow[eRFPath][Offset].Value = (Data & bMask20Bits); + RF_Shadow[eRFPath][Offset].Driver_Write = true; + +} /* PHY_RFShadowWrite */ + + +extern bool PHY_RFShadowCompare( + struct net_device * dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset) +{ + u32 reg; + + if (RF_Shadow[eRFPath][Offset].Compare == true) + { + reg = rtl8192_phy_QueryRFReg(dev, eRFPath, Offset, bMask20Bits); + if (RF_Shadow[eRFPath][Offset].Value != reg) + { + RF_Shadow[eRFPath][Offset].ErrorOrNot = true; + RT_TRACE(COMP_INIT, "PHY_RFShadowCompare RF-%d Addr%02xErr = %05x", eRFPath, Offset, reg); + } + else + { + RT_TRACE(COMP_INIT, "PHY_RFShadowCompare RF-%d Addr%02x Err = %05x return false\n", eRFPath, Offset, reg); + RF_Shadow[eRFPath][Offset].ErrorOrNot = false; + } + return RF_Shadow[eRFPath][Offset].ErrorOrNot; + } + return false; +} /* PHY_RFShadowCompare */ + +extern void PHY_RFShadowRecorver( + struct net_device * dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset) +{ + if (RF_Shadow[eRFPath][Offset].ErrorOrNot == true) + { + if (RF_Shadow[eRFPath][Offset].Recorver == true) + { + rtl8192_phy_SetRFReg(dev, eRFPath, Offset, bMask20Bits, RF_Shadow[eRFPath][Offset].Value); + RT_TRACE(COMP_INIT, "PHY_RFShadowRecorver RF-%d Addr%02x=%05x", + eRFPath, Offset, RF_Shadow[eRFPath][Offset].Value); + } + } + +} /* PHY_RFShadowRecorver */ + + +extern void PHY_RFShadowCompareAll(struct net_device * dev) +{ + u32 eRFPath; + u32 Offset; + + for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) + { + for (Offset = 0; Offset <= RF6052_MAX_REG; Offset++) + { + PHY_RFShadowCompare(dev, (RF90_RADIO_PATH_E)eRFPath, Offset); + } + } + +} /* PHY_RFShadowCompareAll */ + + +extern void PHY_RFShadowRecorverAll(struct net_device * dev) +{ + u32 eRFPath; + u32 Offset; + + for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) + { + for (Offset = 0; Offset <= RF6052_MAX_REG; Offset++) + { + PHY_RFShadowRecorver(dev, (RF90_RADIO_PATH_E)eRFPath, Offset); + } + } + +} /* PHY_RFShadowRecorverAll */ + + +extern void PHY_RFShadowCompareFlagSet( + struct net_device * dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset, + u8 Type) +{ + RF_Shadow[eRFPath][Offset].Compare = Type; + +} /* PHY_RFShadowCompareFlagSet */ + + +extern void PHY_RFShadowRecorverFlagSet( + struct net_device * dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset, + u8 Type) +{ + RF_Shadow[eRFPath][Offset].Recorver= Type; + +} /* PHY_RFShadowRecorverFlagSet */ + + +extern void PHY_RFShadowCompareFlagSetAll(struct net_device * dev) +{ + u32 eRFPath; + u32 Offset; + + for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) + { + for (Offset = 0; Offset <= RF6052_MAX_REG; Offset++) + { + if (Offset != 0x26 && Offset != 0x27) + PHY_RFShadowCompareFlagSet(dev, (RF90_RADIO_PATH_E)eRFPath, Offset, false); + else + PHY_RFShadowCompareFlagSet(dev, (RF90_RADIO_PATH_E)eRFPath, Offset, true); + } + } + +} /* PHY_RFShadowCompareFlagSetAll */ + + +extern void PHY_RFShadowRecorverFlagSetAll(struct net_device * dev) +{ + u32 eRFPath; + u32 Offset; + + for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) + { + for (Offset = 0; Offset <= RF6052_MAX_REG; Offset++) + { + if (Offset != 0x26 && Offset != 0x27) + PHY_RFShadowRecorverFlagSet(dev, (RF90_RADIO_PATH_E)eRFPath, Offset, false); + else + PHY_RFShadowRecorverFlagSet(dev, (RF90_RADIO_PATH_E)eRFPath, Offset, true); + } + } + +} /* PHY_RFShadowCompareFlagSetAll */ + + + +extern void PHY_RFShadowRefresh(struct net_device * dev) +{ + u32 eRFPath; + u32 Offset; + + for (eRFPath = 0; eRFPath < RF6052_MAX_PATH; eRFPath++) + { + for (Offset = 0; Offset <= RF6052_MAX_REG; Offset++) + { + RF_Shadow[eRFPath][Offset].Value = 0; + RF_Shadow[eRFPath][Offset].Compare = false; + RF_Shadow[eRFPath][Offset].Recorver = false; + RF_Shadow[eRFPath][Offset].ErrorOrNot = false; + RF_Shadow[eRFPath][Offset].Driver_Write = false; + } + } + +} /* PHY_RFShadowRead */ + +/* End of HalRf6052.c */ + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_rtl6052.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_rtl6052.h @@ -0,0 +1,116 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ + + +/*--------------------------Define Parameters-------------------------------*/ + +#define RF6052_MAX_TX_PWR 0x3F +#define RF6052_MAX_REG 0x3F +#define RF6052_MAX_PATH 4 +/*--------------------------Define Parameters-------------------------------*/ + + +/*------------------------------Define structure----------------------------*/ + +/*------------------------------Define structure----------------------------*/ + + +/*------------------------Export global variable----------------------------*/ +/*------------------------Export global variable----------------------------*/ + +/*------------------------Export Marco Definition---------------------------*/ + +/*------------------------Export Marco Definition---------------------------*/ + + +/*--------------------------Exported Function prototype---------------------*/ +#if 1 +extern void PHY_SetRF0222DBandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth); +extern void PHY_SetRF8225Bandwidth( struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth); +extern bool PHY_RF8225_Config(struct net_device* dev ); +extern void phy_RF8225_Config_HardCode(struct net_device* dev); +extern bool phy_RF8225_Config_ParaFile(struct net_device* dev); +extern void PHY_SetRF8225CckTxPower(struct net_device* dev ,u8 powerlevel); +extern void PHY_SetRF8225OfdmTxPower(struct net_device* dev ,u8 powerlevel); +extern void PHY_SetRF0222DOfdmTxPower(struct net_device* dev ,u8 powerlevel); +extern void PHY_SetRF0222DCckTxPower(struct net_device* dev ,u8 powerlevel); + +extern void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth); +extern void PHY_RF8256_Config(struct net_device* dev); +extern void phy_RF8256_Config_ParaFile(struct net_device* dev); +extern void PHY_SetRF8256CCKTxPower(struct net_device* dev, u8 powerlevel); +extern void PHY_SetRF8256OFDMTxPower(struct net_device* dev, u8 powerlevel); +#endif + +extern void RF_ChangeTxPath(struct net_device * dev, u16 DataRate); +extern void PHY_RF6052SetBandwidth(struct net_device * dev,HT_CHANNEL_WIDTH Bandwidth); +extern void PHY_RF6052SetCckTxPower(struct net_device * dev, u8 powerlevel); +extern void PHY_RF6052SetOFDMTxPower(struct net_device * dev, u8* pPowerLevel, u8 Channel); +extern bool PHY_RF6052_Config(struct net_device * dev); +extern void PHY_RFShadowRefresh( struct net_device * dev); +extern void PHY_RFShadowWrite( struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data); + +extern bool +PHY_RFShadowCompare( + struct net_device * dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset); +extern void +PHY_RFShadowRecorver( + struct net_device * dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset); +extern void +PHY_RFShadowCompareFlagSet( + struct net_device * dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset, + u8 Type); +extern void +PHY_RFShadowRecorverFlagSet( + struct net_device * dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset, + u8 Type); +#if 0 +extern u32 +PHY_RFShadowRead( + struct net_device * dev, + RF90_RADIO_PATH_E eRFPath, + u32 Offset); +extern void +PHY_RFShadowCompareAll( + struct net_device * dev); +extern void +PHY_RFShadowRecorverAll( + struct net_device * dev); +extern void +PHY_RFShadowCompareFlagSetAll( + struct net_device * dev); +extern void +PHY_RFShadowRecorverFlagSetAll( + struct net_device * dev); +extern void +PHY_RFShadowRefresh( + struct net_device * dev); +#endif +/*--------------------------Exported Function prototype---------------------*/ + + +/* End of HalRf.h */ --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_scan.c +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_scan.c @@ -0,0 +1,413 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#include "../rtl_core.h" + +#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) + +void rtl8192se_hw_scan_simu(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,hw_scan_simu_wq); + struct net_device *dev = priv->rtllib->dev; +#else + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = rtllib_priv(dev); +#endif + + rtllib_update_active_chan_map(priv->rtllib); + + priv->rtllib->current_network.channel = (priv->rtllib->current_network.channel + 1) % 12; + if (priv->rtllib->scan_watch_dog++ > 12) + { + goto out; /* no good chans */ + } + + if ((!test_bit(STATUS_SCANNING, &priv->rtllib->status)) || + (test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status))){ + goto out; + } + + if(priv->rtllib->current_network.channel != 0){ + priv->rtllib->set_chan(dev,priv->rtllib->current_network.channel); +#ifdef _RTL8192_EXT_PATCH_ + rtllib_send_probe_requests(priv->rtllib, 1); +#else + rtllib_send_probe_requests(priv->rtllib, 0); +#endif + } + + queue_delayed_work_rsl(priv->priv_wq, &priv->hw_scan_simu_wq, MSECS(RTLLIB_SOFTMAC_SCAN_TIME)); + + return; +out: + priv->rtllib->scan_watch_dog =0; + rtl8192se_rx_surveydone_cmd(dev); + + if(priv->rtllib->state == RTLLIB_LINKED_SCANNING){ + priv->rtllib->current_network.channel = priv->rtllib->hwscan_ch_bk; + printk("%s():back to linked chan:%d\n", __func__,priv->rtllib->current_network.channel); + priv->rtllib->set_chan(dev,priv->rtllib->current_network.channel); + } +} + +void rtl8192se_before_hw_scan(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + HT_EXTCHNL_OFFSET chan_offset=0; + HT_CHANNEL_WIDTH bandwidth=0; + struct rtllib_device *ieee = priv->rtllib; + + if(priv->rtllib->state != RTLLIB_LINKED) + return; + + +#ifdef ENABLE_LPS + if (ieee->LeisurePSLeave) { + ieee->LeisurePSLeave(ieee->dev); + } + /* notify AP to be in PS mode */ + rtllib_sta_ps_send_null_frame(ieee, 1); + rtllib_sta_ps_send_null_frame(ieee, 1); +#endif + + rtllib_stop_all_queues(ieee); + + if (ieee->data_hard_stop) + ieee->data_hard_stop(ieee->dev); + rtllib_stop_send_beacons(ieee); + ieee->state = RTLLIB_LINKED_SCANNING; + ieee->link_change(ieee->dev); + /* wait for ps packet to be kicked out successfully */ + mdelay(50); + +#if(RTL8192S_DISABLE_FW_DM == 0) + if (ieee->SetFwCmdHandler) { + ieee->SetFwCmdHandler(ieee->dev, FW_CMD_PAUSE_DM_BY_SCAN); + } +#endif + + if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) { + priv->hwscan_bw_40 = 1; + priv->rtllib->chan_offset_bk = chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset; + priv->rtllib->bandwidth_bk = bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz; + printk("before scan force BW to 20M:%d, %d\n", chan_offset, bandwidth); + ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + } +} +void rtl8192se_after_hw_scan(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + HT_EXTCHNL_OFFSET chan_offset = priv->rtllib->chan_offset_bk; + HT_CHANNEL_WIDTH bandwidth = priv->rtllib->bandwidth_bk; + struct rtllib_device *ieee = priv->rtllib; + + if(priv->rtllib->state != RTLLIB_LINKED_SCANNING){ + goto out; + } + + if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 || + ieee->LinkDetectInfo.NumRecvDataInPeriod == 0 ) { + ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1; + ieee->LinkDetectInfo.NumRecvDataInPeriod= 1; + } + + if (priv->hwscan_bw_40) { + priv->hwscan_bw_40 = 0; + printk("after scan back BW to 40M:%d, %d\n", chan_offset, bandwidth); +#if 1 + if (chan_offset == HT_EXTCHNL_OFFSET_UPPER){ + ieee->set_chan(ieee->dev, priv->rtllib->hwscan_ch_bk + 2); + }else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER){ + ieee->set_chan(ieee->dev, priv->rtllib->hwscan_ch_bk - 2); + }else{ + priv->rtllib->current_network.channel = priv->rtllib->hwscan_ch_bk; + ieee->set_chan(ieee->dev, priv->rtllib->hwscan_ch_bk); + } +#endif + ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset); + } else { + ieee->set_chan(ieee->dev, priv->rtllib->hwscan_ch_bk); + } + +#if(RTL8192S_DISABLE_FW_DM == 0) + if (ieee->SetFwCmdHandler) { + ieee->SetFwCmdHandler(ieee->dev, FW_CMD_RESUME_DM_BY_SCAN); + } +#endif + ieee->state = RTLLIB_LINKED; + ieee->link_change(ieee->dev); + +#ifdef ENABLE_LPS + /* Notify AP that I wake up again */ + rtllib_sta_ps_send_null_frame(ieee, 0); +#endif + + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + + if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) + rtllib_start_send_beacons(ieee); + + rtllib_wake_all_queues(ieee); + +out: + return; +} +/* Service HAL_FW_C2H_CMD_SurveyDone (0x9) */ +void rtl8192se_rx_surveydone_cmd(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + + + + cancel_delayed_work(&priv->check_hw_scan_wq); + + /* If a request to abort was given, or the scan did not succeed + * then we reset the scan state machine and terminate, + * re-queuing another scan if one has been requested */ + if (test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status)) { + RT_TRACE(COMP_ERR, "Aborted scan completed.\n"); + clear_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status); + } + + rtl8192se_after_hw_scan(dev); + +#ifdef CONFIG_FW_PARSEBEACON + if(priv->rtllib->state < RTLLIB_LINKED) + write_nic_dword(dev, RXFILTERMAP, 0x0100); +#endif + + mdelay(1); + + clear_bit(STATUS_SCANNING, &priv->rtllib->status); + + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof(wrqu)); + wireless_send_event(priv->rtllib->dev,SIOCGIWSCAN,&wrqu,NULL); + } + + if(priv->rtllib->hwscan_sem_up == 0){ + up(&priv->wx_sem); + priv->rtllib->hwscan_sem_up = 1; + } + + + return; +} + + +void rtl8192se_check_hw_scan(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,check_hw_scan_wq); + struct net_device *dev = priv->rtllib->dev; +#else + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = rtllib_priv(dev); +#endif + unsigned long flags; + + + spin_lock_irqsave(&priv->fw_scan_lock,flags); + printk("----------->%s()\n", __func__); + + if (test_bit(STATUS_SCANNING, &priv->rtllib->status) || + test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status)) { + printk("FW Scan long time without stop, stop hw scan\n"); + rtl8192se_send_scan_abort(dev); + } + + + if(priv->rtllib->hwscan_sem_up == 0){ + up(&priv->wx_sem); + priv->rtllib->hwscan_sem_up = 1; + } + + printk("<-----------%s()\n", __func__); + spin_unlock_irqrestore(&priv->fw_scan_lock,flags); +} + +void rtl8192se_start_hw_scan(void *data) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) + struct r8192_priv *priv = container_of_dwork_rsl(data,struct r8192_priv,start_hw_scan_wq); + struct net_device *dev = priv->rtllib->dev; +#else + struct net_device *dev = (struct net_device *)data; + struct r8192_priv *priv = rtllib_priv(dev); +#endif + bool start_flag =true; + unsigned long flags; + + down(&priv->wx_sem); + priv->rtllib->hwscan_sem_up = 0; + + spin_lock_irqsave(&priv->fw_scan_lock,flags); + + + cancel_delayed_work(&priv->check_hw_scan_wq); + + /* Make sure the scan wasn't canceled before this queued work + * was given the chance to run... */ + if (!test_bit(STATUS_SCANNING, &priv->rtllib->status)){ + RT_TRACE(COMP_ERR,"scan was canceled."); + goto done; + } + + if (test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status)) { + RT_TRACE(COMP_ERR, "Scan request while abort pending. Queuing."); + goto done; + } + + +#ifdef CONFIG_FW_PARSEBEACON + if(priv->rtllib->state < RTLLIB_LINKED) + write_nic_dword(dev, RXFILTERMAP, 0x0000); +#endif + + rtl8192se_before_hw_scan(dev); + rtl8192se_send_scan_cmd(dev,start_flag); + + queue_delayed_work_rsl(priv->priv_wq,&priv->check_hw_scan_wq,MSECS(7000)); + + + spin_unlock_irqrestore(&priv->fw_scan_lock,flags); + + return; + + done: + up(&priv->wx_sem); + priv->rtllib->hwscan_sem_up = 1; + /* Cannot perform scan. Make sure we clear scanning + * bits from status so next scan request can be performed. + * If we don't clear scanning status bit here all next scan + * will fail + */ + clear_bit(STATUS_SCANNING, &priv->rtllib->status); + + /* inform mac80211 scan aborted */ + + spin_unlock_irqrestore(&priv->fw_scan_lock,flags); + + return; +} + +void rtl8192se_hw_scan_initiate(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&priv->fw_scan_lock,flags); + + + if (test_bit(STATUS_SCANNING, &priv->rtllib->status)) { + printk("Scan already in progress.\n"); + goto done; + } + + if (test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status)) { + printk("Scan request while abort pending\n"); + goto done; + } + + + set_bit(STATUS_SCANNING, &priv->rtllib->status); + + queue_delayed_work_rsl(priv->priv_wq,&priv->start_hw_scan_wq,0); + +done: + spin_unlock_irqrestore(&priv->fw_scan_lock,flags); + + return; +} + +void rtl8192se_send_scan_abort(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + int ret = true; + bool start_flag =false; + + + /* If there isn't a scan actively going on in the hardware + * then we are in between scan bands and not actually + * actively scanning, so don't send the abort command */ + if (!test_bit(STATUS_SCANNING, &priv->rtllib->status)) { + goto done; + } + + ret = rtl8192se_send_scan_cmd(dev, start_flag); + mdelay(1); + +#ifdef CONFIG_FW_PARSEBEACON + if(priv->rtllib->state < RTLLIB_LINKED) + write_nic_dword(dev, RXFILTERMAP, 0x0100); +#endif + + if (ret) { + goto done; + } + + +done: + clear_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status); + clear_bit(STATUS_SCANNING, &priv->rtllib->status); + + return; +} + +/** + * rtl8192se_cancel_hw_scan - Cancel any currently executing HW scan + * + * NOTE: priv->mutex is not required before calling this function + */ +void rtl8192se_cancel_hw_scan(struct net_device *dev) +{ + struct r8192_priv *priv = rtllib_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&priv->fw_scan_lock,flags); + + if (test_bit(STATUS_SCANNING, &priv->rtllib->status)) { + if (!test_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status)) { + printk("====>%s stop HW scan\n", __func__); + cancel_delayed_work(&priv->check_hw_scan_wq); + + set_bit(STATUS_SCAN_ABORTING, &priv->rtllib->status); + rtl8192se_send_scan_abort(dev); + } else { + printk("-------------->%s()Scan abort already in progress.\n", __func__); + } + } + + if(priv->rtllib->hwscan_sem_up == 0){ + up(&priv->wx_sem); + priv->rtllib->hwscan_sem_up = 1; + } + + spin_unlock_irqrestore(&priv->fw_scan_lock,flags); + return; +} + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtl8192s/r8192S_scan.h +++ linux-2.6.37/ubuntu/rtl8192se/rtl8192s/r8192S_scan.h @@ -0,0 +1,38 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * Based on the r8180 driver, which is: + * Copyright 2004-2005 Andrea Merello , et al. + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef _RTL8192SE_SCAN +#define _RTL8192SE_SCAN + +void rtl8192se_hw_scan_simu(void *data); +void rtl8192se_rx_surveydone_cmd(struct net_device *dev); +void rtl8192se_check_hw_scan(void *data); +void rtl8192se_start_hw_scan(void *data); +void rtl8192se_abort_hw_scan(struct net_device *dev); +void rtl8192se_hw_scan_initiate(struct net_device *dev); +void rtl8192se_send_scan_abort(struct net_device *dev); +void rtl8192se_cancel_hw_scan(struct net_device *dev); + +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/Makefile +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/Makefile @@ -0,0 +1,214 @@ +NIC_SELECT = RTL8192SE + +KVER := $(shell uname -r) +MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/$(NIC_SELECT) + +CC = gcc +ifneq ($(shell uname -r|cut -d. -f1,2), 2.4) +EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/wireless +EXTRA_CFLAGS += -O2 + +#it will fail to compile in suse linux enterprise 10 sp2. This flag is to solve this problem. +ifeq ($(shell uname -r | cut -d. -f1,2,3,4), 2.6.16.60-0) +EXTRA_CFLAGS += -DOPENSUSE_SLED +endif +ifeq ($(NIC_SELECT), RTL8192SE) + EXTRA_CFLAGS += -DRTL8192S_DISABLE_FW_DM=0 + EXTRA_CFLAGS += -DRTL8192SE + EXTRA_CFLAGS += -DENABLE_IPS + EXTRA_CFLAGS += -DENABLE_LPS +endif +ifeq ($(NIC_SELECT), RTL8192SU) + EXTRA_CFLAGS += -DRTL8192S_DISABLE_FW_DM=0 + EXTRA_CFLAGS += -DRTL8192SU + EXTRA_CFLAGS += -DENABLE_IPS + EXTRA_CFLAGS += -DENABLE_LPS + EXTRA_CFLAGS += -DUSB_RX_AGGREGATION_SUPPORT + EXTRA_CFLAGS += -DTCP_CSUM_OFFLOAD_RX +endif +ifeq ($(NIC_SELECT), RTL8190P) + EXTRA_CFLAGS += -DRTL8190P +endif +ifeq ($(NIC_SELECT), RTL8192E) + EXTRA_CFLAGS += -DRTL8192E + EXTRA_CFLAGS += -DENABLE_IPS + EXTRA_CFLAGS += -DENABLE_LPS +endif +ifeq ($(NIC_SELECT),RTL8192U) +EXTRA_CFLAGS += -DRTL8192U +#EXTRA_CFLAGS += -DENABLE_AMSDU +EXTRA_CFLAGS += -DUSB_TX_DRIVER_AGGREGATION_ENABLE +EXTRA_CFLAGS += -DUSB_RX_AGGREGATION_SUPPORT + +# For RTK DMP platform +#EXTRA_CFLAGS += -DRTK_DMP_PLATFORM +#EXTRA_CFLAGS += -DWIFI_TEST + +endif +ifeq ($(NIC_SELECT), RTL8191SE_MESH) +AUTHTYPE=SAE +#AUTHTYPE=OPEN +EXTRA_CFLAGS += -DRTL8192SE \ + -DRTL8192S_DISABLE_FW_DM=0 \ + -D_RTL8192_EXT_PATCH_\ + -DENABLE_IPS \ + -DENABLE_LPS \ + -DCUSTOMER_ID_INTEL_CMPC +ifeq ($(AUTHTYPE),SAE) +EXTRA_CFLAGS += -DMESH_ABBR_HANDSHK_SUPPORT\ + -DMESH_ATH_2 +endif +endif +#EXTRA_CFLAGS += -DJOHN_NOCPY +EXTRA_CFLAGS += -DTHOMAS_TURBO +#flags to enable or disble 80211D feature +EXTRA_CFLAGS += -DENABLE_DOT11D +rtllib-rsl-objs := rtllib_rx.o \ + rtllib_softmac.o \ + rtllib_tx.o \ + rtllib_wx.o \ + rtllib_module.o \ + rtllib_softmac_wx.o\ + rtl819x_HTProc.o\ + rtl819x_TSProc.o\ + rtl819x_BAProc.o\ + dot11d.o + +rtllib_crypt-rsl-objs := rtllib_crypt.o +rtllib_crypt_tkip-rsl-objs := rtllib_crypt_tkip.o +rtllib_crypt_ccmp-rsl-objs := rtllib_crypt_ccmp.o +rtllib_crypt_wep-rsl-objs := rtllib_crypt_wep.o + +obj-m +=rtllib-rsl.o +obj-m +=rtllib_crypt-rsl.o +obj-m +=rtllib_crypt_wep-rsl.o +obj-m +=rtllib_crypt_tkip-rsl.o +obj-m +=rtllib_crypt_ccmp-rsl.o + +KSRC := /lib/modules/$(KVER)/build +INSTALL_PREFIX := + +all: modules + +modules: + $(MAKE) -C $(KSRC) M=$(PWD) CC=$(CC) modules + +install: modules + rm -fr $(MODDESTDIR) + mkdir -p $(MODDESTDIR) + @install -p -m 644 rtllib_crypt-rsl.ko $(MODDESTDIR) + @install -p -m 644 rtllib_crypt_wep-rsl.ko $(MODDESTDIR) + @install -p -m 644 rtllib_crypt_tkip-rsl.ko $(MODDESTDIR) + @install -p -m 644 rtllib_crypt_ccmp-rsl.ko $(MODDESTDIR) + @install -p -m 644 rtllib-rsl.ko $(MODDESTDIR) + depmod -a +uninstall: + rm -fr $(MODDESTDIR) + depmod -a + +else +LD := ld +KSRC := /lib/modules/$(KVER)/build +CONFIG_FILE := $(KSRC)/include/linux/autoconf.h + +CFLAGS += -DLINUX -D__KERNEL__ -DMODULE -O2 -pipe -Wall +CFLAGS += -I$(KSRC)/include -I. +#Kernel 2.4.31 +CFLAGS += -DMODVERSIONS -DEXPORT_SYMTAB -include $(KSRC)/include/linux/modversions.h +#Kernel 2.4.20 +#CFLAGS += -D__NO_VERSION__ -DEXPORT_SYMTAB +CFLAGS += -DENABLE_DOT11D +CFLAGS += -DTHOMAS_TURBO + +ifeq ($(NIC_SELECT),RTL8192U) +CFLAGS += -DRTL8192U +#EXTRA_CFLAGS += -DENABLE_AMSDU +EXTRA_CFLAGS += -DUSB_TX_DRIVER_AGGREGATION_ENABLE +EXTRA_CFLAGS += -DUSB_RX_AGGREGATION_SUPPORT +endif +ifeq ($(NIC_SELECT),RTL8192E) +CFLAGS += -DRTL8192E +endif +ifeq ($(NIC_SELECT),RTL8190P) +CFLAGS += -DRTL8190P +endif +ifeq ($(NIC_SELECT),RTL8192SE) +CFLAGS += -DRTL8192SE +CFLAGS += -DRTL8192S_DISABLE_FW_DM=0 +endif +ifeq ($(NIC_SELECT), RTL8191SE_MESH) +AUTHTYPE=SAE +#AUTHTYPE=OPEN +CFLAGS += -DRTL8192SE +CFLAGS += -DRTL8192S_DISABLE_FW_DM=0 +CFLAGS += -D_RTL8192_EXT_PATCH_ +ifeq ($(AUTHTYPE),SAE) +CFLAGS += -DMESH_ABBR_HANDSHK_SUPPORT\ +CFLAGS += -DMESH_ATH_2 +endif +endif + +SMP := $(shell $(CC) $(MODCFLAGS) -E -dM $(CONFIG_FILE) | \ + grep CONFIG_SMP | awk '{print $$3}') +ifneq ($(SMP),1) + SMP := 0 +endif +ifeq ($(SMP),1) + CFLAGS += -D__SMP__ +endif + +#CFLAGS += -DJOHN_NOCPY + +OBJS := ${patsubst %.c, %.o, ${wildcard *.c}} +all:${OBJS} rtllib_crypt-rsl.o michael_mic-rsl.o aes-rsl.o rtllib_crypt_wep-rsl.o rtllib_crypt_tkip-rsl.o rtllib_crypt_ccmp-rsl.o crypto-rsl.o rtllib-rsl.o + +rtllib_crypt-rsl.o: rtllib_crypt.o + mv $^ $@ + +michael_mic-rsl.o: michael_mic.o + mv $^ $@ + +aes-rsl.o: aes.o + mv $^ $@ + +rtllib_crypt_wep-rsl.o: rtllib_crypt_wep.o + mv $^ $@ + +rtllib_crypt_tkip-rsl.o: rtllib_crypt_tkip.o + mv $^ $@ + +rtllib_crypt_ccmp-rsl.o: rtllib_crypt_ccmp.o + mv $^ $@ + +crypto-rsl.o: arc4.o api.o autoload.o cipher.o compress.o digest.o scatterwalk.o proc.o + $(LD) -r $^ -o $@ + +rtllib-rsl.o: rtllib_rx.o rtllib_tx.o rtllib_wx.o rtllib_module.o rtllib_softmac_wx.o rtllib_softmac.o rtl819x_HTProc.o rtl819x_TSProc.o rtl819x_BAProc.o dot11d.o + $(LD) -r $^ -o $@ +install: + rm -fr $(MODDESTDIR) + mkdir -p $(MODDESTDIR) + @install -p -m 644 rtllib_crypt-rsl.o $(MODDESTDIR) + @install -p -m 644 crypto-rsl.o $(MODDESTDIR) + @install -p -m 644 michael_mic-rsl.o $(MODDESTDIR) + @install -p -m 644 aes-rsl.o $(MODDESTDIR) + @install -p -m 644 rtllib_crypt_wep-rsl.o $(MODDESTDIR) + @install -p -m 644 rtllib_crypt_tkip-rsl.o $(MODDESTDIR) + @install -p -m 644 rtllib_crypt_ccmp-rsl.o $(MODDESTDIR) + @install -p -m 644 rtllib-rsl.o $(MODDESTDIR) + /sbin/depmod -a ${shell uname -r} + +uninstall: + rm -fr $(MODDESTDIR) + /sbin/depmod -a ${shell uname -r} + +endif + +.PHONY: clean +clean: + rm -fr *.mod.c *.mod *.o .*.cmd *.mod.* *.ko *.o *~ + rm -rf .tmp_versions + rm -rf Module.symvers + rm -fr Module.markers + rm -fr modules.order + rm -fr tags --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/aes.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/aes.c @@ -0,0 +1,468 @@ +/* + * Cryptographic API. + * + * AES Cipher Algorithm. + * + * Based on Brian Gladman's code. + * + * Linux developers: + * Alexander Kjeldaas + * Herbert Valerio Riedel + * Kyle McMartin + * Adam J. Richter (conversion to 2.5 API). + * + * 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. + * + * --------------------------------------------------------------------------- + * Copyright (c) 2002, Dr Brian Gladman , Worcester, UK. + * All rights reserved. + * + * LICENSE TERMS + * + * The free distribution and use of this software in both source and binary + * form is allowed (with or without changes) provided that: + * + * 1. distributions of this source code include the above copyright + * notice, this list of conditions and the following disclaimer; + * + * 2. distributions in binary form include the above copyright + * notice, this list of conditions and the following disclaimer + * in the documentation and/or other associated materials; + * + * 3. the copyright holder's name is not used to endorse products + * built using this software without specific written permission. + * + * ALTERNATIVELY, provided that this notice is retained in full, this product + * may be distributed under the terms of the GNU General Public License (GPL), + * in which case the provisions of the GPL apply INSTEAD OF those given above. + * + * DISCLAIMER + * + * This software is provided 'as is' with no explicit or implied warranties + * in respect of its properties, including, but not limited to, correctness + * and/or fitness for purpose. + * --------------------------------------------------------------------------- + */ + +/* Some changes from the Gladman version: + s/RIJNDAEL(e_key)/E_KEY/g + s/RIJNDAEL(d_key)/D_KEY/g +*/ + +#include +#include +#include +#include +#include "rtl_crypto.h" +#include + +#define AES_MIN_KEY_SIZE 16 +#define AES_MAX_KEY_SIZE 32 + +#define AES_BLOCK_SIZE 16 + +static inline +u32 generic_rotr32 (const u32 x, const unsigned bits) +{ + const unsigned n = bits % 32; + return (x >> n) | (x << (32 - n)); +} + +static inline +u32 generic_rotl32 (const u32 x, const unsigned bits) +{ + const unsigned n = bits % 32; + return (x << n) | (x >> (32 - n)); +} + +#define rotl generic_rotl32 +#define rotr generic_rotr32 + +/* + * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) + */ +inline static u8 +byte(const u32 x, const unsigned n) +{ + return x >> (n << 3); +} + +#define u32_in(x) le32_to_cpu(*(const u32 *)(x)) +#define u32_out(to, from) (*(u32 *)(to) = cpu_to_le32(from)) + +struct aes_ctx { + int key_length; + u32 E[60]; + u32 D[60]; +}; + +#define E_KEY ctx->E +#define D_KEY ctx->D + +static u8 pow_tab[256] __initdata; +static u8 log_tab[256] __initdata; +static u8 sbx_tab[256] __initdata; +static u8 isb_tab[256] __initdata; +static u32 rco_tab[10]; +static u32 ft_tab[4][256]; +static u32 it_tab[4][256]; + +static u32 fl_tab[4][256]; +static u32 il_tab[4][256]; + +static inline u8 __init +f_mult (u8 a, u8 b) +{ + u8 aa = log_tab[a], cc = aa + log_tab[b]; + + return pow_tab[cc + (cc < aa ? 1 : 0)]; +} + +#define ff_mult(a,b) (a && b ? f_mult(a, b) : 0) + +#define f_rn(bo, bi, n, k) \ + bo[n] = ft_tab[0][byte(bi[n],0)] ^ \ + ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rn(bo, bi, n, k) \ + bo[n] = it_tab[0][byte(bi[n],0)] ^ \ + it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +#define ls_box(x) \ + ( fl_tab[0][byte(x, 0)] ^ \ + fl_tab[1][byte(x, 1)] ^ \ + fl_tab[2][byte(x, 2)] ^ \ + fl_tab[3][byte(x, 3)] ) + +#define f_rl(bo, bi, n, k) \ + bo[n] = fl_tab[0][byte(bi[n],0)] ^ \ + fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \ + fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n) + +#define i_rl(bo, bi, n, k) \ + bo[n] = il_tab[0][byte(bi[n],0)] ^ \ + il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \ + il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \ + il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n) + +static void __init +gen_tabs (void) +{ + u32 i, t; + u8 p, q; + + /* log and power tables for GF(2**8) finite field with + 0x011b as modular polynomial - the simplest primitive + root is 0x03, used here to generate the tables */ + + for (i = 0, p = 1; i < 256; ++i) { + pow_tab[i] = (u8) p; + log_tab[p] = (u8) i; + + p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + log_tab[1] = 0; + + for (i = 0, p = 1; i < 10; ++i) { + rco_tab[i] = p; + + p = (p << 1) ^ (p & 0x80 ? 0x01b : 0); + } + + for (i = 0; i < 256; ++i) { + p = (i ? pow_tab[255 - log_tab[i]] : 0); + q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2)); + p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2)); + sbx_tab[i] = p; + isb_tab[p] = (u8) i; + } + + for (i = 0; i < 256; ++i) { + p = sbx_tab[i]; + + t = p; + fl_tab[0][i] = t; + fl_tab[1][i] = rotl (t, 8); + fl_tab[2][i] = rotl (t, 16); + fl_tab[3][i] = rotl (t, 24); + + t = ((u32) ff_mult (2, p)) | + ((u32) p << 8) | + ((u32) p << 16) | ((u32) ff_mult (3, p) << 24); + + ft_tab[0][i] = t; + ft_tab[1][i] = rotl (t, 8); + ft_tab[2][i] = rotl (t, 16); + ft_tab[3][i] = rotl (t, 24); + + p = isb_tab[i]; + + t = p; + il_tab[0][i] = t; + il_tab[1][i] = rotl (t, 8); + il_tab[2][i] = rotl (t, 16); + il_tab[3][i] = rotl (t, 24); + + t = ((u32) ff_mult (14, p)) | + ((u32) ff_mult (9, p) << 8) | + ((u32) ff_mult (13, p) << 16) | + ((u32) ff_mult (11, p) << 24); + + it_tab[0][i] = t; + it_tab[1][i] = rotl (t, 8); + it_tab[2][i] = rotl (t, 16); + it_tab[3][i] = rotl (t, 24); + } +} + +#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b) + +#define imix_col(y,x) \ + u = star_x(x); \ + v = star_x(u); \ + w = star_x(v); \ + t = w ^ (x); \ + (y) = u ^ v ^ w; \ + (y) ^= rotr(u ^ t, 8) ^ \ + rotr(v ^ t, 16) ^ \ + rotr(t,24) + +/* initialise the key schedule from the user supplied key */ + +#define loop4(i) \ +{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[4 * i]; E_KEY[4 * i + 4] = t; \ + t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t; \ + t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t; \ + t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t; \ +} + +#define loop6(i) \ +{ t = rotr(t, 8); t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[6 * i]; E_KEY[6 * i + 6] = t; \ + t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t; \ + t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t; \ + t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t; \ + t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t; \ + t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t; \ +} + +#define loop8(i) \ +{ t = rotr(t, 8); ; t = ls_box(t) ^ rco_tab[i]; \ + t ^= E_KEY[8 * i]; E_KEY[8 * i + 8] = t; \ + t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t; \ + t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t; \ + t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t; \ + t = E_KEY[8 * i + 4] ^ ls_box(t); \ + E_KEY[8 * i + 12] = t; \ + t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t; \ + t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t; \ + t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t; \ +} + +static int +aes_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) +{ + struct aes_ctx *ctx = ctx_arg; + u32 i, t, u, v, w; + + if (key_len != 16 && key_len != 24 && key_len != 32) { + *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + ctx->key_length = key_len; + + E_KEY[0] = u32_in (in_key); + E_KEY[1] = u32_in (in_key + 4); + E_KEY[2] = u32_in (in_key + 8); + E_KEY[3] = u32_in (in_key + 12); + + switch (key_len) { + case 16: + t = E_KEY[3]; + for (i = 0; i < 10; ++i) + loop4 (i); + break; + + case 24: + E_KEY[4] = u32_in (in_key + 16); + t = E_KEY[5] = u32_in (in_key + 20); + for (i = 0; i < 8; ++i) + loop6 (i); + break; + + case 32: + E_KEY[4] = u32_in (in_key + 16); + E_KEY[5] = u32_in (in_key + 20); + E_KEY[6] = u32_in (in_key + 24); + t = E_KEY[7] = u32_in (in_key + 28); + for (i = 0; i < 7; ++i) + loop8 (i); + break; + } + + D_KEY[0] = E_KEY[0]; + D_KEY[1] = E_KEY[1]; + D_KEY[2] = E_KEY[2]; + D_KEY[3] = E_KEY[3]; + + for (i = 4; i < key_len + 24; ++i) { + imix_col (D_KEY[i], E_KEY[i]); + } + + return 0; +} + +/* encrypt a block of text */ + +#define f_nround(bo, bi, k) \ + f_rn(bo, bi, 0, k); \ + f_rn(bo, bi, 1, k); \ + f_rn(bo, bi, 2, k); \ + f_rn(bo, bi, 3, k); \ + k += 4 + +#define f_lround(bo, bi, k) \ + f_rl(bo, bi, 0, k); \ + f_rl(bo, bi, 1, k); \ + f_rl(bo, bi, 2, k); \ + f_rl(bo, bi, 3, k) + +static void aes_encrypt(void *ctx_arg, u8 *out, const u8 *in) +{ + const struct aes_ctx *ctx = ctx_arg; + u32 b0[4], b1[4]; + const u32 *kp = E_KEY + 4; + b0[0] = u32_in (in) ^ E_KEY[0]; + b0[1] = u32_in (in + 4) ^ E_KEY[1]; + b0[2] = u32_in (in + 8) ^ E_KEY[2]; + b0[3] = u32_in (in + 12) ^ E_KEY[3]; + + if (ctx->key_length > 24) { + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + } + + if (ctx->key_length > 16) { + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + } + + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_nround (b0, b1, kp); + f_nround (b1, b0, kp); + f_lround (b0, b1, kp); + + u32_out (out, b0[0]); + u32_out (out + 4, b0[1]); + u32_out (out + 8, b0[2]); + u32_out (out + 12, b0[3]); +} + +/* decrypt a block of text */ + +#define i_nround(bo, bi, k) \ + i_rn(bo, bi, 0, k); \ + i_rn(bo, bi, 1, k); \ + i_rn(bo, bi, 2, k); \ + i_rn(bo, bi, 3, k); \ + k -= 4 + +#define i_lround(bo, bi, k) \ + i_rl(bo, bi, 0, k); \ + i_rl(bo, bi, 1, k); \ + i_rl(bo, bi, 2, k); \ + i_rl(bo, bi, 3, k) + +static void aes_decrypt(void *ctx_arg, u8 *out, const u8 *in) +{ + const struct aes_ctx *ctx = ctx_arg; + u32 b0[4], b1[4]; + const int key_len = ctx->key_length; + const u32 *kp = D_KEY + key_len + 20; + + b0[0] = u32_in (in) ^ E_KEY[key_len + 24]; + b0[1] = u32_in (in + 4) ^ E_KEY[key_len + 25]; + b0[2] = u32_in (in + 8) ^ E_KEY[key_len + 26]; + b0[3] = u32_in (in + 12) ^ E_KEY[key_len + 27]; + + if (key_len > 24) { + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + } + + if (key_len > 16) { + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + } + + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_nround (b0, b1, kp); + i_nround (b1, b0, kp); + i_lround (b0, b1, kp); + + u32_out (out, b0[0]); + u32_out (out + 4, b0[1]); + u32_out (out + 8, b0[2]); + u32_out (out + 12, b0[3]); +} + + +static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct aes_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_setkey = aes_set_key, + .cia_encrypt = aes_encrypt, + .cia_decrypt = aes_decrypt + } + } +}; + +int __init aes_init(void) +{ + gen_tabs(); + return crypto_register_alg(&aes_alg); +} + +void __exit aes_fini(void) +{ + crypto_unregister_alg(&aes_alg); +} + +#ifndef BUILT_IN_CRYPTO +module_init(aes_init); +module_exit(aes_fini); + +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm"); +MODULE_LICENSE("Dual BSD/GPL"); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/api.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/api.c @@ -0,0 +1,261 @@ +/* + * Scatterlist Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * + * Portions derived from Cryptoapi, by Alexander Kjeldaas + * and Nettle, by Niels Mé°ˆler. + * + * 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. + * + */ + + +#include +#include +#include "rtl_crypto.h" +#include +#include +#include +#include "internal.h" + +LIST_HEAD(crypto_alg_list); +DECLARE_RWSEM(crypto_alg_sem); + +static inline int crypto_alg_get(struct crypto_alg *alg) +{ +#ifdef BUILT_IN_CRYPTO + return 1; +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + return try_module_get(alg->cra_module); +#else + return try_inc_mod_count(alg->cra_module); +#endif +#endif +} + +static inline void crypto_alg_put(struct crypto_alg *alg) +{ +#ifndef BUILT_IN_CRYPTO + if (alg->cra_module) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + module_put(alg->cra_module); +#else + __MOD_DEC_USE_COUNT(alg->cra_module); +#endif +#endif +} + +struct crypto_alg *crypto_alg_lookup(const char *name) +{ + struct crypto_alg *q, *alg = NULL; + + if (!name) + return NULL; + + down_read(&crypto_alg_sem); + + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (!(strcmp(q->cra_name, name))) { + if (crypto_alg_get(q)) + alg = q; + break; + } + } + + up_read(&crypto_alg_sem); + return alg; +} + +static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) +{ + tfm->crt_flags = 0; + + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + return crypto_init_cipher_flags(tfm, flags); + + case CRYPTO_ALG_TYPE_DIGEST: + return crypto_init_digest_flags(tfm, flags); + + case CRYPTO_ALG_TYPE_COMPRESS: + return crypto_init_compress_flags(tfm, flags); + + default: + break; + } + + BUG(); + return -EINVAL; +} + +static int crypto_init_ops(struct crypto_tfm *tfm) +{ + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + return crypto_init_cipher_ops(tfm); + + case CRYPTO_ALG_TYPE_DIGEST: + return crypto_init_digest_ops(tfm); + + case CRYPTO_ALG_TYPE_COMPRESS: + return crypto_init_compress_ops(tfm); + + default: + break; + } + + BUG(); + return -EINVAL; +} + +static void crypto_exit_ops(struct crypto_tfm *tfm) +{ + switch (crypto_tfm_alg_type(tfm)) { + case CRYPTO_ALG_TYPE_CIPHER: + crypto_exit_cipher_ops(tfm); + break; + + case CRYPTO_ALG_TYPE_DIGEST: + crypto_exit_digest_ops(tfm); + break; + + case CRYPTO_ALG_TYPE_COMPRESS: + crypto_exit_compress_ops(tfm); + break; + + default: + BUG(); + + } +} + +struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) +{ + struct crypto_tfm *tfm = NULL; + struct crypto_alg *alg; + + alg = crypto_alg_mod_lookup(name); + if (alg == NULL) + goto out; + + tfm = kmalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL); + if (tfm == NULL) + goto out_put; + + memset(tfm, 0, sizeof(*tfm) + alg->cra_ctxsize); + + tfm->__crt_alg = alg; + + if (crypto_init_flags(tfm, flags)) + goto out_free_tfm; + + if (crypto_init_ops(tfm)) { + crypto_exit_ops(tfm); + goto out_free_tfm; + } + + goto out; + +out_free_tfm: + kfree(tfm); + tfm = NULL; +out_put: + crypto_alg_put(alg); +out: + return tfm; +} + +void crypto_free_tfm(struct crypto_tfm *tfm) +{ + struct crypto_alg *alg = tfm->__crt_alg; + int size = sizeof(*tfm) + alg->cra_ctxsize; + + crypto_exit_ops(tfm); + crypto_alg_put(alg); + memset(tfm, 0, size); + kfree(tfm); +} + +int crypto_register_alg(struct crypto_alg *alg) +{ + int ret = 0; + struct crypto_alg *q; + + down_write(&crypto_alg_sem); + + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (!(strcmp(q->cra_name, alg->cra_name))) { + ret = -EEXIST; + goto out; + } + } + + list_add_tail(&alg->cra_list, &crypto_alg_list); +out: + up_write(&crypto_alg_sem); + return ret; +} + +int crypto_unregister_alg(struct crypto_alg *alg) +{ + int ret = -ENOENT; + struct crypto_alg *q; + + BUG_ON(!alg->cra_module); + + down_write(&crypto_alg_sem); + list_for_each_entry(q, &crypto_alg_list, cra_list) { + if (alg == q) { + list_del(&alg->cra_list); + ret = 0; + goto out; + } + } +out: + up_write(&crypto_alg_sem); + return ret; +} + +int crypto_alg_available(const char *name, u32 flags) +{ + int ret = 0; + struct crypto_alg *alg = crypto_alg_mod_lookup(name); + + if (alg) { + crypto_alg_put(alg); + ret = 1; + } + + return ret; +} + +#ifndef BUILT_IN_CRYPTO +static int __init init_crypto(void) +{ + printk(KERN_INFO "Initializing Cryptographic API\n"); + crypto_init_proc(); + return 0; +} + +__initcall(init_crypto); + + +/* +EXPORT_SYMBOL_GPL(crypto_register_alg); +EXPORT_SYMBOL_GPL(crypto_unregister_alg); +EXPORT_SYMBOL_GPL(crypto_alloc_tfm); +EXPORT_SYMBOL_GPL(crypto_free_tfm); +EXPORT_SYMBOL_GPL(crypto_alg_available); +*/ +EXPORT_SYMBOL_RSL(crypto_register_alg); +EXPORT_SYMBOL_RSL(crypto_unregister_alg); +EXPORT_SYMBOL_RSL(crypto_alloc_tfm); +EXPORT_SYMBOL_RSL(crypto_free_tfm); +EXPORT_SYMBOL_RSL(crypto_alg_available); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/arc4.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/arc4.c @@ -0,0 +1,105 @@ +/* + * Cryptographic API + * + * ARC4 Cipher Algorithm + * + * Jon Oberheide + * + * 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. + * + */ +#include +#include +#include "rtl_crypto.h" + +#define ARC4_MIN_KEY_SIZE 1 +#define ARC4_MAX_KEY_SIZE 256 +#define ARC4_BLOCK_SIZE 1 + +struct arc4_ctx { + u8 S[256]; + u8 x, y; +}; + +static int arc4_set_key(void *ctx_arg, const u8 *in_key, unsigned int key_len, u32 *flags) +{ + struct arc4_ctx *ctx = ctx_arg; + int i, j = 0, k = 0; + + ctx->x = 1; + ctx->y = 0; + + for(i = 0; i < 256; i++) + ctx->S[i] = i; + + for(i = 0; i < 256; i++) + { + u8 a = ctx->S[i]; + j = (j + in_key[k] + a) & 0xff; + ctx->S[i] = ctx->S[j]; + ctx->S[j] = a; + if((unsigned int)++k >= key_len) + k = 0; + } + + return 0; +} + +static void arc4_crypt(void *ctx_arg, u8 *out, const u8 *in) +{ + struct arc4_ctx *ctx = ctx_arg; + + u8 *const S = ctx->S; + u8 x = ctx->x; + u8 y = ctx->y; + u8 a, b; + + a = S[x]; + y = (y + a) & 0xff; + b = S[y]; + S[x] = b; + S[y] = a; + x = (x + 1) & 0xff; + *out++ = *in ^ S[(a + b) & 0xff]; + + ctx->x = x; + ctx->y = y; +} + +static struct crypto_alg arc4_alg = { + .cra_name = "arc4", + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = ARC4_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct arc4_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(arc4_alg.cra_list), + .cra_u = { .cipher = { + .cia_min_keysize = ARC4_MIN_KEY_SIZE, + .cia_max_keysize = ARC4_MAX_KEY_SIZE, + .cia_setkey = arc4_set_key, + .cia_encrypt = arc4_crypt, + .cia_decrypt = arc4_crypt } } +}; + +int __init arc4_init(void) +{ + return crypto_register_alg(&arc4_alg); +} + + +void __exit arc4_exit(void) +{ + crypto_unregister_alg(&arc4_alg); +} + +#ifndef BUILT_IN_CRYPTO +module_init(arc4_init); +module_exit(arc4_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ARC4 Cipher Algorithm"); +MODULE_AUTHOR("Jon Oberheide "); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/autoload.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/autoload.c @@ -0,0 +1,41 @@ +/* + * Cryptographic API. + * + * Algorithm autoloader. + * + * Copyright (c) 2002 James Morris + * + * 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. + * + */ +#include "kmap_types.h" + +#include +#include "rtl_crypto.h" +#include +#include +#include "internal.h" + +#ifdef CONFIG_KMOD +/* + * A far more intelligent version of this is planned. For now, just + * try an exact match on the name of the algorithm. + */ +void crypto_alg_autoload(const char *name) +{ + request_module(name); +} + +struct crypto_alg *crypto_alg_mod_lookup(const char *name) +{ + struct crypto_alg *alg = crypto_alg_lookup(name); + if (alg == NULL) { + crypto_alg_autoload(name); + alg = crypto_alg_lookup(name); + } + return alg; +} +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/cipher.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/cipher.c @@ -0,0 +1,298 @@ +/* + * Cryptographic API. + * + * Cipher operations. + * + * Copyright (c) 2002 James Morris + * + * 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. + * + */ +#include +#include "rtl_crypto.h" +#include +#include +#include +#include +#include "internal.h" +#include "scatterwalk.h" + +typedef void (cryptfn_t)(void *, u8 *, const u8 *); +typedef void (procfn_t)(struct crypto_tfm *, u8 *, + u8*, cryptfn_t, int enc, void *, int); + +static inline void xor_64(u8 *a, const u8 *b) +{ + ((u32 *)a)[0] ^= ((u32 *)b)[0]; + ((u32 *)a)[1] ^= ((u32 *)b)[1]; +} + +static inline void xor_128(u8 *a, const u8 *b) +{ + ((u32 *)a)[0] ^= ((u32 *)b)[0]; + ((u32 *)a)[1] ^= ((u32 *)b)[1]; + ((u32 *)a)[2] ^= ((u32 *)b)[2]; + ((u32 *)a)[3] ^= ((u32 *)b)[3]; +} + + +/* + * Generic encrypt/decrypt wrapper for ciphers, handles operations across + * multiple page boundaries by using temporary blocks. In user context, + * the kernel is given a chance to schedule us once per block. + */ +static int crypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, cryptfn_t crfn, + procfn_t prfn, int enc, void *info) +{ + struct scatter_walk walk_in, walk_out; + const unsigned int bsize = crypto_tfm_alg_blocksize(tfm); + u8 tmp_src[bsize]; + u8 tmp_dst[bsize]; + + if (!nbytes) + return 0; + + if (nbytes % bsize) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_BLOCK_LEN; + return -EINVAL; + } + + scatterwalk_start(&walk_in, src); + scatterwalk_start(&walk_out, dst); + + for(;;) { + u8 *src_p, *dst_p; + int in_place; + + scatterwalk_map(&walk_in, 0); + scatterwalk_map(&walk_out, 1); + src_p = scatterwalk_whichbuf(&walk_in, bsize, tmp_src); + dst_p = scatterwalk_whichbuf(&walk_out, bsize, tmp_dst); + in_place = scatterwalk_samebuf(&walk_in, &walk_out, + src_p, dst_p); + + nbytes -= bsize; + + scatterwalk_copychunks(src_p, &walk_in, bsize, 0); + + prfn(tfm, dst_p, src_p, crfn, enc, info, in_place); + + scatterwalk_done(&walk_in, 0, nbytes); + + scatterwalk_copychunks(dst_p, &walk_out, bsize, 1); + scatterwalk_done(&walk_out, 1, nbytes); + + if (!nbytes) + return 0; + + crypto_yield(tfm); + } +} + +static void cbc_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, + cryptfn_t fn, int enc, void *info, int in_place) +{ + u8 *iv = info; + + /* Null encryption */ + if (!iv) + return; + + if (enc) { + tfm->crt_u.cipher.cit_xor_block(iv, src); + fn(crypto_tfm_ctx(tfm), dst, iv); + memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm)); + } else { + u8 stack[in_place ? crypto_tfm_alg_blocksize(tfm) : 0]; + u8 *buf = in_place ? stack : dst; + + fn(crypto_tfm_ctx(tfm), buf, src); + tfm->crt_u.cipher.cit_xor_block(buf, iv); + memcpy(iv, src, crypto_tfm_alg_blocksize(tfm)); + if (buf != dst) + memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm)); + } +} + +static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, + cryptfn_t fn, int enc, void *info, int in_place) +{ + fn(crypto_tfm_ctx(tfm), dst, src); +} + +static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) +{ + struct cipher_alg *cia = &tfm->__crt_alg->cra_cipher; + + if (keylen < cia->cia_min_keysize || keylen > cia->cia_max_keysize) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } else + return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen, + &tfm->crt_flags); +} + +static int ecb_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + ecb_process, 1, NULL); +} + +static int ecb_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + ecb_process, 1, NULL); +} + +static int cbc_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, tfm->crt_cipher.cit_iv); +} + +static int cbc_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, iv); +} + +static int cbc_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, tfm->crt_cipher.cit_iv); +} + +static int cbc_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, iv); +} + +static int nocrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + return -ENOSYS; +} + +static int nocrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return -ENOSYS; +} + +int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) +{ + u32 mode = flags & CRYPTO_TFM_MODE_MASK; + + tfm->crt_cipher.cit_mode = mode ? mode : CRYPTO_TFM_MODE_ECB; + if (flags & CRYPTO_TFM_REQ_WEAK_KEY) + tfm->crt_flags = CRYPTO_TFM_REQ_WEAK_KEY; + + return 0; +} + +int crypto_init_cipher_ops(struct crypto_tfm *tfm) +{ + int ret = 0; + struct cipher_tfm *ops = &tfm->crt_cipher; + + ops->cit_setkey = setkey; + + switch (tfm->crt_cipher.cit_mode) { + case CRYPTO_TFM_MODE_ECB: + ops->cit_encrypt = ecb_encrypt; + ops->cit_decrypt = ecb_decrypt; + break; + + case CRYPTO_TFM_MODE_CBC: + ops->cit_encrypt = cbc_encrypt; + ops->cit_decrypt = cbc_decrypt; + ops->cit_encrypt_iv = cbc_encrypt_iv; + ops->cit_decrypt_iv = cbc_decrypt_iv; + break; + + case CRYPTO_TFM_MODE_CFB: + ops->cit_encrypt = nocrypt; + ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; + break; + + case CRYPTO_TFM_MODE_CTR: + ops->cit_encrypt = nocrypt; + ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; + break; + + default: + BUG(); + } + + if (ops->cit_mode == CRYPTO_TFM_MODE_CBC) { + + switch (crypto_tfm_alg_blocksize(tfm)) { + case 8: + ops->cit_xor_block = xor_64; + break; + + case 16: + ops->cit_xor_block = xor_128; + break; + + default: + printk(KERN_WARNING "%s: block size %u not supported\n", + crypto_tfm_alg_name(tfm), + crypto_tfm_alg_blocksize(tfm)); + ret = -EINVAL; + goto out; + } + + ops->cit_ivsize = crypto_tfm_alg_blocksize(tfm); + ops->cit_iv = kmalloc(ops->cit_ivsize, GFP_KERNEL); + if (ops->cit_iv == NULL) + ret = -ENOMEM; + } + +out: + return ret; +} + +void crypto_exit_cipher_ops(struct crypto_tfm *tfm) +{ + if (tfm->crt_cipher.cit_iv) + kfree(tfm->crt_cipher.cit_iv); +} --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/compress.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/compress.c @@ -0,0 +1,63 @@ +/* + * Cryptographic API. + * + * Compression operations. + * + * Copyright (c) 2002 James Morris + * + * 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. + * + */ +#include +#include "rtl_crypto.h" +#include +#include +#include +#include "internal.h" + +static int crypto_compress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + return tfm->__crt_alg->cra_compress.coa_compress(crypto_tfm_ctx(tfm), + src, slen, dst, + dlen); +} + +static int crypto_decompress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + return tfm->__crt_alg->cra_compress.coa_decompress(crypto_tfm_ctx(tfm), + src, slen, dst, + dlen); +} + +int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags) +{ + return flags ? -EINVAL : 0; +} + +int crypto_init_compress_ops(struct crypto_tfm *tfm) +{ + int ret = 0; + struct compress_tfm *ops = &tfm->crt_compress; + + ret = tfm->__crt_alg->cra_compress.coa_init(crypto_tfm_ctx(tfm)); + if (ret) + goto out; + + ops->cot_compress = crypto_compress; + ops->cot_decompress = crypto_decompress; + +out: + return ret; +} + +void crypto_exit_compress_ops(struct crypto_tfm *tfm) +{ + tfm->__crt_alg->cra_compress.coa_exit(crypto_tfm_ctx(tfm)); +} --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/crypto_compat.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/crypto_compat.h @@ -0,0 +1,88 @@ +/* + * Header file to maintain compatibility among different kernel versions. + * + * Copyright (c) 2004-2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See README and COPYING for + * more details. + */ + +#include + +static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); +} + + +static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); +} + +#if 0 +/* + * crypto_free_tfm - Free crypto transform + * @tfm: Transform to free + * + * crypto_free_tfm() frees up the transform and any associated resources, + * then drops the refcount on the associated algorithm. + */ +void crypto_free_tfm(struct crypto_tfm *tfm) +{ + struct crypto_alg *alg; + int size; + + if (unlikely(!tfm)) + return; + + alg = tfm->__crt_alg; + size = sizeof(*tfm) + alg->cra_ctxsize; + + if (alg->cra_exit) + alg->cra_exit(tfm); + crypto_exit_ops(tfm); + crypto_mod_put(alg); + memset(tfm, 0, size); + kfree(tfm); +} + +#endif +#if 1 + struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) +{ + struct crypto_tfm *tfm = NULL; + int err; + printk("call crypto_alloc_tfm!!!\n"); + do { + struct crypto_alg *alg; + + alg = crypto_alg_mod_lookup(name, 0, CRYPTO_ALG_ASYNC); + err = PTR_ERR(alg); + if (IS_ERR(alg)) + continue; + + tfm = __crypto_alloc_tfm(alg, flags); + err = 0; + if (IS_ERR(tfm)) { + crypto_mod_put(alg); + err = PTR_ERR(tfm); + tfm = NULL; + } + } while (err == -EAGAIN && !signal_pending(current)); + + return tfm; +} +#endif + + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/digest.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/digest.c @@ -0,0 +1,120 @@ +/* + * Cryptographic API. + * + * Digest operations. + * + * Copyright (c) 2002 James Morris + * + * 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. + * + */ +#include +#include "rtl_crypto.h" +#include +#include +#include +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) +#include +#else +#include +#endif +#include "internal.h" + +static void init(struct crypto_tfm *tfm) +{ + tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm)); +} + +static void update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg) +{ + unsigned int i; + + for (i = 0; i < nsg; i++) { + + #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + struct page *pg = sg[i].page; + #else + struct page *pg = sg_page(&sg[i]); + #endif + unsigned int offset = sg[i].offset; + unsigned int l = sg[i].length; + + do { + unsigned int bytes_from_page = min(l, ((unsigned int) + (PAGE_SIZE)) - + offset); + char *p = crypto_kmap(pg, 0) + offset; + + tfm->__crt_alg->cra_digest.dia_update + (crypto_tfm_ctx(tfm), p, + bytes_from_page); + crypto_kunmap(p, 0); + crypto_yield(tfm); + offset = 0; + pg++; + l -= bytes_from_page; + } while (l > 0); + } +} + +static void final(struct crypto_tfm *tfm, u8 *out) +{ + tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out); +} + +static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) +{ + u32 flags; + if (tfm->__crt_alg->cra_digest.dia_setkey == NULL) + return -ENOSYS; + return tfm->__crt_alg->cra_digest.dia_setkey(crypto_tfm_ctx(tfm), + key, keylen, &flags); +} + +static void digest(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg, u8 *out) +{ + unsigned int i; + + tfm->crt_digest.dit_init(tfm); + + for (i = 0; i < nsg; i++) { + #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; + #else + char *p = crypto_kmap(sg_page(&sg[i]), 0) + sg[i].offset; + #endif + tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), + p, sg[i].length); + crypto_kunmap(p, 0); + crypto_yield(tfm); + } + crypto_digest_final(tfm, out); +} + +int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags) +{ + return flags ? -EINVAL : 0; +} + +int crypto_init_digest_ops(struct crypto_tfm *tfm) +{ + struct digest_tfm *ops = &tfm->crt_digest; + + ops->dit_init = init; + ops->dit_update = update; + ops->dit_final = final; + ops->dit_digest = digest; + ops->dit_setkey = setkey; + + return crypto_alloc_hmac_block(tfm); +} + +void crypto_exit_digest_ops(struct crypto_tfm *tfm) +{ + crypto_free_hmac_block(tfm); +} --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/dot11d.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/dot11d.c @@ -0,0 +1,261 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifdef ENABLE_DOT11D +#include "dot11d.h" + +typedef struct _CHANNEL_LIST +{ + u8 Channel[32]; + u8 Len; +}CHANNEL_LIST, *PCHANNEL_LIST; + +static CHANNEL_LIST ChannelPlan[] = { + {{1,2,3,4,5,6,7,8,9,10,11,36,40,44,48,52,56,60,64,149,153,157,161,165},24}, + {{1,2,3,4,5,6,7,8,9,10,11},11}, + {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21}, + {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, + {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, + {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, + {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, + {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, + {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, + {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,36,40,44,48,52,56,60,64},22}, + {{1,2,3,4,5,6,7,8,9,10,11,12,13,14},14}, + {{1,2,3,4,5,6,7,8,9,10,11,12,13},13}, + {{1,2,3,4,5,6,7,8,9,10,11,12,13,36,40,44,48,52,56,60,64},21} +}; + +void Dot11d_Init(struct rtllib_device *ieee) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); +#ifdef CONFIG_CRDA + ieee->bGlobalDomain = true; + pDot11dInfo->bEnabled = true; +#else + pDot11dInfo->bEnabled = false; +#endif + + pDot11dInfo->State = DOT11D_STATE_NONE; + pDot11dInfo->CountryIeLen = 0; + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + RESET_CIE_WATCHDOG(ieee); + +} + +void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device* ieee) +{ + int i, max_chan = 14, min_chan = 1; + + ieee->bGlobalDomain = false; + + if (ChannelPlan[channel_plan].Len != 0) { + memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); + for (i = 0; i < ChannelPlan[channel_plan].Len; i++) { + if (ChannelPlan[channel_plan].Channel[i] < min_chan || + ChannelPlan[channel_plan].Channel[i] > max_chan) + break; + GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan[channel_plan].Channel[i]] = 1; + } + } + + switch (channel_plan) { + case COUNTRY_CODE_GLOBAL_DOMAIN: + ieee->bGlobalDomain = true; + for (i = 12; i <= 14; i++) { + GET_DOT11D_INFO(ieee)->channel_map[i] = 2; + } + ieee->IbssStartChnl= 10; + ieee->ibss_maxjoin_chal = 11; + break; + + case COUNTRY_CODE_WORLD_WIDE_13: + for (i = 12; i <= 13; i++) { + GET_DOT11D_INFO(ieee)->channel_map[i] = 2; + } + ieee->IbssStartChnl = 10; + ieee->ibss_maxjoin_chal = 11; + break; + + default: + ieee->IbssStartChnl = 1; + ieee->ibss_maxjoin_chal = 14; + break; + } +} + + +void Dot11d_Reset(struct rtllib_device *ieee) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); +#if 0 + if(!pDot11dInfo->bEnabled) + return; +#endif + +#ifndef CONFIG_CRDA + u32 i; + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + for (i=1; i<=11; i++) { + (pDot11dInfo->channel_map)[i] = 1; + } + for (i=12; i<=14; i++) { + (pDot11dInfo->channel_map)[i] = 2; + } +#endif + pDot11dInfo->State = DOT11D_STATE_NONE; + pDot11dInfo->CountryIeLen = 0; + RESET_CIE_WATCHDOG(ieee); + +} + +void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr, + u16 CoutryIeLen, u8* pCoutryIe) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); +#ifdef CONFIG_CRDA + +#else + u8 i, j, NumTriples, MaxChnlNum; + PCHNL_TXPOWER_TRIPLE pTriple; + + memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); + memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); + MaxChnlNum = 0; + NumTriples = (CoutryIeLen - 3) / 3; + pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3); + for(i = 0; i < NumTriples; i++) + { + if(MaxChnlNum >= pTriple->FirstChnl) + { + printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); + return; + } + if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls)) + { + printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); + return; + } + + for(j = 0 ; j < pTriple->NumChnls; j++) + { + pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; + pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm; + MaxChnlNum = pTriple->FirstChnl + j; + } + + pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3); + } +#if 0 + printk("Channel List:"); + for(i=1; i<= MAX_CHANNEL_NUMBER; i++) + if(pDot11dInfo->channel_map[i] > 0) + printk(" %d", i); + printk("\n"); +#endif +#endif + + UPDATE_CIE_SRC(dev, pTaddr); + + pDot11dInfo->CountryIeLen = CoutryIeLen; + memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen); + pDot11dInfo->State = DOT11D_STATE_LEARNED; + +#ifdef CONFIG_CRDA + queue_delayed_work_rsl(dev->wq, &dev->softmac_hint11d_wq, 0); +#endif +} + +u8 DOT11D_GetMaxTxPwrInDbm( struct rtllib_device *dev, u8 Channel) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + u8 MaxTxPwrInDbm = 255; + + if(MAX_CHANNEL_NUMBER < Channel) + { + printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); + return MaxTxPwrInDbm; + } + if(pDot11dInfo->channel_map[Channel]) + { + MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel]; + } + + return MaxTxPwrInDbm; +} + +void DOT11D_ScanComplete( struct rtllib_device * dev) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + + switch(pDot11dInfo->State) + { + case DOT11D_STATE_LEARNED: + pDot11dInfo->State = DOT11D_STATE_DONE; + break; + + case DOT11D_STATE_DONE: + { + Dot11d_Reset(dev); + } + break; + case DOT11D_STATE_NONE: + break; + } +} + +int ToLegalChannel( struct rtllib_device * dev, u8 channel) +{ + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); + u8 default_chn = 0; + u32 i = 0; + + for (i=1; i<= MAX_CHANNEL_NUMBER; i++) + { + if(pDot11dInfo->channel_map[i] > 0) + { + default_chn = i; + break; + } + } + + if(MAX_CHANNEL_NUMBER < channel) + { + printk("%s(): Invalid Channel\n", __FUNCTION__); + return default_chn; + } + + if(pDot11dInfo->channel_map[channel] > 0) + return channel; + + return default_chn; +} + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(Dot11d_Init); +EXPORT_SYMBOL_RSL(Dot11d_Channelmap); +EXPORT_SYMBOL_RSL(Dot11d_Reset); +EXPORT_SYMBOL_RSL(Dot11d_UpdateCountryIe); +EXPORT_SYMBOL_RSL(DOT11D_GetMaxTxPwrInDbm); +EXPORT_SYMBOL_RSL(DOT11D_ScanComplete); +EXPORT_SYMBOL_RSL(ToLegalChannel); +#endif + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/dot11d.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/dot11d.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef __INC_DOT11D_H +#define __INC_DOT11D_H + +#ifdef ENABLE_DOT11D +#include "rtllib.h" + + + +typedef struct _CHNL_TXPOWER_TRIPLE { + u8 FirstChnl; + u8 NumChnls; + u8 MaxTxPowerInDbm; +}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; + +typedef enum _DOT11D_STATE { + DOT11D_STATE_NONE = 0, + DOT11D_STATE_LEARNED, + DOT11D_STATE_DONE, +}DOT11D_STATE; + +typedef struct _RT_DOT11D_INFO { + + bool bEnabled; + + u16 CountryIeLen; + u8 CountryIeBuf[MAX_IE_LEN]; + u8 CountryIeSrcAddr[6]; + u8 CountryIeWatchdog; + + u8 channel_map[MAX_CHANNEL_NUMBER+1]; + u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; + + DOT11D_STATE State; +}RT_DOT11D_INFO, *PRT_DOT11D_INFO; +#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) +#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5]) +#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo)) + +#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled +#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0) + +#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) +#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) + +#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \ + (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \ + false : \ + (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length))) + +#define CIE_WATCHDOG_TH 1 +#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog +#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 +#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev) + +#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) + +void Dot11d_Init( struct rtllib_device *dev); +void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device* ieee); +void Dot11d_Reset(struct rtllib_device *dev); +void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr, u16 CoutryIeLen, u8 *pCoutryIe); +u8 DOT11D_GetMaxTxPwrInDbm(struct rtllib_device *dev, u8 Channel); +void DOT11D_ScanComplete(struct rtllib_device *dev); +int ToLegalChannel(struct rtllib_device *dev, u8 channel); +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/internal.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/internal.h @@ -0,0 +1,130 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2002 James Morris + * + * 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. + * + */ +#ifndef _CRYPTO_INTERNAL_H +#define _CRYPTO_INTERNAL_H + + +#include +#include "rtl_crypto.h" +#include +#include +#include + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)) +#include +#else +#include +#include +#endif +#include + +#ifdef BUILT_IN_CRYPTO +#ifdef CONFIG_CRYPTO_HMAC +#undef CONFIG_CRYPTO_HMAC +#endif + +#ifdef CONFIG_KMOD +#undef CONFIG_KMOD +#endif +#endif /* BUILT_IN_CRYPTO */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,20)) +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + prefetch(pos->member.next); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member), \ + prefetch(pos->member.next)) + +static inline void cond_resched(void) +{ + if (need_resched()) { + set_current_state(TASK_RUNNING); + schedule(); + } +} +#endif + +extern enum km_type crypto_km_types[]; + +static inline enum km_type crypto_kmap_type(int out) +{ + return crypto_km_types[(in_softirq() ? 2 : 0) + out]; +} + +static inline void *crypto_kmap(struct page *page, int out) +{ + return kmap_atomic(page, crypto_kmap_type(out)); +} + +static inline void crypto_kunmap(void *vaddr, int out) +{ + kunmap_atomic(vaddr, crypto_kmap_type(out)); +} + +static inline void crypto_yield(struct crypto_tfm *tfm) +{ + if (!in_softirq()) + cond_resched(); +} + +static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) +{ + return (void *)&tfm[1]; +} + +struct crypto_alg *crypto_alg_lookup(const char *name); + +#ifdef CONFIG_KMOD +void crypto_alg_autoload(const char *name); +struct crypto_alg *crypto_alg_mod_lookup(const char *name); +#else +static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name) +{ + return crypto_alg_lookup(name); +} +#endif + +#ifdef CONFIG_CRYPTO_HMAC +int crypto_alloc_hmac_block(struct crypto_tfm *tfm); +void crypto_free_hmac_block(struct crypto_tfm *tfm); +#else +static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm) +{ + return 0; +} + +static inline void crypto_free_hmac_block(struct crypto_tfm *tfm) +{ } +#endif + +#ifdef CONFIG_PROC_FS +void __init crypto_init_proc(void); +#else +static inline void crypto_init_proc(void) +{ } +#endif + +int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags); +int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags); +int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags); + +int crypto_init_digest_ops(struct crypto_tfm *tfm); +int crypto_init_cipher_ops(struct crypto_tfm *tfm); +int crypto_init_compress_ops(struct crypto_tfm *tfm); + +void crypto_exit_digest_ops(struct crypto_tfm *tfm); +void crypto_exit_cipher_ops(struct crypto_tfm *tfm); +void crypto_exit_compress_ops(struct crypto_tfm *tfm); + +#endif /* _CRYPTO_INTERNAL_H */ + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/kmap_types.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/kmap_types.h @@ -0,0 +1,20 @@ +#ifndef __KMAP_TYPES_H + +#define __KMAP_TYPES_H + + +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BH_IRQ, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_TYPE_NR +}; + +#define _ASM_KMAP_TYPES_H + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/license +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/license @@ -0,0 +1,339 @@ + +"This software program is licensed subject to the GNU General Public License +(GPL). Version 2, June 1991, available at + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include "rtl_crypto.h" + + +struct michael_mic_ctx { + u8 pending[4]; + size_t pending_len; + + u32 l, r; +}; + + +static inline u32 rotl(u32 val, int bits) +{ + return (val << bits) | (val >> (32 - bits)); +} + + +static inline u32 rotr(u32 val, int bits) +{ + return (val >> bits) | (val << (32 - bits)); +} + + +static inline u32 xswap(u32 val) +{ + return ((val & 0x00ff00ff) << 8) | ((val & 0xff00ff00) >> 8); +} + + +#define michael_block(l, r) \ +do { \ + r ^= rotl(l, 17); \ + l += r; \ + r ^= xswap(l); \ + l += r; \ + r ^= rotl(l, 3); \ + l += r; \ + r ^= rotr(l, 2); \ + l += r; \ +} while (0) + + +static inline u32 get_le32(const u8 *p) +{ + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +} + + +static inline void put_le32(u8 *p, u32 v) +{ + p[0] = v; + p[1] = v >> 8; + p[2] = v >> 16; + p[3] = v >> 24; +} + + +static void michael_init(void *ctx) +{ + struct michael_mic_ctx *mctx = ctx; + mctx->pending_len = 0; +} + + +static void michael_update(void *ctx, const u8 *data, unsigned int len) +{ + struct michael_mic_ctx *mctx = ctx; + + if (mctx->pending_len) { + int flen = 4 - mctx->pending_len; + if (flen > len) + flen = len; + memcpy(&mctx->pending[mctx->pending_len], data, flen); + mctx->pending_len += flen; + data += flen; + len -= flen; + + if (mctx->pending_len < 4) + return; + + mctx->l ^= get_le32(mctx->pending); + michael_block(mctx->l, mctx->r); + mctx->pending_len = 0; + } + + while (len >= 4) { + mctx->l ^= get_le32(data); + michael_block(mctx->l, mctx->r); + data += 4; + len -= 4; + } + + if (len > 0) { + mctx->pending_len = len; + memcpy(mctx->pending, data, len); + } +} + + +static void michael_final(void *ctx, u8 *out) +{ + struct michael_mic_ctx *mctx = ctx; + u8 *data = mctx->pending; + + /* Last block and padding (0x5a, 4..7 x 0) */ + switch (mctx->pending_len) { + case 0: + mctx->l ^= 0x5a; + break; + case 1: + mctx->l ^= data[0] | 0x5a00; + break; + case 2: + mctx->l ^= data[0] | (data[1] << 8) | 0x5a0000; + break; + case 3: + mctx->l ^= data[0] | (data[1] << 8) | (data[2] << 16) | + 0x5a000000; + break; + } + michael_block(mctx->l, mctx->r); + /* l ^= 0; */ + michael_block(mctx->l, mctx->r); + + put_le32(out, mctx->l); + put_le32(out + 4, mctx->r); +} + + +static int michael_setkey(void *ctx, const u8 *key, unsigned int keylen, + u32 *flags) +{ + struct michael_mic_ctx *mctx = ctx; + if (keylen != 8) { + if (flags) + *flags = CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + mctx->l = get_le32(key); + mctx->r = get_le32(key + 4); + return 0; +} + + +static struct crypto_alg michael_mic_alg = { + .cra_name = "michael_mic", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = 8, + .cra_ctxsize = sizeof(struct michael_mic_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(michael_mic_alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = 8, + .dia_init = michael_init, + .dia_update = michael_update, + .dia_final = michael_final, + .dia_setkey = michael_setkey } } +}; + + +int __init michael_mic_init(void) +{ + return crypto_register_alg(&michael_mic_alg); +} + + +void __exit michael_mic_exit(void) +{ + crypto_unregister_alg(&michael_mic_alg); +} + +#ifndef BUILT_IN_CRYPTO +module_init(michael_mic_init); +module_exit(michael_mic_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Michael MIC"); +MODULE_AUTHOR("Jouni Malinen "); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/proc.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/proc.c @@ -0,0 +1,115 @@ +/* + * Scatterlist Cryptographic API. + * + * Procfs information. + * + * Copyright (c) 2002 James Morris + * + * 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. + * + */ +#include +#include "rtl_crypto.h" +#include +#include +#include +#include "internal.h" + +extern struct list_head crypto_alg_list; +extern struct rw_semaphore crypto_alg_sem; + +static void *c_start(struct seq_file *m, loff_t *pos) +{ + struct list_head *v; + loff_t n = *pos; + + down_read(&crypto_alg_sem); + list_for_each(v, &crypto_alg_list) + if (!n--) + return list_entry(v, struct crypto_alg, cra_list); + return NULL; +} + +static void *c_next(struct seq_file *m, void *p, loff_t *pos) +{ + struct list_head *v = p; + + (*pos)++; + v = v->next; + return (v == &crypto_alg_list) ? + NULL : list_entry(v, struct crypto_alg, cra_list); +} + +static void c_stop(struct seq_file *m, void *p) +{ + up_read(&crypto_alg_sem); +} + +static int c_show(struct seq_file *m, void *p) +{ + struct crypto_alg *alg = (struct crypto_alg *)p; + + seq_printf(m, "name : %s\n", alg->cra_name); + seq_printf(m, "module : %s\n", + (alg->cra_module ? + alg->cra_module->name : + "kernel")); + + switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { + case CRYPTO_ALG_TYPE_CIPHER: + seq_printf(m, "type : cipher\n"); + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); + seq_printf(m, "min keysize : %u\n", + alg->cra_cipher.cia_min_keysize); + seq_printf(m, "max keysize : %u\n", + alg->cra_cipher.cia_max_keysize); + break; + + case CRYPTO_ALG_TYPE_DIGEST: + seq_printf(m, "type : digest\n"); + seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); + seq_printf(m, "digestsize : %u\n", + alg->cra_digest.dia_digestsize); + break; + case CRYPTO_ALG_TYPE_COMPRESS: + seq_printf(m, "type : compression\n"); + break; + default: + seq_printf(m, "type : unknown\n"); + break; + } + + seq_putc(m, '\n'); + return 0; +} + +static struct seq_operations crypto_seq_ops = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = c_show +}; + +static int crypto_info_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &crypto_seq_ops); +} + +static struct file_operations proc_crypto_ops = { + .open = crypto_info_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; + +void __init crypto_init_proc(void) +{ + struct proc_dir_entry *proc; + + proc = create_proc_entry("crypto", 0, NULL); + if (proc) + proc->proc_fops = &proc_crypto_ops; +} --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/readme +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/readme @@ -0,0 +1,162 @@ +What this layer should do + +- It mantain the old mechanism as alternative, so the + ipw2100 driver works with really few changes. +- Encapsulate / Decapsulate rtllib packet +- Handle fragmentation +- Optionally provide an alterantive mechanism for netif queue stop/wake, + so that the rtllib layer will pass one fragment per time instead of + one txb struct per time. so the driver can stop the queue in the middle + of a packet. +- Provide two different TX interfaces for cards that can handle management + frames on one HW queue, and data on another, and for cards that have only + one HW queue (the latter untested and very, very rough). +- Optionally provide the logic for handling IBSS/MASTER/MONITOR/BSS modes + and for the channel, essid and wap get/set wireless extension requests. + so that the driver has only to change channel when the ieee stack tell it. +- Optionally provide a scanning mechanism so that the driver has not to + worry about this, just implement the set channel calback and pass + frames to the upper layer +- Optionally provide the bss client protocol handshaking (just with open + authentication) +- Optionally provide the probe request send mechanism +- Optionally provide the bss master mode logic to handle association + protocol (only open authentication) and probe responses. +- SW wep encryption (with open authentication) +- It collects some stats +- It provides beacons to the card when it ask for them + +What this layer doesn't do (yet) +- Perform shared authentication +- Have full support for master mode (the AP should loop back in the air + frames from an associated client to another. This could be done easily + with few lines of code, and it is done in my previous version of the + stach, but a table of association must be keept and a disassociation + policy must be decided and implemented. +- Handle cleanly the full ieee 802.11 protocol. In AP mode it never + disassociate clients, and it is really prone to always allow access. + In bss client mode it is a bit rough with AP deauth and disassoc requests. +- It has not any entry point to view the collected stats. +- Altought it takes care of the card supported rates in the management frame + it sends, support for rate changing on TXed packet is not complete. +- Give up once associated in bss client mode (it never detect a + signal loss condition to disassociate and restart scanning) +- Provide a mechanism for enabling the TX in monitor mode, so + userspace programs can TX raw packets. +- Provide a mechanism for cards that need that the SW take care of beacon + TX completely, in sense that the SW has to enqueue by itself beacons + to the card so it TX them (if any...) +APIs + +Callback functions in the original stack has been mantained. +following has been added (from rtllib.h) + + /* Softmac-generated frames (mamagement) are TXed via this + * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is + * not set. As some cards may have different HW queues that + * one might want to use for data and management frames + * the option to have two callbacks might be useful. + * This fucntion can't sleep. + */ + int (*softmac_hard_start_xmit)(struct sk_buff *skb, + struct net_device *dev); + + /* used instead of hard_start_xmit (not softmac_hard_start_xmit) + * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data + * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set + * then also management frames are sent via this callback. + * This function can't sleep. + */ + void (*softmac_data_hard_start_xmit)(struct sk_buff *skb, + struct net_device *dev); + + /* stops the HW queue for DATA frames. Useful to avoid + * waste time to TX data frame when we are reassociating + * This function can sleep. + */ + void (*data_hard_stop)(struct net_device *dev); + + /* OK this is complementar to data_poll_hard_stop */ + void (*data_hard_resume)(struct net_device *dev); + + /* ask to the driver to retune the radio . + * This function can sleep. the driver should ensure + * the radio has been swithced before return. + */ + void (*set_chan)(struct net_device *dev,short ch); + + /* These are not used if the ieee stack takes care of + * scanning (IEEE_SOFTMAC_SCAN feature set). + * In this case only the set_chan is used. + * + * The syncro version is similar to the start_scan but + * does not return until all channels has been scanned. + * this is called in user context and should sleep, + * it is called in a work_queue when swithcing to ad-hoc mode + * or in behalf of iwlist scan when the card is associated + * and root user ask for a scan. + * the fucntion stop_scan should stop both the syncro and + * background scanning and can sleep. + * The fucntion start_scan should initiate the background + * scanning and can't sleep. + */ + void (*scan_syncro)(struct net_device *dev); + void (*start_scan)(struct net_device *dev); + void (*stop_scan)(struct net_device *dev); + + /* indicate the driver that the link state is changed + * for example it may indicate the card is associated now. + * Driver might be interested in this to apply RX filter + * rules or simply light the LINK led + */ + void (*link_change)(struct net_device *dev); + +Functions hard_data_[resume/stop] are optional and should not be used +if the driver decides to uses data+management frames enqueue in a +single HQ queue (thus using just the softmac_hard_data_start_xmit +callback). + +Function that the driver can use are: + +rtllib_get_beacon - this is called by the driver when + the HW needs a beacon. +rtllib_softmac_start_protocol - this should normally be called in the + driver open function +rtllib_softmac_stop_protocol - the opposite of the above +rtllib_wake_queue - this is similar to netif_wake_queue +rtllib_reset_queue - this throw away fragments pending(if any) +rtllib_stop_queue - this is similar to netif_stop_queue + + +known BUGS: +- When performing syncro scan (possiblily when swithcing to ad-hoc mode + and when running iwlist scan when associated) there is still an odd + behaviour.. I have not looked in this more accurately (yet). + +locking: +locking is done by means of three structures. +1- ieee->lock (by means of spin_[un]lock_irq[save/restore] +2- ieee->wx_sem +3- ieee->scan_sem + +the lock 1 is what protect most of the critical sections in the ieee stack. +the lock 2 is used to avoid that more than one of the SET wireless extension +handlers (as well as start/stop protocol function) are running at the same time. +the lock 1 is used when we need to modify or read the shared data in the wx handlers. +In other words the lock 2 will prevent one SET action will run across another SET +action (by make sleep the 2nd one) but allow GET actions, while the lock 1 +make atomic those little shared data access in both GET and SET operation. +So get operation will be never be delayed really: they will never sleep.. +Furthermore in the top of some SET operations a flag is set before acquiring +the lock. This is an help to make the previous running SET operation to +finish faster if needed (just in case the second one will totally undo the +first, so there is not need to complete the 1st really.. ). +The background scanning mechaninsm is protected by the lock 1 except for the +workqueue. this wq is here just to let the set_chan callback sleep (I thinked it +might be appreciated by USB network card driver developer). In this case the lock 3 +take its turn. +Thus the stop function needs both the locks. +Funny in the syncro scan the lock 2 play its role (as both the syncro_scan +function and the stop scan function are called with this semaphore held). + + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtl819x_BA.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtl819x_BA.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef _BATYPE_H_ +#define _BATYPE_H_ + +#define TOTAL_TXBA_NUM 16 +#define TOTAL_RXBA_NUM 16 + +#define BA_SETUP_TIMEOUT 200 +#define BA_INACT_TIMEOUT 60000 + +#define BA_POLICY_DELAYED 0 +#define BA_POLICY_IMMEDIATE 1 + +#define ADDBA_STATUS_SUCCESS 0 +#define ADDBA_STATUS_REFUSED 37 +#define ADDBA_STATUS_INVALID_PARAM 38 + +#define DELBA_REASON_QSTA_LEAVING 36 +#define DELBA_REASON_END_BA 37 +#define DELBA_REASON_UNKNOWN_BA 38 +#define DELBA_REASON_TIMEOUT 39 +typedef union _SEQUENCE_CONTROL{ + u16 ShortData; + struct + { + u16 FragNum:4; + u16 SeqNum:12; + }field; +}SEQUENCE_CONTROL, *PSEQUENCE_CONTROL; + +typedef union _BA_PARAM_SET { + u8 charData[2]; + u16 shortData; + struct { + u16 AMSDU_Support:1; + u16 BAPolicy:1; + u16 TID:4; + u16 BufferSize:10; + } field; +} BA_PARAM_SET, *PBA_PARAM_SET; + +typedef union _DELBA_PARAM_SET { + u8 charData[2]; + u16 shortData; + struct { + u16 Reserved:11; + u16 Initiator:1; + u16 TID:4; + } field; +} DELBA_PARAM_SET, *PDELBA_PARAM_SET; + +typedef struct _BA_RECORD { + struct timer_list Timer; + u8 bValid; + u8 DialogToken; + BA_PARAM_SET BaParamSet; + u16 BaTimeoutValue; + SEQUENCE_CONTROL BaStartSeqCtrl; +} BA_RECORD, *PBA_RECORD; + +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtl819x_BAProc.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtl819x_BAProc.c @@ -0,0 +1,669 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#include "rtllib.h" +#include "rtl819x_BA.h" +#ifdef RTK_DMP_PLATFORM +#include +#endif + +void ActivateBAEntry(struct rtllib_device* ieee, PBA_RECORD pBA, u16 Time) +{ + pBA->bValid = true; + if(Time != 0) + mod_timer(&pBA->Timer, jiffies + MSECS(Time)); +} + +void DeActivateBAEntry( struct rtllib_device* ieee, PBA_RECORD pBA) +{ + pBA->bValid = false; + del_timer_sync(&pBA->Timer); +} +u8 TxTsDeleteBA( struct rtllib_device* ieee, PTX_TS_RECORD pTxTs) +{ + PBA_RECORD pAdmittedBa = &pTxTs->TxAdmittedBARecord; + PBA_RECORD pPendingBa = &pTxTs->TxPendingBARecord; + u8 bSendDELBA = false; + + if(pPendingBa->bValid) + { + DeActivateBAEntry(ieee, pPendingBa); + bSendDELBA = true; + } + + if(pAdmittedBa->bValid) + { + DeActivateBAEntry(ieee, pAdmittedBa); + bSendDELBA = true; + } + + return bSendDELBA; +} + +u8 RxTsDeleteBA( struct rtllib_device* ieee, PRX_TS_RECORD pRxTs) +{ + PBA_RECORD pBa = &pRxTs->RxAdmittedBARecord; + u8 bSendDELBA = false; + + if(pBa->bValid) + { + DeActivateBAEntry(ieee, pBa); + bSendDELBA = true; + } + + return bSendDELBA; +} + +void ResetBaEntry( PBA_RECORD pBA) +{ + pBA->bValid = false; + pBA->BaParamSet.shortData = 0; + pBA->BaTimeoutValue = 0; + pBA->DialogToken = 0; + pBA->BaStartSeqCtrl.ShortData = 0; +} +static struct sk_buff* rtllib_ADDBA(struct rtllib_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type) +{ + struct sk_buff *skb = NULL; + struct rtllib_hdr_3addr* BAReq = NULL; + u8* tag = NULL; + u16 tmp = 0; + u16 len = ieee->tx_headroom + 9; + RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __FUNCTION__, type, MAC_ARG(Dst), ieee->dev); + if (pBA == NULL||ieee == NULL) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee); + return NULL; + } +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr=0; + int alignment=0; + skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr) + USB_512B_ALIGNMENT_SIZE); +#else + skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr)); +#endif + if (skb == NULL) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc skb for ADDBA_REQ\n"); + return NULL; + } + + memset(skb->data, 0, sizeof( struct rtllib_hdr_3addr)); + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + + skb_reserve(skb, ieee->tx_headroom); + + BAReq = ( struct rtllib_hdr_3addr *) skb_put(skb,sizeof( struct rtllib_hdr_3addr)); + + memcpy(BAReq->addr1, Dst, ETH_ALEN); + memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN); + +#ifdef _RTL8192_EXT_PATCH_ + if((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0) && ieee->ext_patch_rtllib_is_mesh && ieee->ext_patch_rtllib_is_mesh(ieee, Dst)){ +#ifdef COMPATIBLE_WITH_RALINK_MESH + memcpy(BAReq->addr3, Dst, ETH_ALEN); +#else + memcpy(BAReq->addr3, ieee->current_mesh_network.bssid, ETH_ALEN); +#endif + } + else + memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN); +#else + memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN); +#endif + BAReq->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT); + + tag = (u8*)skb_put(skb, 9); + *tag ++= ACT_CAT_BA; + *tag ++= type; + *tag ++= pBA->DialogToken; + + if (ACT_ADDBARSP == type) + { + printk("====>to send ADDBARSP\n"); + tmp = cpu_to_le16(StatusCode); + memcpy(tag, (u8*)&tmp, 2); + tag += 2; + } + tmp = cpu_to_le16(pBA->BaParamSet.shortData); + memcpy(tag, (u8*)&tmp, 2); + tag += 2; + tmp = cpu_to_le16(pBA->BaTimeoutValue); + memcpy(tag, (u8*)&tmp, 2); + tag += 2; + + if (ACT_ADDBAREQ == type) + { + memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2); + tag += 2; + } + + RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); + return skb; +} + +static struct sk_buff* rtllib_DELBA( + struct rtllib_device* ieee, + u8* dst, + PBA_RECORD pBA, + TR_SELECT TxRxSelect, + u16 ReasonCode + ) +{ + DELBA_PARAM_SET DelbaParamSet; + struct sk_buff *skb = NULL; + struct rtllib_hdr_3addr* Delba = NULL; + u8* tag = NULL; + u16 tmp = 0; + u16 len = 6 + ieee->tx_headroom; + + if (net_ratelimit()) + RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __FUNCTION__, ReasonCode, MAC_ARG(dst)); + + memset(&DelbaParamSet, 0, 2); + + DelbaParamSet.field.Initiator = (TxRxSelect==TX_DIR)?1:0; + DelbaParamSet.field.TID = pBA->BaParamSet.field.TID; + +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr=0; + int alignment=0; + skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr) + USB_512B_ALIGNMENT_SIZE); +#else + skb = dev_alloc_skb(len + sizeof( struct rtllib_hdr_3addr)); +#endif + if (skb == NULL) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc skb for ADDBA_REQ\n"); + return NULL; + } + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + skb_reserve(skb, ieee->tx_headroom); + + Delba = ( struct rtllib_hdr_3addr *) skb_put(skb,sizeof( struct rtllib_hdr_3addr)); + + memcpy(Delba->addr1, dst, ETH_ALEN); + memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN); +#ifdef _RTL8192_EXT_PATCH_ + if((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0) && ieee->ext_patch_rtllib_is_mesh && ieee->ext_patch_rtllib_is_mesh(ieee, dst)){ +#ifdef COMPATIBLE_WITH_RALINK_MESH + memcpy(Delba->addr3, dst, ETH_ALEN); +#else + memcpy(Delba->addr3, ieee->current_mesh_network.bssid, ETH_ALEN); +#endif + } + else + memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN); +#else + memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN); +#endif + Delba->frame_ctl = cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT); + + tag = (u8*)skb_put(skb, 6); + + *tag ++= ACT_CAT_BA; + *tag ++= ACT_DELBA; + + tmp = cpu_to_le16(DelbaParamSet.shortData); + memcpy(tag, (u8*)&tmp, 2); + tag += 2; + tmp = cpu_to_le16(ReasonCode); + memcpy(tag, (u8*)&tmp, 2); + tag += 2; + + RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); + if (net_ratelimit()) + RTLLIB_DEBUG(RTLLIB_DL_TRACE | RTLLIB_DL_BA, "<=====%s()\n", __FUNCTION__); + return skb; +} + +void rtllib_send_ADDBAReq(struct rtllib_device* ieee, u8* dst, PBA_RECORD pBA) +{ + struct sk_buff *skb = NULL; + skb = rtllib_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); + + if (skb) + { + printk("====>to send ADDBAREQ!!!!!\n"); + softmac_mgmt_xmit(skb, ieee); + } + else + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__); + } + return; +} + +void rtllib_send_ADDBARsp(struct rtllib_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode) +{ + struct sk_buff *skb = NULL; + skb = rtllib_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); + if (skb) + { + softmac_mgmt_xmit(skb, ieee); + } + else + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__); + } + + return; + +} + +void rtllib_send_DELBA(struct rtllib_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode) +{ + struct sk_buff *skb = NULL; + skb = rtllib_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); + if (skb) + { + softmac_mgmt_xmit(skb, ieee); + } + else + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__); + } + return ; +} + +int rtllib_rx_ADDBAReq( struct rtllib_device* ieee, struct sk_buff *skb) +{ + struct rtllib_hdr_3addr* req = NULL; + u16 rc = 0; + u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL; + PBA_RECORD pBA = NULL; + PBA_PARAM_SET pBaParamSet = NULL; + u16* pBaTimeoutVal = NULL; + PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL; + PRX_TS_RECORD pTS = NULL; + + if (skb->len < sizeof( struct rtllib_hdr_3addr) + 9) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n",(int)skb->len, (int)(sizeof( struct rtllib_hdr_3addr) + 9)); + return -1; + } + + RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); + + req = ( struct rtllib_hdr_3addr*) skb->data; + tag = (u8*)req; + dst = (u8*)(&req->addr2[0]); + tag += sizeof( struct rtllib_hdr_3addr); + pDialogToken = tag + 2; + pBaParamSet = (PBA_PARAM_SET)(tag + 3); + pBaTimeoutVal = (u16*)(tag + 5); + pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7); + + printk("====>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst)); + if( +#ifdef _RTL8192_EXT_PATCH_ + (ieee->current_network.qos_data.active == 0 && ieee->current_mesh_network.qos_data.active==0) || +#else + ieee->current_network.qos_data.active == 0 || +#endif + (ieee->pHTInfo->bCurrentHTSupport == false) || + (ieee->pHTInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ)) + { + rc = ADDBA_STATUS_REFUSED; + RTLLIB_DEBUG(RTLLIB_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); + goto OnADDBAReq_Fail; + } + if( !GetTs( + ieee, + (PTS_COMMON_INFO*)(&pTS), + dst, + (u8)(pBaParamSet->field.TID), + RX_DIR, + true) ) + { + rc = ADDBA_STATUS_REFUSED; + RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS in %s()\n", __FUNCTION__); + goto OnADDBAReq_Fail; + } + pBA = &pTS->RxAdmittedBARecord; + + if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) + { + rc = ADDBA_STATUS_INVALID_PARAM; + RTLLIB_DEBUG(RTLLIB_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__); + goto OnADDBAReq_Fail; + } + + + rtllib_FlushRxTsPendingPkts(ieee, pTS); + + DeActivateBAEntry(ieee, pBA); + pBA->DialogToken = *pDialogToken; + pBA->BaParamSet = *pBaParamSet; + pBA->BaTimeoutValue = *pBaTimeoutVal; + pBA->BaStartSeqCtrl = *pBaStartSeqCtrl; + + if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)|| + (ieee->pHTInfo->IOTAction & HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT)) + pBA->BaParamSet.field.BufferSize = 1; + else + pBA->BaParamSet.field.BufferSize = 32; + + ActivateBAEntry(ieee, pBA, 0); + rtllib_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS); + + return 0; + +OnADDBAReq_Fail: + { + BA_RECORD BA; + BA.BaParamSet = *pBaParamSet; + BA.BaTimeoutValue = *pBaTimeoutVal; + BA.DialogToken = *pDialogToken; + BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE; + rtllib_send_ADDBARsp(ieee, dst, &BA, rc); + return 0; + } + +} + +int rtllib_rx_ADDBARsp( struct rtllib_device* ieee, struct sk_buff *skb) +{ + struct rtllib_hdr_3addr* rsp = NULL; + PBA_RECORD pPendingBA, pAdmittedBA; + PTX_TS_RECORD pTS = NULL; + u8* dst = NULL, *pDialogToken = NULL, *tag = NULL; + u16* pStatusCode = NULL, *pBaTimeoutVal = NULL; + PBA_PARAM_SET pBaParamSet = NULL; + u16 ReasonCode; + + if (skb->len < sizeof( struct rtllib_hdr_3addr) + 9) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", (int)skb->len, (int)(sizeof( struct rtllib_hdr_3addr) + 9)); + return -1; + } + rsp = ( struct rtllib_hdr_3addr*)skb->data; + tag = (u8*)rsp; + dst = (u8*)(&rsp->addr2[0]); + tag += sizeof( struct rtllib_hdr_3addr); + pDialogToken = tag + 2; + pStatusCode = (u16*)(tag + 3); + pBaParamSet = (PBA_PARAM_SET)(tag + 5); + pBaTimeoutVal = (u16*)(tag + 7); + + printk("====>rx ADDBARSP from :"MAC_FMT"\n", MAC_ARG(dst)); + if( +#ifdef _RTL8192_EXT_PATCH_ + (ieee->current_network.qos_data.active == 0 && ieee->current_mesh_network.qos_data.active==0) || +#else + ieee->current_network.qos_data.active == 0 || +#endif + ieee->pHTInfo->bCurrentHTSupport == false || + ieee->pHTInfo->bCurrentAMPDUEnable == false ) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable); + ReasonCode = DELBA_REASON_UNKNOWN_BA; + goto OnADDBARsp_Reject; + } + + + if (!GetTs( + ieee, + (PTS_COMMON_INFO*)(&pTS), + dst, + (u8)(pBaParamSet->field.TID), + TX_DIR, + false) ) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS in %s()\n", __FUNCTION__); + ReasonCode = DELBA_REASON_UNKNOWN_BA; + goto OnADDBARsp_Reject; + } + + pTS->bAddBaReqInProgress = false; + pPendingBA = &pTS->TxPendingBARecord; + pAdmittedBA = &pTS->TxAdmittedBARecord; + + + if((pAdmittedBA->bValid==true)) + { + RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n"); + return -1; + } + else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken)) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n"); + ReasonCode = DELBA_REASON_UNKNOWN_BA; + goto OnADDBARsp_Reject; + } + else + { + RTLLIB_DEBUG(RTLLIB_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode); + DeActivateBAEntry(ieee, pPendingBA); + } + + + if(*pStatusCode == ADDBA_STATUS_SUCCESS) + { + if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) + { + pTS->bAddBaReqDelayed = true; + DeActivateBAEntry(ieee, pAdmittedBA); + ReasonCode = DELBA_REASON_END_BA; + goto OnADDBARsp_Reject; + } + + + pAdmittedBA->DialogToken = *pDialogToken; + pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal; + pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl; + pAdmittedBA->BaParamSet = *pBaParamSet; + DeActivateBAEntry(ieee, pAdmittedBA); + ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal); + } else { + pTS->bAddBaReqDelayed = true; + pTS->bDisable_AddBa = true; + ReasonCode = DELBA_REASON_END_BA; + goto OnADDBARsp_Reject; + } + + return 0; + +OnADDBARsp_Reject: + { + BA_RECORD BA; + BA.BaParamSet = *pBaParamSet; + rtllib_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode); + return 0; + } + +} + +int rtllib_rx_DELBA(struct rtllib_device* ieee,struct sk_buff *skb) +{ + struct rtllib_hdr_3addr* delba = NULL; + PDELBA_PARAM_SET pDelBaParamSet = NULL; + u16* pReasonCode = NULL; + u8* dst = NULL; + + if (skb->len < sizeof( struct rtllib_hdr_3addr) + 6) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", (int)skb->len, (int)(sizeof( struct rtllib_hdr_3addr) + 6)); + return -1; + } + + if( +#ifdef _RTL8192_EXT_PATCH_ + (ieee->current_network.qos_data.active == 0 && ieee->current_mesh_network.qos_data.active==0) || +#else + ieee->current_network.qos_data.active == 0 || +#endif + ieee->pHTInfo->bCurrentHTSupport == false ) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport); + return -1; + } + + RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_BA, skb->data, skb->len); + delba = ( struct rtllib_hdr_3addr*)skb->data; + dst = (u8*)(&delba->addr2[0]); + delba += sizeof( struct rtllib_hdr_3addr); + pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2); + pReasonCode = (u16*)(delba+4); + + if(pDelBaParamSet->field.Initiator == 1) + { + PRX_TS_RECORD pRxTs; + + if( !GetTs( + ieee, + (PTS_COMMON_INFO*)&pRxTs, + dst, + (u8)pDelBaParamSet->field.TID, + RX_DIR, + false) ) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS for RXTS in %s().dst:"MAC_FMT" TID:%d\n", __FUNCTION__, MAC_ARG(dst), (u8)pDelBaParamSet->field.TID); + return -1; + } + + RxTsDeleteBA(ieee, pRxTs); + } + else + { + PTX_TS_RECORD pTxTs; + + if(!GetTs( + ieee, + (PTS_COMMON_INFO*)&pTxTs, + dst, + (u8)pDelBaParamSet->field.TID, + TX_DIR, + false) ) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't get TS for TXTS in %s()\n", __FUNCTION__); + return -1; + } + + pTxTs->bUsingBa = false; + pTxTs->bAddBaReqInProgress = false; + pTxTs->bAddBaReqDelayed = false; + del_timer_sync(&pTxTs->TsAddBaTimer); + TxTsDeleteBA(ieee, pTxTs); + } + return 0; +} + +void +TsInitAddBA( + struct rtllib_device* ieee, + PTX_TS_RECORD pTS, + u8 Policy, + u8 bOverwritePending + ) +{ + PBA_RECORD pBA = &pTS->TxPendingBARecord; + + if(pBA->bValid==true && bOverwritePending==false) + return; + + DeActivateBAEntry(ieee, pBA); + + pBA->DialogToken++; + pBA->BaParamSet.field.AMSDU_Support = 0; + pBA->BaParamSet.field.BAPolicy = Policy; + pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID; + pBA->BaParamSet.field.BufferSize = 32; + pBA->BaTimeoutValue = 0; + pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; + + ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT); + + rtllib_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA); +} + +void +TsInitDelBA( struct rtllib_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect) +{ + + if(TxRxSelect == TX_DIR) + { + PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTsCommonInfo; + + if(TxTsDeleteBA(ieee, pTxTs)) + rtllib_send_DELBA( + ieee, + pTsCommonInfo->Addr, + (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord), + TxRxSelect, + DELBA_REASON_END_BA); + } + else if(TxRxSelect == RX_DIR) + { + PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo; + if(RxTsDeleteBA(ieee, pRxTs)) + rtllib_send_DELBA( + ieee, + pTsCommonInfo->Addr, + &pRxTs->RxAdmittedBARecord, + TxRxSelect, + DELBA_REASON_END_BA ); + } +} +void BaSetupTimeOut(unsigned long data) +{ + PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data; + + pTxTs->bAddBaReqInProgress = false; + pTxTs->bAddBaReqDelayed = true; + pTxTs->TxPendingBARecord.bValid = false; +} + +void TxBaInactTimeout(unsigned long data) +{ + PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data; + struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device, TxTsRecord[pTxTs->num]); + TxTsDeleteBA(ieee, pTxTs); + rtllib_send_DELBA( + ieee, + pTxTs->TsCommonInfo.Addr, + &pTxTs->TxAdmittedBARecord, + TX_DIR, + DELBA_REASON_TIMEOUT); +} + +void RxBaInactTimeout(unsigned long data) +{ + PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data; + struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device, RxTsRecord[pRxTs->num]); + + RxTsDeleteBA(ieee, pRxTs); + rtllib_send_DELBA( + ieee, + pRxTs->TsCommonInfo.Addr, + &pRxTs->RxAdmittedBARecord, + RX_DIR, + DELBA_REASON_TIMEOUT); + return ; +} + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtl819x_HT.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtl819x_HT.h @@ -0,0 +1,501 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef _RTL819XU_HTTYPE_H_ +#define _RTL819XU_HTTYPE_H_ + + +#define HT_OPMODE_NO_PROTECT 0 +#define HT_OPMODE_OPTIONAL 1 +#define HT_OPMODE_40MHZ_PROTECT 2 +#define HT_OPMODE_MIXED 3 + +#define MIMO_PS_STATIC 0 +#define MIMO_PS_DYNAMIC 1 +#define MIMO_PS_NOLIMIT 3 + + + +#define sHTCLng 4 + + +#define HT_SUPPORTED_MCS_1SS_BITMAP 0x000000ff +#define HT_SUPPORTED_MCS_2SS_BITMAP 0x0000ff00 +#define HT_SUPPORTED_MCS_1SS_2SS_BITMAP HT_MCS_1SS_BITMAP|HT_MCS_1SS_2SS_BITMAP + + +typedef enum _HT_MCS_RATE{ + HT_MCS0 = 0x00000001, + HT_MCS1 = 0x00000002, + HT_MCS2 = 0x00000004, + HT_MCS3 = 0x00000008, + HT_MCS4 = 0x00000010, + HT_MCS5 = 0x00000020, + HT_MCS6 = 0x00000040, + HT_MCS7 = 0x00000080, + HT_MCS8 = 0x00000100, + HT_MCS9 = 0x00000200, + HT_MCS10 = 0x00000400, + HT_MCS11 = 0x00000800, + HT_MCS12 = 0x00001000, + HT_MCS13 = 0x00002000, + HT_MCS14 = 0x00004000, + HT_MCS15 = 0x00008000, +}HT_MCS_RATE,*PHT_MCS_RATE; + +typedef enum _HT_CHANNEL_WIDTH{ + HT_CHANNEL_WIDTH_20 = 0, + HT_CHANNEL_WIDTH_20_40 = 1, +}HT_CHANNEL_WIDTH, *PHT_CHANNEL_WIDTH; + +typedef enum _HT_EXTCHNL_OFFSET{ + HT_EXTCHNL_OFFSET_NO_EXT = 0, + HT_EXTCHNL_OFFSET_UPPER = 1, + HT_EXTCHNL_OFFSET_NO_DEF = 2, + HT_EXTCHNL_OFFSET_LOWER = 3, +}HT_EXTCHNL_OFFSET, *PHT_EXTCHNL_OFFSET; + +typedef enum _CHNLOP{ + CHNLOP_NONE = 0, + CHNLOP_SCAN = 1, + CHNLOP_SWBW = 2, + CHNLOP_SWCHNL = 3, +} CHNLOP, *PCHNLOP; + +#define CHHLOP_IN_PROGRESS(_pHTInfo) \ + ((_pHTInfo)->ChnlOp > CHNLOP_NONE) ? true : false + +/* +typedef union _HT_CAPABILITY{ + u16 ShortData; + u8 CharData[2]; + struct + { + u16 AdvCoding:1; + u16 ChlWidth:1; + u16 MimoPwrSave:2; + u16 GreenField:1; + u16 ShortGI20Mhz:1; + u16 ShortGI40Mhz:1; + u16 STBC:1; + u16 BeamForm:1; + u16 DelayBA:1; + u16 MaxAMSDUSize:1; + u16 DssCCk:1; + u16 PSMP:1; + u16 Rsvd:3; + }Field; +}HT_CAPABILITY, *PHT_CAPABILITY; + +typedef union _HT_CAPABILITY_MACPARA{ + u8 ShortData; + u8 CharData[1]; + struct + { + u8 MaxRxAMPDU:2; + u8 MPDUDensity:2; + u8 Rsvd:4; + }Field; +}HT_CAPABILITY_MACPARA, *PHT_CAPABILITY_MACPARA; +*/ + +typedef enum _HT_ACTION{ + ACT_RECOMMAND_WIDTH = 0, + ACT_MIMO_PWR_SAVE = 1, + ACT_PSMP = 2, + ACT_SET_PCO_PHASE = 3, + ACT_MIMO_CHL_MEASURE = 4, + ACT_RECIPROCITY_CORRECT = 5, + ACT_MIMO_CSI_MATRICS = 6, + ACT_MIMO_NOCOMPR_STEER = 7, + ACT_MIMO_COMPR_STEER = 8, + ACT_ANTENNA_SELECT = 9, +} HT_ACTION, *PHT_ACTION; + + +typedef enum _HT_Bandwidth_40MHZ_Sub_Carrier{ + SC_MODE_DUPLICATE = 0, + SC_MODE_LOWER = 1, + SC_MODE_UPPER = 2, + SC_MODE_FULL40MHZ = 3, +}HT_BW40_SC_E; + +typedef struct _HT_CAPABILITY_ELE{ + + u8 AdvCoding:1; + u8 ChlWidth:1; + u8 MimoPwrSave:2; + u8 GreenField:1; + u8 ShortGI20Mhz:1; + u8 ShortGI40Mhz:1; + u8 TxSTBC:1; + u8 RxSTBC:2; + u8 DelayBA:1; + u8 MaxAMSDUSize:1; + u8 DssCCk:1; + u8 PSMP:1; + u8 Rsvd1:1; + u8 LSigTxopProtect:1; + + u8 MaxRxAMPDUFactor:2; + u8 MPDUDensity:3; + u8 Rsvd2:3; + + u8 MCS[16]; + + + u16 ExtHTCapInfo; + + u8 TxBFCap[4]; + + u8 ASCap; + +} __attribute__ ((packed)) HT_CAPABILITY_ELE, *PHT_CAPABILITY_ELE; + + +typedef struct _HT_INFORMATION_ELE{ + u8 ControlChl; + + u8 ExtChlOffset:2; + u8 RecommemdedTxWidth:1; + u8 RIFS:1; + u8 PSMPAccessOnly:1; + u8 SrvIntGranularity:3; + + u8 OptMode:2; + u8 NonGFDevPresent:1; + u8 Revd1:5; + u8 Revd2:8; + + u8 Rsvd3:6; + u8 DualBeacon:1; + u8 DualCTSProtect:1; + + u8 SecondaryBeacon:1; + u8 LSigTxopProtectFull:1; + u8 PcoActive:1; + u8 PcoPhase:1; + u8 Rsvd4:4; + + u8 BasicMSC[16]; +} __attribute__ ((packed)) HT_INFORMATION_ELE, *PHT_INFORMATION_ELE; + +typedef struct _MIMOPS_CTRL{ + u8 MimoPsEnable:1; + u8 MimoPsMode:1; + u8 Reserved:6; +} MIMOPS_CTRL, *PMIMOPS_CTRL; + +typedef enum _HT_SPEC_VER{ + HT_SPEC_VER_IEEE = 0, + HT_SPEC_VER_EWC = 1, +}HT_SPEC_VER, *PHT_SPEC_VER; + +typedef enum _HT_AGGRE_MODE_E{ + HT_AGG_AUTO = 0, + HT_AGG_FORCE_ENABLE = 1, + HT_AGG_FORCE_DISABLE = 2, +}HT_AGGRE_MODE_E, *PHT_AGGRE_MODE_E; + + +typedef struct _RT_HIGH_THROUGHPUT{ + u8 bEnableHT; + u8 bCurrentHTSupport; + + u8 bRegBW40MHz; + u8 bCurBW40MHz; + + u8 bRegShortGI40MHz; + u8 bCurShortGI40MHz; + + u8 bRegShortGI20MHz; + u8 bCurShortGI20MHz; + + u8 bRegSuppCCK; + u8 bCurSuppCCK; + + HT_SPEC_VER ePeerHTSpecVer; + + + HT_CAPABILITY_ELE SelfHTCap; + HT_INFORMATION_ELE SelfHTInfo; + + u8 PeerHTCapBuf[32]; + u8 PeerHTInfoBuf[32]; + + + u8 bAMSDU_Support; + u16 nAMSDU_MaxSize; + u8 bCurrent_AMSDU_Support; + u16 nCurrent_AMSDU_MaxSize; +#ifdef _RTL8192_EXT_PATCH_ + u8 bCurrent_Mesh_AMSDU_Support; +#endif + + u8 bAMPDUEnable; + u8 bCurrentAMPDUEnable; + u8 AMPDU_Factor; + u8 CurrentAMPDUFactor; + u8 MPDU_Density; + u8 CurrentMPDUDensity; +#ifdef _RTL8192_EXT_PATCH_ + u8 bCurrentMeshAMPDUEnable; +#endif + + HT_AGGRE_MODE_E ForcedAMPDUMode; + u8 ForcedAMPDUFactor; + u8 ForcedMPDUDensity; + + HT_AGGRE_MODE_E ForcedAMSDUMode; + u16 ForcedAMSDUMaxSize; + + u8 bForcedShortGI; + + u8 CurrentOpMode; + + u8 SelfMimoPs; + u8 PeerMimoPs; + + HT_EXTCHNL_OFFSET CurSTAExtChnlOffset; + u8 bCurTxBW40MHz; + u8 PeerBandwidth; + + u8 bSwBwInProgress; + CHNLOP ChnlOp; + u8 SwBwStep; + + u8 bRegRT2RTAggregation; + u8 RT2RT_HT_Mode; + u8 bCurrentRT2RTAggregation; + u8 bCurrentRT2RTLongSlotTime; + u8 szRT2RTAggBuffer[10]; + + u8 bRegRxReorderEnable; + u8 bCurRxReorderEnable; + u8 RxReorderWinSize; + u8 RxReorderPendingTime; + u16 RxReorderDropCounter; + +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + u8 UsbTxAggrNum; +#endif +#ifdef USB_RX_AGGREGATION_SUPPORT + u8 UsbRxFwAggrEn; + u8 UsbRxFwAggrPageNum; + u8 UsbRxFwAggrPacketNum; + u8 UsbRxFwAggrTimeout; + u8 UsbRxPageSize; +#endif + + u8 bIsPeerBcm; + + u8 IOTPeer; + u32 IOTAction; + u8 IOTRaFunc; + + u8 bWAIotBroadcom; + u8 WAIotTH; + +#ifdef RTL8192CE + u8 bRDGEnable; +#endif + + u8 bAcceptAddbaReq; +} __attribute__ ((packed)) RT_HIGH_THROUGHPUT, *PRT_HIGH_THROUGHPUT; + + + +typedef struct _RT_HTINFO_STA_ENTRY{ + u8 bEnableHT; + + u8 bSupportCck; + + u16 AMSDU_MaxSize; + + u8 AMPDU_Factor; + u8 MPDU_Density; + + u8 HTHighestOperaRate; + + u8 bBw40MHz; + + u8 bCurTxBW40MHz; + + u8 bCurShortGI20MHz; + + u8 bCurShortGI40MHz; + + u8 MimoPs; + + u8 McsRateSet[16]; + + u8 bCurRxReorderEnable; + + u16 nAMSDU_MaxSize; + +}RT_HTINFO_STA_ENTRY, *PRT_HTINFO_STA_ENTRY; + + + + + + +typedef struct _BSS_HT{ + + u8 bdSupportHT; + + u8 bdHTCapBuf[32]; + u16 bdHTCapLen; + u8 bdHTInfoBuf[32]; + u16 bdHTInfoLen; + + HT_SPEC_VER bdHTSpecVer; + HT_CHANNEL_WIDTH bdBandWidth; + + u8 bdRT2RTAggregation; + u8 bdRT2RTLongSlotTime; + u8 RT2RT_HT_Mode; + u8 bdHT1R; +} __attribute__ ((packed)) BSS_HT, *PBSS_HT; + +typedef struct _MIMO_RSSI{ + u32 EnableAntenna; + u32 AntennaA; + u32 AntennaB; + u32 AntennaC; + u32 AntennaD; + u32 Average; +}MIMO_RSSI, *PMIMO_RSSI; + +typedef struct _MIMO_EVM{ + u32 EVM1; + u32 EVM2; +}MIMO_EVM, *PMIMO_EVM; + +typedef struct _FALSE_ALARM_STATISTICS{ + u32 Cnt_Parity_Fail; + u32 Cnt_Rate_Illegal; + u32 Cnt_Crc8_fail; + u32 Cnt_Mcs_fail; + u32 Cnt_Ofdm_fail; + u32 Cnt_Cck_fail; + u32 Cnt_all; +}FALSE_ALARM_STATISTICS, *PFALSE_ALARM_STATISTICS; + + +extern u8 MCS_FILTER_ALL[16]; +extern u8 MCS_FILTER_1SS[16]; + +#define PICK_RATE(_nLegacyRate, _nMcsRate) \ + (_nMcsRate==0)?(_nLegacyRate&0x7f):(_nMcsRate) +#define LEGACY_WIRELESS_MODE IEEE_MODE_MASK + +#define CURRENT_RATE(WirelessMode, LegacyRate, HTRate) \ + ((WirelessMode & (LEGACY_WIRELESS_MODE))!=0)?\ + (LegacyRate):\ + (PICK_RATE(LegacyRate, HTRate)) + + + +#define RATE_ADPT_1SS_MASK 0xFF +#define RATE_ADPT_2SS_MASK 0xF0 +#define RATE_ADPT_MCS32_MASK 0x01 + +#define IS_11N_MCS_RATE(rate) (rate&0x80) + +typedef enum _HT_AGGRE_SIZE{ + HT_AGG_SIZE_8K = 0, + HT_AGG_SIZE_16K = 1, + HT_AGG_SIZE_32K = 2, + HT_AGG_SIZE_64K = 3, +}HT_AGGRE_SIZE_E, *PHT_AGGRE_SIZE_E; + +typedef enum _HT_IOT_PEER +{ + HT_IOT_PEER_UNKNOWN = 0, + HT_IOT_PEER_REALTEK = 1, + HT_IOT_PEER_REALTEK_92SE = 2, + HT_IOT_PEER_BROADCOM = 3, + HT_IOT_PEER_RALINK = 4, + HT_IOT_PEER_ATHEROS = 5, + HT_IOT_PEER_CISCO= 6, + HT_IOT_PEER_MARVELL=7, + HT_IOT_PEER_92U_SOFTAP = 8, + HT_IOT_PEER_SELF_SOFTAP = 9, + HT_IOT_PEER_AIRGO = 10, + HT_IOT_PEER_MAX = 11, +}HT_IOT_PEER_E, *PHTIOT_PEER_E; + +typedef enum _HT_IOT_PEER_SUBTYPE +{ + HT_IOT_PEER_ATHEROS_DIR635 = 0, +}HT_IOT_PEER_SUBTYPE_E, *PHTIOT_PEER_SUBTYPE_E; + +typedef enum _HT_IOT_ACTION{ + HT_IOT_ACT_TX_USE_AMSDU_4K = 0x00000001, + HT_IOT_ACT_TX_USE_AMSDU_8K = 0x00000002, + HT_IOT_ACT_DISABLE_MCS14 = 0x00000004, + HT_IOT_ACT_DISABLE_MCS15 = 0x00000008, + HT_IOT_ACT_DISABLE_ALL_2SS = 0x00000010, + HT_IOT_ACT_DISABLE_EDCA_TURBO = 0x00000020, + HT_IOT_ACT_MGNT_USE_CCK_6M = 0x00000040, + HT_IOT_ACT_CDD_FSYNC = 0x00000080, + HT_IOT_ACT_PURE_N_MODE = 0x00000100, + HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200, + HT_IOT_ACT_FORCED_RTS = 0x00000400, + HT_IOT_ACT_AMSDU_ENABLE = 0x00000800, + HT_IOT_ACT_REJECT_ADDBA_REQ = 0x00001000, + HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT = 0x00002000, + HT_IOT_ACT_EDCA_BIAS_ON_RX = 0x00004000, + + HT_IOT_ACT_HYBRID_AGGREGATION = 0x00010000, + HT_IOT_ACT_DISABLE_SHORT_GI = 0x00020000, + HT_IOT_ACT_DISABLE_HIGH_POWER = 0x00040000, + HT_IOT_ACT_DISABLE_TX_40_MHZ = 0x00080000, + HT_IOT_ACT_TX_NO_AGGREGATION = 0x00100000, + HT_IOT_ACT_DISABLE_TX_2SS = 0x00200000, + + HT_IOT_ACT_MID_HIGHPOWER = 0x00400000, + HT_IOT_ACT_NULL_DATA_POWER_SAVING = 0x00800000, + + HT_IOT_ACT_DISABLE_CCK_RATE = 0x01000000, + HT_IOT_ACT_FORCED_ENABLE_BE_TXOP = 0x02000000, + HT_IOT_ACT_WA_IOT_Broadcom = 0x04000000, + HT_IOT_ACT_DISABLE_RX_40MHZ_SHORT_GI = 0x08000000, + + HT_IOT_ACT_IPTIME_704 = 0x10000000, + +}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E; + +typedef enum _HT_IOT_RAFUNC{ + HT_IOT_RAFUNC_DISABLE_ALL = 0x00, + HT_IOT_RAFUNC_PEER_1R = 0x01, + HT_IOT_RAFUNC_TX_AMSDU = 0x02, +}HT_IOT_RAFUNC, *PHT_IOT_RAFUNC; + +typedef enum _RT_HT_CAP{ + RT_HT_CAP_USE_TURBO_AGGR = 0x01, + RT_HT_CAP_USE_LONG_PREAMBLE = 0x02, + RT_HT_CAP_USE_AMPDU = 0x04, + RT_HT_CAP_USE_WOW = 0x8, + RT_HT_CAP_USE_SOFTAP = 0x10, + RT_HT_CAP_USE_92SE = 0x20, +}RT_HT_CAPBILITY, *PRT_HT_CAPBILITY; + +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtl819x_HTProc.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtl819x_HTProc.c @@ -0,0 +1,1739 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#include "rtllib.h" +#include "rtl819x_HT.h" +u8 MCS_FILTER_ALL[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +u8 MCS_FILTER_1SS[16] = {0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +u16 MCS_DATA_RATE[2][2][77] = + { { {13, 26, 39, 52, 78, 104, 117, 130, 26, 52, 78 ,104, 156, 208, 234, 260, + 39, 78, 117, 234, 312, 351, 390, 52, 104, 156, 208, 312, 416, 468, 520, + 0, 78, 104, 130, 117, 156, 195, 104, 130, 130, 156, 182, 182, 208, 156, 195, + 195, 234, 273, 273, 312, 130, 156, 181, 156, 181, 208, 234, 208, 234, 260, 260, + 286, 195, 234, 273, 234, 273, 312, 351, 312, 351, 390, 390, 429}, + {14, 29, 43, 58, 87, 116, 130, 144, 29, 58, 87, 116, 173, 231, 260, 289, + 43, 87, 130, 173, 260, 347, 390, 433, 58, 116, 173, 231, 347, 462, 520, 578, + 0, 87, 116, 144, 130, 173, 217, 116, 144, 144, 173, 202, 202, 231, 173, 217, + 217, 260, 303, 303, 347, 144, 173, 202, 173, 202, 231, 260, 231, 260, 289, 289, + 318, 217, 260, 303, 260, 303, 347, 390, 347, 390, 433, 433, 477} }, + { {27, 54, 81, 108, 162, 216, 243, 270, 54, 108, 162, 216, 324, 432, 486, 540, + 81, 162, 243, 324, 486, 648, 729, 810, 108, 216, 324, 432, 648, 864, 972, 1080, + 12, 162, 216, 270, 243, 324, 405, 216, 270, 270, 324, 378, 378, 432, 324, 405, + 405, 486, 567, 567, 648, 270, 324, 378, 324, 378, 432, 486, 432, 486, 540, 540, + 594, 405, 486, 567, 486, 567, 648, 729, 648, 729, 810, 810, 891}, + {30, 60, 90, 120, 180, 240, 270, 300, 60, 120, 180, 240, 360, 480, 540, 600, + 90, 180, 270, 360, 540, 720, 810, 900, 120, 240, 360, 480, 720, 960, 1080, 1200, + 13, 180, 240, 300, 270, 360, 450, 240, 300, 300, 360, 420, 420, 480, 360, 450, + 450, 540, 630, 630, 720, 300, 360, 420, 360, 420, 480, 540, 480, 540, 600, 600, + 660, 450, 540, 630, 540, 630, 720, 810, 720, 810, 900, 900, 990} } + }; + +static u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf}; +static u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70}; +static u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e}; +static u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f}; +static u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf}; +static u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc}; +static u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e}; +static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02}; +static u8 DLINK_ATHEROS_1[3] = {0x00, 0x1c, 0xf0}; +static u8 DLINK_ATHEROS_2[3] = {0x00, 0x21, 0x91}; +static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94}; +#if defined(RTL8192SU) +static u8 NETGEAR_BROADCOM[3] = {0x00, 0x1f, 0x33}; +#endif +static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4}; +void HTUpdateDefaultSetting(struct rtllib_device* ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + +#ifdef RTL8192CE + pHTInfo->bRDGEnable = 0; +#endif + + pHTInfo->bAcceptAddbaReq = 1; + + pHTInfo->bRegShortGI20MHz= 1; + pHTInfo->bRegShortGI40MHz= 1; + + pHTInfo->bRegBW40MHz = 1; + + if(pHTInfo->bRegBW40MHz) + pHTInfo->bRegSuppCCK = 1; + else + pHTInfo->bRegSuppCCK = true; + + pHTInfo->nAMSDU_MaxSize = 7935UL; + pHTInfo->bAMSDU_Support = 0; + + pHTInfo->bAMPDUEnable = 1; + pHTInfo->AMPDU_Factor = 2; + pHTInfo->MPDU_Density = 0; + + pHTInfo->SelfMimoPs = 3; + if(pHTInfo->SelfMimoPs == 2) + pHTInfo->SelfMimoPs = 3; + ieee->bTxDisableRateFallBack = 0; + ieee->bTxUseDriverAssingedRate = 0; + + ieee->bTxEnableFwCalcDur = 1; + + pHTInfo->bRegRT2RTAggregation = 1; + + pHTInfo->bRegRxReorderEnable = 1; + pHTInfo->RxReorderWinSize = 64; + pHTInfo->RxReorderPendingTime = 30; + +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + pHTInfo->UsbTxAggrNum = 4; +#endif +#ifdef USB_RX_AGGREGATION_SUPPORT +#ifdef RTL8192SU + pHTInfo->UsbRxFwAggrEn = 1; + pHTInfo->UsbRxFwAggrPageNum = 48; + pHTInfo->UsbRxFwAggrPacketNum = 8; + pHTInfo->UsbRxFwAggrTimeout = 4; + pHTInfo->UsbRxPageSize= 128; +#else + pHTInfo->UsbRxFwAggrEn = 1; + pHTInfo->UsbRxFwAggrPageNum = 24; + pHTInfo->UsbRxFwAggrPacketNum = 8; + pHTInfo->UsbRxFwAggrTimeout = 8; +#endif +#endif + + +} +void HTDebugHTCapability(u8* CapIE, u8* TitleString ) +{ + + static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; + PHT_CAPABILITY_ELE pCapELE; + + if(!memcmp(CapIE, EWC11NHTCap, sizeof(EWC11NHTCap))) + { + RTLLIB_DEBUG(RTLLIB_DL_HT, "EWC IE in %s()\n", __FUNCTION__); + pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[4]); + }else + pCapELE = (PHT_CAPABILITY_ELE)(&CapIE[0]); + + RTLLIB_DEBUG(RTLLIB_DL_HT, ". Called by %s\n", TitleString ); + + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tSupported Channel Width = %s\n", (pCapELE->ChlWidth)?"20MHz": "20/40MHz"); + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tSupport Short GI for 20M = %s\n", (pCapELE->ShortGI20Mhz)?"YES": "NO"); + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tSupport Short GI for 40M = %s\n", (pCapELE->ShortGI40Mhz)?"YES": "NO"); + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tSupport TX STBC = %s\n", (pCapELE->TxSTBC)?"YES": "NO"); + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tMax AMSDU Size = %s\n", (pCapELE->MaxAMSDUSize)?"3839": "7935"); + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tSupport CCK in 20/40 mode = %s\n", (pCapELE->DssCCk)?"YES": "NO"); + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tMax AMPDU Factor = %d\n", pCapELE->MaxRxAMPDUFactor); + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tMPDU Density = %d\n", pCapELE->MPDUDensity); + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tMCS Rate Set = [%x][%x][%x][%x][%x]\n", pCapELE->MCS[0],\ + pCapELE->MCS[1], pCapELE->MCS[2], pCapELE->MCS[3], pCapELE->MCS[4]); + return; + +} +void HTDebugHTInfo(u8* InfoIE, u8* TitleString) +{ + + static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34}; + PHT_INFORMATION_ELE pHTInfoEle; + + if(!memcmp(InfoIE, EWC11NHTInfo, sizeof(EWC11NHTInfo))) + { + RTLLIB_DEBUG(RTLLIB_DL_HT, "EWC IE in %s()\n", __FUNCTION__); + pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[4]); + }else + pHTInfoEle = (PHT_INFORMATION_ELE)(&InfoIE[0]); + + + RTLLIB_DEBUG(RTLLIB_DL_HT, ". Called by %s\n", TitleString); + + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tPrimary channel = %d\n", pHTInfoEle->ControlChl); + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tSenondary channel ="); + switch(pHTInfoEle->ExtChlOffset) + { + case 0: + RTLLIB_DEBUG(RTLLIB_DL_HT, "Not Present\n"); + break; + case 1: + RTLLIB_DEBUG(RTLLIB_DL_HT, "Upper channel\n"); + break; + case 2: + RTLLIB_DEBUG(RTLLIB_DL_HT, "Reserved. Eooro!!!\n"); + break; + case 3: + RTLLIB_DEBUG(RTLLIB_DL_HT, "Lower Channel\n"); + break; + } + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tRecommended channel width = %s\n", (pHTInfoEle->RecommemdedTxWidth)?"20Mhz": "40Mhz"); + + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tOperation mode for protection = "); + switch(pHTInfoEle->OptMode) + { + case 0: + RTLLIB_DEBUG(RTLLIB_DL_HT, "No Protection\n"); + break; + case 1: + RTLLIB_DEBUG(RTLLIB_DL_HT, "HT non-member protection mode\n"); + break; + case 2: + RTLLIB_DEBUG(RTLLIB_DL_HT, "Suggest to open protection\n"); + break; + case 3: + RTLLIB_DEBUG(RTLLIB_DL_HT, "HT mixed mode\n"); + break; + } + + RTLLIB_DEBUG(RTLLIB_DL_HT, "\tBasic MCS Rate Set = [%x][%x][%x][%x][%x]\n", pHTInfoEle->BasicMSC[0],\ + pHTInfoEle->BasicMSC[1], pHTInfoEle->BasicMSC[2], pHTInfoEle->BasicMSC[3], pHTInfoEle->BasicMSC[4]); + return; +} + +bool IsHTHalfNmode40Bandwidth(struct rtllib_device* ieee) +{ + bool retValue = false; + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + if(pHTInfo->bCurrentHTSupport == false ) + retValue = false; + else if(pHTInfo->bRegBW40MHz == false) + retValue = false; + else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + retValue = false; + else if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ChlWidth) + retValue = true; + else + retValue = false; + + return retValue; +} + +bool IsHTHalfNmodeSGI(struct rtllib_device* ieee, bool is40MHz) +{ + bool retValue = false; + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + if(pHTInfo->bCurrentHTSupport == false ) + retValue = false; + else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + retValue = false; + else if(is40MHz) + { + if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI40Mhz) + retValue = true; + else + retValue = false; + } + else + { + if(((PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf))->ShortGI20Mhz) + retValue = true; + else + retValue = false; + } + + return retValue; +} + +u16 HTHalfMcsToDataRate(struct rtllib_device* ieee, u8 nMcsRate) +{ + + u8 is40MHz; + u8 isShortGI; + + is40MHz = (IsHTHalfNmode40Bandwidth(ieee))?1:0; + isShortGI = (IsHTHalfNmodeSGI(ieee, is40MHz))? 1:0; + + return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate&0x7f)]; +} + + +u16 HTMcsToDataRate( struct rtllib_device* ieee, u8 nMcsRate) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + u8 is40MHz = (pHTInfo->bCurBW40MHz)?1:0; + u8 isShortGI = (pHTInfo->bCurBW40MHz)? + ((pHTInfo->bCurShortGI40MHz)?1:0): + ((pHTInfo->bCurShortGI20MHz)?1:0); + return MCS_DATA_RATE[is40MHz][isShortGI][(nMcsRate&0x7f)]; +} + +u16 TxCountToDataRate( struct rtllib_device* ieee, u8 nDataRate) +{ + u16 CCKOFDMRate[12] = {0x02 , 0x04 , 0x0b , 0x16 , 0x0c , 0x12 , 0x18 , 0x24 , 0x30 , 0x48 , 0x60 , 0x6c}; + u8 is40MHz = 0; + u8 isShortGI = 0; + + if(nDataRate < 12) + { + return CCKOFDMRate[nDataRate]; + } + else + { + if (nDataRate >= 0x10 && nDataRate <= 0x1f) + { + is40MHz = 0; + isShortGI = 0; + + } + else if(nDataRate >=0x20 && nDataRate <= 0x2f ) + { + is40MHz = 1; + isShortGI = 0; + + } + else if(nDataRate >= 0x30 && nDataRate <= 0x3f ) + { + is40MHz = 0; + isShortGI = 1; + + } + else if(nDataRate >= 0x40 && nDataRate <= 0x4f ) + { + is40MHz = 1; + isShortGI = 1; + + } + return MCS_DATA_RATE[is40MHz][isShortGI][nDataRate&0xf]; + } +} + + + +bool IsHTHalfNmodeAPs(struct rtllib_device* ieee) +{ + bool retValue = false; + struct rtllib_network* net = &ieee->current_network; + +#if defined RTL8192CE || defined RTL8192SE + return false; +#endif + +#if 0 + if(ieee->bHalfNMode == false) + retValue = false; + else +#endif + if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) || + (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) || + (memcmp(net->bssid, PCI_RALINK, 3)==0) || + (memcmp(net->bssid, EDIMAX_RALINK, 3)==0) || + (memcmp(net->bssid, AIRLINK_RALINK, 3)==0) || + (net->ralink_cap_exist)) + retValue = true; + else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) || + (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)|| + (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)|| + (net->broadcom_cap_exist)) + retValue = true; + else if(net->bssht.bdRT2RTAggregation) + retValue = true; + else + retValue = false; + + return retValue; +} + +void HTIOTPeerDetermine(struct rtllib_device* ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + struct rtllib_network* net = &ieee->current_network; + if(net->bssht.bdRT2RTAggregation){ + pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK; + if(net->bssht.RT2RT_HT_Mode & RT_HT_CAP_USE_92SE){ + pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK_92SE; + } + if(net->bssht.RT2RT_HT_Mode & RT_HT_CAP_USE_SOFTAP){ + pHTInfo->IOTPeer = HT_IOT_PEER_92U_SOFTAP; + } + } + else if(net->broadcom_cap_exist) + pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM; + else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) || + (memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)|| + (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)/*|| + (memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) */) + pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM; + else if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) || + (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) || + (memcmp(net->bssid, PCI_RALINK, 3)==0) || + (memcmp(net->bssid, EDIMAX_RALINK, 3)==0) || + (memcmp(net->bssid, AIRLINK_RALINK, 3)==0) || + net->ralink_cap_exist) + pHTInfo->IOTPeer = HT_IOT_PEER_RALINK; + else if((net->atheros_cap_exist )|| + (memcmp(net->bssid, DLINK_ATHEROS_1, 3) == 0)|| + (memcmp(net->bssid, DLINK_ATHEROS_2, 3) == 0)) + pHTInfo->IOTPeer = HT_IOT_PEER_ATHEROS; + else if((memcmp(net->bssid, CISCO_BROADCOM, 3)==0)||net->cisco_cap_exist) + pHTInfo->IOTPeer = HT_IOT_PEER_CISCO; + else if ((memcmp(net->bssid, LINKSYS_MARVELL_4400N, 3) == 0) || + net->marvell_cap_exist) + pHTInfo->IOTPeer = HT_IOT_PEER_MARVELL; + else if (net->airgo_cap_exist) + pHTInfo->IOTPeer = HT_IOT_PEER_AIRGO; + else + pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN; + + RTLLIB_DEBUG(RTLLIB_DL_IOT, "Joseph debug!! IOTPEER: %x\n", pHTInfo->IOTPeer); +} + +u8 HTIOTActIsDisableMCS14(struct rtllib_device* ieee, u8* PeerMacAddr) +{ + u8 ret = 0; +#if 0 +#if (HAL_CODE_BASE==RTL8192 && DEV_BUS_TYPE==USB_INTERFACE) + if((memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3)==0) || + (memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0) + ) + { + ret = 1; + } + + + if(pHTInfo->bCurrentRT2RTAggregation) + { + ret = 1; + } +#endif +#endif + return ret; + } + + +bool HTIOTActIsDisableMCS15(struct rtllib_device* ieee) +{ + bool retValue = false; + +#if defined(RTL8192U) + if(ieee->current_network.bssht.bdBandWidth == HT_CHANNEL_WIDTH_20_40) + retValue = true; + else + retValue = false; +#endif + + + return retValue; +} + +bool HTIOTActIsDisableMCSTwoSpatialStream(struct rtllib_device* ieee) +{ + bool retValue = false; +#ifdef RTL8192U + struct rtllib_network* net = &ieee->current_network; + + if((ieee->pHTInfo->bCurrentHTSupport == true) && (ieee->pairwise_key_type == KEY_TYPE_CCMP)) + { + if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) || + (memcmp(net->bssid, PCI_RALINK, 3)==0) || + (memcmp(net->bssid, EDIMAX_RALINK, 3)==0)) + { + retValue = false; + } + } +#endif +#if defined(RTL8192SU) || defined RTL8192CE + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + if (ieee->rtllib_ap_sec_type && + (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))) + { + if( (pHTInfo->IOTPeer != HT_IOT_PEER_ATHEROS) && + (pHTInfo->IOTPeer != HT_IOT_PEER_UNKNOWN) && + (pHTInfo->IOTPeer != HT_IOT_PEER_MARVELL) && + (pHTInfo->IOTPeer != HT_IOT_PEER_REALTEK_92SE) && + (pHTInfo->IOTPeer != HT_IOT_PEER_RALINK) ) + retValue = true; + } +#elif defined(RTL8192SE) + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + if (ieee->rtllib_ap_sec_type && + (ieee->rtllib_ap_sec_type(ieee)&SEC_ALG_TKIP)) { + if(pHTInfo->IOTPeer == HT_IOT_PEER_RALINK){ + retValue = true; + } + } +#endif + return retValue; +} + +u8 HTIOTActIsDisableEDCATurbo(struct rtllib_device* ieee, u8* PeerMacAddr) +{ + u8 retValue = false; + + return retValue; +#if 0 + if((memcmp(PeerMacAddr, UNKNOWN_BORADCOM, 3)==0)|| + (memcmp(PeerMacAddr, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)|| + (memcmp(PeerMacAddr, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)) + + { + retValue = 1; + } + + return retValue; +#endif +} + + +bool HTIOTActIsEnableBETxOPLimit(struct rtllib_device* ieee) +{ + bool retValue = false; + +#if defined RTL8192SU + if(ieee->mode == IEEE_G) + retValue = true; +#elif defined RTL8192CE + if(ieee->mode == IEEE_G || + (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))) + retValue = true; +#endif + + return retValue; +} + + +u8 HTIOTActIsMgntUseCCK6M(struct rtllib_device* ieee,struct rtllib_network *network) +{ + u8 retValue = 0; + + +#if (defined RTL8192U || defined RTL8192E || defined RTL8190P) + { + if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) + { + retValue = 1; + } + } +#endif + + return retValue; +} + +u8 +HTIOTActWAIOTBroadcom(struct rtllib_device* ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + u8 retValue = false; + u8 boundary=59; + + pHTInfo->bWAIotBroadcom = false; + if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) + { + if(ieee->current_network.bssht.bdBandWidth == HT_CHANNEL_WIDTH_20_40) + { + if(!(pHTInfo->bRegBW40MHz)) + { + if(ieee->current_network.mode != WIRELESS_MODE_B) + { + pHTInfo->bWAIotBroadcom = true; + + if(ieee->b_customer_lenovo_id == true) + boundary = 30; + + if( ieee->current_network.RSSI >= boundary) + retValue = true; + } + }else{ + ; + } + } + } + return retValue; +} + +u8 HTIOTActIsForcedCTS2Self(struct rtllib_device *ieee, struct rtllib_network *network) +{ + u8 retValue = 0; +#if (defined RTL8192SE || defined RTL8192SU || defined RTL8192CE) + if((ieee->pHTInfo->IOTPeer == HT_IOT_PEER_MARVELL) ||(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_ATHEROS) ) +#else + if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_MARVELL) +#endif + { + retValue = 1; + } + + return retValue; +} + +u8 HTIOTActIsForcedRTSCTS(struct rtllib_device *ieee, struct rtllib_network *network) +{ + u8 retValue = 0; +#if defined(RTL8192SE) || defined(RTL8192SU) + if(ieee->pHTInfo->bCurrentHTSupport) + { + if((ieee->pHTInfo->IOTPeer != HT_IOT_PEER_REALTEK)&& + (ieee->pHTInfo->IOTPeer != HT_IOT_PEER_REALTEK_92SE)) + { + if((ieee->pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION) == 0) + retValue = 1; + } + } +#endif + return retValue; +} + +u8 +HTIOTActIsForcedAMSDU8K(struct rtllib_device *ieee, struct rtllib_network *network) +{ + u8 retValue = 0; + + return retValue; +} + +u8 HTIOTActIsCCDFsync(struct rtllib_device *ieee) +{ + u8 retValue = 0; +#if (defined RTL8190P || defined RTL8192U || defined RTL8192SU) + if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) + { + retValue = 1; + } +#endif + return retValue; +} + +u8 +HTIOCActRejcectADDBARequest(struct rtllib_network *network) +{ + u8 retValue = 0; +#if (defined RTL8192SE || defined RTL8192SU || defined RTL8192CE) + { + + + } +#endif + + return retValue; + +} + +u8 + HTIOTActIsEDCABiasRx(struct rtllib_device* ieee,struct rtllib_network *network) +{ + u8 retValue = 0; +#ifdef RTL8192SU + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + { + if(pHTInfo->IOTPeer==HT_IOT_PEER_ATHEROS || + pHTInfo->IOTPeer==HT_IOT_PEER_BROADCOM || + pHTInfo->IOTPeer==HT_IOT_PEER_RALINK) + return 1; + + } +#elif defined RTL8192CE + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + { + if(pHTInfo->IOTPeer==HT_IOT_PEER_ATHEROS || + pHTInfo->IOTPeer==HT_IOT_PEER_RALINK) + return 1; + + } +#elif defined RTL8192SE + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + { + if(ieee->rtllib_ap_sec_type != NULL) + if(ieee->rtllib_ap_sec_type(ieee) == SEC_ALG_CCMP) + if(pHTInfo->IOTPeer==HT_IOT_PEER_RALINK){ + return 1; + } + + } +#endif + return retValue; +} + +u8 +HTIOTActDisableShortGI(struct rtllib_device* ieee,struct rtllib_network *network) +{ + u8 retValue = 0; + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + if(pHTInfo->IOTPeer==HT_IOT_PEER_RALINK) + { + retValue = 1; + } + + return retValue; +} + +u8 +HTIOTActDisableHighPower(struct rtllib_device* ieee,struct rtllib_network *network) +{ + u8 retValue = 0; + +#if (defined RTL8192SE || defined RTL8192SU || defined RTL8192CE) + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + if(pHTInfo->IOTPeer==HT_IOT_PEER_RALINK || + pHTInfo->IOTPeer==HT_IOT_PEER_REALTEK || + pHTInfo->IOTPeer==HT_IOT_PEER_REALTEK_92SE) + { + retValue = 1; + } +#endif + return retValue; +} + +void +HTIOTActDetermineRaFunc(struct rtllib_device* ieee, bool bPeerRx2ss) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + pHTInfo->IOTRaFunc &= HT_IOT_RAFUNC_DISABLE_ALL; + + if(pHTInfo->IOTPeer == HT_IOT_PEER_RALINK && !bPeerRx2ss) + pHTInfo->IOTRaFunc |= HT_IOT_RAFUNC_PEER_1R; + + if(pHTInfo->IOTAction & HT_IOT_ACT_AMSDU_ENABLE) + pHTInfo->IOTRaFunc |= HT_IOT_RAFUNC_TX_AMSDU; + +} + + +u8 +HTIOTActIsDisableTx40MHz(struct rtllib_device* ieee,struct rtllib_network *network) +{ + u8 retValue = 0; + +#if (defined RTL8192SU || defined RTL8192SE || defined RTL8192CE) + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + if( (KEY_TYPE_WEP104 == ieee->pairwise_key_type) || + (KEY_TYPE_WEP40 == ieee->pairwise_key_type) || + (KEY_TYPE_WEP104 == ieee->group_key_type) || + (KEY_TYPE_WEP40 == ieee->group_key_type) || + (KEY_TYPE_TKIP == ieee->pairwise_key_type) ) + { + if((pHTInfo->IOTPeer==HT_IOT_PEER_REALTEK) && (network->bssht.bdSupportHT)) + retValue = 1; + } +#endif + + return retValue; +} + +u8 +HTIOTActIsTxNoAggregation(struct rtllib_device* ieee,struct rtllib_network *network) +{ + u8 retValue = 0; + +#if (defined RTL8192SU || defined RTL8192SE || defined RTL8192CE) + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + if( (KEY_TYPE_WEP104 == ieee->pairwise_key_type) || + (KEY_TYPE_WEP40 == ieee->pairwise_key_type) || + (KEY_TYPE_WEP104 == ieee->group_key_type) || + (KEY_TYPE_WEP40 == ieee->group_key_type) || + (KEY_TYPE_TKIP == ieee->pairwise_key_type) ) + { + if(pHTInfo->IOTPeer==HT_IOT_PEER_REALTEK) + retValue = 1; + } +#endif + + return retValue; +} + + +u8 +HTIOTActIsDisableTx2SS(struct rtllib_device* ieee,struct rtllib_network *network) +{ + u8 retValue = 0; + +#if (defined RTL8192SU || defined RTL8192SE || defined RTL8192CE) + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + if( (KEY_TYPE_WEP104 == ieee->pairwise_key_type) || + (KEY_TYPE_WEP40 == ieee->pairwise_key_type) || + (KEY_TYPE_WEP104 == ieee->group_key_type) || + (KEY_TYPE_WEP40 == ieee->group_key_type) || + (KEY_TYPE_TKIP == ieee->pairwise_key_type) ) + { + if((pHTInfo->IOTPeer==HT_IOT_PEER_REALTEK) && (network->bssht.bdSupportHT)) + retValue = 1; + } +#endif + + return retValue; +} + + +bool HTIOCActIsDisableCckRate(struct rtllib_device* ieee,struct rtllib_network *network) +{ + bool retValue = false; +#if defined(RTL8192SU) + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) + { + if((memcmp(network->bssid, NETGEAR_BROADCOM, 3)==0) + && (network->bssht.bdBandWidth == HT_CHANNEL_WIDTH_20_40)) + return true; + } +#endif + return retValue; +} + +bool HTIOCActAllowPeerAggOnePacket(struct rtllib_device* ieee,struct rtllib_network *network) +{ + bool retValue = false; +#if defined(RTL8192SE) || defined(RTL8192SU) + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + { + if(ieee->VersionID<2) + if(pHTInfo->IOTPeer == HT_IOT_PEER_MARVELL) + return true; + + } +#endif + return retValue; +} + +bool +HTIOTActIsNullDataPowerSaving(struct rtllib_device* ieee,struct rtllib_network *network) +{ + bool retValue = false; +#if defined(RTL8192SE) || defined(RTL8192SU) + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + { + if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) + return true; + + } +#endif + return retValue; +} + +void HTResetIOTSetting( + PRT_HIGH_THROUGHPUT pHTInfo +) +{ + pHTInfo->IOTAction = 0; + pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN; + pHTInfo->IOTRaFunc = 0; +} + + +#ifdef _RTL8192_EXT_PATCH_ +void HTConstructCapabilityElement(struct rtllib_device* ieee, u8* posHTCap, u8* len, u8 IsEncrypt, u8 bIsBcn, bool bAssoc) +#else +void HTConstructCapabilityElement(struct rtllib_device* ieee, u8* posHTCap, u8* len, u8 IsEncrypt, bool bAssoc) +#endif +{ + PRT_HIGH_THROUGHPUT pHT = ieee->pHTInfo; + PHT_CAPABILITY_ELE pCapELE = NULL; + + if ((posHTCap == NULL) || (pHT == NULL)) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "posHTCap or pHTInfo can't be null in HTConstructCapabilityElement()\n"); + return; + } + memset(posHTCap, 0, *len); + + if((bAssoc) && (pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC)) + { + u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; + memcpy(posHTCap, EWC11NHTCap, sizeof(EWC11NHTCap)); + pCapELE = (PHT_CAPABILITY_ELE)&(posHTCap[4]); + *len = 30 + 2; + }else + { + pCapELE = (PHT_CAPABILITY_ELE)posHTCap; + *len = 26 + 2; + } + + pCapELE->AdvCoding = 0; + if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + { + pCapELE->ChlWidth = 0; + } + else + { +#ifdef _RTL8192_EXT_PATCH_ + if(bIsBcn) + pCapELE->ChlWidth = (pHT->bCurBW40MHz?1:0); + else +#endif + pCapELE->ChlWidth = (pHT->bRegBW40MHz?1:0); + } + + pCapELE->MimoPwrSave = pHT->SelfMimoPs; + pCapELE->GreenField = 0; + pCapELE->ShortGI20Mhz = 1; + pCapELE->ShortGI40Mhz = 1; + + pCapELE->TxSTBC = 1; +#if defined RTL8192SE || defined RTL8192CE + pCapELE->TxSTBC = 0; +#endif + pCapELE->RxSTBC = 0; + pCapELE->DelayBA = 0; + pCapELE->MaxAMSDUSize = (MAX_RECEIVE_BUFFER_SIZE>=7935)?1:0; + pCapELE->DssCCk = ((pHT->bRegBW40MHz)?(pHT->bRegSuppCCK?1:0):0); + pCapELE->PSMP = 0; + pCapELE->LSigTxopProtect = 0; + + + RTLLIB_DEBUG(RTLLIB_DL_HT, "TX HT cap/info ele BW=%d MaxAMSDUSize:%d DssCCk:%d\n", pCapELE->ChlWidth, pCapELE->MaxAMSDUSize, pCapELE->DssCCk); + + if( IsEncrypt) + { + pCapELE->MPDUDensity = 7; + pCapELE->MaxRxAMPDUFactor = 2; + } + else + { + pCapELE->MaxRxAMPDUFactor = 3; + pCapELE->MPDUDensity = 0; + } + + memcpy(pCapELE->MCS, ieee->Regdot11HTOperationalRateSet, 16); +#if 0 + if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS15) + pCapELE->MCS[1] &= 0x7f; + + if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS14) + pCapELE->MCS[1] &= 0xbf; + + if(pHT->IOTAction & HT_IOT_ACT_DISABLE_ALL_2SS) + pCapELE->MCS[1] &= 0x00; + + if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + { + int i; + for(i = 1; i< 16; i++) + pCapELE->MCS[i] = 0; + } +#endif + + memset(&pCapELE->ExtHTCapInfo, 0, 2); + + + memset(pCapELE->TxBFCap, 0, 4); + + pCapELE->ASCap = 0; + +#if 0 + if(pHT->ePeerHTSpecVer == HT_SPEC_VER_EWC) + *len = 30 + 2; + else + *len = 26 + 2; +#endif + + if(bAssoc) + { + if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS15) + pCapELE->MCS[1] &= 0x7f; + + if(pHT->IOTAction & HT_IOT_ACT_DISABLE_MCS14) + pCapELE->MCS[1] &= 0xbf; + + if(pHT->IOTAction & HT_IOT_ACT_DISABLE_ALL_2SS) + pCapELE->MCS[1] &= 0x00; + + if(pHT->IOTAction & HT_IOT_ACT_DISABLE_RX_40MHZ_SHORT_GI) + pCapELE->ShortGI40Mhz = 0; + + if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + { + pCapELE->ChlWidth = 0; + + pCapELE->MCS[1] = 0; + } + } + + + + + + return; + +} +void HTConstructInfoElement(struct rtllib_device* ieee, u8* posHTInfo, u8* len, u8 IsEncrypt) +{ + PRT_HIGH_THROUGHPUT pHT = ieee->pHTInfo; + PHT_INFORMATION_ELE pHTInfoEle = (PHT_INFORMATION_ELE)posHTInfo; + if ((posHTInfo == NULL) || (pHTInfoEle == NULL)) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "posHTInfo or pHTInfoEle can't be null in HTConstructInfoElement()\n"); + return; + } + + memset(posHTInfo, 0, *len); +#ifdef _RTL8192_EXT_PATCH_ + if ((ieee->iw_mode == IW_MODE_ADHOC) || (ieee->iw_mode == IW_MODE_MASTER) ||(ieee->iw_mode == IW_MODE_MESH) ) +#else + if ( (ieee->iw_mode == IW_MODE_ADHOC) || (ieee->iw_mode == IW_MODE_MASTER)) +#endif + { + pHTInfoEle->ControlChl = ieee->current_network.channel; +#ifdef _RTL8192_EXT_PATCH_ + if((!ieee->only_mesh) && (ieee->iw_mode == IW_MODE_MESH) && (ieee->state == RTLLIB_LINKED)) + pHTInfoEle->ExtChlOffset = ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT: + ieee->APExtChlOffset); + else if(ieee->iw_mode == IW_MODE_MESH) + pHTInfoEle->ExtChlOffset = ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT: + (ieee->current_mesh_network.channel<=6)? + HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + else +#endif + pHTInfoEle->ExtChlOffset = ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT: + (ieee->current_network.channel<=6)? + HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + pHTInfoEle->RecommemdedTxWidth = pHT->bRegBW40MHz; + pHTInfoEle->RIFS = 0; + pHTInfoEle->PSMPAccessOnly = 0; + pHTInfoEle->SrvIntGranularity = 0; + pHTInfoEle->OptMode = pHT->CurrentOpMode; + pHTInfoEle->NonGFDevPresent = 0; + pHTInfoEle->DualBeacon = 0; + pHTInfoEle->SecondaryBeacon = 0; + pHTInfoEle->LSigTxopProtectFull = 0; + pHTInfoEle->PcoActive = 0; + pHTInfoEle->PcoPhase = 0; + + memset(pHTInfoEle->BasicMSC, 0, 16); + + + *len = 22 + 2; + + } + else + { + *len = 0; + } + return; +} + +void HTConstructRT2RTAggElement(struct rtllib_device* ieee, u8* posRT2RTAgg, u8* len) +{ + if (posRT2RTAgg == NULL) { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "posRT2RTAgg can't be null in HTConstructRT2RTAggElement()\n"); + return; + } + memset(posRT2RTAgg, 0, *len); + *posRT2RTAgg++ = 0x00; + *posRT2RTAgg++ = 0xe0; + *posRT2RTAgg++ = 0x4c; + *posRT2RTAgg++ = 0x02; + *posRT2RTAgg++ = 0x01; + +#ifdef RTL8192CE + *posRT2RTAgg = 0x70; +#else + *posRT2RTAgg = 0x30; +#endif + + if(ieee->bSupportRemoteWakeUp) { + *posRT2RTAgg |= RT_HT_CAP_USE_WOW; + } + + *len = 6 + 2; + + return; + +#ifdef TODO + posRT2RTAgg->Length = 6; +#endif + + + + +} + +u8 HT_PickMCSRate(struct rtllib_device* ieee, u8* pOperateMCS) +{ + u8 i; + if (pOperateMCS == NULL) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "pOperateMCS can't be null in HT_PickMCSRate()\n"); + return false; + } + + switch(ieee->mode) + { + case IEEE_A: + case IEEE_B: + case IEEE_G: + + for(i=0;i<=15;i++){ + pOperateMCS[i] = 0; + } + break; + + case IEEE_N_24G: + case IEEE_N_5G: + + pOperateMCS[0] &=RATE_ADPT_1SS_MASK; + pOperateMCS[1] &=RATE_ADPT_2SS_MASK; + pOperateMCS[3] &=RATE_ADPT_MCS32_MASK; + break; + + default: + + break; + + } + + return true; +} + +u8 HTGetHighestMCSRate(struct rtllib_device* ieee, u8* pMCSRateSet, u8* pMCSFilter) +{ + u8 i, j; + u8 bitMap; + u8 mcsRate = 0; + u8 availableMcsRate[16]; + if (pMCSRateSet == NULL || pMCSFilter == NULL) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "pMCSRateSet or pMCSFilter can't be null in HTGetHighestMCSRate()\n"); + return false; + } + for(i=0; i<16; i++) + availableMcsRate[i] = pMCSRateSet[i] & pMCSFilter[i]; + + for(i = 0; i < 16; i++) + { + if(availableMcsRate[i] != 0) + break; + } + if(i == 16) + return false; + + for(i = 0; i < 16; i++) + { + if(availableMcsRate[i] != 0) + { + bitMap = availableMcsRate[i]; + for(j = 0; j < 8; j++) + { + if((bitMap%2) != 0) + { + if(HTMcsToDataRate(ieee, (8*i+j)) > HTMcsToDataRate(ieee, mcsRate)) + mcsRate = (8*i+j); + } + bitMap = bitMap>>1; + } + } + } + return (mcsRate|0x80); +} + +u8 HTFilterMCSRate( struct rtllib_device* ieee, u8* pSupportMCS, u8* pOperateMCS) +{ + + u8 i=0; + + for(i=0;i<=15;i++){ + pOperateMCS[i] = ieee->Regdot11TxHTOperationalRateSet[i]&pSupportMCS[i]; + } + + + + HT_PickMCSRate(ieee, pOperateMCS); + + if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + pOperateMCS[1] = 0; + + for(i=2; i<=15; i++) + pOperateMCS[i] = 0; + + return true; +} +void HTSetConnectBwMode(struct rtllib_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset); +void HTOnAssocRsp(struct rtllib_device *ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + PHT_CAPABILITY_ELE pPeerHTCap = NULL; + PHT_INFORMATION_ELE pPeerHTInfo = NULL; + u16 nMaxAMSDUSize = 0; + u8* pMcsFilter = NULL; + + static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; + static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34}; + + if( pHTInfo->bCurrentHTSupport == false ) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "<=== HTOnAssocRsp(): HT_DISABLE\n"); + return; + } + RTLLIB_DEBUG(RTLLIB_DL_HT, "===> HTOnAssocRsp_wq(): HT_ENABLE\n"); + + if(!memcmp(pHTInfo->PeerHTCapBuf,EWC11NHTCap, sizeof(EWC11NHTCap))) + pPeerHTCap = (PHT_CAPABILITY_ELE)(&pHTInfo->PeerHTCapBuf[4]); + else + pPeerHTCap = (PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf); + + if(!memcmp(pHTInfo->PeerHTInfoBuf, EWC11NHTInfo, sizeof(EWC11NHTInfo))) + pPeerHTInfo = (PHT_INFORMATION_ELE)(&pHTInfo->PeerHTInfoBuf[4]); + else + pPeerHTInfo = (PHT_INFORMATION_ELE)(pHTInfo->PeerHTInfoBuf); + +#ifdef _RTL8192_EXT_PATCH_ + ieee->APExtChlOffset = (HT_EXTCHNL_OFFSET)(pPeerHTInfo->ExtChlOffset); +#endif + RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA|RTLLIB_DL_HT, pPeerHTCap, sizeof(HT_CAPABILITY_ELE)); + HTSetConnectBwMode(ieee, (HT_CHANNEL_WIDTH)(pPeerHTCap->ChlWidth), (HT_EXTCHNL_OFFSET)(pPeerHTInfo->ExtChlOffset)); +#if defined RTL8192SE || defined RTL8192SU || defined RTL8192CE + if(pHTInfo->bCurBW40MHz == true) +#endif + pHTInfo->bCurTxBW40MHz = ((pPeerHTInfo->RecommemdedTxWidth == 1)?true:false); + + pHTInfo->bCurShortGI20MHz= + ((pHTInfo->bRegShortGI20MHz)?((pPeerHTCap->ShortGI20Mhz==1)?true:false):false); + pHTInfo->bCurShortGI40MHz= + ((pHTInfo->bRegShortGI40MHz)?((pPeerHTCap->ShortGI40Mhz==1)?true:false):false); + + pHTInfo->bCurSuppCCK = + ((pHTInfo->bRegSuppCCK)?((pPeerHTCap->DssCCk==1)?true:false):false); + + + pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support; + + nMaxAMSDUSize = (pPeerHTCap->MaxAMSDUSize==0)?3839:7935; + + if(pHTInfo->nAMSDU_MaxSize > nMaxAMSDUSize ) + pHTInfo->nCurrent_AMSDU_MaxSize = nMaxAMSDUSize; + else + pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize; + + pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable; + if (ieee->rtllib_ap_sec_type && + (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))){ + if( (pHTInfo->IOTPeer== HT_IOT_PEER_ATHEROS) || + (pHTInfo->IOTPeer == HT_IOT_PEER_UNKNOWN) ) + pHTInfo->bCurrentAMPDUEnable = false; + } + + if(!pHTInfo->bRegRT2RTAggregation) + { + if(pHTInfo->AMPDU_Factor > pPeerHTCap->MaxRxAMPDUFactor) + pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor; + else + pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor; + + } else { +#if 0 + osTmp= PacketGetElement( asocpdu, EID_Vendor, OUI_SUB_REALTEK_AGG, OUI_SUBTYPE_DONT_CARE); + if(osTmp.Length >= 5) +#endif + if (ieee->current_network.bssht.bdRT2RTAggregation) + { + if( ieee->pairwise_key_type != KEY_TYPE_NA) + pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor; + else + pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_64K; + }else + { + if(pPeerHTCap->MaxRxAMPDUFactor < HT_AGG_SIZE_32K) + pHTInfo->CurrentAMPDUFactor = pPeerHTCap->MaxRxAMPDUFactor; + else + pHTInfo->CurrentAMPDUFactor = HT_AGG_SIZE_32K; + } + } +#ifdef _RTL8192_EXT_PATCH_ + if (ieee->iw_mode == IW_MODE_MESH) { + if(ieee->rtllib_ap_sec_type && (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_CCMP))){ + pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor = 0; + printk("%s: In MSTA mode, AP is encrypted with AES, force CurrentAMPDUFactor to 8K!\n", __func__); + } + } +#endif + +#if 0 + if(pHTInfo->MPDU_Density > pPeerHTCap->MPDUDensity) + pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density; + else + pHTInfo->CurrentMPDUDensity = pPeerHTCap->MPDUDensity; + if(ieee->pairwise_key_type != KEY_TYPE_NA ) + pHTInfo->CurrentMPDUDensity = 7; +#else + if(pHTInfo->MPDU_Density > pPeerHTCap->MPDUDensity) + pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density; + else + pHTInfo->CurrentMPDUDensity = pPeerHTCap->MPDUDensity; +#endif +#if (defined RTL8192SE || defined RTL8192SU || defined RTL8192CE) + if(ieee->SetHwRegHandler != NULL) { + ieee->SetHwRegHandler( ieee->dev, HW_VAR_SHORTGI_DENSITY, (u8*)(&ieee->MaxMssDensity)); + ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_FACTOR, &pHTInfo->CurrentAMPDUFactor); + ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_MIN_SPACE, &pHTInfo->CurrentMPDUDensity); + } +#elif defined RTL8192CE + if(ieee->SetHwRegHandler != NULL) { + ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_FACTOR, &pHTInfo->CurrentAMPDUFactor); + ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_MIN_SPACE, &pHTInfo->CurrentMPDUDensity); + } +#endif +#ifndef RTL8190P + if(pHTInfo->IOTAction & HT_IOT_ACT_TX_USE_AMSDU_8K) +#else + if( 0 ) +#endif + { + pHTInfo->bCurrentAMPDUEnable = false; + pHTInfo->ForcedAMSDUMode = HT_AGG_FORCE_ENABLE; + pHTInfo->ForcedAMSDUMaxSize = 7935; + } + pHTInfo->bCurRxReorderEnable = pHTInfo->bRegRxReorderEnable; +#ifdef _RTL8192_EXT_PATCH_ + if (ieee->iw_mode == IW_MODE_MESH) { + if(ieee->rtllib_ap_sec_type && (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_CCMP))){ + pHTInfo->bCurRxReorderEnable = pHTInfo->bRegRxReorderEnable = 0; + printk("%s: In MSTA mode, AP is encrypted with AES, force closing RxReorder!\n", __func__); + } + } +#endif + + + if(pPeerHTCap->MCS[0] == 0) + pPeerHTCap->MCS[0] = 0xff; + + HTIOTActDetermineRaFunc(ieee, ((pPeerHTCap->MCS[1])!=0)); + + HTFilterMCSRate(ieee, pPeerHTCap->MCS, ieee->dot11HTOperationalRateSet); + + pHTInfo->PeerMimoPs = pPeerHTCap->MimoPwrSave; + if(pHTInfo->PeerMimoPs == MIMO_PS_STATIC) + pMcsFilter = MCS_FILTER_1SS; + else + pMcsFilter = MCS_FILTER_ALL; + ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, ieee->dot11HTOperationalRateSet, pMcsFilter); + ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate; + + pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode; + +} + +void HTSetConnectBwModeCallback(struct rtllib_device* ieee); +void HTInitializeHTInfo(struct rtllib_device* ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + RTLLIB_DEBUG(RTLLIB_DL_HT, "===========>%s()\n", __FUNCTION__); + pHTInfo->bCurrentHTSupport = false; + + pHTInfo->bCurBW40MHz = false; + pHTInfo->bCurTxBW40MHz = false; + + pHTInfo->bCurShortGI20MHz = false; + pHTInfo->bCurShortGI40MHz = false; + pHTInfo->bForcedShortGI = false; + + pHTInfo->bCurSuppCCK = true; + + pHTInfo->bCurrent_AMSDU_Support = false; + pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize; +#ifdef _RTL8192_EXT_PATCH_ + pHTInfo->bCurrent_Mesh_AMSDU_Support = true; +#endif + pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density; + pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor; + + memset((void*)(&(pHTInfo->SelfHTCap)), 0, sizeof(pHTInfo->SelfHTCap)); + memset((void*)(&(pHTInfo->SelfHTInfo)), 0, sizeof(pHTInfo->SelfHTInfo)); + memset((void*)(&(pHTInfo->PeerHTCapBuf)), 0, sizeof(pHTInfo->PeerHTCapBuf)); + memset((void*)(&(pHTInfo->PeerHTInfoBuf)), 0, sizeof(pHTInfo->PeerHTInfoBuf)); + + pHTInfo->bSwBwInProgress = false; + pHTInfo->ChnlOp = CHNLOP_NONE; + + pHTInfo->ePeerHTSpecVer = HT_SPEC_VER_IEEE; + + pHTInfo->bCurrentRT2RTAggregation = false; + pHTInfo->bCurrentRT2RTLongSlotTime = false; + pHTInfo->RT2RT_HT_Mode = (RT_HT_CAPBILITY)0; + + pHTInfo->IOTPeer = 0; + pHTInfo->IOTAction = 0; + pHTInfo->IOTRaFunc = 0; + + { + u8* RegHTSuppRateSets = &(ieee->RegHTSuppRateSet[0]); + RegHTSuppRateSets[0] = 0xFF; + RegHTSuppRateSets[1] = 0xFF; + RegHTSuppRateSets[4] = 0x01; + } +} +void HTInitializeBssDesc(PBSS_HT pBssHT) +{ + + pBssHT->bdSupportHT = false; + memset(pBssHT->bdHTCapBuf, 0, sizeof(pBssHT->bdHTCapBuf)); + pBssHT->bdHTCapLen = 0; + memset(pBssHT->bdHTInfoBuf, 0, sizeof(pBssHT->bdHTInfoBuf)); + pBssHT->bdHTInfoLen = 0; + + pBssHT->bdHTSpecVer= HT_SPEC_VER_IEEE; + + pBssHT->bdRT2RTAggregation = false; + pBssHT->bdRT2RTLongSlotTime = false; + pBssHT->RT2RT_HT_Mode = (RT_HT_CAPBILITY)0; +} + +void HTResetSelfAndSavePeerSetting(struct rtllib_device* ieee, struct rtllib_network * pNetwork) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + u8 bIOTAction = 0; + + RTLLIB_DEBUG(RTLLIB_DL_HT, "==============>%s()\n", __FUNCTION__); + /*unmark bEnableHT flag here is the same reason why unmarked in function rtllib_softmac_new_net. WB 2008.09.10*/ + if (pNetwork->bssht.bdSupportHT) + { + pHTInfo->bCurrentHTSupport = true; + pHTInfo->ePeerHTSpecVer = pNetwork->bssht.bdHTSpecVer; + + if(pNetwork->bssht.bdHTCapLen > 0 && pNetwork->bssht.bdHTCapLen <= sizeof(pHTInfo->PeerHTCapBuf)) + memcpy(pHTInfo->PeerHTCapBuf, pNetwork->bssht.bdHTCapBuf, pNetwork->bssht.bdHTCapLen); + + if(pNetwork->bssht.bdHTInfoLen > 0 && pNetwork->bssht.bdHTInfoLen <= sizeof(pHTInfo->PeerHTInfoBuf)) + memcpy(pHTInfo->PeerHTInfoBuf, pNetwork->bssht.bdHTInfoBuf, pNetwork->bssht.bdHTInfoLen); + + if(pHTInfo->bRegRT2RTAggregation) + { + pHTInfo->bCurrentRT2RTAggregation = pNetwork->bssht.bdRT2RTAggregation; + pHTInfo->bCurrentRT2RTLongSlotTime = pNetwork->bssht.bdRT2RTLongSlotTime; + pHTInfo->RT2RT_HT_Mode = pNetwork->bssht.RT2RT_HT_Mode; + } + else + { + pHTInfo->bCurrentRT2RTAggregation = false; + pHTInfo->bCurrentRT2RTLongSlotTime = false; + pHTInfo->RT2RT_HT_Mode = (RT_HT_CAPBILITY)0; + } + + HTIOTPeerDetermine(ieee); + + pHTInfo->IOTAction = 0; + bIOTAction = HTIOTActIsDisableMCS14(ieee, pNetwork->bssid); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS14; + + bIOTAction = HTIOTActIsDisableMCS15(ieee); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS15; + + bIOTAction = HTIOTActIsDisableMCSTwoSpatialStream(ieee); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_ALL_2SS; + + + bIOTAction = HTIOTActIsDisableEDCATurbo(ieee, pNetwork->bssid); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_EDCA_TURBO; + +#if defined(RTL8190P) || defined(RTL8192E) || defined(RTL8192U) + bIOTAction = HTIOTActIsMgntUseCCK6M(ieee,pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_MGNT_USE_CCK_6M; +#elif defined(RTL8192SE) || defined(RTL8192SU) || defined RTL8192CE + bIOTAction = HTIOTActWAIOTBroadcom(ieee); + if(bIOTAction) + { + pHTInfo->IOTAction |= HT_IOT_ACT_WA_IOT_Broadcom; + } +#endif + bIOTAction = HTIOTActIsCCDFsync(ieee); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_CDD_FSYNC; +#if defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE + bIOTAction = HTIOTActIsForcedCTS2Self(ieee,pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF; + + + bIOTAction = HTIOTActIsEnableBETxOPLimit(ieee); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_ENABLE_BE_TXOP; + +#if defined(RTL8192SU) + bIOTAction = HTIOCActRejcectADDBARequest(pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_REJECT_ADDBA_REQ; +#endif + + bIOTAction = HTIOCActAllowPeerAggOnePacket(ieee, pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT; + + bIOTAction = HTIOTActIsEDCABiasRx(ieee, pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_EDCA_BIAS_ON_RX; + +#if defined(RTL8192SU) + bIOTAction = HTIOCActIsDisableCckRate(ieee, pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_CCK_RATE; +#endif + bIOTAction = HTIOTActDisableShortGI(ieee, pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_SHORT_GI; + + bIOTAction = HTIOTActDisableHighPower(ieee, pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_HIGH_POWER; + + + bIOTAction = HTIOTActIsForcedAMSDU8K(ieee, pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_TX_USE_AMSDU_8K; + +#if defined(RTL8192SU) + bIOTAction = HTIOTActIsTxNoAggregation(ieee, pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_TX_NO_AGGREGATION; + + bIOTAction = HTIOTActIsDisableTx40MHz(ieee, pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_TX_40_MHZ; + + bIOTAction = HTIOTActIsDisableTx2SS(ieee, pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_TX_2SS; +#endif + + bIOTAction = HTIOTActIsForcedRTSCTS(ieee, pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_RTS; + + bIOTAction = HTIOTActIsNullDataPowerSaving(ieee, pNetwork); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_NULL_DATA_POWER_SAVING; +#endif + +#if 0 + bIOTAction = HTIOTActDisableRx40MHzShortGI(ieee, pBssDesc); + if(bIOTAction) + pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_RX_40MHZ_SHORT_GI; + +#endif + } + else + { + pHTInfo->bCurrentHTSupport = false; + pHTInfo->bCurrentRT2RTAggregation = false; + pHTInfo->bCurrentRT2RTLongSlotTime = false; + pHTInfo->RT2RT_HT_Mode = (RT_HT_CAPBILITY)0; + + pHTInfo->IOTAction = 0; + pHTInfo->IOTRaFunc = 0; + } + +} + +void HTUpdateSelfAndPeerSetting(struct rtllib_device* ieee, struct rtllib_network * pNetwork) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + PHT_INFORMATION_ELE pPeerHTInfo = (PHT_INFORMATION_ELE)pNetwork->bssht.bdHTInfoBuf; + + if(pHTInfo->bCurrentHTSupport) + { + if(pNetwork->bssht.bdHTInfoLen != 0) + pHTInfo->CurrentOpMode = pPeerHTInfo->OptMode; + + } +} + +void HTUseDefaultSetting(struct rtllib_device* ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + +#ifdef _RTL8192_EXT_PATCH_ + ieee->current_mesh_network.qos_data.supported = 1; + ieee->current_mesh_network.qos_data.active = ieee->current_mesh_network.qos_data.supported; +#endif + if(pHTInfo->bEnableHT) + { + pHTInfo->bCurrentHTSupport = true; + pHTInfo->bCurSuppCCK = pHTInfo->bRegSuppCCK; + +#ifdef _RTL8192_EXT_PATCH_ + if(!((ieee->iw_mode == IW_MODE_MESH) && ieee->proto_started && (ieee->state == RTLLIB_LINKED))) + pHTInfo->bCurBW40MHz = pHTInfo->bRegBW40MHz; +#else + pHTInfo->bCurBW40MHz = pHTInfo->bRegBW40MHz; +#endif + pHTInfo->bCurShortGI20MHz= pHTInfo->bRegShortGI20MHz; + + pHTInfo->bCurShortGI40MHz= pHTInfo->bRegShortGI40MHz; +#ifdef _RTL8192_EXT_PATCH_ + ieee->current_mesh_network.qos_data.supported = 1; + ieee->current_mesh_network.qos_data.active = ieee->current_mesh_network.qos_data.supported; +#endif + + if(ieee->iw_mode == IW_MODE_ADHOC) + { + ieee->current_network.qos_data.active = ieee->current_network.qos_data.supported; + } +#ifdef ENABLE_AMSDU + if(ieee->iw_mode == IW_MODE_ADHOC) + { + pHTInfo->bCurrent_AMSDU_Support = 1; + } +#ifdef _RTL8192_EXT_PATCH_ + else if(ieee->iw_mode == IW_MODE_MESH) + { +#ifdef COMPATIBLE_WITH_RALINK_MESH + pHTInfo->bCurrent_Mesh_AMSDU_Support = 0; +#else + pHTInfo->bCurrent_Mesh_AMSDU_Support = 1; +#endif + pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support; + } +#endif + else + pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support; +#else + pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support; +#endif + pHTInfo->nCurrent_AMSDU_MaxSize = pHTInfo->nAMSDU_MaxSize; + +#ifdef ENABLE_AMSDU + if(ieee->iw_mode == IW_MODE_ADHOC) + pHTInfo->bCurrentAMPDUEnable = 0; +#ifdef _RTL8192_EXT_PATCH_ + else if(ieee->iw_mode == IW_MODE_MESH) + { +#ifdef COMPATIBLE_WITH_RALINK_MESH + pHTInfo->bCurrentMeshAMPDUEnable = 1; +#else + pHTInfo->bCurrentMeshAMPDUEnable = 0; +#endif + pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable; + } +#endif + else + pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable; +#else + pHTInfo->bCurrentAMPDUEnable = pHTInfo->bAMPDUEnable; +#endif + pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor; + + pHTInfo->CurrentMPDUDensity = pHTInfo->CurrentMPDUDensity; + + + HTFilterMCSRate(ieee, ieee->Regdot11TxHTOperationalRateSet, ieee->dot11HTOperationalRateSet); +#ifdef TODO + Adapter->HalFunc.InitHalRATRTableHandler( Adapter, &pMgntInfo->dot11OperationalRateSet, pMgntInfo->dot11HTOperationalRateSet); +#endif + ieee->HTHighestOperaRate = HTGetHighestMCSRate(ieee, ieee->dot11HTOperationalRateSet, MCS_FILTER_ALL); + ieee->HTCurrentOperaRate = ieee->HTHighestOperaRate; + +#if (defined RTL8192SE || defined RTL8192SU || defined RTL8192CE) + if(ieee->SetHwRegHandler != NULL) { + ieee->SetHwRegHandler( ieee->dev, HW_VAR_SHORTGI_DENSITY, (u8*)(&ieee->MaxMssDensity)); + ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_FACTOR, &pHTInfo->CurrentAMPDUFactor); + ieee->SetHwRegHandler(ieee->dev, HW_VAR_AMPDU_MIN_SPACE, &pHTInfo->CurrentMPDUDensity); + } +#endif + + } + else + { + pHTInfo->bCurrentHTSupport = false; + } + return; +} +u8 HTCCheck(struct rtllib_device* ieee, u8* pFrame) +{ + if(ieee->pHTInfo->bCurrentHTSupport) + { + if( (IsQoSDataFrame(pFrame) && Frame_Order(pFrame)) == 1) + { + RTLLIB_DEBUG(RTLLIB_DL_HT, "HT CONTROL FILED EXIST!!\n"); + return true; + } + } + return false; +} + +void HTSetConnectBwMode(struct rtllib_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + if(pHTInfo->bRegBW40MHz == false) + return; + + if(ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + Bandwidth=HT_CHANNEL_WIDTH_20; + + + if(pHTInfo->bSwBwInProgress) { + printk("%s: bSwBwInProgress!!\n", __FUNCTION__); + return; + } + if(Bandwidth==HT_CHANNEL_WIDTH_20_40) + { + if(ieee->current_network.channel<2 && Offset==HT_EXTCHNL_OFFSET_LOWER) + Offset = HT_EXTCHNL_OFFSET_NO_EXT; + if(Offset==HT_EXTCHNL_OFFSET_UPPER || Offset==HT_EXTCHNL_OFFSET_LOWER) { + pHTInfo->bCurBW40MHz = true; + pHTInfo->CurSTAExtChnlOffset = Offset; + } else { + pHTInfo->bCurBW40MHz = false; + pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT; + } + } else { + pHTInfo->bCurBW40MHz = false; + pHTInfo->CurSTAExtChnlOffset = HT_EXTCHNL_OFFSET_NO_EXT; + } + + printk("%s():pHTInfo->bCurBW40MHz:%x\n", __func__, pHTInfo->bCurBW40MHz); + + pHTInfo->bSwBwInProgress = true; + + HTSetConnectBwModeCallback(ieee); + +} + +void HTSetConnectBwModeCallback(struct rtllib_device* ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + RTLLIB_DEBUG(RTLLIB_DL_HT, "======>%s()\n", __FUNCTION__); + if(pHTInfo->bCurBW40MHz) + { + if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_UPPER) + ieee->set_chan(ieee->dev, ieee->current_network.channel+2); + else if(pHTInfo->CurSTAExtChnlOffset==HT_EXTCHNL_OFFSET_LOWER) + ieee->set_chan(ieee->dev, ieee->current_network.channel-2); + else + ieee->set_chan(ieee->dev, ieee->current_network.channel); + + ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20_40, pHTInfo->CurSTAExtChnlOffset); + } else { + ieee->set_chan(ieee->dev, ieee->current_network.channel); + ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + } + + pHTInfo->bSwBwInProgress = false; +} + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(HTUpdateSelfAndPeerSetting); +EXPORT_SYMBOL_RSL(HTFilterMCSRate); +EXPORT_SYMBOL_RSL(HTGetHighestMCSRate); +EXPORT_SYMBOL_RSL(MCS_FILTER_ALL); +EXPORT_SYMBOL_RSL(MCS_FILTER_1SS); +#ifdef _RTL8192_EXT_PATCH_ +EXPORT_SYMBOL_RSL(HTSetConnectBwMode); +EXPORT_SYMBOL_RSL(HTConstructCapabilityElement); +EXPORT_SYMBOL_RSL(HTConstructRT2RTAggElement); +EXPORT_SYMBOL_RSL(HTUseDefaultSetting); +EXPORT_SYMBOL_RSL(HTConstructInfoElement); +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtl819x_Qos.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtl819x_Qos.h @@ -0,0 +1,722 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef __INC_QOS_TYPE_H +#define __INC_QOS_TYPE_H + +#include "rtllib_endianfree.h" + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#ifndef RTK_DMP_PLATFORM +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) +#ifndef bool +typedef enum{false = 0, true} bool; +#endif +#endif +#endif + +typedef union _QOS_TSINFO{ + u8 charData[3]; + struct { + u8 ucTrafficType:1; + u8 ucTSID:4; + u8 ucDirection:2; + u8 ucAccessPolicy:2; + u8 ucAggregation:1; + u8 ucPSB:1; + u8 ucUP:3; + u8 ucTSInfoAckPolicy:2; + u8 ucSchedule:1; + u8 ucReserved:7; + }field; +}QOS_TSINFO, *PQOS_TSINFO; +typedef union _TSPEC_BODY{ + u8 charData[55]; + + struct + { + QOS_TSINFO TSInfo; + u16 NominalMSDUsize; + u16 MaxMSDUsize; + u32 MinServiceItv; + u32 MaxServiceItv; + u32 InactivityItv; + u32 SuspenItv; + u32 ServiceStartTime; + u32 MinDataRate; + u32 MeanDataRate; + u32 PeakDataRate; + u32 MaxBurstSize; + u32 DelayBound; + u32 MinPhyRate; + u16 SurplusBandwidthAllowance; + u16 MediumTime; + } f; +}TSPEC_BODY, *PTSPEC_BODY; + +typedef struct _WMM_TSPEC{ + u8 ID; + u8 Length; + u8 OUI[3]; + u8 OUI_Type; + u8 OUI_SubType; + u8 Version; + TSPEC_BODY Body; +} WMM_TSPEC, *PWMM_TSPEC; + +typedef struct _OCTET_STRING{ + u8 *Octet; + u16 Length; +}OCTET_STRING, *POCTET_STRING; +#define MAX_WMMELE_LENGTH 64 + +typedef u32 QOS_MODE, *PQOS_MODE; +#define QOS_DISABLE 0 +#define QOS_WMM 1 +#define QOS_WMMSA 2 +#define QOS_EDCA 4 +#define QOS_HCCA 8 +#define QOS_WMM_UAPSD 16 + +#define WMM_PARAM_ELE_BODY_LEN 18 + +#define MAX_STA_TS_COUNT 16 +#define MAX_AP_TS_COUNT 32 +#define QOS_TSTREAM_KEY_SIZE 13 + +#define WMM_ACTION_CATEGORY_CODE 17 +#define WMM_PARAM_ELE_BODY_LEN 18 + +#define MAX_TSPEC_TSID 15 +#define SESSION_REJECT_TSID 0xfe +#define DEFAULT_TSID 0xff + +#define ADDTS_TIME_SLOT 100 + +#define ACM_TIMEOUT 1000 +#define SESSION_REJECT_TIMEOUT 60000 + +typedef enum _ACK_POLICY{ + eAckPlc0_ACK = 0x00, + eAckPlc1_NoACK = 0x01, +}ACK_POLICY,*PACK_POLICY; + + +#if 0 +#define FRAME_OFFSET_QOS_CTRL(_pStart) (24 + 6*GET_80211_HDR_FROM_DS(_pStart)*GET_80211_HDR_TO_DS(_pStart)) + +#define GET_QOS_CTRL(_pStart) ReadEF2Byte((pu1Byte)(_pStart) + FRAME_OFFSET_QOS_CTRL(_pStart)) +#define SET_QOS_CTRL(_pStart, _value) WriteEF2Byte((pu1Byte)(_pStart) + FRAME_OFFSET_QOS_CTRL(_pStart), _value) + +#define GET_QOS_CTRL_WMM_UP(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 0, 3)) +#define SET_QOS_CTRL_WMM_UP(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 0, 3, (u1Byte)(_value)) + +#define GET_QOS_CTRL_WMM_EOSP(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 4, 1)) +#define SET_QOS_CTRL_WMM_EOSP(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 4, 1, (u1Byte)(_value)) + +#define GET_QOS_CTRL_WMM_ACK_POLICY(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 5, 2)) +#define SET_QOS_CTRL_WMM_ACK_POLICY(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 5, 2, (u1Byte)(_value)) + +#define GET_QOS_CTRL_STA_DATA_TID(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 0, 4)) +#define SET_QOS_CTRL_STA_DATA_TID(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 0, 4, (u1Byte)(_value)) + +#define GET_QOS_CTRL_STA_DATA_QSIZE_FLAG(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 4, 1)) +#define SET_QOS_CTRL_STA_DATA_QSIZE_FLAG(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 4, 1, (u1Byte)(_value)) + +#define GET_QOS_CTRL_STA_DATA_ACK_POLICY(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 5, 2)) +#define SET_QOS_CTRL_STA_DATA_ACK_POLICY(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 5, 2, (u1Byte)(_value)) + +#define GET_QOS_CTRL_STA_DATA_USRSVD(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 7, 1)) +#define SET_QOS_CTRL_STA_DATA_USRSVD(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 7, 1, (u1Byte)(_value)) + +#define GET_QOS_CTRL_STA_DATA_TXOP(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 8, 8)) +#define SET_QOS_CTRL_STA_DATA_TXOP(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 8, 8, (u1Byte)(_value)) + +#define GET_QOS_CTRL_STA_DATA_QSIZE(_pStart) GET_QOS_CTRL_STA_DATA_TXOP(_pStart) +#define SET_QOS_CTRL_STA_DATA_QSIZE(_pStart, _value) SET_QOS_CTRL_STA_DATA_TXOP(_pStart) + +#define GET_QOS_CTRL_HC_DATA_TID(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 0, 4)) +#define SET_QOS_CTRL_HC_DATA_TID(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 0, 4, (u1Byte)(_value)) + +#define GET_QOS_CTRL_HC_DATA_EOSP(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 4, 1)) +#define SET_QOS_CTRL_HC_DATA_EOSP(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 4, 1, (u1Byte)(_value)) + +#define GET_QOS_CTRL_HC_DATA_ACK_POLICY(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 5, 2)) +#define SET_QOS_CTRL_HC_DATA_ACK_POLICY(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 5, 2, (u1Byte)(_value)) + +#define GET_QOS_CTRL_HC_DATA_PS_BUFSTATE(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 8, 8)) +#define SET_QOS_CTRL_HC_DATA_PS_BUFSTATE(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 8, 8, (u1Byte)(_value)) + +#define GET_QOS_CTRL_HC_CFP_TID(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 0, 4)) +#define SET_QOS_CTRL_HC_CFP_TID(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 0, 4, (u1Byte)(_value)) + +#define GET_QOS_CTRL_HC_CFP_EOSP(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 4, 1)) +#define SET_QOS_CTRL_HC_CFP_EOSP(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 4, 1, (u1Byte)(_value)) + +#define GET_QOS_CTRL_HC_CFP_ACK_POLICY(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 5, 2)) +#define SET_QOS_CTRL_HC_CFP_ACK_POLICY(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 5, 2, (u1Byte)(_value)) + +#define GET_QOS_CTRL_HC_CFP_USRSVD(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 7, 1)) +#define SET_QOS_CTRL_HC_CFP_USRSVD(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 7, 1, (u1Byte)(_value)) + +#define GET_QOS_CTRL_HC_CFP_TXOP_LIMIT(_pStart) ((u1Byte)LE_BITS_TO_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 8, 8)) +#define SET_QOS_CTRL_HC_CFP_TXOP_LIMIT(_pStart, _value) SET_BITS_TO_LE_2BYTE((pu1Byte)(_pStart)+FRAME_OFFSET_QOS_CTRL(_pStart), 8, 8, (u1Byte)(_value)) +#endif + + + +#define SET_WMM_QOS_INFO_FIELD(_pStart, _val) WriteEF1Byte(_pStart, _val) + +#define GET_WMM_QOS_INFO_FIELD_PARAMETERSET_COUNT(_pStart) LE_BITS_TO_1BYTE(_pStart, 0, 4) +#define SET_WMM_QOS_INFO_FIELD_PARAMETERSET_COUNT(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 0, 4, _val) + +#define GET_WMM_QOS_INFO_FIELD_AP_UAPSD(_pStart) LE_BITS_TO_1BYTE(_pStart, 7, 1) +#define SET_WMM_QOS_INFO_FIELD_AP_UAPSD(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 7, 1, _val) + +#define GET_WMM_QOS_INFO_FIELD_STA_AC_VO_UAPSD(_pStart) LE_BITS_TO_1BYTE(_pStart, 0, 1) +#define SET_WMM_QOS_INFO_FIELD_STA_AC_VO_UAPSD(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 0, 1, _val) + +#define GET_WMM_QOS_INFO_FIELD_STA_AC_VI_UAPSD(_pStart) LE_BITS_TO_1BYTE(_pStart, 1, 1) +#define SET_WMM_QOS_INFO_FIELD_STA_AC_VI_UAPSD(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 1, 1, _val) + +#define GET_WMM_QOS_INFO_FIELD_STA_AC_BE_UAPSD(_pStart) LE_BITS_TO_1BYTE(_pStart, 2, 1) +#define SET_WMM_QOS_INFO_FIELD_STA_AC_BE_UAPSD(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 2, 1, _val) + +#define GET_WMM_QOS_INFO_FIELD_STA_AC_BK_UAPSD(_pStart) LE_BITS_TO_1BYTE(_pStart, 3, 1) +#define SET_WMM_QOS_INFO_FIELD_STA_AC_BK_UAPSD(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 3, 1, _val) + +#define GET_WMM_QOS_INFO_FIELD_STA_MAX_SP_LEN(_pStart) LE_BITS_TO_1BYTE(_pStart, 5, 2) +#define SET_WMM_QOS_INFO_FIELD_STA_MAX_SP_LEN(_pStart, _val) SET_BITS_TO_LE_1BYTE(_pStart, 5, 2, _val) + +#if 0 +#define WMM_INFO_ELEMENT_SIZE 7 + +#define GET_WMM_INFO_ELE_OUI(_pStart) ((u8*)(_pStart)) +#define SET_WMM_INFO_ELE_OUI(_pStart, _pVal) memcpy(_pStart, _pVal, 3); + +#define GET_WMM_INFO_ELE_OUI_TYPE(_pStart) ( EF1Byte( *((u8*)(_pStart)+3) ) ) +#define SET_WMM_INFO_ELE_OUI_TYPE(_pStart, _val) ( *((u8*)(_pStart)+3) = EF1Byte(_val) ) + +#define GET_WMM_INFO_ELE_OUI_SUBTYPE(_pStart) ( EF1Byte( *((u8*)(_pStart)+4) ) ) +#define SET_WMM_INFO_ELE_OUI_SUBTYPE(_pStart, _val) ( *((u8*)(_pStart)+4) = EF1Byte(_val) ) + +#define GET_WMM_INFO_ELE_VERSION(_pStart) ( EF1Byte( *((u8*)(_pStart)+5) ) ) +#define SET_WMM_INFO_ELE_VERSION(_pStart, _val) ( *((u8*)(_pStart)+5) = EF1Byte(_val) ) + +#define GET_WMM_INFO_ELE_QOS_INFO_FIELD(_pStart) ( EF1Byte( *((u8*)(_pStart)+6) ) ) +#define SET_WMM_INFO_ELE_QOS_INFO_FIELD(_pStart, _val) ( *((u8*)(_pStart)+6) = EF1Byte(_val) ) + + +#define CLEAR_TSPEC(_tspec) ( PlatformZeroMemory((_tspec), TSPEC_SIZE) ) + +#define GET_TSPEC_ID(_tspec) EF1Byte( (_tspec)[0] ) +#define SET_TSPEC_ID(_tspec, _value) ( (_tspec)[0] = EF1Byte(_value) ) + +#define GET_TSPEC_LENGTH(_tspec) EF1Byte( (_tspec)[1] ) +#define SET_TSPEC_LENGTH(_tspec, _value) ( (_tspec)[1] = EF1Byte(_value) ) + +#define GET_TSPEC_OUI(_tspec, _value) \ + { (_value)[0]=(_tspec)[2]; (_value)[1]=(_tspec)[3]; (_value)[2]=(_tspec)[4]; } +#define SET_TSPEC_OUI(_tspec, _value) \ + { (_tspec)[2]=(_value)[0]; (_tspec)[3]=(_value)[1]; (_tspec)[4]=(_value)[2]; } + +#define GET_TSPEC_OUI_TYPE(_tspec) EF1Byte( (_tspec)[5] ) +#define SET_TSPEC_OUI_TYPE(_tspec, _value) ( (_tspec)[5] = EF1Byte(_value) ) + +#define GET_TSPEC_OUI_SUBTYPE(_tspec) EF1Byte( (_tspec)[6] ) +#define SET_TSPEC_OUI_SUBTYPE(_tspec, _value) ( (_tspec)[6] = EF1Byte(_value) ) + +#define GET_TSPEC_VERSION(_tspec) EF1Byte( (_tspec)[7] ) +#define SET_TSPEC_VERSION(_tspec, _value) ( (_tspec)[7] = EF1Byte(_value) ) + + +#define GET_TSPEC_TSINFO_TRAFFIC_TYPE(_tspec) LE_BITS_TO_1BYTE( (_tspec)+8, 0, 1) +#define SET_TSPEC_TSINFO_TRAFFIC_TYPE(_tspec, _value) SET_BITS_TO_LE_1BYTE( (_tspec)+8, 0, 1, (_value) ) + +#define GET_TSPEC_TSINFO_TSID(_tspec) LE_BITS_TO_1BYTE( (_tspec)+8, 1, 4) +#define SET_TSPEC_TSINFO_TSID(_tspec, _value) SET_BITS_TO_LE_1BYTE( (_tspec)+8, 1, 4, (_value) ) + +#define GET_TSPEC_TSINFO_DIRECTION(_tspec) LE_BITS_TO_1BYTE( (_tspec)+8, 5, 2) +#define SET_TSPEC_TSINFO_DIRECTION(_tspec, _value) SET_BITS_TO_LE_1BYTE( (_tspec)+8, 5, 2, (_value) ) + +#define GET_TSPEC_TSINFO_ACCESS_POLICY_BIT0(_tspec) LE_BITS_TO_1BYTE( (_tspec)+8, 7, 1) +#define SET_TSPEC_TSINFO_ACCESS_POLICY_BIT0(_tspec, _value) SET_BITS_TO_LE_1BYTE( (_tspec)+8, 7, 1, (_value) ) + + +#define GET_TSPEC_TSINFO_ACCESS_POLICY_BIT1(_tspec) LE_BITS_TO_1BYTE( (_tspec)+9, 0, 1) +#define SET_TSPEC_TSINFO_ACCESS_POLICY_BIT1(_tspec, _value) SET_BITS_TO_LE_1BYTE( (_tspec)+9, 0, 1, (_value) ) + +#define GET_TSPEC_TSINFO_AGGREGATION(_tspec) LE_BITS_TO_1BYTE( (_tspec)+9, 1, 1) +#define SET_TSPEC_TSINFO_AGGREGATION(_tspec, _value) SET_BITS_TO_LE_1BYTE( (_tspec)+9, 1, 1, (_value) ) + +#define GET_TSPEC_TSINFO_PSB(_tspec) LE_BITS_TO_1BYTE( (_tspec)+9, 2, 1) +#define SET_TSPEC_TSINFO_PSB(_tspec, _value) SET_BITS_TO_LE_1BYTE( (_tspec)+9, 2, 1, (_value) ) + +#define GET_TSPEC_TSINFO_UP(_tspec) LE_BITS_TO_1BYTE( (_tspec)+9, 3, 3) +#define SET_TSPEC_TSINFO_UP(_tspec, _value) SET_BITS_TO_LE_1BYTE( (_tspec)+9, 3, 3, (_value) ) + +#define GET_TSPEC_TSINFO_ACK_POLICY(_tspec) LE_BITS_TO_1BYTE( (_tspec)+9, 6, 2) +#define SET_TSPEC_TSINFO_ACK_POLICY(_tspec, _value) SET_BITS_TO_LE_1BYTE( (_tspec)+9, 6, 2, (_value) ) + + +#define GET_TSPEC_TSINFO_SCHEDULE(_tspec) LE_BITS_TO_1BYTE( (_tspec)+10, 0, 1) +#define SET_TSPEC_TSINFO_SCHEDULE(_tspec, _value) SET_BITS_TO_LE_1BYTE( (_tspec)+10, 0, 1, (_value) ) + + +#define GET_TSPEC_NOMINAL_MSDU_SIZE(_tspec) LE_BITS_TO_2BYTE( (_tspec)+11, 0, 16) +#define SET_TSPEC_NOMINAL_MSDU_SIZE(_tspec, _value) SET_BITS_TO_LE_2BYTE( (_tspec)+11, 0, 16, (_value) ) + +#define GET_TSPEC_MAX_MSDU_SIZE(_tspec) LE_BITS_TO_2BYTE( (_tspec)+13, 0, 16) +#define SET_TSPEC_MAX_MSDU_SIZE(_tspec, _value) SET_BITS_TO_LE_2BYTE( (_tspec)+13, 0, 16, (_value) ) + +#define GET_TSPEC_MIN_SERVICE_INTERVAL(_tspec) LE_BITS_TO_4BYTE( (_tspec)+15, 0, 32) +#define SET_TSPEC_MIN_SERVICE_INTERVAL(_tspec, _value) SET_BITS_TO_LE_4BYTE( (_tspec)+15, 0, 32, (_value) ) + +#define GET_TSPEC_MAX_SERVICE_INTERVAL(_tspec) LE_BITS_TO_4BYTE( (_tspec)+19, 0, 32) +#define SET_TSPEC_MAX_SERVICE_INTERVAL(_tspec, _value) SET_BITS_TO_LE_4BYTE( (_tspec)+19, 0, 32, (_value) ) + +#define GET_TSPEC_INACTIVITY_INTERVAL(_tspec) LE_BITS_TO_4BYTE( (_tspec)+23, 0, 32) +#define SET_TSPEC_INACTIVITY_INTERVAL(_tspec, _value) SET_BITS_TO_LE_4BYTE( (_tspec)+23, 0, 32, (_value) ) + +#define GET_TSPEC_SUSPENSION_INTERVAL(_tspec) LE_BITS_TO_4BYTE( (_tspec)+27, 0, 32) +#define SET_TSPEC_SUSPENSION_INTERVAL(_tspec, _value) SET_BITS_TO_LE_4BYTE( (_tspec)+27, 0, 32, (_value) ) + +#define GET_TSPEC_SERVICE_START_TIME(_tspec) LE_BITS_TO_4BYTE( (_tspec)+31, 0, 32) +#define SET_TSPEC_SERVICE_START_TIME(_tspec, _value) SET_BITS_TO_LE_4BYTE( (_tspec)+31, 0, 32, (_value) ) + +#define GET_TSPEC_MIN_DATA_RATE(_tspec) LE_BITS_TO_4BYTE( (_tspec)+35, 0, 32) +#define SET_TSPEC_MIN_DATA_RATE(_tspec, _value) SET_BITS_TO_LE_4BYTE( (_tspec)+35, 0, 32, (_value) ) + +#define GET_TSPEC_MEAN_DATA_RATE(_tspec) LE_BITS_TO_4BYTE( (_tspec)+39, 0, 32) +#define SET_TSPEC_MEAN_DATA_RATE(_tspec, _value) SET_BITS_TO_LE_4BYTE( (_tspec)+39, 0, 32, (_value) ) + +#define GET_TSPEC_PEAK_DATA_RATE(_tspec) LE_BITS_TO_4BYTE( (_tspec)+43, 0, 32) +#define SET_TSPEC_PEAK_DATA_RATE(_tspec, _value) SET_BITS_TO_LE_4BYTE( (_tspec)+43, 0, 32, (_value) ) + +#define GET_TSPEC_MAX_BURST_SIZE(_tspec) LE_BITS_TO_4BYTE( (_tspec)+47, 0, 32) +#define SET_TSPEC_MAX_BURST_SIZE(_tspec, _value) SET_BITS_TO_LE_4BYTE( (_tspec)+47, 0, 32, (_value) ) + +#define GET_TSPEC_DELAY_BOUND(_tspec) LE_BITS_TO_4BYTE( (_tspec)+51, 0, 32) +#define SET_TSPEC_DELAY_BOUND(_tspec, _value) SET_BITS_TO_LE_4BYTE( (_tspec)+51, 0, 32, (_value) ) + +#define GET_TSPEC_MIN_PHY_RATE(_tspec) LE_BITS_TO_4BYTE( (_tspec)+55, 0, 32) +#define SET_TSPEC_MIN_PHY_RATE(_tspec, _value) SET_BITS_TO_LE_4BYTE( (_tspec)+55, 0, 32, (_value) ) + +#define GET_TSPEC_SURPLUS_BANDWITH_ALLOWANCE(_tspec) LE_BITS_TO_2BYTE( (_tspec)+59, 0, 16) +#define SET_TSPEC_SURPLUS_BANDWITH_ALLOWANCE(_tspec, _value) SET_BITS_TO_LE_2BYTE( (_tspec)+59, 0, 16, (_value) ) + +#define GET_TSPEC_MEDIUM_TIME(_tspec) LE_BITS_TO_2BYTE( (_tspec)+61, 0, 16) +#define SET_TSPEC_MEDIUM_TIME(_tspec, _value) SET_BITS_TO_LE_2BYTE( (_tspec)+61, 0, 16, (_value) ) + +#define GET_TSPEC_TSINFO_ACCESS_POLICY(_tspec) \ + ( (GET_TSPEC_TSINFO_ACCESS_POLICY_BIT1(_tspec) << 1) | GET_TSPEC_TSINFO_ACCESS_POLICY_BIT0(_tspec) ) +#define SET_TSPEC_TSINFO_ACCESS_POLICY(_tspec, _value) \ + {\ + SET_TSPEC_TSINFO_ACCESS_POLICY_BIT0((_tspec), (_value)&0x01);\ + SET_TSPEC_TSINFO_ACCESS_POLICY_BIT1((_tspec), (_value)&0x02);\ + } + + +#define GET_TSINFO_TRAFFIC_TYPE(_tsinfo) LE_BITS_TO_1BYTE( (_tsinfo), 0, 1) +#define SET_TSINFO_TRAFFIC_TYPE(_tsinfo, _value) SET_BITS_TO_LE_1BYTE( (_tsinfo), 0, 1, (_value) ) + +#define GET_TSINFO_TSID(_tsinfo) LE_BITS_TO_1BYTE( (_tsinfo), 1, 4) +#define SET_TSINFO_TSID(_tsinfo, _value) SET_BITS_TO_LE_1BYTE( (_tsinfo), 1, 4, (_value) ) + +#define GET_TSINFO_DIRECTION(_tsinfo) LE_BITS_TO_1BYTE( (_tsinfo), 5, 2) +#define SET_TSINFO_DIRECTION(_tsinfo, _value) SET_BITS_TO_LE_1BYTE( (_tsinfo), 5, 2, (_value) ) + +#define GET_TSINFO_ACCESS_POLICY_BIT0(_tsinfo) LE_BITS_TO_1BYTE( (_tsinfo), 7, 1) +#define SET_TSINFO_ACCESS_POLICY_BIT0(_tsinfo, _value) SET_BITS_TO_LE_1BYTE( (_tsinfo), 7, 1, (_value) ) + + +#define GET_TSINFO_ACCESS_POLICY_BIT1(_tsinfo) LE_BITS_TO_1BYTE( (_tsinfo) + 1, 0, 1) +#define SET_TSINFO_ACCESS_POLICY_BIT1(_tsinfo, _value) SET_BITS_TO_LE_1BYTE( (_tsinfo) + 1, 0, 1, (_value) ) + +#define GET_TSINFO_AGGREGATION(_tsinfo) LE_BITS_TO_1BYTE( (_tsinfo) + 1, 1, 1) +#define SET_TSINFO_AGGREGATION(_tsinfo, _value) SET_BITS_TO_LE_1BYTE( (_tsinfo) + 1, 1, 1, (_value) ) + +#define GET_TSINFO_PSB(_tsinfo) LE_BITS_TO_1BYTE( (_tsinfo) + 1, 2, 1) +#define SET_TSINFO_PSB(_tsinfo, _value) SET_BITS_TO_LE_1BYTE( (_tsinfo) + 1, 2, 1, (_value) ) + +#define GET_TSINFO_UP(_tsinfo) LE_BITS_TO_1BYTE( (_tsinfo) + 1, 3, 3) +#define SET_TSINFO_UP(_tsinfo, _value) SET_BITS_TO_LE_1BYTE( (_tsinfo) + 1, 3, 3, (_value) ) + +#define GET_TSINFO_ACK_POLICY(_tsinfo) LE_BITS_TO_1BYTE( (_tsinfo) + 1, 6, 2) +#define SET_TSINFO_ACK_POLICY(_tsinfo, _value) SET_BITS_TO_LE_1BYTE( (_tsinfo) + 1, 6, 2, (_value) ) + +#define GET_TSINFO_SCHEDULE(_tsinfo) LE_BITS_TO_1BYTE( (_tsinfo) + 2, 0, 1) +#define SET_TSINFO_SCHEDULE(_tsinfo, _value) SET_BITS_TO_LE_1BYTE( (_tsinfo) + 2, 0, 1, (_value) ) + + +#define QOS_RATE_TO_BPS(_rate) ( (u4Byte)( ((_rate)*1000*1000)/2 ) ) +#define QOS_BPS_TO_RATE(_bps) ( (u1Byte)( ((_bps)/(1000*1000))*2 ) ) +#endif + +typedef enum { + QOSIE_SRC_ADDTSREQ, + QOSIE_SRC_ADDTSRSP, + QOSIE_SRC_REASOCREQ, + QOSIE_SRC_REASOCRSP, + QOSIE_SRC_DELTS, +} QOSIE_SOURCE; + + +typedef u32 AC_CODING; +#define AC0_BE 0 +#define AC1_BK 1 +#define AC2_VI 2 +#define AC3_VO 3 +#define AC_MAX 4 + + +#define AC_PARAM_SIZE 4 + +#define GET_WMM_AC_PARAM_AIFSN(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 0, 4) ) +#define SET_WMM_AC_PARAM_AIFSN(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 0, 4, _val) + +#define GET_WMM_AC_PARAM_ACM(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 4, 1) ) +#define SET_WMM_AC_PARAM_ACM(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 4, 1, _val) + +#define GET_WMM_AC_PARAM_ACI(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 5, 2) ) +#define SET_WMM_AC_PARAM_ACI(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 5, 2, _val) + +#define GET_WMM_AC_PARAM_ACI_AIFSN(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 0, 8) ) +#define SET_WMM_AC_PARAM_ACI_AIFSN(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 0, 8, _val) + +#define GET_WMM_AC_PARAM_ECWMIN(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 8, 4) ) +#define SET_WMM_AC_PARAM_ECWMIN(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 8, 4, _val) + +#define GET_WMM_AC_PARAM_ECWMAX(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 12, 4) ) +#define SET_WMM_AC_PARAM_ECWMAX(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 12, 4, _val) + +#define GET_WMM_AC_PARAM_TXOP_LIMIT(_pStart) ( (u8)LE_BITS_TO_4BYTE(_pStart, 16, 16) ) +#define SET_WMM_AC_PARAM_TXOP_LIMIT(_pStart, _val) SET_BITS_TO_LE_4BYTE(_pStart, 16, 16, _val) + + + +#define WMM_PARAM_ELEMENT_SIZE (8+(4*AC_PARAM_SIZE)) + +#if 0 +#define GET_WMM_PARAM_ELE_OUI(_pStart) ((pu1Byte)(_pStart)) +#define SET_WMM_PARAM_ELE_OUI(_pStart, _pVal) PlatformMoveMemory(_pStart, _pVal, 3) + +#define GET_WMM_PARAM_ELE_OUI_TYPE(_pStart) ( EF1Byte( *((pu1Byte)(_pStart)+3) ) ) +#define SET_WMM_PARAM_ELE_OUI_TYPE(_pStart, _val) ( *((pu1Byte)(_pStart)+3) = EF1Byte(_val) ) + +#define GET_WMM_PARAM_ELE_OUI_SUBTYPE(_pStart) ( EF1Byte( *((pu1Byte)(_pStart)+4) ) ) +#define SET_WMM_PARAM_ELE_OUI_SUBTYPE(_pStart, _val) ( *((pu1Byte)(_pStart)+4) = EF1Byte(_val) ) + +#define GET_WMM_PARAM_ELE_VERSION(_pStart) ( EF1Byte( *((pu1Byte)(_pStart)+5) ) ) +#define SET_WMM_PARAM_ELE_VERSION(_pStart, _val) ( *((pu1Byte)(_pStart)+5) = EF1Byte(_val) ) + +#define GET_WMM_PARAM_ELE_QOS_INFO_FIELD(_pStart) ( EF1Byte( *((pu1Byte)(_pStart)+6) ) ) +#define SET_WMM_PARAM_ELE_QOS_INFO_FIELD(_pStart, _val) ( *((pu1Byte)(_pStart)+6) = EF1Byte(_val) ) + +#define GET_WMM_PARAM_ELE_AC_PARAMS(_pStart) ( (pu1Byte)(_pStart)+8 ) +#define SET_WMM_PARAM_ELE_AC_PARAMS(_pStart, _pVal) PlatformMoveMemory((_pStart)+8, _pVal, 16) + +#define GET_WMM_PARAM_ELE_SINGLE_AC_PARAM(_pStart, acIdx) ( ((pu1Byte)(_pStart))+8+ acIdx*4 ) +#define SET_WMM_PARAM_ELE_SINGLE_AC_PARAM(_pStart, acIdx, _pVal) PlatformMoveMemory( ((pu1Byte)(_pStart))+8+ acIdx*4, _pVal, 4) + +#define GET_WMM_PARAM_ELE_AC_PARAM(_pStart) ( (pu1Byte)(_pStart)+8 ) +#define SET_WMM_PARAM_ELE_AC_PARAM(_pStart, _pVal) PlatformMoveMemory((_pStart)+8, _pVal, 16) +#endif + +typedef enum _QOS_ELE_SUBTYPE{ + QOSELE_TYPE_INFO = 0x00, + QOSELE_TYPE_PARAM = 0x01, +}QOS_ELE_SUBTYPE,*PQOS_ELE_SUBTYPE; + + +typedef enum _DIRECTION_VALUE{ + DIR_UP = 0, + DIR_DOWN = 1, + DIR_DIRECT = 2, + DIR_BI_DIR = 3, +}DIRECTION_VALUE,*PDIRECTION_VALUE; + +#if 0 + +#define GET_TSPEC_BODY_TSINFO_TRAFFIC_TYPE(_TSpecBody) LE_BITS_TO_1BYTE( (_TSpecBody), 0, 1) +#define SET_TSPEC_BODY_TSINFO_TRAFFIC_TYPE(_TSpecBody, _value) SET_BITS_TO_LE_1BYTE( (_TSpecBody), 0, 1 , (_value)) + +#define GET_TSPEC_BODY_TSINFO_TSID(_TSpecBody) LE_BITS_TO_1BYTE( (_TSpecBody), 1, 4) +#define SET_TSPEC_BODY_TSINFO_TSID(_TSpecBody, _value) SET_BITS_TO_LE_1BYTE( (_TSpecBody), 1, 4 , (_value)) + +#define GET_TSPEC_BODY_TSINFO_DIRECTION(_TSpecBody) LE_BITS_TO_1BYTE( (_TSpecBody), 5, 2) +#define SET_TSPEC_BODY_TSINFO_DIRECTION(_TSpecBody, _value) SET_BITS_TO_LE_1BYTE( (_TSpecBody), 5, 2 , (_value)) + +#define GET_TSPEC_BODY_TSINFO_ACCESS_POLICY_BIT0(_TSpecBody) LE_BITS_TO_1BYTE( (_TSpecBody), 7, 1) +#define SET_TSPEC_BODY_TSINFO_ACCESS_POLICY_BIT0(_TSpecBody, _value) SET_BITS_TO_LE_1BYTE( (_TSpecBody), 7, 1 , (_value)) + +#define GET_TSPEC_BODY_TSINFO_ACCESS_POLICY_BIT1(_TSpecBody) LE_BITS_TO_1BYTE( (_TSpecBody)+1, 0, 1) +#define SET_TSPEC_BODY_TSINFO_ACCESS_POLICY_BIT1(_TSpecBody, _value) SET_BITS_TO_LE_1BYTE( (_TSpecBody)+1, 0, 1 , (_value)) + +#define GET_TSPEC_BODY_TSINFO_ACCESS_POLICY(_TSpecBody) \ + ((GET_TSPEC_BODY_TSINFO_ACCESS_POLICY_BIT1(_TSpecBody) << 1 ) | (GET_TSPEC_BODY_TSINFO_ACCESS_POLICY_BIT0(_TSpecBody) )) +#define SET_TSPEC_BODY_TSINFO_ACCESS_POLICY(_TSpecBody, _value) \ + {\ + SET_TSPEC_BODY_TSINFO_ACCESS_POLICY_BIT0((_TSpecBody), (_value) & 0x01); \ + SET_TSPEC_BODY_TSINFO_ACCESS_POLICY_BIT1((_TSpecBody), (_value) & 0x02); \ + } + +#define GET_TSPEC_BODY_TSINFO_AGGREGATION(_TSpecBody) LE_BITS_TO_1BYTE( (_TSpecBody)+1, 1, 1) +#define SET_TSPEC_BODY_TSINFO_AGGREGATION(_TSpecBody, _value) SET_BITS_TO_LE_1BYTE( (_TSpecBody)+1, 1, 1 , (_value)) + +#define GET_TSPEC_BODY_TSINFO_PSB(_TSpecBody) LE_BITS_TO_1BYTE( (_TSpecBody)+1, 2, 1) +#define SET_TSPEC_BODY_TSINFO_PSB(_TSpecBody, _value) SET_BITS_TO_LE_1BYTE( (_TSpecBody)+1, 2, 1 , (_value)) + +#define GET_TSPEC_BODY_TSINFO_UP(_TSpecBody) LE_BITS_TO_1BYTE( (_TSpecBody)+1, 3, 3) +#define SET_TSPEC_BODY_TSINFO_UP(_TSpecBody, _value) SET_BITS_TO_LE_1BYTE( (_TSpecBody)+1, 3, 3 , (_value)) + +#define GET_TSPEC_BODY_TSINFO_ACK_POLICY(_TSpecBody) LE_BITS_TO_1BYTE( (_TSpecBody)+1, 6, 2) +#define SET_TSPEC_BODY_TSINFO_ACK_POLICY(_TSpecBody, _value) SET_BITS_TO_LE_1BYTE( (_TSpecBody)+1, 6, 2 , (_value)) + +#define GET_TSPEC_BODY_TSINFO_SCHEDULE(_TSpecBody) LE_BITS_TO_1BYTE( (_TSpecBody)+2, 0, 1) +#define SET_TSPEC_BODY_TSINFO_SCHEDULE(_TSpecBody, _value) SET_BITS_TO_LE_1BYTE( (_TSpecBody)+2, 0, 1 , (_value)) + + + +#define TSPEC_SIZE (2+6+55) +typedef u8 WMM_TSPEC[TSPEC_SIZE], *PWMM_TSPEC; +#endif + +typedef enum _ACM_METHOD{ + eAcmWay0_SwAndHw = 0, + eAcmWay1_HW = 1, + eAcmWay2_SW = 2, +}ACM_METHOD,*PACM_METHOD; + + +typedef struct _ACM{ + u64 UsedTime; + u64 MediumTime; + u8 HwAcmCtl; +}ACM, *PACM; + + + +typedef u8 AC_UAPSD, *PAC_UAPSD; + +#define GET_VO_UAPSD(_apsd) ((_apsd) & BIT0) +#define SET_VO_UAPSD(_apsd) ((_apsd) |= BIT0) + +#define GET_VI_UAPSD(_apsd) ((_apsd) & BIT1) +#define SET_VI_UAPSD(_apsd) ((_apsd) |= BIT1) + +#define GET_BK_UAPSD(_apsd) ((_apsd) & BIT2) +#define SET_BK_UAPSD(_apsd) ((_apsd) |= BIT2) + +#define GET_BE_UAPSD(_apsd) ((_apsd) & BIT3) +#define SET_BE_UAPSD(_apsd) ((_apsd) |= BIT3) + +typedef union _QOS_TCLAS{ + + struct _TYPE_GENERAL{ + u8 Priority; + u8 ClassifierType; + u8 Mask; + } TYPE_GENERAL; + + struct _TYPE0_ETH{ + u8 Priority; + u8 ClassifierType; + u8 Mask; + u8 SrcAddr[6]; + u8 DstAddr[6]; + u16 Type; + } TYPE0_ETH; + + struct _TYPE1_IPV4{ + u8 Priority; + u8 ClassifierType; + u8 Mask; + u8 Version; + u8 SrcIP[4]; + u8 DstIP[4]; + u16 SrcPort; + u16 DstPort; + u8 DSCP; + u8 Protocol; + u8 Reserved; + } TYPE1_IPV4; + + struct _TYPE1_IPV6{ + u8 Priority; + u8 ClassifierType; + u8 Mask; + u8 Version; + u8 SrcIP[16]; + u8 DstIP[16]; + u16 SrcPort; + u16 DstPort; + u8 FlowLabel[3]; + } TYPE1_IPV6; + + struct _TYPE2_8021Q{ + u8 Priority; + u8 ClassifierType; + u8 Mask; + u16 TagType; + } TYPE2_8021Q; +} QOS_TCLAS, *PQOS_TCLAS; + +typedef struct _QOS_TSTREAM{ + + bool bUsed; + u16 MsduLifetime; + bool bEstablishing; + u8 TimeSlotCount; + u8 DialogToken; + WMM_TSPEC TSpec; + WMM_TSPEC OutStandingTSpec; + u8 NominalPhyRate; +} QOS_TSTREAM, *PQOS_TSTREAM; + +typedef struct _STA_QOS{ + u8 WMMIEBuf[MAX_WMMELE_LENGTH]; + u8* WMMIE; + + QOS_MODE QosCapability; + QOS_MODE CurrentQosMode; + + AC_UAPSD b4ac_Uapsd; + AC_UAPSD Curr4acUapsd; + u8 bInServicePeriod; + u8 MaxSPLength; + int NumBcnBeforeTrigger; + + u8 * pWMMInfoEle; + u8 WMMParamEle[WMM_PARAM_ELEMENT_SIZE]; + + ACM acm[4]; + ACM_METHOD AcmMethod; + + QOS_TSTREAM StaTsArray[MAX_STA_TS_COUNT]; + u8 DialogToken; + WMM_TSPEC TSpec; + + u8 QBssWirelessMode; + + bool bNoAck; + + bool bEnableRxImmBA; + +}STA_QOS, *PSTA_QOS; + +#define QBSS_LOAD_SIZE 5 +#define GET_QBSS_LOAD_STA_COUNT(__pStart) ReadEF2Byte(__pStart) +#define SET_QBSS_LOAD_STA_COUNT(__pStart, __Value) WriteEF2Byte(__pStart, __Value) +#define GET_QBSS_LOAD_CHNL_UTILIZATION(__pStart) ReadEF1Byte((u8*)(__pStart) + 2) +#define SET_QBSS_LOAD_CHNL_UTILIZATION(__pStart, __Value) WriteEF1Byte((u8*)(__pStart) + 2, __Value) +#define GET_QBSS_LOAD_AVAILABLE_CAPACITY(__pStart) ReadEF2Byte((u8*)(__pStart) + 3) +#define SET_QBSS_LOAD_AVAILABLE_CAPACITY(__pStart, __Value) WriteEF2Byte((u8*)(__pStart) + 3, __Value) + +typedef struct _BSS_QOS{ + + QOS_MODE bdQoSMode; + u8 bdWMMIEBuf[MAX_WMMELE_LENGTH]; + OCTET_STRING bdWMMIE; + + QOS_ELE_SUBTYPE EleSubType; + + u8* pWMMInfoEle; + u8* pWMMParamEle; + + u8 QBssLoad[QBSS_LOAD_SIZE]; + bool bQBssLoadValid; +}BSS_QOS, *PBSS_QOS; + +#define sQoSCtlLng 2 +#define QOS_CTRL_LEN(_QosMode) ( (_QosMode > QOS_DISABLE)? sQoSCtlLng : 0 ) + + +#define IsACValid(ac) ( ( ac>=0 && ac<=7 )? true : false ) + + +typedef union _ACI_AIFSN{ + u8 charData; + + struct + { + u8 AIFSN:4; + u8 ACM:1; + u8 ACI:2; + u8 Reserved:1; + }f; +}ACI_AIFSN, *PACI_AIFSN; + +typedef union _ECW{ + u8 charData; + struct + { + u8 ECWmin:4; + u8 ECWmax:4; + }f; +}ECW, *PECW; + +typedef union _AC_PARAM{ + u32 longData; + u8 charData[4]; + + struct + { + ACI_AIFSN AciAifsn; + ECW Ecw; + u16 TXOPLimit; + }f; +}AC_PARAM, *PAC_PARAM; + + + + + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtl819x_TS.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtl819x_TS.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#ifndef _TSTYPE_H_ +#define _TSTYPE_H_ +#include "rtl819x_Qos.h" +#define TS_SETUP_TIMEOUT 60 +#define TS_INACT_TIMEOUT 60 +#define TS_ADDBA_DELAY 60 + +#define TOTAL_TS_NUM 16 +#define TCLAS_NUM 4 + +typedef enum _TR_SELECT { + TX_DIR = 0, + RX_DIR = 1, +} TR_SELECT, *PTR_SELECT; + +typedef struct _TS_COMMON_INFO{ + struct list_head List; + struct timer_list SetupTimer; + struct timer_list InactTimer; + u8 Addr[6]; + TSPEC_BODY TSpec; + QOS_TCLAS TClass[TCLAS_NUM]; + u8 TClasProc; + u8 TClasNum; +} TS_COMMON_INFO, *PTS_COMMON_INFO; + +typedef struct _TX_TS_RECORD{ + TS_COMMON_INFO TsCommonInfo; + u16 TxCurSeq; + BA_RECORD TxPendingBARecord; + BA_RECORD TxAdmittedBARecord; + u8 bAddBaReqInProgress; + u8 bAddBaReqDelayed; + u8 bUsingBa; + u8 bDisable_AddBa; + struct timer_list TsAddBaTimer; + u8 num; +} TX_TS_RECORD, *PTX_TS_RECORD; + +typedef struct _RX_TS_RECORD { + TS_COMMON_INFO TsCommonInfo; + u16 RxIndicateSeq; + u16 RxTimeoutIndicateSeq; + struct list_head RxPendingPktList; + struct timer_list RxPktPendingTimer; + BA_RECORD RxAdmittedBARecord; + u16 RxLastSeqNum; + u8 RxLastFragNum; + u8 num; +} RX_TS_RECORD, *PRX_TS_RECORD; + + +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtl819x_TSProc.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtl819x_TSProc.c @@ -0,0 +1,668 @@ +/****************************************************************************** + * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * wlanfae +******************************************************************************/ +#include "rtllib.h" +#include +#include "rtl819x_TS.h" +extern void _setup_timer( struct timer_list*, void*, unsigned long); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) +#endif +void TsSetupTimeOut(unsigned long data) +{ +} + +void TsInactTimeout(unsigned long data) +{ +} + +void RxPktPendingTimeout(unsigned long data) +{ + PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data; + struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device, RxTsRecord[pRxTs->num]); + + PRX_REORDER_ENTRY pReorderEntry = NULL; + + unsigned long flags = 0; + struct rtllib_rxb *stats_IndicateArray[REORDER_WIN_SIZE]; + u8 index = 0; + bool bPktInBuf = false; + + spin_lock_irqsave(&(ieee->reorder_spinlock), flags); + if(pRxTs->RxTimeoutIndicateSeq != 0xffff) + { + while(!list_empty(&pRxTs->RxPendingPktList)) + { + pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTs->RxPendingPktList.prev,RX_REORDER_ENTRY,List); + if(index == 0) + pRxTs->RxIndicateSeq = pReorderEntry->SeqNum; + + if( SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) || + SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) ) + { + list_del_init(&pReorderEntry->List); + + if(SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq)) + pRxTs->RxIndicateSeq = (pRxTs->RxIndicateSeq + 1) % 4096; + + RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): Indicate SeqNum: %d\n",__func__, pReorderEntry->SeqNum); + stats_IndicateArray[index] = pReorderEntry->prxb; + index++; + + list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List); + } + else + { + bPktInBuf = true; + break; + } + } + } + + if(index>0){ + pRxTs->RxTimeoutIndicateSeq = 0xffff; + + if(index > REORDER_WIN_SIZE){ + RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n"); + spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); + return; + } + rtllib_indicate_packets(ieee, stats_IndicateArray, index); + bPktInBuf = false; + } + + if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff)){ + pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq; + mod_timer(&pRxTs->RxPktPendingTimer, jiffies + MSECS(ieee->pHTInfo->RxReorderPendingTime)); + } + spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); +} + +void TsAddBaProcess(unsigned long data) +{ + PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data; + u8 num = pTxTs->num; + struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device, TxTsRecord[num]); + + TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false); + RTLLIB_DEBUG(RTLLIB_DL_BA, "TsAddBaProcess(): ADDBA Req is started!! \n"); +} + + +void ResetTsCommonInfo(PTS_COMMON_INFO pTsCommonInfo) +{ + memset(pTsCommonInfo->Addr, 0, 6); + memset(&pTsCommonInfo->TSpec, 0, sizeof(TSPEC_BODY)); + memset(&pTsCommonInfo->TClass, 0, sizeof(QOS_TCLAS)*TCLAS_NUM); + pTsCommonInfo->TClasProc = 0; + pTsCommonInfo->TClasNum = 0; +} + +void ResetTxTsEntry(PTX_TS_RECORD pTS) +{ + ResetTsCommonInfo(&pTS->TsCommonInfo); + pTS->TxCurSeq = 0; + pTS->bAddBaReqInProgress = false; + pTS->bAddBaReqDelayed = false; + pTS->bUsingBa = false; + pTS->bDisable_AddBa = false; + ResetBaEntry(&pTS->TxAdmittedBARecord); + ResetBaEntry(&pTS->TxPendingBARecord); +} + +void ResetRxTsEntry(PRX_TS_RECORD pTS) +{ + ResetTsCommonInfo(&pTS->TsCommonInfo); + pTS->RxIndicateSeq = 0xffff; + pTS->RxTimeoutIndicateSeq = 0xffff; + ResetBaEntry(&pTS->RxAdmittedBARecord); +} +#ifdef _RTL8192_EXT_PATCH_ +void ResetAdmitTRStream(struct rtllib_device *ieee, u8 *Addr) +{ + u8 dir; + bool search_dir[4] = {0, 0, 0, 0}; + struct list_head* psearch_list; + PTS_COMMON_INFO pRet = NULL; + PRX_TS_RECORD pRxTS = NULL; + PTX_TS_RECORD pTxTS = NULL; + + if(ieee->iw_mode != IW_MODE_MESH) + return; + + search_dir[DIR_DOWN] = true; + psearch_list = &ieee->Rx_TS_Admit_List; + for(dir = 0; dir <= DIR_BI_DIR; dir++) + { + if(search_dir[dir] ==false ) + continue; + list_for_each_entry(pRet, psearch_list, List){ + if ((memcmp(pRet->Addr, Addr, 6) == 0) && (pRet->TSpec.f.TSInfo.field.ucDirection == dir)) + { + pRxTS = (PRX_TS_RECORD)pRet; + pRxTS->RxIndicateSeq = 0xffff; + pRxTS->RxTimeoutIndicateSeq = 0xffff; + } + + } + } + search_dir[DIR_UP] = true; + psearch_list = &ieee->Tx_TS_Admit_List; + for(dir = 0; dir <= DIR_BI_DIR; dir++) + { + if(search_dir[dir] ==false ) + continue; + list_for_each_entry(pRet, psearch_list, List){ + if ((memcmp(pRet->Addr, Addr, 6) == 0) && (pRet->TSpec.f.TSInfo.field.ucDirection == dir)) + { + pTxTS = (PTX_TS_RECORD)pRet; + pTxTS->TxCurSeq = 0xffff; + } + + } + } + + return; +} +#endif + +void TSInitialize(struct rtllib_device *ieee) +{ + PTX_TS_RECORD pTxTS = ieee->TxTsRecord; + PRX_TS_RECORD pRxTS = ieee->RxTsRecord; + PRX_REORDER_ENTRY pRxReorderEntry = ieee->RxReorderEntry; + u8 count = 0; + RTLLIB_DEBUG(RTLLIB_DL_TS, "==========>%s()\n", __FUNCTION__); + INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List); + INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List); + INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List); + + for(count = 0; count < TOTAL_TS_NUM; count++) + { + pTxTS->num = count; + _setup_timer(&pTxTS->TsCommonInfo.SetupTimer, + TsSetupTimeOut, + (unsigned long) pTxTS); + + _setup_timer(&pTxTS->TsCommonInfo.InactTimer, + TsInactTimeout, + (unsigned long) pTxTS); + + _setup_timer(&pTxTS->TsAddBaTimer, + TsAddBaProcess, + (unsigned long) pTxTS); + + _setup_timer(&pTxTS->TxPendingBARecord.Timer, + BaSetupTimeOut, + (unsigned long) pTxTS); + _setup_timer(&pTxTS->TxAdmittedBARecord.Timer, + TxBaInactTimeout, + (unsigned long) pTxTS); + + ResetTxTsEntry(pTxTS); + list_add_tail(&pTxTS->TsCommonInfo.List, + &ieee->Tx_TS_Unused_List); + pTxTS++; + } + + INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List); + INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List); + INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List); + for(count = 0; count < TOTAL_TS_NUM; count++) + { + pRxTS->num = count; + INIT_LIST_HEAD(&pRxTS->RxPendingPktList); + + _setup_timer(&pRxTS->TsCommonInfo.SetupTimer, + TsSetupTimeOut, + (unsigned long) pRxTS); + + _setup_timer(&pRxTS->TsCommonInfo.InactTimer, + TsInactTimeout, + (unsigned long) pRxTS); + + _setup_timer(&pRxTS->RxAdmittedBARecord.Timer, + RxBaInactTimeout, + (unsigned long) pRxTS); + + _setup_timer(&pRxTS->RxPktPendingTimer, + RxPktPendingTimeout, + (unsigned long) pRxTS); + + ResetRxTsEntry(pRxTS); + list_add_tail(&pRxTS->TsCommonInfo.List, &ieee->Rx_TS_Unused_List); + pRxTS++; + } + INIT_LIST_HEAD(&ieee->RxReorder_Unused_List); + for(count = 0; count < REORDER_ENTRY_NUM; count++) + { + list_add_tail( &pRxReorderEntry->List,&ieee->RxReorder_Unused_List); + if(count == (REORDER_ENTRY_NUM-1)) + break; + pRxReorderEntry = &ieee->RxReorderEntry[count+1]; + } + +} + +void AdmitTS(struct rtllib_device *ieee, PTS_COMMON_INFO pTsCommonInfo, u32 InactTime) +{ + del_timer_sync(&pTsCommonInfo->SetupTimer); + del_timer_sync(&pTsCommonInfo->InactTimer); + + if(InactTime!=0) + mod_timer(&pTsCommonInfo->InactTimer, jiffies + MSECS(InactTime)); +} + + +PTS_COMMON_INFO SearchAdmitTRStream(struct rtllib_device *ieee, u8* Addr, u8 TID, TR_SELECT TxRxSelect) +{ + u8 dir; + bool search_dir[4] = {0, 0, 0, 0}; + struct list_head* psearch_list; + PTS_COMMON_INFO pRet = NULL; + if(ieee->iw_mode == IW_MODE_MASTER) + { + if(TxRxSelect == TX_DIR) + { + search_dir[DIR_DOWN] = true; + search_dir[DIR_BI_DIR]= true; + } + else + { + search_dir[DIR_UP] = true; + search_dir[DIR_BI_DIR]= true; + } + } + else if(ieee->iw_mode == IW_MODE_ADHOC) + { + if(TxRxSelect == TX_DIR) + search_dir[DIR_UP] = true; + else + search_dir[DIR_DOWN] = true; + } + else + { + if(TxRxSelect == TX_DIR) + { + search_dir[DIR_UP] = true; + search_dir[DIR_BI_DIR]= true; + search_dir[DIR_DIRECT]= true; + } + else + { + search_dir[DIR_DOWN] = true; + search_dir[DIR_BI_DIR]= true; + search_dir[DIR_DIRECT]= true; + } + } + + if(TxRxSelect == TX_DIR) + psearch_list = &ieee->Tx_TS_Admit_List; + else + psearch_list = &ieee->Rx_TS_Admit_List; + + for(dir = 0; dir <= DIR_BI_DIR; dir++) + { + if(search_dir[dir] ==false ) + continue; + list_for_each_entry(pRet, psearch_list, List){ + if (memcmp(pRet->Addr, Addr, 6) == 0) + if (pRet->TSpec.f.TSInfo.field.ucTSID == TID) + if(pRet->TSpec.f.TSInfo.field.ucDirection == dir) + { + break; + } + + } + if(&pRet->List != psearch_list) + break; + } + + if(&pRet->List != psearch_list){ + return pRet ; + } + else + return NULL; +} + +void MakeTSEntry( + PTS_COMMON_INFO pTsCommonInfo, + u8* Addr, + PTSPEC_BODY pTSPEC, + PQOS_TCLAS pTCLAS, + u8 TCLAS_Num, + u8 TCLAS_Proc + ) +{ + u8 count; + + if(pTsCommonInfo == NULL) + return; + + memcpy(pTsCommonInfo->Addr, Addr, 6); + + if(pTSPEC != NULL) + memcpy((u8*)(&(pTsCommonInfo->TSpec)), (u8*)pTSPEC, sizeof(TSPEC_BODY)); + + for(count = 0; count < TCLAS_Num; count++) + memcpy((u8*)(&(pTsCommonInfo->TClass[count])), (u8*)pTCLAS, sizeof(QOS_TCLAS)); + + pTsCommonInfo->TClasProc = TCLAS_Proc; + pTsCommonInfo->TClasNum = TCLAS_Num; +} + +#ifdef _RTL8192_EXT_PATCH_ +void dump_ts_list(struct list_head * ts_list) +{ + PTS_COMMON_INFO pRet = NULL; + u8 i=0; + list_for_each_entry(pRet, ts_list, List){ + printk("i=%d ADD:"MAC_FMT", TID:%d, dir:%d\n",i,MAC_ARG(pRet->Addr), pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection); + i++; + } + +} +#endif + +bool GetTs( + struct rtllib_device* ieee, + PTS_COMMON_INFO *ppTS, + u8* Addr, + u8 TID, + TR_SELECT TxRxSelect, + bool bAddNewTs + ) +{ + u8 UP = 0; + if(is_broadcast_ether_addr(Addr) || is_multicast_ether_addr(Addr)) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR! get TS for Broadcast or Multicast\n"); + return false; + } +#if 0 + if(ieee->pStaQos->CurrentQosMode == QOS_DISABLE) + { UP = 0; } + else if(ieee->pStaQos->CurrentQosMode & QOS_WMM) + { +#else + if (ieee->current_network.qos_data.supported == 0) + UP = 0; + else + { +#endif + if (!IsACValid(TID)) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR! in %s(), TID(%d) is not valid\n", __FUNCTION__, TID); + return false; + } + + switch(TID) + { + case 0: + case 3: + UP = 0; + break; + + case 1: + case 2: + UP = 2; + break; + + case 4: + case 5: + UP = 5; + break; + + case 6: + case 7: + UP = 7; + break; + } + } + + *ppTS = SearchAdmitTRStream( + ieee, + Addr, + UP, + TxRxSelect); + if(*ppTS != NULL) + { + return true; + } + else + { + if(bAddNewTs == false) + { + RTLLIB_DEBUG(RTLLIB_DL_TS, "add new TS failed(tid:%d)\n", UP); + return false; + } + else + { + TSPEC_BODY TSpec; + PQOS_TSINFO pTSInfo = &TSpec.f.TSInfo; + struct list_head* pUnusedList = + (TxRxSelect == TX_DIR)? + (&ieee->Tx_TS_Unused_List): + (&ieee->Rx_TS_Unused_List); + + struct list_head* pAddmitList = + (TxRxSelect == TX_DIR)? + (&ieee->Tx_TS_Admit_List): + (&ieee->Rx_TS_Admit_List); + + DIRECTION_VALUE Dir = (ieee->iw_mode == IW_MODE_MASTER)? + ((TxRxSelect==TX_DIR)?DIR_DOWN:DIR_UP): + ((TxRxSelect==TX_DIR)?DIR_UP:DIR_DOWN); + RTLLIB_DEBUG(RTLLIB_DL_TS, "to add Ts\n"); + if(!list_empty(pUnusedList)) + { + (*ppTS) = list_entry(pUnusedList->next, TS_COMMON_INFO, List); + list_del_init(&(*ppTS)->List); + if(TxRxSelect==TX_DIR) + { + PTX_TS_RECORD tmp = container_of(*ppTS, TX_TS_RECORD, TsCommonInfo); + ResetTxTsEntry(tmp); + } + else{ + PRX_TS_RECORD tmp = container_of(*ppTS, RX_TS_RECORD, TsCommonInfo); + ResetRxTsEntry(tmp); + } + + RTLLIB_DEBUG(RTLLIB_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:"MAC_FMT" ppTs=%p\n", UP, Dir, MAC_ARG(Addr), *ppTS); + pTSInfo->field.ucTrafficType = 0; + pTSInfo->field.ucTSID = UP; + pTSInfo->field.ucDirection = Dir; + pTSInfo->field.ucAccessPolicy = 1; + pTSInfo->field.ucAggregation = 0; + pTSInfo->field.ucPSB = 0; + pTSInfo->field.ucUP = UP; + pTSInfo->field.ucTSInfoAckPolicy = 0; + pTSInfo->field.ucSchedule = 0; + + MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0); + AdmitTS(ieee, *ppTS, 0); + list_add_tail(&((*ppTS)->List), pAddmitList); + + return true; + } + else + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!in function %s() There is not enough dir=%d(0=up down=1) TS record to be used!!", __FUNCTION__,Dir); + return false; + } + } + } +} + +void RemoveTsEntry( + struct rtllib_device* ieee, + PTS_COMMON_INFO pTs, + TR_SELECT TxRxSelect + ) +{ + del_timer_sync(&pTs->SetupTimer); + del_timer_sync(&pTs->InactTimer); + TsInitDelBA(ieee, pTs, TxRxSelect); + + if(TxRxSelect == RX_DIR) + { + PRX_REORDER_ENTRY pRxReorderEntry; + PRX_TS_RECORD pRxTS = (PRX_TS_RECORD)pTs; + + if(timer_pending(&pRxTS->RxPktPendingTimer)) + del_timer_sync(&pRxTS->RxPktPendingTimer); + + while(!list_empty(&pRxTS->RxPendingPktList)){ + pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List); + RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): Delete SeqNum %d!\n",__FUNCTION__, pRxReorderEntry->SeqNum); + list_del_init(&pRxReorderEntry->List); + { + int i = 0; + struct rtllib_rxb * prxb = pRxReorderEntry->prxb; + if (unlikely(!prxb)){ + return; + } + for(i =0; i < prxb->nr_subframes; i++) { + dev_kfree_skb(prxb->subframes[i]); + } + kfree(prxb); + prxb = NULL; + } + list_add_tail(&pRxReorderEntry->List,&ieee->RxReorder_Unused_List); + } + } + else{ + PTX_TS_RECORD pTxTS = (PTX_TS_RECORD)pTs; + del_timer_sync(&pTxTS->TsAddBaTimer); + } +} + +void RemovePeerTS(struct rtllib_device* ieee, u8* Addr) +{ + PTS_COMMON_INFO pTS, pTmpTS; + printk("===========>RemovePeerTS,"MAC_FMT"\n", MAC_ARG(Addr)); +#if 1 + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) + { + if (memcmp(pTS->Addr, Addr, 6) == 0) + { + RemoveTsEntry(ieee, pTS, TX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); + } + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) + { + if (memcmp(pTS->Addr, Addr, 6) == 0) + { + printk("====>remove Tx_TS_admin_list\n"); + RemoveTsEntry(ieee, pTS, TX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); + } + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) + { + if (memcmp(pTS->Addr, Addr, 6) == 0) + { + RemoveTsEntry(ieee, pTS, RX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); + } + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) + { + if (memcmp(pTS->Addr, Addr, 6) == 0) + { + RemoveTsEntry(ieee, pTS, RX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); + } + } +#endif +} + +void RemoveAllTS(struct rtllib_device* ieee) +{ + PTS_COMMON_INFO pTS, pTmpTS; +#if 1 + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) + { + RemoveTsEntry(ieee, pTS, TX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) + { + RemoveTsEntry(ieee, pTS, TX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) + { + RemoveTsEntry(ieee, pTS, RX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); + } + + list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) + { + RemoveTsEntry(ieee, pTS, RX_DIR); + list_del_init(&pTS->List); + list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); + } +#endif +} + +void TsStartAddBaProcess(struct rtllib_device* ieee, PTX_TS_RECORD pTxTS) +{ + if(pTxTS->bAddBaReqInProgress == false) + { + pTxTS->bAddBaReqInProgress = true; +#if 1 + if(pTxTS->bAddBaReqDelayed) + { + RTLLIB_DEBUG(RTLLIB_DL_BA, "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n"); + mod_timer(&pTxTS->TsAddBaTimer, jiffies + MSECS(TS_ADDBA_DELAY)); + } + else + { + RTLLIB_DEBUG(RTLLIB_DL_BA,"TsStartAddBaProcess(): Immediately Start ADDBA now!!\n"); + mod_timer(&pTxTS->TsAddBaTimer, jiffies+10); + } +#endif + } + else + RTLLIB_DEBUG(RTLLIB_DL_ERR, "%s()==>BA timer is already added\n", __FUNCTION__); +} + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(RemovePeerTS); +#ifdef _RTL8192_EXT_PATCH_ +EXPORT_SYMBOL_RSL(ResetAdmitTRStream); +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtl_crypto.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtl_crypto.h @@ -0,0 +1,409 @@ +/* + * Scatterlist Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 David S. Miller (davem@redhat.com) + * + * Portions derived from Cryptoapi, by Alexander Kjeldaas + * and Nettle, by Niels Mé°ˆler. + * + * 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. + * + */ +#ifndef _LINUX_CRYPTO_H +#define _LINUX_CRYPTO_H + +#include +#include +#include +#include +#include +#include +#include + +#ifdef BUILT_IN_CRYPTO +#ifdef CONFIG_CRYPTO_HMAC +#undef CONFIG_CRYPTO_HMAC +#endif + +#ifdef CONFIG_KMOD +#undef CONFIG_KMOD +#endif +#endif /* BUILT_IN_CRYPTO */ + +#define crypto_register_alg crypto_register_alg_rsl +#define crypto_unregister_alg crypto_unregister_alg_rsl +#define crypto_alloc_tfm crypto_alloc_tfm_rsl +#define crypto_free_tfm crypto_free_tfm_rsl +#define crypto_alg_available crypto_alg_available_rsl + +/* + * Algorithm masks and types. + */ +#define CRYPTO_ALG_TYPE_MASK 0x000000ff +#define CRYPTO_ALG_TYPE_CIPHER 0x00000001 +#define CRYPTO_ALG_TYPE_DIGEST 0x00000002 +#define CRYPTO_ALG_TYPE_COMPRESS 0x00000004 + +/* + * Transform masks and values (for crt_flags). + */ +#define CRYPTO_TFM_MODE_MASK 0x000000ff +#define CRYPTO_TFM_REQ_MASK 0x000fff00 +#define CRYPTO_TFM_RES_MASK 0xfff00000 + +#define CRYPTO_TFM_MODE_ECB 0x00000001 +#define CRYPTO_TFM_MODE_CBC 0x00000002 +#define CRYPTO_TFM_MODE_CFB 0x00000004 +#define CRYPTO_TFM_MODE_CTR 0x00000008 + +#define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100 +#define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 +#define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 +#define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000 +#define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000 +#define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000 + +/* + * Miscellaneous stuff. + */ +#define CRYPTO_UNSPEC 0 +#define CRYPTO_MAX_ALG_NAME 64 + +struct scatterlist; + +/* + * Algorithms: modular crypto algorithm implementations, managed + * via crypto_register_alg() and crypto_unregister_alg(). + */ +struct cipher_alg { + unsigned int cia_min_keysize; + unsigned int cia_max_keysize; + int (*cia_setkey)(void *ctx, const u8 *key, + unsigned int keylen, u32 *flags); + void (*cia_encrypt)(void *ctx, u8 *dst, const u8 *src); + void (*cia_decrypt)(void *ctx, u8 *dst, const u8 *src); +}; + +struct digest_alg { + unsigned int dia_digestsize; + void (*dia_init)(void *ctx); + void (*dia_update)(void *ctx, const u8 *data, unsigned int len); + void (*dia_final)(void *ctx, u8 *out); + int (*dia_setkey)(void *ctx, const u8 *key, + unsigned int keylen, u32 *flags); +}; + +struct compress_alg { + int (*coa_init)(void *ctx); + void (*coa_exit)(void *ctx); + int (*coa_compress)(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); + int (*coa_decompress)(void *ctx, const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); +}; + +#define cra_cipher cra_u.cipher +#define cra_digest cra_u.digest +#define cra_compress cra_u.compress + +struct crypto_alg { + struct list_head cra_list; + u32 cra_flags; + unsigned int cra_blocksize; + unsigned int cra_ctxsize; + const char cra_name[CRYPTO_MAX_ALG_NAME]; + + union { + struct cipher_alg cipher; + struct digest_alg digest; + struct compress_alg compress; + } cra_u; + + struct module *cra_module; +}; + +/* + * Algorithm registration interface. + */ +int crypto_register_alg(struct crypto_alg *alg); +int crypto_unregister_alg(struct crypto_alg *alg); + +/* + * Algorithm query interface. + */ +int crypto_alg_available(const char *name, u32 flags); + +/* + * Transforms: user-instantiated objects which encapsulate algorithms + * and core processing logic. Managed via crypto_alloc_tfm() and + * crypto_free_tfm(), as well as the various helpers below. + */ +struct crypto_tfm; + +struct cipher_tfm { + void *cit_iv; + unsigned int cit_ivsize; + u32 cit_mode; + int (*cit_setkey)(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen); + int (*cit_encrypt)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes); + int (*cit_encrypt_iv)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv); + int (*cit_decrypt)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes); + int (*cit_decrypt_iv)(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv); + void (*cit_xor_block)(u8 *dst, const u8 *src); +}; + +struct digest_tfm { + void (*dit_init)(struct crypto_tfm *tfm); + void (*dit_update)(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg); + void (*dit_final)(struct crypto_tfm *tfm, u8 *out); + void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg, + unsigned int nsg, u8 *out); + int (*dit_setkey)(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen); +#ifdef CONFIG_CRYPTO_HMAC + void *dit_hmac_block; +#endif +}; + +struct compress_tfm { + int (*cot_compress)(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); + int (*cot_decompress)(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen); +}; + +#define crt_cipher crt_u.cipher +#define crt_digest crt_u.digest +#define crt_compress crt_u.compress + +struct crypto_tfm { + + u32 crt_flags; + + union { + struct cipher_tfm cipher; + struct digest_tfm digest; + struct compress_tfm compress; + } crt_u; + + struct crypto_alg *__crt_alg; +}; + +/* + * Transform user interface. + */ + +/* + * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm. + * If that fails and the kernel supports dynamically loadable modules, it + * will then attempt to load a module of the same name or alias. A refcount + * is grabbed on the algorithm which is then associated with the new transform. + * + * crypto_free_tfm() frees up the transform and any associated resources, + * then drops the refcount on the associated algorithm. + */ +struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags); +void crypto_free_tfm(struct crypto_tfm *tfm); + +/* + * Transform helpers which query the underlying algorithm. + */ +static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm) +{ + return tfm->__crt_alg->cra_name; +} + +static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm) +{ + struct crypto_alg *alg = tfm->__crt_alg; + + if (alg->cra_module) + return alg->cra_module->name; + else + return NULL; +} + +static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm) +{ + return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK; +} + +static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->__crt_alg->cra_cipher.cia_min_keysize; +} + +static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->__crt_alg->cra_cipher.cia_max_keysize; +} + +static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_ivsize; +} + +static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm) +{ + return tfm->__crt_alg->cra_blocksize; +} + +static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + return tfm->__crt_alg->cra_digest.dia_digestsize; +} + +/* + * API wrappers. + */ +static inline void crypto_digest_init(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_init(tfm); +} + +static inline void crypto_digest_update(struct crypto_tfm *tfm, + struct scatterlist *sg, + unsigned int nsg) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_update(tfm, sg, nsg); +} + +static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_final(tfm, out); +} + +static inline void crypto_digest_digest(struct crypto_tfm *tfm, + struct scatterlist *sg, + unsigned int nsg, u8 *out) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + tfm->crt_digest.dit_digest(tfm, sg, nsg, out); +} + +static inline int crypto_digest_setkey(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); + if (tfm->crt_digest.dit_setkey == NULL) + return -ENOSYS; + return tfm->crt_digest.dit_setkey(tfm, key, keylen); +} + +static inline int crypto_cipher_setkey(struct crypto_tfm *tfm, + const u8 *key, unsigned int keylen) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_setkey(tfm, key, keylen); +} + +static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); +} + +static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); + return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv); +} + +static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); +} + +static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); + return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv); +} + +static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm, + const u8 *src, unsigned int len) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + memcpy(tfm->crt_cipher.cit_iv, src, len); +} + +static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm, + u8 *dst, unsigned int len) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); + memcpy(dst, tfm->crt_cipher.cit_iv, len); +} + +static inline int crypto_comp_compress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); + return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen); +} + +static inline int crypto_comp_decompress(struct crypto_tfm *tfm, + const u8 *src, unsigned int slen, + u8 *dst, unsigned int *dlen) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); + return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen); +} + +/* + * HMAC support. + */ +#ifdef CONFIG_CRYPTO_HMAC +void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen); +void crypto_hmac_update(struct crypto_tfm *tfm, + struct scatterlist *sg, unsigned int nsg); +void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, + unsigned int *keylen, u8 *out); +void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, + struct scatterlist *sg, unsigned int nsg, u8 *out); +#endif /* CONFIG_CRYPTO_HMAC */ + +#endif /* _LINUX_CRYPTO_H */ + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib.h @@ -0,0 +1,4206 @@ +/* + * Merged with mainline rtllib.h in Aug 2004. Original ieee802_11 + * remains copyright by the original authors + * + * Portions of the merged code are based on Host AP (software wireless + * LAN access point) driver for Intersil Prism2/2.5/3. + * + * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + * + * Copyright (c) 2002-2003, Jouni Malinen + * + * Adaption to a generic IEEE 802.11 stack by James Ketrenos + * + * Copyright (c) 2004, Intel Corporation + * + * Modified for Realtek's wi-fi cards by Andrea Merello + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See README and COPYING for + * more details. + */ +#ifndef RTLLIB_H +#define RTLLIB_H +#include /* ETH_ALEN */ +#include /* ARRAY_SIZE */ +#include +#include +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#include +#else +#include +#include +#endif +#include +#include + +#include +#include + +#ifdef CONFIG_CFG_80211 +#include +#endif + +#include "rtl819x_HT.h" +#include "rtl819x_BA.h" +#include "rtl819x_TS.h" + +#include +#include /* ARPHRD_ETHER */ + +#ifndef WIRELESS_SPY +#define WIRELESS_SPY +#endif +#include + +#if defined (RTL8192S_WAPI_SUPPORT) +#include "wapi.h" +#include "wapi_interface.h" +#endif + +#ifndef IEEE80211_RADIOTAP_F_BADFCS +#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* bad FCS */ +#endif + +#ifndef IW_MODE_MONITOR +#define IW_MODE_MONITOR 6 +#endif + +#ifndef IWEVCUSTOM +#define IWEVCUSTOM 0x8c02 +#endif + +#ifndef IW_CUSTOM_MAX +/* Max number of char in custom event - use multiple of them if needed */ +#define IW_CUSTOM_MAX 256 /* In bytes */ +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#define jiffies_to_msecs(t) ((t) * 1000 / HZ) +#ifndef __bitwise +#define __bitwise __attribute__((bitwise)) +#endif +typedef __u16 __le16; + +#if (WIRELESS_EXT < 16) +struct iw_spy_data{ + /* --- Standard spy support --- */ + int spy_number; + u_char spy_address[IW_MAX_SPY][ETH_ALEN]; + struct iw_quality spy_stat[IW_MAX_SPY]; + /* --- Enhanced spy support (event) */ + struct iw_quality spy_thr_low; /* Low threshold */ + struct iw_quality spy_thr_high; /* High threshold */ + u_char spy_thr_under[IW_MAX_SPY]; +}; +#endif +#endif + +#ifndef container_of +/** + * container_of - cast a member of a structure out to the containing structure + * + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) +#define skb_tail_pointer_rsl(skb) skb_tail_pointer(skb) +#else +#define skb_tail_pointer_rsl(skb) skb->tail +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) + #define EXPORT_SYMBOL_RSL(x) EXPORT_SYMBOL(x) +#else + #define EXPORT_SYMBOL_RSL(x) EXPORT_SYMBOL_NOVERS(x) +#endif +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +static inline void tq_init(struct tq_struct * task, void(*func)(void *), void *data) +{ + task->routine = func; + task->data = data; + INIT_LIST_HEAD(&task->list); + task->sync = 0; +} +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) +static inline void setup_timer(struct timer_list * timer, void(*function)(unsigned long), unsigned long data) +{ + timer->function = function; + timer->data = data; +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + typedef struct delayed_work delayed_work_struct_rsl; + #define queue_delayed_work_rsl(x,y,z) queue_delayed_work(x,y,z) + #define INIT_DELAYED_WORK_RSL(x,y,z) INIT_DELAYED_WORK(x,y) +#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,40) + typedef struct tq_struct delayed_work_struct_rsl; + #define queue_delayed_work_rsl(x,y,z) schedule_task(y) + #define INIT_DELAYED_WORK_RSL(x,y,z) tq_init(x,y,z) +#else + typedef struct work_struct delayed_work_struct_rsl; + #define queue_delayed_work_rsl(x,y,z) queue_delayed_work(x,y,z) + #define INIT_DELAYED_WORK_RSL(x,y,z) INIT_WORK(x,y,z) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + typedef struct work_struct work_struct_rsl; + #define queue_work_rsl(x,y) queue_work(x,y) + #define INIT_WORK_RSL(x,y,z) INIT_WORK(x,y) +#elif LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,40) + typedef struct tq_struct work_struct_rsl; + #define queue_work_rsl(x,y) schedule_task(y) + #define INIT_WORK_RSL(x,y,z) tq_init(x,y,z) +#else + typedef struct work_struct work_struct_rsl; + #define queue_work_rsl(x,y) queue_work(x,y) + #define INIT_WORK_RSL(x,y,z) INIT_WORK(x,y,z) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) + #define container_of_work_rsl(x,y,z) container_of(x,y,z) + #define container_of_dwork_rsl(x,y,z) container_of(container_of(x, struct delayed_work, work), y, z) +#else + #define container_of_work_rsl(x,y,z) (x) + #define container_of_dwork_rsl(x,y,z) (x) +#endif + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,20)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +static inline char * +iwe_stream_add_event_rsl(struct iw_request_info *info, + char * stream, /* Stream of events */ + char * ends, /* End of stream */ + struct iw_event *iwe, /* Payload */ + int event_len) /* Real size of payload */ +{ + /* Check if it's possible */ + if((stream + event_len) < ends) { + iwe->len = event_len; + ndelay(1); + memcpy(stream, (char *) iwe, event_len); + stream += event_len; + } + return stream; +} +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + #define iwe_stream_add_event_rsl(info,start,stop,iwe,len) iwe_stream_add_event(info,start,stop,iwe,len) +#else + #define iwe_stream_add_event_rsl(info,start,stop,iwe,len) iwe_stream_add_event(start,stop,iwe,len) +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + #define iwe_stream_add_point_rsl(info,start,stop,iwe,p) iwe_stream_add_point(info,start,stop,iwe,p) +#else + #define iwe_stream_add_point_rsl(info,start,stop,iwe,p) iwe_stream_add_point(start,stop,iwe,p) +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + #define usb_alloc_urb_rsl(x,y) usb_alloc_urb(x,y) + #define usb_submit_urb_rsl(x,y) usb_submit_urb(x,y) +#else + #define usb_alloc_urb_rsl(x,y) usb_alloc_urb(x) + #define usb_submit_urb_rsl(x,y) usb_submit_urb(x) +#endif + +static inline void *netdev_priv_rsl(struct net_device *dev) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + return netdev_priv(dev); +#else + return dev->priv; +#endif +} + +#define KEY_TYPE_NA 0x0 +#define KEY_TYPE_WEP40 0x1 +#define KEY_TYPE_TKIP 0x2 +#define KEY_TYPE_CCMP 0x4 +#define KEY_TYPE_WEP104 0x5 +#if defined (RTL8192S_WAPI_SUPPORT) +#define KEY_TYPE_SMS4 0x8 +#endif +/* added for rtl819x tx procedure */ +#define MAX_QUEUE_SIZE 0x10 + +#if defined(RTL8192SU) || defined(RTL8190P) ||defined(RTL8192U) ||defined(RTL8192E) +#define BK_QUEUE 0 +#define BE_QUEUE 1 +#define VI_QUEUE 2 +#define VO_QUEUE 3 +#define HCCA_QUEUE 4 +#define TXCMD_QUEUE 5 +#define MGNT_QUEUE 6 +#define HIGH_QUEUE 7 +#define BEACON_QUEUE 8 +#elif defined(RTL8192SE) +#define BK_QUEUE 0 +#define BE_QUEUE 1 +#define VI_QUEUE 2 +#define VO_QUEUE 3 +#define BEACON_QUEUE 4 +#define TXCMD_QUEUE 5 +#define MGNT_QUEUE 6 +#define HIGH_QUEUE 7 +#define HCCA_QUEUE 8 + +#elif defined(RTL8192CE) + +#define BK_QUEUE 0 +#define BE_QUEUE 1 +#define VI_QUEUE 2 +#define VO_QUEUE 3 +#define BEACON_QUEUE 4 +#define TXCMD_QUEUE 5 +#define MGNT_QUEUE 6 +#define HIGH_QUEUE 7 +#define HCCA_QUEUE 8 +#endif + +#ifdef RTL8192CE +#define LOW_QUEUE BE_QUEUE +#define NORMAL_QUEUE MGNT_QUEUE +#else +#define LOW_QUEUE BE_QUEUE +#define NORMAL_QUEUE MGNT_QUEUE +#endif + +#ifndef IW_MODE_MESH +#define IW_MODE_MESH 7 +#endif +#ifdef _RTL8192_EXT_PATCH_ +#define WIFI_MESH_TYPE RTLLIB_FTYPE_DATA + +#define WLAN_MESH_HDR_LEN 6 +#define WLAN_MESH_HDR_6ADDR_LEN 18 +#define WLAN_MESH_HDR_4ADDR_LEN 6 +#define MAX_MP 65 +#define IEEE_MESH_MAC_HASH_SIZE 31 +#define MAX_MESH_ID_LEN 33 +#define MAX_HOST_NAME_LENGTH 33 +#endif +#define AMSDU_SUBHEADER_LEN 14 +#define SWRF_TIMEOUT 50 + +#define IE_CISCO_FLAG_POSITION 0x08 +#define SUPPORT_CKIP_MIC 0x08 +#define SUPPORT_CKIP_PK 0x10 +#define RT_RF_OFF_LEVL_ASPM BIT0 +#define RT_RF_OFF_LEVL_CLK_REQ BIT1 +#define RT_RF_OFF_LEVL_PCI_D3 BIT2 +#define RT_RF_OFF_LEVL_HALT_NIC BIT3 +#define RT_RF_OFF_LEVL_FREE_FW BIT4 +#define RT_RF_OFF_LEVL_FW_32K BIT5 +#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT6 +#define RT_RF_LPS_DISALBE_2R BIT30 +#define RT_RF_LPS_LEVEL_ASPM BIT31 +#define RT_IN_PS_LEVEL(pPSC, _PS_FLAG) ((pPSC->CurPsLevel & _PS_FLAG) ? true : false) +#define RT_CLEAR_PS_LEVEL(pPSC, _PS_FLAG) (pPSC->CurPsLevel &= (~(_PS_FLAG))) +#define RT_SET_PS_LEVEL(pPSC, _PS_FLAG) (pPSC->CurPsLevel |= _PS_FLAG) + +#if defined (RTL8192S_WAPI_SUPPORT) +#define SMS4_MIC_LEN 16 +#define WAPI_EXT_LEN 18 +#define MAX_WAPI_IE_LEN 255 +#define sMacHdrLng 24 +#endif + +/* defined for skb cb field */ +/* At most 28 byte */ +typedef struct cb_desc { + /* Tx Desc Related flags (8-9) */ + u8 bLastIniPkt:1; + u8 bCmdOrInit:1; + u8 bFirstSeg:1; + u8 bLastSeg:1; + u8 bEncrypt:1; + u8 bTxDisableRateFallBack:1; + u8 bTxUseDriverAssingedRate:1; + u8 bHwSec:1; + + u8 nStuckCount; + + /* Tx Firmware Relaged flags (10-11)*/ + u8 bCTSEnable:1; + u8 bRTSEnable:1; + u8 bUseShortGI:1; + u8 bUseShortPreamble:1; + u8 bTxEnableFwCalcDur:1; + u8 bAMPDUEnable:1; + u8 bRTSSTBC:1; + u8 RTSSC:1; + + u8 bRTSBW:1; + u8 bPacketBW:1; + u8 bRTSUseShortPreamble:1; + u8 bRTSUseShortGI:1; + u8 bMulticast:1; + u8 bBroadcast:1; + u8 drv_agg_enable:1; +#ifdef _RTL8192_EXT_PATCH_ + u8 mesh_pkt:1; +#else + u8 reserved2:1; +#endif + + /* Tx Desc related element(12-19) */ + u8 rata_index; + u8 queue_index; + u16 txbuf_size; + u8 RATRIndex; +#ifdef _RTL8192_EXT_PATCH_ + u8 mesh_type:2; + u8 bFromAggrQ:1; + u8 bAMSDU:1; + u8 brelay_pkt:1; + u8 badhoc:1; + u8 bretry_pkt:1; + u8 bFromRx:1; +#else + u8 bAMSDU:1; + u8 bFromAggrQ:1; + u8 reserved6:6; +#endif + u8 macId; + u8 priority; + + /* Tx firmware related element(20-27) */ + u8 data_rate; + u8 rts_rate; + u8 ampdu_factor; + u8 ampdu_density; + u8 DrvAggrNum; + u8 bdhcp; + u16 pkt_size; + u8 bIsSpecialDataFrame; + + u8 DescPktType; + + u8 bBTTxPacket; + u8 bIsBTProbRsp; + u8 bRxBTdata; +}cb_desc, *pcb_desc; + +/*--------------------------Define -------------------------------------------*/ +#define MGN_1M 0x02 +#define MGN_2M 0x04 +#define MGN_5_5M 0x0b +#define MGN_11M 0x16 + +#define MGN_6M 0x0c +#define MGN_9M 0x12 +#define MGN_12M 0x18 +#define MGN_18M 0x24 +#define MGN_24M 0x30 +#define MGN_36M 0x48 +#define MGN_48M 0x60 +#define MGN_54M 0x6c + +#define MGN_MCS0 0x80 +#define MGN_MCS1 0x81 +#define MGN_MCS2 0x82 +#define MGN_MCS3 0x83 +#define MGN_MCS4 0x84 +#define MGN_MCS5 0x85 +#define MGN_MCS6 0x86 +#define MGN_MCS7 0x87 +#define MGN_MCS8 0x88 +#define MGN_MCS9 0x89 +#define MGN_MCS10 0x8a +#define MGN_MCS11 0x8b +#define MGN_MCS12 0x8c +#define MGN_MCS13 0x8d +#define MGN_MCS14 0x8e +#define MGN_MCS15 0x8f +#define MGN_MCS0_SG 0x90 +#define MGN_MCS1_SG 0x91 +#define MGN_MCS2_SG 0x92 +#define MGN_MCS3_SG 0x93 +#define MGN_MCS4_SG 0x94 +#define MGN_MCS5_SG 0x95 +#define MGN_MCS6_SG 0x96 +#define MGN_MCS7_SG 0x97 +#define MGN_MCS8_SG 0x98 +#define MGN_MCS9_SG 0x99 +#define MGN_MCS10_SG 0x9a +#define MGN_MCS11_SG 0x9b +#define MGN_MCS12_SG 0x9c +#define MGN_MCS13_SG 0x9d +#define MGN_MCS14_SG 0x9e +#define MGN_MCS15_SG 0x9f + + +enum _ReasonCode{ + unspec_reason = 0x1, + auth_not_valid = 0x2, + deauth_lv_ss = 0x3, + inactivity = 0x4, + ap_overload = 0x5, + class2_err = 0x6, + class3_err = 0x7, + disas_lv_ss = 0x8, + asoc_not_auth = 0x9, + + mic_failure = 0xe, + + invalid_IE = 0x0d, + four_way_tmout = 0x0f, + two_way_tmout = 0x10, + IE_dismatch = 0x11, + invalid_Gcipher = 0x12, + invalid_Pcipher = 0x13, + invalid_AKMP = 0x14, + unsup_RSNIEver = 0x15, + invalid_RSNIE = 0x16, + auth_802_1x_fail= 0x17, + ciper_reject = 0x18, + + QoS_unspec = 0x20, + QAP_bandwidth = 0x21, + poor_condition = 0x22, + no_facility = 0x23, + req_declined = 0x25, + invalid_param = 0x26, + req_not_honored= 0x27, + TS_not_created = 0x2F, + DL_not_allowed = 0x30, + dest_not_exist = 0x31, + dest_not_QSTA = 0x32, +}; + +typedef enum _HAL_DEF_VARIABLE{ + HAL_DEF_TPC_ENABLE, + HAL_DEF_INIT_GAIN, + HAL_DEF_PROT_IMP_MODE, + HAL_DEF_HIGH_POWER_MECHANISM, + HAL_DEF_RATE_ADAPTIVE_MECHANISM, + HAL_DEF_ANTENNA_DIVERSITY_MECHANISM, + HAL_DEF_LED, + HAL_DEF_CW_MAX_MIN, + + HAL_DEF_WOWLAN, + HAL_DEF_ENDPOINTS, + HAL_DEF_MIN_TX_POWER_DBM, + HAL_DEF_MAX_TX_POWER_DBM, + HW_DEF_EFUSE_REPG_SECTION1_FLAG, + HW_DEF_EFUSE_REPG_DATA, + HW_DEF_GPIO, + HAL_DEF_PCI_SUPPORT_ASPM, + HAL_DEF_PCI_SUUPORT_L1_BACKDOOR, + HAL_DEF_THERMAL_VALUE, + HAL_DEF_USB_IN_TOKEN_REV, +}HAL_DEF_VARIABLE; + + +typedef enum _HW_VARIABLES{ + HW_VAR_ETHER_ADDR, + HW_VAR_MULTICAST_REG, + HW_VAR_BASIC_RATE, + HW_VAR_BSSID, + HW_VAR_MEDIA_STATUS, + HW_VAR_SECURITY_CONF, + HW_VAR_BEACON_INTERVAL, + HW_VAR_ATIM_WINDOW, + HW_VAR_LISTEN_INTERVAL, + HW_VAR_CS_COUNTER, + HW_VAR_DEFAULTKEY0, + HW_VAR_DEFAULTKEY1, + HW_VAR_DEFAULTKEY2, + HW_VAR_DEFAULTKEY3, + HW_VAR_SIFS, + HW_VAR_DIFS, + HW_VAR_EIFS, + HW_VAR_SLOT_TIME, + HW_VAR_ACK_PREAMBLE, + HW_VAR_CW_CONFIG, + HW_VAR_CW_VALUES, + HW_VAR_RATE_FALLBACK_CONTROL, + HW_VAR_CONTENTION_WINDOW, + HW_VAR_RETRY_COUNT, + HW_VAR_TR_SWITCH, + HW_VAR_COMMAND, + HW_VAR_WPA_CONFIG, + HW_VAR_AMPDU_MIN_SPACE, + HW_VAR_SHORTGI_DENSITY, + HW_VAR_AMPDU_FACTOR, + HW_VAR_MCS_RATE_AVAILABLE, + HW_VAR_AC_PARAM, + HW_VAR_ACM_CTRL, + HW_VAR_DIS_Req_Qsize, + HW_VAR_CCX_CHNL_LOAD, + HW_VAR_CCX_NOISE_HISTOGRAM, + HW_VAR_CCX_CLM_NHM, + HW_VAR_TxOPLimit, + HW_VAR_TURBO_MODE, + HW_VAR_RF_STATE, + HW_VAR_RF_OFF_BY_HW, + HW_VAR_BUS_SPEED, + HW_VAR_SET_DEV_POWER, + + HW_VAR_RCR, + HW_VAR_RATR_0, + HW_VAR_RRSR, + HW_VAR_CPU_RST, + HW_VAR_CECHK_BSSID, + HW_VAR_LBK_MODE, + HW_VAR_AES_11N_FIX, + HW_VAR_USB_RX_AGGR, + HW_VAR_USER_CONTROL_TURBO_MODE, + HW_VAR_RETRY_LIMIT, + HW_VAR_INIT_TX_RATE, + HW_VAR_TX_RATE_REG, + HW_VAR_EFUSE_USAGE, + HW_VAR_EFUSE_BYTES, + HW_VAR_AUTOLOAD_STATUS, + HW_VAR_RF_2R_DISABLE, + HW_VAR_SET_RPWM, + HW_VAR_H2C_FW_PWRMODE, + HW_VAR_H2C_FW_JOINBSSRPT, + HW_VAR_1X1_RECV_COMBINE, + HW_VAR_STOP_SEND_BEACON, + HW_VAR_TSF_TIMER, + HW_VAR_IO_CMD, + + HW_VAR_RF_RECOVERY, + HW_VAR_H2C_FW_UPDATE_GTK, + HW_VAR_WF_MASK, + HW_VAR_WF_CRC, + HW_VAR_WF_IS_MAC_ADDR, + HW_VAR_H2C_FW_OFFLOAD, + HW_VAR_RESET_WFCRC, + + HW_VAR_HANDLE_FW_C2H, + HW_VAR_DL_FW_RSVD_PAGE, + HW_VAR_AID, + HW_VAR_HW_SEQ_ENABLE, + HW_VAR_CORRECT_TSF, + HW_VAR_BCN_VALID, + HW_VAR_FWLPS_RF_ON, + HW_VAR_DUAL_TSF_RST, + HW_VAR_SWITCH_EPHY_WoWLAN, + HW_VAR_INT_MIGRATION, + HW_VAR_INT_AC, + HW_VAR_RF_TIMING, + + HW_VAR_MRC, +}HW_VARIABLES; + +typedef enum _RT_OP_MODE{ + RT_OP_MODE_AP, + RT_OP_MODE_INFRASTRUCTURE, + RT_OP_MODE_IBSS, + RT_OP_MODE_NO_LINK, +}RT_OP_MODE, *PRT_OP_MODE; + + +#define aSifsTime (((priv->rtllib->current_network.mode == IEEE_A)||(priv->rtllib->current_network.mode == IEEE_N_24G)||(priv->rtllib->current_network.mode == IEEE_N_5G))? 16 : 10) + +#define MGMT_QUEUE_NUM 5 + +#define IEEE_CMD_SET_WPA_PARAM 1 +#define IEEE_CMD_SET_WPA_IE 2 +#define IEEE_CMD_SET_ENCRYPTION 3 +#define IEEE_CMD_MLME 4 + +#define IEEE_PARAM_WPA_ENABLED 1 +#define IEEE_PARAM_TKIP_COUNTERMEASURES 2 +#define IEEE_PARAM_DROP_UNENCRYPTED 3 +#define IEEE_PARAM_PRIVACY_INVOKED 4 +#define IEEE_PARAM_AUTH_ALGS 5 +#define IEEE_PARAM_IEEE_802_1X 6 +#define IEEE_PARAM_WPAX_SELECT 7 +#define IEEE_PROTO_WPA 1 +#define IEEE_PROTO_RSN 2 +#define IEEE_WPAX_USEGROUP 0 +#define IEEE_WPAX_WEP40 1 +#define IEEE_WPAX_TKIP 2 +#define IEEE_WPAX_WRAP 3 +#define IEEE_WPAX_CCMP 4 +#define IEEE_WPAX_WEP104 5 + +#define IEEE_KEY_MGMT_IEEE8021X 1 +#define IEEE_KEY_MGMT_PSK 2 + +#define IEEE_MLME_STA_DEAUTH 1 +#define IEEE_MLME_STA_DISASSOC 2 + + +#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2 +#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3 +#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4 +#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5 +#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6 +#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7 +#define IEEE_CRYPT_ALG_NAME_LEN 16 + +#define MAX_IE_LEN 0xff +#ifdef _RTL8192_EXT_PATCH_ +#define ENABLE_NULL_PT_DEBUG +#endif +#ifdef ENABLE_NULL_PT_DEBUG +#define RT_ASSERT_RET(_Exp) \ + if(!(_Exp)) \ + { \ + printk("Rtl819x: "); \ + printk( "Assertion failed! %s,%s,line=%d\n", \ + #_Exp,__FUNCTION__,__LINE__); \ + return; \ + } +#define RT_ASSERT_RET_VALUE(_Exp,Ret) \ + if(!(_Exp)) \ + { \ + printk("Rtl819x: "); \ + printk( "Assertion failed! %s,%s,line=%d\n", \ + #_Exp,__FUNCTION__,__LINE__); \ + return (Ret); \ + } +#else +#define RT_ASSERT_RET(_Exp) do {} while(0) +#define RT_ASSERT_RET_VALUE(_Exp,Ret) do {} while(0) +#endif + +typedef struct ieee_param { + u32 cmd; + u8 sta_addr[ETH_ALEN]; + union { + struct { + u8 name; + u32 value; + } wpa_param; + struct { + u32 len; + u8 reserved[32]; + u8 data[0]; + } wpa_ie; + struct{ + int command; + int reason_code; + } mlme; + struct { + u8 alg[IEEE_CRYPT_ALG_NAME_LEN]; + u8 set_tx; + u32 err; + u8 idx; + u8 seq[8]; /* sequence counter (set: RX, get: TX) */ + u16 key_len; + u8 key[0]; + } crypt; + } u; +}ieee_param; + + +#if WIRELESS_EXT < 17 +#define IW_QUAL_QUAL_INVALID 0x10 +#define IW_QUAL_LEVEL_INVALID 0x20 +#define IW_QUAL_NOISE_INVALID 0x40 +#define IW_QUAL_QUAL_UPDATED 0x1 +#define IW_QUAL_LEVEL_UPDATED 0x2 +#define IW_QUAL_NOISE_UPDATED 0x4 +#endif + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)) +#define MSECS(t) (HZ * ((t) / 1000) + (HZ * ((t) % 1000)) / 1000) +static inline unsigned long msleep_interruptible_rsl(unsigned int msecs) +{ + unsigned long timeout = MSECS(msecs) + 1; + + while (timeout) { + set_current_state(TASK_INTERRUPTIBLE); + timeout = schedule_timeout(timeout); + } + return timeout; +} + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,31)) +static inline void msleep(unsigned int msecs) +{ + unsigned long timeout = MSECS(msecs) + 1; + + while (timeout) { + set_current_state(TASK_UNINTERRUPTIBLE); + timeout = schedule_timeout(timeout); + } +} +#endif +#else +#define MSECS(t) msecs_to_jiffies(t) +#define msleep_interruptible_rsl msleep_interruptible +#endif + +#define RTLLIB_DATA_LEN 2304 +/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section + 6.2.1.1.2. + + The figure in section 7.1.2 suggests a body size of up to 2312 + bytes is allowed, which is a bit confusing, I suspect this + represents the 2304 bytes of real data, plus a possible 8 bytes of + WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ +#define RTLLIB_1ADDR_LEN 10 +#define RTLLIB_2ADDR_LEN 16 +#define RTLLIB_3ADDR_LEN 24 +#define RTLLIB_4ADDR_LEN 30 +#define RTLLIB_FCS_LEN 4 +#define RTLLIB_HLEN (RTLLIB_4ADDR_LEN) +#define RTLLIB_FRAME_LEN (RTLLIB_DATA_LEN + RTLLIB_HLEN) +#define RTLLIB_MGMT_HDR_LEN 24 +#define RTLLIB_DATA_HDR3_LEN 24 +#define RTLLIB_DATA_HDR4_LEN 30 + +#define RTLLIB_SKBBUFFER_SIZE 2500 + +#define MIN_FRAG_THRESHOLD 256U +#define MAX_FRAG_THRESHOLD 2346U +#define MAX_HT_DATA_FRAG_THRESHOLD 0x2000 + +#define HT_AMSDU_SIZE_4K 3839 +#define HT_AMSDU_SIZE_8K 7935 + +/* Frame control field constants */ +#define RTLLIB_FCTL_VERS 0x0003 +#define RTLLIB_FCTL_FTYPE 0x000c +#define RTLLIB_FCTL_STYPE 0x00f0 +#define RTLLIB_FCTL_FRAMETYPE 0x00fc +#define RTLLIB_FCTL_TODS 0x0100 +#define RTLLIB_FCTL_FROMDS 0x0200 +#define RTLLIB_FCTL_DSTODS 0x0300 +#define RTLLIB_FCTL_MOREFRAGS 0x0400 +#define RTLLIB_FCTL_RETRY 0x0800 +#define RTLLIB_FCTL_PM 0x1000 +#define RTLLIB_FCTL_MOREDATA 0x2000 +#define RTLLIB_FCTL_WEP 0x4000 +#define RTLLIB_FCTL_ORDER 0x8000 + +#define RTLLIB_FTYPE_MGMT 0x0000 +#define RTLLIB_FTYPE_CTL 0x0004 +#define RTLLIB_FTYPE_DATA 0x0008 + +/* management */ +#define RTLLIB_STYPE_ASSOC_REQ 0x0000 +#define RTLLIB_STYPE_ASSOC_RESP 0x0010 +#define RTLLIB_STYPE_REASSOC_REQ 0x0020 +#define RTLLIB_STYPE_REASSOC_RESP 0x0030 +#define RTLLIB_STYPE_PROBE_REQ 0x0040 +#define RTLLIB_STYPE_PROBE_RESP 0x0050 +#define RTLLIB_STYPE_BEACON 0x0080 +#define RTLLIB_STYPE_ATIM 0x0090 +#define RTLLIB_STYPE_DISASSOC 0x00A0 +#define RTLLIB_STYPE_AUTH 0x00B0 +#define RTLLIB_STYPE_DEAUTH 0x00C0 +#define RTLLIB_STYPE_MANAGE_ACT 0x00D0 +#ifdef _RTL8192_EXT_PATCH_ +/* added for mesh action frame type */ +#ifdef COMPATIBLE_WITH_RALINK_MESH +#define RTLLIB_STYPE_MESH_ACT 0x00F0 +#else +#define RTLLIB_STYPE_MESH_ACT RTLLIB_STYPE_MANAGE_ACT +#endif +#endif + +/* control */ +#define RTLLIB_STYPE_PSPOLL 0x00A0 +#define RTLLIB_STYPE_RTS 0x00B0 +#define RTLLIB_STYPE_CTS 0x00C0 +#define RTLLIB_STYPE_ACK 0x00D0 +#define RTLLIB_STYPE_CFEND 0x00E0 +#define RTLLIB_STYPE_CFENDACK 0x00F0 +#define RTLLIB_STYPE_BLOCKACK 0x0094 + +/* data */ +#define RTLLIB_STYPE_DATA 0x0000 +#define RTLLIB_STYPE_DATA_CFACK 0x0010 +#define RTLLIB_STYPE_DATA_CFPOLL 0x0020 +#define RTLLIB_STYPE_DATA_CFACKPOLL 0x0030 +#define RTLLIB_STYPE_NULLFUNC 0x0040 +#define RTLLIB_STYPE_CFACK 0x0050 +#define RTLLIB_STYPE_CFPOLL 0x0060 +#define RTLLIB_STYPE_CFACKPOLL 0x0070 +#define RTLLIB_STYPE_QOS_DATA 0x0080 +#define RTLLIB_STYPE_QOS_NULL 0x00C0 + +#define RTLLIB_SCTL_FRAG 0x000F +#define RTLLIB_SCTL_SEQ 0xFFF0 + +/* QOS control */ +#define RTLLIB_QCTL_TID 0x000F + +#define FC_QOS_BIT BIT7 +#define IsDataFrame(pdu) ( ((pdu[0] & 0x0C)==0x08) ? true : false ) +#define IsLegacyDataFrame(pdu) (IsDataFrame(pdu) && (!(pdu[0]&FC_QOS_BIT)) ) +#define IsQoSDataFrame(pframe) ((*(u16*)pframe&(RTLLIB_STYPE_QOS_DATA|RTLLIB_FTYPE_DATA)) == (RTLLIB_STYPE_QOS_DATA|RTLLIB_FTYPE_DATA)) +#define Frame_Order(pframe) (*(u16*)pframe&RTLLIB_FCTL_ORDER) +#define SN_LESS(a, b) (((a-b)&0x800)!=0) +#define SN_EQUAL(a, b) (a == b) +#define MAX_DEV_ADDR_SIZE 8 + +typedef enum _ACT_CATEGORY{ + ACT_CAT_QOS = 1, + ACT_CAT_DLS = 2, + ACT_CAT_BA = 3, + ACT_CAT_HT = 7, + ACT_CAT_WMM = 17, +#ifdef _RTL8192_EXT_PATCH_ + ACT_CAT_MESH_PEERLINK_MGNT = 0x0f, + ACT_CAT_MESH_LINK_METRIC = 0x10, + ACT_CAT_MESH_PATH_SELECT = 0x11, + ACT_CAT_MESH_INTERWORKING = 0x12, + ACT_CAT_MESH_SECURITY_INFO = 35, +#endif +} ACT_CATEGORY, *PACT_CATEGORY; + +typedef enum _TS_ACTION{ + ACT_ADDTSREQ = 0, + ACT_ADDTSRSP = 1, + ACT_DELTS = 2, + ACT_SCHEDULE = 3, +} TS_ACTION, *PTS_ACTION; + +typedef enum _BA_ACTION{ + ACT_ADDBAREQ = 0, + ACT_ADDBARSP = 1, + ACT_DELBA = 2, +} BA_ACTION, *PBA_ACTION; +#ifdef _RTL8192_EXT_PATCH_ +typedef enum _PEERLINK_ACTION{ + ACT_PEERLINK_OPEN = 0, + ACT_PEERLINK_CONFIRM = 1, + ACT_PEERLINK_CLOSE =2, +} PEERLINK_ACTION, *PPEERLINK_ACTION; + +typedef enum _LINK_METRIC_ACTION{ + ACT_LINKMETRIC_REQ = 0, + ACT_LINKMETRIC_RSP = 1, +} LINK_METRIC_ACTION, *PLINK_METRIC_ACTION; + +typedef enum _PATH_SELECT_ACTION{ + ACT_PATH_REQ = 0, + ACT_PATH_REPLY = 1, + ACT_PATH_ERR =2, + ACT_RANN =3, +} PATH_SELECT_ACTION, *PPATH_SELECT_ACTION; + +typedef enum _MESH_PEERING_PROTOCOL_VERSION_VALUE{ + Mesh_Peering_Management_Protocol_V =42, + Abbreviated_Handshake_Protocol_V = 43, +}MESH_PEERING_PROTOCOL_VERSION_VALUE; +#endif + +typedef enum _InitialGainOpType{ + IG_Backup=0, + IG_Restore, + IG_Max +}InitialGainOpType; +typedef enum _LED_CTL_MODE{ + LED_CTL_POWER_ON = 1, + LED_CTL_LINK = 2, + LED_CTL_NO_LINK = 3, + LED_CTL_TX = 4, + LED_CTL_RX = 5, + LED_CTL_SITE_SURVEY = 6, + LED_CTL_POWER_OFF = 7, + LED_CTL_START_TO_LINK = 8, + LED_CTL_START_WPS = 9, + LED_CTL_STOP_WPS = 10, + LED_CTL_START_WPS_BOTTON = 11, + LED_CTL_STOP_WPS_FAIL = 12, + LED_CTL_STOP_WPS_FAIL_OVERLAP = 13, +}LED_CTL_MODE; + +typedef enum _RT_RF_TYPE_DEF +{ + RF_1T2R = 0, + RF_2T4R, + RF_2T2R, + RF_1T1R, + RF_2T2R_GREEN, + RF_819X_MAX_TYPE +}RT_RF_TYPE_DEF; + +typedef enum _WIRELESS_MODE { + WIRELESS_MODE_UNKNOWN = 0x00, + WIRELESS_MODE_A = 0x01, + WIRELESS_MODE_B = 0x02, + WIRELESS_MODE_G = 0x04, + WIRELESS_MODE_AUTO = 0x08, + WIRELESS_MODE_N_24G = 0x10, + WIRELESS_MODE_N_5G = 0x20 +} WIRELESS_MODE; + +typedef enum _NETWORK_TYPE{ + WIRELESS_11B = 1, + WIRELESS_11G = 2, + WIRELESS_11A = 4, + WIRELESS_11N = 8 +} WIRELESS_NETWORK_TYPE; + +#define OUI_SUBTYPE_WMM_INFO 0 +#define OUI_SUBTYPE_WMM_PARAM 1 +#define OUI_SUBTYPE_QOS_CAPABI 5 + +/* debug macros */ +#define CONFIG_RTLLIB_DEBUG +#ifdef CONFIG_RTLLIB_DEBUG +extern u32 rtllib_debug_level; +#define RTLLIB_DEBUG(level, fmt, args...) \ +do { if (rtllib_debug_level & (level)) \ + printk(KERN_DEBUG "rtllib: " fmt, ## args); } while (0) +#define RTLLIB_DEBUG_DATA(level, data, datalen) \ + do{ if ((rtllib_debug_level & (level)) == (level)) \ + { \ + int i; \ + u8* pdata = (u8*) data; \ + printk(KERN_DEBUG "rtllib: %s()\n", __FUNCTION__); \ + for(i=0; i<(int)(datalen); i++) \ + { \ + printk("%2.2x ", pdata[i]); \ + if ((i+1)%16 == 0) printk("\n"); \ + } \ + printk("\n"); \ + } \ + } while (0) +#else +#define RTLLIB_DEBUG(level, fmt, args...) do {} while (0) +#define RTLLIB_DEBUG_DATA(level, data, datalen) do {} while(0) +#endif /* CONFIG_RTLLIB_DEBUG */ + +/* debug macros not dependent on CONFIG_RTLLIB_DEBUG */ + +#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5] + +/* + * To use the debug system; + * + * If you are defining a new debug classification, simply add it to the #define + * list here in the form of: + * + * #define RTLLIB_DL_xxxx VALUE + * + * shifting value to the left one bit from the previous entry. xxxx should be + * the name of the classification (for example, WEP) + * + * You then need to either add a RTLLIB_xxxx_DEBUG() macro definition for your + * classification, or use RTLLIB_DEBUG(RTLLIB_DL_xxxx, ...) whenever you want + * to send output to that classification. + * + * To add your debug level to the list of levels seen when you perform + * + * % cat /proc/net/ipw/debug_level + * + * you simply need to add your entry to the ipw_debug_levels array. + * + * If you do not see debug_level in /proc/net/ipw then you do not have + * CONFIG_RTLLIB_DEBUG defined in your kernel configuration + * + */ + +#define RTLLIB_DL_INFO (1<<0) +#define RTLLIB_DL_WX (1<<1) +#define RTLLIB_DL_SCAN (1<<2) +#define RTLLIB_DL_STATE (1<<3) +#define RTLLIB_DL_MGMT (1<<4) +#define RTLLIB_DL_FRAG (1<<5) +#define RTLLIB_DL_EAP (1<<6) +#define RTLLIB_DL_DROP (1<<7) + +#define RTLLIB_DL_TX (1<<8) +#define RTLLIB_DL_RX (1<<9) + +#define RTLLIB_DL_HT (1<<10) +#define RTLLIB_DL_BA (1<<11) +#define RTLLIB_DL_TS (1<<12) +#define RTLLIB_DL_QOS (1<<13) +#define RTLLIB_DL_REORDER (1<<14) +#define RTLLIB_DL_IOT (1<<15) +#define RTLLIB_DL_IPS (1<<16) +#define RTLLIB_DL_TRACE (1<<29) +#define RTLLIB_DL_DATA (1<<30) +#define RTLLIB_DL_ERR (1<<31) +#define RTLLIB_ERROR(f, a...) printk(KERN_ERR "rtllib: " f, ## a) +#define RTLLIB_WARNING(f, a...) printk(KERN_WARNING "rtllib: " f, ## a) +#define RTLLIB_DEBUG_INFO(f, a...) RTLLIB_DEBUG(RTLLIB_DL_INFO, f, ## a) + +#define RTLLIB_DEBUG_WX(f, a...) RTLLIB_DEBUG(RTLLIB_DL_WX, f, ## a) +#define RTLLIB_DEBUG_SCAN(f, a...) RTLLIB_DEBUG(RTLLIB_DL_SCAN, f, ## a) +#define RTLLIB_DEBUG_STATE(f, a...) RTLLIB_DEBUG(RTLLIB_DL_STATE, f, ## a) +#define RTLLIB_DEBUG_MGMT(f, a...) RTLLIB_DEBUG(RTLLIB_DL_MGMT, f, ## a) +#define RTLLIB_DEBUG_FRAG(f, a...) RTLLIB_DEBUG(RTLLIB_DL_FRAG, f, ## a) +#define RTLLIB_DEBUG_EAP(f, a...) RTLLIB_DEBUG(RTLLIB_DL_EAP, f, ## a) +#define RTLLIB_DEBUG_DROP(f, a...) RTLLIB_DEBUG(RTLLIB_DL_DROP, f, ## a) +#define RTLLIB_DEBUG_TX(f, a...) RTLLIB_DEBUG(RTLLIB_DL_TX, f, ## a) +#define RTLLIB_DEBUG_RX(f, a...) RTLLIB_DEBUG(RTLLIB_DL_RX, f, ## a) +#define RTLLIB_DEBUG_QOS(f, a...) RTLLIB_DEBUG(RTLLIB_DL_QOS, f, ## a) + +#ifdef CONFIG_RTLLIB_DEBUG +/* Added by Annie, 2005-11-22. */ +#define MAX_STR_LEN 64 +/* I want to see ASCII 33 to 126 only. Otherwise, I print '?'. Annie, 2005-11-22.*/ +#define PRINTABLE(_ch) (_ch>'!' && _ch<'~') +#define RTLLIB_PRINT_STR(_Comp, _TitleString, _Ptr, _Len) \ + if((_Comp) & level) \ + { \ + int __i; \ + u8 buffer[MAX_STR_LEN]; \ + int length = (_Len\n", _Len, buffer); \ + } +#else +#define RTLLIB_PRINT_STR(_Comp, _TitleString, _Ptr, _Len) do {} while (0) +#endif + +#ifndef ETH_P_PAE +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#define ETH_P_IP 0x0800 /* Internet Protocol packet */ +#define ETH_P_ARP 0x0806 /* Address Resolution packet */ +#endif /* ETH_P_PAE */ + +#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ + +#ifndef ETH_P_80211_RAW +#define ETH_P_80211_RAW (ETH_P_ECONET + 1) +#endif + +/* IEEE 802.11 defines */ + +#define P80211_OUI_LEN 3 + +struct rtllib_snap_hdr { + + u8 dsap; /* always 0xAA */ + u8 ssap; /* always 0xAA */ + u8 ctrl; /* always 0x03 */ + u8 oui[P80211_OUI_LEN]; /* organizational universal id */ + +} __attribute__ ((packed)); + +enum _REG_PREAMBLE_MODE{ + PREAMBLE_LONG = 1, + PREAMBLE_AUTO = 2, + PREAMBLE_SHORT= 3, +}; + +#define SNAP_SIZE sizeof(struct rtllib_snap_hdr) + +#define WLAN_FC_GET_VERS(fc) ((fc) & RTLLIB_FCTL_VERS) +#define WLAN_FC_GET_TYPE(fc) ((fc) & RTLLIB_FCTL_FTYPE) +#define WLAN_FC_GET_STYPE(fc) ((fc) & RTLLIB_FCTL_STYPE) +#define WLAN_FC_MORE_DATA(fc) ((fc) & RTLLIB_FCTL_MOREDATA) + +#define WLAN_FC_GET_FRAMETYPE(fc) ((fc) & RTLLIB_FCTL_FRAMETYPE) +#define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTLLIB_SCTL_FRAG) +#define WLAN_GET_SEQ_SEQ(seq) (((seq) & RTLLIB_SCTL_SEQ) >> 4) + +#ifndef CONFIG_CFG_80211 +/* Authentication algorithms */ +#define WLAN_AUTH_OPEN 0 +#define WLAN_AUTH_SHARED_KEY 1 +#define WLAN_AUTH_LEAP 128 + +#define WLAN_AUTH_CHALLENGE_LEN 128 + +#define WLAN_CAPABILITY_ESS (1<<0) +#define WLAN_CAPABILITY_IBSS (1<<1) +#define WLAN_CAPABILITY_CF_POLLABLE (1<<2) +#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) +#define WLAN_CAPABILITY_PRIVACY (1<<4) +#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) +#define WLAN_CAPABILITY_PBCC (1<<6) +#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) +#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) +#define WLAN_CAPABILITY_QOS (1<<9) +#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) +#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) + +/* 802.11g ERP information element */ +#define WLAN_ERP_NON_ERP_PRESENT (1<<0) +#define WLAN_ERP_USE_PROTECTION (1<<1) +#define WLAN_ERP_BARKER_PREAMBLE (1<<2) + +/* Status codes */ +enum rtllib_statuscode { + WLAN_STATUS_SUCCESS = 0, + WLAN_STATUS_UNSPECIFIED_FAILURE = 1, + WLAN_STATUS_CAPS_UNSUPPORTED = 10, + WLAN_STATUS_REASSOC_NO_ASSOC = 11, + WLAN_STATUS_ASSOC_DENIED_UNSPEC = 12, + WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG = 13, + WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION = 14, + WLAN_STATUS_CHALLENGE_FAIL = 15, + WLAN_STATUS_AUTH_TIMEOUT = 16, + WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17, + WLAN_STATUS_ASSOC_DENIED_RATES = 18, + /* 802.11b */ + WLAN_STATUS_ASSOC_DENIED_NOSHORTPREAMBLE = 19, + WLAN_STATUS_ASSOC_DENIED_NOPBCC = 20, + WLAN_STATUS_ASSOC_DENIED_NOAGILITY = 21, + /* 802.11h */ + WLAN_STATUS_ASSOC_DENIED_NOSPECTRUM = 22, + WLAN_STATUS_ASSOC_REJECTED_BAD_POWER = 23, + WLAN_STATUS_ASSOC_REJECTED_BAD_SUPP_CHAN = 24, + /* 802.11g */ + WLAN_STATUS_ASSOC_DENIED_NOSHORTTIME = 25, + WLAN_STATUS_ASSOC_DENIED_NODSSSOFDM = 26, + /* 802.11i */ + WLAN_STATUS_INVALID_IE = 40, + WLAN_STATUS_INVALID_GROUP_CIPHER = 41, + WLAN_STATUS_INVALID_PAIRWISE_CIPHER = 42, + WLAN_STATUS_INVALID_AKMP = 43, + WLAN_STATUS_UNSUPP_RSN_VERSION = 44, + WLAN_STATUS_INVALID_RSN_IE_CAP = 45, + WLAN_STATUS_CIPHER_SUITE_REJECTED = 46, +}; + +/* Reason codes */ +enum rtllib_reasoncode { + WLAN_REASON_UNSPECIFIED = 1, + WLAN_REASON_PREV_AUTH_NOT_VALID = 2, + WLAN_REASON_DEAUTH_LEAVING = 3, + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY = 4, + WLAN_REASON_DISASSOC_AP_BUSY = 5, + WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA = 6, + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA = 7, + WLAN_REASON_DISASSOC_STA_HAS_LEFT = 8, + WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH = 9, + /* 802.11h */ + WLAN_REASON_DISASSOC_BAD_POWER = 10, + WLAN_REASON_DISASSOC_BAD_SUPP_CHAN = 11, + /* 802.11i */ + WLAN_REASON_INVALID_IE = 13, + WLAN_REASON_MIC_FAILURE = 14, + WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT = 15, + WLAN_REASON_GROUP_KEY_HANDSHAKE_TIMEOUT = 16, + WLAN_REASON_IE_DIFFERENT = 17, + WLAN_REASON_INVALID_GROUP_CIPHER = 18, + WLAN_REASON_INVALID_PAIRWISE_CIPHER = 19, + WLAN_REASON_INVALID_AKMP = 20, + WLAN_REASON_UNSUPP_RSN_VERSION = 21, + WLAN_REASON_INVALID_RSN_IE_CAP = 22, + WLAN_REASON_IEEE8021X_FAILED = 23, + WLAN_REASON_CIPHER_SUITE_REJECTED = 24, +}; +#endif + +#define RTLLIB_STATMASK_SIGNAL (1<<0) +#define RTLLIB_STATMASK_RSSI (1<<1) +#define RTLLIB_STATMASK_NOISE (1<<2) +#define RTLLIB_STATMASK_RATE (1<<3) +#define RTLLIB_STATMASK_WEMASK 0x7 + +#define RTLLIB_CCK_MODULATION (1<<0) +#define RTLLIB_OFDM_MODULATION (1<<1) + +#define RTLLIB_24GHZ_BAND (1<<0) +#define RTLLIB_52GHZ_BAND (1<<1) + +#define RTLLIB_CCK_RATE_LEN 4 +#define RTLLIB_CCK_RATE_1MB 0x02 +#define RTLLIB_CCK_RATE_2MB 0x04 +#define RTLLIB_CCK_RATE_5MB 0x0B +#define RTLLIB_CCK_RATE_11MB 0x16 +#define RTLLIB_OFDM_RATE_LEN 8 +#define RTLLIB_OFDM_RATE_6MB 0x0C +#define RTLLIB_OFDM_RATE_9MB 0x12 +#define RTLLIB_OFDM_RATE_12MB 0x18 +#define RTLLIB_OFDM_RATE_18MB 0x24 +#define RTLLIB_OFDM_RATE_24MB 0x30 +#define RTLLIB_OFDM_RATE_36MB 0x48 +#define RTLLIB_OFDM_RATE_48MB 0x60 +#define RTLLIB_OFDM_RATE_54MB 0x6C +#define RTLLIB_BASIC_RATE_MASK 0x80 + +#define RTLLIB_CCK_RATE_1MB_MASK (1<<0) +#define RTLLIB_CCK_RATE_2MB_MASK (1<<1) +#define RTLLIB_CCK_RATE_5MB_MASK (1<<2) +#define RTLLIB_CCK_RATE_11MB_MASK (1<<3) +#define RTLLIB_OFDM_RATE_6MB_MASK (1<<4) +#define RTLLIB_OFDM_RATE_9MB_MASK (1<<5) +#define RTLLIB_OFDM_RATE_12MB_MASK (1<<6) +#define RTLLIB_OFDM_RATE_18MB_MASK (1<<7) +#define RTLLIB_OFDM_RATE_24MB_MASK (1<<8) +#define RTLLIB_OFDM_RATE_36MB_MASK (1<<9) +#define RTLLIB_OFDM_RATE_48MB_MASK (1<<10) +#define RTLLIB_OFDM_RATE_54MB_MASK (1<<11) + +#define RTLLIB_CCK_RATES_MASK 0x0000000F +#define RTLLIB_CCK_BASIC_RATES_MASK (RTLLIB_CCK_RATE_1MB_MASK | \ + RTLLIB_CCK_RATE_2MB_MASK) +#define RTLLIB_CCK_DEFAULT_RATES_MASK (RTLLIB_CCK_BASIC_RATES_MASK | \ + RTLLIB_CCK_RATE_5MB_MASK | \ + RTLLIB_CCK_RATE_11MB_MASK) + +#define RTLLIB_OFDM_RATES_MASK 0x00000FF0 +#define RTLLIB_OFDM_BASIC_RATES_MASK (RTLLIB_OFDM_RATE_6MB_MASK | \ + RTLLIB_OFDM_RATE_12MB_MASK | \ + RTLLIB_OFDM_RATE_24MB_MASK) +#define RTLLIB_OFDM_DEFAULT_RATES_MASK (RTLLIB_OFDM_BASIC_RATES_MASK | \ + RTLLIB_OFDM_RATE_9MB_MASK | \ + RTLLIB_OFDM_RATE_18MB_MASK | \ + RTLLIB_OFDM_RATE_36MB_MASK | \ + RTLLIB_OFDM_RATE_48MB_MASK | \ + RTLLIB_OFDM_RATE_54MB_MASK) +#define RTLLIB_DEFAULT_RATES_MASK (RTLLIB_OFDM_DEFAULT_RATES_MASK | \ + RTLLIB_CCK_DEFAULT_RATES_MASK) + +#define RTLLIB_NUM_OFDM_RATES 8 +#define RTLLIB_NUM_CCK_RATES 4 +#define RTLLIB_OFDM_SHIFT_MASK_A 4 + + +/* this is stolen and modified from the madwifi driver*/ +#define RTLLIB_FC0_TYPE_MASK 0x0c +#define RTLLIB_FC0_TYPE_DATA 0x08 +#define RTLLIB_FC0_SUBTYPE_MASK 0xB0 +#define RTLLIB_FC0_SUBTYPE_QOS 0x80 + +#define RTLLIB_QOS_HAS_SEQ(fc) \ + (((fc) & (RTLLIB_FC0_TYPE_MASK | RTLLIB_FC0_SUBTYPE_MASK)) == \ + (RTLLIB_FC0_TYPE_DATA | RTLLIB_FC0_SUBTYPE_QOS)) + +/* this is stolen from ipw2200 driver */ +#define IEEE_IBSS_MAC_HASH_SIZE 31 +struct ieee_ibss_seq { + u8 mac[ETH_ALEN]; + u16 seq_num[17]; + u16 frag_num[17]; + unsigned long packet_time[17]; + struct list_head list; +}; + +#ifdef _RTL8192_EXT_PATCH_ +struct ieee_mesh_seq { + u8 mac[ETH_ALEN]; + u16 seq_num[17]; + u16 frag_num[17]; + unsigned long packet_time[17]; + struct list_head list; +}; +#endif +/* NOTE: This data is for statistical purposes; not all hardware provides this + * information for frames received. Not setting these will not cause + * any adverse affects. */ +struct rtllib_rx_stats { +#if 1 + u32 mac_time[2]; + s8 rssi; + u8 signal; + u8 noise; + u16 rate; /* in 100 kbps */ + u8 received_channel; + u8 control; + u8 mask; + u8 freq; + u16 len; + u64 tsf; + u32 beacon_time; + u8 nic_type; + u16 Length; + u8 SignalQuality; + s32 RecvSignalPower; + s8 RxPower; + u8 SignalStrength; + u16 bHwError:1; + u16 bCRC:1; + u16 bICV:1; + u16 bShortPreamble:1; + u16 Antenna:1; + u16 Decrypted:1; + u16 Wakeup:1; + u16 Reserved0:1; + u8 AGC; + u32 TimeStampLow; + u32 TimeStampHigh; + bool bShift; + bool bIsQosData; + u8 UserPriority; + + u8 RxDrvInfoSize; + u8 RxBufShift; + bool bIsAMPDU; + bool bFirstMPDU; + bool bContainHTC; + bool RxIs40MHzPacket; + u32 RxPWDBAll; + u8 RxMIMOSignalStrength[4]; + s8 RxMIMOSignalQuality[2]; + bool bPacketMatchBSSID; + bool bIsCCK; + bool bPacketToSelf; + u8* virtual_address; + u16 packetlength; + u16 fraglength; + u16 fragoffset; + u16 ntotalfrag; + bool bisrxaggrsubframe; + bool bPacketBeacon; + bool bToSelfBA; + char cck_adc_pwdb[4]; + u16 Seq_Num; + u8 nTotalAggPkt; +#ifdef TCP_CSUM_OFFLOAD_RX + u8 tcp_csum_valid; +#endif +#if defined (RTL8192S_WAPI_SUPPORT) + u8 WapiTempPN[16]; + u8 WapiSrcAddr[6]; + u8 bWapiCheckPNInDecrypt; +#endif +#endif + +}; + +/* IEEE 802.11 requires that STA supports concurrent reception of at least + * three fragmented frames. This define can be increased to support more + * concurrent frames, but it should be noted that each entry can consume about + * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ +#define RTLLIB_FRAG_CACHE_LEN 4 + +struct rtllib_frag_entry { + unsigned long first_frag_time; + unsigned int seq; + unsigned int last_frag; + struct sk_buff *skb; + u8 src_addr[ETH_ALEN]; + u8 dst_addr[ETH_ALEN]; +}; + +struct rtllib_stats { + unsigned int tx_unicast_frames; + unsigned int tx_multicast_frames; + unsigned int tx_fragments; + unsigned int tx_unicast_octets; + unsigned int tx_multicast_octets; + unsigned int tx_deferred_transmissions; + unsigned int tx_single_retry_frames; + unsigned int tx_multiple_retry_frames; + unsigned int tx_retry_limit_exceeded; + unsigned int tx_discards; + unsigned int rx_unicast_frames; + unsigned int rx_multicast_frames; + unsigned int rx_fragments; + unsigned int rx_unicast_octets; + unsigned int rx_multicast_octets; + unsigned int rx_fcs_errors; + unsigned int rx_discards_no_buffer; + unsigned int tx_discards_wrong_sa; + unsigned int rx_discards_undecryptable; + unsigned int rx_message_in_msg_fragments; + unsigned int rx_message_in_bad_msg_fragments; +}; + +struct rtllib_device; + +#include "rtllib_crypt.h" + +#define SEC_KEY_1 (1<<0) +#define SEC_KEY_2 (1<<1) +#define SEC_KEY_3 (1<<2) +#define SEC_KEY_4 (1<<3) +#define SEC_ACTIVE_KEY (1<<4) +#define SEC_AUTH_MODE (1<<5) +#define SEC_UNICAST_GROUP (1<<6) +#define SEC_LEVEL (1<<7) +#define SEC_ENABLED (1<<8) +#define SEC_ENCRYPT (1<<9) + +#define SEC_LEVEL_0 0 /* None */ +#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ +#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ +#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ +#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ + +#define SEC_ALG_NONE 0 +#define SEC_ALG_WEP 1 +#define SEC_ALG_TKIP 2 +#define SEC_ALG_CCMP 4 + +#define WEP_KEYS 4 +#define WEP_KEY_LEN 13 +#define SCM_KEY_LEN 32 +#define SCM_TEMPORAL_KEY_LENGTH 16 + +struct rtllib_security { + u16 active_key:2, + enabled:1, + auth_mode:2, + auth_algo:4, + unicast_uses_group:1, + encrypt:1; + u8 key_sizes[WEP_KEYS]; + u8 keys[WEP_KEYS][SCM_KEY_LEN]; + u8 level; + u16 flags; +} __attribute__ ((packed)); + + +/* + 802.11 data frame from AP + ,-------------------------------------------------------------------. +Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | + |------|------|---------|---------|---------|------|---------|------| +Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | + | | tion | (BSSID) | | | ence | data | | + `-------------------------------------------------------------------' +Total: 28-2340 bytes +*/ + +/* Management Frame Information Element Types */ +enum rtllib_mfie { + MFIE_TYPE_SSID = 0, + MFIE_TYPE_RATES = 1, + MFIE_TYPE_FH_SET = 2, + MFIE_TYPE_DS_SET = 3, + MFIE_TYPE_CF_SET = 4, + MFIE_TYPE_TIM = 5, + MFIE_TYPE_IBSS_SET = 6, + MFIE_TYPE_COUNTRY = 7, + MFIE_TYPE_HOP_PARAMS = 8, + MFIE_TYPE_HOP_TABLE = 9, + MFIE_TYPE_REQUEST = 10, + MFIE_TYPE_CHALLENGE = 16, + MFIE_TYPE_POWER_CONSTRAINT = 32, + MFIE_TYPE_POWER_CAPABILITY = 33, + MFIE_TYPE_TPC_REQUEST = 34, + MFIE_TYPE_TPC_REPORT = 35, + MFIE_TYPE_SUPP_CHANNELS = 36, + MFIE_TYPE_CSA = 37, + MFIE_TYPE_MEASURE_REQUEST = 38, + MFIE_TYPE_MEASURE_REPORT = 39, + MFIE_TYPE_QUIET = 40, + MFIE_TYPE_IBSS_DFS = 41, + MFIE_TYPE_ERP = 42, + MFIE_TYPE_HT_CAP= 45, + MFIE_TYPE_RSN = 48, + MFIE_TYPE_RATES_EX = 50, +#ifdef _RTL8192_EXT_PATCH_ + MFIE_TYPE_MESH_PANN = 51, + MFIE_TYPE_MESH_RANN = 52, + MFIE_TYPE_MESH_PATH_REQ = 138, + MFIE_TYPE_MESH_PATH_REP = 139, + MFIE_TYPE_MESH_PATH_ERR = 140, +#endif + MFIE_TYPE_HT_INFO= 61, +#if defined (RTL8192S_WAPI_SUPPORT) + MFIE_TYPE_WAPI = 68, +#endif + MFIE_TYPE_AIRONET=133, +#ifdef _RTL8192_EXT_PATCH_ + MFIE_TYPE_MESH_CONFIGURATION = 121, + MFIE_TYPE_MESH_ID = 122, + MFIE_TYPE_MESH_LOCAL_LINK_STATE_ANNOU = 138, + MFIE_TYPE_MESH_ABBR_HANDSHAKE_IE_ =139, + MFIE_TYPE_MESH_PEER_LINK_MGNT = 125, + MFIE_TYPE_MESH_NEIGHBOR_LIST = 142, + MFIE_TYPE_MESH_TIM = 143, + MFIE_TYPE_MESH_ATIM_WINDOW = 144, + MFIE_TYPE_MESH_BEACON_TIMING = 145, + MFIE_TYPE_MESH_MDAOP_ADVERTISMENTS = 148, + MFIE_TYPE_MESH_MSC = 149, + MFIE_TYPE_MESH_MSA = 150, + MFIE_TYPE_MESH_MOAOP_SET_TEARDOWN = 212, +#endif + MFIE_TYPE_GENERIC = 221, + MFIE_TYPE_QOS_PARAMETER = 222, +}; + +/* Minimal header; can be used for passing 802.11 frames with sufficient + * information to determine what type of underlying data type is actually + * stored in the data. */ +struct rtllib_pspoll_hdr { + __le16 frame_ctl; + __le16 aid; + u8 bssid[ETH_ALEN]; + u8 ta[ETH_ALEN]; +} __attribute__ ((packed)); + +struct rtllib_hdr { + __le16 frame_ctl; + __le16 duration_id; + u8 payload[0]; +} __attribute__ ((packed)); + +struct rtllib_hdr_1addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct rtllib_hdr_2addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct rtllib_hdr_3addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; +} __attribute__ ((packed)); + +struct rtllib_hdr_4addr { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 addr4[ETH_ALEN]; + u8 payload[0]; +} __attribute__ ((packed)); + +struct rtllib_hdr_3addrqos { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + __le16 qos_ctl; + u8 payload[0]; +} __attribute__ ((packed)); + +struct rtllib_hdr_4addrqos { + __le16 frame_ctl; + __le16 duration_id; + u8 addr1[ETH_ALEN]; + u8 addr2[ETH_ALEN]; + u8 addr3[ETH_ALEN]; + __le16 seq_ctl; + u8 addr4[ETH_ALEN]; + __le16 qos_ctl; + u8 payload[0]; +} __attribute__ ((packed)); + +struct rtllib_info_element { + u8 id; + u8 len; + u8 data[0]; +} __attribute__ ((packed)); + +#ifdef _RTL8192_EXT_PATCH_ + +struct mesh_peering_protocol_version_t{ + u8 OUI[3]; + u8 value; +} __attribute__ ((packed)); +struct rtllib_plink_open { + struct rtllib_hdr_3addr header; + u8 category; + u8 action; +#ifndef COMPATIBLE_WITH_RALINK_MESH + struct mesh_peering_protocol_version_t mesh_peering_protocol_version; +#endif + __le16 capability; + /* SSID, supported rates, RSN */ + struct rtllib_info_element info_element[0]; +} __attribute__ ((packed)); + +struct rtllib_plink_confirm { + struct rtllib_hdr_3addr header; + u8 category; + u8 action; +#ifndef COMPATIBLE_WITH_RALINK_MESH + struct mesh_peering_protocol_version_t mesh_peering_protocol_version; +#endif + __le16 capability; +#ifdef COMPATIBLE_WITH_RALINK_MESH + __le16 status_code; +#endif + __le16 aid; + /* SSID, supported rates, RSN */ + struct rtllib_info_element info_element[0]; +} __attribute__ ((packed)); + +struct rtllib_plink_close { + struct rtllib_hdr_3addr header; + u8 category; + u8 action; +#ifndef COMPATIBLE_WITH_RALINK_MESH + struct mesh_peering_protocol_version_t mesh_peering_protocol_version; +#endif + /* SSID, supported rates, RSN */ + struct rtllib_info_element info_element[0]; +} __attribute__ ((packed)); + +struct rtllib_linkmetric_report { + struct rtllib_hdr_3addr header; + u8 category; + u8 action; + struct rtllib_info_element info_element[0]; +} __attribute__ ((packed)); + +struct rtllib_linkmetric_req { + struct rtllib_hdr_3addr header; + u8 category; + u8 action; +} __attribute__ ((packed)); +#endif + +struct rtllib_authentication { + struct rtllib_hdr_3addr header; + __le16 algorithm; + __le16 transaction; + __le16 status; + /*challenge*/ + struct rtllib_info_element info_element[0]; +} __attribute__ ((packed)); + +struct rtllib_disauth { + struct rtllib_hdr_3addr header; + __le16 reason; +} __attribute__ ((packed)); + +struct rtllib_disassoc { + struct rtllib_hdr_3addr header; + __le16 reason; +} __attribute__ ((packed)); + +struct rtllib_probe_request { + struct rtllib_hdr_3addr header; + /* SSID, supported rates */ + struct rtllib_info_element info_element[0]; +} __attribute__ ((packed)); + +struct rtllib_probe_response { + struct rtllib_hdr_3addr header; + u32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + /* SSID, supported rates, FH params, DS params, + * CF params, IBSS params, TIM (if beacon), RSN */ + struct rtllib_info_element info_element[0]; +} __attribute__ ((packed)); + +/* Alias beacon for probe_response */ +#define rtllib_beacon rtllib_probe_response + +struct rtllib_assoc_request_frame { + struct rtllib_hdr_3addr header; + __le16 capability; + __le16 listen_interval; + /* SSID, supported rates, RSN */ + struct rtllib_info_element info_element[0]; +} __attribute__ ((packed)); + +struct rtllib_reassoc_request_frame { + struct rtllib_hdr_3addr header; + __le16 capability; + __le16 listen_interval; + u8 current_ap[ETH_ALEN]; + /* SSID, supported rates, RSN */ + struct rtllib_info_element info_element[0]; +} __attribute__ ((packed)); + +struct rtllib_assoc_response_frame { + struct rtllib_hdr_3addr header; + __le16 capability; + __le16 status; + __le16 aid; + struct rtllib_info_element info_element[0]; /* supported rates */ +} __attribute__ ((packed)); + +struct rtllib_txb { + u8 nr_frags; + u8 encrypted; + u8 queue_index; + u8 rts_included; + u16 reserved; + __le16 frag_size; + __le16 payload_size; + struct sk_buff *fragments[0]; +}; + +#define MAX_TX_AGG_COUNT 16 +struct rtllib_drv_agg_txb { + u8 nr_drv_agg_frames; + struct sk_buff *tx_agg_frames[MAX_TX_AGG_COUNT]; +}__attribute__((packed)); + +#define MAX_SUBFRAME_COUNT 64 +struct rtllib_rxb { + u8 nr_subframes; + struct sk_buff *subframes[MAX_SUBFRAME_COUNT]; + u8 dst[ETH_ALEN]; + u8 src[ETH_ALEN]; +#ifdef TCP_CSUM_OFFLOAD_RX + u8 tcp_csum_valid; +#endif +#if defined (RTL8192S_WAPI_SUPPORT) + u8 UserPriority; + u8 WapiTempPN[16]; + u8 WapiSrcAddr[6]; + u8 bWapiCheckPNInDecrypt; +#endif +}__attribute__((packed)); + +typedef union _frameqos { + u16 shortdata; + u8 chardata[2]; + struct { + u16 tid:4; + u16 eosp:1; + u16 ack_policy:2; + u16 reserved:1; + u16 txop:8; + }field; +}frameqos,*pframeqos; + +/* SWEEP TABLE ENTRIES NUMBER*/ +#define MAX_SWEEP_TAB_ENTRIES 42 +#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 +/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs + * only use 8, and then use extended rates for the remaining supported + * rates. Other APs, however, stick all of their supported rates on the + * main rates information element... */ +#define MAX_RATES_LENGTH ((u8)12) +#define MAX_RATES_EX_LENGTH ((u8)16) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#define MAX_NETWORK_COUNT 16 +#else +#define MAX_NETWORK_COUNT 96 +#endif + +#define MAX_CHANNEL_NUMBER 161 +#define RTLLIB_SOFTMAC_SCAN_TIME 100 +#define RTLLIB_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2) + +#define CRC_LENGTH 4U + +#define MAX_WPA_IE_LEN 64 +#define MAX_WZC_IE_LEN 256 + +#define NETWORK_EMPTY_ESSID (1<<0) +#define NETWORK_HAS_OFDM (1<<1) +#define NETWORK_HAS_CCK (1<<2) + +/* QoS structure */ +#define NETWORK_HAS_QOS_PARAMETERS (1<<3) +#define NETWORK_HAS_QOS_INFORMATION (1<<4) +#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | \ + NETWORK_HAS_QOS_INFORMATION) +/* 802.11h */ +#define NETWORK_HAS_POWER_CONSTRAINT (1<<5) +#define NETWORK_HAS_CSA (1<<6) +#define NETWORK_HAS_QUIET (1<<7) +#define NETWORK_HAS_IBSS_DFS (1<<8) +#define NETWORK_HAS_TPC_REPORT (1<<9) + +#define NETWORK_HAS_ERP_VALUE (1<<10) + +#define QOS_QUEUE_NUM 4 +#define QOS_OUI_LEN 3 +#define QOS_OUI_TYPE 2 +#define QOS_ELEMENT_ID 221 +#define QOS_OUI_INFO_SUB_TYPE 0 +#define QOS_OUI_PARAM_SUB_TYPE 1 +#define QOS_VERSION_1 1 +#define QOS_AIFSN_MIN_VALUE 2 +#if 1 +struct rtllib_qos_information_element { + u8 elementID; + u8 length; + u8 qui[QOS_OUI_LEN]; + u8 qui_type; + u8 qui_subtype; + u8 version; + u8 ac_info; +} __attribute__ ((packed)); + +struct rtllib_qos_ac_parameter { + u8 aci_aifsn; + u8 ecw_min_max; + __le16 tx_op_limit; +} __attribute__ ((packed)); + +struct rtllib_qos_parameter_info { + struct rtllib_qos_information_element info_element; + u8 reserved; + struct rtllib_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM]; +} __attribute__ ((packed)); + +struct rtllib_qos_parameters { + __le16 cw_min[QOS_QUEUE_NUM]; + __le16 cw_max[QOS_QUEUE_NUM]; + u8 aifs[QOS_QUEUE_NUM]; + u8 flag[QOS_QUEUE_NUM]; + __le16 tx_op_limit[QOS_QUEUE_NUM]; +} __attribute__ ((packed)); + +struct rtllib_qos_data { + struct rtllib_qos_parameters parameters; + unsigned int wmm_acm; + int active; + int supported; + u8 param_count; + u8 old_param_count; +}; + +struct rtllib_tim_parameters { + u8 tim_count; + u8 tim_period; +} __attribute__ ((packed)); + +struct rtllib_wmm_ac_param { + u8 ac_aci_acm_aifsn; + u8 ac_ecwmin_ecwmax; + u16 ac_txop_limit; +}; + +struct rtllib_wmm_ts_info { + u8 ac_dir_tid; + u8 ac_up_psb; + u8 reserved; +} __attribute__ ((packed)); + +struct rtllib_wmm_tspec_elem { + struct rtllib_wmm_ts_info ts_info; + u16 norm_msdu_size; + u16 max_msdu_size; + u32 min_serv_inter; + u32 max_serv_inter; + u32 inact_inter; + u32 suspen_inter; + u32 serv_start_time; + u32 min_data_rate; + u32 mean_data_rate; + u32 peak_data_rate; + u32 max_burst_size; + u32 delay_bound; + u32 min_phy_rate; + u16 surp_band_allow; + u16 medium_time; +}__attribute__((packed)); +#endif +enum eap_type { + EAP_PACKET = 0, + EAPOL_START, + EAPOL_LOGOFF, + EAPOL_KEY, + EAPOL_ENCAP_ASF_ALERT +}; + +static const char *eap_types[] = { + [EAP_PACKET] = "EAP-Packet", + [EAPOL_START] = "EAPOL-Start", + [EAPOL_LOGOFF] = "EAPOL-Logoff", + [EAPOL_KEY] = "EAPOL-Key", + [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert" +}; + +static inline const char *eap_get_type(int type) +{ + return ((u32)type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type]; +} +static inline u8 Frame_QoSTID(u8* buf) +{ + struct rtllib_hdr_3addr *hdr; + u16 fc; + hdr = (struct rtllib_hdr_3addr *)buf; + fc = le16_to_cpu(hdr->frame_ctl); + return (u8)((frameqos*)(buf + (((fc & RTLLIB_FCTL_TODS)&&(fc & RTLLIB_FCTL_FROMDS))? 30 : 24)))->field.tid; +} + + +struct eapol { + u8 snap[6]; + u16 ethertype; + u8 version; + u8 type; + u16 length; +} __attribute__ ((packed)); + +struct rtllib_softmac_stats{ + unsigned int rx_ass_ok; + unsigned int rx_ass_err; + unsigned int rx_probe_rq; + unsigned int tx_probe_rs; + unsigned int tx_beacons; + unsigned int rx_auth_rq; + unsigned int rx_auth_rs_ok; + unsigned int rx_auth_rs_err; + unsigned int tx_auth_rq; + unsigned int no_auth_rs; + unsigned int no_ass_rs; + unsigned int tx_ass_rq; + unsigned int rx_ass_rq; + unsigned int tx_probe_rq; + unsigned int reassoc; + unsigned int swtxstop; + unsigned int swtxawake; + unsigned char CurrentShowTxate; + unsigned char last_packet_rate; + unsigned int txretrycount; +}; + +#define BEACON_PROBE_SSID_ID_POSITION 12 + +struct rtllib_info_element_hdr { + u8 id; + u8 len; +} __attribute__ ((packed)); + +/* + * These are the data types that can make up management packets + * + u16 auth_algorithm; + u16 auth_sequence; + u16 beacon_interval; + u16 capability; + u8 current_ap[ETH_ALEN]; + u16 listen_interval; + struct { + u16 association_id:14, reserved:2; + } __attribute__ ((packed)); + u32 time_stamp[2]; + u16 reason; + u16 status; +*/ + +#define RTLLIB_DEFAULT_TX_ESSID "Penguin" +#define RTLLIB_DEFAULT_BASIC_RATE 2 +#ifdef _RTL8192_EXT_PATCH_ +#define RTLLIB_DEFAULT_MESHID "CMPC-mesh" +#define RTLLIB_DEFAULT_MESH_CHAN 7 +#endif + +enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame}; +#define MAX_SP_Len (WMM_all_frame << 4) +#define RTLLIB_QOS_TID 0x0f +#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5) +#define QOS_CTL_AMSDU_PRESENT (0x01 << 7) + +#define RTLLIB_DTIM_MBCAST 4 +#define RTLLIB_DTIM_UCAST 2 +#define RTLLIB_DTIM_VALID 1 +#define RTLLIB_DTIM_INVALID 0 + +#define RTLLIB_PS_DISABLED 0 +#define RTLLIB_PS_UNICAST RTLLIB_DTIM_UCAST +#define RTLLIB_PS_MBCAST RTLLIB_DTIM_MBCAST + +#ifdef WMM_Hang_8187 +#undef WMM_Hang_8187 +#endif + +#define WME_AC_BK 0x00 +#define WME_AC_BE 0x01 +#define WME_AC_VI 0x02 +#define WME_AC_VO 0x03 +#define WME_ACI_MASK 0x03 +#define WME_AIFSN_MASK 0x03 +#define WME_AC_PRAM_LEN 16 + +#define MAX_RECEIVE_BUFFER_SIZE 9100 + +#if 1 +#define UP2AC(up) ( \ + ((up) < 1) ? WME_AC_BE : \ + ((up) < 3) ? WME_AC_BK : \ + ((up) < 4) ? WME_AC_BE : \ + ((up) < 6) ? WME_AC_VI : \ + WME_AC_VO) +#endif +#define AC2UP(_ac) ( \ + ((_ac) == WME_AC_VO) ? 6 : \ + ((_ac) == WME_AC_VI) ? 5 : \ + ((_ac) == WME_AC_BK) ? 1 : \ + 0) + +#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */ +#define ETHERNET_HEADER_SIZE 14 /* length of two Ethernet address plus ether type*/ + +struct ether_header { + u8 ether_dhost[ETHER_ADDR_LEN]; + u8 ether_shost[ETHER_ADDR_LEN]; + u16 ether_type; +} __attribute__((packed)); + +#ifndef ETHERTYPE_PAE +#define ETHERTYPE_PAE 0x888e /* EAPOL PAE/802.1x */ +#endif +#ifndef ETHERTYPE_IP +#define ETHERTYPE_IP 0x0800 /* IP protocol */ +#endif + + +typedef enum _erp_t{ + ERP_NonERPpresent = 0x01, + ERP_UseProtection = 0x02, + ERP_BarkerPreambleMode = 0x04, +} erp_t; + +#ifdef _RTL8192_EXT_PATCH_ +typedef struct _mesh_config_t { + u8 path_proto_id[4]; + u8 path_metric_id[4]; + u8 congest_ctl_mode[4]; + u8 mesh_capability[2]; +} mesh_config_t; +#define MESH_CONF_TOTAL_LEN 19 +#endif + +struct rtllib_network { + /* These entries are used to identify a unique network */ + u8 bssid[ETH_ALEN]; + u8 channel; + /* Ensure null-terminated for any debug msgs */ + u8 ssid[IW_ESSID_MAX_SIZE + 1]; + u8 ssid_len; + u8 hidden_ssid[IW_ESSID_MAX_SIZE + 1]; + u8 hidden_ssid_len; + struct rtllib_qos_data qos_data; + + bool bWithAironetIE; + bool bCkipSupported; + bool bCcxRmEnable; + u16 CcxRmState[2]; + bool bMBssidValid; + u8 MBssidMask; + u8 MBssid[6]; + bool bWithCcxVerNum; + u8 BssCcxVerNumber; + /* These are network statistics */ + struct rtllib_rx_stats stats; + u16 capability; + u8 rates[MAX_RATES_LENGTH]; + u8 rates_len; + u8 rates_ex[MAX_RATES_EX_LENGTH]; + u8 rates_ex_len; + unsigned long last_scanned; + u8 mode; + u32 flags; + u32 last_associate; + u32 time_stamp[2]; + u16 beacon_interval; + u16 listen_interval; + u16 atim_window; + u8 erp_value; + u8 wpa_ie[MAX_WPA_IE_LEN]; + size_t wpa_ie_len; + u8 rsn_ie[MAX_WPA_IE_LEN]; + size_t rsn_ie_len; +#if defined RTL8192S_WAPI_SUPPORT + u8 wapi_ie[MAX_WAPI_IE_LEN]; + size_t wapi_ie_len; +#endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + u8 wzc_ie[MAX_WZC_IE_LEN]; + size_t wzc_ie_len; +#endif + + struct rtllib_tim_parameters tim; + u8 dtim_period; + u8 dtim_data; + u32 last_dtim_sta_time[2]; + + u8 wmm_info; + struct rtllib_wmm_ac_param wmm_param[4]; +#ifdef THOMAS_TURBO + u8 Turbo_Enable; +#endif +#ifdef ENABLE_DOT11D + u16 CountryIeLen; + u8 CountryIeBuf[MAX_IE_LEN]; +#endif + BSS_HT bssht; + bool broadcom_cap_exist; + bool realtek_cap_exit; + bool marvell_cap_exist; + bool ralink_cap_exist; + bool atheros_cap_exist; + bool cisco_cap_exist; + bool airgo_cap_exist; + bool unknown_cap_exist; + bool berp_info_valid; + bool buseprotection; + bool bIsNetgear854T; + u8 SignalStrength; + u8 RSSI; +#ifdef _RTL8192_EXT_PATCH_ + u8 hostname[MAX_HOST_NAME_LENGTH]; + u8 hostname_len; + u8 mesh_id[MAX_MESH_ID_LEN]; + u8 mesh_id_len; + mesh_config_t mesh_config; + u8 mesh_config_len; + void *ext_entry; +#endif + + struct list_head list; +}; + +#if 1 +enum rtllib_state { + + /* the card is not linked at all */ + RTLLIB_NOLINK = 0, + + /* RTLLIB_ASSOCIATING* are for BSS client mode + * the driver shall not perform RX filtering unless + * the state is LINKED. + * The driver shall just check for the state LINKED and + * defaults to NOLINK for ALL the other states (including + * LINKED_SCANNING) + */ + + /* the association procedure will start (wq scheduling)*/ + RTLLIB_ASSOCIATING, + RTLLIB_ASSOCIATING_RETRY, + + /* the association procedure is sending AUTH request*/ + RTLLIB_ASSOCIATING_AUTHENTICATING, + + /* the association procedure has successfully authentcated + * and is sending association request + */ + RTLLIB_ASSOCIATING_AUTHENTICATED, + + /* the link is ok. the card associated to a BSS or linked + * to a ibss cell or acting as an AP and creating the bss + */ + RTLLIB_LINKED, + + /* same as LINKED, but the driver shall apply RX filter + * rules as we are in NO_LINK mode. As the card is still + * logically linked, but it is doing a syncro site survey + * then it will be back to LINKED state. + */ + RTLLIB_LINKED_SCANNING, +#ifdef _RTL8192_EXT_PATCH_ + RTLLIB_MESH_SCANNING, + RTLLIB_MESH_LINKED, +#endif +}; +#else +enum rtllib_state { + RTLLIB_UNINITIALIZED = 0, + RTLLIB_INITIALIZED, + RTLLIB_ASSOCIATING, + RTLLIB_ASSOCIATED, + RTLLIB_AUTHENTICATING, + RTLLIB_AUTHENTICATED, + RTLLIB_SHUTDOWN +}; +#endif + +#define DEFAULT_MAX_SCAN_AGE (15 * HZ) +#define DEFAULT_FTS 2346 + +#define CFG_RTLLIB_RESERVE_FCS (1<<0) +#define CFG_RTLLIB_COMPUTE_FCS (1<<1) +#define CFG_RTLLIB_RTS (1<<2) + +#define RTLLIB_24GHZ_MIN_CHANNEL 1 +#define RTLLIB_24GHZ_MAX_CHANNEL 14 +#define RTLLIB_24GHZ_CHANNELS (RTLLIB_24GHZ_MAX_CHANNEL - \ + RTLLIB_24GHZ_MIN_CHANNEL + 1) + +#define RTLLIB_52GHZ_MIN_CHANNEL 34 +#define RTLLIB_52GHZ_MAX_CHANNEL 165 +#define RTLLIB_52GHZ_CHANNELS (RTLLIB_52GHZ_MAX_CHANNEL - \ + RTLLIB_52GHZ_MIN_CHANNEL + 1) + +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,11)) +extern inline int is_multicast_ether_addr(const u8 *addr) +{ + return ((addr[0] != 0xff) && (0x01 & addr[0])); +} +#endif + +#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)) +extern inline int is_broadcast_ether_addr(const u8 *addr) +{ + return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && \ + (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); +} +#endif +#ifndef eqMacAddr +#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 ) +#endif +typedef struct tx_pending_t{ + int frag; + struct rtllib_txb *txb; +}tx_pending_t; + +typedef struct _bandwidth_autoswitch +{ + long threshold_20Mhzto40Mhz; + long threshold_40Mhzto20Mhz; + bool bforced_tx20Mhz; + bool bautoswitch_enable; +}bandwidth_autoswitch,*pbandwidth_autoswitch; + + + +#define REORDER_WIN_SIZE 128 +#define REORDER_ENTRY_NUM 128 +typedef struct _RX_REORDER_ENTRY +{ + struct list_head List; + u16 SeqNum; + struct rtllib_rxb* prxb; +} RX_REORDER_ENTRY, *PRX_REORDER_ENTRY; +typedef enum _Fsync_State{ + Default_Fsync, + HW_Fsync, + SW_Fsync +}Fsync_State; + +typedef enum _RT_PS_MODE +{ + eActive, + eMaxPs, + eFastPs, + eAutoPs, +}RT_PS_MODE; + +typedef enum _IPS_CALLBACK_FUNCION +{ + IPS_CALLBACK_NONE = 0, + IPS_CALLBACK_MGNT_LINK_REQUEST = 1, + IPS_CALLBACK_JOIN_REQUEST = 2, +}IPS_CALLBACK_FUNCION; + +typedef enum _RT_JOIN_ACTION{ + RT_JOIN_INFRA = 1, + RT_JOIN_IBSS = 2, + RT_START_IBSS = 3, + RT_NO_ACTION = 4, +}RT_JOIN_ACTION; + +typedef struct _IbssParms{ + u16 atimWin; +}IbssParms, *PIbssParms; +#define MAX_NUM_RATES 264 + +typedef enum _RT_RF_POWER_STATE +{ + eRfOn, + eRfSleep, + eRfOff +}RT_RF_POWER_STATE; + +#define MAX_SUPPORT_WOL_PATTERN_NUM 8 + +#define MAX_WOL_BIT_MASK_SIZE 16 +#define MAX_WOL_PATTERN_SIZE 128 + +typedef enum _WOLPATTERN_TYPE +{ + eNetBIOS = 0, + eIPv4IPv6ARP, + eIPv4IPv6TCPSYN, + eMACIDOnly, + eNoDefined, +}WOLPATTERN_TYPE; + +typedef struct _RT_PM_WOL_PATTERN_INFO +{ + u32 PatternId; + u32 Mask[4]; + u16 CrcRemainder; + u8 WFMIndex; + WOLPATTERN_TYPE PatternType; +}RT_PM_WOL_PATTERN_INFO, *PRT_PM_WOL_PATTERN_INFO; + +typedef struct _RT_POWER_SAVE_CONTROL +{ + + bool bInactivePs; + bool bIPSModeBackup; + bool bHaltAdapterClkRQ; + bool bSwRfProcessing; + RT_RF_POWER_STATE eInactivePowerState; + work_struct_rsl InactivePsWorkItem; + struct timer_list InactivePsTimer; + + IPS_CALLBACK_FUNCION ReturnPoint; + + bool bTmpBssDesc; + RT_JOIN_ACTION tmpJoinAction; + struct rtllib_network tmpBssDesc; + + bool bTmpScanOnly; + bool bTmpActiveScan; + bool bTmpFilterHiddenAP; + bool bTmpUpdateParms; + u8 tmpSsidBuf[33]; + OCTET_STRING tmpSsid2Scan; + bool bTmpSsid2Scan; + u8 tmpNetworkType; + u8 tmpChannelNumber; + u16 tmpBcnPeriod; + u8 tmpDtimPeriod; + u16 tmpmCap; + OCTET_STRING tmpSuppRateSet; + u8 tmpSuppRateBuf[MAX_NUM_RATES]; + bool bTmpSuppRate; + IbssParms tmpIbpm; + bool bTmpIbpm; + + bool bLeisurePs; + u32 PowerProfile; + u8 LpsIdleCount; + u8 PowerMode; + u8 RegMaxLPSAwakeIntvl; + u8 LPSAwakeIntvl; + + u32 CurPsLevel; + u32 RegRfPsLevel; + + bool bFwCtrlLPS; + u8 FWCtrlPSMode; + + bool LinkReqInIPSRFOffPgs; + bool BufConnectinfoBefore; + + + bool bGpioRfSw; + + u8 RegAMDPciASPM; + + u8 oWLANMode; + RT_PM_WOL_PATTERN_INFO PmWoLPatternInfo[MAX_SUPPORT_WOL_PATTERN_NUM]; + +}RT_POWER_SAVE_CONTROL,*PRT_POWER_SAVE_CONTROL; + +typedef u32 RT_RF_CHANGE_SOURCE; +#define RF_CHANGE_BY_SW BIT31 +#define RF_CHANGE_BY_HW BIT30 +#define RF_CHANGE_BY_PS BIT29 +#define RF_CHANGE_BY_IPS BIT28 +#define RF_CHANGE_BY_INIT 0 + +typedef enum +{ + COUNTRY_CODE_FCC = 0, + COUNTRY_CODE_IC = 1, + COUNTRY_CODE_ETSI = 2, + COUNTRY_CODE_SPAIN = 3, + COUNTRY_CODE_FRANCE = 4, + COUNTRY_CODE_MKK = 5, + COUNTRY_CODE_MKK1 = 6, + COUNTRY_CODE_ISRAEL = 7, + COUNTRY_CODE_TELEC = 8, + COUNTRY_CODE_MIC = 9, + COUNTRY_CODE_GLOBAL_DOMAIN = 10, + COUNTRY_CODE_WORLD_WIDE_13 = 11, + COUNTRY_CODE_TELEC_NETGEAR = 12, + COUNTRY_CODE_MAX +}country_code_type_t; + +typedef enum _SCAN_OPERATION_BACKUP_OPT{ + SCAN_OPT_BACKUP=0, + SCAN_OPT_RESTORE, + SCAN_OPT_MAX +}SCAN_OPERATION_BACKUP_OPT; + +typedef enum _FW_CMD_IO_TYPE{ + FW_CMD_DIG_ENABLE = 0, + FW_CMD_DIG_DISABLE = 1, + FW_CMD_DIG_HALT = 2, + FW_CMD_DIG_RESUME = 3, + FW_CMD_HIGH_PWR_ENABLE = 4, + FW_CMD_HIGH_PWR_DISABLE = 5, + FW_CMD_RA_RESET = 6, + FW_CMD_RA_ACTIVE= 7, + FW_CMD_RA_REFRESH_N= 8, + FW_CMD_RA_REFRESH_BG= 9, + FW_CMD_RA_INIT= 10, + FW_CMD_IQK_INIT = 11, + FW_CMD_TXPWR_TRACK_ENABLE = 12, + FW_CMD_TXPWR_TRACK_DISABLE = 13, + FW_CMD_TXPWR_TRACK_THERMAL = 14, + FW_CMD_PAUSE_DM_BY_SCAN = 15, + FW_CMD_RESUME_DM_BY_SCAN = 16, + FW_CMD_RA_REFRESH_N_COMB = 17, + FW_CMD_RA_REFRESH_BG_COMB = 18, + FW_CMD_ANTENNA_SW_ENABLE = 19, + FW_CMD_ANTENNA_SW_DISABLE = 20, + FW_CMD_TX_FEEDBACK_CCX_ENABLE = 21, + FW_CMD_LPS_ENTER = 22, + FW_CMD_LPS_LEAVE = 23, + FW_CMD_DIG_MODE_SS = 24, + FW_CMD_DIG_MODE_FA = 25, + FW_CMD_ADD_A2_ENTRY = 26, + FW_CMD_CTRL_DM_BY_DRIVER = 27, + FW_CMD_CTRL_DM_BY_DRIVER_NEW = 28, + FW_CMD_PAPE_CONTROL = 29, +#ifdef CONFIG_FW_SETCHAN + FW_CMD_CHAN_SET = 30, +#else + FW_CMD_IQK_ENABLE = 30, +#endif +}FW_CMD_IO_TYPE,*PFW_CMD_IO_TYPE; + +#define RT_MAX_LD_SLOT_NUM 10 +typedef struct _RT_LINK_DETECT_T{ + + u32 NumRecvBcnInPeriod; + u32 NumRecvDataInPeriod; + + u32 RxBcnNum[RT_MAX_LD_SLOT_NUM]; + u32 RxDataNum[RT_MAX_LD_SLOT_NUM]; + u16 SlotNum; + u16 SlotIndex; + + u32 NumTxOkInPeriod; + u32 NumRxOkInPeriod; + u32 NumRxUnicastOkInPeriod; + bool bBusyTraffic; + bool bHigherBusyTraffic; + bool bHigherBusyRxTraffic; + u8 IdleCount; + u32 NumTxUnicastOkInPeriod; + u32 LastNumTxUnicast; + u32 LastNumRxUnicast; +}RT_LINK_DETECT_T, *PRT_LINK_DETECT_T; + +#ifdef _RTL8192_EXT_PATCH_ +struct rtllib_crypt_data_list{ + u8 used; + u8 mac_addr[ETH_ALEN]; + struct rtllib_crypt_data *crypt[WEP_KEYS]; +}__attribute__((packed)); + +typedef struct _SW_RATR_TABLE{ + bool bused; + u32 ratr_value; +}SW_RATR_TABLE, *PSW_RATR_TABLE; +#endif + +typedef struct _SW_CAM_TABLE{ + + u8 macaddr[6]; + bool bused; + u8 key_buf[16]; + u16 key_type; + u8 useDK; + u8 key_index; + +}SW_CAM_TABLE,*PSW_CAM_TABLE; +#define TOTAL_CAM_ENTRY 32 +typedef struct _rate_adaptive +{ + u8 rate_adaptive_disabled; + u8 ratr_state; + u16 reserve; + + u32 high_rssi_thresh_for_ra; + u32 high2low_rssi_thresh_for_ra; + u8 low2high_rssi_thresh_for_ra40M; + u32 low_rssi_thresh_for_ra40M; + u8 low2high_rssi_thresh_for_ra20M; + u32 low_rssi_thresh_for_ra20M; + u32 upper_rssi_threshold_ratr; + u32 MiddleUpperRSSIThresholdRATR; + u32 middle_rssi_threshold_ratr; + u32 MiddleLowRSSIThresholdRATR; + u32 low_rssi_threshold_ratr; + u32 UltraLowRSSIThresholdRATR; + u32 low_rssi_threshold_ratr_40M; + u32 low_rssi_threshold_ratr_20M; + u8 ping_rssi_enable; + u32 ping_rssi_ratr; + u32 ping_rssi_thresh_for_ra; + u32 last_ratr; + u8 PreRATRState; + +} rate_adaptive, *prate_adaptive; +typedef enum _RATR_TABLE_MODE_8192S{ + RATR_INX_WIRELESS_NGB = 0, + RATR_INX_WIRELESS_NG = 1, + RATR_INX_WIRELESS_NB = 2, + RATR_INX_WIRELESS_N = 3, + RATR_INX_WIRELESS_GB = 4, + RATR_INX_WIRELESS_G = 5, + RATR_INX_WIRELESS_B = 6, + RATR_INX_WIRELESS_MC = 7, + RATR_INX_WIRELESS_A = 8, +}RATR_TABLE_MODE_8192S, *PRATR_TABLE_MODE_8192S; + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE +#define PEER_MAX_ASSOC 10 +typedef struct _RSSI_STA{ + long UndecoratedSmoothedPWDB; +}RSSI_STA, *PRSSI_STA; + +struct sta_info { + u8 macaddr[ETH_ALEN]; + u16 aid; + u8 authentication; + u8 encryption; + u16 capability; + u8 ratr_index; + int wireless_mode; + RT_HTINFO_STA_ENTRY htinfo; + u8 wme_enable; + u32 CurDataRate; + RSSI_STA rssi_stat; + rate_adaptive rate_adaptive; + u8 bPowerSave; + struct sk_buff_head PsQueue; + u32 LastActiveTime; + u16 StaDataRate; + u32 StaSS; + u16 RetryFrameCnt; + u16 LastRetryCnt; + u16 NoRetryFrameCnt; + u16 LastNoRetryCnt; + int AvgRetryRate; + int LastRetryRate; + u8 txRateIndex; + u16 APDataRate; + u16 ForcedDataRate; +} __attribute__ ((packed)); +#endif +#ifdef _RTL8192_EXT_PATCH_ +typedef struct _RT_PEERMP_HTINFO{ + u8 bEnableHT; + u8 bCurrentHTSupport; + + u8 bRegBW40MHz; + u8 bCurBW40MHz; + + u8 bRegShortGI40MHz; + u8 bCurShortGI40MHz; + + u8 bRegShortGI20MHz; + u8 bCurShortGI20MHz; + + u8 bCurSuppCCK; + + + + + u8 PeerHTCapBuf[32]; + u8 PeerHTInfoBuf[32]; + + + u8 bAMSDU_Support; + u16 nAMSDU_MaxSize; + u8 bCurrent_Mesh_AMSDU_Support; + + + u8 bAMPDUEnable; + u8 bCurrentMeshAMPDUEnable; + u8 AMPDU_Factor; + u8 CurrentAMPDUFactor; + u8 MPDU_Density; + u8 CurrentMPDUDensity; + + u8 ForcedAMPDUFactor; + u8 ForcedMPDUDensity; + + HT_AGGRE_MODE_E ForcedAMSDUMode; + u16 ForcedAMSDUMaxSize; + + u8 bForcedShortGI; + + u8 CurrentOpMode; + + u8 MimoPs; + + HT_EXTCHNL_OFFSET CurSTAExtChnlOffset; + u8 bCurTxBW40MHz; + u8 PeerBandwidth; + + u8 bSwBwInProgress; + CHNLOP ChnlOp; + u8 SwBwStep; + + u8 bRegRT2RTAggregation; + u8 bCurrentRT2RTAggregation; + u8 bCurrentRT2RTLongSlotTime; + u8 szRT2RTAggBuffer[10]; + + u8 bRegRxReorderEnable; + u8 bCurRxReorderEnable; + u8 RxReorderWinSize; + u8 RxReorderPendingTime; + u16 RxReorderDropCounter; + +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + u8 UsbTxAggrNum; +#endif +#ifdef USB_RX_AGGREGATION_SUPPORT + u8 UsbRxFwAggrEn; + u8 UsbRxFwAggrPageNum; + u8 UsbRxFwAggrPacketNum; + u8 UsbRxFwAggrTimeout; +#endif + + u8 bIsPeerBcm; + + u8 McsRateSet[16]; + u8 HTHighestOperaRate; + u8 IOTPeer; + u32 IOTAction; +} __attribute__ ((packed)) peerMP_htinfo, *ppeerMP_htinfo; +#endif + +#define NUM_PMKID_CACHE 16 +typedef struct _RT_PMKID_LIST +{ + u8 bUsed; + u8 Bssid[6]; + u8 PMKID[16]; + u8 SsidBuf[33]; + u8* ssid_octet; + u16 ssid_length; +} RT_PMKID_LIST, *PRT_PMKID_LIST; + +#ifdef CONFIG_CFG_80211 +enum { + LIBIPW_CH_PASSIVE_ONLY = (1 << 0), + LIBIPW_CH_80211H_RULES = (1 << 1), + LIBIPW_CH_B_ONLY = (1 << 2), + LIBIPW_CH_NO_IBSS = (1 << 3), + LIBIPW_CH_UNIFORM_SPREADING = (1 << 4), + LIBIPW_CH_RADAR_DETECT = (1 << 5), + LIBIPW_CH_INVALID = (1 << 6), +}; +struct rtllib_channel { + u32 freq; + u8 channel; + u8 flags; + u8 max_power; +}; + +#define RTLLIB_24GHZ_MIN_CHANNEL 1 +#define RTLLIB_24GHZ_MAX_CHANNEL 14 +#define RTLLIB_24GHZ_CHANNELS (RTLLIB_24GHZ_MAX_CHANNEL - \ + RTLLIB_24GHZ_MIN_CHANNEL + 1) + +struct reg_dmn_pair_mapping { + u16 regDmnEnum; + u16 reg_5ghz_ctl; + u16 reg_2ghz_ctl; +}; + +struct rtl_regulatory { + char alpha2[2]; + u16 country_code; + u16 max_power_level; + u32 tp_scale; + u16 current_rd; + u16 current_rd_ext; + int16_t power_limit; + struct reg_dmn_pair_mapping *regpair; +}; + +struct ieee80211_bss { + /* Yes, this is a hack */ + struct cfg80211_bss cbss; + + /* don't want to look up all the time */ + size_t ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + + u8 dtim_period; + + bool wmm_used; + + unsigned long last_probe_resp; + +#ifdef CONFIG_MAC80211_MESH + u8 *mesh_id; + size_t mesh_id_len; + u8 *mesh_cfg; +#endif + + #define IEEE80211_MAX_SUPP_RATES 32 + u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; + size_t supp_rates_len; + + /* + * During assocation, we save an ERP value from a probe response so + * that we can feed ERP info to the driver when handling the + * association completes. these fields probably won't be up-to-date + * otherwise, you probably don't want to use them. + */ + bool has_erp_value; + u8 erp_value; +}; + +/* Parsed Information Elements */ +struct ieee802_11_elems { + u8 *ie_start; + size_t total_len; + + /* pointers to IEs */ + u8 *ssid; + u8 *supp_rates; + u8 *fh_params; + u8 *ds_params; + u8 *cf_params; + struct ieee80211_tim_ie *tim; + u8 *ibss_params; + u8 *challenge; + u8 *wpa; + u8 *rsn; + u8 *erp_info; + u8 *ext_supp_rates; + u8 *wmm_info; + u8 *wmm_param; + struct ieee80211_ht_cap *ht_cap_elem; + struct ieee80211_ht_info *ht_info_elem; + u8 *mesh_config; + u8 *mesh_id; + u8 *peer_link; + u8 *preq; + u8 *prep; + u8 *perr; + u8 *ch_switch_elem; + u8 *country_elem; + u8 *pwr_constr_elem; + u8 *quiet_elem; /* first quite element */ + u8 *timeout_int; + + /* length of them, respectively */ + u8 ssid_len; + u8 supp_rates_len; + u8 fh_params_len; + u8 ds_params_len; + u8 cf_params_len; + u8 tim_len; + u8 ibss_params_len; + u8 challenge_len; + u8 wpa_len; + u8 rsn_len; + u8 erp_info_len; + u8 ext_supp_rates_len; + u8 wmm_info_len; + u8 wmm_param_len; + u8 mesh_config_len; + u8 mesh_id_len; + u8 peer_link_len; + u8 preq_len; + u8 prep_len; + u8 perr_len; + u8 ch_switch_elem_len; + u8 country_elem_len; + u8 pwr_constr_elem_len; + u8 quiet_elem_len; + u8 num_of_quiet_elem; /* can be more the one */ + u8 timeout_int_len; +}; + +#endif + + +typedef struct _RT_INTEL_PROMISCUOUS_MODE_INFO { + bool bPromiscuousOn; + bool bFilterSourceStationFrame; +} RT_INTEL_PROMISCUOUS_MODE_INFO, *PRT_INTEL_PROMISCUOUS_MODE_INFO; + +typedef struct _WIRELESS_SETTING_BEFORE_SCAN +{ + /*WirelessModeScanInProgress is designed for driver to keep the previous band(2.4G/5G) + during scan. It is only meaningful for a/b/g device which require to switch band twice + during scan (either 2.4->5->2.4 or 5->2.4->5*/ + WIRELESS_MODE WirelessModeScanInProgress; + + /*WirelessMode is designed to keep the original wireless mode setting before scan*/ + WIRELESS_MODE WirelessMode; + + /*ChannelNumber is designd to keep the original channel number before scan*/ + u8 ChannelNumber; + + /*ChannelBandwidth is designed to keep the original channel bandwidth(20/40MHz) before scan*/ + HT_CHANNEL_WIDTH ChannelBandwidth; + + /* Extension channel offset before scan. This is useful when channel bandwidth is 40MHz. */ + HT_EXTCHNL_OFFSET ExtChnlOffset; +}WIRELESS_SETTING_BEFORE_SCAN, *PWIRELESS_SETTING_BEFORE_SCAN; + + +/*************** DRIVER STATUS *****/ +#define STATUS_SCANNING 0 +#define STATUS_SCAN_HW 1 +#define STATUS_SCAN_ABORTING 2 +#define STATUS_SETTING_CHAN 3 +/*************** DRIVER STATUS *****/ + +enum { + NO_USE = 0, + USED = 1, + HW_SEC = 2, + SW_SEC = 3, +}; + +enum { + LPS_IS_WAKE = 0, + LPS_IS_SLEEP = 1, + LPS_WAIT_NULL_DATA_SEND =2, +}; + +struct rtllib_device { + struct pci_dev *pdev; + struct net_device *dev; + struct rtllib_security sec; + + bool disable_mgnt_queue; + + unsigned long status; + short hwscan_ch_bk; + HT_EXTCHNL_OFFSET chan_offset_bk; + HT_CHANNEL_WIDTH bandwidth_bk; + u8 hwscan_sem_up; +#ifdef CONFIG_CFG_80211 + struct wireless_dev wdev; + struct rtl_regulatory regulatory; +#endif + u8 CntAfterLink; + + RT_OP_MODE OpMode; + WIRELESS_SETTING_BEFORE_SCAN SettingBeforeScan; + + u8 VersionID; + /* The last AssocReq/Resp IEs */ + u8 *assocreq_ies, *assocresp_ies; + size_t assocreq_ies_len, assocresp_ies_len; + + bool b_customer_lenovo_id; + bool bForcedShowRxRate; + bool bForcedShowRateStill; + u8 SystemQueryDataRateCount; + bool bForcedBgMode; + bool bUseRAMask; + bool b1x1RecvCombine; + u8 RF_Type; + bool b1SSSupport; + + u8 hwsec_active; + bool is_silent_reset; + bool force_mic_error; + bool is_roaming; + bool ieee_up; + bool cannot_notify; + bool bSupportRemoteWakeUp; + RT_PS_MODE dot11PowerSaveMode; + bool actscanning; + bool FirstIe_InScan; + bool be_scan_inprogress; + bool beinretry; + RT_RF_POWER_STATE eRFPowerState; + RT_RF_CHANGE_SOURCE RfOffReason; + bool is_set_key; + bool wx_set_enc; +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE + struct sta_info *peer_assoc_list[PEER_MAX_ASSOC]; + u8 AvailableAIDTable[PEER_MAX_ASSOC]; + atomic_t AsocEntryNum; + u64 CurrTsf; + u64 TargetTsf; + u64 bdTstamp; + bool Peer_bCurBW40M; +#endif + PRT_HIGH_THROUGHPUT pHTInfo; + spinlock_t bw_spinlock; + + spinlock_t reorder_spinlock; + u8 Regdot11HTOperationalRateSet[16]; + u8 Regdot11TxHTOperationalRateSet[16]; + u8 dot11HTOperationalRateSet[16]; + u8 RegHTSuppRateSet[16]; + u8 HTCurrentOperaRate; + u8 HTHighestOperaRate; + u8 MinSpaceCfg; + u8 MaxMssDensity; + u8 bTxDisableRateFallBack; + u8 bTxUseDriverAssingedRate; + u8 bTxEnableFwCalcDur; + atomic_t atm_chnlop; + atomic_t atm_swbw; + + struct list_head Tx_TS_Admit_List; + struct list_head Tx_TS_Pending_List; + struct list_head Tx_TS_Unused_List; + TX_TS_RECORD TxTsRecord[TOTAL_TS_NUM]; + struct list_head Rx_TS_Admit_List; + struct list_head Rx_TS_Pending_List; + struct list_head Rx_TS_Unused_List; + RX_TS_RECORD RxTsRecord[TOTAL_TS_NUM]; + RX_REORDER_ENTRY RxReorderEntry[128]; + struct list_head RxReorder_Unused_List; + u8 ForcedPriority; + + + /* Bookkeeping structures */ + struct net_device_stats stats; + struct rtllib_stats ieee_stats; + struct rtllib_softmac_stats softmac_stats; + + /* Probe / Beacon management */ + struct list_head network_free_list; + struct list_head network_list; +#ifdef RTL8192U + struct list_head network_bssid_free_list; + struct list_head network_bssid_list; +#endif + struct rtllib_network *networks; + int scans; + int scan_age; + + int iw_mode; /* operating mode (IW_MODE_*) */ + bool bNetPromiscuousMode; + RT_INTEL_PROMISCUOUS_MODE_INFO IntelPromiscuousModeInfo; + + struct iw_spy_data spy_data; + + spinlock_t lock; + spinlock_t wpax_suitlist_lock; + + int tx_headroom; /* Set to size of any additional room needed at front + * of allocated Tx SKBs */ + u32 config; + + /* WEP and other encryption related settings at the device level */ + int open_wep; /* Set to 1 to allow unencrypted frames */ + int auth_mode; + int reset_on_keychange; /* Set to 1 if the HW needs to be reset on + * WEP key changes */ + + /* If the host performs {en,de}cryption, then set to 1 */ + int host_encrypt; + int host_encrypt_msdu; + int host_decrypt; + /* host performs multicast decryption */ + int host_mc_decrypt; + + /* host should strip IV and ICV from protected frames */ + /* meaningful only when hardware decryption is being used */ + int host_strip_iv_icv; + + int host_open_frag; + int host_build_iv; + int ieee802_1x; /* is IEEE 802.1X used */ + + /* WPA data */ + bool bHalfNMode; + bool bHalfWirelessN24GMode; + int wpa_enabled; + int drop_unencrypted; + int tkip_countermeasures; + int privacy_invoked; + size_t wpa_ie_len; + u8 *wpa_ie; + size_t wps_ie_len; + u8 *wps_ie; + u8 ap_mac_addr[6]; + u16 pairwise_key_type; + u16 group_key_type; + struct list_head crypt_deinit_list; +#ifdef _RTL8192_EXT_PATCH_ + struct rtllib_crypt_data_list* cryptlist[MAX_MP]; + struct rtllib_crypt_data *sta_crypt[WEP_KEYS]; +#else + struct rtllib_crypt_data *crypt[WEP_KEYS]; +#endif + + int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ + SW_CAM_TABLE swcamtable[TOTAL_CAM_ENTRY]; + struct timer_list crypt_deinit_timer; + int crypt_quiesced; + + int bcrx_sta_key; /* use individual keys to override default keys even + * with RX of broad/multicast frames */ + + RT_PMKID_LIST PMKIDList[NUM_PMKID_CACHE]; + + /* Fragmentation structures */ + struct rtllib_frag_entry frag_cache[17][RTLLIB_FRAG_CACHE_LEN]; + unsigned int frag_next_idx[17]; + u16 fts; /* Fragmentation Threshold */ +#define DEFAULT_RTS_THRESHOLD 2346U +#define MIN_RTS_THRESHOLD 1 +#define MAX_RTS_THRESHOLD 2346U + u16 rts; /* RTS threshold */ + + /* Association info */ + u8 bssid[ETH_ALEN]; + + /* This stores infos for the current network. + * Either the network we are associated in INFRASTRUCTURE + * or the network that we are creating in MASTER mode. + * ad-hoc is a mixture ;-). + * Note that in infrastructure mode, even when not associated, + * fields bssid and essid may be valid (if wpa_set and essid_set + * are true) as thy carry the value set by the user via iwconfig + */ + struct rtllib_network current_network; + + enum rtllib_state state; + + int short_slot; + int reg_mode; + int mode; /* A, B, G */ + int modulation; /* CCK, OFDM */ + int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */ + int abg_true; /* ABG flag */ + + /* used for forcing the ibss workqueue to terminate + * without wait for the syncro scan to terminate + */ + short sync_scan_hurryup; + u16 scan_watch_dog; + int perfect_rssi; + int worst_rssi; + + u16 prev_seq_ctl; /* used to drop duplicate frames */ + + /* map of allowed channels. 0 is dummy */ +#ifdef ENABLE_DOT11D + void* pDot11dInfo; + bool bGlobalDomain; +#else + u8 channel_map[MAX_CHANNEL_NUMBER+1]; +#endif + u8 active_channel_map[MAX_CHANNEL_NUMBER+1]; + + u8 IbssStartChnl; + u8 ibss_maxjoin_chal; + +#ifdef _RTL8192_EXT_PATCH_ + u8 backup_channel; +#endif + bool bUseProtection; + + int rate; /* current rate */ + int basic_rate; + u32 currentRate; + + short active_scan; + + /* this contains flags for selectively enable softmac support */ + u16 softmac_features; + + /* if the sequence control field is not filled by HW */ + u16 seq_ctrl[5]; + + /* association procedure transaction sequence number */ + u16 associate_seq; + + /* AID for RTXed association responses */ + u16 assoc_id; + + /* power save mode related*/ + u8 ack_tx_to_ieee; + short ps; + short sta_sleep; + int ps_timeout; + int ps_period; + struct tasklet_struct ps_task; + u32 ps_th; + u32 ps_tl; + bool polling; + + short raw_tx; + /* used if IEEE_SOFTMAC_TX_QUEUE is set */ + short queue_stop; + short scanning_continue ; + short proto_started; + short proto_stoppping; + + struct semaphore wx_sem; + struct semaphore scan_sem; + struct semaphore ips_sem; + + spinlock_t mgmt_tx_lock; + spinlock_t beacon_lock; + + short beacon_txing; + + short wap_set; + short ssid_set; + + /* set on initialization */ + u8 qos_support; + unsigned int wmm_acm; + + /* for discarding duplicated packets in IBSS */ + struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE]; + + /* for discarding duplicated packets in BSS */ + u16 last_rxseq_num[17]; /* rx seq previous per-tid */ + u16 last_rxfrag_num[17];/* tx frag previous per-tid */ + unsigned long last_packet_time[17]; + + /* for PS mode */ + unsigned long last_rx_ps_time; + bool bAwakePktSent; + u8 LPSDelayCnt; + + /* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */ + struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM]; + int mgmt_queue_head; + int mgmt_queue_tail; +#define RTLLIB_QUEUE_LIMIT 128 + u8 AsocRetryCount; + unsigned int hw_header; + struct sk_buff_head skb_waitQ[MAX_QUEUE_SIZE]; + struct sk_buff_head skb_aggQ[MAX_QUEUE_SIZE]; + struct sk_buff_head skb_drv_aggQ[MAX_QUEUE_SIZE]; + u32 sta_edca_param[4]; + bool aggregation; + bool enable_rx_imm_BA; + bool bibsscoordinator; + + bool bdynamic_txpower_enable; + + bool bCTSToSelfEnable; + u8 CTSToSelfTH; + + u32 fsync_time_interval; + u32 fsync_rate_bitmap; + u8 fsync_rssi_threshold; + bool bfsync_enable; + + u8 fsync_multiple_timeinterval; + u32 fsync_firstdiff_ratethreshold; + u32 fsync_seconddiff_ratethreshold; + Fsync_State fsync_state; + bool bis_any_nonbepkts; + bandwidth_autoswitch bandwidth_auto_switch; + bool FwRWRF; + + RT_LINK_DETECT_T LinkDetectInfo; + bool bIsAggregateFrame; + RT_POWER_SAVE_CONTROL PowerSaveControl; + u8 amsdu_in_process; + + /* used if IEEE_SOFTMAC_TX_QUEUE is set */ + struct tx_pending_t tx_pending; + + /* used if IEEE_SOFTMAC_ASSOCIATE is set */ + struct timer_list associate_timer; + + /* used if IEEE_SOFTMAC_BEACONS is set */ + struct timer_list beacon_timer; +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + struct timer_list ibss_wait_timer; +#endif + u8 need_sw_enc; +#ifdef _RTL8192_EXT_PATCH_ + struct net_device *meshdev; + struct net_device_stats *meshstats; + u8 only_mesh; + u8 hostname[MAX_HOST_NAME_LENGTH]; + u8 hostname_len; + struct list_head mesh_network_free_list; + struct list_head mesh_network_list; + struct rtllib_network *mesh_networks; + struct rtllib_network current_mesh_network; + enum rtllib_state mesh_state; + short mesh_started; + int mesh_security_setting; + int mesh_sec_type; + struct list_head mesh_mac_hash[IEEE_MESH_MAC_HASH_SIZE]; + u64 LinkingPeerBitMap; + u8 LinkingPeerAddr[MAX_MP-1][ETH_ALEN]; + u8 LinkingPeerSecState[MAX_MP-1]; + u8 mesh_cached_PTK[MAX_MP-1][16]; + u32 peer_AID_bitmap; + u8 peer_AID_Addr[30][ETH_ALEN]; + int mesh_txkeyidx; + u16 mesh_pairwise_key_type; + u16 mesh_group_key_type; + u32 HwSecCamBitMap; + u8 HwSecCamStaAddr[TOTAL_CAM_ENTRY][ETH_ALEN]; + SW_CAM_TABLE swmeshcamtable[TOTAL_CAM_ENTRY]; + SW_RATR_TABLE swmeshratrtable[8]; + short meshid_set; + u8 p2pmode; + u8 serverExtChlOffset; + u8 APExtChlOffset; + short meshScanMode; + struct sk_buff_head skb_meshaggQ[MAX_QUEUE_SIZE]; + u8 mesh_amsdu_in_process; +#endif + work_struct_rsl associate_complete_wq; +#ifdef ENABLE_IPS + work_struct_rsl ips_leave_wq; +#endif +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + delayed_work_struct_rsl check_tsf_wq; + delayed_work_struct_rsl update_assoc_sta_info_wq; +#endif + delayed_work_struct_rsl associate_procedure_wq; + delayed_work_struct_rsl softmac_scan_wq; + delayed_work_struct_rsl softmac_hint11d_wq; + delayed_work_struct_rsl associate_retry_wq; + delayed_work_struct_rsl start_ibss_wq; +#ifndef RTL8190P + delayed_work_struct_rsl hw_wakeup_wq; + delayed_work_struct_rsl hw_sleep_wq; +#endif + delayed_work_struct_rsl link_change_wq; + work_struct_rsl wx_sync_scan_wq; +#ifdef _RTL8192_EXT_PATCH_ + work_struct_rsl ext_stop_scan_wq; + work_struct_rsl ext_send_beacon_wq; + work_struct_rsl ext_create_crypt_for_peers_wq; + work_struct_rsl ext_path_sel_ops_wq; + work_struct_rsl ext_update_extchnloffset_wq; + delayed_work_struct_rsl ext_wx_set_key_wq; + work_struct_rsl ext_start_mesh_protocol_wq; +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct workqueue_struct *wq; +#else + u32 *wq; +#endif +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,40) + /* used for periodly scan */ + struct timer_list scan_timer; +#endif +#if defined (RTL8192S_WAPI_SUPPORT) + u8 WapiSupport; + RT_WAPI_T wapiInfo; + struct list_head cache_frag_list; + spinlock_t wapi_queue_lock; + WAPI_QUEUE *wapi_queue; +#endif + +#ifdef _RTL8192_EXT_PATCH_ + int (*set_mesh_key)(struct net_device *dev, + struct iw_point *encoding, struct iw_encode_ext *ext, u8 *addr); +#endif + /* Callback functions */ + void (*set_security)(struct net_device *dev, + struct rtllib_security *sec); + + /* Used to TX data frame by using txb structs. + * this is not used if in the softmac_features + * is set the flag IEEE_SOFTMAC_TX_QUEUE + */ + int (*hard_start_xmit)(struct rtllib_txb *txb, + struct net_device *dev); + + int (*reset_port)(struct net_device *dev); + int (*is_queue_full) (struct net_device * dev, int pri); + + int (*handle_management) (struct net_device * dev, + struct rtllib_network * network, u16 type); + int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb); + + /* Softmac-generated frames (mamagement) are TXed via this + * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is + * not set. As some cards may have different HW queues that + * one might want to use for data and management frames + * the option to have two callbacks might be useful. + * This fucntion can't sleep. + */ + int (*softmac_hard_start_xmit)(struct sk_buff *skb, + struct net_device *dev); + + /* used instead of hard_start_xmit (not softmac_hard_start_xmit) + * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data + * frames. I the option IEEE_SOFTMAC_SINGLE_QUEUE is also set + * then also management frames are sent via this callback. + * This function can't sleep. + */ + void (*softmac_data_hard_start_xmit)(struct sk_buff *skb, + struct net_device *dev,int rate); + + /* stops the HW queue for DATA frames. Useful to avoid + * waste time to TX data frame when we are reassociating + * This function can sleep. + */ + void (*data_hard_stop)(struct net_device *dev); + + /* OK this is complementar to data_poll_hard_stop */ + void (*data_hard_resume)(struct net_device *dev); + + /* ask to the driver to retune the radio . + * This function can sleep. the driver should ensure + * the radio has been swithced before return. + */ + void (*set_chan)(struct net_device *dev,short ch); + + /* These are not used if the ieee stack takes care of + * scanning (IEEE_SOFTMAC_SCAN feature set). + * In this case only the set_chan is used. + * + * The syncro version is similar to the start_scan but + * does not return until all channels has been scanned. + * this is called in user context and should sleep, + * it is called in a work_queue when swithcing to ad-hoc mode + * or in behalf of iwlist scan when the card is associated + * and root user ask for a scan. + * the fucntion stop_scan should stop both the syncro and + * background scanning and can sleep. + * The fucntion start_scan should initiate the background + * scanning and can't sleep. + */ + void (*scan_syncro)(struct net_device *dev); + void (*start_scan)(struct net_device *dev); + void (*stop_scan)(struct net_device *dev); + + void (*rtllib_start_hw_scan)(struct net_device *dev); + void (*rtllib_stop_hw_scan)(struct net_device *dev); + + /* indicate the driver that the link state is changed + * for example it may indicate the card is associated now. + * Driver might be interested in this to apply RX filter + * rules or simply light the LINK led + */ + void (*link_change)(struct net_device *dev); + + /* these two function indicates to the HW when to start + * and stop to send beacons. This is used when the + * IEEE_SOFTMAC_BEACONS is not set. For now the + * stop_send_bacons is NOT guaranteed to be called only + * after start_send_beacons. + */ + void (*start_send_beacons) (struct net_device *dev); + void (*stop_send_beacons) (struct net_device *dev); + + /* power save mode related */ + void (*sta_wake_up) (struct net_device *dev); + void (*enter_sleep_state) (struct net_device *dev, u32 th, u32 tl); + short (*ps_is_queue_empty) (struct net_device *dev); +#if 0 + /* Typical STA methods */ + int (*handle_auth) (struct net_device * dev, + struct rtllib_auth * auth); + int (*handle_deauth) (struct net_device * dev, + struct rtllib_deauth * auth); + int (*handle_action) (struct net_device * dev, + struct rtllib_action * action, + struct rtllib_rx_stats * stats); + int (*handle_disassoc) (struct net_device * dev, + struct rtllib_disassoc * assoc); +#endif + int (*handle_beacon) (struct net_device * dev, struct rtllib_beacon * beacon, struct rtllib_network * network); +#if 0 + int (*handle_probe_response) (struct net_device * dev, + struct rtllib_probe_response * resp, + struct rtllib_network * network); + int (*handle_probe_request) (struct net_device * dev, + struct rtllib_probe_request * req, + struct rtllib_rx_stats * stats); +#endif + int (*handle_assoc_response) (struct net_device * dev, struct rtllib_assoc_response_frame * resp, struct rtllib_network * network); + +#if 0 + /* Typical AP methods */ + int (*handle_assoc_request) (struct net_device * dev); + int (*handle_reassoc_request) (struct net_device * dev, + struct rtllib_reassoc_request * req); +#endif + + /* check whether Tx hw resouce available */ + short (*check_nic_enough_desc)(struct net_device *dev, int queue_index); + short (*get_nic_desc_num)(struct net_device *dev, int queue_index); + void (*SetBWModeHandler)(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset); + bool (*GetNmodeSupportBySecCfg)(struct net_device* dev); + void (*SetWirelessMode)(struct net_device* dev, u8 wireless_mode); + bool (*GetHalfNmodeSupportByAPsHandler)(struct net_device* dev); + u8 (*rtllib_ap_sec_type)(struct rtllib_device *ieee); + void (*HalUsbRxAggrHandler)(struct net_device *dev, bool Value); + void (*InitialGainHandler)(struct net_device *dev, u8 Operation); + int (*softmac_process_bt_pkt)(struct sk_buff *skb, struct net_device *dev); + +#ifdef _RTL8192_EXT_PATCH_ + int (*set_key_for_AP)(struct rtllib_device *ieee); + void (*del_hwsec_cam_entry)(struct rtllib_device *ieee, u8 *addr); + int (*set_key_for_peer) (struct net_device *dev,u8 *Addr,u8 KeyIndex,u16 KeyType,u32 *KeyContent ); + int (*ext_patch_rtllib_start_protocol) (struct rtllib_device *ieee); + + short (*ext_patch_rtllib_probe_req_1) (struct rtllib_device *ieee); + u8* (*ext_patch_rtllib_probe_req_2) (struct rtllib_device *ieee, struct sk_buff *skb, u8 *tag); + + void (*ext_patch_rtllib_stop_protocol) (struct rtllib_device *ieee,bool is_silent_reset); + + int (*ext_patch_rtllib_rx_frame_softmac_on_peerlink_open) (struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats); + int (*ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm) (struct rtllib_device *ieee, struct sk_buff *skb); + int (*ext_patch_rtllib_rx_frame_softmac_on_peerlink_close) (struct rtllib_device *ieee, struct sk_buff *skb); + void (*ext_patch_rtllib_close_all_peerlink) (struct rtllib_device *ieee, __le16 reason); + + int (*ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report) (struct rtllib_device *ieee, struct sk_buff *skb); + int (*ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req) (struct rtllib_device *ieee, struct sk_buff *skb); + + int (*ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq) (struct rtllib_device *ieee, struct sk_buff *skb,struct rtllib_rx_stats *rx_stats); + int (*ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep) (struct rtllib_device *ieee, struct sk_buff *skb,struct rtllib_rx_stats *rx_stats); + int (*ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr) (struct rtllib_device *ieee, struct sk_buff *skb,struct rtllib_rx_stats *rx_stats); + int (*ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann) (struct rtllib_device *ieee, struct sk_buff *skb,struct rtllib_rx_stats *rx_stats); + int (*ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann) (struct rtllib_device *ieee, struct sk_buff *skb,struct rtllib_rx_stats *rx_stats); + + int (*ext_patch_rtllib_ext_stop_scan_wq_set_channel) (struct rtllib_device *ieee); + int (*ext_patch_r819x_wx_set_mesh_chan)(struct net_device *dev, unsigned char channel); + void (*ext_patch_r819x_wx_set_channel) (struct rtllib_device *ieee, int ch); + + int (*ext_patch_rtllib_softmac_xmit_get_rate) (struct rtllib_device *ieee, struct sk_buff *skb); + int (*ext_patch_rtllib_rx_frame_softmac_on_auth)(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats); + int (*ext_patch_rtllib_rx_frame_softmac_on_deauth)(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats); + int (*ext_patch_rtllib_tx_data)(struct rtllib_device *ieee, struct rtllib_hdr_4addrqos* header, u8* is_peer_n_mode, u8* is_peer_40M, + u8* is_peer_shortGI_40M, u8* is_peer_shortGI_20M,u8* peer_highest_opra_rate,u8* peer_ratr_index, u8* AID); + bool (*ext_patch_rtllib_is_mesh)(struct rtllib_device * ieee,u8 * addr); + ppeerMP_htinfo (*ext_patch_rtllib_get_peermp_htinfo) (struct rtllib_device *ieee,u8 * daddr); + int (* ext_patch_rtllib_create_crypt_for_peer)(struct rtllib_device * ieee); + void (*ext_patch_rtllib_start_mesh)(struct rtllib_device *ieee); + void (*ext_patch_rtllib_rx_mgt_on_probe_req) ( struct rtllib_device *ieee, struct rtllib_probe_request *beacon, struct rtllib_rx_stats *stats); + unsigned int(*ext_patch_rtllib_process_probe_response_1)(struct rtllib_device *ieee, struct rtllib_probe_response *beacon, struct rtllib_rx_stats *stats); + + void (*ext_patch_rtllib_rx_mgt_update_expire) ( struct rtllib_device *ieee, struct sk_buff *skb); + struct sk_buff* (*ext_patch_get_beacon_get_probersp)(struct rtllib_device *ieee, u8 *dest, struct rtllib_network *net); + + int (*ext_patch_rtllib_rx_on_rx) (struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats, u16 type, u16 stype); + + int (*ext_patch_rtllib_rx_frame_get_hdrlen) (struct rtllib_device *ieee, struct sk_buff *skb); + + int (*ext_patch_rtllib_rx_frame_get_mac_hdrlen) (struct rtllib_device *ieee, struct sk_buff *skb); + + int (*ext_patch_rtllib_rx_frame_get_mesh_hdrlen_llc) (struct rtllib_device *ieee, struct sk_buff *skb); + int (*ext_patch_rtllib_rx_is_valid_framectl) (struct rtllib_device *ieee, u16 fc, u16 type, u16 stype); + + + /* added by david for setting acl dynamically */ + u8 (*ext_patch_rtllib_acl_query) (struct rtllib_device *ieee, u8 *sa); + + + struct sk_buff* (*ext_patch_rtllib_send_ath_commit) (struct rtllib_device * ieee,u8 * addr); + struct sk_buff* (*ext_patch_rtllib_send_ath_confirm) (struct rtllib_device * ieee,u8 * addr); + int (*ext_patch_rtllib_rx_ath_commit) (struct rtllib_device * ieee,u8 * addr); + u8 (*ext_patch_rtllib_rx_ath_confirm) (struct rtllib_device *ieee, u8* pframe,u16 strlen,u8 *addr); + +#endif + bool (*SetFwCmdHandler)(struct net_device *dev, FW_CMD_IO_TYPE FwCmdIO); + void (*UpdateHalRAMaskHandler)(struct net_device* dev, bool bMulticast, u8 macId, u8 MimoPs, u8 WirelessMode, u8 bCurTxBW40MHz, u8 rssi_level); + void (*UpdateBeaconInterruptHandler)(struct net_device* dev, bool start); + void (*UpdateInterruptMaskHandler)(struct net_device* dev, u32 AddMSR, u32 RemoveMSR); + u16 (*rtl_11n_user_show_rates)(struct net_device *dev); + void (*ScanOperationBackupHandler)(struct net_device *dev, u8 Operation); + void (*LedControlHandler)(struct net_device * dev, LED_CTL_MODE LedAction); + void (*SetHwRegHandler)(struct net_device *dev,u8 variable,u8* val); + void (*GetHwRegHandler)(struct net_device *dev,u8 variable,u8* val); + + void (*AllowAllDestAddrHandler)(struct net_device *dev, bool bAllowAllDA, bool WriteIntoReg); + +#ifdef ENABLE_IPS + void (*rtllib_ips_leave_wq) (struct net_device *dev); + void (*rtllib_ips_leave)(struct net_device *dev); +#endif +#ifdef ENABLE_LPS + void (*LeisurePSLeave)(struct net_device *dev); +#endif +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + void (*SetBeaconRelatedRegistersHandler)(struct net_device* dev); + bool (*check_ht_cap)(struct net_device* dev, struct sta_info *sta, struct rtllib_network* net); + void (*Adhoc_InitRateAdaptive)(struct net_device *dev,struct sta_info *pEntry); +#endif + void (*rtllib_rfkill_poll)(struct net_device *dev); + + /* This must be the last item so that it points to the data + * allocated beyond this structure by alloc_rtllib */ + u8 priv[0]; +}; + +#define IEEE_A (1<<0) +#define IEEE_B (1<<1) +#define IEEE_G (1<<2) +#define IEEE_N_24G (1<<4) +#define IEEE_N_5G (1<<5) +#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) + +/* Generate a 802.11 header */ + +/* Uses the channel change callback directly + * instead of [start/stop] scan callbacks + */ +#define IEEE_SOFTMAC_SCAN (1<<2) + +/* Perform authentication and association handshake */ +#define IEEE_SOFTMAC_ASSOCIATE (1<<3) + +/* Generate probe requests */ +#define IEEE_SOFTMAC_PROBERQ (1<<4) + +/* Generate respones to probe requests */ +#define IEEE_SOFTMAC_PROBERS (1<<5) + +/* The ieee802.11 stack will manages the netif queue + * wake/stop for the driver, taking care of 802.11 + * fragmentation. See softmac.c for details. */ +#define IEEE_SOFTMAC_TX_QUEUE (1<<7) + +/* Uses only the softmac_data_hard_start_xmit + * even for TX management frames. + */ +#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8) + +/* Generate beacons. The stack will enqueue beacons + * to the card + */ +#define IEEE_SOFTMAC_BEACONS (1<<6) + +#ifdef _RTL8192_EXT_PATCH_ +static inline int rtllib_find_MP(struct rtllib_device* ieee, const u8* addr, u8 set) +{ + int i=0; + for (i=1; icryptlist[i]->used == 0) && set) { + memcpy(ieee->cryptlist[i]->mac_addr, addr, ETH_ALEN); + ieee->cryptlist[i]->used = 1; + return i; + } else if (0 == memcmp(ieee->cryptlist[i]->mac_addr, addr, ETH_ALEN)) { + return i; + } + } + return -1; +} +#endif + +static inline void *rtllib_priv(struct net_device *dev) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + return ((struct rtllib_device *)netdev_priv(dev))->priv; +#else + return ((struct rtllib_device *)dev->priv)->priv; +#endif +} + +extern inline int rtllib_is_empty_essid(const char *essid, int essid_len) +{ + /* Single white space is for Linksys APs */ + if (essid_len == 1 && essid[0] == ' ') + return 1; + + /* Otherwise, if the entire essid is 0, we assume it is hidden */ + while (essid_len) { + essid_len--; + if (essid[essid_len] != '\0') + return 0; + } + + return 1; +} + +extern inline int rtllib_is_valid_mode(struct rtllib_device *ieee, int mode) +{ + /* + * It is possible for both access points and our device to support + * combinations of modes, so as long as there is one valid combination + * of ap/device supported modes, then return success + * + */ + if ((mode & IEEE_A) && + (ieee->modulation & RTLLIB_OFDM_MODULATION) && + (ieee->freq_band & RTLLIB_52GHZ_BAND)) + return 1; + + if ((mode & IEEE_G) && + (ieee->modulation & RTLLIB_OFDM_MODULATION) && + (ieee->freq_band & RTLLIB_24GHZ_BAND)) + return 1; + + if ((mode & IEEE_B) && + (ieee->modulation & RTLLIB_CCK_MODULATION) && + (ieee->freq_band & RTLLIB_24GHZ_BAND)) + return 1; + + return 0; +} + +extern inline int rtllib_get_hdrlen(u16 fc) +{ + int hdrlen = RTLLIB_3ADDR_LEN; + + switch (WLAN_FC_GET_TYPE(fc)) { + case RTLLIB_FTYPE_DATA: + if ((fc & RTLLIB_FCTL_FROMDS) && (fc & RTLLIB_FCTL_TODS)) + hdrlen = RTLLIB_4ADDR_LEN; /* Addr4 */ + if(RTLLIB_QOS_HAS_SEQ(fc)) + hdrlen += 2; /* QOS ctrl*/ + break; + case RTLLIB_FTYPE_CTL: + switch (WLAN_FC_GET_STYPE(fc)) { + case RTLLIB_STYPE_CTS: + case RTLLIB_STYPE_ACK: + hdrlen = RTLLIB_1ADDR_LEN; + break; + default: + hdrlen = RTLLIB_2ADDR_LEN; + break; + } + break; + } + + return hdrlen; +} + +static inline u8 *rtllib_get_payload(struct rtllib_hdr *hdr) +{ + switch (rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl))) { + case RTLLIB_1ADDR_LEN: + return ((struct rtllib_hdr_1addr *)hdr)->payload; + case RTLLIB_2ADDR_LEN: + return ((struct rtllib_hdr_2addr *)hdr)->payload; + case RTLLIB_3ADDR_LEN: + return ((struct rtllib_hdr_3addr *)hdr)->payload; + case RTLLIB_4ADDR_LEN: + return ((struct rtllib_hdr_4addr *)hdr)->payload; + } + return NULL; +} + +static inline int rtllib_is_ofdm_rate(u8 rate) +{ + switch (rate & ~RTLLIB_BASIC_RATE_MASK) { + case RTLLIB_OFDM_RATE_6MB: + case RTLLIB_OFDM_RATE_9MB: + case RTLLIB_OFDM_RATE_12MB: + case RTLLIB_OFDM_RATE_18MB: + case RTLLIB_OFDM_RATE_24MB: + case RTLLIB_OFDM_RATE_36MB: + case RTLLIB_OFDM_RATE_48MB: + case RTLLIB_OFDM_RATE_54MB: + return 1; + } + return 0; +} + +static inline int rtllib_is_cck_rate(u8 rate) +{ + switch (rate & ~RTLLIB_BASIC_RATE_MASK) { + case RTLLIB_CCK_RATE_1MB: + case RTLLIB_CCK_RATE_2MB: + case RTLLIB_CCK_RATE_5MB: + case RTLLIB_CCK_RATE_11MB: + return 1; + } + return 0; +} + + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)) +static inline unsigned compare_ether_addr(const u8 *addr1, const u8 *addr2) +{ + const u16 *a = (const u16 *) addr1; + const u16 *b = (const u16 *) addr2; + + BUILD_BUG_ON(ETH_ALEN != 6); + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0; +} +#endif + +/* rtllib.c */ +extern void free_rtllib(struct net_device *dev); +extern struct net_device *alloc_rtllib(int sizeof_priv); + +extern int rtllib_set_encryption(struct rtllib_device *ieee); + +/* rtllib_tx.c */ + +#ifdef _RTL8192_EXT_PATCH_ +extern int rtllib_encrypt_fragment( + struct rtllib_device *ieee, + struct sk_buff *frag, + int hdr_len, u8 is_mesh, u8 entry); +#else +extern int rtllib_encrypt_fragment( + struct rtllib_device *ieee, + struct sk_buff *frag, + int hdr_len); +#endif + +extern int rtllib_xmit(struct sk_buff *skb, struct net_device *dev); +extern int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev); +#ifdef _RTL8192_EXT_PATCH_ +extern int rtllib_classify(struct sk_buff *skb, u8 bIsAmsdu); +extern int rtllib_mesh_xmit(struct sk_buff *skb, struct net_device *dev); +extern inline int rtllib_put_snap(u8 *data, u16 h_proto); +#endif +extern void rtllib_txb_free(struct rtllib_txb *); + +#ifdef ENABLE_AMSDU +extern struct sk_buff *AMSDU_Aggregation(struct rtllib_device *ieee, struct sk_buff_head *pSendList); +extern u8 AMSDU_GetAggregatibleList(struct rtllib_device *ieee, struct sk_buff *pCurSkb, struct sk_buff_head *pSendList, u8 queue_index); +extern struct sk_buff *msh_AMSDU_Aggregation(struct rtllib_device *ieee, struct sk_buff_head *pSendList); +extern u8 msh_AMSDU_GetAggregatibleList(struct rtllib_device *ieee, struct sk_buff *pCurSkb, struct sk_buff_head *pSendList, u8 queue_index); +#endif + +/* rtllib_rx.c */ +extern int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats); +extern void rtllib_rx_mgt(struct rtllib_device *ieee, + struct sk_buff *skb, + struct rtllib_rx_stats *stats); +extern void rtllib_rx_probe_rq(struct rtllib_device *ieee, + struct sk_buff *skb); +extern int IsLegalChannel( struct rtllib_device *rtllib, u8 channel); + +/* rtllib_wx.c */ +extern int rtllib_wx_get_scan(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +#ifdef _RTL8192_EXT_PATCH_ +extern int rtllib_wx_set_encode(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key, u8 is_mesh); +extern int rtllib_wx_get_encode(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key, u8 is_mesh); +extern int rtllib_mesh_set_encode_ext(struct rtllib_device *ieee, + struct iw_point *encoding, struct iw_encode_ext *ext, int entry); +#if WIRELESS_EXT >= 18 +extern int rtllib_wx_get_encode_ext(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data* wrqu, char *extra, u8 is_mesh); +extern int rtllib_wx_set_encode_ext(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data* wrqu, char *extra, u8 is_mesh); +#endif +#else +extern int rtllib_wx_set_encode(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +extern int rtllib_wx_get_encode(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *key); +#if WIRELESS_EXT >= 18 +extern int rtllib_wx_get_encode_ext(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data* wrqu, char *extra); +extern int rtllib_wx_set_encode_ext(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data* wrqu, char *extra); +#endif +#endif +extern int rtllib_wx_set_auth(struct rtllib_device *ieee, + struct iw_request_info *info, + struct iw_param *data, char *extra); +extern int rtllib_wx_set_mlme(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +extern int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len); + +/* rtllib_softmac.c */ +extern short rtllib_is_54g(struct rtllib_network *net); +extern short rtllib_is_shortslot(struct rtllib_network net); +extern int rtllib_rx_frame_softmac(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats, u16 type, + u16 stype); +extern void rtllib_softmac_new_net(struct rtllib_device *ieee, struct rtllib_network *net); + +void SendDisassociation(struct rtllib_device *ieee, bool deauth, u16 asRsn); +extern void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee); + +extern void rtllib_stop_send_beacons(struct rtllib_device *ieee); +extern void notify_wx_assoc_event(struct rtllib_device *ieee); +extern void rtllib_softmac_check_all_nets(struct rtllib_device *ieee); +extern void rtllib_start_bss(struct rtllib_device *ieee); +extern void rtllib_start_master_bss(struct rtllib_device *ieee); +extern void rtllib_start_ibss(struct rtllib_device *ieee); +extern void rtllib_softmac_init(struct rtllib_device *ieee); +extern void rtllib_softmac_free(struct rtllib_device *ieee); +extern void rtllib_associate_abort(struct rtllib_device *ieee); +extern void rtllib_disassociate(struct rtllib_device *ieee); +extern void rtllib_stop_scan(struct rtllib_device *ieee); +extern bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan); +extern void rtllib_stop_scan_syncro(struct rtllib_device *ieee); +extern void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh); +extern inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee); +extern u8 MgntQuery_MgntFrameTxRate(struct rtllib_device *ieee); +extern void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr); +extern void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl); +extern void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee); +extern void rtllib_check_all_nets(struct rtllib_device *ieee); +extern void rtllib_start_protocol(struct rtllib_device *ieee); +extern void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown); + +extern void rtllib_EnableNetMonitorMode(struct net_device* dev, bool bInitState); +extern void rtllib_DisableNetMonitorMode(struct net_device* dev, bool bInitState); +extern void rtllib_EnableIntelPromiscuousMode(struct net_device* dev, bool bInitState); +extern void rtllib_DisableIntelPromiscuousMode(struct net_device* dev, bool bInitState); +extern void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh); + +extern void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 mesh_flag, u8 shutdown); +extern void rtllib_softmac_start_protocol(struct rtllib_device *ieee,u8 mesh_flag); + +#ifdef _RTL8192_EXT_PATCH_ +extern void rtllib_start_mesh_protocol(struct rtllib_device *ieee); +extern void rtllib_stop_mesh_protocol(struct rtllib_device *ieee); +#endif +extern void rtllib_reset_queue(struct rtllib_device *ieee); +extern void rtllib_wake_queue(struct rtllib_device *ieee); +extern void rtllib_stop_queue(struct rtllib_device *ieee); +extern void rtllib_wake_all_queues(struct rtllib_device *ieee); +extern void rtllib_stop_all_queues(struct rtllib_device *ieee); +extern struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee); +extern void rtllib_start_send_beacons(struct rtllib_device *ieee); +extern void rtllib_stop_send_beacons(struct rtllib_device *ieee); +extern int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p, u8 is_mesh); + +extern void notify_wx_assoc_event(struct rtllib_device *ieee); +extern void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success); + +extern void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee); +extern u16 rtllib_query_seqnum(struct rtllib_device*ieee, struct sk_buff* skb, u8* dst); +extern u8 rtllib_ap_sec_type(struct rtllib_device *ieee); + +#ifdef _RTL8192_EXT_PATCH_ +extern void rtllib_resp_to_auth(struct rtllib_device *ieee, int s, u8* dest); +extern void rtllib_associate_step1(struct rtllib_device *ieee,u8 * addr); +extern bool rtllib_ext_prepare_to_joinmesh(struct rtllib_device *ieee, struct rtllib_network *pstat); +extern u8 HTFilterMCSRate( struct rtllib_device* ieee, u8* pSupportMCS, u8* pOperateMCS); +extern void HTUseDefaultSetting(struct rtllib_device* ieee); +extern void rtllib_start_scan(struct rtllib_device *ieee); +extern struct sk_buff* rtllib_ext_probe_resp_by_net(struct rtllib_device *ieee, u8 *dest, struct rtllib_network *net); +extern int rtllib_network_init(struct rtllib_device *ieee, struct rtllib_probe_response *beacon, struct rtllib_network *network, struct rtllib_rx_stats *stats); +extern struct rtllib_txb *rtllib_alloc_txb(int nr_frags, int txb_size, int gfp_mask); +extern void rtllib_ext_send_11s_beacon(struct rtllib_device *ieee); +#endif + +/* rtllib_crypt_ccmp&tkip&wep.c */ +extern void rtllib_tkip_null(void); +extern void rtllib_wep_null(void); +extern void rtllib_ccmp_null(void); + +/* rtllib_softmac_wx.c */ + +extern int rtllib_wx_get_wap(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *ext); + +extern int rtllib_wx_set_wap(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *awrq, + char *extra); + +extern int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b); + +extern int rtllib_wx_set_rate(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int rtllib_wx_get_rate(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +extern int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +extern int rtllib_wx_set_essid(struct rtllib_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *extra); + +extern int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +extern int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); + +#ifdef _RTL8192_EXT_PATCH_ +extern int rtllib_wx_get_freq(struct rtllib_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b, u8 is_mesh); +#else +extern int rtllib_wx_get_freq(struct rtllib_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b); +#endif +extern void rtllib_wx_sync_scan_wq(void *data); + +extern int rtllib_wx_set_rawtx(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int rtllib_wx_get_name(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int rtllib_wx_set_power(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int rtllib_wx_get_power(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int rtllib_wx_set_rts(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); + +extern int rtllib_wx_get_rts(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +#ifdef _RTL8192_EXT_PATCH_ +extern void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr); +#endif +#define MAX_RECEIVE_BUFFER_SIZE 9100 +extern void HTDebugHTCapability(u8* CapIE, u8* TitleString ); +extern void HTDebugHTInfo(u8* InfoIE, u8* TitleString); + +void HTSetConnectBwMode(struct rtllib_device* ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset); +extern void HTUpdateDefaultSetting(struct rtllib_device* ieee); +#ifdef _RTL8192_EXT_PATCH_ +extern void HTConstructCapabilityElement(struct rtllib_device* ieee, u8* posHTCap, u8* len, u8 isEncrypt, u8 bIsBcn,bool bAssoc); +#else +extern void HTConstructCapabilityElement(struct rtllib_device* ieee, u8* posHTCap, u8* len, u8 isEncrypt,bool bAssoc); +#endif +extern void HTConstructInfoElement(struct rtllib_device* ieee, u8* posHTInfo, u8* len, u8 isEncrypt); +extern void HTConstructRT2RTAggElement(struct rtllib_device* ieee, u8* posRT2RTAgg, u8* len); +extern void HTOnAssocRsp(struct rtllib_device *ieee); +extern void HTInitializeHTInfo(struct rtllib_device* ieee); +extern void HTInitializeBssDesc(PBSS_HT pBssHT); +extern void HTResetSelfAndSavePeerSetting(struct rtllib_device* ieee, struct rtllib_network * pNetwork); +extern void HTUpdateSelfAndPeerSetting(struct rtllib_device* ieee, struct rtllib_network * pNetwork); +extern u8 HTGetHighestMCSRate(struct rtllib_device* ieee, u8* pMCSRateSet, u8* pMCSFilter); +extern u8 MCS_FILTER_ALL[]; +extern u16 MCS_DATA_RATE[2][2][77] ; +extern u8 HTCCheck(struct rtllib_device* ieee, u8* pFrame); +extern void HTResetIOTSetting(PRT_HIGH_THROUGHPUT pHTInfo); +extern bool IsHTHalfNmodeAPs(struct rtllib_device* ieee); +extern u16 HTHalfMcsToDataRate(struct rtllib_device* ieee, u8 nMcsRate); +extern u16 HTMcsToDataRate( struct rtllib_device* ieee, u8 nMcsRate); +extern u16 TxCountToDataRate( struct rtllib_device* ieee, u8 nDataRate); +extern int rtllib_rx_ADDBAReq( struct rtllib_device* ieee, struct sk_buff *skb); +extern int rtllib_rx_ADDBARsp( struct rtllib_device* ieee, struct sk_buff *skb); +extern int rtllib_rx_DELBA(struct rtllib_device* ieee,struct sk_buff *skb); +extern void TsInitAddBA( struct rtllib_device* ieee, PTX_TS_RECORD pTS, u8 Policy, u8 bOverwritePending); +extern void TsInitDelBA( struct rtllib_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect); +extern void BaSetupTimeOut(unsigned long data); +extern void TxBaInactTimeout(unsigned long data); +extern void RxBaInactTimeout(unsigned long data); +extern void ResetBaEntry( PBA_RECORD pBA); +extern bool GetTs( + struct rtllib_device* ieee, + PTS_COMMON_INFO *ppTS, + u8* Addr, + u8 TID, + TR_SELECT TxRxSelect, + bool bAddNewTs + ); +extern void TSInitialize(struct rtllib_device *ieee); +extern void TsStartAddBaProcess(struct rtllib_device* ieee, PTX_TS_RECORD pTxTS); +extern void RemovePeerTS(struct rtllib_device* ieee, u8* Addr); +extern void RemoveAllTS(struct rtllib_device* ieee); +#ifdef _RTL8192_EXT_PATCH_ +extern void ResetAdmitTRStream(struct rtllib_device *ieee, u8 *Addr); +#endif +void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh); + +extern const long rtllib_wlan_frequencies[]; + +extern inline void rtllib_increment_scans(struct rtllib_device *ieee) +{ + ieee->scans++; +} + +extern inline int rtllib_get_scans(struct rtllib_device *ieee) +{ + return ieee->scans; +} + +static inline const char *escape_essid(const char *essid, u8 essid_len) { + static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; + const char *s = essid; + char *d = escaped; + + if (rtllib_is_empty_essid(essid, essid_len)) { + memcpy(escaped, "", sizeof("")); + return escaped; + } + + essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); + while (essid_len--) { + if (*s == '\0') { + *d++ = '\\'; + *d++ = '0'; + s++; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return escaped; +} + +#define CONVERT_RATE(_ieee, _MGN_RATE) (_MGN_RATE + * Portions Copyright (C) 2004, Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See README and COPYING for + * more details. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "rtllib.h" + +#ifndef BUILT_IN_RTLLIB +MODULE_AUTHOR("Jouni Malinen"); +MODULE_DESCRIPTION("HostAP crypto"); +MODULE_LICENSE("GPL"); +#endif + +struct rtllib_crypto_alg { + struct list_head list; + struct rtllib_crypto_ops *ops; +}; + + +struct rtllib_crypto { + struct list_head algs; + spinlock_t lock; +}; + +static struct rtllib_crypto *hcrypt; + +void rtllib_crypt_deinit_entries(struct rtllib_device *ieee, + int force) +{ + struct list_head *ptr, *n; + struct rtllib_crypt_data *entry; + + for (ptr = ieee->crypt_deinit_list.next, n = ptr->next; + ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) { + entry = list_entry(ptr, struct rtllib_crypt_data, list); + + if (atomic_read(&entry->refcnt) != 0 && !force) + continue; + + list_del(ptr); + + if (entry->ops) { + entry->ops->deinit(entry->priv); +#ifndef BUILT_IN_RTLLIB +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + module_put(entry->ops->owner); +#else + __MOD_DEC_USE_COUNT(entry->ops->owner); +#endif +#endif + } + kfree(entry); + } +} + +void rtllib_crypt_deinit_handler(unsigned long data) +{ + struct rtllib_device *ieee = (struct rtllib_device *)data; + unsigned long flags; + + spin_lock_irqsave(&ieee->lock, flags); + rtllib_crypt_deinit_entries(ieee, 0); + if (!list_empty(&ieee->crypt_deinit_list)) { + printk(KERN_DEBUG "%s: entries remaining in delayed crypt " + "deletion list\n", ieee->dev->name); + ieee->crypt_deinit_timer.expires = jiffies + HZ; + add_timer(&ieee->crypt_deinit_timer); + } + spin_unlock_irqrestore(&ieee->lock, flags); + +} + +void rtllib_crypt_delayed_deinit(struct rtllib_device *ieee, + struct rtllib_crypt_data **crypt) +{ + struct rtllib_crypt_data *tmp; + unsigned long flags; + + if (*crypt == NULL) + return; + + tmp = *crypt; + *crypt = NULL; + + /* must not run ops->deinit() while there may be pending encrypt or + * decrypt operations. Use a list of delayed deinits to avoid needing + * locking. */ + + spin_lock_irqsave(&ieee->lock, flags); + list_add(&tmp->list, &ieee->crypt_deinit_list); + if (!timer_pending(&ieee->crypt_deinit_timer)) { + ieee->crypt_deinit_timer.expires = jiffies + HZ; + add_timer(&ieee->crypt_deinit_timer); + } + spin_unlock_irqrestore(&ieee->lock, flags); +} + +int rtllib_register_crypto_ops(struct rtllib_crypto_ops *ops) +{ + unsigned long flags; + struct rtllib_crypto_alg *alg; + + if (hcrypt == NULL) + return -1; + + alg = kmalloc(sizeof(*alg), GFP_KERNEL); + if (alg == NULL) + return -ENOMEM; + + memset(alg, 0, sizeof(*alg)); + alg->ops = ops; + + spin_lock_irqsave(&hcrypt->lock, flags); + list_add(&alg->list, &hcrypt->algs); + spin_unlock_irqrestore(&hcrypt->lock, flags); + + printk(KERN_DEBUG "rtllib_crypt: registered algorithm '%s'\n", + ops->name); + + return 0; +} + +int rtllib_unregister_crypto_ops(struct rtllib_crypto_ops *ops) +{ + unsigned long flags; + struct list_head *ptr; + struct rtllib_crypto_alg *del_alg = NULL; + + if (hcrypt == NULL) + return -1; + + spin_lock_irqsave(&hcrypt->lock, flags); + for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { + struct rtllib_crypto_alg *alg = + (struct rtllib_crypto_alg *) ptr; + if (alg->ops == ops) { + list_del(&alg->list); + del_alg = alg; + break; + } + } + spin_unlock_irqrestore(&hcrypt->lock, flags); + + if (del_alg) { + printk(KERN_DEBUG "rtllib_crypt: unregistered algorithm " + "'%s'\n", ops->name); + kfree(del_alg); + } + + return del_alg ? 0 : -1; +} + + +struct rtllib_crypto_ops * rtllib_get_crypto_ops(const char *name) +{ + unsigned long flags; + struct list_head *ptr; + struct rtllib_crypto_alg *found_alg = NULL; + + if (hcrypt == NULL) + return NULL; + + spin_lock_irqsave(&hcrypt->lock, flags); + for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { + struct rtllib_crypto_alg *alg = + (struct rtllib_crypto_alg *) ptr; + if (strcmp(alg->ops->name, name) == 0) { + found_alg = alg; + break; + } + } + spin_unlock_irqrestore(&hcrypt->lock, flags); + + if (found_alg) + return found_alg->ops; + else + return NULL; +} + + +static void * rtllib_crypt_null_init(int keyidx) { return (void *) 1; } +static void rtllib_crypt_null_deinit(void *priv) {} + +static struct rtllib_crypto_ops rtllib_crypt_null = { + .name = "NULL", + .init = rtllib_crypt_null_init, + .deinit = rtllib_crypt_null_deinit, + .encrypt_mpdu = NULL, + .decrypt_mpdu = NULL, + .encrypt_msdu = NULL, + .decrypt_msdu = NULL, + .set_key = NULL, + .get_key = NULL, + .extra_prefix_len = 0, + .extra_postfix_len = 0, + .owner = THIS_MODULE, +}; + + +int __init rtllib_crypto_init(void) +{ + int ret = -ENOMEM; + + hcrypt = kmalloc(sizeof(*hcrypt), GFP_KERNEL); + if (!hcrypt) + goto out; + + memset(hcrypt, 0, sizeof(*hcrypt)); + INIT_LIST_HEAD(&hcrypt->algs); + spin_lock_init(&hcrypt->lock); + + ret = rtllib_register_crypto_ops(&rtllib_crypt_null); + if (ret < 0) { + kfree(hcrypt); + hcrypt = NULL; + } +out: + return ret; +} + + +void __exit rtllib_crypto_deinit(void) +{ + struct list_head *ptr, *n; + + if (hcrypt == NULL) + return; + + for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs; + ptr = n, n = ptr->next) { + struct rtllib_crypto_alg *alg = + (struct rtllib_crypto_alg *) ptr; + list_del(ptr); + printk(KERN_DEBUG "rtllib_crypt: unregistered algorithm " + "'%s' (deinit)\n", alg->ops->name); + kfree(alg); + } + + kfree(hcrypt); +} + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(rtllib_crypt_deinit_entries); +EXPORT_SYMBOL_RSL(rtllib_crypt_deinit_handler); +EXPORT_SYMBOL_RSL(rtllib_crypt_delayed_deinit); + +EXPORT_SYMBOL_RSL(rtllib_register_crypto_ops); +EXPORT_SYMBOL_RSL(rtllib_unregister_crypto_ops); +EXPORT_SYMBOL_RSL(rtllib_get_crypto_ops); + +module_init(rtllib_crypto_init); +module_exit(rtllib_crypto_deinit); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib_crypt.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib_crypt.h @@ -0,0 +1,93 @@ +/* + * Original code based on Host AP (software wireless LAN access point) driver + * for Intersil Prism2/2.5/3. + * + * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + * + * Copyright (c) 2002-2003, Jouni Malinen + * + * Adaption to a generic IEEE 802.11 stack by James Ketrenos + * + * + * Copyright (c) 2004, Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See README and COPYING for + * more details. + */ + +/* + * This file defines the interface to the rtllib crypto module. + */ +#ifndef RTLLIB_CRYPT_H +#define RTLLIB_CRYPT_H + +#include + +struct rtllib_crypto_ops { + const char *name; + + /* init new crypto context (e.g., allocate private data space, + * select IV, etc.); returns NULL on failure or pointer to allocated + * private data on success */ + void * (*init)(int keyidx); + + /* deinitialize crypto context and free allocated private data */ + void (*deinit)(void *priv); + + /* encrypt/decrypt return < 0 on error or >= 0 on success. The return + * value from decrypt_mpdu is passed as the keyidx value for + * decrypt_msdu. skb must have enough head and tail room for the + * encryption; if not, error will be returned; these functions are + * called for all MPDUs (i.e., fragments). + */ + int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); + int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); + + /* These functions are called for full MSDUs, i.e. full frames. + * These can be NULL if full MSDU operations are not needed. */ + int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv); + int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len, + void *priv, struct rtllib_device* ieee); + + int (*set_key)(void *key, int len, u8 *seq, void *priv); + int (*get_key)(void *key, int len, u8 *seq, void *priv); + + /* procfs handler for printing out key information and possible + * statistics */ + char * (*print_stats)(char *p, void *priv); + + /* maximum number of bytes added by encryption; encrypt buf is + * allocated with extra_prefix_len bytes, copy of in_buf, and + * extra_postfix_len; encrypt need not use all this space, but + * the result must start at the beginning of the buffer and correct + * length must be returned */ + int extra_prefix_len, extra_postfix_len; + + struct module *owner; +}; + +struct rtllib_crypt_data { + struct list_head list; /* delayed deletion list */ + struct rtllib_crypto_ops *ops; + void *priv; + atomic_t refcnt; +}; + +int rtllib_register_crypto_ops(struct rtllib_crypto_ops *ops); +int rtllib_unregister_crypto_ops(struct rtllib_crypto_ops *ops); +struct rtllib_crypto_ops * rtllib_get_crypto_ops(const char *name); +void rtllib_crypt_deinit_entries(struct rtllib_device *, int); +void rtllib_crypt_deinit_handler(unsigned long); +void rtllib_crypt_delayed_deinit(struct rtllib_device *ieee, + struct rtllib_crypt_data **crypt); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK) +#endif +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,31)) +#define crypto_alloc_tfm crypto_alloc_tfm_rsl +#define crypto_free_tfm crypto_free_tfm_rsl +#endif + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib_crypt_ccmp.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib_crypt_ccmp.c @@ -0,0 +1,544 @@ +/* + * Host AP crypt: host-based CCMP encryption implementation for Host AP driver + * + * Copyright (c) 2003-2004, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See README and COPYING for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _RTL8192_EXT_PATCH_ +#include +#endif +#include "rtllib.h" + +#if defined(BUILT_IN_CRYPTO) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include "rtl_crypto.h" +#else +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + #include +#else + #include +#endif + +#ifndef BUILT_IN_RTLLIB +MODULE_AUTHOR("Jouni Malinen"); +MODULE_DESCRIPTION("Host AP crypt: CCMP"); +MODULE_LICENSE("GPL"); +#endif + + +#define AES_BLOCK_LEN 16 +#define CCMP_HDR_LEN 8 +#define CCMP_MIC_LEN 8 +#define CCMP_TK_LEN 16 +#define CCMP_PN_LEN 6 + +struct rtllib_ccmp_data { + u8 key[CCMP_TK_LEN]; + int key_set; + + u8 tx_pn[CCMP_PN_LEN]; + u8 rx_pn[CCMP_PN_LEN]; + + u32 dot11RSNAStatsCCMPFormatErrors; + u32 dot11RSNAStatsCCMPReplays; + u32 dot11RSNAStatsCCMPDecryptErrors; + + int key_idx; + + struct crypto_tfm *tfm; + + /* scratch buffers for virt_to_page() (crypto API) */ + u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], + tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; + u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; +}; + +void rtllib_ccmp_aes_encrypt(struct crypto_tfm *tfm, + const u8 pt[16], u8 ct[16]) +{ +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + struct scatterlist src, dst; + +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + src.page = virt_to_page(pt); + src.offset = offset_in_page(pt); + src.length = AES_BLOCK_LEN; + + dst.page = virt_to_page(ct); + dst.offset = offset_in_page(ct); + dst.length = AES_BLOCK_LEN; + +#else + sg_init_one(&src, pt, AES_BLOCK_LEN); + sg_init_one(&dst, ct, AES_BLOCK_LEN); +#endif + + crypto_cipher_encrypt(tfm, &dst, &src, AES_BLOCK_LEN); +#else + crypto_cipher_encrypt_one((void*)tfm, ct, pt); +#endif +} + +static void * rtllib_ccmp_init(int key_idx) +{ + struct rtllib_ccmp_data *priv; + + priv = kmalloc(sizeof(*priv), GFP_ATOMIC); + if (priv == NULL) + goto fail; + memset(priv, 0, sizeof(*priv)); + priv->key_idx = key_idx; + +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + priv->tfm = crypto_alloc_tfm("aes", 0); + if (priv->tfm == NULL) { + printk(KERN_DEBUG "rtllib_crypt_ccmp: could not allocate " + "crypto API aes\n"); + goto fail; + } + #else + priv->tfm = (void*)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->tfm)) { + printk(KERN_DEBUG "rtllib_crypt_ccmp: could not allocate " + "crypto API aes\n"); + priv->tfm = NULL; + goto fail; + } + #endif + return priv; + +fail: + if (priv) { + if (priv->tfm) + #if defined(BUILT_IN_CRYPTO) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) + crypto_free_tfm(priv->tfm); + #else + crypto_free_cipher((void*)priv->tfm); + #endif + kfree(priv); + } + + return NULL; +} + + +static void rtllib_ccmp_deinit(void *priv) +{ + struct rtllib_ccmp_data *_priv = priv; + if (_priv && _priv->tfm) +#if defined(BUILT_IN_CRYPTO) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) + crypto_free_tfm(_priv->tfm); +#else + crypto_free_cipher((void*)_priv->tfm); +#endif + kfree(priv); +} + + +static inline void xor_block(u8 *b, u8 *a, size_t len) +{ + int i; + for (i = 0; i < len; i++) + b[i] ^= a[i]; +} + + + +static void ccmp_init_blocks(struct crypto_tfm *tfm, + struct rtllib_hdr_4addr *hdr, + u8 *pn, size_t dlen, u8 *b0, u8 *auth, + u8 *s0) +{ + u8 *pos, qc = 0; + size_t aad_len; + u16 fc; + int a4_included, qc_included; + u8 aad[2 * AES_BLOCK_LEN]; + + fc = le16_to_cpu(hdr->frame_ctl); + a4_included = ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) == + (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)); + /* + qc_included = ((WLAN_FC_GET_TYPE(fc) == RTLLIB_FTYPE_DATA) && + (WLAN_FC_GET_STYPE(fc) & 0x08)); + */ + qc_included = ((WLAN_FC_GET_TYPE(fc) == RTLLIB_FTYPE_DATA) && + (WLAN_FC_GET_STYPE(fc) & 0x80)); + aad_len = 22; + if (a4_included) + aad_len += 6; + if (qc_included) { + pos = (u8 *) &hdr->addr4; + if (a4_included) + pos += 6; + qc = *pos & 0x0f; + aad_len += 2; + } + /* CCM Initial Block: + * Flag (Include authentication header, M=3 (8-octet MIC), + * L=1 (2-octet Dlen)) + * Nonce: 0x00 | A2 | PN + * Dlen */ + b0[0] = 0x59; + b0[1] = qc; + memcpy(b0 + 2, hdr->addr2, ETH_ALEN); + memcpy(b0 + 8, pn, CCMP_PN_LEN); + b0[14] = (dlen >> 8) & 0xff; + b0[15] = dlen & 0xff; + + /* AAD: + * FC with bits 4..6 and 11..13 masked to zero; 14 is always one + * A1 | A2 | A3 + * SC with bits 4..15 (seq#) masked to zero + * A4 (if present) + * QC (if present) + */ + pos = (u8 *) hdr; + aad[0] = 0; /* aad_len >> 8 */ + aad[1] = aad_len & 0xff; + aad[2] = pos[0] & 0x8f; + aad[3] = pos[1] & 0xc7; + memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); + pos = (u8 *) &hdr->seq_ctl; + aad[22] = pos[0] & 0x0f; + aad[23] = 0; /* all bits masked */ + memset(aad + 24, 0, 8); + if (a4_included) + memcpy(aad + 24, hdr->addr4, ETH_ALEN); + if (qc_included) { + aad[a4_included ? 30 : 24] = qc; + /* rest of QC masked */ + } + + /* Start with the first block and AAD */ + rtllib_ccmp_aes_encrypt(tfm, b0, auth); + xor_block(auth, aad, AES_BLOCK_LEN); + rtllib_ccmp_aes_encrypt(tfm, auth, auth); + xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); + rtllib_ccmp_aes_encrypt(tfm, auth, auth); + b0[0] &= 0x07; + b0[14] = b0[15] = 0; + rtllib_ccmp_aes_encrypt(tfm, b0, s0); +} + + + +static int rtllib_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct rtllib_ccmp_data *key = priv; + int data_len, i; + u8 *pos; + struct rtllib_hdr_4addr *hdr; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); +#ifdef _RTL8192_EXT_PATCH_ + u8 broadcastaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + u8 is_broadcast_data = 0; +#endif + if (skb_headroom(skb) < CCMP_HDR_LEN || + skb_tailroom(skb) < CCMP_MIC_LEN || + skb->len < hdr_len) + return -1; + + data_len = skb->len - hdr_len; + pos = skb_push(skb, CCMP_HDR_LEN); + memmove(pos, pos + CCMP_HDR_LEN, hdr_len); + pos += hdr_len; + + i = CCMP_PN_LEN - 1; + while (i >= 0) { + key->tx_pn[i]++; + if (key->tx_pn[i] != 0) + break; + i--; + } + + *pos++ = key->tx_pn[5]; + *pos++ = key->tx_pn[4]; + *pos++ = 0; + *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */; + *pos++ = key->tx_pn[3]; + *pos++ = key->tx_pn[2]; + *pos++ = key->tx_pn[1]; + *pos++ = key->tx_pn[0]; + + + hdr = (struct rtllib_hdr_4addr *) skb->data; +#ifdef _RTL8192_EXT_PATCH_ + if(tcb_desc->badhoc == 0){ + if(memcmp(hdr->addr1,broadcastaddr,6) == 0){ + is_broadcast_data = 1; + tcb_desc->bHwSec = 0; + } + if(is_multicast_ether_addr(hdr->addr1)){ + tcb_desc->bHwSec = 0; + } + } +#endif + if (!tcb_desc->bHwSec) + { + int blocks, last, len; + u8 *mic; + u8 *b0 = key->tx_b0; + u8 *b = key->tx_b; + u8 *e = key->tx_e; + u8 *s0 = key->tx_s0; + + mic = skb_put(skb, CCMP_MIC_LEN); + + ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); + + blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; + last = data_len % AES_BLOCK_LEN; + + for (i = 1; i <= blocks; i++) { + len = (i == blocks && last) ? last : AES_BLOCK_LEN; + /* Authentication */ + xor_block(b, pos, len); + rtllib_ccmp_aes_encrypt(key->tfm, b, b); + /* Encryption, with counter */ + b0[14] = (i >> 8) & 0xff; + b0[15] = i & 0xff; + rtllib_ccmp_aes_encrypt(key->tfm, b0, e); + xor_block(pos, e, len); + pos += len; + } + + for (i = 0; i < CCMP_MIC_LEN; i++) + mic[i] = b[i] ^ s0[i]; + } + return 0; +} + + +static int rtllib_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct rtllib_ccmp_data *key = priv; + u8 keyidx, *pos; + struct rtllib_hdr_4addr *hdr; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + u8 pn[6]; + + if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) { + key->dot11RSNAStatsCCMPFormatErrors++; + return -1; + } + + hdr = (struct rtllib_hdr_4addr *) skb->data; + pos = skb->data + hdr_len; + keyidx = pos[3]; + if (!(keyidx & (1 << 5))) { + if (net_ratelimit()) { + printk(KERN_DEBUG "CCMP: received packet without ExtIV" + " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2)); + } + key->dot11RSNAStatsCCMPFormatErrors++; + return -2; + } + keyidx >>= 6; + if (key->key_idx != keyidx) { + printk(KERN_DEBUG "CCMP: RX tkey->key_idx=%d frame " + "keyidx=%d priv=%p\n", key->key_idx, keyidx, priv); + return -6; + } + if (!key->key_set) { + if (net_ratelimit()) { + printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT + " with keyid=%d that does not have a configured" + " key\n", MAC_ARG(hdr->addr2), keyidx); + } + return -3; + } + + pn[0] = pos[7]; + pn[1] = pos[6]; + pn[2] = pos[5]; + pn[3] = pos[4]; + pn[4] = pos[1]; + pn[5] = pos[0]; + pos += 8; +#ifndef _RTL8192_EXT_PATCH_ + if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { + if (net_ratelimit()) { + ; + } + key->dot11RSNAStatsCCMPReplays++; + return -4; + } +#endif + if (!tcb_desc->bHwSec) + { + size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN; + u8 *mic = skb->data + skb->len - CCMP_MIC_LEN; + u8 *b0 = key->rx_b0; + u8 *b = key->rx_b; + u8 *a = key->rx_a; + int i, blocks, last, len; + + + ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b); + xor_block(mic, b, CCMP_MIC_LEN); + + blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; + last = data_len % AES_BLOCK_LEN; + + for (i = 1; i <= blocks; i++) { + len = (i == blocks && last) ? last : AES_BLOCK_LEN; + /* Decrypt, with counter */ + b0[14] = (i >> 8) & 0xff; + b0[15] = i & 0xff; + rtllib_ccmp_aes_encrypt(key->tfm, b0, b); + xor_block(pos, b, len); + /* Authentication */ + xor_block(a, pos, len); + rtllib_ccmp_aes_encrypt(key->tfm, a, a); + pos += len; + } + + if (memcmp(mic, a, CCMP_MIC_LEN) != 0) { + if (net_ratelimit()) { + printk(KERN_DEBUG "CCMP: decrypt failed: STA=" + MAC_FMT "\n", MAC_ARG(hdr->addr2)); + } + key->dot11RSNAStatsCCMPDecryptErrors++; + return -5; + } + + memcpy(key->rx_pn, pn, CCMP_PN_LEN); + } + /* Remove hdr and MIC */ + memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len); + skb_pull(skb, CCMP_HDR_LEN); + skb_trim(skb, skb->len - CCMP_MIC_LEN); + + return keyidx; +} + + +static int rtllib_ccmp_set_key(void *key, int len, u8 *seq, void *priv) +{ + struct rtllib_ccmp_data *data = priv; + int keyidx; + struct crypto_tfm *tfm = data->tfm; + + keyidx = data->key_idx; + memset(data, 0, sizeof(*data)); + data->key_idx = keyidx; + data->tfm = tfm; + if (len == CCMP_TK_LEN) { + memcpy(data->key, key, CCMP_TK_LEN); + data->key_set = 1; + if (seq) { + data->rx_pn[0] = seq[5]; + data->rx_pn[1] = seq[4]; + data->rx_pn[2] = seq[3]; + data->rx_pn[3] = seq[2]; + data->rx_pn[4] = seq[1]; + data->rx_pn[5] = seq[0]; + } + crypto_cipher_setkey((void*)data->tfm, data->key, CCMP_TK_LEN); + } else if (len == 0) + data->key_set = 0; + else + return -1; + + return 0; +} + + +static int rtllib_ccmp_get_key(void *key, int len, u8 *seq, void *priv) +{ + struct rtllib_ccmp_data *data = priv; + + if (len < CCMP_TK_LEN) + return -1; + + if (!data->key_set) + return 0; + memcpy(key, data->key, CCMP_TK_LEN); + + if (seq) { + seq[0] = data->tx_pn[5]; + seq[1] = data->tx_pn[4]; + seq[2] = data->tx_pn[3]; + seq[3] = data->tx_pn[2]; + seq[4] = data->tx_pn[1]; + seq[5] = data->tx_pn[0]; + } + + return CCMP_TK_LEN; +} + + +static char * rtllib_ccmp_print_stats(char *p, void *priv) +{ + struct rtllib_ccmp_data *ccmp = priv; + p += sprintf(p, "key[%d] alg=CCMP key_set=%d " + "tx_pn=%02x%02x%02x%02x%02x%02x " + "rx_pn=%02x%02x%02x%02x%02x%02x " + "format_errors=%d replays=%d decrypt_errors=%d\n", + ccmp->key_idx, ccmp->key_set, + MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn), + ccmp->dot11RSNAStatsCCMPFormatErrors, + ccmp->dot11RSNAStatsCCMPReplays, + ccmp->dot11RSNAStatsCCMPDecryptErrors); + + return p; +} + +void rtllib_ccmp_null(void) +{ + return; +} + +static struct rtllib_crypto_ops rtllib_crypt_ccmp = { + .name = "CCMP", + .init = rtllib_ccmp_init, + .deinit = rtllib_ccmp_deinit, + .encrypt_mpdu = rtllib_ccmp_encrypt, + .decrypt_mpdu = rtllib_ccmp_decrypt, + .encrypt_msdu = NULL, + .decrypt_msdu = NULL, + .set_key = rtllib_ccmp_set_key, + .get_key = rtllib_ccmp_get_key, + .print_stats = rtllib_ccmp_print_stats, + .extra_prefix_len = CCMP_HDR_LEN, + .extra_postfix_len = CCMP_MIC_LEN, + .owner = THIS_MODULE, +}; + + +int __init rtllib_crypto_ccmp_init(void) +{ + return rtllib_register_crypto_ops(&rtllib_crypt_ccmp); +} + + +void __exit rtllib_crypto_ccmp_exit(void) +{ + rtllib_unregister_crypto_ops(&rtllib_crypt_ccmp); +} + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(rtllib_ccmp_null); + +module_init(rtllib_crypto_ccmp_init); +module_exit(rtllib_crypto_ccmp_exit); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib_crypt_tkip.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib_crypt_tkip.c @@ -0,0 +1,1047 @@ +/* + * Host AP crypt: host-based TKIP encryption implementation for Host AP driver + * + * Copyright (c) 2003-2004, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See README and COPYING for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _RTL8192_EXT_PATCH_ +#include +#endif +#include "rtllib.h" +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20)) +#endif + + +#if defined(BUILT_IN_CRYPTO) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include "rtl_crypto.h" +#else +#include +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + #include +#else + #include +#endif + +#include + +#ifndef BUILT_IN_RTLLIB +MODULE_AUTHOR("Jouni Malinen"); +MODULE_DESCRIPTION("Host AP crypt: TKIP"); +MODULE_LICENSE("GPL"); +#endif + + +struct rtllib_tkip_data { +#define TKIP_KEY_LEN 32 + u8 key[TKIP_KEY_LEN]; + int key_set; + + u32 tx_iv32; + u16 tx_iv16; + u16 tx_ttak[5]; + int tx_phase1_done; + + u32 rx_iv32; + u16 rx_iv16; + bool initialized; + u16 rx_ttak[5]; + int rx_phase1_done; + u32 rx_iv32_new; + u16 rx_iv16_new; + + u32 dot11RSNAStatsTKIPReplays; + u32 dot11RSNAStatsTKIPICVErrors; + u32 dot11RSNAStatsTKIPLocalMICFailures; + + int key_idx; +#if ( !defined(BUILT_IN_CRYPTO) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED)) ) + struct crypto_blkcipher *rx_tfm_arc4; + struct crypto_hash *rx_tfm_michael; + struct crypto_blkcipher *tx_tfm_arc4; + struct crypto_hash *tx_tfm_michael; +#else + struct crypto_tfm *tx_tfm_arc4; + struct crypto_tfm *tx_tfm_michael; + struct crypto_tfm *rx_tfm_arc4; + struct crypto_tfm *rx_tfm_michael; +#endif + /* scratch buffers for virt_to_page() (crypto API) */ + u8 rx_hdr[16], tx_hdr[16]; +}; + +static void * rtllib_tkip_init(int key_idx) +{ + struct rtllib_tkip_data *priv; + + priv = kmalloc(sizeof(*priv), GFP_ATOMIC); + if (priv == NULL) + goto fail; + memset(priv, 0, sizeof(*priv)); + priv->key_idx = key_idx; +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + priv->tx_tfm_arc4 = crypto_alloc_tfm("arc4", 0); + if (priv->tx_tfm_arc4 == NULL) { + printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate " + "crypto API arc4\n"); + goto fail; + } + + priv->tx_tfm_michael = crypto_alloc_tfm("michael_mic", 0); + if (priv->tx_tfm_michael == NULL) { + printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate " + "crypto API michael_mic\n"); + goto fail; + } + + priv->rx_tfm_arc4 = crypto_alloc_tfm("arc4", 0); + if (priv->rx_tfm_arc4 == NULL) { + printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate " + "crypto API arc4\n"); + goto fail; + } + + priv->rx_tfm_michael = crypto_alloc_tfm("michael_mic", 0); + if (priv->rx_tfm_michael == NULL) { + printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate " + "crypto API michael_mic\n"); + goto fail; + } +#else + priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->tx_tfm_arc4)) { + printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate " + "crypto API arc4\n"); + priv->tx_tfm_arc4 = NULL; + goto fail; + } + + priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->tx_tfm_michael)) { + printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate " + "crypto API michael_mic\n"); + priv->tx_tfm_michael = NULL; + goto fail; + } + + priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->rx_tfm_arc4)) { + printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate " + "crypto API arc4\n"); + priv->rx_tfm_arc4 = NULL; + goto fail; + } + + priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, + CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->rx_tfm_michael)) { + printk(KERN_DEBUG "rtllib_crypt_tkip: could not allocate " + "crypto API michael_mic\n"); + priv->rx_tfm_michael = NULL; + goto fail; + } +#endif + return priv; + +fail: + if (priv) { +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + if (priv->tx_tfm_michael) + crypto_free_tfm(priv->tx_tfm_michael); + if (priv->tx_tfm_arc4) + crypto_free_tfm(priv->tx_tfm_arc4); + if (priv->rx_tfm_michael) + crypto_free_tfm(priv->rx_tfm_michael); + if (priv->rx_tfm_arc4) + crypto_free_tfm(priv->rx_tfm_arc4); + +#else + if (priv->tx_tfm_michael) + crypto_free_hash(priv->tx_tfm_michael); + if (priv->tx_tfm_arc4) + crypto_free_blkcipher(priv->tx_tfm_arc4); + if (priv->rx_tfm_michael) + crypto_free_hash(priv->rx_tfm_michael); + if (priv->rx_tfm_arc4) + crypto_free_blkcipher(priv->rx_tfm_arc4); +#endif + kfree(priv); + } + + return NULL; +} + + +static void rtllib_tkip_deinit(void *priv) +{ + struct rtllib_tkip_data *_priv = priv; +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + if (_priv->tx_tfm_michael) + crypto_free_tfm(_priv->tx_tfm_michael); + if (_priv->tx_tfm_arc4) + crypto_free_tfm(_priv->tx_tfm_arc4); + if (_priv->rx_tfm_michael) + crypto_free_tfm(_priv->rx_tfm_michael); + if (_priv->rx_tfm_arc4) + crypto_free_tfm(_priv->rx_tfm_arc4); +#else + if (_priv) { + if (_priv->tx_tfm_michael) + crypto_free_hash(_priv->tx_tfm_michael); + if (_priv->tx_tfm_arc4) + crypto_free_blkcipher(_priv->tx_tfm_arc4); + if (_priv->rx_tfm_michael) + crypto_free_hash(_priv->rx_tfm_michael); + if (_priv->rx_tfm_arc4) + crypto_free_blkcipher(_priv->rx_tfm_arc4); + } +#endif + kfree(priv); +} + + +static inline u16 RotR1(u16 val) +{ + return (val >> 1) | (val << 15); +} + + +static inline u8 Lo8(u16 val) +{ + return val & 0xff; +} + + +static inline u8 Hi8(u16 val) +{ + return val >> 8; +} + + +static inline u16 Lo16(u32 val) +{ + return val & 0xffff; +} + + +static inline u16 Hi16(u32 val) +{ + return val >> 16; +} + + +static inline u16 Mk16(u8 hi, u8 lo) +{ + return lo | (((u16) hi) << 8); +} + + +static inline u16 Mk16_le(u16 *v) +{ + return le16_to_cpu(*v); +} + + +static const u16 Sbox[256] = +{ + 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, + 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, + 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, + 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, + 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, + 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, + 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, + 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, + 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, + 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, + 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, + 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, + 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, + 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, + 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, + 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, + 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, + 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, + 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, + 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, + 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, + 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, + 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, + 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, + 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, + 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, + 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, + 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, + 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, + 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, + 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, + 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, +}; + + +static inline u16 _S_(u16 v) +{ + u16 t = Sbox[Hi8(v)]; + return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)); +} + + +#define PHASE1_LOOP_COUNT 8 + + +static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32) +{ + int i, j; + + /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */ + TTAK[0] = Lo16(IV32); + TTAK[1] = Hi16(IV32); + TTAK[2] = Mk16(TA[1], TA[0]); + TTAK[3] = Mk16(TA[3], TA[2]); + TTAK[4] = Mk16(TA[5], TA[4]); + + for (i = 0; i < PHASE1_LOOP_COUNT; i++) { + j = 2 * (i & 1); + TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j])); + TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j])); + TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j])); + TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j])); + TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i; + } +} + + +static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, + u16 IV16) +{ + /* Make temporary area overlap WEP seed so that the final copy can be + * avoided on little endian hosts. */ + u16 *PPK = (u16 *) &WEPSeed[4]; + + /* Step 1 - make copy of TTAK and bring in TSC */ + PPK[0] = TTAK[0]; + PPK[1] = TTAK[1]; + PPK[2] = TTAK[2]; + PPK[3] = TTAK[3]; + PPK[4] = TTAK[4]; + PPK[5] = TTAK[4] + IV16; + + /* Step 2 - 96-bit bijective mixing using S-box */ + PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0])); + PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2])); + PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4])); + PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6])); + PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8])); + PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10])); + + PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12])); + PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14])); + PPK[2] += RotR1(PPK[1]); + PPK[3] += RotR1(PPK[2]); + PPK[4] += RotR1(PPK[3]); + PPK[5] += RotR1(PPK[4]); + + /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value + * WEPSeed[0..2] is transmitted as WEP IV */ + WEPSeed[0] = Hi8(IV16); + WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F; + WEPSeed[2] = Lo8(IV16); + WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1); + +#ifdef __BIG_ENDIAN + { + int i; + for (i = 0; i < 6; i++) + PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8); + } +#endif +} + + +static int rtllib_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct rtllib_tkip_data *tkey = priv; + int len; + u8 *pos; + struct rtllib_hdr_4addr *hdr; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + + #if ( !defined(BUILT_IN_CRYPTO) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED)) ) + struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; + int ret = 0; + #endif + u8 rc4key[16], *icv; + u32 crc; +#ifdef _RTL8192_EXT_PATCH_ + u8 broadcastaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + u8 is_broadcast_data = 0; +#endif + struct scatterlist sg; + + if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 || + skb->len < hdr_len) + return -1; + + hdr = (struct rtllib_hdr_4addr *) skb->data; +#ifdef _RTL8192_EXT_PATCH_ + if(tcb_desc->badhoc == 0){ + if(memcmp(hdr->addr1,broadcastaddr,6) == 0){ + is_broadcast_data = 1; + tcb_desc->bHwSec = 0; + } + if(is_multicast_ether_addr(hdr->addr1)){ + tcb_desc->bHwSec = 0; + } + } +#endif +#if 0 +printk("@@ tkey\n"); +printk("%x|", ((u32*)tkey->key)[0]); +printk("%x|", ((u32*)tkey->key)[1]); +printk("%x|", ((u32*)tkey->key)[2]); +printk("%x|", ((u32*)tkey->key)[3]); +printk("%x|", ((u32*)tkey->key)[4]); +printk("%x|", ((u32*)tkey->key)[5]); +printk("%x|", ((u32*)tkey->key)[6]); +printk("%x\n", ((u32*)tkey->key)[7]); +#endif + + if (!tcb_desc->bHwSec) + { + if (!tkey->tx_phase1_done) { + tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, + tkey->tx_iv32); + tkey->tx_phase1_done = 1; + } + tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); + } + else + tkey->tx_phase1_done = 1; + + + len = skb->len - hdr_len; + pos = skb_push(skb, 8); + memmove(pos, pos + 8, hdr_len); + pos += hdr_len; + + if (tcb_desc->bHwSec) + { + *pos++ = Hi8(tkey->tx_iv16); + *pos++ = (Hi8(tkey->tx_iv16) | 0x20) & 0x7F; + *pos++ = Lo8(tkey->tx_iv16); + } + else + { + *pos++ = rc4key[0]; + *pos++ = rc4key[1]; + *pos++ = rc4key[2]; + } + + *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */; + *pos++ = tkey->tx_iv32 & 0xff; + *pos++ = (tkey->tx_iv32 >> 8) & 0xff; + *pos++ = (tkey->tx_iv32 >> 16) & 0xff; + *pos++ = (tkey->tx_iv32 >> 24) & 0xff; + + if (!tcb_desc->bHwSec) + { + icv = skb_put(skb, 4); +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) + crc = ~crc32_le(~0, pos, len); +#else + crc = ~ether_crc_le(len, pos); +#endif + icv[0] = crc; + icv[1] = crc >> 8; + icv[2] = crc >> 16; + icv[3] = crc >> 24; + +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + sg.page = virt_to_page(pos); + sg.offset = offset_in_page(pos); + sg.length = len + 4; +#else + sg_init_one(&sg, pos, len+4); +#endif + + +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + crypto_cipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); + crypto_cipher_encrypt(tkey->tx_tfm_arc4, &sg, &sg, len + 4); +#else + crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); + ret= crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); +#endif + + } + + tkey->tx_iv16++; + if (tkey->tx_iv16 == 0) { + tkey->tx_phase1_done = 0; + tkey->tx_iv32++; + } + + if (!tcb_desc->bHwSec) + #if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + return 0; + #else + return ret; + #endif + else + return 0; + + +} + +static int rtllib_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct rtllib_tkip_data *tkey = priv; + u8 keyidx, *pos; + u32 iv32; + u16 iv16; + struct rtllib_hdr_4addr *hdr; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + #if ( !defined(BUILT_IN_CRYPTO) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED)) ) + struct blkcipher_desc desc = {.tfm = tkey->rx_tfm_arc4}; + #endif + u8 rc4key[16]; + u8 icv[4]; + u32 crc; + struct scatterlist sg; + int plen; + if (skb->len < hdr_len + 8 + 4) + return -1; + + hdr = (struct rtllib_hdr_4addr *) skb->data; + pos = skb->data + hdr_len; + keyidx = pos[3]; + if (!(keyidx & (1 << 5))) { + if (net_ratelimit()) { + printk(KERN_DEBUG "TKIP: received packet without ExtIV" + " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2)); + } + return -2; + } + keyidx >>= 6; + if (tkey->key_idx != keyidx) { + printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame " + "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv); + return -6; + } + if (!tkey->key_set) { + if (net_ratelimit()) { + printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT + " with keyid=%d that does not have a configured" + " key\n", MAC_ARG(hdr->addr2), keyidx); + } + return -3; + } + iv16 = (pos[0] << 8) | pos[2]; + iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); + pos += 8; + + if (!tcb_desc->bHwSec || (skb->cb[0] == 1)) + { + if ((iv32 < tkey->rx_iv32 || + (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16))&&tkey->initialized) { + if (net_ratelimit()) { + printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT + " previous TSC %08x%04x received TSC " + "%08x%04x\n", MAC_ARG(hdr->addr2), + tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); + } + tkey->dot11RSNAStatsTKIPReplays++; + return -4; + } + tkey->initialized = true; + + if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) { + tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32); + tkey->rx_phase1_done = 1; + } + tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16); + + plen = skb->len - hdr_len - 12; + +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + sg.page = virt_to_page(pos); + sg.offset = offset_in_page(pos); + sg.length = plen + 4; +#else + sg_init_one(&sg, pos, plen+4); +#endif + +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + crypto_cipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); + crypto_cipher_decrypt(tkey->rx_tfm_arc4, &sg, &sg, plen + 4); +#else + crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); + if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { + if (net_ratelimit()) { + printk(KERN_DEBUG ": TKIP: failed to decrypt " + "received packet from " MAC_FMT "\n", + MAC_ARG(hdr->addr2)); + } + return -7; + } +#endif + + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) + crc = ~crc32_le(~0, pos, plen); + #else + crc = ~ether_crc_le(plen, pos); + #endif + icv[0] = crc; + icv[1] = crc >> 8; + icv[2] = crc >> 16; + icv[3] = crc >> 24; + + if (memcmp(icv, pos + plen, 4) != 0) { + if (iv32 != tkey->rx_iv32) { + /* Previously cached Phase1 result was already lost, so + * it needs to be recalculated for the next packet. */ + tkey->rx_phase1_done = 0; + } + if (net_ratelimit()) { + printk(KERN_DEBUG "TKIP: ICV error detected: STA=" + MAC_FMT "\n", MAC_ARG(hdr->addr2)); + } + tkey->dot11RSNAStatsTKIPICVErrors++; + return -5; + } + + } + + /* Update real counters only after Michael MIC verification has + * completed */ + tkey->rx_iv32_new = iv32; + tkey->rx_iv16_new = iv16; + + /* Remove IV and ICV */ + memmove(skb->data + 8, skb->data, hdr_len); + skb_pull(skb, 8); + skb_trim(skb, skb->len - 4); + +#ifdef JOHN_DUMP +if( ((u16*)skb->data)[0] & 0x4000){ + printk("@@ rx decrypted skb->data"); + int i; + for(i=0;ilen;i++){ + if( (i%24)==0 ) printk("\n"); + printk("%2x ", ((u8*)skb->data)[i]); + } + printk("\n"); +} +#endif /*JOHN_DUMP*/ + return keyidx; +} + + +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) +static int michael_mic(struct crypto_tfm * tfm_michael, u8 *key, u8 *hdr, + u8 *data, size_t data_len, u8 *mic) +{ + struct scatterlist sg[2]; +#if ( !defined(BUILT_IN_CRYPTO) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) ) + struct hash_desc desc; + int ret = 0; +#endif + + if (tfm_michael == NULL){ + printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); + return -1; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + sg[0].page = virt_to_page(hdr); + sg[0].offset = offset_in_page(hdr); + sg[0].length = 16; + + sg[1].page = virt_to_page(data); + sg[1].offset = offset_in_page(data); + sg[1].length = data_len; +#else + sg_init_table(sg, 2); + sg_set_buf(&sg[0], hdr, 16); + sg_set_buf(&sg[1], data, data_len); +#endif + +#if ( defined(BUILT_IN_CRYPTO) || LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) ) + crypto_digest_init(tfm_michael); + crypto_digest_setkey(tfm_michael, key, 8); + crypto_digest_update(tfm_michael, sg, 2); + crypto_digest_final(tfm_michael, mic); + return 0; +#else +if (crypto_hash_setkey(tkey->tfm_michael, key, 8)) + return -1; + + desc.tfm = tkey->tfm_michael; + desc.flags = 0; + ret = crypto_hash_digest(&desc, sg, data_len + 16, mic); + return ret; +#endif +} +#else +static int michael_mic(struct crypto_hash *tfm_michael, u8 * key, u8 * hdr, + u8 * data, size_t data_len, u8 * mic) +{ + struct hash_desc desc; + struct scatterlist sg[2]; + + if (tfm_michael == NULL) { + printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); + return -1; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) + sg[0].page = virt_to_page(hdr); + sg[0].offset = offset_in_page(hdr); + sg[0].length = 16; + + sg[1].page = virt_to_page(data); + sg[1].offset = offset_in_page(data); + sg[1].length = data_len; +#else + sg_init_table(sg, 2); + sg_set_buf(&sg[0], hdr, 16); + sg_set_buf(&sg[1], data, data_len); +#endif + + if (crypto_hash_setkey(tfm_michael, key, 8)) + return -1; + + desc.tfm = tfm_michael; + desc.flags = 0; + return crypto_hash_digest(&desc, sg, data_len + 16, mic); +} +#endif + + + +static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) +{ + struct rtllib_hdr_4addr *hdr11; + + hdr11 = (struct rtllib_hdr_4addr *) skb->data; + switch (le16_to_cpu(hdr11->frame_ctl) & + (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) { + case RTLLIB_FCTL_TODS: + memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ + memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ + break; + case RTLLIB_FCTL_FROMDS: + memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ + memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */ + break; + case RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS: + memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ + memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */ + break; + case 0: + memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ + memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ + break; + } + + hdr[12] = 0; /* priority */ + + hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ +} + + +static int rtllib_michael_mic_add(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct rtllib_tkip_data *tkey = priv; + u8 *pos; + struct rtllib_hdr_4addr *hdr; + + hdr = (struct rtllib_hdr_4addr *) skb->data; + + if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { + printk(KERN_DEBUG "Invalid packet for Michael MIC add " + "(tailroom=%d hdr_len=%d skb->len=%d)\n", + skb_tailroom(skb), hdr_len, skb->len); + return -1; + } + + michael_mic_hdr(skb, tkey->tx_hdr); + + if(RTLLIB_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) { + tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; + } + pos = skb_put(skb, 8); +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr, + skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) +#else + if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr, + skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) +#endif + return -1; + + return 0; +} + + +#if WIRELESS_EXT >= 18 +static void rtllib_michael_mic_failure(struct net_device *dev, + struct rtllib_hdr_4addr *hdr, + int keyidx) +{ + union iwreq_data wrqu; + struct iw_michaelmicfailure ev; + + /* TODO: needed parameters: count, keyid, key type, TSC */ + memset(&ev, 0, sizeof(ev)); + ev.flags = keyidx & IW_MICFAILURE_KEY_ID; + if (hdr->addr1[0] & 0x01) + ev.flags |= IW_MICFAILURE_GROUP; + else + ev.flags |= IW_MICFAILURE_PAIRWISE; + ev.src_addr.sa_family = ARPHRD_ETHER; + memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = sizeof(ev); + wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev); +} +#elif WIRELESS_EXT >= 15 +static void rtllib_michael_mic_failure(struct net_device *dev, + struct rtllib_hdr_4addr *hdr, + int keyidx) +{ + union iwreq_data wrqu; + char buf[128]; + + /* TODO: needed parameters: count, keyid, key type, TSC */ + sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr=" + MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni", + MAC_ARG(hdr->addr2)); + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = strlen(buf); + wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); +} +#else /* WIRELESS_EXT >= 15 */ +static inline void rtllib_michael_mic_failure(struct net_device *dev, + struct rtllib_hdr_4addr *hdr, + int keyidx) +{ +} +#endif /* WIRELESS_EXT >= 15 */ + +static int rtllib_michael_mic_verify(struct sk_buff *skb, int keyidx, + int hdr_len, void *priv, struct rtllib_device* ieee) +{ + struct rtllib_tkip_data *tkey = priv; + u8 mic[8]; + struct rtllib_hdr_4addr *hdr; + + hdr = (struct rtllib_hdr_4addr *) skb->data; + + if (!tkey->key_set) + return -1; + + michael_mic_hdr(skb, tkey->rx_hdr); + if(RTLLIB_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) { + tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; + } + +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr, + skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) +#else + if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr, + skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) +#endif + return -1; + + if ((memcmp(mic, skb->data + skb->len - 8, 8) != 0)||(ieee->force_mic_error)) { + struct rtllib_hdr_4addr *hdr; + hdr = (struct rtllib_hdr_4addr *) skb->data; + printk(KERN_DEBUG "%s: Michael MIC verification failed for " + "MSDU from " MAC_FMT " keyidx=%d\n", + skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2), + keyidx); + printk("%d, force_mic_error = %d\n", (memcmp(mic, skb->data + skb->len - 8, 8) != 0),\ + ieee->force_mic_error); + if (skb->dev) { + printk("skb->dev != NULL\n"); + rtllib_michael_mic_failure(skb->dev, hdr, keyidx); + } + tkey->dot11RSNAStatsTKIPLocalMICFailures++; + ieee->force_mic_error = false; + return -1; + } + + /* Update TSC counters for RX now that the packet verification has + * completed. */ + tkey->rx_iv32 = tkey->rx_iv32_new; + tkey->rx_iv16 = tkey->rx_iv16_new; + + skb_trim(skb, skb->len - 8); + + return 0; +} + + +static int rtllib_tkip_set_key(void *key, int len, u8 *seq, void *priv) +{ + struct rtllib_tkip_data *tkey = priv; + int keyidx; +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + struct crypto_tfm *tfm = tkey->tx_tfm_michael; + struct crypto_tfm *tfm2 = tkey->tx_tfm_arc4; + struct crypto_tfm *tfm3 = tkey->rx_tfm_michael; + struct crypto_tfm *tfm4 = tkey->rx_tfm_arc4; +#else + struct crypto_hash *tfm = tkey->tx_tfm_michael; + struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; + struct crypto_hash *tfm3 = tkey->rx_tfm_michael; + struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4; +#endif + + keyidx = tkey->key_idx; + memset(tkey, 0, sizeof(*tkey)); + tkey->key_idx = keyidx; +#if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + tkey->tx_tfm_michael = tfm; + tkey->tx_tfm_arc4 = tfm2; + tkey->rx_tfm_michael = tfm3; + tkey->rx_tfm_arc4 = tfm4; +#else + tkey->tx_tfm_michael = tfm; + tkey->tx_tfm_arc4 = tfm2; + tkey->rx_tfm_michael = tfm3; + tkey->rx_tfm_arc4 = tfm4; +#endif + + if (len == TKIP_KEY_LEN) { + memcpy(tkey->key, key, TKIP_KEY_LEN); + tkey->key_set = 1; + tkey->tx_iv16 = 1; /* TSC is initialized to 1 */ + if (seq) { + tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) | + (seq[3] << 8) | seq[2]; + tkey->rx_iv16 = (seq[1] << 8) | seq[0]; + } + } else if (len == 0) + tkey->key_set = 0; + else + return -1; + + return 0; +} + + +static int rtllib_tkip_get_key(void *key, int len, u8 *seq, void *priv) +{ + struct rtllib_tkip_data *tkey = priv; + + if (len < TKIP_KEY_LEN) + return -1; + + if (!tkey->key_set) + return 0; + memcpy(key, tkey->key, TKIP_KEY_LEN); + + if (seq) { + /* Return the sequence number of the last transmitted frame. */ + u16 iv16 = tkey->tx_iv16; + u32 iv32 = tkey->tx_iv32; + if (iv16 == 0) + iv32--; + iv16--; + seq[0] = tkey->tx_iv16; + seq[1] = tkey->tx_iv16 >> 8; + seq[2] = tkey->tx_iv32; + seq[3] = tkey->tx_iv32 >> 8; + seq[4] = tkey->tx_iv32 >> 16; + seq[5] = tkey->tx_iv32 >> 24; + } + + return TKIP_KEY_LEN; +} + + +static char * rtllib_tkip_print_stats(char *p, void *priv) +{ + struct rtllib_tkip_data *tkip = priv; + p += sprintf(p, "key[%d] alg=TKIP key_set=%d " + "tx_pn=%02x%02x%02x%02x%02x%02x " + "rx_pn=%02x%02x%02x%02x%02x%02x " + "replays=%d icv_errors=%d local_mic_failures=%d\n", + tkip->key_idx, tkip->key_set, + (tkip->tx_iv32 >> 24) & 0xff, + (tkip->tx_iv32 >> 16) & 0xff, + (tkip->tx_iv32 >> 8) & 0xff, + tkip->tx_iv32 & 0xff, + (tkip->tx_iv16 >> 8) & 0xff, + tkip->tx_iv16 & 0xff, + (tkip->rx_iv32 >> 24) & 0xff, + (tkip->rx_iv32 >> 16) & 0xff, + (tkip->rx_iv32 >> 8) & 0xff, + tkip->rx_iv32 & 0xff, + (tkip->rx_iv16 >> 8) & 0xff, + tkip->rx_iv16 & 0xff, + tkip->dot11RSNAStatsTKIPReplays, + tkip->dot11RSNAStatsTKIPICVErrors, + tkip->dot11RSNAStatsTKIPLocalMICFailures); + return p; +} + + +static struct rtllib_crypto_ops rtllib_crypt_tkip = { + .name = "TKIP", + .init = rtllib_tkip_init, + .deinit = rtllib_tkip_deinit, + .encrypt_mpdu = rtllib_tkip_encrypt, + .decrypt_mpdu = rtllib_tkip_decrypt, + .encrypt_msdu = rtllib_michael_mic_add, + .decrypt_msdu = rtllib_michael_mic_verify, + .set_key = rtllib_tkip_set_key, + .get_key = rtllib_tkip_get_key, + .print_stats = rtllib_tkip_print_stats, + .extra_prefix_len = 4 + 4, /* IV + ExtIV */ + .extra_postfix_len = 8 + 4, /* MIC + ICV */ + .owner = THIS_MODULE, +}; + + +int __init rtllib_crypto_tkip_init(void) +{ + return rtllib_register_crypto_ops(&rtllib_crypt_tkip); +} + + +void __exit rtllib_crypto_tkip_exit(void) +{ + rtllib_unregister_crypto_ops(&rtllib_crypt_tkip); +} + +void rtllib_tkip_null(void) +{ + return; +} + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(rtllib_tkip_null); + +module_init(rtllib_crypto_tkip_init); +module_exit(rtllib_crypto_tkip_exit); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib_crypt_wep.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib_crypt_wep.c @@ -0,0 +1,404 @@ +/* + * Host AP crypt: host-based WEP encryption implementation for Host AP driver + * + * Copyright (c) 2002-2004, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See README and COPYING for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef _RTL8192_EXT_PATCH_ +#include +#endif +#include "rtllib.h" + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20)) +#endif + + +#if defined(BUILT_IN_CRYPTO) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include "rtl_crypto.h" +#else +#include +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) + #include +#else + #include +#endif +#include +/* +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include "rtl_crypto.h" +#else +#include +#endif + +#include +#include +*/ +#ifndef BUILT_IN_RTLLIB +MODULE_AUTHOR("Jouni Malinen"); +MODULE_DESCRIPTION("Host AP crypt: WEP"); +MODULE_LICENSE("GPL"); +#endif +struct prism2_wep_data { + u32 iv; +#define WEP_KEY_LEN 13 + u8 key[WEP_KEY_LEN + 1]; + u8 key_len; + u8 key_idx; + #if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + struct crypto_tfm *tfm; + #else + struct crypto_blkcipher *tx_tfm; + struct crypto_blkcipher *rx_tfm; + #endif +}; + + +static void * prism2_wep_init(int keyidx) +{ + struct prism2_wep_data *priv; + + priv = kmalloc(sizeof(*priv), GFP_ATOMIC); + if (priv == NULL) + goto fail; + memset(priv, 0, sizeof(*priv)); + priv->key_idx = keyidx; + + #if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + priv->tfm = crypto_alloc_tfm("arc4", 0); + if (priv->tfm == NULL) { + printk(KERN_DEBUG "rtllib_crypt_wep: could not allocate " + "crypto API arc4\n"); + goto fail; + } + #else + priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->tx_tfm)) { + printk(KERN_DEBUG "rtllib_crypt_wep: could not allocate " + "crypto API arc4\n"); + priv->tx_tfm = NULL; + goto fail; + } + priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(priv->rx_tfm)) { + printk(KERN_DEBUG "rtllib_crypt_wep: could not allocate " + "crypto API arc4\n"); + priv->rx_tfm = NULL; + goto fail; + } + #endif + + /* start WEP IV from a random value */ + get_random_bytes(&priv->iv, 4); + + return priv; + +fail: + #if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + if (priv) { + if (priv->tfm) + crypto_free_tfm(priv->tfm); + kfree(priv); + } + #else + if (priv) { + if (priv->tx_tfm) + crypto_free_blkcipher(priv->tx_tfm); + if (priv->rx_tfm) + crypto_free_blkcipher(priv->rx_tfm); + kfree(priv); + } + #endif + return NULL; +} + + +static void prism2_wep_deinit(void *priv) +{ + struct prism2_wep_data *_priv = priv; + #if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + if (_priv && _priv->tfm) + crypto_free_tfm(_priv->tfm); + #else + if (_priv) { + if (_priv->tx_tfm) + crypto_free_blkcipher(_priv->tx_tfm); + if (_priv->rx_tfm) + crypto_free_blkcipher(_priv->rx_tfm); + } + #endif + kfree(priv); +} + +/* Perform WEP encryption on given skb that has at least 4 bytes of headroom + * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted, + * so the payload length increases with 8 bytes. + * + * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) + */ +static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct prism2_wep_data *wep = priv; + u32 klen, len; + u8 key[WEP_KEY_LEN + 3]; + u8 *pos; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + #if ( !defined(BUILT_IN_CRYPTO) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED)) ) + struct blkcipher_desc desc = {.tfm = wep->tx_tfm}; + #endif + u32 crc; + u8 *icv; +#ifdef _RTL8192_EXT_PATCH_ + u8 broadcastaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; + struct rtllib_hdr_3addr* tmp_header = (struct rtllib_hdr_3addr*)(skb->data); + u8 is_broadcast_data = 0; + u8 is_multicast_data = 0; +#endif + struct scatterlist sg; + if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || + skb->len < hdr_len){ + printk("Error!!!headroom=%d tailroom=%d skblen=%d hdr_len=%d\n",skb_headroom(skb),skb_tailroom(skb),skb->len,hdr_len); + return -1; + } +#ifdef _RTL8192_EXT_PATCH_ + if(tcb_desc->badhoc==0){ + if(memcmp(tmp_header->addr1,broadcastaddr,6) == 0){ + is_broadcast_data = 1; + tcb_desc->bHwSec = 0; + } + if(is_multicast_ether_addr(tmp_header->addr1)){ + is_multicast_data = 1; + tcb_desc->bHwSec = 0; + } + } +#endif + len = skb->len - hdr_len; + pos = skb_push(skb, 4); + memmove(pos, pos + 4, hdr_len); + pos += hdr_len; + + klen = 3 + wep->key_len; + + wep->iv++; + + /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key + * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N) + * can be used to speedup attacks, so avoid using them. */ + if ((wep->iv & 0xff00) == 0xff00) { + u8 B = (wep->iv >> 16) & 0xff; + if (B >= 3 && B < klen) + wep->iv += 0x0100; + } + + /* Prepend 24-bit IV to RC4 key and TX frame */ + *pos++ = key[0] = (wep->iv >> 16) & 0xff; + *pos++ = key[1] = (wep->iv >> 8) & 0xff; + *pos++ = key[2] = wep->iv & 0xff; + *pos++ = wep->key_idx << 6; + + /* Copy rest of the WEP key (the secret part) */ + memcpy(key + 3, wep->key, wep->key_len); + + if (!tcb_desc->bHwSec) + { + + /* Append little-endian CRC32 and encrypt it to produce ICV */ + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) + crc = ~crc32_le(~0, pos, len); + #else + crc = ~ether_crc_le(len, pos); + #endif + icv = skb_put(skb, 4); + icv[0] = crc; + icv[1] = crc >> 8; + icv[2] = crc >> 16; + icv[3] = crc >> 24; + + #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + sg.page = virt_to_page(pos); + sg.offset = offset_in_page(pos); + sg.length = len + 4; + #else + sg_init_one(&sg, pos, len+4); + #endif + #if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + crypto_cipher_setkey(wep->tfm, key, klen); + crypto_cipher_encrypt(wep->tfm, &sg, &sg, len + 4); + return 0; + #else + crypto_blkcipher_setkey(wep->tx_tfm, key, klen); + return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); + #endif + } + + return 0; +} + + +/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of + * the frame: IV (4 bytes), encrypted payload (including SNAP header), + * ICV (4 bytes). len includes both IV and ICV. + * + * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on + * failure. If frame is OK, IV and ICV will be removed. + */ +static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) +{ + struct prism2_wep_data *wep = priv; + u32 klen, plen; + u8 key[WEP_KEY_LEN + 3]; + u8 keyidx, *pos; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); + #if ( !defined(BUILT_IN_CRYPTO) && ((LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)) || (OPENSUSE_SLED)) ) + struct blkcipher_desc desc = {.tfm = wep->rx_tfm}; + #endif + u32 crc; + u8 icv[4]; + struct scatterlist sg; + if (skb->len < hdr_len + 8) + return -1; + + pos = skb->data + hdr_len; + key[0] = *pos++; + key[1] = *pos++; + key[2] = *pos++; + keyidx = *pos++ >> 6; + if (keyidx != wep->key_idx) + return -1; + + klen = 3 + wep->key_len; + + /* Copy rest of the WEP key (the secret part) */ + memcpy(key + 3, wep->key, wep->key_len); + + /* Apply RC4 to data and compute CRC32 over decrypted data */ + plen = skb->len - hdr_len - 8; + + if (!tcb_desc->bHwSec) + { + #if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + sg.page = virt_to_page(pos); + sg.offset = offset_in_page(pos); + sg.length = plen + 4; + #else + sg_init_one(&sg, pos, plen+4); + #endif + #if ( defined(BUILT_IN_CRYPTO) || ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)) && (!OPENSUSE_SLED)) ) + crypto_cipher_setkey(wep->tfm, key, klen); + crypto_cipher_decrypt(wep->tfm, &sg, &sg, plen + 4); + #else + crypto_blkcipher_setkey(wep->rx_tfm, key, klen); + if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) + return -7; + #endif + #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) + crc = ~crc32_le(~0, pos, plen); + #else + crc = ~ether_crc_le(plen, pos); + #endif + icv[0] = crc; + icv[1] = crc >> 8; + icv[2] = crc >> 16; + icv[3] = crc >> 24; + if (memcmp(icv, pos + plen, 4) != 0) { + /* ICV mismatch - drop frame */ + return -2; + } + } + /* Remove IV and ICV */ + memmove(skb->data + 4, skb->data, hdr_len); + skb_pull(skb, 4); + skb_trim(skb, skb->len - 4); + + return 0; +} + + +static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv) +{ + struct prism2_wep_data *wep = priv; + + if (len < 0 || len > WEP_KEY_LEN) + return -1; + + memcpy(wep->key, key, len); + wep->key_len = len; + + return 0; +} + + +static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv) +{ + struct prism2_wep_data *wep = priv; + + if (len < wep->key_len) + return -1; + + memcpy(key, wep->key, wep->key_len); + + return wep->key_len; +} + + +static char * prism2_wep_print_stats(char *p, void *priv) +{ + struct prism2_wep_data *wep = priv; + p += sprintf(p, "key[%d] alg=WEP len=%d\n", + wep->key_idx, wep->key_len); + return p; +} + + +static struct rtllib_crypto_ops rtllib_crypt_wep = { + .name = "WEP", + .init = prism2_wep_init, + .deinit = prism2_wep_deinit, + .encrypt_mpdu = prism2_wep_encrypt, + .decrypt_mpdu = prism2_wep_decrypt, + .encrypt_msdu = NULL, + .decrypt_msdu = NULL, + .set_key = prism2_wep_set_key, + .get_key = prism2_wep_get_key, + .print_stats = prism2_wep_print_stats, + .extra_prefix_len = 4, /* IV */ + .extra_postfix_len = 4, /* ICV */ + .owner = THIS_MODULE, +}; + + +int __init rtllib_crypto_wep_init(void) +{ + return rtllib_register_crypto_ops(&rtllib_crypt_wep); +} + + +void __exit rtllib_crypto_wep_exit(void) +{ + rtllib_unregister_crypto_ops(&rtllib_crypt_wep); +} + +void rtllib_wep_null(void) +{ + return; +} + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(rtllib_wep_null); + +module_init(rtllib_crypto_wep_init); +module_exit(rtllib_crypto_wep_exit); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib_endianfree.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib_endianfree.h @@ -0,0 +1,156 @@ +#ifndef __INC_ENDIANFREE_H +#define __INC_ENDIANFREE_H + +/* + * Call endian free function when + * 1. Read/write packet content. + * 2. Before write integer to IO. + * 3. After read integer from IO. + */ + +#define __MACHINE_LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define __MACHINE_BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net, ppc */ + +#define BYTE_ORDER __MACHINE_LITTLE_ENDIAN + +#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN +#define EF1Byte(_val) ((u8)(_val)) +#define EF2Byte(_val) ((u16)(_val)) +#define EF4Byte(_val) ((u32)(_val)) + +#else +#define EF1Byte(_val) ((u8)(_val)) +#define EF2Byte(_val) (((((u16)(_val))&0x00ff)<<8)|((((u16)(_val))&0xff00)>>8)) +#define EF4Byte(_val) (((((u32)(_val))&0x000000ff)<<24)|\ + ((((u32)(_val))&0x0000ff00)<<8)|\ + ((((u32)(_val))&0x00ff0000)>>8)|\ + ((((u32)(_val))&0xff000000)>>24)) +#endif + +#define ReadEF1Byte(_ptr) EF1Byte(*((u8 *)(_ptr))) +#define ReadEF2Byte(_ptr) EF2Byte(*((u16 *)(_ptr))) +#define ReadEF4Byte(_ptr) EF4Byte(*((u32 *)(_ptr))) + +#define WriteEF1Byte(_ptr, _val) (*((u8 *)(_ptr)))=EF1Byte(_val) +#define WriteEF2Byte(_ptr, _val) (*((u16 *)(_ptr)))=EF2Byte(_val) +#define WriteEF4Byte(_ptr, _val) (*((u32 *)(_ptr)))=EF4Byte(_val) +#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN +#define H2N1BYTE(_val) ((u8)(_val)) +#define H2N2BYTE(_val) (((((u16)(_val))&0x00ff)<<8)|\ + ((((u16)(_val))&0xff00)>>8)) +#define H2N4BYTE(_val) (((((u32)(_val))&0x000000ff)<<24)|\ + ((((u32)(_val))&0x0000ff00)<<8) |\ + ((((u32)(_val))&0x00ff0000)>>8) |\ + ((((u32)(_val))&0xff000000)>>24)) +#else +#define H2N1BYTE(_val) ((u8)(_val)) +#define H2N2BYTE(_val) ((u16)(_val)) +#define H2N4BYTE(_val) ((u32)(_val)) +#endif + +#if BYTE_ORDER == __MACHINE_LITTLE_ENDIAN +#define N2H1BYTE(_val) ((u8)(_val)) +#define N2H2BYTE(_val) (((((u16)(_val))&0x00ff)<<8)|\ + ((((u16)(_val))&0xff00)>>8)) +#define N2H4BYTE(_val) (((((u32)(_val))&0x000000ff)<<24)|\ + ((((u32)(_val))&0x0000ff00)<<8) |\ + ((((u32)(_val))&0x00ff0000)>>8) |\ + ((((u32)(_val))&0xff000000)>>24)) +#else +#define N2H1BYTE(_val) ((u8)(_val)) +#define N2H2BYTE(_val) ((u16)(_val)) +#define N2H4BYTE(_val) ((u32)(_val)) +#endif + +#define BIT_LEN_MASK_32(__BitLen) (0xFFFFFFFF >> (32 - (__BitLen))) +#define BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) (BIT_LEN_MASK_32(__BitLen) << (__BitOffset)) + +#define LE_P4BYTE_TO_HOST_4BYTE(__pStart) (EF4Byte(*((u32 *)(__pStart)))) + +#define LE_BITS_TO_4BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + ( LE_P4BYTE_TO_HOST_4BYTE(__pStart) >> (__BitOffset) ) \ + & \ + BIT_LEN_MASK_32(__BitLen) \ + ) + +#define LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + LE_P4BYTE_TO_HOST_4BYTE(__pStart) \ + & \ + ( ~BIT_OFFSET_LEN_MASK_32(__BitOffset, __BitLen) ) \ + ) + +#define SET_BITS_TO_LE_4BYTE(__pStart, __BitOffset, __BitLen, __Value) \ + *((u32 *)(__pStart)) = \ + EF4Byte( \ + LE_BITS_CLEARED_TO_4BYTE(__pStart, __BitOffset, __BitLen) \ + | \ + ( (((u32)__Value) & BIT_LEN_MASK_32(__BitLen)) << (__BitOffset) ) \ + ); + + +#define BIT_LEN_MASK_16(__BitLen) \ + (0xFFFF >> (16 - (__BitLen))) + +#define BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) \ + (BIT_LEN_MASK_16(__BitLen) << (__BitOffset)) + +#define LE_P2BYTE_TO_HOST_2BYTE(__pStart) \ + (EF2Byte(*((u16 *)(__pStart)))) + +#define LE_BITS_TO_2BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + ( LE_P2BYTE_TO_HOST_2BYTE(__pStart) >> (__BitOffset) ) \ + & \ + BIT_LEN_MASK_16(__BitLen) \ + ) + +#define LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + LE_P2BYTE_TO_HOST_2BYTE(__pStart) \ + & \ + ( ~BIT_OFFSET_LEN_MASK_16(__BitOffset, __BitLen) ) \ + ) + +#define SET_BITS_TO_LE_2BYTE(__pStart, __BitOffset, __BitLen, __Value) \ + *((u16 *)(__pStart)) = \ + EF2Byte( \ + LE_BITS_CLEARED_TO_2BYTE(__pStart, __BitOffset, __BitLen) \ + | \ + ( (((u16)__Value) & BIT_LEN_MASK_16(__BitLen)) << (__BitOffset) ) \ + ); + +#define BIT_LEN_MASK_8(__BitLen) \ + (0xFF >> (8 - (__BitLen))) + +#define BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) \ + (BIT_LEN_MASK_8(__BitLen) << (__BitOffset)) + +#define LE_P1BYTE_TO_HOST_1BYTE(__pStart) \ + (EF1Byte(*((u8 *)(__pStart)))) + +#define LE_BITS_TO_1BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + ( LE_P1BYTE_TO_HOST_1BYTE(__pStart) >> (__BitOffset) ) \ + & \ + BIT_LEN_MASK_8(__BitLen) \ + ) + +#define LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \ + ( \ + LE_P1BYTE_TO_HOST_1BYTE(__pStart) \ + & \ + ( ~BIT_OFFSET_LEN_MASK_8(__BitOffset, __BitLen) ) \ + ) + +#define SET_BITS_TO_LE_1BYTE(__pStart, __BitOffset, __BitLen, __Value) \ + *((u8 *)(__pStart)) = \ + EF1Byte( \ + LE_BITS_CLEARED_TO_1BYTE(__pStart, __BitOffset, __BitLen) \ + | \ + ( (((u8)__Value) & BIT_LEN_MASK_8(__BitLen)) << (__BitOffset) ) \ + ); + +#define N_BYTE_ALIGMENT(__Value, __Aligment) ((__Aligment == 1) ? (__Value) : (((__Value + __Aligment - 1) / __Aligment) * __Aligment)) +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib_module.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib_module.c @@ -0,0 +1,601 @@ +/******************************************************************************* + + Copyright(c) 2004 Intel Corporation. All rights reserved. + + Portions of this file are based on the WEP enablement code provided by the + Host AP project hostap-drivers v0.1.3 + Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + + Copyright (c) 2002-2003, Jouni Malinen + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + James P. Ketrenos + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rtllib.h" + + +#ifndef BUILT_IN_RTLLIB +MODULE_DESCRIPTION("802.11 data/management/control stack"); +MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation "); +MODULE_LICENSE("GPL"); +#endif + +#ifdef RTL8192CE +#define DRV_NAME "rtllib_92ce" +#elif defined RTL8192SE +#define DRV_NAME "rtllib_92se" +#elif defined RTL8192E +#define DRV_NAME "rtllib_92e" +#elif defined RTL8190P +#define DRV_NAME "rtllib_90p" +#elif defined RTL8192SU +#define DRV_NAME "rtllib_92su" +#elif defined RTL8192U +#define DRV_NAME "rtllib_92u" +#else +#define DRV_NAME "rtllib_9x" +#endif + +#ifdef CONFIG_CFG_80211 +#ifdef CONFIG_RTL_RFKILL +static inline void rtllib_rfkill_poll(struct wiphy *wiphy) +{ + struct rtllib_device *rtllib = NULL; + + rtllib = (struct rtllib_device *)wiphy_priv(wiphy); + + rtllib = (struct rtllib_device *)netdev_priv_rsl(rtllib->dev); + + if (rtllib->rtllib_rfkill_poll) + rtllib->rtllib_rfkill_poll(rtllib->dev); +} +#else +static inline void rtllib_rfkill_poll(struct wiphy *wiphy) {} +#endif +struct cfg80211_ops rtllib_config_ops = {.rfkill_poll = rtllib_rfkill_poll }; +void *rtllib_wiphy_privid = &rtllib_wiphy_privid; +#endif + +void _setup_timer( struct timer_list* ptimer, void* fun, unsigned long data ) +{ + ptimer->function = fun; + ptimer->data = data; + init_timer( ptimer ); +} + +#ifdef _RTL8192_EXT_PATCH_ +static inline int rtllib_mesh_networks_allocate(struct rtllib_device *ieee) +{ + if (ieee->mesh_networks) + return 0; + + ieee->mesh_networks = kmalloc( + MAX_NETWORK_COUNT * sizeof(struct rtllib_network), + GFP_KERNEL); + + if (!ieee->mesh_networks) { + printk(KERN_WARNING "%s: Out of memory allocating beacons\n", + ieee->dev->name); + return -ENOMEM; + } + + memset(ieee->mesh_networks, 0, + MAX_NETWORK_COUNT * sizeof(struct rtllib_network)); + + return 0; +} + +static inline void rtllib_mesh_networks_free(struct rtllib_device *ieee) +{ + if (!ieee->mesh_networks) + return; + kfree(ieee->mesh_networks); + ieee->mesh_networks = NULL; +} +#endif + +static inline int rtllib_networks_allocate(struct rtllib_device *ieee) +{ + if (ieee->networks) + return 0; + +#ifndef RTK_DMP_PLATFORM + ieee->networks = kmalloc( + MAX_NETWORK_COUNT * sizeof(struct rtllib_network), + GFP_KERNEL); +#else + ieee->networks = dvr_malloc(MAX_NETWORK_COUNT * sizeof(struct rtllib_network)); +#endif + if (!ieee->networks) { + printk(KERN_WARNING "%s: Out of memory allocating beacons\n", + ieee->dev->name); + return -ENOMEM; + } + + memset(ieee->networks, 0, + MAX_NETWORK_COUNT * sizeof(struct rtllib_network)); + + return 0; +} + +static inline void rtllib_networks_free(struct rtllib_device *ieee) +{ + if (!ieee->networks) + return; +#ifndef RTK_DMP_PLATFORM + kfree(ieee->networks); +#else + dvr_free(ieee->networks); +#endif + ieee->networks = NULL; +} + +static inline void rtllib_networks_initialize(struct rtllib_device *ieee) +{ + int i; + + INIT_LIST_HEAD(&ieee->network_free_list); + INIT_LIST_HEAD(&ieee->network_list); + for (i = 0; i < MAX_NETWORK_COUNT; i++) + list_add_tail(&ieee->networks[i].list, &ieee->network_free_list); +#ifdef _RTL8192_EXT_PATCH_ + INIT_LIST_HEAD(&ieee->mesh_network_free_list); + INIT_LIST_HEAD(&ieee->mesh_network_list); + for (i = 0; i < MAX_NETWORK_COUNT; i++) + list_add_tail(&ieee->mesh_networks[i].list, &ieee->mesh_network_free_list); +#endif +} + +#if defined CONFIG_CFG_80211 +static bool rtllib_wdev_alloc(struct rtllib_device *ieee, int sizeof_priv) +{ + int priv_size; + struct rtllib_device *rtllib = NULL; + + priv_size = ALIGN(sizeof(struct rtllib_device),NETDEV_ALIGN) + sizeof_priv; + + ieee->wdev.wiphy = wiphy_new(&rtllib_config_ops, priv_size); + if (!ieee->wdev.wiphy) { + RTLLIB_ERROR("Unable to allocate wiphy.\n"); + goto out_err_new; + } + + rtllib = (struct rtllib_device *)wiphy_priv(ieee->wdev.wiphy); + rtllib->dev = ieee->dev; + + ieee->dev->ieee80211_ptr = &ieee->wdev; + ieee->wdev.iftype = NL80211_IFTYPE_STATION; + + /* Fill-out wiphy structure bits we know... Not enough info + * here to call set_wiphy_dev or set MAC address or channel info + * -- have to do that in ->ndo_init... */ + ieee->wdev.wiphy->privid = rtllib_wiphy_privid; + + ieee->wdev.wiphy->max_scan_ssids = 1; + ieee->wdev.wiphy->max_scan_ie_len = 0; + ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + + return true; + +out_err_new: + wiphy_free(ieee->wdev.wiphy); + return false; +} +#endif + +struct net_device *alloc_rtllib(int sizeof_priv) +{ + struct rtllib_device *ieee = NULL; + struct net_device *dev; + int i,err; + + RTLLIB_DEBUG_INFO("Initializing...\n"); + + dev = alloc_etherdev(sizeof(struct rtllib_device) + sizeof_priv); + if (!dev) { + RTLLIB_ERROR("Unable to network device.\n"); + goto failed; + } + ieee = (struct rtllib_device *)netdev_priv_rsl(dev); + memset(ieee, 0, sizeof(struct rtllib_device)+sizeof_priv); + ieee->dev = dev; + +#ifdef CONFIG_CFG_80211 + if(!rtllib_wdev_alloc(ieee, sizeof_priv)) + goto failed; +#endif + err = rtllib_networks_allocate(ieee); + if (err) { + RTLLIB_ERROR("Unable to allocate beacon storage: %d\n", + err); + goto failed; + } +#ifdef _RTL8192_EXT_PATCH_ + err = rtllib_mesh_networks_allocate(ieee); + if (err) { + RTLLIB_ERROR("Unable to allocate mesh_beacon storage: %d\n", + err); + goto failed; + } +#endif + rtllib_networks_initialize(ieee); + + + /* Default fragmentation threshold is maximum payload size */ + ieee->fts = DEFAULT_FTS; + ieee->scan_age = DEFAULT_MAX_SCAN_AGE; + ieee->open_wep = 1; + + /* Default to enabling full open WEP with host based encrypt/decrypt */ + ieee->host_encrypt = 1; + ieee->host_decrypt = 1; + ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ + + INIT_LIST_HEAD(&ieee->crypt_deinit_list); + _setup_timer(&ieee->crypt_deinit_timer, + rtllib_crypt_deinit_handler, + (unsigned long) ieee); + ieee->rtllib_ap_sec_type = rtllib_ap_sec_type; + + spin_lock_init(&ieee->lock); + spin_lock_init(&ieee->wpax_suitlist_lock); + spin_lock_init(&ieee->bw_spinlock); + spin_lock_init(&ieee->reorder_spinlock); + atomic_set(&(ieee->atm_chnlop), 0); + atomic_set(&(ieee->atm_swbw), 0); + + ieee->bHalfNMode = false; + ieee->wpa_enabled = 0; + ieee->tkip_countermeasures = 0; + ieee->drop_unencrypted = 0; + ieee->privacy_invoked = 0; + ieee->ieee802_1x = 1; + ieee->raw_tx = 0; + ieee->hwsec_active = 0; + +#ifdef _RTL8192_EXT_PATCH_ + for (i=0; icryptlist[i] = (struct rtllib_crypt_data_list*) kmalloc(sizeof(struct rtllib_crypt_data_list), GFP_KERNEL); + if (NULL == ieee->cryptlist[i]) + { + printk("error kmalloc cryptlist\n"); + goto failed; + } + memset(ieee->cryptlist[i], 0, sizeof(struct rtllib_crypt_data_list)); + } + memset(ieee->swmeshcamtable,0,sizeof(SW_CAM_TABLE)*32); +#endif + memset(ieee->swcamtable,0,sizeof(SW_CAM_TABLE)*32); + rtllib_softmac_init(ieee); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) + ieee->pHTInfo = (RT_HIGH_THROUGHPUT*)kzalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL); +#else + ieee->pHTInfo = (RT_HIGH_THROUGHPUT*)kmalloc(sizeof(RT_HIGH_THROUGHPUT), GFP_KERNEL); + memset(ieee->pHTInfo,0,sizeof(RT_HIGH_THROUGHPUT)); +#endif + if (ieee->pHTInfo == NULL) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc memory for HTInfo\n"); + return NULL; + } + HTUpdateDefaultSetting(ieee); + HTInitializeHTInfo(ieee); + TSInitialize(ieee); +#if 0 + INIT_WORK_RSL(&ieee->ht_onAssRsp, (void(*)(void*)) HTOnAssocRsp_wq, ieee); +#endif + for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) + INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]); + +#ifdef _RTL8192_EXT_PATCH_ + for (i = 0; i < IEEE_MESH_MAC_HASH_SIZE; i++) + INIT_LIST_HEAD(&ieee->mesh_mac_hash[i]); +#endif + + for (i = 0; i < 17; i++) { + ieee->last_rxseq_num[i] = -1; + ieee->last_rxfrag_num[i] = -1; + ieee->last_packet_time[i] = 0; + } + + rtllib_tkip_null(); + rtllib_wep_null(); + rtllib_ccmp_null(); + + return dev; + + failed: +#ifdef _RTL8192_EXT_PATCH_ + for (i=0; icryptlist[i]==NULL){ + continue; + } + kfree(ieee->cryptlist[i]); + ieee->cryptlist[i] = NULL; + + } +#endif + + if (dev) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) + free_netdev(dev); +#else + kfree(dev); +#endif + return NULL; +} + + +void free_rtllib(struct net_device *dev) +{ + struct rtllib_device *ieee = (struct rtllib_device *)netdev_priv_rsl(dev); + int i; +#ifdef _RTL8192_EXT_PATCH_ + int j; + struct list_head *p, *q; + struct rtllib_crypt_data *crypt = NULL; +#endif +#if 1 + if (ieee->pHTInfo != NULL) + { + kfree(ieee->pHTInfo); + ieee->pHTInfo = NULL; + } +#endif + rtllib_softmac_free(ieee); + del_timer_sync(&ieee->crypt_deinit_timer); + rtllib_crypt_deinit_entries(ieee, 1); + +#ifdef _RTL8192_EXT_PATCH_ + for (j=0;jcryptlist[j] == NULL) + continue; + for (i = 0; i < WEP_KEYS; i++) { + crypt = ieee->cryptlist[j]->crypt[i]; + + if (crypt) + { + if (crypt->ops) { + crypt->ops->deinit(crypt->priv); + printk("===>%s():j is %d,i is %d\n",__FUNCTION__,j,i); +#ifndef BUILT_IN_RTLLIB +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + module_put(crypt->ops->owner); +#else + __MOD_DEC_USE_COUNT(crypt->ops->owner); +#endif +#endif + } + kfree(crypt); + ieee->cryptlist[j]->crypt[i] = NULL; + } + } + kfree(ieee->cryptlist[j]); + } + for (i = 0; i < WEP_KEYS; i++) { + crypt = ieee->sta_crypt[i]; + if (crypt) + { + if (crypt->ops) { + crypt->ops->deinit(crypt->priv); +#ifndef BUILT_IN_RTLLIB +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + module_put(crypt->ops->owner); +#else + __MOD_DEC_USE_COUNT(crypt->ops->owner); +#endif +#endif + } + kfree(crypt); + } + ieee->sta_crypt[i] = NULL; + } +#else + for (i = 0; i < WEP_KEYS; i++) { + struct rtllib_crypt_data *crypt = ieee->crypt[i]; + if (crypt) { + if (crypt->ops) { + crypt->ops->deinit(crypt->priv); +#ifndef BUILT_IN_RTLLIB +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + module_put(crypt->ops->owner); +#else + __MOD_DEC_USE_COUNT(crypt->ops->owner); +#endif +#endif + } + kfree(crypt); + ieee->crypt[i] = NULL; + } + } +#endif + + rtllib_networks_free(ieee); +#ifdef _RTL8192_EXT_PATCH_ + rtllib_mesh_networks_free(ieee); +#endif +#if 0 + for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) { + list_for_each_safe(p, q, &ieee->ibss_mac_hash[i]) { + kfree(list_entry(p, struct ieee_ibss_seq, list)); + list_del(p); + } + } + +#endif +#ifdef _RTL8192_EXT_PATCH_ + for (i = 0; i < IEEE_MESH_MAC_HASH_SIZE; i++) { + list_for_each_safe(p, q, &ieee->mesh_mac_hash[i]) { + kfree(list_entry(p, struct ieee_mesh_seq, list)); + list_del(p); + } + } +#endif +#if defined (RTL8192S_WAPI_SUPPORT) + if (ieee->WapiSupport) + { + WapiFreeAllStaInfo(ieee); + } +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) +#ifdef CONFIG_CFG_80211 + wiphy_unregister(ieee->wdev.wiphy); + wiphy_free(ieee->wdev.wiphy); +#endif + free_netdev(dev); +#else + kfree(dev); +#endif +} + +#ifdef CONFIG_RTLLIB_DEBUG + +u32 rtllib_debug_level = 0; +static int debug = \ + RTLLIB_DL_ERR + ; +struct proc_dir_entry *rtllib_proc = NULL; + +static int show_debug_level(char *page, char **start, off_t offset, + int count, int *eof, void *data) +{ + return snprintf(page, count, "0x%08X\n", rtllib_debug_level); +} + +static int store_debug_level(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char buf[] = "0x00000000"; + unsigned long len = min((unsigned long)sizeof(buf) - 1, count); + char *p = (char *)buf; + unsigned long val; + + if (copy_from_user(buf, buffer, len)) + return count; + buf[len] = 0; + if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { + p++; + if (p[0] == 'x' || p[0] == 'X') + p++; + val = simple_strtoul(p, &p, 16); + } else + val = simple_strtoul(p, &p, 10); + if (p == buf) + printk(KERN_INFO DRV_NAME + ": %s is not in hex or decimal form.\n", buf); + else + rtllib_debug_level = val; + + return strnlen(buf, count); +} + +int __init rtllib_init(void) +{ +#ifdef CONFIG_RTLLIB_DEBUG + struct proc_dir_entry *e; + + rtllib_debug_level = debug; +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + rtllib_proc = create_proc_entry(DRV_NAME, S_IFDIR, proc_net); +#else + rtllib_proc = create_proc_entry(DRV_NAME, S_IFDIR, init_net.proc_net); +#endif + if (rtllib_proc == NULL) { + RTLLIB_ERROR("Unable to create " DRV_NAME + " proc directory\n"); + return -EIO; + } + e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR, + rtllib_proc); + if (!e) { +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + remove_proc_entry(DRV_NAME, proc_net); +#else + remove_proc_entry(DRV_NAME, init_net.proc_net); +#endif + rtllib_proc = NULL; + return -EIO; + } + e->read_proc = show_debug_level; + e->write_proc = store_debug_level; + e->data = NULL; +#endif + + return 0; +} + +void __exit rtllib_exit(void) +{ +#ifdef CONFIG_RTLLIB_DEBUG + if (rtllib_proc) { + remove_proc_entry("debug_level", rtllib_proc); +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + remove_proc_entry(DRV_NAME, proc_net); +#else + remove_proc_entry(DRV_NAME, init_net.proc_net); +#endif + rtllib_proc = NULL; + } +#endif +} + +#ifndef BUILT_IN_RTLLIB +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) +#include +module_param(debug, int, 0444); +MODULE_PARM_DESC(debug, "debug output mask"); + + +module_exit(rtllib_exit); +module_init(rtllib_init); +#endif + +EXPORT_SYMBOL_RSL(alloc_rtllib); +EXPORT_SYMBOL_RSL(free_rtllib); +EXPORT_SYMBOL_RSL(rtllib_debug_level); +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib_rx.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib_rx.c @@ -0,0 +1,5322 @@ +/* + * Original code based Host AP (software wireless LAN access point) driver + * for Intersil Prism2/2.5/3 - hostap.o module, common routines + * + * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + * + * Copyright (c) 2002-2003, Jouni Malinen + * Copyright (c) 2004, Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See README and COPYING for + * more details. + ****************************************************************************** + + Few modifications for Realtek's Wi-Fi drivers by + Andrea Merello + + A special thanks goes to Realtek for their support ! + +******************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rtllib.h" +#ifdef ENABLE_DOT11D +#include "dot11d.h" +#endif + +#if defined(RTLLIB_RADIOTAP) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)) +#include +#endif + +#if defined CONFIG_CFG_80211 +#include + +struct ieee80211_channel *rtllib_get_channel(struct wiphy *wiphy, + int freq) +{ + enum ieee80211_band band; + struct ieee80211_supported_band *sband; + int i; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + sband = wiphy->bands[band]; + + if (!sband) + continue; + + for (i = 0; i < sband->n_channels; i++) { + if (sband->channels[i].center_freq == freq) + return &sband->channels[i]; + } + } + + return NULL; +} + +int rtllib_channel_to_frequency(int chan) +{ + if (chan < 14) + return 2407 + chan * 5; + + if (chan == 14) + return 2484; + + /* FIXME: 802.11j 17.3.8.3.2 */ + return (chan + 1000) * 5; +} + +u32 rtllib_parse_elems_crc(u8 *start, size_t len, + struct ieee802_11_elems *elems, + u64 filter, u32 crc) +{ + size_t left = len; + u8 *pos = start; + bool calc_crc = filter != 0; + + memset(elems, 0, sizeof(*elems)); + elems->ie_start = start; + elems->total_len = len; + + while (left >= 2) { + u8 id, elen; + + id = *pos++; + elen = *pos++; + left -= 2; + + if (elen > left) + break; + + if (calc_crc && id < 64 && (filter & BIT(id))) + crc = crc32_be(crc, pos - 2, elen + 2); + + switch (id) { + case WLAN_EID_SSID: + elems->ssid = pos; + elems->ssid_len = elen; + break; + case WLAN_EID_SUPP_RATES: + elems->supp_rates = pos; + elems->supp_rates_len = elen; + break; + case WLAN_EID_FH_PARAMS: + elems->fh_params = pos; + elems->fh_params_len = elen; + break; + case WLAN_EID_DS_PARAMS: + elems->ds_params = pos; + elems->ds_params_len = elen; + break; + case WLAN_EID_CF_PARAMS: + elems->cf_params = pos; + elems->cf_params_len = elen; + break; + case WLAN_EID_TIM: + if (elen >= sizeof(struct ieee80211_tim_ie)) { + elems->tim = (void *)pos; + elems->tim_len = elen; + } + break; + case WLAN_EID_IBSS_PARAMS: + elems->ibss_params = pos; + elems->ibss_params_len = elen; + break; + case WLAN_EID_CHALLENGE: + elems->challenge = pos; + elems->challenge_len = elen; + break; + case WLAN_EID_VENDOR_SPECIFIC: + if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && + pos[2] == 0xf2) { + /* Microsoft OUI (00:50:F2) */ + + if (calc_crc) + crc = crc32_be(crc, pos - 2, elen + 2); + + if (pos[3] == 1) { + /* OUI Type 1 - WPA IE */ + elems->wpa = pos; + elems->wpa_len = elen; + } else if (elen >= 5 && pos[3] == 2) { + /* OUI Type 2 - WMM IE */ + if (pos[4] == 0) { + elems->wmm_info = pos; + elems->wmm_info_len = elen; + } else if (pos[4] == 1) { + elems->wmm_param = pos; + elems->wmm_param_len = elen; + } + } + } + break; + case WLAN_EID_RSN: + elems->rsn = pos; + elems->rsn_len = elen; + break; + case WLAN_EID_ERP_INFO: + elems->erp_info = pos; + elems->erp_info_len = elen; + break; + case WLAN_EID_EXT_SUPP_RATES: + elems->ext_supp_rates = pos; + elems->ext_supp_rates_len = elen; + break; + case WLAN_EID_HT_CAPABILITY: + if (elen >= sizeof(struct ieee80211_ht_cap)) + elems->ht_cap_elem = (void *)pos; + break; + case WLAN_EID_HT_INFORMATION: + if (elen >= sizeof(struct ieee80211_ht_info)) + elems->ht_info_elem = (void *)pos; + break; + case WLAN_EID_MESH_ID: + elems->mesh_id = pos; + elems->mesh_id_len = elen; + break; + case WLAN_EID_MESH_CONFIG: + elems->mesh_config = pos; + elems->mesh_config_len = elen; + break; + case WLAN_EID_PEER_LINK: + elems->peer_link = pos; + elems->peer_link_len = elen; + break; + case WLAN_EID_PREQ: + elems->preq = pos; + elems->preq_len = elen; + break; + case WLAN_EID_PREP: + elems->prep = pos; + elems->prep_len = elen; + break; + case WLAN_EID_PERR: + elems->perr = pos; + elems->perr_len = elen; + break; + case WLAN_EID_CHANNEL_SWITCH: + elems->ch_switch_elem = pos; + elems->ch_switch_elem_len = elen; + break; + case WLAN_EID_QUIET: + if (!elems->quiet_elem) { + elems->quiet_elem = pos; + elems->quiet_elem_len = elen; + } + elems->num_of_quiet_elem++; + break; + case WLAN_EID_COUNTRY: + elems->country_elem = pos; + elems->country_elem_len = elen; + break; + case WLAN_EID_PWR_CONSTRAINT: + elems->pwr_constr_elem = pos; + elems->pwr_constr_elem_len = elen; + break; + case WLAN_EID_TIMEOUT_INTERVAL: + elems->timeout_int = pos; + elems->timeout_int_len = elen; + break; + default: + break; + } + + left -= elen; + pos += elen; + } + + return crc; +} + +void rtllib_parse_elems(u8 *start, size_t len, + struct ieee802_11_elems *elems) +{ + rtllib_parse_elems_crc(start, len, elems, 0, 0); +} + +void ieee80211_scan_rx(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_status) +{ + struct rtllib_hdr_4addr *header = (struct rtllib_hdr_4addr *)skb->data ; + struct ieee80211_mgmt *mgmt; + struct ieee80211_bss *bss; + u8 *elements; + struct ieee80211_channel *channel; + size_t baselen; + int freq; + __le16 fc; + bool presp, beacon = false; + struct ieee802_11_elems elems; + s32 signal = 0; + + if (skb->len < 2) + return; + + mgmt = (struct ieee80211_mgmt *) skb->data; + fc = mgmt->frame_control; + + if (skb->len < 24) + return; + + presp = (WLAN_FC_GET_STYPE(header->frame_ctl) == RTLLIB_STYPE_PROBE_RESP); + if (presp) { + /* ignore ProbeResp to foreign address */ + if (memcmp(mgmt->da, ieee->dev->dev_addr, ETH_ALEN)) + return ;; + + presp = true; + elements = mgmt->u.probe_resp.variable; + baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); + } else { + beacon = (WLAN_FC_GET_STYPE(header->frame_ctl) == RTLLIB_STYPE_BEACON); + baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); + elements = mgmt->u.beacon.variable; + } + + if (!presp && !beacon) + return; + + if (baselen > skb->len) + return; + + rtllib_parse_elems(elements, skb->len - baselen, &elems); + + if (elems.ds_params && elems.ds_params_len == 1) + freq = rtllib_channel_to_frequency(elems.ds_params[0]); + else + return; + + channel = rtllib_get_channel(ieee->wdev.wiphy, freq); + + if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) + return; + + signal = rx_status->signal * 100; + + bss = (void *)cfg80211_inform_bss_frame(ieee->wdev.wiphy, channel, + mgmt, skb->len, signal, GFP_ATOMIC); + + return; +} +#endif + + +#if defined(RTLLIB_RADIOTAP) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)) +static int rtllib_rx_radiotap_len(struct rtllib_device *ieee, struct rtllib_rx_stats *rx_status) +{ + int len; + + /* always present fields */ + len = sizeof(struct ieee80211_radiotap_header) + + 8 + /* TSFT */ + 1 + /* FLAGS */ + 1 + /* RATE */ + 2 + /* CHANNEL IN MHZ */ + 2 + /* CHANNEL BITFIELD */ + 1 + /* HW SIGNAL DBM */ + 1 + /* HW NOISE DBM */ + 1; /* ANTENNA NUMBER */ + + + if (len & 1) /* padding for RX_FLAGS if necessary */ + len++; + + /* make sure radiotap starts at a naturally aligned address */ + if (len % 8) + len = roundup(len, 8); + + return len; +} + +static void rtllib_add_rx_radiotap_header(struct rtllib_device *ieee, + struct sk_buff *skb, int rtap_len, struct rtllib_rx_stats *rx_status) +{ + struct ieee80211_radiotap_header *rthdr; + unsigned char *pos; + printk("add header!\n"); + rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); + memset(rthdr, 0, rtap_len); + + rthdr->it_version = PKTHDR_RADIOTAP_VERSION; + rthdr->it_pad = 0; + rthdr->it_len = cpu_to_le16(rtap_len); + /* radiotap header, set always present flags */ + rthdr->it_present = cpu_to_le32( + (1 << IEEE80211_RADIOTAP_TSFT) | + (1 << IEEE80211_RADIOTAP_FLAGS) | + (1 << IEEE80211_RADIOTAP_RATE) | + (1 << IEEE80211_RADIOTAP_CHANNEL) | + (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | + (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | + (1 << IEEE80211_RADIOTAP_ANTENNA)); + + pos = (unsigned char *)(rthdr+1); + /* the order of the following fields is important */ + /* IEEE80211_RADIOTAP_TSFT */ + *(__le64 *)pos = cpu_to_le64(rx_status->TimeStampLow); + pos += 8; + + /* IEEE80211_RADIOTAP_FLAGS */ + if (rx_status->bCRC) + *pos |= IEEE80211_RADIOTAP_F_BADFCS; + if (rx_status->bShortPreamble) + *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; + pos++; + + /* IEEE80211_RADIOTAP_RATE */ + *pos = rx_status->rate / 5; + pos++; + + /* IEEE80211_RADIOTAP_CHANNEL */ + *(__le16 *)pos = cpu_to_le16(rx_status->received_channel); + pos += 2; +#if 0 + if (status->band == IEEE80211_BAND_5GHZ) + *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | + IEEE80211_CHAN_5GHZ); + else if (rate->flags & IEEE80211_RATE_ERP_G) + *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | + IEEE80211_CHAN_2GHZ); + else + *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_CCK | + IEEE80211_CHAN_2GHZ); +#endif + pos += 2; + + + /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ + *pos = rx_status->RxPower; + pos++; + + /* IEEE80211_RADIOTAP_DBM_ANTNOISE */ + *pos = rx_status->noise; + pos++; + + /* IEEE80211_RADIOTAP_ANTENNA */ + *pos = rx_status->Antenna; + pos++; + + /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ + + /* IEEE80211_RADIOTAP_RX_FLAGS */ + /* ensure 2 byte alignment for the 2 byte field as required */ +#if 0 + if ((pos - (unsigned char *)rthdr) & 1) + pos++; + if (status->flag & RX_FLAG_FAILED_PLCP_CRC) + *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADPLCP); + pos += 2; +#endif +} +#endif + +static inline void rtllib_monitor_rx(struct rtllib_device *ieee, + struct sk_buff *skb,struct rtllib_rx_stats *rx_status, + size_t hdr_length) +{ + +#if defined(RTLLIB_RADIOTAP) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)) + int needed_headroom = 0; + struct sk_buff *radiotap_skb; + + needed_headroom = rtllib_rx_radiotap_len(ieee, rx_status); + printk("needed_headroom = %d\n", needed_headroom); + radiotap_skb = skb_copy_expand(skb, needed_headroom, 0, GFP_ATOMIC); + dev_kfree_skb(skb); + skb = NULL; + + if (!radiotap_skb) { + return; + } + + rtllib_add_rx_radiotap_header(ieee, radiotap_skb, needed_headroom, rx_status); + radiotap_skb->dev = ieee->dev; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + skb_reset_mac_header(radiotap_skb); +#else + radiotap_skb->mac.raw = radiotap_skb->data; +#endif + radiotap_skb->ip_summed = CHECKSUM_UNNECESSARY; + radiotap_skb->pkt_type = PACKET_OTHERHOST; + radiotap_skb->protocol = htons(ETH_P_802_2); + memset(radiotap_skb->cb, 0, sizeof(radiotap_skb->cb)); + netif_rx(radiotap_skb); +#else + skb->dev = ieee->dev; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) + skb_reset_mac_header(skb); +#else + skb->mac.raw = skb->data; +#endif + skb_pull(skb, hdr_length); + skb->pkt_type = PACKET_OTHERHOST; + skb->protocol = __constant_htons(ETH_P_80211_RAW); + memset(skb->cb, 0, sizeof(skb->cb)); + netif_rx(skb); +#endif +} + +/* Called only as a tasklet (software IRQ) */ +static struct rtllib_frag_entry * +rtllib_frag_cache_find(struct rtllib_device *ieee, unsigned int seq, + unsigned int frag, u8 tid,u8 *src, u8 *dst) +{ + struct rtllib_frag_entry *entry; + int i; + + for (i = 0; i < RTLLIB_FRAG_CACHE_LEN; i++) { + entry = &ieee->frag_cache[tid][i]; + if (entry->skb != NULL && + time_after(jiffies, entry->first_frag_time + 2 * HZ)) { + RTLLIB_DEBUG_FRAG( + "expiring fragment cache entry " + "seq=%u last_frag=%u\n", + entry->seq, entry->last_frag); + dev_kfree_skb_any(entry->skb); + entry->skb = NULL; + } + + if (entry->skb != NULL && entry->seq == seq && + (entry->last_frag + 1 == frag || frag == -1) && + memcmp(entry->src_addr, src, ETH_ALEN) == 0 && + memcmp(entry->dst_addr, dst, ETH_ALEN) == 0) + return entry; + } + + return NULL; +} + +/* Called only as a tasklet (software IRQ) */ +static struct sk_buff * +rtllib_frag_cache_get(struct rtllib_device *ieee, + struct rtllib_hdr_4addr *hdr) +{ + struct sk_buff *skb = NULL; + u16 fc = le16_to_cpu(hdr->frame_ctl); + u16 sc = le16_to_cpu(hdr->seq_ctl); + unsigned int frag = WLAN_GET_SEQ_FRAG(sc); + unsigned int seq = WLAN_GET_SEQ_SEQ(sc); + struct rtllib_frag_entry *entry; + struct rtllib_hdr_3addrqos *hdr_3addrqos; + struct rtllib_hdr_4addrqos *hdr_4addrqos; + u8 tid; + + if (((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS)&&RTLLIB_QOS_HAS_SEQ(fc)) { + hdr_4addrqos = (struct rtllib_hdr_4addrqos *)hdr; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else if (RTLLIB_QOS_HAS_SEQ(fc)) { + hdr_3addrqos = (struct rtllib_hdr_3addrqos *)hdr; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else { + tid = 0; + } + + if (frag == 0) { + /* Reserve enough space to fit maximum frame length */ + skb = dev_alloc_skb(ieee->dev->mtu + + sizeof(struct rtllib_hdr_4addr) + + 8 /* LLC */ + + 2 /* alignment */ + + 8 /* WEP */ + + ETH_ALEN /* WDS */ + + (RTLLIB_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */); + if (skb == NULL) + return NULL; + + entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]]; + ieee->frag_next_idx[tid]++; + if (ieee->frag_next_idx[tid] >= RTLLIB_FRAG_CACHE_LEN) + ieee->frag_next_idx[tid] = 0; + + if (entry->skb != NULL) + dev_kfree_skb_any(entry->skb); + + entry->first_frag_time = jiffies; + entry->seq = seq; + entry->last_frag = frag; + entry->skb = skb; + memcpy(entry->src_addr, hdr->addr2, ETH_ALEN); + memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN); + } else { + /* received a fragment of a frame for which the head fragment + * should have already been received */ + entry = rtllib_frag_cache_find(ieee, seq, frag, tid,hdr->addr2, + hdr->addr1); + if (entry != NULL) { + entry->last_frag = frag; + skb = entry->skb; + } + } + + return skb; +} + + +/* Called only as a tasklet (software IRQ) */ +static int rtllib_frag_cache_invalidate(struct rtllib_device *ieee, + struct rtllib_hdr_4addr *hdr) +{ + u16 fc = le16_to_cpu(hdr->frame_ctl); + u16 sc = le16_to_cpu(hdr->seq_ctl); + unsigned int seq = WLAN_GET_SEQ_SEQ(sc); + struct rtllib_frag_entry *entry; + struct rtllib_hdr_3addrqos *hdr_3addrqos; + struct rtllib_hdr_4addrqos *hdr_4addrqos; + u8 tid; + + if(((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS)&&RTLLIB_QOS_HAS_SEQ(fc)) { + hdr_4addrqos = (struct rtllib_hdr_4addrqos *)hdr; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else if (RTLLIB_QOS_HAS_SEQ(fc)) { + hdr_3addrqos = (struct rtllib_hdr_3addrqos *)hdr; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else { + tid = 0; + } + + entry = rtllib_frag_cache_find(ieee, seq, -1, tid,hdr->addr2, + hdr->addr1); + + if (entry == NULL) { + RTLLIB_DEBUG_FRAG( + "could not invalidate fragment cache " + "entry (seq=%u)\n", seq); + return -1; + } + + entry->skb = NULL; + return 0; +} + + + +/* rtllib_rx_frame_mgtmt + * + * Responsible for handling management control frames + * + * Called by rtllib_rx */ +static inline int +rtllib_rx_frame_mgmt(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats, u16 type, + u16 stype) +{ + /* On the struct stats definition there is written that + * this is not mandatory.... but seems that the probe + * response parser uses it + */ + struct rtllib_hdr_3addr * hdr = (struct rtllib_hdr_3addr *)skb->data; + + rx_stats->len = skb->len; + rtllib_rx_mgt(ieee,skb,rx_stats); +#ifdef _RTL8192_EXT_PATCH_ + if(ieee->iw_mode == IW_MODE_MESH){ + if ((stype != RTLLIB_STYPE_MESH_ACT) && (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN))) + { + dev_kfree_skb_any(skb); + return 0; + } + } + else +#endif + { + if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN))) + { + dev_kfree_skb_any(skb); + return 0; + } + } + rtllib_rx_frame_softmac(ieee, skb, rx_stats, type, stype); + + dev_kfree_skb_any(skb); + + return 0; + +#ifdef NOT_YET + if (ieee->iw_mode == IW_MODE_MASTER) { + printk(KERN_DEBUG "%s: Master mode not yet suppported.\n", + ieee->dev->name); + return 0; +/* + hostap_update_sta_ps(ieee, (struct hostap_rtllib_hdr_4addr *) + skb->data);*/ + } + + if (ieee->hostapd && type == RTLLIB_TYPE_MGMT) { + if (stype == WLAN_FC_STYPE_BEACON && + ieee->iw_mode == IW_MODE_MASTER) { + struct sk_buff *skb2; + /* Process beacon frames also in kernel driver to + * update STA(AP) table statistics */ + skb2 = skb_clone(skb, GFP_ATOMIC); + if (skb2) + hostap_rx(skb2->dev, skb2, rx_stats); + } + + /* send management frames to the user space daemon for + * processing */ + ieee->apdevstats.rx_packets++; + ieee->apdevstats.rx_bytes += skb->len; + prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT); + return 0; + } + + if (ieee->iw_mode == IW_MODE_MASTER) { + if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) { + printk(KERN_DEBUG "%s: unknown management frame " + "(type=0x%02x, stype=0x%02x) dropped\n", + skb->dev->name, type, stype); + return -1; + } + + hostap_rx(skb->dev, skb, rx_stats); + return 0; + } + + printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame " + "received in non-Host AP mode\n", skb->dev->name); + return -1; +#endif +} + +#ifndef CONFIG_CFG_80211 +/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ +/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ +static unsigned char rfc1042_header[] = +{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; +/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ +static unsigned char bridge_tunnel_header[] = +{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; +/* No encapsulation header if EtherType < 0x600 (=length) */ +#endif + +/* Called by rtllib_rx_frame_decrypt */ +static int rtllib_is_eapol_frame(struct rtllib_device *ieee, + struct sk_buff *skb, size_t hdrlen) +{ + struct net_device *dev = ieee->dev; + u16 fc, ethertype; + struct rtllib_hdr_4addr *hdr; + u8 *pos; + + if (skb->len < 24) + return 0; + + hdr = (struct rtllib_hdr_4addr *) skb->data; + fc = le16_to_cpu(hdr->frame_ctl); + + /* check that the frame is unicast frame to us */ + if ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) == + RTLLIB_FCTL_TODS && + memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 && + memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) { + /* ToDS frame with own addr BSSID and DA */ + } else if ((fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) == + RTLLIB_FCTL_FROMDS && + memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) { + /* FromDS frame with own addr as DA */ + } else + return 0; + + if (skb->len < 24 + 8) + return 0; + + /* check for port access entity Ethernet type */ + pos = skb->data + hdrlen; + ethertype = (pos[6] << 8) | pos[7]; + if (ethertype == ETH_P_PAE) + return 1; + + return 0; +} + +/* Called only as a tasklet (software IRQ), by rtllib_rx */ +static inline int +rtllib_rx_frame_decrypt(struct rtllib_device* ieee, struct sk_buff *skb, + struct rtllib_crypt_data *crypt) +{ + struct rtllib_hdr_4addr *hdr; + int res, hdrlen; + + if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) + return 0; +#if 1 + if (ieee->hwsec_active) + { + cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE); + tcb_desc->bHwSec = 1; + + if(ieee->need_sw_enc) + tcb_desc->bHwSec = 0; + } +#endif + hdr = (struct rtllib_hdr_4addr *) skb->data; + hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); + +#ifdef CONFIG_RTLLIB_CRYPT_TKIP + if (ieee->tkip_countermeasures && + strcmp(crypt->ops->name, "TKIP") == 0) { + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " + "received packet from " MAC_FMT "\n", + ieee->dev->name, MAC_ARG(hdr->addr2)); + } + return -1; + } +#endif + + atomic_inc(&crypt->refcnt); + res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); + atomic_dec(&crypt->refcnt); + if (res < 0) { + RTLLIB_DEBUG_DROP( + "decryption failed (SA=" MAC_FMT + ") res=%d\n", MAC_ARG(hdr->addr2), res); + if (res == -2) + RTLLIB_DEBUG_DROP("Decryption failed ICV " + "mismatch (key %d)\n", + skb->data[hdrlen + 3] >> 6); + ieee->ieee_stats.rx_discards_undecryptable++; + return -1; + } + + return res; +} + + +/* Called only as a tasklet (software IRQ), by rtllib_rx */ +static inline int +rtllib_rx_frame_decrypt_msdu(struct rtllib_device* ieee, struct sk_buff *skb, + int keyidx, struct rtllib_crypt_data *crypt) +{ + struct rtllib_hdr_4addr *hdr; + int res, hdrlen; + + if (crypt == NULL || crypt->ops->decrypt_msdu == NULL) + return 0; + if (ieee->hwsec_active) + { + cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE); + tcb_desc->bHwSec = 1; + + if(ieee->need_sw_enc) + tcb_desc->bHwSec = 0; + } + + hdr = (struct rtllib_hdr_4addr *) skb->data; + hdrlen = rtllib_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); + + atomic_inc(&crypt->refcnt); + res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv,ieee); + atomic_dec(&crypt->refcnt); + if (res < 0) { + printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed" + " (SA=" MAC_FMT " keyidx=%d)\n", + ieee->dev->name, MAC_ARG(hdr->addr2), keyidx); + return -1; + } + + return 0; +} + +#ifdef _RTL8192_EXT_PATCH_ +static inline int rtllib_has_retry(u16 fc) +{ + return ((fc&RTLLIB_FCTL_RETRY)!=0); +} +#endif + +/* this function is stolen from ipw2200 driver*/ +#define IEEE_PACKET_RETRY_TIME (5*HZ) +static int is_duplicate_packet(struct rtllib_device *ieee, + struct rtllib_hdr_4addr *header) +{ + u16 fc = le16_to_cpu(header->frame_ctl); + u16 sc = le16_to_cpu(header->seq_ctl); + u16 seq = WLAN_GET_SEQ_SEQ(sc); + u16 frag = WLAN_GET_SEQ_FRAG(sc); + u16 *last_seq, *last_frag; + unsigned long *last_time; + struct rtllib_hdr_3addrqos *hdr_3addrqos; + struct rtllib_hdr_4addrqos *hdr_4addrqos; + u8 tid; + + if(((fc & RTLLIB_FCTL_DSTODS) == RTLLIB_FCTL_DSTODS)&&RTLLIB_QOS_HAS_SEQ(fc)) { + hdr_4addrqos = (struct rtllib_hdr_4addrqos *)header; + tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & RTLLIB_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else if(RTLLIB_QOS_HAS_SEQ(fc)) { + hdr_3addrqos = (struct rtllib_hdr_3addrqos*)header; + tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & RTLLIB_QCTL_TID; + tid = UP2AC(tid); + tid ++; + } else { + tid = 0; + } + + switch (ieee->iw_mode) { + case IW_MODE_ADHOC: + { + struct list_head *p; + struct ieee_ibss_seq *entry = NULL; + u8 *mac = header->addr2; + int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE; + list_for_each(p, &ieee->ibss_mac_hash[index]) { + entry = list_entry(p, struct ieee_ibss_seq, list); + if (!memcmp(entry->mac, mac, ETH_ALEN)) + break; + } + if (p == &ieee->ibss_mac_hash[index]) { + entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC); + if (!entry) { + printk(KERN_WARNING "Cannot malloc new mac entry\n"); + return 0; + } + memcpy(entry->mac, mac, ETH_ALEN); + entry->seq_num[tid] = seq; + entry->frag_num[tid] = frag; + entry->packet_time[tid] = jiffies; + list_add(&entry->list, &ieee->ibss_mac_hash[index]); + return 0; + } + last_seq = &entry->seq_num[tid]; + last_frag = &entry->frag_num[tid]; + last_time = &entry->packet_time[tid]; + break; + } + + case IW_MODE_INFRA: + last_seq = &ieee->last_rxseq_num[tid]; + last_frag = &ieee->last_rxfrag_num[tid]; + last_time = &ieee->last_packet_time[tid]; + + break; + +#ifdef _RTL8192_EXT_PATCH_ + case IW_MODE_MESH: + /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ + if(!is_multicast_ether_addr(header->addr1)){ + struct list_head *p; + struct ieee_mesh_seq *entry = NULL; + u8 *mac = header->addr2; + int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE; + list_for_each(p, &ieee->mesh_mac_hash[index]) { + entry = list_entry(p, struct ieee_mesh_seq, list); + if (!memcmp(entry->mac, mac, ETH_ALEN)) + break; + } + + if (p == &ieee->mesh_mac_hash[index]) { + entry = kmalloc(sizeof(struct ieee_mesh_seq), GFP_ATOMIC); + if (!entry) { + printk(KERN_WARNING "Cannot malloc new mac entry\n"); + return 0; + } + memcpy(entry->mac, mac, ETH_ALEN); + entry->seq_num[tid] = header->seq_ctl; + entry->packet_time[tid] = jiffies; + list_add(&entry->list, &ieee->mesh_mac_hash[index]); + return 0; + } + last_seq = &entry->seq_num[tid]; + last_time = &entry->packet_time[tid]; + + if (unlikely(rtllib_has_retry(fc) && + *last_seq == header->seq_ctl)) { + goto drop; + } else { + *last_seq = header->seq_ctl; + } + *last_time = jiffies; + } + return 0; +#endif + default: + return 0; + } + + if ((*last_seq == seq) && + time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) { + if (*last_frag == frag){ + goto drop; + + } + if (*last_frag + 1 != frag) + /* out-of-order fragment */ + goto drop; + } else + *last_seq = seq; + + *last_frag = frag; + *last_time = jiffies; + return 0; + +drop: + + return 1; +} +bool +AddReorderEntry( + PRX_TS_RECORD pTS, + PRX_REORDER_ENTRY pReorderEntry + ) +{ + struct list_head *pList = &pTS->RxPendingPktList; + + while(pList->next != &pTS->RxPendingPktList) + { + if( SN_LESS(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) ) + { + pList = pList->next; + } + else if( SN_EQUAL(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) ) + { + return false; + } + else + { + break; + } + } + pReorderEntry->List.next = pList->next; + pReorderEntry->List.next->prev = &pReorderEntry->List; + pReorderEntry->List.prev = pList; + pList->next = &pReorderEntry->List; + + return true; +} + +void rtllib_indicate_packets(struct rtllib_device *ieee, struct rtllib_rxb** prxbIndicateArray,u8 index) +{ + struct net_device_stats *stats = &ieee->stats; + u8 i = 0 , j=0; + u16 ethertype; + for(j = 0; jWapiSupport) && (ieee->wapiInfo.bWapiEnable)) + { + if(WapiCheckDropForRxReorderCase(ieee,prxb)) + { + WAPI_TRACE(WAPI_ERR, "%s(): Rx Reorder Drop case!!\n", __FUNCTION__); + for(i = 0; inr_subframes; i++) { + if(prxb->subframes[i]) + dev_kfree_skb(prxb->subframes[i]); + } + prxb->nr_subframes = 0; + } + } +#endif + for(i = 0; inr_subframes; i++) { + struct sk_buff *sub_skb = prxb->subframes[i]; + + /* convert hdr + possible LLC headers into Ethernet header */ + ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7]; + if (sub_skb->len >= 8 && + ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 && + ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || + memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) { + /* remove RFC1042 or Bridge-Tunnel encapsulation and + * replace EtherType */ + skb_pull(sub_skb, SNAP_SIZE); + memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN); + memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN); + } else { + u16 len; + /* Leave Ethernet header part of hdr and full payload */ + len = htons(sub_skb->len); + memcpy(skb_push(sub_skb, 2), &len, 2); + memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN); + memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN); + } + + /* Indicat the packets to upper layer */ + if (sub_skb) { + stats->rx_packets++; + stats->rx_bytes += sub_skb->len; + + memset(sub_skb->cb, 0, sizeof(sub_skb->cb)); +#ifdef _RTL8192_EXT_PATCH_ + sub_skb->protocol = eth_type_trans(sub_skb, sub_skb->dev); +#else + sub_skb->protocol = eth_type_trans(sub_skb, ieee->dev); + sub_skb->dev = ieee->dev; +#endif +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) + sub_skb->dev->stats.rx_packets++; + sub_skb->dev->stats.rx_bytes += sub_skb->len; +#endif +#ifdef TCP_CSUM_OFFLOAD_RX + if ( prxb->tcp_csum_valid) + sub_skb->ip_summed = CHECKSUM_UNNECESSARY; + else + sub_skb->ip_summed = CHECKSUM_NONE; + +#else + sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ +#endif + ieee->last_rx_ps_time = jiffies; + netif_rx(sub_skb); + } + } + kfree(prxb); + prxb = NULL; + } +} + +void +rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee, PRX_TS_RECORD pTS) +{ + PRX_REORDER_ENTRY pRxReorderEntry; + struct rtllib_rxb* RfdArray[REORDER_WIN_SIZE]; + u8 RfdCnt = 0; + + + del_timer_sync(&pTS->RxPktPendingTimer); + while(!list_empty(&pTS->RxPendingPktList)) + { + if(RfdCnt >= REORDER_WIN_SIZE){ + printk("-------------->%s() error! RfdCnt >= REORDER_WIN_SIZE\n", __func__); + break; + } + + pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List); + RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): Indicate SeqNum %d!\n",__FUNCTION__, pRxReorderEntry->SeqNum); + list_del_init(&pRxReorderEntry->List); + + RfdArray[RfdCnt] = pRxReorderEntry->prxb; + + RfdCnt = RfdCnt + 1; + list_add_tail(&pRxReorderEntry->List, &ieee->RxReorder_Unused_List); + } + rtllib_indicate_packets(ieee, RfdArray, RfdCnt); + + pTS->RxIndicateSeq = 0xffff; + +#ifdef MERGE_TO_DO +#endif +} + + +void RxReorderIndicatePacket( struct rtllib_device *ieee, + struct rtllib_rxb* prxb, + PRX_TS_RECORD pTS, + u16 SeqNum) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + PRX_REORDER_ENTRY pReorderEntry = NULL; + struct rtllib_rxb* prxbIndicateArray[REORDER_WIN_SIZE]; + u8 WinSize = pHTInfo->RxReorderWinSize; + u16 WinEnd = 0; + u8 index = 0; + bool bMatchWinStart = false, bPktInBuf = false; + unsigned long flags; + + RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): Seq is %d,pTS->RxIndicateSeq is %d, WinSize is %d\n",__FUNCTION__,SeqNum,pTS->RxIndicateSeq,WinSize); + + spin_lock_irqsave(&(ieee->reorder_spinlock), flags); + + WinEnd = (pTS->RxIndicateSeq + WinSize -1)%4096; +#if 0 + if(!list_empty(&ieee->RxReorder_Unused_List)) + RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): ieee->RxReorder_Unused_List is nut NULL\n"); +#endif + /* Rx Reorder initialize condition.*/ + if(pTS->RxIndicateSeq == 0xffff) { + pTS->RxIndicateSeq = SeqNum; + } + + /* Drop out the packet which SeqNum is smaller than WinStart */ + if(SN_LESS(SeqNum, pTS->RxIndicateSeq)) { + RTLLIB_DEBUG(RTLLIB_DL_REORDER,"Packet Drop! IndicateSeq: %d, NewSeq: %d\n", + pTS->RxIndicateSeq, SeqNum); + pHTInfo->RxReorderDropCounter++; + { + int i; + for(i =0; i < prxb->nr_subframes; i++) { + dev_kfree_skb(prxb->subframes[i]); + } + kfree(prxb); + prxb = NULL; + } + spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); + return; + } + + /* + * Sliding window manipulation. Conditions includes: + * 1. Incoming SeqNum is equal to WinStart =>Window shift 1 + * 2. Incoming SeqNum is larger than the WinEnd => Window shift N + */ + if(SN_EQUAL(SeqNum, pTS->RxIndicateSeq)) { + pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096; + bMatchWinStart = true; + } else if(SN_LESS(WinEnd, SeqNum)) { + if(SeqNum >= (WinSize - 1)) { + pTS->RxIndicateSeq = SeqNum + 1 -WinSize; + } else { + pTS->RxIndicateSeq = 4095 - (WinSize - (SeqNum +1)) + 1; + } + RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum); + } + + /* + * Indication process. + * After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets + * with the SeqNum smaller than latest WinStart and buffer other packets. + */ + /* For Rx Reorder condition: + * 1. All packets with SeqNum smaller than WinStart => Indicate + * 2. All packets with SeqNum larger than or equal to WinStart => Buffer it. + */ + if(bMatchWinStart) { + /* Current packet is going to be indicated.*/ + RTLLIB_DEBUG(RTLLIB_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",\ + pTS->RxIndicateSeq, SeqNum); + prxbIndicateArray[0] = prxb; + index = 1; + } else { + /* Current packet is going to be inserted into pending list.*/ + if(!list_empty(&ieee->RxReorder_Unused_List)) { + pReorderEntry = (PRX_REORDER_ENTRY)list_entry(ieee->RxReorder_Unused_List.next,RX_REORDER_ENTRY,List); + list_del_init(&pReorderEntry->List); + + /* Make a reorder entry and insert into a the packet list.*/ + pReorderEntry->SeqNum = SeqNum; + pReorderEntry->prxb = prxb; + +#if 1 + if(!AddReorderEntry(pTS, pReorderEntry)) { + RTLLIB_DEBUG(RTLLIB_DL_REORDER, "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", + __FUNCTION__, pTS->RxIndicateSeq, SeqNum); + list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List); + { + int i; + for(i =0; i < prxb->nr_subframes; i++) { + dev_kfree_skb(prxb->subframes[i]); + } + kfree(prxb); + prxb = NULL; + } + } else { + RTLLIB_DEBUG(RTLLIB_DL_REORDER, + "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum); + } +#endif + } + else { + /* + * Packets are dropped if there is not enough reorder entries. + * This part shall be modified!! We can just indicate all the + * packets in buffer and get reorder entries. + */ + RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n"); + { + int i; + for(i =0; i < prxb->nr_subframes; i++) { + dev_kfree_skb(prxb->subframes[i]); + } + kfree(prxb); + prxb = NULL; + } + } + } + + /* Check if there is any packet need indicate.*/ + while(!list_empty(&pTS->RxPendingPktList)) { + RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): start RREORDER indicate\n",__FUNCTION__); +#if 1 + pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List); + if( SN_LESS(pReorderEntry->SeqNum, pTS->RxIndicateSeq) || + SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq)) + { + /* This protect buffer from overflow. */ + if(index >= REORDER_WIN_SIZE) { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!! \n"); + bPktInBuf = true; + break; + } + + list_del_init(&pReorderEntry->List); + + if(SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq)) + pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096; + + prxbIndicateArray[index] = pReorderEntry->prxb; + RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): Indicate SeqNum %d!\n",__FUNCTION__, pReorderEntry->SeqNum); + index++; + + list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List); + } else { + bPktInBuf = true; + break; + } +#endif + } + + /* Handling pending timer. Set this timer to prevent from long time Rx buffering.*/ + if(index>0) { + if(timer_pending(&pTS->RxPktPendingTimer)){ + del_timer_sync(&pTS->RxPktPendingTimer); + } + pTS->RxTimeoutIndicateSeq = 0xffff; + + if(index>REORDER_WIN_SIZE){ + RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n"); + spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); + return; + } + rtllib_indicate_packets(ieee, prxbIndicateArray, index); + bPktInBuf = false; + } + + if(bPktInBuf && pTS->RxTimeoutIndicateSeq==0xffff) { + RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): SET rx timeout timer\n", __FUNCTION__); + pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq; + mod_timer(&pTS->RxPktPendingTimer, jiffies + MSECS(pHTInfo->RxReorderPendingTime)); + } + spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); +} + +u8 parse_subframe(struct rtllib_device* ieee,struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats, + struct rtllib_rxb *rxb,u8* src,u8* dst) +{ + struct rtllib_hdr_3addr *hdr = (struct rtllib_hdr_3addr* )skb->data; + u16 fc = le16_to_cpu(hdr->frame_ctl); + + u16 LLCOffset= sizeof(struct rtllib_hdr_3addr); + u16 ChkLength; + bool bIsAggregateFrame = false; + u16 nSubframe_Length; + u8 nPadding_Length = 0; + u16 SeqNum=0; + struct sk_buff *sub_skb; + u8 *data_ptr; + /* just for debug purpose */ + SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl)); + if((RTLLIB_QOS_HAS_SEQ(fc))&&\ + (((frameqos *)(skb->data + RTLLIB_3ADDR_LEN))->field.reserved)) { + bIsAggregateFrame = true; + } + + if(RTLLIB_QOS_HAS_SEQ(fc)) { + LLCOffset += 2; + } + if(rx_stats->bContainHTC) { + LLCOffset += sHTCLng; + } + + ChkLength = LLCOffset;/* + (Frame_WEP(frame)!=0 ?Adapter->MgntInfo.SecurityInfo.EncryptionHeadOverhead:0);*/ + + if( skb->len <= ChkLength ) { + return 0; + } + + skb_pull(skb, LLCOffset); + ieee->bIsAggregateFrame = bIsAggregateFrame; + if(!bIsAggregateFrame) { + rxb->nr_subframes = 1; + + /* altered by clark 3/30/2010 + * The buffer size of the skb indicated to upper layer + * must be less than 5000, or the defraged IP datagram + * in the IP layer will exceed "ipfrag_high_tresh" and be + * discarded. so there must not use the function + * "skb_copy" and "skb_clone" for "skb". + */ + + /* Allocate new skb for releasing to upper layer */ + sub_skb = dev_alloc_skb(RTLLIB_SKBBUFFER_SIZE); + skb_reserve(sub_skb, 12); + data_ptr = (u8 *)skb_put(sub_skb, skb->len); + memcpy(data_ptr, skb->data, skb->len); + sub_skb->dev = ieee->dev; + + rxb->subframes[0] = sub_skb; + + memcpy(rxb->src,src,ETH_ALEN); + memcpy(rxb->dst,dst,ETH_ALEN); + rxb->subframes[0]->dev = ieee->dev; + return 1; + } else { + rxb->nr_subframes = 0; + memcpy(rxb->src,src,ETH_ALEN); + memcpy(rxb->dst,dst,ETH_ALEN); + while(skb->len > ETHERNET_HEADER_SIZE) { + /* Offset 12 denote 2 mac address */ + nSubframe_Length = *((u16*)(skb->data + 12)); + nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8); + + if(skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) { + printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\ + __FUNCTION__,rxb->nr_subframes); + printk("%s: A-MSDU parse error!! Subframe Length: %d\n",__FUNCTION__, nSubframe_Length); + printk("nRemain_Length is %d and nSubframe_Length is : %d\n",skb->len,nSubframe_Length); + printk("The Packet SeqNum is %d\n",SeqNum); + return 0; + } + + /* move the data point to data content */ + skb_pull(skb, ETHERNET_HEADER_SIZE); + + /* altered by clark 3/30/2010 + * The buffer size of the skb indicated to upper layer + * must be less than 5000, or the defraged IP datagram + * in the IP layer will exceed "ipfrag_high_tresh" and be + * discarded. so there must not use the function + * "skb_copy" and "skb_clone" for "skb". + */ + + /* Allocate new skb for releasing to upper layer */ + sub_skb = dev_alloc_skb(nSubframe_Length + 12); + skb_reserve(sub_skb, 12); + data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length); + memcpy(data_ptr,skb->data,nSubframe_Length); + + sub_skb->dev = ieee->dev; + rxb->subframes[rxb->nr_subframes++] = sub_skb; + if(rxb->nr_subframes >= MAX_SUBFRAME_COUNT) { + RTLLIB_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n"); + break; + } + skb_pull(skb,nSubframe_Length); + + if(skb->len != 0) { + nPadding_Length = 4 - ((nSubframe_Length + ETHERNET_HEADER_SIZE) % 4); + if(nPadding_Length == 4) { + nPadding_Length = 0; + } + + if(skb->len < nPadding_Length) { + return 0; + } + + skb_pull(skb,nPadding_Length); + } + } + + return rxb->nr_subframes; + } +} + + +size_t rtllib_rx_get_hdrlen(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats) +{ + struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data; + u16 fc = le16_to_cpu(hdr->frame_ctl); + size_t hdrlen = 0; + + hdrlen = rtllib_get_hdrlen(fc); + if (HTCCheck(ieee, skb->data)) { + if(net_ratelimit()) + printk("%s: find HTCControl!\n", __func__); + hdrlen += 4; + rx_stats->bContainHTC = 1; + } + + if(RTLLIB_QOS_HAS_SEQ(fc)) + rx_stats->bIsQosData = 1; + + return hdrlen; +} + +int rtllib_rx_check_duplicate(struct rtllib_device *ieee, struct sk_buff *skb, u8 multicast) +{ + struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data; + u16 fc, sc; + u8 frag, type, stype; + + fc = le16_to_cpu(hdr->frame_ctl); + type = WLAN_FC_GET_TYPE(fc); + stype = WLAN_FC_GET_STYPE(fc); + sc = le16_to_cpu(hdr->seq_ctl); + frag = WLAN_GET_SEQ_FRAG(sc); + +#ifdef _RTL8192_EXT_PATCH_ + if( (ieee->pHTInfo->bCurRxReorderEnable == false) || + !ieee->current_network.qos_data.active|| + !IsDataFrame(skb->data) || + IsLegacyDataFrame(skb->data) || + multicast) { + if (!multicast) { + if (is_duplicate_packet(ieee, hdr)){ + return -1; + } + } + } +#else + if( (ieee->pHTInfo->bCurRxReorderEnable == false) || + !ieee->current_network.qos_data.active || + !IsDataFrame(skb->data) || + IsLegacyDataFrame(skb->data)) { + if(!((type == RTLLIB_FTYPE_MGMT) && (stype == RTLLIB_STYPE_BEACON))){ + if (is_duplicate_packet(ieee, hdr)){ + return -1; + } + } + } +#endif + else { + PRX_TS_RECORD pRxTS = NULL; + if (GetTs(ieee, (PTS_COMMON_INFO*) &pRxTS, hdr->addr2, + (u8)Frame_QoSTID((u8*)(skb->data)), RX_DIR, true)) { + if ((fc & (1<<11)) && (frag == pRxTS->RxLastFragNum) && + (WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum)) { + return -1; + } else { + pRxTS->RxLastFragNum = frag; + pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc); + } + } else { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!%s(): No TS!! Skip the check!!\n",__FUNCTION__); + return -1; + } + } + + return 0; +} +void rtllib_rx_extract_addr(struct rtllib_device *ieee, struct rtllib_hdr_4addr *hdr, u8 *dst, u8 *src, u8 *bssid) +{ + u16 fc = le16_to_cpu(hdr->frame_ctl); + + switch (fc & (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) { + case RTLLIB_FCTL_FROMDS: + memcpy(dst, hdr->addr1, ETH_ALEN); + memcpy(src, hdr->addr3, ETH_ALEN); + memcpy(bssid, hdr->addr2, ETH_ALEN); + break; + case RTLLIB_FCTL_TODS: + memcpy(dst, hdr->addr3, ETH_ALEN); + memcpy(src, hdr->addr2, ETH_ALEN); + memcpy(bssid, hdr->addr1, ETH_ALEN); + break; + case RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS: + memcpy(dst, hdr->addr3, ETH_ALEN); + memcpy(src, hdr->addr4, ETH_ALEN); +#ifdef _RTL8192_EXT_PATCH_ + memcpy(bssid, ieee->current_mesh_network.bssid, ETH_ALEN); +#else + memcpy(bssid, ieee->current_network.bssid, ETH_ALEN); +#endif + break; + case 0: + memcpy(dst, hdr->addr1, ETH_ALEN); + memcpy(src, hdr->addr2, ETH_ALEN); + memcpy(bssid, hdr->addr3, ETH_ALEN); + break; + } +} +int rtllib_rx_data_filter(struct rtllib_device *ieee, u16 fc, u8 *dst, u8 *src, u8 *bssid, u8 *addr2) +{ + u8 zero_addr[ETH_ALEN] = {0}; + u8 type, stype; + + type = WLAN_FC_GET_TYPE(fc); + stype = WLAN_FC_GET_STYPE(fc); + + /* Filter frames from different BSS */ + if (((fc & RTLLIB_FCTL_DSTODS) != RTLLIB_FCTL_DSTODS) + && (compare_ether_addr(ieee->current_network.bssid, bssid) != 0) + && memcmp(ieee->current_network.bssid, zero_addr, ETH_ALEN)) { + return -1; + } + + /* Filter packets sent by an STA that will be forwarded by AP */ + if ( ieee->IntelPromiscuousModeInfo.bPromiscuousOn && + ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame ) { + if ((fc & RTLLIB_FCTL_TODS) && !(fc & RTLLIB_FCTL_FROMDS) && + (compare_ether_addr(dst, ieee->current_network.bssid) != 0) && + (compare_ether_addr(bssid, ieee->current_network.bssid) == 0)) { + return -1; + } + } + + /* Nullfunc frames may have PS-bit set, so they must be passed to + * hostap_handle_sta_rx() before being dropped here. */ + if(!ieee->IntelPromiscuousModeInfo.bPromiscuousOn){ + if (stype != RTLLIB_STYPE_DATA && + stype != RTLLIB_STYPE_DATA_CFACK && + stype != RTLLIB_STYPE_DATA_CFPOLL && + stype != RTLLIB_STYPE_DATA_CFACKPOLL&& + stype != RTLLIB_STYPE_QOS_DATA + ) { + if (stype != RTLLIB_STYPE_NULLFUNC) + RTLLIB_DEBUG_DROP( + "RX: dropped data frame " + "with no data (type=0x%02x, " + "subtype=0x%02x)\n", + type, stype); + return -1; + } + } + + if(ieee->iw_mode == IW_MODE_MESH) { +#ifdef _RTL8192_EXT_PATCH_ + /* check whether it exists the mesh entry for data packet */ + if(ieee->ext_patch_rtllib_is_mesh&&\ + (false ==ieee->ext_patch_rtllib_is_mesh(ieee, addr2))) { + if(ieee->only_mesh) { + return -1; + } else if(memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) { + return -1; + } + } +#endif + } else { + /* packets from our adapter are dropped (echo) */ + if (!memcmp(src, ieee->dev->dev_addr, ETH_ALEN)) + return -1; + + /* {broad,multi}cast packets to our BSS go through */ + if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst)) { + if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) { + return -1; + } + } + } + return 0; +} +int rtllib_rx_get_crypt( + struct rtllib_device *ieee, + struct sk_buff *skb, + struct rtllib_crypt_data **crypt, + size_t hdrlen) +{ + struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data; + u16 fc = le16_to_cpu(hdr->frame_ctl); + int idx = 0; + +#if defined (RTL8192S_WAPI_SUPPORT) + if (ieee->host_decrypt && (!ieee->wapiInfo.bWapiEnable)) +#else + if (ieee->host_decrypt) +#endif + { + if (skb->len >= hdrlen + 3) + idx = skb->data[hdrlen + 3] >> 6; + +#ifdef _RTL8192_EXT_PATCH_ + *crypt = ieee->sta_crypt[idx]; +#else + *crypt = ieee->crypt[idx]; +#endif + /* allow NULL decrypt to indicate an station specific override + * for default encryption */ + if (*crypt && ((*crypt)->ops == NULL || + (*crypt)->ops->decrypt_mpdu == NULL)) + *crypt = NULL; + + if (!*crypt && (fc & RTLLIB_FCTL_WEP)) { + /* This seems to be triggered by some (multicast?) + * frames from other than current BSS, so just drop the + * frames silently instead of filling system log with + * these reports. */ + RTLLIB_DEBUG_DROP("Decryption failed (not set)" + " (SA=" MAC_FMT ")\n", + MAC_ARG(hdr->addr2)); + ieee->ieee_stats.rx_discards_undecryptable++; + return -1; + } + } + + return 0; +} +int rtllib_rx_decrypt( + struct rtllib_device *ieee, + struct sk_buff **skb, + struct rtllib_rx_stats *rx_stats, + struct rtllib_crypt_data *crypt, + size_t hdrlen) +{ + struct rtllib_hdr_4addr *hdr; + int keyidx = 0; + u16 fc, sc; + u8 frag; + + hdr = (struct rtllib_hdr_4addr *)(*skb)->data; + fc = le16_to_cpu(hdr->frame_ctl); + sc = le16_to_cpu(hdr->seq_ctl); + frag = WLAN_GET_SEQ_FRAG(sc); + + if((!rx_stats->Decrypted)){ + ieee->need_sw_enc = 1; + }else{ + ieee->need_sw_enc = 0; + } + + if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) && + ((keyidx = rtllib_rx_frame_decrypt(ieee, (*skb), crypt)) < 0) +#if defined (RTL8192S_WAPI_SUPPORT) + && (!ieee->wapiInfo.bWapiEnable) +#endif + ) + { + printk("%s: decrypt frame error\n", __func__); + return -1; + } + +#if defined (RTL8192S_WAPI_SUPPORT) + if(ieee->wapiInfo.bWapiEnable){ + if(ieee->pairwise_key_type == KEY_TYPE_SMS4){ + if(false == SecSWSMS4Decryption(ieee, (*skb), rx_stats)){ + WAPI_TRACE(WAPI_ERR, "%s():SMS4 decrypt frame error\n",__func__); + return -1; + } + } + } +#endif + hdr = (struct rtllib_hdr_4addr *) (*skb)->data; + if ((frag != 0 || (fc & RTLLIB_FCTL_MOREFRAGS))) { + int flen; + struct sk_buff *frag_skb = rtllib_frag_cache_get(ieee, hdr); + RTLLIB_DEBUG_FRAG("Rx Fragment received (%u)\n", frag); + + if (!frag_skb) { + RTLLIB_DEBUG(RTLLIB_DL_RX | RTLLIB_DL_FRAG, + "Rx cannot get skb from fragment " + "cache (morefrag=%d seq=%u frag=%u)\n", + (fc & RTLLIB_FCTL_MOREFRAGS) != 0, + WLAN_GET_SEQ_SEQ(sc), frag); + return -1; + } + flen = (*skb)->len; + if (frag != 0) + flen -= hdrlen; + + if (frag_skb->tail + flen > frag_skb->end) { + printk(KERN_WARNING "%s: host decrypted and " + "reassembled frame did not fit skb\n", + __func__); + rtllib_frag_cache_invalidate(ieee, hdr); + return -1; + } + + if (frag == 0) { + /* copy first fragment (including full headers) into + * beginning of the fragment cache skb */ + memcpy(skb_put(frag_skb, flen), (*skb)->data, flen); + } else { + /* append frame payload to the end of the fragment + * cache skb */ + memcpy(skb_put(frag_skb, flen), (*skb)->data + hdrlen, + flen); + } + dev_kfree_skb_any(*skb); + *skb = NULL; + + if (fc & RTLLIB_FCTL_MOREFRAGS) { + /* more fragments expected - leave the skb in fragment + * cache for now; it will be delivered to upper layers + * after all fragments have been received */ + return -2; + } + + /* this was the last fragment and the frame will be + * delivered, so remove skb from fragment cache */ + *skb = frag_skb; + hdr = (struct rtllib_hdr_4addr *) (*skb)->data; + rtllib_frag_cache_invalidate(ieee, hdr); + } + + /* skb: hdr + (possible reassembled) full MSDU payload; possibly still + * encrypted/authenticated */ + if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) && +#if defined (RTL8192S_WAPI_SUPPORT) + (!ieee->wapiInfo.bWapiEnable) && +#endif + rtllib_rx_frame_decrypt_msdu(ieee, *skb, keyidx, crypt)) + { + printk("%s: ==>decrypt msdu error\n", __func__); + return -1; + } + + hdr = (struct rtllib_hdr_4addr *) (*skb)->data; + if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep) { + if (/*ieee->ieee802_1x &&*/ + rtllib_is_eapol_frame(ieee, *skb, hdrlen)) { + +#ifdef CONFIG_RTLLIB_DEBUG + /* pass unencrypted EAPOL frames even if encryption is + * configured */ + struct eapol *eap = (struct eapol *)((*skb)->data + + 24); + RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", + eap_get_type(eap->type)); +#endif + } else { + RTLLIB_DEBUG_DROP( + "encryption configured, but RX " + "frame not encrypted (SA=" MAC_FMT ")\n", + MAC_ARG(hdr->addr2)); + return -1; + } + } + +#ifdef CONFIG_RTLLIB_DEBUG + if (crypt && !(fc & RTLLIB_FCTL_WEP) && + rtllib_is_eapol_frame(ieee, *skb, hdrlen)) { + struct eapol *eap = (struct eapol *)((*skb)->data + + 24); + RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", + eap_get_type(eap->type)); + } +#endif + + if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep && + !rtllib_is_eapol_frame(ieee, *skb, hdrlen)) { + RTLLIB_DEBUG_DROP( + "dropped unencrypted RX data " + "frame from " MAC_FMT + " (drop_unencrypted=1)\n", + MAC_ARG(hdr->addr2)); + return -1; + } + + if(rtllib_is_eapol_frame(ieee, *skb, hdrlen)) { + printk(KERN_WARNING "RX: IEEE802.1X EAPOL frame!\n"); + } + + return 0; +} +void rtllib_rx_check_leave_lps(struct rtllib_device *ieee, u8 unicast, u8 nr_subframes) +{ +#if !defined(RTL8192SU) && !defined(RTL8192U) +#ifdef ENABLE_LPS + if(unicast){ + + if((ieee->state == RTLLIB_LINKED) /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) + { + if( ((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) || + (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) ) + { + if(ieee->LeisurePSLeave) + ieee->LeisurePSLeave(ieee->dev); + } + } + } +#endif +#endif + ieee->last_rx_ps_time = jiffies; +} +void rtllib_rx_indicate_pkt_legacy( + struct rtllib_device *ieee, + struct rtllib_rx_stats *rx_stats, + struct rtllib_rxb* rxb, + u8 *dst, + u8 *src) +{ +#ifndef _RTL8192_EXT_PATCH_ + struct net_device *dev = ieee->dev; +#endif + u16 ethertype; + int i = 0; + + if(rxb == NULL){ + printk("%s: rxb is NULL!!\n", __func__); + return ; + } + + for(i = 0; inr_subframes; i++) { + struct sk_buff *sub_skb = rxb->subframes[i]; + + if (sub_skb) { + /* convert hdr + possible LLC headers into Ethernet header */ + ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7]; + if (sub_skb->len >= 8 && + ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 && + ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || + memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) { + /* remove RFC1042 or Bridge-Tunnel encapsulation and + * replace EtherType */ + skb_pull(sub_skb, SNAP_SIZE); + memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN); + memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN); + } else { + u16 len; + /* Leave Ethernet header part of hdr and full payload */ + len = htons(sub_skb->len); + memcpy(skb_push(sub_skb, 2), &len, 2); + memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN); + memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN); + } + + ieee->stats.rx_packets++; + ieee->stats.rx_bytes += sub_skb->len; + + if(is_multicast_ether_addr(dst)) { + ieee->stats.multicast++; + } + + /* Indicat the packets to upper layer */ + memset(sub_skb->cb, 0, sizeof(sub_skb->cb)); +#ifdef _RTL8192_EXT_PATCH_ + sub_skb->protocol = eth_type_trans(sub_skb, sub_skb->dev); +#else + sub_skb->protocol = eth_type_trans(sub_skb, dev); + sub_skb->dev = dev; +#endif +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) + sub_skb->dev->stats.rx_packets++; + sub_skb->dev->stats.rx_bytes += sub_skb->len; +#endif +#ifdef TCP_CSUM_OFFLOAD_RX + if ( rx_stats->tcp_csum_valid) + sub_skb->ip_summed = CHECKSUM_UNNECESSARY; + else + sub_skb->ip_summed = CHECKSUM_NONE; +#else + sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ +#endif + netif_rx(sub_skb); + } + } + kfree(rxb); + rxb = NULL; +} +int rtllib_rx_InfraAdhoc(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats) +{ + struct net_device *dev = ieee->dev; + struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data; + struct rtllib_crypt_data *crypt = NULL; +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + struct sta_info * psta = NULL; +#endif + struct rtllib_rxb* rxb = NULL; + PRX_TS_RECORD pTS = NULL; + u16 fc, sc, SeqNum = 0; + u8 type, stype, multicast = 0, unicast = 0, nr_subframes = 0, TID = 0; + u8 dst[ETH_ALEN], src[ETH_ALEN], bssid[ETH_ALEN] = {0}, *payload; + size_t hdrlen = 0; +#if defined (RTL8192S_WAPI_SUPPORT) + u8 wapiDectResult = 0; +#endif + bool bToOtherSTA = false; + int ret = 0, i = 0; + + hdr = (struct rtllib_hdr_4addr *)skb->data; + fc = le16_to_cpu(hdr->frame_ctl); + type = WLAN_FC_GET_TYPE(fc); + stype = WLAN_FC_GET_STYPE(fc); + sc = le16_to_cpu(hdr->seq_ctl); + + /*Filter pkt not to me*/ + multicast = is_multicast_ether_addr(hdr->addr1)|is_broadcast_ether_addr(hdr->addr1); + unicast = !multicast; + if (unicast && (compare_ether_addr(dev->dev_addr, hdr->addr1) != 0)) { + if(ieee->bNetPromiscuousMode) + bToOtherSTA = true; + else + goto rx_dropped; + } + + /*Filter pkt has too small length */ + hdrlen = rtllib_rx_get_hdrlen(ieee, skb, rx_stats); + if(skb->len < hdrlen){ + printk("%s():ERR!!! skb->len is smaller than hdrlen\n",__FUNCTION__); + goto rx_dropped; + } + + /* Filter Duplicate pkt */ + ret = rtllib_rx_check_duplicate(ieee, skb, multicast); + if(ret < 0) + goto rx_dropped; + + /* Filter CTRL Frame */ + if (type == RTLLIB_FTYPE_CTL) { + goto rx_dropped; + } + + /* Filter MGNT Frame */ + if (type == RTLLIB_FTYPE_MGMT) { + if(bToOtherSTA) + goto rx_dropped; + if (rtllib_rx_frame_mgmt(ieee, skb, rx_stats, type, stype)) + goto rx_dropped; + else + goto rx_exit; + } + + /* Filter WAPI DATA Frame */ +#if defined (RTL8192S_WAPI_SUPPORT) + if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable){ + wapiDectResult = SecIsWAIPacket(ieee, skb); + if(wapiDectResult !=0){ + if(memcmp(&ieee->wapiInfo.wapiSeqnumAndFragNum,&sc,2)) + WapiHandleRecvPacket(ieee, skb, wapiDectResult); + memcpy(&ieee->wapiInfo.wapiSeqnumAndFragNum,&sc,2); + dev_kfree_skb_any(skb); + goto rx_exit; + } + } +#endif + + /* Update statstics for AP roaming */ + if(!bToOtherSTA){ + ieee->LinkDetectInfo.NumRecvDataInPeriod++; + ieee->LinkDetectInfo.NumRxOkInPeriod++; + } + dev->last_rx = jiffies; + + /* Data frame - extract src/dst addresses */ + rtllib_rx_extract_addr(ieee, hdr, dst, src, bssid); + + /* Filter Data frames */ + ret = rtllib_rx_data_filter(ieee, fc, dst, src, bssid, hdr->addr2); + if(ret < 0) + goto rx_dropped; + + if(skb->len == hdrlen){ + goto rx_dropped; + } + + /* Send pspoll based on moredata */ +#ifdef ENABLE_LPS + if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->sta_sleep == LPS_IS_SLEEP) + && (ieee->polling) && (!bToOtherSTA)) { + if (WLAN_FC_MORE_DATA(fc)) { + /* more data bit is set, let's request a new frame from the AP */ + rtllib_sta_ps_send_pspoll_frame(ieee); + } else { + ieee->polling = false; + } + } +#endif + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + if(ieee->iw_mode == IW_MODE_ADHOC){ + psta = GetStaInfo(ieee, src); + if(NULL != psta) + psta->LastActiveTime = jiffies; + } +#endif + + /* Get crypt if encrypted */ + ret = rtllib_rx_get_crypt(ieee, skb, &crypt, hdrlen); + if(ret == -1) + goto rx_dropped; + + /* Decrypt data frame (including reassemble) */ + ret = rtllib_rx_decrypt(ieee, &skb, rx_stats, crypt, hdrlen); + if(ret == -1) + goto rx_dropped; + else if(ret == -2) + goto rx_exit; + + /* Get TS for Rx Reorder */ + hdr = (struct rtllib_hdr_4addr *) skb->data; + if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data) + && !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1) + && (!bToOtherSTA)) + { + TID = Frame_QoSTID(skb->data); + SeqNum = WLAN_GET_SEQ_SEQ(sc); + GetTs(ieee,(PTS_COMMON_INFO*) &pTS,hdr->addr2,TID,RX_DIR,true); + if(TID !=0 && TID !=3){ + ieee->bis_any_nonbepkts = true; + } + } + + /* Parse rx data frame (For AMSDU) */ + /* skb: hdr + (possible reassembled) full plaintext payload */ + payload = skb->data + hdrlen; + rxb = (struct rtllib_rxb*)kmalloc(sizeof(struct rtllib_rxb),GFP_ATOMIC); + if(rxb == NULL) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR,"%s(): kmalloc rxb error\n",__FUNCTION__); + goto rx_dropped; + } + /* to parse amsdu packets */ + /* qos data packets & reserved bit is 1 */ + if(parse_subframe(ieee,skb,rx_stats,rxb,src,dst) == 0) { + /* only to free rxb, and not submit the packets to upper layer */ + for(i =0; i < rxb->nr_subframes; i++) { + dev_kfree_skb(rxb->subframes[i]); + } + kfree(rxb); + rxb = NULL; + goto rx_dropped; + } + + /* Update WAPI PN */ +#ifdef RTL8192S_WAPI_SUPPORT + if(ieee->wapiInfo.bWapiEnable){ + if(rxb){ + rxb->UserPriority = TID; + memcpy(rxb->WapiTempPN, rx_stats->WapiTempPN, 16); + memcpy(rxb->WapiSrcAddr, rx_stats->WapiSrcAddr, 6); + rxb->bWapiCheckPNInDecrypt = rx_stats->bWapiCheckPNInDecrypt; + } + } +#endif + + /* Check if leave LPS */ + if(!bToOtherSTA){ + if(ieee->bIsAggregateFrame) + nr_subframes = rxb->nr_subframes; + else + nr_subframes = 1; + if(unicast) + ieee->LinkDetectInfo.NumRxUnicastOkInPeriod += nr_subframes; + rtllib_rx_check_leave_lps(ieee, unicast, nr_subframes); + } + + /* Indicate packets to upper layer or Rx Reorder */ + if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL || bToOtherSTA){ + rtllib_rx_indicate_pkt_legacy(ieee, rx_stats, rxb, dst, src); + }else{ +#ifdef TCP_CSUM_OFFLOAD_RX + rxb->tcp_csum_valid = rx_stats->tcp_csum_valid; +#endif + RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum); + } + + dev_kfree_skb(skb); + skb = NULL; + + rx_exit: + return 1; + + rx_dropped: + if (rxb != NULL) + { + kfree(rxb); + rxb = NULL; + } + ieee->stats.rx_dropped++; + + /* Returning 0 indicates to caller that we have not handled the SKB-- + * so it is still allocated and can be used again by underlying + * hardware as a DMA target */ + return 0; +} + +int rtllib_rx_Master(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats) +{ + return 0; +} +int rtllib_rx_Monitor(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats) +{ + struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data; + u16 fc = le16_to_cpu(hdr->frame_ctl); + size_t hdrlen = rtllib_get_hdrlen(fc); + + if(skb->len < hdrlen){ + printk("%s():ERR!!! skb->len is smaller than hdrlen\n", __func__); + return 0; + } + + if (HTCCheck(ieee, skb->data)) { + if(net_ratelimit()) + printk("%s: Find HTCControl!\n", __func__); + hdrlen += 4; + } + +#if WIRELESS_EXT > 15 + rtllib_monitor_rx(ieee, skb, rx_stats, hdrlen); + ieee->stats.rx_packets++; + ieee->stats.rx_bytes += skb->len; +#endif + return 1; +} +#ifdef _RTL8192_EXT_PATCH_ +extern u8 msh_parse_subframe(struct rtllib_device *ieee,struct sk_buff *skb, struct rtllib_rxb *rxb); +extern int msh_rx_process_dataframe(struct rtllib_device *ieee, struct rtllib_rxb *rxb, struct rtllib_rx_stats *rx_stats); +int rtllib_rx_get_mesh_crypt( + struct rtllib_device *ieee, + struct sk_buff *skb, + struct rtllib_crypt_data **crypt, + size_t hdrlen) +{ + struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data; + u16 fc = le16_to_cpu(hdr->frame_ctl); + int idx = 0, i; + u8 find_crypt = false; + + if (ieee->host_decrypt){ + if (skb->len >= hdrlen + 3) + idx = skb->data[hdrlen + 3] >> 6; + if (ieee->mesh_sec_type == 1) { + if(ieee->mesh_security_setting==1 ||ieee->mesh_security_setting==3){ + i = rtllib_find_MP(ieee, hdr->addr2, 0); + if(is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1)){ + if(ieee->only_mesh){ + if(i != -1){ + i=0; + }else{ + printk("%s: Err find MP ("MAC_FMT")!SAE, Multicast and only mesh\n", __func__, MAC_ARG(hdr->addr2)); + return -1; + } + }else{ + if(i != -1){ + i=0; + }else{ + find_crypt = true; + *crypt = ieee->sta_crypt[idx]; + } + } + }else{ + if(ieee->only_mesh){ + if (i == -1){ + printk("%s: Err find MP ("MAC_FMT")!SAE, Unicast and only mesh\n", __func__, MAC_ARG(hdr->addr2)); + return -1; + } + }else{ + if (i == -1){ + find_crypt = true; + *crypt = ieee->sta_crypt[idx]; + } + } + } + if(find_crypt == false){ + if(ieee->cryptlist[i] == NULL) + return -1; + else + *crypt = ieee->cryptlist[i]->crypt[idx]; + } + } + } + else { + *crypt = ieee->cryptlist[0]->crypt[idx]; + if(*crypt){ + int i = rtllib_find_MP(ieee, hdr->addr2, 0); + if(ieee->only_mesh){ + if (i == -1){ + printk("%s: Err find MP ("MAC_FMT")!Not SAE, Only mesh.\n", __func__, MAC_ARG(hdr->addr2)); + return -1; + } + if (ieee->cryptlist[i] && ieee->cryptlist[i]->crypt[idx]) + *crypt = ieee->cryptlist[i]->crypt[idx]; + else{ + *crypt = NULL; + printk("%s: Err find crypt!Not SAE, Only mesh.\n", __func__); + return -1; + } + }else{ + if(i != -1) + { + if (ieee->cryptlist[i] && ieee->cryptlist[i]->crypt[idx]) + *crypt = ieee->cryptlist[i]->crypt[idx]; + else{ + *crypt = NULL; + printk("%s: Err find crypt!Not SAE, Only mesh.\n", __func__); + return -1; + } + } + else + *crypt = ieee->sta_crypt[idx]; + } + } + else{ + if(!ieee->ext_patch_rtllib_is_mesh(ieee,hdr->addr2)) + *crypt = ieee->sta_crypt[idx]; + } + } + + /* allow NULL decrypt to indicate an station specific override + * for default encryption */ + if (*crypt && ((*crypt)->ops == NULL || + (*crypt)->ops->decrypt_mpdu == NULL)) + *crypt = NULL; + + if (!*crypt && (fc & RTLLIB_FCTL_WEP)) { + /* This seems to be triggered by some (multicast?) + * frames from other than current BSS, so just drop the + * frames silently instead of filling system log with + * these reports. */ + RTLLIB_DEBUG_DROP("Decryption failed (not set)" + " (SA=" MAC_FMT ")\n", + MAC_ARG(hdr->addr2)); + ieee->ieee_stats.rx_discards_undecryptable++; + return -1; + } + } + return 0; +} +#endif + +int rtllib_rx_Mesh(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats) +{ +#ifdef _RTL8192_EXT_PATCH_ + struct net_device *dev = ieee->dev; + struct rtllib_hdr_4addr *hdr = (struct rtllib_hdr_4addr *)skb->data; + struct rtllib_crypt_data *crypt = NULL; + struct rtllib_rxb* rxb = NULL; + PRX_TS_RECORD pTS = NULL; + u16 fc, sc, SeqNum = 0; + u8 type, stype, multicast = 0, unicast = 0, nr_subframes = 0, TID = 0; + u8 dst[ETH_ALEN], src[ETH_ALEN], bssid[ETH_ALEN] = {0}, *payload; + size_t hdrlen = 0; + int ret = 0, i = 0; + + hdr = (struct rtllib_hdr_4addr *)skb->data; + fc = le16_to_cpu(hdr->frame_ctl); + type = WLAN_FC_GET_TYPE(fc); + stype = WLAN_FC_GET_STYPE(fc); + sc = le16_to_cpu(hdr->seq_ctl); + + /*Filter pkt not to me*/ + multicast = is_multicast_ether_addr(hdr->addr1)|is_broadcast_ether_addr(hdr->addr1); + unicast = !multicast; + if (unicast && (compare_ether_addr(dev->dev_addr, hdr->addr1) != 0)) { + goto rx_dropped; + } + + /*Filter pkt has too small length */ + hdrlen = rtllib_rx_get_hdrlen(ieee, skb, rx_stats); + if(skb->len < hdrlen){ + printk("%s():ERR!!! skb->len is smaller than hdrlen\n",__FUNCTION__); + goto rx_dropped; + } + + /* Filter Duplicate pkt */ + ret = rtllib_rx_check_duplicate(ieee, skb, multicast); + if(ret < 0){ + goto rx_dropped; + } + + /* Update PeerMP expire time */ + if(ieee->ext_patch_rtllib_rx_mgt_update_expire) + ieee->ext_patch_rtllib_rx_mgt_update_expire( ieee, skb ); + + /* Filter CTRL Frame */ + if (type == RTLLIB_FTYPE_CTL) { + goto rx_dropped; + } + + /* Filter MGNT Frame */ + if (type == RTLLIB_FTYPE_MGMT) { + if (rtllib_rx_frame_mgmt(ieee, skb, rx_stats, type, stype)){ + printk("%s: Mgnt Frame! ret!=0\n", __func__); + goto rx_dropped; + } + else + goto rx_exit; + } + + /* Update statstics for AP roaming */ + if(ieee->only_mesh == 0){ + ieee->LinkDetectInfo.NumRecvDataInPeriod++; + ieee->LinkDetectInfo.NumRxOkInPeriod++; + dev->last_rx = jiffies; + } + + /* Data frame - extract src/dst addresses */ + rtllib_rx_extract_addr(ieee, hdr, dst, src, bssid); + + /* Filter Data frames */ + ret = rtllib_rx_data_filter(ieee, fc, dst, src, bssid, hdr->addr2); + if(ret < 0){ + goto rx_dropped; + } + if(skb->len == hdrlen){ + goto rx_dropped; + } + + /* Get crypt if encrypted */ + ret = rtllib_rx_get_mesh_crypt(ieee, skb, &crypt, hdrlen); + if(ret == -1) + goto rx_dropped; + + /* Decrypt data frame (including reassemble) */ + ret = rtllib_rx_decrypt(ieee, &skb, rx_stats, crypt, hdrlen); + if(ret == -1) + goto rx_dropped; + else if(ret == -2) + goto rx_exit; + + /* Get TS for Rx Reorder */ + hdr = (struct rtllib_hdr_4addr *) skb->data; + if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data) + && !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1)) + { + TID = Frame_QoSTID(skb->data); + SeqNum = WLAN_GET_SEQ_SEQ(sc); + GetTs(ieee,(PTS_COMMON_INFO*) &pTS,hdr->addr2,TID,RX_DIR,true); + if(TID !=0 && TID !=3){ + ieee->bis_any_nonbepkts = true; + } + } + + /* Parse rx data frame */ + if((fc & (WIFI_MESH_TYPE | RTLLIB_FCTL_DSTODS)) + == (WIFI_MESH_TYPE | RTLLIB_FCTL_DSTODS)) + { + /* Parse Mesh data frame */ + rxb = (struct rtllib_rxb*)kmalloc(sizeof(struct rtllib_rxb),GFP_ATOMIC); + if(rxb == NULL) + { + printk("%s(): kmalloc rxb error\n", __func__); + goto rx_dropped; + } + memset(rxb, 0, sizeof(struct rtllib_rxb)); + if(msh_parse_subframe(ieee, skb, rxb)==0){ + /* only to free rxb, and not submit the packets to upper layer */ + for(i =0; i < rxb->nr_subframes; i++) { + if(rxb->subframes[i]) + dev_kfree_skb(rxb->subframes[i]); + } + kfree(rxb); + rxb = NULL; + goto rx_dropped; + } + ret = msh_rx_process_dataframe(ieee,rxb,rx_stats); + if(ret < 0) { + for(i =0; i < rxb->nr_subframes; i++) { + if(rxb->subframes[i]) + dev_kfree_skb(rxb->subframes[i]); + } + kfree(rxb); + rxb = NULL; + goto rx_dropped; + }else{ + kfree(rxb); + rxb = NULL; + } + } + else{ + /* Parse INFRA data frame (Server Ra0 mode) */ + /* skb: hdr + (possible reassembled) full plaintext payload */ + payload = skb->data + hdrlen; + rxb = (struct rtllib_rxb*)kmalloc(sizeof(struct rtllib_rxb),GFP_ATOMIC); + if(rxb == NULL) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR,"%s(): kmalloc rxb error\n", __func__); + goto rx_dropped; + } + /* to parse amsdu packets */ + /* qos data packets & reserved bit is 1 */ + if(parse_subframe(ieee,skb,rx_stats,rxb,src,dst) == 0) { + /* only to free rxb, and not submit the packets to upper layer */ + for(i =0; i < rxb->nr_subframes; i++) { + dev_kfree_skb(rxb->subframes[i]); + } + kfree(rxb); + rxb = NULL; + goto rx_dropped; + } + + if(ieee->bIsAggregateFrame) + nr_subframes = rxb->nr_subframes; + else + nr_subframes = 1; + if(unicast) + ieee->LinkDetectInfo.NumRxUnicastOkInPeriod += nr_subframes; + + /* Indicate packets to upper layer or Rx Reorder */ + if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){ + rtllib_rx_indicate_pkt_legacy(ieee, rx_stats, rxb, dst, src); + }else{ + RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n",__FUNCTION__); +#ifdef TCP_CSUM_OFFLOAD_RX + rxb->tcp_csum_valid = rx_stats->tcp_csum_valid; +#endif + RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum); + } + } + + dev_kfree_skb(skb); + skb = NULL; + + + rx_exit: + return 1; + + rx_dropped: + if (rxb != NULL) + { + kfree(rxb); + rxb = NULL; + } + ieee->stats.rx_dropped++; + + /* Returning 0 indicates to caller that we have not handled the SKB-- + * so it is still allocated and can be used again by underlying + * hardware as a DMA target */ +#endif + return 0; +} + +#if 1 +/* All received frames are sent to this function. @skb contains the frame in + * IEEE 802.11 format, i.e., in the format it was sent over air. + * This function is called only as a tasklet (software IRQ). */ +int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats) +{ + int ret = 0; + + if((NULL==ieee) || (NULL==skb) || (NULL==rx_stats)){ + printk(KERN_INFO "%s: Input parameters NULL!\n", __func__); + goto rx_dropped; + } + if (skb->len < 10) { + printk(KERN_INFO "%s: SKB length < 10 \n", __func__); + goto rx_dropped; + } + + + if(ieee->softmac_process_bt_pkt) + ieee->softmac_process_bt_pkt(skb, ieee->dev); + + switch(ieee->iw_mode){ + case IW_MODE_ADHOC: + case IW_MODE_INFRA: + ret = rtllib_rx_InfraAdhoc(ieee, skb, rx_stats); + break; + case IW_MODE_MASTER: + case IW_MODE_REPEAT: + ret = rtllib_rx_Master(ieee, skb, rx_stats); + break; + case IW_MODE_MONITOR: + ret = rtllib_rx_Monitor(ieee, skb, rx_stats); + break; + case IW_MODE_MESH: + ret = rtllib_rx_Mesh(ieee, skb, rx_stats); + break; + default: + printk(KERN_INFO"%s: ERR iw mode!!!\n", __func__); + break; + } + + return ret; + + rx_dropped: + ieee->stats.rx_dropped++; + return 0; +} +#else +int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats) +{ + struct net_device *dev = ieee->dev; + struct rtllib_hdr_4addr *hdr; + size_t hdrlen; + u16 fc, type, stype, sc; + struct net_device_stats *stats = NULL; + unsigned int frag; + u8 *payload; + u16 ethertype; + u8 TID = 0; + u16 SeqNum = 0; + PRX_TS_RECORD pTS = NULL; +#ifdef NOT_YET + struct net_device *wds = NULL; + struct sk_buff *skb2 = NULL; + struct net_device *wds = NULL; + int frame_authorized = 0; + int from_assoc_ap = 0; + void *sta = NULL; +#endif + u8 dst[ETH_ALEN]; + u8 src[ETH_ALEN]; + u8 bssid[ETH_ALEN] = {0}; + u8 zero_addr[ETH_ALEN] = {0}; + struct rtllib_crypt_data *crypt = NULL; + int keyidx = 0; +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + struct sta_info * psta = NULL; +#endif + bool unicast_packet = false; + int i; + struct rtllib_rxb* rxb = NULL; + int multicast = 0; + bool tmp_dump = false; +#if defined _RTL8192_EXT_PATCH_ + int ret = 0; +#endif + bool bToOtherSTA = false; +#if defined (RTL8192S_WAPI_SUPPORT) + u8 wapiDectResult = 0; +#endif + hdr = (struct rtllib_hdr_4addr *)skb->data; + stats = &ieee->stats; + + multicast = is_multicast_ether_addr(hdr->addr1)|is_broadcast_ether_addr(hdr->addr1); + if (!multicast && (compare_ether_addr(dev->dev_addr, hdr->addr1) != 0)) { + if ((ieee->iw_mode == IW_MODE_MONITOR) || ieee->bNetPromiscuousMode){ + bToOtherSTA = true; + }else{ + goto rx_dropped; + } + } + + fc = le16_to_cpu(hdr->frame_ctl); + type = WLAN_FC_GET_TYPE(fc); + stype = WLAN_FC_GET_STYPE(fc); + sc = le16_to_cpu(hdr->seq_ctl); + frag = WLAN_GET_SEQ_FRAG(sc); + + ieee->need_sw_enc = 0; + + hdrlen = rtllib_get_hdrlen(fc); + if(skb->len < hdrlen){ + printk("%s():ERR!!! skb->len is smaller than hdrlen\n",__FUNCTION__); + goto rx_dropped; + } + + if (HTCCheck(ieee, skb->data)) { + if(net_ratelimit()) + printk("find HTCControl\n"); + hdrlen += 4; + rx_stats->bContainHTC = 1; + } + if(RTLLIB_QOS_HAS_SEQ(fc)) + rx_stats->bIsQosData = 1; + if ((0) && (type == RTLLIB_FTYPE_DATA) && ((is_broadcast_ether_addr(hdr->addr1)) || (compare_ether_addr(dev->dev_addr, hdr->addr1) == 0))) { + printk("===>RX data before decrypt\n"); + tmp_dump = true; + dump_buf(skb->data,skb->len); + } +#ifdef NOT_YET + hostap_update_rx_stats(local->ap, hdr, rx_stats); +#endif + +#ifndef _RTL8192_EXT_PATCH_ +#if defined (RTL8192S_WAPI_SUPPORT) + if (ieee->host_decrypt && (!ieee->wapiInfo.bWapiEnable)) +#else + if (ieee->host_decrypt) +#endif + { + int idx = 0; + if (skb->len >= hdrlen + 3) + idx = skb->data[hdrlen + 3] >> 6; + crypt = ieee->crypt[idx]; +#ifdef NOT_YET + sta = NULL; + + /* Use station specific key to override default keys if the + * receiver address is a unicast address ("individual RA"). If + * bcrx_sta_key parameter is set, station specific key is used + * even with broad/multicast targets (this is against IEEE + * 802.11, but makes it easier to use different keys with + * stations that do not support WEP key mapping). */ + + if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) + (void) hostap_handle_sta_crypto(local, hdr, &crypt, + &sta); +#endif + + /* allow NULL decrypt to indicate an station specific override + * for default encryption */ + if (crypt && (crypt->ops == NULL || + crypt->ops->decrypt_mpdu == NULL)) + crypt = NULL; + + if (!crypt && (fc & RTLLIB_FCTL_WEP)) { + /* This seems to be triggered by some (multicast?) + * frames from other than current BSS, so just drop the + * frames silently instead of filling system log with + * these reports. */ + RTLLIB_DEBUG_DROP("Decryption failed (not set)" + " (SA=" MAC_FMT ")\n", + MAC_ARG(hdr->addr2)); + ieee->ieee_stats.rx_discards_undecryptable++; + goto rx_dropped; + } + } +#endif + + if (skb->len < RTLLIB_DATA_HDR3_LEN) + goto rx_dropped; + +#ifdef _RTL8192_EXT_PATCH_ + if( (ieee->pHTInfo->bCurRxReorderEnable == false) || + !ieee->current_network.qos_data.active|| + !IsDataFrame(skb->data) || + IsLegacyDataFrame(skb->data) || + multicast) { + if (!multicast) { + if (is_duplicate_packet(ieee, hdr)){ + goto rx_dropped; + } + } + } +#else + if( (ieee->pHTInfo->bCurRxReorderEnable == false) || + !ieee->current_network.qos_data.active || + !IsDataFrame(skb->data) || + IsLegacyDataFrame(skb->data)) { + if(!((type == RTLLIB_FTYPE_MGMT) && (stype == RTLLIB_STYPE_BEACON))){ + if (is_duplicate_packet(ieee, hdr)){ + goto rx_dropped; + } + } + } +#endif + else { + PRX_TS_RECORD pRxTS = NULL; + if (GetTs(ieee, (PTS_COMMON_INFO*) &pRxTS, hdr->addr2, + (u8)Frame_QoSTID((u8*)(skb->data)), RX_DIR, true)) { + if ((fc & (1<<11)) && (frag == pRxTS->RxLastFragNum) && + (WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum)) { + goto rx_dropped; + } else { + pRxTS->RxLastFragNum = frag; + pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc); + } + } else { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!%s(): No TS!! Skip the check!!\n",__FUNCTION__); + goto rx_dropped; + } + } +#ifdef _RTL8192_EXT_PATCH_ + if((ieee->iw_mode == IW_MODE_MESH) && ieee->ext_patch_rtllib_rx_mgt_update_expire) + ieee->ext_patch_rtllib_rx_mgt_update_expire( ieee, skb ); +#endif + if (type == RTLLIB_FTYPE_MGMT) { + if (bToOtherSTA){ + goto rx_dropped; + } + if (rtllib_rx_frame_mgmt(ieee, skb, rx_stats, type, stype)) + goto rx_dropped; + else + goto rx_exit; + } + if (type == RTLLIB_FTYPE_CTL) { + goto rx_dropped; + } +#if defined (RTL8192S_WAPI_SUPPORT) + if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable){ + wapiDectResult = SecIsWAIPacket(ieee, skb); + if(wapiDectResult !=0){ + if(memcmp(&ieee->wapiInfo.wapiSeqnumAndFragNum,&sc,2)) + WapiHandleRecvPacket(ieee, skb, wapiDectResult); + memcpy(&ieee->wapiInfo.wapiSeqnumAndFragNum,&sc,2); + dev_kfree_skb_any(skb); + goto rx_exit; + } + } +#endif + /* Data frame - extract src/dst addresses */ + switch (fc & (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) { + case RTLLIB_FCTL_FROMDS: + memcpy(dst, hdr->addr1, ETH_ALEN); + memcpy(src, hdr->addr3, ETH_ALEN); + memcpy(bssid, hdr->addr2, ETH_ALEN); + break; + case RTLLIB_FCTL_TODS: + memcpy(dst, hdr->addr3, ETH_ALEN); + memcpy(src, hdr->addr2, ETH_ALEN); + memcpy(bssid, hdr->addr1, ETH_ALEN); + break; + case RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS: + if (skb->len < RTLLIB_DATA_HDR4_LEN) + goto rx_dropped; + memcpy(dst, hdr->addr3, ETH_ALEN); + memcpy(src, hdr->addr4, ETH_ALEN); +#ifdef _RTL8192_EXT_PATCH_ + memcpy(bssid, ieee->current_mesh_network.bssid, ETH_ALEN); +#else + memcpy(bssid, ieee->current_network.bssid, ETH_ALEN); +#endif + break; + case 0: + memcpy(dst, hdr->addr1, ETH_ALEN); + memcpy(src, hdr->addr2, ETH_ALEN); + memcpy(bssid, hdr->addr3, ETH_ALEN); + break; + } + + /* Filter frames from different BSS */ + if ((type != RTLLIB_FTYPE_CTL) && ((fc & RTLLIB_FCTL_DSTODS) != RTLLIB_FCTL_DSTODS) + && (compare_ether_addr(ieee->current_network.bssid, bssid) != 0) && memcmp(ieee->current_network.bssid, zero_addr, ETH_ALEN)) { + goto rx_dropped; + } + + /* Filter packets sent by an STA that will be forwarded by AP */ + if ( ieee->IntelPromiscuousModeInfo.bPromiscuousOn && + ieee->IntelPromiscuousModeInfo.bFilterSourceStationFrame ) { + if ((fc & RTLLIB_FCTL_TODS) && !(fc & RTLLIB_FCTL_FROMDS) && + (compare_ether_addr(dst, ieee->current_network.bssid) != 0) && + (compare_ether_addr(bssid, ieee->current_network.bssid) == 0)) { + goto rx_dropped; + } + } + +#ifdef NOT_YET + if (hostap_rx_frame_wds(ieee, hdr, fc, &wds)) + goto rx_dropped; + if (wds) { + skb->dev = dev = wds; + stats = hostap_get_stats(dev); + } + + if (ieee->iw_mode == IW_MODE_MASTER && !wds && + (fc & (RTLLIB_FCTL_TODS | RTLLIB_FCTL_FROMDS)) == RTLLIB_FCTL_FROMDS && + ieee->stadev && + memcmp(hdr->addr2, ieee->assoc_ap_addr, ETH_ALEN) == 0) { + /* Frame from BSSID of the AP for which we are a client */ + skb->dev = dev = ieee->stadev; + stats = hostap_get_stats(dev); + from_assoc_ap = 1; + } +#endif + + dev->last_rx = jiffies; + +#ifdef NOT_YET + if ((ieee->iw_mode == IW_MODE_MASTER || + ieee->iw_mode == IW_MODE_REPEAT) && + !from_assoc_ap) { + switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats, + wds != NULL)) { + case AP_RX_CONTINUE_NOT_AUTHORIZED: + frame_authorized = 0; + break; + case AP_RX_CONTINUE: + frame_authorized = 1; + break; + case AP_RX_DROP: + goto rx_dropped; + case AP_RX_EXIT: + goto rx_exit; + } + } +#endif + /* Nullfunc frames may have PS-bit set, so they must be passed to + * hostap_handle_sta_rx() before being dropped here. */ + if (stype != RTLLIB_STYPE_DATA && + stype != RTLLIB_STYPE_DATA_CFACK && + stype != RTLLIB_STYPE_DATA_CFPOLL && + stype != RTLLIB_STYPE_DATA_CFACKPOLL&& + stype != RTLLIB_STYPE_QOS_DATA + ) { + if (stype != RTLLIB_STYPE_NULLFUNC) + RTLLIB_DEBUG_DROP( + "RX: dropped data frame " + "with no data (type=0x%02x, " + "subtype=0x%02x, len=%d)\n", + type, stype, skb->len); + goto rx_dropped; + } + + if(skb->len == hdrlen){ + goto rx_dropped; + } + +#ifdef _RTL8192_EXT_PATCH_ + if(ieee->iw_mode == IW_MODE_MESH) { + /* check whether it exists the mesh entry for data packet */ + if(ieee->ext_patch_rtllib_is_mesh&&\ + (false ==ieee->ext_patch_rtllib_is_mesh(ieee,hdr->addr2))) { + if(ieee->only_mesh) { + goto rx_dropped; + } else if(memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) { + goto rx_dropped; + } + } + } else +#endif + { +#if 0 + /* check bssid under none mesh mode */ + if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) { + goto rx_dropped; + } +#endif + /* network filter more precisely */ + switch (ieee->iw_mode) { + case IW_MODE_ADHOC: + /* packets from our adapter are dropped (echo) */ + if (!memcmp(hdr->addr2, dev->dev_addr, ETH_ALEN)) + goto rx_dropped; + + /* {broad,multi}cast packets to our BSSID go through */ + if (is_multicast_ether_addr(hdr->addr1)) { + if(!memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN)) + break; + else + goto rx_dropped; + } + + /* packets not to our adapter, just discard it */ + if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) { + if (bToOtherSTA) + break; + else + goto rx_dropped; + } + + break; + + case IW_MODE_INFRA: + /* packets from our adapter are dropped (echo) */ + if (!memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN)) + goto rx_dropped; + + /* {broad,multi}cast packets to our BSS go through */ + if (is_multicast_ether_addr(hdr->addr1)) { + if (!memcmp(hdr->addr2, ieee->current_network.bssid, ETH_ALEN)) { + break; + } else { + goto rx_dropped; + } + } + + /* packets to our adapter go through */ + if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) { + if (bToOtherSTA) + break; + else + goto rx_dropped; + } + + break; + } + + + } + +#ifdef ENABLE_LPS + if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->sta_sleep == LPS_IS_SLEEP) + && (ieee->polling)) { + if (WLAN_FC_MORE_DATA(fc)) { + /* more data bit is set, let's request a new frame from the AP */ + rtllib_sta_ps_send_pspoll_frame(ieee); + } else { + ieee->polling = false; + } + } +#endif + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + if(ieee->iw_mode == IW_MODE_ADHOC){ + psta = GetStaInfo(ieee, src); + if(NULL != psta) + psta->LastActiveTime = jiffies; + } +#endif + /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ +#ifdef _RTL8192_EXT_PATCH_ +#if defined (RTL8192S_WAPI_SUPPORT) + if (ieee->host_decrypt && (!ieee->wapiInfo.bWapiEnable)) +#else + if (ieee->host_decrypt) +#endif + { + + int idx = 0; + if (skb->len >= hdrlen + 3) + idx = skb->data[hdrlen + 3] >> 6; + if (ieee->iw_mode == IW_MODE_MESH) + { + if (ieee->mesh_sec_type == 1) { + if(ieee->mesh_security_setting==1 ||ieee->mesh_security_setting==3) + { + bool find_crypt = false; + i = rtllib_find_MP(ieee, hdr->addr2, 0); + if(is_multicast_ether_addr(((struct rtllib_hdr_3addr*)skb->data)->addr1) || is_broadcast_ether_addr(((struct rtllib_hdr_3addr*)skb->data)->addr1)) + { + if(ieee->only_mesh){ + if(i != -1){ + i=0; + }else{ + printk("err find crypt\n"); + goto rx_dropped; + } + }else{ + if(i != -1){ + i=0; + }else{ + find_crypt = true; + crypt = ieee->sta_crypt[idx]; + } + } + }else{ + if(ieee->only_mesh){ + if (i != -1){ + }else{ + printk("err find crypt\n"); + goto rx_dropped; + } + }else{ + if (i != -1){ + }else{ + find_crypt = true; + crypt = ieee->sta_crypt[idx]; + } + } + } + if(find_crypt == false){ + if(ieee->cryptlist[i] == NULL) + goto rx_dropped; + else + crypt = ieee->cryptlist[i]->crypt[idx]; + } + } + } + else { + crypt = ieee->cryptlist[0]->crypt[idx]; + if(crypt) + { + int i = rtllib_find_MP(ieee, hdr->addr2, 0); + if(ieee->only_mesh) + { + if (i == -1) + { + printk("error find entry in entry list\n"); + goto rx_dropped; + } + if (ieee->cryptlist[i]&&ieee->cryptlist[i]->crypt[idx]) + crypt = ieee->cryptlist[i]->crypt[idx]; + + else + crypt = NULL; + } + else + { + if(i != -1) + { + if (ieee->cryptlist[i]&&ieee->cryptlist[i]->crypt[idx]) + crypt = ieee->cryptlist[i]->crypt[idx]; + else + crypt = NULL; + } + else + crypt = ieee->sta_crypt[idx]; + + } + } + else + { + if(!ieee->ext_patch_rtllib_is_mesh(ieee,hdr->addr2)) + crypt = ieee->sta_crypt[idx]; + } + } + } + else + crypt = ieee->sta_crypt[idx]; +#ifdef NOT_YET + sta = NULL; + + /* Use station specific key to override default keys if the + * receiver address is a unicast address ("individual RA"). If + * bcrx_sta_key parameter is set, station specific key is used + * even with broad/multicast targets (this is against IEEE + * 802.11, but makes it easier to use different keys with + * stations that do not support WEP key mapping). */ + + if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) + (void) hostap_handle_sta_crypto(local, hdr, &crypt, + &sta); +#endif + + /* allow NULL decrypt to indicate an station specific override + * for default encryption */ + if (crypt && (crypt->ops == NULL || + crypt->ops->decrypt_mpdu == NULL)) + crypt = NULL; + + if (!crypt && (fc & RTLLIB_FCTL_WEP)) { + /* This seems to be triggered by some (multicast?) + * frames from other than current BSS, so just drop the + * frames silently instead of filling system log with + * these reports. */ + RTLLIB_DEBUG_DROP("Decryption failed (not set)" + " (SA=" MAC_FMT ")\n", + MAC_ARG(hdr->addr2)); + ieee->ieee_stats.rx_discards_undecryptable++; + goto rx_dropped; + } + } +#endif + if((!rx_stats->Decrypted)){ + ieee->need_sw_enc = 1; + } + + if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) && + ((keyidx = rtllib_rx_frame_decrypt(ieee, skb, crypt)) < 0) +#if defined (RTL8192S_WAPI_SUPPORT) + && (!ieee->wapiInfo.bWapiEnable) +#endif + ) + { + printk("decrypt frame error\n"); + goto rx_dropped; + } + if (tmp_dump) { + printk("************after decrypt\n"); + dump_buf(skb->data,skb->len); + } +#if defined (RTL8192S_WAPI_SUPPORT) + if(ieee->wapiInfo.bWapiEnable){ + if(ieee->pairwise_key_type == KEY_TYPE_SMS4){ + if(false == SecSWSMS4Decryption(ieee, skb, rx_stats)){ + WAPI_TRACE(WAPI_ERR, "%s():SMS4 decrypt frame error\n",__FUNCTION__); + goto rx_dropped; + } + } + } +#endif + hdr = (struct rtllib_hdr_4addr *) skb->data; + + /* skb: hdr + (possibly fragmented) plaintext payload */ + if ((frag != 0 || (fc & RTLLIB_FCTL_MOREFRAGS))) { + int flen; + struct sk_buff *frag_skb = rtllib_frag_cache_get(ieee, hdr); + RTLLIB_DEBUG_FRAG("Rx Fragment received (%u)\n", frag); + + if (!frag_skb) { + RTLLIB_DEBUG(RTLLIB_DL_RX | RTLLIB_DL_FRAG, + "Rx cannot get skb from fragment " + "cache (morefrag=%d seq=%u frag=%u)\n", + (fc & RTLLIB_FCTL_MOREFRAGS) != 0, + WLAN_GET_SEQ_SEQ(sc), frag); + goto rx_dropped; + } + flen = skb->len; + if (frag != 0) + flen -= hdrlen; + + if (frag_skb->tail + flen > frag_skb->end) { + printk(KERN_WARNING "%s: host decrypted and " + "reassembled frame did not fit skb\n", + dev->name); + rtllib_frag_cache_invalidate(ieee, hdr); + goto rx_dropped; + } + + if (frag == 0) { + /* copy first fragment (including full headers) into + * beginning of the fragment cache skb */ + memcpy(skb_put(frag_skb, flen), skb->data, flen); + } else { + /* append frame payload to the end of the fragment + * cache skb */ + memcpy(skb_put(frag_skb, flen), skb->data + hdrlen, + flen); + } + dev_kfree_skb_any(skb); + skb = NULL; + + if (fc & RTLLIB_FCTL_MOREFRAGS) { + /* more fragments expected - leave the skb in fragment + * cache for now; it will be delivered to upper layers + * after all fragments have been received */ + goto rx_exit; + } + + /* this was the last fragment and the frame will be + * delivered, so remove skb from fragment cache */ + skb = frag_skb; + hdr = (struct rtllib_hdr_4addr *) skb->data; + rtllib_frag_cache_invalidate(ieee, hdr); + } + + /* skb: hdr + (possible reassembled) full MSDU payload; possibly still + * encrypted/authenticated */ + if (ieee->host_decrypt && (fc & RTLLIB_FCTL_WEP) && +#if defined (RTL8192S_WAPI_SUPPORT) + (!ieee->wapiInfo.bWapiEnable) && +#endif + rtllib_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) + { + printk("==>decrypt msdu error\n"); + goto rx_dropped; + } + + ieee->LinkDetectInfo.NumRecvDataInPeriod++; + ieee->LinkDetectInfo.NumRxOkInPeriod++; + + hdr = (struct rtllib_hdr_4addr *) skb->data; + if((!is_multicast_ether_addr(hdr->addr1)) && (!is_broadcast_ether_addr(hdr->addr1))) + unicast_packet = true; + if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep) { + if (/*ieee->ieee802_1x &&*/ + rtllib_is_eapol_frame(ieee, skb, hdrlen)) { + +#ifdef CONFIG_RTLLIB_DEBUG + /* pass unencrypted EAPOL frames even if encryption is + * configured */ + struct eapol *eap = (struct eapol *)(skb->data + + 24); + RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", + eap_get_type(eap->type)); +#endif + } else { + RTLLIB_DEBUG_DROP( + "encryption configured, but RX " + "frame not encrypted (SA=" MAC_FMT ")\n", + MAC_ARG(hdr->addr2)); + goto rx_dropped; + } + } + +#ifdef CONFIG_RTLLIB_DEBUG + if (crypt && !(fc & RTLLIB_FCTL_WEP) && + rtllib_is_eapol_frame(ieee, skb, hdrlen)) { + struct eapol *eap = (struct eapol *)(skb->data + + 24); + RTLLIB_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", + eap_get_type(eap->type)); + } +#endif + + if (crypt && !(fc & RTLLIB_FCTL_WEP) && !ieee->open_wep && + !rtllib_is_eapol_frame(ieee, skb, hdrlen)) { + RTLLIB_DEBUG_DROP( + "dropped unencrypted RX data " + "frame from " MAC_FMT + " (drop_unencrypted=1)\n", + MAC_ARG(hdr->addr2)); + goto rx_dropped; + } +/* + if(rtllib_is_eapol_frame(ieee, skb, hdrlen)) { + printk(KERN_WARNING "RX: IEEE802.1X EAPOL frame!\n"); + } +*/ + if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data) + && !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1)) + { + TID = Frame_QoSTID(skb->data); + SeqNum = WLAN_GET_SEQ_SEQ(sc); + GetTs(ieee,(PTS_COMMON_INFO*) &pTS,hdr->addr2,TID,RX_DIR,true); + if(TID !=0 && TID !=3){ + ieee->bis_any_nonbepkts = true; + } + } +#ifdef _RTL8192_EXT_PATCH_ + if((fc & (WIFI_MESH_TYPE | RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) + == (WIFI_MESH_TYPE | RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) + { + if(ieee->iw_mode == IW_MODE_MESH){ + rxb = (struct rtllib_rxb*)kmalloc(sizeof(struct rtllib_rxb),GFP_ATOMIC); + if(rxb == NULL) + { + printk("%s(): kmalloc rxb error\n",__FUNCTION__); + goto rx_dropped; + } + memset(rxb, 0, sizeof(struct rtllib_rxb)); + if(msh_parse_subframe(ieee, skb, rxb)==0){ + /* only to free rxb, and not submit the packets to upper layer */ + for(i =0; i < rxb->nr_subframes; i++) { + if(rxb->subframes[i]) + dev_kfree_skb(rxb->subframes[i]); + } + kfree(rxb); + rxb = NULL; + goto rx_dropped; + } + ret = msh_rx_process_dataframe(ieee,rxb,rx_stats); + if(ret < 0) { + for(i =0; i < rxb->nr_subframes; i++) { + if(rxb->subframes[i]) + dev_kfree_skb(rxb->subframes[i]); + } + kfree(rxb); + rxb = NULL; + goto rx_dropped; + }else{ + kfree(rxb); + rxb = NULL; + } + }else + goto rx_dropped; + }else{ +#endif + /* skb: hdr + (possible reassembled) full plaintext payload */ + payload = skb->data + hdrlen; + rxb = (struct rtllib_rxb*)kmalloc(sizeof(struct rtllib_rxb),GFP_ATOMIC); + if(rxb == NULL) + { + RTLLIB_DEBUG(RTLLIB_DL_ERR,"%s(): kmalloc rxb error\n",__FUNCTION__); + goto rx_dropped; + } + /* to parse amsdu packets */ + /* qos data packets & reserved bit is 1 */ + if(parse_subframe(ieee,skb,rx_stats,rxb,src,dst) == 0) { + /* only to free rxb, and not submit the packets to upper layer */ + for(i =0; i < rxb->nr_subframes; i++) { + dev_kfree_skb(rxb->subframes[i]); + } + kfree(rxb); + rxb = NULL; + goto rx_dropped; + } +#ifdef RTL8192S_WAPI_SUPPORT + if(ieee->wapiInfo.bWapiEnable){ + if(rxb){ + rxb->UserPriority = TID; + memcpy(rxb->WapiTempPN, rx_stats->WapiTempPN, 16); + memcpy(rxb->WapiSrcAddr, rx_stats->WapiSrcAddr, 6); + rxb->bWapiCheckPNInDecrypt = rx_stats->bWapiCheckPNInDecrypt; + } + } +#endif +#if !defined(RTL8192SU) && !defined(RTL8192U) +#ifdef ENABLE_LPS + if(unicast_packet) + { + if (type == RTLLIB_FTYPE_DATA) + { + + if(ieee->bIsAggregateFrame) + ieee->LinkDetectInfo.NumRxUnicastOkInPeriod+=rxb->nr_subframes; + else + ieee->LinkDetectInfo.NumRxUnicastOkInPeriod++; + + if((ieee->state == RTLLIB_LINKED) /*&& !MgntInitAdapterInProgress(pMgntInfo)*/) + { + if( ((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) || + (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) ) + { + if(ieee->LeisurePSLeave) + ieee->LeisurePSLeave(dev); + } + } + } + } +#endif +#endif + ieee->last_rx_ps_time = jiffies; + if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL || bToOtherSTA ){ + for(i = 0; inr_subframes; i++) { + struct sk_buff *sub_skb = rxb->subframes[i]; + + if (sub_skb) { + /* convert hdr + possible LLC headers into Ethernet header */ + ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7]; + if (sub_skb->len >= 8 && + ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 && + ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || + memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) { + /* remove RFC1042 or Bridge-Tunnel encapsulation and + * replace EtherType */ + skb_pull(sub_skb, SNAP_SIZE); + memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN); + memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN); + } else { + u16 len; + /* Leave Ethernet header part of hdr and full payload */ + len = htons(sub_skb->len); + memcpy(skb_push(sub_skb, 2), &len, 2); + memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN); + memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN); + } + + stats->rx_packets++; + stats->rx_bytes += sub_skb->len; + + if(is_multicast_ether_addr(dst)) { + stats->multicast++; + } + + /* Indicat the packets to upper layer */ + memset(sub_skb->cb, 0, sizeof(sub_skb->cb)); +#ifdef _RTL8192_EXT_PATCH_ + sub_skb->protocol = eth_type_trans(sub_skb, sub_skb->dev); +#else + sub_skb->protocol = eth_type_trans(sub_skb, dev); + sub_skb->dev = dev; +#endif +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) + sub_skb->dev->stats.rx_packets++; + sub_skb->dev->stats.rx_bytes += sub_skb->len; +#endif +#ifdef TCP_CSUM_OFFLOAD_RX + if ( rx_stats->tcp_csum_valid) + sub_skb->ip_summed = CHECKSUM_UNNECESSARY; + else + sub_skb->ip_summed = CHECKSUM_NONE; +#else + sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ +#endif + + netif_rx(sub_skb); + } + } + kfree(rxb); + rxb = NULL; + + } + else + { + RTLLIB_DEBUG(RTLLIB_DL_REORDER,"%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n",__FUNCTION__); +#ifdef TCP_CSUM_OFFLOAD_RX + rxb->tcp_csum_valid = rx_stats->tcp_csum_valid; +#endif + RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum); + } +#ifdef _RTL8192_EXT_PATCH_ + } +#endif +#ifndef JOHN_NOCPY + dev_kfree_skb(skb); +#endif + + rx_exit: +#ifdef NOT_YET + if (sta) + hostap_handle_sta_release(sta); +#endif + return 1; + + rx_dropped: + if (rxb != NULL) + { + kfree(rxb); + rxb = NULL; + } + stats->rx_dropped++; + + /* Returning 0 indicates to caller that we have not handled the SKB-- + * so it is still allocated and can be used again by underlying + * hardware as a DMA target */ + return 0; +} +#endif + +#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 + +static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; + +/* +* Make ther structure we read from the beacon packet has +* the right values +*/ +static int rtllib_verify_qos_info(struct rtllib_qos_information_element + *info_element, int sub_type) +{ + + if (info_element->qui_subtype != sub_type) + return -1; + if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN)) + return -1; + if (info_element->qui_type != QOS_OUI_TYPE) + return -1; + if (info_element->version != QOS_VERSION_1) + return -1; + + return 0; +} + + +/* + * Parse a QoS parameter element + */ +static int rtllib_read_qos_param_element(struct rtllib_qos_parameter_info + *element_param, struct rtllib_info_element + *info_element) +{ + int ret = 0; + u16 size = sizeof(struct rtllib_qos_parameter_info) - 2; + + if ((info_element == NULL) || (element_param == NULL)) + return -1; + + if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) { + memcpy(element_param->info_element.qui, info_element->data, + info_element->len); + element_param->info_element.elementID = info_element->id; + element_param->info_element.length = info_element->len; + } else + ret = -1; + if (ret == 0) + ret = rtllib_verify_qos_info(&element_param->info_element, + QOS_OUI_PARAM_SUB_TYPE); + return ret; +} + +/* + * Parse a QoS information element + */ +static int rtllib_read_qos_info_element(struct + rtllib_qos_information_element + *element_info, struct rtllib_info_element + *info_element) +{ + int ret = 0; + u16 size = sizeof(struct rtllib_qos_information_element) - 2; + + if (element_info == NULL) + return -1; + if (info_element == NULL) + return -1; + + if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) { + memcpy(element_info->qui, info_element->data, + info_element->len); + element_info->elementID = info_element->id; + element_info->length = info_element->len; + } else + ret = -1; + + if (ret == 0) + ret = rtllib_verify_qos_info(element_info, + QOS_OUI_INFO_SUB_TYPE); + return ret; +} + + +/* + * Write QoS parameters from the ac parameters. + */ +static int rtllib_qos_convert_ac_to_parameters(struct rtllib_qos_parameter_info *param_elm, + struct rtllib_qos_data *qos_data) +{ + struct rtllib_qos_ac_parameter *ac_params; + struct rtllib_qos_parameters *qos_param = &(qos_data->parameters); + int rc = 0; + int i; + u8 aci; + u8 acm; + + qos_data->wmm_acm = 0; + for (i = 0; i < QOS_QUEUE_NUM; i++) { + ac_params = &(param_elm->ac_params_record[i]); + + aci = (ac_params->aci_aifsn & 0x60) >> 5; + acm = (ac_params->aci_aifsn & 0x10) >> 4; + + if(aci >= QOS_QUEUE_NUM) + continue; + switch (aci) { + case 1: + /* BIT(0) | BIT(3) */ + if (acm) + qos_data->wmm_acm |= (0x01<<0)|(0x01<<3); + break; + case 2: + /* BIT(4) | BIT(5) */ + if (acm) + qos_data->wmm_acm |= (0x01<<4)|(0x01<<5); + break; + case 3: + /* BIT(6) | BIT(7) */ + if (acm) + qos_data->wmm_acm |= (0x01<<6)|(0x01<<7); + break; + case 0: + default: + /* BIT(1) | BIT(2) */ + if (acm) + qos_data->wmm_acm |= (0x01<<1)|(0x01<<2); + break; + } + + qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f; + + /* WMM spec P.11: The minimum value for AIFSN shall be 2 */ + qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2:qos_param->aifs[aci]; + + qos_param->cw_min[aci] = ac_params->ecw_min_max & 0x0F; + + qos_param->cw_max[aci] = (ac_params->ecw_min_max & 0xF0) >> 4; + + qos_param->flag[aci] = + (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00; + qos_param->tx_op_limit[aci] = le16_to_cpu(ac_params->tx_op_limit); + } + return rc; +} + +/* + * we have a generic data element which it may contain QoS information or + * parameters element. check the information element length to decide + * which type to read + */ +static int rtllib_parse_qos_info_param_IE(struct rtllib_info_element + *info_element, + struct rtllib_network *network) +{ + int rc = 0; + struct rtllib_qos_information_element qos_info_element; + + rc = rtllib_read_qos_info_element(&qos_info_element, info_element); + + if (rc == 0) { + network->qos_data.param_count = qos_info_element.ac_info & 0x0F; + network->flags |= NETWORK_HAS_QOS_INFORMATION; + } else { + struct rtllib_qos_parameter_info param_element; + + rc = rtllib_read_qos_param_element(¶m_element, + info_element); + if (rc == 0) { + rtllib_qos_convert_ac_to_parameters(¶m_element, + &(network->qos_data)); + network->flags |= NETWORK_HAS_QOS_PARAMETERS; + network->qos_data.param_count = + param_element.info_element.ac_info & 0x0F; + } + } + + if (rc == 0) { + RTLLIB_DEBUG_QOS("QoS is supported\n"); + network->qos_data.supported = 1; + } + return rc; +} + +#ifdef CONFIG_RTLLIB_DEBUG +#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x + +static const char *get_info_element_string(u16 id) +{ + switch (id) { + MFIE_STRING(SSID); + MFIE_STRING(RATES); + MFIE_STRING(FH_SET); + MFIE_STRING(DS_SET); + MFIE_STRING(CF_SET); + MFIE_STRING(TIM); + MFIE_STRING(IBSS_SET); + MFIE_STRING(COUNTRY); + MFIE_STRING(HOP_PARAMS); + MFIE_STRING(HOP_TABLE); + MFIE_STRING(REQUEST); + MFIE_STRING(CHALLENGE); + MFIE_STRING(POWER_CONSTRAINT); + MFIE_STRING(POWER_CAPABILITY); + MFIE_STRING(TPC_REQUEST); + MFIE_STRING(TPC_REPORT); + MFIE_STRING(SUPP_CHANNELS); + MFIE_STRING(CSA); + MFIE_STRING(MEASURE_REQUEST); + MFIE_STRING(MEASURE_REPORT); + MFIE_STRING(QUIET); + MFIE_STRING(IBSS_DFS); + MFIE_STRING(RSN); + MFIE_STRING(RATES_EX); + MFIE_STRING(GENERIC); + MFIE_STRING(QOS_PARAMETER); + default: + return "UNKNOWN"; + } +} +#endif + +#ifdef ENABLE_DOT11D +static inline void rtllib_extract_country_ie( + struct rtllib_device *ieee, + struct rtllib_info_element *info_element, + struct rtllib_network *network, + u8 * addr2) +{ + if (IS_DOT11D_ENABLE(ieee)) { + if(info_element->len!= 0) { + memcpy(network->CountryIeBuf, info_element->data, info_element->len); + network->CountryIeLen = info_element->len; + + if(!IS_COUNTRY_IE_VALID(ieee)) + { + if((rtllib_act_scanning(ieee,false) == true) && (ieee->FirstIe_InScan == 1)) + printk("Received beacon ContryIE, SSID: <%s>\n",network->ssid); + Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data); + } + } + + if (IS_EQUAL_CIE_SRC(ieee, addr2)) { + UPDATE_CIE_WATCHDOG(ieee); + } + } + +} +#endif + +int rtllib_parse_info_param(struct rtllib_device *ieee, + struct rtllib_info_element *info_element, + u16 length, + struct rtllib_network *network, + struct rtllib_rx_stats *stats) +{ + u8 i; + short offset; + u16 tmp_htcap_len=0; + u16 tmp_htinfo_len=0; + u16 ht_realtek_agg_len=0; + u8 ht_realtek_agg_buf[MAX_IE_LEN]; +#ifdef CONFIG_RTLLIB_DEBUG + char rates_str[64]; + char *p; +#endif +#ifdef RTL8192S_WAPI_SUPPORT + u8 tmp_wapi_len = 0; +#endif + while (length >= sizeof(*info_element)) { + if (sizeof(*info_element) + info_element->len > length) { + RTLLIB_DEBUG_MGMT("Info elem: parse failed: " + "info_element->len + 2 > left : " + "info_element->len+2=%zd left=%d, id=%d.\n", + info_element->len + + sizeof(*info_element), + length, info_element->id); + /* We stop processing but don't return an error here + * because some misbehaviour APs break this rule. ie. + * Orinoco AP1000. */ + break; + } + + switch (info_element->id) { + case MFIE_TYPE_SSID: + if (rtllib_is_empty_essid(info_element->data, + info_element->len)) { + network->flags |= NETWORK_EMPTY_ESSID; + break; + } + + network->ssid_len = min(info_element->len, + (u8) IW_ESSID_MAX_SIZE); + memcpy(network->ssid, info_element->data, network->ssid_len); + if (network->ssid_len < IW_ESSID_MAX_SIZE) + memset(network->ssid + network->ssid_len, 0, + IW_ESSID_MAX_SIZE - network->ssid_len); + + RTLLIB_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n", + network->ssid, network->ssid_len); + break; + + case MFIE_TYPE_RATES: +#ifdef CONFIG_RTLLIB_DEBUG + p = rates_str; +#endif + network->rates_len = min(info_element->len, + MAX_RATES_LENGTH); + for (i = 0; i < network->rates_len; i++) { + network->rates[i] = info_element->data[i]; +#ifdef CONFIG_RTLLIB_DEBUG + p += snprintf(p, sizeof(rates_str) - + (p - rates_str), "%02X ", + network->rates[i]); +#endif + if (rtllib_is_ofdm_rate + (info_element->data[i])) { + network->flags |= NETWORK_HAS_OFDM; + if (info_element->data[i] & + RTLLIB_BASIC_RATE_MASK) + network->flags &= + ~NETWORK_HAS_CCK; + } + + if (rtllib_is_cck_rate + (info_element->data[i])) { + network->flags |= NETWORK_HAS_CCK; + } + } + + RTLLIB_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n", + rates_str, network->rates_len); + break; + + case MFIE_TYPE_RATES_EX: +#ifdef CONFIG_RTLLIB_DEBUG + p = rates_str; +#endif + network->rates_ex_len = min(info_element->len, + MAX_RATES_EX_LENGTH); + for (i = 0; i < network->rates_ex_len; i++) { + network->rates_ex[i] = info_element->data[i]; +#ifdef CONFIG_RTLLIB_DEBUG + p += snprintf(p, sizeof(rates_str) - + (p - rates_str), "%02X ", + network->rates[i]); +#endif + if (rtllib_is_ofdm_rate + (info_element->data[i])) { + network->flags |= NETWORK_HAS_OFDM; + if (info_element->data[i] & + RTLLIB_BASIC_RATE_MASK) + network->flags &= + ~NETWORK_HAS_CCK; + } + } + + RTLLIB_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n", + rates_str, network->rates_ex_len); + break; + + case MFIE_TYPE_DS_SET: + RTLLIB_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n", + info_element->data[0]); + network->channel = info_element->data[0]; + break; + + case MFIE_TYPE_FH_SET: + RTLLIB_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n"); + break; + + case MFIE_TYPE_CF_SET: + RTLLIB_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n"); + break; + + case MFIE_TYPE_TIM: + if(info_element->len < 4) + break; + + network->tim.tim_count = info_element->data[0]; + network->tim.tim_period = info_element->data[1]; + + network->dtim_period = info_element->data[1]; + if(ieee->state != RTLLIB_LINKED) + break; +#if 0 + network->last_dtim_sta_time[0] = stats->mac_time[0]; +#else + network->last_dtim_sta_time[0] = jiffies; +#endif + network->last_dtim_sta_time[1] = stats->mac_time[1]; + + network->dtim_data = RTLLIB_DTIM_VALID; + + + if(info_element->data[2] & 1) + network->dtim_data |= RTLLIB_DTIM_MBCAST; + +#if 1 + offset = (info_element->data[2] >> 1)*2; + + + if(ieee->assoc_id < 8*offset || + ieee->assoc_id > 8*(offset + info_element->len -3)) + + break; + + offset = (ieee->assoc_id / 8) - offset; + if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) + network->dtim_data |= RTLLIB_DTIM_UCAST; +#else + { + u16 numSta = 0; + u16 offset_byte = 0; + u16 offset_bit = 0; + + numSta = (info_element->data[2] &0xFE)*8; + + if(ieee->assoc_id < numSta || + ieee->assoc_id > (numSta + (info_element->len -3)*8)) + break; + + offset = ieee->assoc_id - numSta; + offset_byte = offset / 8; + offset_bit = offset % 8; + if(info_element->data[3+offset_byte] & (0x01<dtim_data |= RTLLIB_DTIM_UCAST; + } +#endif + + network->listen_interval = network->dtim_period; + break; + + case MFIE_TYPE_ERP: + network->erp_value = info_element->data[0]; + network->flags |= NETWORK_HAS_ERP_VALUE; + RTLLIB_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", + network->erp_value); + break; + case MFIE_TYPE_IBSS_SET: + network->atim_window = info_element->data[0]; + RTLLIB_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n", + network->atim_window); + break; + + case MFIE_TYPE_CHALLENGE: + RTLLIB_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n"); + break; + + case MFIE_TYPE_GENERIC: + RTLLIB_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n", + info_element->len); + if (!rtllib_parse_qos_info_param_IE(info_element, + network)) + break; + if (info_element->len >= 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x50 && + info_element->data[2] == 0xf2 && + info_element->data[3] == 0x01) { + network->wpa_ie_len = min(info_element->len + 2, + MAX_WPA_IE_LEN); + memcpy(network->wpa_ie, info_element, + network->wpa_ie_len); + break; + } +#ifdef THOMAS_TURBO + if (info_element->len == 7 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0xe0 && + info_element->data[2] == 0x4c && + info_element->data[3] == 0x01 && + info_element->data[4] == 0x02) { + network->Turbo_Enable = 1; + } +#endif + + if(tmp_htcap_len == 0){ + if(info_element->len >= 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x90 && + info_element->data[2] == 0x4c && + info_element->data[3] == 0x033){ + + tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN); + if(tmp_htcap_len != 0){ + network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; + network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\ + sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len; + memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen); + } + } + if(tmp_htcap_len != 0){ + network->bssht.bdSupportHT = true; + network->bssht.bdHT1R = ((((PHT_CAPABILITY_ELE)(network->bssht.bdHTCapBuf))->MCS[1]) == 0); + }else{ + network->bssht.bdSupportHT = false; + network->bssht.bdHT1R = false; + } + } + + + if(tmp_htinfo_len == 0){ + if(info_element->len >= 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x90 && + info_element->data[2] == 0x4c && + info_element->data[3] == 0x034){ + + tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN); + if(tmp_htinfo_len != 0){ + network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; + if(tmp_htinfo_len){ + network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\ + sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len; + memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen); + } + + } + + } + } + + if(ieee->aggregation){ + if(network->bssht.bdSupportHT){ + if(info_element->len >= 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0xe0 && + info_element->data[2] == 0x4c && + info_element->data[3] == 0x02){ + + ht_realtek_agg_len = min(info_element->len,(u8)MAX_IE_LEN); + memcpy(ht_realtek_agg_buf,info_element->data,info_element->len); + + } + if(ht_realtek_agg_len >= 5){ + network->realtek_cap_exit = true; + network->bssht.bdRT2RTAggregation = true; + + if((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02)) + network->bssht.bdRT2RTLongSlotTime = true; + + if((ht_realtek_agg_buf[4]==1) && (ht_realtek_agg_buf[5] & RT_HT_CAP_USE_92SE)) + { + network->bssht.RT2RT_HT_Mode |= RT_HT_CAP_USE_92SE; + } + } + } + if(ht_realtek_agg_len >= 5){ + if((ht_realtek_agg_buf[5] & RT_HT_CAP_USE_SOFTAP)) + network->bssht.RT2RT_HT_Mode |= RT_HT_CAP_USE_SOFTAP; + } + } + + { + if((info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x05 && + info_element->data[2] == 0xb5) || + (info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x0a && + info_element->data[2] == 0xf7) || + (info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x10 && + info_element->data[2] == 0x18)){ + + network->broadcom_cap_exist = true; + + } + } +#if 0 + if (tmp_htcap_len !=0) + { + u16 cap_ext = ((PHT_CAPABILITY_ELE)&info_element->data[0])->ExtHTCapInfo; + if ((cap_ext & 0x0c00) == 0x0c00) + { + network->ralink_cap_exist = true; + } + } +#endif + if(info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x0c && + info_element->data[2] == 0x43) + { + network->ralink_cap_exist = true; + } + if((info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x03 && + info_element->data[2] == 0x7f) || + (info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x13 && + info_element->data[2] == 0x74)) + { + network->atheros_cap_exist = true; + } + + if ((info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x50 && + info_element->data[2] == 0x43) ) + { + network->marvell_cap_exist = true; + } + if(info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x40 && + info_element->data[2] == 0x96) + { + network->cisco_cap_exist = true; + } + + + if(info_element->len >= 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x0a && + info_element->data[2] == 0xf5) + { + network->airgo_cap_exist = true; + } + + if(info_element->len > 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x40 && + info_element->data[2] == 0x96 && + info_element->data[3] == 0x01) + { + if(info_element->len == 6) + { + memcpy(network->CcxRmState, &info_element[4], 2); + if(network->CcxRmState[0] != 0) + { + network->bCcxRmEnable = true; + } + else + network->bCcxRmEnable = false; + network->MBssidMask = network->CcxRmState[1] & 0x07; + if(network->MBssidMask != 0) + { + network->bMBssidValid = true; + network->MBssidMask = 0xff << (network->MBssidMask); + memcpy(network->MBssid, network->bssid, ETH_ALEN); + network->MBssid[5] &= network->MBssidMask; + } + else + { + network->bMBssidValid = false; + } + } + else + { + network->bCcxRmEnable = false; + } + } + if(info_element->len > 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x40 && + info_element->data[2] == 0x96 && + info_element->data[3] == 0x03) + { + if(info_element->len == 5) + { + network->bWithCcxVerNum = true; + network->BssCcxVerNumber = info_element->data[4]; + } + else + { + network->bWithCcxVerNum = false; + network->BssCcxVerNumber = 0; + } + } + if(info_element->len > 4 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x50 && + info_element->data[2] == 0xf2 && + info_element->data[3] == 0x04) + { + RTLLIB_DEBUG_MGMT("MFIE_TYPE_WZC: %d bytes\n", + info_element->len); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + network->wzc_ie_len = min(info_element->len+2, + MAX_WZC_IE_LEN); + memcpy(network->wzc_ie, info_element, + network->wzc_ie_len); +#endif + } +#ifdef _RTL8192_EXT_PATCH_ +#ifdef COMPATIBLE_WITH_RALINK_MESH + if(info_element->len > 3 && + info_element->data[0] == 0x00 && + info_element->data[1] == 0x0F && + info_element->data[2] == 0xAC) + { + network->hostname_len = info_element->len - 3; + memcpy(network->hostname, (info_element->data+3), network->hostname_len); + } +#else + if(info_element->len > 4 && + info_element->data[0] == 0x48 && + info_element->data[1] == 0x4F && + info_element->data[2] == 0x53 && + info_element->data[3] == 0x54) + { + network->hostname_len = info_element->len - 4; + memcpy(network->hostname, (info_element->data+4), network->hostname_len); + } +#endif +#endif + break; + + case MFIE_TYPE_RSN: + RTLLIB_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n", + info_element->len); + network->rsn_ie_len = min(info_element->len + 2, + MAX_WPA_IE_LEN); + memcpy(network->rsn_ie, info_element, + network->rsn_ie_len); + break; + + case MFIE_TYPE_HT_CAP: + RTLLIB_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n", + info_element->len); + tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN); + if(tmp_htcap_len != 0){ + network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC; + network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\ + sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len; + memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen); + + network->bssht.bdSupportHT = true; + network->bssht.bdHT1R = ((((PHT_CAPABILITY_ELE)(network->bssht.bdHTCapBuf))->MCS[1]) == 0); + + network->bssht.bdBandWidth = (HT_CHANNEL_WIDTH)(((PHT_CAPABILITY_ELE)(network->bssht.bdHTCapBuf))->ChlWidth); + } + else{ + network->bssht.bdSupportHT = false; + network->bssht.bdHT1R = false; + network->bssht.bdBandWidth = HT_CHANNEL_WIDTH_20 ; + } + break; + + + case MFIE_TYPE_HT_INFO: + RTLLIB_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n", + info_element->len); + tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN); + if(tmp_htinfo_len){ + network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE; + network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\ + sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len; + memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen); + } + break; + + case MFIE_TYPE_AIRONET: + RTLLIB_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n", + info_element->len); + if(info_element->len >IE_CISCO_FLAG_POSITION) + { + network->bWithAironetIE = true; + + if( (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_MIC) || + (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_PK) ) + { + network->bCkipSupported = true; + } + else + { + network->bCkipSupported = false; + } + } + else + { + network->bWithAironetIE = false; + network->bCkipSupported = false; + } + break; + case MFIE_TYPE_QOS_PARAMETER: + printk(KERN_ERR + "QoS Error need to parse QOS_PARAMETER IE\n"); + break; + +#ifdef ENABLE_DOT11D + case MFIE_TYPE_COUNTRY: + RTLLIB_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n", + info_element->len); + rtllib_extract_country_ie(ieee, info_element, network, network->bssid); + break; +#endif +#ifdef _RTL8192_EXT_PATCH_ + case MFIE_TYPE_MESH_ID: + network->mesh_id_len = min(info_element->len, (u8)MAX_MESH_ID_LEN); + memcpy(network->mesh_id, info_element->data, network->mesh_id_len); + if (network->mesh_id_len < MAX_MESH_ID_LEN) { + memset(network->mesh_id + network->mesh_id_len, 0, + MAX_MESH_ID_LEN - network->mesh_id_len); + } + RTLLIB_DEBUG_MGMT("MFIE_TYPE_MESH_ID: '%s'len=%d.\n", network->mesh_id, + network->mesh_id_len); + break; + + case MFIE_TYPE_MESH_CONFIGURATION: + network->mesh_config_len = min(info_element->len, (u8)MESH_CONF_TOTAL_LEN); + memcpy(network->mesh_config.path_proto_id, info_element->data + 1, 4); + memcpy(network->mesh_config.path_metric_id, info_element->data + 5, 4); + memcpy(network->mesh_config.congest_ctl_mode, info_element->data + 9, 4); + memcpy(network->mesh_config.mesh_capability, info_element->data + 17, 2); + break; +#endif +/* TODO */ +#if 0 + /* 802.11h */ + case MFIE_TYPE_POWER_CONSTRAINT: + network->power_constraint = info_element->data[0]; + network->flags |= NETWORK_HAS_POWER_CONSTRAINT; + break; + + case MFIE_TYPE_CSA: + network->power_constraint = info_element->data[0]; + network->flags |= NETWORK_HAS_CSA; + break; + + case MFIE_TYPE_QUIET: + network->quiet.count = info_element->data[0]; + network->quiet.period = info_element->data[1]; + network->quiet.duration = info_element->data[2]; + network->quiet.offset = info_element->data[3]; + network->flags |= NETWORK_HAS_QUIET; + break; + + case MFIE_TYPE_IBSS_DFS: + if (network->ibss_dfs) + break; + network->ibss_dfs = kmemdup(info_element->data, + info_element->len, + GFP_ATOMIC); + if (!network->ibss_dfs) + return 1; + network->flags |= NETWORK_HAS_IBSS_DFS; + break; + + case MFIE_TYPE_TPC_REPORT: + network->tpc_report.transmit_power = + info_element->data[0]; + network->tpc_report.link_margin = info_element->data[1]; + network->flags |= NETWORK_HAS_TPC_REPORT; + break; +#endif +#ifdef RTL8192S_WAPI_SUPPORT + case MFIE_TYPE_WAPI: + RTLLIB_DEBUG_MGMT("MFIE_TYPE_WAPI: %d bytes\n", info_element->len); + tmp_wapi_len = min(info_element->len,(u8)MAX_WAPI_IE_LEN); + if(tmp_wapi_len){ + network->wapi_ie_len = tmp_wapi_len; + memcpy(network->wapi_ie,info_element->data,network->wapi_ie_len); + } + break; +#endif + default: + RTLLIB_DEBUG_MGMT + ("Unsupported info element: %s (%d)\n", + get_info_element_string(info_element->id), + info_element->id); + break; + } + + length -= sizeof(*info_element) + info_element->len; + info_element = + (struct rtllib_info_element *)&info_element-> + data[info_element->len]; + } + + if(!network->atheros_cap_exist && !network->broadcom_cap_exist && + !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation) + { + network->unknown_cap_exist = true; + } + else + { + network->unknown_cap_exist = false; + } + return 0; +} + +static inline u8 rtllib_SignalStrengthTranslate( + u8 CurrSS + ) +{ + u8 RetSS; + + if(CurrSS >= 71 && CurrSS <= 100) + { + RetSS = 90 + ((CurrSS - 70) / 3); + } + else if(CurrSS >= 41 && CurrSS <= 70) + { + RetSS = 78 + ((CurrSS - 40) / 3); + } + else if(CurrSS >= 31 && CurrSS <= 40) + { + RetSS = 66 + (CurrSS - 30); + } + else if(CurrSS >= 21 && CurrSS <= 30) + { + RetSS = 54 + (CurrSS - 20); + } + else if(CurrSS >= 5 && CurrSS <= 20) + { + RetSS = 42 + (((CurrSS - 5) * 2) / 3); + } + else if(CurrSS == 4) + { + RetSS = 36; + } + else if(CurrSS == 3) + { + RetSS = 27; + } + else if(CurrSS == 2) + { + RetSS = 18; + } + else if(CurrSS == 1) + { + RetSS = 9; + } + else + { + RetSS = CurrSS; + } + + + + return RetSS; +} + +long rtllib_translate_todbm(u8 signal_strength_index ) +{ + long signal_power; + + signal_power = (long)((signal_strength_index + 1) >> 1); + signal_power -= 95; + + return signal_power; +} + +#ifdef _RTL8192_EXT_PATCH_ +extern int rtllib_network_init( +#else +static inline int rtllib_network_init( +#endif + struct rtllib_device *ieee, + struct rtllib_probe_response *beacon, + struct rtllib_network *network, + struct rtllib_rx_stats *stats) +{ +#ifdef CONFIG_RTLLIB_DEBUG +#endif + + /* + network->qos_data.active = 0; + network->qos_data.supported = 0; + network->qos_data.param_count = 0; + network->qos_data.old_param_count = 0; + */ + memset(&network->qos_data, 0, sizeof(struct rtllib_qos_data)); + + /* Pull out fixed field data */ + memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); + network->capability = le16_to_cpu(beacon->capability); + network->last_scanned = jiffies; + network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]); + network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]); + network->beacon_interval = le32_to_cpu(beacon->beacon_interval); + /* Where to pull this? beacon->listen_interval;*/ + network->listen_interval = 0x0A; + network->rates_len = network->rates_ex_len = 0; + network->last_associate = 0; + network->ssid_len = 0; + network->hidden_ssid_len = 0; + memset(network->hidden_ssid, 0, sizeof(network->hidden_ssid)); + network->flags = 0; + network->atim_window = 0; + network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? + 0x3 : 0x0; + network->berp_info_valid = false; + network->broadcom_cap_exist = false; + network->ralink_cap_exist = false; + network->atheros_cap_exist = false; + network->cisco_cap_exist = false; + network->unknown_cap_exist = false; + network->realtek_cap_exit = false; + network->marvell_cap_exist = false; + network->airgo_cap_exist = false; +#ifdef THOMAS_TURBO + network->Turbo_Enable = 0; +#endif + network->SignalStrength = stats->SignalStrength; + network->RSSI = stats->SignalStrength; +#ifdef ENABLE_DOT11D + network->CountryIeLen = 0; + memset(network->CountryIeBuf, 0, MAX_IE_LEN); +#endif +#ifdef _RTL8192_EXT_PATCH_ + memset(network->hostname, 0, MAX_HOST_NAME_LENGTH); + network->hostname_len = 0; +#endif + HTInitializeBssDesc(&network->bssht); + if (stats->freq == RTLLIB_52GHZ_BAND) { + /* for A band (No DS info) */ + network->channel = stats->received_channel; + } else + network->flags |= NETWORK_HAS_CCK; + + network->wpa_ie_len = 0; + network->rsn_ie_len = 0; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + network->wzc_ie_len = 0; +#endif + + if (rtllib_parse_info_param(ieee, + beacon->info_element, + (stats->len - sizeof(*beacon)), + network, + stats)) + return 1; + + network->mode = 0; + if (stats->freq == RTLLIB_52GHZ_BAND) + network->mode = IEEE_A; + else { + if (network->flags & NETWORK_HAS_OFDM) + network->mode |= IEEE_G; + if (network->flags & NETWORK_HAS_CCK) + network->mode |= IEEE_B; + } + + if (network->mode == 0) { + RTLLIB_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' " + "network.\n", + escape_essid(network->ssid, + network->ssid_len), + MAC_ARG(network->bssid)); + return 1; + } + + if(network->bssht.bdSupportHT){ +#ifdef _RTL8192_EXT_PATCH_ + if(network->mode == IEEE_A) + network->mode |= IEEE_N_5G; + else if(network->mode & (IEEE_G | IEEE_B)) + network->mode |= IEEE_N_24G; +#else + if(network->mode == IEEE_A) + network->mode = IEEE_N_5G; + else if(network->mode & (IEEE_G | IEEE_B)) + network->mode = IEEE_N_24G; +#endif + } + if (rtllib_is_empty_essid(network->ssid, network->ssid_len)) + network->flags |= NETWORK_EMPTY_ESSID; + +#if 0 + { + static u8 Netgear845T_Mac[3] = {0x00, 0x1B, 0x2F}; + static u8 Buffalo300N_Mac[3] = {0x00, 0x16, 0x01}; + + if(ieee->RF_Type == RF_1T1R || ieee->b1SSSupport == true) + { + if((memcmp(network->bssid, Netgear845T_Mac, 3)==0) ||(memcmp(network->bssid, Buffalo300N_Mac, 3)==0)) + { + network->bIsNetgear854T = true; + network->bssht.bdSupportHT = false; + if(network->mode == WIRELESS_MODE_N_24G) + { + network->mode = WIRELESS_MODE_B | WIRELESS_MODE_G; + } + + } + else + { + network->bIsNetgear854T = false; + } + } + } +#endif + +#if 1 + stats->signal = 30 + (stats->SignalStrength * 70) / 100; + stats->noise = rtllib_translate_todbm((u8)(100-stats->signal)) -25; +#endif + + memcpy(&network->stats, stats, sizeof(network->stats)); + + return 0; +} + +static inline int is_same_network(struct rtllib_network *src, + struct rtllib_network *dst, u8 ssidbroad) +{ + /* A network is only a duplicate if the channel, BSSID, ESSID + * and the capability field (in particular IBSS and BSS) all match. + * We treat all with the same BSSID and channel + * as one network */ + return + (((src->ssid_len == dst->ssid_len) || (!ssidbroad)) && + (src->channel == dst->channel) && + !memcmp(src->bssid, dst->bssid, ETH_ALEN) && + (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (!ssidbroad)) && + ((src->capability & WLAN_CAPABILITY_IBSS) == + (dst->capability & WLAN_CAPABILITY_IBSS)) && + ((src->capability & WLAN_CAPABILITY_ESS) == + (dst->capability & WLAN_CAPABILITY_ESS))); +} + +static inline void update_ibss_network(struct rtllib_network *dst, + struct rtllib_network *src) +{ + memcpy(&dst->stats, &src->stats, sizeof(struct rtllib_rx_stats)); + dst->last_scanned = jiffies; +} + + +static inline void update_network(struct rtllib_network *dst, + struct rtllib_network *src) +{ + int qos_active; + u8 old_param; + + memcpy(&dst->stats, &src->stats, sizeof(struct rtllib_rx_stats)); + dst->capability = src->capability; + memcpy(dst->rates, src->rates, src->rates_len); + dst->rates_len = src->rates_len; + memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); + dst->rates_ex_len = src->rates_ex_len; + if(src->ssid_len > 0) + { + if(dst->ssid_len == 0) + { + memset(dst->hidden_ssid, 0, sizeof(dst->hidden_ssid)); + dst->hidden_ssid_len = src->ssid_len; + memcpy(dst->hidden_ssid, src->ssid, src->ssid_len); + }else{ + memset(dst->ssid, 0, dst->ssid_len); + dst->ssid_len = src->ssid_len; + memcpy(dst->ssid, src->ssid, src->ssid_len); + } + } + dst->mode = src->mode; + dst->flags = src->flags; + dst->time_stamp[0] = src->time_stamp[0]; + dst->time_stamp[1] = src->time_stamp[1]; + if (src->flags & NETWORK_HAS_ERP_VALUE) + { + dst->erp_value = src->erp_value; + dst->berp_info_valid = src->berp_info_valid = true; + } + dst->beacon_interval = src->beacon_interval; + dst->listen_interval = src->listen_interval; + dst->atim_window = src->atim_window; + dst->dtim_period = src->dtim_period; + dst->dtim_data = src->dtim_data; + dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0]; + dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1]; + memcpy(&dst->tim, &src->tim, sizeof(struct rtllib_tim_parameters)); + + dst->bssht.bdSupportHT = src->bssht.bdSupportHT; + dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation; + dst->bssht.bdHTCapLen= src->bssht.bdHTCapLen; + memcpy(dst->bssht.bdHTCapBuf,src->bssht.bdHTCapBuf,src->bssht.bdHTCapLen); + dst->bssht.bdHTInfoLen= src->bssht.bdHTInfoLen; + memcpy(dst->bssht.bdHTInfoBuf,src->bssht.bdHTInfoBuf,src->bssht.bdHTInfoLen); + dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer; + dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime; + dst->broadcom_cap_exist = src->broadcom_cap_exist; + dst->ralink_cap_exist = src->ralink_cap_exist; + dst->atheros_cap_exist = src->atheros_cap_exist; + dst->realtek_cap_exit = src->realtek_cap_exit; + dst->marvell_cap_exist = src->marvell_cap_exist; + dst->cisco_cap_exist = src->cisco_cap_exist; + dst->airgo_cap_exist = src->airgo_cap_exist; + dst->unknown_cap_exist = src->unknown_cap_exist; + memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); + dst->wpa_ie_len = src->wpa_ie_len; + memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len); + dst->rsn_ie_len = src->rsn_ie_len; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + memcpy(dst->wzc_ie, src->wzc_ie, src->wzc_ie_len); + dst->wzc_ie_len = src->wzc_ie_len; +#endif + + dst->last_scanned = jiffies; + /* qos related parameters */ + qos_active = dst->qos_data.active; + old_param = dst->qos_data.param_count; +#if 0 + if(dst->flags & NETWORK_HAS_QOS_MASK){ + } + else { + dst->qos_data.supported = src->qos_data.supported; + dst->qos_data.param_count = src->qos_data.param_count; + } +#else + dst->qos_data.supported = src->qos_data.supported; + if(dst->flags & NETWORK_HAS_QOS_PARAMETERS){ + memcpy(&dst->qos_data, &src->qos_data, sizeof(struct rtllib_qos_data)); + } +#endif + if(dst->qos_data.supported == 1) { + if(dst->ssid_len) + RTLLIB_DEBUG_QOS + ("QoS the network %s is QoS supported\n", + dst->ssid); + else + RTLLIB_DEBUG_QOS + ("QoS the network is QoS supported\n"); + } + dst->qos_data.active = qos_active; + dst->qos_data.old_param_count = old_param; + + /* dst->last_associate is not overwritten */ + dst->wmm_info = src->wmm_info; + if(src->wmm_param[0].ac_aci_acm_aifsn|| \ + src->wmm_param[1].ac_aci_acm_aifsn|| \ + src->wmm_param[2].ac_aci_acm_aifsn|| \ + src->wmm_param[1].ac_aci_acm_aifsn) { + memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); + } + + dst->SignalStrength = src->SignalStrength; + dst->RSSI = src->RSSI; +#ifdef THOMAS_TURBO + dst->Turbo_Enable = src->Turbo_Enable; +#endif + +#ifdef ENABLE_DOT11D + dst->CountryIeLen = src->CountryIeLen; + memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen); +#endif + + dst->bWithAironetIE = src->bWithAironetIE; + dst->bCkipSupported = src->bCkipSupported; + memcpy(dst->CcxRmState,src->CcxRmState,2); + dst->bCcxRmEnable = src->bCcxRmEnable; + dst->MBssidMask = src->MBssidMask; + dst->bMBssidValid = src->bMBssidValid; + memcpy(dst->MBssid,src->MBssid,6); + dst->bWithCcxVerNum = src->bWithCcxVerNum; + dst->BssCcxVerNumber = src->BssCcxVerNumber; + +} +static inline int is_beacon(__le16 fc) +{ + return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == RTLLIB_STYPE_BEACON); +} + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE +u8 AsocEntry_ComputeSum(u8 *paddr) +{ + u32 sum; + + sum = paddr[0]+ + paddr[1]+ + paddr[2]+ + paddr[3]+ + paddr[4]+ + paddr[5]; + + return (u8)(sum % PEER_MAX_ASSOC); +} +u8 AsocEntry_AssignAvailableAID(struct rtllib_device *ieee, u8 *paddr) +{ + int i; + + for(i = 0; i < PEER_MAX_ASSOC; i++) + { + if(ieee->AvailableAIDTable[i] == 99) + { + ieee->AvailableAIDTable[i] = AsocEntry_ComputeSum(paddr); + return i+1; + } + } + + return 1; +} + +void InitStaInfo(struct rtllib_device *ieee,int index) +{ + int idx = index; + ieee->peer_assoc_list[idx]->StaDataRate = 0; + ieee->peer_assoc_list[idx]->StaSS = 0; + ieee->peer_assoc_list[idx]->RetryFrameCnt = 0; + ieee->peer_assoc_list[idx]->NoRetryFrameCnt = 0; + ieee->peer_assoc_list[idx]->LastRetryCnt = 0; + ieee->peer_assoc_list[idx]->LastNoRetryCnt = 0; + ieee->peer_assoc_list[idx]->AvgRetryRate = 0; + ieee->peer_assoc_list[idx]->LastRetryRate = 0; + ieee->peer_assoc_list[idx]->txRateIndex = 11; + ieee->peer_assoc_list[idx]->APDataRate = 0x2; + ieee->peer_assoc_list[idx]->ForcedDataRate = 0x2; + +} + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) +static u8 IsStaInfoExist(struct rtllib_device *ieee, u8 *addr) +{ + int k=0; + struct sta_info * psta = NULL; + u8 sta_idx = PEER_MAX_ASSOC; + + for(k=0; kpeer_assoc_list[k]; + if(NULL != psta) + { + if(memcmp(addr, psta->macaddr, ETH_ALEN) == 0) + { + sta_idx = k; + break; + } + } + } + return sta_idx; +} + +static u8 GetFreeStaInfoIdx(struct rtllib_device *ieee, u8 *addr) +{ + int k = 0; + while((ieee->peer_assoc_list[k] != NULL) && (k < PEER_MAX_ASSOC)) + k++; + printk("%s: addr:"MAC_FMT" index: %d\n", __FUNCTION__, MAC_ARG(addr), k); + return k; +} +#endif + +struct sta_info *GetStaInfo(struct rtllib_device *ieee, u8 *addr) +{ + int k=0; + struct sta_info * psta = NULL; + struct sta_info * psta_find = NULL; + + for(k=0; kpeer_assoc_list[k]; + if(NULL != psta) + { + if(memcmp(addr, psta->macaddr, ETH_ALEN) == 0) + { + psta_find = psta; + break; + } + } + } + return psta_find; +} +void DelStaInfoList(struct rtllib_device *ieee) +{ + int idx = 0; + struct sta_info * AsocEntry = NULL; + + atomic_set(&ieee->AsocEntryNum, 0); + for(idx=0; idxpeer_assoc_list[idx]; + if(NULL != AsocEntry){ + kfree(AsocEntry); + ieee->peer_assoc_list[idx] = NULL; + } + ieee->AvailableAIDTable[idx] = 99; + } +} +void DelStaInfo(struct rtllib_device *ieee, u8 *addr) +{ + struct sta_info * psta = NULL; + int k=0; + + for(k=0; kpeer_assoc_list[k]; + if(NULL != psta){ + if(memcmp(addr, psta->macaddr, ETH_ALEN) == 0){ + if (psta->aid > 0 && psta->aid-1 < PEER_MAX_ASSOC) + ieee->AvailableAIDTable[psta->aid-1] = 99; + else + printk("%s(): clear non-existing entry AID\n", __func__); + + kfree(psta); + ieee->peer_assoc_list[k] = NULL; + atomic_dec(&ieee->AsocEntryNum); + } + } + } +} +void IbssAgeFunction(struct rtllib_device *ieee) +{ + struct sta_info* AsocEntry = NULL; + int idx; + unsigned long CurrentTime; + signed long TimeDifference; + struct rtllib_network *target; + + CurrentTime = jiffies; + + for(idx = 0; idx < PEER_MAX_ASSOC; idx++) + { + AsocEntry = ieee->peer_assoc_list[idx]; + if(AsocEntry) + { + TimeDifference = jiffies_to_msecs(CurrentTime - AsocEntry->LastActiveTime); + + if(TimeDifference > 20000) + { + printk("IbssAgeFunction(): "MAC_FMT" timeout\n", MAC_ARG(AsocEntry->macaddr)); +#ifdef RTL8192S_WAPI_SUPPORT + if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)) + { + WapiReturnOneStaInfo(ieee, AsocEntry->macaddr, 0); + } +#endif + kfree(AsocEntry); + ieee->peer_assoc_list[idx] = NULL; + atomic_dec(&ieee->AsocEntryNum); + + if(atomic_read(&ieee->AsocEntryNum) == 0){ + + down(&ieee->wx_sem); + rtllib_stop_protocol(ieee,true); + + list_for_each_entry(target, &ieee->network_list, list) { + if (is_same_network(target, &ieee->current_network,(target->ssid_len?1:0))){ + printk("delete sta of previous Ad-hoc\n"); + list_del(&target->list); + break; + } + } + + rtllib_start_protocol(ieee); + up(&ieee->wx_sem); + }else{ +#if defined (RTL8192S_WAPI_SUPPORT) + if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){ + WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0); + } +#endif + } + } + } + } + +#ifdef TO_DO_LIST + if(AsocEntry_AnyStationAssociated(pMgntInfo)==false) + DrvIFIndicateDisassociation(Adapter, unspec_reason); + + if(pMgntInfo->dot11CurrentWirelessMode == WIRELESS_MODE_G || + (IS_WIRELESS_MODE_N_24G(Adapter) && pMgntInfo->pHTInfo->bCurSuppCCK) ) + { + if(nBModeStaCnt == 0) + { + pMgntInfo->bUseProtection = false; + ActUpdate_mCapInfo(Adapter, pMgntInfo->mCap); + } + } + + if(IS_WIRELESS_MODE_N_24G(Adapter) || IS_WIRELESS_MODE_N_5G(Adapter) ) + { + if(nLegacyStaCnt > 0) + { + pMgntInfo->pHTInfo->CurrentOpMode = HT_OPMODE_MIXED; + } + else + { + if((pMgntInfo->pHTInfo->bCurBW40MHz) && (n20MHzStaCnt > 0)) + pMgntInfo->pHTInfo->CurrentOpMode = HT_OPMODE_40MHZ_PROTECT; + else + pMgntInfo->pHTInfo->CurrentOpMode = HT_OPMODE_NO_PROTECT; + + } + } + + if(IS_WIRELESS_MODE_G(Adapter) || + (IS_WIRELESS_MODE_N_24G(Adapter) && pMgntInfo->pHTInfo->bCurSuppCCK)) + { + if(pMgntInfo->bUseProtection) + { + u8 CckRate[4] = { MGN_1M, MGN_2M, MGN_5_5M, MGN_11M }; + OCTET_STRING osCckRate; + FillOctetString(osCckRate, CckRate, 4); + FilterSupportRate(pMgntInfo->mBrates, &osCckRate, false); + Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_BASIC_RATE, (pu1Byte)&osCckRate); + } + else + { + Adapter->HalFunc.SetHwRegHandler( Adapter, HW_VAR_BASIC_RATE, (pu1Byte)(&pMgntInfo->mBrates) ); + } + } +#endif +} +#endif + +static int IsPassiveChannel( struct rtllib_device *rtllib, u8 channel) +{ + if (MAX_CHANNEL_NUMBER < channel) { + printk("%s(): Invalid Channel\n", __FUNCTION__); + return 0; + } + + if(rtllib->active_channel_map[channel] == 2) + return 1; + + return 0; +} + +int IsLegalChannel( struct rtllib_device *rtllib, u8 channel) +{ + if (MAX_CHANNEL_NUMBER < channel) { + printk("%s(): Invalid Channel\n", __FUNCTION__); + return 0; + } + if (rtllib->active_channel_map[channel] > 0) + return 1; + + return 0; +} + + +static inline void rtllib_process_probe_response( + struct rtllib_device *ieee, + struct rtllib_probe_response *beacon, + struct rtllib_rx_stats *stats) +{ + struct rtllib_network *target; + struct rtllib_network *oldest = NULL; +#ifdef CONFIG_RTLLIB_DEBUG + struct rtllib_info_element *info_element = &beacon->info_element[0]; +#endif + unsigned long flags; + short renew; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) + struct rtllib_network *network = kzalloc(sizeof(struct rtllib_network), GFP_ATOMIC); +#else + struct rtllib_network *network = kmalloc(sizeof(*network), GFP_ATOMIC); + memset(network,0,sizeof(*network)); +#endif + + if (!network) { + return; + } + +#ifdef _RTL8192_EXT_PATCH_ + if(ieee->ext_patch_rtllib_process_probe_response_1) { + /* 2 deonte the normal beacon packet, + * discard it under mesh only mode */ + if(ieee->ext_patch_rtllib_process_probe_response_1(ieee, beacon, stats) != 2){ + goto free_network; + } else if((ieee->iw_mode == IW_MODE_MESH)&&ieee->only_mesh) { + goto free_network; + } + } +#endif + + RTLLIB_DEBUG_SCAN( + "'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", + escape_essid(info_element->data, info_element->len), + MAC_ARG(beacon->header.addr3), + (beacon->capability & (1<<0xf)) ? '1' : '0', + (beacon->capability & (1<<0xe)) ? '1' : '0', + (beacon->capability & (1<<0xd)) ? '1' : '0', + (beacon->capability & (1<<0xc)) ? '1' : '0', + (beacon->capability & (1<<0xb)) ? '1' : '0', + (beacon->capability & (1<<0xa)) ? '1' : '0', + (beacon->capability & (1<<0x9)) ? '1' : '0', + (beacon->capability & (1<<0x8)) ? '1' : '0', + (beacon->capability & (1<<0x7)) ? '1' : '0', + (beacon->capability & (1<<0x6)) ? '1' : '0', + (beacon->capability & (1<<0x5)) ? '1' : '0', + (beacon->capability & (1<<0x4)) ? '1' : '0', + (beacon->capability & (1<<0x3)) ? '1' : '0', + (beacon->capability & (1<<0x2)) ? '1' : '0', + (beacon->capability & (1<<0x1)) ? '1' : '0', + (beacon->capability & (1<<0x0)) ? '1' : '0'); + + if (rtllib_network_init(ieee, beacon, network, stats)) { + RTLLIB_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n", + escape_essid(info_element->data, + info_element->len), + MAC_ARG(beacon->header.addr3), + WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + RTLLIB_STYPE_PROBE_RESP ? + "PROBE RESPONSE" : "BEACON"); + goto free_network; + } + + + if (!IsLegalChannel(ieee, network->channel)) + goto free_network; + + if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == RTLLIB_STYPE_PROBE_RESP) { + if (IsPassiveChannel(ieee, network->channel)) { + printk("GetScanInfo(): For Global Domain, " + "filter probe response at channel(%d).\n", network->channel); + goto free_network; + } + } + + /* The network parsed correctly -- so now we scan our known networks + * to see if we can find it in our list. + * + * NOTE: This search is definitely not optimized. Once its doing + * the "right thing" we'll optimize it for efficiency if + * necessary */ + + /* Search for this entry in the list and update it if it is + * already there. */ + + spin_lock_irqsave(&ieee->lock, flags); +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + if(is_beacon(beacon->header.frame_ctl)){ + if((ieee->iw_mode == IW_MODE_ADHOC) && (ieee->state == RTLLIB_LINKED)) + { + if((network->ssid_len == ieee->current_network.ssid_len) + && (!memcmp(network->ssid,ieee->current_network.ssid,ieee->current_network.ssid_len)) + && (network->channel == ieee->current_network.channel) + && (ieee->current_network.channel > 0) + && (ieee->current_network.channel <= 14)) + { + if(!memcmp(ieee->current_network.bssid,network->bssid,6)) + { + int idx = 0; + struct rtllib_hdr_3addr* header = NULL; + int idx_exist = 0; + if(timer_pending(&ieee->ibss_wait_timer)) + del_timer_sync(&ieee->ibss_wait_timer); + header = (struct rtllib_hdr_3addr*)&(beacon->header); + idx_exist = IsStaInfoExist(ieee,header->addr2); + if(idx_exist >= PEER_MAX_ASSOC) { + idx = GetFreeStaInfoIdx(ieee, header->addr2); + } else { + ieee->peer_assoc_list[idx_exist]->LastActiveTime = jiffies; + goto no_alloc; + } + if (idx >= PEER_MAX_ASSOC - 1) { + printk("\n%s():ERR!!!Buffer overflow - could not append!!!",__FUNCTION__); + goto free_network; + } else { + ieee->peer_assoc_list[idx] = (struct sta_info *)kmalloc(sizeof(struct sta_info), GFP_ATOMIC); + memset(ieee->peer_assoc_list[idx], 0, sizeof(struct sta_info)); + ieee->peer_assoc_list[idx]->LastActiveTime = jiffies; + memcpy(ieee->peer_assoc_list[idx]->macaddr,header->addr2,ETH_ALEN); + ieee->peer_assoc_list[idx]->ratr_index = 8; + InitStaInfo(ieee,idx); + atomic_inc(&ieee->AsocEntryNum); + ieee->peer_assoc_list[idx]->aid = AsocEntry_AssignAvailableAID(ieee, ieee->peer_assoc_list[idx]->macaddr); + ieee->check_ht_cap(ieee->dev,ieee->peer_assoc_list[idx],network); + queue_delayed_work_rsl(ieee->wq, &ieee->update_assoc_sta_info_wq, 0); + ieee->Adhoc_InitRateAdaptive(ieee->dev,ieee->peer_assoc_list[idx]); + } +#if defined (RTL8192S_WAPI_SUPPORT) + if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){ + WapiCreateAppEventAndSend(ieee,NULL,0,header->addr2,false, false, false, 0, false); + } +#endif + } + else + { +#if 0 + printk("%s(): SSID matched but BSSID mismatched.\n",__FUNCTION__); + + ieee->TargetTsf = beacon->time_stamp[1]; + ieee->TargetTsf <<= 32; + ieee->TargetTsf |= beacon->time_stamp[0]; + + ieee->CurrTsf = stats->TimeStampLow; + + queue_delayed_work_rsl(ieee->wq, &ieee->check_tsf_wq, 0); +#endif + } + } + } + } + if(ieee->iw_mode == IW_MODE_ADHOC){ + if((network->ssid_len == ieee->current_network.ssid_len) + && (!memcmp(network->ssid,ieee->current_network.ssid,ieee->current_network.ssid_len)) + && (network->capability & WLAN_CAPABILITY_IBSS) + && (ieee->state == RTLLIB_LINKED_SCANNING)) + { + if(memcmp(ieee->current_network.bssid,network->bssid,6)) + { + printk("%s(): SSID matched but BSSID mismatched.\n",__FUNCTION__); + + ieee->TargetTsf = beacon->time_stamp[1]; + ieee->TargetTsf <<= 32; + ieee->TargetTsf |= beacon->time_stamp[0]; + + ieee->CurrTsf = stats->TimeStampLow; + + queue_delayed_work_rsl(ieee->wq, &ieee->check_tsf_wq, 0); + } + } + } +#endif +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) +no_alloc: + if(ieee->iw_mode == IW_MODE_INFRA) +#endif + { + if(is_same_network(&ieee->current_network, network, (network->ssid_len?1:0))) { + update_network(&ieee->current_network, network); + if((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G) + && ieee->current_network.berp_info_valid){ + if(ieee->current_network.erp_value& ERP_UseProtection) + ieee->current_network.buseprotection = true; + else + ieee->current_network.buseprotection = false; + } + if(is_beacon(beacon->header.frame_ctl)) + { + if(ieee->state >= RTLLIB_LINKED) + ieee->LinkDetectInfo.NumRecvBcnInPeriod++; + } +#if 0 + else + network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags); +#endif + } + } +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + else if(ieee->iw_mode == IW_MODE_ADHOC) + { + if(is_same_network(&ieee->current_network, network, (network->ssid_len?1:0))) { + update_ibss_network(&ieee->current_network, network); + } + } +#endif + list_for_each_entry(target, &ieee->network_list, list) { + if (is_same_network(target, network,(target->ssid_len?1:0))) + break; + if ((oldest == NULL) || + (target->last_scanned < oldest->last_scanned)) + oldest = target; + } + + /* If we didn't find a match, then get a new network slot to initialize + * with this beacon's information */ + if (&target->list == &ieee->network_list) { + if (list_empty(&ieee->network_free_list)) { + /* If there are no more slots, expire the oldest */ + list_del(&oldest->list); + target = oldest; + RTLLIB_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from " + "network list.\n", + escape_essid(target->ssid, + target->ssid_len), + MAC_ARG(target->bssid)); + } else { + /* Otherwise just pull from the free list */ + target = list_entry(ieee->network_free_list.next, + struct rtllib_network, list); + list_del(ieee->network_free_list.next); + } + + +#ifdef CONFIG_RTLLIB_DEBUG + RTLLIB_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n", + escape_essid(network->ssid, + network->ssid_len), + MAC_ARG(network->bssid), + WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + RTLLIB_STYPE_PROBE_RESP ? + "PROBE RESPONSE" : "BEACON"); +#endif +#ifdef _RTL8192_EXT_PATCH_ + network->ext_entry = target->ext_entry; +#endif + memcpy(target, network, sizeof(*target)); + list_add_tail(&target->list, &ieee->network_list); + if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) + rtllib_softmac_new_net(ieee, network); + } else { + RTLLIB_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n", + escape_essid(target->ssid, + target->ssid_len), + MAC_ARG(target->bssid), + WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == + RTLLIB_STYPE_PROBE_RESP ? + "PROBE RESPONSE" : "BEACON"); + + /* we have an entry and we are going to update it. But this entry may + * be already expired. In this case we do the same as we found a new + * net and call the new_net handler + */ + renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); +#if 0 + if(is_beacon(beacon->header.frame_ctl) == 0) + network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags); + if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ + && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\ + ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == RTLLIB_NOLINK)))) + renew = 1; +#else + if((!target->ssid_len) && + (((network->ssid_len > 0) && (target->hidden_ssid_len == 0)) + || ((ieee->current_network.ssid_len == network->ssid_len) && + (strncmp(ieee->current_network.ssid, network->ssid, network->ssid_len) == 0) && + (ieee->state == RTLLIB_NOLINK))) + ) { + renew = 1; + } +#endif +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + if(ieee->iw_mode == IW_MODE_ADHOC) + update_ibss_network(target, network); + else + update_network(target, network); +#else + update_network(target, network); +#endif + if(renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)) + rtllib_softmac_new_net(ieee, network); + } + + spin_unlock_irqrestore(&ieee->lock, flags); + if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, network, (network->ssid_len?1:0))&&\ + (ieee->state == RTLLIB_LINKED)) { + if(ieee->handle_beacon != NULL) { + ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network); + } + } +free_network: + kfree(network); + return; +} + +void rtllib_rx_mgt(struct rtllib_device *ieee, + struct sk_buff *skb, + struct rtllib_rx_stats *stats) +{ + struct rtllib_hdr_4addr *header = (struct rtllib_hdr_4addr *)skb->data ; +#if 0 + if(ieee->sta_sleep || (ieee->ps != RTLLIB_PS_DISABLED && + ieee->iw_mode == IW_MODE_INFRA && + ieee->state == RTLLIB_LINKED)) + { + tasklet_schedule(&ieee->ps_task); + } +#endif + if(WLAN_FC_GET_STYPE(header->frame_ctl) != RTLLIB_STYPE_PROBE_RESP && + WLAN_FC_GET_STYPE(header->frame_ctl) != RTLLIB_STYPE_BEACON) + ieee->last_rx_ps_time = jiffies; + + switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { + + case RTLLIB_STYPE_BEACON: + RTLLIB_DEBUG_MGMT("received BEACON (%d)\n", + WLAN_FC_GET_STYPE(header->frame_ctl)); + RTLLIB_DEBUG_SCAN("Beacon\n"); + rtllib_process_probe_response( + ieee, (struct rtllib_probe_response *)header, stats); + +#ifdef ENABLE_LPS + if(ieee->sta_sleep || (ieee->ps != RTLLIB_PS_DISABLED && + ieee->iw_mode == IW_MODE_INFRA && + ieee->state == RTLLIB_LINKED)) + { + tasklet_schedule(&ieee->ps_task); + } +#endif + + break; + + case RTLLIB_STYPE_PROBE_RESP: + RTLLIB_DEBUG_MGMT("received PROBE RESPONSE (%d)\n", + WLAN_FC_GET_STYPE(header->frame_ctl)); + RTLLIB_DEBUG_SCAN("Probe response\n"); + rtllib_process_probe_response( + ieee, (struct rtllib_probe_response *)header, stats); + break; + case RTLLIB_STYPE_PROBE_REQ: + RTLLIB_DEBUG_MGMT("received PROBE RESQUEST (%d)\n", + WLAN_FC_GET_STYPE(header->frame_ctl)); + RTLLIB_DEBUG_SCAN("Probe request\n"); + if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) && + ((ieee->iw_mode == IW_MODE_ADHOC || + ieee->iw_mode == IW_MODE_MASTER) && + ieee->state == RTLLIB_LINKED)){ + rtllib_rx_probe_rq(ieee, skb); + } +#ifdef _RTL8192_EXT_PATCH_ + if((ieee->iw_mode == IW_MODE_MESH) && ieee->ext_patch_rtllib_rx_mgt_on_probe_req ) + ieee->ext_patch_rtllib_rx_mgt_on_probe_req( ieee, (struct rtllib_probe_request *)header, stats); +#endif + break; + } + +#if 0 +#ifdef CONFIG_CFG_80211 + if((rtllib_act_scanning(ieee,false) == true) && ((WLAN_FC_GET_STYPE(header->frame_ctl) ==RTLLIB_STYPE_PROBE_RESP) || + (WLAN_FC_GET_STYPE(header->frame_ctl) ==RTLLIB_STYPE_BEACON))) + return ieee80211_scan_rx(ieee, skb, stats); +#endif +#endif +} + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(rtllib_rx_mgt); +EXPORT_SYMBOL_RSL(rtllib_rx); +EXPORT_SYMBOL_RSL(IsLegalChannel); +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) +EXPORT_SYMBOL_RSL(IbssAgeFunction); +EXPORT_SYMBOL_RSL(GetStaInfo); +#endif +#ifdef _RTL8192_EXT_PATCH_ +EXPORT_SYMBOL_RSL(rtllib_network_init); +EXPORT_SYMBOL_RSL(rtllib_parse_info_param); +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib_softmac.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib_softmac.c @@ -0,0 +1,5423 @@ +/* IEEE 802.11 SoftMAC layer + * Copyright (c) 2005 Andrea Merello + * + * Mostly extracted from the rtl8180-sa2400 driver for the + * in-kernel generic ieee802.11 stack. + * + * Few lines might be stolen from other part of the rtllib + * stack. Copyright who own it's copyright + * + * WPA code stolen from the ipw2200 driver. + * Copyright who own it's copyright. + * + * released under the GPL + */ + + +#include "rtllib.h" + +#include +#include +#include +#include +#ifdef ENABLE_DOT11D +#include "dot11d.h" +#endif + +#ifdef RTK_DMP_PLATFORM +#include +#endif +extern void _setup_timer( struct timer_list*, void*, unsigned long ); +u8 rsn_authen_cipher_suite[16][4] = { + {0x00,0x0F,0xAC,0x00}, + {0x00,0x0F,0xAC,0x01}, + {0x00,0x0F,0xAC,0x02}, + {0x00,0x0F,0xAC,0x03}, + {0x00,0x0F,0xAC,0x04}, + {0x00,0x0F,0xAC,0x05}, +}; + +short rtllib_is_54g(struct rtllib_network *net) +{ + return ((net->rates_ex_len > 0) || (net->rates_len > 4)); +} + +short rtllib_is_shortslot(struct rtllib_network net) +{ + return (net.capability & WLAN_CAPABILITY_SHORT_SLOT_TIME); +} + +/* returns the total length needed for pleacing the RATE MFIE + * tag and the EXTENDED RATE MFIE tag if needed. + * It encludes two bytes per tag for the tag itself and its len + */ +unsigned int rtllib_MFIE_rate_len(struct rtllib_device *ieee) +{ + unsigned int rate_len = 0; + + if (ieee->modulation & RTLLIB_CCK_MODULATION) + rate_len = RTLLIB_CCK_RATE_LEN + 2; + + if (ieee->modulation & RTLLIB_OFDM_MODULATION) + + rate_len += RTLLIB_OFDM_RATE_LEN + 2; + + return rate_len; +} + +/* pleace the MFIE rate, tag to the memory (double) poined. + * Then it updates the pointer so that + * it points after the new MFIE tag added. + */ +void rtllib_MFIE_Brate(struct rtllib_device *ieee, u8 **tag_p) +{ + u8 *tag = *tag_p; + + if (ieee->modulation & RTLLIB_CCK_MODULATION){ + *tag++ = MFIE_TYPE_RATES; + *tag++ = 4; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_1MB; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_2MB; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_5MB; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_11MB; + } + + /* We may add an option for custom rates that specific HW might support */ + *tag_p = tag; +} + +void rtllib_MFIE_Grate(struct rtllib_device *ieee, u8 **tag_p) +{ + u8 *tag = *tag_p; + + if (ieee->modulation & RTLLIB_OFDM_MODULATION){ + + *tag++ = MFIE_TYPE_RATES_EX; + *tag++ = 8; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_6MB; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_9MB; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_12MB; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_18MB; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_24MB; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_36MB; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_48MB; + *tag++ = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_54MB; + + } + + /* We may add an option for custom rates that specific HW might support */ + *tag_p = tag; +} + +void rtllib_WMM_Info(struct rtllib_device *ieee, u8 **tag_p) { + u8 *tag = *tag_p; + + *tag++ = MFIE_TYPE_GENERIC; + *tag++ = 7; + *tag++ = 0x00; + *tag++ = 0x50; + *tag++ = 0xf2; + *tag++ = 0x02; + *tag++ = 0x00; + *tag++ = 0x01; +#ifdef SUPPORT_USPD + if(ieee->current_network.wmm_info & 0x80) { + *tag++ = 0x0f|MAX_SP_Len; + } else { + *tag++ = MAX_SP_Len; + } +#else + *tag++ = MAX_SP_Len; +#endif + *tag_p = tag; +} + +#ifdef THOMAS_TURBO +void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p) { + u8 *tag = *tag_p; + + *tag++ = MFIE_TYPE_GENERIC; + *tag++ = 7; + *tag++ = 0x00; + *tag++ = 0xe0; + *tag++ = 0x4c; + *tag++ = 0x01; + *tag++ = 0x02; + *tag++ = 0x11; + *tag++ = 0x00; + + *tag_p = tag; + printk(KERN_ALERT "This is enable turbo mode IE process\n"); +} +#endif + +void enqueue_mgmt(struct rtllib_device *ieee, struct sk_buff *skb) +{ + int nh; + nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM; + +/* + * if the queue is full but we have newer frames then + * just overwrites the oldest. + * + * if (nh == ieee->mgmt_queue_tail) + * return -1; + */ + ieee->mgmt_queue_head = nh; + ieee->mgmt_queue_ring[nh] = skb; + +} + +struct sk_buff *dequeue_mgmt(struct rtllib_device *ieee) +{ + struct sk_buff *ret; + + if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head) + return NULL; + + ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail]; + + ieee->mgmt_queue_tail = + (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM; + + return ret; +} + +void init_mgmt_queue(struct rtllib_device *ieee) +{ + ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0; +} + + +u8 +MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee) +{ + u16 i; + u8 QueryRate = 0; + u8 BasicRate; + + + for( i = 0; i < ieee->current_network.rates_len; i++) + { + BasicRate = ieee->current_network.rates[i]&0x7F; + if(!rtllib_is_cck_rate(BasicRate)) + { + if(QueryRate == 0) + { + QueryRate = BasicRate; + } + else + { + if(BasicRate < QueryRate) + { + QueryRate = BasicRate; + } + } + } + } + + if(QueryRate == 0) + { + QueryRate = 12; + printk("No BasicRate found!!\n"); + } + return QueryRate; +} + +u8 MgntQuery_MgntFrameTxRate(struct rtllib_device *ieee) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + u8 rate; + +#if defined RTL8190P || defined RTL8192E || defined RTL8192U + if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M) + rate = 0x0c; + else + rate = ieee->basic_rate & 0x7f; +#elif defined RTL8192SE || defined RTL8192SU || defined RTL8192CE + if(pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) + { + rate = MgntQuery_TxRateExcludeCCKRates(ieee); + } + else + rate = ieee->basic_rate & 0x7f; +#endif + + if(rate == 0){ + if(ieee->mode == IEEE_A|| + ieee->mode== IEEE_N_5G|| + (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK)) + rate = 0x0c; + else + rate = 0x02; + } + + /* + if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) ) + { + if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A) + rate = 0x0c; + else + rate = 0x02; + } + */ + return rate; +} + + +void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl); + +inline void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee) +{ + unsigned long flags; + short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; + struct rtllib_hdr_3addr *header= + (struct rtllib_hdr_3addr *) skb->data; + + cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8); + spin_lock_irqsave(&ieee->lock, flags); + + /* called with 2nd param 0, no mgmt lock required */ + rtllib_sta_wakeup(ieee,0); + + if(header->frame_ctl == RTLLIB_STYPE_BEACON) { +#if defined(RTL8192CE) && defined(_RTL8192_EXT_PATCH_) + if((ieee->iw_mode == IW_MODE_MESH) && !ieee->only_mesh) + tcb_desc->queue_index = MGNT_QUEUE; + else +#endif + tcb_desc->queue_index = BEACON_QUEUE; + } else { + tcb_desc->queue_index = MGNT_QUEUE; + } + + if(ieee->disable_mgnt_queue) + tcb_desc->queue_index = HIGH_QUEUE; + + tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee); + tcb_desc->RATRIndex = 7; + tcb_desc->bTxDisableRateFallBack = 1; + tcb_desc->bTxUseDriverAssingedRate = 1; +#ifdef _RTL8192_EXT_PATCH_ + tcb_desc->macId = 0; +#endif + if(single){ + if(ieee->queue_stop){ + enqueue_mgmt(ieee,skb); + }else{ + header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + /* avoid watchdog triggers */ + ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); + } + + spin_unlock_irqrestore(&ieee->lock, flags); + }else{ + spin_unlock_irqrestore(&ieee->lock, flags); + spin_lock_irqsave(&ieee->mgmt_tx_lock, flags); + + header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + /* check wether the managed packet queued greater than 5 */ + if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\ + (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\ + (ieee->queue_stop) ) { + /* insert the skb packet to the management queue */ + /* as for the completion function, it does not need + * to check it any more. + * */ + printk("%s():insert to waitqueue, queue_index:%d!\n",__FUNCTION__,tcb_desc->queue_index); + skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb); + } else { + ieee->softmac_hard_start_xmit(skb,ieee->dev); + } + spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags); + } +} + +inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, + struct rtllib_device *ieee) +{ + short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; + struct rtllib_hdr_3addr *header = + (struct rtllib_hdr_3addr *) skb->data; + u16 fc,type,stype; + cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8); + + fc = header->frame_ctl; + type = WLAN_FC_GET_TYPE(fc); + stype = WLAN_FC_GET_STYPE(fc); + + + if(stype != RTLLIB_STYPE_PSPOLL) + tcb_desc->queue_index = MGNT_QUEUE; + else{ +#ifdef RTL8192CE + tcb_desc->queue_index = MGNT_QUEUE; +#else + tcb_desc->queue_index = HIGH_QUEUE; +#endif + } + + if(ieee->disable_mgnt_queue) + tcb_desc->queue_index = HIGH_QUEUE; + + + tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee); + tcb_desc->RATRIndex = 7; + tcb_desc->bTxDisableRateFallBack = 1; + tcb_desc->bTxUseDriverAssingedRate = 1; + if (single) { + if (type != RTLLIB_FTYPE_CTL) { + header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + } + /* avoid watchdog triggers */ + ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); + + } else { + if (type != RTLLIB_FTYPE_CTL) { + header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + } + ieee->softmac_hard_start_xmit(skb,ieee->dev); + + } +} + +inline struct sk_buff *rtllib_probe_req(struct rtllib_device *ieee) +{ + unsigned int len,rate_len; + u8 *tag; + struct sk_buff *skb; + struct rtllib_probe_request *req; + + u8* ht_cap_buf = NULL; + u8 ht_cap_len=0; + int encrypt; + struct rtllib_crypt_data* crypt; + int wpa_ie_len = ieee->wpa_ie_len; + +#ifdef _RTL8192_EXT_PATCH_ + short extMore = 0; + if(ieee->ext_patch_rtllib_probe_req_1) + extMore = ieee->ext_patch_rtllib_probe_req_1(ieee); +#endif + + len = ieee->current_network.ssid_len; + + rate_len = rtllib_MFIE_rate_len(ieee); + +#ifdef _RTL8192_EXT_PATCH_ + if(!extMore) + skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) + + 2 + len + rate_len + ieee->tx_headroom); + else + skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) + + 2 + len + rate_len+128+ieee->tx_headroom); +#else +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr; + int alignment; + skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) + + 2 + len + rate_len + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE); +#else + skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) + + 2 + len + rate_len + ieee->tx_headroom); +#endif +#endif + + if (!skb) + return NULL; + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + + skb_reserve(skb, ieee->tx_headroom); + + req = (struct rtllib_probe_request *) skb_put(skb,sizeof(struct rtllib_probe_request)); + req->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_REQ); + req->header.duration_id = 0; + + memset(req->header.addr1, 0xff, ETH_ALEN); + memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memset(req->header.addr3, 0xff, ETH_ALEN); + + tag = (u8 *) skb_put(skb,len+2+rate_len); + + *tag++ = MFIE_TYPE_SSID; + *tag++ = len; + memcpy(tag, ieee->current_network.ssid, len); + tag += len; + + rtllib_MFIE_Brate(ieee,&tag); + rtllib_MFIE_Grate(ieee,&tag); + +#ifdef _RTL8192_EXT_PATCH_ + if(extMore) + ieee->ext_patch_rtllib_probe_req_2(ieee, skb, tag); +#endif + + if(0) + { +#ifdef _RTL8192_EXT_PATCH_ + crypt = ieee->sta_crypt[ieee->tx_keyidx]; +#else + crypt = ieee->crypt[ieee->tx_keyidx]; +#endif + if(crypt != NULL) { + encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len)); + } else { + encrypt = 0; + } + + ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap); + ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap); +#ifdef _RTL8192_EXT_PATCH_ + HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt, 0, false); +#else + HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt, false); +#endif + if(ht_cap_len){ + *(tag++) = MFIE_TYPE_HT_CAP; + *(tag++) = ht_cap_len - 2; + memcpy(tag, ht_cap_buf, ht_cap_len - 2); + tag += ht_cap_len - 2; + } + } + + return skb; +} + +struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee); + +#ifdef _RTL8192_EXT_PATCH_ +void ext_rtllib_send_beacon_wq(void *data) +{ + struct rtllib_device *ieee = (struct rtllib_device *)container_of_work_rsl((struct work_struct *)data, struct rtllib_device, ext_send_beacon_wq); + struct sk_buff *skb; + + skb = rtllib_get_beacon_(ieee); + + if (skb){ + softmac_mgmt_xmit(skb, ieee); + ieee->softmac_stats.tx_beacons++; + } + + + +} +#endif +void rtllib_send_beacon(struct rtllib_device *ieee) +{ + struct sk_buff *skb; + if(!ieee->ieee_up) + return; + skb = rtllib_get_beacon_(ieee); + + if (skb){ + softmac_mgmt_xmit(skb, ieee); + ieee->softmac_stats.tx_beacons++; + } + + if(ieee->beacon_txing && ieee->ieee_up){ + mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5))); + } +} + + +void rtllib_send_beacon_cb(unsigned long _ieee) +{ + struct rtllib_device *ieee = + (struct rtllib_device *) _ieee; + unsigned long flags; + + spin_lock_irqsave(&ieee->beacon_lock, flags); + rtllib_send_beacon(ieee); + spin_unlock_irqrestore(&ieee->beacon_lock, flags); +} + +#ifdef _RTL8192_EXT_PATCH_ + +inline struct sk_buff *rtllib_probe_req_with_SSID(struct rtllib_device *ieee, char *ssid, int len_ssid) +{ + unsigned int len,rate_len; + u8 *tag; + struct sk_buff *skb; + struct rtllib_probe_request *req; + +#ifdef _RTL8192_EXT_PATCH_ + short extMore = 0; + if(ieee->ext_patch_rtllib_probe_req_1) + extMore = ieee->ext_patch_rtllib_probe_req_1(ieee); +#endif + + len = len_ssid; + + rate_len = rtllib_MFIE_rate_len(ieee); + +#ifdef _RTL8192_EXT_PATCH_ + if(!extMore) +#endif + skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) + + 2 + len + rate_len + ieee->tx_headroom); +#ifdef _RTL8192_EXT_PATCH_ + else + skb = dev_alloc_skb(sizeof(struct rtllib_probe_request) + + 2 + len + rate_len+128+ieee->tx_headroom); +#endif + + if (!skb) + return NULL; + + req = (struct rtllib_probe_request *) skb_put(skb,sizeof(struct rtllib_probe_request)); + req->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_REQ); + req->header.duration_id = 0; + + memset(req->header.addr1, 0xff, ETH_ALEN); + memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memset(req->header.addr3, 0xff, ETH_ALEN); + + tag = (u8 *) skb_put(skb,len+2+rate_len); + + *tag++ = MFIE_TYPE_SSID; + *tag++ = len; + if(len) + { + memcpy(tag, ssid, len); + tag += len; + } + + rtllib_MFIE_Brate(ieee,&tag); + rtllib_MFIE_Grate(ieee,&tag); + +#ifdef _RTL8192_EXT_PATCH_ + if(extMore) + ieee->ext_patch_rtllib_probe_req_2(ieee, skb, tag); +#endif + return skb; +} + +#endif + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) +void rtllib_ibss_wait_timeout(unsigned long _ieee) +{ + struct rtllib_device *ieee = + (struct rtllib_device *) _ieee; + printk("======>%s():oh oh ibss wait beacon time out, search a new ibss now\n",__FUNCTION__); + rtllib_stop_send_beacons(ieee); +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + cancel_delayed_work(&ieee->start_ibss_wq); + cancel_delayed_work(&ieee->link_change_wq); +#endif + rtllib_stop_scan(ieee); + queue_delayed_work_rsl(ieee->wq, &ieee->start_ibss_wq, MSECS(150)); +} +#endif + + +/* + * Description: + * Enable network monitor mode, all rx packets will be received. + */ +void rtllib_EnableNetMonitorMode(struct net_device* dev, + bool bInitState) +{ + struct rtllib_device* ieee = netdev_priv_rsl(dev); + + printk("========>Enter Monitor Mode\n"); + + ieee->AllowAllDestAddrHandler(dev, true, !bInitState); +} + + +/* + * Description: + * Disable network network monitor mode, only packets destinated to + * us will be received. + */ +void rtllib_DisableNetMonitorMode(struct net_device* dev, + bool bInitState) +{ + struct rtllib_device* ieee = netdev_priv_rsl(dev); + + printk("========>Exit Monitor Mode\n"); + + ieee->AllowAllDestAddrHandler(dev, false, !bInitState); +} + + +/* + * Description: + * This enables the specialized promiscuous mode required by Intel. + * In this mode, Intel intends to hear traffics from/to other STAs in the same BSS. + * Therefore we don't have to disable checking BSSID and we only need to allow all dest. + * BUT: if we enable checking BSSID then we can't recv packets from other STA. + */ +void rtllib_EnableIntelPromiscuousMode(struct net_device* dev, + bool bInitState) +{ + bool bFilterOutNonAssociatedBSSID = false; + + struct rtllib_device* ieee = netdev_priv_rsl(dev); + + printk("========>Enter Intel Promiscuous Mode\n"); + + ieee->AllowAllDestAddrHandler(dev, true, !bInitState); + ieee->SetHwRegHandler(dev, HW_VAR_CECHK_BSSID, (u8*)&bFilterOutNonAssociatedBSSID); + + ieee->bNetPromiscuousMode = true; +} + + +/* + * Description: + * This disables the specialized promiscuous mode required by Intel. + * See MgntEnableIntelPromiscuousMode for detail. + */ +void rtllib_DisableIntelPromiscuousMode(struct net_device* dev, + bool bInitState) +{ + bool bFilterOutNonAssociatedBSSID = true; + + struct rtllib_device* ieee = netdev_priv_rsl(dev); + + printk("========>Exit Intel Promiscuous Mode\n"); + + ieee->AllowAllDestAddrHandler(dev, false, !bInitState); + ieee->SetHwRegHandler(dev, HW_VAR_CECHK_BSSID, (u8*)&bFilterOutNonAssociatedBSSID); + + ieee->bNetPromiscuousMode = false; +} + +void rtllib_send_probe(struct rtllib_device *ieee, u8 is_mesh) +{ + struct sk_buff *skb; +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + skb = rtllib_probe_req_with_SSID(ieee, NULL, 0); + else +#endif + skb = rtllib_probe_req(ieee); + if (skb){ + softmac_mgmt_xmit(skb, ieee); + ieee->softmac_stats.tx_probe_rq++; + } +} + + +void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh) +{ +#ifdef _RTL8192_EXT_PATCH_ + if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){ + rtllib_send_probe(ieee,is_mesh); + rtllib_send_probe(ieee,is_mesh); + } +#else + if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){ + rtllib_send_probe(ieee, 0); + rtllib_send_probe(ieee, 0); +} +#endif +} + +void rtllib_softmac_hint11d_wq(void *data) +{ +#ifdef CONFIG_CRDA + struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, softmac_hint11d_wq); + PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); + struct wireless_dev *wdev = &ieee->wdev; + + regulatory_hint_11d(wdev->wiphy, pDot11dInfo->CountryIeBuf, pDot11dInfo->CountryIeLen); +#endif +} + +void rtllib_update_active_chan_map(struct rtllib_device *ieee) +{ +#ifdef ENABLE_DOT11D + memcpy(ieee->active_channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); +#else + memcpy(ieee->active_channel_map, ieee->channel_map, MAX_CHANNEL_NUMBER+1); +#endif +#if 0 + { + int i; + for(i=1;i<=14;i++) + printk("%d ", ieee->active_channel_map[i]); + printk("\n"); + } +#endif +} + +/* this performs syncro scan blocking the caller until all channels + * in the allowed channel map has been checked. + */ +void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) +{ + short ch = 0; + + rtllib_update_active_chan_map(ieee); + + ieee->be_scan_inprogress = true; + + down(&ieee->scan_sem); + + while(1) + { + + do { + ch++; + if (ch > MAX_CHANNEL_NUMBER) + goto out; /* scan completed */ + } while(!ieee->active_channel_map[ch]); + + /* this fuction can be called in two situations + * 1- We have switched to ad-hoc mode and we are + * performing a complete syncro scan before conclude + * there are no interesting cell and to create a + * new one. In this case the link state is + * RTLLIB_NOLINK until we found an interesting cell. + * If so the ieee8021_new_net, called by the RX path + * will set the state to RTLLIB_LINKED, so we stop + * scanning + * 2- We are linked and the root uses run iwlist scan. + * So we switch to RTLLIB_LINKED_SCANNING to remember + * that we are still logically linked (not interested in + * new network events, despite for updating the net list, + * but we are temporarly 'unlinked' as the driver shall + * not filter RX frames and the channel is changing. + * So the only situation in witch are interested is to check + * if the state become LINKED because of the #1 situation + */ + + if (ieee->state == RTLLIB_LINKED) + goto out; + if (ieee->sync_scan_hurryup){ + printk("============>sync_scan_hurryup out\n"); + goto out; + } + + ieee->set_chan(ieee->dev, ch); + if(ieee->active_channel_map[ch] == 1) +#ifdef _RTL8192_EXT_PATCH_ + rtllib_send_probe_requests(ieee, is_mesh); +#else + rtllib_send_probe_requests(ieee, 0); +#endif + + /* this prevent excessive time wait when we + * need to wait for a syncro scan to end.. + */ + msleep_interruptible_rsl(RTLLIB_SOFTMAC_SCAN_TIME); + } +out: + ieee->actscanning = false; + ieee->sync_scan_hurryup = 0; + + if(ieee->state >= RTLLIB_LINKED){ +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee)) + DOT11D_ScanComplete(ieee); +#endif + } + up(&ieee->scan_sem); + + ieee->be_scan_inprogress = false; + +#ifndef FOR_MOBLIN + { + union iwreq_data wrqu; + memset(&wrqu, 0, sizeof(wrqu)); + wireless_send_event(ieee->dev,SIOCGIWSCAN,&wrqu,NULL); + } +#endif +} + +void rtllib_softmac_scan_wq(void *data) +{ + struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, softmac_scan_wq); + +#ifndef _RTL8192_EXT_PATCH_ + u8 last_channel = ieee->current_network.channel; +#endif + rtllib_update_active_chan_map(ieee); + + if(!ieee->ieee_up) + return; + if(rtllib_act_scanning(ieee,true) == true) + return; + + down(&ieee->scan_sem); + + if(ieee->eRFPowerState == eRfOff) + { + printk("======>%s():rf state is eRfOff, return\n",__FUNCTION__); + goto out1; + } + + do{ + ieee->current_network.channel = + (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER; + if (ieee->scan_watch_dog++ > MAX_CHANNEL_NUMBER) + { + if (!ieee->active_channel_map[ieee->current_network.channel]) + ieee->current_network.channel = 6; + goto out; /* no good chans */ + } + } while(!ieee->active_channel_map[ieee->current_network.channel]); + + if (ieee->scanning_continue == 0 ) + goto out; + + ieee->set_chan(ieee->dev, ieee->current_network.channel); + + if(ieee->active_channel_map[ieee->current_network.channel] == 1) +#ifdef _RTL8192_EXT_PATCH_ + rtllib_send_probe_requests(ieee, 0); +#else + rtllib_send_probe_requests(ieee, 0); +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,40) + queue_delayed_work_rsl(ieee->wq, &ieee->softmac_scan_wq, MSECS(RTLLIB_SOFTMAC_SCAN_TIME)); +#else + if (ieee->scanning_continue == 1) + mod_timer(&ieee->scan_timer,(jiffies + MSECS(RTLLIB_SOFTMAC_SCAN_TIME))); +#endif + + up(&ieee->scan_sem); + return; + +out: +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee)) + DOT11D_ScanComplete(ieee); +#endif +#ifdef _RTL8192_EXT_PATCH_ + ieee->current_network.channel = ieee->backup_channel; + ieee->set_chan(ieee->dev, ieee->current_network.channel); +#else + ieee->current_network.channel = last_channel; +#endif + +out1: + ieee->actscanning = false; + ieee->scan_watch_dog = 0; + ieee->scanning_continue = 0; + up(&ieee->scan_sem); +} + + + +void rtllib_beacons_start(struct rtllib_device *ieee) +{ + unsigned long flags; + spin_lock_irqsave(&ieee->beacon_lock,flags); + + ieee->beacon_txing = 1; + rtllib_send_beacon(ieee); + + spin_unlock_irqrestore(&ieee->beacon_lock,flags); +} + +void rtllib_beacons_stop(struct rtllib_device *ieee) +{ + unsigned long flags; + + spin_lock_irqsave(&ieee->beacon_lock,flags); + + ieee->beacon_txing = 0; + del_timer_sync(&ieee->beacon_timer); + + spin_unlock_irqrestore(&ieee->beacon_lock,flags); + +} + + +void rtllib_stop_send_beacons(struct rtllib_device *ieee) +{ + if(ieee->stop_send_beacons) + ieee->stop_send_beacons(ieee->dev); + if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS) + rtllib_beacons_stop(ieee); +} + + +void rtllib_start_send_beacons(struct rtllib_device *ieee) +{ + if(ieee->start_send_beacons) + ieee->start_send_beacons(ieee->dev); + if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS) + rtllib_beacons_start(ieee); +} + + +void rtllib_softmac_stop_scan(struct rtllib_device *ieee) +{ + + + down(&ieee->scan_sem); + ieee->scan_watch_dog = 0; + if (ieee->scanning_continue == 1){ + ieee->scanning_continue = 0; + ieee->actscanning = 0; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,40) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,67) + cancel_delayed_work(&ieee->softmac_scan_wq); +#endif +#else + del_timer_sync(&ieee->scan_timer); +#endif + } + + up(&ieee->scan_sem); +} + +void rtllib_stop_scan(struct rtllib_device *ieee) +{ + if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){ + rtllib_softmac_stop_scan(ieee); + }else{ + if(ieee->rtllib_stop_hw_scan) + ieee->rtllib_stop_hw_scan(ieee->dev); + } +} + +void rtllib_stop_scan_syncro(struct rtllib_device *ieee) +{ + if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){ + ieee->sync_scan_hurryup = 1; + }else{ + if(ieee->rtllib_stop_hw_scan) + ieee->rtllib_stop_hw_scan(ieee->dev); + } +} + +bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan) +{ + if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){ + if(sync_scan){ + return ieee->be_scan_inprogress; + }else{ + return (ieee->actscanning ||ieee->be_scan_inprogress); + } + }else{ + return test_bit(STATUS_SCANNING, &ieee->status); + } +} + +/* called with ieee->lock held */ +void rtllib_start_scan(struct rtllib_device *ieee) +{ + printk("===>%s()\n",__FUNCTION__); +#ifdef ENABLE_IPS + if(ieee->rtllib_ips_leave_wq != NULL) + ieee->rtllib_ips_leave_wq(ieee->dev); +#endif + + +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee) ) + { + if(IS_COUNTRY_IE_VALID(ieee)) + { + RESET_CIE_WATCHDOG(ieee); + } + } +#endif + if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){ + if (ieee->scanning_continue == 0){ + ieee->actscanning = true; + ieee->scanning_continue = 1; +#ifdef _RTL8192_EXT_PATCH_ + ieee->backup_channel = ieee->current_network.channel; + printk("===>backup_channel is %d\n",ieee->backup_channel); +#endif + queue_delayed_work_rsl(ieee->wq, &ieee->softmac_scan_wq, 0); + } + }else{ + if(ieee->rtllib_start_hw_scan) + ieee->rtllib_start_hw_scan(ieee->dev); + } + +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,40) +void rtllib_softmac_scan_cb(unsigned long _dev) +{ + unsigned long flags; + struct rtllib_device *ieee = (struct rtllib_device *)_dev; + + spin_lock_irqsave(&ieee->lock, flags); + rtllib_start_scan(ieee); + spin_unlock_irqrestore(&ieee->lock, flags); +} +#endif + +/* called with wx_sem held */ +void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh) +{ +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee) ) + { + if(IS_COUNTRY_IE_VALID(ieee)) + { + RESET_CIE_WATCHDOG(ieee); + } + } +#endif + ieee->sync_scan_hurryup = 0; + if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){ + rtllib_softmac_scan_syncro(ieee, is_mesh); + }else{ + if(ieee->rtllib_start_hw_scan) + ieee->rtllib_start_hw_scan(ieee->dev); + } + +} + +inline struct sk_buff *rtllib_authentication_req(struct rtllib_network *beacon, + struct rtllib_device *ieee, int challengelen,u8 * daddr) +{ + struct sk_buff *skb; + struct rtllib_authentication *auth; + int len = 0; +#ifdef _RTL8192_EXT_PATCH_ + bool is_mesh = false; + is_mesh = ieee->ext_patch_rtllib_is_mesh(ieee,daddr); +#endif +#ifdef _RTL8192_EXT_PATCH_ + if((ieee->mesh_sec_type == 1) && (ieee->mesh_security_setting == 3) && is_mesh){ + skb = ieee->ext_patch_rtllib_send_ath_commit(ieee,daddr); + return skb; + } +#endif + len = sizeof(struct rtllib_authentication) + challengelen + ieee->tx_headroom + 4; +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr; + int alignment; + skb = dev_alloc_skb(len + USB_512B_ALIGNMENT_SIZE); +#else + skb = dev_alloc_skb(len); +#endif + + if (!skb) return NULL; + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + + skb_reserve(skb, ieee->tx_headroom); + + auth = (struct rtllib_authentication *) + skb_put(skb, sizeof(struct rtllib_authentication)); + + auth->header.frame_ctl = RTLLIB_STYPE_AUTH; + if (challengelen) auth->header.frame_ctl |= RTLLIB_FCTL_WEP; + + auth->header.duration_id = 0x013a; +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + memcpy(auth->header.addr1,daddr,ETH_ALEN); + else +#endif + memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN); + memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + memcpy(auth->header.addr3, ieee->current_mesh_network.bssid, ETH_ALEN); + else + memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN); +#else + memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN); +#endif + if(ieee->auth_mode == 0) + auth->algorithm = WLAN_AUTH_OPEN; + else if(ieee->auth_mode == 1) + auth->algorithm = WLAN_AUTH_SHARED_KEY; + else if(ieee->auth_mode == 2) + auth->algorithm = WLAN_AUTH_OPEN; + auth->transaction = cpu_to_le16(ieee->associate_seq); + ieee->associate_seq++; + + auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS); + + return skb; + +} + +void constructWMMIE(u8* wmmie, u8* wmm_len,u8 oui_subtype) +{ + u8 szQoSOUI[] ={221, 0, 0x00, 0x50, 0xf2, 0x02, 0, 1}; + + if (oui_subtype == OUI_SUBTYPE_QOS_CAPABI) + { + szQoSOUI[0] = 46; + szQoSOUI[1] = *wmm_len; + memcpy(wmmie,szQoSOUI,3); + *wmm_len = 3; + } + else + { + szQoSOUI[1] = *wmm_len + 6; + szQoSOUI[6] = oui_subtype; + memcpy(wmmie, szQoSOUI, 8); + *(wmmie+8) = 0; + *wmm_len = 9; + } +} + +static struct sk_buff* rtllib_probe_resp(struct rtllib_device *ieee, u8 *dest) +{ + u8 *tag; + int beacon_size; + struct rtllib_probe_response *beacon_buf; + struct sk_buff *skb = NULL; + int encrypt; + int atim_len,erp_len; + struct rtllib_crypt_data* crypt; + + char *ssid = ieee->current_network.ssid; + int ssid_len = ieee->current_network.ssid_len; + int rate_len = ieee->current_network.rates_len+2; + int rate_ex_len = ieee->current_network.rates_ex_len; + int wpa_ie_len = ieee->wpa_ie_len; + u8 erpinfo_content = 0; + + u8* tmp_ht_cap_buf=NULL; + u8 tmp_ht_cap_len=0; + u8* tmp_ht_info_buf=NULL; + u8 tmp_ht_info_len=0; + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + u8* tmp_generic_ie_buf=NULL; + u8 tmp_generic_ie_len=0; +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + u8 wmmie[9] = {0}; + u8 wmm_len = 0; +#endif +#ifdef RTL8192S_WAPI_SUPPORT + PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo); + u8 pWapiIELen = 0; +#endif + if(rate_ex_len > 0) rate_ex_len+=2; + + if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS) + atim_len = 4; + else + atim_len = 0; + +#if 0 + if(rtllib_is_54g(&ieee->current_network)) + erp_len = 3; + else + erp_len = 0; +#else + if((ieee->current_network.mode == IEEE_G) + ||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) { + erp_len = 3; + erpinfo_content = 0; + if(ieee->current_network.buseprotection) + erpinfo_content |= ERP_UseProtection; + } + else + erp_len = 0; +#endif + +#ifdef _RTL8192_EXT_PATCH_ + crypt = ieee->sta_crypt[ieee->tx_keyidx]; +#else + crypt = ieee->crypt[ieee->tx_keyidx]; +#endif + encrypt = ieee->host_encrypt && crypt && crypt->ops && + ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len)); +#if 1 + if(ieee->pHTInfo->bCurrentHTSupport){ + tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap); + tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap); + tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo); + tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo); +#ifdef _RTL8192_EXT_PATCH_ + HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt, 1, false); +#else + HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt, false); +#endif + HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt); + + + if(pHTInfo->bRegRT2RTAggregation) + { + tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer; + tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer); + HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len); + } + } +#endif + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + if(ieee->iw_mode == IW_MODE_ADHOC){ + if(ieee->current_network.qos_data.supported){ + wmm_len = 1; + constructWMMIE(wmmie,&wmm_len,OUI_SUBTYPE_WMM_INFO); + }else{ + wmm_len = 0; + } + } +#endif +#ifdef RTL8192S_WAPI_SUPPORT + if(ieee->WapiSupport && pWapiInfo->bWapiEnable) + { + WapiSetIE(ieee); + pWapiIELen = pWapiInfo->wapiIELength; + } +#endif + beacon_size = sizeof(struct rtllib_probe_response)+2+ + ssid_len + +3 + +rate_len + +rate_ex_len + +atim_len + +erp_len + +wpa_ie_len +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + +tmp_ht_cap_len + +tmp_ht_info_len + +tmp_generic_ie_len + +wmm_len +#endif +#ifdef RTL8192S_WAPI_SUPPORT + +pWapiIELen+2 +#endif + +ieee->tx_headroom; +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr=0; + int alignment=0; + skb = dev_alloc_skb(beacon_size + USB_512B_ALIGNMENT_SIZE); +#else + skb = dev_alloc_skb(beacon_size); +#endif + if (!skb) + return NULL; + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + + skb_reserve(skb, ieee->tx_headroom); + + beacon_buf = (struct rtllib_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom)); + memcpy (beacon_buf->header.addr1, dest,ETH_ALEN); + memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN); + + beacon_buf->header.duration_id = 0; + beacon_buf->beacon_interval = + cpu_to_le16(ieee->current_network.beacon_interval); + beacon_buf->capability = + cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS); + beacon_buf->capability |= + cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); + + if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) + cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME)); + +#ifndef _RTL8192_EXT_PATCH_ + crypt = ieee->crypt[ieee->tx_keyidx]; +#endif + if (encrypt) + beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); + + + beacon_buf->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_RESP); + beacon_buf->info_element[0].id = MFIE_TYPE_SSID; + beacon_buf->info_element[0].len = ssid_len; + + tag = (u8*) beacon_buf->info_element[0].data; + + memcpy(tag, ssid, ssid_len); + + tag += ssid_len; + + *(tag++) = MFIE_TYPE_RATES; + *(tag++) = rate_len-2; + memcpy(tag,ieee->current_network.rates,rate_len-2); + tag+=rate_len-2; + + *(tag++) = MFIE_TYPE_DS_SET; + *(tag++) = 1; + *(tag++) = ieee->current_network.channel; + + if(atim_len){ + u16 val16; + *(tag++) = MFIE_TYPE_IBSS_SET; + *(tag++) = 2; + val16 = cpu_to_le16(ieee->current_network.atim_window); + memcpy((u8 *)tag, (u8 *)&val16, 2); + tag+=2; + } + + if(erp_len){ + *(tag++) = MFIE_TYPE_ERP; + *(tag++) = 1; + *(tag++) = erpinfo_content; + } +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + if(tmp_ht_cap_len){ + *(tag++) = MFIE_TYPE_HT_CAP; + *(tag++) = tmp_ht_cap_len - 2; + memcpy(tag, tmp_ht_cap_buf, tmp_ht_cap_len - 2); + tag += tmp_ht_cap_len - 2; + } +#endif + if(rate_ex_len){ + *(tag++) = MFIE_TYPE_RATES_EX; + *(tag++) = rate_ex_len-2; + memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2); + tag+=rate_ex_len-2; + } + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + if(tmp_ht_info_len){ + *(tag++) = MFIE_TYPE_HT_INFO; + *(tag++) = tmp_ht_info_len - 2; + memcpy(tag, tmp_ht_info_buf, tmp_ht_info_len -2); + tag += tmp_ht_info_len - 2; + } +#endif + + if (wpa_ie_len) + { + if (ieee->iw_mode == IW_MODE_ADHOC) + { + memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4); + } + memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); + tag += ieee->wpa_ie_len; + } + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + if(tmp_generic_ie_len) + { + (*tag++) = 0xdd; + (*tag++) = tmp_generic_ie_len - 2; + memcpy(tag,tmp_generic_ie_buf,tmp_generic_ie_len -2); + tag += tmp_generic_ie_len -2; + + } +#endif + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + if(wmm_len) { + memcpy(tag,wmmie,wmm_len); + tag += wmm_len; + } +#endif +#ifdef RTL8192S_WAPI_SUPPORT + if(pWapiIELen) + { + *(tag++) = MFIE_TYPE_WAPI; + *(tag++) = pWapiIELen; + memcpy(tag, pWapiInfo->wapiIE, pWapiIELen); + tag += pWapiIELen; + + pWapiInfo->sendbeaconWapiIE[0] = MFIE_TYPE_WAPI; + pWapiInfo->sendbeaconWapiIE[1] = pWapiIELen; + pWapiInfo->sendbeaconWapiIELength = pWapiIELen+2; + memcpy(pWapiInfo->sendbeaconWapiIE+2, pWapiInfo->wapiIE, pWapiIELen); + } +#endif + return skb; +} + +#ifdef RTL8192S_WAPI_SUPPORT +void ConstructWapiIEForInit(struct rtllib_device* ieee) +{ + PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo); + u8 pWapiIELen = 0; + + if(ieee->WapiSupport && pWapiInfo->bWapiEnable){ + WapiSetIE(ieee); + pWapiIELen = pWapiInfo->wapiIELength; + if(pWapiIELen){ + pWapiInfo->sendbeaconWapiIE[0] = MFIE_TYPE_WAPI; + pWapiInfo->sendbeaconWapiIE[1] = pWapiIELen; + pWapiInfo->sendbeaconWapiIELength = pWapiIELen+2; + memcpy(pWapiInfo->sendbeaconWapiIE+2, pWapiInfo->wapiIE, pWapiIELen); + } + } +} +#endif + +#ifdef _RTL8192_EXT_PATCH_ +#ifdef COMPATIBLE_WITH_RALINK_MESH +extern void ConstructRalinkHostNameIE(struct rtllib_device* ieee, + u8* p_hostname_ie, u8* hostname_ie_len); +#else +extern void ConstructHostNameIE(struct rtllib_device* ieee, + u8* hostname_ie, u8* hostname_ie_len); +#endif +struct sk_buff* rtllib_ext_probe_resp_by_net(struct rtllib_device *ieee, u8 *dest, struct rtllib_network *net) +{ + u8 *tag; + int beacon_size; + struct rtllib_probe_response *beacon_buf; + struct sk_buff *skb; + int encrypt; + int atim_len = 0,erp_len = 0; + struct rtllib_crypt_data* crypt; + u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff}; + + char *ssid = net->ssid; + int ssid_len = net->ssid_len; + + int rate_len = ieee->current_mesh_network.rates_len+2; + int rate_ex_len = ieee->current_mesh_network.rates_ex_len; + int wpa_ie_len = 0; + u8 erpinfo_content = 0; +#if 0 + u8* tmp_ht_cap_buf=NULL; + u8 tmp_ht_cap_len=0; + u8* tmp_ht_info_buf=NULL; + u8 tmp_ht_info_len=0; + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + u8* tmp_generic_ie_buf=NULL; + u8 tmp_generic_ie_len=0; +#endif + u8 wmmie[9] = {0}; + u8 wmm_len = 0; + u8 hostname_ie_buf[MAX_HOST_NAME_LENGTH+4]; + u8 hostname_ie_len=0; + if(rate_ex_len > 0) rate_ex_len+=2; + if( ieee->meshScanMode&4){ + ieee->current_mesh_network.channel = ieee->ext_patch_rtllib_ext_stop_scan_wq_set_channel(ieee); + if(ieee->current_mesh_network.channel == 0) + ieee->current_mesh_network.channel = 1; + } + if( ieee->meshScanMode&6) + { + queue_work_rsl(ieee->wq, &ieee->ext_stop_scan_wq); + } + if(ieee->current_mesh_network.capability & WLAN_CAPABILITY_IBSS) + atim_len = 4; + else + atim_len = 0; + + + if((ieee->current_mesh_network.mode == IEEE_G) + ||( ieee->mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)){ + erp_len = 3; + erpinfo_content = 0; + if(ieee->bUseProtection) + erpinfo_content |= ERP_UseProtection; + } + else + erp_len = 0; + + if ((IW_MODE_MESH==ieee->iw_mode)) + { + wpa_ie_len = ieee->wpa_ie_len; + } + + crypt = ieee->cryptlist[0]->crypt[ieee->mesh_txkeyidx]; + + encrypt = ieee->host_encrypt && crypt && crypt->ops && + ((0 == strcmp(crypt->ops->name, "WEP")||wpa_ie_len)); +#if 0 + if(ieee->pHTInfo->bCurrentHTSupport){ + tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap); + tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap); + tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo); + tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo); + HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt, 1); + HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt); + + + if(pHTInfo->bRegRT2RTAggregation) + { + tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer; + tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer); + HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len); + } + } +#endif + { +#ifdef COMPATIBLE_WITH_RALINK_MESH + ConstructRalinkHostNameIE(ieee, hostname_ie_buf, &hostname_ie_len); +#else + ConstructHostNameIE(ieee, hostname_ie_buf, &hostname_ie_len); +#endif + } + if((ieee->iw_mode == IW_MODE_MESH) && (ieee->current_mesh_network.qos_data.supported == 1)){ + wmm_len = 1; + constructWMMIE(wmmie,&wmm_len,OUI_SUBTYPE_WMM_INFO); + } + beacon_size = sizeof(struct rtllib_probe_response)+2+ + ssid_len + +3 + +rate_len + +rate_ex_len + +atim_len + +erp_len + +wpa_ie_len +#if 0 + +tmp_ht_cap_len + +tmp_ht_info_len + +tmp_generic_ie_len +#endif + +hostname_ie_len + +wmm_len + +ieee->tx_headroom; + skb = dev_alloc_skb(beacon_size+300); + + if (!skb) + return NULL; + skb_reserve(skb, ieee->tx_headroom); + beacon_buf = (struct rtllib_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom)); + + memcpy (beacon_buf->header.addr1, dest,ETH_ALEN); + memcpy (beacon_buf->header.addr2, ieee->meshdev->dev_addr, ETH_ALEN); + memcpy (beacon_buf->header.addr3, ieee->current_mesh_network.bssid, ETH_ALEN); + + beacon_buf->header.duration_id = 0; + + beacon_buf->beacon_interval = + cpu_to_le16(ieee->current_mesh_network.beacon_interval); + beacon_buf->capability = + cpu_to_le16(ieee->current_mesh_network.capability & WLAN_CAPABILITY_IBSS); + + if(ieee->short_slot && (ieee->current_mesh_network.capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) + cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT_TIME)); + + if (encrypt) + beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); + + + beacon_buf->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_PROBE_RESP); + + beacon_buf->info_element[0].id = MFIE_TYPE_SSID; + beacon_buf->info_element[0].len = ssid_len; + + tag = (u8*) beacon_buf->info_element[0].data; + + if(memcmp(dest, broadcast_addr, ETH_ALEN )) + memcpy(tag, ssid, ssid_len); + else + ssid_len=0; + + tag += ssid_len; + + + *(tag++) = MFIE_TYPE_RATES; + *(tag++) = rate_len-2; + memcpy(tag,ieee->current_mesh_network.rates,rate_len-2); + tag+=rate_len-2; + + *(tag++) = MFIE_TYPE_DS_SET; + *(tag++) = 1; + *(tag++) = ieee->current_mesh_network.channel; + + + if(atim_len){ + u16 val16; + *(tag++) = MFIE_TYPE_IBSS_SET; + *(tag++) = 2; + val16 = cpu_to_le16(ieee->current_mesh_network.atim_window); + memcpy((u8 *)tag, (u8 *)&val16, 2); + tag+=2; + } + + if(erp_len){ + *(tag++) = MFIE_TYPE_ERP; + *(tag++) = 1; + *(tag++) = erpinfo_content; + } +#if 0 + if(tmp_ht_cap_len){ + *(tag++) = MFIE_TYPE_HT_CAP; + *(tag++) = tmp_ht_cap_len - 2; + memcpy(tag, tmp_ht_cap_buf, tmp_ht_cap_len - 2); + tag += tmp_ht_cap_len - 2; + } +#endif + + if(rate_ex_len){ + *(tag++) = MFIE_TYPE_RATES_EX; + *(tag++) = rate_ex_len-2; + memcpy(tag,ieee->current_mesh_network.rates_ex,rate_ex_len-2); + tag+=rate_ex_len-2; + } + +#if 0 + if(tmp_ht_info_len){ + *(tag++) = MFIE_TYPE_HT_INFO; + *(tag++) = tmp_ht_info_len - 2; + memcpy(tag, tmp_ht_info_buf, tmp_ht_info_len -2); + tag += tmp_ht_info_len - 2; + } +#endif + if (wpa_ie_len) { + memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); + tag+=ieee->wpa_ie_len; + } + +#if 0 + if(tmp_generic_ie_len) + { + (*tag++) = 0xdd; + (*tag++) = tmp_generic_ie_len - 2; + memcpy(tag,tmp_generic_ie_buf,tmp_generic_ie_len -2); + tag += tmp_generic_ie_len -2; + + } +#endif + if(hostname_ie_len) + { + (*tag++) = 0xdd; + (*tag++) = hostname_ie_len - 2; + memcpy(tag, hostname_ie_buf, hostname_ie_len - 2); + tag += hostname_ie_len -2; + } + + if(wmm_len) + { + memcpy(tag,wmmie,wmm_len); + } + + skb->dev = ieee->dev; + return skb; +} +#endif + +struct sk_buff* rtllib_assoc_resp(struct rtllib_device *ieee, u8 *dest) +{ + struct sk_buff *skb; + u8* tag; + + struct rtllib_crypt_data* crypt; + struct rtllib_assoc_response_frame *assoc; + short encrypt; + + unsigned int rate_len = rtllib_MFIE_rate_len(ieee); + int len = sizeof(struct rtllib_assoc_response_frame) + rate_len + ieee->tx_headroom; + +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr=0; + int alignment=0; + skb = dev_alloc_skb(len + USB_512B_ALIGNMENT_SIZE); +#else + skb = dev_alloc_skb(len); +#endif + + if (!skb) + return NULL; + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + + skb_reserve(skb, ieee->tx_headroom); + + assoc = (struct rtllib_assoc_response_frame *) + skb_put(skb,sizeof(struct rtllib_assoc_response_frame)); + + assoc->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_ASSOC_RESP); + memcpy(assoc->header.addr1, dest,ETH_ALEN); + memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN); + memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ? + WLAN_CAPABILITY_ESS : WLAN_CAPABILITY_IBSS); + + + if(ieee->short_slot) + assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); + + if (ieee->host_encrypt){ +#ifdef _RTL8192_EXT_PATCH_ + crypt = ieee->cryptlist[0]->crypt[ieee->tx_keyidx]; +#else + crypt = ieee->crypt[ieee->tx_keyidx]; +#endif + + } + else crypt = NULL; + + encrypt = ( crypt && crypt->ops); + + if (encrypt) + assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); + + assoc->status = 0; + assoc->aid = cpu_to_le16(ieee->assoc_id); + if (ieee->assoc_id == 0x2007) + ieee->assoc_id=0; + else + ieee->assoc_id++; + + tag = (u8*) skb_put(skb, rate_len); + rtllib_MFIE_Brate(ieee, &tag); + rtllib_MFIE_Grate(ieee, &tag); + + return skb; +} + +struct sk_buff* rtllib_auth_resp(struct rtllib_device *ieee,int status, u8 *dest) +{ + struct sk_buff *skb = NULL; + struct rtllib_authentication *auth; + int len = ieee->tx_headroom + sizeof(struct rtllib_authentication)+1; +#ifdef _RTL8192_EXT_PATCH_ + bool is_mesh = ieee->ext_patch_rtllib_is_mesh(ieee,dest); + if(is_mesh && (ieee->mesh_sec_type == 1) && (ieee->mesh_security_setting == 3)) + skb = ieee->ext_patch_rtllib_send_ath_confirm(ieee,dest); + return skb; +#endif +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr=0; + int alignment=0; + skb = dev_alloc_skb(len + USB_512B_ALIGNMENT_SIZE); +#else + skb = dev_alloc_skb(len); +#endif + if (!skb) + return NULL; + + skb->len = sizeof(struct rtllib_authentication); + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + + skb_reserve(skb, ieee->tx_headroom); + + auth = (struct rtllib_authentication *) + skb_put(skb, sizeof(struct rtllib_authentication)); + + auth->status = cpu_to_le16(status); + auth->transaction = cpu_to_le16(2); + auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN); + +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + memset(auth->header.addr3, 0, ETH_ALEN); + else + memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN); +#else + memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN); +#endif + memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy(auth->header.addr1, dest, ETH_ALEN); + auth->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_AUTH); + return skb; + + +} + +struct sk_buff* rtllib_null_func(struct rtllib_device *ieee,short pwr) +{ + struct sk_buff *skb; + struct rtllib_hdr_3addr* hdr; + +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr=0; + int alignment=0; + skb = dev_alloc_skb(sizeof(struct rtllib_hdr_3addr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE); +#else + skb = dev_alloc_skb(sizeof(struct rtllib_hdr_3addr)+ieee->tx_headroom); +#endif + if (!skb) + return NULL; + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + skb_reserve(skb, ieee->tx_headroom); + + hdr = (struct rtllib_hdr_3addr*)skb_put(skb,sizeof(struct rtllib_hdr_3addr)); + + memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN); + memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN); + + hdr->frame_ctl = cpu_to_le16(RTLLIB_FTYPE_DATA | + RTLLIB_STYPE_NULLFUNC | RTLLIB_FCTL_TODS | + (pwr ? RTLLIB_FCTL_PM:0)); + + return skb; + + +} + +struct sk_buff* rtllib_pspoll_func(struct rtllib_device *ieee) +{ + struct sk_buff *skb; + struct rtllib_pspoll_hdr* hdr; + +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr=0; + int alignment=0; + skb = dev_alloc_skb(sizeof(struct rtllib_pspoll_hdr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE); +#else + skb = dev_alloc_skb(sizeof(struct rtllib_pspoll_hdr)+ieee->tx_headroom); +#endif + if (!skb) + return NULL; + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + skb_reserve(skb, ieee->tx_headroom); + + hdr = (struct rtllib_pspoll_hdr*)skb_put(skb,sizeof(struct rtllib_pspoll_hdr)); + + memcpy(hdr->bssid, ieee->current_network.bssid, ETH_ALEN); + memcpy(hdr->ta, ieee->dev->dev_addr, ETH_ALEN); + + hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000); + hdr->frame_ctl = cpu_to_le16(RTLLIB_FTYPE_CTL |RTLLIB_STYPE_PSPOLL | RTLLIB_FCTL_PM); + + return skb; + +} + +void rtllib_resp_to_assoc_rq(struct rtllib_device *ieee, u8* dest) +{ + struct sk_buff *buf = rtllib_assoc_resp(ieee, dest); + + if (buf) + softmac_mgmt_xmit(buf, ieee); +} + + +void rtllib_resp_to_auth(struct rtllib_device *ieee, int s, u8* dest) +{ + struct sk_buff *buf = rtllib_auth_resp(ieee, s, dest); + + if (buf) + softmac_mgmt_xmit(buf, ieee); +} + + +void rtllib_resp_to_probe(struct rtllib_device *ieee, u8 *dest) +{ + + struct sk_buff *buf = rtllib_probe_resp(ieee, dest); + if (buf) + softmac_mgmt_xmit(buf, ieee); +} + + +inline int SecIsInPMKIDList(struct rtllib_device *ieee, u8 *bssid) +{ + int i = 0; + + do + { + if ((ieee->PMKIDList[i].bUsed) && (memcmp(ieee->PMKIDList[i].Bssid, bssid, ETH_ALEN) == 0)) + { + break; + } + else + { + i++; + } + } while (i < NUM_PMKID_CACHE); + + if (i == NUM_PMKID_CACHE) + { + i = -1; + } + else + { + } + + return (i); + +} + + +inline struct sk_buff *rtllib_association_req(struct rtllib_network *beacon,struct rtllib_device *ieee) +{ + struct sk_buff *skb; + + struct rtllib_assoc_request_frame *hdr; + u8 *tag, *ies; + int i; + u8* ht_cap_buf = NULL; + u8 ht_cap_len=0; + u8* realtek_ie_buf=NULL; + u8 realtek_ie_len=0; + int wpa_ie_len= ieee->wpa_ie_len; + int wps_ie_len = ieee->wps_ie_len; + unsigned int ckip_ie_len=0; + unsigned int ccxrm_ie_len=0; + unsigned int cxvernum_ie_len=0; + struct rtllib_crypt_data* crypt; + int encrypt; + int PMKCacheIdx; + + unsigned int rate_len = (beacon->rates_len?(beacon->rates_len+2):0) + (beacon->rates_ex_len?(beacon->rates_ex_len)+2:0); + + unsigned int wmm_info_len = beacon->qos_data.supported?9:0; +#ifdef THOMAS_TURBO + unsigned int turbo_info_len = beacon->Turbo_Enable?9:0; +#endif + + int len = 0; +#ifdef RTL8192S_WAPI_SUPPORT + PRT_WAPI_BKID pWapiBKID; + u16 bkidNum; + PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo); + u8 WapiIE[256]; + u8 WapiIELength = 0; +#endif +#ifdef _RTL8192_EXT_PATCH_ + crypt = ieee->sta_crypt[ieee->tx_keyidx]; +#else + crypt = ieee->crypt[ieee->tx_keyidx]; +#endif + if(crypt != NULL) { + encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len)); + } else { + encrypt = 0; + } + +#ifdef ENABLE_TKIP11N + if (ieee->bForcedBgMode == true) +#else + if ((ieee->rtllib_ap_sec_type && (ieee->rtllib_ap_sec_type(ieee)&SEC_ALG_TKIP)) || (ieee->bForcedBgMode == true)) +#endif + { + ieee->pHTInfo->bEnableHT = 0; + ieee->mode = WIRELESS_MODE_G; + } + + if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT) + { + ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap); + ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap); +#ifdef _RTL8192_EXT_PATCH_ + HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt, 0, true); +#else + HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt, true); +#endif + if(ieee->pHTInfo->bCurrentRT2RTAggregation) + { + realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer; + realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer); + HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len); + + } + } + + if(beacon->bCkipSupported) + { + ckip_ie_len = 30+2; + } + if(beacon->bCcxRmEnable) + { + ccxrm_ie_len = 6+2; + } + if( beacon->BssCcxVerNumber >= 2 ) + { + cxvernum_ie_len = 5+2; + } + + PMKCacheIdx = SecIsInPMKIDList(ieee, ieee->current_network.bssid); + if (PMKCacheIdx >= 0) + { + wpa_ie_len += 18; + printk("[PMK cache]: WPA2 IE length: %x\n", wpa_ie_len); + } +#ifdef RTL8192S_WAPI_SUPPORT + if(ieee->WapiSupport && pWapiInfo->bWapiEnable) + { + wpa_ie_len = 0; + + WAPI_TRACE(WAPI_API, "%s(): Set WAPI IE in assoc req!!\n",__FUNCTION__); + WapiSetIE(ieee); + WapiIELength = pWapiInfo->wapiIELength; + memcpy(WapiIE, pWapiInfo->wapiIE ,pWapiInfo->wapiIELength); + + bkidNum = 0; + WapiIELength +=2; + if(!list_empty(&(pWapiInfo->wapiBKIDStoreList))){ + list_for_each_entry(pWapiBKID, &pWapiInfo->wapiBKIDStoreList, list) { + bkidNum ++; + memcpy(WapiIE+WapiIELength, pWapiBKID->bkid,16); + WapiIELength += 16; + } + + } + memcpy(WapiIE+pWapiInfo->wapiIELength,&bkidNum,2); + } +#endif + + len = sizeof(struct rtllib_assoc_request_frame)+ 2 + + beacon->ssid_len + + rate_len + + wpa_ie_len + + wps_ie_len +#ifdef RTL8192S_WAPI_SUPPORT + + WapiIELength + 2 +#endif + + wmm_info_len +#ifdef THOMAS_TURBO + + turbo_info_len +#endif + + ht_cap_len + + realtek_ie_len + + ckip_ie_len + + ccxrm_ie_len + + cxvernum_ie_len + + ieee->tx_headroom; + +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr=0; + int alignment=0; + skb = dev_alloc_skb(len + USB_512B_ALIGNMENT_SIZE); +#else + skb = dev_alloc_skb(len); +#endif + + if (!skb) + return NULL; + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + + skb_reserve(skb, ieee->tx_headroom); + + hdr = (struct rtllib_assoc_request_frame *) + skb_put(skb, sizeof(struct rtllib_assoc_request_frame)+2); + + + hdr->header.frame_ctl = RTLLIB_STYPE_ASSOC_REQ; + hdr->header.duration_id= 37; + memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN); + memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN); + + memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN); + + hdr->capability = cpu_to_le16(WLAN_CAPABILITY_ESS); + if (beacon->capability & WLAN_CAPABILITY_PRIVACY ) + hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); + + if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); + + if(ieee->short_slot && (beacon->capability&WLAN_CAPABILITY_SHORT_SLOT_TIME)) + hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); + + + hdr->listen_interval = beacon->listen_interval; + + hdr->info_element[0].id = MFIE_TYPE_SSID; + + hdr->info_element[0].len = beacon->ssid_len; + tag = skb_put(skb, beacon->ssid_len); + memcpy(tag, beacon->ssid, beacon->ssid_len); + + tag = skb_put(skb, rate_len); + + if(beacon->rates_len){ + *tag++ = MFIE_TYPE_RATES; + *tag++ = beacon->rates_len; + for(i=0;irates_len;i++){ + *tag++ = beacon->rates[i]; + } + } + + if(beacon->rates_ex_len){ + *tag++ = MFIE_TYPE_RATES_EX; + *tag++ = beacon->rates_ex_len; + for(i=0;irates_ex_len;i++){ + *tag++ = beacon->rates_ex[i]; + } + } + + if( beacon->bCkipSupported ) + { + static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; + u8 CcxAironetBuf[30]; + OCTET_STRING osCcxAironetIE; + + memset(CcxAironetBuf, 0,30); + osCcxAironetIE.Octet = CcxAironetBuf; + osCcxAironetIE.Length = sizeof(CcxAironetBuf); + memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui)); + + osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ; + tag = skb_put(skb, ckip_ie_len); + *tag++ = MFIE_TYPE_AIRONET; + *tag++ = osCcxAironetIE.Length; + memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length); + tag += osCcxAironetIE.Length; + } + + if(beacon->bCcxRmEnable) + { + static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00}; + OCTET_STRING osCcxRmCap; + + osCcxRmCap.Octet = CcxRmCapBuf; + osCcxRmCap.Length = sizeof(CcxRmCapBuf); + tag = skb_put(skb,ccxrm_ie_len); + *tag++ = MFIE_TYPE_GENERIC; + *tag++ = osCcxRmCap.Length; + memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length); + tag += osCcxRmCap.Length; + } + + if( beacon->BssCcxVerNumber >= 2 ) + { + u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00}; + OCTET_STRING osCcxVerNum; + CcxVerNumBuf[4] = beacon->BssCcxVerNumber; + osCcxVerNum.Octet = CcxVerNumBuf; + osCcxVerNum.Length = sizeof(CcxVerNumBuf); + tag = skb_put(skb,cxvernum_ie_len); + *tag++ = MFIE_TYPE_GENERIC; + *tag++ = osCcxVerNum.Length; + memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length); + tag += osCcxVerNum.Length; + } + if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){ + if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC) + { + tag = skb_put(skb, ht_cap_len); + *tag++ = MFIE_TYPE_HT_CAP; + *tag++ = ht_cap_len - 2; + memcpy(tag, ht_cap_buf,ht_cap_len -2); + tag += ht_cap_len -2; + } + } + + + if (wpa_ie_len){ + tag = skb_put(skb, ieee->wpa_ie_len); + memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); + + if (PMKCacheIdx >= 0) + { + tag = skb_put(skb, 18); + *tag = 1; + *(tag + 1) = 0; + memcpy((tag + 2), &ieee->PMKIDList[PMKCacheIdx].PMKID, 16); + } + } +#ifdef RTL8192S_WAPI_SUPPORT + if(WapiIELength){ + tag = skb_put(skb, WapiIELength+2); + *tag = MFIE_TYPE_WAPI; + *(tag+1) = WapiIELength; + memcpy((tag+2), WapiIE, WapiIELength); + + pWapiInfo->assoReqWapiIELength = WapiIELength+2; + pWapiInfo->assoReqWapiIE[0] = MFIE_TYPE_WAPI; + pWapiInfo->assoReqWapiIE[1] = WapiIELength; + memcpy(pWapiInfo->assoReqWapiIE+2,WapiIE,WapiIELength); + } +#endif + + if(wmm_info_len) { + tag = skb_put(skb,wmm_info_len); + rtllib_WMM_Info(ieee, &tag); + } + + if(wps_ie_len && ieee->wps_ie) + { + tag = skb_put(skb, wps_ie_len); + memcpy(tag, ieee->wps_ie, wps_ie_len); + } + +#ifdef THOMAS_TURBO + tag = skb_put(skb,turbo_info_len); + if(turbo_info_len) { + rtllib_TURBO_Info(ieee, &tag); + } +#endif + + if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){ + if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC) + { + tag = skb_put(skb, ht_cap_len); + *tag++ = MFIE_TYPE_GENERIC; + *tag++ = ht_cap_len - 2; + memcpy(tag, ht_cap_buf,ht_cap_len - 2); + tag += ht_cap_len -2; + } + + if(ieee->pHTInfo->bCurrentRT2RTAggregation){ + tag = skb_put(skb, realtek_ie_len); + *tag++ = MFIE_TYPE_GENERIC; + *tag++ = realtek_ie_len - 2; + memcpy(tag, realtek_ie_buf,realtek_ie_len -2 ); + } + } + + if(ieee->assocreq_ies){ + kfree(ieee->assocreq_ies); + ieee->assocreq_ies = NULL; + } + ies = &(hdr->info_element[0].id); + ieee->assocreq_ies_len = (skb->data + skb->len) - ies; + ieee->assocreq_ies = kmalloc(ieee->assocreq_ies_len, GFP_ATOMIC); + if (ieee->assocreq_ies) + memcpy(ieee->assocreq_ies, ies, ieee->assocreq_ies_len); + else{ + printk("%s()Warning: can't alloc memory for assocreq_ies\n", __func__); + ieee->assocreq_ies_len = 0; + } + + return skb; +} + +void rtllib_associate_abort(struct rtllib_device *ieee) +{ + + unsigned long flags; + spin_lock_irqsave(&ieee->lock, flags); + + ieee->associate_seq++; + + /* don't scan, and avoid to have the RX path possibily + * try again to associate. Even do not react to AUTH or + * ASSOC response. Just wait for the retry wq to be scheduled. + * Here we will check if there are good nets to associate + * with, so we retry or just get back to NO_LINK and scanning + */ + if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING){ + RTLLIB_DEBUG_MGMT("Authentication failed\n"); + ieee->softmac_stats.no_auth_rs++; + }else{ + RTLLIB_DEBUG_MGMT("Association failed\n"); + ieee->softmac_stats.no_ass_rs++; + } + + ieee->state = RTLLIB_ASSOCIATING_RETRY; + + queue_delayed_work_rsl(ieee->wq, &ieee->associate_retry_wq, \ + RTLLIB_SOFTMAC_ASSOC_RETRY_TIME); + + spin_unlock_irqrestore(&ieee->lock, flags); +} + +void rtllib_associate_abort_cb(unsigned long dev) +{ + rtllib_associate_abort((struct rtllib_device *) dev); +} + +void rtllib_associate_step1(struct rtllib_device *ieee,u8 * daddr) +{ + struct rtllib_network *beacon = &ieee->current_network; + struct sk_buff *skb; +#ifdef _RTL8192_EXT_PATCH_ + bool is_mesh = false; +#endif + RTLLIB_DEBUG_MGMT("Stopping scan\n"); + + ieee->softmac_stats.tx_auth_rq++; + + skb=rtllib_authentication_req(beacon, ieee, 0,daddr); + +#ifdef _RTL8192_EXT_PATCH_ + is_mesh = ieee->ext_patch_rtllib_is_mesh(ieee,daddr); + if(is_mesh) { + if(skb){ + softmac_mgmt_xmit(skb, ieee); + } + return; + }else +#endif + if (!skb) + rtllib_associate_abort(ieee); + else{ + ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATING ; + RTLLIB_DEBUG_MGMT("Sending authentication request\n"); + softmac_mgmt_xmit(skb, ieee); + if(!timer_pending(&ieee->associate_timer)){ + ieee->associate_timer.expires = jiffies + (HZ / 2); + add_timer(&ieee->associate_timer); + } + } +} + +void rtllib_auth_challenge(struct rtllib_device *ieee, u8 *challenge, int chlen) +{ + u8 *c; + struct sk_buff *skb; + struct rtllib_network *beacon = &ieee->current_network; + + ieee->associate_seq++; + ieee->softmac_stats.tx_auth_rq++; + + skb = rtllib_authentication_req(beacon, ieee, chlen+2,beacon->bssid); + + if (!skb) + rtllib_associate_abort(ieee); + else{ + c = skb_put(skb, chlen+2); + *(c++) = MFIE_TYPE_CHALLENGE; + *(c++) = chlen; + memcpy(c, challenge, chlen); + + RTLLIB_DEBUG_MGMT("Sending authentication challenge response\n"); + +#ifdef _RTL8192_EXT_PATCH_ + rtllib_encrypt_fragment(ieee, skb, sizeof(struct rtllib_hdr_3addr ), 0, 0); +#else + rtllib_encrypt_fragment(ieee, skb, sizeof(struct rtllib_hdr_3addr )); +#endif + + softmac_mgmt_xmit(skb, ieee); + mod_timer(&ieee->associate_timer, jiffies + (HZ/2)); +#if 0 + ieee->associate_timer.expires = jiffies + (HZ / 2); + add_timer(&ieee->associate_timer); +#endif + } + kfree(challenge); +} + +void rtllib_associate_step2(struct rtllib_device *ieee) +{ + struct sk_buff* skb; + struct rtllib_network *beacon = &ieee->current_network; + + del_timer_sync(&ieee->associate_timer); + + RTLLIB_DEBUG_MGMT("Sending association request\n"); + + ieee->softmac_stats.tx_ass_rq++; + skb=rtllib_association_req(beacon, ieee); + if (!skb) + rtllib_associate_abort(ieee); + else{ + softmac_mgmt_xmit(skb, ieee); + mod_timer(&ieee->associate_timer, jiffies + (HZ/2)); +#if 0 + ieee->associate_timer.expires = jiffies + (HZ / 2); + add_timer(&ieee->associate_timer); +#endif + } +} + +#define CANCELLED 2 +void rtllib_associate_complete_wq(void *data) +{ + struct rtllib_device *ieee = (struct rtllib_device *)container_of_work_rsl(data, struct rtllib_device, associate_complete_wq); + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl)); + printk(KERN_INFO "Associated successfully\n"); + if(ieee->is_silent_reset == 0){ + printk("normal associate\n"); + notify_wx_assoc_event(ieee); + } + + netif_carrier_on(ieee->dev); + ieee->is_roaming = false; + if(rtllib_is_54g(&ieee->current_network) && + (ieee->modulation & RTLLIB_OFDM_MODULATION)){ + + ieee->rate = 108; + printk(KERN_INFO"Using G rates:%d\n", ieee->rate); + }else{ + ieee->rate = 22; + ieee->SetWirelessMode(ieee->dev, IEEE_B); + printk(KERN_INFO"Using B rates:%d\n", ieee->rate); + } + if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT) + { + printk("Successfully associated, ht enabled\n"); + HTOnAssocRsp(ieee); + } else { + printk("Successfully associated, ht not enabled(%d, %d)\n", + ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT); + memset(ieee->dot11HTOperationalRateSet, 0, 16); + } + ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500); + if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 ) + { + ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1; + ieee->LinkDetectInfo.NumRecvDataInPeriod= 1; + } + pPSC->LpsIdleCount = 0; + ieee->link_change(ieee->dev); + +#ifdef _RTL8192_EXT_PATCH_ + if(ieee->set_key_for_AP) + ieee->set_key_for_AP(ieee); + /* Synchronize mesh channel to wlan channel in MSTA mode.*/ + { + if(ieee->current_mesh_network.channel != ieee->current_network.channel) + { + printk("^^^^^^^^^^^^^^^^Change mesh channel %d with wlan channel %d\n", + ieee->current_mesh_network.channel, ieee->current_network.channel); + ieee->ext_patch_rtllib_close_all_peerlink(ieee, CANCELLED); + ieee->current_mesh_network.channel = ieee->current_network.channel; + if(ieee->ext_patch_r819x_wx_set_channel) + { + ieee->ext_patch_r819x_wx_set_channel(ieee, ieee->current_network.channel); + ieee->ext_patch_r819x_wx_set_mesh_chan(ieee->dev,ieee->current_network.channel); + } + } + } +#endif + if(ieee->is_silent_reset == 0){ + } else if(ieee->is_silent_reset == 1) { + printk("silent reset associate\n"); + ieee->is_silent_reset = 0; + } + + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + +#ifdef RTK_DMP_PLATFORM + kobject_hotplug(&ieee->dev->class_dev.kobj, KOBJ_LINKUP); +#endif +} + +static void rtllib_sta_send_associnfo(struct rtllib_device *ieee) +{ + char *buf; + size_t len; + int i; + union iwreq_data wrqu; + + return; + + + buf = kmalloc(50 + 2 * (ieee->assocreq_ies_len + ieee->assocresp_ies_len), GFP_ATOMIC); + if (!buf) + return; + + len = sprintf(buf, "ASSOCINFO("); + if (ieee->assocreq_ies) { + len += sprintf(buf + len, "ReqIEs="); + for (i = 0; i < ieee->assocreq_ies_len; i++) { + len += sprintf(buf + len, "%02x", ieee->assocreq_ies[i]); + } + } + if (ieee->assocresp_ies) { + if (ieee->assocreq_ies) + len += sprintf(buf + len, " "); + len += sprintf(buf + len, "RespIEs="); + for (i = 0; i < ieee->assocresp_ies_len; i++) { + len += sprintf(buf + len, "%02x", ieee->assocresp_ies[i]); + } + } + len += sprintf(buf + len, ")"); + + if (len > IW_CUSTOM_MAX) { + len = sprintf(buf, "ASSOCRESPIE="); + for (i = 0; i < ieee->assocresp_ies_len; i++) { + len += sprintf(buf + len, "%02x", ieee->assocresp_ies[i]); + } + } + + if (len <= IW_CUSTOM_MAX) { + memset(&wrqu, 0, sizeof(wrqu)); + wrqu.data.length = len; + wireless_send_event(ieee->dev, IWEVCUSTOM, &wrqu, buf); + } + + kfree(buf); +} + +void rtllib_associate_complete(struct rtllib_device *ieee) +{ + del_timer_sync(&ieee->associate_timer); + +#if 0 + for(i = 0; i < 6; i++) { + ieee->seq_ctrl[i] = 0; + } +#endif + ieee->state = RTLLIB_LINKED; +#if defined (RTL8192S_WAPI_SUPPORT) + if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){ + WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0); + } +#endif +#if 0 + if (ieee->pHTInfo->bCurrentHTSupport) + { + printk("Successfully associated, ht enabled\n"); + queue_work_rsl(ieee->wq, &ieee->ht_onAssRsp); + } + else + { + printk("Successfully associated, ht not enabled\n"); + memset(ieee->dot11HTOperationalRateSet, 0, 16); + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + } +#endif + + rtllib_sta_send_associnfo(ieee); + + queue_work_rsl(ieee->wq, &ieee->associate_complete_wq); +} + +void rtllib_associate_procedure_wq(void *data) +{ + struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, associate_procedure_wq); + rtllib_stop_scan_syncro(ieee); +#ifdef ENABLE_IPS + if(ieee->rtllib_ips_leave != NULL) + ieee->rtllib_ips_leave(ieee->dev); +#endif + down(&ieee->wx_sem); + + if (ieee->data_hard_stop) + ieee->data_hard_stop(ieee->dev); + + rtllib_stop_scan(ieee); + printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel); + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + if(ieee->eRFPowerState == eRfOff) + { + printk("=============>%s():Rf state is eRfOff, schedule ipsleave wq again,return\n",__FUNCTION__); +#ifdef ENABLE_IPS + if(ieee->rtllib_ips_leave_wq != NULL) + ieee->rtllib_ips_leave_wq(ieee->dev); +#endif + up(&ieee->wx_sem); + return; + } + ieee->associate_seq = 1; + + rtllib_associate_step1(ieee, ieee->current_network.bssid); + + up(&ieee->wx_sem); +} + +#ifdef _RTL8192_EXT_PATCH_ + +void rtllib_ext_stop_scan_wq(void *data) +{ + struct rtllib_device *ieee = (struct rtllib_device *)container_of_work_rsl(data, struct rtllib_device, ext_stop_scan_wq); + rtllib_stop_scan_syncro(ieee); + + down(&ieee->wx_sem); + + if (ieee->data_hard_stop) + ieee->data_hard_stop(ieee->dev); + + rtllib_stop_scan(ieee); + + up(&ieee->wx_sem); +} + + +void rtllib_ext_send_11s_beacon(struct rtllib_device *ieee) +{ + queue_work_rsl(ieee->wq, &ieee->ext_send_beacon_wq); +} + +#endif + + +inline void rtllib_softmac_new_net(struct rtllib_device *ieee, struct rtllib_network *net) +{ + u8 tmp_ssid[IW_ESSID_MAX_SIZE+1]; + int tmp_ssid_len = 0; + + short apset,ssidset,ssidbroad,apmatch,ssidmatch; + + /* we are interested in new new only if we are not associated + * and we are not associating / authenticating + */ + if (ieee->state != RTLLIB_NOLINK) + return; + + if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_ESS)) + return; + + if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS)) + return; + + if ((ieee->iw_mode == IW_MODE_ADHOC) && (net->channel > ieee->ibss_maxjoin_chal)) { + return; + } +#ifdef _RTL8192_EXT_PATCH_ + if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC + || ((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0))) +#else + if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) +#endif + { + /* if the user specified the AP MAC, we need also the essid + * This could be obtained by beacons or, if the network does not + * broadcast it, it can be put manually. + */ + apset = ieee->wap_set; + ssidset = ieee->ssid_set; + ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0'); + apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0); + if(!ssidbroad){ + ssidmatch = (ieee->current_network.ssid_len == net->hidden_ssid_len)&&\ + (!strncmp(ieee->current_network.ssid, net->hidden_ssid, net->hidden_ssid_len)); + if(net->hidden_ssid_len > 0) + { + strncpy(net->ssid, net->hidden_ssid, net->hidden_ssid_len); + net->ssid_len = net->hidden_ssid_len; + ssidbroad = 1; + } + } + else + ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\ + (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len)); + + if ( /* if the user set the AP check if match. + * if the network does not broadcast essid we check the user supplyed ANY essid + * if the network does broadcast and the user does not set essid it is OK + * if the network does broadcast and the user did set essid chech if essid match + */ + ( apset && apmatch && + ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) + /* if the ap is not set, check that the user set the bssid + * and the network does bradcast and that those two bssid matches + */ + || (!apset && ssidset && ssidbroad && ssidmatch) || (ieee->is_roaming && ssidset && ssidbroad && ssidmatch) + ){ + /* if the essid is hidden replace it with the + * essid provided by the user. + */ + if (!ssidbroad){ + strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE); + tmp_ssid_len = ieee->current_network.ssid_len; + } + memcpy(&ieee->current_network, net, sizeof(struct rtllib_network)); + if (!ssidbroad){ + strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE); + ieee->current_network.ssid_len = tmp_ssid_len; + } + printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d, mode:%x cur_net.flags:0x%x\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT, ieee->current_network.mode, ieee->current_network.flags); + + if ((rtllib_act_scanning(ieee, false)) && !(ieee->softmac_features & IEEE_SOFTMAC_SCAN)){ + rtllib_stop_scan_syncro(ieee); + } + + ieee->hwscan_ch_bk = ieee->current_network.channel; + HTResetIOTSetting(ieee->pHTInfo); + ieee->wmm_acm = 0; +#ifdef _RTL8192_EXT_PATCH_ + if ((ieee->iw_mode == IW_MODE_INFRA) || + ((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0))) +#else + if (ieee->iw_mode == IW_MODE_INFRA) +#endif + { + /* Join the network for the first time */ + ieee->AsocRetryCount = 0; + if(/*(ieee->current_network.qos_data.supported == 1) &&*/ + ieee->current_network.bssht.bdSupportHT) +/*WB, 2008.09.09:bCurrentHTSupport and bEnableHT two flags are going to put together to check whether we are in HT now, so needn't to check bEnableHT flags here. That's is to say we will set to HT support whenever joined AP has the ability to support HT. And whether we are in HT or not, please check bCurrentHTSupport&&bEnableHT now please.*/ + { +#ifdef ENABLE_AMSDU + if((ieee->mode == IEEE_N_24G) && (ieee->mode == IEEE_N_5G)) + HTUseDefaultSetting(ieee); +#endif + HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network)); + } + else + { + ieee->pHTInfo->bCurrentHTSupport = false; + } + + ieee->state = RTLLIB_ASSOCIATING; + if(ieee->LedControlHandler != NULL) + ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK); + queue_delayed_work_rsl(ieee->wq, &ieee->associate_procedure_wq, 0); + }else{ +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) +#if defined (RTL8192S_WAPI_SUPPORT) + if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){ + WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0); + } +#endif + ieee->state = RTLLIB_LINKED; + if(ieee->mode > ieee->current_network.mode) + ieee->SetWirelessMode(ieee->dev, ieee->current_network.mode); + else + ieee->SetWirelessMode(ieee->dev, ieee->mode); + mod_timer(&ieee->ibss_wait_timer,jiffies+(MSECS(20000))); +#else + if(rtllib_is_54g(&ieee->current_network) && + (ieee->modulation & RTLLIB_OFDM_MODULATION)){ + ieee->rate = 108; + ieee->SetWirelessMode(ieee->dev, IEEE_G); + printk(KERN_INFO"Using G rates\n"); + }else{ + ieee->rate = 22; + ieee->SetWirelessMode(ieee->dev, IEEE_B); + printk(KERN_INFO"Using B rates\n"); + } + memset(ieee->dot11HTOperationalRateSet, 0, 16); + ieee->state = RTLLIB_LINKED; +#endif + } + + } + } + +} + +void rtllib_softmac_check_all_nets(struct rtllib_device *ieee) +{ + unsigned long flags; + struct rtllib_network *target; + + spin_lock_irqsave(&ieee->lock, flags); + + list_for_each_entry(target, &ieee->network_list, list) { + + /* if the state become different that NOLINK means + * we had found what we are searching for + */ + + if (ieee->state != RTLLIB_NOLINK) + break; + + if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies)) + rtllib_softmac_new_net(ieee, target); + } + + spin_unlock_irqrestore(&ieee->lock, flags); + +} + + +static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen) +{ + struct rtllib_authentication *a; + u8 *t; + if (skb->len < (sizeof(struct rtllib_authentication)-sizeof(struct rtllib_info_element))){ + RTLLIB_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len); + return 0xcafe; + } + *challenge = NULL; + a = (struct rtllib_authentication*) skb->data; + if(skb->len > (sizeof(struct rtllib_authentication) +3)){ + t = skb->data + sizeof(struct rtllib_authentication); + + if(*(t++) == MFIE_TYPE_CHALLENGE){ + *chlen = *(t++); + *challenge = (u8*)kmalloc(*chlen, GFP_ATOMIC); + memcpy(*challenge, t, *chlen); + } + } + + return cpu_to_le16(a->status); + +} + + +int auth_rq_parse(struct sk_buff *skb,u8* dest) +{ + struct rtllib_authentication *a; + + if (skb->len < (sizeof(struct rtllib_authentication)-sizeof(struct rtllib_info_element))){ + RTLLIB_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len); + return -1; + } + a = (struct rtllib_authentication*) skb->data; + + memcpy(dest,a->header.addr2, ETH_ALEN); + + if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN) + return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; + + return WLAN_STATUS_SUCCESS; +} + +static short probe_rq_parse(struct rtllib_device *ieee, struct sk_buff *skb, u8 *src) +{ + u8 *tag; + u8 *skbend; + u8 *ssid=NULL; + u8 ssidlen = 0; + + struct rtllib_hdr_3addr *header = + (struct rtllib_hdr_3addr *) skb->data; + + if (skb->len < sizeof (struct rtllib_hdr_3addr )) + return -1; /* corrupted */ + if((memcmp(header->addr3,ieee->current_network.bssid,ETH_ALEN) != 0)&& + (memcmp(header->addr3,"\xff\xff\xff\xff\xff\xff",ETH_ALEN) != 0)) { + return -1; + } + + if(memcmp(header->addr3,ieee->current_network.bssid,ETH_ALEN) == 0) { + } + + if(memcmp(header->addr3,"\xff\xff\xff\xff\xff\xff",ETH_ALEN) == 0) { + } + memcpy(src,header->addr2, ETH_ALEN); + + skbend = (u8*)skb->data + skb->len; + + tag = skb->data + sizeof (struct rtllib_hdr_3addr ); + + while (tag+1 < skbend){ + if (*tag == 0){ + ssid = tag+2; + ssidlen = *(tag+1); + break; + } + tag++; /* point to the len field */ + tag = tag + *(tag); /* point to the last data byte of the tag */ + tag++; /* point to the next tag */ + } + + if (ssidlen == 0) return 1; + + if (!ssid) return 1; /* ssid not found in tagged param */ + return (!strncmp(ssid, ieee->current_network.ssid, ssidlen)); + +} + +int assoc_rq_parse(struct sk_buff *skb,u8* dest) +{ + struct rtllib_assoc_request_frame *a; + + if (skb->len < (sizeof(struct rtllib_assoc_request_frame) - + sizeof(struct rtllib_info_element))) { + + RTLLIB_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len); + return -1; + } + + a = (struct rtllib_assoc_request_frame*) skb->data; + + memcpy(dest,a->header.addr2,ETH_ALEN); + + return 0; +} + +static inline u16 assoc_parse(struct rtllib_device *ieee, struct sk_buff *skb, int *aid) +{ + struct rtllib_assoc_response_frame *response_head; + u16 status_code; + + if (skb->len < sizeof(struct rtllib_assoc_response_frame)){ + RTLLIB_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len); + return 0xcafe; + } + + response_head = (struct rtllib_assoc_response_frame*) skb->data; + *aid = le16_to_cpu(response_head->aid) & 0x3fff; + + status_code = le16_to_cpu(response_head->status); + if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \ + status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&& + ((ieee->mode == IEEE_G) && + (ieee->current_network.mode == IEEE_N_24G) && + (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) { + ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE; + }else { + ieee->AsocRetryCount = 0; + } + + return le16_to_cpu(response_head->status); +} + +void rtllib_rx_probe_rq(struct rtllib_device *ieee, struct sk_buff *skb) +{ + u8 dest[ETH_ALEN]; +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + struct sta_info *psta = NULL; +#endif + ieee->softmac_stats.rx_probe_rq++; + if (probe_rq_parse(ieee, skb, dest) > 0){ + ieee->softmac_stats.tx_probe_rs++; + rtllib_resp_to_probe(ieee, dest); +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + if(ieee->iw_mode == IW_MODE_ADHOC){ + psta = GetStaInfo(ieee, dest); + if(NULL != psta) + psta->LastActiveTime = jiffies; + } +#endif + } +} + +static inline void rtllib_rx_auth_rq(struct rtllib_device *ieee, struct sk_buff *skb) +{ + u8 dest[ETH_ALEN]; + int status; + ieee->softmac_stats.rx_auth_rq++; + + if ((status = auth_rq_parse(skb, dest))!= -1){ + rtllib_resp_to_auth(ieee, status, dest); + } + +} + +static inline void rtllib_rx_assoc_rq(struct rtllib_device *ieee, struct sk_buff *skb) +{ + + u8 dest[ETH_ALEN]; + + ieee->softmac_stats.rx_ass_rq++; + if (assoc_rq_parse(skb,dest) != -1){ + rtllib_resp_to_assoc_rq(ieee, dest); + } + + printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest)); + #if 0 + spin_lock_irqsave(&ieee->lock,flags); + add_associate(ieee,dest); + spin_unlock_irqrestore(&ieee->lock,flags); + #endif +} + + +void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr) +{ + + struct sk_buff *buf = rtllib_null_func(ieee, pwr); + + if (buf) + softmac_ps_mgmt_xmit(buf, ieee); + +} + +void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee) +{ + + struct sk_buff *buf = rtllib_pspoll_func(ieee); + + if (buf) + softmac_ps_mgmt_xmit(buf, ieee); + +} + +short rtllib_sta_ps_sleep(struct rtllib_device *ieee, u32 *time_h, u32 *time_l) +{ + int timeout = ieee->ps_timeout; + u8 dtim; + PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl)); + /*if(ieee->ps == RTLLIB_PS_DISABLED || + ieee->iw_mode != IW_MODE_INFRA || + ieee->state != RTLLIB_LINKED) + + return 0; + */ + + if(ieee->LPSDelayCnt) + { + ieee->LPSDelayCnt --; + return 0; + } + + dtim = ieee->current_network.dtim_data; + if(!(dtim & RTLLIB_DTIM_VALID)) + return 0; + timeout = ieee->current_network.beacon_interval; + ieee->current_network.dtim_data = RTLLIB_DTIM_INVALID; + /* there's no need to nofity AP that I find you buffered with broadcast packet */ + if(dtim & (RTLLIB_DTIM_UCAST & ieee->ps)) + return 2; + + if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){ + return 0; + } + if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){ + return 0; + } + if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) && + (ieee->mgmt_queue_tail != ieee->mgmt_queue_head)) + return 0; + + if(time_l){ + if(ieee->bAwakePktSent == true) { + pPSC->LPSAwakeIntvl = 1; + } else { + u8 MaxPeriod = 1; + + if(pPSC->LPSAwakeIntvl == 0) + pPSC->LPSAwakeIntvl = 1; + if(pPSC->RegMaxLPSAwakeIntvl == 0) + MaxPeriod = 1; + else if(pPSC->RegMaxLPSAwakeIntvl == 0xFF) + MaxPeriod = ieee->current_network.dtim_period; + else + MaxPeriod = pPSC->RegMaxLPSAwakeIntvl; + pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (pPSC->LPSAwakeIntvl + 1); + } + { + u8 LPSAwakeIntvl_tmp = 0; + u8 period = ieee->current_network.dtim_period; + u8 count = ieee->current_network.tim.tim_count; + if(count == 0 ) { + if(pPSC->LPSAwakeIntvl > period) + LPSAwakeIntvl_tmp = period + (pPSC->LPSAwakeIntvl - period) -((pPSC->LPSAwakeIntvl-period)%period); + else + LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl; + + } else { + if(pPSC->LPSAwakeIntvl > ieee->current_network.tim.tim_count) + LPSAwakeIntvl_tmp = count + (pPSC->LPSAwakeIntvl - count) -((pPSC->LPSAwakeIntvl-count)%period); + else + LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl; + } + + *time_l = ieee->current_network.last_dtim_sta_time[0] + + MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp); + } + } + + if(time_h){ +#ifdef _RTL8192_EXT_PATCH_ + if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0]) + *time_h =1; + else + *time_h =0; +#else + *time_h = ieee->current_network.last_dtim_sta_time[1]; + if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0]) + *time_h += 1; +#endif + } + + return 1; + + +} + +inline void rtllib_sta_ps(struct rtllib_device *ieee) +{ + + u32 th,tl; + short sleep; + + unsigned long flags,flags2; + + spin_lock_irqsave(&ieee->lock, flags); + + if((ieee->ps == RTLLIB_PS_DISABLED || + ieee->iw_mode != IW_MODE_INFRA || + ieee->state != RTLLIB_LINKED)){ + + printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n", + __FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state); + spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); + + rtllib_sta_wakeup(ieee, 1); + + spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); + } + + sleep = rtllib_sta_ps_sleep(ieee,&th, &tl); + /* 2 wake, 1 sleep, 0 do nothing */ + if(sleep == 0) + { + goto out; + } + if(sleep == 1){ + if(ieee->sta_sleep == LPS_IS_SLEEP){ + ieee->enter_sleep_state(ieee->dev,th,tl); + } + + else if(ieee->sta_sleep == LPS_IS_WAKE){ + spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); + + if(ieee->ps_is_queue_empty(ieee->dev)){ + ieee->sta_sleep = LPS_WAIT_NULL_DATA_SEND; + ieee->ack_tx_to_ieee = 1; + rtllib_sta_ps_send_null_frame(ieee,1); + ieee->ps_th = th; + ieee->ps_tl = tl; + } + spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); + + } + + ieee->bAwakePktSent = false; + + }else if(sleep == 2){ + spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); + + rtllib_sta_wakeup(ieee,1); + + spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); + } + +out: + spin_unlock_irqrestore(&ieee->lock, flags); + +} + +void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl) +{ + if(ieee->sta_sleep == LPS_IS_WAKE){ + if(nl){ + if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING) + { + ieee->ack_tx_to_ieee = 1; + rtllib_sta_ps_send_null_frame(ieee, 0); + } + else + { + ieee->ack_tx_to_ieee = 1; + rtllib_sta_ps_send_pspoll_frame(ieee); + } + } + return; + + } + + if(ieee->sta_sleep == LPS_IS_SLEEP) + ieee->sta_wake_up(ieee->dev); + if(nl){ + /* + ieee->ack_tx_to_ieee = 1; + printk("%s(3): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__); + rtllib_sta_ps_send_null_frame(ieee, 0); + */ + if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING) + { + ieee->ack_tx_to_ieee = 1; + rtllib_sta_ps_send_null_frame(ieee, 0); + } + else + { + ieee->ack_tx_to_ieee = 1; + ieee->polling = true; + rtllib_sta_ps_send_pspoll_frame(ieee); + } + + } else { + ieee->sta_sleep = LPS_IS_WAKE; + ieee->polling = false; + } +} + +void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success) +{ + unsigned long flags,flags2; + + spin_lock_irqsave(&ieee->lock, flags); + + if(ieee->sta_sleep == LPS_WAIT_NULL_DATA_SEND){ + /* Null frame with PS bit set */ + if(success){ + ieee->sta_sleep = LPS_IS_SLEEP; + ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl); + } + /* if the card report not success we can't be sure the AP + * has not RXed so we can't assume the AP believe us awake + */ + } else {/* 21112005 - tx again null without PS bit if lost */ + + if((ieee->sta_sleep == LPS_IS_WAKE) && !success){ + spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); + if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING) + { + rtllib_sta_ps_send_null_frame(ieee, 0); + } + else + { + rtllib_sta_ps_send_pspoll_frame(ieee); + } + spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); + } + } + spin_unlock_irqrestore(&ieee->lock, flags); +} + +void rtllib_process_action(struct rtllib_device* ieee, struct sk_buff* skb) +{ + struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data; + u8* act = rtllib_get_payload((struct rtllib_hdr *)header); + u8 category = 0; + + if (act == NULL) { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "error to get payload of action frame\n"); + return; + } + + category = *act; + act ++; + switch (category) { + case ACT_CAT_BA: + switch (*act) { + case ACT_ADDBAREQ: + rtllib_rx_ADDBAReq(ieee, skb); + break; + case ACT_ADDBARSP: + rtllib_rx_ADDBARsp(ieee, skb); + break; + case ACT_DELBA: + rtllib_rx_DELBA(ieee, skb); + break; + } + break; + default: + break; + } + return; +} + +#ifdef _RTL8192_EXT_PATCH_ +void rtllib_process_action_mesh(struct rtllib_device* ieee, struct sk_buff* skb, + struct rtllib_rx_stats *rx_stats) +{ + struct rtllib_hdr_3addr *header = NULL; + u8* act = NULL; + u8 category = 0; + +#ifdef COMPATIBLE_WITH_RALINK_MESH + memmove(skb->data + WLAN_MESH_HDR_LEN, skb->data, sizeof(struct rtllib_hdr_3addr)); + skb_pull(skb, WLAN_MESH_HDR_LEN); +#endif + + header = (struct rtllib_hdr_3addr *) skb->data; + act = rtllib_get_payload((struct rtllib_hdr *)header); + + if (act == NULL) { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "error to get payload of action frame\n"); + return; + } + if (ieee->iw_mode != IW_MODE_MESH) { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "not in mesh mode\n"); + return; + } + + category = *act; + act ++; + switch (category) { + case ACT_CAT_MESH_PEERLINK_MGNT: + if(ieee->iw_mode != IW_MODE_MESH) { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "peerlink received not in mesh mode\n"); + return; + } + switch (*act) { + case ACT_PEERLINK_OPEN: + if (ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_open) { + ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_open(ieee, skb, rx_stats); + } + break; + case ACT_PEERLINK_CONFIRM: + if (ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm) { + ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_confirm(ieee, skb); + } + break; + case ACT_PEERLINK_CLOSE: + if ( ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_close) { + ieee->ext_patch_rtllib_rx_frame_softmac_on_peerlink_close(ieee, skb); + } + break; + } + break; + case ACT_CAT_MESH_LINK_METRIC: + if (ieee->iw_mode != IW_MODE_MESH) { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "link metric received not in mesh mode\n"); + return; + } + switch (*act) { + case ACT_LINKMETRIC_REQ: + if (ieee->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req) { + ieee->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_req( + ieee, skb); + } + break; + case ACT_LINKMETRIC_RSP: + if (ieee->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report) { + ieee->ext_patch_rtllib_rx_frame_softmac_on_linkmetric_report( + ieee, skb); + } + break; + } + + break; + case ACT_CAT_MESH_PATH_SELECT: + if (ieee->iw_mode != IW_MODE_MESH) { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "not in mesh mode\n"); + return; + } + + switch (*act) { + case ACT_PATH_REQ: + if( ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq) { + ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_preq( + ieee, skb, rx_stats); + } + break; + case ACT_PATH_REPLY: + if(ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep) { + ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_prep( + ieee, skb, rx_stats); + } + break; + case ACT_PATH_ERR: + if(ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr) { + ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_perr( + ieee, skb, rx_stats); + } + break; + case ACT_RANN: + if(ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann) { + ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_rann( + ieee, skb, rx_stats); + } + break; + } + break; + case ACT_CAT_MESH_INTERWORKING: + if (ieee->iw_mode != IW_MODE_MESH) { + RTLLIB_DEBUG(RTLLIB_DL_ERR, "not in mesh mode\n"); + return; + } + if (*act == 0) { + if (ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann) { + ieee->ext_patch_rtllib_rx_frame_softmac_on_pathselect_pann( + ieee, skb, rx_stats); + } + } + break; + default: + break; + } + return; +} +#endif + + +inline int rtllib_rx_assoc_resp(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats) +{ + u16 errcode; + int aid; + u8* ies; + struct rtllib_assoc_response_frame *assoc_resp; + struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data; + + RTLLIB_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n", + WLAN_FC_GET_STYPE(header->frame_ctl)); + + if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && + ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATED && +#ifdef _RTL8192_EXT_PATCH_ + ((ieee->iw_mode == IW_MODE_INFRA) || + (ieee->iw_mode == IW_MODE_MESH && ieee->only_mesh == 0))) +#else + (ieee->iw_mode == IW_MODE_INFRA)) +#endif + { + if (0 == (errcode=assoc_parse(ieee,skb, &aid))){ +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) + struct rtllib_network *network = kzalloc(sizeof(struct rtllib_network), GFP_ATOMIC); +#else + struct rtllib_network *network = kmalloc(sizeof(*network), GFP_ATOMIC); +#endif + if (!network) { + return 1; + } + memset(network,0,sizeof(*network)); + ieee->state=RTLLIB_LINKED; + ieee->assoc_id = aid; + ieee->softmac_stats.rx_ass_ok++; + /* station support qos */ + /* Let the register setting defaultly with Legacy station */ + assoc_resp = (struct rtllib_assoc_response_frame*)skb->data; + if(ieee->current_network.qos_data.supported == 1) { + if (rtllib_parse_info_param(ieee,assoc_resp->info_element,\ + rx_stats->len - sizeof(*assoc_resp),\ + network,rx_stats)){ + kfree(network); + return 1; + } + else + { + memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen); + memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen); + } + if (ieee->handle_assoc_response != NULL) + ieee->handle_assoc_response(ieee->dev, (struct rtllib_assoc_response_frame*)header, network); + kfree(network); + } + + if(ieee->assocresp_ies){ + kfree(ieee->assocresp_ies); + ieee->assocresp_ies = NULL; + } + ies = &(assoc_resp->info_element[0].id); + ieee->assocresp_ies_len = (skb->data + skb->len) - ies; + ieee->assocresp_ies = kmalloc(ieee->assocresp_ies_len, GFP_ATOMIC); + if (ieee->assocresp_ies) + memcpy(ieee->assocresp_ies, ies, ieee->assocresp_ies_len); + else{ + printk("%s()Warning: can't alloc memory for assocresp_ies\n", __func__); + ieee->assocresp_ies_len = 0; + } +#ifdef RTL8192S_WAPI_SUPPORT + { + PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo); + PRT_WAPI_STA_INFO pWapiSta; + u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; + u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; + if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)) + { + pWapiSta =(PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list); + list_del_init(&pWapiSta->list); + list_add_tail(&pWapiSta->list, &pWapiInfo->wapiSTAUsedList); + WAPI_TRACE(WAPI_API, "%s(): New WAPI STA ("MAC_FMT")!!\n",__FUNCTION__,MAC_ARG(ieee->current_network.bssid)); + memcpy(pWapiSta->PeerMacAddr,ieee->current_network.bssid,6); + memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16); + memcpy(pWapiSta->lastRxUnicastPN, WapiAEPNInitialValueSrc, 16); + pWapiInfo->bFirstAuthentiateInProgress= true; + pWapiInfo->assoRspWapiIE[0] = MFIE_TYPE_WAPI; + pWapiInfo->assoRspWapiIE[1] = network->wapi_ie_len; + pWapiInfo->assoRspWapiIELength = network->wapi_ie_len+2; + memcpy(pWapiInfo->assoRspWapiIE+2,network->wapi_ie,network->wapi_ie_len); + } + } +#endif + rtllib_associate_complete(ieee); + } else { + /* aid could not been allocated */ + ieee->softmac_stats.rx_ass_err++; + printk( + "Association response status code 0x%x\n", + errcode); + RTLLIB_DEBUG_MGMT( + "Association response status code 0x%x\n", + errcode); + if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) { + queue_delayed_work_rsl(ieee->wq, &ieee->associate_procedure_wq, 0); + } else { + rtllib_associate_abort(ieee); + } + } + } + + return 0; +} + +inline int rtllib_rx_auth(struct rtllib_device *ieee, struct sk_buff *skb, struct rtllib_rx_stats *rx_stats) +{ +#ifdef _RTL8192_EXT_PATCH_ + struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data; + u8 mesh_bssid[6] = {0,0,0,0,0,0}; +#endif + u16 errcode; + u8* challenge; + int chlen=0; + bool bSupportNmode = true, bHalfSupportNmode = false; + +#ifdef _RTL8192_EXT_PATCH_ + if((ieee->iw_mode == IW_MODE_MESH) && ieee->ext_patch_rtllib_rx_frame_softmac_on_auth && ieee->mesh_started && ((memcmp(header->addr3, ieee->current_network.bssid, 6)) || (memcmp(ieee->current_network.bssid, mesh_bssid, 6) == 0))) + ieee->ext_patch_rtllib_rx_frame_softmac_on_auth(ieee, skb, rx_stats); + else +#endif + if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){ + if (ieee->state == RTLLIB_ASSOCIATING_AUTHENTICATING && +#ifdef _RTL8192_EXT_PATCH_ + ((ieee->iw_mode == IW_MODE_INFRA)|| + ((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0)))) +#else + (ieee->iw_mode == IW_MODE_INFRA)) +#endif + { + RTLLIB_DEBUG_MGMT("Received authentication response"); + + if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){ + if(ieee->open_wep || !challenge){ + ieee->state = RTLLIB_ASSOCIATING_AUTHENTICATED; + ieee->softmac_stats.rx_auth_rs_ok++; + if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE)) + { + if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) + { + if(IsHTHalfNmodeAPs(ieee)) + { + bSupportNmode = true; + bHalfSupportNmode = true; + } + else + { + bSupportNmode = false; + bHalfSupportNmode = false; + } + } + } + /* Dummy wirless mode setting to avoid encryption issue */ + if(bSupportNmode) { + ieee->SetWirelessMode(ieee->dev, \ + ieee->current_network.mode); + }else{ + /*TODO*/ + ieee->SetWirelessMode(ieee->dev, IEEE_G); + } + + if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true) + { + printk("===============>entern half N mode\n"); + ieee->bHalfWirelessN24GMode = true; + } + else + ieee->bHalfWirelessN24GMode = false; + + rtllib_associate_step2(ieee); + }else{ + rtllib_auth_challenge(ieee, challenge, chlen); + } + }else{ + ieee->softmac_stats.rx_auth_rs_err++; + RTLLIB_DEBUG_MGMT("Authentication respose status code 0x%x",errcode); + + printk("Authentication respose status code 0x%x",errcode); + rtllib_associate_abort(ieee); + } + + }else if (ieee->iw_mode == IW_MODE_MASTER){ + rtllib_rx_auth_rq(ieee, skb); + } + } + + return 0; +} + +inline int rtllib_rx_deauth(struct rtllib_device *ieee, struct sk_buff *skb) +{ + struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data; + + if(memcmp(header->addr3, ieee->current_network.bssid, ETH_ALEN) != 0) + return 0; + + /* FIXME for now repeat all the association procedure + * both for disassociation and deauthentication + */ + if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && + ieee->state == RTLLIB_LINKED && +#ifdef _RTL8192_EXT_PATCH_ + ((ieee->iw_mode == IW_MODE_INFRA) || + ((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0)))) +#else + (ieee->iw_mode == IW_MODE_INFRA)) +#endif + { + printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_ctl), ((struct rtllib_disassoc*)skb->data)->reason); + ieee->state = RTLLIB_ASSOCIATING; + ieee->softmac_stats.reassoc++; + ieee->is_roaming = true; + ieee->LinkDetectInfo.bBusyTraffic = false; + rtllib_disassociate(ieee); + RemovePeerTS(ieee, header->addr2); + if(ieee->LedControlHandler != NULL) + ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK); + + if(!(ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_CCMP|SEC_ALG_TKIP))) + queue_delayed_work_rsl(ieee->wq, &ieee->associate_procedure_wq, 5); + } + + return 0; +} + +inline int rtllib_rx_frame_softmac(struct rtllib_device *ieee, struct sk_buff *skb, + struct rtllib_rx_stats *rx_stats, u16 type, + u16 stype) +{ + struct rtllib_hdr_3addr *header = (struct rtllib_hdr_3addr *) skb->data; + +#ifdef _RTL8192_EXT_PATCH_ + if((!ieee->proto_started)&&(!ieee->mesh_started)) +#else + if(!ieee->proto_started) +#endif + return 0; + + switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { + + case RTLLIB_STYPE_ASSOC_RESP: + case RTLLIB_STYPE_REASSOC_RESP: + + if(rtllib_rx_assoc_resp(ieee, skb, rx_stats) == 1) + return 1; + + break; + + case RTLLIB_STYPE_ASSOC_REQ: + case RTLLIB_STYPE_REASSOC_REQ: + + if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && + ieee->iw_mode == IW_MODE_MASTER) + + rtllib_rx_assoc_rq(ieee, skb); + break; + + case RTLLIB_STYPE_AUTH: + + rtllib_rx_auth(ieee, skb, rx_stats); + + break; +#if 0 + case RTLLIB_STYPE_PROBE_REQ: + + if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) && + ((ieee->iw_mode == IW_MODE_ADHOC || + ieee->iw_mode == IW_MODE_MASTER) && + ieee->state == RTLLIB_LINKED)){ + rtllib_rx_probe_rq(ieee, skb); + } + break; +#endif + case RTLLIB_STYPE_DISASSOC: + case RTLLIB_STYPE_DEAUTH: + + rtllib_rx_deauth(ieee, skb); + + break; + + case RTLLIB_STYPE_MANAGE_ACT: + rtllib_process_action(ieee,skb); +#ifdef _RTL8192_EXT_PATCH_ + rtllib_process_action_mesh(ieee,skb,rx_stats); +#endif + break; +#ifdef COMPATIBLE_WITH_RALINK_MESH + case RTLLIB_STYPE_MESH_ACT: + rtllib_process_action_mesh(ieee,skb,rx_stats); + break; +#endif + default: + return -1; + break; + } + + return 0; +} + +/* following are for a simplier TX queue management. + * Instead of using netif_[stop/wake]_queue the driver + * will uses these two function (plus a reset one), that + * will internally uses the kernel netif_* and takes + * care of the ieee802.11 fragmentation. + * So the driver receives a fragment per time and might + * call the stop function when it want without take care + * to have enought room to TX an entire packet. + * This might be useful if each fragment need it's own + * descriptor, thus just keep a total free memory > than + * the max fragmentation treshold is not enought.. If the + * ieee802.11 stack passed a TXB struct then you needed + * to keep N free descriptors where + * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD + * In this way you need just one and the 802.11 stack + * will take care of buffering fragments and pass them to + * to the driver later, when it wakes the queue. + */ +void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee) +{ + + unsigned int queue_index = txb->queue_index; + unsigned long flags; + int i; + cb_desc *tcb_desc = NULL; + unsigned long queue_len = 0; + + spin_lock_irqsave(&ieee->lock,flags); + + /* called with 2nd parm 0, no tx mgmt lock required */ + rtllib_sta_wakeup(ieee,0); + + /* update the tx status */ + tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); + if(tcb_desc->bMulticast) { + ieee->stats.multicast++; + } +#if 1 + /* if xmit available, just xmit it immediately, else just insert it to the wait queue */ + for(i = 0; i < txb->nr_frags; i++) { +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + queue_len = skb_queue_len(&ieee->skb_drv_aggQ[queue_index]); +#else + queue_len = skb_queue_len(&ieee->skb_waitQ[queue_index]); +#endif + if((queue_len != 0) ||\ + (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\ + (ieee->queue_stop)) { + /* insert the skb packet to the wait queue */ + /* as for the completion function, it does not need + * to check it any more. + * */ +#ifdef WIFI_TEST + if (1) +#else + if(queue_len < 200) +#endif + { +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]); +#else + skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]); +#endif + }else{ + kfree_skb(txb->fragments[i]); + } + }else{ + ieee->softmac_data_hard_start_xmit( + txb->fragments[i], + ieee->dev,ieee->rate); + } + } +#endif + rtllib_txb_free(txb); + + spin_unlock_irqrestore(&ieee->lock,flags); + +} + +/* called with ieee->lock acquired */ +void rtllib_resume_tx(struct rtllib_device *ieee) +{ + int i; + for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) { + + if (ieee->queue_stop){ + ieee->tx_pending.frag = i; + return; + }else{ + + ieee->softmac_data_hard_start_xmit( + ieee->tx_pending.txb->fragments[i], + ieee->dev,ieee->rate); + ieee->stats.tx_packets++; + } + } + + rtllib_txb_free(ieee->tx_pending.txb); + ieee->tx_pending.txb = NULL; +} + + +void rtllib_reset_queue(struct rtllib_device *ieee) +{ + unsigned long flags; + + spin_lock_irqsave(&ieee->lock,flags); + init_mgmt_queue(ieee); + if (ieee->tx_pending.txb){ + rtllib_txb_free(ieee->tx_pending.txb); + ieee->tx_pending.txb = NULL; + } + ieee->queue_stop = 0; + spin_unlock_irqrestore(&ieee->lock,flags); + +} + +void rtllib_wake_queue(struct rtllib_device *ieee) +{ + + unsigned long flags; + struct sk_buff *skb; + struct rtllib_hdr_3addr *header; + + spin_lock_irqsave(&ieee->lock,flags); + if (! ieee->queue_stop) goto exit; + + ieee->queue_stop = 0; + + if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){ + while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){ + + header = (struct rtllib_hdr_3addr *) skb->data; + + header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); + } + } + if (!ieee->queue_stop && ieee->tx_pending.txb) + rtllib_resume_tx(ieee); + + if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){ + ieee->softmac_stats.swtxawake++; + netif_wake_queue(ieee->dev); + } + +exit : + spin_unlock_irqrestore(&ieee->lock,flags); +} + + +void rtllib_stop_queue(struct rtllib_device *ieee) +{ + + if (! netif_queue_stopped(ieee->dev)){ + netif_stop_queue(ieee->dev); + ieee->softmac_stats.swtxstop++; + } + ieee->queue_stop = 1; + +} + +void rtllib_stop_all_queues(struct rtllib_device *ieee) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) + unsigned int i; + for(i=0; i < ieee->dev->num_tx_queues; i++) + netdev_get_tx_queue(ieee->dev,i)->trans_start = jiffies; +#else + ieee->dev->trans_start = jiffies; +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) + netif_carrier_off(ieee->dev); +#else + netif_tx_stop_all_queues(ieee->dev); +#endif +} + +void rtllib_wake_all_queues(struct rtllib_device *ieee) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) + netif_carrier_on(ieee->dev); +#else + netif_tx_wake_all_queues(ieee->dev); +#endif +} + +inline void rtllib_randomize_cell(struct rtllib_device *ieee) +{ + + get_random_bytes(ieee->current_network.bssid, ETH_ALEN); + + /* an IBSS cell address must have the two less significant + * bits of the first byte = 2 + */ + ieee->current_network.bssid[0] &= ~0x01; + ieee->current_network.bssid[0] |= 0x02; +} + +/* called in user context only */ +void rtllib_start_master_bss(struct rtllib_device *ieee) +{ + ieee->assoc_id = 1; + + if (ieee->current_network.ssid_len == 0){ + strncpy(ieee->current_network.ssid, + RTLLIB_DEFAULT_TX_ESSID, + IW_ESSID_MAX_SIZE); + + ieee->current_network.ssid_len = strlen(RTLLIB_DEFAULT_TX_ESSID); + ieee->ssid_set = 1; + } + + memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN); + + ieee->set_chan(ieee->dev, ieee->current_network.channel); + ieee->state = RTLLIB_LINKED; +#if defined (RTL8192S_WAPI_SUPPORT) + if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){ + WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0); + } +#endif + ieee->link_change(ieee->dev); + notify_wx_assoc_event(ieee); + + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + + netif_carrier_on(ieee->dev); +} + +void rtllib_start_monitor_mode(struct rtllib_device *ieee) +{ + /* reset hardware status */ + if(ieee->raw_tx){ + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + + netif_carrier_on(ieee->dev); + } +} + +void rtllib_start_ibss_wq(void *data) +{ + struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, start_ibss_wq); + /* iwconfig mode ad-hoc will schedule this and return + * on the other hand this will block further iwconfig SET + * operations because of the wx_sem hold. + * Anyway some most set operations set a flag to speed-up + * (abort) this wq (when syncro scanning) before sleeping + * on the semaphore + */ + if(!ieee->proto_started){ + printk("==========oh driver down return\n"); + return; + } + down(&ieee->wx_sem); + + if (ieee->current_network.ssid_len == 0){ + strcpy(ieee->current_network.ssid,RTLLIB_DEFAULT_TX_ESSID); + ieee->current_network.ssid_len = strlen(RTLLIB_DEFAULT_TX_ESSID); + ieee->ssid_set = 1; + } + + ieee->state = RTLLIB_NOLINK; +#ifdef ADHOC_11N + ieee->mode = IEEE_N_24G; +#else + ieee->mode = IEEE_G; +#endif + /* check if we have this cell in our network list */ + rtllib_softmac_check_all_nets(ieee); + + + /* if not then the state is not linked. Maybe the user swithced to + * ad-hoc mode just after being in monitor mode, or just after + * being very few time in managed mode (so the card have had no + * time to scan all the chans..) or we have just run up the iface + * after setting ad-hoc mode. So we have to give another try.. + * Here, in ibss mode, should be safe to do this without extra care + * (in bss mode we had to make sure no-one tryed to associate when + * we had just checked the ieee->state and we was going to start the + * scan) beacause in ibss mode the rtllib_new_net function, when + * finds a good net, just set the ieee->state to RTLLIB_LINKED, + * so, at worst, we waste a bit of time to initiate an unneeded syncro + * scan, that will stop at the first round because it sees the state + * associated. + */ + if (ieee->state == RTLLIB_NOLINK) + rtllib_start_scan_syncro(ieee, 0); + + /* the network definitively is not here.. create a new cell */ + if (ieee->state == RTLLIB_NOLINK){ + printk("creating new IBSS cell\n"); + ieee->current_network.channel = ieee->IbssStartChnl; + if(!ieee->wap_set) + rtllib_randomize_cell(ieee); + + if(ieee->modulation & RTLLIB_CCK_MODULATION){ + + ieee->current_network.rates_len = 4; + + ieee->current_network.rates[0] = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_1MB; + ieee->current_network.rates[1] = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_2MB; + ieee->current_network.rates[2] = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_5MB; + ieee->current_network.rates[3] = RTLLIB_BASIC_RATE_MASK | RTLLIB_CCK_RATE_11MB; + + }else + ieee->current_network.rates_len = 0; + + if(ieee->modulation & RTLLIB_OFDM_MODULATION){ + ieee->current_network.rates_ex_len = 8; + + /*ieee->current_network.rates_ex[0] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_6MB; + ieee->current_network.rates_ex[1] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_9MB; + ieee->current_network.rates_ex[2] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_12MB; + ieee->current_network.rates_ex[3] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_18MB; + ieee->current_network.rates_ex[4] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_24MB; + ieee->current_network.rates_ex[5] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_36MB; + ieee->current_network.rates_ex[6] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_48MB; + ieee->current_network.rates_ex[7] = RTLLIB_BASIC_RATE_MASK | RTLLIB_OFDM_RATE_54MB;*/ + + ieee->current_network.rates_ex[0] = RTLLIB_OFDM_RATE_6MB; + ieee->current_network.rates_ex[1] = RTLLIB_OFDM_RATE_9MB; + ieee->current_network.rates_ex[2] = RTLLIB_OFDM_RATE_12MB; + ieee->current_network.rates_ex[3] = RTLLIB_OFDM_RATE_18MB; + ieee->current_network.rates_ex[4] = RTLLIB_OFDM_RATE_24MB; + ieee->current_network.rates_ex[5] = RTLLIB_OFDM_RATE_36MB; + ieee->current_network.rates_ex[6] = RTLLIB_OFDM_RATE_48MB; + ieee->current_network.rates_ex[7] = RTLLIB_OFDM_RATE_54MB; + + ieee->rate = 108; + }else{ + ieee->current_network.rates_ex_len = 0; + ieee->rate = 22; + } + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) +#ifdef ADHOC_11N + ieee->current_network.qos_data.supported = 1; +#else + ieee->current_network.qos_data.supported = 0; +#endif + ieee->SetWirelessMode(ieee->dev, ieee->mode); +#else + ieee->current_network.qos_data.supported = 0; + ieee->SetWirelessMode(ieee->dev, IEEE_G); +#endif + ieee->current_network.mode = ieee->mode; + ieee->current_network.atim_window = 0; + ieee->current_network.capability = WLAN_CAPABILITY_IBSS; + } + + printk("%s(): ieee->mode = %d\n", __FUNCTION__, ieee->mode); + if((ieee->mode == IEEE_N_24G) || (ieee->mode == IEEE_N_5G)) + HTUseDefaultSetting(ieee); + else + ieee->pHTInfo->bCurrentHTSupport = false; + + ieee->SetHwRegHandler(ieee->dev, HW_VAR_MEDIA_STATUS, (u8 *)(&ieee->state)); + +#if defined (RTL8192S_WAPI_SUPPORT) + if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)){ + WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0); + } +#endif + ieee->state = RTLLIB_LINKED; +#ifdef _RTL8192_EXT_PATCH_ + ieee->set_chan(ieee->dev, ieee->current_network.channel); +#endif + ieee->link_change(ieee->dev); + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + + if(ieee->pHTInfo->bCurBW40MHz) + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20_40, (ieee->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); + else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, (ieee->current_network.channel<=6)?HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER); +#else + HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); +#endif + if(ieee->LedControlHandler != NULL) + ieee->LedControlHandler(ieee->dev,LED_CTL_LINK); + + rtllib_start_send_beacons(ieee); + + notify_wx_assoc_event(ieee); + + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + + netif_carrier_on(ieee->dev); + + up(&ieee->wx_sem); +} + +inline void rtllib_start_ibss(struct rtllib_device *ieee) +{ + queue_delayed_work_rsl(ieee->wq, &ieee->start_ibss_wq, MSECS(150)); +} + +/* this is called only in user context, with wx_sem held */ +void rtllib_start_bss(struct rtllib_device *ieee) +{ + unsigned long flags; +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) + { + if(! ieee->bGlobalDomain) + { + return; + } + } +#endif + /* check if we have already found the net we + * are interested in (if any). + * if not (we are disassociated and we are not + * in associating / authenticating phase) start the background scanning. + */ + rtllib_softmac_check_all_nets(ieee); + + /* ensure no-one start an associating process (thus setting + * the ieee->state to rtllib_ASSOCIATING) while we + * have just cheked it and we are going to enable scan. + * The rtllib_new_net function is always called with + * lock held (from both rtllib_softmac_check_all_nets and + * the rx path), so we cannot be in the middle of such function + */ + spin_lock_irqsave(&ieee->lock, flags); + + if (ieee->state == RTLLIB_NOLINK) { + rtllib_start_scan(ieee); + } + spin_unlock_irqrestore(&ieee->lock, flags); +} + +void rtllib_link_change_wq(void *data) +{ + struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, link_change_wq); + ieee->link_change(ieee->dev); +} +/* called only in userspace context */ +void rtllib_disassociate(struct rtllib_device *ieee) +{ + netif_carrier_off(ieee->dev); + if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) + rtllib_reset_queue(ieee); + + if (ieee->data_hard_stop) + ieee->data_hard_stop(ieee->dev); +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee)) + Dot11d_Reset(ieee); +#endif + ieee->state = RTLLIB_NOLINK; + ieee->is_set_key = false; + ieee->wap_set = 0; + + queue_delayed_work_rsl(ieee->wq, &ieee->link_change_wq, 0); + + +#ifndef FOR_ANDROID_X86 + notify_wx_assoc_event(ieee); +#endif +#ifdef RTL8192S_WAPI_SUPPORT + printk("==============> %s()\n", __FUNCTION__); + WapiReturnOneStaInfo(ieee, ieee->current_network.bssid, 0); +#endif +} +#ifdef RTL8192S_WAPI_SUPPORT +void ieee80211_disassociate_from_app(struct rtllib_device *ieee) +{ + netif_carrier_off(ieee->dev); + if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) + rtllib_reset_queue(ieee); + + if (ieee->data_hard_stop) + ieee->data_hard_stop(ieee->dev); +#ifdef ENABLE_DOT11D + if(IS_DOT11D_ENABLE(ieee)) + Dot11d_Reset(ieee); +#endif + ieee->state = RTLLIB_NOLINK; + ieee->is_set_key = false; + ieee->wap_set = 0; + + queue_delayed_work_rsl(ieee->wq, &ieee->link_change_wq, 0); + + +#ifndef FOR_ANDROID_X86 + notify_wx_assoc_event(ieee); +#endif + + printk("==============> %s()\n", __FUNCTION__); + WapiReturnOneStaInfo(ieee, ieee->current_network.bssid, 1); +} + +#endif +void rtllib_associate_retry_wq(void *data) +{ + struct rtllib_device *ieee = container_of_dwork_rsl(data, struct rtllib_device, associate_retry_wq); + unsigned long flags; + + down(&ieee->wx_sem); + if(!ieee->proto_started) + goto exit; + + if(ieee->state != RTLLIB_ASSOCIATING_RETRY) + goto exit; + + /* until we do not set the state to RTLLIB_NOLINK + * there are no possibility to have someone else trying + * to start an association procdure (we get here with + * ieee->state = RTLLIB_ASSOCIATING). + * When we set the state to RTLLIB_NOLINK it is possible + * that the RX path run an attempt to associate, but + * both rtllib_softmac_check_all_nets and the + * RX path works with ieee->lock held so there are no + * problems. If we are still disassociated then start a scan. + * the lock here is necessary to ensure no one try to start + * an association procedure when we have just checked the + * state and we are going to start the scan. + */ + ieee->beinretry = true; + ieee->state = RTLLIB_NOLINK; + + rtllib_softmac_check_all_nets(ieee); + + spin_lock_irqsave(&ieee->lock, flags); + + if(ieee->state == RTLLIB_NOLINK) + { + rtllib_start_scan(ieee); + } + spin_unlock_irqrestore(&ieee->lock, flags); + + ieee->beinretry = false; +exit: + up(&ieee->wx_sem); +} + +struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee) +{ + u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff}; + + struct sk_buff *skb; + struct rtllib_probe_response *b; +#ifdef _RTL8192_EXT_PATCH_ + if((ieee->iw_mode == IW_MODE_MESH)&&(ieee->ext_patch_get_beacon_get_probersp )) + skb = ieee->ext_patch_get_beacon_get_probersp(ieee, broadcast_addr, &(ieee->current_mesh_network)); + else + skb = rtllib_probe_resp(ieee, broadcast_addr); +#else + skb = rtllib_probe_resp(ieee, broadcast_addr); +#endif + + if (!skb) + return NULL; + + b = (struct rtllib_probe_response *) skb->data; + b->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_BEACON); + + return skb; + +} + +struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee) +{ + struct sk_buff *skb; + struct rtllib_probe_response *b; + + skb = rtllib_get_beacon_(ieee); + if(!skb) + return NULL; + + b = (struct rtllib_probe_response *) skb->data; + b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + return skb; +} + +void rtllib_softmac_stop_protocol(struct rtllib_device *ieee, u8 mesh_flag, u8 shutdown) +{ + rtllib_stop_scan_syncro(ieee); + down(&ieee->wx_sem); +#ifdef _RTL8192_EXT_PATCH_ + if(mesh_flag) { + rtllib_stop_mesh_protocol(ieee); + } + else +#endif + rtllib_stop_protocol(ieee,shutdown); + up(&ieee->wx_sem); +} + + +void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown) +{ + if (!ieee->proto_started) + return; + + if(shutdown){ + ieee->proto_started = 0; + ieee->proto_stoppping = 1; +#ifdef ENABLE_IPS + if(ieee->rtllib_ips_leave != NULL) + ieee->rtllib_ips_leave(ieee->dev); +#endif + } + + rtllib_stop_send_beacons(ieee); + del_timer_sync(&ieee->associate_timer); +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + del_timer_sync(&ieee->ibss_wait_timer); +#endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + cancel_delayed_work(&ieee->associate_retry_wq); + cancel_delayed_work(&ieee->start_ibss_wq); + cancel_delayed_work(&ieee->link_change_wq); +#endif + rtllib_stop_scan(ieee); + + if(ieee->state <= RTLLIB_ASSOCIATING_AUTHENTICATED) + ieee->state = RTLLIB_NOLINK; + + if (ieee->state == RTLLIB_LINKED){ + if (ieee->iw_mode == IW_MODE_INFRA) + SendDisassociation(ieee,1,deauth_lv_ss); + rtllib_disassociate(ieee); + } + + if(shutdown){ + RemoveAllTS(ieee); + ieee->proto_stoppping = 0; +#ifdef RTL8192S_WAPI_SUPPORT + if ((ieee->WapiSupport) && (ieee->wapiInfo.bWapiEnable)) + { + WapiReturnAllStaInfo(ieee); + } +#endif + } +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + if(ieee->iw_mode == IW_MODE_ADHOC) + DelStaInfoList(ieee); +#endif + + if(ieee->assocreq_ies){ + kfree(ieee->assocreq_ies); + ieee->assocreq_ies = NULL; + ieee->assocreq_ies_len = 0; + } + if(ieee->assocresp_ies){ + kfree(ieee->assocresp_ies); + ieee->assocresp_ies = NULL; + ieee->assocresp_ies_len = 0; + } +} + +#ifdef _RTL8192_EXT_PATCH_ +void rtllib_stop_mesh_protocol(struct rtllib_device *ieee) +{ + if (!ieee->mesh_started) + return; + ieee->mesh_started = 0; + + if(ieee->ext_patch_rtllib_stop_protocol) + ieee->ext_patch_rtllib_stop_protocol(ieee,0); + + rtllib_stop_send_beacons(ieee); +} +#endif + +void rtllib_softmac_start_protocol(struct rtllib_device *ieee, u8 mesh_flag) +{ + down(&ieee->wx_sem); +#ifdef _RTL8192_EXT_PATCH_ + if (mesh_flag) { + rtllib_start_mesh_protocol(ieee); + } + else +#endif + rtllib_start_protocol(ieee); + up(&ieee->wx_sem); +} + +void rtllib_start_protocol(struct rtllib_device *ieee) +{ + short ch = 0; + int i = 0; + + rtllib_update_active_chan_map(ieee); + + if (ieee->proto_started) + return; + + ieee->proto_started = 1; + + if (ieee->current_network.channel == 0) { + do { + ch++; + if (ch > MAX_CHANNEL_NUMBER) + return; /* no channel found */ + } while(!ieee->active_channel_map[ch]); + ieee->current_network.channel = ch; + } + + if (ieee->current_network.beacon_interval == 0) + ieee->current_network.beacon_interval = 100; + + for(i = 0; i < 17; i++) { + ieee->last_rxseq_num[i] = -1; + ieee->last_rxfrag_num[i] = -1; + ieee->last_packet_time[i] = 0; + } + + if(ieee->UpdateBeaconInterruptHandler) { +#ifdef _RTL8192_EXT_PATCH_ + if (ieee->iw_mode == IW_MODE_MESH) + ieee->UpdateBeaconInterruptHandler(ieee->dev, true); + else +#endif + ieee->UpdateBeaconInterruptHandler(ieee->dev, false); + } + ieee->wmm_acm = 0; + /* if the user set the MAC of the ad-hoc cell and then + * switch to managed mode, shall we make sure that association + * attempts does not fail just because the user provide the essid + * and the nic is still checking for the AP MAC ?? + */ +#ifdef _RTL8192_EXT_PATCH_ + if ((ieee->iw_mode == IW_MODE_INFRA) || ((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0))) +#else + if (ieee->iw_mode == IW_MODE_INFRA) +#endif + { + rtllib_start_bss(ieee); + }else if (ieee->iw_mode == IW_MODE_ADHOC){ + if(ieee->UpdateBeaconInterruptHandler) + ieee->UpdateBeaconInterruptHandler(ieee->dev, true); + + rtllib_start_ibss(ieee); + + }else if (ieee->iw_mode == IW_MODE_MASTER) + rtllib_start_master_bss(ieee); + + else if(ieee->iw_mode == IW_MODE_MONITOR) + rtllib_start_monitor_mode(ieee); +} + +#ifdef _RTL8192_EXT_PATCH_ +void rtllib_start_mesh_protocol(struct rtllib_device *ieee) +{ + short ch = 0; + + rtllib_update_active_chan_map(ieee); + + if (ieee->mesh_started) + return; + + ieee->mesh_started = 1; + + if (ieee->current_mesh_network.channel == 0){ + do { + ch++; + if (ch > MAX_CHANNEL_NUMBER) + return; /* no channel found */ + } while(ieee->active_channel_map[ch]); + + ieee->current_mesh_network.channel = ch; + } + + if (ieee->current_mesh_network.beacon_interval == 0) + ieee->current_mesh_network.beacon_interval = 100; + ieee->wmm_acm = 0; + + if(ieee->UpdateBeaconInterruptHandler) + ieee->UpdateBeaconInterruptHandler(ieee->dev, true); + + if(ieee->ext_patch_rtllib_start_mesh) + ieee->ext_patch_rtllib_start_mesh(ieee); +} +#endif + + +#define DRV_NAME "Ieee80211" +void rtllib_softmac_init(struct rtllib_device *ieee) +{ + int i; + memset(&ieee->current_network, 0, sizeof(struct rtllib_network)); + + ieee->state = RTLLIB_NOLINK; +#ifdef _RTL8192_EXT_PATCH_ + ieee->mesh_state = RTLLIB_NOLINK; +#endif + for(i = 0; i < 5; i++) { + ieee->seq_ctrl[i] = 0; + } +#ifdef ENABLE_DOT11D + ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC); + if (!ieee->pDot11dInfo) + RTLLIB_DEBUG(RTLLIB_DL_ERR, "can't alloc memory for DOT11D\n"); + memset(ieee->pDot11dInfo, 0, sizeof(RT_DOT11D_INFO)); +#endif + ieee->LinkDetectInfo.SlotIndex = 0; + ieee->LinkDetectInfo.SlotNum = 2; + ieee->LinkDetectInfo.NumRecvBcnInPeriod=0; + ieee->LinkDetectInfo.NumRecvDataInPeriod=0; + ieee->LinkDetectInfo.NumTxOkInPeriod =0; + ieee->LinkDetectInfo.NumRxOkInPeriod =0; + ieee->LinkDetectInfo.NumRxUnicastOkInPeriod=0; +#ifdef _RTL8192_EXT_PATCH_ + ieee->LinkDetectInfo.NumTxUnicastOkInPeriod = 0; + ieee->LinkDetectInfo.LastNumRxUnicast = 0; + ieee->LinkDetectInfo.LastNumTxUnicast = 0; + ieee->LinkDetectInfo.IdleCount = 0; +#endif + ieee->bIsAggregateFrame = false; + ieee->assoc_id = 0; + ieee->queue_stop = 0; + ieee->scanning_continue = 0; + ieee->softmac_features = 0; + ieee->wap_set = 0; + ieee->ssid_set = 0; + ieee->proto_started = 0; + ieee->proto_stoppping = 0; + ieee->basic_rate = RTLLIB_DEFAULT_BASIC_RATE; + ieee->rate = 22; + ieee->ps = RTLLIB_PS_DISABLED; + ieee->sta_sleep = LPS_IS_WAKE; + +#ifdef _RTL8192_EXT_PATCH_ + ieee->mesh_started = 0; +#endif + ieee->Regdot11HTOperationalRateSet[0]= 0xff; + ieee->Regdot11HTOperationalRateSet[1]= 0xff; + ieee->Regdot11HTOperationalRateSet[4]= 0x01; + + ieee->Regdot11TxHTOperationalRateSet[0]= 0xff; + ieee->Regdot11TxHTOperationalRateSet[1]= 0xff; + ieee->Regdot11TxHTOperationalRateSet[4]= 0x01; + + ieee->FirstIe_InScan = false; + ieee->actscanning = false; + ieee->beinretry = false; + ieee->is_set_key = false; + init_mgmt_queue(ieee); + + ieee->sta_edca_param[0] = 0x0000A403; + ieee->sta_edca_param[1] = 0x0000A427; + ieee->sta_edca_param[2] = 0x005E4342; + ieee->sta_edca_param[3] = 0x002F3262; + ieee->aggregation = true; + ieee->enable_rx_imm_BA = 1; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,40) + _setup_timer(&ieee->scan_timer, + rtllib_softmac_scan_cb, + (unsigned long) ieee); +#endif + ieee->tx_pending.txb = NULL; + + _setup_timer(&ieee->associate_timer, + rtllib_associate_abort_cb, + (unsigned long) ieee); + + _setup_timer(&ieee->beacon_timer, + rtllib_send_beacon_cb, + (unsigned long) ieee); + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) + _setup_timer(&ieee->ibss_wait_timer, + rtllib_ibss_wait_timeout, + (unsigned long) ieee); +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) +#ifdef PF_SYNCTHREAD + ieee->wq = create_workqueue(DRV_NAME,0); +#else + ieee->wq = create_workqueue(DRV_NAME); +#endif +#endif + + INIT_DELAYED_WORK_RSL(&ieee->link_change_wq,(void*)rtllib_link_change_wq,ieee); + INIT_DELAYED_WORK_RSL(&ieee->start_ibss_wq,(void*)rtllib_start_ibss_wq,ieee); + INIT_WORK_RSL(&ieee->associate_complete_wq, (void*)rtllib_associate_complete_wq,ieee); + INIT_DELAYED_WORK_RSL(&ieee->associate_procedure_wq, (void*)rtllib_associate_procedure_wq,ieee); + INIT_DELAYED_WORK_RSL(&ieee->softmac_scan_wq,(void*)rtllib_softmac_scan_wq,ieee); + INIT_DELAYED_WORK_RSL(&ieee->softmac_hint11d_wq,(void*)rtllib_softmac_hint11d_wq,ieee); + INIT_DELAYED_WORK_RSL(&ieee->associate_retry_wq, (void*)rtllib_associate_retry_wq,ieee); + INIT_WORK_RSL(&ieee->wx_sync_scan_wq,(void*)rtllib_wx_sync_scan_wq,ieee); + +#ifdef _RTL8192_EXT_PATCH_ + INIT_WORK_RSL(&ieee->ext_stop_scan_wq,(void*) rtllib_ext_stop_scan_wq,ieee); + INIT_WORK_RSL(&ieee->ext_send_beacon_wq,(void*) ext_rtllib_send_beacon_wq,ieee); +#endif + + sema_init(&ieee->wx_sem, 1); + sema_init(&ieee->scan_sem, 1); + sema_init(&ieee->ips_sem,1); + + spin_lock_init(&ieee->mgmt_tx_lock); + spin_lock_init(&ieee->beacon_lock); + + tasklet_init(&ieee->ps_task, + (void(*)(unsigned long)) rtllib_sta_ps, + (unsigned long)ieee); + +} + +void rtllib_softmac_free(struct rtllib_device *ieee) +{ + down(&ieee->wx_sem); +#ifdef ENABLE_DOT11D + if(NULL != ieee->pDot11dInfo) + { + kfree(ieee->pDot11dInfo); + ieee->pDot11dInfo = NULL; + } +#endif + del_timer_sync(&ieee->associate_timer); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + cancel_delayed_work(&ieee->associate_retry_wq); + destroy_workqueue(ieee->wq); +#endif + + up(&ieee->wx_sem); +} + +/******************************************************** + * Start of WPA code. * + * this is stolen from the ipw2200 driver * + ********************************************************/ + + +static int rtllib_wpa_enable(struct rtllib_device *ieee, int value) +{ + /* This is called when wpa_supplicant loads and closes the driver + * interface. */ + printk("%s WPA\n",value ? "enabling" : "disabling"); + ieee->wpa_enabled = value; + memset(ieee->ap_mac_addr, 0, 6); + return 0; +} + + +void rtllib_wpa_assoc_frame(struct rtllib_device *ieee, char *wpa_ie, int wpa_ie_len) +{ + /* make sure WPA is enabled */ + rtllib_wpa_enable(ieee, 1); + + rtllib_disassociate(ieee); +} + + +static int rtllib_wpa_mlme(struct rtllib_device *ieee, int command, int reason) +{ + + int ret = 0; + + switch (command) { + case IEEE_MLME_STA_DEAUTH: + break; + + case IEEE_MLME_STA_DISASSOC: + rtllib_disassociate(ieee); + break; + + default: + printk("Unknown MLME request: %d\n", command); + ret = -EOPNOTSUPP; + } + + return ret; +} + + +static int rtllib_wpa_set_wpa_ie(struct rtllib_device *ieee, + struct ieee_param *param, int plen) +{ + u8 *buf; + + if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || + (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) + return -EINVAL; + + if (param->u.wpa_ie.len) { + buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len); + kfree(ieee->wpa_ie); + ieee->wpa_ie = buf; + ieee->wpa_ie_len = param->u.wpa_ie.len; + } else { + kfree(ieee->wpa_ie); + ieee->wpa_ie = NULL; + ieee->wpa_ie_len = 0; + } + + rtllib_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len); + return 0; +} + +#define AUTH_ALG_OPEN_SYSTEM 0x1 +#define AUTH_ALG_SHARED_KEY 0x2 +#define AUTH_ALG_LEAP 0x4 +static int rtllib_wpa_set_auth_algs(struct rtllib_device *ieee, int value) +{ + + struct rtllib_security sec = { + .flags = SEC_AUTH_MODE, + }; + int ret = 0; + + if (value & AUTH_ALG_SHARED_KEY) { + sec.auth_mode = WLAN_AUTH_SHARED_KEY; + ieee->open_wep = 0; + ieee->auth_mode = 1; + } else if (value & AUTH_ALG_OPEN_SYSTEM){ + sec.auth_mode = WLAN_AUTH_OPEN; + ieee->open_wep = 1; + ieee->auth_mode = 0; + } + else if (value & AUTH_ALG_LEAP){ + sec.auth_mode = WLAN_AUTH_LEAP >> 6; + ieee->open_wep = 1; + ieee->auth_mode = 2; + } + + + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + + return ret; +} + +static int rtllib_wpa_set_param(struct rtllib_device *ieee, u8 name, u32 value) +{ + int ret=0; + unsigned long flags; + + switch (name) { + case IEEE_PARAM_WPA_ENABLED: + ret = rtllib_wpa_enable(ieee, value); + break; + + case IEEE_PARAM_TKIP_COUNTERMEASURES: + ieee->tkip_countermeasures=value; + break; + + case IEEE_PARAM_DROP_UNENCRYPTED: + { + /* HACK: + * + * wpa_supplicant calls set_wpa_enabled when the driver + * is loaded and unloaded, regardless of if WPA is being + * used. No other calls are made which can be used to + * determine if encryption will be used or not prior to + * association being expected. If encryption is not being + * used, drop_unencrypted is set to false, else true -- we + * can use this to determine if the CAP_PRIVACY_ON bit should + * be set. + */ + struct rtllib_security sec = { + .flags = SEC_ENABLED, + .enabled = value, + }; + ieee->drop_unencrypted = value; + /* We only change SEC_LEVEL for open mode. Others + * are set by ipw_wpa_set_encryption. + */ + if (!value) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_0; + } + else { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + break; + } + + case IEEE_PARAM_PRIVACY_INVOKED: + ieee->privacy_invoked=value; + break; + + case IEEE_PARAM_AUTH_ALGS: + ret = rtllib_wpa_set_auth_algs(ieee, value); + break; + + case IEEE_PARAM_IEEE_802_1X: + ieee->ieee802_1x=value; + break; + case IEEE_PARAM_WPAX_SELECT: + spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags); + spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags); + break; + + default: + printk("Unknown WPA param: %d\n",name); + ret = -EOPNOTSUPP; + } + + return ret; +} + +/* implementation borrowed from hostap driver */ +static int rtllib_wpa_set_encryption(struct rtllib_device *ieee, + struct ieee_param *param, int param_len, u8 is_mesh) +{ + int ret = 0; +#ifdef _RTL8192_EXT_PATCH_ + u8 i = 0; +#endif + struct rtllib_crypto_ops *ops; + struct rtllib_crypt_data **crypt; + + struct rtllib_security sec = { + .flags = 0, + }; + + param->u.crypt.err = 0; + param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; + + if (param_len != + (int) ((char *) param->u.crypt.key - (char *) param) + + param->u.crypt.key_len) { + printk("Len mismatch %d, %d\n", param_len, + param->u.crypt.key_len); + return -EINVAL; + } + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { + if (param->u.crypt.idx >= WEP_KEYS) + return -EINVAL; +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + crypt = &ieee->cryptlist[0]->crypt[param->u.crypt.idx]; + else + crypt = &ieee->sta_crypt[param->u.crypt.idx]; +#else + crypt = &ieee->crypt[param->u.crypt.idx]; +#endif + } else { + return -EINVAL; + } + + if (strcmp(param->u.crypt.alg, "none") == 0) { + if (crypt) { + sec.enabled = 0; + sec.level = SEC_LEVEL_0; + sec.flags |= SEC_ENABLED | SEC_LEVEL; + rtllib_crypt_delayed_deinit(ieee, crypt); + } + goto done; + } + sec.enabled = 1; + sec.flags |= SEC_ENABLED; + + /* IPW HW cannot build TKIP MIC, host decryption still needed. */ + if (!(ieee->host_encrypt || ieee->host_decrypt) && + strcmp(param->u.crypt.alg, "TKIP")) + goto skip_host_crypt; + + ops = rtllib_get_crypto_ops(param->u.crypt.alg); + if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { + request_module("rtllib_crypt_wep"); + ops = rtllib_get_crypto_ops(param->u.crypt.alg); + } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { + request_module("rtllib_crypt_tkip"); + ops = rtllib_get_crypto_ops(param->u.crypt.alg); + } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { + request_module("rtllib_crypt_ccmp"); + ops = rtllib_get_crypto_ops(param->u.crypt.alg); + } + if (ops == NULL) { + printk("unknown crypto alg '%s'\n", param->u.crypt.alg); + param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG; + ret = -EINVAL; + goto done; + } +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + { + for (i=0; icryptlist[i]->crypt[param->u.crypt.idx]; + + *crypt = ieee->cryptlist[i]->crypt[param->u.crypt.idx]; + } +#endif + + if (*crypt == NULL || (*crypt)->ops != ops) { + struct rtllib_crypt_data *new_crypt; + + rtllib_crypt_delayed_deinit(ieee, crypt); + + new_crypt = (struct rtllib_crypt_data *) + kmalloc(sizeof(*new_crypt), GFP_KERNEL); + if (new_crypt == NULL) { + ret = -ENOMEM; + goto done; + } + memset(new_crypt, 0, sizeof(struct rtllib_crypt_data)); + new_crypt->ops = ops; +#ifdef BUILT_IN_RTLLIB + if (new_crypt->ops) +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) +#else + if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner)) +#endif +#endif + new_crypt->priv = + new_crypt->ops->init(param->u.crypt.idx); + + if (new_crypt->priv == NULL) { + kfree(new_crypt); + param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED; + ret = -EINVAL; + goto done; + } + + *crypt = new_crypt; + } + + if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key && + (*crypt)->ops->set_key(param->u.crypt.key, + param->u.crypt.key_len, param->u.crypt.seq, + (*crypt)->priv) < 0) { + printk("key setting failed\n"); + param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED; + ret = -EINVAL; + goto done; + } +#ifdef _RTL8192_EXT_PATCH_ + } +#endif + + skip_host_crypt: + if (param->u.crypt.set_tx) { + ieee->tx_keyidx = param->u.crypt.idx; + sec.active_key = param->u.crypt.idx; + sec.flags |= SEC_ACTIVE_KEY; + } else + sec.flags &= ~SEC_ACTIVE_KEY; + + if (param->u.crypt.alg != NULL) { + memcpy(sec.keys[param->u.crypt.idx], + param->u.crypt.key, + param->u.crypt.key_len); + sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len; + sec.flags |= (1 << param->u.crypt.idx); + + if (strcmp(param->u.crypt.alg, "WEP") == 0) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_2; + } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_3; + } + } + done: + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + +#ifdef _RTL8192_EXT_PATCH_ + if (ret != 0) + { + if(is_mesh) + { + for (i=0; icryptlist[i]->crypt[param->u.crypt.idx]==NULL){ + break; + } + else{ + kfree(ieee->cryptlist[i]->crypt[param->u.crypt.idx]); + ieee->cryptlist[i]->crypt[param->u.crypt.idx] = NULL; + } + } + } + else + { + kfree(ieee->sta_crypt[param->u.crypt.idx]); + ieee->sta_crypt[param->u.crypt.idx] = NULL; + } + } +#endif + + + /* Do not reset port if card is in Managed mode since resetting will + * generate new IEEE 802.11 authentication which may end up in looping + * with IEEE 802.1X. If your hardware requires a reset after WEP + * configuration (for example... Prism2), implement the reset_port in + * the callbacks structures used to initialize the 802.11 stack. */ + if (ieee->reset_on_keychange && + ieee->iw_mode != IW_MODE_INFRA && + ieee->reset_port && + ieee->reset_port(ieee->dev)) { + printk("reset_port failed\n"); + param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED; + return -EINVAL; + } + + return ret; +} + +inline struct sk_buff *rtllib_disauth_skb( struct rtllib_network *beacon, + struct rtllib_device *ieee, u16 asRsn) +{ + struct sk_buff *skb; + struct rtllib_disauth *disauth; +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr=0; + int alignment=0; + int len = sizeof(struct rtllib_disauth) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE; +#else + int len = sizeof(struct rtllib_disauth) + ieee->tx_headroom; + +#endif + skb = dev_alloc_skb(len); + if (!skb) { + return NULL; + } + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + skb_reserve(skb, ieee->tx_headroom); + + disauth = (struct rtllib_disauth *) skb_put(skb,sizeof(struct rtllib_disauth)); + disauth->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_DEAUTH); + disauth->header.duration_id = 0; + + memcpy(disauth->header.addr1, beacon->bssid, ETH_ALEN); + memcpy(disauth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy(disauth->header.addr3, beacon->bssid, ETH_ALEN); + + disauth->reason = cpu_to_le16(asRsn); + return skb; +} + +inline struct sk_buff *rtllib_disassociate_skb( struct rtllib_network *beacon, + struct rtllib_device *ieee, u16 asRsn) +{ + struct sk_buff *skb; + struct rtllib_disassoc *disass; +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr=0; + int alignment=0; + int len = sizeof(struct rtllib_disassoc) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE; +#else + int len = sizeof(struct rtllib_disassoc) + ieee->tx_headroom; +#endif + skb = dev_alloc_skb(len); + + if (!skb) { + return NULL; + } + +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)skb->data; + alignment = Tmpaddr & 0x1ff; + skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + skb_reserve(skb, ieee->tx_headroom); + + disass = (struct rtllib_disassoc *) skb_put(skb,sizeof(struct rtllib_disassoc)); + disass->header.frame_ctl = cpu_to_le16(RTLLIB_STYPE_DISASSOC); + disass->header.duration_id = 0; + + memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN); + memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN); + memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN); + + disass->reason = cpu_to_le16(asRsn); + return skb; +} + +void SendDisassociation(struct rtllib_device *ieee, bool deauth, u16 asRsn) +{ + struct rtllib_network *beacon = &ieee->current_network; + struct sk_buff *skb; + + if(deauth) { + skb = rtllib_disauth_skb(beacon,ieee,asRsn); + } else { + skb = rtllib_disassociate_skb(beacon,ieee,asRsn); + } + + if (skb){ + softmac_mgmt_xmit(skb, ieee); + } +} + +u8 rtllib_ap_sec_type(struct rtllib_device *ieee) +{ + static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04}; + static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04}; + int wpa_ie_len= ieee->wpa_ie_len; + struct rtllib_crypt_data* crypt; + int encrypt; + +#ifdef _RTL8192_EXT_PATCH_ + crypt = ieee->sta_crypt[ieee->tx_keyidx]; +#else + crypt = ieee->crypt[ieee->tx_keyidx]; +#endif + encrypt = (ieee->current_network.capability & WLAN_CAPABILITY_PRIVACY) ||\ + (ieee->host_encrypt && crypt && crypt->ops && \ + (0 == strcmp(crypt->ops->name,"WEP"))); + + /* simply judge */ + if(encrypt && (wpa_ie_len == 0)) { + return SEC_ALG_WEP; + } else if((wpa_ie_len != 0)) { + if (((ieee->wpa_ie[0] == 0xdd) && (!memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) || + ((ieee->wpa_ie[0] == 0x30) && (!memcmp(&ieee->wpa_ie[10],ccmp_rsn_ie, 4)))) + return SEC_ALG_CCMP; + else + return SEC_ALG_TKIP; + } else { + return SEC_ALG_NONE; + } +} + +int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee, struct iw_point *p, u8 is_mesh) +{ + struct ieee_param *param; + int ret=0; + + down(&ieee->wx_sem); + + if (p->length < sizeof(struct ieee_param) || !p->pointer){ + ret = -EINVAL; + goto out; + } + + param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL); + if (param == NULL){ + ret = -ENOMEM; + goto out; + } + if (copy_from_user(param, p->pointer, p->length)) { + kfree(param); + ret = -EFAULT; + goto out; + } + + switch (param->cmd) { + + case IEEE_CMD_SET_WPA_PARAM: + ret = rtllib_wpa_set_param(ieee, param->u.wpa_param.name, + param->u.wpa_param.value); + break; + + case IEEE_CMD_SET_WPA_IE: + ret = rtllib_wpa_set_wpa_ie(ieee, param, p->length); + break; + + case IEEE_CMD_SET_ENCRYPTION: +#ifdef _RTL8192_EXT_PATCH_ + ret = rtllib_wpa_set_encryption(ieee, param, p->length, is_mesh); +#else + ret = rtllib_wpa_set_encryption(ieee, param, p->length, 0); +#endif + break; + + case IEEE_CMD_MLME: + ret = rtllib_wpa_mlme(ieee, param->u.mlme.command, + param->u.mlme.reason_code); + break; + + default: + printk("Unknown WPA supplicant request: %d\n",param->cmd); + ret = -EOPNOTSUPP; + break; + } + + if (ret == 0 && copy_to_user(p->pointer, param, p->length)) + ret = -EFAULT; + + kfree(param); +out: + up(&ieee->wx_sem); + + return ret; +} + +void +rtllib_MgntDisconnectIBSS(struct rtllib_device* rtllib) +{ + u8 OpMode; + u8 i; + bool bFilterOutNonAssociatedBSSID = false; + + rtllib->state = RTLLIB_NOLINK; + + for(i=0;i<6;i++) rtllib->current_network.bssid[i]= 0x55; + + rtllib->OpMode = RT_OP_MODE_NO_LINK; + rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_BSSID, rtllib->current_network.bssid); + OpMode = RT_OP_MODE_NO_LINK; + rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_MEDIA_STATUS, &OpMode); + rtllib_stop_send_beacons(rtllib); + + bFilterOutNonAssociatedBSSID = false; + rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_CECHK_BSSID, (u8*)(&bFilterOutNonAssociatedBSSID)); + notify_wx_assoc_event(rtllib); + +} + +void +rtllib_MlmeDisassociateRequest( + struct rtllib_device* rtllib, + u8* asSta, + u8 asRsn + ) +{ + u8 i; + u8 OpMode; + + RemovePeerTS(rtllib, asSta); + + + if(memcpy(rtllib->current_network.bssid,asSta,6) == 0) + { + rtllib->state = RTLLIB_NOLINK; + + for(i=0;i<6;i++) rtllib->current_network.bssid[i] = 0x22; + OpMode = RT_OP_MODE_NO_LINK; + rtllib->OpMode = RT_OP_MODE_NO_LINK; + rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_MEDIA_STATUS, (u8 *)(&OpMode) ); + rtllib_disassociate(rtllib); + + rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_BSSID, rtllib->current_network.bssid); + + } + +} + +void +rtllib_MgntDisconnectAP( + struct rtllib_device* rtllib, + u8 asRsn +) +{ + bool bFilterOutNonAssociatedBSSID = false; + + +#ifdef TO_DO + if( pMgntInfo->SecurityInfo.AuthMode > RT_802_11AuthModeAutoSwitch || + (pMgntInfo->bAPSuportCCKM && pMgntInfo->bCCX8021xenable) ) + { + SecClearAllKeys(rtllib->dev); + RT_TRACE(COMP_SEC, DBG_LOUD,("======>CCKM clear key...")) + } +#endif + bFilterOutNonAssociatedBSSID = false; + rtllib->SetHwRegHandler(rtllib->dev, HW_VAR_CECHK_BSSID, (u8*)(&bFilterOutNonAssociatedBSSID)); + rtllib_MlmeDisassociateRequest( rtllib, rtllib->current_network.bssid, asRsn ); + + rtllib->state = RTLLIB_NOLINK; +} + +bool +rtllib_MgntDisconnect( + struct rtllib_device* rtllib, + u8 asRsn +) +{ + if(rtllib->ps != RTLLIB_PS_DISABLED) + { +#ifndef RTL8190P + rtllib->sta_wake_up(rtllib->dev); +#endif + } + +#ifdef TO_DO + if(pMgntInfo->mActingAsAp) + { + RT_TRACE(COMP_MLME, DBG_LOUD, ("MgntDisconnect() ===> AP_DisassociateAllStation\n")); + AP_DisassociateAllStation(rtllib->dev, unspec_reason); + return true; + } +#endif + + if( rtllib->state == RTLLIB_LINKED ) + { + if( rtllib->iw_mode == IW_MODE_ADHOC ) + { + rtllib_MgntDisconnectIBSS(rtllib); + } +#ifdef _RTL8192_EXT_PATCH_ + if((rtllib->iw_mode == IW_MODE_INFRA ) || ((rtllib->iw_mode == IW_MODE_MESH) && (rtllib->only_mesh == 0))) +#else + if( rtllib->iw_mode == IW_MODE_INFRA ) +#endif + { +#ifdef TO_DO_LIST + SecClearAllKeys(Adapter); +#endif + rtllib_MgntDisconnectAP(rtllib, asRsn); + } + + } + + return true; +} + +void notify_wx_assoc_event(struct rtllib_device *ieee) +{ + union iwreq_data wrqu; + + if(ieee->cannot_notify) + return; + + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + if (ieee->state == RTLLIB_LINKED) + memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN); + else{ + + printk("%s(): Tell user space disconnected\n",__func__); + memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); + } + wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL); +} + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(rtllib_get_beacon); +EXPORT_SYMBOL_RSL(rtllib_wake_queue); +EXPORT_SYMBOL_RSL(rtllib_stop_queue); +EXPORT_SYMBOL_RSL(rtllib_reset_queue); +EXPORT_SYMBOL_RSL(rtllib_softmac_stop_protocol); +EXPORT_SYMBOL_RSL(rtllib_softmac_start_protocol); +EXPORT_SYMBOL_RSL(rtllib_is_shortslot); +EXPORT_SYMBOL_RSL(rtllib_is_54g); +EXPORT_SYMBOL_RSL(rtllib_wpa_supplicant_ioctl); +EXPORT_SYMBOL_RSL(rtllib_ps_tx_ack); +EXPORT_SYMBOL_RSL(rtllib_softmac_xmit); +EXPORT_SYMBOL_RSL(rtllib_stop_send_beacons); +EXPORT_SYMBOL_RSL(notify_wx_assoc_event); +EXPORT_SYMBOL_RSL(SendDisassociation); +EXPORT_SYMBOL_RSL(rtllib_disassociate); +EXPORT_SYMBOL_RSL(rtllib_start_send_beacons); +EXPORT_SYMBOL_RSL(rtllib_stop_scan); +EXPORT_SYMBOL_RSL(rtllib_send_probe_requests); +EXPORT_SYMBOL_RSL(rtllib_softmac_scan_syncro); +EXPORT_SYMBOL_RSL(rtllib_start_scan_syncro); +EXPORT_SYMBOL_RSL(rtllib_sta_ps_send_null_frame); +EXPORT_SYMBOL_RSL(rtllib_sta_ps_send_pspoll_frame); +EXPORT_SYMBOL_RSL(rtllib_sta_wakeup); +EXPORT_SYMBOL_RSL(rtllib_ap_sec_type); +#ifdef _RTL8192_EXT_PATCH_ +EXPORT_SYMBOL_RSL(rtllib_MFIE_rate_len); +EXPORT_SYMBOL_RSL(rtllib_MFIE_Brate); +EXPORT_SYMBOL_RSL(rtllib_MFIE_Grate); +EXPORT_SYMBOL_RSL(rtllib_WMM_Info); +EXPORT_SYMBOL_RSL(rtllib_TURBO_Info); +EXPORT_SYMBOL_RSL(rtllib_ext_probe_resp_by_net); +EXPORT_SYMBOL_RSL(softmac_mgmt_xmit); +EXPORT_SYMBOL_RSL(rtllib_start_scan); +EXPORT_SYMBOL_RSL(rtllib_ext_send_11s_beacon); +EXPORT_SYMBOL_RSL(rtllib_rx_auth_rq); +EXPORT_SYMBOL_RSL(rtllib_associate_step1); +EXPORT_SYMBOL_RSL(rtllib_stop_protocol); +EXPORT_SYMBOL_RSL(rtllib_start_protocol); +EXPORT_SYMBOL_RSL(rtllib_resp_to_auth); + +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib_softmac_wx.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib_softmac_wx.c @@ -0,0 +1,747 @@ +/* IEEE 802.11 SoftMAC layer + * Copyright (c) 2005 Andrea Merello + * + * Mostly extracted from the rtl8180-sa2400 driver for the + * in-kernel generic ieee802.11 stack. + * + * Some pieces of code might be stolen from ipw2100 driver + * copyright of who own it's copyright ;-) + * + * PS wx handler mostly stolen from hostap, copyright who + * own it's copyright ;-) + * + * released under the GPL + */ + + +#include "rtllib.h" +#ifdef ENABLE_DOT11D +#include "dot11d.h" +#endif +/* FIXME: add A freqs */ + +const long rtllib_wlan_frequencies[] = { + 2412, 2417, 2422, 2427, + 2432, 2437, 2442, 2447, + 2452, 2457, 2462, 2467, + 2472, 2484 +}; + + +int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + int ret; + struct iw_freq *fwrq = & wrqu->freq; + + down(&ieee->wx_sem); + + if(ieee->iw_mode == IW_MODE_INFRA){ + ret = 0; + goto out; + } + + /* if setting by freq convert to channel */ + if (fwrq->e == 1) { + if ((fwrq->m >= (int) 2.412e8 && + fwrq->m <= (int) 2.487e8)) { + int f = fwrq->m / 100000; + int c = 0; + + while ((c < 14) && (f != rtllib_wlan_frequencies[c])) + c++; + + /* hack to fall through */ + fwrq->e = 0; + fwrq->m = c + 1; + } + } + + if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1 ){ + ret = -EOPNOTSUPP; + goto out; + + }else { /* Set the channel */ + +#ifdef ENABLE_DOT11D + if (ieee->active_channel_map[fwrq->m] != 1) { + ret = -EINVAL; + goto out; + } +#endif + ieee->current_network.channel = fwrq->m; + ieee->set_chan(ieee->dev, ieee->current_network.channel); + + if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) + if(ieee->state == RTLLIB_LINKED){ + + rtllib_stop_send_beacons(ieee); + rtllib_start_send_beacons(ieee); + } + } + + ret = 0; +out: + up(&ieee->wx_sem); + return ret; +} + + +#ifdef _RTL8192_EXT_PATCH_ +int rtllib_wx_get_freq(struct rtllib_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b, u8 is_mesh) +#else +int rtllib_wx_get_freq(struct rtllib_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +#endif +{ + struct iw_freq *fwrq = & wrqu->freq; + +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + { + if (ieee->current_mesh_network.channel == 0) + return -1; + fwrq->m = rtllib_wlan_frequencies[ieee->current_mesh_network.channel-1] * 100000; + fwrq->e = 1; + } + else +#endif + { + if (ieee->current_network.channel == 0) + return -1; + fwrq->m = rtllib_wlan_frequencies[ieee->current_network.channel-1] * 100000; + fwrq->e = 1; + } + return 0; +} + +int rtllib_wx_get_wap(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + unsigned long flags; + + wrqu->ap_addr.sa_family = ARPHRD_ETHER; + + if (ieee->iw_mode == IW_MODE_MONITOR) + return -1; + + /* We want avoid to give to the user inconsistent infos*/ + spin_lock_irqsave(&ieee->lock, flags); + + if (ieee->state != RTLLIB_LINKED && + ieee->state != RTLLIB_LINKED_SCANNING && + ieee->wap_set == 0) + + memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); + else + memcpy(wrqu->ap_addr.sa_data, + ieee->current_network.bssid, ETH_ALEN); + + spin_unlock_irqrestore(&ieee->lock, flags); + + return 0; +} + + +int rtllib_wx_set_wap(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *awrq, + char *extra) +{ + + int ret = 0; + u8 zero[] = {0,0,0,0,0,0}; + unsigned long flags; + + short ifup = ieee->proto_started; + struct sockaddr *temp = (struct sockaddr *)awrq; + + rtllib_stop_scan_syncro(ieee); + + down(&ieee->wx_sem); + /* use ifconfig hw ether */ + if (ieee->iw_mode == IW_MODE_MASTER){ + ret = -1; + goto out; + } + + if (temp->sa_family != ARPHRD_ETHER){ + ret = -EINVAL; + goto out; + } + + if (memcmp(temp->sa_data, zero,ETH_ALEN) == 0){ + spin_lock_irqsave(&ieee->lock, flags); + memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); + ieee->wap_set = 0; + spin_unlock_irqrestore(&ieee->lock, flags); + ret = -1; + goto out; + } + + + if (ifup) + rtllib_stop_protocol(ieee,true); + + /* just to avoid to give inconsistent infos in the + * get wx method. not really needed otherwise + */ + spin_lock_irqsave(&ieee->lock, flags); + + ieee->cannot_notify = false; + memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); + ieee->wap_set = (memcmp(temp->sa_data, zero,ETH_ALEN)!=0); + + spin_unlock_irqrestore(&ieee->lock, flags); + + if (ifup) + rtllib_start_protocol(ieee); +out: + up(&ieee->wx_sem); + return ret; +} + + int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b) +{ + int len,ret = 0; + unsigned long flags; + + if (ieee->iw_mode == IW_MODE_MONITOR) + return -1; + + /* We want avoid to give to the user inconsistent infos*/ + spin_lock_irqsave(&ieee->lock, flags); + + if (ieee->current_network.ssid[0] == '\0' || + ieee->current_network.ssid_len == 0){ + ret = -1; + goto out; + } + + if (ieee->state != RTLLIB_LINKED && + ieee->state != RTLLIB_LINKED_SCANNING && + ieee->ssid_set == 0){ + ret = -1; + goto out; + } + len = ieee->current_network.ssid_len; + wrqu->essid.length = len; + strncpy(b,ieee->current_network.ssid,len); + wrqu->essid.flags = 1; + +out: + spin_unlock_irqrestore(&ieee->lock, flags); + + return ret; + +} + +int rtllib_wx_set_rate(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + u32 target_rate = wrqu->bitrate.value; + + ieee->rate = target_rate/100000; + return 0; +} + +int rtllib_wx_get_rate(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + u32 tmp_rate = 0; +#if defined RTL8192SU + if (ieee->mode & (IEEE_A | IEEE_B | IEEE_G)) + tmp_rate = ieee->rate; + else if (ieee->mode & IEEE_N_5G) + tmp_rate = 580; + else if (ieee->mode & IEEE_N_24G) { + if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) + tmp_rate = HTHalfMcsToDataRate(ieee, 15); + else + tmp_rate = HTMcsToDataRate(ieee, 15); + } +#elif defined RTL8192SE || defined RTL8192CE + tmp_rate = ieee->rtl_11n_user_show_rates(ieee->dev); +#else + tmp_rate = TxCountToDataRate(ieee, ieee->softmac_stats.CurrentShowTxate); +#endif + wrqu->bitrate.value = tmp_rate * 500000; + + return 0; +} + + +int rtllib_wx_set_rts(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + if (wrqu->rts.disabled || !wrqu->rts.fixed) + ieee->rts = DEFAULT_RTS_THRESHOLD; + else + { + if (wrqu->rts.value < MIN_RTS_THRESHOLD || + wrqu->rts.value > MAX_RTS_THRESHOLD) + return -EINVAL; + ieee->rts = wrqu->rts.value; + } + return 0; +} + +int rtllib_wx_get_rts(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + wrqu->rts.value = ieee->rts; + wrqu->rts.fixed = 0; /* no auto select */ + wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); + return 0; +} + +int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + int set_mode_status = 0; + + rtllib_stop_scan_syncro(ieee); + down(&ieee->wx_sem); + switch (wrqu->mode) { + case IW_MODE_MONITOR: + case IW_MODE_ADHOC: + case IW_MODE_INFRA: +#ifdef _RTL8192_EXT_PATCH_ + case IW_MODE_MESH: +#endif + break; + case IW_MODE_AUTO: + wrqu->mode = IW_MODE_INFRA; + break; + default: + set_mode_status = -EINVAL; + goto out; + } + + if (wrqu->mode == ieee->iw_mode) + goto out; + + if (wrqu->mode == IW_MODE_MONITOR) { +#if defined(RTLLIB_RADIOTAP) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10)) + ieee->dev->type = ARPHRD_IEEE80211_RADIOTAP; +#else + ieee->dev->type = ARPHRD_IEEE80211; +#endif + rtllib_EnableNetMonitorMode(ieee->dev,false); + + } else { + ieee->dev->type = ARPHRD_ETHER; + if (ieee->iw_mode == IW_MODE_MONITOR) + rtllib_DisableNetMonitorMode(ieee->dev,false); + } + + if (!ieee->proto_started) { + ieee->iw_mode = wrqu->mode; + } else { + rtllib_stop_protocol(ieee,true); + ieee->iw_mode = wrqu->mode; +#if defined (RTL8192S_WAPI_SUPPORT) + if(ieee->iw_mode == IW_MODE_ADHOC) + ieee->wapiInfo.bWapiPSK = true; +#endif + rtllib_start_protocol(ieee); + } + +out: + up(&ieee->wx_sem); + return set_mode_status; +} + +void rtllib_wx_sync_scan_wq(void *data) +{ + struct rtllib_device *ieee = container_of_work_rsl(data, struct rtllib_device, wx_sync_scan_wq); + short chan; + HT_EXTCHNL_OFFSET chan_offset=0; + HT_CHANNEL_WIDTH bandwidth=0; + int b40M = 0; + static int count = 0; + + if (!(ieee->softmac_features & IEEE_SOFTMAC_SCAN)){ + rtllib_start_scan_syncro(ieee, 0); + goto out; + } + + chan = ieee->current_network.channel; + +#ifdef ENABLE_LPS + if (ieee->LeisurePSLeave) { + ieee->LeisurePSLeave(ieee->dev); + } + /* notify AP to be in PS mode */ + rtllib_sta_ps_send_null_frame(ieee, 1); + rtllib_sta_ps_send_null_frame(ieee, 1); +#endif + + rtllib_stop_all_queues(ieee); + + if (ieee->data_hard_stop) + ieee->data_hard_stop(ieee->dev); + rtllib_stop_send_beacons(ieee); + ieee->state = RTLLIB_LINKED_SCANNING; + ieee->link_change(ieee->dev); + /* wait for ps packet to be kicked out successfully */ + msleep(50); + + if(ieee->ScanOperationBackupHandler) + ieee->ScanOperationBackupHandler(ieee->dev,SCAN_OPT_BACKUP); + + if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) { + b40M = 1; + chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset; + bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz; + printk("Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth); + ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); + } + + rtllib_start_scan_syncro(ieee, 0); + + if (b40M) { + printk("Scan in 20M, back to 40M\n"); + if (chan_offset == HT_EXTCHNL_OFFSET_UPPER) + ieee->set_chan(ieee->dev, chan + 2); + else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER) + ieee->set_chan(ieee->dev, chan - 2); + else + ieee->set_chan(ieee->dev, chan); + ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset); + } else { + ieee->set_chan(ieee->dev, chan); + } + + if(ieee->ScanOperationBackupHandler) + ieee->ScanOperationBackupHandler(ieee->dev,SCAN_OPT_RESTORE); + + ieee->state = RTLLIB_LINKED; + ieee->link_change(ieee->dev); + +#ifdef ENABLE_LPS + /* Notify AP that I wake up again */ + rtllib_sta_ps_send_null_frame(ieee, 0); +#endif + + if (ieee->LinkDetectInfo.NumRecvBcnInPeriod == 0 || + ieee->LinkDetectInfo.NumRecvDataInPeriod == 0 ) { + ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1; + ieee->LinkDetectInfo.NumRecvDataInPeriod= 1; + } + + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + + if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) + rtllib_start_send_beacons(ieee); + + rtllib_wake_all_queues(ieee); + + count = 0; +out: + up(&ieee->wx_sem); + +} + +int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ + int ret = 0; + + down(&ieee->wx_sem); + + if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){ + ret = -1; + goto out; + } + + if ( ieee->state == RTLLIB_LINKED){ + queue_work_rsl(ieee->wq, &ieee->wx_sync_scan_wq); + /* intentionally forget to up sem */ + return 0; + } + +out: + up(&ieee->wx_sem); + return ret; +} + +int rtllib_wx_set_essid(struct rtllib_device *ieee, + struct iw_request_info *a, + union iwreq_data *wrqu, char *extra) +{ + + int ret=0,len,i; + short proto_started; + unsigned long flags; + + rtllib_stop_scan_syncro(ieee); + down(&ieee->wx_sem); + + proto_started = ieee->proto_started; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) + len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE; +#else + len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? wrqu->essid.length : IW_ESSID_MAX_SIZE; +#endif + + if (len > IW_ESSID_MAX_SIZE){ + ret= -E2BIG; + goto out; + } + + if (ieee->iw_mode == IW_MODE_MONITOR){ + ret= -1; + goto out; + } + + for (i=0; ilock, flags); + + if (wrqu->essid.flags && wrqu->essid.length) { + strncpy(ieee->current_network.ssid, extra, len); + ieee->current_network.ssid_len = len; +#if 0 + { + int i; + for (i=0; icannot_notify = false; + ieee->ssid_set = 1; + } + else{ + ieee->ssid_set = 0; + ieee->current_network.ssid[0] = '\0'; + ieee->current_network.ssid_len = 0; + } + spin_unlock_irqrestore(&ieee->lock, flags); + + if (proto_started) + rtllib_start_protocol(ieee); +out: + up(&ieee->wx_sem); + return ret; +} + + int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a, + union iwreq_data *wrqu, char *b) +{ +#ifdef _RTL8192_EXT_PATCH_ + if(ieee->iw_mode == IW_MODE_MESH) { + /* WEXT could not show mesh mode properly, + * just disable it */ + if(ieee->only_mesh) { + return -1; + } else { + wrqu->mode = IW_MODE_INFRA; + } + } + else +#endif + wrqu->mode = ieee->iw_mode; + return 0; +} + + int rtllib_wx_set_rawtx(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + int *parms = (int *)extra; + int enable = (parms[0] > 0); + short prev = ieee->raw_tx; + + down(&ieee->wx_sem); + + if(enable) + ieee->raw_tx = 1; + else + ieee->raw_tx = 0; + + printk(KERN_INFO"raw TX is %s\n", + ieee->raw_tx ? "enabled" : "disabled"); + + if(ieee->iw_mode == IW_MODE_MONITOR) + { + if(prev == 0 && ieee->raw_tx){ + if (ieee->data_hard_resume) + ieee->data_hard_resume(ieee->dev); + + netif_carrier_on(ieee->dev); + } + + if(prev && ieee->raw_tx == 1) + netif_carrier_off(ieee->dev); + } + + up(&ieee->wx_sem); + + return 0; +} + +int rtllib_wx_get_name(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + strcpy(wrqu->name, "802.11"); + + if (ieee->modulation & RTLLIB_CCK_MODULATION) + strcat(wrqu->name, "b"); + if (ieee->modulation & RTLLIB_OFDM_MODULATION) + strcat(wrqu->name, "g"); + if (ieee->mode & (IEEE_N_24G | IEEE_N_5G)) + strcat(wrqu->name, "n"); +#if 0 + if((ieee->state == RTLLIB_LINKED) || + (ieee->state == RTLLIB_LINKED_SCANNING)) + strcat(wrqu->name," linked"); + else if(ieee->state != RTLLIB_NOLINK) + strcat(wrqu->name," link.."); +#endif + return 0; +} + + +/* this is mostly stolen from hostap */ +int rtllib_wx_set_power(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret = 0; +#if 1 + if( + (!ieee->sta_wake_up) || + (!ieee->enter_sleep_state) || + (!ieee->ps_is_queue_empty)){ + + RTLLIB_DEBUG(RTLLIB_DL_ERR,"%s(): PS mode is tryied to be use but driver missed a callback\n\n",__FUNCTION__); + + return -1; + } +#endif + down(&ieee->wx_sem); + + if (wrqu->power.disabled){ + printk("===>%s(): power disable\n",__FUNCTION__); + ieee->ps = RTLLIB_PS_DISABLED; + goto exit; + } + if (wrqu->power.flags & IW_POWER_TIMEOUT) { + ieee->ps_timeout = wrqu->power.value / 1000; + printk("===>%s():ps_timeout is %d\n",__FUNCTION__,ieee->ps_timeout); + } + + if (wrqu->power.flags & IW_POWER_PERIOD) { + + ieee->ps_period = wrqu->power.value / 1000; + + } + switch (wrqu->power.flags & IW_POWER_MODE) { + case IW_POWER_UNICAST_R: + ieee->ps = RTLLIB_PS_UNICAST; + break; + case IW_POWER_MULTICAST_R: + ieee->ps = RTLLIB_PS_MBCAST; + break; + case IW_POWER_ALL_R: + ieee->ps = RTLLIB_PS_UNICAST | RTLLIB_PS_MBCAST; + break; + + case IW_POWER_ON: + break; + + default: + ret = -EINVAL; + goto exit; + + } +exit: + up(&ieee->wx_sem); + return ret; + +} + +/* this is stolen from hostap */ +int rtllib_wx_get_power(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret =0; + + down(&ieee->wx_sem); + + if(ieee->ps == RTLLIB_PS_DISABLED){ + wrqu->power.disabled = 1; + goto exit; + } + + wrqu->power.disabled = 0; + + if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { + wrqu->power.flags = IW_POWER_TIMEOUT; + wrqu->power.value = ieee->ps_timeout * 1000; + } else { + wrqu->power.flags = IW_POWER_PERIOD; + wrqu->power.value = ieee->ps_period * 1000; + } + + if ((ieee->ps & (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) == (RTLLIB_PS_MBCAST | RTLLIB_PS_UNICAST)) + wrqu->power.flags |= IW_POWER_ALL_R; + else if (ieee->ps & RTLLIB_PS_MBCAST) + wrqu->power.flags |= IW_POWER_MULTICAST_R; + else + wrqu->power.flags |= IW_POWER_UNICAST_R; + +exit: + up(&ieee->wx_sem); + return ret; + +} + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(rtllib_wx_get_essid); +EXPORT_SYMBOL_RSL(rtllib_wx_set_essid); +EXPORT_SYMBOL_RSL(rtllib_wx_set_rate); +EXPORT_SYMBOL_RSL(rtllib_wx_get_rate); +EXPORT_SYMBOL_RSL(rtllib_wx_set_wap); +EXPORT_SYMBOL_RSL(rtllib_wx_get_wap); +EXPORT_SYMBOL_RSL(rtllib_wx_set_mode); +EXPORT_SYMBOL_RSL(rtllib_wx_get_mode); +EXPORT_SYMBOL_RSL(rtllib_wx_set_scan); +EXPORT_SYMBOL_RSL(rtllib_wx_get_freq); +EXPORT_SYMBOL_RSL(rtllib_wx_set_freq); +EXPORT_SYMBOL_RSL(rtllib_wx_set_rawtx); +EXPORT_SYMBOL_RSL(rtllib_wx_get_name); +EXPORT_SYMBOL_RSL(rtllib_wx_set_power); +EXPORT_SYMBOL_RSL(rtllib_wx_get_power); +EXPORT_SYMBOL_RSL(rtllib_wlan_frequencies); +EXPORT_SYMBOL_RSL(rtllib_wx_set_rts); +EXPORT_SYMBOL_RSL(rtllib_wx_get_rts); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib_tx.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib_tx.c @@ -0,0 +1,1622 @@ +/****************************************************************************** + + Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + James P. Ketrenos + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +****************************************************************************** + + Few modifications for Realtek's Wi-Fi drivers by + Andrea Merello + + A special thanks goes to Realtek for their support ! + +******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rtllib.h" + +#ifdef RTK_DMP_PLATFORM +#include +#endif + +/* + + +802.11 Data Frame + + +802.11 frame_contorl for data frames - 2 bytes + ,-----------------------------------------------------------------------------------------. +bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | + |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| +val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x | + |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| +desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep | + | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | | + '-----------------------------------------------------------------------------------------' + /\ + | +802.11 Data Frame | + ,--------- 'ctrl' expands to >-----------' + | + ,--'---,-------------------------------------------------------------. +Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | + |------|------|---------|---------|---------|------|---------|------| +Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | + | | tion | (BSSID) | | | ence | data | | + `--------------------------------------------------| |------' +Total: 28 non-data bytes `----.----' + | + .- 'Frame data' expands to <---------------------------' + | + V + ,---------------------------------------------------. +Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | + |------|------|---------|----------|------|---------| +Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | + | DSAP | SSAP | | | | Packet | + | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | + `-----------------------------------------| | +Total: 8 non-data bytes `----.----' + | + .- 'IP Packet' expands, if WEP enabled, to <--' + | + V + ,-----------------------. +Bytes | 4 | 0-2296 | 4 | + |-----|-----------|-----| +Desc. | IV | Encrypted | ICV | + | | IP Packet | | + `-----------------------' +Total: 8 non-data bytes + + +802.3 Ethernet Data Frame + + ,-----------------------------------------. +Bytes | 6 | 6 | 2 | Variable | 4 | + |-------|-------|------|-----------|------| +Desc. | Dest. | Source| Type | IP Packet | fcs | + | MAC | MAC | | | | + `-----------------------------------------' +Total: 18 non-data bytes + +In the event that fragmentation is required, the incoming payload is split into +N parts of size ieee->fts. The first fragment contains the SNAP header and the +remaining packets are just data. + +If encryption is enabled, each fragment payload size is reduced by enough space +to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP) +So if you have 1500 bytes of payload with ieee->fts set to 500 without +encryption it will take 3 frames. With WEP it will take 4 frames as the +payload of each frame is reduced to 492 bytes. + +* SKB visualization +* +* ,- skb->data +* | +* | ETHERNET HEADER ,-<-- PAYLOAD +* | | 14 bytes from skb->data +* | 2 bytes for Type --> ,T. | (sizeof ethhdr) +* | | | | +* |,-Dest.--. ,--Src.---. | | | +* | 6 bytes| | 6 bytes | | | | +* v | | | | | | +* 0 | v 1 | v | v 2 +* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 +* ^ | ^ | ^ | +* | | | | | | +* | | | | `T' <---- 2 bytes for Type +* | | | | +* | | '---SNAP--' <-------- 6 bytes for SNAP +* | | +* `-IV--' <-------------------- 4 bytes for IV (WEP) +* +* SNAP HEADER +* +*/ + +static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; +static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; + +inline int rtllib_put_snap(u8 *data, u16 h_proto) +{ + struct rtllib_snap_hdr *snap; + u8 *oui; + + snap = (struct rtllib_snap_hdr *)data; + snap->dsap = 0xaa; + snap->ssap = 0xaa; + snap->ctrl = 0x03; + + if (h_proto == 0x8137 || h_proto == 0x80f3) + oui = P802_1H_OUI; + else + oui = RFC1042_OUI; + snap->oui[0] = oui[0]; + snap->oui[1] = oui[1]; + snap->oui[2] = oui[2]; + + *(u16 *)(data + SNAP_SIZE) = htons(h_proto); + + return SNAP_SIZE + sizeof(u16); +} + +#ifdef _RTL8192_EXT_PATCH_ +int rtllib_encrypt_fragment( + struct rtllib_device *ieee, + struct sk_buff *frag, + int hdr_len, + u8 is_mesh, + u8 entry) +#else +int rtllib_encrypt_fragment( + struct rtllib_device *ieee, + struct sk_buff *frag, + int hdr_len) +#endif +{ + struct rtllib_crypt_data* crypt = NULL; + int res; + +#ifdef _RTL8192_EXT_PATCH_ + if (is_mesh) { + crypt = ieee->cryptlist[entry]->crypt[ieee->mesh_txkeyidx]; + } else + crypt = ieee->sta_crypt[ieee->tx_keyidx]; +#else + crypt = ieee->crypt[ieee->tx_keyidx]; +#endif + + if (!(crypt && crypt->ops)) + { + printk("=========>%s(), crypt is null\n", __FUNCTION__); + return -1; + } +#ifdef CONFIG_RTLLIB_CRYPT_TKIP + struct rtllib_hdr_1addr *header; + + if (ieee->tkip_countermeasures && + crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) { + header = (struct rtllib_hdr_1addr *) frag->data; + if (net_ratelimit()) { + printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " + "TX packet to " MAC_FMT "\n", + ieee->dev->name, MAC_ARG(header->addr1)); + } + return -1; + } +#endif + /* To encrypt, frame format is: + * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ + + /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so + * call both MSDU and MPDU encryption functions from here. */ + atomic_inc(&crypt->refcnt); + res = 0; + if (crypt->ops->encrypt_msdu) + res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv); + if (res == 0 && crypt->ops->encrypt_mpdu) + res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); + + atomic_dec(&crypt->refcnt); + if (res < 0) { + printk(KERN_INFO "%s: Encryption failed: len=%d.\n", + ieee->dev->name, frag->len); + ieee->ieee_stats.tx_discards++; + return -1; + } + + return 0; +} + + +void rtllib_txb_free(struct rtllib_txb *txb) { + if (unlikely(!txb)) + return; +#if 0 + for (i = 0; i < txb->nr_frags; i++) + if (txb->fragments[i]) + dev_kfree_skb_any(txb->fragments[i]); +#endif + kfree(txb); +} + +struct rtllib_txb *rtllib_alloc_txb(int nr_frags, int txb_size, + int gfp_mask) +{ +#ifdef USB_USE_ALIGNMENT + u32 Tmpaddr=0; + int alignment=0; +#endif + struct rtllib_txb *txb; + int i; + txb = kmalloc( + sizeof(struct rtllib_txb) + (sizeof(u8*) * nr_frags), + gfp_mask); + if (!txb) + return NULL; + + memset(txb, 0, sizeof(struct rtllib_txb)); + txb->nr_frags = nr_frags; + txb->frag_size = txb_size; + + for (i = 0; i < nr_frags; i++) { +#ifdef USB_USE_ALIGNMENT + txb->fragments[i] = dev_alloc_skb(txb_size+USB_512B_ALIGNMENT_SIZE); +#else + txb->fragments[i] = dev_alloc_skb(txb_size); +#endif + if (unlikely(!txb->fragments[i])) { + i--; + break; + } +#ifdef USB_USE_ALIGNMENT + Tmpaddr = (u32)(txb->fragments[i]->data); + alignment = Tmpaddr & 0x1ff; + skb_reserve(txb->fragments[i],(USB_512B_ALIGNMENT_SIZE - alignment)); +#endif + memset(txb->fragments[i]->cb, 0, sizeof(txb->fragments[i]->cb)); + } + if (unlikely(i != nr_frags)) { + while (i >= 0) + dev_kfree_skb_any(txb->fragments[i--]); + kfree(txb); + return NULL; + } + return txb; +} + +int +rtllib_classify(struct sk_buff *skb, u8 bIsAmsdu) +{ + struct ethhdr *eth; + struct iphdr *ip; + + eth = (struct ethhdr *)skb->data; + if (eth->h_proto != htons(ETH_P_IP)) + return 0; + +#ifdef ENABLE_AMSDU + if(bIsAmsdu) + ip = (struct iphdr*)(skb->data + sizeof(struct ether_header) + AMSDU_SUBHEADER_LEN + SNAP_SIZE + sizeof(u16)); + else + ip = (struct iphdr*)(skb->data + sizeof(struct ether_header)); +#else + RTLLIB_DEBUG_DATA(RTLLIB_DL_DATA, skb->data, skb->len); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)) + ip = ip_hdr(skb); +#else + ip = (struct iphdr*)(skb->data + sizeof(struct ether_header)); +#endif +#endif + switch (ip->tos & 0xfc) { + case 0x20: + return 2; + case 0x40: + return 1; + case 0x60: + return 3; + case 0x80: + return 4; + case 0xa0: + return 5; + case 0xc0: + return 6; + case 0xe0: + return 7; + default: + return 0; + } +} + +#define SN_LESS(a, b) (((a-b)&0x800)!=0) +void rtllib_tx_query_agg_cap(struct rtllib_device* ieee, struct sk_buff* skb, cb_desc* tcb_desc) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + PTX_TS_RECORD pTxTs = NULL; + struct rtllib_hdr_1addr* hdr = (struct rtllib_hdr_1addr*)skb->data; + + if(rtllib_act_scanning(ieee,false)) + return; + + if (!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT){ + return; + } + if (!IsQoSDataFrame(skb->data)){ + return; + } + if (is_multicast_ether_addr(hdr->addr1) || is_broadcast_ether_addr(hdr->addr1)){ + return; + } +#ifdef TO_DO_LIST + if(pTcb->PacketLength >= 4096) + return; + if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter)) + return; +#endif + + if(tcb_desc->bdhcp || ieee->CntAfterLink<2){ + return; + } + + if(pHTInfo->IOTAction & HT_IOT_ACT_TX_NO_AGGREGATION){ + return; + } + + if(!ieee->GetNmodeSupportBySecCfg(ieee->dev)){ + return; + } + if(pHTInfo->bCurrentAMPDUEnable){ + if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTxTs), hdr->addr1, skb->priority, TX_DIR, true)){ + printk("%s: can't get TS\n", __func__); + return; + } + if (pTxTs->TxAdmittedBARecord.bValid == false){ + if (ieee->wpa_ie_len && (ieee->pairwise_key_type == KEY_TYPE_NA)) { + ; + } else if (tcb_desc->bdhcp == 1){ + ; + } else if (!pTxTs->bDisable_AddBa){ + TsStartAddBaProcess(ieee, pTxTs); + } + goto FORCED_AGG_SETTING; + } + else if (pTxTs->bUsingBa == false) + { + if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096)) + pTxTs->bUsingBa = true; + else + goto FORCED_AGG_SETTING; + } +#ifndef _RTL8192_EXT_PATCH_ +#ifndef RTL8192S_WAPI_SUPPORT + if (ieee->iw_mode == IW_MODE_INFRA) +#endif +#endif + { + tcb_desc->bAMPDUEnable = true; + tcb_desc->ampdu_factor = pHTInfo->CurrentAMPDUFactor; + tcb_desc->ampdu_density = pHTInfo->CurrentMPDUDensity; + } + } +FORCED_AGG_SETTING: + switch(pHTInfo->ForcedAMPDUMode ) + { + case HT_AGG_AUTO: + break; + + case HT_AGG_FORCE_ENABLE: + tcb_desc->bAMPDUEnable = true; + tcb_desc->ampdu_density = pHTInfo->ForcedMPDUDensity; + tcb_desc->ampdu_factor = pHTInfo->ForcedAMPDUFactor; + break; + + case HT_AGG_FORCE_DISABLE: + tcb_desc->bAMPDUEnable = false; + tcb_desc->ampdu_density = 0; + tcb_desc->ampdu_factor = 0; + break; + + } + return; +} + +extern void rtllib_qurey_ShortPreambleMode(struct rtllib_device* ieee, cb_desc* tcb_desc) +{ + tcb_desc->bUseShortPreamble = false; + if (tcb_desc->data_rate == 2) + { + return; + } + else if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + { + tcb_desc->bUseShortPreamble = true; + } + return; +} + +extern void +rtllib_query_HTCapShortGI(struct rtllib_device *ieee, cb_desc *tcb_desc) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + tcb_desc->bUseShortGI = false; + + if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + return; + + if(pHTInfo->bForcedShortGI) + { + tcb_desc->bUseShortGI = true; + return; + } + + if((pHTInfo->bCurBW40MHz==true) && pHTInfo->bCurShortGI40MHz) + tcb_desc->bUseShortGI = true; + else if((pHTInfo->bCurBW40MHz==false) && pHTInfo->bCurShortGI20MHz) + tcb_desc->bUseShortGI = true; +} + +void rtllib_query_BandwidthMode(struct rtllib_device* ieee, cb_desc *tcb_desc) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + tcb_desc->bPacketBW = false; + + if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT) + return; + + if(tcb_desc->bMulticast || tcb_desc->bBroadcast) + return; + + if((tcb_desc->data_rate & 0x80)==0) + return; + if(pHTInfo->bCurBW40MHz && pHTInfo->bCurTxBW40MHz && !ieee->bandwidth_auto_switch.bforced_tx20Mhz) + tcb_desc->bPacketBW = true; + return; +} +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) || defined(RTL8192CE) +extern void rtllib_ibss_query_HTCapShortGI(struct rtllib_device *ieee, cb_desc *tcb_desc,u8 is_peer_shortGI_40M,u8 is_peer_shortGI_20M) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + tcb_desc->bUseShortGI = false; + + if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT || (ieee->iw_mode != IW_MODE_ADHOC)) + { + return; + } + + if(pHTInfo->bForcedShortGI) + { + tcb_desc->bUseShortGI = true; + return; + } + if((pHTInfo->bCurBW40MHz==true) && is_peer_shortGI_40M) + tcb_desc->bUseShortGI = true; + else if((pHTInfo->bCurBW40MHz==false) && is_peer_shortGI_20M) + tcb_desc->bUseShortGI = true; +} +void rtllib_ibss_query_BandwidthMode(struct rtllib_device* ieee, cb_desc *tcb_desc, u8 is_peer_40M) +{ + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + + tcb_desc->bPacketBW = false; + + if(!pHTInfo->bCurrentHTSupport||!pHTInfo->bEnableHT || (ieee->iw_mode != IW_MODE_ADHOC)) + { + return; + } + + if(tcb_desc->bMulticast || tcb_desc->bBroadcast) + { + return; + } + + if((tcb_desc->data_rate & 0x80)==0) + { + return; + } + if(pHTInfo->bCurBW40MHz && is_peer_40M && !ieee->bandwidth_auto_switch.bforced_tx20Mhz) + tcb_desc->bPacketBW = true; + return; +} +#endif +void rtllib_query_protectionmode(struct rtllib_device* ieee, cb_desc* tcb_desc, struct sk_buff* skb) +{ + tcb_desc->bRTSSTBC = false; + tcb_desc->bRTSUseShortGI = false; + tcb_desc->bCTSEnable = false; + tcb_desc->RTSSC = 0; + tcb_desc->bRTSBW = false; + + if(tcb_desc->bBroadcast || tcb_desc->bMulticast) + return; + + if (is_broadcast_ether_addr(skb->data+16)) + return; + + if (ieee->mode < IEEE_N_24G) + { + if (skb->len > ieee->rts) + { + tcb_desc->bRTSEnable = true; + tcb_desc->rts_rate = MGN_24M; + } + else if (ieee->current_network.buseprotection) + { + tcb_desc->bRTSEnable = true; + tcb_desc->bCTSEnable = true; + tcb_desc->rts_rate = MGN_24M; + } + return; + } + else + { + PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; + while (true) + { + if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) + { + tcb_desc->bCTSEnable = true; + tcb_desc->rts_rate = MGN_24M; +#if defined(RTL8192SE) || defined(RTL8192SU) || defined RTL8192CE + tcb_desc->bRTSEnable = false; +#else + tcb_desc->bRTSEnable = true; +#endif + break; + } + else if(pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS|HT_IOT_ACT_PURE_N_MODE)) + { + tcb_desc->bRTSEnable = true; + tcb_desc->rts_rate = MGN_24M; + break; + } + if (ieee->current_network.buseprotection) + { + tcb_desc->bRTSEnable = true; + tcb_desc->bCTSEnable = true; + tcb_desc->rts_rate = MGN_24M; + break; + } + if(pHTInfo->bCurrentHTSupport && pHTInfo->bEnableHT) + { + u8 HTOpMode = pHTInfo->CurrentOpMode; + if((pHTInfo->bCurBW40MHz && (HTOpMode == 2 || HTOpMode == 3)) || + (!pHTInfo->bCurBW40MHz && HTOpMode == 3) ) + { + tcb_desc->rts_rate = MGN_24M; + tcb_desc->bRTSEnable = true; + break; + } + } + if (skb->len > ieee->rts) + { + tcb_desc->rts_rate = MGN_24M; + tcb_desc->bRTSEnable = true; + break; + } + if(tcb_desc->bAMPDUEnable) + { + tcb_desc->rts_rate = MGN_24M; + tcb_desc->bRTSEnable = false; + break; + } + goto NO_PROTECTION; + } + } + if( 0 ) + { + tcb_desc->bCTSEnable = true; + tcb_desc->rts_rate = MGN_24M; + tcb_desc->bRTSEnable = true; + } + if (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + tcb_desc->bUseShortPreamble = true; + if (ieee->iw_mode == IW_MODE_MASTER) + goto NO_PROTECTION; + return; +NO_PROTECTION: + tcb_desc->bRTSEnable = false; + tcb_desc->bCTSEnable = false; + tcb_desc->rts_rate = 0; + tcb_desc->RTSSC = 0; + tcb_desc->bRTSBW = false; +} + + +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE +void rtllib_txrate_selectmode(struct rtllib_device* ieee, cb_desc* tcb_desc,struct sta_info *psta) +#else +void rtllib_txrate_selectmode(struct rtllib_device* ieee, cb_desc* tcb_desc) +#endif +{ + if(ieee->bTxDisableRateFallBack) + tcb_desc->bTxDisableRateFallBack = true; + + if(ieee->bTxUseDriverAssingedRate) + tcb_desc->bTxUseDriverAssingedRate = true; + +#if (defined _RTL8192_EXT_PATCH_ || defined RTL8192CE) + if(!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate) + { + if ((ieee->iw_mode == IW_MODE_INFRA) || (ieee->iw_mode == IW_MODE_MESH)) + tcb_desc->RATRIndex = 0; + else if (ieee->iw_mode == IW_MODE_ADHOC){ + if(tcb_desc->bMulticast || tcb_desc->bBroadcast){ + tcb_desc->data_rate = ieee->basic_rate; + tcb_desc->bTxUseDriverAssingedRate = 1; + }else{ + if(psta != NULL) + tcb_desc->RATRIndex = psta->ratr_index; + else + tcb_desc->RATRIndex = 7; + } + } + } + +#ifdef RTL8192CE + if(ieee->bUseRAMask && ieee->mode != WIRELESS_MODE_B) +#else + if(ieee->bUseRAMask) +#endif + { + if((ieee->iw_mode == IW_MODE_ADHOC) && (NULL != psta)){ + short peer_AID = psta->aid; + + tcb_desc->macId =0; + if((peer_AID > 0) && (peer_AID < PEER_MAX_ASSOC)) + { + tcb_desc->macId = peer_AID + 1; + }else{ + tcb_desc->macId = 1; + } + } + else{ + if((ieee->mode & WIRELESS_MODE_N_24G) || (ieee->mode & WIRELESS_MODE_N_5G)) + tcb_desc->RATRIndex = RATR_INX_WIRELESS_NGB; + else if(ieee->mode & WIRELESS_MODE_G) + tcb_desc->RATRIndex = RATR_INX_WIRELESS_GB; + else if(ieee->mode & WIRELESS_MODE_B) + tcb_desc->RATRIndex = RATR_INX_WIRELESS_B; + + tcb_desc->macId = 0; + } + } +#else + if(!tcb_desc->bTxDisableRateFallBack || !tcb_desc->bTxUseDriverAssingedRate) + { + if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) + tcb_desc->RATRIndex = 0; + } +#endif +} + +u16 rtllib_query_seqnum(struct rtllib_device*ieee, struct sk_buff* skb, u8* dst) +{ + u16 seqnum = 0; + + if (is_multicast_ether_addr(dst) || is_broadcast_ether_addr(dst)) + return 0; + if (IsQoSDataFrame(skb->data)) + { + PTX_TS_RECORD pTS = NULL; + if (!GetTs(ieee, (PTS_COMMON_INFO*)(&pTS), dst, skb->priority, TX_DIR, true)) + { + return 0; + } + seqnum = pTS->TxCurSeq; + pTS->TxCurSeq = (pTS->TxCurSeq+1)%4096; + return seqnum; + } + return 0; +} + + + +#ifdef ENABLE_AMSDU +#if 0 +static void CB_DESC_DUMP(pcb_desc tcb, char* func) +{ + printk("\n%s",func); + printk("\n-------------------CB DESC DUMP ><------------------------"); + printk("\npkt_size:\t %d", tcb->pkt_size); + printk("\nqueue_index:\t %d", tcb->queue_index); + printk("\nbMulticast:\t %d", tcb->bMulticast); + printk("\nbBroadcast:\t %d", tcb->bBroadcast); + printk("\nbPacketBw:\t %d", tcb->bPacketBW); + printk("\nbRTSEnable:\t %d", tcb->bRTSEnable); + printk("\nrts_rate:\t %d", tcb->rts_rate); + printk("\nbUseShortGI:\t %d", tcb->bUseShortGI); + printk("\nbAMSDU:\t %d", tcb->bAMSDU); + printk("\nFromAggrQ:\t %d", tcb->bFromAggrQ); + printk("\nRATRIndex:\t %d", tcb->RATRIndex); + printk("\ndata_rate:\t %d", tcb->data_rate); + printk("\n-------------------CB DESC DUMP <>------------------------\n"); +} +#endif +struct sk_buff *AMSDU_Aggregation( + struct rtllib_device *ieee, + struct sk_buff_head *pSendList + ) +{ + struct sk_buff * pSkb; + struct sk_buff * pAggrSkb; + u8 i; + u32 total_length = 0; + u32 skb_len, num_skb; + pcb_desc pcb; + u8 amsdu_shdr[AMSDU_SUBHEADER_LEN]; + u8 padding = 0; + u8 *p = NULL, *q=NULL; + u16 ether_type; + + num_skb = skb_queue_len(pSendList); + if(num_skb == 0) + return NULL; + if(num_skb == 1) + { + pSkb = (struct sk_buff *)skb_dequeue(pSendList); + memset(pSkb->cb, 0, sizeof(pSkb->cb)); + pcb = (pcb_desc)(pSkb->cb + MAX_DEV_ADDR_SIZE); + pcb->bFromAggrQ = true; + return pSkb; + } + + total_length += sizeof(struct ethhdr); + for(i=0; ilen <= (ETH_ALEN*2)) + { + dev_kfree_skb_any(pSkb); + continue; + } + skb_len = pSkb->len - ETH_ALEN*2 + SNAP_SIZE + AMSDU_SUBHEADER_LEN; + if(i < (num_skb-1)) + { + skb_len += ((4-skb_len%4)==4)?0:(4-skb_len%4); + } + total_length += skb_len; + skb_queue_tail(pSendList, pSkb); + } + + pAggrSkb = dev_alloc_skb(total_length); + if(NULL == pAggrSkb) + { + skb_queue_purge(pSendList); + printk("%s: Can not alloc skb!\n", __FUNCTION__); + return NULL; + } + skb_put(pAggrSkb,total_length); + pAggrSkb->priority = pSkb->priority; + + memset(pAggrSkb->cb, 0, sizeof(pAggrSkb->cb)); + pcb = (pcb_desc)(pAggrSkb->cb + MAX_DEV_ADDR_SIZE); + pcb->bFromAggrQ = true; + pcb->bAMSDU = true; + + memset(amsdu_shdr, 0, AMSDU_SUBHEADER_LEN); + p = pAggrSkb->data; + for(i=0; idata)->h_proto); + + skb_len = pSkb->len - sizeof(struct ethhdr) + AMSDU_SUBHEADER_LEN + SNAP_SIZE + sizeof(u16); + if(i < (num_skb-1)) + { + padding = ((4-skb_len%4)==4)?0:(4-skb_len%4); + skb_len += padding; + } + if(i == 0) + { + memcpy(p, pSkb->data, sizeof(struct ethhdr)); + p += sizeof(struct ethhdr); + } + memcpy(amsdu_shdr, pSkb->data, (ETH_ALEN*2)); + skb_pull(pSkb, sizeof(struct ethhdr)); + *(u16*)(amsdu_shdr+ETH_ALEN*2) = ntohs(pSkb->len + SNAP_SIZE + sizeof(u16)); + memcpy(p, amsdu_shdr, AMSDU_SUBHEADER_LEN); + p += AMSDU_SUBHEADER_LEN; + + rtllib_put_snap(p, ether_type); + p += SNAP_SIZE + sizeof(u16); + + memcpy(p, pSkb->data, pSkb->len); + p += pSkb->len; + if(padding > 0) + { + memset(p, 0, padding); + p += padding; + padding = 0; + } + dev_kfree_skb_any(pSkb); + } + + return pAggrSkb; +} + + +/* NOTE: + This function return a list of SKB which is proper to be aggregated. + If no proper SKB is found to do aggregation, SendList will only contain the input SKB. +*/ +u8 AMSDU_GetAggregatibleList( + struct rtllib_device * ieee, + struct sk_buff * pCurSkb, + struct sk_buff_head *pSendList, + u8 queue_index + ) +{ + struct sk_buff *pSkb = NULL; + u16 nMaxAMSDUSize = 0; + u32 AggrSize = 0; + u32 nAggrSkbNum = 0; + u8 padding = 0; + struct sta_info *psta = NULL; + u8 *addr = (u8*)(pCurSkb->data); + struct sk_buff_head *header; + struct sk_buff *punlinkskb = NULL; + + padding = ((4-pCurSkb->len%4)==4)?0:(4-pCurSkb->len%4); + AggrSize = AMSDU_SUBHEADER_LEN + pCurSkb->len + padding; + skb_queue_tail(pSendList, pCurSkb); + nAggrSkbNum++; + + if(ieee->iw_mode == IW_MODE_MASTER){ + psta = GetStaInfo(ieee, addr); + if(NULL != psta) + nMaxAMSDUSize = psta->htinfo.AMSDU_MaxSize; + else + return 1; + }else if(ieee->iw_mode == IW_MODE_ADHOC){ + psta = GetStaInfo(ieee, addr); + if(NULL != psta) + nMaxAMSDUSize = psta->htinfo.AMSDU_MaxSize; + else + return 1; + }else{ + nMaxAMSDUSize = ieee->pHTInfo->nCurrent_AMSDU_MaxSize; + } + + if(ieee->pHTInfo->ForcedAMSDUMode == HT_AGG_FORCE_ENABLE) + { + nMaxAMSDUSize = ieee->pHTInfo->ForcedAMSDUMaxSize; + } + + header = (&ieee->skb_aggQ[queue_index]); + pSkb = header->next; + while(pSkb != (struct sk_buff*)header) + { + if((ieee->iw_mode == IW_MODE_MASTER) ||(ieee->iw_mode == IW_MODE_ADHOC)) + { + if(memcmp(pCurSkb->data, pSkb->data, ETH_ALEN) != 0) + { + pSkb = pSkb->next; + continue; + } + } + if((AMSDU_SUBHEADER_LEN + pSkb->len + AggrSize < nMaxAMSDUSize) ) + { + punlinkskb = pSkb; + pSkb = pSkb->next; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) + skb_unlink(punlinkskb, header); +#else + /* + * __skb_unlink before linux2.6.14 does not use spinlock to protect list head. + * add spinlock function manually. john,2008/12/03 + */ + { + unsigned long flags; + spin_lock_irqsave(&ieee->lock, flags); + __skb_unlink(punlinkskb,header); + spin_unlock_irqrestore(&ieee->lock, flags); + } +#endif + + padding = ((4-punlinkskb->len%4)==4)?0:(4-punlinkskb->len%4); + AggrSize += AMSDU_SUBHEADER_LEN + punlinkskb->len + padding; + skb_queue_tail(pSendList, punlinkskb); + nAggrSkbNum++; + } + else + { + if(!(AMSDU_SUBHEADER_LEN + pSkb->len + AggrSize < nMaxAMSDUSize)) + ; + + break; + } + } + return nAggrSkbNum; +} +#endif +static int wme_downgrade_ac(struct sk_buff *skb) +{ + switch (skb->priority) { + case 6: + case 7: + skb->priority = 5; /* VO -> VI */ + return 0; + case 4: + case 5: + skb->priority = 3; /* VI -> BE */ + return 0; + case 0: + case 3: + skb->priority = 1; /* BE -> BK */ + return 0; + default: + return -1; + } +} + +int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev) +{ + struct rtllib_device *ieee = (struct rtllib_device *)netdev_priv_rsl(dev); + struct rtllib_txb *txb = NULL; + struct rtllib_hdr_3addrqos *frag_hdr; + int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; + unsigned long flags; + struct net_device_stats *stats = &ieee->stats; + int ether_type = 0, encrypt; + int bytes, fc, qos_ctl = 0, hdr_len; + struct sk_buff *skb_frag; + struct rtllib_hdr_3addrqos header = { /* Ensure zero initialized */ + .duration_id = 0, + .seq_ctl = 0, + .qos_ctl = 0 + }; + u8 dest[ETH_ALEN], src[ETH_ALEN]; + int qos_actived = ieee->current_network.qos_data.active; + struct rtllib_crypt_data* crypt = NULL; + cb_desc *tcb_desc; + u8 bIsMulticast = false; +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE + struct sta_info *p_sta = NULL; +#endif + u8 IsAmsdu = false; +#ifdef ENABLE_AMSDU + u8 queue_index = WME_AC_BE; + cb_desc *tcb_desc_skb; + u8 bIsSptAmsdu = false; +#endif + + bool bdhcp =false; +#ifndef _RTL8192_EXT_PATCH_ +#endif +#ifdef RTL8192S_WAPI_SUPPORT + static u8 zero14[14] = {0}; +#endif + spin_lock_irqsave(&ieee->lock, flags); + + /* If there is no driver handler to take the TXB, dont' bother + * creating it... */ + if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))|| + ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { + printk(KERN_WARNING "%s: No xmit handler.\n", + ieee->dev->name); + goto success; + } + + + if(likely(ieee->raw_tx == 0)){ + if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { + printk(KERN_WARNING "%s: skb too small (%d).\n", + ieee->dev->name, skb->len); + goto success; + } +#ifdef RTL8192S_WAPI_SUPPORT + if(memcmp(skb->data, zero14, sizeof(zero14))==0){ + if(WapiSendWaiPacket(ieee, skb)< 0) + goto failed; + else{ + spin_unlock_irqrestore(&ieee->lock, flags); + return 0; + } + } +#endif + /* Save source and destination addresses */ + memcpy(dest, skb->data, ETH_ALEN); + memcpy(src, skb->data+ETH_ALEN, ETH_ALEN); + +#ifdef ENABLE_AMSDU + if(ieee->iw_mode == IW_MODE_ADHOC) + { + p_sta = GetStaInfo(ieee, dest); + if(p_sta) { + if(p_sta->htinfo.bEnableHT) + bIsSptAmsdu = true; + } + }else if(ieee->iw_mode == IW_MODE_INFRA) { + bIsSptAmsdu = true; + }else + bIsSptAmsdu = true; + bIsSptAmsdu = (bIsSptAmsdu && ieee->pHTInfo->bCurrent_AMSDU_Support && qos_actived); + + tcb_desc_skb = (pcb_desc)(skb->cb + MAX_DEV_ADDR_SIZE); + if(bIsSptAmsdu) { + if(!tcb_desc_skb->bFromAggrQ) + { + if(qos_actived) + { + queue_index = UP2AC(skb->priority); + } else { + queue_index = WME_AC_BE; + } + + if ((skb_queue_len(&ieee->skb_aggQ[queue_index]) != 0)|| +#if defined RTL8192SE || defined RTL8192CE + (ieee->get_nic_desc_num(ieee->dev,queue_index)) > 1|| +#else + (!ieee->check_nic_enough_desc(ieee->dev,queue_index))|| +#endif + (ieee->queue_stop) || + (ieee->amsdu_in_process)) + { + /* insert the skb packet to the Aggregation queue */ + skb_queue_tail(&ieee->skb_aggQ[queue_index], skb); + spin_unlock_irqrestore(&ieee->lock, flags); + return 0; + } + } + else + { + if(tcb_desc_skb->bAMSDU) + IsAmsdu = true; + + ieee->amsdu_in_process = false; + } + } +#endif + memset(skb->cb, 0, sizeof(skb->cb)); + ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); + + if(ieee->iw_mode == IW_MODE_MONITOR) + { + txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC); + if (unlikely(!txb)) { + printk(KERN_WARNING "%s: Could not allocate TXB\n", + ieee->dev->name); + goto failed; + } + + txb->encrypted = 0; + txb->payload_size = skb->len; + memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); + + goto success; + } + + if (skb->len > 282){ + if (ETH_P_IP == ether_type) { + const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14); + if (IPPROTO_UDP == ip->protocol) { + struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2)); + if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) || + ((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) { + printk("DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]); + + bdhcp = true; +#ifdef _RTL8192_EXT_PATCH_ + ieee->LPSDelayCnt = 200; +#else + ieee->LPSDelayCnt = 200; +#endif + } + } + }else if(ETH_P_ARP == ether_type){ + printk("=================>DHCP Protocol start tx ARP pkt!!\n"); + bdhcp = true; + ieee->LPSDelayCnt = ieee->current_network.tim.tim_count; + + + } + } + + skb->priority = rtllib_classify(skb, IsAmsdu); +#ifdef RTL8192S_WAPI_SUPPORT + if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable){ + crypt = NULL; + encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && + ieee->host_encrypt && ieee->WapiSupport && ieee->wapiInfo.bWapiEnable; + } + else{ +#endif +#ifdef _RTL8192_EXT_PATCH_ + crypt = ieee->sta_crypt[ieee->tx_keyidx]; +#else + crypt = ieee->crypt[ieee->tx_keyidx]; +#endif + encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && + ieee->host_encrypt && crypt && crypt->ops; +#ifdef RTL8192S_WAPI_SUPPORT + } +#endif + if (!encrypt && ieee->ieee802_1x && + ieee->drop_unencrypted && ether_type != ETH_P_PAE) { + stats->tx_dropped++; + goto success; + } + #ifdef CONFIG_RTLLIB_DEBUG + if (crypt && !encrypt && ether_type == ETH_P_PAE) { + struct eapol *eap = (struct eapol *)(skb->data + + sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); + RTLLIB_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", + eap_get_type(eap->type)); + } + #endif + + /* Advance the SKB to the start of the payload */ + skb_pull(skb, sizeof(struct ethhdr)); + + /* Determine total amount of storage required for TXB packets */ +#ifdef ENABLE_AMSDU + if(!IsAmsdu) + bytes = skb->len + SNAP_SIZE + sizeof(u16); + else + bytes = skb->len; +#else + bytes = skb->len + SNAP_SIZE + sizeof(u16); +#endif + + if (encrypt) + fc = RTLLIB_FTYPE_DATA | RTLLIB_FCTL_WEP; + else + fc = RTLLIB_FTYPE_DATA; + + if(qos_actived) + fc |= RTLLIB_STYPE_QOS_DATA; + else + fc |= RTLLIB_STYPE_DATA; + +#ifdef _RTL8192_EXT_PATCH_ + if ((ieee->iw_mode == IW_MODE_INFRA) + || (ieee->iw_mode == IW_MODE_MESH) ) +#else + if (ieee->iw_mode == IW_MODE_INFRA) +#endif + { + fc |= RTLLIB_FCTL_TODS; + /* To DS: Addr1 = BSSID, Addr2 = SA, + Addr3 = DA */ + memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); + memcpy(&header.addr2, &src, ETH_ALEN); + if(IsAmsdu) + memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); + else + memcpy(&header.addr3, &dest, ETH_ALEN); + } else if (ieee->iw_mode == IW_MODE_ADHOC) { + /* not From/To DS: Addr1 = DA, Addr2 = SA, + Addr3 = BSSID */ + memcpy(&header.addr1, dest, ETH_ALEN); + memcpy(&header.addr2, src, ETH_ALEN); + memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); + } + + bIsMulticast = is_broadcast_ether_addr(header.addr1) ||is_multicast_ether_addr(header.addr1); + + header.frame_ctl = cpu_to_le16(fc); + + /* Determine fragmentation size based on destination (multicast + * and broadcast are not fragmented) */ + if (bIsMulticast) { + frag_size = MAX_FRAG_THRESHOLD; + qos_ctl |= QOS_CTL_NOTCONTAIN_ACK; + } + else { +#ifdef ENABLE_AMSDU + if(bIsSptAmsdu) { + if(ieee->iw_mode == IW_MODE_ADHOC) { + if(p_sta) + frag_size = p_sta->htinfo.AMSDU_MaxSize; + else + frag_size = ieee->pHTInfo->nAMSDU_MaxSize; + } + else + frag_size = ieee->pHTInfo->nAMSDU_MaxSize; + qos_ctl = 0; + } + else +#endif + { + frag_size = ieee->fts; + qos_ctl = 0; + } + } + + if(qos_actived) + { + hdr_len = RTLLIB_3ADDR_LEN + 2; + + /* in case we are a client verify acm is not set for this ac */ + while (unlikely(ieee->wmm_acm & (0x01 << skb->priority))) { + printk("skb->priority = %x\n", skb->priority); + if (wme_downgrade_ac(skb)) { + break; + } + printk("converted skb->priority = %x\n", skb->priority); + } + qos_ctl |= skb->priority; +#ifdef ENABLE_AMSDU + if(IsAmsdu) + { + qos_ctl |= QOS_CTL_AMSDU_PRESENT; + } + header.qos_ctl = cpu_to_le16(qos_ctl); +#else + header.qos_ctl = cpu_to_le16(qos_ctl & RTLLIB_QOS_TID); +#endif + } else { + hdr_len = RTLLIB_3ADDR_LEN; + } + /* Determine amount of payload per fragment. Regardless of if + * this stack is providing the full 802.11 header, one will + * eventually be affixed to this fragment -- so we must account for + * it when determining the amount of payload space. */ + bytes_per_frag = frag_size - hdr_len; + if (ieee->config & + (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) + bytes_per_frag -= RTLLIB_FCS_LEN; + + /* Each fragment may need to have room for encryptiong pre/postfix */ + if (encrypt) { +#ifdef RTL8192S_WAPI_SUPPORT + if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable) + bytes_per_frag -= ieee->wapiInfo.extra_prefix_len + + ieee->wapiInfo.extra_postfix_len; + else +#endif + bytes_per_frag -= crypt->ops->extra_prefix_len + + crypt->ops->extra_postfix_len; + } + /* Number of fragments is the total bytes_per_frag / + * payload_per_fragment */ + nr_frags = bytes / bytes_per_frag; + bytes_last_frag = bytes % bytes_per_frag; + if (bytes_last_frag) + nr_frags++; + else + bytes_last_frag = bytes_per_frag; + + /* When we allocate the TXB we allocate enough space for the reserve + * and full fragment bytes (bytes_per_frag doesn't include prefix, + * postfix, header, FCS, etc.) */ + txb = rtllib_alloc_txb(nr_frags, frag_size + ieee->tx_headroom, GFP_ATOMIC); + if (unlikely(!txb)) { + printk(KERN_WARNING "%s: Could not allocate TXB\n", + ieee->dev->name); + goto failed; + } + txb->encrypted = encrypt; + txb->payload_size = bytes; + + if(qos_actived) + { + txb->queue_index = UP2AC(skb->priority); + } else { + txb->queue_index = WME_AC_BE;; + } + + for (i = 0; i < nr_frags; i++) { + skb_frag = txb->fragments[i]; + tcb_desc = (cb_desc *)(skb_frag->cb + MAX_DEV_ADDR_SIZE); +#ifdef _RTL8192_EXT_PATCH_ + tcb_desc->mesh_pkt = 0; + if(ieee->iw_mode == IW_MODE_ADHOC) + tcb_desc->badhoc = 1; + else + tcb_desc->badhoc = 0; +#endif + if(qos_actived){ + skb_frag->priority = skb->priority; + tcb_desc->queue_index = UP2AC(skb->priority); + } else { + skb_frag->priority = WME_AC_BE; + tcb_desc->queue_index = WME_AC_BE; + } + skb_reserve(skb_frag, ieee->tx_headroom); + + if (encrypt){ + if (ieee->hwsec_active) + tcb_desc->bHwSec = 1; + else + tcb_desc->bHwSec = 0; +#ifdef RTL8192S_WAPI_SUPPORT + if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable) + skb_reserve(skb_frag, ieee->wapiInfo.extra_prefix_len); + else +#endif + skb_reserve(skb_frag, crypt->ops->extra_prefix_len); + } + else + { + tcb_desc->bHwSec = 0; + } + frag_hdr = (struct rtllib_hdr_3addrqos *)skb_put(skb_frag, hdr_len); + memcpy(frag_hdr, &header, hdr_len); + + /* If this is not the last fragment, then add the MOREFRAGS + * bit to the frame control */ + if (i != nr_frags - 1) { + frag_hdr->frame_ctl = cpu_to_le16( + fc | RTLLIB_FCTL_MOREFRAGS); + bytes = bytes_per_frag; + + } else { + /* The last fragment takes the remaining length */ + bytes = bytes_last_frag; + } + if((qos_actived) && (!bIsMulticast)) + { + frag_hdr->seq_ctl = rtllib_query_seqnum(ieee, skb_frag, header.addr1); + frag_hdr->seq_ctl = cpu_to_le16(frag_hdr->seq_ctl<<4 | i); + } else { + frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i); + } + /* Put a SNAP header on the first fragment */ +#ifdef ENABLE_AMSDU + if ((i == 0) && (!IsAmsdu)) +#else + if (i == 0) +#endif + { + rtllib_put_snap( + skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), + ether_type); + bytes -= SNAP_SIZE + sizeof(u16); + } + + memcpy(skb_put(skb_frag, bytes), skb->data, bytes); + + /* Advance the SKB... */ + skb_pull(skb, bytes); + + /* Encryption routine will move the header forward in order + * to insert the IV between the header and the payload */ + if (encrypt) { +#ifdef RTL8192S_WAPI_SUPPORT + if(ieee->WapiSupport && ieee->wapiInfo.bWapiEnable){ + if(SecSMS4HeaderFillIV(ieee, skb_frag) == 0){ + SecSWSMS4Encryption(ieee, skb_frag); + } else { + spin_unlock_irqrestore(&ieee->lock, flags); + dev_kfree_skb_any(skb); + rtllib_txb_free(txb); + return 0; + } + } + else +#endif + { + +#ifdef _RTL8192_EXT_PATCH_ + rtllib_encrypt_fragment(ieee, skb_frag, hdr_len, 0, 0); +#else + rtllib_encrypt_fragment(ieee, skb_frag, hdr_len); +#endif + } + } + if (ieee->config & + (CFG_RTLLIB_COMPUTE_FCS | CFG_RTLLIB_RESERVE_FCS)) + skb_put(skb_frag, 4); + } + + if((qos_actived) && (!bIsMulticast)) + { + if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) + ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; + else + ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; + } else { + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + } + }else{ + if (unlikely(skb->len < sizeof(struct rtllib_hdr_3addr))) { + printk(KERN_WARNING "%s: skb too small (%d).\n", + ieee->dev->name, skb->len); + goto success; + } + + txb = rtllib_alloc_txb(1, skb->len, GFP_ATOMIC); + if(!txb){ + printk(KERN_WARNING "%s: Could not allocate TXB\n", + ieee->dev->name); + goto failed; + } + + txb->encrypted = 0; + txb->payload_size = skb->len; + memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len); + } + + success: + if (txb) + { +#if 1 + cb_desc *tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); + tcb_desc->bTxEnableFwCalcDur = 1; + tcb_desc->priority = skb->priority; + + if(ether_type == ETH_P_PAE) { + if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) + { + tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee); + tcb_desc->bTxDisableRateFallBack = false; + }else{ + tcb_desc->data_rate = ieee->basic_rate; + tcb_desc->bTxDisableRateFallBack = 1; + } + + + tcb_desc->RATRIndex = 7; + tcb_desc->bTxUseDriverAssingedRate = 1; + } else { + if (is_multicast_ether_addr(header.addr1)) + tcb_desc->bMulticast = 1; + if (is_broadcast_ether_addr(header.addr1)) + tcb_desc->bBroadcast = 1; +#if defined(RTL8192U) || defined(RTL8192SU) || defined(RTL8192SE) || defined RTL8192CE + if ( tcb_desc->bMulticast || tcb_desc->bBroadcast){ + rtllib_txrate_selectmode(ieee, tcb_desc, p_sta); + tcb_desc->data_rate = ieee->basic_rate; + } + else + { + if(ieee->iw_mode == IW_MODE_ADHOC) + { + u8 is_peer_shortGI_40M = 0; + u8 is_peer_shortGI_20M = 0; + u8 is_peer_BW_40M = 0; + p_sta = GetStaInfo(ieee, header.addr1); + if(NULL == p_sta) + { + rtllib_txrate_selectmode(ieee, tcb_desc, p_sta); + tcb_desc->data_rate = ieee->rate; + } + else + { + rtllib_txrate_selectmode(ieee, tcb_desc, p_sta); + tcb_desc->data_rate = CURRENT_RATE(p_sta->wireless_mode, p_sta->CurDataRate, p_sta->htinfo.HTHighestOperaRate); + is_peer_shortGI_40M = p_sta->htinfo.bCurShortGI40MHz; + is_peer_shortGI_20M = p_sta->htinfo.bCurShortGI20MHz; + is_peer_BW_40M = p_sta->htinfo.bCurTxBW40MHz; + } + rtllib_qurey_ShortPreambleMode(ieee, tcb_desc); + rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); + rtllib_ibss_query_HTCapShortGI(ieee, tcb_desc,is_peer_shortGI_40M,is_peer_shortGI_20M); + rtllib_ibss_query_BandwidthMode(ieee, tcb_desc,is_peer_BW_40M); + rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); + } + else { + rtllib_txrate_selectmode(ieee, tcb_desc, p_sta); + tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); + if(bdhcp == true){ + if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) { + tcb_desc->data_rate = MGN_1M; + tcb_desc->bTxDisableRateFallBack = false; + }else{ + tcb_desc->data_rate = MGN_1M; + tcb_desc->bTxDisableRateFallBack = 1; + } + + tcb_desc->RATRIndex = 7; + tcb_desc->bTxUseDriverAssingedRate = 1; + tcb_desc->bdhcp = 1; + } + rtllib_qurey_ShortPreambleMode(ieee, tcb_desc); + rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); + rtllib_query_HTCapShortGI(ieee, tcb_desc); + rtllib_query_BandwidthMode(ieee, tcb_desc); + rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); +#ifdef _RTL8192_EXT_PATCH_ + ieee->LinkDetectInfo.NumTxUnicastOkInPeriod ++; +#endif + } + } +#else + rtllib_txrate_selectmode(ieee, tcb_desc); + if ( tcb_desc->bMulticast || tcb_desc->bBroadcast) + tcb_desc->data_rate = ieee->basic_rate; + else + tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate); + + if(bdhcp == true){ + if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) + { + tcb_desc->data_rate = MgntQuery_TxRateExcludeCCKRates(ieee); + tcb_desc->bTxDisableRateFallBack = false; + }else{ + tcb_desc->data_rate = MGN_1M; + tcb_desc->bTxDisableRateFallBack = 1; + } + + + tcb_desc->RATRIndex = 7; + tcb_desc->bTxUseDriverAssingedRate = 1; + tcb_desc->bdhcp = 1; + } + + rtllib_qurey_ShortPreambleMode(ieee, tcb_desc); + rtllib_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc); + rtllib_query_HTCapShortGI(ieee, tcb_desc); + rtllib_query_BandwidthMode(ieee, tcb_desc); + rtllib_query_protectionmode(ieee, tcb_desc, txb->fragments[0]); +#endif + } +#endif + } + spin_unlock_irqrestore(&ieee->lock, flags); + dev_kfree_skb_any(skb); + if (txb) { + if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){ +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) + dev->stats.tx_packets++; + dev->stats.tx_bytes += txb->payload_size; +#endif + rtllib_softmac_xmit(txb, ieee); + }else{ + if ((*ieee->hard_start_xmit)(txb, dev) == 0) { + stats->tx_packets++; + stats->tx_bytes += txb->payload_size; + return 0; + } + rtllib_txb_free(txb); + } + } + + return 0; + + failed: + spin_unlock_irqrestore(&ieee->lock, flags); + netif_stop_queue(dev); + stats->tx_errors++; + return 1; + +} +int rtllib_xmit(struct sk_buff *skb, struct net_device *dev) +{ + memset(skb->cb, 0, sizeof(skb->cb)); + return rtllib_xmit_inter(skb, dev); +} + + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(rtllib_txb_free); +#ifdef ENABLE_AMSDU +EXPORT_SYMBOL_RSL(rtllib_xmit_inter); +EXPORT_SYMBOL_RSL(AMSDU_Aggregation); +EXPORT_SYMBOL_RSL(AMSDU_GetAggregatibleList); +#endif +#ifdef _RTL8192_EXT_PATCH_ +EXPORT_SYMBOL_RSL(rtllib_query_seqnum); +EXPORT_SYMBOL_RSL(rtllib_alloc_txb); +EXPORT_SYMBOL_RSL(rtllib_encrypt_fragment); +#endif +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/rtllib_wx.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/rtllib_wx.c @@ -0,0 +1,1346 @@ +/****************************************************************************** + + Copyright(c) 2004 Intel Corporation. All rights reserved. + + Portions of this file are based on the WEP enablement code provided by the + Host AP project hostap-drivers v0.1.3 + Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen + + Copyright (c) 2002-2003, Jouni Malinen + + This program is free software; you can redistribute it and/or modify it + under the terms of version 2 of the GNU General Public License as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + The full GNU General Public License is included in this distribution in the + file called LICENSE. + + Contact Information: + James P. Ketrenos + Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + +******************************************************************************/ +#include +#include +#include +#include + +#include "rtllib.h" +#if 0 +static const char *rtllib_modes[] = { + "?", "a", "b", "ab", "g", "ag", "bg", "abg" +}; +#endif +struct modes_unit { + char *mode_string; + int mode_size; +}; +static struct modes_unit rtllib_modes[] = { + {"a",1}, + {"b",1}, + {"g",1}, + {"?",1}, +#ifdef _RTL8192_EXT_PATCH_ + {"n",5}, + {"n",4}, +#else + {"N-24G",5}, + {"N-5G",4}, +#endif +}; + +#define MAX_CUSTOM_LEN 64 +static inline char *rtl819x_translate_scan(struct rtllib_device *ieee, + char *start, char *stop, + struct rtllib_network *network, + struct iw_request_info *info) +{ + char custom[MAX_CUSTOM_LEN]; + char proto_name[IFNAMSIZ]; + char *pname = proto_name; + char *p; + struct iw_event iwe; + int i, j; + u16 max_rate, rate; + static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; + + /* First entry *MUST* be the AP MAC address */ + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN); + start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_ADDR_LEN); + /* Remaining entries will be displayed in the order we provide them */ + + /* Add the ESSID */ + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; + if(network->ssid_len > 0){ + iwe.u.data.length = min(network->ssid_len, (u8)32); + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, network->ssid); + }else if(network->hidden_ssid_len == 0){ + iwe.u.data.length = sizeof(""); + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, ""); + }else { + iwe.u.data.length = min(network->hidden_ssid_len, (u8)32); + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, network->hidden_ssid); + } + /* Add the protocol name */ + iwe.cmd = SIOCGIWNAME; + for(i=0; i<(sizeof(rtllib_modes)/sizeof(rtllib_modes[0])); i++) { + if(network->mode&(1<capability & + (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { + if (network->capability & WLAN_CAPABILITY_ESS) + iwe.u.mode = IW_MODE_MASTER; + else + iwe.u.mode = IW_MODE_ADHOC; + start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_UINT_LEN); + } + + /* Add frequency/channel */ + iwe.cmd = SIOCGIWFREQ; +/* iwe.u.freq.m = rtllib_frequency(network->channel, network->mode); + iwe.u.freq.e = 3; */ + iwe.u.freq.m = network->channel; + iwe.u.freq.e = 0; + iwe.u.freq.i = 0; + start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_FREQ_LEN); + + /* Add encryption capability */ + iwe.cmd = SIOCGIWENCODE; + if (network->capability & WLAN_CAPABILITY_PRIVACY) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, network->ssid); + /* Add basic and extended rates */ + max_rate = 0; + p = custom; + p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): "); + for (i = 0, j = 0; i < network->rates_len; ) { + if (j < network->rates_ex_len && + ((network->rates_ex[j] & 0x7F) < + (network->rates[i] & 0x7F))) + rate = network->rates_ex[j++] & 0x7F; + else + rate = network->rates[i++] & 0x7F; + if (rate > max_rate) + max_rate = rate; + p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), + "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); + } + for (; j < network->rates_ex_len; j++) { + rate = network->rates_ex[j] & 0x7F; + p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), + "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); + if (rate > max_rate) + max_rate = rate; + } + + if (network->mode >= IEEE_N_24G) + { + PHT_CAPABILITY_ELE ht_cap = NULL; + bool is40M = false, isShortGI = false; + u8 max_mcs = 0; + if (!memcmp(network->bssht.bdHTCapBuf, EWC11NHTCap, 4)) + ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[4]; + else + ht_cap = (PHT_CAPABILITY_ELE)&network->bssht.bdHTCapBuf[0]; + is40M = (ht_cap->ChlWidth)?1:0; + isShortGI = (ht_cap->ChlWidth)? + ((ht_cap->ShortGI40Mhz)?1:0): + ((ht_cap->ShortGI20Mhz)?1:0); + + max_mcs = HTGetHighestMCSRate(ieee, ht_cap->MCS, MCS_FILTER_ALL); + rate = MCS_DATA_RATE[is40M][isShortGI][max_mcs&0x7f]; + if (rate > max_rate) + max_rate = rate; + } +#if 0 + printk("max rate:%d ===basic rate:\n", max_rate); + for (i=0;irates_len;i++) + printk(" %x", network->rates[i]); + printk("\n=======extend rate\n"); + for (i=0; irates_ex_len; i++) + printk(" %x", network->rates_ex[i]); + printk("\n"); +#endif + iwe.cmd = SIOCGIWRATE; + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + iwe.u.bitrate.value = max_rate * 500000; + start = iwe_stream_add_event_rsl(info, start, stop, &iwe, + IW_EV_PARAM_LEN); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = p - custom; + if (iwe.u.data.length) + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, custom); + /* Add quality statistics */ + /* TODO: Fix these values... */ + iwe.cmd = IWEVQUAL; + iwe.u.qual.qual = network->stats.signal; + iwe.u.qual.level = network->stats.rssi; + iwe.u.qual.noise = network->stats.noise; + iwe.u.qual.updated = network->stats.mask & RTLLIB_STATMASK_WEMASK; + if (!(network->stats.mask & RTLLIB_STATMASK_RSSI)) + iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID; + if (!(network->stats.mask & RTLLIB_STATMASK_NOISE)) + iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID; + if (!(network->stats.mask & RTLLIB_STATMASK_SIGNAL)) + iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID; + iwe.u.qual.updated = 7; + start = iwe_stream_add_event_rsl(info, start, stop, &iwe, IW_EV_QUAL_LEN); + + iwe.cmd = IWEVCUSTOM; + p = custom; + iwe.u.data.length = p - custom; + if (iwe.u.data.length) + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, custom); +#if (WIRELESS_EXT < 18) + if (ieee->wpa_enabled && network->wpa_ie_len){ + char buf[MAX_WPA_IE_LEN * 2 + 30]; + u8 *p = buf; + p += sprintf(p, "wpa_ie="); + for (i = 0; i < network->wpa_ie_len; i++) { + p += sprintf(p, "%02x", network->wpa_ie[i]); + } + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = strlen(buf); + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf); + } + + if (ieee->wpa_enabled && network->rsn_ie_len){ + char buf[MAX_WPA_IE_LEN * 2 + 30]; + + u8 *p = buf; + p += sprintf(p, "rsn_ie="); + for (i = 0; i < network->rsn_ie_len; i++) { + p += sprintf(p, "%02x", network->rsn_ie[i]); + } + + memset(&iwe, 0, sizeof(iwe)); + iwe.cmd = IWEVCUSTOM; + iwe.u.data.length = strlen(buf); + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf); + } +#else + memset(&iwe, 0, sizeof(iwe)); + if (network->wpa_ie_len) + { + char buf[MAX_WPA_IE_LEN]; + memcpy(buf, network->wpa_ie, network->wpa_ie_len); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = network->wpa_ie_len; + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf); + } + memset(&iwe, 0, sizeof(iwe)); + if (network->rsn_ie_len) + { + char buf[MAX_WPA_IE_LEN]; + memcpy(buf, network->rsn_ie, network->rsn_ie_len); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = network->rsn_ie_len; + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf); + } + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) +#ifndef CUSTOMER_ID_INTEL_CMPC + /* add info for WZC */ + memset(&iwe, 0, sizeof(iwe)); + if (network->wzc_ie_len) + { + char buf[MAX_WZC_IE_LEN]; + memcpy(buf, network->wzc_ie, network->wzc_ie_len); + iwe.cmd = IWEVGENIE; + iwe.u.data.length = network->wzc_ie_len; + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, buf); + } +#endif +#endif +#endif + + /* Add EXTRA: Age to display seconds since last beacon/probe response + * for given network. */ + iwe.cmd = IWEVCUSTOM; + p = custom; + p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), + " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100)); + iwe.u.data.length = p - custom; + if (iwe.u.data.length) + start = iwe_stream_add_point_rsl(info, start, stop, &iwe, custom); + + return start; +} + +int rtllib_wx_get_scan(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + struct rtllib_network *network; + unsigned long flags; + + char *ev = extra; + char *stop = ev + wrqu->data.length; + int i = 0; + int err = 0; + RTLLIB_DEBUG_WX("Getting scan\n"); + down(&ieee->wx_sem); + spin_lock_irqsave(&ieee->lock, flags); + + list_for_each_entry(network, &ieee->network_list, list) { + i++; + if((stop-ev)<200) + { + err = -E2BIG; + break; + } + if (ieee->scan_age == 0 || + time_after(network->last_scanned + ieee->scan_age, jiffies)) + ev = rtl819x_translate_scan(ieee, ev, stop, network, info); + else + RTLLIB_DEBUG_SCAN( + "Not showing network '%s (" + MAC_FMT ")' due to age (%lums).\n", + escape_essid(network->ssid, + network->ssid_len), + MAC_ARG(network->bssid), + (jiffies - network->last_scanned) / (HZ / 100)); + } + + spin_unlock_irqrestore(&ieee->lock, flags); + up(&ieee->wx_sem); + wrqu->data.length = ev - extra; + wrqu->data.flags = 0; + + RTLLIB_DEBUG_WX("exit: %d networks returned.\n", i); + + return err; +} + +#ifdef _RTL8192_EXT_PATCH_ +int rtllib_wx_set_encode(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *keybuf, u8 is_mesh) +#else +int rtllib_wx_set_encode(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *keybuf) +#endif +{ + struct iw_point *erq = &(wrqu->encoding); + struct net_device *dev = ieee->dev; + struct rtllib_security sec = { + .flags = 0 + }; + int i, key, key_provided, len; + struct rtllib_crypt_data **crypt; + + RTLLIB_DEBUG_WX("SET_ENCODE\n"); + + key = erq->flags & IW_ENCODE_INDEX; + if (key) { + if (key > WEP_KEYS) + return -EINVAL; + key--; + key_provided = 1; + } else { + key_provided = 0; +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + key = ieee->mesh_txkeyidx; + else +#endif + key = ieee->tx_keyidx; + } + + RTLLIB_DEBUG_WX("Key: %d [%s]\n", key, key_provided ? + "provided" : "default"); +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + crypt = &ieee->cryptlist[0]->crypt[key]; + else + crypt = &ieee->sta_crypt[key]; +#else + crypt = &ieee->crypt[key]; +#endif + if (erq->flags & IW_ENCODE_DISABLED) { + if (key_provided && *crypt) { + RTLLIB_DEBUG_WX("Disabling encryption on key %d.\n", + key); + rtllib_crypt_delayed_deinit(ieee, crypt); + } else + RTLLIB_DEBUG_WX("Disabling encryption.\n"); + + /* Check all the keys to see if any are still configured, + * and if no key index was provided, de-init them all */ + for (i = 0; i < WEP_KEYS; i++) { +#ifdef _RTL8192_EXT_PATCH_ + bool null_crypt = false; + if(is_mesh) + null_crypt = (ieee->cryptlist[0]->crypt[i] != NULL) ? true:false; + else + null_crypt = (ieee->sta_crypt[i] != NULL) ? true:false; + if (null_crypt) +#else + if (ieee->crypt[i] != NULL) +#endif + { + if (key_provided) + break; +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + rtllib_crypt_delayed_deinit(ieee, &ieee->cryptlist[0]->crypt[i]); + else + rtllib_crypt_delayed_deinit(ieee, &ieee->sta_crypt[i]); +#else + rtllib_crypt_delayed_deinit(ieee, &ieee->crypt[i]); +#endif + + } + } + + if (i == WEP_KEYS) { + sec.enabled = 0; + sec.level = SEC_LEVEL_0; + sec.flags |= SEC_ENABLED | SEC_LEVEL; + } + + goto done; + } + + + + sec.enabled = 1; + sec.flags |= SEC_ENABLED; + + if (*crypt != NULL && (*crypt)->ops != NULL && + strcmp((*crypt)->ops->name, "WEP") != 0) { + /* changing to use WEP; deinit previously used algorithm + * on this key */ + rtllib_crypt_delayed_deinit(ieee, crypt); + } + + if (*crypt == NULL) { + struct rtllib_crypt_data *new_crypt; + + /* take WEP into use */ + new_crypt = kmalloc(sizeof(struct rtllib_crypt_data), + GFP_KERNEL); + if (new_crypt == NULL) + return -ENOMEM; + memset(new_crypt, 0, sizeof(struct rtllib_crypt_data)); + new_crypt->ops = rtllib_get_crypto_ops("WEP"); + if (!new_crypt->ops) { + request_module("rtllib_crypt_wep"); + new_crypt->ops = rtllib_get_crypto_ops("WEP"); + } + +#ifdef BUILT_IN_RTLLIB + if (new_crypt->ops) +#else +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) +#else + if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner)) +#endif +#endif + { + new_crypt->priv = new_crypt->ops->init(key); + } + + if (!new_crypt->ops || !new_crypt->priv) { + kfree(new_crypt); + new_crypt = NULL; + + printk(KERN_WARNING "%s: could not initialize WEP: " + "load module rtllib_crypt_wep\n", + dev->name); + return -EOPNOTSUPP; + } + *crypt = new_crypt; + } + + /* If a new key was provided, set it up */ + if (erq->length > 0) { + len = erq->length <= 5 ? 5 : 13; + memcpy(sec.keys[key], keybuf, erq->length); + if (len > erq->length) + memset(sec.keys[key] + erq->length, 0, + len - erq->length); + RTLLIB_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n", + key, escape_essid(sec.keys[key], len), + erq->length, len); + sec.key_sizes[key] = len; + (*crypt)->ops->set_key(sec.keys[key], len, NULL, + (*crypt)->priv); + sec.flags |= (1 << key); + /* This ensures a key will be activated if no key is + * explicitely set */ + if (key == sec.active_key) + sec.flags |= SEC_ACTIVE_KEY; +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + ieee->mesh_txkeyidx = key; + else +#endif + ieee->tx_keyidx = key; + + } else { + len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN, + NULL, (*crypt)->priv); + if (len == 0) { + /* Set a default key of all 0 */ + printk("Setting key %d to all zero.\n", + key); + + RTLLIB_DEBUG_WX("Setting key %d to all zero.\n", + key); + memset(sec.keys[key], 0, 13); + (*crypt)->ops->set_key(sec.keys[key], 13, NULL, + (*crypt)->priv); + sec.key_sizes[key] = 13; + sec.flags |= (1 << key); + } + + /* No key data - just set the default TX key index */ + if (key_provided) { + RTLLIB_DEBUG_WX( + "Setting key %d to default Tx key.\n", key); +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + ieee->mesh_txkeyidx = key; + else +#endif + ieee->tx_keyidx = key; + sec.active_key = key; + sec.flags |= SEC_ACTIVE_KEY; + } + } +#ifdef _RTL8192_EXT_PATCH_ + if ((ieee->iw_mode == IW_MODE_MESH)&&(is_mesh)&&ieee->ext_patch_rtllib_create_crypt_for_peer) + { + ieee->ext_patch_rtllib_create_crypt_for_peer(ieee); + } +#endif + done: + ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED); + ieee->auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; + sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; + sec.flags |= SEC_AUTH_MODE; + RTLLIB_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ? + "OPEN" : "SHARED KEY"); + + /* For now we just support WEP, so only set that security level... + * TODO: When WPA is added this is one place that needs to change */ + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */ + + if (ieee->set_security) + ieee->set_security(dev, &sec); + + /* Do not reset port if card is in Managed mode since resetting will + * generate new IEEE 802.11 authentication which may end up in looping + * with IEEE 802.1X. If your hardware requires a reset after WEP + * configuration (for example... Prism2), implement the reset_port in + * the callbacks structures used to initialize the 802.11 stack. */ + if (ieee->reset_on_keychange && + ieee->iw_mode != IW_MODE_INFRA && + ieee->reset_port && ieee->reset_port(dev)) { + printk(KERN_DEBUG "%s: reset_port failed\n", dev->name); + return -EINVAL; + } + return 0; +} + +#ifdef _RTL8192_EXT_PATCH_ +int rtllib_wx_get_encode(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *keybuf, u8 is_mesh) +#else +int rtllib_wx_get_encode(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *keybuf) +#endif +{ + struct iw_point *erq = &(wrqu->encoding); + int len, key; + struct rtllib_crypt_data *crypt; + + RTLLIB_DEBUG_WX("GET_ENCODE\n"); + + if(ieee->iw_mode == IW_MODE_MONITOR) + return -1; + + key = erq->flags & IW_ENCODE_INDEX; + if (key) { + if (key > WEP_KEYS) + return -EINVAL; + key--; + } else { +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + key = ieee->mesh_txkeyidx; + else +#endif + key = ieee->tx_keyidx; + } +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + crypt = ieee->cryptlist[0]->crypt[key]; + else + crypt = ieee->sta_crypt[key]; +#else + crypt = ieee->crypt[key]; +#endif + + erq->flags = key + 1; + + if (crypt == NULL || crypt->ops == NULL) { + erq->length = 0; + erq->flags |= IW_ENCODE_DISABLED; + return 0; + } +#if 0 + if (strcmp(crypt->ops->name, "WEP") != 0) { + /* only WEP is supported with wireless extensions, so just + * report that encryption is used */ + erq->length = 0; + erq->flags |= IW_ENCODE_ENABLED; + return 0; + } +#endif + len = crypt->ops->get_key(keybuf, SCM_KEY_LEN, NULL, crypt->priv); + erq->length = (len >= 0 ? len : 0); + + erq->flags |= IW_ENCODE_ENABLED; + + if (ieee->open_wep) + erq->flags |= IW_ENCODE_OPEN; + else + erq->flags |= IW_ENCODE_RESTRICTED; + + return 0; +} +#if (WIRELESS_EXT >= 18) +#ifdef _RTL8192_EXT_PATCH_ +int rtllib_wx_set_encode_ext(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra, u8 is_mesh) +#else +int rtllib_wx_set_encode_ext(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +#endif +{ + int ret = 0; + struct net_device *dev = ieee->dev; + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + int i, idx; + int group_key = 0; + const char *alg, *module; + struct rtllib_crypto_ops *ops; + struct rtllib_crypt_data **crypt; + + struct rtllib_security sec = { + .flags = 0, + }; + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) { + if (idx < 1 || idx > WEP_KEYS) + return -EINVAL; + idx--; + } else{ +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + idx = ieee->mesh_txkeyidx; + else +#endif + idx = ieee->tx_keyidx; + } + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + crypt = &ieee->cryptlist[0]->crypt[idx]; + else + crypt = &ieee->sta_crypt[idx]; +#else + crypt = &ieee->crypt[idx]; +#endif + group_key = 1; + } else { + /* some Cisco APs use idx>0 for unicast in dynamic WEP */ + if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) + return -EINVAL; +#ifdef _RTL8192_EXT_PATCH_ + if ((ieee->iw_mode == IW_MODE_INFRA)|| + ((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0))){ + if(is_mesh) + crypt = &ieee->cryptlist[0]->crypt[idx]; + else + crypt = &ieee->sta_crypt[idx]; + } + else + return -EINVAL; +#else + if (ieee->iw_mode == IW_MODE_INFRA) + crypt = &ieee->crypt[idx]; + else + return -EINVAL; +#endif + } + + sec.flags |= SEC_ENABLED; + if ((encoding->flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE) { + if (*crypt) + rtllib_crypt_delayed_deinit(ieee, crypt); + + for (i = 0; i < WEP_KEYS; i++) + { +#ifdef _RTL8192_EXT_PATCH_ + if ((is_mesh)&&(ieee->cryptlist[0]->crypt[i] != NULL)) + break; + if ((!is_mesh)&&(ieee->sta_crypt[i] != NULL)) + break; +#else + if (ieee->crypt[i] != NULL) + break; +#endif + } + if (i == WEP_KEYS) { + sec.enabled = 0; + sec.level = SEC_LEVEL_0; + sec.flags |= SEC_LEVEL; + } + goto done; + } + + sec.enabled = 1; +#if 0 + if (group_key ? !ieee->host_mc_decrypt : + !(ieee->host_encrypt || ieee->host_decrypt || + ieee->host_encrypt_msdu)) + goto skip_host_crypt; +#endif + switch (ext->alg) { + case IW_ENCODE_ALG_WEP: + alg = "WEP"; + module = "rtllib_crypt_wep"; + break; + case IW_ENCODE_ALG_TKIP: + alg = "TKIP"; + module = "rtllib_crypt_tkip"; + break; + case IW_ENCODE_ALG_CCMP: + alg = "CCMP"; + module = "rtllib_crypt_ccmp"; + break; + default: + RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n", + dev->name, ext->alg); + ret = -EINVAL; + goto done; + } + printk("alg name:%s\n",alg); + + ops = rtllib_get_crypto_ops(alg); + if (ops == NULL) { + char tempbuf[100]; + + memset( tempbuf, 0x00, 100 ); + sprintf( tempbuf, "%s", module); + request_module("%s",tempbuf); + ops = rtllib_get_crypto_ops(alg); + } + if (ops == NULL) { + RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n", + dev->name, ext->alg); + printk("========>unknown crypto alg %d\n", ext->alg); + ret = -EINVAL; + goto done; + } + + if (*crypt == NULL || (*crypt)->ops != ops) { + struct rtllib_crypt_data *new_crypt; + + rtllib_crypt_delayed_deinit(ieee, crypt); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) + new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); +#else + new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL); + memset(new_crypt,0,sizeof(*new_crypt)); +#endif + if (new_crypt == NULL) { + ret = -ENOMEM; + goto done; + } + new_crypt->ops = ops; +#ifdef BUILT_IN_RTLLIB + if (new_crypt->ops) +#else + if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) +#endif + { + new_crypt->priv = new_crypt->ops->init(idx); + } + + if (new_crypt->priv == NULL) { + kfree(new_crypt); + ret = -EINVAL; + goto done; + } + *crypt = new_crypt; + + } +#ifdef _RTL8192_EXT_PATCH_ + if ((ieee->iw_mode == IW_MODE_MESH)&&(is_mesh)) + { + int j; + for (j=1; jcryptlist[j]->crypt[idx]; + if (*crypttmp == NULL) + break; + if (*crypttmp && (*crypttmp)->ops != ops) + rtllib_crypt_delayed_deinit(ieee, crypttmp); + } + } +#endif + + if (ext->key_len > 0 && (*crypt)->ops->set_key && + (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq, + (*crypt)->priv) < 0) { + RTLLIB_DEBUG_WX("%s: key setting failed\n", dev->name); + printk("key setting failed\n"); + ret = -EINVAL; + goto done; + } +#if 1 + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + ieee->mesh_txkeyidx = idx; + else +#endif + ieee->tx_keyidx = idx; + sec.active_key = idx; + sec.flags |= SEC_ACTIVE_KEY; + } +#ifdef _RTL8192_EXT_PATCH_ + if ((ieee->iw_mode == IW_MODE_MESH)&&(is_mesh)&&ieee->ext_patch_rtllib_create_crypt_for_peer) + { + ieee->ext_patch_rtllib_create_crypt_for_peer(ieee); + } +#endif + if (ext->alg != IW_ENCODE_ALG_NONE) { + sec.key_sizes[idx] = ext->key_len; + sec.flags |= (1 << idx); + if (ext->alg == IW_ENCODE_ALG_WEP) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } else if (ext->alg == IW_ENCODE_ALG_TKIP) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_2; + } else if (ext->alg == IW_ENCODE_ALG_CCMP) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_3; + } + /* Don't set sec level for group keys. */ + if (group_key) + sec.flags &= ~SEC_LEVEL; + } +#endif +done: + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + + if (ieee->reset_on_keychange && + ieee->iw_mode != IW_MODE_INFRA && + ieee->reset_port && ieee->reset_port(dev)) { + RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev->name); + return -EINVAL; + } + return ret; +} + +#ifdef _RTL8192_EXT_PATCH_ +int rtllib_wx_get_encode_ext(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra, u8 is_mesh) +#else +int rtllib_wx_get_encode_ext(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +#endif +{ + struct iw_point *encoding = &wrqu->encoding; + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; + struct rtllib_crypt_data *crypt; + int idx, max_key_len; + + max_key_len = encoding->length - sizeof(*ext); + if (max_key_len < 0) + return -EINVAL; + + idx = encoding->flags & IW_ENCODE_INDEX; + if (idx) { + if (idx < 1 || idx > WEP_KEYS) + return -EINVAL; + idx--; + } else{ +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + idx = ieee->mesh_txkeyidx; + else +#endif + idx = ieee->tx_keyidx; + } + if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) && + (ext->alg != IW_ENCODE_ALG_WEP)) +#ifdef _RTL8192_EXT_PATCH_ + if (idx != 0 || !((ieee->iw_mode == IW_MODE_INFRA) || ((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 0)))) +#else + if (idx != 0 || (ieee->iw_mode != IW_MODE_INFRA)) +#endif + return -EINVAL; + +#ifdef _RTL8192_EXT_PATCH_ + if(is_mesh) + crypt = ieee->cryptlist[0]->crypt[idx]; + else + crypt = ieee->sta_crypt[idx]; +#else + crypt = ieee->crypt[idx]; +#endif + + encoding->flags = idx + 1; + memset(ext, 0, sizeof(*ext)); + + if (crypt == NULL || crypt->ops == NULL ) { + ext->alg = IW_ENCODE_ALG_NONE; + ext->key_len = 0; + encoding->flags |= IW_ENCODE_DISABLED; + } else { + if (strcmp(crypt->ops->name, "WEP") == 0 ) + ext->alg = IW_ENCODE_ALG_WEP; + else if (strcmp(crypt->ops->name, "TKIP")) + ext->alg = IW_ENCODE_ALG_TKIP; + else if (strcmp(crypt->ops->name, "CCMP")) + ext->alg = IW_ENCODE_ALG_CCMP; + else + return -EINVAL; + ext->key_len = crypt->ops->get_key(ext->key, SCM_KEY_LEN, NULL, crypt->priv); + encoding->flags |= IW_ENCODE_ENABLED; + if (ext->key_len && + (ext->alg == IW_ENCODE_ALG_TKIP || + ext->alg == IW_ENCODE_ALG_CCMP)) + ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID; + + } + + return 0; +} +#ifdef _RTL8192_EXT_PATCH_ +int rtllib_mesh_set_encode_ext(struct rtllib_device *ieee, + struct iw_point *encoding, struct iw_encode_ext *ext, int entry) +{ + int ret = 0; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + struct net_device *dev = ieee->dev; + int i, idx; + int group_key = 0; + const char *alg, *module; + struct rtllib_crypto_ops *ops; + struct rtllib_crypt_data **crypt; + + struct rtllib_security sec = { + .flags = 0, + }; + idx = encoding->flags & IW_ENCODE_INDEX; + + if (idx) { + if (idx < 1 || idx > WEP_KEYS) + return -EINVAL; + idx--; + } else + idx = ieee->tx_keyidx; + + + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + crypt = &ieee->cryptlist[0]->crypt[idx]; + group_key = 1; + } else { + /* some Cisco APs use idx>0 for unicast in dynamic WEP */ + if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) + return -EINVAL; + if ((ieee->iw_mode == IW_MODE_INFRA) || (ieee->mesh_started==1)) + { + crypt = &ieee->cryptlist[entry]->crypt[idx]; +#if 0 + if(*crypt == NULL ) + printk("%s: ERR! &ieee->cryptlist[%d]->crypt[%d] is NULL.\n",__func__, entry,idx); +#endif + } + else + return -EINVAL; + } + + sec.flags |= SEC_ENABLED; + if ((encoding->flags & IW_ENCODE_DISABLED) || + ext->alg == IW_ENCODE_ALG_NONE) { + if (*crypt){ + printk("=====>%s():DISABLE crypt is not NULL\n",__FUNCTION__); + rtllib_crypt_delayed_deinit(ieee, crypt); + } +#ifdef _RTL8192_EXT_PATCH_ + if(1) + { + int j; + for (j=1; jcryptlist[j]->crypt[idx]; + if (*crypttmp == NULL) + continue; + printk("======>crypt is not NULL\n"); + rtllib_crypt_delayed_deinit(ieee, crypttmp); + } + } +#endif + + for (i = 0; i < WEP_KEYS; i++){ + if (ieee->cryptlist[0]->crypt[i] != NULL) + break; + } + if (i == WEP_KEYS) { + sec.enabled = 0; + sec.level = SEC_LEVEL_0; + sec.flags |= SEC_LEVEL; + } + goto done; + } + + sec.enabled = 1; +#if 0 + if (group_key ? !ieee->host_mc_decrypt : + !(ieee->host_encrypt || ieee->host_decrypt || + ieee->host_encrypt_msdu)) + goto skip_host_crypt; +#endif + switch (ext->alg) { + case IW_ENCODE_ALG_WEP: + alg = "WEP"; + module = "rtllib_crypt_wep"; + break; + case IW_ENCODE_ALG_TKIP: + alg = "TKIP"; + module = "rtllib_crypt_tkip"; + break; + case IW_ENCODE_ALG_CCMP: + alg = "CCMP"; + module = "rtllib_crypt_ccmp"; + break; + default: + RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n", + dev->name, ext->alg); + ret = -EINVAL; + goto done; + } + printk("%s: alg name:%s\n",__FUNCTION__, alg); + + ops = rtllib_get_crypto_ops(alg); + if (ops == NULL) { + request_module("%s",module); + ops = rtllib_get_crypto_ops(alg); + } + if (ops == NULL) { + RTLLIB_DEBUG_WX("%s: unknown crypto alg %d\n", + dev->name, ext->alg); + printk("========>unknown crypto alg %d\n", ext->alg); + ret = -EINVAL; + goto done; + } + + if (*crypt == NULL || (*crypt)->ops != ops) { + + struct rtllib_crypt_data *new_crypt; + + rtllib_crypt_delayed_deinit(ieee, crypt); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13)) + new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); +#else + new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL); + memset(new_crypt,0,sizeof(*new_crypt)); +#endif + if (new_crypt == NULL) { + ret = -ENOMEM; + goto done; + } + new_crypt->ops = ops; +#ifdef BUILT_IN_RTLLIB + if (new_crypt->ops) +#else + if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) +#endif + { + new_crypt->priv = new_crypt->ops->init(idx); + } + if (new_crypt->priv == NULL) { + kfree(new_crypt); + ret = -EINVAL; + goto done; + } + *crypt = new_crypt; + } + + printk("%s: key_len %x \n",__FUNCTION__, ext->key_len); + + if (ext->key_len > 0 && (*crypt)->ops->set_key && + (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq, + (*crypt)->priv) < 0) { + RTLLIB_DEBUG_WX("%s: key setting failed\n", dev->name); + printk("key setting failed\n"); + ret = -EINVAL; + goto done; + } +#if 1 + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + ieee->mesh_txkeyidx = idx; + sec.active_key = idx; + sec.flags |= SEC_ACTIVE_KEY; + } + + if (ext->alg != IW_ENCODE_ALG_NONE) { + sec.key_sizes[idx] = ext->key_len; + sec.flags |= (1 << idx); + if (ext->alg == IW_ENCODE_ALG_WEP) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_1; + } else if (ext->alg == IW_ENCODE_ALG_TKIP) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_2; + } else if (ext->alg == IW_ENCODE_ALG_CCMP) { + sec.flags |= SEC_LEVEL; + sec.level = SEC_LEVEL_3; + } + /* Don't set sec level for group keys. */ + if (group_key) + sec.flags &= ~SEC_LEVEL; + } +#endif +done: + if (ieee->set_security) + ieee->set_security(ieee->dev, &sec); + + if (ieee->reset_on_keychange && + ieee->iw_mode != IW_MODE_INFRA && + ieee->reset_port && ieee->reset_port(dev)) { + RTLLIB_DEBUG_WX("%s: reset_port failed\n", dev->name); + return -EINVAL; + } +#endif + return ret; +} +#endif + +int rtllib_wx_set_mlme(struct rtllib_device *ieee, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + u8 i = 0; + bool deauth = false; + struct iw_mlme *mlme = (struct iw_mlme *) extra; + + if (ieee->state != RTLLIB_LINKED) + return -ENOLINK; + + down(&ieee->wx_sem); + + switch (mlme->cmd) { + case IW_MLME_DEAUTH: + deauth = true; + /* leave break out intentionly */ + + case IW_MLME_DISASSOC: +#ifdef _RTL8192_EXT_PATCH_ + if(!((ieee->iw_mode == IW_MODE_MESH) && (ieee->only_mesh == 1))) + { +#endif + if(deauth == true) { + printk("disauth packet !\n"); + } else { + printk("dis associate packet!\n"); + } + + ieee->cannot_notify = true; + + SendDisassociation(ieee,deauth,mlme->reason_code); + rtllib_disassociate(ieee); + + ieee->wap_set = 0; + for(i=0;i<6;i++) ieee->current_network.bssid[i]= 0x55; + + ieee->ssid_set = 0; + ieee->current_network.ssid[0] = '\0'; + ieee->current_network.ssid_len = 0; +#ifdef _RTL8192_EXT_PATCH_ + } +#endif + break; + default: + up(&ieee->wx_sem); + return -EOPNOTSUPP; + } + + up(&ieee->wx_sem); + +#endif + return 0; +} + +int rtllib_wx_set_auth(struct rtllib_device *ieee, + struct iw_request_info *info, + struct iw_param *data, char *extra) +{ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + switch (data->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + break; + case IW_AUTH_CIPHER_PAIRWISE: + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + /* + * Host AP driver does not use these parameters and allows + * wpa_supplicant to control them internally. + */ + break; + case IW_AUTH_TKIP_COUNTERMEASURES: + ieee->tkip_countermeasures = data->value; + break; + case IW_AUTH_DROP_UNENCRYPTED: + ieee->drop_unencrypted = data->value; + break; + + case IW_AUTH_80211_AUTH_ALG: + if(data->value & IW_AUTH_ALG_SHARED_KEY){ + ieee->open_wep = 0; + ieee->auth_mode = 1; + } + else if(data->value & IW_AUTH_ALG_OPEN_SYSTEM){ + ieee->open_wep = 1; + ieee->auth_mode = 0; + } + else if(data->value & IW_AUTH_ALG_LEAP){ + ieee->open_wep = 1; + ieee->auth_mode = 2; + } + else + return -EINVAL; + break; + +#if 1 + case IW_AUTH_WPA_ENABLED: + ieee->wpa_enabled = (data->value)?1:0; + break; + +#endif + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + ieee->ieee802_1x = data->value; + break; + case IW_AUTH_PRIVACY_INVOKED: + ieee->privacy_invoked = data->value; + break; + default: + return -EOPNOTSUPP; + } +#endif + return 0; +} +#endif + +int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len) +{ +#if (WIRELESS_EXT >= 18 ) + u8 *buf; + u8 eid, wps_oui[4]={0x0,0x50,0xf2,0x04}; + + if (len > MAX_WPA_IE_LEN || (len && ie == NULL)) { + return -EINVAL; + } + + if (len) { + eid = ie[0]; + if ((eid == MFIE_TYPE_GENERIC) && (!memcmp(&ie[2], wps_oui, 4))) { + + ieee->wps_ie_len = (len < MAX_WZC_IE_LEN) ? (len):(MAX_WZC_IE_LEN); + buf = kmalloc(ieee->wps_ie_len, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + memcpy(buf, ie, ieee->wps_ie_len); + ieee->wps_ie = buf; + return 0; + } + } + ieee->wps_ie_len = 0; + if (ieee->wps_ie) + kfree(ieee->wps_ie); + ieee->wps_ie = NULL; + if (len) { + if (len != ie[1]+2) { + return -EINVAL; + } + buf = kmalloc(len, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + memcpy(buf, ie, len); + kfree(ieee->wpa_ie); + ieee->wpa_ie = buf; + ieee->wpa_ie_len = len; + } else { + if (ieee->wpa_ie) + kfree(ieee->wpa_ie); + ieee->wpa_ie = NULL; + ieee->wpa_ie_len = 0; + } +#endif + return 0; +} + +#ifndef BUILT_IN_RTLLIB +EXPORT_SYMBOL_RSL(rtllib_wx_set_gen_ie); +#if (WIRELESS_EXT >= 18) +EXPORT_SYMBOL_RSL(rtllib_wx_set_mlme); +EXPORT_SYMBOL_RSL(rtllib_wx_set_auth); +EXPORT_SYMBOL_RSL(rtllib_wx_set_encode_ext); +EXPORT_SYMBOL_RSL(rtllib_wx_get_encode_ext); +#endif +EXPORT_SYMBOL_RSL(rtllib_wx_get_scan); +EXPORT_SYMBOL_RSL(rtllib_wx_set_encode); +EXPORT_SYMBOL_RSL(rtllib_wx_get_encode); +#endif +#ifdef _RTL8192_EXT_PATCH_ +EXPORT_SYMBOL_RSL(rtllib_mesh_set_encode_ext); +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/scatterwalk.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/scatterwalk.c @@ -0,0 +1,138 @@ +/* + * Cryptographic API. + * + * Cipher operations. + * + * Copyright (c) 2002 James Morris + * 2002 Adam J. Richter + * 2004 Jean-Luc Cooke + * + * 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. + * + */ + +#include +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) +#include "kmap_types.h" +#endif + +#include +#include +#include +#include +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) +#include +#else +#include +#endif +#include "internal.h" +#include "scatterwalk.h" + +enum km_type crypto_km_types[] = { + KM_USER0, + KM_USER1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, +}; + +void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch) +{ + if (nbytes <= walk->len_this_page && + (((unsigned long)walk->data) & (PAGE_CACHE_SIZE - 1)) + nbytes <= + PAGE_CACHE_SIZE) + return walk->data; + else + return scratch; +} + +static void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) +{ + if (out) + memcpy(sgdata, buf, nbytes); + else + memcpy(buf, sgdata, nbytes); +} + +void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg) +{ + unsigned int rest_of_page; + + walk->sg = sg; + +#if(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + walk->page = sg->page; +#else + walk->page = sg_page(sg); +#endif + walk->len_this_segment = sg->length; + + rest_of_page = PAGE_CACHE_SIZE - (sg->offset & (PAGE_CACHE_SIZE - 1)); + walk->len_this_page = min(sg->length, rest_of_page); + walk->offset = sg->offset; +} + +void scatterwalk_map(struct scatter_walk *walk, int out) +{ + walk->data = crypto_kmap(walk->page, out) + walk->offset; +} + +static void scatterwalk_pagedone(struct scatter_walk *walk, int out, + unsigned int more) +{ + /* walk->data may be pointing the first byte of the next page; + however, we know we transfered at least one byte. So, + walk->data - 1 will be a virtual address in the mapped page. */ + + if (out) + flush_dcache_page(walk->page); + + if (more) { + walk->len_this_segment -= walk->len_this_page; + + if (walk->len_this_segment) { + walk->page++; + walk->len_this_page = min(walk->len_this_segment, + (unsigned)PAGE_CACHE_SIZE); + walk->offset = 0; + } + else + scatterwalk_start(walk, sg_next(walk->sg)); + } +} + +void scatterwalk_done(struct scatter_walk *walk, int out, int more) +{ + crypto_kunmap(walk->data, out); + if (walk->len_this_page == 0 || !more) + scatterwalk_pagedone(walk, out, more); +} + +/* + * Do not call this unless the total length of all of the fragments + * has been verified as multiple of the block size. + */ +int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, + size_t nbytes, int out) +{ + if (buf != walk->data) { + while (nbytes > walk->len_this_page) { + memcpy_dir(buf, walk->data, walk->len_this_page, out); + buf += walk->len_this_page; + nbytes -= walk->len_this_page; + + crypto_kunmap(walk->data, out); + scatterwalk_pagedone(walk, out, 1); + scatterwalk_map(walk, out); + } + + memcpy_dir(buf, walk->data, nbytes, out); + } + + walk->offset += nbytes; + walk->len_this_page -= nbytes; + walk->len_this_segment -= nbytes; + return 0; +} --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/scatterwalk.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/scatterwalk.h @@ -0,0 +1,53 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2002 James Morris + * Copyright (c) 2002 Adam J. Richter + * Copyright (c) 2004 Jean-Luc Cooke + * + * 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. + * + */ + +#ifndef _CRYPTO_SCATTERWALK_H +#define _CRYPTO_SCATTERWALK_H +#include +#include + +struct scatter_walk { + struct scatterlist *sg; + struct page *page; + void *data; + unsigned int len_this_page; + unsigned int len_this_segment; + unsigned int offset; +}; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) +/* Define sg_next is an inline routine now in case we want to change + scatterlist to a linked list later. */ +static inline struct scatterlist *sg_next(struct scatterlist *sg) +{ + return sg + 1; +} +#endif + +static inline int scatterwalk_samebuf(struct scatter_walk *walk_in, + struct scatter_walk *walk_out, + void *src_p, void *dst_p) +{ + return walk_in->page == walk_out->page && + walk_in->offset == walk_out->offset && + walk_in->data == src_p && walk_out->data == dst_p; +} + +void *scatterwalk_whichbuf(struct scatter_walk *walk, unsigned int nbytes, void *scratch); +void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg); +int scatterwalk_copychunks(void *buf, struct scatter_walk *walk, size_t nbytes, int out); +void scatterwalk_map(struct scatter_walk *walk, int out); +void scatterwalk_done(struct scatter_walk *walk, int out, int more); + +#endif /* _CRYPTO_SCATTERWALK_H */ --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/wapi.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/wapi.c @@ -0,0 +1,1842 @@ +#if defined (RTL8192S_WAPI_SUPPORT) + +#include +#include +#include "wapi.h" +#include "wapi_interface.h" +#include "rtllib.h" + +#define LITTLE_ENDIAN +#define ENCRYPT 0 +#define DECRYPT 1 + +u32 wapi_debug_component = WAPI_INIT | + WAPI_ERR ; + +void WapiInit(struct rtllib_device *ieee) +{ + PRT_WAPI_T pWapiInfo; + int i; + + WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__); + RT_ASSERT_RET(ieee); + + pWapiInfo = &ieee->wapiInfo; + pWapiInfo->bWapiEnable = false; + + INIT_LIST_HEAD(&ieee->cache_frag_list); + + INIT_LIST_HEAD(&pWapiInfo->wapiBKIDIdleList); + INIT_LIST_HEAD(&pWapiInfo->wapiBKIDStoreList); + for(i=0;iwapiBKID[i].list, &pWapiInfo->wapiBKIDIdleList); + } + + INIT_LIST_HEAD(&pWapiInfo->wapiSTAIdleList); + INIT_LIST_HEAD(&pWapiInfo->wapiSTAUsedList); + for(i=0;iwapiSta[i].list, &pWapiInfo->wapiSTAIdleList); + } + + spin_lock_init(&ieee->wapi_queue_lock); + + ieee->wapi_queue = (WAPI_QUEUE *)kmalloc((sizeof(WAPI_QUEUE)), GFP_KERNEL); + if (!ieee->wapi_queue) { + return; + } + memset((void *)ieee->wapi_queue, 0, sizeof (WAPI_QUEUE)); + WAPI_InitQueue(ieee->wapi_queue, WAPI_MAX_QUEUE_LEN, WAPI_MAX_BUFF_LEN); + + WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__); +} + +void WapiExit(struct rtllib_device *ieee) +{ + WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__); + RT_ASSERT_RET(ieee); + + if(ieee->wapi_queue) + kfree(ieee->wapi_queue); + ieee->wapi_queue = 0; + + WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__); +} + +void WapiCreateAppEventAndSend( + struct rtllib_device *ieee, + u8 *pbuffer, + u16 buf_len, + u8 *DestAddr, + u8 bUpdateBK, + u8 bUpdateUSK, + u8 bUpdateMSK, + u8 RcvPktType, + u8 bDisconnect +) +{ + PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo); + PRT_WAPI_STA_INFO pWapiSta = NULL; + u8 WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; + u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; + u8 bFind = false, bRecvAEPacket = false, bRecvASUEPacket = false, EventId = 0; + + WAPI_TRACE(WAPI_API, "==========> %s\n", __FUNCTION__); + WAPI_TRACE(WAPI_API, "DestAddr="MAC_FMT" bUpdateBK=%d bUpdateUSK=%d bUpdateMSK=%d RcvPktType=%d bDisconnect=%d\n", + MAC_ARG(DestAddr), bUpdateBK, bUpdateUSK, bUpdateMSK, RcvPktType,bDisconnect); + + /*if(!pWapiInfo->bWapiEnable){ + WAPI_TRACE(WAPI_ERR,"%s: ieee->WapiSupport = 0!!\n",__FUNCTION__); + return; + }*/ + + if(list_empty(&pWapiInfo->wapiSTAUsedList)){ + bFind = false; + }else{ + list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { + if(!memcmp(DestAddr,pWapiSta->PeerMacAddr,ETH_ALEN)){ + bFind = true; + break; + } + } + } + + WAPI_TRACE(WAPI_API, "%s: DestAddr="MAC_FMT" bFind=%d\n", __FUNCTION__, MAC_ARG(DestAddr), bFind); + switch(RcvPktType){ + case WAPI_PREAUTHENTICATE: + EventId = WAPI_EVENT_RCV_PREAUTHENTICATE; + bRecvAEPacket = true; + bRecvASUEPacket = false; + break; + case WAPI_ACCESS_AUTHENTICATE_REQUEST: + EventId = WAPI_EVENT_RCV_ACCESS_AUTHENTICATE_REQUEST; + bRecvAEPacket = true; + bRecvASUEPacket = false; + break; + case WAPI_USK_RESPONSE: + EventId = WAPI_EVENT_RCV_USK_RESPONSE; + bRecvAEPacket = true; + bRecvASUEPacket = false; + break; + case WAPI_MSK_RESPONSE: + EventId = WAPI_EVENT_RCV_MSK_RESPONSE; + bRecvAEPacket = true; + bRecvASUEPacket = false; + break; + case WAPI_STAKEY_REQUEST: + EventId = WAPI_EVENT_RCV_STAKEY_REQUEST; + bRecvAEPacket = false; + bRecvASUEPacket = true; + break; + case WAPI_AUTHENTICATE_ACTIVE: + EventId = WAPI_EVENT_RCV_AUTHENTICATE_ACTIVE; + bRecvAEPacket = false; + bRecvASUEPacket = true; + break; + case WAPI_ACCESS_AUTHENTICATE_RESPONSE: + EventId = WAPI_EVENT_RCV_ACCESS_AUTHENTICATE_RESPONSE; + bRecvAEPacket = false; + bRecvASUEPacket = true; + break; + case WAPI_USK_REQUEST: + EventId = WAPI_EVENT_RCV_USK_REQUEST; + bRecvAEPacket = false; + bRecvASUEPacket = true; + break; + case WAPI_USK_CONFIRM: + EventId = WAPI_EVENT_RCV_USK_CONFIRM; + bRecvAEPacket = false; + bRecvASUEPacket = true; + break; + case WAPI_MSK_NOTIFICATION: + EventId = WAPI_EVENT_RCV_MSK_NOTIFICATION; + bRecvAEPacket = false; + bRecvASUEPacket = true; + break; + default: + break; + } + + if(ieee->iw_mode == IW_MODE_INFRA){ + if(bRecvAEPacket || bUpdateMSK){ + goto out; + } + if(bRecvASUEPacket){ + WAPI_CreateEvent_Send(ieee, EventId, DestAddr, pbuffer, buf_len); + goto out; + } + if(bUpdateBK && bFind){ + EventId = WAPI_EVENT_ASUE_UPDATE_BK; + WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0); + goto out; + } + if(bUpdateUSK&& bFind){ + EventId = WAPI_EVENT_ASUE_UPDATE_USK; + WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0); + goto out; + } + if(bDisconnect && bFind){ + EventId = WAPI_EVENT_DISCONNECT; + WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0); + goto out; + } + } + else if(ieee->iw_mode == IW_MODE_ADHOC) + { + if((bFind )&& (!pWapiSta->bSetkeyOk) && (bUpdateBK ||bUpdateUSK||bUpdateMSK)) + goto out; + if(bRecvASUEPacket){ + WAPI_CreateEvent_Send(ieee, EventId, DestAddr, pbuffer, buf_len); + if(EventId != WAPI_EVENT_RCV_USK_REQUEST) + goto out; + } + if((!bFind) && (!bDisconnect) && (!bUpdateMSK)) + { + if(!list_empty(&pWapiInfo->wapiSTAIdleList)) + { + pWapiSta =(PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list); + list_del_init(&pWapiSta->list); + list_add_tail(&pWapiSta->list, &pWapiInfo->wapiSTAUsedList); + WAPI_TRACE(WAPI_API, "%s: Add wapi station "MAC_FMT"\n", __FUNCTION__, MAC_ARG(DestAddr)); + memcpy(pWapiSta->PeerMacAddr,DestAddr,6); + memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16); + memcpy(pWapiSta->lastRxUnicastPN, WapiASUEPNInitialValueSrc, 16); + } + + pWapiInfo->bFirstAuthentiateInProgress= true; + + EventId = WAPI_EVENT_FIRST_AUTHENTICATOR; + WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0); + goto out; + }else{ + if(bRecvAEPacket){ + WAPI_CreateEvent_Send(ieee, EventId, DestAddr, pbuffer, buf_len); + goto out; + } + if(bDisconnect){ + EventId = WAPI_EVENT_DISCONNECT; + WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0); + goto out; + } + if(bUpdateBK){ + EventId = WAPI_EVENT_AE_UPDATE_BK; + WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0); + goto out; + } + if(bUpdateUSK){ + EventId = WAPI_EVENT_AE_UPDATE_USK; + WAPI_CreateEvent_Send(ieee, EventId, DestAddr, NULL, 0); + goto out; + } + if(bUpdateMSK){ + list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { + if(pWapiSta->bSetkeyOk){ + EventId = WAPI_EVENT_AE_UPDATE_MSK; + WAPI_CreateEvent_Send(ieee, EventId, pWapiSta->PeerMacAddr, NULL, 0); + } + } + goto out; + } + } + } + +out: + WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__); + return; +} + + +void WapiReturnAllStaInfo(struct rtllib_device *ieee) +{ + PRT_WAPI_T pWapiInfo; + PRT_WAPI_STA_INFO pWapiStaInfo; + PRT_WAPI_BKID pWapiBkid; + WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__); + + pWapiInfo = &ieee->wapiInfo; + + while(!list_empty(&(pWapiInfo->wapiSTAUsedList))) + { + pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAUsedList.next, RT_WAPI_STA_INFO, list); + list_del_init(&pWapiStaInfo->list); + memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN); + pWapiStaInfo->bSetkeyOk = 0; + list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList); + } + + while(!list_empty(&(pWapiInfo->wapiBKIDStoreList))) + { + pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list); + list_del_init(&pWapiBkid->list); + memset(pWapiBkid->bkid,0,16); + list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList); + } + WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__); +} + +void WapiReturnOneStaInfo(struct rtllib_device *ieee, u8 *MacAddr, u8 from_app) +{ + PRT_WAPI_T pWapiInfo; + PRT_WAPI_STA_INFO pWapiStaInfo = NULL; + PRT_WAPI_BKID pWapiBkid = NULL; + + pWapiInfo = &ieee->wapiInfo; + + WAPI_TRACE(WAPI_API, "==========> %s\n", __FUNCTION__); + + if(!from_app) + WapiCreateAppEventAndSend(ieee,NULL,0,MacAddr, false,false,false,0,true); + if(list_empty(&(pWapiInfo->wapiSTAUsedList))){ + return; + }else{ + list_for_each_entry(pWapiStaInfo, &pWapiInfo->wapiSTAUsedList, list) { + if(!memcmp(pWapiStaInfo->PeerMacAddr,MacAddr,ETH_ALEN)){ + pWapiStaInfo->bAuthenticateInProgress = false; + pWapiStaInfo->bSetkeyOk = false; + memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN); + list_del_init(&pWapiStaInfo->list); + list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList); + break; + } + + } + } + + if(ieee->iw_mode == IW_MODE_INFRA){ + while(!list_empty(&(pWapiInfo->wapiBKIDStoreList))) + { + pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list); + list_del_init(&pWapiBkid->list); + memset(pWapiBkid->bkid,0,16); + list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList); + } + } + WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__); + return; +} + +void WapiFreeAllStaInfo(struct rtllib_device *ieee) +{ + PRT_WAPI_T pWapiInfo; + PRT_WAPI_STA_INFO pWapiStaInfo; + PRT_WAPI_BKID pWapiBkid; + WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__); + pWapiInfo = &ieee->wapiInfo; + + WapiReturnAllStaInfo(ieee); + while(!list_empty(&(pWapiInfo->wapiSTAIdleList))) + { + pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list); + list_del_init(&pWapiStaInfo->list); + } + + while(!list_empty(&(pWapiInfo->wapiBKIDIdleList))) + { + pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID, list); + list_del_init(&pWapiBkid->list); + } + WAPI_TRACE(WAPI_INIT, "<=========== %s\n", __FUNCTION__); + return; +} + +u8 SecIsWAIPacket(struct rtllib_device* ieee,struct sk_buff *skb) +{ + PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo); + PRT_WAPI_STA_INFO pWapiSta = NULL; + u8 WaiPkt = 0, *pTaddr, bFind = false; + u8 Offset_TypeWAI = 24 + 6; + struct rtllib_hdr_3addrqos *header; + u16 mask = 1, fc = 0; + + if((!pWapiInfo->bWapiEnable) || (!ieee->wapiInfo.bWapiEnable)) + return 0; + + header = (struct rtllib_hdr_3addrqos *)skb->data; + + fc = le16_to_cpu(header->frame_ctl); + if(fc & RTLLIB_FCTL_WEP) + return 0; + + pTaddr = header->addr2; + if(list_empty(&pWapiInfo->wapiSTAUsedList)){ + bFind = false; + }else{ + list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){ + if(!memcmp(pTaddr,pWapiSta->PeerMacAddr,6)){ + bFind = true; + break; + } + } + } + + WAPI_TRACE(WAPI_API, "%s: bFind=%d pTaddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(pTaddr)); + + if( IsQoSDataFrame(skb->data) ){ + Offset_TypeWAI += sQoSCtlLng; + } + + if((header->frame_ctl & (mask<<14)) != 0){ + Offset_TypeWAI += WAPI_EXT_LEN; + } + + if( skb->len < (Offset_TypeWAI+1) ){ + WAPI_TRACE(WAPI_ERR, "%s(): invalid length(%d)\n",__FUNCTION__,skb->len); + return 0; + } + + if( (skb->data[Offset_TypeWAI]==0x88) && (skb->data[Offset_TypeWAI+1]==0xb4) ){ + WaiPkt = skb->data[Offset_TypeWAI+5]; + if(ieee->iw_mode == IW_MODE_ADHOC){ + if(bFind){ + if((WaiPkt == 8) && (pWapiInfo->wapiTxMsk.bSet) && (pWapiSta->wapiMsk.bSet) && ((skb->data[Offset_TypeWAI+14] & 0x10)==0)){ + printk("==============> %s(): Receive USK Request After MSK set!\n", __FUNCTION__); + DelStaInfo(ieee, pTaddr); + WapiReturnOneStaInfo (ieee, pTaddr, 0); + WAPI_CreateEvent_Send(ieee, WAPI_EVENT_CONNECT, ieee->current_network.bssid, NULL, 0); + } + + } + } + }else{ + WAPI_TRACE(WAPI_API, "%s(): non wai packet\n",__FUNCTION__); + } + + WAPI_TRACE(WAPI_API, "%s(): Recvd WAI frame. IsWAIPkt(%d)\n",__FUNCTION__, WaiPkt); + + return WaiPkt; +} + +/****************** +*********************/ +u8 Wapi_defragment(struct rtllib_device* ieee,u8* data, u16 len, + u8* pTaddr,bool bAuthenticator,u8* rxbuffer,u16* rxbuffer_len) +{ + PRT_CACHE_INFO pcache_info = NULL; + bool bfind = false; + + if(!list_empty(&ieee->cache_frag_list)){ + list_for_each_entry(pcache_info, &ieee->cache_frag_list, list) { + if((memcmp(pcache_info->saddr,pTaddr,ETH_ALEN)==0) + && (pcache_info->bAuthenticator == bAuthenticator)) + { + bfind = true; + break; + } + } + } + WAPI_TRACE(WAPI_RX, "%s: bFind=%d pTaddr="MAC_FMT"\n", __FUNCTION__, bfind, MAC_ARG(pTaddr)); + if(bfind == false) { + pcache_info = kmalloc(sizeof(RT_CACHE_INFO),GFP_ATOMIC); + if(pcache_info == NULL){ + WAPI_TRACE(WAPI_ERR,"%s(): can't malloc mem\n", __FUNCTION__); + goto drop2; + } + memset(pcache_info,0,sizeof(RT_CACHE_INFO)); + if(data[11] == 0x1){ + WAPI_TRACE(WAPI_RX, "%s(): First fragment, and have More fragments\n",__FUNCTION__); + memcpy(&(pcache_info->recvSeq),data+8, 2); + if(data[10] != 0x00) + { + WAPI_TRACE(WAPI_ERR, "%s(): First fragment,but fragnum is not 0.\n",__FUNCTION__); + goto drop1; + }else{ + data[10] = 0x0; + data[11] = 0x0; + if (len > 2000) { + WAPI_TRACE(WAPI_ERR,"111****************************%s():cache buf len is not enough: %d\n",__FUNCTION__,len); + goto drop1; + } + pcache_info->lastFragNum= 0x00; + memcpy(pcache_info->cache_buffer,data,len); + pcache_info->cache_buffer_len = len; + pcache_info->bAuthenticator = bAuthenticator; + memcpy(pcache_info->saddr,pTaddr,ETH_ALEN); + list_add_tail(&pcache_info->list, &ieee->cache_frag_list); + WAPI_TRACE(WAPI_RX, "%s(): First fragment, allocate cache to store.\n",__FUNCTION__); + goto drop2; + } + }else{ + if(data[10] == 0){ + WAPI_TRACE(WAPI_RX, "%s(): First fragment, no More fragment, ready to send to App.\n",__FUNCTION__); + if (len > 2000) { + WAPI_TRACE(WAPI_ERR,"222****************************%s():cache buf len is not enough: %d\n",__FUNCTION__,len); + goto drop1; + } + memcpy(rxbuffer,data,len); + *rxbuffer_len = len; + goto success; + }else{ + WAPI_TRACE(WAPI_ERR, "%s(): First fragment,no More fragment, but fragnum is not 0.\n",__FUNCTION__); + goto drop1; + } + } + } + else{ + if(data[11] == 0x1){ + if(memcmp(data+8,&(pcache_info->recvSeq),2)) { + WAPI_TRACE(WAPI_ERR, "%s(): Not First fragment, More fragment, seq num error.\n",__FUNCTION__); + list_del(&pcache_info->list); + goto drop1; + }else{ + if(data[10] == (pcache_info->lastFragNum+1)){ + WAPI_TRACE(WAPI_RX, "%s(): Not First fragment, More fragment, same seq num, copy to cache.\n",__FUNCTION__); + if ((pcache_info->cache_buffer_len + len - 12) > 2000) { + WAPI_TRACE(WAPI_ERR,"333****************************%s():cache buf len is not enough: %d\n",__FUNCTION__,pcache_info->cache_buffer_len + len - 12); + list_del(&pcache_info->list); + goto drop1; + } + memcpy(pcache_info->cache_buffer+(pcache_info->cache_buffer_len),data+12,len-12); + pcache_info->cache_buffer_len += len-12; + pcache_info->lastFragNum = data[10]; + goto drop2; + }else{ + WAPI_TRACE(WAPI_ERR, "%s(): Not First fragment, More fragment, same seq num, fragnum error.\n",__FUNCTION__); + list_del(&pcache_info->list); + goto drop1; + } + } + }else{ + if(memcmp(data+8,&(pcache_info->recvSeq),2)) { + WAPI_TRACE(WAPI_ERR, "%s(): Not First fragment, no More fragment, seq num error.\n",__FUNCTION__); + list_del(&pcache_info->list); + goto drop1; + }else{ + if(data[10] == (pcache_info->lastFragNum+1)){ + WAPI_TRACE(WAPI_RX, "%s(): Not First fragment, no More fragment, same seq num, ready to send to App.\n",__FUNCTION__); + if ((pcache_info->cache_buffer_len + len - 12) > 2000) { + WAPI_TRACE(WAPI_ERR,"444****************************%s():cache buf len is not enough: %d\n",__FUNCTION__,pcache_info->cache_buffer_len + len - 12); + list_del(&pcache_info->list); + goto drop1; + } + memcpy(pcache_info->cache_buffer+(pcache_info->cache_buffer_len),data+12,len-12); + pcache_info->cache_buffer_len += len-12; + memcpy(rxbuffer,pcache_info->cache_buffer,pcache_info->cache_buffer_len); + *rxbuffer_len = pcache_info->cache_buffer_len; + list_del(&pcache_info->list); + goto success; + }else{ + WAPI_TRACE(WAPI_ERR, "%s(): Not First fragment, no More fragment, same seq num, fragnum error.\n",__FUNCTION__); + list_del(&pcache_info->list); + goto drop1; + } + } + } + } + +drop1: + if(pcache_info) + kfree(pcache_info); + pcache_info = NULL; + return false; +drop2: + return false; +success: + if(pcache_info) + kfree(pcache_info); + pcache_info = NULL; + return true; +} + +/**************************************************************************** + * data[8-9]: Sequence Number + * data[10]: Fragment No + * data[11]: Flag = 1 indicates more data. + *****************************************************************************/ +void WapiHandleRecvPacket(struct rtllib_device* ieee,struct sk_buff *skb,u8 WaiPkt) +{ + PRT_WAPI_T pWapiInfo; + struct rtllib_hdr_3addrqos *hdr; + u8 *pTaddr, *recvPtr, *rxbuffer; + u8 bAuthenticator = false, receive_result = false; + int hdrlen = 0; + u16 recvLength = 0, fc = 0, rxbuffer_len = 0; + + WAPI_TRACE(WAPI_RX, "===========> %s: WaiPkt is %d\n", __FUNCTION__,WaiPkt); + + hdr = (struct rtllib_hdr_3addrqos *)skb->data; + pTaddr = hdr->addr2; + fc = hdr->frame_ctl; + hdrlen = rtllib_get_hdrlen(fc); + + pWapiInfo = &(ieee->wapiInfo); + if((WaiPkt == WAPI_CERTIFICATE_AUTHENTICATE_REQUEST) + ||(WaiPkt == WAPI_CERTIFICATE_AUTHENTICATE_RESPONSE)) + { + WAPI_TRACE(WAPI_RX, "%s: Valid Wai Packet \n", __FUNCTION__); + return; + }else{ + switch(WaiPkt) + { + case WAPI_PREAUTHENTICATE: + case WAPI_ACCESS_AUTHENTICATE_REQUEST: + case WAPI_USK_RESPONSE: + case WAPI_MSK_RESPONSE: + bAuthenticator = true; + break; + default: + break; + } + recvLength = skb->len - hdrlen - (SNAP_SIZE + sizeof(u16)); + recvPtr = skb->data + hdrlen + (SNAP_SIZE + sizeof(u16)); + + rxbuffer = kmalloc(2000, GFP_ATOMIC); + if(NULL == rxbuffer) + return; + + receive_result = Wapi_defragment(ieee,recvPtr, recvLength,pTaddr,bAuthenticator,rxbuffer,&rxbuffer_len); + if(receive_result) + WapiCreateAppEventAndSend(ieee, rxbuffer, rxbuffer_len, pTaddr, false,false, false, WaiPkt, false); + + kfree(rxbuffer); + } + WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__); +} + +void WapiSetIE(struct rtllib_device *ieee) +{ + PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo); + u16 protocolVer = 1; + u16 akmCnt = 1; + u16 suiteCnt = 1; + u16 capability = 0; + u8 OUI[3]; + + OUI[0] = 0x00; + OUI[1] = 0x14; + OUI[2] = 0x72; + + pWapiInfo->wapiIELength = 0; + memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &protocolVer, 2); + pWapiInfo->wapiIELength +=2; + memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &akmCnt, 2); + pWapiInfo->wapiIELength +=2; + + if(pWapiInfo->bWapiPSK){ + memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3); + pWapiInfo->wapiIELength +=3; + pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x2; + pWapiInfo->wapiIELength +=1; + }else{ + memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3); + pWapiInfo->wapiIELength +=3; + pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1; + pWapiInfo->wapiIELength +=1; + } + + memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &suiteCnt, 2); + pWapiInfo->wapiIELength +=2; + memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3); + pWapiInfo->wapiIELength +=3; + pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1; + pWapiInfo->wapiIELength +=1; + + memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3); + pWapiInfo->wapiIELength +=3; + pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1; + pWapiInfo->wapiIELength +=1; + + memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &capability, 2); + pWapiInfo->wapiIELength +=2; +} + + +/* PN1 > PN2, return 1, + * else return 0. + */ +u32 WapiComparePN(u8 *PN1, u8 *PN2) +{ + char i; + + if ((NULL == PN1) || (NULL == PN2)) + return 1; + + if ((PN2[15] - PN1[15]) & 0x80) + return 1; + + for (i=16; i>0; i--) + { + if(PN1[i-1] == PN2[i-1]) + continue; + else if(PN1[i-1] > PN2[i-1]) + return 1; + else + return 0; + } + + return 0; +} + +/* AddCount: 1 or 2. + * If overflow, return 1, + * else return 0. + */ +u8 WapiIncreasePN(u8 *PN, u8 AddCount) +{ + u8 i; + + if (NULL == PN) + return 1; + /* + if(AddCount == 2){ + printk("############################%s(): PN[0]=0x%x\n", __FUNCTION__, PN[0]); + if(PN[0] == 0x48){ + PN[0] += AddCount; + return 1; + }else{ + PN[0] += AddCount; + return 0; + } + } + */ + + for (i=0; i<16; i++) + { + if (PN[i] + AddCount <= 0xff) + { + PN[i] += AddCount; + return 0; + } + else + { + PN[i] += AddCount; + AddCount = 1; + } + } + + return 1; +} + + +void WapiGetLastRxUnicastPNForQoSData( + u8 UserPriority, + PRT_WAPI_STA_INFO pWapiStaInfo, + u8 *PNOut +) +{ + WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__); + switch(UserPriority) + { + case 0: + case 3: + memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBEQueue,16); + break; + case 1: + case 2: + memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBKQueue,16); + break; + case 4: + case 5: + memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVIQueue,16); + break; + case 6: + case 7: + memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVOQueue,16); + break; + default: + WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__); + break; + } + WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__); +} + + +void WapiSetLastRxUnicastPNForQoSData( + u8 UserPriority, + u8 *PNIn, + PRT_WAPI_STA_INFO pWapiStaInfo +) +{ + WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__); + switch(UserPriority) + { + case 0: + case 3: + memcpy(pWapiStaInfo->lastRxUnicastPNBEQueue,PNIn,16); + break; + case 1: + case 2: + memcpy(pWapiStaInfo->lastRxUnicastPNBKQueue,PNIn,16); + break; + case 4: + case 5: + memcpy(pWapiStaInfo->lastRxUnicastPNVIQueue,PNIn,16); + break; + case 6: + case 7: + memcpy(pWapiStaInfo->lastRxUnicastPNVOQueue,PNIn,16); + break; + default: + WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__); + break; + } + WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__); +} + + +/**************************************************************************** +TRUE-----------------bRxReorder == FALSE not RX-Reorder +FALSE----------------bRxReorder == TRUE do RX Reorder +add to support WAPI to N-mode +*****************************************************************************/ +u8 WapiCheckPnInSwDecrypt( + struct rtllib_device *ieee, + struct sk_buff *pskb +) +{ + struct rtllib_hdr_3addrqos *header; + u16 fc; + u8 *pDaddr, *pTaddr, *pRaddr; + u8 ret = false; + + header = (struct rtllib_hdr_3addrqos *)pskb->data; + pTaddr = header->addr2; + pRaddr = header->addr1; + fc = le16_to_cpu(header->frame_ctl); + + if((fc & RTLLIB_FCTL_TODS) == RTLLIB_FCTL_TODS) + pDaddr = header->addr3; + else + pDaddr = header->addr1; + + if(eqMacAddr(pRaddr, ieee->dev->dev_addr) && + !is_multicast_ether_addr(pDaddr) && + ieee->current_network.qos_data.active && + IsQoSDataFrame(pskb->data) && ieee->pHTInfo->bCurrentHTSupport && + ieee->pHTInfo->bCurRxReorderEnable) + ret = false; + else + ret = true; + + WAPI_TRACE(WAPI_RX, "%s: return %d\n", __FUNCTION__, ret); + return ret; +} + + +/**************************************************************************** +TRUE-----------------Drop +FALSE---------------- handle +add to support WAPI to N-mode +*****************************************************************************/ +u8 WapiCheckDropForRxReorderCase( + struct rtllib_device *ieee, + struct rtllib_rxb* prxb +) +{ + PRT_WAPI_T pWapiInfo = &(ieee->wapiInfo); + u8 *pLastRecvPN = NULL; + u8 bFind = false; + PRT_WAPI_STA_INFO pWapiSta = NULL; + + if(!pWapiInfo->bWapiEnable) + return false; + + if(list_empty(&pWapiInfo->wapiSTAUsedList)){ + bFind = false; + }else{ + list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { + if(!memcmp(prxb->WapiSrcAddr,pWapiSta->PeerMacAddr,ETH_ALEN)){ + bFind = true; + break; + } + } + } + WAPI_TRACE(WAPI_RX, "%s: bFind=%d prxb->WapiSrcAddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(prxb->WapiSrcAddr)); + + if(bFind){ + switch(prxb->UserPriority) + { + case 0: + case 3: + pLastRecvPN = pWapiSta->lastRxUnicastPNBEQueue; + break; + case 1: + case 2: + pLastRecvPN = pWapiSta->lastRxUnicastPNBKQueue; + break; + case 4: + case 5: + pLastRecvPN = pWapiSta->lastRxUnicastPNVIQueue; + break; + case 6: + case 7: + pLastRecvPN = pWapiSta->lastRxUnicastPNVOQueue; + break; + default: + WAPI_TRACE(WAPI_ERR,"%s: Unknown TID \n",__FUNCTION__); + break; + } + + if(!WapiComparePN(prxb->WapiTempPN,pLastRecvPN)) + { + WAPI_TRACE(WAPI_RX,"%s: Equal PN!!\n",__FUNCTION__); + return true; + } + else + { + memcpy(pLastRecvPN,prxb->WapiTempPN,16); + return false; + } + } + else + return false; +} + +int WapiSendWaiPacket(struct rtllib_device *ieee, struct sk_buff *pskb) +{ + struct sk_buff * newskb = NULL; + struct rtllib_hdr_3addr *mac_hdr=NULL; + cb_desc *tcb_desc = NULL; + + RT_ASSERT_RET_VALUE(ieee,-1); + RT_ASSERT_RET_VALUE(pskb,-1); + + if(pskb->len < (14 + sizeof(struct rtllib_hdr_3addr))) + { + WAPI_TRACE(WAPI_ERR, "%s: WAI frame is too small!!\n", __FUNCTION__); + goto failed; + } + + skb_pull(pskb, 14); + + newskb = dev_alloc_skb(pskb->len+ieee->tx_headroom); + if(!newskb){ + WAPI_TRACE(WAPI_ERR,"%s: can't alloc skb\n",__FUNCTION__); + goto failed; + } + skb_reserve(newskb, ieee->tx_headroom); + memcpy(skb_put(newskb, pskb->len), pskb->data, pskb->len); + dev_kfree_skb_any(pskb); + /* called with 2nd parm 0, no tx mgmt lock required */ + rtllib_sta_wakeup(ieee,0); + + tcb_desc = (cb_desc *)(newskb->cb + MAX_DEV_ADDR_SIZE); +#ifdef RTL8192SU_FPGA_UNSPECIFIED_NETWORK + tcb_desc->queue_index = NORMAL_QUEUE; +#else + tcb_desc->queue_index = BE_QUEUE; +#endif + tcb_desc->data_rate = 0x02; + tcb_desc->bTxUseDriverAssingedRate = true; + tcb_desc->RATRIndex = 7; + tcb_desc->bTxDisableRateFallBack = 1; +#ifdef _RTL8192_EXT_PATCH_ + tcb_desc->macId = 0; +#endif + + mac_hdr = (struct rtllib_hdr_3addr *)(newskb->data); + mac_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); + if (ieee->seq_ctrl[0] == 0xFFF) + ieee->seq_ctrl[0] = 0; + else + ieee->seq_ctrl[0]++; + + if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\ + (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\ + (ieee->queue_stop) ) { + WAPI_TRACE(WAPI_TX, "%s: Insert to waitqueue (idx=%d)!!\n", __FUNCTION__, tcb_desc->queue_index); + skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], newskb); + } else { + ieee->softmac_hard_start_xmit(newskb,ieee->dev); + } + + return 0; + +failed: + dev_kfree_skb_any(pskb); + return -1; +} +/********************************************************** + **********************************************************/ +const u8 Sbox[256] = { +0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05, +0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99, +0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62, +0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6, +0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8, +0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35, +0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87, +0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e, +0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1, +0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3, +0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f, +0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51, +0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8, +0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0, +0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84, +0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48 +}; + +const u32 CK[32] = { + 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, + 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, + 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, + 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, + 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, + 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, + 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, + 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 }; + +#define Rotl(_x, _y) (((_x) << (_y)) | ((_x) >> (32 - (_y)))) + +#define ByteSub(_A) (Sbox[(_A) >> 24 & 0xFF] << 24 | \ + Sbox[(_A) >> 16 & 0xFF] << 16 | \ + Sbox[(_A) >> 8 & 0xFF] << 8 | \ + Sbox[(_A) & 0xFF]) + +#define L1(_B) ((_B) ^ Rotl(_B, 2) ^ Rotl(_B, 10) ^ Rotl(_B, 18) ^ Rotl(_B, 24)) +#define L2(_B) ((_B) ^ Rotl(_B, 13) ^ Rotl(_B, 23)) + +static void +xor_block(void *dst, void *src1, void *src2) +/* 128-bit xor: *dst = *src1 xor *src2. Pointers must be 32-bit aligned */ +{ + ((u32 *)dst)[0] = ((u32 *)src1)[0] ^ ((u32 *)src2)[0]; + ((u32 *)dst)[1] = ((u32 *)src1)[1] ^ ((u32 *)src2)[1]; + ((u32 *)dst)[2] = ((u32 *)src1)[2] ^ ((u32 *)src2)[2]; + ((u32 *)dst)[3] = ((u32 *)src1)[3] ^ ((u32 *)src2)[3]; +} + + +void SMS4Crypt(u8 *Input, u8 *Output, u32 *rk) +{ + u32 r, mid, x0, x1, x2, x3, *p; + p = (u32 *)Input; + x0 = p[0]; + x1 = p[1]; + x2 = p[2]; + x3 = p[3]; +#ifdef LITTLE_ENDIAN + x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8); + x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8); + x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8); + x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8); +#endif + for (r = 0; r < 32; r += 4) + { + mid = x1 ^ x2 ^ x3 ^ rk[r + 0]; + mid = ByteSub(mid); + x0 ^= L1(mid); + mid = x2 ^ x3 ^ x0 ^ rk[r + 1]; + mid = ByteSub(mid); + x1 ^= L1(mid); + mid = x3 ^ x0 ^ x1 ^ rk[r + 2]; + mid = ByteSub(mid); + x2 ^= L1(mid); + mid = x0 ^ x1 ^ x2 ^ rk[r + 3]; + mid = ByteSub(mid); + x3 ^= L1(mid); + } +#ifdef LITTLE_ENDIAN + x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8); + x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8); + x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8); + x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8); +#endif + p = (u32 *)Output; + p[0] = x3; + p[1] = x2; + p[2] = x1; + p[3] = x0; +} + + + +void SMS4KeyExt(u8 *Key, u32 *rk, u32 CryptFlag) +{ + u32 r, mid, x0, x1, x2, x3, *p; + + p = (u32 *)Key; + x0 = p[0]; + x1 = p[1]; + x2 = p[2]; + x3 = p[3]; +#ifdef LITTLE_ENDIAN + x0 = Rotl(x0, 16); x0 = ((x0 & 0xFF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8); + x1 = Rotl(x1, 16); x1 = ((x1 & 0xFF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8); + x2 = Rotl(x2, 16); x2 = ((x2 & 0xFF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8); + x3 = Rotl(x3, 16); x3 = ((x3 & 0xFF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8); +#endif + + x0 ^= 0xa3b1bac6; + x1 ^= 0x56aa3350; + x2 ^= 0x677d9197; + x3 ^= 0xb27022dc; + for (r = 0; r < 32; r += 4) + { + mid = x1 ^ x2 ^ x3 ^ CK[r + 0]; + mid = ByteSub(mid); + rk[r + 0] = x0 ^= L2(mid); + mid = x2 ^ x3 ^ x0 ^ CK[r + 1]; + mid = ByteSub(mid); + rk[r + 1] = x1 ^= L2(mid); + mid = x3 ^ x0 ^ x1 ^ CK[r + 2]; + mid = ByteSub(mid); + rk[r + 2] = x2 ^= L2(mid); + mid = x0 ^ x1 ^ x2 ^ CK[r + 3]; + mid = ByteSub(mid); + rk[r + 3] = x3 ^= L2(mid); + } + if (CryptFlag == DECRYPT) + { + for (r = 0; r < 16; r++) + mid = rk[r], rk[r] = rk[31 - r], rk[31 - r] = mid; + } +} + + +void WapiSMS4Cryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength, + u8 *Output, u16 *OutputLength, u32 CryptFlag) +{ + u32 blockNum,i,j, rk[32]; + u16 remainder; + u8 blockIn[16],blockOut[16], tempIV[16], k; + + *OutputLength = 0; + remainder = InputLength & 0x0F; + blockNum = InputLength >> 4; + if(remainder !=0) + blockNum++; + else + remainder = 16; + + for(k=0;k<16;k++) + tempIV[k] = IV[15-k]; + + memcpy(blockIn, tempIV, 16); + + SMS4KeyExt((u8 *)Key, rk,CryptFlag); + + for(i=0; i> 4; + + for(k=0;k<16;k++) + tempIV[k] = IV[15-k]; + + memcpy(BlockIn, tempIV, 16); + + SMS4KeyExt((u8 *)Key, rk, ENCRYPT); + + SMS4Crypt((u8 *)BlockIn, BlockOut, rk); + + for(i=0; i> 4; + + for(i=0; iframe_ctl); + if((fc & (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) == (RTLLIB_FCTL_FROMDS | RTLLIB_FCTL_TODS)) + { + memcpy((TempBuf+22), (pHeader+24), 6); + QosOffset = 30; + }else{ + memset((TempBuf+22), 0, 6); + QosOffset = 24; + } + + if( IsQoSDataFrame(pHeader)){ + memcpy((TempBuf+28), (pHeader+QosOffset), 2); + TempLen += 2; + IV = pHeader + QosOffset + 2 + 2; + }else{ + IV = pHeader + QosOffset + 2; + } + + TempBuf[TempLen-1] = (u8)(DataLen & 0xff); + TempBuf[TempLen-2] = (u8)((DataLen & 0xff00)>>8); + TempBuf[TempLen-4] = KeyIdx; + + WAPI_DATA(WAPI_TX, "CalculateMic - KEY", MicKey, 16); + WAPI_DATA(WAPI_TX, "CalculateMic - IV", IV, 16); + WAPI_DATA(WAPI_TX, "CalculateMic - TempBuf", TempBuf, TempLen); + WAPI_DATA(WAPI_TX, "CalculateMic - pData", pData, DataLen); + + WapiSMS4CalculateMic(MicKey, IV, TempBuf, TempLen, + pData, DataLen, MicBuffer, &MicLen); + + if (MicLen != 16) + WAPI_TRACE(WAPI_ERR,"%s: MIC Length Error!!\n",__FUNCTION__); +} + +int SecSMS4HeaderFillIV(struct rtllib_device *ieee, struct sk_buff *pskb) +{ + u8 *pSecHeader = NULL, *pos = NULL, *pRA = NULL; + u8 bPNOverflow = false, bFindMatchPeer = false, hdr_len = 0; + PWLAN_HEADER_WAPI_EXTENSION pWapiExt = NULL; + PRT_WAPI_T pWapiInfo = &ieee->wapiInfo; + PRT_WAPI_STA_INFO pWapiSta = NULL; + int ret = 0; + + if ((!ieee->WapiSupport) || (!ieee->wapiInfo.bWapiEnable)){ + WAPI_TRACE(WAPI_ERR,"%s: ieee->WapiSupport = 0!!\n",__FUNCTION__); + return -1; + } + + hdr_len = sMacHdrLng; + if(IsQoSDataFrame(pskb->data) ){ + hdr_len += sQoSCtlLng; + } + + pos = skb_push(pskb, ieee->wapiInfo.extra_prefix_len); + memmove(pos, pos+ieee->wapiInfo.extra_prefix_len, hdr_len); + + pSecHeader = pskb->data + hdr_len; + pWapiExt = (PWLAN_HEADER_WAPI_EXTENSION)pSecHeader; + pRA = pskb->data + 4; + + WAPI_DATA(WAPI_TX, "FillIV - Before Fill IV", pskb->data, pskb->len); + + if( is_multicast_ether_addr(pRA) ){ + if(!pWapiInfo->wapiTxMsk.bTxEnable){ + WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__); + return -2; + } + if(pWapiInfo->wapiTxMsk.keyId <= 1){ + pWapiExt->KeyIdx = pWapiInfo->wapiTxMsk.keyId; + pWapiExt->Reserved = 0; + bPNOverflow = WapiIncreasePN(pWapiInfo->lastTxMulticastPN, 1); + memcpy(pWapiExt->PN, pWapiInfo->lastTxMulticastPN, 16); + if (bPNOverflow){ + WAPI_TRACE(WAPI_ERR,"===============>%s():multicast PN overflow\n",__FUNCTION__); + WapiCreateAppEventAndSend(ieee,NULL,0,pRA, false, false, true, 0, false); + } + }else{ + WAPI_TRACE(WAPI_ERR,"%s: Invalid Wapi Multicast KeyIdx!!\n",__FUNCTION__); + ret = -3; + } + } + else{ + list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { + if(!memcmp(pWapiSta->PeerMacAddr,pRA,6)){ + bFindMatchPeer = true; + break; + } + } + if (bFindMatchPeer){ + if((!pWapiSta->wapiUskUpdate.bTxEnable) && (!pWapiSta->wapiUsk.bTxEnable)){ + WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__); + return -4; + } + if (pWapiSta->wapiUsk.keyId <= 1){ + if(pWapiSta->wapiUskUpdate.bTxEnable) + pWapiExt->KeyIdx = pWapiSta->wapiUskUpdate.keyId; + else + pWapiExt->KeyIdx = pWapiSta->wapiUsk.keyId; + + pWapiExt->Reserved = 0; + bPNOverflow = WapiIncreasePN(pWapiSta->lastTxUnicastPN, 2); + memcpy(pWapiExt->PN, pWapiSta->lastTxUnicastPN, 16); + if (bPNOverflow){ + WAPI_TRACE(WAPI_ERR,"===============>%s():unicast PN overflow\n",__FUNCTION__); + WapiCreateAppEventAndSend(ieee,NULL,0,pWapiSta->PeerMacAddr, false, true, false, 0, false); + } + }else{ + WAPI_TRACE(WAPI_ERR,"%s: Invalid Wapi Unicast KeyIdx!!\n",__FUNCTION__); + ret = -5; + } + } + else{ + WAPI_TRACE(WAPI_ERR,"%s: Can not find Peer Sta "MAC_FMT"!!\n",__FUNCTION__, MAC_ARG(pRA)); + ret = -6; + } + } + + WAPI_DATA(WAPI_TX, "FillIV - After Fill IV", pskb->data, pskb->len); + return ret; +} + +void SecSWSMS4Encryption( + struct rtllib_device *ieee, + struct sk_buff *pskb + ) +{ + PRT_WAPI_T pWapiInfo = &ieee->wapiInfo; + PRT_WAPI_STA_INFO pWapiSta = NULL; + u8 *SecPtr = NULL, *pRA, *pMicKey = NULL, *pDataKey = NULL, *pIV = NULL, *pHeader = pskb->data; + u8 IVOffset, DataOffset, bFindMatchPeer = false, KeyIdx = 0, MicBuffer[16]; + u16 OutputLength; + +#if defined(RTL8192U) || defined(RTL8192SU) + u32 SpecificHeadOverhead = 0; +#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE + cb_desc *tcb_desc = (cb_desc *)(pskb->cb + MAX_DEV_ADDR_SIZE); + if (tcb_desc->drv_agg_enable) + SpecificHeadOverhead = TX_PACKET_DRVAGGR_SUBFRAME_SHIFT_BYTES; + else +#endif + SpecificHeadOverhead = TX_PACKET_SHIFT_BYTES; + + pHeader += SpecificHeadOverhead; +#endif + WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__); + + if( IsQoSDataFrame(pHeader) ){ + IVOffset = sMacHdrLng + sQoSCtlLng; + }else{ + IVOffset = sMacHdrLng; + } + + DataOffset = IVOffset + ieee->wapiInfo.extra_prefix_len; + + pRA = pHeader + 4; + if( is_multicast_ether_addr(pRA) ){ + KeyIdx = pWapiInfo->wapiTxMsk.keyId; + pIV = pWapiInfo->lastTxMulticastPN; + pMicKey = pWapiInfo->wapiTxMsk.micKey; + pDataKey = pWapiInfo->wapiTxMsk.dataKey; + }else{ + if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){ + list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { + if (0 == memcmp(pWapiSta->PeerMacAddr, pRA, 6)){ + bFindMatchPeer = true; + break; + } + } + + if (bFindMatchPeer){ + if (pWapiSta->wapiUskUpdate.bTxEnable){ + KeyIdx = pWapiSta->wapiUskUpdate.keyId; + WAPI_TRACE(WAPI_TX, "%s(): Use update USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx); + pIV = pWapiSta->lastTxUnicastPN; + pMicKey = pWapiSta->wapiUskUpdate.micKey; + pDataKey = pWapiSta->wapiUskUpdate.dataKey; + }else{ + KeyIdx = pWapiSta->wapiUsk.keyId; + WAPI_TRACE(WAPI_TX, "%s(): Use USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx); + pIV = pWapiSta->lastTxUnicastPN; + pMicKey = pWapiSta->wapiUsk.micKey; + pDataKey = pWapiSta->wapiUsk.dataKey; + } + }else{ + WAPI_TRACE(WAPI_ERR,"%s: Can not find Peer Sta!!\n",__FUNCTION__); + return; + } + }else{ + WAPI_TRACE(WAPI_ERR,"%s: wapiSTAUsedList is empty!!\n",__FUNCTION__); + return; + } + } + + SecPtr = pHeader; + SecCalculateMicSMS4(KeyIdx, pMicKey, SecPtr, (SecPtr+DataOffset), pskb->len-DataOffset, MicBuffer); + + WAPI_DATA(WAPI_TX, "Encryption - MIC", MicBuffer, ieee->wapiInfo.extra_postfix_len); + + memcpy(skb_put(pskb,ieee->wapiInfo.extra_postfix_len), + MicBuffer, + ieee->wapiInfo.extra_postfix_len + ); + + WapiSMS4Encryption(pDataKey, pIV, (SecPtr+DataOffset), pskb->len-DataOffset, (SecPtr+DataOffset), &OutputLength); + + WAPI_DATA(WAPI_TX, "Encryption - After SMS4 encryption", pskb->data,pskb->len); + + if (OutputLength != pskb->len-DataOffset) + WAPI_TRACE(WAPI_ERR,"%s: Output Length Error!!\n",__FUNCTION__); + + WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__); +} + +u8 SecSWSMS4Decryption( + struct rtllib_device *ieee, + struct sk_buff *pskb, + struct rtllib_rx_stats *rx_stats + ) +{ + PRT_WAPI_T pWapiInfo = &ieee->wapiInfo; + PRT_WAPI_STA_INFO pWapiSta = NULL; + u8 IVOffset, DataOffset, bFindMatchPeer = false, bUseUpdatedKey = false; + u8 KeyIdx, MicBuffer[16], lastRxPNforQoS[16]; + u8 *pRA, *pTA, *pMicKey, *pDataKey, *pLastRxPN, *pRecvPN, *pSecData, *pRecvMic, *pos; + u8 TID = 0; + u16 OutputLength, DataLen; + + rx_stats->bWapiCheckPNInDecrypt = WapiCheckPnInSwDecrypt(ieee, pskb); + WAPI_TRACE(WAPI_RX, "=========>%s: check PN %d\n", __FUNCTION__,rx_stats->bWapiCheckPNInDecrypt); + WAPI_DATA(WAPI_RX, "Decryption - Before decryption", pskb->data, pskb->len); + + IVOffset = sMacHdrLng; + if( rx_stats->bIsQosData ){ + IVOffset += sQoSCtlLng; + } + if( rx_stats->bContainHTC ) + IVOffset += sHTCLng; + + + DataOffset = IVOffset + ieee->wapiInfo.extra_prefix_len; + + pRA = pskb->data + 4; + pTA = pskb->data + 10; + KeyIdx = *(pskb->data + IVOffset); + pRecvPN = pskb->data + IVOffset + 2; + pSecData = pskb->data + DataOffset; + DataLen = pskb->len - DataOffset; + pRecvMic = pskb->data + pskb->len - ieee->wapiInfo.extra_postfix_len; + TID = Frame_QoSTID(pskb->data); + + if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){ + list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { + if (0 == memcmp(pWapiSta->PeerMacAddr, pTA, 6)){ + bFindMatchPeer = true; + break; + } + } + } + + if (!bFindMatchPeer){ + WAPI_TRACE(WAPI_ERR, "%s: Can not find Peer Sta "MAC_FMT" for Key Info!!!\n", __FUNCTION__, MAC_ARG(pTA)); + return false; + } + + if( is_multicast_ether_addr(pRA) ){ + WAPI_TRACE(WAPI_RX, "%s: Multicast decryption !!!\n", __FUNCTION__); + if (pWapiSta->wapiMsk.keyId == KeyIdx && pWapiSta->wapiMsk.bSet){ + pLastRxPN = pWapiSta->lastRxMulticastPN; + if (!WapiComparePN(pRecvPN, pLastRxPN)){ + WAPI_TRACE(WAPI_ERR, "%s: MSK PN is not larger than last, Dropped!!!\n", __FUNCTION__); + WAPI_DATA(WAPI_ERR, "pRecvPN:", pRecvPN, 16); + WAPI_DATA(WAPI_ERR, "pLastRxPN:", pLastRxPN, 16); + return false; + } + + memcpy(pLastRxPN, pRecvPN, 16); + pMicKey = pWapiSta->wapiMsk.micKey; + pDataKey = pWapiSta->wapiMsk.dataKey; + }else if (pWapiSta->wapiMskUpdate.keyId == KeyIdx && pWapiSta->wapiMskUpdate.bSet){ + WAPI_TRACE(WAPI_RX, "%s: Use Updated MSK for Decryption !!!\n", __FUNCTION__); + bUseUpdatedKey = true; + memcpy(pWapiSta->lastRxMulticastPN, pRecvPN, 16); + pMicKey = pWapiSta->wapiMskUpdate.micKey; + pDataKey = pWapiSta->wapiMskUpdate.dataKey; + }else{ + WAPI_TRACE(WAPI_ERR, "%s: Can not find MSK with matched KeyIdx(%d), Dropped !!!\n", __FUNCTION__,KeyIdx); + return false; + } + } + else{ + WAPI_TRACE(WAPI_RX, "%s: Unicast decryption !!!\n", __FUNCTION__); + if (pWapiSta->wapiUsk.keyId == KeyIdx && pWapiSta->wapiUsk.bSet){ + WAPI_TRACE(WAPI_RX, "%s: Use USK for Decryption!!!\n", __FUNCTION__); + if(rx_stats->bWapiCheckPNInDecrypt){ + if(rx_stats->bIsQosData){ + WapiGetLastRxUnicastPNForQoSData(TID, pWapiSta, lastRxPNforQoS); + pLastRxPN = lastRxPNforQoS; + }else{ + pLastRxPN = pWapiSta->lastRxUnicastPN; + } + if (!WapiComparePN(pRecvPN, pLastRxPN)){ + return false; + } + if(rx_stats->bIsQosData){ + WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta); + }else{ + memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16); + } + }else{ + memcpy(rx_stats->WapiTempPN,pRecvPN,16); + } + + if (ieee->iw_mode == IW_MODE_INFRA){ + if ((pRecvPN[0] & 0x1) == 0){ + WAPI_TRACE(WAPI_ERR, "%s: Rx USK PN is not odd when Infra STA mode, Dropped !!!\n", __FUNCTION__); + return false; + } + } + + pMicKey = pWapiSta->wapiUsk.micKey; + pDataKey = pWapiSta->wapiUsk.dataKey; + } + else if (pWapiSta->wapiUskUpdate.keyId == KeyIdx && pWapiSta->wapiUskUpdate.bSet ){ + WAPI_TRACE(WAPI_RX, "%s: Use Updated USK for Decryption!!!\n", __FUNCTION__); + if(pWapiSta->bAuthenticatorInUpdata) + bUseUpdatedKey = true; + else + bUseUpdatedKey = false; + + if(rx_stats->bIsQosData){ + WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta); + }else{ + memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16); + } + pMicKey = pWapiSta->wapiUskUpdate.micKey; + pDataKey = pWapiSta->wapiUskUpdate.dataKey; + }else{ + WAPI_TRACE(WAPI_ERR, "%s: No valid USK!!!KeyIdx=%d pWapiSta->wapiUsk.keyId=%d pWapiSta->wapiUskUpdate.keyId=%d\n", __FUNCTION__, KeyIdx, pWapiSta->wapiUsk.keyId, pWapiSta->wapiUskUpdate.keyId); + dump_buf(pskb->data,pskb->len); + return false; + } + } + + WAPI_DATA(WAPI_RX, "Decryption - DataKey", pDataKey, 16); + WAPI_DATA(WAPI_RX, "Decryption - IV", pRecvPN, 16); + WapiSMS4Decryption(pDataKey, pRecvPN, pSecData, DataLen, pSecData, &OutputLength); + + if (OutputLength != DataLen) + WAPI_TRACE(WAPI_ERR, "%s: Output Length Error!!!!\n", __FUNCTION__); + + WAPI_DATA(WAPI_RX, "Decryption - After decryption", pskb->data, pskb->len); + + DataLen -= ieee->wapiInfo.extra_postfix_len; + + SecCalculateMicSMS4(KeyIdx, pMicKey, pskb->data, pSecData, DataLen, MicBuffer); + + WAPI_DATA(WAPI_RX, "Decryption - MIC received", pRecvMic, SMS4_MIC_LEN); + WAPI_DATA(WAPI_RX, "Decryption - MIC calculated", MicBuffer, SMS4_MIC_LEN); + + if (0 == memcmp(MicBuffer, pRecvMic, ieee->wapiInfo.extra_postfix_len)){ + WAPI_TRACE(WAPI_RX, "%s: Check MIC OK!!\n", __FUNCTION__); + if (bUseUpdatedKey){ + if ( is_multicast_ether_addr(pRA) ){ + WAPI_TRACE(WAPI_API, "%s(): AE use new update MSK!!\n", __FUNCTION__); + pWapiSta->wapiMsk.keyId = pWapiSta->wapiMskUpdate.keyId; + memcpy(pWapiSta->wapiMsk.dataKey, pWapiSta->wapiMskUpdate.dataKey, 16); + memcpy(pWapiSta->wapiMsk.micKey, pWapiSta->wapiMskUpdate.micKey, 16); + pWapiSta->wapiMskUpdate.bTxEnable = pWapiSta->wapiMskUpdate.bSet = false; + }else{ + WAPI_TRACE(WAPI_API, "%s(): AE use new update USK!!\n", __FUNCTION__); + pWapiSta->wapiUsk.keyId = pWapiSta->wapiUskUpdate.keyId; + memcpy(pWapiSta->wapiUsk.dataKey, pWapiSta->wapiUskUpdate.dataKey, 16); + memcpy(pWapiSta->wapiUsk.micKey, pWapiSta->wapiUskUpdate.micKey, 16); + pWapiSta->wapiUskUpdate.bTxEnable = pWapiSta->wapiUskUpdate.bSet = false; + } + } + }else{ + WAPI_TRACE(WAPI_ERR, "%s: Check MIC Error, Dropped !!!!\n", __FUNCTION__); + return false; + } + + pos = pskb->data; + memmove(pos+ieee->wapiInfo.extra_prefix_len, pos, IVOffset); + skb_pull(pskb, ieee->wapiInfo.extra_prefix_len); + + WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__); + + return true; +} + +void wapi_test_set_key(struct rtllib_device *ieee, u8* buf) +{ /*Data: keyType(1) + bTxEnable(1) + bAuthenticator(1) + bUpdate(1) + PeerAddr(6) + DataKey(16) + MicKey(16) + KeyId(1)*/ + PRT_WAPI_T pWapiInfo = &ieee->wapiInfo; + PRT_WAPI_BKID pWapiBkid; + PRT_WAPI_STA_INFO pWapiSta; + u8 data[43]; + bool bTxEnable; + bool bUpdate; + bool bAuthenticator; + u8 PeerAddr[6]; + u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; + u8 WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; + u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ; + + WAPI_TRACE(WAPI_INIT, "===========>%s\n", __FUNCTION__); + + if (!ieee->WapiSupport){ + return; + } + + copy_from_user(data, buf, 43); + bTxEnable = data[1]; + bAuthenticator = data[2]; + bUpdate = data[3]; + memcpy(PeerAddr,data+4,6); + + if(data[0] == 0x3){ + if(!list_empty(&(pWapiInfo->wapiBKIDIdleList))){ + pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID, list); + list_del_init(&pWapiBkid->list); + memcpy(pWapiBkid->bkid, data+10, 16); + WAPI_DATA(WAPI_INIT, "SetKey - BKID", pWapiBkid->bkid, 16); + list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDStoreList); + } + }else{ + list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) { + if(!memcmp(pWapiSta->PeerMacAddr,PeerAddr,6)){ + pWapiSta->bAuthenticatorInUpdata = false; + switch(data[0]){ + case 1: + if(bAuthenticator){ + memcpy(pWapiSta->lastTxUnicastPN,WapiAEPNInitialValueSrc,16); + if(!bUpdate) { + WAPI_TRACE(WAPI_INIT,"AE fisrt set usk \n"); + pWapiSta->wapiUsk.bSet = true; + memcpy(pWapiSta->wapiUsk.dataKey,data+10,16); + memcpy(pWapiSta->wapiUsk.micKey,data+26,16); + pWapiSta->wapiUsk.keyId = *(data+42); + pWapiSta->wapiUsk.bTxEnable = true; + WAPI_DATA(WAPI_INIT, "SetKey - AE USK Data Key", pWapiSta->wapiUsk.dataKey, 16); + WAPI_DATA(WAPI_INIT, "SetKey - AE USK Mic Key", pWapiSta->wapiUsk.micKey, 16); + } + else + { + WAPI_TRACE(WAPI_INIT, "AE update usk \n"); + pWapiSta->wapiUskUpdate.bSet = true; + pWapiSta->bAuthenticatorInUpdata = true; + memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16); + memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16); + memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16); + pWapiSta->wapiUskUpdate.keyId = *(data+42); + pWapiSta->wapiUskUpdate.bTxEnable = true; + } + } + else{ + if(!bUpdate){ + WAPI_TRACE(WAPI_INIT,"ASUE fisrt set usk \n"); + if(bTxEnable){ + pWapiSta->wapiUsk.bTxEnable = true; + memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16); + }else{ + pWapiSta->wapiUsk.bSet = true; + memcpy(pWapiSta->wapiUsk.dataKey,data+10,16); + memcpy(pWapiSta->wapiUsk.micKey,data+26,16); + pWapiSta->wapiUsk.keyId = *(data+42); + pWapiSta->wapiUsk.bTxEnable = false; + } + }else{ + WAPI_TRACE(WAPI_INIT,"ASUE update usk \n"); + if(bTxEnable){ + pWapiSta->wapiUskUpdate.bTxEnable = true; + if(pWapiSta->wapiUskUpdate.bSet){ + memcpy(pWapiSta->wapiUsk.dataKey,pWapiSta->wapiUskUpdate.dataKey,16); + memcpy(pWapiSta->wapiUsk.micKey,pWapiSta->wapiUskUpdate.micKey,16); + pWapiSta->wapiUsk.keyId=pWapiSta->wapiUskUpdate.keyId; + memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16); + memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16); + pWapiSta->wapiUskUpdate.bTxEnable = false; + pWapiSta->wapiUskUpdate.bSet = false; + } + memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16); + }else{ + pWapiSta->wapiUskUpdate.bSet = true; + memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16); + memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16); + pWapiSta->wapiUskUpdate.keyId = *(data+42); + pWapiSta->wapiUskUpdate.bTxEnable = false; + } + } + } + break; + case 2: + if(bAuthenticator){ + pWapiInfo->wapiTxMsk.bSet = true; + memcpy(pWapiInfo->wapiTxMsk.dataKey,data+10,16); + memcpy(pWapiInfo->wapiTxMsk.micKey,data+26,16); + pWapiInfo->wapiTxMsk.keyId = *(data+42); + pWapiInfo->wapiTxMsk.bTxEnable = true; + memcpy(pWapiInfo->lastTxMulticastPN,WapiAEMultiCastPNInitialValueSrc,16); + + if(!bUpdate){ + WAPI_TRACE(WAPI_INIT, "AE fisrt set msk \n"); + if(!pWapiSta->bSetkeyOk) + pWapiSta->bSetkeyOk = true; + pWapiInfo->bFirstAuthentiateInProgress= false; + }else{ + WAPI_TRACE(WAPI_INIT,"AE update msk \n"); + } + + WAPI_DATA(WAPI_INIT, "SetKey - AE MSK Data Key", pWapiInfo->wapiTxMsk.dataKey, 16); + WAPI_DATA(WAPI_INIT, "SetKey - AE MSK Mic Key", pWapiInfo->wapiTxMsk.micKey, 16); + } + else{ + if(!bUpdate){ + WAPI_TRACE(WAPI_INIT,"ASUE fisrt set msk \n"); + pWapiSta->wapiMsk.bSet = true; + memcpy(pWapiSta->wapiMsk.dataKey,data+10,16); + memcpy(pWapiSta->wapiMsk.micKey,data+26,16); + pWapiSta->wapiMsk.keyId = *(data+42); + pWapiSta->wapiMsk.bTxEnable = false; + if(!pWapiSta->bSetkeyOk) + pWapiSta->bSetkeyOk = true; + pWapiInfo->bFirstAuthentiateInProgress= false; + WAPI_DATA(WAPI_INIT, "SetKey - ASUE MSK Data Key", pWapiSta->wapiMsk.dataKey, 16); + WAPI_DATA(WAPI_INIT, "SetKey - ASUE MSK Mic Key", pWapiSta->wapiMsk.micKey, 16); + }else{ + WAPI_TRACE(WAPI_INIT,"ASUE update msk \n"); + pWapiSta->wapiMskUpdate.bSet = true; + memcpy(pWapiSta->wapiMskUpdate.dataKey,data+10,16); + memcpy(pWapiSta->wapiMskUpdate.micKey,data+26,16); + pWapiSta->wapiMskUpdate.keyId = *(data+42); + pWapiSta->wapiMskUpdate.bTxEnable = false; + } + } + break; + default: + WAPI_TRACE(WAPI_ERR,"Unknown Flag \n"); + break; + } + } + } + } + WAPI_TRACE(WAPI_INIT, "<===========%s\n", __FUNCTION__); +} + +void wapi_test_init(struct rtllib_device *ieee) +{ + u8 keybuf[100]; + u8 mac_addr[6]={0x00,0xe0,0x4c,0x72,0x04,0x70}; + u8 UskDataKey[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; + u8 UskMicKey[16]={0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f}; + u8 UskId = 0; + u8 MskDataKey[16]={0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f}; + u8 MskMicKey[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f}; + u8 MskId = 0; + + WAPI_TRACE(WAPI_INIT, "===========>%s\n", __FUNCTION__); + + WAPI_TRACE(WAPI_INIT, "%s: Enable wapi!!!!\n", __FUNCTION__); + ieee->wapiInfo.bWapiEnable = true; + ieee->pairwise_key_type = KEY_TYPE_SMS4; + ieee->group_key_type = KEY_TYPE_SMS4; + ieee->wapiInfo.extra_prefix_len = WAPI_EXT_LEN; + ieee->wapiInfo.extra_postfix_len = SMS4_MIC_LEN; + + WAPI_TRACE(WAPI_INIT, "%s: Set USK!!!!\n", __FUNCTION__); + memset(keybuf,0,100); + keybuf[0] = 1; + keybuf[1] = 1; + keybuf[2] = 1; + keybuf[3] = 0; + + memcpy(keybuf+4,mac_addr,6); + memcpy(keybuf+10,UskDataKey,16); + memcpy(keybuf+26,UskMicKey,16); + keybuf[42]=UskId; + wapi_test_set_key(ieee, keybuf); + + memset(keybuf,0,100); + keybuf[0] = 1; + keybuf[1] = 1; + keybuf[2] = 0; + keybuf[3] = 0; + + memcpy(keybuf+4,mac_addr,6); + memcpy(keybuf+10,UskDataKey,16); + memcpy(keybuf+26,UskMicKey,16); + keybuf[42]=UskId; + wapi_test_set_key(ieee, keybuf); + + WAPI_TRACE(WAPI_INIT, "%s: Set MSK!!!!\n", __FUNCTION__); + memset(keybuf,0,100); + keybuf[0] = 2; + keybuf[1] = 1; + keybuf[2] = 1; + keybuf[3] = 0; + memcpy(keybuf+4,mac_addr,6); + memcpy(keybuf+10,MskDataKey,16); + memcpy(keybuf+26,MskMicKey,16); + keybuf[42] = MskId; + wapi_test_set_key(ieee, keybuf); + + memset(keybuf,0,100); + keybuf[0] = 2; + keybuf[1] = 1; + keybuf[2] = 0; + keybuf[3] = 0; + memcpy(keybuf+4,mac_addr,6); + memcpy(keybuf+10,MskDataKey,16); + memcpy(keybuf+26,MskMicKey,16); + keybuf[42] = MskId; + wapi_test_set_key(ieee, keybuf); + WAPI_TRACE(WAPI_INIT, "<===========%s\n", __FUNCTION__); +} + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/wapi.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/wapi.h @@ -0,0 +1,135 @@ +#ifndef __INC_WAPI_H +#define __INC_WAPI_H + +#include +#include +#include "rtl819x_Qos.h" + +/* WAPI trace debug */ +extern u32 wapi_debug_component; + +#define WAPI_TRACE(component, x, args...) \ +do { if(wapi_debug_component & (component)) \ + printk(KERN_DEBUG "WAPI" ":" x "" , \ + ##args);\ +}while(0); + +#define WAPI_DATA(component, x, buf, len) \ +do { if(wapi_debug_component & (component)){ \ + printk("%s:\n", x);\ + dump_buf((buf), (len));}\ +}while(0); + +enum WAPI_DEBUG { + WAPI_INIT =BIT0, + WAPI_API = BIT1, + WAPI_TX = BIT2, + WAPI_RX = BIT3, + WAPI_ERR = BIT31 +}; + +#define WAPI_MAX_BKID_NUM 64 +#define WAPI_MAX_STAINFO_NUM 64 +typedef struct _RT_WAPI_BKID +{ + struct list_head list; + u8 bkid[16]; +}RT_WAPI_BKID,*PRT_WAPI_BKID; + +typedef struct _RT_WAPI_KEY +{ + u8 dataKey[16]; + u8 micKey[16]; + u8 keyId; + bool bSet; + bool bTxEnable; +}RT_WAPI_KEY,*PRT_WAPI_KEY; + +typedef enum _RT_WAPI_PACKET_TYPE +{ + WAPI_NONE = 0, + WAPI_PREAUTHENTICATE=1, + WAPI_STAKEY_REQUEST=2, + WAPI_AUTHENTICATE_ACTIVE=3, + WAPI_ACCESS_AUTHENTICATE_REQUEST=4, + WAPI_ACCESS_AUTHENTICATE_RESPONSE=5, + WAPI_CERTIFICATE_AUTHENTICATE_REQUEST=6, + WAPI_CERTIFICATE_AUTHENTICATE_RESPONSE=7, + WAPI_USK_REQUEST=8, + WAPI_USK_RESPONSE=9, + WAPI_USK_CONFIRM=10, + WAPI_MSK_NOTIFICATION=11, + WAPI_MSK_RESPONSE=12 +}RT_WAPI_PACKET_TYPE; + +typedef struct _RT_CACHE_INFO { + u8 cache_buffer[2000]; + u16 cache_buffer_len; + u8 saddr[6]; + bool bAuthenticator; + u16 recvSeq; + u8 lastFragNum; + struct list_head list; +}RT_CACHE_INFO, *PRT_CACHE_INFO; + +typedef struct _RT_WAPI_STA_INFO +{ + struct list_head list; + u8 PeerMacAddr[6]; + RT_WAPI_KEY wapiUsk; + RT_WAPI_KEY wapiUskUpdate; + RT_WAPI_KEY wapiMsk; + RT_WAPI_KEY wapiMskUpdate; + u8 lastRxUnicastPN[16]; + u8 lastTxUnicastPN[16]; + u8 lastRxMulticastPN[16]; + u8 lastRxUnicastPNBEQueue[16]; + u8 lastRxUnicastPNBKQueue[16]; + u8 lastRxUnicastPNVIQueue[16]; + u8 lastRxUnicastPNVOQueue[16]; + bool bSetkeyOk; + bool bAuthenticateInProgress; + bool bAuthenticatorInUpdata; +}RT_WAPI_STA_INFO,*PRT_WAPI_STA_INFO; + +typedef struct _RT_WAPI_T +{ + u8 assoReqWapiIE[256]; + u8 assoReqWapiIELength; + u8 assoRspWapiIE[256]; + u8 assoRspWapiIELength; + u8 sendbeaconWapiIE[256]; + u8 sendbeaconWapiIELength; + RT_WAPI_BKID wapiBKID[WAPI_MAX_BKID_NUM]; + struct list_head wapiBKIDIdleList; + struct list_head wapiBKIDStoreList; + RT_WAPI_KEY wapiTxMsk; + + u8 wapiDestMacAddr[6]; + bool bAuthenticator; + u8 lastTxMulticastPN[16]; + RT_WAPI_STA_INFO wapiSta[WAPI_MAX_STAINFO_NUM]; + struct list_head wapiSTAIdleList; + struct list_head wapiSTAUsedList; + bool bWapiEnable; + bool bUpdateUsk; + bool bUpdateMsk; + + u8 wapiIE[256]; + u8 wapiIELength; + bool bWapiNotSetEncMacHeader; + bool bWapiPSK; + bool bFirstAuthentiateInProgress; + u16 wapiSeqnumAndFragNum; + int extra_prefix_len; + int extra_postfix_len; +}RT_WAPI_T,*PRT_WAPI_T; + +typedef struct _WLAN_HEADER_WAPI_EXTENSION +{ + u8 KeyIdx; + u8 Reserved; + u8 PN[16]; +} WLAN_HEADER_WAPI_EXTENSION, *PWLAN_HEADER_WAPI_EXTENSION; + +#endif --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/wapi_interface.c +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/wapi_interface.c @@ -0,0 +1,151 @@ +#if defined (RTL8192S_WAPI_SUPPORT) + +#include "wapi.h" +#include "wapi_interface.h" +#include "rtllib.h" + + +/************************************************************* + * WAPI EVENT QUEUE : * + * Buffer events from driver to application. * + *************************************************************/ +void WAPI_InitQueue(WAPI_QUEUE * q, int szMaxItem, int szMaxData) +{ + RT_ASSERT_RET(q); + + q->Head = 0; + q->Tail = 0; + q->NumItem = 0; + q->MaxItem = szMaxItem; + q->MaxData = szMaxData; +} + +int WAPI_EnQueue(spinlock_t *plock, WAPI_QUEUE *q, u8 *item, int itemsize) +{ + unsigned long flags; + + RT_ASSERT_RET_VALUE(plock, (-E_WAPI_QNULL)); + RT_ASSERT_RET_VALUE(q, (-E_WAPI_QNULL)); + RT_ASSERT_RET_VALUE(item, (-E_WAPI_QNULL)); + + if(WAPI_IsFullQueue(q)) + return -E_WAPI_QFULL; + if(itemsize > q->MaxData) + return -E_WAPI_ITEM_TOO_LARGE; + + spin_lock_irqsave(plock, flags); + + q->ItemArray[q->Tail].ItemSize = itemsize; + memset(q->ItemArray[q->Tail].Item, 0, sizeof(q->ItemArray[q->Tail].Item)); + memcpy(q->ItemArray[q->Tail].Item, item, itemsize); + q->NumItem++; + if((q->Tail+1) == q->MaxItem) + q->Tail = 0; + else + q->Tail++; + + spin_unlock_irqrestore(plock, flags); + + return E_WAPI_OK; +} + + +int WAPI_DeQueue(spinlock_t *plock, WAPI_QUEUE *q, u8 *item, int *itemsize) +{ + unsigned long flags; + + RT_ASSERT_RET_VALUE(plock, (-E_WAPI_QNULL)); + RT_ASSERT_RET_VALUE(q, (-E_WAPI_QNULL)); + RT_ASSERT_RET_VALUE(item, (-E_WAPI_QNULL)); + + if(WAPI_IsEmptyQueue(q)) + return -E_WAPI_QEMPTY; + + spin_lock_irqsave(plock, flags); + + memcpy(item, q->ItemArray[q->Head].Item, q->ItemArray[q->Head].ItemSize); + *itemsize = q->ItemArray[q->Head].ItemSize; + q->NumItem--; + if((q->Head+1) == q->MaxItem) + q->Head = 0; + else + q->Head++; + + spin_unlock_irqrestore(plock, flags); + + return E_WAPI_OK; +} + +void WAPI_PrintQueue(WAPI_QUEUE *q) +{ + int i, j, index; + + RT_ASSERT_RET(q); + + printk("\n/-------------------------------------------------\n"); + printk("[DOT11_PrintQueue]: MaxItem = %d, NumItem = %d, Head = %d, Tail = %d\n", q->MaxItem, q->NumItem, q->Head, q->Tail); + for(i=0; iNumItem; i++) { + index = (i + q->Head) % q->MaxItem; + printk("Queue[%d].ItemSize = %d ", index, q->ItemArray[index].ItemSize); + for(j=0; jItemArray[index].ItemSize; j++) + printk(" %x", q->ItemArray[index].Item[j]); + printk("\n"); + } + printk("------------------------------------------------/\n"); +} + +int pid_wapi = 0; +void notifyWapiApplication() +{ + struct task_struct *p; + + if(pid_wapi != 0){ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)) + p = find_task_by_pid(pid_wapi); +#else + p = find_task_by_vpid(pid_wapi); +#endif + if(p){ + send_sig(SIGUSR1,p,0); + }else { + pid_wapi = 0; + } + } +} + +int WAPI_CreateEvent_Send(struct rtllib_device *ieee, u8 EventId, u8 *MacAddr, u8 *Buff, u16 BufLen) +{ + WAPI_EVENT_T *pEvent; + u8 *pbuf = NULL; + int ret = 0; + + WAPI_TRACE(WAPI_API, "==========> %s: EventId=%d\n", __FUNCTION__, EventId); + + RT_ASSERT_RET_VALUE(ieee, -1); + RT_ASSERT_RET_VALUE(MacAddr, -1); + + pbuf= (u8 *)kmalloc((sizeof(WAPI_EVENT_T) + BufLen), GFP_ATOMIC); + if(NULL == pbuf) + return -1; + + pEvent = (WAPI_EVENT_T *)pbuf; + pEvent->EventId = EventId; + memcpy(pEvent->MACAddr, MacAddr, ETH_ALEN); + pEvent->BuffLength = BufLen; + if(BufLen > 0){ + memcpy(pEvent->Buff, Buff, BufLen); + } + + ret = WAPI_EnQueue(&ieee->wapi_queue_lock, ieee->wapi_queue, pbuf, (sizeof(WAPI_EVENT_T) + BufLen)); + notifyWapiApplication(); + + if(pbuf) + kfree(pbuf); + + WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__); + return ret; +} + +#endif + --- linux-2.6.37.orig/ubuntu/rtl8192se/rtllib/wapi_interface.h +++ linux-2.6.37/ubuntu/rtl8192se/rtllib/wapi_interface.h @@ -0,0 +1,98 @@ +#ifndef __INC_WAPI_INTERFACE_H +#define __INC_WAPI_INTERFACE_H +#include +#include /* ETH_ALEN */ + +/************************************************************* + * WAPI EVENT QUEUE : * + * Buffer events from driver to application. * + *************************************************************/ +#define WAPI_MAX_BUFF_LEN 2000 +#define WAPI_MAX_QUEUE_LEN 6 + +typedef enum +{ + E_WAPI_OK = 0, + E_WAPI_ITEM_TOO_LARGE = 1, + E_WAPI_QFULL = 2, + E_WAPI_QEMPTY = 3, + E_WAPI_QNULL = 4 +}WAPI_QUEUE_RET_VAL; + +typedef struct _WAPI_QUEUE_NODE +{ + u16 ItemSize; + u8 Item[WAPI_MAX_BUFF_LEN]; +}WAPI_QUEUE_NODE; + +typedef struct _WAPI_QUEUE +{ + int Head; + int Tail; + int NumItem; + int MaxItem; + WAPI_QUEUE_NODE ItemArray[WAPI_MAX_QUEUE_LEN]; + int MaxData; +}WAPI_QUEUE; + +typedef enum{ + WAPI_EVENT_RCV_PREAUTHENTICATE = 1, + WAPI_EVENT_RCV_STAKEY_REQUEST = 2, + WAPI_EVENT_RCV_AUTHENTICATE_ACTIVE = 3, + WAPI_EVENT_RCV_ACCESS_AUTHENTICATE_REQUEST = 4, + WAPI_EVENT_RCV_ACCESS_AUTHENTICATE_RESPONSE = 5, + WAPI_EVENT_RCV_CERTIFICATE_AUTHENTICATE_REQUEST = 6, + WAPI_EVENT_RCV_CERTIFICATE_AUTHENTICATE_RESPONSE = 7, + WAPI_EVENT_RCV_USK_REQUEST = 8, + WAPI_EVENT_RCV_USK_RESPONSE = 9, + WAPI_EVENT_RCV_USK_CONFIRM = 10, + WAPI_EVENT_RCV_MSK_NOTIFICATION = 11, + WAPI_EVENT_RCV_MSK_RESPONSE = 12, + WAPI_EVENT_AE_UPDATE_BK = 13, + WAPI_EVENT_AE_UPDATE_USK = 14, + WAPI_EVENT_AE_UPDATE_MSK = 15, + WAPI_EVENT_ASUE_UPDATE_BK = 16, + WAPI_EVENT_ASUE_UPDATE_USK = 17, + WAPI_EVENT_FIRST_AUTHENTICATOR = 18, + WAPI_EVENT_CONNECT = 19, + WAPI_EVENT_DISCONNECT = 20, + WAPI_EVENT_MAX_NUM = 21 +} WAPI_EVENT_ID; + +typedef struct _WAPI_EVENT_T{ + u8 EventId; + u8 MACAddr[ETH_ALEN]; + u16 BuffLength; + u8 Buff[0]; +}__attribute__ ((packed))WAPI_EVENT_T; + +#define WAPI_IsEmptyQueue(q) (q->NumItem==0 ? 1:0) +#define WAPI_IsFullQueue(q) (q->NumItem==q->MaxItem? 1:0) +#define WAPI_NumItemQueue(q) q->NumItem + +void WAPI_InitQueue(WAPI_QUEUE *q, int szMaxItem, int szMaxData); +int WAPI_EnQueue(spinlock_t *plock, WAPI_QUEUE *q, u8 *item, int itemsize); +int WAPI_DeQueue(spinlock_t *plock, WAPI_QUEUE *q, u8 *item, int *itemsize); +void WAPI_PrintQueue(WAPI_QUEUE *q); + +extern int pid_wapi; +extern void notifyWapiApplication(void); +/************************************************************* + * WAPI IOCTL: FROM APPLICATION TO DRIVER * + *************************************************************/ +#define WAPI_CMD_GET_WAPI_SUPPORT 0X8B81 +#define WAPI_CMD_SET_WAPI_ENABLE 0X8B82 +#define WAPI_CMD_SET_WAPI_PSK 0X8B83 +#define WAPI_CMD_SET_KEY 0X8B84 +#define WAPI_CMD_SET_MULTICAST_PN 0X8B85 +#define WAPI_CMD_GET_PN 0X8B86 +#define WAPI_CMD_GET_WAPIIE 0X8B87 +#define WAPI_CMD_SET_SSID 0X8B88 +#define WAPI_CMD_GET_BSSID 0X8B89 +#define WAPI_CMD_SET_IW_MODE 0X8B8b +#define WAPI_CMD_SET_DISASSOCIATE 0X8B8c +#define WAPI_CMD_SAVE_PID 0X8B8d +#define WAPI_CMD_DEQUEUE 0X8B90 + +#endif +